npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@uform/next

v1.0.5

Published

### Install

Downloads

46

Readme

@uform/next

Install

npm install --save @uform/next

Table Of Contents

Quick-Start


Example:develop with JSX

import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  SchemaMarkupField as Field,
  createFormActions,
  FormBlock,
  FormLayout,
  FormButtonGroup,
  Submit,
  Reset
} from '@uform/next'
import { Button } from '@alifd/next'
import '@alifd/next/dist/next.css'

const actions = createFormActions()

const App = () => {
  return (
    <SchemaForm actions={actions}>
      <Field
        type="radio"
        enum={['1', '2', '3', '4']}
        title="Radio"
        name="radio"
      />
      <Field
        type="string"
        enum={['1', '2', '3', '4']}
        required
        title="Select"
        name="select"
      />
      <Field
        type="checkbox"
        enum={['1', '2', '3', '4']}
        required
        title="Checkbox"
        name="checkbox"
      />
      <Field
        type="string"
        title="TextArea"
        name="textarea"
        x-component="textarea"
      />
      <Field type="number" title="number" name="number" />
      <Field type="boolean" title="boolean" name="boolean" />
      <Field type="date" title="date" name="date" />
      <Field
        type="daterange"
        title="daterange"
        default={['2018-12-19', '2018-12-19']}
        name="daterange"
      />
      <Field type="year" title="year" name="year" />
      <Field type="time" title="time" name="time" />
      <Field
        type="upload"
        title="upload(card)"
        name="upload"
        x-props={{ listType: 'card' }}
      />
      <Field
        type="upload"
        title="upload(dragge)"
        name="upload2"
        x-props={{ listType: 'dragger' }}
      />
      <Field
        type="upload"
        title="upload(text)"
        name="upload3"
        x-props={{ listType: 'text' }}
      />
      <Field
        type="range"
        title="range"
        name="range"
        x-props={{ min: 0, max: 1024, marks: [0, 1024] }}
      />
      <Field
        type="transfer"
        enum={[{ value: 1, label: 'opt1' }, { value: 2, label: 'opt2' }]}
        title="transfer"
        name="transfer"
      />
      <Field type="rating" title="rating" name="rating" />
      <FormButtonGroup offset={7} sticky>
        <Submit />
        <Reset />
        <Button
          onClick={() => {
            actions.setFieldState('upload', state => {
              state.value = [
                {
                  downloadURL:
                    '//img.alicdn.com/tfs/TB1n8jfr1uSBuNjy1XcXXcYjFXa-200-200.png',
                  imgURL:
                    '//img.alicdn.com/tfs/TB1n8jfr1uSBuNjy1XcXXcYjFXa-200-200.png',
                  name: 'doc.svg'
                }
              ]
            })
          }}
        >
          Upload
        </Button>
        <Button
          onClick={() => {
            actions.setFormState(state => {
              state.values = {
                radio: '4',
                checkbox: ['2', '3']
              }
            })
          }}
        >
          Set Value
        </Button>
      </FormButtonGroup>
    </SchemaForm>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

Example:develop with JSON Schema

import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  SchemaMarkupField as Field,
  createFormActions,
  FormBlock,
  FormLayout,
  FormButtonGroup,
  Submit,
  Reset
} from '@uform/next'
import { Button } from '@alifd/next'
import '@alifd/next/dist/next.css'

const actions = createFormActions()

const App = () => {
  const schema = {
    type: 'object',
    properties: {
      radio: {
        type: 'radio',
        enum: ['1', '2', '3', '4'],
        title: 'Radio'
      },
      select: {
        type: 'string',
        enum: ['1', '2', '3', '4'],
        title: 'Select',
        required: true
      },
      checkbox: {
        type: 'checkbox',
        enum: ['1', '2', '3', '4'],
        title: 'Checkbox',
        required: true
      },
      textarea: {
        type: 'string',
        'x-component': 'textarea',
        title: 'TextArea'
      },
      number: {
        type: 'number',
        title: 'number'
      },
      boolean: {
        type: 'boolean',
        title: 'boolean'
      },
      date: {
        type: 'date',
        title: 'date'
      },
      daterange: {
        type: 'daterange',
        default: ['2018-12-19', '2018-12-19'],
        title: 'daterange'
      },
      year: {
        type: 'year',
        title: 'year'
      },
      time: {
        type: 'time',
        title: 'time'
      },
      upload: {
        type: 'upload',
        'x-props': {
          listType: 'card'
        },
        title: 'upload(card)'
      },
      upload2: {
        type: 'upload',
        'x-props': {
          listType: 'dragger'
        },
        title: 'uplaod(dragger)'
      },
      upload3: {
        type: 'upload',
        'x-props': {
          listType: 'text'
        },
        title: 'upload(text)'
      },
      range: {
        type: 'range',
        'x-props': {
          min: 0,
          max: 1024,
          marks: [0, 1024]
        },
        title: 'range'
      },
      transfer: {
        type: 'transfer',
        enum: [
          {
            value: 1,
            label: 'opt1'
          },
          {
            value: 2,
            label: 'opt2'
          }
        ],
        title: 'transfer'
      },
      rating: {
        type: 'rating',
        title: 'rating'
      },
      layout_btb_group: {
        type: 'object',
        'x-component': 'button-group',
        'x-component-props': {
          offset:7,
          sticky: true,
        },
        properties: {
          submit_btn: {
            type: 'object',
            'x-component': 'submit',
            'x-component-props': {
              children: 'Submit',
            },
          },
          reset_btn: {
            type: 'object',
            'x-component': 'reset',
            'x-component-props': {
              children: 'Reset',
            },
          },
        }
      },
    }
  }
  return <SchemaForm actions={actions} schema={schema} />
}

ReactDOM.render(<App />, document.getElementById('root'))

Components


<SchemaForm/>

Base on <SchemaMarkupForm/> of @uform/react-schema-renderer. Recommended for production environments.

interface INextSchemaFormProps {
    // render by schema
    schema?: ISchema;
    fields?: ISchemaFormRegistry['fields'];
    virtualFields?: ISchemaFormRegistry['virtualFields'];
    // pre-registered Form Component
    formComponent?: ISchemaFormRegistry['formComponent'];
    // pre-registered FormItem Component
    formItemComponent?: ISchemaFormRegistry['formItemComponent'];
    // label column settiing
    labelCol?: number | { span: number; offset?: number }
    // FormItem column settiing
    wrapperCol?: number | { span: number; offset?: number }
    // custom placeholder when preivew
    previewPlaceholder?: string | ((props: IPreviewTextProps) => string);
    // prefix
    prefix?: string;
    // is it inline
    inline?: boolean;
    // The size of a single Item is customized, and takes precedence over the size of the Form, and when a component is used with an Item, the component itself does not set the size property.
    size?: 'large' | 'medium' | 'small';
    // position of label
    labelAlign?: 'top' | 'left' | 'inset';
    // aligment of label
    labelTextAlign?: 'left' | 'right';
    // labelCol of FormItem
    labelCol?: {};
    // wrapperCol of FormItem
    wrapperCol?: {};
    children?: any;
    className?: string;
    style?: React.CSSProperties;
    // type of component
    component?: string | (() => void);
    // form state value
    value?: Value;
    // form state defaultValue
    defaultValue?: DefaultValue;
    // form state initialValues
    initialValues?: DefaultValue;
    // FormActions instance 
    actions?: FormActions;
    // IFormEffect instance
    effects?: IFormEffect<FormEffectPayload, FormActions>;
    // form instance
    form?: IForm;
    // Form change event callback
    onChange?: (values: Value) => void;
    // triggered by `htmlType="submit"` or actions.submit时
    onSubmit?: (values: Value) => void | Promise<Value>;
    // triggered by <Reset/> or actions.reset
    onReset?: () => void;
    // Form verification failure event callback
    onValidateFailed?: (valideted: IFormValidateResult) => void;
    children?: React.ReactElement | ((form: IForm) => React.ReactElement);
    // Whether to use the dirty check, the default will go immer accurate update
    useDirty?: boolean;
    // Is it editable, overall control in the Form dimension
    editable?: boolean | ((name: string) => boolean);
    // Whether to go pessimistic check, stop the subsequent check when the first check fails
    validateFirst?: boolean;    
}

Usage

Example1: Sync value of a and a-mirror

import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  registerFormField,
  Field,  
  connect,
  createFormActions
} from '@uform/next'

