Preview: http://dashboards.webkom.co/react/airframe
This commit is contained in:
Tomasz Owczarczyk
2019-08-15 00:54:44 +02:00
parent f975443095
commit 37092d1d6c
626 changed files with 56691 additions and 0 deletions

View File

@@ -0,0 +1,154 @@
import React from 'react';
import DatePicker, { setDefaultLocale } from 'react-datepicker';
import moment from 'moment';
import {
Container,
Row,
Card,
Col,
CardBody
} from './../../../components';
import { Example, ButtonInput, AddonInput } from './components';
import { HeaderMain } from "../../components/HeaderMain";
setDefaultLocale('en');
export class DatePickerExamples extends React.Component {
state = {
startDate: moment().toDate(),
endDate: moment().add(5, 'days').toDate()
}
render() {
return (
<Container>
<HeaderMain
title="Date Picker"
className="mb-5 mt-4"
/>
<p className="mb-4">
Youll need to install React, PropTypes, and Moment.js separately since those dependencies
arent included in the package. Below is a simple example of how to use the Datepicker in a React view.
You will also need to require the CSS file from this package (or provide your own).
The example below shows how to include the CSS from this package if your build system supports
requiring CSS files (Webpack is one that does).
</p>
<Row>
<Col lg={ 4 }>
{ /* START Card */}
<Card className="mb-3">
<CardBody>
<Example
title="Default"
no="1.01"
exampleInput={(
<DatePicker
customInput={ <ButtonInput /> }
selected={this.state.startDate}
onChange={this._handleChangeStart}
/>
)}
>
{
'<DatePicker\n' +
' selected={this.state.startDate}\n' +
' onChange={this._handleChange}\n' +
'/>'
}
</Example>
</CardBody>
</Card>
{ /* END Card */}
{ /* START Card */}
<Card className="mb-3">
<CardBody>
<Example
title="Inline"
no="1.02"
exampleInput={(
<DatePicker
inline
selected={this.state.startDate}
onChange={this._handleChangeStart}
/>
)}
>
{
'<DatePicker\n' +
' inline\n' +
' selected={this.state.startDate}\n' +
' onChange={this._handleChange}\n' +
'/>'
}
</Example>
</CardBody>
</Card>
{ /* END Card */}
</Col>
<Col lg={ 8 }>
{ /* START Card */}
<Card>
<CardBody>
<Example
title="Range"
no="1.03"
exampleInput={(
<div className="d-flex">
<DatePicker
customInput={ <AddonInput /> }
selected={this.state.startDate}
selectsStart
startDate={this.state.startDate}
endDate={this.state.endDate}
onChange={this._handleChangeStart}
/>
<DatePicker
className="ml-2"
customInput={ <AddonInput /> }
selected={this.state.endDate}
selectsEnd
startDate={this.state.startDate}
endDate={this.state.endDate}
onChange={this._handleChangeEnd}
/>
</div>
)}
>
{
'<DatePicker\n' +
' selected={this.state.startDate}\n' +
' selectsStart\n' +
' startDate={this.state.startDate}\n' +
' endDate={this.state.endDate}\n' +
' onChange={this.handleChangeStart}\n' +
'/>\n' +
'\n' +
'<DatePicker\n' +
' selected={this.state.endDate}\n' +
' selectsEnd\n' +
' startDate={this.state.startDate}\n' +
' endDate={this.state.endDate}\n' +
' onChange={this.handleChangeEnd}\n' +
'/>\n'
}
</Example>
</CardBody>
</Card>
{ /* END Card */}
</Col>
</Row>
</Container>
)
}
_handleChangeStart = (startDate) => (
this.setState({ startDate })
)
_handleChangeEnd = (endDate) => (
this.setState({ endDate })
)
}

View File

@@ -0,0 +1,31 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
InputGroup,
InputGroupAddon,
Input
} from './../../../../components';
// eslint-disable-next-line react/display-name
const AddonInputFR = React.forwardRef((props, ref) => (
<InputGroup className={props.className}>
<InputGroupAddon addonType="prepend">
<i className="fa fa-calendar-o"></i>
</InputGroupAddon>
<Input
onClick={ props.onClick }
onChange={ props.onChange }
value={ props.value }
ref={ ref }
/>
</InputGroup>
));
AddonInputFR.propTypes = {
onClick: PropTypes.func,
onChange: PropTypes.func,
value: PropTypes.string,
className: PropTypes.string
}
export { AddonInputFR as AddonInput };

View File

@@ -0,0 +1,23 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
Button
} from './../../../../components';
// eslint-disable-next-line react/display-name
const ButtonInputFR = React.forwardRef((props, ref) => (
<Button outline
onClick={props.onClick}
ref={ref}
>
<i className="fa fa-fw fa-calendar-o mr-1" />
{ props.value }
</Button>
));
ButtonInputFR.propTypes = {
onClick: PropTypes.func,
value: PropTypes.string
}
export { ButtonInputFR as ButtonInput };

View File

@@ -0,0 +1,50 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
Row,
Col,
FormGroup,
Label
} from './../../../../components';
export const Example = ({ title, exampleInput, children, no }) => (
<Row>
<Col sm={ 12 }>
<h6>
{ title }
<span className="small ml-1 text-muted">
#{ no }
</span>
</h6>
</Col>
<Col md={ 12 }>
<FormGroup>
<Label>
Example
</Label>
<div>
{ exampleInput }
</div>
</FormGroup>
</Col>
<Col md={ 12 }>
<FormGroup>
<Label>
Code
</Label>
<pre>
<code>
{ children }
</code>
</pre>
</FormGroup>
</Col>
</Row>
);
Example.propTypes = {
exampleInput: PropTypes.node.isRequired,
children: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
no: PropTypes.node.isRequired
}

View File

@@ -0,0 +1,3 @@
export * from './Example';
export * from './ButtonInput';
export * from './AddonInput';

View File

@@ -0,0 +1,3 @@
import { DatePickerExamples } from './DatePickerExamples';
export default DatePickerExamples;

View File

@@ -0,0 +1,134 @@
import React from 'react';
import classNames from 'classnames';
import FileDrop from 'react-dropzone';
import _ from 'lodash';
import {
Container,
Divider,
Badge,
Button,
ButtonGroup
} from './../../../components';
import {
FilesGrid,
FilesList
} from './components';
import { HeaderMain } from "../../components/HeaderMain";
export class Dropzone extends React.Component {
state = {
isOver: false,
files: [],
listStyle: 'grid'
}
render() {
const { isOver, files, listStyle } = this.state;
const dropzoneClass = classNames({
'dropzone--active': isOver
}, 'dropzone');
return (
<Container>
<HeaderMain
title="Dropzone"
className="mb-5 mt-4"
/>
{ /* DropZone */ }
<div className="mb-4">
<p className="mb-3">
Simple HTML5-compliant drag&apos;n&apos;drop zone for files built with React.js.
</p>
<FileDrop
multiple
onDragEnter={() => { this.setState({isOver: true}) }}
onDragLeave={() => { this.setState({isOver: false}) }}
onDrop={this._filesDropped}
>
{
({ getRootProps, getInputProps }) => (
<div {...getRootProps()} className={dropzoneClass}>
<i className="fa fa-cloud-upload fa-fw fa-3x mb-3"></i>
<h5 className='mt-0'>
Upload Your files
</h5>
<p>
Drag a file here or <span className='text-primary'>browse</span> for a file to upload.
</p>
<p className="small">
JPG, GIF, PNG, MOV, and AVI. Please choose files under 2GB for upload. File sizes are 400x300px.
</p>
<input { ...getInputProps() } />
</div>
)
}
</FileDrop>
</div>
{ /* Files List */}
{
files.length > 0 && (
<div className="mt-2">
<div className="d-flex">
<Divider
position="left"
className="flex-shrink-1 flex-grow-1"
>
<div className="px-2">
Attachments
<Badge
className="ml-1 text-white"
pill
color="secondary"
>
{ files.length }
</Badge>
</div>
</Divider>
<ButtonGroup className="flex-grow-0 flex-shrink-0 pl-2">
<Button
active={ listStyle === 'list' }
onClick={() => {this.setState({listStyle: 'list'})}}
size="sm"
outline
>
<i className='fa fa-bars fa-fw'></i>
</Button>
<Button
active={ listStyle === 'grid' }
onClick={() => {this.setState({listStyle: 'grid'})}}
size="sm"
outline
>
<i className='fa fa-th-large fa-fw'></i>
</Button>
</ButtonGroup>
</div>
{
listStyle === 'grid' ?
<FilesGrid files={ files } onFileRemove={this._removeFile} /> :
<FilesList files={ files } onFileRemove={this._removeFile} />
}
</div>
)
}
</Container>
);
}
_filesDropped = (files) => {
this.setState({
files: [...this.state.files, ...files],
isOver: false
})
}
_removeFile = (file) => {
this.setState({
files: _.reject(this.state.files, file)
})
}
}

View File

@@ -0,0 +1,64 @@
import React from 'react';
import _ from 'lodash';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import numeral from 'numeral';
import moment from 'moment';
import {
Col,
Row,
Card,
CardBody,
Button,
UncontrolledTooltip
} from './../../../../components';
import classes from './common.scss';
import {
getFileIcon
} from './../utilities';
export const FilesGrid = ({ files, onFileRemove }) => (
<Row className="mt-4">
{
_.map(files, (file, index) => (
<Col lg={ 4 } md={ 6 } key={index}>
<Card className="mb-3">
<div className={ classNames("card-img-top", classes['ph--large']) }>
<i className={`fa fa-fw fa-3x ${getFileIcon(file)}`} />
</div>
<CardBody className="pt-2">
<div className="d-flex align-items-center mb-0 mt-0">
<h6 className="text-truncate mb-0">
{ file.name }
</h6>
<Button
color="link"
onClick={() => {onFileRemove(file)}}
size="sm"
id={`delete-file-${index}`}
>
<i className="fa fa-times fa-fw text-danger"></i>
</Button>
<UncontrolledTooltip placement="left" target={`delete-file-${index}`}>
Delete File
</UncontrolledTooltip>
</div>
<div className="mb-0">
by You &middot; <span className='text-uppercase'>{`${numeral(file.size).format('0.00a')}B`}</span>
</div>
<div className='mb-0'>
{ moment(file.modifiedDate).format('DD-MMM-YYYY, HH:mm') }
</div>
</CardBody>
</Card>
</Col>
))
}
</Row>
);
FilesGrid.propTypes = {
files: PropTypes.array,
onFileRemove: PropTypes.func
}

View File

@@ -0,0 +1,73 @@
import React from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
import numeral from 'numeral';
import moment from 'moment';
import {
Table,
Button,
UncontrolledTooltip
} from './../../../../components';
import classes from './common.scss';
import {
getFileIcon
} from './../utilities';
export const FilesList = ({ files, onFileRemove }) => (
<Table responsive hover className="mt-3">
<thead>
<tr>
<th className="bt-0"></th>
<th className="bt-0">File Name</th>
<th className="bt-0">Size</th>
<th className="bt-0">Owner</th>
<th className="bt-0">Modified Date</th>
<th className="bt-0 text-right">Actions</th>
</tr>
</thead>
<tbody>
{
_.map(files, (file, index) => (
<tr key={ index }>
<td className="align-middle">
<div className={ classes['ph--small'] }>
<i className={`fa fa-fw fa-2x ${getFileIcon(file)}`} />
</div>
</td>
<td className="align-middle">
{ file.name }
</td>
<td className="align-middle text-uppercase">
{ numeral(file.size).format('0.00a') }B
</td>
<td className="align-middle">
You
</td>
<td className="align-middle">
{ moment(file.modifiedDate).format('DD-MMM-YYYY, HH:mm') }
</td>
<td className="text-right align-middle">
<Button
color="link"
onClick={() => {onFileRemove(file)}}
size="sm"
id={`delete-file-${index}`}
>
<i className="fa fa-times fa-fw text-danger"></i>
</Button>
<UncontrolledTooltip placement="left" target={`delete-file-${index}`}>
Delete File
</UncontrolledTooltip>
</td>
</tr>
))
}
</tbody>
</Table>
);
FilesList.propTypes = {
files: PropTypes.array,
onFileRemove: PropTypes.func
}

View File

@@ -0,0 +1,25 @@
@import "./../../../../styles/variables.scss";
.ph--large {
display: flex;
align-items: center;
justify-content: center;
min-height: 200px;
background-color: $gray-400;
margin-bottom: 5px;
> i {
color: #fff;
}
}
.ph--small {
display: inline-block;
background-color: $gray-400;
padding: 7px 5px;
border-radius: 7px;
> i {
color: #fff;
}
}

