Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
d291618
Migrate to TS
MaciejSWM Oct 24, 2023
1aada2b
Merge branch 'main' into ts-migration/TextLink
MaciejSWM Nov 6, 2023
cda8b73
Relative imports; optional params; types
MaciejSWM Nov 6, 2023
383db18
Remove unused import
MaciejSWM Nov 6, 2023
f7ea0fe
Import ordering; Ignore no spreading
MaciejSWM Nov 6, 2023
71fe175
Extract logic to openLink method
MaciejSWM Nov 6, 2023
4c0a808
Missing semicolon
MaciejSWM Nov 6, 2023
659b4cc
Merge branch 'main' into ts-migration/TextLink
MaciejSWM Nov 7, 2023
89f3905
Better ref handling
MaciejSWM Nov 7, 2023
af92086
More preventDefault after early return
MaciejSWM Nov 7, 2023
d4802db
Merge branch 'main' into ts-migration/TextLink
MaciejSWM Nov 8, 2023
0ded84a
Make href optional
MaciejSWM Nov 8, 2023
5304f4d
More compact else/if syntax
MaciejSWM Nov 8, 2023
df2d98a
Use discriminating union type for link and onPress
MaciejSWM Nov 9, 2023
eadc4a2
Merge branch 'main' into ts-migration/TextLink
MaciejSWM Nov 9, 2023
65e05f9
Prettier
MaciejSWM Nov 9, 2023
1b89761
Better type for children + export type
MaciejSWM Nov 10, 2023
bc41d43
Extend TextProps; rename props->rest
MaciejSWM Nov 10, 2023
3b4ceaf
Merge branch 'main' into ts-migration/TextLink
MaciejSWM Nov 20, 2023
3e26c7b
Fix merge - apply changes from olx .js file
MaciejSWM Nov 20, 2023
1d5c0af
Lint
MaciejSWM Nov 20, 2023
732efed
Extend ChildrenProps
MaciejSWM Nov 20, 2023
95ab86a
Lint
MaciejSWM Nov 20, 2023
0e109d4
Merge branch 'main' into ts-migration/TextLink
MaciejSWM Nov 27, 2023
cfc444c
Use TextStyles' textAlign type
MaciejSWM Nov 27, 2023
82d1eb7
Merge branch 'main' into ts-migration/TextLink
MaciejSWM Dec 6, 2023
1a8f7ad
Drop js file
MaciejSWM Dec 6, 2023
d95966a
Restore environmentURL
MaciejSWM Dec 6, 2023
ddf0d4e
Merge branch 'main' into ts-migration/TextLink
MaciejSWM Dec 6, 2023
83504ed
Merge branch 'main' into ts-migration/TextLink
MaciejSWM Dec 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 18 additions & 14 deletions src/components/Text.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
import React, {ForwardedRef} from 'react';
// eslint-disable-next-line no-restricted-imports
import {Text as RNText, TextProps as RNTextProps, StyleSheet} from 'react-native';
import type {TextStyle} from 'react-native';
import fontFamily from '@styles/fontFamily';
import useTheme from '@styles/themes/useTheme';
import variables from '@styles/variables';
import ChildrenProps from '@src/types/utils/ChildrenProps';

type TextProps = RNTextProps & {
/** The color of the text */
color?: string;
type TextProps = RNTextProps &
ChildrenProps & {
/** The color of the text */
color?: string;

/** The size of the text */
fontSize?: number;
/** The size of the text */
fontSize?: number;

/** The alignment of the text */
textAlign?: 'left' | 'right' | 'auto' | 'center' | 'justify';
/** The alignment of the text */
textAlign?: TextStyle['textAlign'];

/** Any children to display */
children: React.ReactNode;
/** Any children to display */
children: React.ReactNode;

/** The family of the font to use */
family?: keyof typeof fontFamily;
};
/** The family of the font to use */
family?: keyof typeof fontFamily;
};

