diff --git a/docs/details.md b/docs/details.md new file mode 100644 index 00000000..b4a7dca6 --- /dev/null +++ b/docs/details.md @@ -0,0 +1,454 @@ +--- +id: details +title: Explanations of functionalities +sidebar_label: Technical details +--- + +# +## VernaContextProvider + +This provider is used to manage the data of the VernaForm. +It stores the schema of this one, the translations, and the customized components used for the render of the form. + +# +### Optionnal parameters + +
+ +___ +- #### DropZone `(id, render, isSection) => ReactElement` + +The default rendering of the DropZone is css customizable if you want simple design. +If you want a specific behaviour or render you can give this as a property. + +
+ +___ +- #### FieldTemplate `(id, schema, children, ...) => ReactElement` + +This property is used as a wrapper to render every level component (root, section and widget). +By default, it serves basic functions. + +
+ +___ +- #### Section `(id: string, schema: VernaSchemaType, selector: Maybe, ...) => ReactElement` + +The Section component is used as a wrapper of the sections. +It's a level below FieldTemplate. + +
+ +___ +- #### SubmitButton `() => ReactElement` + +This property override the render of the submit button. + +
+ +___ +- #### configSchema `VernaJSONSchemaType` + +This object is necessary to give possibility to the user to configure the fields he creates. +It will be used to generate another form still using the RJSF norm. +You can still use further options existing already in RJSF to parameter this form. +(like minItems that makes mandatory the creation of two items on WidgetName1) + +By default, it gives the user the possibility to customize the title field, so it's not needed to specify it here. + +For example, here is a configuration of two widgets, one with additional items and one for a number field: + +```json +{ + "properties": { + "WidgetName1": { + "properties": { + "items": { + "additionalItems": { + "type": "boolean" + }, + "items": { + "type": "string" + }, + "minItems": 2, + "type": "array" + }, + "required": { + "type": "boolean" + }, + "type": "object" + } + }, + "WidgetName2": { + "properties": { + "maximum": { + "type": "number" + }, + "minimum": { + "type": "number" + }, + "required": { + "type": "boolean" + } + } + } + } +} +``` + +The widget names are corresponding to the name of the widgets you added in the property defaultWidgets. + +You can see more detail examples in the demos. +cf: `examples/playground/App.tsx` + +The existing options are: +1. description +2. enum +3. items +4. maxLength +5. maximum +6. minimum +7. required +8. title + +
+ +___ +- #### defaultSchema `VernaJSONSchemaType` + +You can give the schema to render here. +If you want to start with an empty schema you can ignore this property. + +It will include 3 sub-objects: +1. formSchema + +The formSchema is a modified version of the JSONSchema7 type from @rjsf/core. +It will create the shape of the form and some parameter properties like required. +And it will store the values like the titles or descriptions of the fields. +In the case of Verna it will only contain translation keys that are replaces on each render. + +2. translationSchema + +The translationSchema object it an intlShape type. +It will include the locales and the translations of this one. + +3. uiSchema + +This object is complementary with formSchema. +Its type UiSchema is directly imported from @rjsf/core. +It will give further detail on the schema such as: + +1. the widget to be used to render a field +2. the order to display sections or widgets +3. details on the workaround of some features (like "ui:submitButtonOptions") +4. ... more detailed information in the RJSF documentation + +
+ +___ +- #### defaultFormValues `any` + +This property will be used to give default values on the field. +It can be used to view the values entered the submitted form. + +
+ +___ +- #### defaultLocale `string` + +Default locale is used for the workaround of the library keeping it as a reference and default language. + +
+ +___ +- #### defaultSelector `string` + +This property is used to manage specific rendering of parts of the form. +If you need to cut a form you may use it. +It can match the name of a section, so it will display only this section. + +> The form validation will still be on the whole form. + +It serves an organizational purpose. + +
+ +___ +- #### defaultWidgets `{ [name: string]: Widget }` + +This property is used to give customized widgets. +Those widgets will be used to render your own fields for the form. + +Those widgets will be React components. +They will receive in parameter VernaWidgetProps. +This type includes many required information to parameter your field properly. + +The object taken in parameter will be shaped like this: + +```typescript +const defaultWidgets = { + "WidgetName": WidgetComponent, +} +``` + +WidgetName is free to choose. +It will be necessary for customized way of adding widgets, where you will have to give this name. + +
+ +___ +- #### intl `IntlShape` + +This object is required if your app already have an Intl provider, you can give its object to the library. +This way it doesn't create a new nested one. + +If your app doesn't use multi-language you don't need to bother with this property. + +
+ +___ +- #### isEditor `boolean` + +This boolean indicate the mode of usage of the library, either the view to fill the form or to edit it. + +
+ +___ +- #### locale `string` + +The locale is managed outside the library, it will be used to manage the language translating Verna. + +# +### Data provided + +Those data are accessible through the Verna provider + +
+ +___ +- #### DropZone `(id, render, isSection) => ReactElement` + +Direct access to the property given in parameter or to the default one. + +
+ +___ +- #### FieldTemplate `(id, schema, children, ...) => ReactElement` + +Direct access to the property given in parameter or to the default one. + +
+ +___ +- #### Section `(id: string, schema: VernaSchemaType, selector: Maybe, ...) => ReactElement` + +Direct access to the property given in parameter or to the default one. + +
+ +___ +- #### SubmitButton `() => ReactElement` + +Direct access to the property given in parameter or to the default one. + +
+ +___ +- #### addVernaSection `(idPreviousSection: Nullable) => void` + +This function is to be called to create a new section. +If you want to create it at a specific location you can give in parameter the id of the previous widget. +If the id is null it will create the section in first place. + +
+ +___ +- #### addVernaTranslations `(translations: TranslationType) => void` + +This function is to be called to add translations in the schema.translationSchema object. +It takes an IntlShape object shaped like such: +`{ [locale]: { "key": "translation"} }` + +If a translation exists already on a key it will override the old one. + +
+ +___ +- #### addVernaWidget `(idPreviousWidget: string, widgetInfos?: ShowCaseWidgetProps, intl?: IntlShape) => void` + +This function is to be called to create a new widget. + +It needs an id to position the widget. +This id can be a section id, in this case the widget will be created in first place. +And if the id is a widget id, it will create the widget below the one corresponding to the id provided. + +The property widgetInfos will be an object needed to parameter the widget we want to create. +It will be composed of a name, a type and a boolean to indicate if the widget is added in a section directly (if the id is a sectionId). + +If you want to see an example of usage of this, you can check the way the Verna toolbar is done. cf: `lib/src/components/VernaToolbar/index.tsx` + +The intl object must be given manually to avoid a conflict between the providers. + +
+ +___ +- #### configSchema `VernaJSONSchemaType` + +Direct access to the property given in parameter or to the default one. + +
+ +___ +- #### formData `unknown` + +This property gives direct access to the formData provided in parameter with [defaultFormValues](#defaultformvalues-any). + +> Be careful, the value **is** updated on submit but not on change. + +
+ +___ +- #### handleSubmit `(callback: (formData: unknown) => void) => (event: ISubmitEvent, nativeEvent: FormEvent) => void` + +This function is executed when the form is valid and submitted. +It will be running **before** the function given in parameter of VernaForm. +It will take a custom onSubmit function in parameter. +You can use it if you want to do a custom submit system. + +
+ +___ +- #### isEditor `boolean` + +Direct access to the property given in parameter or to the default one. + + + +
+ +___ +- #### removeVernaTranslations `(translationToDelete: Maybe) => void` + + + +
+ +___ +- #### removeVernaProperty `(id: string) => void` + + + +
+ +___ +- #### schema `VernaSchemaType` + +Direct access to the property given in parameter. +The schema is updated on every call made on those functions (the rerender is done only once every call is done, cf: [useReducer](https://fr.reactjs.org/docs/hooks-reference.html#usereducer)): +- addVernaSection +- addVernaTranslations +- addVernaWidget +- removeVernaTranslations +- removeVernaProperty +- setSchema +- updateVernaProperty +- updateWidget + +[more details here](#defaultschema-vernajsonschematype) + +
+ +___ +- #### selectedFormData `unknown` + +Default values of the form. +If none given the form will be empty. + +
+ +___ +- #### selector `string | undefined` + +The selector is used to display only a part of the form. +The form may be split in sections, if so, the selector prop may be used to display only one section. +If you fill a section using it, then set the selector to undefined, the values entered will still be known and displayed. + +> If you want to use it, you **must** set it to undefined to have the validation of the **whole** form, otherwise it will only be the section. + +
+ +___ +- #### setFormData `(newDefaultValues: unknown) => void` + +May be used to define the default values on the fly. +For example if you change the schema displayed you may want to change the values displayed in it. + +
+ +___ +- #### setSchema `(newSchema: VernaSchemaType) => void` + +Set the whole schema object without any merge. +It must be shaped on the same type as [here](#defaultschema-vernajsonschematype). +You can set it to an empty object to simply unset it. + +
+ +___ +- #### setSelector `(selector: string | undefined) => void` + +Used to set the [selector](#selector-string--undefined). + +
+ +___ +- #### setWidgets `(newWidgets: WidgetsType) => void` + +Used to set the [widgets](#defaultwidgets--name-string-widget-). + +
+ +___ +- #### updateVernaProperty `(schema: VernaSchemaType) => void` + +Used to update the schema by **adding** the values given in the parameter. +The schema parameter must have the same structure as the [original schema](#defaultschema-vernajsonschematype). + +
+ +___ +- #### updateWidget `(schema: VernaJSONSchemaType, id: string) => void` + +This function will **replace** a widget content by the schema given as the parameter schema. +The widget you want to redefine will be the one with the id provided in second parameter. + +> You must remember to provide the type of the widget, such as `{ type: "string" }` + +
+ +___ +- #### widgets `WidgetsType` + +This property provide direct access to the custom widgets given in parameter in `defaultWidgets` + +# +## VernaForm + +VernaForm is a React component. +It will be here that the form will be rendered. +It **must** be wrapped in the VernaContextProvider. +It will only take in parameter the onSubmit. + +> The onSubmit will natively only be triggered if the form is valid and a submit button pressed + +# +## VernaToolbar + +The VernaToolbar is a tool to automatically convert to drag and drop elements usable in Verna. +The children given to this component will be modified by the component. +Every child must receive two properties: +``` + widgetName: string; + type: JSONSchema7TypeName; +``` +Those properties are used by the library to know what type of widget to build and what widget must be rendered. diff --git a/docs/discover.md b/docs/discover.md new file mode 100644 index 00000000..e57f0f1d --- /dev/null +++ b/docs/discover.md @@ -0,0 +1,59 @@ +--- +id: discover +title: Discover Verna +sidebar_label: Discover Verna +--- + +`Verna` is a **library** that provides an easy way to create, modify, fill and display forms. + +It's based on the standard React JSON Schema Form (RJSF). + +Verna features malleable functionalities such as: +- multi-lingual by default +- customization of the fields +- customization of the parameters available to parameter a field +- form split in sections while managing the validation of the whole form +- native drag and drop of the fields for creation +- role management for editing or filling +- fully customizable renders + +## Quick preview + +If you are looking for a demo of what Verna can do, you can test the two demo available. + +The code is in the repository of the library [repository Github](https://github.com/openfun/verna). +The demos are: +- Previewing the most complex use case with split form [demo site playground](https://openfun.github.io/verna/playground/). +- Previewing a use case to create a poll builder using a React component library [demo site poll manager](https://openfun.github.io/verna/poll/). + +## Quick introduction + +The Verna library can help you to create different types of forms. + +> Tips: the forms will be built around sections and widgets. +> A section is a group of fields and a field is called a widget in the context of Verna + +It can help you build one level form such as: +``` +- the main section + \-> field 1 + \-> field 2 + \-> ... +``` + +Or it can help you build more complex forms such as: +``` +- the main section + \-> section 1 + \-> widget 1.1 + \-> widget 2.2 + \-> ... + \-> section 2 + \-> widget 2.1 + \-> widget 2.2 + \-> ... +``` + +## Start using it + +If you want to try it, you can follow the [starter guide](./starter.md) diff --git a/docs/starter.md b/docs/starter.md new file mode 100644 index 00000000..057a2fb2 --- /dev/null +++ b/docs/starter.md @@ -0,0 +1,139 @@ +--- +id: installation +title: Installing Verna for development +sidebar_label: Installation +--- + +# Installation +`Verna` is a npm **library**. +You can install it with either +```bash +yarn add verna +``` +or +```bash +npm install verna +``` +depending on the package manager you are using. + +# Implementation + +## Once installed you will have two required components + +- `VernaContextProvider` that must wrap the component VernaForm [more details](./details.md#VernaContextProvider). +- `VernaForm` that will display the form [more details](./details.md#VernaForm). + +### Basic example + +You don't need to give most of the parameters to the provider to test it. +Here is a simple example using every tool provided by the library. +It includes the usage of a custom widget and a default schema including already a section. + +> Here we pre-create a section but you can create sections however you want. + +```typescript jsx +function App() { + return ( + + + + ) +} +``` + +Then we can add a button to create new widgets in the default section each time we press it. +In this simple case we give directly the id of the section, but in more complex cases you'll use the one provided in overloading components. + +```typescript jsx +import { VernaForm, VernaToolbar } from '@openfun/verna'; +import { useIntl } from 'react-intl'; + +function VernaWrapper() { + const { addVernaWidget } = useVerna(); + const intl = useIntl(); + + return ( + <> + + console.log(values)} /> + + ); +} +``` + +```typescript jsx +function CustomWidgetRender({ + disabled, + required, + label, + }: VernaWidgetProps) { + return
+