View File

@@ -0,0 +1,2 @@
export * from './FilesGrid';
export * from './FilesList';

View File

@@ -0,0 +1,3 @@
import { Dropzone } from './Dropzone';
export default Dropzone;

View File

@@ -0,0 +1,32 @@
export const typeToIcon = type => {
const map = {
['application/msword']: 'fa-file-word-o',
['application/excel']: 'fa-file-excel-o',
['application/vnd.oasis.opendocument.spreadsheet']: 'fa-file-excel-o',
['application/vnd.oasis.opendocument.presentation']: 'fa-file-powerpoint-o',
['application/mspowerpoint']: 'fa-file-powerpoint-o',
['application/x-zip-compressed']: 'fa-file-archive-o',
['image/jpeg']: 'fa-file-image-o',
['image/png']: 'fa-file-image-o',
['audio/mp3']: 'fa-file-audio-o',
['text/plain']: 'fa-file-text-o'
}
return map[type] || null;
}
export const extToIcon = filename => {
const map = {
['doc']: 'fa-file-word-o',
['docx']: 'fa-file-word-o',
['xls']: 'fa-file-excel-o',
['xlsx']: 'fa-file-excel-o',
['ppt']: 'fa-file-powerpoint-o',
['pdf']: 'fa-file-pdf-o'
}
return map[filename.split('.').pop()] || null;
}
export const getFileIcon = file => {
return typeToIcon(file.type) || extToIcon(file.name) || 'fa-file-o';
}

View File

@@ -0,0 +1,66 @@
import React from 'react';
import ReactQuill from 'react-quill';
import faker from 'faker/locale/en_US';
import {
Container,
Card
} from './../../../components';
import { HeaderMain } from "../../components/HeaderMain";
export class Editor extends React.Component {
state = {
text: `
<p>${ faker.lorem.paragraph() }</p>
<br/>
<p>${ faker.lorem.paragraph() }</p>
<br/>
<p>${ faker.lorem.paragraph() }</p>
`
}
modules = {
toolbar: [
[{ 'header': [1, 2, false] }],
['bold', 'italic', 'underline','strike', 'blockquote'],
[{'list': 'ordered'}, {'list': 'bullet'}, {'indent': '-1'}, {'indent': '+1'}],
['clean']
],
}
formats = [
'header',
'bold', 'italic', 'underline', 'strike', 'blockquote',
'list', 'bullet', 'indent'
]
render() {
return (
<Container>
<HeaderMain
title="Editor"
className="mb-5 mt-4"
/>
<p>
<strong>Quill</strong> is a modern rich text editor built for compatibility and extensibility.
</p>
<Card>
<ReactQuill
value={ this.state.text }
onChange={ this._handleChange }
modules={ this.modules }
formats={ this.formats }
style={{
minHeight: '480px'
}}
/>
</Card>
</Container>
);
}
_handleChange = (text) => {
this.setState({ text })
}
}

View File

@@ -0,0 +1,3 @@
import { Editor } from './Editor';
export default Editor;

1137
app/routes/Forms/Forms/Forms.js Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
import Forms from './Forms';
export default Forms;

View File

@@ -0,0 +1,484 @@
import React from 'react';
import {
Container,
Row,
Col,
Card,
CardTitle,
CardBody,
Button,
InputGroup,
InputGroupAddon,
CustomInput,
Form,
FormGroup,
Label,
Input,
FormText
} from './../../../components';
import { HeaderMain } from "../../components/HeaderMain";
import { HeaderDemo } from "../../components/HeaderDemo";
const FormsLayouts = () => (
<React.Fragment>
<Container>
<HeaderMain
title="Forms Layouts"
className="mb-5 mt-4"
/>
{ /* START Header 1 */}
<Row>
<Col lg={ 12 }>
<HeaderDemo
no={1}
title="Forms Horizontal & Vertical"
subTitle={(
<React.Fragment>
Create horizontal forms with the grid by adding the
.row class to form groups and using the .col-*-* classes
to specify the width of your labels and controls.
</React.Fragment>
)}
/>
</Col>
</Row>
{ /* END Header 1 */}
{ /* START Section 1 */}
<Row>
<Col lg={ 6 }>
<Card className="mb-3">
<CardBody>
<CardTitle tag="h6" className="mb-4">
Forms Horizontal: Basic Example
<span className="small ml-1 text-muted">
#1.01
</span>
</CardTitle>
{ /* START Form */}
<Form>
{ /* START Input */}
<FormGroup row>
<Label for="input-1" sm={4}>
Input
</Label>
<Col sm={8}>
<Input
type="text"
name=""
id="input-1"
placeholder="Enter Name..."
/>
</Col>
</FormGroup>
{ /* END Input */}
{ /* START Input */}
<FormGroup row>
<Label for="inputPassword-1" sm={4}>
Password
</Label>
<Col sm={8}>
<Input
type="password"
name="password"
id="inputPassword-1"
placeholder="Password..."
/>
</Col>
</FormGroup>
{ /* END Input */}
{ /* START Radios */}
<FormGroup row>
<Label for="operatingSystem11" sm={4} className="pt-0">
Operating System
</Label>
<Col sm={8}>
<CustomInput
type="radio"
id="operatingSystem11"
name="operatingSystem"
label="OSX"
inline
defaultChecked
/>
<CustomInput
type="radio"
id="operatingSystem12"
name="operatingSystem"
label="Windows"
inline
/>
<CustomInput
type="radio"
id="operatingSystem13"
name="operatingSystem"
label="Linux"
inline
disabled
/>
</Col>
</FormGroup>
{ /* END Radios */}
{ /* START Select */}
<FormGroup row>
<Label for="country-selector-1" sm={4}>
Country
</Label>
<Col sm={8}>
<CustomInput
type="select"
name="customSelect"
id="country-selector-1"
>
<option value="">Select Country...</option>
<option>United States of America (US)</option>
<option>United Kingdom (UK)</option>
<option>Australia</option>
<option>Canada</option>
<option>Other...</option>
</CustomInput>
</Col>
</FormGroup>
{ /* END Select */}
{ /* START File Select */}
<FormGroup row>
<Label for="addCv" sm={4}>
Add CV
</Label>
<Col sm={8}>
<CustomInput type="file" id="addCv" name="customFile" label="Choose file..." />
<FormText color="muted">
Accepted formats: pdf, doc, txt. Max file size 7Mb
</FormText>
</Col>
</FormGroup>
{ /* END File Select */}
{ /* START Textarea */}
<FormGroup row>
<Label for="message-1" sm={4}>
Message
</Label>
<Col sm={8}>
<Input
type="textarea"
name="text"
id="message-1"
placeholder="Enter Your Message..."
className="mb-2"
/>
<CustomInput
type="checkbox"
id="iConfirm2"
label="I confirm that I have read the Terms."
className="mb-3"
/>
<Button color="primary">Save</Button>
</Col>
</FormGroup>
{ /* END Textarea */}
</Form>
{ /* END Form */}
</CardBody>
</Card>
<Card className="mb-3">
<CardBody>
<CardTitle tag="h6" className="mb-4">
Forms Without Labels: Preview Example #1.03
<span className="small ml-1 text-muted">
#1.03
</span>
</CardTitle>
{ /* START Form */}
<Form>
{ /* START Input */}
<FormGroup>
<Input
type="text"
name=""
placeholder="Enter Name..."
/>
</FormGroup>
{ /* END Input */}
{ /* START Input */}
<FormGroup>
<Input
type="password"
name="password"
placeholder="Password..."
/>
</FormGroup>
{ /* END Input */}
{ /* START Radios */}
<FormGroup>
<CustomInput
type="radio"
name="operatingSystem"
id="operatingSystem21"
label="OSX"
inline
defaultChecked
/>
<CustomInput
type="radio"
name="operatingSystem"
id="operatingSystem22"
label="Windows"
inline
/>
<CustomInput
type="radio"
name="operatingSystem"
id="operatingSystem23"
label="Linux"
inline
disabled
/>
</FormGroup>
{ /* END Radios */}
{ /* START Select */}
<FormGroup>
<CustomInput
type="select"
name="customSelect"
id="country-selector"
>
<option value="">Select Country...</option>
<option>United States of America (US)</option>
<option>United Kingdom (UK)</option>
<option>Australia</option>
<option>Canada</option>
<option>Other...</option>
</CustomInput>
</FormGroup>
{ /* END Select */}
{ /* START File Select */}
<FormGroup>
<CustomInput type="file" id="addCv1" name="customFile" label="Choose file..." />
<FormText color="muted">
Accepted formats: pdf, doc, txt. Max file size 7Mb
</FormText>
</FormGroup>
{ /* END File Select */}
{ /* START Textarea */}
<FormGroup>
<Input
type="textarea"
name="text"
placeholder="Enter Your Message..."
className="mb-2"
/>
<CustomInput
type="checkbox"
id="iConfirm3"
label="I confirm that I have read the Terms."
className="mb-3"
/>
<Button color="primary">Save</Button>
</FormGroup>
{ /* END Textarea */}
</Form>
{ /* END Form */}
</CardBody>
</Card>
</Col>
<Col lg={ 6 }>
<Card className="mb-3">
<CardBody>
<CardTitle tag="h6" className="mb-4">
Forms Vertical: Preview Example
<span className="small ml-1 text-muted">
#1.02
</span>
</CardTitle>
{ /* START Form */}
<Form>
{ /* START Input */}
<FormGroup>
<Label for="input-2">
Input
</Label>
<Input
type="text"
name=""
id="input-2"
placeholder="Enter Name..."
/>
</FormGroup>
{ /* END Input */}
{ /* START Input */}
<FormGroup>
<Label for="inputPassword-2">
Password
</Label>
<Input
type="password"
name="password"
id="inputPassword-2"
placeholder="Password..."
/>
</FormGroup>
{ /* END Input */}
{ /* START Radios */}
<FormGroup>
<Label for="operatingSystem" className="pt-0">
Operating System
</Label>
<div>
<CustomInput
type="radio"
id="operatingSystem1"
name="operatingSystem"
label="OSX"
inline
defaultChecked
/>
<CustomInput
type="radio"
id="operatingSystem2"
name="operatingSystem"
label="Windows"
inline
/>
<CustomInput
type="radio"
id="operatingSystem3"
name="operatingSystem"
label="Linux"
inline
disabled
/>
</div>
</FormGroup>
{ /* END Radios */}
{ /* START Select */}
<FormGroup>
<Label for="country-selector-2">
Country
</Label>
<CustomInput
type="select"
name="customSelect"
id="country-selector-2"
>
<option value="">Select Country...</option>
<option>United States of America (US)</option>
<option>United Kingdom (UK)</option>
<option>Australia</option>
<option>Canada</option>
<option>Other...</option>
</CustomInput>
</FormGroup>
{ /* END Select */}
{ /* START File Select */}
<FormGroup>
<Label for="addCv2">
Add CV
</Label>
<CustomInput type="file" id="addCv2" name="customFile" label="Choose file..." />
<FormText color="muted">
Accepted formats: pdf, doc, txt. Max file size 7Mb
</FormText>
</FormGroup>
{ /* END File Select */}
{ /* START Textarea */}
<FormGroup>
<Label for="message-2">
Message
</Label>
<Input
type="textarea"
name="text"
id="message-2"
placeholder="Enter Your Message..."
className="mb-2"
/>
<CustomInput
type="checkbox"
id="iConfirm"
label="I confirm that I have read the Terms."
className="mb-3"
/>
<Button color="primary">Save</Button>
</FormGroup>
{ /* END Textarea */}
</Form>
{ /* END Form */}
</CardBody>
</Card>
</Col>
</Row>
{ /* END Section 1 */}
{ /* START Header 2 */}
<Row>
<Col lg={ 12 }>
<HeaderDemo
no={2}
title="Forms Inline"
className="mt-5"
subTitle={(
<React.Fragment>
Form controls within inline forms vary slightly from their default states.
</React.Fragment>
)}
/>
</Col>
</Row>
{ /* END Header 2 */}
{ /* START Section 2 */}
<Row>
<Col lg={ 12 }>
<Card className="mb-3">
<CardBody>
<CardTitle tag="h6" className="mb-4">
Forms Inline: Preview Example
<span className="small ml-1 text-muted">
#2.01
</span>
</CardTitle>
{ /* START Form */}
<Form inline>
<FormGroup className="mb-2 mr-sm-2 mb-sm-0">
<Input type="text" name="text" id="enterName" placeholder="Enter Name..." />
</FormGroup>
<FormGroup className="mb-2 mr-sm-2 mb-sm-0">
<InputGroup>
<InputGroupAddon addonType="prepend">
<i className="fa fa-key fa-fw" />
</InputGroupAddon>
<Input type="password" name="password" placeholder="Password..." />
</InputGroup>
</FormGroup>
<FormGroup className="mb-2 mr-sm-2 mb-sm-0">
<InputGroup>
<InputGroupAddon addonType="prepend">
Country
</InputGroupAddon>
<CustomInput type="select" id="country-selector-3" name="customSelect">
<option value="">Select...</option>
<option>United Kingdom</option>
<option>United States</option>
<option>Canada</option>
<option>Australia</option>
<option>New Zeland</option>
</CustomInput>
</InputGroup>
</FormGroup>
<FormGroup>
<CustomInput type="checkbox" id="rememberMe" label="Remember Me" inline />
</FormGroup>
<Button color="primary">
Submit
</Button>
</Form>
{ /* END Form */}
</CardBody>
</Card>
</Col>
</Row>
{ /* END Section 2 */}
</Container>
</React.Fragment>
);
export default FormsLayouts;

