diff --git a/public/samples/CustomType-setup.js b/public/samples/CustomType-setup.js
new file mode 100644
index 0000000..4b0e8a1
--- /dev/null
+++ b/public/samples/CustomType-setup.js
@@ -0,0 +1,106 @@
+var {decorators, PropTypes, tutils} = Subschema;
+var {provide} = decorators;
+var {extend} = tutils;
+
+//This adds it to the loader, loader.addType still works.
+@provide.type
+class SwitchButton extends React.Component {
+ //Prevents form-control from being passed to className.
+ static inputClassName = ' ';
+
+ static propTypes = {
+ //This tells subschema to not process e.target.value, but just take the value.
+ onChange: PropTypes.valueEvent,
+ //Normal React.PropTypes
+ onText: React.PropTypes.string,
+ offText: React.PropTypes.string,
+ value: React.PropTypes.oneOfType([React.PropTypes.bool, React.PropTypes.oneOf(['on', 'off', 0, 1])]) //Values can be (true, 1, '1', 'ON')
+ }
+
+ static defaultProps = {
+ onText: "ON",
+ offText: "OFF"
+ }
+ //In case you have "special" value handling.
+ isChecked(value) {
+ return value === true || value === 1 || value === 'on';
+ }
+
+ //This is bound to the object instance
+ handleClick = (e)=> {
+ //This updates the valueManager
+ this.props.onChange(this.isChecked(this.props.value) ? '' : 'on');
+ }
+
+ render() {
+ var props = this.props;
+ var isChecked = this.isChecked(props.value);
+
+ //you prolly won't do it this way, but use classes instead, but the demo platform
+ // has its limitations.
+ var container = extend({}, styles.container, isChecked ? styles.on : styles.off);
+ var button = extend({}, styles.button, isChecked ? styles.buttonOn : styles.buttonOff);
+
+ return
+
+
+ {isChecked === true ? props.onText : props.offText}
+
+
+
+ }
+
+}
+
+//Normally you would do this via CSS but the demo can't load css dynamically, so this a workaround.
+var styles = {
+ fieldContainer: {
+ display: 'block',
+ width: '100%',
+ height: '34px',
+ padding: '6px 12px',
+ fontSize: '14px',
+ lineHeight: '1.42857143',
+ color: '#555',
+ backgroundColor: '#fff'
+ },
+ container: {
+ position: 'relative',
+ borderRadius: "11px",
+ backgroundColor: '#fff',
+ border: 'inset 2px',
+ boxSizing: 'border-box',
+ display: 'inline-block'
+ },
+ on: {
+ color: 'white',
+ backgroundColor: 'blue',
+ paddingLeft: '20px',
+ paddingRight: '6px',
+
+ },
+ off: {
+ paddingLeft: '6px',
+ paddingRight: '20px'
+ },
+ button: {
+ top: 2,
+ display: 'inline-block',
+ height: '16px',
+ width: '16px',
+ boxSizing: 'border-box',
+ borderRadius: '8px',
+ border: '1px outset #fff',
+ position: 'absolute',
+ backgroundColor: '#ccc',
+ transition: 'all .2s',
+
+ },
+ buttonOn: {
+ left: 1
+ },
+ buttonOff: {
+ left: '100%',
+ marginLeft: '-18px',
+ }
+}
diff --git a/public/samples/CustomType.js b/public/samples/CustomType.js
new file mode 100644
index 0000000..89f5032
--- /dev/null
+++ b/public/samples/CustomType.js
@@ -0,0 +1,22 @@
+module.exports = {
+ description: 'Shows how to create a custom type',
+ schema: {
+ "schema": {
+ "areYouSure": {
+ "type": "SwitchButton",
+ "onText": "On",
+ "offText": "Off",
+ "title": "Are you sure?"
+ }
+ },
+ },
+ data: {
+ areYouSure: true
+ },
+ errors: {
+ name: [{
+ message: 'Name is already taken'
+ }]
+ },
+ setupTxt: require('!!raw!./CustomType-setup.js')
+}
diff --git a/test/components/form-test.jsx b/test/components/form-test.jsx
index 03d37df..5d3d0a5 100644
--- a/test/components/form-test.jsx
+++ b/test/components/form-test.jsx
@@ -277,4 +277,4 @@ describe('Form', function () {
expect(count).toBe(2);
})
-})
+});
diff --git a/test/public/CustomType-test.jsx b/test/public/CustomType-test.jsx
new file mode 100644
index 0000000..d7133e9
--- /dev/null
+++ b/test/public/CustomType-test.jsx
@@ -0,0 +1,21 @@
+import {React, into,TestUtils,expect,byTypes, byId, select, Simulate} from '../support';
+import Subschema, {Form, types, ValueManager} from 'Subschema';
+
+var Select = types.Select;
+var CustomTypeSetup = require('../../public/samples/CarMake-setup.js');
+var CustomType = require('../../public/samples/CarMake.js');
+
+describe('CustomType', function () {
+ it('should render', function () {
+ var schema = CustomType.schema;
+ //loader, schema, Subschema, React
+ var loader = Subschema.loaderFactory([Subschema.DefaultLoader]);
+ expect(CustomTypeSetup).toExist('CarMake-setup should load');
+ var valueManager = ValueManager();
+ CustomTypeSetup(loader, schema, Subschema, React, valueManager);
+
+ var form = into(