From d11a585b9fe808d23d2de42d56bf1ec5fd1791f3 Mon Sep 17 00:00:00 2001 From: Daniel Naab Date: Tue, 26 Mar 2024 09:08:49 -0500 Subject: [PATCH 01/18] flatten location of form elements --- .../design/src/FormManager/FormEdit/DraggableList.tsx | 2 +- packages/design/src/config/edit/FormSummaryEdit.tsx | 5 ++--- packages/design/src/config/edit/InputElementEdit.tsx | 5 ++--- .../design/src/config/edit/ParagraphElementEdit.tsx | 7 ++++--- .../design/src/config/edit/SequenceElementEdit.tsx | 9 ++++----- .../src/config/edit/SubmissionConfirmationEdit.tsx | 5 ++--- packages/forms/src/{config/index.ts => config.ts} | 6 +++--- packages/forms/src/{config => }/elements/fieldset.ts | 9 ++++----- .../forms/src/{config => }/elements/form-summary.ts | 6 +++--- .../forms/src/{config/config.ts => elements/index.ts} | 10 +++++----- packages/forms/src/{config => }/elements/input.ts | 8 ++++---- packages/forms/src/{config => }/elements/paragraph.ts | 7 +++---- packages/forms/src/{config => }/elements/sequence.ts | 6 +++--- .../src/{transform/index.ts => util/transform.ts} | 0 14 files changed, 40 insertions(+), 45 deletions(-) rename packages/forms/src/{config/index.ts => config.ts} (87%) rename packages/forms/src/{config => }/elements/fieldset.ts (84%) rename packages/forms/src/{config => }/elements/form-summary.ts (84%) rename packages/forms/src/{config/config.ts => elements/index.ts} (60%) rename packages/forms/src/{config => }/elements/input.ts (85%) rename packages/forms/src/{config => }/elements/paragraph.ts (80%) rename packages/forms/src/{config => }/elements/sequence.ts (86%) rename packages/forms/src/{transform/index.ts => util/transform.ts} (100%) diff --git a/packages/design/src/FormManager/FormEdit/DraggableList.tsx b/packages/design/src/FormManager/FormEdit/DraggableList.tsx index 0cadabd5..690428e0 100644 --- a/packages/design/src/FormManager/FormEdit/DraggableList.tsx +++ b/packages/design/src/FormManager/FormEdit/DraggableList.tsx @@ -23,7 +23,7 @@ import { FormElementId, } from '@atj/forms'; -import { SequenceElement } from '@atj/forms/src/config/elements/sequence'; +import { SequenceElement } from '@atj/forms/src/elements/sequence'; const SortableItem = ({ id, diff --git a/packages/design/src/config/edit/FormSummaryEdit.tsx b/packages/design/src/config/edit/FormSummaryEdit.tsx index 1092e298..e9e783a5 100644 --- a/packages/design/src/config/edit/FormSummaryEdit.tsx +++ b/packages/design/src/config/edit/FormSummaryEdit.tsx @@ -1,9 +1,8 @@ import React from 'react'; import { useFormContext } from 'react-hook-form'; -import { type FormSummary } from '@atj/forms/src/config/elements/form-summary'; - -import { FormElementEditComponent } from '..'; +import { type FormSummary } from '@atj/forms/src/elements/form-summary'; +import { FormElementEditComponent } from '../../FormManager/FormEdit/types'; const FormSummaryEdit: FormElementEditComponent = ({ element, diff --git a/packages/design/src/config/edit/InputElementEdit.tsx b/packages/design/src/config/edit/InputElementEdit.tsx index 3e4f0fe1..1416d190 100644 --- a/packages/design/src/config/edit/InputElementEdit.tsx +++ b/packages/design/src/config/edit/InputElementEdit.tsx @@ -1,9 +1,8 @@ import React from 'react'; import { useFormContext } from 'react-hook-form'; -import { type InputElement } from '@atj/forms/src/config/elements/input'; - -import { FormElementEditComponent } from '..'; +import { type InputElement } from '@atj/forms/src/elements/input'; +import { FormElementEditComponent } from '../../FormManager/FormEdit/types'; const InputElementEdit: FormElementEditComponent = ({ element, diff --git a/packages/design/src/config/edit/ParagraphElementEdit.tsx b/packages/design/src/config/edit/ParagraphElementEdit.tsx index e27bd9c6..7952ac51 100644 --- a/packages/design/src/config/edit/ParagraphElementEdit.tsx +++ b/packages/design/src/config/edit/ParagraphElementEdit.tsx @@ -1,10 +1,11 @@ import React from 'react'; import { useFormContext } from 'react-hook-form'; -import { type FormElementComponent } from '../../Form'; -import { type ParagraphElement } from '@atj/forms/src/config/elements/paragraph'; +import { type ParagraphElement } from '@atj/forms/src/elements/paragraph'; -const ParagraphElementEdit: FormElementComponent = ({ +import { type FormElementEditComponent } from '../../FormManager/FormEdit/types'; + +const ParagraphElementEdit: FormElementEditComponent = ({ element, }) => { const { register } = useFormContext(); diff --git a/packages/design/src/config/edit/SequenceElementEdit.tsx b/packages/design/src/config/edit/SequenceElementEdit.tsx index 56f242e4..9b1c708d 100644 --- a/packages/design/src/config/edit/SequenceElementEdit.tsx +++ b/packages/design/src/config/edit/SequenceElementEdit.tsx @@ -18,7 +18,7 @@ import { CSS } from '@dnd-kit/utilities'; import { useFormContext } from 'react-hook-form'; import { type FormDefinition, type FormElement } from '@atj/forms'; -import { type SequenceElement } from '@atj/forms/src/config/elements/sequence'; +import { type SequenceElement } from '@atj/forms/src/elements/sequence'; import { type FormEditUIContext, type FormElementEditComponent, @@ -73,8 +73,8 @@ const SequenceElementEdit: FormElementEditComponent = ({ element, }) => { const { register, setValue } = useFormContext(); - const [elements, setElements] = useState( - element.data.elements.map(elementId => { + const [elements, setElements] = useState( + element.data.elements.map((elementId: string) => { return form.elements[elementId]; }) ); @@ -103,8 +103,7 @@ const SequenceElementEdit: FormElementEditComponent = ({ const newOrder = arrayMove(elements, oldIndex, newIndex); setElements(newOrder); setValue(element.id, { - id: element.id, - type: element.type, + ...element, data: { elements: newOrder.map(element => element.id), }, diff --git a/packages/design/src/config/edit/SubmissionConfirmationEdit.tsx b/packages/design/src/config/edit/SubmissionConfirmationEdit.tsx index db5ec764..8b6c6517 100644 --- a/packages/design/src/config/edit/SubmissionConfirmationEdit.tsx +++ b/packages/design/src/config/edit/SubmissionConfirmationEdit.tsx @@ -1,9 +1,8 @@ import React from 'react'; import { useFormContext } from 'react-hook-form'; -import { type InputElement } from '@atj/forms/src/config/elements/input'; - -import { FormElementEditComponent } from '..'; +import { type InputElement } from '@atj/forms/src/elements/input'; +import { type FormElementEditComponent } from '../../FormManager/FormEdit/types'; const InputElementEdit: FormElementEditComponent = ({ element, diff --git a/packages/forms/src/config/index.ts b/packages/forms/src/config.ts similarity index 87% rename from packages/forms/src/config/index.ts rename to packages/forms/src/config.ts index fbb57c45..0790dede 100644 --- a/packages/forms/src/config/index.ts +++ b/packages/forms/src/config.ts @@ -3,10 +3,10 @@ import { type FormElementId, type ParseFormElementData, type ParseFormElementConfigData, -} from '../element'; -import { type CreatePrompt } from '../pattern'; +} from './element'; +import { type CreatePrompt } from './pattern'; -export { defaultFormConfig } from './config'; +export { defaultFormConfig } from './elements'; export type FormElementConfig = { acceptsInput: boolean; diff --git a/packages/forms/src/config/elements/fieldset.ts b/packages/forms/src/elements/fieldset.ts similarity index 84% rename from packages/forms/src/config/elements/fieldset.ts rename to packages/forms/src/elements/fieldset.ts index 6fa993ab..8431f78e 100644 --- a/packages/forms/src/config/elements/fieldset.ts +++ b/packages/forms/src/elements/fieldset.ts @@ -1,14 +1,13 @@ import * as z from 'zod'; -import { type FormElementConfig } from '..'; -import { type FormElement, type FormElementId } from '../../element'; +import { type FormElementConfig, getFormElement } from '..'; +import { type FormElement, type FormElementId } from '../element'; import { type FieldsetPattern, type Pattern, createPromptForElement, -} from '../../pattern'; -import { safeZodParse } from '../../util/zod'; -import { getFormElement } from '../..'; +} from '../pattern'; +import { safeZodParse } from '../util/zod'; export type FieldsetElement = FormElement<{ legend?: string; diff --git a/packages/forms/src/config/elements/form-summary.ts b/packages/forms/src/elements/form-summary.ts similarity index 84% rename from packages/forms/src/config/elements/form-summary.ts rename to packages/forms/src/elements/form-summary.ts index c1181189..31262b32 100644 --- a/packages/forms/src/config/elements/form-summary.ts +++ b/packages/forms/src/elements/form-summary.ts @@ -1,9 +1,9 @@ import * as z from 'zod'; import { type FormElementConfig } from '..'; -import { type FormElement } from '../../element'; -import { FormSummaryPattern, type Pattern } from '../../pattern'; -import { safeZodParse } from '../../util/zod'; +import { type FormElement } from '../element'; +import { FormSummaryPattern, type Pattern } from '../pattern'; +import { safeZodParse } from '../util/zod'; const configSchema = z.object({ title: z.string().max(128), diff --git a/packages/forms/src/config/config.ts b/packages/forms/src/elements/index.ts similarity index 60% rename from packages/forms/src/config/config.ts rename to packages/forms/src/elements/index.ts index f3d19ed8..bf3327a6 100644 --- a/packages/forms/src/config/config.ts +++ b/packages/forms/src/elements/index.ts @@ -1,8 +1,8 @@ -import { type FormConfig } from '.'; -import { fieldsetConfig } from './elements/fieldset'; -import { inputConfig } from './elements/input'; -import { paragraphConfig } from './elements/paragraph'; -import { sequenceConfig } from './elements/sequence'; +import { type FormConfig } from '../config'; +import { fieldsetConfig } from './fieldset'; +import { inputConfig } from './input'; +import { paragraphConfig } from './paragraph'; +import { sequenceConfig } from './sequence'; // This configuration reflects what a user of this library would provide for // their usage scenarios. For now, keep here in the form service until we diff --git a/packages/forms/src/config/elements/input.ts b/packages/forms/src/elements/input.ts similarity index 85% rename from packages/forms/src/config/elements/input.ts rename to packages/forms/src/elements/input.ts index afe2c8a8..244913b2 100644 --- a/packages/forms/src/config/elements/input.ts +++ b/packages/forms/src/elements/input.ts @@ -1,10 +1,10 @@ import * as z from 'zod'; import { type FormElementConfig } from '..'; -import { type FormElement, validateElement } from '../../element'; -import { type Pattern, type TextInputPattern } from '../../pattern'; -import { getFormSessionValue } from '../../session'; -import { safeZodParse } from '../../util/zod'; +import { type FormElement, validateElement } from '../element'; +import { type Pattern, type TextInputPattern } from '../pattern'; +import { getFormSessionValue } from '../session'; +import { safeZodParse } from '../util/zod'; const configSchema = z.object({ label: z.string(), diff --git a/packages/forms/src/config/elements/paragraph.ts b/packages/forms/src/elements/paragraph.ts similarity index 80% rename from packages/forms/src/config/elements/paragraph.ts rename to packages/forms/src/elements/paragraph.ts index 2e34c92c..ca7f8208 100644 --- a/packages/forms/src/config/elements/paragraph.ts +++ b/packages/forms/src/elements/paragraph.ts @@ -1,10 +1,9 @@ import * as z from 'zod'; import { type FormElementConfig } from '..'; -import { type FormElement, validateElement } from '../../element'; -import { type Pattern, type ParagraphPattern } from '../../pattern'; -import { getFormSessionValue } from '../../session'; -import { safeZodParse } from '../../util/zod'; +import { type FormElement } from '../element'; +import { type Pattern, type ParagraphPattern } from '../pattern'; +import { safeZodParse } from '../util/zod'; const configSchema = z.object({ text: z.string(), diff --git a/packages/forms/src/config/elements/sequence.ts b/packages/forms/src/elements/sequence.ts similarity index 86% rename from packages/forms/src/config/elements/sequence.ts rename to packages/forms/src/elements/sequence.ts index 6d4624d1..b678bb98 100644 --- a/packages/forms/src/config/elements/sequence.ts +++ b/packages/forms/src/elements/sequence.ts @@ -1,9 +1,9 @@ import * as z from 'zod'; import { type FormElementConfig } from '..'; -import { type FormElement, type FormElementId } from '../../element'; -import { createPromptForElement } from '../../pattern'; -import { safeZodParse } from '../../util/zod'; +import { type FormElement, type FormElementId } from '../element'; +import { createPromptForElement } from '../pattern'; +import { safeZodParse } from '../util/zod'; import { getFormElement } from '../..'; export type SequenceElement = FormElement<{ diff --git a/packages/forms/src/transform/index.ts b/packages/forms/src/util/transform.ts similarity index 100% rename from packages/forms/src/transform/index.ts rename to packages/forms/src/util/transform.ts From a6d5606edf1450b9b9573d4dd0538c0b0583c728 Mon Sep 17 00:00:00 2001 From: Daniel Naab Date: Tue, 26 Mar 2024 10:11:43 -0500 Subject: [PATCH 02/18] Move form element definitions --- apps/doj-demo/astro.config.mjs | 2 +- packages/forms/src/config.ts | 27 --------------------- packages/forms/src/element.ts | 27 +++++++++++++++++---- packages/forms/src/elements/fieldset.ts | 8 ++++-- packages/forms/src/elements/form-summary.ts | 5 ++-- packages/forms/src/elements/index.ts | 2 +- packages/forms/src/elements/input.ts | 3 +-- packages/forms/src/elements/paragraph.ts | 3 +-- packages/forms/src/elements/sequence.ts | 9 ++++--- 9 files changed, 40 insertions(+), 46 deletions(-) diff --git a/apps/doj-demo/astro.config.mjs b/apps/doj-demo/astro.config.mjs index 8562221c..5dc1c0bf 100644 --- a/apps/doj-demo/astro.config.mjs +++ b/apps/doj-demo/astro.config.mjs @@ -5,7 +5,7 @@ import react from '@astrojs/react'; // https://astro.build/config export default defineConfig({ output: 'server', - trailingSlash: 'never', + trailingSlash: 'always', base: addTrailingSlash(process.env.BASEURL || ''), adapter: node({ mode: 'standalone', diff --git a/packages/forms/src/config.ts b/packages/forms/src/config.ts index 0790dede..bb2c8050 100644 --- a/packages/forms/src/config.ts +++ b/packages/forms/src/config.ts @@ -1,28 +1 @@ -import { - type FormElement, - type FormElementId, - type ParseFormElementData, - type ParseFormElementConfigData, -} from './element'; -import { type CreatePrompt } from './pattern'; - export { defaultFormConfig } from './elements'; - -export type FormElementConfig = { - acceptsInput: boolean; - initial: ThisFormElement['data']; - parseData: ParseFormElementData; - parseConfigData: ParseFormElementConfigData; - getChildren: ( - element: ThisFormElement, - elements: Record - ) => FormElement[]; - createPrompt: CreatePrompt; -}; -export type FormConfig = { - elements: Record>; -}; - -export type ConfigElements = ReturnType< - Config['elements'][keyof Config['elements']]['parseData'] ->; diff --git a/packages/forms/src/element.ts b/packages/forms/src/element.ts index 8a5d16bd..d3b179a0 100644 --- a/packages/forms/src/element.ts +++ b/packages/forms/src/element.ts @@ -1,9 +1,7 @@ import { type Result } from '@atj/common'; -import { - type FormElementConfig, - type FormConfig, - type FormDefinition, -} from '..'; +import { type FormDefinition } from '..'; + +import { type CreatePrompt } from './pattern'; export type FormElement = { type: string; @@ -36,6 +34,25 @@ export const getFormElement: GetFormElement = (form, elementId) => { return form.elements[elementId]; }; +export type FormElementConfig = { + acceptsInput: boolean; + initial: ThisFormElement['data']; + parseData: ParseFormElementData; + parseConfigData: ParseFormElementConfigData; + getChildren: ( + element: ThisFormElement, + elements: Record + ) => FormElement[]; + createPrompt: CreatePrompt; +}; +export type FormConfig = { + elements: Record>; +}; + +export type ConfigElements = ReturnType< + Config['elements'][keyof Config['elements']]['parseData'] +>; + export const getFormElementMap = (elements: FormElement[]) => { return Object.fromEntries( elements.map(element => { diff --git a/packages/forms/src/elements/fieldset.ts b/packages/forms/src/elements/fieldset.ts index 8431f78e..e5c9746e 100644 --- a/packages/forms/src/elements/fieldset.ts +++ b/packages/forms/src/elements/fieldset.ts @@ -1,7 +1,11 @@ import * as z from 'zod'; -import { type FormElementConfig, getFormElement } from '..'; -import { type FormElement, type FormElementId } from '../element'; +import { + type FormElement, + type FormElementConfig, + type FormElementId, + getFormElement, +} from '../element'; import { type FieldsetPattern, type Pattern, diff --git a/packages/forms/src/elements/form-summary.ts b/packages/forms/src/elements/form-summary.ts index 31262b32..f770a784 100644 --- a/packages/forms/src/elements/form-summary.ts +++ b/packages/forms/src/elements/form-summary.ts @@ -1,8 +1,7 @@ import * as z from 'zod'; -import { type FormElementConfig } from '..'; -import { type FormElement } from '../element'; -import { FormSummaryPattern, type Pattern } from '../pattern'; +import { type FormElement, type FormElementConfig } from '../element'; +import { type FormSummaryPattern, type Pattern } from '../pattern'; import { safeZodParse } from '../util/zod'; const configSchema = z.object({ diff --git a/packages/forms/src/elements/index.ts b/packages/forms/src/elements/index.ts index bf3327a6..cf3e03c2 100644 --- a/packages/forms/src/elements/index.ts +++ b/packages/forms/src/elements/index.ts @@ -1,4 +1,4 @@ -import { type FormConfig } from '../config'; +import { FormConfig } from '../element'; import { fieldsetConfig } from './fieldset'; import { inputConfig } from './input'; import { paragraphConfig } from './paragraph'; diff --git a/packages/forms/src/elements/input.ts b/packages/forms/src/elements/input.ts index 244913b2..57ff1088 100644 --- a/packages/forms/src/elements/input.ts +++ b/packages/forms/src/elements/input.ts @@ -1,7 +1,6 @@ import * as z from 'zod'; -import { type FormElementConfig } from '..'; -import { type FormElement, validateElement } from '../element'; +import { type FormElement, type FormElementConfig } from '../element'; import { type Pattern, type TextInputPattern } from '../pattern'; import { getFormSessionValue } from '../session'; import { safeZodParse } from '../util/zod'; diff --git a/packages/forms/src/elements/paragraph.ts b/packages/forms/src/elements/paragraph.ts index ca7f8208..48e22664 100644 --- a/packages/forms/src/elements/paragraph.ts +++ b/packages/forms/src/elements/paragraph.ts @@ -1,7 +1,6 @@ import * as z from 'zod'; -import { type FormElementConfig } from '..'; -import { type FormElement } from '../element'; +import { type FormElement, type FormElementConfig } from '../element'; import { type Pattern, type ParagraphPattern } from '../pattern'; import { safeZodParse } from '../util/zod'; diff --git a/packages/forms/src/elements/sequence.ts b/packages/forms/src/elements/sequence.ts index b678bb98..ce5fb9ad 100644 --- a/packages/forms/src/elements/sequence.ts +++ b/packages/forms/src/elements/sequence.ts @@ -1,10 +1,13 @@ import * as z from 'zod'; -import { type FormElementConfig } from '..'; -import { type FormElement, type FormElementId } from '../element'; +import { + type FormElement, + type FormElementConfig, + type FormElementId, + getFormElement, +} from '../element'; import { createPromptForElement } from '../pattern'; import { safeZodParse } from '../util/zod'; -import { getFormElement } from '../..'; export type SequenceElement = FormElement<{ elements: FormElementId[]; From 0c37f26c502160ddb035678f7f7240a2e3d2326e Mon Sep 17 00:00:00 2001 From: Daniel Naab Date: Tue, 26 Mar 2024 12:17:21 -0500 Subject: [PATCH 03/18] Rename UI component types --- apps/doj-demo/src/components/AppFormManager.tsx | 4 ++-- .../spotlight/src/components/AppFormManager.tsx | 4 ++-- .../design/src/FormManager/FormEdit/types.ts | 17 ++++++++--------- .../design/src/config/edit/FormSummaryEdit.tsx | 6 ++---- .../design/src/config/edit/InputElementEdit.tsx | 6 ++---- .../src/config/edit/ParagraphElementEdit.tsx | 4 ++-- .../src/config/edit/SequenceElementEdit.tsx | 4 ++-- .../config/edit/SubmissionConfirmationEdit.tsx | 6 ++---- packages/design/src/config/edit/index.ts | 4 ++-- packages/design/src/test-form.ts | 4 ++-- 10 files changed, 26 insertions(+), 33 deletions(-) diff --git a/apps/doj-demo/src/components/AppFormManager.tsx b/apps/doj-demo/src/components/AppFormManager.tsx index 394120a1..cfffb154 100644 --- a/apps/doj-demo/src/components/AppFormManager.tsx +++ b/apps/doj-demo/src/components/AppFormManager.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { FormManager, defaultFormElementComponents, - defaultFormElementEditComponents, + defaultPatternEditComponents, } from '@atj/design'; import { getAppContext } from '../context'; @@ -15,7 +15,7 @@ export default function () { context={{ config: ctx.formConfig, components: defaultFormElementComponents, - editComponents: defaultFormElementEditComponents, + editComponents: defaultPatternEditComponents, uswdsRoot: ctx.uswdsRoot, }} formService={ctx.formService} diff --git a/apps/spotlight/src/components/AppFormManager.tsx b/apps/spotlight/src/components/AppFormManager.tsx index 394120a1..cfffb154 100644 --- a/apps/spotlight/src/components/AppFormManager.tsx +++ b/apps/spotlight/src/components/AppFormManager.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { FormManager, defaultFormElementComponents, - defaultFormElementEditComponents, + defaultPatternEditComponents, } from '@atj/design'; import { getAppContext } from '../context'; @@ -15,7 +15,7 @@ export default function () { context={{ config: ctx.formConfig, components: defaultFormElementComponents, - editComponents: defaultFormElementEditComponents, + editComponents: defaultPatternEditComponents, uswdsRoot: ctx.uswdsRoot, }} formService={ctx.formService} diff --git a/packages/design/src/FormManager/FormEdit/types.ts b/packages/design/src/FormManager/FormEdit/types.ts index 04d13069..9417015b 100644 --- a/packages/design/src/FormManager/FormEdit/types.ts +++ b/packages/design/src/FormManager/FormEdit/types.ts @@ -9,16 +9,15 @@ import { type ComponentForPattern } from '../../Form'; export type FormEditUIContext = { config: FormConfig; components: ComponentForPattern; - editComponents: EditComponentForFormElement; + editComponents: EditComponentForPattern; uswdsRoot: `${string}/`; }; -export type FormElementEditComponent = - React.ComponentType<{ - context: FormEditUIContext; - form: FormDefinition; - element: T; - }>; +export type PatternEditComponent = React.ComponentType<{ + context: FormEditUIContext; + form: FormDefinition; + element: T; +}>; -export type EditComponentForFormElement = - Record>; +export type EditComponentForPattern = + Record>; diff --git a/packages/design/src/config/edit/FormSummaryEdit.tsx b/packages/design/src/config/edit/FormSummaryEdit.tsx index e9e783a5..25ba1c44 100644 --- a/packages/design/src/config/edit/FormSummaryEdit.tsx +++ b/packages/design/src/config/edit/FormSummaryEdit.tsx @@ -2,11 +2,9 @@ import React from 'react'; import { useFormContext } from 'react-hook-form'; import { type FormSummary } from '@atj/forms/src/elements/form-summary'; -import { FormElementEditComponent } from '../../FormManager/FormEdit/types'; +import { PatternEditComponent } from '../../FormManager/FormEdit/types'; -const FormSummaryEdit: FormElementEditComponent = ({ - element, -}) => { +const FormSummaryEdit: PatternEditComponent = ({ element }) => { const { register } = useFormContext(); return (
diff --git a/packages/design/src/config/edit/InputElementEdit.tsx b/packages/design/src/config/edit/InputElementEdit.tsx index 1416d190..6f4e141f 100644 --- a/packages/design/src/config/edit/InputElementEdit.tsx +++ b/packages/design/src/config/edit/InputElementEdit.tsx @@ -2,11 +2,9 @@ import React from 'react'; import { useFormContext } from 'react-hook-form'; import { type InputElement } from '@atj/forms/src/elements/input'; -import { FormElementEditComponent } from '../../FormManager/FormEdit/types'; +import { PatternEditComponent } from '../../FormManager/FormEdit/types'; -const InputElementEdit: FormElementEditComponent = ({ - element, -}) => { +const InputElementEdit: PatternEditComponent = ({ element }) => { const { register } = useFormContext(); return (
diff --git a/packages/design/src/config/edit/ParagraphElementEdit.tsx b/packages/design/src/config/edit/ParagraphElementEdit.tsx index 7952ac51..843a32d6 100644 --- a/packages/design/src/config/edit/ParagraphElementEdit.tsx +++ b/packages/design/src/config/edit/ParagraphElementEdit.tsx @@ -3,9 +3,9 @@ import { useFormContext } from 'react-hook-form'; import { type ParagraphElement } from '@atj/forms/src/elements/paragraph'; -import { type FormElementEditComponent } from '../../FormManager/FormEdit/types'; +import { type PatternEditComponent } from '../../FormManager/FormEdit/types'; -const ParagraphElementEdit: FormElementEditComponent = ({ +const ParagraphElementEdit: PatternEditComponent = ({ element, }) => { const { register } = useFormContext(); diff --git a/packages/design/src/config/edit/SequenceElementEdit.tsx b/packages/design/src/config/edit/SequenceElementEdit.tsx index 9b1c708d..0d342e5a 100644 --- a/packages/design/src/config/edit/SequenceElementEdit.tsx +++ b/packages/design/src/config/edit/SequenceElementEdit.tsx @@ -21,7 +21,7 @@ import { type FormDefinition, type FormElement } from '@atj/forms'; import { type SequenceElement } from '@atj/forms/src/elements/sequence'; import { type FormEditUIContext, - type FormElementEditComponent, + type PatternEditComponent, } from '../../FormManager/FormEdit/types'; interface ItemProps { @@ -67,7 +67,7 @@ const SortableItem = ({ id, form, element, context }: ItemProps) => { ); }; -const SequenceElementEdit: FormElementEditComponent = ({ +const SequenceElementEdit: PatternEditComponent = ({ context, form, element, diff --git a/packages/design/src/config/edit/SubmissionConfirmationEdit.tsx b/packages/design/src/config/edit/SubmissionConfirmationEdit.tsx index 8b6c6517..e6ba7212 100644 --- a/packages/design/src/config/edit/SubmissionConfirmationEdit.tsx +++ b/packages/design/src/config/edit/SubmissionConfirmationEdit.tsx @@ -2,11 +2,9 @@ import React from 'react'; import { useFormContext } from 'react-hook-form'; import { type InputElement } from '@atj/forms/src/elements/input'; -import { type FormElementEditComponent } from '../../FormManager/FormEdit/types'; +import { type PatternEditComponent } from '../../FormManager/FormEdit/types'; -const InputElementEdit: FormElementEditComponent = ({ - element, -}) => { +const InputElementEdit: PatternEditComponent = ({ element }) => { const { register } = useFormContext(); return (
diff --git a/packages/design/src/config/edit/index.ts b/packages/design/src/config/edit/index.ts index cf4e2dd9..bbe5f5c5 100644 --- a/packages/design/src/config/edit/index.ts +++ b/packages/design/src/config/edit/index.ts @@ -1,9 +1,9 @@ import InputElementEdit from './InputElementEdit'; import SequenceElementEdit from './SequenceElementEdit'; import SubmissionConfirmationEdit from './SubmissionConfirmationEdit'; -import { type EditComponentForFormElement } from '../../FormManager/FormEdit/types'; +import { type EditComponentForPattern } from '../../FormManager/FormEdit/types'; -export const defaultFormElementEditComponents: EditComponentForFormElement = { +export const defaultPatternEditComponents: EditComponentForPattern = { input: InputElementEdit, sequence: SequenceElementEdit, 'submission-confirmation': SubmissionConfirmationEdit, diff --git a/packages/design/src/test-form.ts b/packages/design/src/test-form.ts index 4caaf04d..cd66d810 100644 --- a/packages/design/src/test-form.ts +++ b/packages/design/src/test-form.ts @@ -2,7 +2,7 @@ import { createForm, createFormSession, defaultFormConfig } from '@atj/forms'; import { defaultFormElementComponents, - defaultFormElementEditComponents, + defaultPatternEditComponents, } from './config'; import { FormUIContext } from 'Form'; import { type FormEditUIContext } from './FormManager/FormEdit/types'; @@ -74,7 +74,7 @@ export const createTestFormEditContext = (): FormEditUIContext => { return { config: defaultFormConfig, components: defaultFormElementComponents, - editComponents: defaultFormElementEditComponents, + editComponents: defaultPatternEditComponents, uswdsRoot: `/static/uswds/`, }; }; From d1023b9843df00a4b2e1d9322442976382aef28c Mon Sep 17 00:00:00 2001 From: Daniel Naab Date: Tue, 26 Mar 2024 12:44:54 -0500 Subject: [PATCH 04/18] Rename Pattern -> PatternProps --- packages/design/src/Form/index.tsx | 20 +++++++++---------- .../src/FormManager/FormEdit/Preview.tsx | 2 +- .../design/src/FormManager/FormEdit/store.tsx | 6 +++--- .../design/src/config/view/Fieldset/index.tsx | 4 ++-- .../src/config/view/FormSummary/index.tsx | 4 ++-- .../src/config/view/Paragraph/index.tsx | 4 ++-- .../design/src/config/view/Sequence/index.tsx | 4 ++-- .../view/SubmissionConfirmation/index.tsx | 4 ++-- .../view/TextInput/TestInput.stories.tsx | 6 +++--- .../src/config/view/TextInput/index.tsx | 4 ++-- packages/forms/src/elements/fieldset.ts | 4 ++-- packages/forms/src/elements/form-summary.ts | 2 +- packages/forms/src/elements/input.ts | 4 ++-- packages/forms/src/elements/paragraph.ts | 4 ++-- packages/forms/src/pattern.ts | 8 ++++---- 15 files changed, 40 insertions(+), 40 deletions(-) diff --git a/packages/design/src/Form/index.tsx b/packages/design/src/Form/index.tsx index 3cdd0bca..d48e59df 100644 --- a/packages/design/src/Form/index.tsx +++ b/packages/design/src/Form/index.tsx @@ -7,7 +7,7 @@ import { createPrompt, type FormConfig, type FormSession, - type Pattern, + type PatternProps, type Prompt, type PromptPart, } from '@atj/forms'; @@ -20,16 +20,16 @@ export type FormUIContext = { uswdsRoot: `${string}/`; }; -export type ComponentForPattern> = Record< - string, - FormElementComponent ->; +export type ComponentForPattern< + T extends PatternProps = PatternProps, +> = Record>; -export type FormElementComponent> = - React.ComponentType<{ - pattern: T; - children?: React.ReactNode; - }>; +export type FormElementComponent< + T extends PatternProps = PatternProps, +> = React.ComponentType<{ + pattern: T; + children?: React.ReactNode; +}>; const usePrompt = ( initialPrompt: Prompt, diff --git a/packages/design/src/FormManager/FormEdit/Preview.tsx b/packages/design/src/FormManager/FormEdit/Preview.tsx index 3ee3c8da..0993aca9 100644 --- a/packages/design/src/FormManager/FormEdit/Preview.tsx +++ b/packages/design/src/FormManager/FormEdit/Preview.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { type Pattern, createFormSession } from '@atj/forms'; +import { type PatternProps, createFormSession } from '@atj/forms'; import Form, { type ComponentForPattern, diff --git a/packages/design/src/FormManager/FormEdit/store.tsx b/packages/design/src/FormManager/FormEdit/store.tsx index 3c1f5724..7869fc83 100644 --- a/packages/design/src/FormManager/FormEdit/store.tsx +++ b/packages/design/src/FormManager/FormEdit/store.tsx @@ -5,7 +5,7 @@ import { createContext } from 'zustand-utils'; import { type FormDefinition, type FormElementMap, - type Pattern, + type PatternProps, getFormElement, FormBuilder, FormElement, @@ -33,7 +33,7 @@ type FormEditState = { form: FormDefinition; selectedElement?: FormElement; - handleEditClick: (pattern: Pattern) => void; + handleEditClick: (pattern: PatternProps) => void; setSelectedElement: (element?: FormElement) => void; updateSelectedFormElement: (formData: FormElementMap) => void; }; @@ -48,7 +48,7 @@ const createFormEditStore = ({ create((set, get) => ({ context, form, - handleEditClick: (pattern: Pattern) => { + handleEditClick: (pattern: PatternProps) => { const state = get(); if (state.selectedElement?.id === pattern._elementId) { set({ selectedElement: undefined }); diff --git a/packages/design/src/config/view/Fieldset/index.tsx b/packages/design/src/config/view/Fieldset/index.tsx index d2b23dd5..10e32c83 100644 --- a/packages/design/src/config/view/Fieldset/index.tsx +++ b/packages/design/src/config/view/Fieldset/index.tsx @@ -1,10 +1,10 @@ import React from 'react'; -import { type FieldsetPattern, type Pattern } from '@atj/forms'; +import { type FieldsetPattern, type PatternProps } from '@atj/forms'; import { type FormElementComponent } from '../../../Form'; -const FormSummary: FormElementComponent> = ({ +const FormSummary: FormElementComponent> = ({ pattern, children, }) => { diff --git a/packages/design/src/config/view/FormSummary/index.tsx b/packages/design/src/config/view/FormSummary/index.tsx index 95a7002e..648f1dbc 100644 --- a/packages/design/src/config/view/FormSummary/index.tsx +++ b/packages/design/src/config/view/FormSummary/index.tsx @@ -1,9 +1,9 @@ import React from 'react'; -import { Pattern, type FormSummaryPattern } from '@atj/forms'; +import { type PatternProps, type FormSummaryPattern } from '@atj/forms'; import { type FormElementComponent } from '../../../Form'; -const FormSummary: FormElementComponent> = ({ +const FormSummary: FormElementComponent> = ({ pattern, }) => { return ( diff --git a/packages/design/src/config/view/Paragraph/index.tsx b/packages/design/src/config/view/Paragraph/index.tsx index bf9428a0..a107eca8 100644 --- a/packages/design/src/config/view/Paragraph/index.tsx +++ b/packages/design/src/config/view/Paragraph/index.tsx @@ -1,10 +1,10 @@ import React from 'react'; -import { type ParagraphPattern, type Pattern } from '@atj/forms'; +import { type ParagraphPattern, type PatternProps } from '@atj/forms'; import { type FormElementComponent } from '../../../Form'; -const FormSummary: FormElementComponent> = ({ +const FormSummary: FormElementComponent> = ({ pattern, }) => { if (pattern.style === 'heading') { diff --git a/packages/design/src/config/view/Sequence/index.tsx b/packages/design/src/config/view/Sequence/index.tsx index 92e92d75..52c4cb94 100644 --- a/packages/design/src/config/view/Sequence/index.tsx +++ b/packages/design/src/config/view/Sequence/index.tsx @@ -1,11 +1,11 @@ import React from 'react'; -import { type Pattern } from '@atj/forms'; +import { type PatternProps } from '@atj/forms'; import { SequenceElement } from '@atj/forms/src/config/elements/sequence'; import { FormElementComponent } from '../../../Form'; -const Sequence: FormElementComponent> = ({ +const Sequence: FormElementComponent> = ({ children, }) => { return <>{children}; diff --git a/packages/design/src/config/view/SubmissionConfirmation/index.tsx b/packages/design/src/config/view/SubmissionConfirmation/index.tsx index b9cd3294..51b273b5 100644 --- a/packages/design/src/config/view/SubmissionConfirmation/index.tsx +++ b/packages/design/src/config/view/SubmissionConfirmation/index.tsx @@ -1,10 +1,10 @@ import React from 'react'; -import { Pattern, type SubmissionConfirmationPattern } from '@atj/forms'; +import { PatternProps, type SubmissionConfirmationPattern } from '@atj/forms'; import { FormElementComponent } from '../../../Form'; const SubmissionConfirmation: FormElementComponent< - Pattern + PatternProps > = ({ pattern }) => { return ( <> diff --git a/packages/design/src/config/view/TextInput/TestInput.stories.tsx b/packages/design/src/config/view/TextInput/TestInput.stories.tsx index dd1b139b..d51c2b9e 100644 --- a/packages/design/src/config/view/TextInput/TestInput.stories.tsx +++ b/packages/design/src/config/view/TextInput/TestInput.stories.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import type { Meta, StoryObj } from '@storybook/react'; -import { type Pattern, type TextInputPattern } from '@atj/forms'; +import { type PatternProps, type TextInputPattern } from '@atj/forms'; import TextInput from '.'; export default { @@ -33,7 +33,7 @@ export const Required = { value: '', label: 'Please enter your first name.', required: true, - } as Pattern, + } as PatternProps, }, } satisfies StoryObj; @@ -46,6 +46,6 @@ export const NotRequired = { value: '', label: 'Please enter your first name.', required: false, - } as Pattern, + } as PatternProps, }, } satisfies StoryObj; diff --git a/packages/design/src/config/view/TextInput/index.tsx b/packages/design/src/config/view/TextInput/index.tsx index 1b618d0a..5773d9c9 100644 --- a/packages/design/src/config/view/TextInput/index.tsx +++ b/packages/design/src/config/view/TextInput/index.tsx @@ -2,10 +2,10 @@ import classNames from 'classnames'; import React from 'react'; import { useFormContext } from 'react-hook-form'; -import { Pattern, type TextInputPattern } from '@atj/forms'; +import { PatternProps, type TextInputPattern } from '@atj/forms'; import { type FormElementComponent } from '../../../Form'; -const TextInput: FormElementComponent> = ({ +const TextInput: FormElementComponent> = ({ pattern, }) => { const { register } = useFormContext(); diff --git a/packages/forms/src/elements/fieldset.ts b/packages/forms/src/elements/fieldset.ts index e5c9746e..2f7a1e48 100644 --- a/packages/forms/src/elements/fieldset.ts +++ b/packages/forms/src/elements/fieldset.ts @@ -8,7 +8,7 @@ import { } from '../element'; import { type FieldsetPattern, - type Pattern, + type PatternProps, createPromptForElement, } from '../pattern'; import { safeZodParse } from '../util/zod'; @@ -50,7 +50,7 @@ export const fieldsetConfig: FormElementConfig = { _elementId: element.id, type: 'fieldset', legend: element.data.legend, - } satisfies Pattern, + } satisfies PatternProps, children, }; }, diff --git a/packages/forms/src/elements/form-summary.ts b/packages/forms/src/elements/form-summary.ts index f770a784..cfdbad85 100644 --- a/packages/forms/src/elements/form-summary.ts +++ b/packages/forms/src/elements/form-summary.ts @@ -30,7 +30,7 @@ export const formSummaryConfig: FormElementConfig = { type: 'form-summary', title: element.data.title, description: element.data.description, - } as Pattern, + } as PatternProps, children: [], }; }, diff --git a/packages/forms/src/elements/input.ts b/packages/forms/src/elements/input.ts index 57ff1088..d5ed25fb 100644 --- a/packages/forms/src/elements/input.ts +++ b/packages/forms/src/elements/input.ts @@ -1,7 +1,7 @@ import * as z from 'zod'; import { type FormElement, type FormElementConfig } from '../element'; -import { type Pattern, type TextInputPattern } from '../pattern'; +import { type PatternProps, type TextInputPattern } from '../pattern'; import { getFormSessionValue } from '../session'; import { safeZodParse } from '../util/zod'; @@ -47,7 +47,7 @@ export const inputConfig: FormElementConfig = { label: element.data.label, required: element.data.required, ...extraAttributes, - } as Pattern, + } as PatternProps, children: [], }; }, diff --git a/packages/forms/src/elements/paragraph.ts b/packages/forms/src/elements/paragraph.ts index 48e22664..bc119e0e 100644 --- a/packages/forms/src/elements/paragraph.ts +++ b/packages/forms/src/elements/paragraph.ts @@ -1,7 +1,7 @@ import * as z from 'zod'; import { type FormElement, type FormElementConfig } from '../element'; -import { type Pattern, type ParagraphPattern } from '../pattern'; +import { type PatternProps, type ParagraphPattern } from '../pattern'; import { safeZodParse } from '../util/zod'; const configSchema = z.object({ @@ -31,7 +31,7 @@ export const paragraphConfig: FormElementConfig = { type: 'paragraph' as const, text: element.data.text, style: element.data.style, - } as Pattern, + } as PatternProps, children: [], }; }, diff --git a/packages/forms/src/pattern.ts b/packages/forms/src/pattern.ts index 7657ee57..f0754125 100644 --- a/packages/forms/src/pattern.ts +++ b/packages/forms/src/pattern.ts @@ -45,7 +45,7 @@ export type FieldsetPattern = { legend: string; }; -export type Pattern = { +export type PatternProps = { _elementId: FormElementId; _children: PromptPart[]; type: string; @@ -58,7 +58,7 @@ export type SubmitAction = { export type PromptAction = SubmitAction; export type PromptPart = { - pattern: Pattern; + pattern: PatternProps; children: PromptPart[]; }; @@ -94,7 +94,7 @@ export const createPrompt = ( value: value, }; }), - } as Pattern, + } as PatternProps, children: [], }, ], @@ -107,7 +107,7 @@ export const createPrompt = ( type: 'form-summary', title: session.form.summary.title, description: session.form.summary.description, - } as Pattern, + } as PatternProps, children: [], }, ]; From 92617627cec29c5f64e6bdd31c5fc5a6fc5e2d2c Mon Sep 17 00:00:00 2001 From: Daniel Naab Date: Tue, 26 Mar 2024 13:05:15 -0500 Subject: [PATCH 05/18] Rename FormElement -> Pattern --- .../src/components/AppFormManager.tsx | 4 +- .../doj-demo/src/components/AppFormRouter.tsx | 4 +- .../src/components/AppFormManager.tsx | 4 +- .../src/components/AppFormRouter.tsx | 4 +- packages/design/src/Form/index.tsx | 13 ++- .../FormManager/FormEdit/DraggableList.tsx | 16 ++-- .../{FormElementEdit.tsx => PatternEdit.tsx} | 12 +-- .../src/FormManager/FormEdit/Preview.tsx | 12 +-- .../design/src/FormManager/FormEdit/index.tsx | 4 +- .../design/src/FormManager/FormEdit/store.tsx | 18 ++-- .../design/src/FormManager/FormEdit/types.ts | 14 ++-- .../src/config/edit/SequenceElementEdit.tsx | 6 +- .../design/src/config/view/Fieldset/index.tsx | 4 +- .../src/config/view/FormSummary/index.tsx | 4 +- .../src/config/view/Paragraph/index.tsx | 4 +- .../design/src/config/view/Sequence/index.tsx | 4 +- .../view/SubmissionConfirmation/index.tsx | 4 +- .../src/config/view/TextInput/index.tsx | 4 +- packages/design/src/config/view/index.tsx | 2 +- packages/design/src/test-form.ts | 14 ++-- packages/forms/src/builder/index.ts | 14 ++-- packages/forms/src/documents/document.ts | 16 ++-- packages/forms/src/documents/pdf/mock-api.ts | 22 ++--- packages/forms/src/documents/suggestions.ts | 2 +- packages/forms/src/element.ts | 73 ++++++++-------- packages/forms/src/elements/fieldset.ts | 16 ++-- packages/forms/src/elements/form-summary.ts | 6 +- packages/forms/src/elements/input.ts | 6 +- packages/forms/src/elements/paragraph.ts | 6 +- packages/forms/src/elements/sequence.ts | 16 ++-- packages/forms/src/index.ts | 84 +++++++++---------- packages/forms/src/pattern.ts | 22 ++--- packages/forms/src/response.ts | 14 ++-- packages/forms/src/session.ts | 34 ++++---- packages/forms/src/util/zod.ts | 4 +- packages/forms/tests/two-field-form.test.ts | 2 +- 36 files changed, 235 insertions(+), 253 deletions(-) rename packages/design/src/FormManager/FormEdit/{FormElementEdit.tsx => PatternEdit.tsx} (88%) diff --git a/apps/doj-demo/src/components/AppFormManager.tsx b/apps/doj-demo/src/components/AppFormManager.tsx index cfffb154..32ddbb86 100644 --- a/apps/doj-demo/src/components/AppFormManager.tsx +++ b/apps/doj-demo/src/components/AppFormManager.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { FormManager, - defaultFormElementComponents, + defaultPatternComponents, defaultPatternEditComponents, } from '@atj/design'; @@ -14,7 +14,7 @@ export default function () { , -> = Record>; +> = Record>; -export type FormElementComponent< - T extends PatternProps = PatternProps, -> = React.ComponentType<{ - pattern: T; - children?: React.ReactNode; -}>; +export type PatternComponent> = + React.ComponentType<{ + pattern: T; + children?: React.ReactNode; + }>; const usePrompt = ( initialPrompt: Prompt, diff --git a/packages/design/src/FormManager/FormEdit/DraggableList.tsx b/packages/design/src/FormManager/FormEdit/DraggableList.tsx index 690428e0..d5f7931e 100644 --- a/packages/design/src/FormManager/FormEdit/DraggableList.tsx +++ b/packages/design/src/FormManager/FormEdit/DraggableList.tsx @@ -17,10 +17,10 @@ import { import { CSS } from '@dnd-kit/utilities'; import { - getFormElement, + getPattern, type FormDefinition, - type FormElement, - FormElementId, + type Pattern, + PatternId, } from '@atj/forms'; import { SequenceElement } from '@atj/forms/src/elements/sequence'; @@ -59,9 +59,9 @@ const SortableItem = ({ }; type DraggableListProps = React.PropsWithChildren<{ - element: FormElement; + element: Pattern; form: FormDefinition; - setSelectedElement: (element: FormElement) => void; + setSelectedElement: (element: Pattern) => void; }>; export const DraggableList: React.FC = ({ element, @@ -69,9 +69,9 @@ export const DraggableList: React.FC = ({ setSelectedElement, children, }) => { - const [elements, setElements] = useState( - element.data.elements.map((elementId: FormElementId) => { - return getFormElement(form, elementId); + const [elements, setElements] = useState( + element.data.elements.map((elementId: PatternId) => { + return getPattern(form, elementId); }) ); const sensors = useSensors( diff --git a/packages/design/src/FormManager/FormEdit/FormElementEdit.tsx b/packages/design/src/FormManager/FormEdit/PatternEdit.tsx similarity index 88% rename from packages/design/src/FormManager/FormEdit/FormElementEdit.tsx rename to packages/design/src/FormManager/FormEdit/PatternEdit.tsx index a5015519..9046e959 100644 --- a/packages/design/src/FormManager/FormEdit/FormElementEdit.tsx +++ b/packages/design/src/FormManager/FormEdit/PatternEdit.tsx @@ -1,21 +1,21 @@ import React, { useEffect, useRef } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; -import { type FormElementMap } from '@atj/forms'; +import { type PatternMap } from '@atj/forms'; import { useFormEditStore } from './store'; -export const FormElementEdit = () => { +export const PatternEdit = () => { const context = useFormEditStore(state => state.context); const form = useFormEditStore(state => state.form); const selectedElement = useFormEditStore(state => state.selectedElement); - const { setSelectedElement, updateSelectedFormElement } = useFormEditStore( + const { setSelectedElement, updateSelectedPattern } = useFormEditStore( state => ({ setSelectedElement: state.setSelectedElement, - updateSelectedFormElement: state.updateSelectedFormElement, + updateSelectedPattern: state.updateSelectedPattern, }) ); - const methods = useForm({ + const methods = useForm({ defaultValues: selectedElement ? { [selectedElement.id]: selectedElement, @@ -69,7 +69,7 @@ export const FormElementEdit = () => {
{ - updateSelectedFormElement(formData); + updateSelectedPattern(formData); })} >

Editing "{selectedElement.data.label}"...

diff --git a/packages/design/src/FormManager/FormEdit/Preview.tsx b/packages/design/src/FormManager/FormEdit/Preview.tsx index 0993aca9..045568be 100644 --- a/packages/design/src/FormManager/FormEdit/Preview.tsx +++ b/packages/design/src/FormManager/FormEdit/Preview.tsx @@ -4,7 +4,7 @@ import { type PatternProps, createFormSession } from '@atj/forms'; import Form, { type ComponentForPattern, - type FormElementComponent, + type PatternComponent, type FormUIContext, } from '../../Form'; import { useFormEditStore } from './store'; @@ -64,14 +64,14 @@ const createPreviewComponents = ( /* const createSequencePatternPreviewComponent = ( - Component: FormElementComponent, + Component: PatternComponent, previewComponents: ComponentForPattern ) => { - const PatternPreviewSequenceComponent: FormElementComponent = ({ + const PatternPreviewSequenceComponent: PatternComponent = ({ pattern, }) => { const { form, setSelectedElement } = usePreviewContext(); - const element = getFormElement(form, pattern._elementId); + const element = getPattern(form, pattern._elementId); const Component = previewComponents[pattern.type]; return ( { - const PatternPreviewComponent: FormElementComponent = ({ + const PatternPreviewComponent: PatternComponent = ({ pattern, }: { pattern: Pattern; diff --git a/packages/design/src/FormManager/FormEdit/index.tsx b/packages/design/src/FormManager/FormEdit/index.tsx index 670b76bd..3fa00744 100644 --- a/packages/design/src/FormManager/FormEdit/index.tsx +++ b/packages/design/src/FormManager/FormEdit/index.tsx @@ -3,7 +3,7 @@ import React, { useEffect } from 'react'; import { FormDefinition } from '@atj/forms'; import { type FormService } from '@atj/form-service'; -import { FormElementEdit } from './FormElementEdit'; +import { PatternEdit } from './PatternEdit'; import { PreviewForm } from './Preview'; import { FormEditProvider, useFormEditStore } from './store'; import { type FormEditUIContext } from './types'; @@ -51,7 +51,7 @@ const EditForm = ({
- +
diff --git a/packages/design/src/FormManager/FormEdit/store.tsx b/packages/design/src/FormManager/FormEdit/store.tsx index 7869fc83..ae5973d7 100644 --- a/packages/design/src/FormManager/FormEdit/store.tsx +++ b/packages/design/src/FormManager/FormEdit/store.tsx @@ -4,11 +4,11 @@ import { createContext } from 'zustand-utils'; import { type FormDefinition, - type FormElementMap, + type PatternMap, type PatternProps, - getFormElement, + getPattern, FormBuilder, - FormElement, + Pattern, } from '@atj/forms'; import { type FormEditUIContext } from './types'; @@ -31,11 +31,11 @@ export const FormEditProvider = (props: { type FormEditState = { context: FormEditUIContext; form: FormDefinition; - selectedElement?: FormElement; + selectedElement?: Pattern; handleEditClick: (pattern: PatternProps) => void; - setSelectedElement: (element?: FormElement) => void; - updateSelectedFormElement: (formData: FormElementMap) => void; + setSelectedElement: (element?: Pattern) => void; + updateSelectedPattern: (formData: PatternMap) => void; }; const createFormEditStore = ({ @@ -53,19 +53,19 @@ const createFormEditStore = ({ if (state.selectedElement?.id === pattern._elementId) { set({ selectedElement: undefined }); } else { - const elementToSet = getFormElement(state.form, pattern._elementId); + const elementToSet = getPattern(state.form, pattern._elementId); set({ selectedElement: elementToSet }); } }, setSelectedElement: selectedElement => set({ selectedElement }), - updateSelectedFormElement: (formData: FormElementMap) => { + updateSelectedPattern: (formData: PatternMap) => { const state = get(); if (state.selectedElement === undefined) { console.warn('No selected element'); return; } const builder = new FormBuilder(state.form); - const success = builder.updateFormElement( + const success = builder.updatePattern( state.context.config, state.selectedElement, formData diff --git a/packages/design/src/FormManager/FormEdit/types.ts b/packages/design/src/FormManager/FormEdit/types.ts index 9417015b..d9ae1392 100644 --- a/packages/design/src/FormManager/FormEdit/types.ts +++ b/packages/design/src/FormManager/FormEdit/types.ts @@ -1,8 +1,4 @@ -import { - type FormConfig, - type FormDefinition, - type FormElement, -} from '@atj/forms'; +import { type FormConfig, type FormDefinition, type Pattern } from '@atj/forms'; import { type ComponentForPattern } from '../../Form'; @@ -13,11 +9,13 @@ export type FormEditUIContext = { uswdsRoot: `${string}/`; }; -export type PatternEditComponent = React.ComponentType<{ +export type PatternEditComponent = React.ComponentType<{ context: FormEditUIContext; form: FormDefinition; element: T; }>; -export type EditComponentForPattern = - Record>; +export type EditComponentForPattern = Record< + string, + PatternEditComponent +>; diff --git a/packages/design/src/config/edit/SequenceElementEdit.tsx b/packages/design/src/config/edit/SequenceElementEdit.tsx index 0d342e5a..e178f0a1 100644 --- a/packages/design/src/config/edit/SequenceElementEdit.tsx +++ b/packages/design/src/config/edit/SequenceElementEdit.tsx @@ -17,7 +17,7 @@ import { import { CSS } from '@dnd-kit/utilities'; import { useFormContext } from 'react-hook-form'; -import { type FormDefinition, type FormElement } from '@atj/forms'; +import { type FormDefinition, type Pattern } from '@atj/forms'; import { type SequenceElement } from '@atj/forms/src/elements/sequence'; import { type FormEditUIContext, @@ -27,7 +27,7 @@ import { interface ItemProps { id: string; form: FormDefinition; - element: FormElement; + element: Pattern; context: FormEditUIContext; } @@ -73,7 +73,7 @@ const SequenceElementEdit: PatternEditComponent = ({ element, }) => { const { register, setValue } = useFormContext(); - const [elements, setElements] = useState( + const [elements, setElements] = useState( element.data.elements.map((elementId: string) => { return form.elements[elementId]; }) diff --git a/packages/design/src/config/view/Fieldset/index.tsx b/packages/design/src/config/view/Fieldset/index.tsx index 10e32c83..0c4da614 100644 --- a/packages/design/src/config/view/Fieldset/index.tsx +++ b/packages/design/src/config/view/Fieldset/index.tsx @@ -2,9 +2,9 @@ import React from 'react'; import { type FieldsetPattern, type PatternProps } from '@atj/forms'; -import { type FormElementComponent } from '../../../Form'; +import { type PatternComponent } from '../../../Form'; -const FormSummary: FormElementComponent> = ({ +const FormSummary: PatternComponent> = ({ pattern, children, }) => { diff --git a/packages/design/src/config/view/FormSummary/index.tsx b/packages/design/src/config/view/FormSummary/index.tsx index 648f1dbc..b9c377e8 100644 --- a/packages/design/src/config/view/FormSummary/index.tsx +++ b/packages/design/src/config/view/FormSummary/index.tsx @@ -1,9 +1,9 @@ import React from 'react'; import { type PatternProps, type FormSummaryPattern } from '@atj/forms'; -import { type FormElementComponent } from '../../../Form'; +import { type PatternComponent } from '../../../Form'; -const FormSummary: FormElementComponent> = ({ +const FormSummary: PatternComponent> = ({ pattern, }) => { return ( diff --git a/packages/design/src/config/view/Paragraph/index.tsx b/packages/design/src/config/view/Paragraph/index.tsx index a107eca8..d2f67884 100644 --- a/packages/design/src/config/view/Paragraph/index.tsx +++ b/packages/design/src/config/view/Paragraph/index.tsx @@ -2,9 +2,9 @@ import React from 'react'; import { type ParagraphPattern, type PatternProps } from '@atj/forms'; -import { type FormElementComponent } from '../../../Form'; +import { type PatternComponent } from '../../../Form'; -const FormSummary: FormElementComponent> = ({ +const FormSummary: PatternComponent> = ({ pattern, }) => { if (pattern.style === 'heading') { diff --git a/packages/design/src/config/view/Sequence/index.tsx b/packages/design/src/config/view/Sequence/index.tsx index 52c4cb94..4c3ccbeb 100644 --- a/packages/design/src/config/view/Sequence/index.tsx +++ b/packages/design/src/config/view/Sequence/index.tsx @@ -3,9 +3,9 @@ import React from 'react'; import { type PatternProps } from '@atj/forms'; import { SequenceElement } from '@atj/forms/src/config/elements/sequence'; -import { FormElementComponent } from '../../../Form'; +import { PatternComponent } from '../../../Form'; -const Sequence: FormElementComponent> = ({ +const Sequence: PatternComponent> = ({ children, }) => { return <>{children}; diff --git a/packages/design/src/config/view/SubmissionConfirmation/index.tsx b/packages/design/src/config/view/SubmissionConfirmation/index.tsx index 51b273b5..8b3d6fa9 100644 --- a/packages/design/src/config/view/SubmissionConfirmation/index.tsx +++ b/packages/design/src/config/view/SubmissionConfirmation/index.tsx @@ -1,9 +1,9 @@ import React from 'react'; import { PatternProps, type SubmissionConfirmationPattern } from '@atj/forms'; -import { FormElementComponent } from '../../../Form'; +import { PatternComponent } from '../../../Form'; -const SubmissionConfirmation: FormElementComponent< +const SubmissionConfirmation: PatternComponent< PatternProps > = ({ pattern }) => { return ( diff --git a/packages/design/src/config/view/TextInput/index.tsx b/packages/design/src/config/view/TextInput/index.tsx index 5773d9c9..016d6a65 100644 --- a/packages/design/src/config/view/TextInput/index.tsx +++ b/packages/design/src/config/view/TextInput/index.tsx @@ -3,9 +3,9 @@ import React from 'react'; import { useFormContext } from 'react-hook-form'; import { PatternProps, type TextInputPattern } from '@atj/forms'; -import { type FormElementComponent } from '../../../Form'; +import { type PatternComponent } from '../../../Form'; -const TextInput: FormElementComponent> = ({ +const TextInput: PatternComponent> = ({ pattern, }) => { const { register } = useFormContext(); diff --git a/packages/design/src/config/view/index.tsx b/packages/design/src/config/view/index.tsx index 1e704d5e..0066eb4e 100644 --- a/packages/design/src/config/view/index.tsx +++ b/packages/design/src/config/view/index.tsx @@ -6,7 +6,7 @@ import SubmissionConfirmation from './SubmissionConfirmation'; import TextInput from './TextInput'; import { type ComponentForPattern } from '../../Form'; -export const defaultFormElementComponents: ComponentForPattern = { +export const defaultPatternComponents: ComponentForPattern = { fieldset: Fieldset, 'form-summary': FormSummary, input: TextInput, diff --git a/packages/design/src/test-form.ts b/packages/design/src/test-form.ts index cd66d810..04c3a40e 100644 --- a/packages/design/src/test-form.ts +++ b/packages/design/src/test-form.ts @@ -1,7 +1,7 @@ import { createForm, createFormSession, defaultFormConfig } from '@atj/forms'; import { - defaultFormElementComponents, + defaultPatternComponents, defaultPatternEditComponents, } from './config'; import { FormUIContext } from 'Form'; @@ -31,7 +31,7 @@ export const createTestForm = () => { type: 'input', id: 'element-1', data: { - text: 'FormElement 1', + text: 'Pattern 1', required: true, initial: '', }, @@ -42,7 +42,7 @@ export const createTestForm = () => { type: 'input', id: 'element-2', data: { - text: 'FormElement 2', + text: 'Pattern 2', required: false, initial: 'test', }, @@ -58,14 +58,14 @@ export const createTestFormConfig = () => { return defaultFormConfig; }; -export const createTestFormElementComponentMap = () => { - return defaultFormElementComponents; +export const createTestPatternComponentMap = () => { + return defaultPatternComponents; }; export const createTestFormContext = (): FormUIContext => { return { config: defaultFormConfig, - components: defaultFormElementComponents, + components: defaultPatternComponents, uswdsRoot: '/uswds/', }; }; @@ -73,7 +73,7 @@ export const createTestFormContext = (): FormUIContext => { export const createTestFormEditContext = (): FormEditUIContext => { return { config: defaultFormConfig, - components: defaultFormElementComponents, + components: defaultPatternComponents, editComponents: defaultPatternEditComponents, uswdsRoot: `/static/uswds/`, }; diff --git a/packages/forms/src/builder/index.ts b/packages/forms/src/builder/index.ts index 7fa4116b..460c19a0 100644 --- a/packages/forms/src/builder/index.ts +++ b/packages/forms/src/builder/index.ts @@ -4,9 +4,9 @@ import { addDocument, nullFormDefinition, updateFormSummary, - updateFormElement, - FormElementMap, - FormElement, + updatePattern, + PatternMap, + Pattern, FormConfig, } from '..'; @@ -30,12 +30,12 @@ export class FormBuilder { this._form = updatedForm; } - updateFormElement( + updatePattern( config: FormConfig, - formElement: FormElement, - formData: FormElementMap + formElement: Pattern, + formData: PatternMap ) { - const updatedElement = updateFormElement( + const updatedElement = updatePattern( config, this.form, formElement, diff --git a/packages/forms/src/documents/document.ts b/packages/forms/src/documents/document.ts index f5b3bb8a..2563fd12 100644 --- a/packages/forms/src/documents/document.ts +++ b/packages/forms/src/documents/document.ts @@ -1,14 +1,14 @@ import { FormDefinition, - FormElement, + Pattern, addFormOutput, - addFormElements, - addFormElementMap, + addPatterns, + addPatternMap, updateFormSummary, } from '..'; import { InputElement } from '../config/elements/input'; import { PDFDocument, getDocumentFieldData } from './pdf'; -import { getSuggestedFormElementsFromCache } from './suggestions'; +import { getSuggestedPatternsFromCache } from './suggestions'; import { DocumentFieldMap } from './types'; export type DocumentTemplate = PDFDocument; @@ -21,14 +21,14 @@ export const addDocument = async ( } ) => { const fields = await getDocumentFieldData(fileDetails.data); - const cachedPdf = await getSuggestedFormElementsFromCache(fileDetails.data); + const cachedPdf = await getSuggestedPatternsFromCache(fileDetails.data); if (cachedPdf) { form = updateFormSummary(form, { title: cachedPdf.title, description: '', }); - form = addFormElementMap(form, cachedPdf.elements, cachedPdf.root); + form = addPatternMap(form, cachedPdf.elements, cachedPdf.root); const updatedForm = addFormOutput(form, { data: fileDetails.data, path: fileDetails.name, @@ -69,7 +69,7 @@ export const addDocumentFieldsToForm = ( form: FormDefinition, fields: DocumentFieldMap ) => { - const elements: FormElement[] = []; + const elements: Pattern[] = []; Object.entries(fields).map(([elementId, field]) => { if (field.type === 'CheckBox') { elements.push({ @@ -163,5 +163,5 @@ export const addDocumentFieldsToForm = ( default: [], required: true, }); - return addFormElements(form, elements, 'root'); + return addPatterns(form, elements, 'root'); }; diff --git a/packages/forms/src/documents/pdf/mock-api.ts b/packages/forms/src/documents/pdf/mock-api.ts index dddbd6c6..f07c3ec5 100644 --- a/packages/forms/src/documents/pdf/mock-api.ts +++ b/packages/forms/src/documents/pdf/mock-api.ts @@ -1,10 +1,6 @@ import * as z from 'zod'; -import { - type FormElement, - type FormElementId, - type FormElementMap, -} from '../..'; +import { type Pattern, type PatternId, type PatternMap } from '../..'; import { ParagraphElement } from '../../config/elements/paragraph'; import { InputElement } from '../../config/elements/input'; @@ -94,9 +90,9 @@ const ExtractedObject = z.object({ type ExtractedObject = z.infer; export type ParsedPdf = { - elements: FormElementMap; + elements: PatternMap; outputs: DocumentFieldMap; // to populate FormOutput - root: FormElementId; + root: PatternId; title: string; }; @@ -108,9 +104,9 @@ export const parseAlabamaNameChangeForm = (): ParsedPdf => { root: 'root', title: extracted.title, }; - const rootSequence: FormElementId[] = []; + const rootSequence: PatternId[] = []; for (const element of extracted.elements) { - const fieldsetElements: FormElementId[] = []; + const fieldsetElements: PatternId[] = []; if (element.inputs.length === 0) { parsedPdf.elements[element.id] = { type: 'paragraph', @@ -186,7 +182,7 @@ export const parseAlabamaNameChangeForm = (): ParsedPdf => { return parsedPdf; }; -const getElementInputs = (element: ExtractedElement): FormElement[] => { +const getElementInputs = (element: ExtractedElement): Pattern[] => { return element.inputs .map((input: ExtractedInput) => { if (input.input_type === 'Tx') { @@ -200,9 +196,9 @@ const getElementInputs = (element: ExtractedElement): FormElement[] => { required: true, } satisfies InputElement; } - return null as unknown as FormElement; + return null as unknown as Pattern; }) - .filter((item): item is NonNullable => item !== null); + .filter((item): item is NonNullable => item !== null); }; const PdfFieldMap: Record = { @@ -277,7 +273,7 @@ function parseInputs( function parseElements( pdfElements: ExtractedJsonType['elements'] -): FormElement[] { +): Pattern[] { const output = pdfElements.reduce((acc, element) => { const elementOutput = { type: 'Paragraph', diff --git a/packages/forms/src/documents/suggestions.ts b/packages/forms/src/documents/suggestions.ts index 4445199c..3103f297 100644 --- a/packages/forms/src/documents/suggestions.ts +++ b/packages/forms/src/documents/suggestions.ts @@ -9,7 +9,7 @@ export type SuggestedForm = { type?: 'text'; }[]; -export const getSuggestedFormElementsFromCache = async ( +export const getSuggestedPatternsFromCache = async ( rawData: Uint8Array ): Promise => { const cache = getFakeCache(); diff --git a/packages/forms/src/element.ts b/packages/forms/src/element.ts index d3b179a0..1aba3af8 100644 --- a/packages/forms/src/element.ts +++ b/packages/forms/src/element.ts @@ -3,57 +3,53 @@ import { type FormDefinition } from '..'; import { type CreatePrompt } from './pattern'; -export type FormElement = { +export type Pattern = { type: string; - id: FormElementId; + id: PatternId; data: C; default: T; required: boolean; }; -export type FormElementId = string; -export type FormElementValue = - T['default']; -export type FormElementValueMap = Record; -export type FormElementMap = Record; -export type GetFormElement = ( - form: FormDefinition, - id: FormElementId -) => FormElement; +export type PatternId = string; +export type PatternValue = T['default']; +export type PatternValueMap = Record; +export type PatternMap = Record; +export type GetPattern = (form: FormDefinition, id: PatternId) => Pattern; -export type ParseFormElementData = ( +export type ParsePatternData = ( elementData: T['data'], obj: string ) => Result; -export type ParseFormElementConfigData = ( +export type ParsePatternConfigData = ( elementData: T['data'] ) => Result; -export const getFormElement: GetFormElement = (form, elementId) => { +export const getPattern: GetPattern = (form, elementId) => { return form.elements[elementId]; }; -export type FormElementConfig = { +export type PatternConfig = { acceptsInput: boolean; - initial: ThisFormElement['data']; - parseData: ParseFormElementData; - parseConfigData: ParseFormElementConfigData; + initial: ThisPattern['data']; + parseData: ParsePatternData; + parseConfigData: ParsePatternConfigData; getChildren: ( - element: ThisFormElement, - elements: Record - ) => FormElement[]; - createPrompt: CreatePrompt; + element: ThisPattern, + elements: Record + ) => Pattern[]; + createPrompt: CreatePrompt; }; -export type FormConfig = { - elements: Record>; +export type FormConfig = { + elements: Record>; }; export type ConfigElements = ReturnType< Config['elements'][keyof Config['elements']]['parseData'] >; -export const getFormElementMap = (elements: FormElement[]) => { +export const getPatternMap = (elements: Pattern[]) => { return Object.fromEntries( elements.map(element => { return [element.id, element]; @@ -61,25 +57,22 @@ export const getFormElementMap = (elements: FormElement[]) => { ); }; -export const getFormElements = ( - form: FormDefinition, - elementIds: FormElementId[] -) => { - return elementIds.map(elementId => getFormElement(form, elementId)); +export const getPatterns = (form: FormDefinition, elementIds: PatternId[]) => { + return elementIds.map(elementId => getPattern(form, elementId)); }; -export const getFormElementConfig = ( +export const getPatternConfig = ( config: FormConfig, - elementType: FormElement['type'] + elementType: Pattern['type'] ) => { return config.elements[elementType]; }; export const validateElement = ( - elementConfig: FormElementConfig, - element: FormElement, + elementConfig: PatternConfig, + element: Pattern, value: any -): Result => { +): Result => { if (!elementConfig.acceptsInput) { return { success: true, @@ -105,18 +98,18 @@ export const validateElement = ( }; }; -export const getFirstFormElement = ( +export const getFirstPattern = ( config: FormConfig, form: FormDefinition, - element?: FormElement -): FormElement => { + element?: Pattern +): Pattern => { if (!element) { element = form.elements[form.root]; } - const elemConfig = getFormElementConfig(config, element.type); + const elemConfig = getPatternConfig(config, element.type); const children = elemConfig.getChildren(element, form.elements); if (children?.length === 0) { return element; } - return getFirstFormElement(config, form, children[0]); + return getFirstPattern(config, form, children[0]); }; diff --git a/packages/forms/src/elements/fieldset.ts b/packages/forms/src/elements/fieldset.ts index 2f7a1e48..3c97c2a6 100644 --- a/packages/forms/src/elements/fieldset.ts +++ b/packages/forms/src/elements/fieldset.ts @@ -1,10 +1,10 @@ import * as z from 'zod'; import { - type FormElement, - type FormElementConfig, - type FormElementId, - getFormElement, + type Pattern, + type PatternConfig, + type PatternId, + getPattern, } from '../element'; import { type FieldsetPattern, @@ -13,9 +13,9 @@ import { } from '../pattern'; import { safeZodParse } from '../util/zod'; -export type FieldsetElement = FormElement<{ +export type FieldsetElement = Pattern<{ legend?: string; - elements: FormElementId[]; + elements: PatternId[]; }>; const FieldsetSchema = z.array(z.string()); @@ -25,7 +25,7 @@ const configSchema = z.object({ elements: z.array(z.string()), }); -export const fieldsetConfig: FormElementConfig = { +export const fieldsetConfig: PatternConfig = { acceptsInput: false, initial: { elements: [], @@ -41,7 +41,7 @@ export const fieldsetConfig: FormElementConfig = { }, createPrompt(config, session, element, options) { const children = element.data.elements.map((elementId: string) => { - const element = getFormElement(session.form, elementId); + const element = getPattern(session.form, elementId); return createPromptForElement(config, session, element, options); }); return { diff --git a/packages/forms/src/elements/form-summary.ts b/packages/forms/src/elements/form-summary.ts index cfdbad85..299403fc 100644 --- a/packages/forms/src/elements/form-summary.ts +++ b/packages/forms/src/elements/form-summary.ts @@ -1,6 +1,6 @@ import * as z from 'zod'; -import { type FormElement, type FormElementConfig } from '../element'; +import { type Pattern, type PatternConfig } from '../element'; import { type FormSummaryPattern, type Pattern } from '../pattern'; import { safeZodParse } from '../util/zod'; @@ -8,9 +8,9 @@ const configSchema = z.object({ title: z.string().max(128), summary: z.string().max(2024), }); -export type FormSummary = FormElement>; +export type FormSummary = Pattern>; -export const formSummaryConfig: FormElementConfig = { +export const formSummaryConfig: PatternConfig = { acceptsInput: false, initial: { text: '', diff --git a/packages/forms/src/elements/input.ts b/packages/forms/src/elements/input.ts index d5ed25fb..18e8a8e9 100644 --- a/packages/forms/src/elements/input.ts +++ b/packages/forms/src/elements/input.ts @@ -1,6 +1,6 @@ import * as z from 'zod'; -import { type FormElement, type FormElementConfig } from '../element'; +import { type Pattern, type PatternConfig } from '../element'; import { type PatternProps, type TextInputPattern } from '../pattern'; import { getFormSessionValue } from '../session'; import { safeZodParse } from '../util/zod'; @@ -11,12 +11,12 @@ const configSchema = z.object({ required: z.boolean(), maxLength: z.coerce.number(), }); -export type InputElement = FormElement>; +export type InputElement = Pattern>; const createSchema = (data: InputElement['data']) => z.string().max(data.maxLength); -export const inputConfig: FormElementConfig = { +export const inputConfig: PatternConfig = { acceptsInput: true, initial: { label: '', diff --git a/packages/forms/src/elements/paragraph.ts b/packages/forms/src/elements/paragraph.ts index bc119e0e..306186ee 100644 --- a/packages/forms/src/elements/paragraph.ts +++ b/packages/forms/src/elements/paragraph.ts @@ -1,6 +1,6 @@ import * as z from 'zod'; -import { type FormElement, type FormElementConfig } from '../element'; +import { type Pattern, type PatternConfig } from '../element'; import { type PatternProps, type ParagraphPattern } from '../pattern'; import { safeZodParse } from '../util/zod'; @@ -8,12 +8,12 @@ const configSchema = z.object({ text: z.string(), maxLength: z.coerce.number(), }); -export type ParagraphElement = FormElement>; +export type ParagraphElement = Pattern>; const createSchema = (data: ParagraphElement['data']) => z.string().max(data.maxLength); -export const paragraphConfig: FormElementConfig = { +export const paragraphConfig: PatternConfig = { acceptsInput: false, initial: { text: 'normal', diff --git a/packages/forms/src/elements/sequence.ts b/packages/forms/src/elements/sequence.ts index ce5fb9ad..1a9ec914 100644 --- a/packages/forms/src/elements/sequence.ts +++ b/packages/forms/src/elements/sequence.ts @@ -1,16 +1,16 @@ import * as z from 'zod'; import { - type FormElement, - type FormElementConfig, - type FormElementId, - getFormElement, + type Pattern, + type PatternConfig, + type PatternId, + getPattern, } from '../element'; import { createPromptForElement } from '../pattern'; import { safeZodParse } from '../util/zod'; -export type SequenceElement = FormElement<{ - elements: FormElementId[]; +export type SequenceElement = Pattern<{ + elements: PatternId[]; }>; const sequenceSchema = z.array(z.string()); @@ -19,7 +19,7 @@ const configSchema = z.object({ elements: z.array(z.string()), }); -export const sequenceConfig: FormElementConfig = { +export const sequenceConfig: PatternConfig = { acceptsInput: false, initial: { elements: [], @@ -35,7 +35,7 @@ export const sequenceConfig: FormElementConfig = { }, createPrompt(config, session, element, options) { const children = element.data.elements.map((elementId: string) => { - const childElement = getFormElement(session.form, elementId); + const childElement = getPattern(session.form, elementId); return createPromptForElement(config, session, childElement, options); }); return { diff --git a/packages/forms/src/index.ts b/packages/forms/src/index.ts index 6df46d1f..3f0006b7 100644 --- a/packages/forms/src/index.ts +++ b/packages/forms/src/index.ts @@ -2,13 +2,13 @@ import { FormConfig } from './config'; import { SequenceElement } from './config/elements/sequence'; import { DocumentFieldMap } from './documents'; import { - type FormElement, - type FormElementId, - type FormElementMap, - type FormElementValue, - type FormElementValueMap, - getFormElementMap, - getFormElementConfig, + type Pattern, + type PatternId, + type PatternMap, + type PatternValue, + type PatternValueMap, + getPatternMap, + getPatternConfig, } from './element'; export * from './builder'; @@ -21,8 +21,8 @@ export * from './session'; export type FormDefinition = { summary: FormSummary; - root: FormElementId; - elements: FormElementMap; + root: PatternId; + elements: PatternMap; outputs: FormOutput[]; }; @@ -54,12 +54,12 @@ export type FormSummary = { }; export type FormSessionId = string; -type ErrorMap = Record; +type ErrorMap = Record; export type FormSession = { id: FormSessionId; data: { errors: ErrorMap; - values: FormElementValueMap; + values: PatternValueMap; }; form: FormDefinition; }; @@ -74,8 +74,8 @@ export type FormOutput = { export const createForm = ( summary: FormSummary, initial: { - elements: FormElement[]; - root: FormElementId; + elements: Pattern[]; + root: PatternId; } = { elements: [ { @@ -96,12 +96,12 @@ export const createForm = ( return { summary, root: initial.root, - elements: getFormElementMap(initial.elements), + elements: getPatternMap(initial.elements), outputs: [], }; }; -export const getRootFormElement = (form: FormDefinition) => { +export const getRootPattern = (form: FormDefinition) => { return form.elements[form.root]; }; @@ -120,13 +120,9 @@ export const createFormSession = (form: FormDefinition): FormSession => { }; }; -export const updateForm = ( - context: FormSession, - id: FormElementId, - value: any -) => { +export const updateForm = (context: FormSession, id: PatternId, value: any) => { if (!(id in context.form.elements)) { - console.error(`FormElement "${id}" does not exist on form.`); + console.error(`Pattern "${id}" does not exist on form.`); return context; } const nextForm = addValue(context, id, value); @@ -139,10 +135,10 @@ export const updateForm = ( return nextForm; }; -const addValue = ( +const addValue = ( form: FormSession, - id: FormElementId, - value: FormElementValue + id: PatternId, + value: PatternValue ): FormSession => ({ ...form, data: { @@ -156,7 +152,7 @@ const addValue = ( const addError = ( session: FormSession, - id: FormElementId, + id: PatternId, error: string ): FormSession => ({ ...session, @@ -169,10 +165,10 @@ const addError = ( }, }); -export const addFormElementMap = ( +export const addPatternMap = ( form: FormDefinition, - elements: FormElementMap, - root?: FormElementId + elements: PatternMap, + root?: PatternId ) => { return { ...form, @@ -181,18 +177,18 @@ export const addFormElementMap = ( }; }; -export const addFormElements = ( +export const addPatterns = ( form: FormDefinition, - elements: FormElement[], - root?: FormElementId + elements: Pattern[], + root?: PatternId ) => { - const formElementMap = getFormElementMap(elements); - return addFormElementMap(form, formElementMap, root); + const formElementMap = getPatternMap(elements); + return addPatternMap(form, formElementMap, root); }; -export const replaceFormElements = ( +export const replacePatterns = ( form: FormDefinition, - elements: FormElement[] + elements: Pattern[] ): FormDefinition => { return { ...form, @@ -201,7 +197,7 @@ export const replaceFormElements = ( acc[element.id] = element; return acc; }, - {} as Record + {} as Record ), }; }; @@ -209,10 +205,10 @@ export const replaceFormElements = ( export const updateElements = ( config: FormConfig, form: FormDefinition, - newElements: FormElementMap + newElements: PatternMap ): FormDefinition => { const root = newElements[form.root]; - const targetElements: FormElementMap = { + const targetElements: PatternMap = { root, }; const resource = config.elements[root.type as keyof FormConfig]; @@ -227,7 +223,7 @@ export const updateElements = ( export const updateElement = ( form: FormDefinition, - formElement: FormElement + formElement: Pattern ): FormDefinition => { return { ...form, @@ -245,7 +241,7 @@ export const addFormOutput = (form: FormDefinition, document: FormOutput) => { }; }; -export const getFormElement = (form: FormDefinition, id: FormElementId) => { +export const getPattern = (form: FormDefinition, id: PatternId) => { return form.elements[id]; }; @@ -259,13 +255,13 @@ export const updateFormSummary = ( }; }; -export const updateFormElement = ( +export const updatePattern = ( config: FormConfig, form: FormDefinition, - formElement: FormElement, - formData: FormElementMap + formElement: Pattern, + formData: PatternMap ) => { - const elementConfig = getFormElementConfig(config, formElement.type); + const elementConfig = getPatternConfig(config, formElement.type); const data = formData[formElement.id].data; const result = elementConfig.parseConfigData(data); if (!result.success) { diff --git a/packages/forms/src/pattern.ts b/packages/forms/src/pattern.ts index f0754125..37cef5b0 100644 --- a/packages/forms/src/pattern.ts +++ b/packages/forms/src/pattern.ts @@ -1,10 +1,10 @@ import { type FormConfig, - type FormElement, - type FormElementId, - getRootFormElement, + type Pattern, + type PatternId, + getRootPattern, } from '..'; -import { getFormElementConfig } from './element'; +import { getPatternConfig } from './element'; import { type FormSession, nullSession, sessionIsComplete } from './session'; export type TextInputPattern = { @@ -46,7 +46,7 @@ export type FieldsetPattern = { }; export type PatternProps = { - _elementId: FormElementId; + _elementId: PatternId; _children: PromptPart[]; type: string; } & T; @@ -82,7 +82,7 @@ export const createPrompt = ( type: 'submission-confirmation', table: Object.entries(session.data.values) .filter(([elementId, value]) => { - const elemConfig = getFormElementConfig( + const elemConfig = getPatternConfig( config, session.form.elements[elementId].type ); @@ -111,7 +111,7 @@ export const createPrompt = ( children: [], }, ]; - const root = getRootFormElement(session.form); + const root = getRootPattern(session.form); parts.push(createPromptForElement(config, session, root, options)); return { actions: [ @@ -131,13 +131,13 @@ export type CreatePrompt = ( options: { validate: boolean } ) => PromptPart; -export const createPromptForElement: CreatePrompt = ( +export const createPromptForElement: CreatePrompt = ( config, session, element, options ) => { - const formElementConfig = getFormElementConfig(config, element.type); + const formElementConfig = getPatternConfig(config, element.type); return formElementConfig.createPrompt(config, session, element, options); }; @@ -150,9 +150,9 @@ export const createNullPrompt = ({ element, }: { config: FormConfig; - element: FormElement; + element: Pattern; }): Prompt => { - const formElementConfig = getFormElementConfig(config, element.type); + const formElementConfig = getPatternConfig(config, element.type); return { parts: [ formElementConfig.createPrompt(config, nullSession, element, { diff --git a/packages/forms/src/response.ts b/packages/forms/src/response.ts index 88274b4e..ec909a74 100644 --- a/packages/forms/src/response.ts +++ b/packages/forms/src/response.ts @@ -2,9 +2,9 @@ import { type Result } from '@atj/common'; import { type FormConfig, - type FormElementId, - getFormElement, - getFormElementConfig, + type PatternId, + getPattern, + getPatternConfig, validateElement, } from '.'; import { type PromptAction, createPrompt, isPromptAction } from './pattern'; @@ -40,11 +40,11 @@ export const applyPromptResponse = ( const parseElementValue = ( config: FormConfig, session: FormSession, - elementId: FormElementId, + elementId: PatternId, promptValue: string ) => { const element = session.form.elements[elementId]; - const formElementConfig = getFormElementConfig(config, element.type); + const formElementConfig = getPatternConfig(config, element.type); return formElementConfig.parseData(element, promptValue); }; @@ -56,8 +56,8 @@ const parsePromptResponse = ( const values: Record = {}; const errors: Record = {}; for (const [elementId, promptValue] of Object.entries(response.data)) { - const element = getFormElement(session.form, elementId); - const elementConfig = getFormElementConfig(config, element.type); + const element = getPattern(session.form, elementId); + const elementConfig = getPatternConfig(config, element.type); const isValidResult = validateElement(elementConfig, element, promptValue); if (isValidResult.success) { values[elementId] = isValidResult.data; diff --git a/packages/forms/src/session.ts b/packages/forms/src/session.ts index 87659159..0a1e5894 100644 --- a/packages/forms/src/session.ts +++ b/packages/forms/src/session.ts @@ -1,23 +1,23 @@ import { type FormConfig, type FormDefinition, - type FormElement, - getFormElementConfig, + type Pattern, + getPatternConfig, validateElement, } from '.'; import { SequenceElement } from './config/elements/sequence'; import { - type FormElementId, - type FormElementValue, - type FormElementValueMap, + type PatternId, + type PatternValue, + type PatternValueMap, } from './element'; -type ErrorMap = Record; +type ErrorMap = Record; export type FormSession = { data: { errors: ErrorMap; - values: FormElementValueMap; + values: PatternValueMap; }; form: FormDefinition; }; @@ -66,18 +66,18 @@ export const createFormSession = (form: FormDefinition): FormSession => { export const getFormSessionValue = ( session: FormSession, - elementId: FormElementId + elementId: PatternId ) => { return session.data.values[elementId]; }; export const updateSessionValue = ( session: FormSession, - id: FormElementId, - value: FormElementValue + id: PatternId, + value: PatternValue ): FormSession => { if (!(id in session.form.elements)) { - console.error(`FormElement "${id}" does not exist on form.`); + console.error(`Pattern "${id}" does not exist on form.`); return session; } const nextSession = addValue(session, id, value); @@ -92,7 +92,7 @@ export const updateSessionValue = ( export const updateSession = ( session: FormSession, - values: FormElementValueMap, + values: PatternValueMap, errors: ErrorMap ): FormSession => { const keysValid = @@ -120,17 +120,17 @@ export const updateSession = ( export const sessionIsComplete = (config: FormConfig, session: FormSession) => { return Object.values(session.form.elements).every(element => { - const elementConfig = getFormElementConfig(config, element.type); + const elementConfig = getPatternConfig(config, element.type); const value = getFormSessionValue(session, element.id); const isValidResult = validateElement(elementConfig, element, value); return isValidResult.success; }); }; -const addValue = ( +const addValue = ( form: FormSession, - id: FormElementId, - value: FormElementValue + id: PatternId, + value: PatternValue ): FormSession => ({ ...form, data: { @@ -144,7 +144,7 @@ const addValue = ( const addError = ( session: FormSession, - id: FormElementId, + id: PatternId, error: string ): FormSession => ({ ...session, diff --git a/packages/forms/src/util/zod.ts b/packages/forms/src/util/zod.ts index 8f6ba5fe..262bfe5b 100644 --- a/packages/forms/src/util/zod.ts +++ b/packages/forms/src/util/zod.ts @@ -2,9 +2,9 @@ import * as z from 'zod'; import { type Result } from '@atj/common'; -import { type FormElement } from '..'; +import { type Pattern } from '..'; -export const safeZodParse = ( +export const safeZodParse = ( schema: z.Schema, obj: string ): Result => { diff --git a/packages/forms/tests/two-field-form.test.ts b/packages/forms/tests/two-field-form.test.ts index 4b0cf98e..2a334759 100644 --- a/packages/forms/tests/two-field-form.test.ts +++ b/packages/forms/tests/two-field-form.test.ts @@ -2,7 +2,7 @@ import { describe, expect, test } from 'vitest'; import * as forms from '../src'; -const elements: forms.FormElement[] = [ +const elements: forms.Pattern[] = [ { type: 'sequence', id: 'root', From b896ce695d4d599d18f77df5d1898f109a642495 Mon Sep 17 00:00:00 2001 From: Daniel Naab Date: Tue, 26 Mar 2024 14:10:23 -0500 Subject: [PATCH 06/18] Rename FormDefinition -> BluePrint --- README.md | 15 +++++++ .../FormManager/DocumentImporter/index.tsx | 10 ++--- .../FormManager/FormEdit/DraggableList.tsx | 4 +- .../design/src/FormManager/FormEdit/index.tsx | 8 +--- .../design/src/FormManager/FormEdit/store.tsx | 8 ++-- .../design/src/FormManager/FormEdit/types.ts | 4 +- .../src/FormManager/FormPreview/index.tsx | 4 +- .../src/config/edit/SequenceElementEdit.tsx | 4 +- .../view/FormSummary/FormSummary.stories.tsx | 5 ++- .../design/src/config/view/Sequence/index.tsx | 4 +- .../SubmissionConfirmation.stories.tsx | 12 ++++-- .../view/SubmissionConfirmation/index.tsx | 7 +++- .../src/context/browser/form-repo.ts | 16 ++++---- .../form-service/src/context/test/storage.ts | 4 +- .../form-service/src/operations/add-form.ts | 4 +- .../form-service/src/operations/get-form.ts | 4 +- .../form-service/src/operations/save-form.ts | 4 +- .../src/operations/submit-form.ts | 4 +- packages/form-service/src/types.ts | 8 ++-- packages/forms/src/builder/index.ts | 12 +++--- packages/forms/src/documents/document.ts | 6 +-- packages/forms/src/element.ts | 8 ++-- packages/forms/src/index.ts | 39 +++++++++---------- packages/forms/src/session.ts | 6 +-- 24 files changed, 108 insertions(+), 92 deletions(-) diff --git a/README.md b/README.md index da1ef07d..3269232f 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,21 @@ Additional documentation: - [Architectural Decision Records (ADRs)](./documents/adr/) - [Non-project contributions](./documents/value-created-log.md) +## Terminology + +The platform is made up of the following high-level terms. + +### Personas + +- Content authors: legal experts who craft guided interview experiences via a "no code" interface +- Self-represented litigants (SREs): end-users who interact with the court via guided interviews created by content authors + +### Things + +- Blueprint: produced by a content author, the blueprint defines the structure of an interactive session between a court and an SRL +- Conversation: one instance of a blueprint; the interactive session between a court and an SRL. +- Pattern: the building blocks of a blueprint, patterns implement UX best-practices. + ## Development This project uses [pnpm workspaces](https://pnpm.io/workspaces). To work with this project, [install pnpm](https://pnpm.io/installation) and then the project dependencies: diff --git a/packages/design/src/FormManager/DocumentImporter/index.tsx b/packages/design/src/FormManager/DocumentImporter/index.tsx index 733f64e7..a969dc83 100644 --- a/packages/design/src/FormManager/DocumentImporter/index.tsx +++ b/packages/design/src/FormManager/DocumentImporter/index.tsx @@ -3,7 +3,7 @@ import { useNavigate } from 'react-router-dom'; import { type DocumentFieldMap, - type FormDefinition, + type Blueprint, SAMPLE_DOCUMENTS, addDocument, addDocumentFieldsToForm, @@ -24,7 +24,7 @@ const DocumentImporter = ({ baseUrl: string; formId: string; context: FormUIContext; - form: FormDefinition; + form: Blueprint; formService: FormService; }) => { const { state, actions } = useDocumentImporter(formService, form, baseUrl); @@ -184,13 +184,13 @@ const DocumentImporter = ({ type State = { page: number; - previewForm: FormDefinition; + previewForm: Blueprint; documentFields?: DocumentFieldMap; }; const useDocumentImporter = ( formService: FormService, - form: FormDefinition, + form: Blueprint, baseUrl: string ) => { const navigate = useNavigate(); @@ -203,7 +203,7 @@ const useDocumentImporter = ( data: { path: string; fields: DocumentFieldMap; - previewForm: FormDefinition; + previewForm: Blueprint; }; } | { diff --git a/packages/design/src/FormManager/FormEdit/DraggableList.tsx b/packages/design/src/FormManager/FormEdit/DraggableList.tsx index d5f7931e..2fdaf31c 100644 --- a/packages/design/src/FormManager/FormEdit/DraggableList.tsx +++ b/packages/design/src/FormManager/FormEdit/DraggableList.tsx @@ -18,7 +18,7 @@ import { CSS } from '@dnd-kit/utilities'; import { getPattern, - type FormDefinition, + type Blueprint, type Pattern, PatternId, } from '@atj/forms'; @@ -60,7 +60,7 @@ const SortableItem = ({ type DraggableListProps = React.PropsWithChildren<{ element: Pattern; - form: FormDefinition; + form: Blueprint; setSelectedElement: (element: Pattern) => void; }>; export const DraggableList: React.FC = ({ diff --git a/packages/design/src/FormManager/FormEdit/index.tsx b/packages/design/src/FormManager/FormEdit/index.tsx index 3fa00744..36855417 100644 --- a/packages/design/src/FormManager/FormEdit/index.tsx +++ b/packages/design/src/FormManager/FormEdit/index.tsx @@ -1,6 +1,6 @@ import React, { useEffect } from 'react'; -import { FormDefinition } from '@atj/forms'; +import { Blueprint } from '@atj/forms'; import { type FormService } from '@atj/form-service'; import { PatternEdit } from './PatternEdit'; @@ -34,11 +34,7 @@ export default function FormEdit({ ); } -const EditForm = ({ - saveForm, -}: { - saveForm: (form: FormDefinition) => void; -}) => { +const EditForm = ({ saveForm }: { saveForm: (form: Blueprint) => void }) => { const { form, selectedElement } = useFormEditStore(); useEffect(() => { saveForm(form); diff --git a/packages/design/src/FormManager/FormEdit/store.tsx b/packages/design/src/FormManager/FormEdit/store.tsx index ae5973d7..2b8d20ff 100644 --- a/packages/design/src/FormManager/FormEdit/store.tsx +++ b/packages/design/src/FormManager/FormEdit/store.tsx @@ -3,7 +3,7 @@ import { StoreApi, create } from 'zustand'; import { createContext } from 'zustand-utils'; import { - type FormDefinition, + type Blueprint, type PatternMap, type PatternProps, getPattern, @@ -18,7 +18,7 @@ export const useFormEditStore = useStore; export const FormEditProvider = (props: { context: FormEditUIContext; - form: FormDefinition; + form: Blueprint; children: React.ReactNode; }) => { return ( @@ -30,7 +30,7 @@ export const FormEditProvider = (props: { type FormEditState = { context: FormEditUIContext; - form: FormDefinition; + form: Blueprint; selectedElement?: Pattern; handleEditClick: (pattern: PatternProps) => void; @@ -43,7 +43,7 @@ const createFormEditStore = ({ form, }: { context: FormEditUIContext; - form: FormDefinition; + form: Blueprint; }) => create((set, get) => ({ context, diff --git a/packages/design/src/FormManager/FormEdit/types.ts b/packages/design/src/FormManager/FormEdit/types.ts index d9ae1392..1d3c434c 100644 --- a/packages/design/src/FormManager/FormEdit/types.ts +++ b/packages/design/src/FormManager/FormEdit/types.ts @@ -1,4 +1,4 @@ -import { type FormConfig, type FormDefinition, type Pattern } from '@atj/forms'; +import { type FormConfig, type Blueprint, type Pattern } from '@atj/forms'; import { type ComponentForPattern } from '../../Form'; @@ -11,7 +11,7 @@ export type FormEditUIContext = { export type PatternEditComponent = React.ComponentType<{ context: FormEditUIContext; - form: FormDefinition; + form: Blueprint; element: T; }>; diff --git a/packages/design/src/FormManager/FormPreview/index.tsx b/packages/design/src/FormManager/FormPreview/index.tsx index a9101172..7dd933f8 100644 --- a/packages/design/src/FormManager/FormPreview/index.tsx +++ b/packages/design/src/FormManager/FormPreview/index.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { type FormDefinition, createFormSession } from '@atj/forms'; +import { type Blueprint, createFormSession } from '@atj/forms'; import { FormService } from '@atj/form-service'; import Form, { type FormUIContext } from '../../Form'; @@ -10,7 +10,7 @@ export default function FormPreview({ form, }: { context: FormUIContext; - form: FormDefinition; + form: Blueprint; }) { const session = createFormSession(form); return ; diff --git a/packages/design/src/config/edit/SequenceElementEdit.tsx b/packages/design/src/config/edit/SequenceElementEdit.tsx index e178f0a1..35ce5574 100644 --- a/packages/design/src/config/edit/SequenceElementEdit.tsx +++ b/packages/design/src/config/edit/SequenceElementEdit.tsx @@ -17,7 +17,7 @@ import { import { CSS } from '@dnd-kit/utilities'; import { useFormContext } from 'react-hook-form'; -import { type FormDefinition, type Pattern } from '@atj/forms'; +import { type Blueprint, type Pattern } from '@atj/forms'; import { type SequenceElement } from '@atj/forms/src/elements/sequence'; import { type FormEditUIContext, @@ -26,7 +26,7 @@ import { interface ItemProps { id: string; - form: FormDefinition; + form: Blueprint; element: Pattern; context: FormEditUIContext; } diff --git a/packages/design/src/config/view/FormSummary/FormSummary.stories.tsx b/packages/design/src/config/view/FormSummary/FormSummary.stories.tsx index b0c63e52..d0c838ac 100644 --- a/packages/design/src/config/view/FormSummary/FormSummary.stories.tsx +++ b/packages/design/src/config/view/FormSummary/FormSummary.stories.tsx @@ -1,6 +1,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import FormSummary from '.'; +import { type PatternProps, type FormSummaryPattern } from '@atj/forms'; export default { title: 'patterns/FormSummary', @@ -16,7 +17,7 @@ export const FormSummaryWithLongDescription = { title: 'Form title', description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', - }, + } as PatternProps, }, } satisfies StoryObj; @@ -27,6 +28,6 @@ export const FormSummaryWithShortDescription = { type: 'form-summary', title: 'Title 2', description: 'Short description', - }, + } as PatternProps, }, } satisfies StoryObj; diff --git a/packages/design/src/config/view/Sequence/index.tsx b/packages/design/src/config/view/Sequence/index.tsx index 4c3ccbeb..03658894 100644 --- a/packages/design/src/config/view/Sequence/index.tsx +++ b/packages/design/src/config/view/Sequence/index.tsx @@ -1,9 +1,9 @@ import React from 'react'; import { type PatternProps } from '@atj/forms'; -import { SequenceElement } from '@atj/forms/src/config/elements/sequence'; +import { type SequenceElement } from '@atj/forms/src/elements/sequence'; -import { PatternComponent } from '../../../Form'; +import { type PatternComponent } from '../../../Form'; const Sequence: PatternComponent> = ({ children, diff --git a/packages/design/src/config/view/SubmissionConfirmation/SubmissionConfirmation.stories.tsx b/packages/design/src/config/view/SubmissionConfirmation/SubmissionConfirmation.stories.tsx index b745e3d6..638d4219 100644 --- a/packages/design/src/config/view/SubmissionConfirmation/SubmissionConfirmation.stories.tsx +++ b/packages/design/src/config/view/SubmissionConfirmation/SubmissionConfirmation.stories.tsx @@ -1,6 +1,10 @@ import type { Meta, StoryObj } from '@storybook/react'; -import SubmissionConfirmation, { type SubmissionConfirmationProps } from '.'; +import SubmissionConfirmation from '.'; +import { + type PatternProps, + type SubmissionConfirmationPattern, +} from '@atj/forms'; export default { title: 'patterns/SubmissionConfirmation', @@ -10,7 +14,7 @@ export default { export const SubmissionConfirmationExample = { args: { - prompt: { + pattern: { type: 'submission-confirmation', table: [ { label: 'Field 1', value: 'Value 1' }, @@ -18,6 +22,6 @@ export const SubmissionConfirmationExample = { { label: 'Field 3', value: 'Value 3' }, { label: 'Field 4', value: 'Value 4' }, ], - }, - } satisfies SubmissionConfirmationProps, + } as PatternProps, + }, } satisfies StoryObj; diff --git a/packages/design/src/config/view/SubmissionConfirmation/index.tsx b/packages/design/src/config/view/SubmissionConfirmation/index.tsx index 8b3d6fa9..5371a465 100644 --- a/packages/design/src/config/view/SubmissionConfirmation/index.tsx +++ b/packages/design/src/config/view/SubmissionConfirmation/index.tsx @@ -1,7 +1,10 @@ import React from 'react'; -import { PatternProps, type SubmissionConfirmationPattern } from '@atj/forms'; -import { PatternComponent } from '../../../Form'; +import { + type PatternProps, + type SubmissionConfirmationPattern, +} from '@atj/forms'; +import { type PatternComponent } from '../../../Form'; const SubmissionConfirmation: PatternComponent< PatternProps diff --git a/packages/form-service/src/context/browser/form-repo.ts b/packages/form-service/src/context/browser/form-repo.ts index f2e13978..ba2ccd10 100644 --- a/packages/form-service/src/context/browser/form-repo.ts +++ b/packages/form-service/src/context/browser/form-repo.ts @@ -1,10 +1,10 @@ import { Result } from '@atj/common'; -import { type FormDefinition } from '@atj/forms'; +import { type Blueprint } from '@atj/forms'; export const getFormFromStorage = ( storage: Storage, id?: string -): FormDefinition | null => { +): Blueprint | null => { if (!storage || !id) { return null; } @@ -33,7 +33,7 @@ export const getFormSummaryListFromStorage = (storage: Storage) => { return null; } return forms.map(key => { - const form = getFormFromStorage(storage, key) as FormDefinition; + const form = getFormFromStorage(storage, key) as Blueprint; if (form === null) { throw new Error('key mismatch'); } @@ -47,7 +47,7 @@ export const getFormSummaryListFromStorage = (storage: Storage) => { export const addFormToStorage = ( storage: Storage, - form: FormDefinition + form: Blueprint ): Result => { const uuid = crypto.randomUUID(); @@ -65,7 +65,7 @@ export const addFormToStorage = ( export const saveFormToStorage = ( storage: Storage, formId: string, - form: FormDefinition + form: Blueprint ) => { try { storage.setItem(formId, stringifyForm(form)); @@ -84,7 +84,7 @@ export const deleteFormFromStorage = (storage: Storage, formId: string) => { storage.removeItem(formId); }; -const stringifyForm = (form: FormDefinition) => { +const stringifyForm = (form: Blueprint) => { return JSON.stringify({ ...form, outputs: form.outputs.map(output => ({ @@ -95,8 +95,8 @@ const stringifyForm = (form: FormDefinition) => { }); }; -const parseStringForm = (formString: string): FormDefinition => { - const form = JSON.parse(formString) as FormDefinition; +const parseStringForm = (formString: string): Blueprint => { + const form = JSON.parse(formString) as Blueprint; return { ...form, outputs: form.outputs.map(output => ({ diff --git a/packages/form-service/src/context/test/storage.ts b/packages/form-service/src/context/test/storage.ts index bcc9831e..3de3dfbc 100644 --- a/packages/form-service/src/context/test/storage.ts +++ b/packages/form-service/src/context/test/storage.ts @@ -1,7 +1,7 @@ -import { type FormDefinition } from '@atj/forms'; +import { type Blueprint } from '@atj/forms'; import { saveFormToStorage } from '../browser/form-repo'; -export type TestData = Record; +export type TestData = Record; export const createTestStorage = (testData: TestData): Storage => { const records: Record = {}; diff --git a/packages/form-service/src/operations/add-form.ts b/packages/form-service/src/operations/add-form.ts index 997613c9..079300dd 100644 --- a/packages/form-service/src/operations/add-form.ts +++ b/packages/form-service/src/operations/add-form.ts @@ -1,11 +1,11 @@ import { Result } from '@atj/common'; -import { FormDefinition } from '@atj/forms'; +import { Blueprint } from '@atj/forms'; import { addFormToStorage } from '../context/browser/form-repo'; export const addForm = ( ctx: { storage: Storage }, - form: FormDefinition + form: Blueprint ): Result => { return addFormToStorage(ctx.storage, form); }; diff --git a/packages/form-service/src/operations/get-form.ts b/packages/form-service/src/operations/get-form.ts index 4c5c94b4..077a351b 100644 --- a/packages/form-service/src/operations/get-form.ts +++ b/packages/form-service/src/operations/get-form.ts @@ -1,12 +1,12 @@ import { Result } from '@atj/common'; -import { type FormDefinition } from '@atj/forms'; +import { type Blueprint } from '@atj/forms'; import { getFormFromStorage } from '../context/browser/form-repo'; export const getForm = ( ctx: { storage: Storage }, formId: string -): Result => { +): Result => { const result = getFormFromStorage(ctx.storage, formId); if (result === null) { return { diff --git a/packages/form-service/src/operations/save-form.ts b/packages/form-service/src/operations/save-form.ts index 7b537644..d689b1df 100644 --- a/packages/form-service/src/operations/save-form.ts +++ b/packages/form-service/src/operations/save-form.ts @@ -1,12 +1,12 @@ import { VoidResult } from '@atj/common'; -import { FormDefinition } from '@atj/forms'; +import { Blueprint } from '@atj/forms'; import { saveFormToStorage } from '../context/browser/form-repo'; export const saveForm = ( ctx: { storage: Storage }, formId: string, - form: FormDefinition + form: Blueprint ): VoidResult => { const result = saveFormToStorage(ctx.storage, formId, form); if (result.success === false) { diff --git a/packages/form-service/src/operations/submit-form.ts b/packages/form-service/src/operations/submit-form.ts index 5c9fe47d..e0d46e16 100644 --- a/packages/form-service/src/operations/submit-form.ts +++ b/packages/form-service/src/operations/submit-form.ts @@ -1,7 +1,7 @@ import { type Result } from '@atj/common'; import { type FormConfig, - type FormDefinition, + type Blueprint, type FormSession, applyPromptResponse, createFormOutputFieldData, @@ -55,7 +55,7 @@ export const submitForm = async ( }; const generateDocumentPackage = async ( - form: FormDefinition, + form: Blueprint, formData: Record ) => { const errors = new Array(); diff --git a/packages/form-service/src/types.ts b/packages/form-service/src/types.ts index fc65989f..8cc51342 100644 --- a/packages/form-service/src/types.ts +++ b/packages/form-service/src/types.ts @@ -1,14 +1,14 @@ import { Result, VoidResult } from '@atj/common'; -import { FormDefinition, FormSession } from '@atj/forms'; +import { Blueprint, FormSession } from '@atj/forms'; import { FormListItem } from './operations/get-form-list'; export type FormService = { - addForm: (form: FormDefinition) => Result; + addForm: (form: Blueprint) => Result; deleteForm: (formId: string) => VoidResult; - getForm: (formId: string) => Result; + getForm: (formId: string) => Result; getFormList: () => Result; - saveForm: (formId: string, form: FormDefinition) => VoidResult; + saveForm: (formId: string, form: Blueprint) => VoidResult; submitForm: ( //sessionId: string, session: FormSession, // TODO: load session from storage by ID diff --git a/packages/forms/src/builder/index.ts b/packages/forms/src/builder/index.ts index 460c19a0..53f3ac2a 100644 --- a/packages/forms/src/builder/index.ts +++ b/packages/forms/src/builder/index.ts @@ -1,8 +1,8 @@ import { - type FormDefinition, + type Blueprint, type FormSummary, addDocument, - nullFormDefinition, + nullBlueprint, updateFormSummary, updatePattern, PatternMap, @@ -11,13 +11,13 @@ import { } from '..'; export class FormBuilder { - private _form: FormDefinition; + private _form: Blueprint; - constructor(initialForm: FormDefinition = nullFormDefinition) { - this._form = initialForm || nullFormDefinition; + constructor(initialForm: Blueprint = nullBlueprint) { + this._form = initialForm || nullBlueprint; } - get form(): FormDefinition { + get form(): Blueprint { return this._form; } diff --git a/packages/forms/src/documents/document.ts b/packages/forms/src/documents/document.ts index 2563fd12..eb0313ca 100644 --- a/packages/forms/src/documents/document.ts +++ b/packages/forms/src/documents/document.ts @@ -1,5 +1,5 @@ import { - FormDefinition, + Blueprint, Pattern, addFormOutput, addPatterns, @@ -14,7 +14,7 @@ import { DocumentFieldMap } from './types'; export type DocumentTemplate = PDFDocument; export const addDocument = async ( - form: FormDefinition, + form: Blueprint, fileDetails: { name: string; data: Uint8Array; @@ -66,7 +66,7 @@ export const addDocument = async ( }; export const addDocumentFieldsToForm = ( - form: FormDefinition, + form: Blueprint, fields: DocumentFieldMap ) => { const elements: Pattern[] = []; diff --git a/packages/forms/src/element.ts b/packages/forms/src/element.ts index 1aba3af8..52a7a83b 100644 --- a/packages/forms/src/element.ts +++ b/packages/forms/src/element.ts @@ -1,5 +1,5 @@ import { type Result } from '@atj/common'; -import { type FormDefinition } from '..'; +import { type Blueprint } from '..'; import { type CreatePrompt } from './pattern'; @@ -15,7 +15,7 @@ export type PatternId = string; export type PatternValue = T['default']; export type PatternValueMap = Record; export type PatternMap = Record; -export type GetPattern = (form: FormDefinition, id: PatternId) => Pattern; +export type GetPattern = (form: Blueprint, id: PatternId) => Pattern; export type ParsePatternData = ( elementData: T['data'], @@ -57,7 +57,7 @@ export const getPatternMap = (elements: Pattern[]) => { ); }; -export const getPatterns = (form: FormDefinition, elementIds: PatternId[]) => { +export const getPatterns = (form: Blueprint, elementIds: PatternId[]) => { return elementIds.map(elementId => getPattern(form, elementId)); }; @@ -100,7 +100,7 @@ export const validateElement = ( export const getFirstPattern = ( config: FormConfig, - form: FormDefinition, + form: Blueprint, element?: Pattern ): Pattern => { if (!element) { diff --git a/packages/forms/src/index.ts b/packages/forms/src/index.ts index 3f0006b7..b73617ac 100644 --- a/packages/forms/src/index.ts +++ b/packages/forms/src/index.ts @@ -19,14 +19,14 @@ export * from './pattern'; export * from './response'; export * from './session'; -export type FormDefinition = { +export type Blueprint = { summary: FormSummary; root: PatternId; elements: PatternMap; outputs: FormOutput[]; }; -export const nullFormDefinition: FormDefinition = { +export const nullBlueprint: Blueprint = { summary: { title: '', description: '', @@ -61,7 +61,7 @@ export type FormSession = { errors: ErrorMap; values: PatternValueMap; }; - form: FormDefinition; + form: Blueprint; }; export type FormOutput = { @@ -92,7 +92,7 @@ export const createForm = ( ], root: 'root', } -): FormDefinition => { +): Blueprint => { return { summary, root: initial.root, @@ -101,11 +101,11 @@ export const createForm = ( }; }; -export const getRootPattern = (form: FormDefinition) => { +export const getRootPattern = (form: Blueprint) => { return form.elements[form.root]; }; -export const createFormSession = (form: FormDefinition): FormSession => { +export const createFormSession = (form: Blueprint): FormSession => { return { id: crypto.randomUUID(), data: { @@ -166,7 +166,7 @@ const addError = ( }); export const addPatternMap = ( - form: FormDefinition, + form: Blueprint, elements: PatternMap, root?: PatternId ) => { @@ -178,7 +178,7 @@ export const addPatternMap = ( }; export const addPatterns = ( - form: FormDefinition, + form: Blueprint, elements: Pattern[], root?: PatternId ) => { @@ -187,9 +187,9 @@ export const addPatterns = ( }; export const replacePatterns = ( - form: FormDefinition, + form: Blueprint, elements: Pattern[] -): FormDefinition => { +): Blueprint => { return { ...form, elements: elements.reduce( @@ -204,9 +204,9 @@ export const replacePatterns = ( export const updateElements = ( config: FormConfig, - form: FormDefinition, + form: Blueprint, newElements: PatternMap -): FormDefinition => { +): Blueprint => { const root = newElements[form.root]; const targetElements: PatternMap = { root, @@ -222,9 +222,9 @@ export const updateElements = ( }; export const updateElement = ( - form: FormDefinition, + form: Blueprint, formElement: Pattern -): FormDefinition => { +): Blueprint => { return { ...form, elements: { @@ -234,21 +234,18 @@ export const updateElement = ( }; }; -export const addFormOutput = (form: FormDefinition, document: FormOutput) => { +export const addFormOutput = (form: Blueprint, document: FormOutput) => { return { ...form, outputs: [...form.outputs, document], }; }; -export const getPattern = (form: FormDefinition, id: PatternId) => { +export const getPattern = (form: Blueprint, id: PatternId) => { return form.elements[id]; }; -export const updateFormSummary = ( - form: FormDefinition, - summary: FormSummary -) => { +export const updateFormSummary = (form: Blueprint, summary: FormSummary) => { return { ...form, summary, @@ -257,7 +254,7 @@ export const updateFormSummary = ( export const updatePattern = ( config: FormConfig, - form: FormDefinition, + form: Blueprint, formElement: Pattern, formData: PatternMap ) => { diff --git a/packages/forms/src/session.ts b/packages/forms/src/session.ts index 0a1e5894..ac7a57ae 100644 --- a/packages/forms/src/session.ts +++ b/packages/forms/src/session.ts @@ -1,6 +1,6 @@ import { type FormConfig, - type FormDefinition, + type Blueprint, type Pattern, getPatternConfig, validateElement, @@ -19,7 +19,7 @@ export type FormSession = { errors: ErrorMap; values: PatternValueMap; }; - form: FormDefinition; + form: Blueprint; }; export const nullSession: FormSession = { @@ -50,7 +50,7 @@ export const nullSession: FormSession = { }, }; -export const createFormSession = (form: FormDefinition): FormSession => { +export const createFormSession = (form: Blueprint): FormSession => { return { data: { errors: {}, From 746802ae5f18d763b7633913e2347211af0e973e Mon Sep 17 00:00:00 2001 From: Daniel Naab Date: Tue, 26 Mar 2024 16:19:53 -0500 Subject: [PATCH 07/18] Rename FormSession -> Session. Also, create preview components once when initializing the FormEditProvider, rather than on every render. --- packages/design/src/Form/index.tsx | 6 +- .../FormManager/DocumentImporter/index.tsx | 4 +- .../src/FormManager/FormEdit/Preview.tsx | 130 ++---------------- .../FormEdit/preview-components.tsx | 107 ++++++++++++++ .../design/src/FormManager/FormEdit/store.tsx | 5 + .../src/FormManager/FormPreview/index.tsx | 4 +- packages/design/src/FormRouter/index.tsx | 4 +- packages/design/src/test-form.ts | 4 +- .../src/context/browser/session-repo.ts | 14 +- .../src/operations/submit-form.test.ts | 4 +- .../src/operations/submit-form.ts | 6 +- packages/form-service/src/types.ts | 4 +- packages/forms/src/elements/input.ts | 4 +- packages/forms/src/index.ts | 20 ++- packages/forms/src/pattern.ts | 6 +- packages/forms/src/response.ts | 10 +- packages/forms/src/session.ts | 33 ++--- packages/forms/tests/two-field-form.test.ts | 12 +- 18 files changed, 184 insertions(+), 193 deletions(-) create mode 100644 packages/design/src/FormManager/FormEdit/preview-components.tsx diff --git a/packages/design/src/Form/index.tsx b/packages/design/src/Form/index.tsx index 5295b4a1..1d87e168 100644 --- a/packages/design/src/Form/index.tsx +++ b/packages/design/src/Form/index.tsx @@ -6,7 +6,7 @@ import { applyPromptResponse, createPrompt, type FormConfig, - type FormSession, + type Session, type PatternProps, type Prompt, type PromptPart, @@ -33,7 +33,7 @@ export type PatternComponent> = const usePrompt = ( initialPrompt: Prompt, config: FormConfig, - session: FormSession + session: Session ) => { const [prompt, _setPrompt] = useState(initialPrompt); const setPrompt = (newPrompt: Prompt) => { @@ -63,7 +63,7 @@ export default function Form({ isPreview, // ideally this should be removed. just here now for the FFP demo }: { context: FormUIContext; - session: FormSession; + session: Session; onSubmit?: (data: Record) => void; isPreview?: boolean; }) { diff --git a/packages/design/src/FormManager/DocumentImporter/index.tsx b/packages/design/src/FormManager/DocumentImporter/index.tsx index a969dc83..924e65a8 100644 --- a/packages/design/src/FormManager/DocumentImporter/index.tsx +++ b/packages/design/src/FormManager/DocumentImporter/index.tsx @@ -7,7 +7,7 @@ import { SAMPLE_DOCUMENTS, addDocument, addDocumentFieldsToForm, - createFormSession, + createSession, } from '@atj/forms'; import { type FormService } from '@atj/form-service'; @@ -147,7 +147,7 @@ const DocumentImporter = ({ <> { //handleFormSubmission(formId, data); console.log(formId, data); diff --git a/packages/design/src/FormManager/FormEdit/Preview.tsx b/packages/design/src/FormManager/FormEdit/Preview.tsx index 045568be..2477b5a3 100644 --- a/packages/design/src/FormManager/FormEdit/Preview.tsx +++ b/packages/design/src/FormManager/FormEdit/Preview.tsx @@ -1,136 +1,26 @@ import React from 'react'; -import { type PatternProps, createFormSession } from '@atj/forms'; +import { createSession } from '@atj/forms'; -import Form, { - type ComponentForPattern, - type PatternComponent, - type FormUIContext, -} from '../../Form'; +import Form from '../../Form'; import { useFormEditStore } from './store'; export const PreviewForm = () => { const uiContext = useFormEditStore(state => state.context); const form = useFormEditStore(state => state.form); - - const previewUiContext: FormUIContext = { - config: uiContext.config, - // TODO: We'll want to hoist this definition up to a higher level, so we - // don't have to regenerate it every time we render the form. - components: createPreviewComponents( - uiContext.components, - uiContext.uswdsRoot - ), - uswdsRoot: uiContext.uswdsRoot, - }; - const disposable = createFormSession(form); // nullSession instead? + const disposable = createSession(form); // nullSession instead? return ( ); }; - -const createPreviewComponents = ( - components: ComponentForPattern, - uswdsRoot: string -): ComponentForPattern => { - const previewComponents: ComponentForPattern = {}; - // TODO: Create a configurable way to to define preview components. - for (const [patternType, Component] of Object.entries(components)) { - if (patternType === 'sequence' || patternType === 'fieldset') { - previewComponents[patternType] = Component; - /* - previewComponents[patternType] = createSequencePatternPreviewComponent( - Component, - previewComponents - ); - */ - } else if (patternType === 'form-summary') { - previewComponents[patternType] = Component; - } else { - //previewComponents[patternType] = Component; - previewComponents[patternType] = createPatternPreviewComponent( - Component, - uswdsRoot - ); - } - } - return previewComponents; -}; - -/* -const createSequencePatternPreviewComponent = ( - Component: PatternComponent, - previewComponents: ComponentForPattern -) => { - const PatternPreviewSequenceComponent: PatternComponent = ({ - pattern, - }) => { - const { form, setSelectedElement } = usePreviewContext(); - const element = getPattern(form, pattern._elementId); - const Component = previewComponents[pattern.type]; - return ( - - - - ); - }; - return PatternPreviewSequenceComponent; -}; -*/ - -const createPatternPreviewComponent = ( - Component: PatternComponent, - uswdsRoot: string -) => { - const PatternPreviewComponent: PatternComponent = ({ - pattern, - }: { - pattern: Pattern; - }) => { - const selectedElement = useFormEditStore(state => state.selectedElement); - const handleEditClick = useFormEditStore(state => state.handleEditClick); - - const isSelected = selectedElement?.id === pattern._elementId; - const divClassNames = isSelected - ? 'form-group-row field-selected' - : 'form-group-row'; - - return ( -
- - - - -
- ); - }; - return PatternPreviewComponent; -}; diff --git a/packages/design/src/FormManager/FormEdit/preview-components.tsx b/packages/design/src/FormManager/FormEdit/preview-components.tsx new file mode 100644 index 00000000..251e81c1 --- /dev/null +++ b/packages/design/src/FormManager/FormEdit/preview-components.tsx @@ -0,0 +1,107 @@ +import React from 'react'; + +import { type PatternProps } from '@atj/forms'; + +import { type PatternComponent, type ComponentForPattern } from '../../Form'; +import { useFormEditStore } from './store'; + +export const createPreviewComponents = ( + components: ComponentForPattern, + uswdsRoot: string +): ComponentForPattern => { + const previewComponents: ComponentForPattern = {}; + // TODO: Create a configurable way to to define preview components. + for (const [patternType, Component] of Object.entries(components)) { + if (patternType === 'sequence' || patternType === 'fieldset') { + previewComponents[patternType] = Component; + /* + previewComponents[patternType] = createSequencePatternPreviewComponent( + Component, + previewComponents + ); + */ + } else if (patternType === 'form-summary') { + previewComponents[patternType] = Component; + } else { + //previewComponents[patternType] = Component; + previewComponents[patternType] = createPatternPreviewComponent( + Component, + uswdsRoot + ); + } + } + return previewComponents; +}; + +const createPatternPreviewComponent = ( + Component: PatternComponent, + uswdsRoot: string +) => { + const PatternPreviewComponent: PatternComponent = ({ + pattern, + }: { + pattern: PatternProps; + }) => { + const selectedElement = useFormEditStore(state => state.selectedElement); + const handleEditClick = useFormEditStore(state => state.handleEditClick); + + const isSelected = selectedElement?.id === pattern._elementId; + const divClassNames = isSelected + ? 'form-group-row field-selected' + : 'form-group-row'; + + return ( +
+ + + + +
+ ); + }; + return PatternPreviewComponent; +}; + +/* +const createSequencePatternPreviewComponent = ( + Component: PatternComponent, + previewComponents: ComponentForPattern +) => { + const PatternPreviewSequenceComponent: PatternComponent = ({ + pattern, + }) => { + const { form, setSelectedElement } = usePreviewContext(); + const element = getPattern(form, pattern._elementId); + const Component = previewComponents[pattern.type]; + return ( + + + + ); + }; + return PatternPreviewSequenceComponent; +}; +*/ diff --git a/packages/design/src/FormManager/FormEdit/store.tsx b/packages/design/src/FormManager/FormEdit/store.tsx index 2b8d20ff..cacc4c2b 100644 --- a/packages/design/src/FormManager/FormEdit/store.tsx +++ b/packages/design/src/FormManager/FormEdit/store.tsx @@ -10,7 +10,10 @@ import { FormBuilder, Pattern, } from '@atj/forms'; + +import { type ComponentForPattern } from '../../Form'; import { type FormEditUIContext } from './types'; +import { createPreviewComponents } from './preview-components'; const { Provider, useStore } = createContext>(); @@ -30,6 +33,7 @@ export const FormEditProvider = (props: { type FormEditState = { context: FormEditUIContext; + components: ComponentForPattern; form: Blueprint; selectedElement?: Pattern; @@ -47,6 +51,7 @@ const createFormEditStore = ({ }) => create((set, get) => ({ context, + components: createPreviewComponents(context.components, context.uswdsRoot), form, handleEditClick: (pattern: PatternProps) => { const state = get(); diff --git a/packages/design/src/FormManager/FormPreview/index.tsx b/packages/design/src/FormManager/FormPreview/index.tsx index 7dd933f8..480d49b3 100644 --- a/packages/design/src/FormManager/FormPreview/index.tsx +++ b/packages/design/src/FormManager/FormPreview/index.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { type Blueprint, createFormSession } from '@atj/forms'; +import { type Blueprint, createSession } from '@atj/forms'; import { FormService } from '@atj/form-service'; import Form, { type FormUIContext } from '../../Form'; @@ -12,7 +12,7 @@ export default function FormPreview({ context: FormUIContext; form: Blueprint; }) { - const session = createFormSession(form); + const session = createSession(form); return
; } diff --git a/packages/design/src/FormRouter/index.tsx b/packages/design/src/FormRouter/index.tsx index 39db9012..05544874 100644 --- a/packages/design/src/FormRouter/index.tsx +++ b/packages/design/src/FormRouter/index.tsx @@ -3,7 +3,7 @@ import { useParams, HashRouter, Route, Routes } from 'react-router-dom'; import { type FormService } from '@atj/form-service'; import Form, { type FormUIContext } from '../Form'; -import { createFormSession } from '@atj/forms'; +import { createSession } from '@atj/forms'; // Wrapper around Form that includes a client-side router for loading forms. export default function FormRouter({ @@ -34,7 +34,7 @@ export default function FormRouter({ ); } - const session = createFormSession(result.data); + const session = createSession(result.data); return ( { export const createTestSession = () => { const form = createTestForm(); - return createFormSession(form); + return createSession(form); }; diff --git a/packages/form-service/src/context/browser/session-repo.ts b/packages/form-service/src/context/browser/session-repo.ts index bb1bd610..3e7e12b7 100644 --- a/packages/form-service/src/context/browser/session-repo.ts +++ b/packages/form-service/src/context/browser/session-repo.ts @@ -1,10 +1,10 @@ import { type Result, type VoidResult } from '@atj/common'; -import { type FormSession } from '@atj/forms'; +import { type Session } from '@atj/forms'; export const getSessionFromStorage = ( storage: Storage, id?: string -): FormSession | null => { +): Session | null => { if (!storage || !id) { return null; } @@ -17,7 +17,7 @@ export const getSessionFromStorage = ( export const addFormToStorage = ( storage: Storage, - session: FormSession + session: Session ): Result => { const uuid = crypto.randomUUID(); @@ -35,7 +35,7 @@ export const addFormToStorage = ( export const saveSessionToStorage = ( storage: Storage, sessionId: string, - session: FormSession + session: Session ): VoidResult => { try { storage.setItem(sessionId, stringifySession(session)); @@ -57,10 +57,10 @@ export const deleteSessionFromStorage = ( storage.removeItem(sessionId); }; -const stringifySession = (session: FormSession) => { +const stringifySession = (session: Session) => { return JSON.stringify(session); }; -const parseStringSession = (sessionString: string): FormSession => { - return JSON.parse(sessionString) as FormSession; +const parseStringSession = (sessionString: string): Session => { + return JSON.parse(sessionString) as Session; }; diff --git a/packages/form-service/src/operations/submit-form.test.ts b/packages/form-service/src/operations/submit-form.test.ts index c27d8038..135ea844 100644 --- a/packages/form-service/src/operations/submit-form.test.ts +++ b/packages/form-service/src/operations/submit-form.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest'; -import { createForm, createFormSession } from '@atj/forms'; +import { createForm, createSession } from '@atj/forms'; import { createTestFormService } from '../context/test'; describe('submitForm', () => { @@ -12,7 +12,7 @@ describe('submitForm', () => { if (!formResult.success) { throw new Error('form not found'); } - const session = createFormSession(formResult.data); + const session = createSession(formResult.data); const result = await service.submitForm(session, 'test-form', {}); expect(result).toEqual({ success: true, diff --git a/packages/form-service/src/operations/submit-form.ts b/packages/form-service/src/operations/submit-form.ts index e0d46e16..794c5e4f 100644 --- a/packages/form-service/src/operations/submit-form.ts +++ b/packages/form-service/src/operations/submit-form.ts @@ -2,7 +2,7 @@ import { type Result } from '@atj/common'; import { type FormConfig, type Blueprint, - type FormSession, + type Session, applyPromptResponse, createFormOutputFieldData, fillPDF, @@ -14,7 +14,7 @@ import { getFormFromStorage } from '../context/browser/form-repo'; export const submitForm = async ( ctx: { storage: Storage; config: FormConfig }, //sessionId: string, - session: FormSession, // TODO: load session from storage by ID + session: Session, // TODO: load session from storage by ID formId: string, formData: Record ): Promise< @@ -32,7 +32,7 @@ export const submitForm = async ( error: 'Form not found', }); } - //const session = getSessionFromStorage(ctx.storage, sessionId) || createFormSession(form); + //const session = getSessionFromStorage(ctx.storage, sessionId) || createSession(form); // For now, the client-side is producing its own error messages. // In the future, we'll want this service to return errors to the client. const newSessionResult = applyPromptResponse(ctx.config, session, { diff --git a/packages/form-service/src/types.ts b/packages/form-service/src/types.ts index 8cc51342..bbfcf78b 100644 --- a/packages/form-service/src/types.ts +++ b/packages/form-service/src/types.ts @@ -1,5 +1,5 @@ import { Result, VoidResult } from '@atj/common'; -import { Blueprint, FormSession } from '@atj/forms'; +import { Blueprint, Session } from '@atj/forms'; import { FormListItem } from './operations/get-form-list'; @@ -11,7 +11,7 @@ export type FormService = { saveForm: (formId: string, form: Blueprint) => VoidResult; submitForm: ( //sessionId: string, - session: FormSession, // TODO: load session from storage by ID + session: Session, // TODO: load session from storage by ID formId: string, formData: Record ) => Promise>; diff --git a/packages/forms/src/elements/input.ts b/packages/forms/src/elements/input.ts index 18e8a8e9..96867bd3 100644 --- a/packages/forms/src/elements/input.ts +++ b/packages/forms/src/elements/input.ts @@ -2,7 +2,7 @@ import * as z from 'zod'; import { type Pattern, type PatternConfig } from '../element'; import { type PatternProps, type TextInputPattern } from '../pattern'; -import { getFormSessionValue } from '../session'; +import { getSessionValue } from '../session'; import { safeZodParse } from '../util/zod'; const configSchema = z.object({ @@ -31,7 +31,7 @@ export const inputConfig: PatternConfig = { }, createPrompt(_, session, element, options) { const extraAttributes: Record = {}; - const sessionValue = getFormSessionValue(session, element.id); + const sessionValue = getSessionValue(session, element.id); if (options.validate) { const isValidResult = validateElement(inputConfig, element, sessionValue); if (!isValidResult.success) { diff --git a/packages/forms/src/index.ts b/packages/forms/src/index.ts index b73617ac..1ccca85d 100644 --- a/packages/forms/src/index.ts +++ b/packages/forms/src/index.ts @@ -53,10 +53,10 @@ export type FormSummary = { description: string; }; -export type FormSessionId = string; +export type SessionId = string; type ErrorMap = Record; -export type FormSession = { - id: FormSessionId; +export type Session = { + id: SessionId; data: { errors: ErrorMap; values: PatternValueMap; @@ -105,7 +105,7 @@ export const getRootPattern = (form: Blueprint) => { return form.elements[form.root]; }; -export const createFormSession = (form: Blueprint): FormSession => { +export const createSession = (form: Blueprint): Session => { return { id: crypto.randomUUID(), data: { @@ -120,7 +120,7 @@ export const createFormSession = (form: Blueprint): FormSession => { }; }; -export const updateForm = (context: FormSession, id: PatternId, value: any) => { +export const updateForm = (context: Session, id: PatternId, value: any) => { if (!(id in context.form.elements)) { console.error(`Pattern "${id}" does not exist on form.`); return context; @@ -136,10 +136,10 @@ export const updateForm = (context: FormSession, id: PatternId, value: any) => { }; const addValue = ( - form: FormSession, + form: Session, id: PatternId, value: PatternValue -): FormSession => ({ +): Session => ({ ...form, data: { ...form.data, @@ -150,11 +150,7 @@ const addValue = ( }, }); -const addError = ( - session: FormSession, - id: PatternId, - error: string -): FormSession => ({ +const addError = (session: Session, id: PatternId, error: string): Session => ({ ...session, data: { ...session.data, diff --git a/packages/forms/src/pattern.ts b/packages/forms/src/pattern.ts index 37cef5b0..adacff8d 100644 --- a/packages/forms/src/pattern.ts +++ b/packages/forms/src/pattern.ts @@ -5,7 +5,7 @@ import { getRootPattern, } from '..'; import { getPatternConfig } from './element'; -import { type FormSession, nullSession, sessionIsComplete } from './session'; +import { type Session, nullSession, sessionIsComplete } from './session'; export type TextInputPattern = { type: 'input'; @@ -69,7 +69,7 @@ export type Prompt = { export const createPrompt = ( config: FormConfig, - session: FormSession, + session: Session, options: { validate: boolean } ): Prompt => { if (options.validate && sessionIsComplete(config, session)) { @@ -126,7 +126,7 @@ export const createPrompt = ( export type CreatePrompt = ( config: FormConfig, - session: FormSession, + session: Session, element: T, options: { validate: boolean } ) => PromptPart; diff --git a/packages/forms/src/response.ts b/packages/forms/src/response.ts index ec909a74..fdbbae29 100644 --- a/packages/forms/src/response.ts +++ b/packages/forms/src/response.ts @@ -8,7 +8,7 @@ import { validateElement, } from '.'; import { type PromptAction, createPrompt, isPromptAction } from './pattern'; -import { type FormSession, updateSession } from './session'; +import { type Session, updateSession } from './session'; export type PromptResponse = { action: PromptAction['type']; @@ -17,9 +17,9 @@ export type PromptResponse = { export const applyPromptResponse = ( config: FormConfig, - session: FormSession, + session: Session, response: PromptResponse -): Result => { +): Result => { // Get the current prompt for this session. const prompt = createPrompt(config, session, { validate: false }); if (!isPromptAction(prompt, response.action)) { @@ -39,7 +39,7 @@ export const applyPromptResponse = ( const parseElementValue = ( config: FormConfig, - session: FormSession, + session: Session, elementId: PatternId, promptValue: string ) => { @@ -49,7 +49,7 @@ const parseElementValue = ( }; const parsePromptResponse = ( - session: FormSession, + session: Session, config: FormConfig, response: PromptResponse ) => { diff --git a/packages/forms/src/session.ts b/packages/forms/src/session.ts index ac7a57ae..44ff75fd 100644 --- a/packages/forms/src/session.ts +++ b/packages/forms/src/session.ts @@ -14,7 +14,7 @@ import { type ErrorMap = Record; -export type FormSession = { +export type Session = { data: { errors: ErrorMap; values: PatternValueMap; @@ -22,7 +22,7 @@ export type FormSession = { form: Blueprint; }; -export const nullSession: FormSession = { +export const nullSession: Session = { data: { errors: {}, values: { @@ -50,7 +50,7 @@ export const nullSession: FormSession = { }, }; -export const createFormSession = (form: Blueprint): FormSession => { +export const createSession = (form: Blueprint): Session => { return { data: { errors: {}, @@ -64,18 +64,15 @@ export const createFormSession = (form: Blueprint): FormSession => { }; }; -export const getFormSessionValue = ( - session: FormSession, - elementId: PatternId -) => { +export const getSessionValue = (session: Session, elementId: PatternId) => { return session.data.values[elementId]; }; export const updateSessionValue = ( - session: FormSession, + session: Session, id: PatternId, value: PatternValue -): FormSession => { +): Session => { if (!(id in session.form.elements)) { console.error(`Pattern "${id}" does not exist on form.`); return session; @@ -91,10 +88,10 @@ export const updateSessionValue = ( }; export const updateSession = ( - session: FormSession, + session: Session, values: PatternValueMap, errors: ErrorMap -): FormSession => { +): Session => { const keysValid = Object.keys(values).every( elementId => elementId in session.form.elements @@ -118,20 +115,20 @@ export const updateSession = ( }; }; -export const sessionIsComplete = (config: FormConfig, session: FormSession) => { +export const sessionIsComplete = (config: FormConfig, session: Session) => { return Object.values(session.form.elements).every(element => { const elementConfig = getPatternConfig(config, element.type); - const value = getFormSessionValue(session, element.id); + const value = getSessionValue(session, element.id); const isValidResult = validateElement(elementConfig, element, value); return isValidResult.success; }); }; const addValue = ( - form: FormSession, + form: Session, id: PatternId, value: PatternValue -): FormSession => ({ +): Session => ({ ...form, data: { ...form.data, @@ -142,11 +139,7 @@ const addValue = ( }, }); -const addError = ( - session: FormSession, - id: PatternId, - error: string -): FormSession => ({ +const addError = (session: Session, id: PatternId, error: string): Session => ({ ...session, data: { ...session.data, diff --git a/packages/forms/tests/two-field-form.test.ts b/packages/forms/tests/two-field-form.test.ts index 2a334759..1540dc87 100644 --- a/packages/forms/tests/two-field-form.test.ts +++ b/packages/forms/tests/two-field-form.test.ts @@ -54,12 +54,12 @@ describe('two element form session', () => { /* test('initializes', () => { - const session = forms.createFormSession(form); + const session = forms.createSession(form); expect(session).to.not.toBeNull(); }); test('empty field value on required field is stored with error', () => { - const session = forms.createFormSession(form); + const session = forms.createSession(form); const nextSession = forms.updateForm(session, elements[0].id, null); expect(nextSession).toEqual({ ...session, @@ -76,7 +76,7 @@ describe('two element form session', () => { }); test('valid field value is stored on session', () => { - const formSession = forms.createFormSession(form); + const formSession = forms.createSession(form); const nextSession = forms.updateForm( formSession, elements[0].id, @@ -95,7 +95,7 @@ describe('two element form session', () => { }); test('empty field value on non-required field is set with no errors on the session', () => { - const session = forms.createFormSession(form); + const session = forms.createSession(form); const session2 = forms.updateForm( session, elements[1].id, @@ -115,7 +115,7 @@ describe('two element form session', () => { }); test('valid field value on non-required field is stored on the session', () => { - const session = forms.createFormSession(form); + const session = forms.createSession(form); const nextSession = forms.updateForm( session, elements[1].id, @@ -138,7 +138,7 @@ describe('two element form session', () => { /* describe('two element prompt', () => { const config = forms.defaultFormConfig; - const session = forms.createFormSession(form); + const session = forms.createSession(form); test('includes a submit button', () => { const prompt = createPrompt(config, session, { validate: true }); expect(prompt.actions).toEqual([]); From 4874eb2fcfa7c55be9b3911668cd6126f3385751 Mon Sep 17 00:00:00 2001 From: Daniel Naab Date: Tue, 26 Mar 2024 21:07:47 -0500 Subject: [PATCH 08/18] Remove required attribute --- packages/design/src/test-form.ts | 3 --- packages/forms/src/documents/document.ts | 6 ------ packages/forms/src/element.ts | 1 - packages/forms/src/elements/input.ts | 2 +- packages/forms/src/index.ts | 11 +++++------ packages/forms/src/session.ts | 8 ++++---- 6 files changed, 10 insertions(+), 21 deletions(-) diff --git a/packages/design/src/test-form.ts b/packages/design/src/test-form.ts index 3ecde83b..65b75c03 100644 --- a/packages/design/src/test-form.ts +++ b/packages/design/src/test-form.ts @@ -25,7 +25,6 @@ export const createTestForm = () => { default: { elements: [], }, - required: true, }, { type: 'input', @@ -36,7 +35,6 @@ export const createTestForm = () => { initial: '', }, default: '', - required: true, }, { type: 'input', @@ -47,7 +45,6 @@ export const createTestForm = () => { initial: 'test', }, default: '', - required: true, }, ], } diff --git a/packages/forms/src/documents/document.ts b/packages/forms/src/documents/document.ts index eb0313ca..2b04def1 100644 --- a/packages/forms/src/documents/document.ts +++ b/packages/forms/src/documents/document.ts @@ -84,7 +84,6 @@ export const addDocumentFieldsToForm = ( required: false, maxLength: 128, }, - required: field.required, } satisfies InputElement); } else if (field.type === 'OptionList') { elements.push({ @@ -99,7 +98,6 @@ export const addDocumentFieldsToForm = ( required: false, maxLength: 128, }, - required: field.required, } satisfies InputElement); } else if (field.type === 'Dropdown') { elements.push({ @@ -114,7 +112,6 @@ export const addDocumentFieldsToForm = ( required: false, maxLength: 128, }, - required: field.required, } satisfies InputElement); } else if (field.type === 'TextField') { elements.push({ @@ -129,7 +126,6 @@ export const addDocumentFieldsToForm = ( required: false, maxLength: 128, }, - required: field.required, } satisfies InputElement); } else if (field.type === 'RadioGroup') { elements.push({ @@ -144,7 +140,6 @@ export const addDocumentFieldsToForm = ( required: false, maxLength: 128, }, - required: field.required, } satisfies InputElement); } else if (field.type === 'Paragraph') { // skip purely presentational fields @@ -161,7 +156,6 @@ export const addDocumentFieldsToForm = ( elements: elements.map(element => element.id), }, default: [], - required: true, }); return addPatterns(form, elements, 'root'); }; diff --git a/packages/forms/src/element.ts b/packages/forms/src/element.ts index 52a7a83b..6b15a847 100644 --- a/packages/forms/src/element.ts +++ b/packages/forms/src/element.ts @@ -8,7 +8,6 @@ export type Pattern = { id: PatternId; data: C; default: T; - required: boolean; }; export type PatternId = string; diff --git a/packages/forms/src/elements/input.ts b/packages/forms/src/elements/input.ts index 96867bd3..e5720aa2 100644 --- a/packages/forms/src/elements/input.ts +++ b/packages/forms/src/elements/input.ts @@ -1,6 +1,6 @@ import * as z from 'zod'; -import { type Pattern, type PatternConfig } from '../element'; +import { type Pattern, type PatternConfig, validateElement } from '../element'; import { type PatternProps, type TextInputPattern } from '../pattern'; import { getSessionValue } from '../session'; import { safeZodParse } from '../util/zod'; diff --git a/packages/forms/src/index.ts b/packages/forms/src/index.ts index 1ccca85d..16d00dac 100644 --- a/packages/forms/src/index.ts +++ b/packages/forms/src/index.ts @@ -1,11 +1,10 @@ -import { FormConfig } from './config'; -import { SequenceElement } from './config/elements/sequence'; -import { DocumentFieldMap } from './documents'; +import { type SequenceElement } from './elements/sequence'; +import { type DocumentFieldMap } from './documents'; import { + type FormConfig, type Pattern, type PatternId, type PatternMap, - type PatternValue, type PatternValueMap, getPatternMap, getPatternConfig, @@ -42,7 +41,6 @@ export const nullBlueprint: Blueprint = { default: { elements: [], }, - required: true, }, }, outputs: [], @@ -87,7 +85,6 @@ export const createForm = ( default: { elements: [], }, - required: true, } satisfies SequenceElement, ], root: 'root', @@ -120,6 +117,7 @@ export const createSession = (form: Blueprint): Session => { }; }; +/* export const updateForm = (context: Session, id: PatternId, value: any) => { if (!(id in context.form.elements)) { console.error(`Pattern "${id}" does not exist on form.`); @@ -160,6 +158,7 @@ const addError = (session: Session, id: PatternId, error: string): Session => ({ }, }, }); +*/ export const addPatternMap = ( form: Blueprint, diff --git a/packages/forms/src/session.ts b/packages/forms/src/session.ts index 44ff75fd..0e9fb1c9 100644 --- a/packages/forms/src/session.ts +++ b/packages/forms/src/session.ts @@ -50,17 +50,17 @@ export const nullSession: Session = { }, }; -export const createSession = (form: Blueprint): Session => { +export const createSession = (blueprint: Blueprint): Session => { return { data: { errors: {}, values: Object.fromEntries( - Object.values(form.elements).map(element => { - return [element.id, form.elements[element.id].default]; + Object.values(blueprint.elements).map(element => { + return [element.id, blueprint.elements[element.id].default]; }) ), }, - form, + form: blueprint, }; }; From 1a130a0bc380051f8ca38ddc67fc9b9c21a9194e Mon Sep 17 00:00:00 2001 From: Daniel Naab Date: Tue, 26 Mar 2024 21:29:39 -0500 Subject: [PATCH 09/18] Revert "Rename FormSession -> Session." This reverts commit 746802ae5f18d763b7633913e2347211af0e973e. --- packages/design/src/Form/index.tsx | 6 +- .../FormManager/DocumentImporter/index.tsx | 4 +- .../src/FormManager/FormEdit/Preview.tsx | 130 ++++++++++++++++-- .../FormEdit/preview-components.tsx | 107 -------------- .../design/src/FormManager/FormEdit/store.tsx | 5 - .../src/FormManager/FormPreview/index.tsx | 4 +- packages/design/src/FormRouter/index.tsx | 4 +- packages/design/src/test-form.ts | 4 +- .../src/context/browser/session-repo.ts | 14 +- .../src/operations/submit-form.test.ts | 4 +- .../src/operations/submit-form.ts | 6 +- packages/form-service/src/types.ts | 4 +- packages/forms/src/elements/input.ts | 4 +- packages/forms/src/index.ts | 18 ++- packages/forms/src/pattern.ts | 6 +- packages/forms/src/response.ts | 10 +- packages/forms/src/session.ts | 37 +++-- packages/forms/tests/two-field-form.test.ts | 12 +- 18 files changed, 194 insertions(+), 185 deletions(-) delete mode 100644 packages/design/src/FormManager/FormEdit/preview-components.tsx diff --git a/packages/design/src/Form/index.tsx b/packages/design/src/Form/index.tsx index 1d87e168..5295b4a1 100644 --- a/packages/design/src/Form/index.tsx +++ b/packages/design/src/Form/index.tsx @@ -6,7 +6,7 @@ import { applyPromptResponse, createPrompt, type FormConfig, - type Session, + type FormSession, type PatternProps, type Prompt, type PromptPart, @@ -33,7 +33,7 @@ export type PatternComponent> = const usePrompt = ( initialPrompt: Prompt, config: FormConfig, - session: Session + session: FormSession ) => { const [prompt, _setPrompt] = useState(initialPrompt); const setPrompt = (newPrompt: Prompt) => { @@ -63,7 +63,7 @@ export default function Form({ isPreview, // ideally this should be removed. just here now for the FFP demo }: { context: FormUIContext; - session: Session; + session: FormSession; onSubmit?: (data: Record) => void; isPreview?: boolean; }) { diff --git a/packages/design/src/FormManager/DocumentImporter/index.tsx b/packages/design/src/FormManager/DocumentImporter/index.tsx index 924e65a8..a969dc83 100644 --- a/packages/design/src/FormManager/DocumentImporter/index.tsx +++ b/packages/design/src/FormManager/DocumentImporter/index.tsx @@ -7,7 +7,7 @@ import { SAMPLE_DOCUMENTS, addDocument, addDocumentFieldsToForm, - createSession, + createFormSession, } from '@atj/forms'; import { type FormService } from '@atj/form-service'; @@ -147,7 +147,7 @@ const DocumentImporter = ({ <> { //handleFormSubmission(formId, data); console.log(formId, data); diff --git a/packages/design/src/FormManager/FormEdit/Preview.tsx b/packages/design/src/FormManager/FormEdit/Preview.tsx index 2477b5a3..045568be 100644 --- a/packages/design/src/FormManager/FormEdit/Preview.tsx +++ b/packages/design/src/FormManager/FormEdit/Preview.tsx @@ -1,26 +1,136 @@ import React from 'react'; -import { createSession } from '@atj/forms'; +import { type PatternProps, createFormSession } from '@atj/forms'; -import Form from '../../Form'; +import Form, { + type ComponentForPattern, + type PatternComponent, + type FormUIContext, +} from '../../Form'; import { useFormEditStore } from './store'; export const PreviewForm = () => { const uiContext = useFormEditStore(state => state.context); const form = useFormEditStore(state => state.form); - const disposable = createSession(form); // nullSession instead? + + const previewUiContext: FormUIContext = { + config: uiContext.config, + // TODO: We'll want to hoist this definition up to a higher level, so we + // don't have to regenerate it every time we render the form. + components: createPreviewComponents( + uiContext.components, + uiContext.uswdsRoot + ), + uswdsRoot: uiContext.uswdsRoot, + }; + const disposable = createFormSession(form); // nullSession instead? return ( ); }; + +const createPreviewComponents = ( + components: ComponentForPattern, + uswdsRoot: string +): ComponentForPattern => { + const previewComponents: ComponentForPattern = {}; + // TODO: Create a configurable way to to define preview components. + for (const [patternType, Component] of Object.entries(components)) { + if (patternType === 'sequence' || patternType === 'fieldset') { + previewComponents[patternType] = Component; + /* + previewComponents[patternType] = createSequencePatternPreviewComponent( + Component, + previewComponents + ); + */ + } else if (patternType === 'form-summary') { + previewComponents[patternType] = Component; + } else { + //previewComponents[patternType] = Component; + previewComponents[patternType] = createPatternPreviewComponent( + Component, + uswdsRoot + ); + } + } + return previewComponents; +}; + +/* +const createSequencePatternPreviewComponent = ( + Component: PatternComponent, + previewComponents: ComponentForPattern +) => { + const PatternPreviewSequenceComponent: PatternComponent = ({ + pattern, + }) => { + const { form, setSelectedElement } = usePreviewContext(); + const element = getPattern(form, pattern._elementId); + const Component = previewComponents[pattern.type]; + return ( + + + + ); + }; + return PatternPreviewSequenceComponent; +}; +*/ + +const createPatternPreviewComponent = ( + Component: PatternComponent, + uswdsRoot: string +) => { + const PatternPreviewComponent: PatternComponent = ({ + pattern, + }: { + pattern: Pattern; + }) => { + const selectedElement = useFormEditStore(state => state.selectedElement); + const handleEditClick = useFormEditStore(state => state.handleEditClick); + + const isSelected = selectedElement?.id === pattern._elementId; + const divClassNames = isSelected + ? 'form-group-row field-selected' + : 'form-group-row'; + + return ( +
+ + + + +
+ ); + }; + return PatternPreviewComponent; +}; diff --git a/packages/design/src/FormManager/FormEdit/preview-components.tsx b/packages/design/src/FormManager/FormEdit/preview-components.tsx deleted file mode 100644 index 251e81c1..00000000 --- a/packages/design/src/FormManager/FormEdit/preview-components.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import React from 'react'; - -import { type PatternProps } from '@atj/forms'; - -import { type PatternComponent, type ComponentForPattern } from '../../Form'; -import { useFormEditStore } from './store'; - -export const createPreviewComponents = ( - components: ComponentForPattern, - uswdsRoot: string -): ComponentForPattern => { - const previewComponents: ComponentForPattern = {}; - // TODO: Create a configurable way to to define preview components. - for (const [patternType, Component] of Object.entries(components)) { - if (patternType === 'sequence' || patternType === 'fieldset') { - previewComponents[patternType] = Component; - /* - previewComponents[patternType] = createSequencePatternPreviewComponent( - Component, - previewComponents - ); - */ - } else if (patternType === 'form-summary') { - previewComponents[patternType] = Component; - } else { - //previewComponents[patternType] = Component; - previewComponents[patternType] = createPatternPreviewComponent( - Component, - uswdsRoot - ); - } - } - return previewComponents; -}; - -const createPatternPreviewComponent = ( - Component: PatternComponent, - uswdsRoot: string -) => { - const PatternPreviewComponent: PatternComponent = ({ - pattern, - }: { - pattern: PatternProps; - }) => { - const selectedElement = useFormEditStore(state => state.selectedElement); - const handleEditClick = useFormEditStore(state => state.handleEditClick); - - const isSelected = selectedElement?.id === pattern._elementId; - const divClassNames = isSelected - ? 'form-group-row field-selected' - : 'form-group-row'; - - return ( -
- - - - -
- ); - }; - return PatternPreviewComponent; -}; - -/* -const createSequencePatternPreviewComponent = ( - Component: PatternComponent, - previewComponents: ComponentForPattern -) => { - const PatternPreviewSequenceComponent: PatternComponent = ({ - pattern, - }) => { - const { form, setSelectedElement } = usePreviewContext(); - const element = getPattern(form, pattern._elementId); - const Component = previewComponents[pattern.type]; - return ( - - - - ); - }; - return PatternPreviewSequenceComponent; -}; -*/ diff --git a/packages/design/src/FormManager/FormEdit/store.tsx b/packages/design/src/FormManager/FormEdit/store.tsx index cacc4c2b..2b8d20ff 100644 --- a/packages/design/src/FormManager/FormEdit/store.tsx +++ b/packages/design/src/FormManager/FormEdit/store.tsx @@ -10,10 +10,7 @@ import { FormBuilder, Pattern, } from '@atj/forms'; - -import { type ComponentForPattern } from '../../Form'; import { type FormEditUIContext } from './types'; -import { createPreviewComponents } from './preview-components'; const { Provider, useStore } = createContext>(); @@ -33,7 +30,6 @@ export const FormEditProvider = (props: { type FormEditState = { context: FormEditUIContext; - components: ComponentForPattern; form: Blueprint; selectedElement?: Pattern; @@ -51,7 +47,6 @@ const createFormEditStore = ({ }) => create((set, get) => ({ context, - components: createPreviewComponents(context.components, context.uswdsRoot), form, handleEditClick: (pattern: PatternProps) => { const state = get(); diff --git a/packages/design/src/FormManager/FormPreview/index.tsx b/packages/design/src/FormManager/FormPreview/index.tsx index 480d49b3..7dd933f8 100644 --- a/packages/design/src/FormManager/FormPreview/index.tsx +++ b/packages/design/src/FormManager/FormPreview/index.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { type Blueprint, createSession } from '@atj/forms'; +import { type Blueprint, createFormSession } from '@atj/forms'; import { FormService } from '@atj/form-service'; import Form, { type FormUIContext } from '../../Form'; @@ -12,7 +12,7 @@ export default function FormPreview({ context: FormUIContext; form: Blueprint; }) { - const session = createSession(form); + const session = createFormSession(form); return
; } diff --git a/packages/design/src/FormRouter/index.tsx b/packages/design/src/FormRouter/index.tsx index 05544874..39db9012 100644 --- a/packages/design/src/FormRouter/index.tsx +++ b/packages/design/src/FormRouter/index.tsx @@ -3,7 +3,7 @@ import { useParams, HashRouter, Route, Routes } from 'react-router-dom'; import { type FormService } from '@atj/form-service'; import Form, { type FormUIContext } from '../Form'; -import { createSession } from '@atj/forms'; +import { createFormSession } from '@atj/forms'; // Wrapper around Form that includes a client-side router for loading forms. export default function FormRouter({ @@ -34,7 +34,7 @@ export default function FormRouter({ ); } - const session = createSession(result.data); + const session = createFormSession(result.data); return ( { export const createTestSession = () => { const form = createTestForm(); - return createSession(form); + return createFormSession(form); }; diff --git a/packages/form-service/src/context/browser/session-repo.ts b/packages/form-service/src/context/browser/session-repo.ts index 3e7e12b7..bb1bd610 100644 --- a/packages/form-service/src/context/browser/session-repo.ts +++ b/packages/form-service/src/context/browser/session-repo.ts @@ -1,10 +1,10 @@ import { type Result, type VoidResult } from '@atj/common'; -import { type Session } from '@atj/forms'; +import { type FormSession } from '@atj/forms'; export const getSessionFromStorage = ( storage: Storage, id?: string -): Session | null => { +): FormSession | null => { if (!storage || !id) { return null; } @@ -17,7 +17,7 @@ export const getSessionFromStorage = ( export const addFormToStorage = ( storage: Storage, - session: Session + session: FormSession ): Result => { const uuid = crypto.randomUUID(); @@ -35,7 +35,7 @@ export const addFormToStorage = ( export const saveSessionToStorage = ( storage: Storage, sessionId: string, - session: Session + session: FormSession ): VoidResult => { try { storage.setItem(sessionId, stringifySession(session)); @@ -57,10 +57,10 @@ export const deleteSessionFromStorage = ( storage.removeItem(sessionId); }; -const stringifySession = (session: Session) => { +const stringifySession = (session: FormSession) => { return JSON.stringify(session); }; -const parseStringSession = (sessionString: string): Session => { - return JSON.parse(sessionString) as Session; +const parseStringSession = (sessionString: string): FormSession => { + return JSON.parse(sessionString) as FormSession; }; diff --git a/packages/form-service/src/operations/submit-form.test.ts b/packages/form-service/src/operations/submit-form.test.ts index 135ea844..c27d8038 100644 --- a/packages/form-service/src/operations/submit-form.test.ts +++ b/packages/form-service/src/operations/submit-form.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest'; -import { createForm, createSession } from '@atj/forms'; +import { createForm, createFormSession } from '@atj/forms'; import { createTestFormService } from '../context/test'; describe('submitForm', () => { @@ -12,7 +12,7 @@ describe('submitForm', () => { if (!formResult.success) { throw new Error('form not found'); } - const session = createSession(formResult.data); + const session = createFormSession(formResult.data); const result = await service.submitForm(session, 'test-form', {}); expect(result).toEqual({ success: true, diff --git a/packages/form-service/src/operations/submit-form.ts b/packages/form-service/src/operations/submit-form.ts index 794c5e4f..e0d46e16 100644 --- a/packages/form-service/src/operations/submit-form.ts +++ b/packages/form-service/src/operations/submit-form.ts @@ -2,7 +2,7 @@ import { type Result } from '@atj/common'; import { type FormConfig, type Blueprint, - type Session, + type FormSession, applyPromptResponse, createFormOutputFieldData, fillPDF, @@ -14,7 +14,7 @@ import { getFormFromStorage } from '../context/browser/form-repo'; export const submitForm = async ( ctx: { storage: Storage; config: FormConfig }, //sessionId: string, - session: Session, // TODO: load session from storage by ID + session: FormSession, // TODO: load session from storage by ID formId: string, formData: Record ): Promise< @@ -32,7 +32,7 @@ export const submitForm = async ( error: 'Form not found', }); } - //const session = getSessionFromStorage(ctx.storage, sessionId) || createSession(form); + //const session = getSessionFromStorage(ctx.storage, sessionId) || createFormSession(form); // For now, the client-side is producing its own error messages. // In the future, we'll want this service to return errors to the client. const newSessionResult = applyPromptResponse(ctx.config, session, { diff --git a/packages/form-service/src/types.ts b/packages/form-service/src/types.ts index bbfcf78b..8cc51342 100644 --- a/packages/form-service/src/types.ts +++ b/packages/form-service/src/types.ts @@ -1,5 +1,5 @@ import { Result, VoidResult } from '@atj/common'; -import { Blueprint, Session } from '@atj/forms'; +import { Blueprint, FormSession } from '@atj/forms'; import { FormListItem } from './operations/get-form-list'; @@ -11,7 +11,7 @@ export type FormService = { saveForm: (formId: string, form: Blueprint) => VoidResult; submitForm: ( //sessionId: string, - session: Session, // TODO: load session from storage by ID + session: FormSession, // TODO: load session from storage by ID formId: string, formData: Record ) => Promise>; diff --git a/packages/forms/src/elements/input.ts b/packages/forms/src/elements/input.ts index e5720aa2..ffb2f0ca 100644 --- a/packages/forms/src/elements/input.ts +++ b/packages/forms/src/elements/input.ts @@ -2,7 +2,7 @@ import * as z from 'zod'; import { type Pattern, type PatternConfig, validateElement } from '../element'; import { type PatternProps, type TextInputPattern } from '../pattern'; -import { getSessionValue } from '../session'; +import { getFormSessionValue } from '../session'; import { safeZodParse } from '../util/zod'; const configSchema = z.object({ @@ -31,7 +31,7 @@ export const inputConfig: PatternConfig = { }, createPrompt(_, session, element, options) { const extraAttributes: Record = {}; - const sessionValue = getSessionValue(session, element.id); + const sessionValue = getFormSessionValue(session, element.id); if (options.validate) { const isValidResult = validateElement(inputConfig, element, sessionValue); if (!isValidResult.success) { diff --git a/packages/forms/src/index.ts b/packages/forms/src/index.ts index 16d00dac..ece6d4cf 100644 --- a/packages/forms/src/index.ts +++ b/packages/forms/src/index.ts @@ -51,10 +51,10 @@ export type FormSummary = { description: string; }; -export type SessionId = string; +export type FormSessionId = string; type ErrorMap = Record; -export type Session = { - id: SessionId; +export type FormSession = { + id: FormSessionId; data: { errors: ErrorMap; values: PatternValueMap; @@ -102,7 +102,7 @@ export const getRootPattern = (form: Blueprint) => { return form.elements[form.root]; }; -export const createSession = (form: Blueprint): Session => { +export const createFormSession = (form: Blueprint): FormSession => { return { id: crypto.randomUUID(), data: { @@ -134,10 +134,10 @@ export const updateForm = (context: Session, id: PatternId, value: any) => { }; const addValue = ( - form: Session, + form: FormSession, id: PatternId, value: PatternValue -): Session => ({ +): FormSession => ({ ...form, data: { ...form.data, @@ -148,7 +148,11 @@ const addValue = ( }, }); -const addError = (session: Session, id: PatternId, error: string): Session => ({ +const addError = ( + session: FormSession, + id: PatternId, + error: string +): FormSession => ({ ...session, data: { ...session.data, diff --git a/packages/forms/src/pattern.ts b/packages/forms/src/pattern.ts index adacff8d..37cef5b0 100644 --- a/packages/forms/src/pattern.ts +++ b/packages/forms/src/pattern.ts @@ -5,7 +5,7 @@ import { getRootPattern, } from '..'; import { getPatternConfig } from './element'; -import { type Session, nullSession, sessionIsComplete } from './session'; +import { type FormSession, nullSession, sessionIsComplete } from './session'; export type TextInputPattern = { type: 'input'; @@ -69,7 +69,7 @@ export type Prompt = { export const createPrompt = ( config: FormConfig, - session: Session, + session: FormSession, options: { validate: boolean } ): Prompt => { if (options.validate && sessionIsComplete(config, session)) { @@ -126,7 +126,7 @@ export const createPrompt = ( export type CreatePrompt = ( config: FormConfig, - session: Session, + session: FormSession, element: T, options: { validate: boolean } ) => PromptPart; diff --git a/packages/forms/src/response.ts b/packages/forms/src/response.ts index fdbbae29..ec909a74 100644 --- a/packages/forms/src/response.ts +++ b/packages/forms/src/response.ts @@ -8,7 +8,7 @@ import { validateElement, } from '.'; import { type PromptAction, createPrompt, isPromptAction } from './pattern'; -import { type Session, updateSession } from './session'; +import { type FormSession, updateSession } from './session'; export type PromptResponse = { action: PromptAction['type']; @@ -17,9 +17,9 @@ export type PromptResponse = { export const applyPromptResponse = ( config: FormConfig, - session: Session, + session: FormSession, response: PromptResponse -): Result => { +): Result => { // Get the current prompt for this session. const prompt = createPrompt(config, session, { validate: false }); if (!isPromptAction(prompt, response.action)) { @@ -39,7 +39,7 @@ export const applyPromptResponse = ( const parseElementValue = ( config: FormConfig, - session: Session, + session: FormSession, elementId: PatternId, promptValue: string ) => { @@ -49,7 +49,7 @@ const parseElementValue = ( }; const parsePromptResponse = ( - session: Session, + session: FormSession, config: FormConfig, response: PromptResponse ) => { diff --git a/packages/forms/src/session.ts b/packages/forms/src/session.ts index 0e9fb1c9..97158b44 100644 --- a/packages/forms/src/session.ts +++ b/packages/forms/src/session.ts @@ -5,7 +5,7 @@ import { getPatternConfig, validateElement, } from '.'; -import { SequenceElement } from './config/elements/sequence'; +import { SequenceElement } from './elements/sequence'; import { type PatternId, type PatternValue, @@ -14,7 +14,7 @@ import { type ErrorMap = Record; -export type Session = { +export type FormSession = { data: { errors: ErrorMap; values: PatternValueMap; @@ -22,7 +22,7 @@ export type Session = { form: Blueprint; }; -export const nullSession: Session = { +export const nullSession: FormSession = { data: { errors: {}, values: { @@ -50,7 +50,7 @@ export const nullSession: Session = { }, }; -export const createSession = (blueprint: Blueprint): Session => { +export const createSession = (blueprint: Blueprint): FormSession => { return { data: { errors: {}, @@ -64,15 +64,18 @@ export const createSession = (blueprint: Blueprint): Session => { }; }; -export const getSessionValue = (session: Session, elementId: PatternId) => { +export const getFormSessionValue = ( + session: FormSession, + elementId: PatternId +) => { return session.data.values[elementId]; }; export const updateSessionValue = ( - session: Session, + session: FormSession, id: PatternId, value: PatternValue -): Session => { +): FormSession => { if (!(id in session.form.elements)) { console.error(`Pattern "${id}" does not exist on form.`); return session; @@ -80,7 +83,7 @@ export const updateSessionValue = ( const nextSession = addValue(session, id, value); const element = session.form.elements[id]; if (element.type === 'input') { - if (element.required && !value) { + if (element && !value) { return addError(nextSession, id, 'Required value not provided.'); } } @@ -88,10 +91,10 @@ export const updateSessionValue = ( }; export const updateSession = ( - session: Session, + session: FormSession, values: PatternValueMap, errors: ErrorMap -): Session => { +): FormSession => { const keysValid = Object.keys(values).every( elementId => elementId in session.form.elements @@ -115,20 +118,20 @@ export const updateSession = ( }; }; -export const sessionIsComplete = (config: FormConfig, session: Session) => { +export const sessionIsComplete = (config: FormConfig, session: FormSession) => { return Object.values(session.form.elements).every(element => { const elementConfig = getPatternConfig(config, element.type); - const value = getSessionValue(session, element.id); + const value = getFormSessionValue(session, element.id); const isValidResult = validateElement(elementConfig, element, value); return isValidResult.success; }); }; const addValue = ( - form: Session, + form: FormSession, id: PatternId, value: PatternValue -): Session => ({ +): FormSession => ({ ...form, data: { ...form.data, @@ -139,7 +142,11 @@ const addValue = ( }, }); -const addError = (session: Session, id: PatternId, error: string): Session => ({ +const addError = ( + session: FormSession, + id: PatternId, + error: string +): FormSession => ({ ...session, data: { ...session.data, diff --git a/packages/forms/tests/two-field-form.test.ts b/packages/forms/tests/two-field-form.test.ts index 1540dc87..2a334759 100644 --- a/packages/forms/tests/two-field-form.test.ts +++ b/packages/forms/tests/two-field-form.test.ts @@ -54,12 +54,12 @@ describe('two element form session', () => { /* test('initializes', () => { - const session = forms.createSession(form); + const session = forms.createFormSession(form); expect(session).to.not.toBeNull(); }); test('empty field value on required field is stored with error', () => { - const session = forms.createSession(form); + const session = forms.createFormSession(form); const nextSession = forms.updateForm(session, elements[0].id, null); expect(nextSession).toEqual({ ...session, @@ -76,7 +76,7 @@ describe('two element form session', () => { }); test('valid field value is stored on session', () => { - const formSession = forms.createSession(form); + const formSession = forms.createFormSession(form); const nextSession = forms.updateForm( formSession, elements[0].id, @@ -95,7 +95,7 @@ describe('two element form session', () => { }); test('empty field value on non-required field is set with no errors on the session', () => { - const session = forms.createSession(form); + const session = forms.createFormSession(form); const session2 = forms.updateForm( session, elements[1].id, @@ -115,7 +115,7 @@ describe('two element form session', () => { }); test('valid field value on non-required field is stored on the session', () => { - const session = forms.createSession(form); + const session = forms.createFormSession(form); const nextSession = forms.updateForm( session, elements[1].id, @@ -138,7 +138,7 @@ describe('two element form session', () => { /* describe('two element prompt', () => { const config = forms.defaultFormConfig; - const session = forms.createSession(form); + const session = forms.createFormSession(form); test('includes a submit button', () => { const prompt = createPrompt(config, session, { validate: true }); expect(prompt.actions).toEqual([]); From 02a5ebde91456c4c915f719181307d6b14b85ff9 Mon Sep 17 00:00:00 2001 From: Daniel Naab Date: Tue, 26 Mar 2024 21:34:18 -0500 Subject: [PATCH 10/18] Rename Pattern.default to Pattern.initial --- packages/design/src/test-form.ts | 6 +++--- packages/forms/src/documents/document.ts | 12 ++++++------ packages/forms/src/documents/pdf/mock-api.ts | 15 +++++---------- packages/forms/src/element.ts | 4 ++-- packages/forms/src/index.ts | 4 ++-- packages/forms/src/session.ts | 4 ++-- packages/forms/tests/two-field-form.test.ts | 9 +++------ 7 files changed, 23 insertions(+), 31 deletions(-) diff --git a/packages/design/src/test-form.ts b/packages/design/src/test-form.ts index eabe3f31..3e2c847c 100644 --- a/packages/design/src/test-form.ts +++ b/packages/design/src/test-form.ts @@ -22,7 +22,7 @@ export const createTestForm = () => { data: { elements: ['element-1', 'element-2'], }, - default: { + initial: { elements: [], }, }, @@ -34,7 +34,7 @@ export const createTestForm = () => { required: true, initial: '', }, - default: '', + initial: '', }, { type: 'input', @@ -44,7 +44,7 @@ export const createTestForm = () => { required: false, initial: 'test', }, - default: '', + initial: '', }, ], } diff --git a/packages/forms/src/documents/document.ts b/packages/forms/src/documents/document.ts index 2b04def1..205bd642 100644 --- a/packages/forms/src/documents/document.ts +++ b/packages/forms/src/documents/document.ts @@ -78,7 +78,7 @@ export const addDocumentFieldsToForm = ( data: { label: field.label, }, - default: { + initial: { label: '', initial: '', required: false, @@ -92,7 +92,7 @@ export const addDocumentFieldsToForm = ( data: { label: field.label, }, - default: { + initial: { label: '', initial: '', required: false, @@ -106,7 +106,7 @@ export const addDocumentFieldsToForm = ( data: { label: field.label, }, - default: { + initial: { label: '', initial: '', required: false, @@ -120,7 +120,7 @@ export const addDocumentFieldsToForm = ( data: { label: field.label, }, - default: { + initial: { label: '', initial: '', required: false, @@ -134,7 +134,7 @@ export const addDocumentFieldsToForm = ( data: { label: field.label, }, - default: { + initial: { label: '', initial: '', required: false, @@ -155,7 +155,7 @@ export const addDocumentFieldsToForm = ( data: { elements: elements.map(element => element.id), }, - default: [], + initial: [], }); return addPatterns(form, elements, 'root'); }; diff --git a/packages/forms/src/documents/pdf/mock-api.ts b/packages/forms/src/documents/pdf/mock-api.ts index f07c3ec5..67f0d34f 100644 --- a/packages/forms/src/documents/pdf/mock-api.ts +++ b/packages/forms/src/documents/pdf/mock-api.ts @@ -111,7 +111,7 @@ export const parseAlabamaNameChangeForm = (): ParsedPdf => { parsedPdf.elements[element.id] = { type: 'paragraph', id: element.id, - default: { + initial: { text: '', maxLength: 2048, }, @@ -119,7 +119,6 @@ export const parseAlabamaNameChangeForm = (): ParsedPdf => { text: element.element_params.text, style: element.element_params.text_style, }, - required: false, } satisfies ParagraphElement; rootSequence.push(element.id); continue; @@ -130,7 +129,7 @@ export const parseAlabamaNameChangeForm = (): ParsedPdf => { parsedPdf.elements[id] = { type: 'input', id, - default: { + initial: { required: false, label: '', initial: '', @@ -139,7 +138,6 @@ export const parseAlabamaNameChangeForm = (): ParsedPdf => { data: { label: input.input_params.instructions, }, - required: false, } satisfies InputElement; fieldsetElements.push(id); parsedPdf.outputs[id] = { @@ -160,10 +158,9 @@ export const parseAlabamaNameChangeForm = (): ParsedPdf => { legend: element.element_params.text, elements: fieldsetElements, }, - default: { + initial: { elements: [], }, - required: true, } as FieldsetElement; rootSequence.push(element.id); } @@ -174,10 +171,9 @@ export const parseAlabamaNameChangeForm = (): ParsedPdf => { data: { elements: rootSequence, }, - default: { + initial: { elements: [], }, - required: true, }; return parsedPdf; }; @@ -189,11 +185,10 @@ const getElementInputs = (element: ExtractedElement): Pattern[] => { return { type: 'input', id: input.input_params.output_id, - default: {} as unknown as any, + initial: {} as unknown as any, data: { label: input.input_params.instructions, }, - required: true, } satisfies InputElement; } return null as unknown as Pattern; diff --git a/packages/forms/src/element.ts b/packages/forms/src/element.ts index 6b15a847..578e17de 100644 --- a/packages/forms/src/element.ts +++ b/packages/forms/src/element.ts @@ -7,11 +7,11 @@ export type Pattern = { type: string; id: PatternId; data: C; - default: T; + initial: T; }; export type PatternId = string; -export type PatternValue = T['default']; +export type PatternValue = T['initial']; export type PatternValueMap = Record; export type PatternMap = Record; export type GetPattern = (form: Blueprint, id: PatternId) => Pattern; diff --git a/packages/forms/src/index.ts b/packages/forms/src/index.ts index ece6d4cf..c626fb5c 100644 --- a/packages/forms/src/index.ts +++ b/packages/forms/src/index.ts @@ -38,7 +38,7 @@ export const nullBlueprint: Blueprint = { data: { elements: [], }, - default: { + initial: { elements: [], }, }, @@ -82,7 +82,7 @@ export const createForm = ( data: { elements: [], }, - default: { + initial: { elements: [], }, } satisfies SequenceElement, diff --git a/packages/forms/src/session.ts b/packages/forms/src/session.ts index 97158b44..4bbd277c 100644 --- a/packages/forms/src/session.ts +++ b/packages/forms/src/session.ts @@ -35,7 +35,7 @@ export const nullSession: FormSession = { id: 'root', type: 'sequence', required: false, - default: { + initial: { elements: [], }, data: {}, @@ -56,7 +56,7 @@ export const createSession = (blueprint: Blueprint): FormSession => { errors: {}, values: Object.fromEntries( Object.values(blueprint.elements).map(element => { - return [element.id, blueprint.elements[element.id].default]; + return [element.id, blueprint.elements[element.id].initial]; }) ), }, diff --git a/packages/forms/tests/two-field-form.test.ts b/packages/forms/tests/two-field-form.test.ts index 2a334759..305c3dc9 100644 --- a/packages/forms/tests/two-field-form.test.ts +++ b/packages/forms/tests/two-field-form.test.ts @@ -9,10 +9,9 @@ const elements: forms.Pattern[] = [ data: { elements: ['element-1', 'element-2'], }, - default: { + initial: { elements: [], }, - required: true, }, { type: 'input', @@ -22,8 +21,7 @@ const elements: forms.Pattern[] = [ initial: '', required: true, }, - default: '', - required: true, + initial: '', }, { type: 'input', @@ -33,8 +31,7 @@ const elements: forms.Pattern[] = [ initial: '', required: false, }, - default: '', - required: true, + initial: '', }, ]; const form = forms.createForm( From c8dda43c919303aefa7f3d084dd8d1914f86cfd3 Mon Sep 17 00:00:00 2001 From: Daniel Naab Date: Tue, 26 Mar 2024 21:42:17 -0500 Subject: [PATCH 11/18] Remove ambiguity around createSession / createFormSession --- packages/forms/src/index.ts | 27 --------------------------- packages/forms/src/session.ts | 8 ++++---- 2 files changed, 4 insertions(+), 31 deletions(-) diff --git a/packages/forms/src/index.ts b/packages/forms/src/index.ts index c626fb5c..53a003fa 100644 --- a/packages/forms/src/index.ts +++ b/packages/forms/src/index.ts @@ -5,7 +5,6 @@ import { type Pattern, type PatternId, type PatternMap, - type PatternValueMap, getPatternMap, getPatternConfig, } from './element'; @@ -51,17 +50,6 @@ export type FormSummary = { description: string; }; -export type FormSessionId = string; -type ErrorMap = Record; -export type FormSession = { - id: FormSessionId; - data: { - errors: ErrorMap; - values: PatternValueMap; - }; - form: Blueprint; -}; - export type FormOutput = { data: Uint8Array; path: string; @@ -102,21 +90,6 @@ export const getRootPattern = (form: Blueprint) => { return form.elements[form.root]; }; -export const createFormSession = (form: Blueprint): FormSession => { - return { - id: crypto.randomUUID(), - data: { - errors: {}, - values: Object.fromEntries( - Object.values(form.elements).map((element, index) => { - return [element.id, form.elements[element.id].data.initial]; - }) - ), - }, - form, - }; -}; - /* export const updateForm = (context: Session, id: PatternId, value: any) => { if (!(id in context.form.elements)) { diff --git a/packages/forms/src/session.ts b/packages/forms/src/session.ts index 4bbd277c..575614fb 100644 --- a/packages/forms/src/session.ts +++ b/packages/forms/src/session.ts @@ -50,17 +50,17 @@ export const nullSession: FormSession = { }, }; -export const createSession = (blueprint: Blueprint): FormSession => { +export const createFormSession = (form: Blueprint): FormSession => { return { data: { errors: {}, values: Object.fromEntries( - Object.values(blueprint.elements).map(element => { - return [element.id, blueprint.elements[element.id].initial]; + Object.values(form.elements).map((element, index) => { + return [element.id, form.elements[element.id].data.initial]; }) ), }, - form: blueprint, + form, }; }; From b1ef27f131a7a14288924e9a6adb76d5d46a9e27 Mon Sep 17 00:00:00 2001 From: Daniel Naab Date: Wed, 27 Mar 2024 09:11:56 -0500 Subject: [PATCH 12/18] Rename forms/elements to forms/patterns --- packages/design/src/FormManager/FormEdit/DraggableList.tsx | 2 +- packages/design/src/config/edit/FormSummaryEdit.tsx | 2 +- packages/design/src/config/edit/InputElementEdit.tsx | 2 +- packages/design/src/config/edit/ParagraphElementEdit.tsx | 2 +- packages/design/src/config/edit/SequenceElementEdit.tsx | 2 +- .../design/src/config/edit/SubmissionConfirmationEdit.tsx | 2 +- packages/design/src/config/view/Sequence/index.tsx | 2 +- packages/forms/src/config.ts | 2 +- packages/forms/src/documents/document.ts | 2 +- packages/forms/src/documents/pdf/mock-api.ts | 6 +++--- packages/forms/src/index.ts | 2 +- packages/forms/src/{elements => patterns}/fieldset.ts | 0 packages/forms/src/{elements => patterns}/form-summary.ts | 0 packages/forms/src/{elements => patterns}/index.ts | 0 packages/forms/src/{elements => patterns}/input.ts | 0 packages/forms/src/{elements => patterns}/paragraph.ts | 0 packages/forms/src/{elements => patterns}/sequence.ts | 0 packages/forms/src/session.ts | 2 +- 18 files changed, 14 insertions(+), 14 deletions(-) rename packages/forms/src/{elements => patterns}/fieldset.ts (100%) rename packages/forms/src/{elements => patterns}/form-summary.ts (100%) rename packages/forms/src/{elements => patterns}/index.ts (100%) rename packages/forms/src/{elements => patterns}/input.ts (100%) rename packages/forms/src/{elements => patterns}/paragraph.ts (100%) rename packages/forms/src/{elements => patterns}/sequence.ts (100%) diff --git a/packages/design/src/FormManager/FormEdit/DraggableList.tsx b/packages/design/src/FormManager/FormEdit/DraggableList.tsx index 2fdaf31c..3cfde08c 100644 --- a/packages/design/src/FormManager/FormEdit/DraggableList.tsx +++ b/packages/design/src/FormManager/FormEdit/DraggableList.tsx @@ -23,7 +23,7 @@ import { PatternId, } from '@atj/forms'; -import { SequenceElement } from '@atj/forms/src/elements/sequence'; +import { SequenceElement } from '@atj/forms/src/patterns/sequence'; const SortableItem = ({ id, diff --git a/packages/design/src/config/edit/FormSummaryEdit.tsx b/packages/design/src/config/edit/FormSummaryEdit.tsx index 25ba1c44..ee724ac9 100644 --- a/packages/design/src/config/edit/FormSummaryEdit.tsx +++ b/packages/design/src/config/edit/FormSummaryEdit.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { useFormContext } from 'react-hook-form'; -import { type FormSummary } from '@atj/forms/src/elements/form-summary'; +import { type FormSummary } from '@atj/forms/src/patterns/form-summary'; import { PatternEditComponent } from '../../FormManager/FormEdit/types'; const FormSummaryEdit: PatternEditComponent = ({ element }) => { diff --git a/packages/design/src/config/edit/InputElementEdit.tsx b/packages/design/src/config/edit/InputElementEdit.tsx index 6f4e141f..5ae2ea2c 100644 --- a/packages/design/src/config/edit/InputElementEdit.tsx +++ b/packages/design/src/config/edit/InputElementEdit.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { useFormContext } from 'react-hook-form'; -import { type InputElement } from '@atj/forms/src/elements/input'; +import { type InputElement } from '@atj/forms/src/patterns/input'; import { PatternEditComponent } from '../../FormManager/FormEdit/types'; const InputElementEdit: PatternEditComponent = ({ element }) => { diff --git a/packages/design/src/config/edit/ParagraphElementEdit.tsx b/packages/design/src/config/edit/ParagraphElementEdit.tsx index 843a32d6..10b38baa 100644 --- a/packages/design/src/config/edit/ParagraphElementEdit.tsx +++ b/packages/design/src/config/edit/ParagraphElementEdit.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { useFormContext } from 'react-hook-form'; -import { type ParagraphElement } from '@atj/forms/src/elements/paragraph'; +import { type ParagraphElement } from '@atj/forms/src/patterns/paragraph'; import { type PatternEditComponent } from '../../FormManager/FormEdit/types'; diff --git a/packages/design/src/config/edit/SequenceElementEdit.tsx b/packages/design/src/config/edit/SequenceElementEdit.tsx index 35ce5574..9652304c 100644 --- a/packages/design/src/config/edit/SequenceElementEdit.tsx +++ b/packages/design/src/config/edit/SequenceElementEdit.tsx @@ -18,7 +18,7 @@ import { CSS } from '@dnd-kit/utilities'; import { useFormContext } from 'react-hook-form'; import { type Blueprint, type Pattern } from '@atj/forms'; -import { type SequenceElement } from '@atj/forms/src/elements/sequence'; +import { type SequenceElement } from '@atj/forms/src/patterns/sequence'; import { type FormEditUIContext, type PatternEditComponent, diff --git a/packages/design/src/config/edit/SubmissionConfirmationEdit.tsx b/packages/design/src/config/edit/SubmissionConfirmationEdit.tsx index e6ba7212..bff839ed 100644 --- a/packages/design/src/config/edit/SubmissionConfirmationEdit.tsx +++ b/packages/design/src/config/edit/SubmissionConfirmationEdit.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { useFormContext } from 'react-hook-form'; -import { type InputElement } from '@atj/forms/src/elements/input'; +import { type InputElement } from '@atj/forms/src/patterns/input'; import { type PatternEditComponent } from '../../FormManager/FormEdit/types'; const InputElementEdit: PatternEditComponent = ({ element }) => { diff --git a/packages/design/src/config/view/Sequence/index.tsx b/packages/design/src/config/view/Sequence/index.tsx index 03658894..8f055c3e 100644 --- a/packages/design/src/config/view/Sequence/index.tsx +++ b/packages/design/src/config/view/Sequence/index.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { type PatternProps } from '@atj/forms'; -import { type SequenceElement } from '@atj/forms/src/elements/sequence'; +import { type SequenceElement } from '@atj/forms/src/patterns/sequence'; import { type PatternComponent } from '../../../Form'; diff --git a/packages/forms/src/config.ts b/packages/forms/src/config.ts index bb2c8050..f77b1adc 100644 --- a/packages/forms/src/config.ts +++ b/packages/forms/src/config.ts @@ -1 +1 @@ -export { defaultFormConfig } from './elements'; +export { defaultFormConfig } from './patterns'; diff --git a/packages/forms/src/documents/document.ts b/packages/forms/src/documents/document.ts index 205bd642..dbc25216 100644 --- a/packages/forms/src/documents/document.ts +++ b/packages/forms/src/documents/document.ts @@ -6,7 +6,7 @@ import { addPatternMap, updateFormSummary, } from '..'; -import { InputElement } from '../config/elements/input'; +import { InputElement } from '../config/patterns/input'; import { PDFDocument, getDocumentFieldData } from './pdf'; import { getSuggestedPatternsFromCache } from './suggestions'; import { DocumentFieldMap } from './types'; diff --git a/packages/forms/src/documents/pdf/mock-api.ts b/packages/forms/src/documents/pdf/mock-api.ts index 67f0d34f..7561f21d 100644 --- a/packages/forms/src/documents/pdf/mock-api.ts +++ b/packages/forms/src/documents/pdf/mock-api.ts @@ -2,9 +2,9 @@ import * as z from 'zod'; import { type Pattern, type PatternId, type PatternMap } from '../..'; -import { ParagraphElement } from '../../config/elements/paragraph'; -import { InputElement } from '../../config/elements/input'; -import { FieldsetElement } from '../../config/elements/fieldset'; +import { ParagraphElement } from '../../config/patterns/paragraph'; +import { InputElement } from '../../config/patterns/input'; +import { FieldsetElement } from '../../config/patterns/fieldset'; import { stringToBase64 } from '../util'; import { DocumentFieldMap } from '../types'; diff --git a/packages/forms/src/index.ts b/packages/forms/src/index.ts index 53a003fa..b86e2e75 100644 --- a/packages/forms/src/index.ts +++ b/packages/forms/src/index.ts @@ -1,4 +1,4 @@ -import { type SequenceElement } from './elements/sequence'; +import { type SequenceElement } from './patterns/sequence'; import { type DocumentFieldMap } from './documents'; import { type FormConfig, diff --git a/packages/forms/src/elements/fieldset.ts b/packages/forms/src/patterns/fieldset.ts similarity index 100% rename from packages/forms/src/elements/fieldset.ts rename to packages/forms/src/patterns/fieldset.ts diff --git a/packages/forms/src/elements/form-summary.ts b/packages/forms/src/patterns/form-summary.ts similarity index 100% rename from packages/forms/src/elements/form-summary.ts rename to packages/forms/src/patterns/form-summary.ts diff --git a/packages/forms/src/elements/index.ts b/packages/forms/src/patterns/index.ts similarity index 100% rename from packages/forms/src/elements/index.ts rename to packages/forms/src/patterns/index.ts diff --git a/packages/forms/src/elements/input.ts b/packages/forms/src/patterns/input.ts similarity index 100% rename from packages/forms/src/elements/input.ts rename to packages/forms/src/patterns/input.ts diff --git a/packages/forms/src/elements/paragraph.ts b/packages/forms/src/patterns/paragraph.ts similarity index 100% rename from packages/forms/src/elements/paragraph.ts rename to packages/forms/src/patterns/paragraph.ts diff --git a/packages/forms/src/elements/sequence.ts b/packages/forms/src/patterns/sequence.ts similarity index 100% rename from packages/forms/src/elements/sequence.ts rename to packages/forms/src/patterns/sequence.ts diff --git a/packages/forms/src/session.ts b/packages/forms/src/session.ts index 575614fb..0ee5f0ed 100644 --- a/packages/forms/src/session.ts +++ b/packages/forms/src/session.ts @@ -5,7 +5,7 @@ import { getPatternConfig, validateElement, } from '.'; -import { SequenceElement } from './elements/sequence'; +import { SequenceElement } from './patterns/sequence'; import { type PatternId, type PatternValue, From c823d1d1626b2e66d5a3a57403ba1cc74418fd17 Mon Sep 17 00:00:00 2001 From: Daniel Naab Date: Wed, 27 Mar 2024 09:21:29 -0500 Subject: [PATCH 13/18] Rename forms/pattern.ts to forms/components.ts --- packages/design/src/FormManager/FormEdit/DraggableList.tsx | 3 +-- packages/forms/src/{pattern.ts => components.ts} | 0 packages/forms/src/documents/document.ts | 2 +- packages/forms/src/documents/pdf/mock-api.ts | 6 +++--- packages/forms/src/element.ts | 2 +- packages/forms/src/index.ts | 2 +- packages/forms/src/patterns/fieldset.ts | 2 +- packages/forms/src/patterns/form-summary.ts | 2 +- packages/forms/src/patterns/input.ts | 2 +- packages/forms/src/patterns/paragraph.ts | 2 +- packages/forms/src/patterns/sequence.ts | 2 +- packages/forms/src/response.ts | 2 +- 12 files changed, 13 insertions(+), 14 deletions(-) rename packages/forms/src/{pattern.ts => components.ts} (100%) diff --git a/packages/design/src/FormManager/FormEdit/DraggableList.tsx b/packages/design/src/FormManager/FormEdit/DraggableList.tsx index 3cfde08c..72f11627 100644 --- a/packages/design/src/FormManager/FormEdit/DraggableList.tsx +++ b/packages/design/src/FormManager/FormEdit/DraggableList.tsx @@ -104,10 +104,9 @@ export const DraggableList: React.FC = ({ data: { elements: newOrder.map(element => element.id), }, - default: { + initial: { elements: [], }, - required: element.required, } satisfies SequenceElement); } }} diff --git a/packages/forms/src/pattern.ts b/packages/forms/src/components.ts similarity index 100% rename from packages/forms/src/pattern.ts rename to packages/forms/src/components.ts diff --git a/packages/forms/src/documents/document.ts b/packages/forms/src/documents/document.ts index dbc25216..6d1ae1d5 100644 --- a/packages/forms/src/documents/document.ts +++ b/packages/forms/src/documents/document.ts @@ -6,7 +6,7 @@ import { addPatternMap, updateFormSummary, } from '..'; -import { InputElement } from '../config/patterns/input'; +import { InputElement } from '../patterns/input'; import { PDFDocument, getDocumentFieldData } from './pdf'; import { getSuggestedPatternsFromCache } from './suggestions'; import { DocumentFieldMap } from './types'; diff --git a/packages/forms/src/documents/pdf/mock-api.ts b/packages/forms/src/documents/pdf/mock-api.ts index 7561f21d..0e09ae57 100644 --- a/packages/forms/src/documents/pdf/mock-api.ts +++ b/packages/forms/src/documents/pdf/mock-api.ts @@ -2,9 +2,9 @@ import * as z from 'zod'; import { type Pattern, type PatternId, type PatternMap } from '../..'; -import { ParagraphElement } from '../../config/patterns/paragraph'; -import { InputElement } from '../../config/patterns/input'; -import { FieldsetElement } from '../../config/patterns/fieldset'; +import { ParagraphElement } from '../../patterns/paragraph'; +import { InputElement } from '../../patterns/input'; +import { FieldsetElement } from '../../patterns/fieldset'; import { stringToBase64 } from '../util'; import { DocumentFieldMap } from '../types'; diff --git a/packages/forms/src/element.ts b/packages/forms/src/element.ts index 578e17de..56a8ef00 100644 --- a/packages/forms/src/element.ts +++ b/packages/forms/src/element.ts @@ -1,7 +1,7 @@ import { type Result } from '@atj/common'; import { type Blueprint } from '..'; -import { type CreatePrompt } from './pattern'; +import { type CreatePrompt } from './components'; export type Pattern = { type: string; diff --git a/packages/forms/src/index.ts b/packages/forms/src/index.ts index b86e2e75..0c23cf93 100644 --- a/packages/forms/src/index.ts +++ b/packages/forms/src/index.ts @@ -10,10 +10,10 @@ import { } from './element'; export * from './builder'; +export * from './components'; export * from './config'; export * from './documents'; export * from './element'; -export * from './pattern'; export * from './response'; export * from './session'; diff --git a/packages/forms/src/patterns/fieldset.ts b/packages/forms/src/patterns/fieldset.ts index 3c97c2a6..f8bd2272 100644 --- a/packages/forms/src/patterns/fieldset.ts +++ b/packages/forms/src/patterns/fieldset.ts @@ -10,7 +10,7 @@ import { type FieldsetPattern, type PatternProps, createPromptForElement, -} from '../pattern'; +} from '../components'; import { safeZodParse } from '../util/zod'; export type FieldsetElement = Pattern<{ diff --git a/packages/forms/src/patterns/form-summary.ts b/packages/forms/src/patterns/form-summary.ts index 299403fc..caa215f4 100644 --- a/packages/forms/src/patterns/form-summary.ts +++ b/packages/forms/src/patterns/form-summary.ts @@ -1,7 +1,7 @@ import * as z from 'zod'; import { type Pattern, type PatternConfig } from '../element'; -import { type FormSummaryPattern, type Pattern } from '../pattern'; +import { type PatternProps, type FormSummaryPattern } from '../components'; import { safeZodParse } from '../util/zod'; const configSchema = z.object({ diff --git a/packages/forms/src/patterns/input.ts b/packages/forms/src/patterns/input.ts index ffb2f0ca..3770c9da 100644 --- a/packages/forms/src/patterns/input.ts +++ b/packages/forms/src/patterns/input.ts @@ -1,7 +1,7 @@ import * as z from 'zod'; import { type Pattern, type PatternConfig, validateElement } from '../element'; -import { type PatternProps, type TextInputPattern } from '../pattern'; +import { type PatternProps, type TextInputPattern } from '../components'; import { getFormSessionValue } from '../session'; import { safeZodParse } from '../util/zod'; diff --git a/packages/forms/src/patterns/paragraph.ts b/packages/forms/src/patterns/paragraph.ts index 306186ee..5f14891a 100644 --- a/packages/forms/src/patterns/paragraph.ts +++ b/packages/forms/src/patterns/paragraph.ts @@ -1,7 +1,7 @@ import * as z from 'zod'; import { type Pattern, type PatternConfig } from '../element'; -import { type PatternProps, type ParagraphPattern } from '../pattern'; +import { type PatternProps, type ParagraphPattern } from '../components'; import { safeZodParse } from '../util/zod'; const configSchema = z.object({ diff --git a/packages/forms/src/patterns/sequence.ts b/packages/forms/src/patterns/sequence.ts index 1a9ec914..b35ac62b 100644 --- a/packages/forms/src/patterns/sequence.ts +++ b/packages/forms/src/patterns/sequence.ts @@ -6,7 +6,7 @@ import { type PatternId, getPattern, } from '../element'; -import { createPromptForElement } from '../pattern'; +import { createPromptForElement } from '../components'; import { safeZodParse } from '../util/zod'; export type SequenceElement = Pattern<{ diff --git a/packages/forms/src/response.ts b/packages/forms/src/response.ts index ec909a74..f70dca0f 100644 --- a/packages/forms/src/response.ts +++ b/packages/forms/src/response.ts @@ -7,7 +7,7 @@ import { getPatternConfig, validateElement, } from '.'; -import { type PromptAction, createPrompt, isPromptAction } from './pattern'; +import { type PromptAction, createPrompt, isPromptAction } from './components'; import { type FormSession, updateSession } from './session'; export type PromptResponse = { From 923a47f8f8fd5a19d0f6ef59d612e8001bf7d0bc Mon Sep 17 00:00:00 2001 From: Daniel Naab Date: Wed, 27 Mar 2024 09:29:55 -0500 Subject: [PATCH 14/18] To avoid confusion, remove "Pattern" from the name of component props. --- .../design/src/config/view/Fieldset/index.tsx | 4 ++-- .../view/FormSummary/FormSummary.stories.tsx | 6 +++--- .../src/config/view/FormSummary/index.tsx | 4 ++-- .../src/config/view/Paragraph/index.tsx | 4 ++-- .../SubmissionConfirmation.stories.tsx | 4 ++-- .../view/SubmissionConfirmation/index.tsx | 4 ++-- .../view/TextInput/TestInput.stories.tsx | 6 +++--- .../src/config/view/TextInput/index.tsx | 4 ++-- packages/forms/src/components.ts | 21 +++++++------------ packages/forms/src/patterns/fieldset.ts | 4 ++-- packages/forms/src/patterns/form-summary.ts | 4 ++-- packages/forms/src/patterns/input.ts | 4 ++-- packages/forms/src/patterns/paragraph.ts | 4 ++-- 13 files changed, 33 insertions(+), 40 deletions(-) diff --git a/packages/design/src/config/view/Fieldset/index.tsx b/packages/design/src/config/view/Fieldset/index.tsx index 0c4da614..bf1b6f32 100644 --- a/packages/design/src/config/view/Fieldset/index.tsx +++ b/packages/design/src/config/view/Fieldset/index.tsx @@ -1,10 +1,10 @@ import React from 'react'; -import { type FieldsetPattern, type PatternProps } from '@atj/forms'; +import { type FieldsetProps, type PatternProps } from '@atj/forms'; import { type PatternComponent } from '../../../Form'; -const FormSummary: PatternComponent> = ({ +const FormSummary: PatternComponent> = ({ pattern, children, }) => { diff --git a/packages/design/src/config/view/FormSummary/FormSummary.stories.tsx b/packages/design/src/config/view/FormSummary/FormSummary.stories.tsx index d0c838ac..e480aa66 100644 --- a/packages/design/src/config/view/FormSummary/FormSummary.stories.tsx +++ b/packages/design/src/config/view/FormSummary/FormSummary.stories.tsx @@ -1,7 +1,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import FormSummary from '.'; -import { type PatternProps, type FormSummaryPattern } from '@atj/forms'; +import { type PatternProps, type FormSummaryProps } from '@atj/forms'; export default { title: 'patterns/FormSummary', @@ -17,7 +17,7 @@ export const FormSummaryWithLongDescription = { title: 'Form title', description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', - } as PatternProps, + } as PatternProps, }, } satisfies StoryObj; @@ -28,6 +28,6 @@ export const FormSummaryWithShortDescription = { type: 'form-summary', title: 'Title 2', description: 'Short description', - } as PatternProps, + } as PatternProps, }, } satisfies StoryObj; diff --git a/packages/design/src/config/view/FormSummary/index.tsx b/packages/design/src/config/view/FormSummary/index.tsx index b9c377e8..8b011d90 100644 --- a/packages/design/src/config/view/FormSummary/index.tsx +++ b/packages/design/src/config/view/FormSummary/index.tsx @@ -1,9 +1,9 @@ import React from 'react'; -import { type PatternProps, type FormSummaryPattern } from '@atj/forms'; +import { type PatternProps, type FormSummaryProps } from '@atj/forms'; import { type PatternComponent } from '../../../Form'; -const FormSummary: PatternComponent> = ({ +const FormSummary: PatternComponent> = ({ pattern, }) => { return ( diff --git a/packages/design/src/config/view/Paragraph/index.tsx b/packages/design/src/config/view/Paragraph/index.tsx index d2f67884..c22626ee 100644 --- a/packages/design/src/config/view/Paragraph/index.tsx +++ b/packages/design/src/config/view/Paragraph/index.tsx @@ -1,10 +1,10 @@ import React from 'react'; -import { type ParagraphPattern, type PatternProps } from '@atj/forms'; +import { type ParagraphProps, type PatternProps } from '@atj/forms'; import { type PatternComponent } from '../../../Form'; -const FormSummary: PatternComponent> = ({ +const FormSummary: PatternComponent> = ({ pattern, }) => { if (pattern.style === 'heading') { diff --git a/packages/design/src/config/view/SubmissionConfirmation/SubmissionConfirmation.stories.tsx b/packages/design/src/config/view/SubmissionConfirmation/SubmissionConfirmation.stories.tsx index 638d4219..ccdcf931 100644 --- a/packages/design/src/config/view/SubmissionConfirmation/SubmissionConfirmation.stories.tsx +++ b/packages/design/src/config/view/SubmissionConfirmation/SubmissionConfirmation.stories.tsx @@ -3,7 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import SubmissionConfirmation from '.'; import { type PatternProps, - type SubmissionConfirmationPattern, + type SubmissionConfirmationProps, } from '@atj/forms'; export default { @@ -22,6 +22,6 @@ export const SubmissionConfirmationExample = { { label: 'Field 3', value: 'Value 3' }, { label: 'Field 4', value: 'Value 4' }, ], - } as PatternProps, + } as PatternProps, }, } satisfies StoryObj; diff --git a/packages/design/src/config/view/SubmissionConfirmation/index.tsx b/packages/design/src/config/view/SubmissionConfirmation/index.tsx index 5371a465..6b85a758 100644 --- a/packages/design/src/config/view/SubmissionConfirmation/index.tsx +++ b/packages/design/src/config/view/SubmissionConfirmation/index.tsx @@ -2,12 +2,12 @@ import React from 'react'; import { type PatternProps, - type SubmissionConfirmationPattern, + type SubmissionConfirmationProps, } from '@atj/forms'; import { type PatternComponent } from '../../../Form'; const SubmissionConfirmation: PatternComponent< - PatternProps + PatternProps > = ({ pattern }) => { return ( <> diff --git a/packages/design/src/config/view/TextInput/TestInput.stories.tsx b/packages/design/src/config/view/TextInput/TestInput.stories.tsx index d51c2b9e..dd08e0ee 100644 --- a/packages/design/src/config/view/TextInput/TestInput.stories.tsx +++ b/packages/design/src/config/view/TextInput/TestInput.stories.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import type { Meta, StoryObj } from '@storybook/react'; -import { type PatternProps, type TextInputPattern } from '@atj/forms'; +import { type PatternProps, type TextInputProps } from '@atj/forms'; import TextInput from '.'; export default { @@ -33,7 +33,7 @@ export const Required = { value: '', label: 'Please enter your first name.', required: true, - } as PatternProps, + } as PatternProps, }, } satisfies StoryObj; @@ -46,6 +46,6 @@ export const NotRequired = { value: '', label: 'Please enter your first name.', required: false, - } as PatternProps, + } as PatternProps, }, } satisfies StoryObj; diff --git a/packages/design/src/config/view/TextInput/index.tsx b/packages/design/src/config/view/TextInput/index.tsx index 016d6a65..e9c59fa7 100644 --- a/packages/design/src/config/view/TextInput/index.tsx +++ b/packages/design/src/config/view/TextInput/index.tsx @@ -2,10 +2,10 @@ import classNames from 'classnames'; import React from 'react'; import { useFormContext } from 'react-hook-form'; -import { PatternProps, type TextInputPattern } from '@atj/forms'; +import { PatternProps, type TextInputProps } from '@atj/forms'; import { type PatternComponent } from '../../../Form'; -const TextInput: PatternComponent> = ({ +const TextInput: PatternComponent> = ({ pattern, }) => { const { register } = useFormContext(); diff --git a/packages/forms/src/components.ts b/packages/forms/src/components.ts index 37cef5b0..1da96a2c 100644 --- a/packages/forms/src/components.ts +++ b/packages/forms/src/components.ts @@ -7,7 +7,7 @@ import { import { getPatternConfig } from './element'; import { type FormSession, nullSession, sessionIsComplete } from './session'; -export type TextInputPattern = { +export type TextInputProps = { type: 'input'; inputId: string; value: string; @@ -16,31 +16,24 @@ export type TextInputPattern = { error?: string; }; -export type TextPrompt = { - type: 'text'; - id: string; - value: string; - error?: string; -}; - -export type FormSummaryPattern = { +export type FormSummaryProps = { type: 'form-summary'; title: string; description: string; }; -export type SubmissionConfirmationPattern = { +export type SubmissionConfirmationProps = { type: 'submission-confirmation'; table: { label: string; value: string }[]; }; -export type ParagraphPattern = { +export type ParagraphProps = { type: 'paragraph'; text: string; style: 'indent' | 'normal' | 'heading' | 'subheading'; }; -export type FieldsetPattern = { +export type FieldsetProps = { type: 'fieldset'; legend: string; }; @@ -94,7 +87,7 @@ export const createPrompt = ( value: value, }; }), - } as PatternProps, + } as PatternProps, children: [], }, ], @@ -107,7 +100,7 @@ export const createPrompt = ( type: 'form-summary', title: session.form.summary.title, description: session.form.summary.description, - } as PatternProps, + } as PatternProps, children: [], }, ]; diff --git a/packages/forms/src/patterns/fieldset.ts b/packages/forms/src/patterns/fieldset.ts index f8bd2272..65261689 100644 --- a/packages/forms/src/patterns/fieldset.ts +++ b/packages/forms/src/patterns/fieldset.ts @@ -7,7 +7,7 @@ import { getPattern, } from '../element'; import { - type FieldsetPattern, + type FieldsetProps, type PatternProps, createPromptForElement, } from '../components'; @@ -50,7 +50,7 @@ export const fieldsetConfig: PatternConfig = { _elementId: element.id, type: 'fieldset', legend: element.data.legend, - } satisfies PatternProps, + } satisfies PatternProps, children, }; }, diff --git a/packages/forms/src/patterns/form-summary.ts b/packages/forms/src/patterns/form-summary.ts index caa215f4..9c4a728c 100644 --- a/packages/forms/src/patterns/form-summary.ts +++ b/packages/forms/src/patterns/form-summary.ts @@ -1,7 +1,7 @@ import * as z from 'zod'; import { type Pattern, type PatternConfig } from '../element'; -import { type PatternProps, type FormSummaryPattern } from '../components'; +import { type PatternProps, type FormSummaryProps } from '../components'; import { safeZodParse } from '../util/zod'; const configSchema = z.object({ @@ -30,7 +30,7 @@ export const formSummaryConfig: PatternConfig = { type: 'form-summary', title: element.data.title, description: element.data.description, - } as PatternProps, + } as PatternProps, children: [], }; }, diff --git a/packages/forms/src/patterns/input.ts b/packages/forms/src/patterns/input.ts index 3770c9da..4043fd60 100644 --- a/packages/forms/src/patterns/input.ts +++ b/packages/forms/src/patterns/input.ts @@ -1,7 +1,7 @@ import * as z from 'zod'; import { type Pattern, type PatternConfig, validateElement } from '../element'; -import { type PatternProps, type TextInputPattern } from '../components'; +import { type PatternProps, type TextInputProps } from '../components'; import { getFormSessionValue } from '../session'; import { safeZodParse } from '../util/zod'; @@ -47,7 +47,7 @@ export const inputConfig: PatternConfig = { label: element.data.label, required: element.data.required, ...extraAttributes, - } as PatternProps, + } as PatternProps, children: [], }; }, diff --git a/packages/forms/src/patterns/paragraph.ts b/packages/forms/src/patterns/paragraph.ts index 5f14891a..95dcefd3 100644 --- a/packages/forms/src/patterns/paragraph.ts +++ b/packages/forms/src/patterns/paragraph.ts @@ -1,7 +1,7 @@ import * as z from 'zod'; import { type Pattern, type PatternConfig } from '../element'; -import { type PatternProps, type ParagraphPattern } from '../components'; +import { type PatternProps, type ParagraphProps } from '../components'; import { safeZodParse } from '../util/zod'; const configSchema = z.object({ @@ -31,7 +31,7 @@ export const paragraphConfig: PatternConfig = { type: 'paragraph' as const, text: element.data.text, style: element.data.style, - } as PatternProps, + } as PatternProps, children: [], }; }, From 652061843f944a1f6fd0452e18cc93b7a7b7504f Mon Sep 17 00:00:00 2001 From: Daniel Naab Date: Wed, 27 Mar 2024 10:25:37 -0500 Subject: [PATCH 15/18] Use PatternProps at the point of component prop definition, rather than where comsumed. --- .../src/FormManager/FormEdit/Preview.tsx | 2 +- .../design/src/config/view/Fieldset/index.tsx | 4 ++-- .../view/FormSummary/FormSummary.stories.tsx | 6 ++--- .../src/config/view/FormSummary/index.tsx | 6 ++--- .../src/config/view/Paragraph/index.tsx | 6 ++--- .../design/src/config/view/Sequence/index.tsx | 7 +----- .../SubmissionConfirmation.stories.tsx | 7 ++---- .../view/SubmissionConfirmation/index.tsx | 11 ++++----- .../view/TextInput/TestInput.stories.tsx | 6 ++--- .../src/config/view/TextInput/index.tsx | 6 ++--- packages/forms/src/components.ts | 24 +++++++++---------- packages/forms/src/patterns/fieldset.ts | 2 +- packages/forms/src/patterns/form-summary.ts | 4 ++-- packages/forms/src/patterns/input.ts | 4 ++-- packages/forms/src/patterns/paragraph.ts | 4 ++-- 15 files changed, 41 insertions(+), 58 deletions(-) diff --git a/packages/design/src/FormManager/FormEdit/Preview.tsx b/packages/design/src/FormManager/FormEdit/Preview.tsx index 045568be..fd7ed1ea 100644 --- a/packages/design/src/FormManager/FormEdit/Preview.tsx +++ b/packages/design/src/FormManager/FormEdit/Preview.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { type PatternProps, createFormSession } from '@atj/forms'; +import { createFormSession } from '@atj/forms'; import Form, { type ComponentForPattern, diff --git a/packages/design/src/config/view/Fieldset/index.tsx b/packages/design/src/config/view/Fieldset/index.tsx index bf1b6f32..2e09f7c1 100644 --- a/packages/design/src/config/view/Fieldset/index.tsx +++ b/packages/design/src/config/view/Fieldset/index.tsx @@ -1,10 +1,10 @@ import React from 'react'; -import { type FieldsetProps, type PatternProps } from '@atj/forms'; +import { type FieldsetProps } from '@atj/forms'; import { type PatternComponent } from '../../../Form'; -const FormSummary: PatternComponent> = ({ +const FormSummary: PatternComponent = ({ pattern, children, }) => { diff --git a/packages/design/src/config/view/FormSummary/FormSummary.stories.tsx b/packages/design/src/config/view/FormSummary/FormSummary.stories.tsx index e480aa66..aec0c7ad 100644 --- a/packages/design/src/config/view/FormSummary/FormSummary.stories.tsx +++ b/packages/design/src/config/view/FormSummary/FormSummary.stories.tsx @@ -1,7 +1,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import FormSummary from '.'; -import { type PatternProps, type FormSummaryProps } from '@atj/forms'; +import { type FormSummaryProps } from '@atj/forms'; export default { title: 'patterns/FormSummary', @@ -17,7 +17,7 @@ export const FormSummaryWithLongDescription = { title: 'Form title', description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', - } as PatternProps, + } as FormSummaryProps, }, } satisfies StoryObj; @@ -28,6 +28,6 @@ export const FormSummaryWithShortDescription = { type: 'form-summary', title: 'Title 2', description: 'Short description', - } as PatternProps, + } as FormSummaryProps, }, } satisfies StoryObj; diff --git a/packages/design/src/config/view/FormSummary/index.tsx b/packages/design/src/config/view/FormSummary/index.tsx index 8b011d90..0d77b53a 100644 --- a/packages/design/src/config/view/FormSummary/index.tsx +++ b/packages/design/src/config/view/FormSummary/index.tsx @@ -1,11 +1,9 @@ import React from 'react'; -import { type PatternProps, type FormSummaryProps } from '@atj/forms'; +import { type FormSummaryProps } from '@atj/forms'; import { type PatternComponent } from '../../../Form'; -const FormSummary: PatternComponent> = ({ - pattern, -}) => { +const FormSummary: PatternComponent = ({ pattern }) => { return ( <>
diff --git a/packages/design/src/config/view/Paragraph/index.tsx b/packages/design/src/config/view/Paragraph/index.tsx index c22626ee..ef01808f 100644 --- a/packages/design/src/config/view/Paragraph/index.tsx +++ b/packages/design/src/config/view/Paragraph/index.tsx @@ -1,12 +1,10 @@ import React from 'react'; -import { type ParagraphProps, type PatternProps } from '@atj/forms'; +import { type ParagraphProps } from '@atj/forms'; import { type PatternComponent } from '../../../Form'; -const FormSummary: PatternComponent> = ({ - pattern, -}) => { +const FormSummary: PatternComponent = ({ pattern }) => { if (pattern.style === 'heading') { return ( <> diff --git a/packages/design/src/config/view/Sequence/index.tsx b/packages/design/src/config/view/Sequence/index.tsx index 8f055c3e..955b4765 100644 --- a/packages/design/src/config/view/Sequence/index.tsx +++ b/packages/design/src/config/view/Sequence/index.tsx @@ -1,13 +1,8 @@ import React from 'react'; -import { type PatternProps } from '@atj/forms'; -import { type SequenceElement } from '@atj/forms/src/patterns/sequence'; - import { type PatternComponent } from '../../../Form'; -const Sequence: PatternComponent> = ({ - children, -}) => { +const Sequence: PatternComponent = ({ children }) => { return <>{children}; }; diff --git a/packages/design/src/config/view/SubmissionConfirmation/SubmissionConfirmation.stories.tsx b/packages/design/src/config/view/SubmissionConfirmation/SubmissionConfirmation.stories.tsx index ccdcf931..fea444e5 100644 --- a/packages/design/src/config/view/SubmissionConfirmation/SubmissionConfirmation.stories.tsx +++ b/packages/design/src/config/view/SubmissionConfirmation/SubmissionConfirmation.stories.tsx @@ -1,10 +1,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import SubmissionConfirmation from '.'; -import { - type PatternProps, - type SubmissionConfirmationProps, -} from '@atj/forms'; +import { type SubmissionConfirmationProps } from '@atj/forms'; export default { title: 'patterns/SubmissionConfirmation', @@ -22,6 +19,6 @@ export const SubmissionConfirmationExample = { { label: 'Field 3', value: 'Value 3' }, { label: 'Field 4', value: 'Value 4' }, ], - } as PatternProps, + } as SubmissionConfirmationProps, }, } satisfies StoryObj; diff --git a/packages/design/src/config/view/SubmissionConfirmation/index.tsx b/packages/design/src/config/view/SubmissionConfirmation/index.tsx index 6b85a758..d763ecb1 100644 --- a/packages/design/src/config/view/SubmissionConfirmation/index.tsx +++ b/packages/design/src/config/view/SubmissionConfirmation/index.tsx @@ -1,14 +1,11 @@ import React from 'react'; -import { - type PatternProps, - type SubmissionConfirmationProps, -} from '@atj/forms'; +import { type SubmissionConfirmationProps } from '@atj/forms'; import { type PatternComponent } from '../../../Form'; -const SubmissionConfirmation: PatternComponent< - PatternProps -> = ({ pattern }) => { +const SubmissionConfirmation: PatternComponent = ({ + pattern, +}) => { return ( <> diff --git a/packages/design/src/config/view/TextInput/TestInput.stories.tsx b/packages/design/src/config/view/TextInput/TestInput.stories.tsx index dd08e0ee..a29f8e74 100644 --- a/packages/design/src/config/view/TextInput/TestInput.stories.tsx +++ b/packages/design/src/config/view/TextInput/TestInput.stories.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import type { Meta, StoryObj } from '@storybook/react'; -import { type PatternProps, type TextInputProps } from '@atj/forms'; +import { type TextInputProps } from '@atj/forms'; import TextInput from '.'; export default { @@ -33,7 +33,7 @@ export const Required = { value: '', label: 'Please enter your first name.', required: true, - } as PatternProps, + } as TextInputProps, }, } satisfies StoryObj; @@ -46,6 +46,6 @@ export const NotRequired = { value: '', label: 'Please enter your first name.', required: false, - } as PatternProps, + } as TextInputProps, }, } satisfies StoryObj; diff --git a/packages/design/src/config/view/TextInput/index.tsx b/packages/design/src/config/view/TextInput/index.tsx index e9c59fa7..3ea57703 100644 --- a/packages/design/src/config/view/TextInput/index.tsx +++ b/packages/design/src/config/view/TextInput/index.tsx @@ -2,12 +2,10 @@ import classNames from 'classnames'; import React from 'react'; import { useFormContext } from 'react-hook-form'; -import { PatternProps, type TextInputProps } from '@atj/forms'; +import { type TextInputProps } from '@atj/forms'; import { type PatternComponent } from '../../../Form'; -const TextInput: PatternComponent> = ({ - pattern, -}) => { +const TextInput: PatternComponent = ({ pattern }) => { const { register } = useFormContext(); return (
diff --git a/packages/forms/src/components.ts b/packages/forms/src/components.ts index 1da96a2c..d61061e5 100644 --- a/packages/forms/src/components.ts +++ b/packages/forms/src/components.ts @@ -7,36 +7,36 @@ import { import { getPatternConfig } from './element'; import { type FormSession, nullSession, sessionIsComplete } from './session'; -export type TextInputProps = { +export type TextInputProps = PatternProps<{ type: 'input'; inputId: string; value: string; label: string; required: boolean; error?: string; -}; +}>; -export type FormSummaryProps = { +export type FormSummaryProps = PatternProps<{ type: 'form-summary'; title: string; description: string; -}; +}>; -export type SubmissionConfirmationProps = { +export type SubmissionConfirmationProps = PatternProps<{ type: 'submission-confirmation'; table: { label: string; value: string }[]; -}; +}>; -export type ParagraphProps = { +export type ParagraphProps = PatternProps<{ type: 'paragraph'; text: string; style: 'indent' | 'normal' | 'heading' | 'subheading'; -}; +}>; -export type FieldsetProps = { +export type FieldsetProps = PatternProps<{ type: 'fieldset'; legend: string; -}; +}>; export type PatternProps = { _elementId: PatternId; @@ -87,7 +87,7 @@ export const createPrompt = ( value: value, }; }), - } as PatternProps, + } as SubmissionConfirmationProps, children: [], }, ], @@ -100,7 +100,7 @@ export const createPrompt = ( type: 'form-summary', title: session.form.summary.title, description: session.form.summary.description, - } as PatternProps, + } as FormSummaryProps, children: [], }, ]; diff --git a/packages/forms/src/patterns/fieldset.ts b/packages/forms/src/patterns/fieldset.ts index 65261689..487445de 100644 --- a/packages/forms/src/patterns/fieldset.ts +++ b/packages/forms/src/patterns/fieldset.ts @@ -50,7 +50,7 @@ export const fieldsetConfig: PatternConfig = { _elementId: element.id, type: 'fieldset', legend: element.data.legend, - } satisfies PatternProps, + } satisfies FieldsetProps, children, }; }, diff --git a/packages/forms/src/patterns/form-summary.ts b/packages/forms/src/patterns/form-summary.ts index 9c4a728c..8bd0917c 100644 --- a/packages/forms/src/patterns/form-summary.ts +++ b/packages/forms/src/patterns/form-summary.ts @@ -1,7 +1,7 @@ import * as z from 'zod'; import { type Pattern, type PatternConfig } from '../element'; -import { type PatternProps, type FormSummaryProps } from '../components'; +import { type FormSummaryProps } from '../components'; import { safeZodParse } from '../util/zod'; const configSchema = z.object({ @@ -30,7 +30,7 @@ export const formSummaryConfig: PatternConfig = { type: 'form-summary', title: element.data.title, description: element.data.description, - } as PatternProps, + } as FormSummaryProps, children: [], }; }, diff --git a/packages/forms/src/patterns/input.ts b/packages/forms/src/patterns/input.ts index 4043fd60..97230865 100644 --- a/packages/forms/src/patterns/input.ts +++ b/packages/forms/src/patterns/input.ts @@ -1,7 +1,7 @@ import * as z from 'zod'; import { type Pattern, type PatternConfig, validateElement } from '../element'; -import { type PatternProps, type TextInputProps } from '../components'; +import { type TextInputProps } from '../components'; import { getFormSessionValue } from '../session'; import { safeZodParse } from '../util/zod'; @@ -47,7 +47,7 @@ export const inputConfig: PatternConfig = { label: element.data.label, required: element.data.required, ...extraAttributes, - } as PatternProps, + } as TextInputProps, children: [], }; }, diff --git a/packages/forms/src/patterns/paragraph.ts b/packages/forms/src/patterns/paragraph.ts index 95dcefd3..ebe9997d 100644 --- a/packages/forms/src/patterns/paragraph.ts +++ b/packages/forms/src/patterns/paragraph.ts @@ -1,7 +1,7 @@ import * as z from 'zod'; import { type Pattern, type PatternConfig } from '../element'; -import { type PatternProps, type ParagraphProps } from '../components'; +import { type ParagraphProps } from '../components'; import { safeZodParse } from '../util/zod'; const configSchema = z.object({ @@ -31,7 +31,7 @@ export const paragraphConfig: PatternConfig = { type: 'paragraph' as const, text: element.data.text, style: element.data.style, - } as PatternProps, + } as ParagraphProps, children: [], }; }, From b62da46bc1bcdf65c4ae9516519ebb4f23398c6b Mon Sep 17 00:00:00 2001 From: Daniel Naab Date: Wed, 27 Mar 2024 10:35:14 -0500 Subject: [PATCH 16/18] Update README with terminology --- README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3269232f..5a103777 100644 --- a/README.md +++ b/README.md @@ -13,20 +13,22 @@ Additional documentation: - [Architectural Decision Records (ADRs)](./documents/adr/) - [Non-project contributions](./documents/value-created-log.md) -## Terminology +## Overview The platform is made up of the following high-level terms. -### Personas +### Key personas - Content authors: legal experts who craft guided interview experiences via a "no code" interface - Self-represented litigants (SREs): end-users who interact with the court via guided interviews created by content authors ### Things -- Blueprint: produced by a content author, the blueprint defines the structure of an interactive session between a court and an SRL -- Conversation: one instance of a blueprint; the interactive session between a court and an SRL. -- Pattern: the building blocks of a blueprint, patterns implement UX best-practices. +- **Blueprint**: produced by a content author, the blueprint defines the structure of an interactive session between a court and an SRL +- **Conversation**: one instance of a blueprint; the interactive session between a court and an SRL. Other terms for this concept include dialogue or session. +- **Pattern**: the building blocks of a blueprint, patterns implement UX best-practices, defining the content and behavior of the user interface. +- **Prompt**: produced by a pattern, the prompt defines what is presented to the end user at single point in a conversation. +- **Component**: user interface component that acts as the building block of prompts. ## Development From 6840fb1cd5ef090b60c7f96b6195b0fc0f02ca35 Mon Sep 17 00:00:00 2001 From: Daniel Naab Date: Wed, 27 Mar 2024 10:47:59 -0500 Subject: [PATCH 17/18] Rename forms/element.ts to forms/pattern.ts --- packages/forms/src/components.ts | 6 +++--- packages/forms/src/index.ts | 4 ++-- packages/forms/src/{element.ts => pattern.ts} | 0 packages/forms/src/patterns/fieldset.ts | 8 ++------ packages/forms/src/patterns/form-summary.ts | 2 +- packages/forms/src/patterns/index.ts | 3 ++- packages/forms/src/patterns/input.ts | 2 +- packages/forms/src/patterns/paragraph.ts | 2 +- packages/forms/src/patterns/sequence.ts | 2 +- packages/forms/src/session.ts | 2 +- 10 files changed, 14 insertions(+), 17 deletions(-) rename packages/forms/src/{element.ts => pattern.ts} (100%) diff --git a/packages/forms/src/components.ts b/packages/forms/src/components.ts index d61061e5..0baf6568 100644 --- a/packages/forms/src/components.ts +++ b/packages/forms/src/components.ts @@ -1,10 +1,10 @@ +import { getRootPattern } from '..'; import { type FormConfig, type Pattern, type PatternId, - getRootPattern, -} from '..'; -import { getPatternConfig } from './element'; + getPatternConfig, +} from './pattern'; import { type FormSession, nullSession, sessionIsComplete } from './session'; export type TextInputProps = PatternProps<{ diff --git a/packages/forms/src/index.ts b/packages/forms/src/index.ts index 0c23cf93..dc51a817 100644 --- a/packages/forms/src/index.ts +++ b/packages/forms/src/index.ts @@ -7,13 +7,13 @@ import { type PatternMap, getPatternMap, getPatternConfig, -} from './element'; +} from './pattern'; export * from './builder'; export * from './components'; export * from './config'; export * from './documents'; -export * from './element'; +export * from './pattern'; export * from './response'; export * from './session'; diff --git a/packages/forms/src/element.ts b/packages/forms/src/pattern.ts similarity index 100% rename from packages/forms/src/element.ts rename to packages/forms/src/pattern.ts diff --git a/packages/forms/src/patterns/fieldset.ts b/packages/forms/src/patterns/fieldset.ts index 487445de..21c6cf35 100644 --- a/packages/forms/src/patterns/fieldset.ts +++ b/packages/forms/src/patterns/fieldset.ts @@ -5,12 +5,8 @@ import { type PatternConfig, type PatternId, getPattern, -} from '../element'; -import { - type FieldsetProps, - type PatternProps, - createPromptForElement, -} from '../components'; +} from '../pattern'; +import { type FieldsetProps, createPromptForElement } from '../components'; import { safeZodParse } from '../util/zod'; export type FieldsetElement = Pattern<{ diff --git a/packages/forms/src/patterns/form-summary.ts b/packages/forms/src/patterns/form-summary.ts index 8bd0917c..ec54c9e2 100644 --- a/packages/forms/src/patterns/form-summary.ts +++ b/packages/forms/src/patterns/form-summary.ts @@ -1,6 +1,6 @@ import * as z from 'zod'; -import { type Pattern, type PatternConfig } from '../element'; +import { type Pattern, type PatternConfig } from '../pattern'; import { type FormSummaryProps } from '../components'; import { safeZodParse } from '../util/zod'; diff --git a/packages/forms/src/patterns/index.ts b/packages/forms/src/patterns/index.ts index cf3e03c2..65327fea 100644 --- a/packages/forms/src/patterns/index.ts +++ b/packages/forms/src/patterns/index.ts @@ -1,4 +1,5 @@ -import { FormConfig } from '../element'; +import { type FormConfig } from '../pattern'; + import { fieldsetConfig } from './fieldset'; import { inputConfig } from './input'; import { paragraphConfig } from './paragraph'; diff --git a/packages/forms/src/patterns/input.ts b/packages/forms/src/patterns/input.ts index 97230865..250322d4 100644 --- a/packages/forms/src/patterns/input.ts +++ b/packages/forms/src/patterns/input.ts @@ -1,6 +1,6 @@ import * as z from 'zod'; -import { type Pattern, type PatternConfig, validateElement } from '../element'; +import { type Pattern, type PatternConfig, validateElement } from '../pattern'; import { type TextInputProps } from '../components'; import { getFormSessionValue } from '../session'; import { safeZodParse } from '../util/zod'; diff --git a/packages/forms/src/patterns/paragraph.ts b/packages/forms/src/patterns/paragraph.ts index ebe9997d..cd0b950a 100644 --- a/packages/forms/src/patterns/paragraph.ts +++ b/packages/forms/src/patterns/paragraph.ts @@ -1,6 +1,6 @@ import * as z from 'zod'; -import { type Pattern, type PatternConfig } from '../element'; +import { type Pattern, type PatternConfig } from '../pattern'; import { type ParagraphProps } from '../components'; import { safeZodParse } from '../util/zod'; diff --git a/packages/forms/src/patterns/sequence.ts b/packages/forms/src/patterns/sequence.ts index b35ac62b..8a6162c8 100644 --- a/packages/forms/src/patterns/sequence.ts +++ b/packages/forms/src/patterns/sequence.ts @@ -5,7 +5,7 @@ import { type PatternConfig, type PatternId, getPattern, -} from '../element'; +} from '../pattern'; import { createPromptForElement } from '../components'; import { safeZodParse } from '../util/zod'; diff --git a/packages/forms/src/session.ts b/packages/forms/src/session.ts index 0ee5f0ed..4771771e 100644 --- a/packages/forms/src/session.ts +++ b/packages/forms/src/session.ts @@ -10,7 +10,7 @@ import { type PatternId, type PatternValue, type PatternValueMap, -} from './element'; +} from './pattern'; type ErrorMap = Record; From 3b96a921c0bc400403bee28be55f45e958fd7fe4 Mon Sep 17 00:00:00 2001 From: Daniel Naab Date: Wed, 27 Mar 2024 11:37:15 -0500 Subject: [PATCH 18/18] Replace additional references to "element" with "pattern" --- .../FormManager/FormEdit/DraggableList.tsx | 44 ++++---- .../src/FormManager/FormEdit/PatternEdit.tsx | 32 +++--- .../src/FormManager/FormEdit/Preview.tsx | 16 +-- .../design/src/FormManager/FormEdit/index.tsx | 4 +- .../design/src/FormManager/FormEdit/store.tsx | 20 ++-- .../design/src/FormManager/FormEdit/types.ts | 2 +- .../FormList/PDFFileSelect/file-input.test.ts | 2 +- .../FormList/PDFFileSelect/file-input.ts | 2 +- .../src/config/edit/FormSummaryEdit.tsx | 6 +- ...utElementEdit.tsx => InputPatternEdit.tsx} | 38 +++---- ...ementEdit.tsx => ParagraphPatternEdit.tsx} | 12 +-- ...lementEdit.tsx => SequencePatternEdit.tsx} | 60 +++++------ .../edit/SubmissionConfirmationEdit.tsx | 22 ++-- packages/design/src/config/edit/index.ts | 8 +- .../view/FormSummary/FormSummary.stories.tsx | 4 +- .../view/TextInput/TestInput.stories.tsx | 4 +- packages/design/src/test-form.ts | 36 +++++-- packages/forms/src/builder/index.ts | 18 ++-- packages/forms/src/components.ts | 34 +++--- packages/forms/src/documents/document.ts | 44 ++++---- packages/forms/src/documents/pdf/generate.ts | 6 +- packages/forms/src/documents/pdf/mock-api.ts | 42 ++++---- packages/forms/src/index.ts | 100 +++++++----------- packages/forms/src/pattern.ts | 65 ++++++++---- packages/forms/src/patterns/fieldset.ts | 30 +++--- packages/forms/src/patterns/form-summary.ts | 8 +- packages/forms/src/patterns/index.ts | 2 +- packages/forms/src/patterns/input.ts | 24 ++--- packages/forms/src/patterns/paragraph.ts | 16 +-- packages/forms/src/patterns/sequence.ts | 28 ++--- packages/forms/src/response.ts | 24 ++--- packages/forms/src/session.ts | 40 +++---- packages/forms/tests/two-field-form.test.ts | 42 ++++---- 33 files changed, 422 insertions(+), 413 deletions(-) rename packages/design/src/config/edit/{InputElementEdit.tsx => InputPatternEdit.tsx} (58%) rename packages/design/src/config/edit/{ParagraphElementEdit.tsx => ParagraphPatternEdit.tsx} (77%) rename packages/design/src/config/edit/{SequenceElementEdit.tsx => SequencePatternEdit.tsx} (64%) diff --git a/packages/design/src/FormManager/FormEdit/DraggableList.tsx b/packages/design/src/FormManager/FormEdit/DraggableList.tsx index 72f11627..a33cbb71 100644 --- a/packages/design/src/FormManager/FormEdit/DraggableList.tsx +++ b/packages/design/src/FormManager/FormEdit/DraggableList.tsx @@ -23,7 +23,7 @@ import { PatternId, } from '@atj/forms'; -import { SequenceElement } from '@atj/forms/src/patterns/sequence'; +import { SequencePattern } from '@atj/forms/src/patterns/sequence'; const SortableItem = ({ id, @@ -59,19 +59,19 @@ const SortableItem = ({ }; type DraggableListProps = React.PropsWithChildren<{ - element: Pattern; + pattern: Pattern; form: Blueprint; - setSelectedElement: (element: Pattern) => void; + setSelectedPattern: (pattern: Pattern) => void; }>; export const DraggableList: React.FC = ({ - element, + pattern, form, - setSelectedElement, + setSelectedPattern, children, }) => { - const [elements, setElements] = useState( - element.data.elements.map((elementId: PatternId) => { - return getPattern(form, elementId); + const [patterns, setPatterns] = useState( + pattern.data.patterns.map((patternId: PatternId) => { + return getPattern(form, patternId); }) ); const sensors = useSensors( @@ -90,31 +90,31 @@ export const DraggableList: React.FC = ({ return; } if (active.id !== over.id) { - const oldIndex = elements.findIndex(element => { - return element.id === active.id; + const oldIndex = patterns.findIndex(pattern => { + return pattern.id === active.id; }); - const newIndex = elements.findIndex(element => { - return element.id === over.id; + const newIndex = patterns.findIndex(pattern => { + return pattern.id === over.id; }); - const newOrder = arrayMove(elements, oldIndex, newIndex); - setElements(newOrder); - setSelectedElement({ - id: element.id, - type: element.type, + const newOrder = arrayMove(patterns, oldIndex, newIndex); + setPatterns(newOrder); + setSelectedPattern({ + id: pattern.id, + type: pattern.type, data: { - elements: newOrder.map(element => element.id), + patterns: newOrder.map(pattern => pattern.id), }, initial: { - elements: [], + patterns: [], }, - } satisfies SequenceElement); + } satisfies SequencePattern); } }} > - +
    {arrayChildren.map((child, index) => ( - + {child} ))} diff --git a/packages/design/src/FormManager/FormEdit/PatternEdit.tsx b/packages/design/src/FormManager/FormEdit/PatternEdit.tsx index 9046e959..55e61fff 100644 --- a/packages/design/src/FormManager/FormEdit/PatternEdit.tsx +++ b/packages/design/src/FormManager/FormEdit/PatternEdit.tsx @@ -7,39 +7,39 @@ import { useFormEditStore } from './store'; export const PatternEdit = () => { const context = useFormEditStore(state => state.context); const form = useFormEditStore(state => state.form); - const selectedElement = useFormEditStore(state => state.selectedElement); - const { setSelectedElement, updateSelectedPattern } = useFormEditStore( + const selectedPattern = useFormEditStore(state => state.selectedPattern); + const { setSelectedPattern, updateSelectedPattern } = useFormEditStore( state => ({ - setSelectedElement: state.setSelectedElement, + setSelectedPattern: state.setSelectedPattern, updateSelectedPattern: state.updateSelectedPattern, }) ); const methods = useForm({ - defaultValues: selectedElement + defaultValues: selectedPattern ? { - [selectedElement.id]: selectedElement, + [selectedPattern.id]: selectedPattern, } : {}, }); const settingsContainerRef = useRef(null); useEffect(() => { - if (selectedElement === undefined) { + if (selectedPattern === undefined) { return; } methods.reset(); - methods.setValue(selectedElement.id, selectedElement); - }, [selectedElement]); + methods.setValue(selectedPattern.id, selectedPattern); + }, [selectedPattern]); // Updates the scroll position of the edit form when it's visible useEffect(() => { let frameId: number; const updatePosition = () => { if (window.innerWidth > 879) { - if (selectedElement) { + if (selectedPattern) { const element = document.querySelector( - `[data-id="${selectedElement.id}"]` + `[data-id="${selectedPattern.id}"]` ); if (element && settingsContainerRef.current) { const rect = element.getBoundingClientRect(); @@ -53,13 +53,13 @@ export const PatternEdit = () => { return () => { cancelAnimationFrame(frameId); }; - }, [selectedElement]); + }, [selectedPattern]); - if (!selectedElement) { + if (!selectedPattern) { return; } - const SelectedEditComponent = context.editComponents[selectedElement.type]; + const SelectedEditComponent = context.editComponents[selectedPattern.type]; return (
    { updateSelectedPattern(formData); })} > -

    Editing "{selectedElement.data.label}"...

    +

    Editing "{selectedPattern.data.label}"...

    setSelectedElement(undefined)} + onClick={() => setSelectedPattern(undefined)} className="usa-button close-button" type="submit" value="Cancel" diff --git a/packages/design/src/FormManager/FormEdit/Preview.tsx b/packages/design/src/FormManager/FormEdit/Preview.tsx index fd7ed1ea..2777a1a9 100644 --- a/packages/design/src/FormManager/FormEdit/Preview.tsx +++ b/packages/design/src/FormManager/FormEdit/Preview.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import { createFormSession } from '@atj/forms'; +import { type PatternProps, createFormSession } from '@atj/forms'; import Form, { type ComponentForPattern, @@ -70,14 +70,14 @@ const createSequencePatternPreviewComponent = ( const PatternPreviewSequenceComponent: PatternComponent = ({ pattern, }) => { - const { form, setSelectedElement } = usePreviewContext(); - const element = getPattern(form, pattern._elementId); + const { form, setSelectedPattern } = usePreviewContext(); + const element = getPattern(form, pattern._patternId); const Component = previewComponents[pattern.type]; return ( @@ -94,18 +94,18 @@ const createPatternPreviewComponent = ( const PatternPreviewComponent: PatternComponent = ({ pattern, }: { - pattern: Pattern; + pattern: PatternProps; }) => { - const selectedElement = useFormEditStore(state => state.selectedElement); + const selectedPattern = useFormEditStore(state => state.selectedPattern); const handleEditClick = useFormEditStore(state => state.handleEditClick); - const isSelected = selectedElement?.id === pattern._elementId; + const isSelected = selectedPattern?.id === pattern._patternId; const divClassNames = isSelected ? 'form-group-row field-selected' : 'form-group-row'; return ( -

    +