View File

@@ -0,0 +1,3 @@
import FormsLayouts from './FormsLayouts';
export default FormsLayouts;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
import InputGroups from './InputGroups';
export default InputGroups;

View File

@@ -0,0 +1,500 @@
import React from 'react';
import PropTypes from 'prop-types';
import Slider, { Range } from 'rc-slider';
import colors from './../../../colors';
import {
Form,
FormGroup,
Card,
CardBody,
CardTitle,
Label,
Input,
Button,
Row,
Col,
Container
} from './../../../components';
import { HeaderMain } from "../../components/HeaderMain";
import { HeaderDemo } from "../../components/HeaderDemo";
import classes from './Sliders.scss';
const marks = {
'-10': '-10°C',
0: <strong>0°C</strong>,
26: '26°C',
37: '37°C',
50: '50°C',
100: {
style: {
color: colors['danger'],
},
label: <strong>100°C</strong>,
},
}
class CustomizedRange extends React.Component {
constructor(props) {
super(props);
this.state = {
lowerBound: 20,
upperBound: 40,
value: [20, 40]
};
}
onLowerBoundChange(e) {
this.setState({ lowerBound: +e.target.value });
}
onUpperBoundChange(e) {
this.setState({ upperBound: +e.target.value });
}
onSliderChange(value) {
this.setState({
value,
});
}
handleApply() {
const { lowerBound, upperBound } = this.state;
this.setState({ value: [lowerBound, upperBound] });
}
render() {
return (
<div>
<Form inline className='mb-3 d-flex justify-content-between'>
<div className="d-flex">
<FormGroup className='mr-3'>
<Label>
Lower Bound
</Label>
<Input
type="number"
bsSize="sm"
className={ classes.inlineInput }
value={this.state.lowerBound}
onChange={this.onLowerBoundChange.bind(this)}
/>
</FormGroup>
<FormGroup>
<Label>
Upper Bound
</Label>
<Input
type="number"
bsSize="sm"
className={ classes.inlineInput }
value={this.state.upperBound}
onChange={this.onUpperBoundChange.bind(this)}
/>
</FormGroup>
</div>
<FormGroup>
<Button
onClick={this.handleApply.bind(this)}
type="button"
color="primary"
size="sm"
block
>
Apply
</Button>
</FormGroup>
</Form>
<div className={ classes.sliderWrap }>
<Range allowCross={false} value={this.state.value} onChange={this.onSliderChange.bind(this)} />
</div>
</div>
);
}
}
class DynamicBounds extends React.Component {
static propTypes = {
children: PropTypes.node.isRequired
}
constructor(props) {
super(props);
this.state = {
min: 0,
max: 100,
};
}
onMinChange(e) {
this.setState({
min: +e.target.value || 0,
});
}
onMaxChange(e) {
this.setState({
max: +e.target.value || 100,
});
}
render() {
const { children } = this.props;
const updatedChild = React.cloneElement(React.Children.only(children), {
min: this.state.min,
max: this.state.max
});
return (
<div>
<Form inline className="mb-3">
<FormGroup className="mr-3">
<Label>
Min
</Label>
<Input
className={ classes.inlineInput }
type="number"
value={this.state.min}
onChange={this.onMinChange.bind(this)}
bsSize="sm"
/>
</FormGroup>
<FormGroup>
<Label>
Max
</Label>
<Input
className={ classes.inlineInput }
type="number"
value={this.state.max}
onChange={this.onMaxChange.bind(this)}
bsSize="sm"
/>
</FormGroup>
</Form>
<div className={ classes.sliderWrap }>
{ updatedChild }
</div>
</div>
);
}
}
class ControlledRange extends React.Component {
constructor(props) {
super(props);
this.state = {
value: [20, 40, 60, 80],
};
}
handleChange = (value) => {
this.setState({
value,
});
}
render() {
return (
<Range value={this.state.value} onChange={this.handleChange}/>
);
}
}
class CustomizedSlider extends React.Component {
constructor() {
super();
this.state = {
value: 50
}
}
onSliderChange(value) {
this.setState({
value
});
}
render() {
return(
<Slider value={this.state.value} onChange={this.onSliderChange.bind(this)} />
)
}
}
export class Sliders extends React.Component {
render() {
return (
<Container>
<HeaderMain
title="Sliders"
className="mb-5 mt-4"
/>
<Row>
<Col>
{ /* START Header 1 */}
<HeaderDemo
no={1}
title="Marks"
subTitle={(
<React.Fragment>
See 6 examples below:
</React.Fragment>
)}
/>
{ /* END Header 1 */}
{ /* START Card Example */}
<Card>
<CardBody>
<Row>
<Col lg={ 6 }>
<p>Slider with marks, <code>step=null</code></p>
<div className={ classes.markedSliderWrap }>
<Slider min={-10} marks={marks} step={null} defaultValue={20} />
</div>
</Col>
<Col lg={ 6 }>
<p>Slider with marks, <code>included=false</code></p>
<div className={ classes.markedSliderWrap }>
<Slider min={-10} marks={marks} included={false} defaultValue={20} />
</div>
</Col>
<Col lg={ 6 }>
<p>Slider with marks and steps</p>
<div className={ classes.markedSliderWrap }>
<Slider dots min={-10} marks={marks} step={10} defaultValue={20} />
</div>
</Col>
<Col lg={ 6 }>
<p>Slider with marks and steps, <code>included=false</code></p>
<div className={ classes.markedSliderWrap }>
<Slider min={-10} marks={marks} step={10} included={false} defaultValue={20} />
</div>
</Col>
<Col lg={ 6 }>
<p>Range with marks</p>
<div className={ classes.markedSliderWrap }>
<Range min={-10} marks={marks} defaultValue={[20, 40]} />
</div>
</Col>
<Col lg={ 6 }>
<p>Range with marks and steps</p>
<div className={ classes.markedSliderWrap }>
<Range min={-10} marks={marks} step={10} defaultValue={[20, 40]} />
</div>
</Col>
</Row>
</CardBody>
</Card>
{ /* END Card Example */}
{ /* START Header 2 */}
<HeaderDemo
no={2}
title="Range"
className="mt-5"
subTitle={(
<React.Fragment>
See 8 examples below:
</React.Fragment>
)}
/>
{ /* END Header 2 */}
{ /* START Card Example */}
<Card>
<CardBody>
<Row>
<Col lg={ 6 }>
<p>Basic Range<code>allowCross=false</code></p>
<div className={ classes.rangeSliderWrap }>
<Range allowCross={false} defaultValue={[0, 20]} />
</div>
</Col>
<Col lg={ 6 }>
<p>Basic Range<code>disabled</code></p>
<div className={ classes.rangeSliderWrap }>
<Range allowCross={false} defaultValue={[0, 20]} disabled />
</div>
</Col>
<Col lg={ 6 }>
<p>Basic Range<code>step=20</code> </p>
<div className={ classes.rangeSliderWrap }>
<Range step={20} defaultValue={[20, 20]} />
</div>
</Col>
<Col lg={ 6 }>
<p>Basic Range<code>step=20, dots</code> </p>
<div className={ classes.rangeSliderWrap }>
<Range dots step={20} defaultValue={[20, 40]} />
</div>
</Col>
<Col lg={ 6 }>
<p>Controlled Range</p>
<div className={ classes.rangeSliderWrap }>
<ControlledRange />
</div>
</Col>
<Col lg={ 6 }>
<p>Multi Range</p>
<div className={ classes.rangeSliderWrap }>
<Range count={3} defaultValue={[20, 40, 60, 80]} pushable />
</div>
</Col>
<Col lg={ 6 }>
<p>Customized Range</p>
<div className={ classes.rangeSliderWrap }>
<CustomizedRange />
</div>
</Col>
<Col lg={ 6 }>
<p>Range with dynamic <code>max</code> <code>min</code></p>
<div className={ classes.rangeSliderWrap }>
<DynamicBounds>
<Range defaultValue={[20, 50]} />
</DynamicBounds>
</div>
</Col>
</Row>
</CardBody>
</Card>
{ /* END Card Example */}
{ /* START Header 3 */}
<HeaderDemo
no={3}
title="Sliders"
className="mt-5"
subTitle={(
<React.Fragment>
See 7 examples below:
</React.Fragment>
)}
/>
{ /* END Header 3 */}
{ /* START Card Example */}
<Card>
<CardBody>
<Row>
<Col lg={ 6 }>
<p>Basic Slider</p>
<div className={ classes.rangeSliderWrap }>
<Slider tipTransitionName="rc-slider-tooltip-zoom-down" />
</div>
</Col>
<Col lg={ 6 }>
<p>Basic Slider, <code>disabled</code></p>
<div className={ classes.rangeSliderWrap }>
<Slider tipTransitionName="rc-slider-tooltip-zoom-down" disabled />
</div>
</Col>
<Col lg={ 6 }>
<p>Basic Slider<code>step=20</code></p>
<div className={ classes.rangeSliderWrap }>
<Slider step={20} defaultValue={50} />
</div>
</Col>
<Col lg={ 6 }>
<p>Basic Slider<code>step=20, dots</code></p>
<div className={ classes.rangeSliderWrap }>
<Slider dots step={20} defaultValue={100} />
</div>
</Col>
<Col lg={ 6 }>
<p>Controlled Slider</p>
<div className={ classes.rangeSliderWrap }>
<Slider value={50} />
</div>
</Col>
<Col lg={ 6 }>
<p>Customized Slider</p>
<div className={ classes.rangeSliderWrap }>
<CustomizedSlider />
</div>
</Col>
<Col lg={ 6 }>
<p>Slider with dynamic <code>min</code>, <code>max</code></p>
<div className={ classes.rangeSliderWrap }>
<DynamicBounds>
<Slider defaultValue={50} />
</DynamicBounds>
</div>
</Col>
</Row>
</CardBody>
</Card>
{ /* START Header 4 */}
<HeaderDemo
no={4}
title="Vertical Sliders"
className="mt-5"
subTitle={(
<React.Fragment>
See 6 examples below:
</React.Fragment>
)}
/>
{ /* END Header 4 */}
{ /* START Card Example */}
<Card>
<CardBody>
<Row>
<Col lg={ 3 }>
<p>Slider with marks, <code>step=null</code></p>
<div className={ classes.markedSliderVerticalWrap }>
<Slider vertical min={-10} marks={marks} step={null} defaultValue={20} />
</div>
</Col>
<Col lg={ 3 }>
<p>Slider with marks and steps</p>
<div className={ classes.markedSliderVerticalWrap }>
<Slider vertical dots min={-10} marks={marks} step={10} defaultValue={20} />
</div>
</Col>
<Col lg={ 3 }>
<p>Slider with marks, <code>included=false</code></p>
<div className={ classes.markedSliderVerticalWrap }>
<Slider vertical min={-10} marks={marks} included={false} defaultValue={20} />
</div>
</Col>
<Col lg={ 3 }>
<p>Slider with marks and steps, <code>included=false</code></p>
<div className={ classes.markedSliderVerticalWrap }>
<Slider vertical min={-10} marks={marks} step={10} included={false} defaultValue={20} />
</div>
</Col>
<Col lg={ 3 }>
<p>Range with marks</p>
<div className={ classes.markedSliderVerticalWrap }>
<Range vertical min={-10} marks={marks} defaultValue={[20, 40]} />
</div>
</Col>
<Col lg={ 3 }>
<p>Range with marks and steps</p>
<div className={ classes.markedSliderVerticalWrap }>
<Range vertical min={-10} marks={marks} step={10}
defaultValue={[20, 40]}
/>
</div>
</Col>
</Row>
</CardBody>
</Card>
{ /* END Card Example */}
</Col>
</Row>
</Container>
);
}
}

