tidy up the ref to ref with a forwardRef and initialComponent signature

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski 2020-05-30 13:30:59 +01:00
parent 8087b521e6
commit bc83984a62
7 changed files with 51 additions and 73 deletions

View file

@ -90,11 +90,12 @@ export default class CommunityProvider extends AutocompleteProvider {
type: "community",
href: makeGroupPermalink(groupId),
component: (
<PillCompletion initialComponent={
<PillCompletion title={name} description={groupId}>
<BaseAvatar name={name || groupId}
width={24} height={24}
width={24}
height={24}
url={avatarUrl ? cli.mxcUrlToHttp(avatarUrl, 24, 24) : null} />
} title={name} description={groupId} />
</PillCompletion>
),
range,
}))

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, {createRef} from 'react';
import React, {forwardRef} from 'react';
import classNames from 'classnames';
/* These were earlier stateless functional components but had to be converted
@ -30,62 +30,37 @@ interface ITextualCompletionProps {
className?: string;
}
export abstract class Completion<T> extends React.PureComponent<T> {
nodeRef = createRef<HTMLDivElement>();
export const TextualCompletion = forwardRef<ITextualCompletionProps, any>((props, ref) => {
const {title, subtitle, description, className, ...restProps} = props;
return (
<div {...restProps}
className={classNames('mx_Autocomplete_Completion_block', className)}
role="option"
ref={ref}
>
<span className="mx_Autocomplete_Completion_title">{ title }</span>
<span className="mx_Autocomplete_Completion_subtitle">{ subtitle }</span>
<span className="mx_Autocomplete_Completion_description">{ description }</span>
</div>
);
});
interface IPillCompletionProps extends ITextualCompletionProps {
children?: React.ReactNode,
}
export class TextualCompletion extends Completion<ITextualCompletionProps> {
render() {
const {
title,
subtitle,
description,
className,
...restProps
} = this.props;
return (
<div {...restProps}
className={classNames('mx_Autocomplete_Completion_block', className)}
role="option"
ref={this.nodeRef}
>
<span className="mx_Autocomplete_Completion_title">{ title }</span>
<span className="mx_Autocomplete_Completion_subtitle">{ subtitle }</span>
<span className="mx_Autocomplete_Completion_description">{ description }</span>
</div>
);
}
}
interface IPillCompletionProps {
title?: string;
subtitle?: string;
description?: string;
initialComponent?: React.ReactNode,
className?: string;
}
export class PillCompletion extends Completion<IPillCompletionProps> {
render() {
const {
title,
subtitle,
description,
initialComponent,
className,
...restProps
} = this.props;
return (
<div {...restProps}
className={classNames('mx_Autocomplete_Completion_pill', className)}
role="option"
ref={this.nodeRef}
>
{ initialComponent }
<span className="mx_Autocomplete_Completion_title">{ title }</span>
<span className="mx_Autocomplete_Completion_subtitle">{ subtitle }</span>
<span className="mx_Autocomplete_Completion_description">{ description }</span>
</div>
);
}
}
export const PillCompletion = forwardRef<IPillCompletionProps, any>((props, ref) => {
const {title, subtitle, description, className, children, ...restProps} = props;
return (
<div {...restProps}
className={classNames('mx_Autocomplete_Completion_pill', className)}
role="option"
ref={ref}
>
{ children }
<span className="mx_Autocomplete_Completion_title">{ title }</span>
<span className="mx_Autocomplete_Completion_subtitle">{ subtitle }</span>
<span className="mx_Autocomplete_Completion_description">{ description }</span>
</div>
);
});

View file

@ -121,9 +121,9 @@ export default class EmojiProvider extends AutocompleteProvider {
return {
completion: unicode,
component: (
<PillCompletion title={shortname} aria-label={unicode} initialComponent={
<PillCompletion title={shortname} aria-label={unicode}>
<span style={{maxWidth: '1em'}}>{ unicode }</span>
} />
</PillCompletion>
),
range,
};

View file

@ -48,7 +48,9 @@ export default class NotifProvider extends AutocompleteProvider {
type: "at-room",
suffix: ' ',
component: (
<PillCompletion initialComponent={<RoomAvatar width={24} height={24} room={this.room} />} title="@room" description={_t("Notify the whole room")} />
<PillCompletion title="@room" description={_t("Notify the whole room")}>
<RoomAvatar width={24} height={24} room={this.room} />
</PillCompletion>
),
range,
}];

View file

@ -103,7 +103,9 @@ export default class RoomProvider extends AutocompleteProvider {
suffix: ' ',
href: makeRoomPermalink(room.displayedAlias),
component: (
<PillCompletion initialComponent={<RoomAvatar width={24} height={24} room={room.room} />} title={room.room.name} description={room.displayedAlias} />
<PillCompletion title={room.room.name} description={room.displayedAlias}>
<RoomAvatar width={24} height={24} room={room.room} />
</PillCompletion>
),
range,
};

View file

@ -125,10 +125,9 @@ export default class UserProvider extends AutocompleteProvider {
suffix: (selection.beginning && range.start === 0) ? ': ' : ' ',
href: makeUserPermalink(user.userId),
component: (
<PillCompletion
initialComponent={<MemberAvatar member={user} width={24} height={24} />}
title={displayName}
description={user.userId} />
<PillCompletion title={displayName} description={user.userId}>
<MemberAvatar member={user} width={24} height={24} />
</PillCompletion>
),
range,
};

View file

@ -23,7 +23,6 @@ import {Room} from 'matrix-js-sdk/src/models/room';
import SettingsStore from "../../../settings/SettingsStore";
import Autocompleter from '../../../autocomplete/Autocompleter';
import { Completion } from '../../../autocomplete/Components';
const COMPOSER_SELECTED = 0;
@ -254,10 +253,10 @@ export default class Autocomplete extends React.PureComponent<IProps, IState> {
componentDidUpdate(prevProps: IProps) {
this.applyNewProps(prevProps.query, prevProps.room);
// this is the selected completion, so scroll it into view if needed
const selectedCompletion = this.refs[`completion${this.state.selectionOffset}`] as Completion<any>;
const selectedCompletion = this.refs[`completion${this.state.selectionOffset}`] as HTMLElement;
if (selectedCompletion && selectedCompletion.nodeRef.current) {
selectedCompletion.nodeRef.current.scrollIntoView({
if (selectedCompletion) {
selectedCompletion.scrollIntoView({
behavior: "auto",
block: "nearest",
});