1.0.0 • Published 4 years ago

react-customizable-component v1.0.0

Weekly downloads
-
License
ISC
Repository
-
Last release
4 years ago

React Flex Component

ReactFlexComponents is a tool that can help you to customize app. Main idea - many themes, one component.

Logo

This package can:

  • Mix modifiers
  • Modify component head
  • Modify whole component

What's the problem?

How many component's visual style can you modify without changing its code? The value is low I bet.

An example of typical situation

const TestC = (
    <div classname="test">
        <div className="test__block">
            <span className="test__text">Text</span>
        </div>
    </div>
);

const App = (
    <div classname="app">
        <TestC />
    </div>
);

Can't add theme or change position. Obviously you can't reuse that component. Cause if you're going to position it, you position it everywhere.

Can we solve the problem? Actually we can. There is 2 ways: 1. Create wrapper with class, that modifies nested elements 2. Create component, that receives modifiers props, and returns modified version.

Solved example:

// first method
const App = (
    <div classname="app">
        {/* unwanted structure */} 
        <div className="app__testc">
            <TestC />
        </div>
    </div>
);

// second method
const mod = { className: "app__testc" };
const App = (
    {/* all good */} 
    <div classname="app">
        <TestC mod={mod} />
    </div>
);

This package using second way.

Install

To download this package from npm paste this command in a terminal

npm install react-flex-components

How to use

First of all you have to import the library.

import { IFlexComponentProps, IFlexComponentTheme } from "../libs/flexComponent";
import { IFlexComponentModifier, createModifier, mixModifiers, modifyElement } from "../libs/flexComponentModifier";

Then you can create customizable functional or class components

Functional component example

// define theme interface
export interface FlexAppTheme extends IFlexComponentTheme {
    textMod: IFlexComponentModifier;
};

// define props interface
export interface IFlexAppProps extends IFlexComponentProps<FlexAppTheme> {
    text: string;
};

export const FlexAppF: FunctionComponent<IFlexAppProps> = (props: IFlexAppProps) => {
    const { text, theme, mod } = props;

    if (theme) {
        return modifyElement((
            <div className="app">
                {modifyElement((
                    <span className="app__text">
                        {text}
                    </span>
                ), theme.textMod)}
            </div>
        ), mixModifiers(mod, theme.head));
    }

    return modifyElement((
        <div className="app">
            {modifyElement((
                <span className="app__text">{text}</span>
            ), theme.textMod)}
        </div>
    ), mod);
}

// theme instance
const darkTheme: FlexAppTheme = {
    head: createModifier("app_dark"),
    textMod: createModifier("app__text_dark")
}

// all themes
export const flexAppThemes = {
    dark: darkTheme
};

Class component

Just import FlexComponent class, that decides wich function result to return.

export class FlexApp extends FlexComponent<FlexAppTheme, IFlexAppProps> {
    constructor(props: IFlexAppProps) {
        super(props);
    }

    renderWithTheme() {
        return modifyElement((
            <div className="app">
                {modifyElement((
                    <span className="app__text">
                        {this.props.text}
                    </span>
                ), this.theme.textMod)}
            </div>
        ), mixModifiers(this.mod, this.theme.head));
    }

    renderWithoutTheme() {
        return modifyElement((
            <div className="app">
                <span className="app__text">{this.props.text}</span>
            </div>
        ), this.mod);
    }
}

Okay, now we can use new component. A Theme prop is optional, mod always required, but you always can pass zero mod: createMod("").

FlexAppF text="It actually works" mod={createModifier("root__app")} theme={flexAppThemes.dark}></FlexAppF>

Result will be

    <div class="app root__app app_dark">
        <span class="app__text app__text_dark">It actually works</span>
    </div>

Documentation

Lets take a look how does it work

Modifier is just an interface, that haves className and id properties;

interface IFlexComponentModifier {
    className: string;
    id?: string;

    // if you want to modify more props, extend that interface
}

createModifier function wraps your args to new IFlexCompnentModifier obj

// createModifier(className, id?);
createModifier("mod_class", "mod-el");
createModifier("mod_class");

mixModifier function combining all classNames to one and chooses id

mixModifiers(mod, mod2, mod3...) => IFlexComponentModifier;

modifyElement function applies mod on provided element and

returns modified version

modifyElement(element: ReactElement, mod: IFlexComponentModifier): ReactElement;

IFlexComponentProps is an interface that haves theme and head mod

interface IFlexComponentProps<T> {
    theme?: T; // head && body modifiers
    mod: IFlexComponentModifier; // component head modifier
}

// extend that interface to add other props

IFlexComponentTheme contains head mod

interface IFlexComponentTheme {
    head: IFlexComponentModifier;
}

// extend that interface to add other customizable parts

FlexComponent class choosing what to render by checking props.theme value

// pass your own Theme & Props interface realization
class FlexComponent<Theme: IFlexComponentTheme, Props: IFlexComponentProps> extends React.Component {
    renderWithTheme() {
        // your code
    }

    renderWithoutTheme() {
        // your code
    }
}

Enjoy this package