View File

@@ -0,0 +1,21 @@
.markedSliderWrap {
padding: 0px 20px 50px;
}
.rangeSliderWrap {
padding: 0 0 20px 0;
}
.markedSliderVerticalWrap {
width: 100%;
height: 400px;
display: flex;
align-items: center;
justify-content: center;
padding: 20px 20px 30px 20px;
}
.inlineInput {
max-width: 70px;
margin-left: 0.5rem;
}

View File

@@ -0,0 +1,3 @@
import { Sliders } from './Sliders';
export default Sliders;

View File

@@ -0,0 +1,216 @@
import React from 'react';
import MaskedInput from 'react-text-mask'
import {
createAutoCorrectedDatePipe,
createNumberMask,
emailMask
} from 'text-mask-addons';
import {
Row,
Card,
CardBody,
Container,
Col,
FormGroup,
Label,
Input
} from './../../../components';
import { HeaderMain } from "../../components/HeaderMain";
const autoCorrectedDatePipe = createAutoCorrectedDatePipe('mm/dd/yyyy');
const dolarsMask = createNumberMask({ prefix: '$' });
const dolarsMaskDecimal = createNumberMask({ prefix: '$', allowDecimal: true });
const percentageMask = createNumberMask({ prefix: '', suffix: '%', integerLimit: 3 });
const upperCasePipe = conformedValue => conformedValue.toUpperCase();
export const TextMask = () => (
<Container>
<HeaderMain
title="Text Mask"
className="mb-4 mt-4"
/>
<p className="mb-3">
Text Mask is an input mask library.
It can create input masks for <code>phone</code>,
<code>date</code>, <code>currency</code>, <code>zip code</code>, <code>percentage</code>, <code>email</code>, and literally anything!
</p>
<Card>
<CardBody>
<Row>
<Col lg={ 4 }>
<FormGroup>
<Label for="uSPhoneNumber">
US Phone Number
<span className="small ml-1 text-muted">
#1.01
</span>
</Label>
<Input
mask={ ['(', /[1-9]/, /\d/, /\d/, ')', ' ', /\d/, /\d/, /\d/, '-', /\d/, /\d/, /\d/, /\d/] }
placeholder='(555) 495-3947'
tag={ MaskedInput }
id="uSPhoneNumber"
/>
</FormGroup>
</Col>
<Col lg={ 4 }>
<FormGroup>
<Label for="uSPhoneNumberWith">
US Phone Number With Masked Input
<span className="small ml-1 text-muted">
#1.02
</span>
</Label>
<Input
mask={ ['+', '1', ' ', '(', /[1-9]/, /\d/, /\d/, ')', ' ', /\d/, /\d/, /\d/, '-', /\d/, /\d/, /\d/, /\d/] }
placeholder='+1 (555) 495-3947'
tag={ MaskedInput }
id="uSPhoneNumberWith"
/>
</FormGroup>
</Col>
<Col lg={ 4 }>
<FormGroup>
<Label for="date">
Date
<span className="small ml-1 text-muted">
#1.03
</span>
</Label>
<Input
mask={ [/\d/, /\d/, '/', /\d/, /\d/, '/', /\d/, /\d/, /\d/, /\d/] }
placeholder='25/09/1970'
tag={ MaskedInput }
id="date"
/>
</FormGroup>
</Col>
<Col lg={ 4 }>
<FormGroup>
<Label for="dateAuto">
Date (Auto-Corrected)
<span className="small ml-1 text-muted">
#1.04
</span>
</Label>
<Input
mask={ [/\d/, /\d/, '/', /\d/, /\d/, '/', /\d/, /\d/, /\d/, /\d/] }
keepCharPositions={ true }
pipe={ autoCorrectedDatePipe }
placeholder='Please Enter a Date'
tag={ MaskedInput }
id="dateAuto"
/>
</FormGroup>
</Col>
<Col lg={ 4 }>
<FormGroup>
<Label for="uSDollarAmount">
US dollar amount
<span className="small ml-1 text-muted">
#1.05
</span>
</Label>
<Input
mask={ dolarsMask }
className='text-right form-control'
placeholder='Enter an amount'
tag={ MaskedInput }
id="uSDollarAmount"
/>
</FormGroup>
</Col>
<Col lg={ 4 }>
<FormGroup>
<Label for="uSDollarAmountAllows">
US dollar amount (allows decimal)
<span className="small ml-1 text-muted">
#1.06
</span>
</Label>
<Input
mask={ dolarsMaskDecimal }
className='text-right form-control'
placeholder='Enter an amount'
tag={ MaskedInput }
id="uSDollarAmountAllows"
/>
</FormGroup>
</Col>
<Col lg={ 4 }>
<FormGroup>
<Label for="percentageAmount">
Percentage Amount
<span className="small ml-1 text-muted">
#1.07
</span>
</Label>
<Input
mask={ percentageMask }
className='text-right form-control'
placeholder='Enter an amount'
tag={ MaskedInput }
id="percentageAmount"
/>
</FormGroup>
</Col>
<Col lg={ 4 }>
<FormGroup>
<Label for="email">
Email
<span className="small ml-1 text-muted">
#1.08
</span>
</Label>
<Input
mask={ emailMask }
placeholder='john@smith.com'
tag={ MaskedInput }
id="email"
/>
</FormGroup>
</Col>
<Col lg={ 4 }>
<FormGroup>
<Label for="uSZipCode">
US Zip Code
<span className="small ml-1 text-muted">
#1.09
</span>
</Label>
<Input
mask={ [/[1-9]/, /\d/, /\d/, /\d/, /\d/] }
placeholder='94303'
tag={ MaskedInput }
id="uSZipCode"
/>
</FormGroup>
</Col>
<Col lg={ 4 }>
<FormGroup>
<Label for="canadianPostal">
Canadian Postal Code
<span className="small ml-1 text-muted">
#1.10
</span>
</Label>
<Input
pipe={ upperCasePipe }
mask={ [/[A-Z]/i, /\d/, /[A-Z]/i, ' ', /\d/, /[A-Z]/i, /\d/] }
placeholder='K1A 0B2'
tag={ MaskedInput }
id="canadianPostal"
/>
</FormGroup>
</Col>
</Row>
</CardBody>
</Card>
</Container>
);

View File

@@ -0,0 +1,3 @@
import { TextMask } from './TextMask';
export default TextMask;

View File

@@ -0,0 +1,201 @@
import React from 'react';
import {
Row,
Col,
Table,
Container,
CustomInput
} from './../../../components';
import Toggle from 'react-toggle';
import { HeaderMain } from "../../components/HeaderMain";
import { HeaderDemo } from "../../components/HeaderDemo";
import classes from './Toggles.scss';
export class Toggles extends React.Component {
state = {
baconIsReady: true,
cheeseIsReady: false,
biscuitIsReady: false,
eggsAreReady: false,
milkIsReady: false,
toastIsReady: false,
soupIsReady: true,
tofuIsReady: false
}
render() {
return (
<Container>
<HeaderMain
title="Toggles"
className="mb-5 mt-4"
/>
<p className="mb-4">An elegant, accessible toggle component for React. Also a glorified checkbox.</p>
<Row>
<Col lg={ 6 }>
<Table>
<thead>
<tr>
<th>
Switch Name
</th>
<th className="text-right">
Switch Example
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<CustomInput
type="checkbox"
id="controlled-component-check"
checked={ this.state.milkIsReady }
onChange={ () => { this.setState({ milkIsReady: !this.state.milkIsReady }) } }
label="Controlled Component"
/>
</td>
<td className="text-right">
<Toggle
checked={ this.state.milkIsReady }
name='milkIsReady'
value='yes'
onChange={ () => { this.setState({ milkIsReady: !this.state.milkIsReady }) } }/>
</td>
</tr>
<tr>
<td>
<CustomInput
type="checkbox"
id="controlled-component-check-no-onchange"
checked={ this.state.toastIsReady }
onChange={ () => { this.setState({ toastIsReady: !this.state.toastIsReady }) } }
label="Controlled Component without onChange"
/>
</td>
<td className="text-right">
<Toggle
checked={ this.state.toastIsReady }
name='toastIsReady'
value='yes' />
</td>
</tr>
<tr>
<td className="text-inverse">
Diabled, Unchecked
</td>
<td className="text-right">
<Toggle
defaultChecked={false}
disabled={true} />
</td>
</tr>
<tr>
<td className="text-inverse">
Disabled, Checked
</td>
<td className="text-right">
<Toggle
defaultChecked={true}
disabled={true} />
</td>
</tr>
<tr>
<td className="text-inverse">
Custom className
</td>
<td className="text-right">
<Toggle
defaultChecked={this.state.aubergineIsReady}
className={ classes.switchCustomClass }
onChange={this.handleAubergineChange} />
</td>
</tr>
<tr>
<td className="text-inverse">
Custom Icons
</td>
<td className="text-right">
<Toggle
defaultChecked={this.state.soupIsReady}
icons={{
checked: <i className="fa fa-heart text-white" />,
unchecked: null,
}}
onChange={ () => { this.setState({ soupIsReady: !this.state.soupIsReady }) } } />
</td>
</tr>
<tr>
<td className="text-inverse">
No Icons
</td>
<td className="text-right">
<Toggle
defaultChecked={this.state.tofuIsReady}
icons={false}
onChange={() => { this.setState({ tofuIsReady: !this.state.tofuIsReady }) }} />
</td>
</tr>
</tbody>
</Table>
</Col>
<Col lg={ 6 }>
<Table className={ classes.singleTable }>
<thead>
<tr>
<th>
Switch Example
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<label className="d-flex align-items-middle mb-0">
<Toggle
defaultChecked={this.state.baconIsReady}
onChange={() => { this.setState({baconIsReady: !this.state.baconIsReady}) }} />
<span className="ml-2 text-inverse">Wrapper label tag</span>
</label>
</td>
</tr>
<tr>
<td className="d-flex align-items-middle">
<Toggle
id='cheese-status'
defaultChecked={this.state.cheeseIsReady}
onChange={ () => { this.setState({cheeseIsReady: !this.state.cheeseIsReady}) } } />
<label htmlFor='cheese-status' className="ml-2 mb-0 text-inverse">Adjacent label tag</label>
</td>
</tr>
<tr>
<td className="d-flex align-items-middle">
<Toggle
id='biscuit-status'
defaultChecked={this.state.biscuitIsReady}
aria-labelledby='biscuit-label'
onChange={ () => { this.setState({biscuitIsReady: !this.state.biscuitIsReady}) } } />
<span id='biscuit-label' className="ml-2 text-inverse">Adjacent label, but not standard tag</span>
</td>
</tr>
<tr>
<td className="d-flex align-items-middle">
<Toggle
defaultChecked={this.state.eggsAreReady}
aria-label='No label tag'
onChange={ () => { this.setState({eggsAreReady: !this.state.eggsAreReady}) } } />
<span className="ml-2 text-inverse">No label tag</span>
</td>
</tr>
</tbody>
</Table>
</Col>
</Row>
</Container>
);
}
}

View File

@@ -0,0 +1,3 @@
.switchCustomClass > :first-child {
background-color: #ab199f;
}

View File

@@ -0,0 +1,3 @@
import { Toggles } from './Toggles';
export default Toggles;

View File

