UNPKG

2.8 kBJSXView Raw
1/**
2 * Higher order component with form
3 * @function withForm
4 * @param {function} Component - A component constructor
5 * @returns {function} - Wrapped component
6 */
7'use strict'
8
9import {wrap} from 'breact'
10import classnames from 'classnames'
11import {ApStyle} from 'apeman-react-style'
12import uuid from 'uuid'
13import {spinalcase} from 'stringcase'
14import React, {PropTypes as types} from 'react'
15import {alpha} from 'apemancolor'
16
17const noop = () => null
18
19/** @lends withForm */
20function withForm (Component) {
21 return wrap(Component, {
22 propTypes: {
23 /** Form id */
24 id: types.string,
25 /** Submit handling */
26 onSubmit: types.func,
27 /** Cancel handling */
28 onCancel: types.func,
29 /** Update values */
30 onUpdate: types.func.isRequired,
31 /** Form values */
32 values: types.object.isRequired,
33 /** Form errors */
34 errors: types.object,
35 /** Error color */
36 errorColor: types.string
37 },
38
39 getDefaultProps () {
40 return {
41 onSubmit: noop,
42 onCancel: noop,
43 onUpdate: noop,
44 values: {},
45 errors: null,
46 errorColor: '#E11'
47 }
48 },
49
50 render () {
51 const s = this
52 let { props } = s
53 let {
54 id = `form-${s.uuid}`,
55 errors
56 } = props
57 let errorList = s.renderErrorList(errors, id)
58 let errorStyle = s.renderErrorStyle(errors, id)
59 let idOf = (name) => `${id}-${spinalcase(name)}`
60 return (
61 <Component { ...props }
62 id={ id }
63 idOf={ idOf }
64 errorStyle={ errorStyle }
65 errorList={ errorList }
66 />
67 )
68 },
69
70 componentWillMount () {
71 const s = this
72 s.uuid = uuid.v4()
73 },
74
75 // ------------------
76 // Custom
77 // ------------------
78
79 renderErrorList (errors, id) {
80 let names = Object.keys(errors || {})
81 let className = classnames('ap-form-error-list', {
82 'ap-form-error-list-empty': names.length === 0
83 })
84 return (
85 <ul className={ className }
86 id={ `error-list-for-${id}` }
87 >
88 {
89 names.map((name) => (
90 <li key={ name }
91 className='ap-form-error-list-item'
92 >{ errors[ name ] }</li>
93 ))
94 }
95 </ul>
96 )
97 },
98
99 renderErrorStyle (errors, id) {
100 const s = this
101 let { errorColor } = s.props
102 let data = Object.keys(errors || {})
103 .reduce((data, name) => Object.assign(data, {
104 [`#${id} [name="${name}"]`]: {
105 borderColor: errorColor,
106 backgroundColor: alpha(errorColor, 0.1)
107 }
108 }), {})
109 return (
110 <ApStyle data={ data }/>
111 )
112 }
113 })
114}
115
116export default withForm