react-extras
Version:
Useful components and utilities for working with React
358 lines (277 loc) • 7.8 kB
TypeScript
import {Component as ReactComponent, ComponentClass, HTMLProps, ReactNode} from 'react';
/**
Automatically binds your `Component` subclass methods to the instance.
@see https://github.com/sindresorhus/auto-bind#autobindreactself-options
@param self - Object with methods to bind.
@example
```
import {autoBind} from 'react-extras';
class Foo extends Component {
constructor(props) {
super(props);
autoBind.react(this);
}
// …
}
```
*/
/**
Conditionally join CSS class names together.
@param input - Accepts a combination of strings and objects. Only object keys with truthy values are included. Anything else is ignored.
@example
```
import {classNames} from 'react-extras';
classNames('unicorn', 'rainbow');
//=> 'unicorn rainbow'
classNames({awesome: true, foo: false}, 'unicorn', {rainbow: false});
//=> 'awesome unicorn'
classNames('unicorn', null, undefined, 0, 1, {foo: null});
//=> 'unicorn'
const buttonType = 'main';
classNames({[`button-${buttonType}`]: true});
//=> 'button-main'
```
@example
```
import {classNames} from 'react-extras';
const Button = props => {
const buttonClass = classNames(
'button',
{
[`button-${props.type}`]: props.type,
'button-block': props.block,
'button-small': props.small
}
);
console.log(buttonClass);
//=> 'button button-success button-small'
return <button className={buttonClass}>…</button>;
};
```
*/
/**
Returns a boolean of whether the given `Component` is a functional stateless component.
@see https://javascriptplayground.com/functional-stateless-components-react/
*/
export function isStatelessComponent(component: ComponentClass): boolean;
/**
Returns the display name of the given `Component`.
@see https://reactjs.org/docs/react-component.html#displayname
*/
export function getDisplayName(component: ComponentClass): string;
/**
A boolean of whether you're running in a context with a DOM.
Can be used to check if your component is running in the browser or if it's being server-rendered.
@see https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction
*/
export const canUseDOM: boolean;
interface IfProps {
/**
Condition to check. Children are only rendered if `true`.
*/
readonly condition: boolean;
/**
Children to render if `condition` is `true`.
*/
readonly children?: ReactNode;
/**
If you need the children to not be evaluated when `condition` is `false`, pass a function to the `render` prop that returns the children.
*/
readonly render?: () => ReactNode;
}
/**
React component that renders the children if the `condition` prop is `true`.
Beware that even though the children are not rendered when the `condition` is `false`, they're still evaluated.
If you need it to not be evaluated on `false`, you can pass a function to the `render` prop that returns the children:
@example
```
import {If} from 'react-extras';
<div>
<If condition={props.error} render={() => (
<h1>{props.error}</h1>
)}/>
</div>
```
Or you could just use plain JavaScript:
@example
```
import {If} from 'react-extras';
<div>
{props.error && (
<h1>{props.error}</h1>
)}
</div>
```
*/
export class If extends ReactComponent<IfProps> {}
interface ChooseOtherwiseProps {
/**
Children to render in the default case.
*/
readonly children?: ReactNode;
/**
If you need the children to not be evaluated when a `<Condition.When>` component has a true condition, pass a function to the `render` prop that returns the children.
*/
readonly render?: () => ReactNode;
}
export class ChooseOtherwise extends ReactComponent<ChooseOtherwiseProps> {}
/**
React component similar to a switch case. `<Choose>` has 2 children components:
- `<Choose.When>` that renders the children if the `condition` prop is `true`.
- `<Choose.Otherwise>` that renders the children if has no `<Choose.When>` with `true` prop `condition`.
Note that even when the children are not rendered, they're still evaluated.
@example
```
import {Choose} from 'react-extras';
<div>
<Choose>
<Choose.When condition={props.success}>
<h1>{props.success}</h1>
</Choose.When>
<Choose.When condition={props.error}>
<h1>{props.error}</h1>
</Choose.When>
<Choose.Otherwise>
<h1>😎</h1>
</Choose.Otherwise>
</Choose>
</div>
```
@example
```
<div>
{(() => {
if (props.success) {
return <h1>{props.success}</h1>;
}
if (props.error) {
return <h1>{props.error}</h1>;
}
return <h1>😎</h1>;
})()}
</div>
```
*/
export class Choose extends ReactComponent {
/**
Renders the children if the `condition` prop is `true`.
Use with `Choose` and `Choose.Otherwise`.
*/
static When: typeof If;
/**
Renders the children if there is no `<Choose.When>` with `true` prop `condition`.
Use with `Choose` and `Choose.When`.
*/
static Otherwise: typeof ChooseOtherwise;
}
interface ForProps<T> {
/**
Items to iterate over. `render` will be called once per item.
*/
readonly of: readonly T[];
/**
Returns the element to render corresponding to an `item`.
*/
readonly render?: (item: T, index: number) => ReactNode;
}
/**
React component that iterates over the `of` prop and renders the `render` prop.
@example
```
import {For} from 'react-extras';
<div>
<For of={['🌈', '🦄', '😎']} render={(item, index) =>
<button key={index}>{item}</button>
}/>
</div>
```
Or you could just use plain JavaScript:
@example
```
<div>
{['🌈', '🦄', '😎'].map((item, index) =>
<button key={index}>{item}</button>
)}
</div>
```
*/
export class For<T> extends ReactComponent<ForProps<T>> {}
interface ImageProps extends HTMLProps<HTMLImageElement> {
/**
URL of the image. Use instead of `src`.
*/
readonly url: string;
/**
Fallback URL to display if the image does not load.
Default: Hide the image if it fails to load.
*/
readonly fallbackUrl?: string;
}
/**
React component that improves the `<img>` element.
It makes the image invisible if it fails to load instead of showing the default broken image icon. Optionally, specify a fallback image URL.
@example
```
import {Image} from 'react-extras';
<Image
url="https://sindresorhus.com/unicorn.jpg"
fallbackUrl="https://sindresorhus.com/rainbow.jpg"
/>
```
It supports all the props that `<img>` supports, but you use the prop `url` instead of `src`.
*/
export class Image extends ReactComponent<ImageProps> {}
interface ElementClassProps {
/**
Classes to add to the root element.
Either a single class or multiple classes separated by space.
*/
readonly add?: string;
/**
Classes to remove from the root element.
Either a single class or multiple classes separated by space.
*/
readonly remove?: string;
}
/**
Renderless React component that can add and remove classes to the root `<html>` element. It accepts an `add` prop for adding classes, and a `remove` prop for removing classes. Both accept either a single class or multiple classes separated by space.
@example
```
import {If, RootClass} from 'react-extras';
<If condition={props.isDarkMode}>
<RootClass add="dark-mode"/>
</If>
```
@example
```
import {RootClass} from 'react-extras';
<RootClass add="logged-in paid-user" remove="promo"/>
```
*/
export class RootClass extends ReactComponent<ElementClassProps> {}
/**
Same as `<RootClass/>` but for `<body>`.
Prefer `<RootClass/>` though, because it's nicer to put global classes on `<html>` as you can consistently prefix everything with the class:
@example
```css
.dark-mode body {
background: #000;
}
.dark-mode a {
…
}
```
With `<BodyClass/>` you need to do:
@example
```css
body.dark-mode {
background: #000;
}
.dark-mode a {
…
}
```
*/
export class BodyClass extends ReactComponent<ElementClassProps> {}
export {default as classNames} from '@sindresorhus/class-names';
export {default as autoBind} from 'auto-bind/react';