diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 07fd9e9..fe53f2b 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -24,6 +24,8 @@ jobs: cmd: yarn test - name: Types cmd: yarn test:types + - name: Lint + cmd: yarn lint steps: - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: actions/setup-node@aca7b64a59c0063db8564e0ffdadd3887f1cbae5 diff --git a/.nvmrc b/.nvmrc index 4a1f488..2edeafb 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -18.17.1 +20 \ No newline at end of file diff --git a/babel.config.js b/babel.config.js index 4bbd64e..cf1f9fb 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,3 +1,3 @@ module.exports = { - "presets": ["module:metro-react-native-babel-preset"], + presets: ['module:metro-react-native-babel-preset'], } diff --git a/benchmark/chart/chart.js b/benchmark/chart/chart.js index 765be5b..d3471e1 100644 --- a/benchmark/chart/chart.js +++ b/benchmark/chart/chart.js @@ -1,10 +1,10 @@ /* global Chart, results */ -Chart.defaults.global.defaultFontFamily = 'Open Sans'; -Chart.defaults.global.legend.display = false; +Chart.defaults.global.defaultFontFamily = 'Open Sans' +Chart.defaults.global.legend.display = false const createChart = () => { - const chart = new Chart(document.getElementById('chart'), { + return new Chart(document.querySelector('#chart'), { type: 'horizontalBar', data: { labels: Object.keys(results), @@ -15,21 +15,19 @@ const createChart = () => { 'rgba(40, 167, 69, 0.2)', 'rgba(0, 92, 197, 0.2)', 'rgba(111, 66, 193, 0.2)', - 'rgba(215, 58, 73, 0.2)' + 'rgba(215, 58, 73, 0.2)', ], borderColor: [ 'rgb(40, 167, 69)', 'rgb(0, 92, 197)', 'rgb(111, 66, 193)', - 'rgb(215, 58, 73)' + 'rgb(215, 58, 73)', ], - borderWidth: 1 - } - ] - } - }); + borderWidth: 1, + }, + ], + }, + }) +} - return chart; -}; - -createChart(); +createChart() diff --git a/benchmark/index.test.js b/benchmark/index.test.js index eb53876..19e4b8e 100644 --- a/benchmark/index.test.js +++ b/benchmark/index.test.js @@ -1,82 +1,78 @@ -import React from 'react'; +import React from 'react' -import { create as r } from 'react-test-renderer'; +import { create as r } from 'react-test-renderer' -import fs from 'fs'; +import fs from 'fs' -import Benchmark from 'benchmark'; +import Benchmark from 'benchmark' import styled from 'styled-components/native' -import emotion from '@emotion/native'; +import emotion from '@emotion/native' -import shakl from '../src/rn'; - -const suite = new Benchmark.Suite(); +import shakl from '../src/rn' +const suite = new Benchmark.Suite() suite.add('Shakl', () => { - const Foo = shakl.View({ padding: 10 }); - r(); -}); + const Foo = shakl.View({ padding: 10 }) + r() +}) suite.add('Emotion', () => { const Foo = emotion.View`padding: 10px` r() -}); +}) suite.add('Styled Components', () => { - const Foo = styled.View`padding: 10px` + const Foo = styled.View` + padding: 10px; + ` r() -}); +}) -const results = {}; +const results = {} + +afterAll(() => { + const result = `const results = ${JSON.stringify(results, null, 2)};\n` + fs.writeFileSync(`${__dirname}/results.js`, result) +}) it('runs', () => { suite - .on('complete', e => { + .on('complete', (e) => { const { stats: { mean: first }, - name: firstFunc - } = e.currentTarget[0]; + name: firstFunc, + } = e.currentTarget[0] - let min = first; - let max = first; + let min = first + let max = first - let minFunc = firstFunc; - let maxFunc = firstFunc; + let minFunc = firstFunc - let output = ''; + let output = '' e.currentTarget.forEach(({ stats: { mean }, name }) => { if (mean < min) { - min = mean; - minFunc = name; + min = mean + minFunc = name } if (mean > max) { - max = mean; - maxFunc = name; + max = mean } - const result = mean * 1000; + const result = mean * 1000 - results[name] = result; + results[name] = result - output += `${name} averaged ${result} ms\n`; - }); + output += `${name} averaged ${result} ms\n` + }) - output += `\n${minFunc} is min, ${min * 1000} ms\n`; - output += `diff is ${(((max - min) / max) * 100).toFixed(2)}%\n`; + output += `\n${minFunc} is min, ${min * 1000} ms\n` + output += `diff is ${(((max - min) / max) * 100).toFixed(2)}%\n` - console.log(output); + console.log(output) }) - .run(); -}); - -afterAll(() => { - const result = `const results = ${JSON.stringify(results, null, 2)};\n` - fs.writeFileSync( - `${__dirname}/results.js`, - result - ); -}); + .run() +}) diff --git a/benchmark/results.js b/benchmark/results.js index f9963ca..0893c9a 100644 --- a/benchmark/results.js +++ b/benchmark/results.js @@ -1,5 +1,6 @@ +// eslint-disable-next-line no-unused-vars const results = { - "Shakl": 0.02981142424152011, - "Emotion": 0.03720938087122486, - "Styled Components": 0.04661131669539433 -}; + Shakl: 0.029_811_424_241_520_11, + Emotion: 0.037_209_380_871_224_86, + 'Styled Components': 0.046_611_316_695_394_33, +} diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..49b064d --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,25 @@ +import { createTypescriptReactBabelPreset } from '@exodus/eslint-config-exodus' + +const config = [ + { ignores: ['lib', 'node_modules'] }, + createTypescriptReactBabelPreset({ project: ['./tsconfig.test.json'] }), + { + settings: { + 'import/ignore': ['node_modules/react-native/index\\.js$'], + }, + }, + { + files: ['jest.config.js', 'jest-setup.js'], + rules: { + 'import/no-extraneous-dependencies': ['error', { devDependencies: true }], + }, + }, + { + files: ['**/*.type-test.ts{x,}'], + rules: { + '@typescript-eslint/no-unused-vars': 'off', + }, + }, +].flat() + +export default config diff --git a/jest-setup.js b/jest-setup.js index 8080db6..eb527f0 100644 --- a/jest-setup.js +++ b/jest-setup.js @@ -1 +1 @@ -require('react-native-reanimated').setUpTests(); +require('react-native-reanimated').setUpTests() diff --git a/jest.config.js b/jest.config.js index 957c028..e9e90fe 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,13 +1,9 @@ module.exports = { - 'collectCoverageFrom': [ - 'src/**/*.js' + collectCoverageFrom: ['src/**/*.js'], + verbose: true, + preset: 'react-native', + transformIgnorePatterns: [ + '/node_modules/(?!(@react-native|react-native|react-native-reanimated)/).*/', ], - 'verbose': true, - 'preset': 'react-native', - 'transformIgnorePatterns': [ - '/node_modules/(?!(@react-native|react-native|react-native-reanimated)/).*/' - ], - 'setupFilesAfterEnv': [ - './jest-setup.js' - ] + setupFilesAfterEnv: ['./jest-setup.js'], } diff --git a/package.json b/package.json index 904bb83..752a9ce 100755 --- a/package.json +++ b/package.json @@ -11,21 +11,27 @@ "url": "git+https://github.com/sonaye/shakl.git" }, "peerDependencies": { - "react": ">=16.3.0" + "react": ">=16.3.0", + "react-native": "*" }, "devDependencies": { "@babel/core": "^7.24.3", + "@babel/preset-react": "^7.25.9", "@emotion/native": "^11.11.0", "@emotion/react": "^11.11.4", + "@exodus/eslint-config-exodus": "^1.3.1", + "@exodus/prettier": "^1.0.0", "@testing-library/react-native": "^12.4.5", "@tsconfig/react-native": "^3.0.5", "@types/react": "^18.3.11", "babel-jest": "^29.7.0", "benchmark": "2.1.4", "emotion": "9.2.6", + "eslint": "^9.13.0", "jest": "^29.7.0", "metro-react-native-babel-preset": "^0.77.0", "microtime": "^3.1.1", + "prettier": "^3.3.3", "react": "18.2.0", "react-native": "^0.73.6", "react-native-linear-gradient": "^2.8.3", @@ -39,6 +45,7 @@ "test:all": "yarn test && yarn test:types", "test": "jest /test", "test:types": "tsc -p tsconfig.test.json", + "lint": "eslint", "coverage": "yarn test --coverage", "postcoverage": "open -a Chrome coverage/lcov-report/index.html", "benchmark": "jest /benchmark", @@ -48,5 +55,6 @@ }, "files": [ "lib" - ] + ], + "prettier": "@exodus/prettier" } diff --git a/src/index.ts b/src/index.ts index c72aebd..1451b1b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,132 +1,140 @@ -import React from 'react'; -import type {StyleProp} from "react-native"; +import React from 'react' +import type { StyleProp } from 'react-native' export interface Config

