Skip to content

Commit

Permalink
bootstrap3 (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
zeroasterisk authored and radekmie committed May 25, 2016
1 parent 1099f0d commit 3d35ad9
Show file tree
Hide file tree
Showing 25 changed files with 890 additions and 0 deletions.
13 changes: 13 additions & 0 deletions packages/uniforms-bootstrap3/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# uniforms-bootstrap3

> Bootstrap4 UI components for `uniforms`.
## Install

```sh
$ npm install uniforms-bootstrap3
```

For more in depth documentation see: [https://github.com/vazco/uniforms/](https://github.com/vazco/uniforms/).

> Looking for Bootstrap4? We have that too.
58 changes: 58 additions & 0 deletions packages/uniforms-bootstrap3/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"name": "uniforms-bootstrap3",
"version": "1.0.0-rc.5",
"main": "lib/index.js",
"jsnext:main": "src/index.js",
"description": "Bootstrap3 UI components for uniforms.",
"repository": "https://github.com/vazco/uniforms/tree/master/packages/uniforms-bootstrap3",
"homepage": "https://github.com/vazco/uniforms/",
"license": "MIT",
"bugs": {
"url": "https://github.com/vazco/uniforms/issues"
},
"keyword": [
"forms",
"meteor",
"react",
"schema"
],
"scripts": {
"lint": "./node_modules/.bin/eslint src",
"test": "true",
"cover": "true",
"build": "./node_modules/.bin/babel --out-dir lib src",
"watch": "./node_modules/.bin/babel --out-dir lib src --watch",
"prepublish": "npm run lint && npm run test && npm run build"
},
"devDependencies": {
"babel-cli": "^6.8.0",
"babel-eslint": "^6.0.4",
"babel-preset-es2015": "^6.6.0",
"babel-preset-react": "^6.5.0",
"babel-preset-stage-0": "^6.5.0",
"eslint": "^2.9.0",
"eslint-config-vazco": "^1.0.0",
"eslint-plugin-babel": "^3.2.0",
"eslint-plugin-react": "^5.0.1"
},
"peerDependencies": {
"react": "^15.0.2",
"uniforms": "^1.0.0-rc.5"
},
"babel": {
"presets": [
"es2015",
"react",
"stage-0"
]
},
"eslintConfig": {
"root": true,
"extends": [
"vazco"
]
},
"dependencies": {
"classnames": "^2.2.5"
}
}
34 changes: 34 additions & 0 deletions packages/uniforms-bootstrap3/src/components/fields/AutoField.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {connectField} from 'uniforms';
import {createElement} from 'react';

import NumField from './NumField';
import BoolField from './BoolField';
import DateField from './DateField';
import ListField from './ListField';
import NestField from './NestField';
import TextField from './TextField';
import SelectField from './SelectField';

const Auto = props => {
let component = props.component;
if (component === undefined) {
if (props.allowedValues) {
component = SelectField;
} else {
switch (props.type) {
case Date: component = DateField; break;
case Array: component = ListField; break;
case Number: component = NumField; break;
case Object: component = NestField; break;
case String: component = TextField; break;
case Boolean: component = BoolField; break;

default: throw new Error(`Unsupported field type: ${props.type.toString()}`);
}
}
}

return createElement(component, props);
};

export default connectField(Auto, {includeInChain: false});
25 changes: 25 additions & 0 deletions packages/uniforms-bootstrap3/src/components/fields/BoolField.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react';
import {connectField} from 'uniforms';

import FormGroup from './FormGroup';

const Bool = props =>
<FormGroup {...props}>
<section className={`checkbox${props.inline ? '-inline' : ''}`}>
<label onClick={() => props.onChange(!props.value)}>
<input
checked={props.value}
className="hidden"
disabled={props.disabled}
name={props.name}
onChange={() => props.onChange(!props.value)}
type="checkbox"
/>
{props.label}
</label>
</section>
</FormGroup>
;

export default connectField(Bool);

36 changes: 36 additions & 0 deletions packages/uniforms-bootstrap3/src/components/fields/DateField.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';
import classnames from 'classnames';
import {connectField} from 'uniforms';

import FormGroup from './FormGroup';

const dateFormat = value => value && value.toISOString().slice(0, -8);
const dateParse = (timestamp, onChange) => {
let date = new Date(timestamp);
if (date.getFullYear() < 10000) {
onChange(date);
}
};

const Date_ = props =>
<FormGroup {...props}>
<input
className={classnames(
props.inputClassName,
'form-control',
{'form-control-danger': props.error}
)}
disabled={props.disabled}
max={dateFormat(props.max)}
min={dateFormat(props.min)}
name={props.name}
onChange={event => dateParse(event.target.valueAsNumber, props.onChange)}
type="datetime-local"
value={dateFormat(props.value)}
/>
</FormGroup>
;

Date_.displayName = 'Date';

export default connectField(Date_);
28 changes: 28 additions & 0 deletions packages/uniforms-bootstrap3/src/components/fields/ErrorsField.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';
import classnames from 'classnames';
import {BaseField} from 'uniforms';

const ErrorsField = ({className, children, ...props}, {uniforms: {error, schema}}) =>
(!error && !children) ? null : (
<section className={classnames(
'panel panel-danger text-left',
className,
'error message'
)} {...props}>
<div className="panel-heading">
{children}
<ul className="list">
{schema.getErrorMessages(error).map((message, index) =>
<li key={index}>
{message}
</li>
)}
</ul>
</div>
</section>
)
;

ErrorsField.contextTypes = BaseField.contextTypes;

export default ErrorsField;
55 changes: 55 additions & 0 deletions packages/uniforms-bootstrap3/src/components/fields/FormGroup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from 'react';
import classnames from 'classnames';

import gridClassName from '../../lib/gridClassName';

const makeHelp = (help, helpClassName) => help && (
<span className={helpClassName || 'text-muted'}>
{help}
</span>
);

const FormGroup = ({
children,
className, // class name for the whole .form-group
disabled, // boolean, if true, show fields as disabled
error, // error validation response
grid, // grid is either a int [1-11] or object {xs:6,sm:4,md:2}
help, // help text
helpClassName, // class name for the help text (default: 'text-muted')
label, // string label (or false)
required,
feedbackable, // only some input types support feedback icons
wrapClassName // class name for the section wrapping the input(s)
}) =>
<section
className={classnames(
className,
'field',
'form-group',
{
'has-feedback': error && feedbackable,
'has-error': error,
disabled,
required
}
)}
>
{label && (
<label className={classnames('control-label', gridClassName(grid, 'label'))}>
{label}
</label>
)}

{(grid || wrapClassName) ?
<section className={classnames(wrapClassName, gridClassName(grid, 'input'))}>
{children}
{makeHelp(help, helpClassName)}
</section>
: ''}
{(grid || wrapClassName) ? '' : children}
{(grid || wrapClassName) ? '' : makeHelp(help, helpClassName)}
</section>
;

export default FormGroup;
23 changes: 23 additions & 0 deletions packages/uniforms-bootstrap3/src/components/fields/ListAddField.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import classnames from 'classnames';
import {connectField} from 'uniforms';

const ListAdd = ({className, parent, value, ...props}) => {
const limitNotReached = !(parent.maxCount <= parent.value.length);

return (
<i
{...props}
className={classnames(
'add glyphicon glyphicon-plus', // TODO configure to alternate icon
className,
limitNotReached
? 'link'
: 'disabled',
)}
onClick={() => limitNotReached && parent.onChange(parent.value.concat([value]))}
/>
);
};

export default connectField(ListAdd, {includeParent: true, initialValue: false});
27 changes: 27 additions & 0 deletions packages/uniforms-bootstrap3/src/components/fields/ListDelField.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';
import classnames from 'classnames';
import {connectField} from 'uniforms';

const ListFieldDel = ({className, disabled, parent, name, ...props}) => {
const fieldIndex = +name.slice(1 + name.lastIndexOf('.'));
const limitNotReached = !(parent.minCount >= parent.value.length);

return (
<i
{...props}
className={classnames(
'del glyphicon glyphicon-minus', // TODO configure to alternate icon
className,
limitNotReached && !disabled
? 'link'
: 'disabled',
)}
onClick={() => limitNotReached && parent.onChange(
[].concat(parent.value.slice(0, fieldIndex))
.concat(parent.value.slice(1 + fieldIndex))
)}
/>
);
};

export default connectField(ListFieldDel, {includeParent: true, initialValue: false});
68 changes: 68 additions & 0 deletions packages/uniforms-bootstrap3/src/components/fields/ListField.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React from 'react';
import classnames from 'classnames';
import {Children} from 'react';
import {connectField} from 'uniforms';
import {joinName} from 'uniforms';

import ListAddField from './ListAddField';
import ListItemField from './ListItemField';

const List = ({
children,
className,
disabled,
error,
label,
name,
// onChange shouldn't be passed to <section>
// eslint-disable-next-line no-unused-vars
onChange,
required,
value,
...props
}) =>
<section className={classnames(
'panel panel-default',
className,
{
'panel-danger': error,
disabled,
required
},
'grouped fields list'
)} {...props}>
<div className="panel-heading">
{label ? <label className="control-label">{label}&nbsp;</label> : ''}
<div className="badge pull-right">
<ListAddField name={`${name}.$`} />
</div>
</div>

<ul className="list-group list-group-flush">
{children ? (
value.map((item, index) =>
Children.map(children, child =>
React.cloneElement(child, {
key: index,
label: null,
name: joinName(
name,
child.props.name && child.props.name.replace('$', index)
)
})
)
)
) : (
value.map((item, index) =>
<ListItemField
key={index}
label={null}
name={joinName(name, index)}
/>
)
)}
</ul>
</section>
;

export default connectField(List, {includeInChain: false});
Loading

0 comments on commit 3d35ad9

Please sign in to comment.