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 🙏

© 2025 – Pkg Stats / Ryan Hefner

react-easel

v0.0.14

Published

Widget to dynamically build forms using simple-schema and uniforms

Readme

React Easel

A react component to dynamically build reusable forms. See the demo here

Acknowledgements

React Uniform Builder is built on top of uniforms and simple-schema with styling inspiration from formBuilder

This project is maintained by Amdirent, Inc. If you'd like to build forms that hook up to arbitrary processes, and a dynamically created database table, check out Amdirent Opslab

Usage

Installing

npm install --save react-easel

or

yarn add react-easel

Quick Start

First, ensure you have loaded bootstrap4 css. This library can be used with custom components and custom styling, but defaults exist for bootstrap.

import Easel, { defaults } from 'react-easel';

<Easel onSchemaChange={console.log} {...defaults.bootstrap4} />

Using onSchemaChange, you can extract a json defintion of a SimpleSchema, which can then be used to render the form like so:

import AutoFields from 'uniforms-bootstrap4';
import { defaults } from 'react-easel';
import SimpleSchema from 'node-simpl-schema';

const AutoForm = defaults.bootstrap4.AutoForm;
const AutoField = defaults.bootstrap4.AutoField;

const jsonSchemaDef = <your json definition of a SimpleSchema>

<AutoForm model={{}} schema={new SimpleSchema(jsonSchemaDef)} onSubmit={console.log}>
  <AutoFields autoField={AutoField} />
</AutoForm>

Note: onSchemaChange exists to get data out. It should not be used to drive Easel like a normal controlled component. Easel will populate initial values with props.schema, but it does not update on componentWillReceiveProps. This is because the process of creating Easel's interanal state from a schema is slow, but onSchemaChange is called every time a component is rearanged. Using this like a normal controlled component leads to a laggy drag and drop experience.

Defining Your Own Components/Inputs

Defaults exist for bootstrap4. You can see those in src/bootstrap4/defaults

The easel component expects five props:

| Argument | Description | | -------- | ---------- | | AutoForm | A uniforms AutoForm. Can import directly from your uniforms package of choice, or use a custom form | | components | A list of component definitions that will appear in the sidebar to be used on the form builder | | AutoField | A uniforms AutoField component capable of rendering all the specified components. This will receive a prop componentType, which you can use to decide which component to render. | | onSchemaChange | A callback function that will receive a json representation of the SimpleSchema when the component changes. This SimpleSchema can be used to render future forms.
| schema | (optional) A json representation of an existing SimpleSchema to render.

Component Definiton

Components are defined as follows:

| Argument | Type | Description| | -------- | ---- | ---------- | | type | string | A unique identifier for the component. Ex: 'Text Field' | | schema | object | Corresponds to the node-simple-schema definition. Should, at the very least, contain type | | sidebar | object | The definition for what will show in the sidebar| | sidebar.text | string | The text that shows up on the sidebar. Ex: 'Text Field' | sidebar.icon | React Component | The icon that shows up in the sidebar. Ex: <i className="fa fa-pencil" /> | | admin | object | Definition of any additional configuration the field has. Defaults include name, placeholder, label, optional, and value| | admin.schema | SimpleSchema | A Simple Schema definition to render configuration fields for this Component. Whatever is filled into these fields will be passed as a prop to the component |

Example: Using react-select instead of a regular select

First, make a uniforms driven react-select component:

import React from 'react';
import connectField from 'uniforms/connectField';
import UnconnectedReactSelect from 'react-select';
import wrapField from 'uniforms-bootstrap4/wrapField';

const ReactSelect = connectField((props) => wrapField(props,
  <UnconnectedReactSelect {...props} onChange={e => props.onChange(e ? e.value : null)} />
));

export default ReactSelect;

Now, override the Select field in the bootstrap defaults with your custom select field:

import Easel, { defaults } from 'react-easel';
import ReactSelect from './ReactSelectUniforms';

const myDefaults = { ...defaults.bootstrap4 };
myDefaults.components = defaults.bootstrap4.map(component => {
  if (component.type === 'Select') {
    return {
      ...component,
      formElement: ReactSelect
    }
  }
  
  return component;
});

<Easel onSchemaChange={console.log} {...myDefaults} />

Example: Adding a WYSIWYG editor

For this example, we're going to use Trumbowyg.

First, make the Uniforms driven component:

import React from 'react';
import $ from 'jquery';
import wrapField from 'uniforms-bootstrap4/wrapField';
import connectField from 'uniforms/connectField';
import 'react-trumbowyg/dist/trumbowyg.min.css'

global.$ = global.jQuery = window.$ = window.jQuery = $;

const Trumbowyg = require('react-trumbowyg').default;

let id = 0;

// Made to only load the first value passed, that way trumbo can do its thing.
class MyTrumboWyg extends React.Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      data: props.value
    }
  }

  render() {
    const props = this.props;

    return <Trumbowyg
      id={"react-trumbowyg" + (++id)}
      placeholder={props.placeholder}
      data={this.state.value}
      onChange={(e) => {
        props.onChange($(e.target).trumbowyg('html'));
      }}
    />
  }
}

export default connectField(props => wrapField(props,
  <MyTrumboWyg {...props} />
));

Now, create your easel:

import BaseField from 'uniforms-bootstrap4/AutoField';
import Easel, { defaults } from 'react-easel';
import MyTrumboWyg from './MyTrumboWyg';

// A custom auto field capable of using `componentType` to decide to render the WYSIWYG
class CustomAuto extends BaseField {
  getChildContextName() {
    return this.context.uniforms.name;
  }

  render() {
    const props = this.getFieldProps(undefined, {ensureValue: false});
    if (props.componentType === 'WYSIWYG') {
      return <MyTrumboWyg {...props} />
    }

    return <defaults.bootstrap4.AutoField {...this.props} />;
  }
}

const WYSIWYGComponent = {
  type: 'WYSIWYG Editor',
  schema: {
    type: String
  },
  sidebar: {
    icon: <i className="fa fa-file-text-o"/>,
    text: 'WYSIWYG Editor'
  },
}

<Easel
  AutoForm={defaults.bootstrap4.AutoForm}
  AutoField={CustomAuto}
  components={defaults.bootstrap4.components.concat([WYSIWYGComponent])}
/>

Example: Text Area with admin configuration.

Uniforms-bootstrap4 gives us a LongTextField, and that LongTextField can take rows as a prop. We'd like to show that in the admin section of the field in Easel.

This example will just show the component configuration, since this already exists in defaults.bootstrap4

import LongTextField from 'uniforms-bootstrap4/LongTextField';

const LongTextFieldComponent = {
                                 type: 'Textarea',
                                 schema: {
                                   String,
                                   uniforms: {
                                     rows: 10                                     
                                   }
                                 },
                                 sidebar: {
                                   icon: <i className="fa fa-pencil-square-o" />,
                                   text: 'Textarea'
                                 },
                                 admin: {
                                   schema: new SimpleSchema({
                                     rows: {
                                       type: Number
                                     },
                                   })
                                 }
                               }