{ - name?: string; - props?: Partial

; - style?: any; - fixedStyle?: any; - attrs?: Attrs; - comp?: React.ComponentType; - child?: React.ComponentType; - childProps?: ((props: any) => any) | any; - [key: string]: any; + name?: string + props?: Partial

+ style?: any + fixedStyle?: any + attrs?: Attrs + comp?: React.ComponentType + child?: React.ComponentType + childProps?: ((props: any) => any) | any + [key: string]: any } export type StyledProps = { - childRef?: React.Ref; - style?: StyleProp; -}; + childRef?: React.Ref + style?: StyleProp +} -type WithOptional = Omit & { [P in K]?: P extends keyof T ? T[P] : never } +type WithOptional = Omit & { + [P in K]?: P extends keyof T ? T[P] : never +} type Attrs = ((props: Partial) => Partial) | Partial -type ComponentStyle

= ((props: Partial

& SP) => S) | S +type ComponentStyle

= + | ((props: Partial

& SP) => S) + | S export type StyledComponent

= React.ForwardRefExoticComponent< React.PropsWithoutRef

& { children?: React.ReactNode }> & - React.RefAttributes + React.RefAttributes > & { - extend: (more: ComponentStyle) => StyledComponent

; - attrs: (attrs: Attrs) => StyledComponent, S>; - withComponent: (comp: React.ComponentType) => StyledComponent; - withChild: (child: React.ComponentType, childProps?: any) => StyledComponent; -}; - -const styled =

