InseeFr / Lunatic

Library of questionnaire components
https://inseefr.github.io/Lunatic/
MIT License
20 stars 21 forks source link
transverse-component
Lunatic logo

Lunatic

Lunatic CI npm version Coverage Quality Gate Status License: MIT

Lunatic is a front-end library in the form of a React hook and component libraries for generating a questionnaire from the Lunatic-Model data format.

Table of Contents

Usage

To get started, you need to install Lunatic:

yarn add @inseefr/lunatic

The useLunatic Hook

Next, wherever you want to display the form, you'll need to use the useLunatic hook.

import { useLunatic } from '@inseefr/lunatic';

const obj = useLunatic(source, data, options);

This hook takes three parameters:

And it returns an object that allows you to control the questionnaire:

For more information on the types of this return, you can refer to the available types in the source code. You can also find an example of using the hook in the Storybook section.

Components

To display the questionnaire, start by retrieving the list of components to display using the getComponents() method returned by the hook.

Lunatic offers a library of pre-designed components to cover the different types of fields available in questionnaires.

import * as lunatic from '@inseefr/lunatic';

function App({source, data}) {
    const {getComponents, getCurrentErrors, getModalErrors} =
        lunatic.useLunatic(source, data, {});
    const components = getComponents();
    const currentErrors = getCurrentErrors();
    const modalErrors = getModalErrors();

    return (
        <div className="container">
            <LunaticComponents components={components}/>
            <lunatic.Modal errors={modalErrors} goNext={goNextPageAction}/>
        </div>
    );
}

All the components offered by Lunatic are available in the src/components folder.

To activate the autofocus, you need to pass a key in the autoFocusKey property of LunaticComponents. As soon as this value changes, the first field is focused (a good solution is to pass the pageTag provided by useLunatic).

Customization

By default, the components offered by Lunatic are quite simple with a minimal style. You can customize the fields with your own CSS, but for more complex cases, you can also replace the basic components using the custom property that you can pass when calling useLunatic.

const custom = {
    Input: MyCustomInput,
    InputNumber: MyCustomInputNumber,
};

function App({ source, data }) {
    const {} = useLunatic(source, data, { custom });

    // ...
}

Internal Working

This section covers the internal working of the useLunatic() hook. The goal is to help understand how it operates.

General Functioning

The hook is based on an internal state that is updated through a reducer system. The actions affecting this state are limited:

All the reducers corresponding to these actions are available here. Generally, they are broken down into several methods depending on the part of the state they modify.

Pages and Pager

At initialization, the questionnaire scenario is modeled as an object which is stored in the state (in the pages property). This object is indexed by page number and contains the list of components to display for each page. Combined with the pager which contains the state of navigation, this property allows resolving the components to display.

VTL Execution

Another important point of Lunatic is the execution of VTL expressions which allow making certain properties dynamic (labels, errors, etc.). This filling is done when the state changes.

To facilitate expression execution, an executeExpression() method is exposed in the Lunatic state. This method is accompanied by an updateBindings() method which allows updating internal values. This expression execution system uses a memoization system to not re-execute the same expression multiple times. When the use-lunatic/handle-change action is executed, the values ("bindings") are updated to memorize the values associated with the different VTL variables. Similarly, the values of calculated variables on which the modified variable depends are forgotten to refresh the value during the next execution.

Convention and Best Practices

Stable Branchs

Commits and feature branches