154
app/routes/Forms/DatePicker/DatePickerExamples.js
Executable file
154
app/routes/Forms/DatePicker/DatePickerExamples.js
Executable 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">
|
||||
You’ll need to install React, PropTypes, and Moment.js separately since those dependencies
|
||||
aren’t 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 })
|
||||
)
|
||||
}
|
31
app/routes/Forms/DatePicker/components/AddonInput.js
Executable file
31
app/routes/Forms/DatePicker/components/AddonInput.js
Executable 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 };
|
23
app/routes/Forms/DatePicker/components/ButtonInput.js
Executable file
23
app/routes/Forms/DatePicker/components/ButtonInput.js
Executable 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 };
|
50
app/routes/Forms/DatePicker/components/Example.js
Executable file
50
app/routes/Forms/DatePicker/components/Example.js
Executable 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
|
||||
}
|
3
app/routes/Forms/DatePicker/components/index.js
Executable file
3
app/routes/Forms/DatePicker/components/index.js
Executable file
@@ -0,0 +1,3 @@
|
||||
export * from './Example';
|
||||
export * from './ButtonInput';
|
||||
export * from './AddonInput';
|
3
app/routes/Forms/DatePicker/index.js
Executable file
3
app/routes/Forms/DatePicker/index.js
Executable file
@@ -0,0 +1,3 @@
|
||||
import { DatePickerExamples } from './DatePickerExamples';
|
||||
|
||||
export default DatePickerExamples;
|
134
app/routes/Forms/Dropzone/Dropzone.js
Executable file
134
app/routes/Forms/Dropzone/Dropzone.js
Executable 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'n'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)
|
||||
})
|
||||
}
|
||||
}
|
64
app/routes/Forms/Dropzone/components/FilesGrid.js
Executable file
64
app/routes/Forms/Dropzone/components/FilesGrid.js
Executable 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 · <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
|
||||
}
|
73
app/routes/Forms/Dropzone/components/FilesList.js
Executable file
73
app/routes/Forms/Dropzone/components/FilesList.js
Executable 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
|
||||
}
|
25
app/routes/Forms/Dropzone/components/common.scss
Executable file
25
app/routes/Forms/Dropzone/components/common.scss
Executable 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;
|
||||
}
|
||||
}
|
2
app/routes/Forms/Dropzone/components/index.js
Executable file
2
app/routes/Forms/Dropzone/components/index.js
Executable file
@@ -0,0 +1,2 @@
|
||||
export * from './FilesGrid';
|
||||
export * from './FilesList';
|
3
app/routes/Forms/Dropzone/index.js
Executable file
3
app/routes/Forms/Dropzone/index.js
Executable file
@@ -0,0 +1,3 @@
|
||||
import { Dropzone } from './Dropzone';
|
||||
|
||||
export default Dropzone;
|
32
app/routes/Forms/Dropzone/utilities.js
Executable file
32
app/routes/Forms/Dropzone/utilities.js
Executable 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';
|
||||
}
|
66
app/routes/Forms/Editor/Editor.js
Executable file
66
app/routes/Forms/Editor/Editor.js
Executable 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 })
|
||||
}
|
||||
}
|
3
app/routes/Forms/Editor/index.js
Executable file
3
app/routes/Forms/Editor/index.js
Executable file
@@ -0,0 +1,3 @@
|
||||
import { Editor } from './Editor';
|
||||
|
||||
export default Editor;
|
1137
app/routes/Forms/Forms/Forms.js
Executable file
1137
app/routes/Forms/Forms/Forms.js
Executable file
File diff suppressed because it is too large
Load Diff
3
app/routes/Forms/Forms/index.js
Executable file
3
app/routes/Forms/Forms/index.js
Executable file
@@ -0,0 +1,3 @@
|
||||
import Forms from './Forms';
|
||||
|
||||
export default Forms;
|
484
app/routes/Forms/FormsLayouts/FormsLayouts.js
Executable file
484
app/routes/Forms/FormsLayouts/FormsLayouts.js
Executable 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;
|
3
app/routes/Forms/FormsLayouts/index.js
Executable file
3
app/routes/Forms/FormsLayouts/index.js
Executable file
@@ -0,0 +1,3 @@
|
||||
import FormsLayouts from './FormsLayouts';
|
||||
|
||||
export default FormsLayouts;
|
1702
app/routes/Forms/InputGroups/InputGroups.js
Executable file
1702
app/routes/Forms/InputGroups/InputGroups.js
Executable file
File diff suppressed because it is too large
Load Diff
3
app/routes/Forms/InputGroups/index.js
Executable file
3
app/routes/Forms/InputGroups/index.js
Executable file
@@ -0,0 +1,3 @@
|
||||
import InputGroups from './InputGroups';
|
||||
|
||||
export default InputGroups;
|
500
app/routes/Forms/Sliders/Sliders.js
Executable file
500
app/routes/Forms/Sliders/Sliders.js
Executable 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>
|
||||
);
|
||||
}
|
||||
}
|
21
app/routes/Forms/Sliders/Sliders.scss
Executable file
21
app/routes/Forms/Sliders/Sliders.scss
Executable 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;
|
||||
}
|
3
app/routes/Forms/Sliders/index.js
Executable file
3
app/routes/Forms/Sliders/index.js
Executable file
@@ -0,0 +1,3 @@
|
||||
import { Sliders } from './Sliders';
|
||||
|
||||
export default Sliders;
|
216
app/routes/Forms/TextMask/TextMask.js
Executable file
216
app/routes/Forms/TextMask/TextMask.js
Executable 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>
|
||||
);
|
3
app/routes/Forms/TextMask/index.js
Executable file
3
app/routes/Forms/TextMask/index.js
Executable file
@@ -0,0 +1,3 @@
|
||||
import { TextMask } from './TextMask';
|
||||
|
||||
export default TextMask;
|
201
app/routes/Forms/Toggles/Toggles.js
Executable file
201
app/routes/Forms/Toggles/Toggles.js
Executable 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>
|
||||
);
|
||||
}
|
||||
}
|
3
app/routes/Forms/Toggles/Toggles.scss
Executable file
3
app/routes/Forms/Toggles/Toggles.scss
Executable file
@@ -0,0 +1,3 @@
|
||||
.switchCustomClass > :first-child {
|
||||
background-color: #ab199f;
|
||||
}
|
3
app/routes/Forms/Toggles/index.js
Executable file
3
app/routes/Forms/Toggles/index.js
Executable file
@@ -0,0 +1,3 @@
|
||||
import { Toggles } from './Toggles';
|
||||
|
||||
export default Toggles;
|
451
app/routes/Forms/Typeahead/Typeahead.js
Executable file
451
app/routes/Forms/Typeahead/Typeahead.js
Executable 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>
|
||||
);
|
87
app/routes/Forms/Typeahead/components/AsynchronousPagination.js
Executable file
87
app/routes/Forms/Typeahead/components/AsynchronousPagination.js
Executable 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,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
74
app/routes/Forms/Typeahead/components/AsynchronousSearching.js
Executable file
74
app/routes/Forms/Typeahead/components/AsynchronousSearching.js
Executable 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,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
81
app/routes/Forms/Typeahead/components/BasicBehaviors.js
Executable file
81
app/routes/Forms/Typeahead/components/BasicBehaviors.js
Executable 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);
|
||||
}
|
||||
}
|
38
app/routes/Forms/Typeahead/components/BasicExample.js
Executable file
38
app/routes/Forms/Typeahead/components/BasicExample.js
Executable 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>
|
||||
);
|
||||
}
|
||||
}
|
64
app/routes/Forms/Typeahead/components/BodyContainer.js
Executable file
64
app/routes/Forms/Typeahead/components/BodyContainer.js
Executable 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});
|
||||
}
|
||||
}
|
15
app/routes/Forms/Typeahead/components/ControllingSelections.js
Executable file
15
app/routes/Forms/Typeahead/components/ControllingSelections.js
Executable 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..."
|
||||
/>
|
||||
)
|
65
app/routes/Forms/Typeahead/components/CustomFiltering.js
Executable file
65
app/routes/Forms/Typeahead/components/CustomFiltering.js
Executable 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>
|
||||
);
|
||||
}
|
||||
}
|
12
app/routes/Forms/Typeahead/components/CustomSelections.js
Executable file
12
app/routes/Forms/Typeahead/components/CustomSelections.js
Executable 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..."
|
||||
/>
|
||||
);
|
69
app/routes/Forms/Typeahead/components/Filtering.js
Executable file
69
app/routes/Forms/Typeahead/components/Filtering.js
Executable 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>
|
||||
);
|
||||
}
|
||||
}
|
67
app/routes/Forms/Typeahead/components/FormExample.js
Executable file
67
app/routes/Forms/Typeahead/components/FormExample.js
Executable 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>
|
||||
);
|
||||
}
|
||||
}
|
24
app/routes/Forms/Typeahead/components/GithubMenuItem.js
Executable file
24
app/routes/Forms/Typeahead/components/GithubMenuItem.js
Executable 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,
|
||||
};
|
50
app/routes/Forms/Typeahead/components/InputSize.js
Executable file
50
app/routes/Forms/Typeahead/components/InputSize.js
Executable 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>
|
||||
);
|
||||
}
|
||||
}
|
17
app/routes/Forms/Typeahead/components/LabelKey.js
Executable file
17
app/routes/Forms/Typeahead/components/LabelKey.js
Executable 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?"
|
||||
/>
|
||||
);
|
50
app/routes/Forms/Typeahead/components/MenuAlignment.js
Executable file
50
app/routes/Forms/Typeahead/components/MenuAlignment.js
Executable 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>
|
||||
);
|
||||
}
|
||||
}
|
38
app/routes/Forms/Typeahead/components/PaginationExample.js
Executable file
38
app/routes/Forms/Typeahead/components/PaginationExample.js
Executable 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>
|
||||
);
|
||||
}
|
||||
}
|
57
app/routes/Forms/Typeahead/components/PublicMethods.js
Executable file
57
app/routes/Forms/Typeahead/components/PublicMethods.js
Executable 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>
|
||||
);
|
||||
}
|
||||
}
|
111
app/routes/Forms/Typeahead/components/RenderingExample.js
Executable file
111
app/routes/Forms/Typeahead/components/RenderingExample.js
Executable 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>
|
||||
);
|
||||
}
|
||||
}
|
52
app/routes/Forms/Typeahead/components/exampleData.js
Executable file
52
app/routes/Forms/Typeahead/components/exampleData.js
Executable 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' },
|
||||
];
|
16
app/routes/Forms/Typeahead/components/index.js
Executable file
16
app/routes/Forms/Typeahead/components/index.js
Executable 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';
|
16
app/routes/Forms/Typeahead/components/utils.js
Executable file
16
app/routes/Forms/Typeahead/components/utils.js
Executable 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};
|
||||
});
|
||||
}
|
3
app/routes/Forms/Typeahead/index.js
Executable file
3
app/routes/Forms/Typeahead/index.js
Executable file
@@ -0,0 +1,3 @@
|
||||
import { Typeahead } from './Typeahead';
|
||||
|
||||
export default Typeahead;
|
619
app/routes/Forms/Wizard/Wizard.js
Executable file
619
app/routes/Forms/Wizard/Wizard.js
Executable 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'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'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>
|
||||
|
||||
<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)
|
||||
}
|
3
app/routes/Forms/Wizard/index.js
Executable file
3
app/routes/Forms/Wizard/index.js
Executable file
@@ -0,0 +1,3 @@
|
||||
import { WizardExample } from './Wizard';
|
||||
|
||||
export default WizardExample;
|
Reference in New Issue
Block a user