From 9dfe31a2491bd481ae447225f328e89da7525220 Mon Sep 17 00:00:00 2001 From: jameswilddev Date: Tue, 13 Aug 2024 15:46:46 +0100 Subject: [PATCH] Add text decoration. --- .../components/createTextComponent/index.tsx | 29 ++- .../components/createTextComponent/readme.md | 21 +- .../components/createTextComponent/unit.tsx | 230 +++++++++++++++++- 3 files changed, 266 insertions(+), 14 deletions(-) diff --git a/react-native/components/createTextComponent/index.tsx b/react-native/components/createTextComponent/index.tsx index 2678701c..356ba61e 100644 --- a/react-native/components/createTextComponent/index.tsx +++ b/react-native/components/createTextComponent/index.tsx @@ -12,6 +12,8 @@ import type { TextProps } from '../../types/TextProps' * @param multiLine When true, text will wrap across multiple lines when it does * not fit within the available width. When false, text will * be truncated with an ellipsis. + * @param decoration When null, the text is not decorated. Otherwise, a + * description of the decoration to apply. * @returns A new React component which can be used to render text. */ export const createTextComponent = ( @@ -19,7 +21,27 @@ export const createTextComponent = ( fontSize: number, color: ColorValue, alignment: 'left' | 'center' | 'right', - multiLine: boolean + multiLine: boolean, + decoration: null | (({ + readonly underline: true + readonly strikethrough: true + } | { + readonly underline: false + readonly strikethrough: true + } | { + readonly underline: true + readonly strikethrough: false + }) & { + /** + * The style of the text decoration to apply. + */ + readonly style: 'solid' | 'double' | 'dotted' | 'dashed' + + /** + * The color of hte xt d + */ + readonly color: ColorValue + }) ): React.FunctionComponent => { const styles = StyleSheet.create({ text: { @@ -28,7 +50,10 @@ export const createTextComponent = ( lineHeight: fontSize * 1.4, color, textAlign: alignment, - flexShrink: 1 + flexShrink: 1, + textDecorationLine: decoration === null ? 'none' : (decoration.strikethrough ? (decoration.underline ? 'underline line-through' : 'line-through') : 'underline'), + textDecorationColor: decoration === null ? undefined : decoration.color, + textDecorationStyle: decoration === null ? undefined : decoration.style } }) diff --git a/react-native/components/createTextComponent/readme.md b/react-native/components/createTextComponent/readme.md index 0b2aca95..5fdbe46a 100644 --- a/react-native/components/createTextComponent/readme.md +++ b/react-native/components/createTextComponent/readme.md @@ -7,7 +7,7 @@ Creates a new React component which can be used to render text. ```tsx import { createTextComponent } from "react-native-app-helpers"; -const ExampleText = createTextComponent(`example`, `red`, 12, `left`, false); +const ExampleText = createTextComponent(`example`, `red`, 12, `left`, false, null); const ExampleScreen = () => ( @@ -25,7 +25,7 @@ const ExampleScreen = () => ( ```tsx import { createTextComponent } from "react-native-app-helpers"; -const ExampleText = createTextComponent(`example`, `red`, 12, `left`, true); +const ExampleText = createTextComponent(`example`, `red`, 12, `left`, true, null); const ExampleScreen = () => ( @@ -39,3 +39,20 @@ const ExampleScreen = () => ( ); ``` + +```tsx +import { createTextComponent } from "react-native-app-helpers"; + +const ExampleText = createTextComponent(`example`, `red`, 12, `left`, false, { + underline: true, + strikethrough: false, + style: `solid`, // Also: double, dotted, dashed. + color: `blue`, +}); + +const ExampleScreen = () => ( + + This has text decorations applied to it as described above. + +); +``` diff --git a/react-native/components/createTextComponent/unit.tsx b/react-native/components/createTextComponent/unit.tsx index 7de1af16..2ab3415f 100644 --- a/react-native/components/createTextComponent/unit.tsx +++ b/react-native/components/createTextComponent/unit.tsx @@ -9,7 +9,8 @@ test('renders single-line', () => { 37, '#34AE17', 'left', - false + false, + null ) const rendered = Test Content @@ -22,7 +23,10 @@ test('renders single-line', () => { lineHeight: 51.8, color: '#34AE17', textAlign: 'left', - flexShrink: 1 + flexShrink: 1, + textDecorationLine: 'none', + textDecorationStyle: undefined, + textDecorationColor: undefined }} numberOfLines={1} > @@ -37,7 +41,8 @@ test('renders multi-line', () => { 37, '#34AE17', 'left', - true + true, + null ) const rendered = Test Content @@ -50,7 +55,10 @@ test('renders multi-line', () => { lineHeight: 51.8, color: '#34AE17', textAlign: 'left', - flexShrink: 1 + flexShrink: 1, + textDecorationLine: 'none', + textDecorationStyle: undefined, + textDecorationColor: undefined }} numberOfLines={0} > @@ -59,13 +67,206 @@ test('renders multi-line', () => { ) }) +test('renders underlined', () => { + const Component = createTextComponent( + 'Test Font Family', + 37, + '#34AE17', + 'left', + false, + { underline: true, strikethrough: false, style: 'solid', color: 'blue' } + ) + + const rendered = Test Content + + expect(unwrapRenderedFunctionComponent(rendered)).toEqual( + + Test Content + + ) +}) + +test('renders strikethrough', () => { + const Component = createTextComponent( + 'Test Font Family', + 37, + '#34AE17', + 'left', + false, + { underline: false, strikethrough: true, style: 'solid', color: 'blue' } + ) + + const rendered = Test Content + + expect(unwrapRenderedFunctionComponent(rendered)).toEqual( + + Test Content + + ) +}) + +test('renders underlined strikethrough', () => { + const Component = createTextComponent( + 'Test Font Family', + 37, + '#34AE17', + 'left', + false, + { underline: true, strikethrough: true, style: 'solid', color: 'blue' } + ) + + const rendered = Test Content + + expect(unwrapRenderedFunctionComponent(rendered)).toEqual( + + Test Content + + ) +}) + +test('renders double', () => { + const Component = createTextComponent( + 'Test Font Family', + 37, + '#34AE17', + 'left', + false, + { underline: true, strikethrough: false, style: 'double', color: 'blue' } + ) + + const rendered = Test Content + + expect(unwrapRenderedFunctionComponent(rendered)).toEqual( + + Test Content + + ) +}) + +test('renders dotted', () => { + const Component = createTextComponent( + 'Test Font Family', + 37, + '#34AE17', + 'left', + false, + { underline: true, strikethrough: false, style: 'dotted', color: 'blue' } + ) + + const rendered = Test Content + + expect(unwrapRenderedFunctionComponent(rendered)).toEqual( + + Test Content + + ) +}) + +test('renders dashed', () => { + const Component = createTextComponent( + 'Test Font Family', + 37, + '#34AE17', + 'left', + false, + { underline: true, strikethrough: false, style: 'dashed', color: 'blue' } + ) + + const rendered = Test Content + + expect(unwrapRenderedFunctionComponent(rendered)).toEqual( + + Test Content + + ) +}) + test('renders with onPress undefined', () => { const Component = createTextComponent( 'Test Font Family', 37, '#34AE17', 'left', - false + false, + null ) const rendered = Test Content @@ -78,7 +279,10 @@ test('renders with onPress undefined', () => { lineHeight: 51.8, color: '#34AE17', textAlign: 'left', - flexShrink: 1 + flexShrink: 1, + textDecorationLine: 'none', + textDecorationStyle: undefined, + textDecorationColor: undefined }} numberOfLines={1} > @@ -93,7 +297,8 @@ test('renders with onPress set', () => { 37, '#34AE17', 'left', - false + false, + null ) const onPress = jest.fn() @@ -107,7 +312,10 @@ test('renders with onPress set', () => { lineHeight: 51.8, color: '#34AE17', textAlign: 'left', - flexShrink: 1 + flexShrink: 1, + textDecorationLine: 'none', + textDecorationStyle: undefined, + textDecorationColor: undefined }} numberOfLines={1} onPress={expect.any(Function)} @@ -125,7 +333,8 @@ test('executes the press callback once when hitboxes are enabled', () => { 37, '#34AE17', 'left', - false + false, + null ) const onPress = jest.fn() @@ -149,7 +358,8 @@ test('does not execute the press callback when hitboxes are disabled', () => { 37, '#34AE17', 'left', - false + false, + null ) const onPress = jest.fn()