const actions = createFormActions()

ReactDOM.render(
    <SchemaForm actions={actions} effects={($)=>{
       $('onFieldChange','a').subscribe((fieldState)=>{
         actions.setFieldState('a-mirror',state=>{
           state.value = fieldState.value
         })
       })
    }}>
       <Field type="string" name="a" title="a"/>
       <Field type="string" name="a-mirror" title="a-mirror"/>
    </SchemaForm>,
    document.getElementById('root')
)

Example:Layout

import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  Field,  
  createFormActions,
  FormLayout,
  FormButtonGroup,
  Submit,
  Reset,
} from '@uform/next'

const actions = createFormActions()

ReactDOM.render(
    <div>
    <h5>Basic Layout</h5>
    <SchemaForm>
      <FormLayout labelCol={8} wrapperCol={6}>
        <Field name="aaa" type="string" title="field1" />
        <Field name="bbb" type="number" title="field2" />
        <Field name="ccc" type="date" title="field3" />
      </FormLayout>
      <FormButtonGroup offset={8}>
        <Submit>Submit</Submit>​ <Reset>Reset</Reset>​
      </FormButtonGroup>
    </SchemaForm>
    <h5>Inline Layout</h5>
    <SchemaForm inline>
      <Field name="aaa" type="string" title="field1" />
      <Field name="bbb" type="number" title="field2" />
      <Field name="ccc" type="date" title="field3" />​
      <FormButtonGroup>
        <Submit>Submit</Submit>​ <Reset>Reset</Reset>​
      </FormButtonGroup>
    </SchemaForm>
    <h5>editable = false</h5>
    <SchemaForm inline editable={false}>
      <Field name="aaa" type="string" title="field1" />
      <Field name="bbb" type="number" title="field2" />
      <Field name="ccc" type="date" title="field3" />​
      <FormButtonGroup>
        <Submit>Submit</Submit>​ <Reset>Reset</Reset>​
      </FormButtonGroup>
    </SchemaForm>
    </div>,
    document.getElementById('root')
)

<SchemaMarkupField/>

Core components of @uform/next, used to describe form fields

interface IMarkupSchemaFieldProps {
  name?: string
  /** base json schema spec**/
  title?: SchemaMessage
  description?: SchemaMessage
  default?: any
  readOnly?: boolean
  writeOnly?: boolean
  type?: 'string' | 'object' | 'array' | 'number' | string
  enum?: Array<string | number | { label: SchemaMessage; value: any }>
  const?: any
  multipleOf?: number
  maximum?: number
  exclusiveMaximum?: number
  minimum?: number
  exclusiveMinimum?: number
  maxLength?: number
  minLength?: number
  pattern?: string | RegExp
  maxItems?: number
  minItems?: number
  uniqueItems?: boolean
  maxProperties?: number
  minProperties?: number
  required?: string[] | boolean
  format?: string
  /** nested json schema spec **/
  properties?: {
    [key: string]: ISchema
  }
  items?: ISchema | ISchema[]
  additionalItems?: ISchema
  patternProperties?: {
    [key: string]: ISchema
  }
  additionalProperties?: ISchema
  /** extend json schema specs */
  editable?: boolean
  visible?: boolean
  display?: boolean
  ['x-props']?: { [name: string]: any }
  ['x-index']?: number
  ['x-rules']?: ValidatePatternRules
  ['x-component']?: string
  ['x-component-props']?: { [name: string]: any }
  ['x-render']?: <T = ISchemaFieldComponentProps>(
    props: T & {
      renderComponent: () => React.ReactElement
    }
  ) => React.ReactElement
  ['x-effect']?: (
    dispatch: (type: string, payload: any) => void,
    option?: object
  ) => { [key: string]: any }
}
Usage
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  FormSlot,
  Field,  
  createFormActions,
  FormLayout,
  FormButtonGroup,
  Submit,
  Reset,
} from '@uform/next'

const actions = createFormActions()

ReactDOM.render(
    <SchemaForm>
      <FormSlot><div>required</div></FormSlot>
      <Field name="a" required type="string" title="field1" />
      
      <FormSlot><div>description</div></FormSlot>
      <Field name="b" description="description" type="string" title="field1" />
      
      <FormSlot><div>default value</div></FormSlot>
      <Field name="c" default={10} type="string" title="field1" />

      <FormSlot><div>readOnly</div></FormSlot>
      <Field name="d" readOnly default={10} type="string" title="field1" />

      <FormSlot><div>visible = false</div></FormSlot>
      <Field name="e" visible={false} default={10} type="string" title="field1" />

      <FormSlot><div>display = false</div></FormSlot>
      <Field name="f" visible={false} default={10} type="string" title="field1" />

      <FormSlot><div>editable = false</div></FormSlot>
      <Field name="g" editable={false} default={10} type="string" title="field1" />
    </SchemaForm>,
    document.getElementById('root')
)

<Submit/>

Props of <Submit/>

interface ISubmitProps {
  /** reset pops **/
  onSubmit?: ISchemaFormProps['onSubmit']
  showLoading?: boolean
  /** nextBtnProps **/
  // type of btn
  type?: 'primary' | 'secondary' | 'normal'
  // size of btn
  size?: 'small' | 'medium' | 'large'
  // size of Icon 
  iconSize?: 'xxs' | 'xs' | 'small' | 'medium' | 'large' | 'xl' | 'xxl' | 'xxxl'
  // type of button  when component = 'button'
  htmlType?: 'submit' | 'reset' | 'button'
  // typeof btn
  component?: 'button' | 'a'
  // Set the loading state of the button
  loading?: boolean
  // Whether it is a ghost button
  ghost?: true | false | 'light' | 'dark'
  // Whether it is a text button
  text?: boolean
  // Whether it is a warning button
  warning?: boolean
  // Whether it is disabled
  disabled?: boolean
  // Callback for button click
  onClick?: (e: {}) => void
  // Valid when Button component is set to 'a', which represents the URL of the linked page
  href?: string
  // Valid when Button component is set to 'a', which represents the way of open the linked document
  target?: string
}

<Reset/>

Props of <Reset/>

