Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(components): update useStyleSheet hook #833

Merged
merged 4 commits into from
Jan 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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