function Text({color, fontSize = variables.fontSizeNormal, textAlign = 'left', children = null, family = 'EXP_NEUE', style = {}, ...props}: TextProps, ref: ForwardedRef<RNText>) {
function Text({color, fontSize = variables.fontSizeNormal, textAlign = 'left', children, family = 'EXP_NEUE', style = {}, ...props}: TextProps, ref: ForwardedRef<RNText>) {
const theme = useTheme();

const componentStyle: TextStyle = {
color: color ?? theme.text,
fontSize,
Expand All @@ -36,6 +38,7 @@ function Text({color, fontSize = variables.fontSizeNormal, textAlign = 'left', c
if (!componentStyle.lineHeight && componentStyle.fontSize === variables.fontSizeNormal) {
componentStyle.lineHeight = variables.fontSizeNormalHeight;
}

return (
<RNText
allowFontScaling={false}
Expand All @@ -52,3 +55,4 @@ function Text({color, fontSize = variables.fontSizeNormal, textAlign = 'left', c
Text.displayName = 'Text';

export default React.forwardRef(Text);
export type {TextProps};
101 changes: 0 additions & 101 deletions src/components/TextLink.js

This file was deleted.

79 changes: 79 additions & 0 deletions src/components/TextLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React, {ForwardedRef, forwardRef, KeyboardEventHandler, MouseEventHandler} from 'react';
import {GestureResponderEvent, Text as RNText, StyleProp, TextStyle} from 'react-native';
import useEnvironment from '@hooks/useEnvironment';
import useThemeStyles from '@styles/useThemeStyles';
import * as Link from '@userActions/Link';
import CONST from '@src/CONST';
import Text, {TextProps} from './Text';

type LinkProps = {
/** Link to open in new tab */
href: string;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

href is optional

Suggested change
href: string;
href?: string;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it be optional?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me it makes more sense to have href required for a LinkText component, wdyt?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i.e. FormAlertWrapper doesn't have href

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the code one of 'onPress' and 'href' should be defined:

    const openLink = (event) => {
        event.preventDefault();
        if (props.onPress) {
            props.onPress();
            return;
        }

        Link.openExternalLink(props.href);
    };

My proposal is to use discriminating union @situchan @MaciejSWM:

{ onPress: type; } | { href: type; }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented. I tested and it throws an error as expected when both href and onPress are defined. Nice @blazejkustra


onPress?: undefined;
};

type PressProps = {
href?: undefined;

/** Overwrites the default link behavior with a custom callback */
onPress: () => void;
};

type TextLinkProps = (LinkProps | PressProps) &
TextProps & {
/** Additional style props */
style?: StyleProp<TextStyle>;

/** Callback that is called when mousedown is triggered */
onMouseDown?: MouseEventHandler;
};

function TextLink({href, onPress, children, style, onMouseDown = (event) => event.preventDefault(), ...rest}: TextLinkProps, ref: ForwardedRef<RNText>) {
const {environmentURL} = useEnvironment();
const styles = useThemeStyles();

const openLink = () => {
if (onPress) {
onPress();
} else {
Link.openLink(href, environmentURL);
}
};

const openLinkOnTap = (event: GestureResponderEvent) => {
event.preventDefault();

openLink();
};

const openLinkOnEnterKey: KeyboardEventHandler = (event) => {
if (event.key !== 'Enter') {
return;
}
event.preventDefault();

openLink();
};

return (
<Text
style={[styles.link, style]}
role={CONST.ACCESSIBILITY_ROLE.LINK}
href={href}
onPress={openLinkOnTap}
onKeyDown={openLinkOnEnterKey}
onMouseDown={onMouseDown}
ref={ref}
suppressHighlighting
// eslint-disable-next-line react/jsx-props-no-spreading
{...rest}
>
{children}
</Text>
);
}

TextLink.displayName = 'TextLink';

export default forwardRef(TextLink);