interface IResetProps {
  /** reset pops **/
  forceClear?: boolean
  validate?: boolean
  /** nextBtnProps **/
  // type of btn
  type?: 'primary' | 'secondary' | 'normal'
  // size of btn
  size?: 'small' | 'medium' | 'large'
  // size of Icon 
  iconSize?: 'xxs' | 'xs' | 'small' | 'medium' | 'large' | 'xl' | 'xxl' | 'xxxl'
  // type of button when component = 'button'
  htmlType?: 'submit' | 'reset' | 'button'
  // typeof btn
  component?: 'button' | 'a'
  // Set the loading state of the button
  loading?: boolean
  // Whether it is a ghost button
  ghost?: true | false | 'light' | 'dark'
  // Whether it is a text button
  text?: boolean
  // Whether it is a warning button
  warning?: boolean
  // Whether it is disabled
  disabled?: boolean
  // Callback for button click
  onClick?: (e: {}) => void
  // Valid when Button component is set to 'a', which represents the URL of the linked page
  href?: string
  // Valid when Button component is set to 'a', which represents the way of open the linked document
  target?: string
}

<FormSpy/>

<FormSpy> Props

interface IFormSpyProps {
  // selector, eg: [ LifeCycleTypes.ON_FORM_SUBMIT_START, LifeCycleTypes.ON_FORM_SUBMIT_END ]
  selector?: string[] | string
  // reducer
  reducer?: (
    state: any,
    action: { type: string; payload: any },
    form: IForm
  ) => any
  children?: React.ReactElement | ((api: IFormSpyAPI) => React.ReactElement)
}

<Field/>

deprecated,please use SchemaMarkupField

Usage

Example1: Form state change counter

import React from 'react'
import ReactDOM from 'react-dom'
import { Form, Field, createFormActions, FormSpy, LifeCycleTypes } from '@uform/react'

const actions = createFormActions()
const InputField = props => (
  <Field {...props}>
    {({ state, mutators }) => (
      <React.Fragment>
        <input
          disabled={!state.editable}
          value={state.value || ''}
          onChange={mutators.change}
          onBlur={mutators.blur}
          onFocus={mutators.focus}
        />
        <span style={{ color: 'red' }}>{state.errors}</span>
        <span style={{ color: 'orange' }}>{state.warnings}</span>
      </React.Fragment>
    )}
  </Field>
)

