├── src ├── sass │ ├── clean │ │ ├── _mixins.sass │ │ ├── Formol.sass │ │ ├── fields │ │ │ └── SwitchButton.sass │ │ ├── _base.sass │ │ ├── _variables.sass │ │ └── Field.sass │ ├── default.sass │ ├── clean.sass │ └── default │ │ ├── fields │ │ ├── Preview.sass │ │ ├── TextAreaField.sass │ │ ├── NumberField.sass │ │ ├── ColorField.sass │ │ ├── PasswordField.sass │ │ ├── RangeField.sass │ │ ├── PasswordStrengthField.sass │ │ ├── SwitchButton.sass │ │ ├── BooleanField.sass │ │ └── FileField.sass │ │ ├── async │ │ ├── CalendarField.sass │ │ ├── SelectMenuField.sass │ │ └── HTMLField.sass │ │ ├── Inliner.sass │ │ ├── _variables.sass │ │ ├── _mixins.sass │ │ ├── _base.sass │ │ ├── Formol.sass │ │ └── Field.sass ├── fields │ ├── Datefield.css │ ├── CalendarField.jsx │ ├── SelectMenuField.jsx │ ├── PasswordStrengthField.jsx │ ├── FileField.jsx │ ├── HTMLField.jsx │ ├── UrlField.jsx │ ├── EmailField.jsx │ ├── MonthField.jsx │ ├── TimeField.jsx │ ├── WeekField.jsx │ ├── DatetimeLocalField.jsx │ ├── DateNativeField.jsx │ ├── TelField.jsx │ ├── RadioField.jsx │ ├── TextareaField.jsx │ ├── CheckboxField.jsx │ ├── ColorField.jsx │ ├── NumberField.jsx │ ├── InputField.jsx │ ├── BooleanField.jsx │ ├── SwitchField.jsx │ ├── RadioSetField.jsx │ ├── RangeField.jsx │ ├── CheckboxSetField.jsx │ ├── PasswordField.jsx │ ├── SelectField.jsx │ ├── MoneyField.jsx │ └── DateField.jsx ├── Inliner.jsx ├── FormolContext.jsx ├── __mocks__ │ └── react-text-mask.jsx ├── ConditionalContext.jsx ├── utils │ ├── Preview.jsx │ ├── choicesAdapter.jsx │ ├── SwitchButton.jsx │ ├── index.js │ ├── multipleAdapter.jsx │ ├── Async.jsx │ ├── object.js │ ├── FieldSet.jsx │ ├── memoizedChoices.jsx │ ├── MenuList.jsx │ └── fieldPropsAdapter.jsx ├── async │ ├── CalendarFieldLocales.js │ ├── HTMLField.jsx │ ├── PasswordStrengthField.jsx │ ├── CalendarField.jsx │ ├── SelectMenuField.jsx │ └── FileField.jsx ├── index.js ├── i18n │ ├── fr.js │ └── en.js ├── ext │ └── unrest.js ├── Conditional.jsx └── Field.jsx ├── test ├── styleMock.js ├── setup.js ├── samples │ ├── pixel.png.base64.js │ ├── blank.pdf.base64.js │ └── molecule.svg.base64.js ├── helpers.js ├── formol │ ├── util.test.jsx │ ├── types │ │ ├── text.test.jsx │ │ ├── switch.test.jsx │ │ ├── area.test.jsx │ │ ├── radio.test.jsx │ │ ├── checkbox.test.jsx │ │ ├── dates.test.jsx │ │ ├── radio-set.test.jsx │ │ ├── password.test.jsx │ │ ├── checkbox-set.test.jsx │ │ ├── color.test.jsx │ │ ├── datepicker.test.jsx │ │ ├── tel.test.jsx │ │ ├── email.test.jsx │ │ ├── number.test.jsx │ │ ├── html.test.jsx │ │ └── select.test.jsx │ └── conditional.test.jsx └── utils.object.test.js ├── demos ├── public │ ├── favicon.png │ ├── github.svg │ ├── formol-simple-logo.svg │ ├── formol-baseline-logo.svg │ └── index.html ├── src │ ├── components │ │ └── VersionHeader.jsx │ ├── index.jsx │ ├── pages │ │ ├── AllFieldsDemo.jsx │ │ └── FeaturesDemo.jsx │ └── demos.sass └── deploy.sh ├── .gitignore ├── assets ├── favicon.png ├── github.svg └── formol-simple-logo.svg ├── jsconfig.json ├── .prettierrc ├── babel.config.js ├── jest.config.js ├── LICENSE ├── webpack.config.demos.js ├── webpack.config.babel.js └── package.json /src/sass/clean/_mixins.sass: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/styleMock.js: -------------------------------------------------------------------------------- 1 | module.exports = {} 2 | -------------------------------------------------------------------------------- /demos/public/favicon.png: -------------------------------------------------------------------------------- 1 | ../../assets/favicon.png -------------------------------------------------------------------------------- /demos/public/github.svg: -------------------------------------------------------------------------------- 1 | ../../assets/github.svg -------------------------------------------------------------------------------- /demos/public/formol-simple-logo.svg: -------------------------------------------------------------------------------- 1 | ../../assets/formol-simple-logo.svg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | lib/ 3 | coverage/ 4 | .cache/ 5 | demos/dist 6 | -------------------------------------------------------------------------------- /demos/public/formol-baseline-logo.svg: -------------------------------------------------------------------------------- 1 | ../../assets/formol-baseline-logo.svg -------------------------------------------------------------------------------- /src/sass/default.sass: -------------------------------------------------------------------------------- 1 | @import default/variables 2 | @import default/base 3 | -------------------------------------------------------------------------------- /src/fields/Datefield.css: -------------------------------------------------------------------------------- 1 | .react-datepicker-wrapper { 2 | width: 100%; 3 | } 4 | -------------------------------------------------------------------------------- /assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kozea/formol/HEAD/assets/favicon.png -------------------------------------------------------------------------------- /src/sass/clean/Formol.sass: -------------------------------------------------------------------------------- 1 | // form 2 | .Formol_Formol 3 | font-family: sans-serif 4 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "experimentalDecorators": true, 4 | "allowJs": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/sass/clean.sass: -------------------------------------------------------------------------------- 1 | @import clean/variables 2 | @import default/variables 3 | @import default/base 4 | @import clean/base 5 | -------------------------------------------------------------------------------- /src/sass/clean/fields/SwitchButton.sass: -------------------------------------------------------------------------------- 1 | .Formol_Field--type-switch 2 | input[type='checkbox'] + label 3 | border: solid 2px 4 | -------------------------------------------------------------------------------- /src/sass/default/fields/Preview.sass: -------------------------------------------------------------------------------- 1 | .Formol_Preview 2 | display: block 3 | margin: 0 auto 4 | max-height: 15em 5 | max-width: 100% 6 | -------------------------------------------------------------------------------- /src/sass/clean/_base.sass: -------------------------------------------------------------------------------- 1 | // formol general style 2 | @import Field 3 | @import Formol 4 | 5 | // specific fields 6 | @import fields/SwitchButton 7 | -------------------------------------------------------------------------------- /test/setup.js: -------------------------------------------------------------------------------- 1 | import { configure } from 'enzyme' 2 | import Adapter from 'enzyme-adapter-react-16' 3 | 4 | configure({ adapter: new Adapter() }) 5 | -------------------------------------------------------------------------------- /src/sass/default/fields/TextAreaField.sass: -------------------------------------------------------------------------------- 1 | .Formol_Field--type-area 2 | .Formol_Field 3 | &__element 4 | max-width: 100% 5 | width: $formol-big-field-size 6 | -------------------------------------------------------------------------------- /test/samples/pixel.png.base64.js: -------------------------------------------------------------------------------- 1 | export default 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJgggw=' // eslint-disable-line max-len 2 | -------------------------------------------------------------------------------- /src/fields/CalendarField.jsx: -------------------------------------------------------------------------------- 1 | import Async from '../utils/Async' 2 | 3 | export default Async( 4 | () => import(/* webpackChunkName: "CalendarField" */ '../async/CalendarField') 5 | ) 6 | -------------------------------------------------------------------------------- /src/sass/default/fields/NumberField.sass: -------------------------------------------------------------------------------- 1 | .Formol_Field--readOnly 2 | &.Formol_Field--type-number 3 | .Formol_Field 4 | &__element[type=number] 5 | -moz-appearance: textfield 6 | -------------------------------------------------------------------------------- /src/fields/SelectMenuField.jsx: -------------------------------------------------------------------------------- 1 | import Async from '../utils/Async' 2 | 3 | export default Async( 4 | () => 5 | import(/* webpackChunkName: "SelectMenuField" */ '../async/SelectMenuField') 6 | ) 7 | -------------------------------------------------------------------------------- /test/helpers.js: -------------------------------------------------------------------------------- 1 | export const forCondition = async (condition, wrapper) => { 2 | while (!condition()) { 3 | await new Promise((resolve) => setTimeout(resolve, 1)) 4 | wrapper.update() 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "tabWidth": 2, 4 | "useTabs": false, 5 | "semi": false, 6 | "singleQuote": true, 7 | "trailingComma": "es5", 8 | "bracketSpacing": true, 9 | "bracketSameLine": false 10 | } 11 | -------------------------------------------------------------------------------- /src/fields/PasswordStrengthField.jsx: -------------------------------------------------------------------------------- 1 | import Async from '../utils/Async' 2 | 3 | export default Async( 4 | () => 5 | import( 6 | /* webpackChunkName: "PasswordField" */ 7 | '../async/PasswordStrengthField' 8 | ) 9 | ) 10 | -------------------------------------------------------------------------------- /src/fields/FileField.jsx: -------------------------------------------------------------------------------- 1 | import Async from '../utils/Async' 2 | 3 | const FileField = Async( 4 | () => import(/* webpackChunkName: "FileField" */ '../async/FileField') 5 | ) 6 | FileField.formolFieldLabelElement = 'div' 7 | export default FileField 8 | -------------------------------------------------------------------------------- /test/samples/blank.pdf.base64.js: -------------------------------------------------------------------------------- 1 | export default 'JVBERi0xLgoxIDAgb2JqPDwvUGFnZXMgMiAwIFI+PmVuZG9iagoyIDAgb2JqPDwvS2lkc1szIDAgUl0vQ291bnQgMT4+ZW5kb2JqCjMgMCBvYmo8PC9QYXJlbnQgMiAwIFI+PmVuZG9iagp0cmFpbGVyIDw8L1Jvb3QgMSAwIFI+Pg==' // eslint-disable-line max-len 2 | -------------------------------------------------------------------------------- /src/fields/HTMLField.jsx: -------------------------------------------------------------------------------- 1 | import Async from '../utils/Async' 2 | 3 | const HTMLField = Async( 4 | () => import(/* webpackChunkName: "HTMLField" */ '../async/HTMLField') 5 | ) 6 | 7 | HTMLField.formolFieldLabelElement = 'div' 8 | 9 | export default HTMLField 10 | -------------------------------------------------------------------------------- /src/sass/clean/_variables.sass: -------------------------------------------------------------------------------- 1 | // colors 2 | $formol-color: #222f3e 3 | $formol-color-action: #341f97 4 | $formol-color-inactive: rgba($formol-color-action, .35) 5 | $formol-background-color: rgba($formol-color, .01) 6 | 7 | // fields margin & padding 8 | $formol-field-margin: 2em 9 | -------------------------------------------------------------------------------- /src/Inliner.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { block } from './utils' 4 | 5 | @block 6 | export default class Inliner extends React.PureComponent { 7 | render(b) { 8 | const { children } = this.props 9 | return
{children}
10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/sass/default/async/CalendarField.sass: -------------------------------------------------------------------------------- 1 | .Formol_Field--type-calendar 2 | .Formol_CalendarField 3 | @extend .Formol_Field__element 4 | 5 | &__field 6 | +hidden-field__element 7 | 8 | 9 | .Formol_Field--readOnly 10 | .Formol_CalendarField 11 | +read-only-field__element 12 | -------------------------------------------------------------------------------- /src/sass/default/Inliner.sass: -------------------------------------------------------------------------------- 1 | @use 'sass:math' 2 | 3 | .Formol_Inliner 4 | margin: math.div(-$formol-field-margin, 2) 0 5 | 6 | .Formol_Field 7 | display: inline-block 8 | margin: math.div($formol-field-margin, 2) 0 9 | vertical-align: top 10 | 11 | &:not(:last-of-type) 12 | margin-right: 1em 13 | -------------------------------------------------------------------------------- /src/sass/default/fields/ColorField.sass: -------------------------------------------------------------------------------- 1 | .Formol_Field--type-color 2 | .Formol_Field 3 | &__element 4 | box-sizing: content-box 5 | cursor: pointer 6 | height: 1.5em 7 | // padding: .5em 8 | width: 1.5em 9 | 10 | &.Formol_Field--disabled 11 | .Formol_Field 12 | &__element 13 | cursor: default 14 | -------------------------------------------------------------------------------- /src/fields/UrlField.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { block } from '../utils' 4 | import InputField from './InputField' 5 | 6 | @block 7 | export default class UrlField extends React.PureComponent { 8 | render(b) { 9 | const { className, ...props } = this.props 10 | return 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /demos/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Formol Demos 7 | 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /src/fields/EmailField.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { block } from '../utils' 4 | import InputField from './InputField' 5 | 6 | @block 7 | export default class EmailField extends React.PureComponent { 8 | render(b) { 9 | const { className, ...props } = this.props 10 | return 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/fields/MonthField.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { block } from '../utils' 4 | import InputField from './InputField' 5 | 6 | @block 7 | export default class MonthField extends React.PureComponent { 8 | render(b) { 9 | const { className, ...props } = this.props 10 | return 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/fields/TimeField.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { block } from '../utils' 4 | import InputField from './InputField' 5 | 6 | @block 7 | export default class TimeField extends React.PureComponent { 8 | render(b) { 9 | const { className, ...props } = this.props 10 | return 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/fields/WeekField.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { block } from '../utils' 4 | import InputField from './InputField' 5 | 6 | @block 7 | export default class WeekField extends React.PureComponent { 8 | render(b) { 9 | const { className, ...props } = this.props 10 | return 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/fields/DatetimeLocalField.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { block } from '../utils' 4 | import InputField from './InputField' 5 | 6 | @block 7 | export default class DatetimeLocalField extends React.PureComponent { 8 | render(b) { 9 | const { className, ...props } = this.props 10 | return 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/fields/DateNativeField.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { block } from '../utils' 4 | import InputField from './InputField' 5 | 6 | @block 7 | export default class DateNativeField extends React.PureComponent { 8 | render(b) { 9 | const { className, ...props } = this.props 10 | return 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/FormolContext.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | export const FormolContext = React.createContext({}) 4 | 5 | export default function FormolContextWrapper(Component) { 6 | // eslint-disable-next-line react/display-name 7 | return (props) => ( 8 | 9 | {(context) => } 10 | 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /src/__mocks__/react-text-mask.jsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | 3 | // https://github.com/text-mask/text-mask/issues/427#issuecomment-479945031 4 | const mock = React.forwardRef((props, ref) => { 5 | const { render, ...otherProps } = props 6 | 7 | return render ? ( 8 | render(ref, { ...otherProps }) 9 | ) : ( 10 | 11 | ) 12 | }) 13 | 14 | export default mock 15 | -------------------------------------------------------------------------------- /src/fields/TelField.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { block } from '../utils' 4 | import InputField from './InputField' 5 | 6 | @block 7 | export default class TelField extends React.PureComponent { 8 | render(b) { 9 | const { className, pattern, ...props } = this.props 10 | props.pattern = pattern || props.i18n.tel.pattern.source 11 | return 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/ConditionalContext.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | export const ConditionalContext = React.createContext({}) 4 | 5 | export default function ConditionalContextWrapper(Component) { 6 | // eslint-disable-next-line react/display-name 7 | return (props) => ( 8 | 9 | {(conditionalContext) => ( 10 | 11 | )} 12 | 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true) 3 | 4 | const presets = ['@babel/preset-react', '@babel/preset-env'] 5 | const plugins = [ 6 | 'dynamic-import-node', 7 | '@babel/plugin-proposal-object-rest-spread', 8 | ['@babel/plugin-proposal-decorators', { legacy: true }], 9 | ['@babel/plugin-proposal-class-properties', { loose: true }], 10 | '@babel/plugin-transform-runtime', 11 | ] 12 | 13 | return { 14 | presets, 15 | plugins, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/fields/RadioField.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { block } from '../utils' 4 | import BooleanField from './BooleanField' 5 | 6 | @block 7 | export default class RadioField extends React.PureComponent { 8 | static defaultFieldProps = { 9 | classNameModifiers: (_, value) => ({ 10 | label: { on: value }, 11 | }), 12 | } 13 | render(b) { 14 | const { className, ...props } = this.props 15 | return 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/fields/TextareaField.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { block } from '../utils' 4 | 5 | @block 6 | export default class TextAreaField extends React.PureComponent { 7 | render(b) { 8 | const { type, i18n, className, elementRef, onChange, ...props } = this.props 9 | return ( 10 |