@@ -0,0 +1,451 @@
import React from 'react';
import {
Container,
Row,
Card,
CardBody,
CardTitle,
Col
} from './../../../components';
import {
BasicExample,
BasicBehaviors,
ControllingSelections,
InputSize,
MenuAlignment,
FormExample,
PaginationExample,
BodyContainer,
RenderingExample,
LabelKey,
FilteringExample,
CustomFilteringExample,
CustomSelections,
AsyncSearch,
AsyncPagination,
PublicMethods
} from './components';
import { HeaderMain } from "../../components/HeaderMain";
import { HeaderDemo } from "../../components/HeaderDemo";
export const Typeahead = () => (
<Container>
<HeaderMain
title="Typeahead"
className="mb-5 mt-4"
/>
<Row>
<Col>
{ /* START Header Example */}
<HeaderDemo
no={1}
title="Basic Example"
subTitle={(
<React.Fragment>
The typeahead allows single-selection by default.
Setting the <code>multiple</code> prop turns the component into a tokenizer,
allowing multiple selections.
</React.Fragment>
)}
/>
{ /* END Header Example */}
{ /* START Card Example */}
<Card>
<CardBody className="pb-0">
<CardTitle tag="h6">
Basic Example
<span className="small ml-1 text-muted">
#1.01
</span>
</CardTitle>
<BasicExample />
</CardBody>
</Card>
{ /* END Card Example */}
</Col>
</Row>
{ /* START Header Example */}
<HeaderDemo
no={2}
title="Behaviors"
className="mt-5"
subTitle={(
<React.Fragment>
The typeahead has several basic configurable behaviors.
You can <code>disable</code> it as you would any input.
You can position the menu above the input with <code>dropup</code> or aoutomatically re-position it when it hits the viewport bounds.
Use <code>minLength</code> to require a minimum user input before displaying results,
or hide the menu when there are no results by passing an empty
string to <code>emptyLabel</code>.
</React.Fragment>
)}
/>
{ /* END Header Example */}
<Row className="mt-3">
<Col>
{ /* START Card Example */}
<Card>
<CardBody className="pb-0">
<CardTitle tag="h6">
Behaviors
<span className="small ml-1 text-muted">
#2.01
</span>
</CardTitle>
<BasicBehaviors />
</CardBody>
</Card>
{ /* END Card Example */}
</Col>
</Row>
<Row className="mt-4">
<Col>
{ /* START Card Example */}
<Card>
<CardBody>
<CardTitle tag="h6">
Controlling Selections
<span className="small ml-1 text-muted">
#2.02
</span>
</CardTitle>
<p>
You can pre-populate the the typeahead by passing in an array of selections.
Setting the <code>clearButton</code> prop displays a button allowing users to clear the input.
</p>
<ControllingSelections />
</CardBody>
</Card>
{ /* END Card Example */}
</Col>
</Row>
<Row className="mt-4">
<Col>
{ /* START Card Example */}
<Card>
<CardBody className="pb-0">
<CardTitle tag="h6">
Input Size
<span className="small ml-1 text-muted">
#2.03
</span>
</CardTitle>
<p>
Besides the default input size, you can specify either a
<code>small</code> or <code>large</code> size using the <code>bsSize</code> prop.
</p>
<InputSize />
</CardBody>
</Card>
{ /* END Card Example */}
</Col>
</Row>
<Row className="mt-4">
<Col>
{ /* START Card Example */}
<Card>
<CardBody className="pb-0">
<CardTitle tag="h6">
Menu Alignment
<span className="small ml-1 text-muted">
#2.04
</span>
</CardTitle>
<p>
Specify alignment of the menu via the <code>align</code> prop.
Valid values are <code>justify</code>, <code>left</code>, or <code>right</code>.
</p>
<MenuAlignment />
</CardBody>
</Card>
{ /* END Card Example */}
</Col>
</Row>
<Row className="mt-4">
<Col>
{ /* START Card Example */}
<Card>
<CardBody className="pb-0">
<CardTitle tag="h6">
Input Groups and Validation States
<span className="small ml-1 text-muted">
#2.05
</span>
</CardTitle>
<p>
The typeahead works with Bootstrap input groups and add-ons; it also handles validation states.
</p>
<FormExample />
</CardBody>
</Card>
{ /* END Card Example */}
</Col>
</Row>
<Row className="mt-4">
<Col>
{ /* START Card Example */}
<Card>
<CardBody className="pb-0">
<CardTitle tag="h6">
Pagination
<span className="small ml-1 text-muted">
#2.06
</span>
</CardTitle>
<p>
To improve browser performance, the typeahead paginates large data sets by default.
You can set the number of results to be displayed using <code>maxResults</code>,
or override pagination completely using <code>paginate</code>. The <code>onPaginate</code>
hook allows you to respond to the pagination event.
</p>
<PaginationExample />
</CardBody>
</Card>
{ /* END Card Example */}
</Col>
</Row>
<Row className="mt-5">
<Col>
<CardTitle tag="h6">
Body Container
<span className="small ml-1 text-muted">
#2.07
</span>
</CardTitle>
<p>
Setting the <code>bodyContainer</code> prop will attach the menu
to <code>document.body</code> instead of the typeahead.
Compare the behaviors in the srolling container below.
</p>
<BodyContainer />
</Col>
</Row>
{ /* START Header Example */}
<HeaderDemo
no={3}
title="Rendering"
className="mt-5"
subTitle={(
<React.Fragment>
You can customize how the typeahead looks and behaves by using the provided rendering hooks.
</React.Fragment>
)}
/>
{ /* END Header Example */}
<Row className="mt-3">
<Col>
{ /* START Card Example */}
<Card>
<CardBody className="pb-0">
<CardTitle tag="h6">
Rendering
<span className="small ml-1 text-muted">
#3.01
</span>
</CardTitle>
<p>
You can customize how the typeahead looks and behaves
by using the provided rendering hooks.
</p>
<RenderingExample />
</CardBody>
</Card>
{ /* END Card Example */}
</Col>
</Row>
<Row className="mt-4">
<Col>
{ /* START Card Example */}
<Card>
<CardBody>
<CardTitle tag="h6">
LabelKey
<span className="small ml-1 text-muted">
#3.02
</span>
</CardTitle>
<p>
The <code>labelKey</code> prop accepts a callback allowing you to transform
your data and return a compound string rather than just a single data field.
</p>
<LabelKey />
</CardBody>
</Card>
{ /* END Card Example */}
</Col>
</Row>
{ /* START Header Example */}
<HeaderDemo
no={4}
title="Filtering"
className="mt-5"
subTitle={(
<React.Fragment>
By default, the typeahead is not case-sensitive and ignores diacritical marks when filtering.
You can change these behaviors using the <code>caseSensitive</code> and
<code>ignoreDiacritics</code> props.
</React.Fragment>
)}
/>
{ /* END Header Example */}
<Row className="mt-3">
<Col>
{ /* START Card Example */}
<Card>
<CardBody className="pb-0">
<CardTitle tag="h6">
Filtering
<span className="small ml-1 text-muted">
#4.01
</span>
</CardTitle>
<p>
By default, the typeahead is not case-sensitive and ignores diacritical marks when filtering.
You can change these behaviors using the <code>caseSensitive</code> and
<code>ignoreDiacritics</code> props.
</p>
<FilteringExample />
</CardBody>
</Card>
{ /* END Card Example */}
</Col>
</Row>
<Row className="mt-4">
<Col>
{ /* START Card Example */}
<Card>
<CardBody className="pb-0">
<CardTitle tag="h6">
Custom Filtering
<span className="small ml-1 text-muted">
#4.02
</span>
</CardTitle>
<p>
Using the <code>filterBy</code> prop, you can either specify your own
callback or an array of fields on your data object by which to filter.
</p>
<CustomFilteringExample />
</CardBody>
</Card>
{ /* END Card Example */}
</Col>
</Row>
{ /* START Header Example */}
<HeaderDemo
no={5}
title="Custom Selections"
className="mt-5"
subTitle={(
<React.Fragment>
Setting the <code>allowNew</code> prop provides the ability to create new options for the data set.
You can change the label displayed before the custom option in the menu by using the
<code>newSelectionPrefix</code> prop.
</React.Fragment>
)}
/>
{ /* END Header Example */}
<Row className="mt-3">
<Col>
{ /* START Card Example */}
<Card>
<CardBody>
<CardTitle tag="h6">
Custom Selections
<span className="small ml-1 text-muted">
#5.01
</span>
</CardTitle>
<p>
Setting the <code>allowNew</code> prop provides the ability to create new options for the data set.
You can change the label displayed before the custom option in the menu by using the
<code>newSelectionPrefix</code> prop.
</p>
<CustomSelections />
</CardBody>
</Card>
{ /* END Card Example */}
</Col>
</Row>
{ /* START Header Example */}
<HeaderDemo
no={6}
title="Asynchronous Searching"
className="mt-5"
subTitle={(
<React.Fragment>
You can use the <code>AsyncTypeahead</code> component for asynchronous searches.
It debounces user input and includes an optional query cache to avoid making the same
request more than once in basic cases.
</React.Fragment>
)}
/>
{ /* END Header Example */}
<Row className="mt-3">
<Col>
{ /* START Card Example */}
<Card>
<CardBody className="pb-0">
<CardTitle tag="h6">
Asynchronous Searching
<span className="small ml-1 text-muted">
#6.01
</span>
</CardTitle>
<p>
You can use the <code>AsyncTypeahead</code> component for asynchronous searches.
It debounces user input and includes an optional query cache to avoid making the same
request more than once in basic cases.
</p>
<AsyncSearch />
</CardBody>
</Card>
{ /* END Card Example */}
</Col>
</Row>
<Row className="mt-4">
<Col>
{ /* START Card Example */}
<Card>
<CardBody>
<CardTitle tag="h6">
Pagination
<span className="small ml-1 text-muted">
#6.02
</span>
</CardTitle>
<p>
A more advanced case involves paginating async results.
Additional results are fetched using <code>onPaginate</code> while a
custom query cache tracks the incremental results and page number for each query.
</p>
<AsyncPagination />
</CardBody>
</Card>
{ /* END Card Example */}
</Col>
</Row>
<Row className="mt-4">
<Col>
{ /* START Card Example */}
<Card>
<CardBody>
<CardTitle tag="h6">
Public Methods
<span className="small ml-1 text-muted">
#6.03
</span>
</CardTitle>
<p>
The <code>clear</code>, <code>focus</code>, and <code>blur</code>
methods are exposed for programmatic control of the typeahead.
</p>
<PublicMethods />
</CardBody>
</Card>
{ /* END Card Example */}
</Col>
</Row>
</Container>
);

View File

@@ -0,0 +1,87 @@
import React from 'react';
import { AsyncTypeahead } from 'react-bootstrap-typeahead';
import { GithubMenuItem } from './GithubMenuItem';
import { makeAndHandleRequest } from './utils';
const PER_PAGE = 20;
export class AsyncPagination extends React.Component {
state = {
isLoading: false,
options: [],
query: '',
};
_cache = {};
render() {
return (
<AsyncTypeahead
{...this.state}
labelKey="login"
maxResults={PER_PAGE - 1}
minLength={2}
onInputChange={this._handleInputChange}
onPaginate={this._handlePagination}
onSearch={this._handleSearch}
paginate
placeholder="Search for a Github user..."
renderMenuItemChildren={(option) => (
<GithubMenuItem key={option.id} user={option} />
)}
useCache={false}
/>
);
}
_handleInputChange = (query) => {
this.setState({query});
}
_handlePagination = (e, shownResults) => {
const {query} = this.state;
const cachedQuery = this._cache[query];
// Don't make another request if:
// - the cached results exceed the shown results
// - we've already fetched all possible results
if (
cachedQuery.options.length > shownResults ||
cachedQuery.options.length === cachedQuery.total_count
) {
return;
}
this.setState({isLoading: true});
const page = cachedQuery.page + 1;
makeAndHandleRequest(query, page)
.then((resp) => {
const options = cachedQuery.options.concat(resp.options);
this._cache[query] = {...cachedQuery, options, page};
this.setState({
isLoading: false,
options,
});
});
}
_handleSearch = (query) => {
if (this._cache[query]) {
this.setState({options: this._cache[query].options});
return;
}
this.setState({isLoading: true});
makeAndHandleRequest(query)
.then((resp) => {
this._cache[query] = {...resp, page: 1};
this.setState({
isLoading: false,
options: resp.options,
});
});
}
}

View File

@@ -0,0 +1,74 @@
import React from 'react';
import { AsyncTypeahead } from 'react-bootstrap-typeahead';
import {
CustomInput,
FormGroup
} from './../../../../components';
import { GithubMenuItem } from './GithubMenuItem';
import { makeAndHandleRequest } from './utils';
export class AsyncSearch extends React.Component {
state = {
allowNew: false,
isLoading: false,
multiple: false,
options: [],
};
render() {
return (
<React.Fragment>
<AsyncTypeahead
{...this.state}
labelKey="login"
minLength={3}
onSearch={this._handleSearch}
placeholder="Search for a Github user..."
renderMenuItemChildren={(option) => (
<GithubMenuItem key={option.id} user={option} />
)}
/>
<FormGroup className="mt-2">
{this._renderCheckboxes()}
</FormGroup>
</React.Fragment>
);
}
_renderCheckboxes() {
const checkboxes = [
{label: 'Multi-Select', name: 'multiple'},
{label: 'Allow custom selections', name: 'allowNew'},
];
return checkboxes.map(({label, name}) => (
<CustomInput
checked={this.state[name]}
key={name}
name={name}
onChange={this._handleChange}
type="checkbox"
id={`control-${name}`}
label={label}
/>
));
}
_handleChange = (e) => {
const {checked, name} = e.target;
this.setState({[name]: checked});
}
_handleSearch = (query) => {
this.setState({isLoading: true});
makeAndHandleRequest(query)
.then(({options}) => {
this.setState({
isLoading: false,
options,
});
});
}
}

