react-customizable-component v1.0.0
React Flex Component
ReactFlexComponents is a tool that can help you to customize app. Main idea - many themes, one component.
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
4 years ago