Skip to content

Latest commit

 

History

History
386 lines (312 loc) · 11.6 KB

Readme.md

File metadata and controls

386 lines (312 loc) · 11.6 KB

One Component

<One /> is a component of the react-declarative library, representing a form with various fields (text, images, rating, etc.) and a css-grid layout. This allows for convenient storage, creation, and modification of data, such as a user's profile.

Articles:

  1. The code as the side effect
  2. React components for undirected data flow
  3. MobX onion architecture
  4. DataGrid software design to reduce app cost

Source Description:

Main concept

  1. OneInternal
  2. OneGenesis
  3. One
  4. useResolved
  5. StateProvider
  6. PayloadProvider
  7. OneContextProvider
  8. IManaged
  9. makeField
  10. TypedField
  11. SlotFactory
  12. Form schema
  13. Routing
  14. Route Outlets
  15. Dependency Injection

Additional functionality

  1. Components
  2. Hooks
  3. Higher Order Function
  4. Mathematical Logic
  5. Reactive Programming
  6. Utility Functions

Other

  1. react-declarative.d.ts

Field properties with JSDoc:

With slots:

  1. CheckBox
  2. Choose
  3. Combo
  4. Complete
  5. Date
  6. Dict
  7. File
  8. Items
  9. Line
  10. Progress
  11. Radio
  12. Rating
  13. Slider
  14. Switch
  15. Text
  16. Time
  17. Tree
  18. Typography
  19. YesNo

Without slots:

  1. Component
  2. Init
  3. Line

Layout properties with JSDoc:

  1. Box
  2. Center
  3. Condition
  4. Custom
  5. Div
  6. Expansion
  7. Fragment
  8. Group
  9. Hero
  10. Outline
  11. Paper
  12. Stretch
  13. Tabs

Documentation

Code guide

  1. Implement your own field

Software design

  1. API reference
  2. Release notes
  3. Philosophy notes

Overview

The goal is to create a unified React component for settings-like forms. The component manages form state, handles validation, and streamlines the development process by reducing boilerplate code.

Key Features

  1. Field Configuration : Fields are configured using an array of objects implementing the IField interface, defining the field type, structure, and other properties.

Link to the demo

<One
  fields={[
    {
      type: FieldType.Items,
      title: 'A sample field',
      placeholder: 'Multiple selection',
      name: 'items',
      itemList: ['a', 'b', 'c'],
      isVisible: (obj) => obj.visible,
      isDisabled: (obj) => obj.disabled,
    },
    {
      type: FieldType.Checkbox,
      title: 'Mark as visible',
      defaultValue: true,
      name: 'visible',
    },
    {
      type: FieldType.Checkbox,
      title: 'Mark as disabled',
      defaultValue: false,
      name: 'disabled',
    },
  ]}
/>
  1. Automatic State Management : The component automatically manages form state based on three criteria - field name, a handler function for fetching data, and an onChange callback.

Link to the demo

const handler = () => Promise.resolve({ key: 'value' }) // or simply handler = { key: 'value' }
<One
  fields={[
    {
      type: FieldType.Checkbox,
      title: 'Tomato',
      defaultValue: true,
      name: 'isTomatoChecked',
    },
    {
      type: FieldType.Checkbox,
      title: 'Cheese',
      name: 'isCheeseChecked',
    },
  ]}
  handler={handler}
  fallback={fallback}
  onChange={change}
  LoadPlaceholder={SpinerComponent}
/>
  1. Responsive Layout : The component supports a responsive layout with columns specified for different screen sizes.

Link to the demo

<One fields={[
  {
    type: FieldType.Group,
    phoneColumns: '12',
    columns: '6',
    fields: [
      //...
    ],
  },
  {
    type: FieldType.Group,
    phoneColumns: '12',
    columns: '6',
    fields: [
      //...
    ],
  },
]} />
  1. Field Customization : Fields can be customized with options such as visibility, disabled state, and invalidity.

Link to the demo

<One
  fields={[
    {
      type: FieldType.Items,
      title: 'A sample field',
      placeholder: 'Multiple selection',
      name: 'items',
      itemList: ['a', 'b', 'c'],
      isVisible: (obj) => obj.visible,
      isDisabled: (obj) => obj.disabled,
    },
    //...
  ]}