View File

@@ -0,0 +1,81 @@
import React from 'react';
import { Typeahead } from 'react-bootstrap-typeahead';
import _ from 'lodash';
import {
CustomInput,
FormGroup
} from './../../../../components';
import options from './exampleData';
export class BasicBehaviors extends React.Component {
state = {
disabled: false,
dropup: false,
flip: false,
highlightOnlyResult: false,
minLength: 0,
selectHintOnEnter: false
};
render() {
const {
disabled,
dropup,
emptyLabel,
flip,
highlightOnlyResult,
minLength,
selectHintOnEnter,
} = this.state;
const checkboxes = [
/* eslint-disable max-len */
{checked: disabled, label: 'Disable the input', name: 'disabled'},
{checked: dropup, label: 'Dropup menu', name: 'dropup'},
{checked: flip, label: 'Flip the menu position when it reaches the viewport bounds', name: 'flip'},
{checked: !!minLength, label: 'Require minimum input before showing results (2 chars)', name: 'minLength'},
{checked: emptyLabel, label: 'Hide the menu when there are no results', name: 'emptyLabel'},
{checked: selectHintOnEnter, label: 'Select the hinted result by pressing enter', name: 'selectHintOnEnter'},
{checked: highlightOnlyResult, label: 'Highlight the only result', name: 'highlightOnlyResult'},
/* eslint-enable max-len */
];
return (
<React.Fragment>
<Typeahead
{...this.state}
emptyLabel={emptyLabel ? '' : undefined}
labelKey="name"
options={options}
placeholder="Choose a state..."
/>
<FormGroup className="mt-2">
{
_.map(checkboxes, checkbox => (
<CustomInput
{...checkbox}
key={checkbox.name}
onChange={this._handleChange}
type="checkbox"
id={`basic-behaviors-${checkbox.name}`}
/>
))
}
</FormGroup>
</React.Fragment>
);
}
_handleChange = (e) => {
const {checked, name} = e.target;
const newState = {[name]: checked};
if (name === 'minLength') {
newState.minLength = checked ? 2 : 0;
}
this.setState(newState);
}
}

View File

@@ -0,0 +1,38 @@
import React from 'react';
import { Typeahead } from 'react-bootstrap-typeahead';
import {
CustomInput,
FormGroup
} from './../../../../components';
import options from './exampleData';
export class BasicExample extends React.Component {
state = {
multiple: false,
};
render() {
const {multiple} = this.state;
return (
<React.Fragment>
<Typeahead
labelKey="name"
multiple={multiple}
options={options}
placeholder="Choose a state..."
/>
<FormGroup className="mt-2">
<CustomInput
checked={multiple}
onChange={(e) => this.setState({multiple: e.target.checked})}
type="checkbox"
id="basic-example-multiselect"
label="Multi-Select"
/>
</FormGroup>
</React.Fragment>
);
}
}

View File

@@ -0,0 +1,64 @@
import React from 'react';
import { Typeahead } from 'react-bootstrap-typeahead';
import {
CustomInput,
Card,
FormGroup
} from './../../../../components';
import options from './exampleData';
export class BodyContainer extends React.Component {
state = {
bodyContainer: true,
dropup: false
};
render() {
const {bodyContainer, dropup} = this.state;
return (
<React.Fragment>
<Card
style={{
height: '116px',
overflowY: 'scroll',
padding: '40px',
}}
>
<div style={{height: '300px'}}>
<Typeahead
{...this.state}
labelKey="name"
options={options}
placeholder="Choose a state..."
/>
</div>
</Card>
<FormGroup className="mt-2">
<CustomInput
checked={bodyContainer}
name="bodyContainer"
onChange={this._handleChange}
type="checkbox"
id="enable-attach-menu"
label="Attach menu to document body"
/>
<CustomInput
checked={dropup}
name="dropup"
onChange={this._handleChange}
type="checkbox"
id="enable-dropup-menu"
label="Dropup menu"
/>
</FormGroup>
</React.Fragment>
);
}
_handleChange = (e) => {
const {checked, name} = e.target;
this.setState({[name]: checked});
}
}

View File

@@ -0,0 +1,15 @@
import React from 'react';
import { Typeahead } from 'react-bootstrap-typeahead';
import options from './exampleData';
export const ControllingSelections = () => (
<Typeahead
clearButton
defaultSelected={options.slice(0, 5)}
labelKey="name"
multiple
options={options}
placeholder="Choose a state..."
/>
)

View File

@@ -0,0 +1,65 @@
import React from 'react';
import { Typeahead } from 'react-bootstrap-typeahead';
import {
CustomInput,
FormGroup
} from './../../../../components';
import options from './exampleData';
export class CustomFilteringExample extends React.Component {
state = {
filterBy: 'callback',
};
render() {
const {filterBy} = this.state;
const radios = [
{label: 'Use callback', value: 'callback'},
{label: 'Use data fields', value: 'fields'},
];
const filterByCallback = (option, props) => {
return (
option.capital.toLowerCase().indexOf(props.text.toLowerCase()) !== -1 ||
option.name.toLowerCase().indexOf(props.text.toLowerCase()) !== -1
);
};
const filterByFields = ['capital', 'name'];
return (
<React.Fragment>
<Typeahead
filterBy={filterBy === 'callback' ? filterByCallback : filterByFields}
labelKey="name"
options={options}
placeholder="Filter by state name or capital..."
renderMenuItemChildren={(option) => (
<div>
{option.name}
<div>
<small>Capital: {option.capital}</small>
</div>
</div>
)}
/>
<FormGroup className="mt-2">
{
radios.map(({label, value}) => (
<CustomInput
checked={filterBy === value}
key={value}
onChange={() => this.setState({filterBy: value})}
type="radio"
value={value}
id={`capital-option-${value}`}
label={label}
/>
))
}
</FormGroup>
</React.Fragment>
);
}
}

View File

@@ -0,0 +1,12 @@
import React from 'react';
import { Typeahead } from 'react-bootstrap-typeahead';
export const CustomSelections = () => (
<Typeahead
allowNew
multiple
newSelectionPrefix="Add a new item: "
options={[]}
placeholder="Type anything..."
/>
);

View File

@@ -0,0 +1,69 @@
import React from 'react';
import { Typeahead } from 'react-bootstrap-typeahead';
import { FormGroup, CustomInput } from './../../../../components';
export class FilteringExample extends React.Component {
state = {
caseSensitive: false,
ignoreDiacritics: true,
};
render() {
const {caseSensitive, ignoreDiacritics} = this.state;
return (
<React.Fragment>
<Typeahead
{...this.state}
options={[
'Warsaw',
'Kraków',
'Łódź',
'Wrocław',
'Poznań',
'Gdańsk',
'Szczecin',
'Bydgoszcz',
'Lublin',
'Katowice',
'Białystok',
'Gdynia',
'Częstochowa',
'Radom',
'Sosnowiec',
'Toruń',
'Kielce',
'Gliwice',
'Zabrze',
'Bytom',
'Olsztyn',
'Bielsko-Biała',
'Rzeszów',
'Ruda Śląska',
'Rybnik',
]}
placeholder="Cities in Poland..."
/>
<FormGroup className="mt-2">
<CustomInput
checked={caseSensitive}
onChange={(e) => this.setState({caseSensitive: e.target.checked})}
type="checkbox"
id="case-sensitive-enabled"
label="Case-sensitive filtering"
/>
<CustomInput
checked={!ignoreDiacritics}
onChange={(e) => {
this.setState({ignoreDiacritics: !e.target.checked});
}}
type="checkbox"
id="ignore-diactrical-enabled"
label="Don't ignore diacritical marks"
/>
</FormGroup>
</React.Fragment>
);
}
}

View File

@@ -0,0 +1,67 @@
import React from 'react';
import _ from 'lodash';
import { Typeahead } from 'react-bootstrap-typeahead';
import {
InputGroup,
InputGroupAddon,
FormGroup,
Button
} from './../../../../components';
import options from './exampleData';
const getInitialState = () => ({
index: Math.floor(Math.random() * options.length),
selected: [],
});
export class FormExample extends React.Component {
state = getInitialState();
render() {
const {index, selected} = this.state;
const state = options[index];
let isInvalid;
let isValid;
if (selected.length) {
const isMatch = selected[0].name === state.name;
// BS4 validation
isInvalid = !isMatch;
isValid = isMatch;
}
return (
<React.Fragment>
<FormGroup>
<InputGroup>
<InputGroupAddon addonType="prepend">
<span className="input-group-text">
The capital of {state.name} is
</span>
</InputGroupAddon>
<Typeahead
isInvalid={isInvalid}
isValid={isValid}
labelKey="capital"
onChange={(selected) => this.setState({selected})}
options={_.sortBy(options, 'capital')}
placeholder="Select a capital..."
selected={selected}
/>
<InputGroupAddon addonType="append">
<Button
className="btn-outline-secondary"
onClick={() => this.setState(getInitialState())}
>
Play Again
</Button>
</InputGroupAddon>
</InputGroup>
</FormGroup>
</React.Fragment>
);
}
}

View File

@@ -0,0 +1,24 @@
import PropTypes from 'prop-types';
import React from 'react';
export const GithubMenuItem = ({user}) => (
<div>
<img
alt={user.login}
src={user.avatar_url}
style={{
height: '24px',
marginRight: '10px',
width: '24px',
}}
/>
<span>{user.login}</span>
</div>
);
GithubMenuItem.propTypes = {
user: PropTypes.shape({
avatar_url: PropTypes.string.isRequired,
login: PropTypes.string.isRequired,
}).isRequired,
};

View File

@@ -0,0 +1,50 @@
import React from 'react';
import _ from 'lodash';
import { Typeahead } from 'react-bootstrap-typeahead';
import {
CustomInput,
FormGroup
} from './../../../../components';
import options from './exampleData';
export class InputSize extends React.Component {
state = {
bsSize: undefined
};
render() {
const {bsSize} = this.state;
const radios = [
{label: 'Small', value: 'small'},
{label: 'Default', value: undefined},
{label: 'Large', value: 'large'},
];
return (
<React.Fragment>
<Typeahead
bsSize={bsSize}
labelKey="name"
options={options}
placeholder="Choose a state..."
/>
<FormGroup className="mt-2">
{
_.map(radios, ({ label, value }) => (
<CustomInput
checked={bsSize === value}
key={value || 'default'}
onChange={() => this.setState({bsSize: value})}
type="radio"
value={value}
id={`input-size-${label}`}
label={ label }
/>
))
}
</FormGroup>
</React.Fragment>
);
}
}

View File

@@ -0,0 +1,17 @@
import React from 'react';
import { Typeahead } from 'react-bootstrap-typeahead';
export const LabelKey = () => (
<Typeahead
labelKey={(option) => `${option.firstName} ${option.lastName}`}
options={[
{firstName: 'Art', lastName: 'Blakey'},
{firstName: 'John', lastName: 'Coltrane'},
{firstName: 'Miles', lastName: 'Davis'},
{firstName: 'Herbie', lastName: 'Hancock'},
{firstName: 'Charlie', lastName: 'Parker'},
{firstName: 'Tony', lastName: 'Williams'},
]}
placeholder="Who's the coolest cat?"
/>
);

View File

@@ -0,0 +1,50 @@
import React from 'react';
import _ from 'lodash';
import { Typeahead } from 'react-bootstrap-typeahead';
import {
CustomInput,
FormGroup
} from './../../../../components';
import options from './exampleData';
export class MenuAlignment extends React.Component {
state = {
align: 'justify',
};
render() {
const {align} = this.state;
const radios = [
{label: 'Justify (default)', value: 'justify'},
{label: 'Align left', value: 'left'},
{label: 'Align right', value: 'right'},
];
return (
<React.Fragment>
<Typeahead
align={align}
labelKey="name"
options={options}
placeholder="Choose a state..."
/>
<FormGroup className="mt-2">
{
_.map(radios, ({ label, value }) => (
<CustomInput
checked={align === value}
key={value || 'default'}
onChange={() => this.setState({align: value})}
type="radio"
value={value}
id={`input-align-${value}`}
label={ label }
/>
))
}
</FormGroup>
</React.Fragment>
);
}
}

View File

