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

draupnir

v0.2.1

Published

![draupnir](https://github.com/hashedalgorithm/draupnir/assets/53309069/da55b4b6-0f06-4d3c-8ca3-0d718ef0ccef)

Downloads

193

Readme

Draupnir 🪄

draupnir

Draupnir is a dynamic form generator for React applications, designed to streamline the process of creating forms based on JSON Schema. Unlike some existing libraries, Draupnir prioritizes flexibility and customization, empowering developers to tailor the form renderer to their specific needs.

Features

  • 📋 Render Forms with JSON: Draupnir enables the rendering of forms dynamically based on JSON schema definitions.
  • 🎨 Conditional Rendering: Developers can conditionally render form elements based on specific criteria using Draupnir.
  • 🛠️ Customizable Components: Draupnir provides developers with the flexibility to customize form components according to their requirements.
  • ⚡ Built Upon React Hook Forms for Performance: Leveraging React Hook Forms, Draupnir ensures optimal performance and efficiency in form rendering.
  • 🔒 Data Validations Using Zod: Draupnir integrates Zod for robust data validations, ensuring data integrity and consistency.
  • ❗ Clear Error Messages: Draupnir offers specific and clear error messages for various data validation scenarios, including minimum/maximum values, required fields, and improper data types. Developers can also provide custom error messages.

Limitations

  • 🚫 Single Condition per Field: Draupnir currently supports applying only one condition per field, limiting the complexity of conditional rendering scenarios.

Table of Contents

Installation

NPM :

npm install draupnir

Yarn :

yarn add draupnir

Basic Usage

Using Draupnir is straightforward. Simply provide your JSON Schema to the form generator, along with any customizations for the form renderer.

// Define your JSON Schema
const schema = {
  // Your Schema here 
};

// Initialize Widgets Object. This object contains the renderes.
const widgets = {
  base: {
  string: StringWidget,
  // If you want use your own custom form components add this as needed
  },
  nonreactive: {},
  custom: {},
};

const handleOnSubmit = async (val: any) => {
  console.log(val)
  // your onsubmit logic here
}

// Render the form
const App = () => (
  <DraupnirRoot widgets={widgets}>
    <DraupnirProvider
        schema={schema}
        onSubmit={handleOnSubmit}
        mode={'onChange'}> // Controls when validations should run, onChange, onBlur, all, onSubmit
          <button type='submit'>Sumit</button>
          <button type='button'>Cancel</button>
          // you can extend the form with form action button here.
    </DraupnirProvider>
  </DraupnirRoot>
);

export default App;

Example Schema

  const schema = {
    title: "Sample",
    version: "0.1",
    conditions: [
      {
        type: "if",
        id: 'age',
        match: 18,
        operator: "lesser_or_equal",
        then: ['hasVoterId']
      },
      {
        type: "select_injection",
        id: "gender",
        match: "male",
        mode: "replace",
        then: "weight",
        enum: ['less than 90', '90 - 100', '100 -120', '120 - 130'],
      }
    ],
    properties: {
      title: {
        id: "title",
        type: "string",
        widget: "heading",
        hlevel: "h2",
        label: "Personal Details Form"
      },
      fullname: {
        id: "fullname",
        type: "string",
        label: "Full Name",
        maximum: 20,
        minimum: 5,
        view: {
          lg: 12,
          xl: 4,
          xxl: 4, 
          wide: 4
        }
      },
      age: {
        id: "age",
        type: "number",
        maximum: 50,
        minimum: 0
      },
      hasVoterId: {
        id: "hasVoterId",
        type: 'boolean',
        label: "Do you have Voter ID (Provided by your Respected Governtment)",
        helperText: "If you have applied and waiting for issue, then please choose 'yes'."
      },
      gender: {
        id: "gender",
        type: "string",
        widget: 'select',
        enum: ['male', 'female', "others"],
        default: "male"
      },
      weight: {
        id: "weight",
        type: "string",
        widget: 'select',
        enum: ['Lesser than 50', '55 - 60', "60 - 80"],
      },
      height: {
        id: "height",
        type: "string",
        widget: 'select',
        label: "Height (CM)",
        enum: ['lesser than 150', '150 - 170', "Greater than 170"],
        default: "lesser than 150"
      },
      isAgree: {
        id: "isAgree",
        type: "boolean",
        required: true
      },
      separator: {
        id: "separator",
        type: "string",
        widget: "separator"
      }
    },
  } satisfies TSchema;

Explanation of Schema

Link to Types : https://github.com/hashedalgorithm/draupnir/blob/main/src/types/schema.ts

TSchema

type TSchema = {
  title: string;
  version?: string;
  readOnly?: boolean;
  properties: TProperties;
  conditions: TCondition[];
};
  • title: Required. A string representing the title of the schema.
  • version: Optional. A string representing the version of the schema.
  • readOnly: Optional. Indicates whether the schema is read-only.
  • properties: Required. An object containing the properties of the schema. It is of type TProperties.
  • conditions: Required. An array containing conditions to be applied to the schema. It is of type TCondition[].

These keys provide essential information and configuration options for defining a schema within Draupnir, ensuring flexibility and customization in form generation.

TProperties

  • Represents the properties/field of a schema.
  • It is a recod of field configurations.

TProperty

The TProperty type represents a property/form field within a schema. Each property can have various configuration options that can alter behaviour, validations of that respective field:

  • id: Required. Unique identifier for the property and it also serves as the name. if you want to want have field inside deep levels then use dot notation here. eg. 'address.streetno' results data as
...
properties: {
  address.streetno: {
    id: "address.streetno"
  }
}
{
  address: {
    streetno: 123
  }
}
  • type: Required. Type of the property. It can be one of: 'string', 'number', or 'boolean'.
  • widget: Optional. Type of widget to be used for rendering the field (It can be one of: 'select', 'checkbox', 'radio', 'email', 'url', 'datepicker', 'text', 'separator', 'heading').
  • maximum: Optional. Maximum value allowed for the property (applicable for number, string type).
  • minimum: Optional. Minimum value allowed for the property (applicable for number, string type).
  • placeholder: Optional. Placeholder text for the field (applicable for string, number, widgets: select, datepicker, email, url, text).
  • label: Optional. Label text for the field.
  • helperText: Optional. Helper text to provide additional guidance for the field.
  • required: Optional. Indicates whether the field is required.
  • readOnly: Optional. Indicates whether the field is read-only.
  • errorText: Optional. Custom Error message to display when validation fails.
  • default: Optional. Default value for the field.
  • pattern: Optional. Regular expression pattern for validating the field value.
  • view: Optional. Configuration for the view of the property, including size settings for different breakpoints.

Screen Breakpoints

  sm: { max: '600px' },
  md: { min: '601px', max: '767px' },
  lg: { min: '768px', max: '991px' },
  xl: { min: '992px', max: '1199px' },
  xxl: { min: '1200px', max: '1500px' },
  wide: { min: '1500px' },

It includes optional sizes for different breakpoints: 'sm', 'md', 'lg', 'xl', 'xxl', and 'wide'. The whole container is a grid of 12 columns and you can configure how much cols each field occupies here.

Example:

{
  id: "fullname",
  type: "string",
  label: "Full Name",
  view: {
    lg: 12,
    xl: 4,
    xxl: 4, 
    wide: 4
  }
}

Default field span | Breakpoint | Default Span size | |------------|------| | sm | 12 | | md | 12 | | lg | 12 | | xl | 6 | | xxl | 6 | | wide | 6 |

  • disabled: Optional. Indicates whether the field is disabled.
  • enum: Optional. List of values for the field (applicable for widgets: radio and selet only).
  • hlevel: Optional. Heading level for the field (applicable only for widget: heading).
  • step: Optional. Step value for number inputs (applicable for number type).

These keys provide comprehensive options for configuring fields within a schema, ensuring flexibility and customization in form generation.

TCondition

The TCondition type represents a condition to be applied to the field:

type TCondition =
  | {
      type: 'if';
      id: string;
      match: string | number | boolean;
      operator: TConditionOperator;
      then: string[];
    }
  | {
      type: 'ifelse';
      id: string;
      match: string | number | boolean;
      operator: TConditionOperator;
      then: string[];
      else: string[];
    }
  | {
      type: 'select_injection';
      mode: 'replace' | 'add' | 'remove';
      id: string;
      match: string;
      then: string;
      enum: string[];
    };
  • type: Required. Specifies the type of condition. It can be one of:
    • 'if': Specifies a condition to be met for certain actions to be taken.
    • 'ifelse': Specifies a condition to be met for certain actions to be taken, with an alternative action if the condition is not met.
    • 'select_injection': Specifies a condition for injecting options into a select widget based on a match.
  • id: Required. Unique identifier for the field to which the condition is applied.
  • match: Required. Value to match against in the condition. It can be a string, number, or boolean.
  • operator: Required. The operator to apply in the condition. It is of type TConditionOperator.
  • then: Required. Array of fieldIds to render if the condition is met.
  • else: Optional. Array of fieldIds to render if the condition is not met (applicable only for 'ifelse' type).
  • enum: Optional. Enum array of strings injected to target select if conditions are met. (Only applicable for type 'select_inject')
  • mode: Required. Mode of injection of enum to target select. (Only applicable for type 'select_inject')

These keys provide a flexible mechanism for defining conditional logic within schemas, enabling dynamic behavior based on specified conditions.

TConditionOperator

  • Represents operators used in conditions.
  • It can be one of: 'greater', 'lesser', 'greater_or_equal', 'lesser_or_equal', 'equal', or 'not_equal'.

Issues

If you encounter any bugs or have suggestions for improvements, please open an issue.

Contributing

Contributions are welcome! Please refer to the contribution guidelines before getting started.

License

This project is licensed under the MIT License - see the LICENSE file for details.