const App = () => {
  return (
    <Form actions={actions}>
      <label>username</label>
      <InputField name="username" />
      <label>age</label>
      <InputField name="age" />
      <FormSpy
        selector={LifeCycleTypes.ON_FORM_VALUES_CHANGE}
        reducer={(state, action, form) => ({
          count: state.count ? state.count + 1 : 1
        })}
      >
        {({ state, type, form }) => {
          return <div>count: {state.count || 0}</div>
        }}
      </FormSpy>
    </Form>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

Example2:Combo

import React from 'react'
import ReactDOM from 'react-dom'
import { Form, Field, createFormActions, FormSpy } from '@uform/react'

const actions = createFormActions()
const InputField = props => (
  <Field {...props}>
    {({ state, mutators }) => (
      <React.Fragment>
        <input
          disabled={!state.editable}
          value={state.value || ''}
          onChange={mutators.change}
          onBlur={mutators.blur}
          onFocus={mutators.focus}
        />
        <span style={{ color: 'red' }}>{state.errors}</span>
        <span style={{ color: 'orange' }}>{state.warnings}</span>
      </React.Fragment>
    )}
  </Field>
)

const App = () => {
  return (
    <Form actions={actions}>
      <label>username</label>
      <InputField name="username" />
      <label>age</label>
      <InputField name="age" />
      <FormSpy>
        {({ state, form }) => {
          return (
            <div>
              name: {form.getFieldValue('username')}
              <br />
              age: {form.getFieldValue('age')}
            </div>
          )
        }}
      </FormSpy>
    </Form>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

Array Components

array

import React, { useState, useEffect } from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  Field,
  FormItemGrid,
  FormButtonGroup,
  Submit,
  Reset,
  FormBlock,
  FormLayout
} from '@uform/next'
import '@alifd/next/dist/next.css'
import Printer from '@uform/printer'

const App = () => {
  const [value, setValues] = useState({})
  useEffect(() => {
    setTimeout(() => {
      setValues({
        array: [{ array2: [{ aa: '123', bb: '321' }] }]
      })
    }, 1000)
  }, [])
  return (
    <Printer>
      <SchemaForm initialValues={value} onSubmit={v => console.log(v)}>
        <Field
          title="Array"
          name="array"
          maxItems={3}
          type="array"
          x-props={{
            renderAddition: 'Add Text',
            renderRemove: 'Remove Text'
          }}
        >
          <Field type="object">
            <FormBlock title="Object Field">
              <FormLayout labelCol={9} wrapperCol={6}>
                <Field name="aa" type="string" title="field1" />
                <Field name="bb" type="string" title="field2" />
                <FormItemGrid title="field3" gutter={10}>
                  <Field name="cc" type="string" />
                  <Field name="dd" type="string" />
                </FormItemGrid>
              </FormLayout>
            </FormBlock>
            <FormBlock title="Nested Array Field">
              <Field name="array2" maxItems={3} type="array">
                <Field type="object">
                  <FormLayout labelCol={9} wrapperCol={6}>
                    <Field name="aa" type="string" title="field1" />
                    <Field name="bb" type="string" title="field2" />
                    <FormItemGrid title="field3" gutter={10}>
                      <Field name="cc" type="string" />
                      <Field name="dd" type="string" />
                    </FormItemGrid>
                  </FormLayout>
                </Field>
              </Field>
            </FormBlock>
          </Field>
        </Field>
        <FormButtonGroup>
          <Submit>Submit</Submit>
          <Reset>Reset</Reset>
        </FormButtonGroup>
      </SchemaForm>
    </Printer>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

cards

Usage

import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  Field,
  FormItemGrid,
  FormButtonGroup,
  Submit,
  Reset,
  FormBlock,
  FormLayout
} from '@uform/next'
import '@alifd/next/dist/next.css'
import Printer from '@uform/printer'

const App = () => (
  <Printer>
    <SchemaForm>
      <Field
        name="array"
        maxItems={3}
        type="array"
        x-component="cards"
        x-props={{
          title: 'Title of cards',
          renderAddition: 'Add Text',
          renderRemove: 'Remove Text'
        }}
      >
        <Field type="object">
          <FormLayout labelCol={6} wrapperCol={8}>
            <Field
              name="aa"
              type="string"
              description="hello world"
              title="field1"
            />
            <Field name="bb" type="string" title="field2" />
            <Field name="cc" type="string" title="field3" />
            <Field name="dd" type="string" title="field4" />
            <Field name="dd" type="string" title="field5" />
            <Field name="ee" type="string" title="field6" />
            <Field name="ff" type="string" title="field7" />
            <Field name="gg" type="daterange" title="field8" />
          </FormLayout>
          <Field
            name="array"
            maxItems={3}
            type="array"
            x-component="cards"
            x-props={{ title: 'Title of cards' }}
          >
            <Field type="object">
              <FormLayout labelCol={6} wrapperCol={8}>
                <Field
                  name="aa"
                  type="string"
                  description="hello world"
                  title="field1"
                />
                <Field name="bb" type="string" title="field2" />
                <Field name="cc" type="string" title="field3" />
                <Field name="dd" type="string" title="field4" />
                <Field name="dd" type="string" title="field5" />
                <Field name="ee" type="string" title="field6" />
                <Field name="ff" type="string" title="field7" />
                <Field name="gg" type="daterange" title="field8" />
              </FormLayout>
            </Field>
          </Field>
        </Field>
      </Field>
    </SchemaForm>
  </Printer>
)
ReactDOM.render(<App />, document.getElementById('root'))

table

import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  Field,
  FormItemGrid,
  FormButtonGroup,
  Submit,
  Reset,
  FormBlock,
  FormLayout
} from '@uform/next'
import '@alifd/next/dist/next.css'
import Printer from '@uform/printer'

const App = () => (
  <Printer>
    <SchemaForm>
      <FormLayout>
        <Field
          title="Array"
          name="array"
          maxItems={3}
          type="array"
          x-component="table"
          x-props={{
            renderExtraOperations() {
              return <div>Hello worldasdasdasdasd</div>
            },
            operationsWidth: 300
          }}
        >
          <Field type="object">
            <Field
              name="aa"
              type="string"
              description="hello world"
              title="field1"
            />
            <Field name="bb" type="string" title="field2" />
            <Field name="cc" type="string" title="field3" />
            <Field name="dd" type="string" title="field4" x-index={1} />
            <Field name="ee" type="string" title="field5" />
            <Field name="ff" type="string" title="field6" />
            <Field name="gg" type="string" title="field7" />
            <Field name="hh" type="daterange" title="field8" />
          </Field>
        </Field>
      </FormLayout>
    </SchemaForm>
  </Printer>
)
ReactDOM.render(<App />, document.getElementById('root'))

Layout Components

<FormCard/>

Props of <FormCard/>, fully inherited from CardProps。 The only difference between FormCard FormBlock is a border on the style

Usage

import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, { FormCard, SchemaMarkupField as Field } from '@uform/next'
import '@alifd/next/dist/next.css'

const App = () => (
  <SchemaForm>
    <FormCard title="block">
      <Field type="string" name="username" title="username" />
    </FormCard>
  </SchemaForm>
)
ReactDOM.render(<App />, document.getElementById('root'))

<FormBlock/>

Props of <FormBlock/> , fully inherited from CardProps

Usage

import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, { FormBlock, SchemaMarkupField as Field } from '@uform/next'
import '@alifd/next/dist/next.css'

const App = () => (
  <SchemaForm>
    <FormBlock title="block">
      <Field type="string" name="username" title="username" />
    </FormBlock>
  </SchemaForm>
)
ReactDOM.render(<App />, document.getElementById('root'))

<FormStep/>

Props of <FormStep/>

interface IFormStep {
  dataSource: StepItemProps[]
  /** next step props**/
  // current
  current?: number
  // direction of step
  direction?: 'hoz' | 'ver'
  // Content arrangement in horizontal layout
  labelPlacement?: 'hoz' | 'ver'
  // shape of step
  shape?: 'circle' | 'arrow' | 'dot'
  readOnly?: boolean
  // Whether to activate animation
  animation?: boolean
  className?: string
  // Custom StepItem render
  itemRender?: (index: number, status: string) => React.ReactNode
}

Usage

import {
  SchemaForm,
  Field,
  FormButtonGroup,
  Submit,
  FormEffectHooks,
  createFormActions,
  FormGridRow,
  FormItemGrid,
  FormGridCol,
  FormPath,
  FormLayout,
  FormBlock,
  FormCard,
  FormTextBox,
  FormStep
} from '@uform/next'
import { Button } from '@alifd/next'
import '@alifd/next/dist/next.css'

const { onFormInit$ } = FormEffectHooks

const actions = createFormActions()

let cache = {}

export default () => (
  <SchemaForm
    onSubmit={values => {
      console.log('submit')
      console.log(values)
    }}
    actions={actions}
    labelCol={{ span: 8 }}
    wrapperCol={{ span: 6 }}
    validateFirst
    effects={({ setFieldState, getFormGraph }) => {
      onFormInit$().subscribe(() => {
        setFieldState('col1', state => {
          state.visible = false
        })
      })
    }}
  >
    <FormStep
      style={{ marginBottom: 20 }}
      dataSource={[
        { title: 'Step1', name: 'step-1' },
        { title: 'Step2', name: 'step-2' },
        { title: 'Step3', name: 'step-3' }
      ]}
    />
    <FormCard name="step-1" title="Step1">
      <Field name="a1" required title="A1" type="string" />
    </FormCard>
    <FormCard name="step-2" title="Step2">
      <Field name="a2" required title="A2" type="string" />
    </FormCard>
    <FormCard name="step-3" title="Step3">
      <Field name="a3" required title="A3" type="string" />
    </FormCard>
    <FormButtonGroup>
      <Submit>Submit</Submit>
      <Button onClick={() => actions.dispatch(FormStep.ON_FORM_STEP_PREVIOUS)}>
        Prev
      </Button>
      <Button onClick={() => actions.dispatch(FormStep.ON_FORM_STEP_NEXT)}>
        Next
      </Button>
      <Button
        onClick={() => {
          cache = actions.getFormGraph()
        }}
      >
        Save State
      </Button>
      <Button
        onClick={() => {
          actions.setFormGraph(cache)
        }}
      >
        Rollback State
      </Button>
    </FormButtonGroup>
  </SchemaForm>
)

<FormLayout/>

Props of <FormLayout/>

interface IFormItemTopProps {
  inline?: boolean
  className?: string
  style?: React.CSSProperties
  labelCol?: number | { span: number; offset?: number }
  wrapperCol?: number | { span: number; offset?: number }
}

Usage

import React from 'react'
import ReactDOM from 'react-dom'
import {
  SchemaForm,
  Field,
  FormButtonGroup,
  Submit,
  Reset,
  FormItemGrid,
  FormCard,
  FormBlock,
  FormLayout
} from '@uform/next'
import { Button } from '@alifd/next'
import Printer from '@uform/printer'
import '@alifd/next/dist/next.css'
const App = () => (
  <Printer>
    <SchemaForm>
      <FormLayout labelCol={8} wrapperCol={6}>
        <Field name="aaa" type="string" title="field1" />
        <Field name="bbb" type="number" title="field2" />
        <Field name="ccc" type="date" title="field3" />
      </FormLayout>
      <FormButtonGroup offset={8}>
        <Submit>Submit</Submit>​ <Reset>Reset</Reset>​
      </FormButtonGroup>
    </SchemaForm>
  </Printer>
)
ReactDOM.render(<App />, document.getElementById('root'))

<FormItemGrid/>

Props of <FormItemGrid/>

interface IFormItemGridProps {
  cols?: Array<number | { span: number; offset: number }>
  gutter?: number
  /** next Form.Item props**/
  // prefix od FormItem
  prefix?: string

  // label od FormItem
  label?: React.ReactNode

  // label layout setting, eg, {span: 8, offset: 16}
  labelCol?: {}
  wrapperCol?: {}

  // Custom prompt information, if not set, it will be automatically generated according to the verification rules.
  help?: React.ReactNode

  // Additional prompt information, similar to help, can be used when error messages and prompt copy are required at the same time. Behind the error message.
  extra?: React.ReactNode

  // Check status, if not set, it will be generated automatically according to check rules
  validateState?: 'error' | 'success' | 'loading'

  // Used in conjunction with the validateState property, whether to display the success / loading validation status icon. Currently only Input supports
  hasFeedback?: boolean

  // Custom inline style

  style?: React.CSSProperties

  // node or function(values)
  children?: React.ReactNode | (() => void)

  // The size of a single Item is customized, and takes precedence over the size of the Form, and when a component is used with an Item, the component itself does not set the size property.
  size?: 'large' | 'small' | 'medium'

  // Position of the label
  labelAlign?: 'top' | 'left' | 'inset'

  // alignment of labels
  labelTextAlign?: 'left' | 'right'

  className?: string

  // [validation] required
  required?: boolean

  // whether required asterisks are displayed
  asterisk?: boolean

  // required custom error message
  requiredMessage?: string

  // required Custom trigger method
  requiredTrigger?: string | Array<any>

  // [validation] min
  min?: number

  // [validation] max
  max?: number

  // min/max error message
  minmaxMessage?: string

  // min/max custom trigger method
  minmaxTrigger?: string | Array<any>

  // [validation] min length of string / min length of array
  minLength?: number

  // [validation] max length of string / max length of array
  maxLength?: number

  // minLength/maxLength custom error message
  minmaxLengthMessage?: string

  // minLength/maxLength custom trigger method
  minmaxLengthTrigger?: string | Array<any>

  // [validation] length of string / length of array
  length?: number

  // length custom error message
  lengthMessage?: string

  // length custom trigger method
  lengthTrigger?: string | Array<any>

  // Regular pattern
  pattern?: any

  // pattern custom error message
  patternMessage?: string

  // pattern custom trigger method
  patternTrigger?: string | Array<any>

  // [validation] regular pattern
  format?: 'number' | 'email' | 'url' | 'tel'

  // format custom error message
  formatMessage?: string

  // format custom trigger method
  formatTrigger?: string | Array<any>

  // [validation] custom validator
  validator?: () => void

  // validator custom trigger method
  validatorTrigger?: string | Array<any>

  // Whether to automatically trigger validate when data is modified
  autoValidate?: boolean
}

Usage

import React from 'react'
import ReactDOM from 'react-dom'
import {
  SchemaForm,
  Field,
  FormButtonGroup,
  Submit,
  Reset,
  FormItemGrid,
  FormCard,
  FormBlock,
  FormLayout
} from '@uform/next'
import { Button } from '@alifd/next'
import Printer from '@uform/printer'
import '@alifd/next/dist/next.css'

const App = () => (
  <Printer>
    <SchemaForm onSubmit={v => console.log(v)}>
      <FormItemGrid gutter={20}>
        <Field type="string" name="a1" title="field1" />
        <Field type="string" name="a2" title="field2" />
        <Field type="string" name="a3" title="field3" />
        <Field type="string" name="a4" title="field4" />
      </FormItemGrid>
      <FormItemGrid gutter={20} cols={[6, 6]}>
        <Field type="string" name="a5" title="field5" />
        <Field type="string" name="a6" title="field6" />
      </FormItemGrid>
      <FormButtonGroup style={{ minWidth: 150 }}>
        ​<Submit>Submit</Submit>​<Reset>Reset</Reset>​
      </FormButtonGroup>
    </SchemaForm>
  </Printer>
)
ReactDOM.render(<App />, document.getElementById('root'))

<FormTextBox/>

Props of <FormTextBox/>

interface IFormTextBox {
  text?: string
  gutter?: number
  title?: React.ReactText
  description?: React.ReactText
}

Usage

import React, { useState } from 'react'
import ReactDOM from 'react-dom'
import {
  SchemaForm,
  Field,
  FormTextBox,
  FormCard,
  FormLayout
} from '@uform/next'
import { Button } from '@alifd/next'
import Printer from '@uform/printer'
import '@alifd/next/dist/next.css'

const App = () => {
  return (
    <Printer>
      <SchemaForm labelCol={8} wrapperCol={6} onSubmit={v => console.log(v)}>
        <FormCard title="FormTextBox">
          <FormLayout labelCol={8} wrapperCol={16}>
            <FormTextBox
              title="text label"
              text="prefix%suffix prefix2%suffix2 prefix3%suffix3"
              gutter={8}
            >
              <Field
                type="string"
                default={10}
                required
                name="aa1"
                x-props={{ style: { width: 80 } }}
                description="desc1"
              />
              <Field
                type="number"
                default={20}
                required
                name="aa2"
                description="desc2"
              />
              <Field
                type="number"
                default={30}
                required
                name="aa3"
                description="desc3"
              />
            </FormTextBox>
          </FormLayout>
        </FormCard>
      </SchemaForm>
    </Printer>
  )
}
ReactDOM.render(<App />, document.getElementById('root'))

<FormButtonGroup/>

Props of <FormButtonGroup/>

interface IFormButtonGroupProps {
  sticky?: boolean
  style?: React.CSSProperties
  itemStyle?: React.CSSProperties
  className?: string
  align?: 'left' | 'right' | 'start' | 'end' | 'top' | 'bottom' | 'center'
  triggerDistance?: number
  zIndex?: number
  span?: ColSpanType
  offset?: ColSpanType
}

Usage

import React, { useState } from 'react'
import ReactDOM from 'react-dom'
import {
  SchemaForm,
  Field,
  FormButtonGroup,
  Submit,
  Reset,
  FormItemGrid,
  FormCard,
  FormBlock,
  FormLayout
} from '@uform/next'
import { Button } from '@alifd/next'
import Printer from '@uform/printer'
import '@alifd/next/dist/next.css'

const App = () => {
  const [state, setState] = useState({ editable: true })
  return (
    <Printer>
      <SchemaForm onSubmit={v => console.log(v)}>
        <div>normal</div>
        <FormButtonGroup style={{ minWidth: 150 }}>
          ​<Submit>Submit</Submit>​<Reset>Reset</Reset>​
        </FormButtonGroup>
        <div>sticky</div>
        <FormButtonGroup offset={8} sticky>
          ​<Submit>Submit</Submit>​
          <Button
            type="primary"
            onClick={() => setState({ editable: !state.editable })}
          >
            {state.editable ? 'Preview' : 'Edit'}
          </Button>
          <Reset>Reset</Reset>​
        </FormButtonGroup>
      </SchemaForm>
    </Printer>
  )
}
ReactDOM.render(<App />, document.getElementById('root'))

<TextButton/>

Props of <TextButton/>, fully inherited from ButtonProps

Usage

import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, { TextButton } from '@uform/next'
import '@alifd/next/dist/next.css'

const App = () => (
  <SchemaForm>
    <TextButton>content</TextButton>
  </SchemaForm>
)
ReactDOM.render(<App />, document.getElementById('root'))

<CircleButton/>

Props of <CircleButton/>, fully inherited from ButtonProps

Usage

import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, { CircleButton } from '@uform/next'
import '@alifd/next/dist/next.css'

const App = () => (
  <SchemaForm>
    <CircleButton>ok</CircleButton>
  </SchemaForm>
)
ReactDOM.render(<App />, document.getElementById('root'))

Type of SchemaMarkupField

string

  • Schema Type : string
  • Schema UI Component: Fusion-Next <Input/>, <Input.Textarea/>, <Select/>

Usage

import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  SchemaMarkupField as Field,
  createFormActions,
  FormBlock,
  FormLayout,
  FormButtonGroup,
  Submit,
  Reset
} from '@uform/next'
import '@alifd/next/dist/next.css'

const actions = createFormActions()
const App = () => {
  return (
    <SchemaForm actions={actions}>
      <Field
        type="string"
        required
        title="Text"
        name="text"
        x-component-props={{
          placeholder: 'input'
        }}
      />
      <Field
        type="string"
        enum={['1', '2', '3', '4']}
        required
        title="Simple Select"
        name="simpleSelect"
        x-component-props={{
          placeholder: 'select'
        }}
      />
      <Field
        type="string"
        enum={[
          { label: 'One', value: '1' },
          { label: 'Two', value: '2' },
          { label: 'Three', value: '3' },
          { label: 'Four', value: '4' }
        ]}
        required
        title="Object Select"
        name="objSelect"
        x-component-props={{
          placeholder: 'select'
        }}
      />
      <Field
        type="string"
        title="TextArea"
        name="textarea"
        x-component="textarea"
        x-component-props={{
          placeholder: 'textarea'
        }}
      />
    </SchemaForm>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

textarea

  • Schema Type : string
  • Schema UI Component: Fusion-Next <Input.Textarea/>

Usage

import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  SchemaMarkupField as Field,
  createFormActions,
  FormBlock,
  FormLayout,
  FormButtonGroup,
  Submit,
  Reset
} from '@uform/next'
import '@alifd/next/dist/next.css'

const actions = createFormActions()
const App = () => {
  return (
    <SchemaForm actions={actions}>
      <Field
        type="string"
        title="TextArea"
        name="textarea"
        x-component="textarea"
        x-component-props={{
          placeholder: 'textarea'
        }}
      />
    </SchemaForm>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

password

  • Schema Type : password
  • Schema UI Component: Fusion-Next <Input htmlType="password"/>
interface IPasswordProps {
  checkStrength: boolean
  /** next input props **/
  // value
  value?: string | number

  // default value
  defaultValue?: string | number

  // callback triggered when value change
  onChange?: (value: string, e: React.ChangeEvent<HTMLInputElement>) => void

  // callback triggered when keyboard is press
  onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>, opts: {}) => void

  // Disabled
  disabled?: boolean

  // Max length
  maxLength?: number

  // Whether to show the maximum length style
  hasLimitHint?: boolean

  // When maxLength is set, whether to truncate beyond the string
  cutString?: boolean

  // readOnly
  readOnly?: boolean

  // Automatically remove the leading and trailing blank characters when trigger onChange
  trim?: boolean

  // placeholder
  placeholder?: string

  // callback triggered when focus
  onFocus?: () => void

  // callback triggered when blur
  onBlur?: () => void

  // Custom string length calculation
  getValueLength?: (value: string) => number

  className?: string
  style?: React.CSSProperties
  htmlType?: string

  // name of field
  name?: string

  // state of field
  state?: 'error' | 'loading' | 'success'

  // label
  label?: React.ReactNode

  // whether to show clear
  hasClear?: boolean

  // whether to show border
  hasBorder?: boolean

  // size of field
  size?: 'small' | 'medium' | 'large'

  // callback triggered when enter is press
  onPressEnter?: () => void

  // Watermark (Icon type, shared with hasClear)
  hint?: string

  // Append content before text
  innerBefore?: React.ReactNode

  // Append content after text
  innerAfter?: React.ReactNode

  // Append content before input
  addonBefore?: React.ReactNode

  // Append content after input
  addonAfter?: React.ReactNode

  // Append text before input
  addonTextBefore?: React.ReactNode

  // Append text after input
  addonTextAfter?: React.ReactNode

  // (Native supported by input)
  autoComplete?: string

  // (Native supported by input)
  autoFocus?: boolean
}

Usage

import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  SchemaMarkupField as Field,
  createFormActions,
  FormBlock,
  FormLayout,
  FormButtonGroup,
  Submit,
  Reset
} from '@uform/next'
import '@alifd/next/dist/next.css'

const actions = createFormActions()
const App = () => {
  return (
    <SchemaForm actions={actions}>
      <Field
        type="string"
        title="Password"
        name="password"
        x-component="password"
        x-component-props={{
          placeholder: 'password'
        }}
      />
    </SchemaForm>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

number

  • Schema Type : number
  • Schema UI Component: Fusion-Next <NumberPicker/>

Usage

import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  SchemaMarkupField as Field,
  createFormActions,
  FormBlock,
  FormLayout,
  FormButtonGroup,
  Submit,
  Reset
} from '@uform/next'
import '@alifd/next/dist/next.css'

const actions = createFormActions()
const App = () => {
  return (
    <SchemaForm actions={actions}>
      <Field type="number" required title="Number" name="number" />
    </SchemaForm>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

boolean

  • Schema Type : boolean
  • Schema UI Component: Fusion-Next <Switch/>

Usage

import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  SchemaMarkupField as Field,
  createFormActions,
  FormBlock,
  FormLayout,
  FormButtonGroup,
  Submit,
  Reset
} from '@uform/next'
import '@alifd/next/dist/next.css'

const actions = createFormActions()
const App = () => {
  return (
    <SchemaForm actions={actions}>
      <Field
        type="boolean"
        required
        title="Boolean"
        name="boolean"
        x-component-props={{
          checkedChildren: 'on',
          unCheckedChildren: 'off'
        }}
      />
    </SchemaForm>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

date

  • Schema Type : date
  • Schema UI Component: Fusion-Next <DatePicker/>

Usage

import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  SchemaMarkupField as Field,
  createFormActions,
  FormBlock,
  FormLayout,
  FormButtonGroup,
  Submit,
  Reset
} from '@uform/next'
import '@alifd/next/dist/next.css'

const actions = createFormActions()
const App = () => {
  return (
    <SchemaForm actions={actions}>
      <Field
        type="date"
        required
        title="DatePicker"
        name="datePicker"
        x-component-props={{
          format: 'YYYY-MM-DD HH:mm:ss'
        }}
      />
    </SchemaForm>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

time

  • Schema Type : time
  • Schema UI Component: Fusion-Next <TimePicker/>

Usage

import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  SchemaMarkupField as Field,
  createFormActions,
  FormBlock,
  FormLayout,
  FormButtonGroup,
  Submit,
  Reset
} from '@uform/next'
import '@alifd/next/dist/next.css'

const actions = createFormActions()
const App = () => {
  return (
    <SchemaForm actions={actions}>
      <Field
        type="time"
        required
        title="TimePicker"
        name="timePicker"
        x-component-props={{
          format: 'YYYY-MM-DD HH:mm:ss'
        }}
      />
    </SchemaForm>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

range

  • Schema Type : range
  • Schema UI Component: Fusion-Next <Range/>

Usage

import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  SchemaMarkupField as Field,
  createFormActions,
  FormBlock,
  FormLayout,
  FormButtonGroup,
  Submit,
  Reset
} from '@uform/next'
import '@alifd/next/dist/next.css'

const actions = createFormActions()
const App = () => {
  return (
    <SchemaForm actions={actions}>
      <Field
        type="range"
        required
        title="Range"
        name="range"
        x-component-props={{
          min: 0,
          max: 1024,
          marks: [0, 1024]
        }}
      />
    </SchemaForm>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

upload

  • Schema Type : upload
  • Schema UI Component: Fusion-Next <Upload/>

Usage

import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  SchemaMarkupField as Field,
  createFormActions,
  FormBlock,
  FormLayout,
  FormButtonGroup,
  Submit,
  Reset
} from '@uform/next'
import '@alifd/next/dist/next.css'

const actions = createFormActions()
const App = () => {
  return (
    <SchemaForm actions={actions}>
      <Field
        type="upload"
        required
        title="Card Upload"
        name="upload2"
        x-component-props={{
          listType: 'card'
        }}
      />
      <Field
        type="upload"
        required
        title="Dragger Upload"
        name="upload1"
        x-component-props={{
          listType: 'dragger'
        }}
      />
      <Field
        type="upload"
        required
        title="Text Upload"
        name="upload3"
        x-component-props={{
          listType: 'text'
        }}
      />
    </SchemaForm>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

checkbox

  • Schema Type : checkbox
  • Schema UI Component: Fusion-Next <Checkbox/>

Usage

import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  SchemaMarkupField as Field,
  createFormActions,
  FormBlock,
  FormLayout,
  FormButtonGroup,
  Submit,
  Reset
} from '@uform/next'
import '@alifd/next/dist/next.css'

const actions = createFormActions()
const App = () => {
  return (
    <SchemaForm actions={actions}>
      <Field
        type="checkbox"
        required
        title="Simple Checkbox"
        name="checkbox"
        enum={['1', '2', '3', '4']}
      />
      <Field
        type="checkbox"
        required
        title="Object Checkbox"
        name="checkbox2"
        enum={[
          { label: 'One', value: '1' },
          { label: 'Two', value: '2' },
          { label: 'Three', value: '3' },
          { label: 'Four', value: '4' }
        ]}
      />
    </SchemaForm>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

radio

  • Schema Type : radio
  • Schema UI Component: Fusion-Next <Radio/>

Usage

import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  SchemaMarkupField as Field,
  createFormActions,
  FormBlock,
  FormLayout,
  FormButtonGroup,
  Submit,
  Reset
} from '@uform/next'
import '@alifd/next/dist/next.css'

const actions = createFormActions()
const App = () => {
  return (
    <SchemaForm actions={actions}>
      <Field
        type="radio"
        required
        title="Simple Radio"
        name="radio"
        enum={['1', '2', '3', '4']}
      />
      <Field
        type="radio"
        required
        title="Object Radio"
        name="radio2"
        enum={[
          { label: 'One', value: '1' },
          { label: 'Two', value: '2' },
          { label: 'Three', value: '3' },
          { label: 'Four', value: '4' }
        ]}
      />
    </SchemaForm>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

rating

  • Schema Type : rating
  • Schema UI Component: Fusion-Next <Rating/>

Usage

import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  SchemaMarkupField as Field,
  createFormActions,
  FormBlock,
  FormLayout,
  FormButtonGroup,
  Submit,
  Reset
} from '@uform/next'
import '@alifd/next/dist/next.css'

const actions = createFormActions()
const App = () => {
  return (
    <SchemaForm actions={actions}>
      <Field
        type="rating"
        title="Rating"
        name="rating"
        x-component-props={{
          allowHalf: true
        }}
      />
    </SchemaForm>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

transfer

  • Schema Type : transfer
  • Schema UI Component: Fusion-Next <Transfer/>

Usage

import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  SchemaMarkupField as Field,
  createFormActions,
  FormBlock,
  FormLayout,
  FormButtonGroup,
  Submit,
  Reset
} from '@uform/next'
import '@alifd/next/dist/next.css'

const actions = createFormActions()
const App = () => {
  return (
    <SchemaForm actions={actions}>
      <Field
        type="transfer"
        title="Transfer"
        name="transfer"
        enum={[
          { label: 'One', value: '1' },
          { label: 'Two', value: '2' },
          { label: 'Three', value: '3' },
          { label: 'Four', value: '4' }
        ]}
        x-component-props={{
          showSearch: true
        }}
      />
    </SchemaForm>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

Hook

useFormEffects

Implement local effects by using useFormEffects. Same effect as the example of Linkage Note: The life cycle of the listener starts from ON_FORM_MOUNT

Signature

(effects: IFormEffect): void
import React from 'react'
import ReactDOM from 'react-dom'
import SchemaForm, {
  SchemaMarkupField as Field,
  VirtualField,
  createFormActions,
  useFormEffects,
  LifeCycleTypes,
  createVirtualBox
} from '@uform/next'

const actions = createFormActions()

const FragmentContainer = createVirtualBox('ffb', (props) => {
  useFormEffects(($, { setFieldState }) => {
    $(LifeCycleTypes.ON_FORM_MOUNT).subscribe(() => {
      setFieldState('a~', state => state.visible = false)
    })

    $(LifeCycleTypes.ON_FIELD_VALUE_CHANGE, 'trigger').subscribe((triggerState) => {
      setFieldState('a~', state => {
        state.visible = triggerState.value
      })
    })

    $(LifeCycleTypes.ON_FIELD_VALUE_CHANGE, 'a').subscribe((fieldState) => {
      setFieldState('a-copy', state => {
        state.value = fieldState.value
      })
    })
  })

  return (
    <React.Fragment>
      {props.children}
    </React.Fragment>
  )
});

const FormFragment = () => {
  return <FragmentContainer>
    <Field
      type="radio"
      name="trigger"
      title="trigger"
      enum={[{ label: 'show', value: true }, { label: 'hide', value: false } ]}
    />
    <Field type="string" name="a" title="a" />
    <Field type="string" name="a-copy" title="a-copy" />   
  </FragmentContainer>   
}

const App = () => {
  return (
    <SchemaForm actions={actions}>
      <FormFragment />
    </SchemaForm>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

useFormState

使用 useFormState 为自定义组件提供FormState扩展和管理能力

签名

(defaultState: T): [state: IFormState, setFormState: (state?: IFormState) => void]

用法

import React, { useRef } from 'react'
import ReactDOM from 'react-dom'
import { Form, Field, VirtualField,
  createFormActions, createEffectHook,
  useForm,  
  useFormState,
  useFormEffects,
  useFieldState,
  LifeCycleTypes
} from '@uform/react'

const InputField = props => (
  <Field {...props}>
    {({ state, mutators }) => {
      const loading = state.props.loading
      return <React.Fragment>
        { props.label && <label>{props.label}</label> }
        { loading ? ' loading... ' : <input
          disabled={!state.editable}
          value={state.value || ''}
          onChange={mutators.change}
          onBlur={mutators.blur}
          onFocus={mutators.focus}
        /> }
        <span style={{ color: 'red' }}>{state.errors}</span>
        <span style={{ color: 'orange' }}>{state.warnings}</span>
      </React.Fragment>
    }}
  </Field>
)

const actions = createFormActions()
const FormFragment = (props) => {  
  const [formState, setFormState ] = useFormState({ extendVar: 0 })
  const { extendVar } = formState

  return <div>
    <button onClick={() => {
      setFormState({ extendVar: extendVar + 1 })
    }}>add</button>
    <div>count: {extendVar}</div>
  </div>
}

const App = () => {
  return (
    <Form actions={actions}>
      <FormFragment />
    </Form>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

useFieldState

Manage state of custom field by using useFieldState

Signature

(defaultState: T): [state: IFieldState, setFieldState: (state?: IFieldState) => void]
import React, { useRef } from 'react'
import ReactDOM from 'react-dom'
import { Form, Field, VirtualField,
  createFormActions, createEffectHook,
  useForm,  
  useFormEffects,
  useFieldState,
  LifeCycleTypes
} from '@uform/react'

const InputField = props => (
  <Field {...props}>
    {({ state, mutators }) => {
      const loading = state.props.loading
      return <React.Fragment>
        { props.label && <label>{props.label}</label> }
        { loading ? ' loading... ' : <input
          disabled={!state.editable}
          value={state.value || ''}
          onChange={mutators.change}
          onBlur={mutators.blur}
          onFocus={mutators.focus}
        /> }
        <span style={{ color: 'red' }}>{state.errors}</span>
        <span style={{ color: 'orange' }}>{state.warnings}</span>
      </React.Fragment>
    }}
  </Field>
)

const changeTab$ = createEffectHook('changeTab')
const actions = createFormActions()
const TabFragment = (props) => {  
  const [fieldState, setLocalFieldState ] = useFieldState({ current: 0 })
  const { current } = fieldState
  const { children, dataSource, form } = props
  const ref = useRef(current)

  const update = (cur) => {    
    form.notify('changeTab', cur)
    setLocalFieldState({
      current: cur
    })
  }

  useFormEffects(($, { setFieldState }) => {
    dataSource.forEach((item, itemIdx) => {
      setFieldState(item.name, state => {
        state.display = itemIdx === current
      })
    })

    changeTab$().subscribe((idx) => {
      dataSource.forEach((item, itemIdx) => {
      setFieldState(item.name, state => {
        state.display = itemIdx === idx
      })
    })
    })
  })

  ref.current = current
  const btns = dataSource.map((item, idx) => {
    console.log('current', current, ref.current)
    const focusStyle = idx === current ? { color: '#fff', background: 'blue' } : {}
    return <button style={focusStyle} onClick={() => {
      update(idx)
    }}>{item.label}</button>
  })

  return btns
}

const FormTab = (props) => {
  return <VirtualField name="layout_tab">
    {({ form }) => {
      return <TabFragment {...props} form={form} />
    }}
  </VirtualField>
}

const App = () => {
  return (
    <Form actions={actions}>
      <FormTab dataSource={[
        { label: 'tab-1', name: 'username' },
        { label: 'tab-2', name: 'age' }
      ]} />
      <div>
        <InputField name="username" label="username"/>
        <InputField name="age" label="age"/>
      </div>
    </Form>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))

useForm

get IForm instance

Signature

type useForm = <
  Value = any,
  DefaultValue = any,
  EffectPayload = any,
  EffectAction = any
>(
  props: IFormProps<Value, DefaultValue, EffectPayload, EffectAction>
) => IForm

Usage

import { useForm } from '@uform/react'

const FormFragment = () => {
  const form = useForm()
  return <div>{form.getFieldValue('username')}</div>
}

useField

get IFieldHook instance

Signature

type useField = (options: IFieldStateUIProps): IFieldHook

Usage

import { useField } from '@uform/react'

const FormFragment = (props) => {
  const {
    form,
    state,
    props: fieldProps,
    mutators
  } = useField({ name: 'username' })
  
  return <input {...fieldProps} {...props} value={state.value} onChange={mutators.change} />
}

useVirtualField

get IVirtualFieldHook instance

Signature

type UseVirtualField = (options: IVirtualFieldStateProps): IVirtualFieldHook

Usage

import { UseVirtualField } from '@uform/react'

const FormFragment = (props) => {
  const {
    form,
    state,
    props: fieldProps,
  } = UseVirtualField({ name: 'username' })
  
  return <div style={{ width: fieldProps.width, height: fieldProps.height }}>
    {props.children}
  </div>
}

useFormSpy

get ISpyHook instance. Same effect as the first example of FormSpy.

Signature

type useFormSpy = (props: IFormSpyProps): ISpyHook

Usage

import { useFormSpy, LifeCycleTypes } from '@uform/react'
const FormFragment = (props) => {
  const {
    form,
    state,
    type,
  } = useFormSpy({
    selector: LifeCycleTypes.ON_FORM_VALUES_CHANGE,
    reducer: (state, action, form) => ({
      count: state.count ? state.count + 1 : 1
    })
  })
  
  return <div>
    <div>count: {state.count || 0}</div>
  </div>
}

API

Fully inherited from @uform/react, The specific API of @uform/next is listed below.


createFormActions

Return IFormActions

Signature

createFormActions(): IFormActions

Usage

import { createFormActions } from '@uform/next'

const actions = createFormActions()
console.log(actions.getFieldValue('username'))

createAsyncFormActions

Return IFormAsyncActions

Signature

createAsyncFormActions(): IFormAsyncActions

Usage

import { createAsyncFormActions } from '@uform/next'

const actions = createAsyncFormActions()
actions.getFieldValue('username').then(val => console.log(val))

FormEffectHooks

Return all @uform/core lifeCycles hook which can be subscribe

Usage

import { FormEffectHooks, Form } from '@uform/react'
const {
  /**
   * Form LifeCycle
   **/
  // Form pre-initialization trigger
  onFormWillInit$,
  // Form initialization trigger
  onFormInit$,
  // Triggered when the form changes
  onFormChange$,
  // Triggered when the form event is triggered, used to monitor only manual operations
  onFormInputChange$,
  // Trigger when the form initial value changes
  onFormInitialValueChange$,
  // Triggered when the form is reset
  onFormReset$,
  // Triggered when the form is submitted
  onFormSubmit$,
  // Triggered when the form submission starts
  onFormSubmitStart$,
  // Triggered when the form submission ends
  onFormSubmitEnd$,
  // Triggered when the form is mounted
  onFormMount$,
  // Triggered when the form is unloaded
  onFormUnmount$,
  // Triggered when form validation begins
  onFormValidateStart$,
  // Triggered when the form validation ends
  onFormValidateEnd$,
  // Trigger when the form initial value changes
  onFormValuesChange$,
  /**
   * FormGraph LifeCycle
   **/
  // Triggered when the form observer tree changes
  onFormGraphChange$,
  /**
   * Field LifeCycle
   **/
  // Triggered when pre-initialized
  onFieldWillInit$,
  // Triggered when the field is initialized
  onFieldInit$,
  // Triggered when the field changes
  onFieldChange$,
  // Triggered when the field is mounted
  onFieldMount$,
  // Trigger when the field is unloaded
  onFieldUnmount$,
  // Triggered when the field event is triggered, used to monitor only manual operations
  onFieldInputChange$,
  // Triggered when the field value changes
  onFieldValueChange$,
  // Trigger when the initial value of the field changes
  onFieldInitialValueChange$
} = FormEffectHooks

const App = () => {
  return (
    <Form
      effects={() => {
        onFormInit$().subscribe(() => {
          console.log('initialized')
        })
      }}
    >