= {}>( - Comp: React.ComponentType

, - config: Config = {} -) => (componentStyle?: ComponentStyle): StyledComponent, S> => { - const { - name, - props: factoryProps = {}, - style: factoryStyle = {}, - fixedStyle = {}, - ...opts - } = config; - - const Styled = React.forwardRef & { children?: React.ReactNode }>( - (props, ref) => { - const { childRef, children, ...restProps } = props; - const { comp, child, childProps = {} } = opts; - - const attrs = opts.attrs; - const attrsResult = attrs - ? typeof attrs === 'function' - ? attrs(restProps as P) - : attrs - : {}; - - let style = { - ...factoryStyle, - ...(attrsResult as any).style, - ...(typeof componentStyle === 'function' - ? componentStyle(restProps as P & SP) - : componentStyle), - }; - - let styleFromProps = props.style; - - if (Array.isArray(styleFromProps)) { - styleFromProps = styleFromProps.filter((style) => !!style); - } + extend: (more: ComponentStyle) => StyledComponent

+ attrs: (attrs: Attrs) => StyledComponent, S> + withComponent: (comp: React.ComponentType) => StyledComponent + withChild: (child: React.ComponentType, childProps?: any) => StyledComponent +} - if (styleFromProps) { - if ( - typeof styleFromProps === 'number' || - (styleFromProps as any).hasOwnProperty('viewDescriptors') - ) { - style = [style, styleFromProps, fixedStyle]; - } else if (Array.isArray(styleFromProps)) { - style = [style, ...styleFromProps, fixedStyle]; - } else { - style = { - ...style, - ...styleFromProps, - ...fixedStyle, - }; +const styled = +

= {}>( // eslint-disable-line @typescript-eslint/no-empty-object-type + Comp: React.ComponentType

, + config: Config = {} + ) => + ( + componentStyle?: ComponentStyle + ): StyledComponent, S> => { + const { + name, + props: factoryProps = {}, + style: factoryStyle = {}, + fixedStyle = {}, + ...opts + } = config + + const Styled = React.forwardRef & { children?: React.ReactNode }>( + (props, ref) => { + const { childRef, children, ...restProps } = props + const { comp, child, childProps = {} } = opts + + const attrs = opts.attrs + const attrsResult = attrs + ? typeof attrs === 'function' + ? attrs(restProps as P) + : attrs + : {} + + let style = { + ...factoryStyle, + ...(attrsResult as any).style, + ...(typeof componentStyle === 'function' + ? componentStyle(restProps as P & SP) + : componentStyle), } - } - const parentProps = { - ...factoryProps, - ...attrsResult, - ...restProps, - style, - }; - - return React.createElement( - comp || Comp, - { ref, ...parentProps }, - child - ? React.createElement( - child, - { - ref: childRef, - ...(typeof childProps === 'function' - ? childProps(parentProps) - : childProps), - }, - children - ) - : children - ); - } - ); - - Styled.displayName = name || `styled(${Comp.displayName || Comp.name})`; - - // Extend the Styled component with custom methods - const StyledComponent = Object.assign(Styled, { - extend: (more: ComponentStyle) => styled(StyledComponent, { name })(more), - attrs: (attrs: Attrs) => styled(StyledComponent, { attrs })() as StyledComponent, S>, - withComponent: (comp: React.ComponentType) => - styled(StyledComponent, { comp })(componentStyle) as StyledComponent

, - withChild: (child: React.ComponentType, childProps: any) => - styled(StyledComponent, { child, childProps })() as StyledComponent

, - }); - - return StyledComponent as StyledComponent, S>; -}; - -export default styled; + let styleFromProps = props.style + + if (Array.isArray(styleFromProps)) { + styleFromProps = styleFromProps.filter((style) => !!style) + } + + if (styleFromProps) { + if ( + typeof styleFromProps === 'number' || + (styleFromProps as any).hasOwnProperty('viewDescriptors') + ) { + style = [style, styleFromProps, fixedStyle] + } else if (Array.isArray(styleFromProps)) { + style = [style, ...styleFromProps, fixedStyle] + } else { + style = { + ...style, + ...styleFromProps, + ...fixedStyle, + } + } + } + + const parentProps = { + ...factoryProps, + ...attrsResult, + ...restProps, + style, + } + + return React.createElement( + comp || Comp, + { ref, ...parentProps }, + child + ? React.createElement( + child, + { + ref: childRef, + ...(typeof childProps === 'function' ? childProps(parentProps) : childProps), + }, + children + ) + : children + ) + } + ) + + Styled.displayName = name || `styled(${Comp.displayName || Comp.name})` + + // Extend the Styled component with custom methods + const StyledComponent = Object.assign(Styled, { + extend: (more: ComponentStyle) => + styled(StyledComponent, { name })(more), + attrs: (attrs: Attrs) => + styled(StyledComponent, { attrs })() as StyledComponent, S>, + withComponent: (comp: React.ComponentType) => + styled(StyledComponent, { comp })(componentStyle) as StyledComponent