@@ -0,0 +1,38 @@
import React from 'react';
import _ from 'lodash';
import { Typeahead } from 'react-bootstrap-typeahead';
import {
CustomInput,
FormGroup
} from './../../../../components';
export class PaginationExample extends React.Component {
state = {
paginate: true,
};
render() {
const {paginate} = this.state;
return (
<React.Fragment>
<Typeahead
onPaginate={() => console.log('Results paginated')}
options={_.range(0, 1000).map((o) => o.toString())}
paginate={paginate}
placeholder="Pick a number..."
/>
<FormGroup className="mt-2">
<CustomInput
checked={paginate}
onChange={(e) => this.setState({paginate: !!e.target.checked})}
type="checkbox"
id="enable-pagination"
label="Paginate results"
/>
</FormGroup>
</React.Fragment>
);
}
}

View File

@@ -0,0 +1,57 @@
import React from 'react';
import { Typeahead } from 'react-bootstrap-typeahead';
import {
ButtonToolbar,
Button
} from './../../../../components';
import data from './exampleData';
export class PublicMethods extends React.Component {
_typeahead = React.createRef();
render() {
return (
<React.Fragment>
<Typeahead
labelKey="name"
multiple
options={data}
placeholder="Choose a state..."
ref={this._typeahead}
selected={data.slice(0, 4)}
/>
<ButtonToolbar className="mt-2">
<Button
outline
color="secondary"
onClick={() => this._typeahead.getInstance().clear()}
className="mr-2"
>
Clear
</Button>
<Button
outline
color="secondary"
onClick={() => this._typeahead.getInstance().focus()}
className="mr-2"
>
Focus
</Button>
<Button
outline
color="secondary"
onClick={() => {
const instance = this._typeahead.getInstance();
instance.focus();
setTimeout(() => instance.blur(), 1000);
}}
className="mr-2"
>
Focus, then blur after 1 second
</Button>
</ButtonToolbar>
</React.Fragment>
);
}
}

View File

@@ -0,0 +1,111 @@
import React from 'react';
import _ from 'lodash';
import { Highlighter, Menu, MenuItem, Token, Typeahead } from 'react-bootstrap-typeahead';
import {
CustomInput,
FormGroup
} from './../../../../components';
import options from './exampleData';
export class RenderingExample extends React.Component {
state = {
selectedOption: 'renderMenu',
};
render() {
const {selectedOption} = this.state;
const props = {};
const radios = [
{label: 'Custom menu', value: 'renderMenu'},
{label: 'Custom menu item contents', value: 'renderMenuItemChildren'},
{label: 'Custom token', value: 'renderToken'},
];
switch (selectedOption) {
case radios[0].value:
props.renderMenu = this._renderMenu;
break;
case radios[1].value:
props.renderMenuItemChildren = this._renderMenuItemChildren;
break;
case radios[2].value:
props.multiple = true;
props.renderToken = this._renderToken;
break;
}
return (
<React.Fragment>
<Typeahead
{...props}
labelKey="name"
options={options}
placeholder="Choose a state..."
/>
<FormGroup className="mt-2">
{radios.map(({label, value}) => (
<CustomInput
checked={selectedOption === value}
key={value}
onChange={() => this.setState({selectedOption: value})}
type="radio"
value={value}
id={`rendering-type-${value}`}
label={label}
/>
))}
</FormGroup>
</React.Fragment>
);
}
_renderMenu(results, menuProps) {
let idx = 0;
const grouped = _.groupBy(results, (r) => r.region);
const items = Object.keys(grouped).sort().map((region) => {
return [
!!idx && <Menu.Divider key={`${region}-divider`} />,
<Menu.Header key={`${region}-header`}>
{region}
</Menu.Header>,
_.map(grouped[region], (state) => {
const item =
<MenuItem key={idx} option={state} position={idx}>
<Highlighter search={menuProps.text}>
{state.name}
</Highlighter>
</MenuItem>;
idx++;
return item;
}),
];
});
return <Menu {...menuProps}>{items}</Menu>;
}
_renderMenuItemChildren(option, props) {
return [
<Highlighter key="name" search={props.text}>
{option.name}
</Highlighter>,
<div key="population">
<small>
Population: {option.population.toLocaleString()}
</small>
</div>,
];
}
_renderToken(option, props, index) {
return (
<Token
key={index}
onRemove={props.onRemove}>
{`${option.name} (Pop: ${option.population.toLocaleString()})`}
</Token>
);
}
}

View File

@@ -0,0 +1,52 @@
export default [
{ name: 'Alabama', population: 4780127, capital: 'Montgomery', region: 'South' },
{ name: 'Alaska', population: 710249, capital: 'Juneau', region: 'West' },
{ name: 'Arizona', population: 6392307, capital: 'Phoenix', region: 'West' },
{ name: 'Arkansas', population: 2915958, capital: 'Little Rock', region: 'South' },
{ name: 'California', population: 37254503, capital: 'Sacramento', region: 'West' },
{ name: 'Colorado', population: 5029324, capital: 'Denver', region: 'West' },
{ name: 'Connecticut', population: 3574118, capital: 'Hartford', region: 'Northeast' },
{ name: 'Delaware', population: 897936, capital: 'Dover', region: 'South' },
{ name: 'Florida', population: 18804623, capital: 'Tallahassee', region: 'South' },
{ name: 'Georgia', population: 9688681, capital: 'Atlanta', region: 'South' },
{ name: 'Hawaii', population: 1360301, capital: 'Honolulu', region: 'West' },
{ name: 'Idaho', population: 1567652, capital: 'Boise', region: 'West' },
{ name: 'Illinois', population: 12831549, capital: 'Springfield', region: 'Midwest' },
{ name: 'Indiana', population: 6484229, capital: 'Indianapolis', region: 'Midwest' },
{ name: 'Iowa', population: 3046869, capital: 'Des Moines', region: 'Midwest' },
{ name: 'Kansas', population: 2853132, capital: 'Topeka', region: 'Midwest' },
{ name: 'Kentucky', population: 4339349, capital: 'Frankfort', region: 'South' },
{ name: 'Louisiana', population: 4533479, capital: 'Baton Rouge', region: 'South' },
{ name: 'Maine', population: 1328361, capital: 'Augusta', region: 'Northeast' },
{ name: 'Maryland', population: 5773785, capital: 'Annapolis', region: 'South' },
{ name: 'Massachusetts', population: 6547817, capital: 'Boston', region: 'Northeast' },
{ name: 'Michigan', population: 9884129, capital: 'Lansing', region: 'Midwest' },
{ name: 'Minnesota', population: 5303925, capital: 'Saint Paul', region: 'Midwest' },
{ name: 'Mississippi', population: 2968103, capital: 'Jackson', region: 'South' },
{ name: 'Missouri', population: 5988927, capital: 'Jefferson City', region: 'Midwest' },
{ name: 'Montana', population: 989417, capital: 'Alberta', region: 'West' },
{ name: 'Nebraska', population: 1826341, capital: 'Lincoln', region: 'Midwest' },
{ name: 'Nevada', population: 2700691, capital: 'Carson City', region: 'West' },
{ name: 'New Hampshire', population: 1316466, capital: 'Concord', region: 'Northeast' },
{ name: 'New Jersey', population: 8791936, capital: 'Trenton', region: 'Northeast' },
{ name: 'New Mexico', population: 2059192, capital: 'Santa Fe', region: 'West' },
{ name: 'New York', population: 19378087, capital: 'Albany', region: 'Northeast' },
{ name: 'North Carolina', population: 9535692, capital: 'Raleigh', region: 'South' },
{ name: 'North Dakota', population: 672591, capital: 'Bismarck', region: 'Midwest' },
{ name: 'Ohio', population: 11536725, capital: 'Columbus', region: 'Midwest' },
{ name: 'Oklahoma', population: 3751616, capital: 'Oklahoma City', region: 'South' },
{ name: 'Oregon', population: 3831073, capital: 'Salem', region: 'West' },
{ name: 'Pennsylvania', population: 12702887, capital: 'Harrisburg', region: 'Northeast' },
{ name: 'Rhode Island', population: 1052931, capital: 'Providence', region: 'Northeast' },
{ name: 'South Carolina', population: 4625401, capital: 'Columbia', region: 'South' },
{ name: 'South Dakota', population: 814191, capital: 'Pierre', region: 'Midwest' },
{ name: 'Tennessee', population: 6346275, capital: 'Nashville', region: 'South' },
{ name: 'Texas', population: 25146105, capital: 'Austin', region: 'South' },
{ name: 'Utah', population: 2763888, capital: 'Salt Lake City', region: 'West' },
{ name: 'Vermont', population: 625745, capital: 'Montpelier', region: 'Northeast' },
{ name: 'Virginia', population: 8001045, capital: 'Richmond', region: 'South' },
{ name: 'Washington', population: 6724543, capital: 'Olympia', region: 'West' },
{ name: 'West Virginia', population: 1853011, capital: 'Charleston', region: 'South' },
{ name: 'Wisconsin', population: 5687289, capital: 'Madison', region: 'West' },
{ name: 'Wyoming', population: 563767, capital: 'Cheyenne', region: 'West' },
];

View File

@@ -0,0 +1,16 @@
export * from './BasicExample';
export * from './BasicBehaviors';
export * from './ControllingSelections';
export * from './InputSize';
export * from './MenuAlignment';
export * from './FormExample';
export * from './PaginationExample';
export * from './BodyContainer';
export * from './RenderingExample';
export * from './LabelKey';
export * from './Filtering';
export * from './CustomFiltering';
export * from './CustomSelections';
export * from './AsynchronousSearching';
export * from './AsynchronousPagination';
export * from './PublicMethods';

View File

@@ -0,0 +1,16 @@
import fetch from 'isomorphic-fetch';
const SEARCH_URI = 'https://api.github.com/search/users';
export function makeAndHandleRequest(query, page = 1) {
return fetch(`${SEARCH_URI}?q=${query}+in:login&page=${page}&per_page=50`)
.then((resp) => resp.json())
.then(({items, total_count}) => {
const options = items.map((i) => ({
avatar_url: i.avatar_url,
id: i.id,
login: i.login,
}));
return {options, total_count};
});
}

View File

@@ -0,0 +1,3 @@
import { Typeahead } from './Typeahead';
export default Typeahead;

619
app/routes/Forms/Wizard/Wizard.js Executable file
View File

