Skip to content

Commit

Permalink
[TS migration] Migrate 'MentionSuggestions.js' component to TypeScript
Browse files Browse the repository at this point in the history
  • Loading branch information
pasyukevich committed Oct 31, 2023
1 parent 2707647 commit 52ff093
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 59 deletions.
13 changes: 13 additions & 0 deletions src/components/AvatarTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import CONST from '@src/CONST';

type AvatarFunctionType = () => void;

type AvatarType = {
source: string | AvatarFunctionType;
type: typeof CONST.ICON_TYPE_AVATAR | typeof CONST.ICON_TYPE_WORKSPACE;
name: string;
id: number | string;
fallbackIcon: string | AvatarFunctionType;
};

export default AvatarType;
Original file line number Diff line number Diff line change
@@ -1,73 +1,64 @@
import PropTypes from 'prop-types';
import React from 'react';
import {View} from 'react-native';
import _ from 'underscore';
import getStyledTextArray from '@libs/GetStyledTextArray';
import styles from '@styles/styles';
import * as StyleUtils from '@styles/StyleUtils';
import themeColors from '@styles/themes/default';
import CONST from '@src/CONST';
import AutoCompleteSuggestions from './AutoCompleteSuggestions';
import Avatar from './Avatar';
import avatarPropTypes from './avatarPropTypes';
import AvatarTypes from './AvatarTypes';
import Text from './Text';

const propTypes = {
/** The index of the highlighted mention */
highlightedMentionIndex: PropTypes.number,
type Mention = {
/** Display name of the user */
text: string;

/** Array of suggested mentions */
mentions: PropTypes.arrayOf(
PropTypes.shape({
/** Display name of the user */
text: PropTypes.string,
/** Email/phone number of the user */
alternateText: string;

/** Array of icons of the user. We use the first element of this array */
icons: AvatarTypes[];
};

/** Email/phone number of the user */
alternateText: PropTypes.string,
type MentionSuggestionsProps = {
/** The index of the highlighted mention */
highlightedMentionIndex?: number;

/** Array of icons of the user. We use the first element of this array */
icons: PropTypes.arrayOf(avatarPropTypes),
}),
).isRequired,
/** Array of suggested mentions */
mentions: Mention[];

/** Fired when the user selects an mention */
onSelect: PropTypes.func.isRequired,
onSelect: () => void;

/** Mention prefix that follows the @ sign */
prefix: PropTypes.string.isRequired,
prefix: string;

/** Show that we can use large mention picker.
* Depending on available space and whether the input is expanded, we can have a small or large mention suggester.
* When this value is false, the suggester will have a height of 2.5 items. When this value is true, the height can be up to 5 items. */
isMentionPickerLarge: PropTypes.bool.isRequired,
isMentionPickerLarge: boolean;

/** Meaures the parent container's position and dimensions. */
measureParentContainer: PropTypes.func,
};

const defaultProps = {
highlightedMentionIndex: 0,
measureParentContainer: () => {},
measureParentContainer: () => void;
};

/**
* Create unique keys for each mention item
* @param {Object} item
* @param {Number} index
* @returns {String}
* @param item
* @param index
*/
const keyExtractor = (item) => item.alternateText;
const keyExtractor = (item: Mention) => item.alternateText;

function MentionSuggestions(props) {
function MentionSuggestions({prefix, mentions, highlightedMentionIndex = 0, onSelect, isMentionPickerLarge, measureParentContainer = () => {}}: MentionSuggestionsProps) {
/**
* Render a suggestion menu item component.
* @param {Object} item
* @returns {JSX.Element}
* @param item
*/
const renderSuggestionMenuItem = (item) => {
const renderSuggestionMenuItem = (item: Mention) => {
const isIcon = item.text === CONST.AUTO_COMPLETE_SUGGESTER.HERE_TEXT;
const styledDisplayName = getStyledTextArray(item.text, props.prefix);
const styledHandle = item.text === item.alternateText ? '' : getStyledTextArray(item.alternateText, props.prefix);
const styledDisplayName = getStyledTextArray(item.text, prefix);
const styledHandle = item.text === item.alternateText ? '' : getStyledTextArray(item.alternateText, prefix);

return (
<View style={[styles.autoCompleteSuggestionContainer, styles.ph2]}>
Expand All @@ -85,9 +76,9 @@ function MentionSuggestions(props) {
style={[styles.mentionSuggestionsText, styles.flexShrink1]}
numberOfLines={1}
>
{_.map(styledDisplayName, ({text, isColored}, i) => (
{styledDisplayName.map(({text, isColored}) => (
<Text
key={`${text}${i}`}
key={`${text}${isColored}`}
style={[StyleUtils.getColoredBackgroundStyle(isColored), styles.mentionSuggestionsDisplayName]}
>
{text}
Expand All @@ -98,39 +89,37 @@ function MentionSuggestions(props) {
style={[styles.mentionSuggestionsText, styles.flex1]}
numberOfLines={1}
>
{_.map(
styledHandle,
({text, isColored}, i) =>
text !== '' && (
<Text
key={`${text}${i}`}
style={[StyleUtils.getColoredBackgroundStyle(isColored), styles.mentionSuggestionsHandle, {...(isColored && {color: styles.text})}]}
>
{text}
</Text>
),
)}
{styledHandle &&
styledHandle.map(
({text, isColored}) =>
text !== '' && (
<Text
key={`${text}${isColored}`}
style={[StyleUtils.getColoredBackgroundStyle(isColored), styles.mentionSuggestionsHandle]}
>
{text}
</Text>
),
)}
</Text>
</View>
);
};

return (
<AutoCompleteSuggestions
suggestions={props.mentions}
suggestions={mentions}
renderSuggestionMenuItem={renderSuggestionMenuItem}
keyExtractor={keyExtractor}
highlightedSuggestionIndex={props.highlightedMentionIndex}
onSelect={props.onSelect}
isSuggestionPickerLarge={props.isMentionPickerLarge}
highlightedSuggestionIndex={highlightedMentionIndex}
onSelect={onSelect}
isSuggestionPickerLarge={isMentionPickerLarge}
accessibilityLabelExtractor={keyExtractor}
measureParentContainer={props.measureParentContainer}
measureParentContainer={measureParentContainer}
/>
);
}

MentionSuggestions.propTypes = propTypes;
MentionSuggestions.defaultProps = defaultProps;
MentionSuggestions.displayName = 'MentionSuggestions';

export default MentionSuggestions;
4 changes: 2 additions & 2 deletions src/styles/StyleUtils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {CSSProperties} from 'react';
import {Animated, DimensionValue, ImageStyle, PressableStateCallbackType, TextStyle, ViewStyle} from 'react-native';
import {Animated, DimensionValue, ImageStyle, PressableStateCallbackType, StyleProp, TextStyle, ViewStyle} from 'react-native';
import {EdgeInsets} from 'react-native-safe-area-context';
import {ValueOf} from 'type-fest';
import * as Browser from '@libs/Browser';
Expand Down Expand Up @@ -1012,7 +1012,7 @@ function getAutoCompleteSuggestionContainerStyle(itemsHeight: number): ViewStyle
/**
* Select the correct color for text.
*/
function getColoredBackgroundStyle(isColored: boolean): ViewStyle {
function getColoredBackgroundStyle(isColored: boolean): StyleProp<TextStyle> | undefined {
return {backgroundColor: isColored ? themeColors.link : undefined};
}

Expand Down

0 comments on commit 52ff093

Please sign in to comment.