Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
b360c8f
-init branch
Oct 11, 2018
4bb3874
-initial implementation of Form and FormField
Oct 11, 2018
ce6f7a1
-small fix
Oct 11, 2018
0f735b2
-added required prop in the form field
Oct 15, 2018
8993e5a
-added size context which is used in the FormField for setting the si…
Oct 15, 2018
f7193cb
-small fixes
Oct 15, 2018
69f6204
-added fields as collection shorthand prop in the form component
Oct 15, 2018
bcbe9a5
-renamed renderItem to renderField
Oct 15, 2018
6911e83
-added message prop to the form field component
Oct 15, 2018
3e65732
-added content prop to the Form and FormField components
Oct 15, 2018
e63df93
Merge branch 'master' into feat/form-base
Oct 15, 2018
d6abc37
-remove content from the FormField and used label in it
Oct 15, 2018
cd3b140
-removed Grid usage from the Form
Oct 16, 2018
fcd7c36
-added control type to the form field and changed control prop to be …
Oct 16, 2018
c5deb09
-added some tests
Oct 16, 2018
f415432
-refactored the code
Oct 17, 2018
1fee3a8
-fixed after element for the label
Oct 17, 2018
21f8a31
-Slot component updates
Oct 17, 2018
d0e1754
-fixing typings
Oct 17, 2018
43ec09b
-foxes for the id
Oct 18, 2018
bc72a97
-foxes for the id
Oct 18, 2018
507c455
-id, name, required and type are advertised from the FormField and go…
Oct 18, 2018
88c80d4
-removed unnecessary as tag
Oct 18, 2018
faa9922
changing id, adding accessibility description
mituron Oct 18, 2018
0ea2e86
Merge branch 'feat/form-base' of https://github.com/stardust-ui/react…
mituron Oct 18, 2018
817c525
adding IDs which get disappear in last push
mituron Oct 18, 2018
515f5fc
-fixing the styling for the input checkbox and radios
Oct 18, 2018
db240e0
-fixed test in the docs examples
Oct 18, 2018
dc3a845
Merge branch 'master' into feat/form-base
Oct 18, 2018
5a9bed1
Addressed comments in PR:
Oct 18, 2018
ae308e0
-replaced controlType with control:as
Oct 18, 2018
3f92280
Merge branch 'master' into feat/form-base
Oct 18, 2018
b20345e
-removed wrapper logic from the Input, updated tests and removed wrap…
Oct 19, 2018
e624787
-reverted changes for removing the wrapper from the input and added c…
Oct 19, 2018
23269fb
-added default control to be {as: Input}
Oct 19, 2018
b0179b1
-improved export for the Form components
Oct 19, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Features
- Add `target` prop to `Popup` @kuzhelog ([#356](https://github.com/stardust-ui/react/pull/356))
- Add new `Input` component with `wrapper` prop @Bugaa92 ([#326](https://github.com/stardust-ui/react/pull/326))
- Add `Form` and `Form.Field` components @mnajdova ([#353](https://github.com/stardust-ui/react/pull/353))

<!--------------------------------[ v0.9.1 ]------------------------------- -->
## [v0.9.1](https://github.com/stardust-ui/react/tree/v0.9.1) (2018-10-11)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react'
import { Form, Button } from '@stardust-ui/react'

const fields = [
{
label: 'First name',
name: 'firstName',
id: 'first-name-shorthand',
key: 'first-name',
required: true,
},
{
label: 'Last name',
name: 'lastName',
id: 'last-name-shorthand',
key: 'last-name',
required: true,
},
{
label: 'I agree to the Terms and Conditions',
control: { as: 'input' },
type: 'checkbox',
id: 'conditions-shorthand',
key: 'conditions',
},
{ control: { as: Button, content: 'Submit' }, key: 'submit' },
]

const FormExample = () => (
<Form
onSubmit={() => {
alert('Form submitted')
}}
fields={fields}
/>
)

export default FormExample
22 changes: 22 additions & 0 deletions docs/src/examples/components/Form/Types/FormExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react'
import { Form, Button } from '@stardust-ui/react'

const FormExample = () => (
<Form
onSubmit={() => {
alert('Form submitted')
}}
>
<Form.Field label="First name" name="firstName" id="first-name" required={true} />
<Form.Field label="Last name" name="lastName" id="last-name" required={true} />
<Form.Field
label="I agree to the Terms and Conditions"
control={{ as: 'input' }}
type="checkbox"
id="conditions"
/>
<Form.Field control={{ as: Button, content: 'Submit' }} />
</Form>
)

export default FormExample
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react'
import { Form, Button } from '@stardust-ui/react'

const fields = [
{
label: 'First name',
name: 'firstName',
id: 'first-name-inline-shorthand',
key: 'first-name',
required: true,
inline: true,
},
{
label: 'Last name',
name: 'lastName',
id: 'last-name-inline-shorthand',
key: 'last-name',
required: true,
inline: true,
},
{
label: 'I agree to the Terms and Conditions',
control: { as: 'input' },
type: 'checkbox',
id: 'conditions-inline-shorthand',
key: 'conditions',
},
{ control: { as: Button, content: 'Submit' }, key: 'submit' },
]

const FormExample = () => (
<Form
onSubmit={() => {
alert('Form submitted')
}}
fields={fields}
/>
)

export default FormExample
34 changes: 34 additions & 0 deletions docs/src/examples/components/Form/Types/FormExampleInline.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react'
import { Form, Button } from '@stardust-ui/react'

const FormExample = () => (
<Form
onSubmit={() => {
alert('Form submitted')
}}
>
<Form.Field
label="First name"
name="firstName"
id="first-name-inline"
inline={true}
required={true}
/>
<Form.Field
label="Last name"
name="lastName"
id="last-name-inline"
inline={true}
required={true}
/>
<Form.Field
label="I agree to the Terms and Conditions"
control={{ as: 'input' }}
type="checkbox"
id="conditions-inline"
/>
<Form.Field control={{ as: Button, content: 'Submit' }} />
</Form>
)

export default FormExample
20 changes: 20 additions & 0 deletions docs/src/examples/components/Form/Types/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react'
import ComponentExample from 'docs/src/components/ComponentDoc/ComponentExample'
import ExampleSection from 'docs/src/components/ComponentDoc/ExampleSection'

const Types = () => (
<ExampleSection title="Types">
<ComponentExample
title="Default"
description="A default form."
examplePath="components/Form/Types/FormExample"
/>
<ComponentExample
title="Inline"
description="The form controls can appear next to the label instead of below it."
examplePath="components/Form/Types/FormExampleInline"
/>
</ExampleSection>
)

export default Types
10 changes: 10 additions & 0 deletions docs/src/examples/components/Form/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react'
import Types from './Types'

const FormExamples = () => (
<div>
<Types />
</div>
)

export default FormExamples
128 changes: 128 additions & 0 deletions src/components/Form/Form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import * as PropTypes from 'prop-types'
import * as React from 'react'
import * as _ from 'lodash'

import { UIComponent, childrenExist, customPropTypes } from '../../lib'
import { ComponentVariablesInput, ComponentPartStyle } from '../../../types/theme'
import {
ComponentEventHandler,
Extendable,
ReactChildren,
ShorthandValue,
ShorthandRenderFunction,
} from '../../../types/utils'
import FormField from './FormField'

export interface IFormProps {
action?: string
as?: any
children?: ReactChildren
className?: string
content?: ShorthandValue
fields?: ShorthandValue[]
onSubmit?: ComponentEventHandler<IFormProps>
renderField?: ShorthandRenderFunction
styles?: ComponentPartStyle
variables?: ComponentVariablesInput
}

/**
* A Form displays a set of related user input fields in a structured way.
* @accessibility
* Label needs to be provided by using 'aria-label', or 'aria-labelledby' attributes on the <form> element.
*/
class Form extends UIComponent<Extendable<IFormProps>, any> {
static create: Function

public static displayName = 'Form'

public static className = 'ui-form'

public static propTypes = {
/** The HTML form action. */
action: PropTypes.string,

/** An element type to render as (string or function). */
as: customPropTypes.as,

/**
* Form content for childrenApi.
* @docSiteIgnore
*/
children: PropTypes.node,

/** Additional CSS class name(s) to apply. */
className: PropTypes.string,

/** Shorthand for primary content. */
content: customPropTypes.contentShorthand,

/** Shorthand array of props for the Form.Fields inside the Form. */
fields: customPropTypes.collectionShorthand,

/**
* The HTML form submit handler.
* @param {SyntheticEvent} event - React's original SyntheticEvent.
* @param {object} data - All props.
*/
onSubmit: PropTypes.func,

/**
* A custom render iterator for rendering each of the Form fields.
* The default component, props, and children are available for each field.
*
* @param {React.ReactType} Component - The computed component for this slot.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just to be sure, what are the scenarios where these JS Doc attributes (like @param) will augment IntelliSense experience? Maybe it is safe for us to just avoid them, if there is no much value in them?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are differently displayed in the props table in the docs
image

* @param {object} props - The computed props for this slot.
* @param {ReactNode|ReactNodeArray} children - The computed children for this slot.
*/
renderField: PropTypes.func,

/** Additional CSS styles to apply to the component instance. */
styles: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),

/** Override for theme site variables to allow modifications of component styling via themes. */
variables: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
}

public static defaultProps = {
as: 'form',
}

public static Field = FormField

public renderComponent({
ElementType,
classes,
accessibility,
variables,
styles,
rest,
}): React.ReactNode {
const { action, children } = this.props
return (
<ElementType className={classes.root} action={action} onSubmit={this.handleSubmit} {...rest}>
{childrenExist(children) ? children : this.renderFields()}
</ElementType>
)
}

private handleSubmit = (e, ...args) => {
const { action } = this.props

// Heads up! Third party libs can pass own data as first argument, we need to check that it has preventDefault()
// method.
if (!action) _.invoke(e, 'preventDefault')
_.invoke(this.props, 'onSubmit', e, this.props, ...args)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you, please, suggest the case where these ...args will be utilized?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there are some additional arguments sent here, for example if the form is going to be used with some additional library (as for validation for example) we must propagate this arguments further. Also taken from Semantic UI, made sense to me.

}

private renderFields = () => {
const { fields, renderField } = this.props
return _.map(fields, field =>
FormField.create(field, {
render: renderField,
}),
)
}
}

export default Form
Loading