Skip to content

Commit

Permalink
docs(theme): add theme components documentation (#387)
Browse files Browse the repository at this point in the history
  • Loading branch information
artyorsh authored and 32penkin committed May 14, 2019
1 parent 664a823 commit c2e5be0
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 10 deletions.
50 changes: 48 additions & 2 deletions src/framework/theme/application/applicationProvider.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import React from 'react';
import merge from 'lodash.merge';
import { SchemaProcessor } from '@eva/processor-kitten';
import {
ThemeStyleType,
SchemaType,
CustomSchemaType,
SchemaType,
ThemeStyleType,
} from '@eva/core';
import { StyleProvider } from '../style/styleProvider.component';
import { ThemeProviderProps } from '../theme/themeProvider.component';
Expand All @@ -29,6 +29,52 @@ interface State {
theme: ThemeType;
}

/**
* The `ApplicationProvider` component is designed to be a root of the application.
*
* This does basically two things:
* - Provides styles for react-native-ui-kitten basic components (e.g `Button`);
* - Renders modal window which is used to be common for all elements presented as modal;
*
* @extends React.Component
*
* @property {SchemaType} mapping - Determines the mapping for basic components.
* This is designed to be provided by developers team and can be imported from npm package (e.g `@eva/eva`).
*
* @property {CustomSchemaType} customMapping - Determines the customization mapping.
* This is merged with `mapping` property and designed to be used components customization.
* Optional.
*
* @property {ThemeType} theme - Determines the theme for basic components.
* This is designed to be provided by developers team and can be imported from npm package (e.v `@eva/theme-eva`).
*
* @property {React.ReactNode} children - Determines application root component.
*
* @property ThemeProviderProps
*
* @example ApplicationProvider API example
*
* ```
* import { mapping } from '@eva/eva';
* import { theme } from '@eva/theme-eva';
* import { ApplicationProvider } from '@kitten/theme';
* import { Application } from './path-to/root.component';
*
* export default class App extends React.Component {
*
* public render(): React.ReactNode {
* return (
* <ApplicationProvider
* mapping={mapping}
* theme={theme}>
* <Application/>
* </ApplicationProvider>
* );
* }
* }
* ```
*/

export class ApplicationProvider extends React.Component<ApplicationProviderProps, State> {

private schemaProcessor: SchemaProcessor = new SchemaProcessor();
Expand Down
92 changes: 91 additions & 1 deletion src/framework/theme/style/styleConsumer.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,97 @@ export interface ContextProps {

export type StyledComponentClass<P> = React.ComponentClass<StyledComponentProps & P>;

export const styled = <P, T = {}>(Component: React.ComponentClass<P>): StyledComponentClass<P> => {
/**
* The `styled` function is a High Order Function which is used to apply style `mapping`s on components.
*
* To be styled, source component class should have static `styledComponentName` property which defines
* corresponding component name in `mapping`. (e.g 'Button' for `Button` class).
*
* Passes following props to `Component` when it is rendered:
*
* @property {string} appearance - Determines style appearance of component. Default is provided by mapping.
* @property {ThemeType} theme - Determines theme used to style component.
* @property {StyleType} themedStyle - Determines component style for it's current state.
* @property {(interaction: Interaction[]) => void} - Determines function
* for dispatching current state of component. This is designed to be used as style request function.
* Calls component re-render if style for requested state differ from current.
*
* @param {React.ComponentClass} Component - Determines class of component to be styled.
*
* @example Declaring Styled Component
*
* ```
* import {
* styled,
* StyledComponentProps,
* Interaction,
* } from '@kitten/theme';
*
* type StyledButtonProps = ButtonProps & StyledComponentProps;
*
* class Button extends React.Component<StyledButtonProps> {
*
* // Define component name used in `mapping`
* static styledComponentName: string = 'Button';
*
* private onPressIn = (e: GestureResponderEvent) => {
* // Request styles for `active` state and re-render
*
* this.props.dispatch([Interaction.ACTIVE]);
*
* if(this.props.onPressIn) {
* this.props.onPressIn(e);
* }
* };
*
* private onPressOut = (e: GestureResponderEvent) => {
* // Request styles for default state and re-render
*
* this.props.dispatch([]);
*
* if(this.props.onPressOut) {
* this.props.onPressOut(e);
* }
* };
*
* public render(): React.ReactElement<ButtonProps> {
* // Retrieve styles for current state from props (provided with themedStyle prop)
* // And apply it with saving priority of `style` prop
*
* const { style, themedStyle, ...restProps } = this.props;
*
* return (
* <TouchableOpacity
* {...restProps}
* style={[themedStyle, style]}
* onPressIn={this.onPressIn}
* onPressOut={this.onPressOut}
* />
* );
* }
* }
*
* export const StyledButton = styled<StyledButtonProps>(Button);
* ```
*
* @example Styled Component Usage
*
* ```
* import {
* StyledButton,
* StyledButtonProps,
* } from './path-to/styledButton.component';
*
* public render(): React.ReactElement<StyledButtonProps> {
* return (
* <StyledButton/>
* );
* }
* ```
*
* @returns {StyledComponentClass} - component class which can be used as styled component
*/
export const styled = <P extends object>(Component: React.ComponentClass<P>): StyledComponentClass<P> => {

// @ts-ignore
if (!Component.styledComponentName) {
Expand Down
73 changes: 66 additions & 7 deletions src/framework/theme/theme/themeConsumer.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import React from 'react';
import hoistNonReactStatics from 'hoist-non-react-statics';
import { ThemeContext } from './themeContext';
import {
ThemeType,
ThemedStyleType,
StyleSheetType,
ThemedStyleType,
ThemeType,
} from './type';

interface PrivateProps<T> {
Expand All @@ -28,12 +28,71 @@ export interface Context {
theme: ThemeType;
}

// `P` is for component-specific props which could be passed into jsx element
// `T` is for component-specific static props like `TabView.Tab`
export type ThemedComponentClass<P, T = {}> = React.ComponentClass<ThemedComponentProps & P> & T;
export type ThemedComponentClass<P> = React.ComponentClass<ThemedComponentProps & P>;

export const withStyles = <P, T = {}>(Component: React.ComponentClass<P>,
createStyles?: CreateStylesFunction): ThemedComponentClass<P, T> => {
/**
* The `withStyles` function is a High Order Function which is used to create themed style for non-styled component.
* Basically used when need to use `theme` variables somewhere.
*
* Passes following props to `Component` when it is rendered:
*
* @property {ThemeType} theme - Determines theme used to style component.
* @property {StyleType} themedStyle - Determines component style for it's current state.
*
* @param {React.ComponentClass} Component - Determines class of component to be themed
* @param {(theme: ThemeType) => any} createStyles - Determines arrow function used to create styles
*
* @example Declaring Themed Component
*
* ```
* import {
* withStyles,
* ThemedComponentProps,
* } from '@kitten/theme';
*
* type ThemedButtonProps = ButtonProps & ThemedComponentProps;
*
* class Button extends React.Component<ThemedButtonProps> {
*
* public render(): React.ReactElement<ButtonProps> {
* // Retrieve styles from props (provided with themedStyle prop)
* // And apply it with saving priority of `style` prop
*
* const { style, themedStyle, ...restProps } = this.props;
*
* return (
* <TouchableOpacity
* {...restProps}
* style={[themedStyle, style]}
* />
* );
* }
* }
*
* export const ThemedButton = withStyles(Button, (theme: ThemeType) => ({
* backgroundColor: theme['color-primary-500'],
* }));
* ```
*
* @example Themed Component Usage
*
* ```
* import {
* ThemedButton,
* ThemedButtonProps,
* } from './path-to/themedButton.component';
*
* public render(): React.ReactElement<ThemedButtonProps> {
* return (
* <ThemedButton/>
* );
* }
* ```
*
* @returns {ThemedComponentClass} - component class which can be used as styled component
*/
export const withStyles = <P extends object>(Component: React.ComponentClass<P>,
createStyles?: CreateStylesFunction): ThemedComponentClass<P> => {

type WrappingProps = PrivateProps<WrappedElementInstance> & WrappedProps;
type WrappedProps = ThemedComponentProps & P;
Expand Down

0 comments on commit c2e5be0

Please sign in to comment.