Skip to content

Commit

Permalink
refactor(components): update useStyleSheet hook
Browse files Browse the repository at this point in the history
  • Loading branch information
artyorsh authored Jan 21, 2020
1 parent de531b9 commit 8b33c91
Show file tree
Hide file tree
Showing 16 changed files with 242 additions and 150 deletions.
2 changes: 1 addition & 1 deletion src/components/theme/application/application.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ import {
ApplicationProvider,
ApplicationProviderProps,
} from './applicationProvider.component';
import { ThemeType } from '../theme/theme.service';
import {
mapping,
theme,
themeInverse,
} from '../support/tests';
import { ThemeType } from '../style/styleSheet.service';

describe('@app: application wrapper check', () => {

Expand Down
15 changes: 9 additions & 6 deletions src/components/theme/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ export {
StyledComponentProps,
StyledComponentClass,
} from './style/styled';
export { useStyleSheet } from './style/useStyleSheet';
export {
StyleService,
useStyleSheet,
} from './style/style.service';
export {
StyleType,
Styles,
ThemeType,
} from './style/styleSheet.service';
export {
Interaction,
State,
} from './style/type';
} from './style/style.service';
export {
ThemeProvider,
ThemeProviderProps,
Expand All @@ -35,4 +35,7 @@ export {
ThemedComponentProps,
ThemedComponentClass,
} from './theme/withStyles';
export { useTheme } from './theme/useTheme';
export {
ThemeType,
useTheme,
} from './theme/theme.service';
108 changes: 108 additions & 0 deletions src/components/theme/style/style.service.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/**
* @license
* Copyright Akveo. All Rights Reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*/

import { StyleSheet } from 'react-native';
import {
ThemeService,
ThemeType,
useTheme,
} from '../theme/theme.service';


export type StyleType = Record<string, any>;
export type Styles<T> = StyleSheet.NamedStyles<T>;

/**
* User interactions that can be handled by Eva.
*/
export enum Interaction {
HOVER = 'hover',
ACTIVE = 'active',
FOCUSED = 'focused',
INDETERMINATE = 'indeterminate',
VISIBLE = 'visible',
}

/**
* Component states that can be handled by Eva.
*/
export enum State {
CHECKED = 'checked',
SELECTED = 'selected',
DISABLED = 'disabled',
}

/**
* Takes a theme provided by ApplicationProvider or ThemeProvider and applies it to style.
* Consider not using this function when not using Eva theme variables.
*
* @overview-example UseStyleSheetSimpleUsage
*/
export const useStyleSheet = <T extends Styles<T>>(styles: Styles<T>): T => {
const theme: ThemeType = useTheme();

return StyleService.createThemed(styles, theme);
};

/**
* Service for creating styles that fit current theme.
* Unlike StyleSheet class exported from React Native package, it allows using Eva theme variables.
*/
export class StyleService {

/**
* Unlike `StyleSheet.create` from RN package,
* this does nothing with `styles` validation because of inability to process Eva theme variables
* and returns styles as it is just to support the syntax we used to.
*
* However, this may be useful to have this function
* because future RN versions may allow pre-processing.
* @see {StyleSheet.setStyleAttributePreprocessor}
*
* Notice it is better to use `StyleSheet.create` from RN package since it does style registering.
* You don't need to use this function if custom variables are not used.
*
* When using Eva theme variables, `useStyleSheet` should be called.
*
* @example
* ```
* const Component = () => {
* const styles = useStyleSheet(themedStyles);
* return (
* <View style={styles.container} />
* );
* };
*
* const themedStyles = StyleService.create({
* container: { backgroundColor: 'color-primary-default' },
* });
* ```
*/
static create = <T extends Styles<T>>(styles: T): T => {
return styles;
};

/**
* @returns stylesheet mapped to theme
*/
static createThemed = <T extends Styles<T>>(styles: Styles<T>, theme: ThemeType): T => {
return Object.keys(styles).reduce((acc: T, key: string): T => {
return { ...acc, [key]: StyleService.createThemedEntry(styles[key], theme) };
}, {} as T);
};

/**
* @returns a style mapped to theme
*/
static createThemedEntry = (style: StyleType, theme: ThemeType): StyleType => {
return Object.keys(style).reduce((acc: StyleType, key: string): StyleType => {
const value: any = style[key];
return { ...acc, [key]: ThemeService.getValue(value, theme, value) };
}, {});
};
}


21 changes: 12 additions & 9 deletions src/components/theme/style/style.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@ import {
StyledComponentProps,
} from './styled';
import { StyleConsumerService } from './styleConsumer.service';
import { Interaction } from './type';
import {
StyleSheet,
StyleService,
Interaction,
} from './style.service';
import {
ThemeService,
ThemeType,
} from './styleSheet.service';
} from '../theme/theme.service';
import {
styles,
theme,
Expand Down Expand Up @@ -134,27 +137,27 @@ describe('@style: consumer service methods check', () => {
describe('@style-sheet: service checks', () => {

it('finds theme value properly', async () => {
const themeValue = StyleSheet.getThemeValue('gray-100', theme);
const undefinedValue = StyleSheet.getThemeValue('undefined', theme);
const themeValue = ThemeService.getValue('gray-100', theme);
const undefinedValue = ThemeService.getValue('undefined', theme);

expect(themeValue).toEqual(theme['gray-100']);
expect(undefinedValue).toBeUndefined();
});

it('finds referencing theme value properly', async () => {
const themeValue = StyleSheet.getThemeValue('referencing', theme);
const themeValue = ThemeService.getValue('referencing', theme);

expect(themeValue).toEqual(theme['gray-100']);
});

it('finds multiple referencing theme value properly', async () => {
const themeValue = StyleSheet.getThemeValue('double-referencing', theme);
const themeValue = ThemeService.getValue('double-referencing', theme);

expect(themeValue).toEqual(theme['gray-100']);
});

it('finds referencing theme value properly (initial reference)', async () => {
const themeValue = StyleSheet.getThemeValue('referencing', theme);
const themeValue = ThemeService.getValue('referencing', theme);

expect(themeValue).toEqual(theme['gray-100']);
});
Expand All @@ -167,7 +170,7 @@ describe('@style-sheet: service checks', () => {
prop4: 42,
};

const value = StyleSheet.createThemedStyle(mapping as ViewStyle, theme);
const value = StyleService.createThemedEntry(mapping as ViewStyle, theme);
expect(value).toMatchSnapshot();
});

Expand Down
13 changes: 7 additions & 6 deletions src/components/theme/style/styleConsumer.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import {
} from '@eva-design/dss';
import { StyledComponentProps } from './styled';
import {
StyleSheet,
Interaction,
StyleService,
StyleType,
ThemeType,
} from './styleSheet.service';
import { Interaction } from './type';
} from './style.service';
import { ThemeType } from '../theme/theme.service';

const SEPARATOR_MAPPING_ENTRY: string = '.';

Expand Down Expand Up @@ -84,7 +84,7 @@ export class StyleConsumerService {
}

const mapping: StyleType = this.withValidParameters(generatedMapping);
const themedStyle: StyleType = StyleSheet.createThemedStyle(mapping, theme);
const themedStyle: StyleType = StyleService.createThemedEntry(mapping, theme);

return { ...source, theme, themedStyle };
}
Expand Down Expand Up @@ -125,7 +125,8 @@ export class StyleConsumerService {
return mapping;
}

private getStyleInfo<P extends StyledComponentProps>(props: P, interaction: Interaction[]): StyleInfo {
private getStyleInfo<P extends StyledComponentProps>(props: P,
interaction: Interaction[]): StyleInfo {
const variantProps: Partial<P> = this.getDerivedVariants(this.meta, props);
const stateProps: Partial<P> = this.getDerivedStates(this.meta, props);

Expand Down
63 changes: 0 additions & 63 deletions src/components/theme/style/styleSheet.service.ts

This file was deleted.

15 changes: 9 additions & 6 deletions src/components/theme/style/styled.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import hoistNonReactStatics from 'hoist-non-react-statics';
import { ThemeStyleType } from '@eva-design/dss';
import { StyleConsumerService } from './styleConsumer.service';
import {
Interaction,
StyleType,
ThemeType,
} from './styleSheet.service';
import { Interaction } from './type';
} from './style.service';
import { MappingContext } from '../mapping/mappingContext';
import { ThemeContext } from '../theme/themeContext';
import { ThemeType } from '../theme/theme.service';

interface PrivateProps<T> {
forwardedRef?: React.Ref<T>;
Expand Down Expand Up @@ -96,7 +96,9 @@ export const styled = <P extends object>(Component: React.ComponentType<P>): Sty
this.setState({ interaction });
};

private withStyledProps = (source: P, style: ThemeStyleType, theme: ThemeType): WrappedProps => {
private withStyledProps = (source: P,
style: ThemeStyleType,
theme: ThemeType): WrappedProps => {
const { interaction } = this.state;

const props: WrappingProps = { ...this.defaultProps, ...source };
Expand Down Expand Up @@ -125,14 +127,15 @@ export const styled = <P extends object>(Component: React.ComponentType<P>): Sty
return (
<MappingContext.Consumer>{(style: ThemeStyleType): WrappedElement => (
<ThemeContext.Consumer>{(theme: ThemeType): WrappedElement => {
return this.renderWrappedElement(style, theme);
return this.renderWrappedElement(style, theme);
}}</ThemeContext.Consumer>
)}</MappingContext.Consumer>
);
}
}

const WrappingElement = (props: WrappingProps, ref: React.Ref<WrappedElementInstance>): WrappingElement => {
const WrappingElement = (props: WrappingProps,
ref: React.Ref<WrappedElementInstance>): WrappingElement => {
return (
// @ts-ignore

Expand Down
13 changes: 0 additions & 13 deletions src/components/theme/style/type.ts

This file was deleted.

20 changes: 0 additions & 20 deletions src/components/theme/style/useStyleSheet.tsx

This file was deleted.

Loading

0 comments on commit 8b33c91

Please sign in to comment.