README
GitHub license">
Lucas
Set of React componets, High order components and other UI tools we miss in other packages.
Name of package refers to Luke the evangelist the patron of all painters.
Table of contents
Installation
Using npm:
npm i -s @ackee/lucas
Using yarn:
yarn add @ackee/lucas
API
Components
DataList
Component that display list of data, optionally scrollable (but scrolling is turned on in default).
Props
data
(object[]): List of objects that determines data supplied toRowComponent
.RowComponent
(ReactComponent|ReactNode): Component or Element used as a list row. If custom rootelement
prop no supplied, then it'stable
and so this component should havetr
as a root element to work properly.noDataMessage
(ReactNode [optional]): Message displayed when data list is empty. Default is'No data'
.scrollable
(boolean [optional]): Wheather scrollbars should be displayed when content overflow container. Default istrue
.element
(Component|string): Determine type of list root element.
Style
It's recommended to style scrollbar thumb using widget-data-list__scrollbar-thumb
class name, because in default it's rgba(0, 0, 0, 0)
. Below is a simple example of styling thumb (but most time it's all you need)
.widget-data-list__scrollbar-thumb {
background-color: grey;
border-radius: inherit;
}
Example
import { DataList } from '@ackee/lucas';
const data = [
{ id: 1, text: 'Text 1' },
{ id: 2, text: 'Text 2' },
{ id: 3, text: 'Text 3' },
];
const CustomRowComponent = ({ id, text }) => (
<tr>
<td style={rowStyle}>{id}</td>
<td style={rowStyle}>{text}</td>
</tr>
);
React.render(
<div>
<DataList data={data} RowComponent={CustomRowComponent} noDataMessage="Data list is empty" />
</div>
)
));
Prop types
childrenPropType
Prop type shape for children
.
Example
import { childrenPropType } from '@ackee/lucas'
MyComponent.propTypes = {
children: childrenPropType,
};
HOC
errorBoundary(ErrorComponent): BoundedComponent
High order component for setting error boundaries up. Implementation is very similar to that described by React authors.
Arguments
ErrorComponent
: React component that shows the error. Receives
- prop
error
which is occured error - all the props supplied to
BoundedComponent
Returns
Component that catch any unexpected error that occured anywhere in subtree and invoke LOG_ERROR
action
Example
// components/SimpleError.js
const SimpleError = ({ error }) => (
<div>
Error occured!:
<code>{error.message}</code>
</div>
);
// components/MainContent.js
const MainContent = () => (
<div>
<p>Error will be caught up</p>
{/* Click on the button bellow generates uncaught error */}
<button onClick={(e) => e.callNonExistingFunction()}>Do error</button>
</div>
);
// containers/MainContent.js
import { errorBoundary } from '@ackee/lucas';
import { compose } from 'redux';
import MainContent from '../components/MainContent';
compose(
errorBoundary(SimpleError),
)(MainContent);
loadable(LoaderComponent: Component, defaultText?: string): (MyComponent) => LoadableMyComponent
High order component that wraps your content component with supplied loader and pass prop showLoader
just to the loader.
HOC accepts two arguments:
LoaderComponent
- component that is used as a loader, so it's displayed whileshowLoader
is truthydefaultText
[optional] - default text that is provided toLoaderComponent
unlessloaderText
prop is supplied to LoadableComponent
Wrapped loadable component accepts two more props:
showLoader
- controls if loader is visibleloaderText
[optional] - text that is provided intoLoaderComponent
LoaderComponent
receives loadable content (the component(s) hidden behind loader until load finish) as a children and two props:
show
- loader visibility flagtext
- loader text
Example
// components/Loader.jsx
const Loader = ({ children, show, text }) => (
<div>
{ children }
{ show && <div className="loader">{text}</div> }
</div>
);
export default Loader;
// containers/Users.js
import { loadable } from '@ackee/lucas';
import Users from '../components/Users';
import Loader from '../components/Loader';
export default compose(
connect(
state => ({
showLoader: isFetchingUsersSelector(state),
})
)
loadable(SimpleLoader),
)(Users);
makeDropzone(GraphicComponent): DropzoneComponent
High order component for easy making of file upload component with file dropzone.
Arguments
GraphicComponent
: React component that creates dropzone graphic.
Returns
Component that receives two extra props:
isMouseOver
(boolean): Determine if user drags with mouse over zone. Useful for changing dropzone style.uploadState
(FS): Actual state of file upload
File state
File upload state, accessible as a property of HOC, so makeDropzone.FS
.
enum FS {
failed,
pending,
uploading,
uploaded
}
Example
// components/DropArea.js
const DropArea = ({ isMouseOver, uploadState }) => (
<div style={{ backgroundColor: isMouseOver ? 'yellow' : 'grey' }}>
<span className="button--blue button">
{
uploadState === makeDropzone.FS.uploaded || uploadState === makeDropzone.FS.failed
? 'Change'
: 'Select'
}
</span>
</div>
);
// containers/Dropzone.js
import { makeDropzone } from '@ackee/lucas';
import { compose } from 'redux';
import DropArea from '../components/DropArea';
export default compose(
makeDropzone,
)(DropArea);
// components/UploadImages.js
import containers from '@ackee/lucas';
import DropArea from '../containers/Dropzone';
const UploadImages = () => (
<Dropzone
onDrop={handleFilesDrop}
input={{
accept: 'image/png, image/jpeg',
multiple: boolean,
}}
/>
)
pure(equalityChecker): (UnpureComponent) => PureComponent
Makre provided component pure - it means that component not rerender until it's props change.
Arguments
equalityChecker
(function(prevProps, nextProps):bool [optional]) - Function that returns boolean which determines if prev props are equal to next props. You can provide your own eqaulity checker, if you don't provide equality checker, lodash'sisEqual
function is used.
Returns:
Function that accepts UnpureComponent
(React component that should be optimilized for useless rerenderes) and return PureComponent
(component that rerender only if their props change). Change is determined either by equality checker.
Example - custom equality checker
import { pure } from '@ackee/lucas';
import { compose } from 'redux';
const customEqualityChecker = (props, nextProps) => {
return props.data.changableProp === nextProps.data.changableProp;
};
compose(
pure(customEqualityChecker),
)(DataConsumerComponent);
Example - default equality checker
import { pure } from '@ackee/lucas';
import { compose } from 'redux';
compose(
pure(),
)(DataConsumerComponent);
Action types
Logging action types
LOG_ERROR
import { actionTypes } from '@ackee/lucas';
import { takeEvery } from 'redux-saga/effects';
takeEvery(actionTypes.logging.LOG_ERROR, function* (action) {
const { error, extra } = action;
console.log(error, extra);
});