Skip to content

Commit

Permalink
feat(theme): token integration (#191)
Browse files Browse the repository at this point in the history
  • Loading branch information
artyorsh authored and malashkevich committed Dec 10, 2018
1 parent 34f560a commit c97fa06
Show file tree
Hide file tree
Showing 36 changed files with 855 additions and 254 deletions.
5 changes: 5 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const { defaults: tsJestConfig } = require('ts-jest/presets');
const { pathsToModuleNameMapper } = require('ts-jest/utils');
const jestConfig = require('./tsconfig.jest');

module.exports = {
...tsJestConfig,
Expand All @@ -14,6 +16,9 @@ module.exports = {
},
},
cacheDirectory: './dist/jest',
moduleNameMapper: pathsToModuleNameMapper(jestConfig.compilerOptions.paths, {
prefix: '<rootDir>/',
}),
modulePathIgnorePatterns: [
'<rootDir>/src/playground/'
],
Expand Down
7 changes: 3 additions & 4 deletions src/framework/theme/component/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export { ThemeProvider } from './themeProvider.component';
export { withTheme } from './themeConsumer.component';
export { withThemedStyles } from './themeConsumerStyled.component';
export { ThemeType } from './type';
export * from './mapping';
export * from './theme';
export * from './style';
5 changes: 5 additions & 0 deletions src/framework/theme/component/mapping/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './type';
export {
MappingProvider as ThemeMappingProvider,
Props as ThemeMappingProviderProps,
} from './mappingProvider.component';
7 changes: 7 additions & 0 deletions src/framework/theme/component/mapping/mappingContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react';
import { ThemeMappingType } from './type';

const defaultValue: ThemeMappingType[] = [];
const MappingContext = React.createContext(defaultValue);

export default MappingContext;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import MappingContext from './mappingContext';
import { ThemeMappingType } from './type';

export interface Props {
mapping: ThemeMappingType[];
children: JSX.Element | React.ReactNode;
}

export class MappingProvider extends React.PureComponent<Props> {

render() {
return (
<MappingContext.Provider
value={this.props.mapping}>
{this.props.children}
</MappingContext.Provider>
);
}
}
22 changes: 22 additions & 0 deletions src/framework/theme/component/mapping/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export interface ThemeMappingType {
name: string;
parameters: ParameterType[];
variants: VariantType[];
}

export interface ParameterType {
name: string;
}

export interface VariantType {
name: string;
mapping: MappingType[];
}

export interface MappingType {
parameter: string;
token: string;
}

// TODO(mapping/type): declare Token type
export type TokenType = any;
9 changes: 9 additions & 0 deletions src/framework/theme/component/style/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export {
StyleProvider,
Props as StyleProviderProps,
} from './styleProvider.component';

export {
StyledComponent,
Props as StyledComponentProps,
} from './styleConsumer.component';
78 changes: 78 additions & 0 deletions src/framework/theme/component/style/styleConsumer.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React from 'react';
import {
ThemeType,
StyleType,
} from '../theme';
import { ThemeMappingType } from '../mapping';
import ThemeContext from '../theme/themeContext';
import MappingContext from '../mapping/mappingContext';
import {
createStyle,
getComponentThemeMapping,
} from '../../service';

interface PrivateProps<T> {
forwardedRef: React.RefObject<T>;
}

interface ConsumerProps {
mapping: ThemeMappingType[];
theme: ThemeType;
}

export interface Props {
variant: string;
theme?: ThemeType;
themedStyle?: StyleType;
}

export const StyledComponent = <T extends React.Component, P extends object>(Component: React.ComponentClass<P>) => {

type ComponentProps = Props & P;
type WrapperProps = PrivateProps<T> & ComponentProps;

class Wrapper extends React.Component<WrapperProps> {

getComponentName = (): string => Component.displayName || Component.name;

createCustomProps = (props: ConsumerProps, variant: string): Props => {
const mapping = getComponentThemeMapping(this.getComponentName(), props.mapping);
return {
variant: variant,
theme: props.theme,
themedStyle: mapping && props.theme && createStyle(props.theme, mapping, variant),
};
};

renderWrappedComponent = (props: ConsumerProps) => {
// TS issue: with spreading Generics https://github.com/Microsoft/TypeScript/issues/15792
const { forwardedRef, ...restProps } = this.props as PrivateProps<T>;
const componentProps = restProps as P & Props;
return (
<Component
ref={forwardedRef}
{...this.createCustomProps(props, componentProps.variant)}
{...componentProps}
/>
);
};

render() {
return (
<MappingContext.Consumer>{(mapping: ThemeMappingType[]) => (
<ThemeContext.Consumer>{(theme: ThemeType) => {
return this.renderWrappedComponent({ mapping: mapping, theme: theme });
}}</ThemeContext.Consumer>
)}</MappingContext.Consumer>
);
}
}

const RefForwardingFactory = (props: WrapperProps, ref: T) => {
return (
<Wrapper {...props} forwardedRef={ref}/>
);
};

return React.forwardRef<T, P>(RefForwardingFactory as any);
};
45 changes: 45 additions & 0 deletions src/framework/theme/component/style/styleProvider.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react';
import {
ThemeProvider,
ThemeType,
} from '../theme';
import {
ThemeMappingProvider,
ThemeMappingType,
} from '../mapping';

export interface Props {
mapping: ThemeMappingType[];
theme: ThemeType;
children: JSX.Element | React.ReactNode;
}

interface State {
mapping: ThemeMappingType[];
theme: ThemeType;
}

export class StyleProvider extends React.Component<Props, State> {

static getDerivedStateFromProps(props: Props): State {
return {
mapping: props.mapping,
theme: props.theme,
};
}

state: State = {
mapping: [],
theme: {},
};

render() {
return (
<ThemeMappingProvider mapping={this.state.mapping}>
<ThemeProvider theme={this.state.theme}>
{this.props.children}
</ThemeProvider>
</ThemeMappingProvider>
);
}
}
9 changes: 9 additions & 0 deletions src/framework/theme/component/theme/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export * from './type';
export {
ThemeProvider,
Props as ThemeProviderProps,
} from './themeProvider.component';
export {
withStyles,
Props as ThemedComponentProps,
} from './themeConsumer.component';
69 changes: 69 additions & 0 deletions src/framework/theme/component/theme/themeConsumer.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React from 'react';
import { StyleSheet } from 'react-native';
import ThemeContext from './themeContext';
import {
ThemeType,
ThemedStyleType,
StyleSheetType,
} from './type';

interface PrivateProps<T> {
forwardedRef: React.RefObject<T>;
}

interface ConsumerProps {
theme: ThemeType;
}

export interface Props {
theme: ThemeType;
themedStyle: ThemedStyleType | undefined;
}

export type CreateStylesFunction = (theme: ThemeType) => StyleSheetType;

export const withStyles = <T extends React.Component, P extends object>(Component: React.ComponentClass<P>,
createStyles?: CreateStylesFunction) => {

type ComponentProps = Props & P;
type WrapperProps = PrivateProps<T> & ComponentProps;

class Wrapper extends React.Component<WrapperProps> {

createCustomProps = (props: ConsumerProps): Props => {
return ({
theme: props.theme,
themedStyle: createStyles ? createStyles(props.theme) : undefined,
});
};

renderWrappedComponent = (props: ConsumerProps) => {
// TS issue: with spreading Generics https://github.com/Microsoft/TypeScript/issues/15792
const { forwardedRef, ...restProps } = this.props as PrivateProps<T>;
const componentProps = restProps as P & Props;
return (
<Component
ref={forwardedRef}
{...this.createCustomProps(props)}
{...componentProps}
/>
);
};

render() {
return (
<ThemeContext.Consumer>{(theme: ThemeType) => {
return this.renderWrappedComponent({theme: theme});
}}</ThemeContext.Consumer>
);
}
}

const RefForwardingFactory = (props: WrapperProps, ref: T) => {
return (
<Wrapper {...props} forwardedRef={ref}/>
);
};

return React.forwardRef<T, P>(RefForwardingFactory as any);
};
7 changes: 7 additions & 0 deletions src/framework/theme/component/theme/themeContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react';
import { ThemeType } from './type';

const defaultValue: ThemeType = {};
const ThemeContext = React.createContext(defaultValue);

export default ThemeContext;
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
import React, { ReactNode } from 'react';
import { Provider } from '../service';
import ThemeContext from './themeContext';
import { ThemeType } from './type';

interface Props {
children: JSX.Element | ReactNode;
export interface Props {
theme: ThemeType;
children: JSX.Element | ReactNode;
}

export class ThemeProvider extends React.PureComponent<Props> {

static defaultProps = {
theme: {},
};

render() {
return (
<Provider
<ThemeContext.Provider
value={this.props.theme}>
{this.props.children}
</Provider>
</ThemeContext.Provider>
);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// TODO(@type): declare theme types
// TODO(theme/type): declare Theme types

export type ThemeType = any;
export type StyleType = any;
export type ThemedStyleType = any;
export type StyleSheetType = any;
48 changes: 0 additions & 48 deletions src/framework/theme/component/themeConsumer.component.tsx

This file was deleted.

Loading

0 comments on commit c97fa06

Please sign in to comment.