+ {label} +

+ +
+} +``` + + +### Example using VernaToolbar + +With this example you may create fields by dragging and dropping the CustomWidgetShowcase +element in the drop area displayed by Verna + +> You may add a VernaToolbar to make a drag and drop feature to add widgets +> But it will need some css or giving a render component for the DropZone property + +> You can customize with only css using the classes `drop-zone`, `drop-zone-divider`, `drop-zone-divider-drag-over` and `drop-zone-drag-over`. + +```typescript jsx +import { VernaForm, VernaToolbar } from '@openfun/verna'; +import { useIntl } from 'react-intl'; + +function VernaWrapper() { + const { addVernaWidget } = useVerna(); + const intl = useIntl(); + + return ( + <> + + + + console.log(values)} /> + + ); +} +``` + +```typescript jsx +function CustomWidgetShowcase(props: ShowCaseWidgetProps) { + return
+ This is my test widget +
+} +``` diff --git a/lib/src/providers/VernaProvider/index.tsx b/lib/src/providers/VernaProvider/index.tsx index fa9759e9..f338b72b 100644 --- a/lib/src/providers/VernaProvider/index.tsx +++ b/lib/src/providers/VernaProvider/index.tsx @@ -210,12 +210,12 @@ VernaProvider.defaultProps = { FieldTemplate: EditorFieldTemplate, Section: DefaultSection, SubmitButton: undefined, + defaultFormValues: {}, defaultSchema: { formSchema: {}, translationSchema: {}, uiSchema: {}, }, - defaultValues: {}, defaultWidgets: {}, isEditor: false, locale: 'en-US',