From b86d0f97ca940863fe0bf913d46c409e538ca52f Mon Sep 17 00:00:00 2001 From: Sven van de Scheur Date: Fri, 12 May 2023 16:56:31 +0200 Subject: [PATCH 1/5] :sparkles: #43 - Add support for multiple. --- src/containers/index.ts | 1 + src/containers/multiple/index.ts | 1 + .../multiple/multiple.container.tsx | 93 +++++++++++++++++++ src/containers/multiple/multiple.stories.tsx | 64 +++++++++++++ src/lib/renderer/renderer.tsx | 76 ++++++++++++--- src/types/componentprops.d.ts | 12 +-- src/types/config.d.ts | 17 ++++ tsconfig.json | 1 + 8 files changed, 247 insertions(+), 18 deletions(-) create mode 100644 src/containers/index.ts create mode 100644 src/containers/multiple/index.ts create mode 100644 src/containers/multiple/multiple.container.tsx create mode 100644 src/containers/multiple/multiple.stories.tsx diff --git a/src/containers/index.ts b/src/containers/index.ts new file mode 100644 index 0000000..e6a6634 --- /dev/null +++ b/src/containers/index.ts @@ -0,0 +1 @@ +export * from './multiple'; diff --git a/src/containers/multiple/index.ts b/src/containers/multiple/index.ts new file mode 100644 index 0000000..16bc0aa --- /dev/null +++ b/src/containers/multiple/index.ts @@ -0,0 +1 @@ +export * from './multiple.container'; diff --git a/src/containers/multiple/multiple.container.tsx b/src/containers/multiple/multiple.container.tsx new file mode 100644 index 0000000..0cc96b6 --- /dev/null +++ b/src/containers/multiple/multiple.container.tsx @@ -0,0 +1,93 @@ +import {Component, Description, Label} from '@components'; +import {IRenderable, RenderComponent} from '@lib/renderer'; +import {IComponentProps, Values} from '@types'; +import {ComponentSchema} from 'formiojs'; +import React, {useState} from 'react'; + +export interface IMultipleComponent extends ComponentSchema { + type: string; +} + +export interface IMultipleProps extends IComponentProps { + component: IMultipleComponent; + value: Values; +} + +/** + * Implements `multiple: true` behaviour. + * + * Provide a thin wrapper around a component with controls for adding multiple instances. Utilizes + * to render individual instances. + */ +export const Multiple: React.FC = props => { + const {component, form, path, value = [], setValue} = props; // FIXME: Awaits future pr. + const [keys, setKeys] = useState(Array.from({length: 1}, (_, i) => i)); + + /** Finds next key by increasing the max key with 1. */ + const getKey = (): number => { + if (!keys.length) { + return 0; + } + const max = Math.max(...keys); + return max + 1; + }; + + /** Add item. */ + const add = () => { + setKeys([...keys, getKey()]); + }; + + /** Remove item at index. */ + const remove = (index: number) => { + const _keys = keys.filter((_, i) => i !== index); + const val = value.filter((_, i) => i !== index); + setKeys(_keys); + setValue(path, val); + }; + + /** Renders individual components utilizing . */ + const renderComponents = () => + Array.from({length: keys.length}, (_, index) => { + // Clone and adjust component to fit nested needs. + const renderable: IRenderable = { + ...structuredClone(component), + key: `${path}.${index}`, // Trigger Formik array values. + multiple: false, // Handled by + description: '', // One description rendered for all components. + label: '', // One label rendered for all components. + }; + + return ( + + + + + + + + + ); + }); + + return ( + + );