@@ -0,0 +1,619 @@
import React from 'react';
import _ from 'lodash';
import {
Container,
Wizard,
Card,
Nav,
NavItem,
NavLink,
CardFooter,
CardBody,
Button,
Row,
Col,
Table,
Form,
FormGroup,
Input,
InputGroup,
InputGroupAddon,
Label,
DropdownToggle,
DropdownMenu,
DropdownItem,
UncontrolledDropdown
} from './../../../components';
import { HeaderMain } from "../../components/HeaderMain";
const sequence = ['your-cart', 'shipping', 'payment', 'summary'];
const items = [
{
name: 'Incredible Metal Keyboard',
quantity: 22,
price: '$578.00'
},
{
name: 'Incredible Soft Cheese',
quantity: 3,
price: '$278.00'
},
{
name: 'Handcrafted Granite Sausages',
quantity: 29,
price: '$465.00'
},
{
name: 'Awesome Metal Gloves',
quantity: 15,
price: '$501.00'
}
];
const WizardStep1 = () => (
<Row>
<Col md={ 6 }>
<div>
<h3 className="mb-4">
Your Bags are Ready to Check Out!
</h3>
<p>
Discover goods you&apos;ll love from brands that inspire.
The easiest way to open your own online store.
Discover amazing stuff or open your own store for free!
</p>
<small>
Below is a sample page for your cart,
Created using pages design UI Elementes
</small>
</div>
</Col>
<Col md={ 6 }>
<Table>
<thead>
<tr>
<th>#</th>
<th>Description</th>
<th>Qty</th>
<th className="text-right">Total</th>
</tr>
</thead>
<tbody>
{
_.map(items, (item, index) => (
<tr key={index}>
<td>
<i className="fa fa-close text-danger"></i>
</td>
<td>
{ item.name }
</td>
<td>
{ item.quantity }
</td>
<td className="text-right">
{ item.price }
</td>
</tr>
))
}
<tr>
<td colSpan={3}></td>
<td>
<Row tag="dl">
<dt className="col-sm-6 text-right">Sub-Total</dt>
<dd className="col-sm-6 text-right">$114.00</dd>
<dt className="col-sm-6 text-right">VAT</dt>
<dd className="col-sm-6 text-right">$876.78</dd>
<dt className="col-sm-6 mt-3 text-right h4 mb-0">Total</dt>
<dd className="col-sm-6 mt-3 text-right h4 mb-0">$986.78</dd>
</Row>
</td>
</tr>
</tbody>
</Table>
</Col>
</Row>
);
const WizardStep2 = () => (
<Row>
<Col md={6}>
<div>
<h3 className="mb-4">
Your Information is Safe with Us!
</h3>
<p>
We respect your privacy and protect it with strong encryption, plus strict policies.
Two-step verification, which we encourage all our customers to use.
</p>
<small>
Fields marked as <span className="text-danger">*</span> are Required!
</small>
</div>
</Col>
<Col md={6}>
<Form>
<h6 className="pb-3">
Name and Email Address
</h6>
<Row className="pb-4">
<Col sm={6}>
<FormGroup>
<Label for="firstName">
First Name <span className="text-danger">*</span>
</Label>
<Input
id="firstName"
placeholder='First Name...'
/>
</FormGroup>
</Col>
<Col sm={6}>
<FormGroup>
<Label for="lastName">
Last Name <span className="text-danger">*</span>
</Label>
<Input
id="lastName"
placeholder='Last Name...'
/>
</FormGroup>
</Col>
<Col sm={12}>
<FormGroup>
<Label for="email">
Email <span className="text-danger">*</span>
</Label>
<Input id="email" placeholder='Email address...'/>
</FormGroup>
</Col>
</Row>
<h6 className="pb-3">
Billing Address
</h6>
<Row>
<Col sm={12}>
<FormGroup>
<Label for="address">
Address <span className="text-danger">*</span>
</Label>
<Input id="address" placeholder='Current address...'/>
</FormGroup>
</Col>
<Col sm={3}>
<FormGroup>
<Label for="country">
Country <span className="text-danger">*</span>
</Label>
<UncontrolledDropdown className="d-block">
<DropdownToggle color="secondary" outline id="country">
PL (+48) <i className="fa fa-fw fa-angle-down"></i>
</DropdownToggle>
<DropdownMenu>
<DropdownItem active>PL (+48)</DropdownItem>
<DropdownItem>UK (+44)</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
</FormGroup>
</Col>
<Col sm={9}>
<FormGroup>
<Label for="city">
City <span className="text-danger">*</span>
</Label>
<Input id="city" placeholder='Enter City...'/>
</FormGroup>
</Col>
<Col sm={9}>
<FormGroup>
<Label for="state">
State/Province <span className="text-danger">*</span>
</Label>
<Input id="state" placeholder='Outside US/Canada...'/>
</FormGroup>
</Col>
<Col sm={3}>
<FormGroup>
<Label for="zipCode">
ZIP Code <span className="text-danger">*</span>
</Label>
<Input id="zipCode" placeholder='Email...'/>
</FormGroup>
</Col>
<Col sm={12}>
<FormGroup>
<Label for="phoneNumber">
Phone Number
</Label>
<InputGroup>
<InputGroupAddon
addonType="prepend"
tag={UncontrolledDropdown}
>
<DropdownToggle outline>
PL (+48) <i className="fa fa-fw fa-angle-down"></i>
</DropdownToggle>
<DropdownMenu>
<DropdownItem active>PL (+48)</DropdownItem>
<DropdownItem>UK (+44)</DropdownItem>
</DropdownMenu>
</InputGroupAddon>
<Input id="phoneNumber" type="text" placeholder='For Verification Purpose...' />
</InputGroup>
</FormGroup>
</Col>
</Row>
</Form>
</Col>
</Row>
);
const WizardStep3 = () => (
<Row>
<Col md={6}>
<div>
<h3 className="mb-4">
We Secured Your Line
</h3>
<p className="pb-3">
Below is a sample page for your cart , Created using pages design UI Elementes.
</p>
<Table className='my-2'>
<thead>
<tr>
<th>#</th>
<th>Description</th>
<th>Qty</th>
<th className="text-right">Total</th>
</tr>
</thead>
<tbody>
{
_.map(items, (item, index) => (
<tr key={index}>
<td>
<i className="fa fa-close text-danger"></i>
</td>
<td>
{ item.name }
</td>
<td>
{ item.quantity }
</td>
<td className="text-right">
{ item.price }
</td>
</tr>
))
}
<tr>
<td colSpan={4} className='text-right'>
<strong>$986.78</strong>
</td>
</tr>
</tbody>
</Table>
<small>
Invoice are issued on the date of despatch.
Payment terms: Pre-orders: within 10 days of invoice date with 4% discount,
from the 11th to the 30th day net. Re-orders: non-reduced stock items are payable net after 20 days.
</small>
</div>
</Col>
<Col md={6}>
<Nav pills className="pb-3">
<NavItem>
<NavLink href="#" active>
Credit Card
</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">
PayPal
</NavLink>
</NavItem>
<NavItem>
<NavLink href="#">
Skrill
</NavLink>
</NavItem>
</Nav>
<Card>
<CardBody>
<div className="d-flex justify-content-between align-items-center pb-3">
<h5>Credit Card</h5>
<div className="d-flex align-items-start">
<i className="fa fa-lg fa-cc-visa text-primary mr-1"></i>
<i className="fa fa-lg fa-cc-mastercard text-muted mr-1"></i>
<i className="fa fa-lg fa-cc-jcb text-muted mr-1"></i>
</div>
</div>
<Form>
<FormGroup>
<Label for="cardHolder">
Card Holder&apos;s Name <span className="text-danger">*</span>
</Label>
<Input id="cardHolder" placeholder='Name on the card...'/>
</FormGroup>
<FormGroup>
<Label for="cardNumber">
Card Number <span className="text-danger">*</span>
</Label>
<Input id="cardNumber" placeholder='8888-8888-8888-8888'/>
</FormGroup>
<div className="d-flex justify-content-between align-items-center">
<FormGroup>
<Label>
Expiriation <span className="text-danger">*</span>
</Label>
<div className="d-flex">
<UncontrolledDropdown className="d-block">
<DropdownToggle outline>
Jun (06) <i className="fa fa-fw fa-angle-down"></i>
</DropdownToggle>
<DropdownMenu>
<DropdownItem active>Jun (06)</DropdownItem>
<DropdownItem>Jul (07))</DropdownItem>
<DropdownItem>Aug (08)</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
&nbsp;
<UncontrolledDropdown className="d-block">
<DropdownToggle outline>
2018 <i className="fa fa-fw fa-angle-down"></i>
</DropdownToggle>
<DropdownMenu>
<DropdownItem active>2018</DropdownItem>
<DropdownItem>2019</DropdownItem>
<DropdownItem>2020</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
</div>
</FormGroup>
<FormGroup className='text-right'>
<Label for="cvcCode">
CVC Code <span className="text-danger">*</span>
</Label>
<Input id="cvcCode" placeholder='000'/>
</FormGroup>
</div>
</Form>
</CardBody>
</Card>
</Col>
</Row>
);
const WizardStep4 = () => (
<Row>
<Col md={6}>
<div>
<h3 className="mb-4">
Summary
</h3>
<p className="mb-5">
Below is a sample page for your cart , Created using pages design UI Elementes.
</p>
<Table className='my-2'>
<thead>
<tr>
<th>#</th>
<th>Description</th>
<th>Qty</th>
<th className="text-right">Total</th>
</tr>
</thead>
<tbody>
{
_.map(items, (item, index) => (
<tr key={index}>
<td>
<i className="fa fa-close text-danger"></i>
</td>
<td>
{ item.name }
</td>
<td>
{ item.quantity }
</td>
<td className="text-right">
{ item.price }
</td>
</tr>
))
}
<tr>
<td colSpan={4} className='text-right'>
<strong>$986.78</strong>
</td>
</tr>
</tbody>
</Table>
<small>Invoice are issued on the date of despatch. Payment terms: Pre-orders: within 10 days of invoice date with 4% discount, from the 11th to the 30th day net. Re-orders: non-reduced stock items are payable net after 20 days.</small>
</div>
</Col>
<Col md={6}>
<h6 className="mb-3 mt-2">Name and Email Address</h6>
<Row tag="dl">
<dt className="col-sm-4">First Name</dt>
<dd className="col-sm-8">John</dd>
<dt className="col-sm-4">Last Name</dt>
<dd className="col-sm-8">Novoselic</dd>
<dt className="col-sm-4">Email</dt>
<dd className="col-sm-8">john@novoselic.com</dd>
<dt className="col-sm-4"></dt>
<dd className="col-sm-8">
<Button color='link' className="p-0"><i className="fa fa-angle-left mr-1"></i> Change</Button>
</dd>
</Row>
<h6 className="my-3">Billing Address</h6>
<Row tag="dl">
<dt className="col-sm-4">Address</dt>
<dd className="col-sm-8">65575 Wintheiser Skyway Einar Pike</dd>
<dt className="col-sm-4">Country</dt>
<dd className="col-sm-8">United Kingdom</dd>
<dt className="col-sm-4">City</dt>
<dd className="col-sm-8">London</dd>
<dt className="col-sm-4">State/Province</dt>
<dd className="col-sm-8">Greater London</dd>
<dt className="col-sm-4">ZIP Code</dt>
<dd className="col-sm-8">151</dd>
<dt className="col-sm-4">Phone</dt>
<dd className="col-sm-8">+48 383-747-234</dd>
<dt className="col-sm-4"></dt>
<dd className="col-sm-8">
<Button color='link' className="p-0"><i className="fa fa-angle-left mr-1"></i> Change</Button>
</dd>
</Row>
<h6 className="my-3">Credit Card</h6>
<Row tag="dl">
<dt className="col-sm-4">Card Name</dt>
<dd className="col-sm-8"><i className="fa fa-cc-visa text-primary mr-1"></i> Visa </dd>
<dt className="col-sm-4">Card Number</dt>
<dd className="col-sm-8">**** **** **** 6765</dd>
<dt className="col-sm-4"></dt>
<dd className="col-sm-8">
<Button color='link' className="p-0"><i className="fa fa-angle-left mr-1"></i> Change</Button>
</dd>
</Row>
</Col>
</Row>
);
export class WizardExample extends React.Component {
state = {
currentStep: _.first(sequence)
}
render() {
const { currentStep } = this.state;
return (
<Container>
<HeaderMain
title="Wizard"
className="my-4"
/>
<Card>
<CardBody className="d-flex justify-content-center pt-5">
<Wizard
activeStep={ currentStep }
onStepChanged={ this._changeStep }
>
<Wizard.Step
id={ sequence[0] }
icon={ <i className="fa fa-shopping-basket fa-fw"></i> }
complete={ this._isComplete(sequence[0]) }
>
Your Cart
</Wizard.Step>
<Wizard.Step
id={ sequence[1] }
icon={ <i className="fa fa-cube fa-fw"></i> }
complete={ this._isComplete(sequence[1]) }
>
Shipping
</Wizard.Step>
<Wizard.Step
id={ sequence[2] }
icon={ <i className="fa fa-credit-card fa-fw"></i> }
complete={ this._isComplete(sequence[2]) }
>
Payment
</Wizard.Step>
<Wizard.Step
id={ sequence[3] }
icon={ <i className="fa fa-navicon fa-fw"></i> }
complete={ this._isComplete(sequence[3]) }
>
Summary
</Wizard.Step>
</Wizard>
</CardBody>
<CardBody className="p-5">
{
(() => {
switch(this.state.currentStep) {
case sequence[0]:
return <WizardStep1 />
case sequence[1]:
return <WizardStep2 />
case sequence[2]:
return <WizardStep3 />
case sequence[3]:
return <WizardStep4 />
}
})()
}
</CardBody>
<CardFooter className="p-4 bt-0">
<div className="d-flex">
{
currentStep !== sequence[0] && (
<Button onClick={() => {this._prevStep()}} color="link" className='mr-3'>
<i className='fa fa-angle-left mr-2'></i>
Previous
</Button>
)
}
{
currentStep !== sequence[sequence.length - 1] && (
<Button color='primary' onClick={() => {this._nextStep()}} className="ml-auto px-4">
Next
<i className='fa fa-angle-right ml-2'></i>
</Button>
)
}
</div>
</CardFooter>
</Card>
</Container>
);
}
_changeStep = (stepId) => {
this.setState({
currentStep: stepId
});
}
_prevStep = () => {
const index = sequence.indexOf(this.state.currentStep);
this.setState({
currentStep: sequence[index - 1]
});
}
_nextStep = () => {
const index = sequence.indexOf(this.state.currentStep);
this.setState({
currentStep: sequence[index + 1]
});
}
_isComplete = (stepId) =>
sequence.indexOf(stepId) < sequence.indexOf(this.state.currentStep)
}

View File

@@ -0,0 +1,3 @@
import { WizardExample } from './Wizard';
export default WizardExample;