, + withChild: (child: React.ComponentType, childProps: any) => + styled(StyledComponent, { child, childProps })() as StyledComponent

, + }) + + return StyledComponent as StyledComponent, S> + } + +export default styled diff --git a/src/rn.ts b/src/rn.ts index 7880ffe..7118f86 100644 --- a/src/rn.ts +++ b/src/rn.ts @@ -1,27 +1,24 @@ import styled from './index' -import { - Image, +import type { ImageProps, ImageStyle, - Text, TextInputProps, - TextInput, TextProps, TextStyle, - TouchableOpacity, TouchableOpacityProps, - View, ViewProps, ViewStyle, } from 'react-native' +import { Image, Text, TextInput, TouchableOpacity, View } from 'react-native' - -const extended = Object.assign(styled,{ +const extended = Object.assign(styled, { View: styled(View, { name: 'styled(View)' }), Text: styled(Text, { name: 'styled(Text)' }), - Image: styled(Image, { name: "styled(Image)" }), - Touchable: styled(TouchableOpacity, { name: 'styled(Touchable)' }), + Image: styled(Image, { name: 'styled(Image)' }), + Touchable: styled(TouchableOpacity, { + name: 'styled(Touchable)', + }), TextInput: styled(TextInput, { name: 'styled(TextInput)' }), }) -export default extended; +export default extended diff --git a/test/Example.js b/test/Example.js index 993a340..0b67a24 100644 --- a/test/Example.js +++ b/test/Example.js @@ -44,6 +44,12 @@ const ButtonText = s.Text({ color: 'green' }) const AnotherButton = s.Touchable({ flex: 1 }).withChild(ButtonText) +const Container = s(ScrollView, { name: 'Container' })(({ backgroundColor }) => ({ + backgroundColor, +})) + +Container.defaultProps = { backgroundColor: '#000' } + export default class Example extends React.PureComponent { container = React.createRef() @@ -76,9 +82,3 @@ export default class Example extends React.PureComponent { ) } } - -const Container = s(ScrollView, { name: 'Container' })(({ backgroundColor }) => ({ - backgroundColor, -})) - -Container.defaultProps = { backgroundColor: '#000' } diff --git a/test/index.type-test.tsx b/test/index.type-test.tsx index a16dd8c..bc570d8 100644 --- a/test/index.type-test.tsx +++ b/test/index.type-test.tsx @@ -1,75 +1,112 @@ -import React, {Text, ViewStyle} from 'react-native' +import type { ViewStyle } from 'react-native' +import React, { Text } from 'react-native' import styled from '../src/index' import extendedStyled from '../src/rn' -import {useRef} from "react"; -import LinearGradient, { LinearGradientProps } from 'react-native-linear-gradient' +import { useRef } from 'react' +import type { LinearGradientProps } from 'react-native-linear-gradient' +import LinearGradient from 'react-native-linear-gradient' -const StyledText = styled(Text)(({ transparent }: { transparent?: boolean; color: string }) => ({ flex: 1, opacity: transparent ? 0.5 : 1 })) +const StyledText = styled(Text)(({ transparent }: { transparent?: boolean; color: string }) => ({ + flex: 1, + opacity: transparent ? 0.5 : 1, +})) const StyledTextWithAttrs = StyledText.attrs({ color: 'black' }) const StyledTextWithAttrsFromConfig = styled(StyledText, { attrs: { color: 'black' } })() -const StyledScalableText = StyledText.extend(({ big }: { big?: boolean }) => ({ fontSize: big ? 20 : 10 })) +const StyledScalableText = StyledText.extend(({ big }: { big?: boolean }) => ({ + fontSize: big ? 20 : 10, +})) const StyledTextWithObjectProps = styled(Text)({ flex: 1, opacity: 1 }) -const ExtendedStyledText = extendedStyled.Text(({ transparent }: { transparent?: boolean; }) => ({ flex: 1, opacity: transparent ? 0.5 : 1 })) -const ExtendedStyledTextWithStyle = extendedStyled(Text)((props: {specificColor: string}) => ({color: props.specificColor})) -const ExtenedStyledTextWithAttrs = extendedStyled.Text(({ transparent }: { transparent?: boolean; big?:boolean }) => ({ flex: 1, opacity: transparent ? 0.5 : 1 })).attrs(({ big}) => ({ - ellipsizeMode: big ? 'middle' : 'head', +const ExtendedStyledText = extendedStyled.Text(({ transparent }: { transparent?: boolean }) => ({ + flex: 1, + opacity: transparent ? 0.5 : 1, })) +const ExtendedStyledTextWithStyle = extendedStyled(Text)((props: { specificColor: string }) => ({ + color: props.specificColor, +})) +const ExtenedStyledTextWithAttrs = extendedStyled + .Text(({ transparent }: { transparent?: boolean; big?: boolean }) => ({ + flex: 1, + opacity: transparent ? 0.5 : 1, + })) + .attrs(({ big }) => ({ + ellipsizeMode: big ? 'middle' : 'head', + })) -const StyledView = extendedStyled.View({width: 100}) -const StyledViewWithDynamicProps = extendedStyled.View((props: {active: boolean}) => ({width: props.active ? 100 : 50})) +const StyledView = extendedStyled.View({ width: 100 }) +const StyledViewWithDynamicProps = extendedStyled.View((props: { active: boolean }) => ({ + width: props.active ? 100 : 50, +})) const Row = extendedStyled.View((props: { spaced?: boolean; full?: boolean }) => ({ - alignItems: 'center', - flexDirection: 'row', - justifyContent: props.spaced ? 'space-between' : undefined, - width: props.full ? '100%' : undefined, + alignItems: 'center', + flexDirection: 'row', + justifyContent: props.spaced ? 'space-between' : undefined, + width: props.full ? '100%' : undefined, })) +const StyledImage = extendedStyled.Image({ width: 100 }) +const StyledImageWithDynamicProps = extendedStyled.Image((props: { active: boolean }) => ({ + width: props.active ? 100 : 50, +})) -const StyledImage = extendedStyled.Image({width: 100}) -const StyledImageWithDynamicProps = extendedStyled.Image((props: {active: boolean}) => ({width: props.active ? 100 : 50})) - -const StyledTouchable = extendedStyled.Touchable({width: 100}) -const StyledTouchableWithDynamicProps = extendedStyled.Image((props: {active: boolean}) => ({width: props.active ? 100 : 50})) +const StyledTouchable = extendedStyled.Touchable({ width: 100 }) +const StyledTouchableWithDynamicProps = extendedStyled.Image((props: { active: boolean }) => ({ + width: props.active ? 100 : 50, +})) const ViewWithText = extendedStyled.View({}).withChild(StyledText) const extendedWithLinear = Object.assign(extendedStyled, { - LinearGradient: styled(LinearGradient, { - name: 'styled(LinearGradient)', - }) + LinearGradient: styled(LinearGradient, { + name: 'styled(LinearGradient)', + }), }) -const DangerGradient = styled(LinearGradient)().attrs({ colors: ['orange', 'red']}) -const DefaultGradient = extendedWithLinear.LinearGradient({ }).attrs({ - colors: ['blue', 'green'], +const DangerGradient = styled(LinearGradient)().attrs({ colors: ['orange', 'red'] }) +const DefaultGradient = extendedWithLinear.LinearGradient({}).attrs({ + colors: ['blue', 'green'], }) const MyScreen = () => { - const ref = useRef() + const ref = useRef() return ( <> - Hello Transparent World - Hello Transparent World with ref - Color set through .attrs() and therefore not required - Color is set through config.attrs and therefore not required + + Hello Transparent World + + + Hello Transparent World with ref + + + Color set through .attrs() and therefore not required + + + Color is set through config.attrs and therefore not required + {/* should also work without transparent prop */} Hello World {/* @ts-expect-error -- should not work without required color prop */} Hello World {/* @ts-expect-error -- big is only available on StyledScalableText */} - Hello World - Hi + + Hello World + + + Hi + {/* @ts-expect-error -- transparent prop is not allowed */} Hi Hello Extended World - Hello Extended World - Text with inline style + + Hello Extended World + + + Text with inline style + Just a View - - some text - - + + some text + View with dynamic style @@ -77,12 +114,14 @@ const MyScreen = () => { Image with dynamic style Touchable - Touchable with dynamic style + + Touchable with dynamic style + {/* @ts-expect-error -- missing "colors" */} - + {/* doesn't require optional props */} diff --git a/test/reanimated.test.js b/test/reanimated.test.js index 9a424bf..bb365e2 100644 --- a/test/reanimated.test.js +++ b/test/reanimated.test.js @@ -1,48 +1,56 @@ import React from 'react' -import Animated, {useSharedValue, useAnimatedStyle} from 'react-native-reanimated' -import { render } from '@testing-library/react-native'; +import Animated, { useSharedValue, useAnimatedStyle } from 'react-native-reanimated' +import { render } from '@testing-library/react-native' import s from '../src/rn' - it('works with reanimated styles', () => { const AnimatedComponent = () => { const animatedValue = useSharedValue(0.5) const Foo = s(Animated.View)({ flex: 1, opacity: 0 }) - const animatedStyle = useAnimatedStyle(() => ({opacity: animatedValue.value}), [animatedValue]) + const animatedStyle = useAnimatedStyle( + () => ({ opacity: animatedValue.value }), + [animatedValue] + ) return } - - const { getByTestId } = render(); - const element = getByTestId('foo'); - expect(element.props.style).toEqual({opacity: 0.5, flex: 1}) - expect(element).toHaveAnimatedStyle({opacity: 0.5}) + + const { getByTestId } = render() + const element = getByTestId('foo') + expect(element.props.style).toEqual({ opacity: 0.5, flex: 1 }) + expect(element).toHaveAnimatedStyle({ opacity: 0.5 }) }) it('works with reanimated styles when use array', () => { const AnimatedComponent = () => { const animatedValue = useSharedValue(0.5) const Foo = s(Animated.View)({ flex: 1, opacity: 0 }) - const animatedStyle = useAnimatedStyle(() => ({opacity: animatedValue.value}), [animatedValue]) - return + const animatedStyle = useAnimatedStyle( + () => ({ opacity: animatedValue.value }), + [animatedValue] + ) + return } - - const { getByTestId } = render(); - const element = getByTestId('foo'); - expect(element.props.style).toEqual({opacity: 0.5, flex: 1, width: 50}) - expect(element).toHaveAnimatedStyle({opacity: 0.5}) + + const { getByTestId } = render() + const element = getByTestId('foo') + expect(element.props.style).toEqual({ opacity: 0.5, flex: 1, width: 50 }) + expect(element).toHaveAnimatedStyle({ opacity: 0.5 }) }) it('works with reanimated styles when use array and some style is undefined', () => { const AnimatedComponent = () => { const animatedValue = useSharedValue(0.5) const Foo = s(Animated.View)({ flex: 1, opacity: 0 }) - const animatedStyle = useAnimatedStyle(() => ({opacity: animatedValue.value}), [animatedValue]) - return + const animatedStyle = useAnimatedStyle( + () => ({ opacity: animatedValue.value }), + [animatedValue] + ) + return } - - const { getByTestId } = render(); - const element = getByTestId('foo'); - expect(element.props.style).toEqual({opacity: 0.5, flex: 1, width: 50}) - expect(element).toHaveAnimatedStyle({opacity: 0.5}) + + const { getByTestId } = render() + const element = getByTestId('foo') + expect(element.props.style).toEqual({ opacity: 0.5, flex: 1, width: 50 }) + expect(element).toHaveAnimatedStyle({ opacity: 0.5 }) }) diff --git a/test/stylesheet.test.js b/test/stylesheet.test.js index 0babeaf..4220e46 100644 --- a/test/stylesheet.test.js +++ b/test/stylesheet.test.js @@ -3,58 +3,54 @@ import React from 'react' import { render } from '@testing-library/react-native' import s from '../src/rn' -import { - View, - StyleSheet -} from 'react-native' +import { View, StyleSheet } from 'react-native' it('works with stylesheet styles', () => { const stylesheetStyle = StyleSheet.create({ foo: { - marginBottom: 10 - } + marginBottom: 10, + }, }) const StyledComponent = () => { const Foo = s(View)({ flex: 1, - opacity: 0 + opacity: 0, }) - return + return } - + const { getByTestId } = render() const element = getByTestId('foo') expect(element.props.style).toEqual({ marginBottom: 10, flex: 1, - opacity: 0 + opacity: 0, }) }) it('works with stylesheet styles when use array', () => { const stylesheetStyle = StyleSheet.create({ foo: { - marginBottom: 10 - } + marginBottom: 10, + }, }) const StyledComponent = () => { const Foo = s(View)({ flex: 1, - opacity: 0 + opacity: 0, }) - return + return } - + const { getByTestId } = render() const element = getByTestId('foo') - expect(element.props.style).toEqual([{ - 'flex': 1, - 'opacity': 0 - }, { 'marginBottom': 10 }, { 'width': 10 }, {}]) + expect(element.props.style).toEqual([ + { + flex: 1, + opacity: 0, + }, + { marginBottom: 10 }, + { width: 10 }, + {}, + ]) }) diff --git a/tsconfig.json b/tsconfig.json index 8216542..15fbc49 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,5 @@ "noEmit": false, "declaration": true }, - "include": ["src/**/*"] } diff --git a/tsconfig.test.json b/tsconfig.test.json index 573b11c..e1e1835 100644 --- a/tsconfig.test.json +++ b/tsconfig.test.json @@ -4,5 +4,8 @@ "rootDir": ".", "noEmit": true }, - "include": ["test/**/*.tsx"], + "include": [ + "test/**/*.ts*", + "src/**/*.ts*" + ], }