/>
  1. Additional Features : The component supports computed fields, event handling for icons, and options for disabling the "Save" button based on form validation.

Link to the demo

<One
  fields={[
    {
      type: FieldType.Progress,
      showPercentLabel: true,
      name: 'slider',
    },
    {
      type: FieldType.Slider,
      name: 'slider',
      leadingIcon: VolumeDown,
      trailingIcon: VolumeUp,
      defaultValue: 30,
      leadingIconClick(v, change) { change(v - 10) },
      trailingIconClick(v, change) { change(v + 10) },
    },
    //...
  ]}
/>

Benefits

  • Code Reusability : Reduces duplication by creating a unified component for form handling.

  • Simplified Configuration : Abstracts away complex form configurations into a simple and customizable interface.

  • Responsive Design : Easily adapts to different screen sizes with responsive layout options.

  • Improved Developer Experience : Streamlines development with automatic state management and customizable field behaviors.

This One form component aims to enhance code maintainability, readability, and efficiency in developing settings-like forms.

Usage

There are four main props which you need to pay attention to.

1. fields

This is the primary aspect to work with. Here, you list the fields that should be in the form. It is defined through the fields variable (an array) with the type TypedField[].

const fields: TypedField[] = [
{
    type: FieldType.Group,
    fields: [
      {
        type: FieldType.Rating,
        columns: "2",
        phoneColumns: '12',
        fieldBottomMargin: "0",
        name: "rating",
        defaultValue: 3
      },
      {
        type: FieldType.Group,
        columns: "10",
        phoneColumns: '12',
        fields: [
          {
            name: 'lastName',
            type: FieldType.Text,
            title: 'Last name',
            description: 'Required',
          },
          {
            type: FieldType.Combo,
            title: "Gender",
            placeholder: "Choose your gender",
            name: "gender",
            itemList: [
              "Male",
              "Female",
            ]
          },
        ]
      }   
    ]  
}] 

export const examplePage = () => (
  <One
    fields={fields}
  /> 
);

The main props include:

type - specifies the field type, for example, type: FieldType.Group. There are a total of 22 field types.

columns - used for layout, with a string value from 1 to 12, where 12 represents the full width (following grid logic).

desktopColumns, tabletColumns, and phoneColumns - used to configure the layout on desktop, tablet, and smartphone, respectively.

Each field type has its own properties such as name, title, fieldBottomMargin, outlined, defaultValue, etc.

To insert a separate component into fields, use type: FieldType.Component, where the desired component is specified in the element property. For example:

{
    type: FieldType.Component,
    element: () => (
        <div> Example </div>
    ),
}

2. handler

It should be a function (can return a promise) or a reference to the component's state. It is used to connect the component to the server or mock data. Through variable context composition, you can reach the id from the route.

3. fallback

A callback in case of an error in handler.

4. onChange

A function triggered when data in the <One/> form changes. For example, when the user's name changes.

How do columns work in the layout?

columns are responsible for the layout and work on a grid logic. They determine the width each element occupies. The maximum value is '12' (as columns is of type string), representing the full width. The value "6" would mean half the width, "4" is 1/3 width, "3" is 1/4, and so on. Note: the width refers to the parent's width. The default value is "12".

For example:

{
    type: FieldType.Group,
    fields: [
      {
        type: FieldType.Rating,
        columns: "2",
        desktopColumns: '2',
        tabletColumns: '2',
        phoneColumns: '12',
        fieldBottomMargin: "0",
        fieldBottomMargin: "0",
        name: "rating",
        defaultValue: 3
      },
      {
        type: FieldType.Group,
        columns: "10",
        desktopColumns: '10',
        tabletColumns: '10',
        phoneColumns: '12',
        fields: [
          {
            name: 'name',
            type: FieldType.Text,
            title: 'Name',
          }
        ]
      }
    ]
}

In this example, the Rating element will occupy 20% of the width, and the second Group element will occupy 80% of the width.

desktopColumns used for desktop layout;

tabletColumns used for tablet layout;

phoneColumns used for smartphone layout;

You can adjust the bottom and right margin using fieldBottomMargin and fieldRightMargin, respectively.