@defra/forms-engine-plugin 5.0.0-alpha.22 → 5.0.0-alpha.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,6 +6,14 @@
6
6
  "path": "/all-components",
7
7
  "title": "All Components",
8
8
  "components": [
9
+ {
10
+ "type": "TrackingField",
11
+ "name": "trackingField",
12
+ "title": "Tracking field",
13
+ "hint": "Help text",
14
+ "options": {},
15
+ "schema": {}
16
+ },
9
17
  {
10
18
  "type": "TextField",
11
19
  "name": "textField",
@@ -5,6 +5,10 @@ pages:
5
5
  - path: '/whats-your-name'
6
6
  title: What's your name?
7
7
  components:
8
+ - type: TrackingField
9
+ name: hasSeenNamePage
10
+ title: Tracks if the user has seen the name page
11
+ options: {}
8
12
  - type: TextField
9
13
  name: textField
10
14
  title: Name
@@ -0,0 +1,21 @@
1
+ import { type TrackingFieldComponent } from '@defra/forms-model';
2
+ import { type BooleanSchema } from 'joi';
3
+ import { FormComponent } from '../../../../server/plugins/engine/components/FormComponent.js';
4
+ import { type ErrorMessageTemplateList, type FormState, type FormStateValue, type FormSubmissionState } from '../../../../server/plugins/engine/types.js';
5
+ export declare class TrackingField extends FormComponent {
6
+ formSchema: BooleanSchema;
7
+ stateSchema: BooleanSchema;
8
+ options: TrackingFieldComponent['options'];
9
+ constructor(def: TrackingFieldComponent, props: ConstructorParameters<typeof FormComponent>[1]);
10
+ getFormValueFromState(state: FormSubmissionState): NonNullable<FormStateValue> | undefined;
11
+ isValue(value?: FormStateValue | FormState): value is true;
12
+ /**
13
+ * For error preview page that shows all possible errors on a component
14
+ */
15
+ getAllPossibleErrors(): ErrorMessageTemplateList;
16
+ static isTracking(value?: FormStateValue | FormState): value is true;
17
+ /**
18
+ * Static version of getAllPossibleErrors that doesn't require a component instance.
19
+ */
20
+ static getAllPossibleErrors(): ErrorMessageTemplateList;
21
+ }
@@ -0,0 +1,46 @@
1
+ import joi from 'joi';
2
+ import { FormComponent, isFormValue } from "./FormComponent.js";
3
+ import { messageTemplate } from "../pageControllers/validationOptions.js";
4
+ export class TrackingField extends FormComponent {
5
+ constructor(def, props) {
6
+ super(def, props);
7
+ const formSchema = joi.boolean().valid(true).label(this.label).required();
8
+ this.formSchema = formSchema.default(false);
9
+ this.stateSchema = formSchema.default(null).allow(null);
10
+ this.schema = {};
11
+ this.options = {};
12
+ }
13
+ getFormValueFromState(state) {
14
+ const {
15
+ name
16
+ } = this;
17
+ return this.getFormValue(state[name]);
18
+ }
19
+ isValue(value) {
20
+ return TrackingField.isTracking(value);
21
+ }
22
+
23
+ /**
24
+ * For error preview page that shows all possible errors on a component
25
+ */
26
+ getAllPossibleErrors() {
27
+ return TrackingField.getAllPossibleErrors();
28
+ }
29
+ static isTracking(value) {
30
+ return isFormValue(value) && typeof value === 'boolean';
31
+ }
32
+
33
+ /**
34
+ * Static version of getAllPossibleErrors that doesn't require a component instance.
35
+ */
36
+ static getAllPossibleErrors() {
37
+ return {
38
+ baseErrors: [{
39
+ type: 'required',
40
+ template: messageTemplate.required
41
+ }],
42
+ advancedSettingsErrors: []
43
+ };
44
+ }
45
+ }
46
+ //# sourceMappingURL=TrackingField.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TrackingField.js","names":["joi","FormComponent","isFormValue","messageTemplate","TrackingField","constructor","def","props","formSchema","boolean","valid","label","required","default","stateSchema","allow","schema","options","getFormValueFromState","state","name","getFormValue","isValue","value","isTracking","getAllPossibleErrors","baseErrors","type","template","advancedSettingsErrors"],"sources":["../../../../../src/server/plugins/engine/components/TrackingField.ts"],"sourcesContent":["import { type TrackingFieldComponent } from '@defra/forms-model'\nimport joi, { type BooleanSchema } from 'joi'\n\nimport {\n FormComponent,\n isFormValue\n} from '~/src/server/plugins/engine/components/FormComponent.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport {\n type ErrorMessageTemplateList,\n type FormState,\n type FormStateValue,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\n\nexport class TrackingField extends FormComponent {\n declare formSchema: BooleanSchema\n declare stateSchema: BooleanSchema\n declare options: TrackingFieldComponent['options']\n\n constructor(\n def: TrackingFieldComponent,\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n const formSchema = joi.boolean().valid(true).label(this.label).required()\n\n this.formSchema = formSchema.default(false)\n this.stateSchema = formSchema.default(null).allow(null)\n this.schema = {}\n this.options = {}\n }\n\n getFormValueFromState(state: FormSubmissionState) {\n const { name } = this\n return this.getFormValue(state[name])\n }\n\n isValue(value?: FormStateValue | FormState): value is true {\n return TrackingField.isTracking(value)\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return TrackingField.getAllPossibleErrors()\n }\n\n static isTracking(value?: FormStateValue | FormState): value is true {\n return isFormValue(value) && typeof value === 'boolean'\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [{ type: 'required', template: messageTemplate.required }],\n advancedSettingsErrors: []\n }\n }\n}\n"],"mappings":"AACA,OAAOA,GAAG,MAA8B,KAAK;AAE7C,SACEC,aAAa,EACbC,WAAW;AAEb,SAASC,eAAe;AAQxB,OAAO,MAAMC,aAAa,SAASH,aAAa,CAAC;EAK/CI,WAAWA,CACTC,GAA2B,EAC3BC,KAAqD,EACrD;IACA,KAAK,CAACD,GAAG,EAAEC,KAAK,CAAC;IAEjB,MAAMC,UAAU,GAAGR,GAAG,CAACS,OAAO,CAAC,CAAC,CAACC,KAAK,CAAC,IAAI,CAAC,CAACC,KAAK,CAAC,IAAI,CAACA,KAAK,CAAC,CAACC,QAAQ,CAAC,CAAC;IAEzE,IAAI,CAACJ,UAAU,GAAGA,UAAU,CAACK,OAAO,CAAC,KAAK,CAAC;IAC3C,IAAI,CAACC,WAAW,GAAGN,UAAU,CAACK,OAAO,CAAC,IAAI,CAAC,CAACE,KAAK,CAAC,IAAI,CAAC;IACvD,IAAI,CAACC,MAAM,GAAG,CAAC,CAAC;IAChB,IAAI,CAACC,OAAO,GAAG,CAAC,CAAC;EACnB;EAEAC,qBAAqBA,CAACC,KAA0B,EAAE;IAChD,MAAM;MAAEC;IAAK,CAAC,GAAG,IAAI;IACrB,OAAO,IAAI,CAACC,YAAY,CAACF,KAAK,CAACC,IAAI,CAAC,CAAC;EACvC;EAEAE,OAAOA,CAACC,KAAkC,EAAiB;IACzD,OAAOnB,aAAa,CAACoB,UAAU,CAACD,KAAK,CAAC;EACxC;;EAEA;AACF;AACA;EACEE,oBAAoBA,CAAA,EAA6B;IAC/C,OAAOrB,aAAa,CAACqB,oBAAoB,CAAC,CAAC;EAC7C;EAEA,OAAOD,UAAUA,CAACD,KAAkC,EAAiB;IACnE,OAAOrB,WAAW,CAACqB,KAAK,CAAC,IAAI,OAAOA,KAAK,KAAK,SAAS;EACzD;;EAEA;AACF;AACA;EACE,OAAOE,oBAAoBA,CAAA,EAA6B;IACtD,OAAO;MACLC,UAAU,EAAE,CAAC;QAAEC,IAAI,EAAE,UAAU;QAAEC,QAAQ,EAAEzB,eAAe,CAACS;MAAS,CAAC,CAAC;MACtEiB,sBAAsB,EAAE;IAC1B,CAAC;EACH;AACF","ignoreList":[]}
@@ -5,7 +5,7 @@ import * as Components from '../../../../../server/plugins/engine/components/ind
5
5
  import { type Translator } from '../../../../../server/plugins/engine/i18n/types.js';
6
6
  import { type FormState } from '../../../../../server/plugins/engine/types.js';
7
7
  export type Component = InstanceType<(typeof Components)[keyof typeof Components]>;
8
- export type Field = InstanceType<typeof Components.AutocompleteField | typeof Components.RadiosField | typeof Components.YesNoField | typeof Components.CheckboxesField | typeof Components.DatePartsField | typeof Components.DeclarationField | typeof Components.EastingNorthingField | typeof Components.EmailAddressField | typeof Components.LatLongField | typeof Components.MonthYearField | typeof Components.MultilineTextField | typeof Components.NationalGridFieldNumberField | typeof Components.NumberField | typeof Components.OsGridRefField | typeof Components.SelectField | typeof Components.TelephoneNumberField | typeof Components.TextField | typeof Components.UkAddressField | typeof Components.FileUploadField | typeof Components.HiddenField | typeof Components.PaymentField | typeof Components.GeospatialField>;
8
+ export type Field = InstanceType<typeof Components.AutocompleteField | typeof Components.RadiosField | typeof Components.YesNoField | typeof Components.CheckboxesField | typeof Components.DatePartsField | typeof Components.DeclarationField | typeof Components.EastingNorthingField | typeof Components.EmailAddressField | typeof Components.LatLongField | typeof Components.MonthYearField | typeof Components.MultilineTextField | typeof Components.NationalGridFieldNumberField | typeof Components.NumberField | typeof Components.OsGridRefField | typeof Components.SelectField | typeof Components.TelephoneNumberField | typeof Components.TextField | typeof Components.UkAddressField | typeof Components.FileUploadField | typeof Components.HiddenField | typeof Components.TrackingField | typeof Components.PaymentField | typeof Components.GeospatialField>;
9
9
  export type Guidance = InstanceType<typeof Components.Details> | InstanceType<typeof Components.Html> | InstanceType<typeof Components.Markdown> | InstanceType<typeof Components.InsetText> | InstanceType<typeof Components.List> | InstanceType<typeof Components.NotificationBanner>;
10
10
  export type ListField = InstanceType<typeof Components.AutocompleteField | typeof Components.CheckboxesField | typeof Components.RadiosField | typeof Components.SelectField | typeof Components.YesNoField>;
11
11
  export declare const designerUrl: string;
@@ -114,6 +114,9 @@ export function createComponent(def, options) {
114
114
  case ComponentType.HiddenField:
115
115
  component = new Components.HiddenField(def, options);
116
116
  break;
117
+ case ComponentType.TrackingField:
118
+ component = new Components.TrackingField(def, options);
119
+ break;
117
120
  case ComponentType.PaymentField:
118
121
  component = new Components.PaymentField(def, options);
119
122
  break;
@@ -1 +1 @@
1
- {"version":3,"file":"components.js","names":["ComponentType","config","ListFormComponent","escapeMarkdown","Components","markdown","UnknownComponentTypeError","designerUrl","get","hasListFormField","field","type","undefined","isListFieldType","allowedTypes","AutocompleteField","CheckboxesField","RadiosField","SelectField","YesNoField","includes","createComponent","def","options","component","DatePartsField","DeclarationField","Details","EmailAddressField","Html","InsetText","List","Markdown","NotificationBanner","MultilineTextField","NumberField","TelephoneNumberField","TextField","UkAddressField","MonthYearField","FileUploadField","EastingNorthingField","OsGridRefField","NationalGridFieldNumberField","LatLongField","HiddenField","PaymentField","GeospatialField","getAnswer","state","translator","format","getAnswerMarkdown","context","getContextValueFromState","toString","parse","async","trim","getDisplayStringFromState","answer","answerEscaped","files","getFormValueFromState","length","map","status","file","form","filename","fileId","join","values","flat","items","filter","value","item","resolvedText","tListItem","text","label","line","toLowerCase","split","concat","features","getDisplayStringFromFormValue"],"sources":["../../../../../../src/server/plugins/engine/components/helpers/components.ts"],"sourcesContent":["import { ComponentType, type ComponentDef } from '@defra/forms-model'\n\nimport { config } from '~/src/config/index.js'\nimport { type ComponentBase } from '~/src/server/plugins/engine/components/ComponentBase.js'\nimport { ListFormComponent } from '~/src/server/plugins/engine/components/ListFormComponent.js'\nimport { escapeMarkdown } from '~/src/server/plugins/engine/components/helpers/index.js'\nimport * as Components from '~/src/server/plugins/engine/components/index.js'\nimport { markdown } from '~/src/server/plugins/engine/components/markdownParser.js'\nimport { UnknownComponentTypeError } from '~/src/server/plugins/engine/errors.js'\nimport { type Translator } from '~/src/server/plugins/engine/i18n/types.js'\nimport { type FormState } from '~/src/server/plugins/engine/types.js'\n\n// All component instances\nexport type Component = InstanceType<\n (typeof Components)[keyof typeof Components]\n>\n\n// Field component instances only\nexport type Field = InstanceType<\n | typeof Components.AutocompleteField\n | typeof Components.RadiosField\n | typeof Components.YesNoField\n | typeof Components.CheckboxesField\n | typeof Components.DatePartsField\n | typeof Components.DeclarationField\n | typeof Components.EastingNorthingField\n | typeof Components.EmailAddressField\n | typeof Components.LatLongField\n | typeof Components.MonthYearField\n | typeof Components.MultilineTextField\n | typeof Components.NationalGridFieldNumberField\n | typeof Components.NumberField\n | typeof Components.OsGridRefField\n | typeof Components.SelectField\n | typeof Components.TelephoneNumberField\n | typeof Components.TextField\n | typeof Components.UkAddressField\n | typeof Components.FileUploadField\n | typeof Components.HiddenField\n | typeof Components.PaymentField\n | typeof Components.GeospatialField\n>\n\n// Guidance component instances only\nexport type Guidance =\n | InstanceType<typeof Components.Details>\n | InstanceType<typeof Components.Html>\n | InstanceType<typeof Components.Markdown>\n | InstanceType<typeof Components.InsetText>\n | InstanceType<typeof Components.List>\n | InstanceType<typeof Components.NotificationBanner>\n\n// List component instances only\nexport type ListField = InstanceType<\n | typeof Components.AutocompleteField\n | typeof Components.CheckboxesField\n | typeof Components.RadiosField\n | typeof Components.SelectField\n | typeof Components.YesNoField\n>\n\nexport const designerUrl = config.get('designerUrl')\n\n// Re-export markdown from its own module to avoid circular dependencies\nexport { markdown } from '~/src/server/plugins/engine/components/markdownParser.js'\n\n/**\n * Filter known components with lists\n */\nexport function hasListFormField(\n field?: Partial<Component>\n): field is ListFormComponent {\n return !!field && field.type !== undefined && isListFieldType(field.type)\n}\n\nexport function isListFieldType(\n type?: ComponentType\n): type is ListField['type'] {\n const allowedTypes = [\n ComponentType.AutocompleteField,\n ComponentType.CheckboxesField,\n ComponentType.RadiosField,\n ComponentType.SelectField,\n ComponentType.YesNoField\n ]\n\n return !!type && allowedTypes.includes(type)\n}\n\n/**\n * Create field instance for each {@link ComponentDef} type\n */\nexport function createComponent(\n def: ComponentDef,\n options: ConstructorParameters<typeof ComponentBase>[1]\n): Component {\n let component: Component | undefined\n\n switch (def.type) {\n case ComponentType.AutocompleteField:\n component = new Components.AutocompleteField(def, options)\n break\n\n case ComponentType.CheckboxesField:\n component = new Components.CheckboxesField(def, options)\n break\n\n case ComponentType.DatePartsField:\n component = new Components.DatePartsField(def, options)\n break\n\n case ComponentType.DeclarationField:\n component = new Components.DeclarationField(def, options)\n break\n\n case ComponentType.Details:\n component = new Components.Details(def, options)\n break\n\n case ComponentType.EmailAddressField:\n component = new Components.EmailAddressField(def, options)\n break\n\n case ComponentType.Html:\n component = new Components.Html(def, options)\n break\n\n case ComponentType.InsetText:\n component = new Components.InsetText(def, options)\n break\n\n case ComponentType.List:\n component = new Components.List(def, options)\n break\n\n case ComponentType.Markdown:\n component = new Components.Markdown(def, options)\n break\n\n case ComponentType.NotificationBanner:\n component = new Components.NotificationBanner(def, options)\n break\n\n case ComponentType.MultilineTextField:\n component = new Components.MultilineTextField(def, options)\n break\n\n case ComponentType.NumberField:\n component = new Components.NumberField(def, options)\n break\n\n case ComponentType.RadiosField:\n component = new Components.RadiosField(def, options)\n break\n\n case ComponentType.SelectField:\n component = new Components.SelectField(def, options)\n break\n\n case ComponentType.TelephoneNumberField:\n component = new Components.TelephoneNumberField(def, options)\n break\n\n case ComponentType.TextField:\n component = new Components.TextField(def, options)\n break\n\n case ComponentType.UkAddressField:\n component = new Components.UkAddressField(def, options)\n break\n\n case ComponentType.YesNoField:\n component = new Components.YesNoField(def, options)\n break\n\n case ComponentType.MonthYearField:\n component = new Components.MonthYearField(def, options)\n break\n\n case ComponentType.FileUploadField:\n component = new Components.FileUploadField(def, options)\n break\n\n case ComponentType.EastingNorthingField:\n component = new Components.EastingNorthingField(def, options)\n break\n\n case ComponentType.OsGridRefField:\n component = new Components.OsGridRefField(def, options)\n break\n\n case ComponentType.NationalGridFieldNumberField:\n component = new Components.NationalGridFieldNumberField(def, options)\n break\n\n case ComponentType.LatLongField:\n component = new Components.LatLongField(def, options)\n break\n\n case ComponentType.HiddenField:\n component = new Components.HiddenField(def, options)\n break\n\n case ComponentType.PaymentField:\n component = new Components.PaymentField(def, options)\n break\n\n case ComponentType.GeospatialField:\n component = new Components.GeospatialField(def, options)\n break\n }\n\n if (typeof component === 'undefined') {\n throw new UnknownComponentTypeError(def.type)\n }\n\n return component\n}\n\n/**\n * Get formatted answer for a field\n */\nexport function getAnswer(\n field: Field,\n state: FormState,\n translator: Translator,\n options: {\n format:\n | 'data' // Submission data\n | 'email' // GOV.UK Notify emails\n | 'summary' // Check answers summary\n } = { format: 'summary' }\n) {\n // Use escaped display text for GOV.UK Notify emails\n if (options.format === 'email') {\n return getAnswerMarkdown(field, state, translator, { format: 'email' })\n }\n\n // Use context value for submission data\n if (options.format === 'data') {\n const context = field.getContextValueFromState(state)\n return context?.toString() ?? ''\n }\n\n // Use display HTML for check answers summary (multi line)\n if (\n field instanceof ListFormComponent ||\n field instanceof Components.MultilineTextField ||\n field instanceof Components.UkAddressField ||\n field instanceof Components.EastingNorthingField ||\n field instanceof Components.LatLongField\n ) {\n return markdown\n .parse(\n getAnswerMarkdown(field, state, translator, { format: 'summary' }),\n { async: false }\n )\n .trim()\n }\n\n // Use display text for check answers summary (single line)\n return field.getDisplayStringFromState(state, translator)\n}\n\n/**\n * Get formatted answer for a field (Markdown only)\n */\nexport function getAnswerMarkdown(\n field: Field,\n state: FormState,\n translator: Translator,\n options: {\n format:\n | 'email' // GOV.UK Notify emails\n | 'summary' // Check answers summary\n } = { format: 'summary' }\n) {\n const answer = field.getDisplayStringFromState(state, translator)\n\n // Use escaped display text\n let answerEscaped = `${escapeMarkdown(answer)}\\n`\n\n if (field instanceof Components.FileUploadField) {\n const files = field.getFormValueFromState(state)\n\n // Skip empty files\n if (!files?.length) {\n return answerEscaped\n }\n\n answerEscaped = `${escapeMarkdown(answer)}:\\n\\n`\n\n // Append bullet points\n answerEscaped += files\n .map(({ status }) => {\n const { file } = status.form\n const filename = escapeMarkdown(file.filename)\n return `* [${filename}](${designerUrl}/file-download/${file.fileId})\\n`\n })\n .join('')\n } else if (field instanceof ListFormComponent) {\n const values = [field.getContextValueFromState(state)].flat()\n const items = field.items.filter(({ value }) => values.includes(value))\n\n // Skip empty values\n if (!items.length) {\n return answerEscaped\n }\n\n answerEscaped = ''\n\n // Append bullet points\n answerEscaped += items\n .map((item) => {\n const resolvedText = translator.tListItem(item, 'text') || item.text\n const label = escapeMarkdown(resolvedText)\n const value = escapeMarkdown(`(${item.value})`)\n\n let line = label\n\n // Prepend bullet points for checkboxes only\n if (field instanceof Components.CheckboxesField) {\n line = `* ${line}`\n }\n\n // Append raw values in parentheses\n // e.g. `* None of the above (false)`\n return options.format === 'email' &&\n `${item.value}`.toLowerCase() !== item.text.toLowerCase()\n ? `${line} ${value}\\n`\n : `${line}\\n`\n })\n .join('')\n } else if (field instanceof Components.MultilineTextField) {\n // Preserve Multiline text new lines\n answerEscaped = answer\n .split(/(?:\\r?\\n)+/)\n .map(escapeMarkdown)\n .join('\\n')\n .concat('\\n')\n } else if (field instanceof Components.UkAddressField) {\n // Format UK addresses into new lines\n answerEscaped = (field.getContextValueFromState(state) ?? [])\n .map(escapeMarkdown)\n .join('\\n')\n .concat('\\n')\n } else if (\n field instanceof Components.EastingNorthingField ||\n field instanceof Components.LatLongField\n ) {\n answerEscaped = answer ? `${answer}\\n` : ''\n } else if (field instanceof Components.GeospatialField) {\n const features = field.getFormValueFromState(state)\n const value = field.getDisplayStringFromFormValue(features, translator)\n\n answerEscaped = value ? `${value}\\n` : ''\n }\n\n return answerEscaped\n}\n"],"mappings":"AAAA,SAASA,aAAa,QAA2B,oBAAoB;AAErE,SAASC,MAAM;AAEf,SAASC,iBAAiB;AAC1B,SAASC,cAAc;AACvB,OAAO,KAAKC,UAAU;AACtB,SAASC,QAAQ;AACjB,SAASC,yBAAyB;;AAIlC;;AAKA;;AA0BA;;AASA;;AASA,OAAO,MAAMC,WAAW,GAAGN,MAAM,CAACO,GAAG,CAAC,aAAa,CAAC;;AAEpD;AACA,SAASH,QAAQ;;AAEjB;AACA;AACA;AACA,OAAO,SAASI,gBAAgBA,CAC9BC,KAA0B,EACE;EAC5B,OAAO,CAAC,CAACA,KAAK,IAAIA,KAAK,CAACC,IAAI,KAAKC,SAAS,IAAIC,eAAe,CAACH,KAAK,CAACC,IAAI,CAAC;AAC3E;AAEA,OAAO,SAASE,eAAeA,CAC7BF,IAAoB,EACO;EAC3B,MAAMG,YAAY,GAAG,CACnBd,aAAa,CAACe,iBAAiB,EAC/Bf,aAAa,CAACgB,eAAe,EAC7BhB,aAAa,CAACiB,WAAW,EACzBjB,aAAa,CAACkB,WAAW,EACzBlB,aAAa,CAACmB,UAAU,CACzB;EAED,OAAO,CAAC,CAACR,IAAI,IAAIG,YAAY,CAACM,QAAQ,CAACT,IAAI,CAAC;AAC9C;;AAEA;AACA;AACA;AACA,OAAO,SAASU,eAAeA,CAC7BC,GAAiB,EACjBC,OAAuD,EAC5C;EACX,IAAIC,SAAgC;EAEpC,QAAQF,GAAG,CAACX,IAAI;IACd,KAAKX,aAAa,CAACe,iBAAiB;MAClCS,SAAS,GAAG,IAAIpB,UAAU,CAACW,iBAAiB,CAACO,GAAG,EAAEC,OAAO,CAAC;MAC1D;IAEF,KAAKvB,aAAa,CAACgB,eAAe;MAChCQ,SAAS,GAAG,IAAIpB,UAAU,CAACY,eAAe,CAACM,GAAG,EAAEC,OAAO,CAAC;MACxD;IAEF,KAAKvB,aAAa,CAACyB,cAAc;MAC/BD,SAAS,GAAG,IAAIpB,UAAU,CAACqB,cAAc,CAACH,GAAG,EAAEC,OAAO,CAAC;MACvD;IAEF,KAAKvB,aAAa,CAAC0B,gBAAgB;MACjCF,SAAS,GAAG,IAAIpB,UAAU,CAACsB,gBAAgB,CAACJ,GAAG,EAAEC,OAAO,CAAC;MACzD;IAEF,KAAKvB,aAAa,CAAC2B,OAAO;MACxBH,SAAS,GAAG,IAAIpB,UAAU,CAACuB,OAAO,CAACL,GAAG,EAAEC,OAAO,CAAC;MAChD;IAEF,KAAKvB,aAAa,CAAC4B,iBAAiB;MAClCJ,SAAS,GAAG,IAAIpB,UAAU,CAACwB,iBAAiB,CAACN,GAAG,EAAEC,OAAO,CAAC;MAC1D;IAEF,KAAKvB,aAAa,CAAC6B,IAAI;MACrBL,SAAS,GAAG,IAAIpB,UAAU,CAACyB,IAAI,CAACP,GAAG,EAAEC,OAAO,CAAC;MAC7C;IAEF,KAAKvB,aAAa,CAAC8B,SAAS;MAC1BN,SAAS,GAAG,IAAIpB,UAAU,CAAC0B,SAAS,CAACR,GAAG,EAAEC,OAAO,CAAC;MAClD;IAEF,KAAKvB,aAAa,CAAC+B,IAAI;MACrBP,SAAS,GAAG,IAAIpB,UAAU,CAAC2B,IAAI,CAACT,GAAG,EAAEC,OAAO,CAAC;MAC7C;IAEF,KAAKvB,aAAa,CAACgC,QAAQ;MACzBR,SAAS,GAAG,IAAIpB,UAAU,CAAC4B,QAAQ,CAACV,GAAG,EAAEC,OAAO,CAAC;MACjD;IAEF,KAAKvB,aAAa,CAACiC,kBAAkB;MACnCT,SAAS,GAAG,IAAIpB,UAAU,CAAC6B,kBAAkB,CAACX,GAAG,EAAEC,OAAO,CAAC;MAC3D;IAEF,KAAKvB,aAAa,CAACkC,kBAAkB;MACnCV,SAAS,GAAG,IAAIpB,UAAU,CAAC8B,kBAAkB,CAACZ,GAAG,EAAEC,OAAO,CAAC;MAC3D;IAEF,KAAKvB,aAAa,CAACmC,WAAW;MAC5BX,SAAS,GAAG,IAAIpB,UAAU,CAAC+B,WAAW,CAACb,GAAG,EAAEC,OAAO,CAAC;MACpD;IAEF,KAAKvB,aAAa,CAACiB,WAAW;MAC5BO,SAAS,GAAG,IAAIpB,UAAU,CAACa,WAAW,CAACK,GAAG,EAAEC,OAAO,CAAC;MACpD;IAEF,KAAKvB,aAAa,CAACkB,WAAW;MAC5BM,SAAS,GAAG,IAAIpB,UAAU,CAACc,WAAW,CAACI,GAAG,EAAEC,OAAO,CAAC;MACpD;IAEF,KAAKvB,aAAa,CAACoC,oBAAoB;MACrCZ,SAAS,GAAG,IAAIpB,UAAU,CAACgC,oBAAoB,CAACd,GAAG,EAAEC,OAAO,CAAC;MAC7D;IAEF,KAAKvB,aAAa,CAACqC,SAAS;MAC1Bb,SAAS,GAAG,IAAIpB,UAAU,CAACiC,SAAS,CAACf,GAAG,EAAEC,OAAO,CAAC;MAClD;IAEF,KAAKvB,aAAa,CAACsC,cAAc;MAC/Bd,SAAS,GAAG,IAAIpB,UAAU,CAACkC,cAAc,CAAChB,GAAG,EAAEC,OAAO,CAAC;MACvD;IAEF,KAAKvB,aAAa,CAACmB,UAAU;MAC3BK,SAAS,GAAG,IAAIpB,UAAU,CAACe,UAAU,CAACG,GAAG,EAAEC,OAAO,CAAC;MACnD;IAEF,KAAKvB,aAAa,CAACuC,cAAc;MAC/Bf,SAAS,GAAG,IAAIpB,UAAU,CAACmC,cAAc,CAACjB,GAAG,EAAEC,OAAO,CAAC;MACvD;IAEF,KAAKvB,aAAa,CAACwC,eAAe;MAChChB,SAAS,GAAG,IAAIpB,UAAU,CAACoC,eAAe,CAAClB,GAAG,EAAEC,OAAO,CAAC;MACxD;IAEF,KAAKvB,aAAa,CAACyC,oBAAoB;MACrCjB,SAAS,GAAG,IAAIpB,UAAU,CAACqC,oBAAoB,CAACnB,GAAG,EAAEC,OAAO,CAAC;MAC7D;IAEF,KAAKvB,aAAa,CAAC0C,cAAc;MAC/BlB,SAAS,GAAG,IAAIpB,UAAU,CAACsC,cAAc,CAACpB,GAAG,EAAEC,OAAO,CAAC;MACvD;IAEF,KAAKvB,aAAa,CAAC2C,4BAA4B;MAC7CnB,SAAS,GAAG,IAAIpB,UAAU,CAACuC,4BAA4B,CAACrB,GAAG,EAAEC,OAAO,CAAC;MACrE;IAEF,KAAKvB,aAAa,CAAC4C,YAAY;MAC7BpB,SAAS,GAAG,IAAIpB,UAAU,CAACwC,YAAY,CAACtB,GAAG,EAAEC,OAAO,CAAC;MACrD;IAEF,KAAKvB,aAAa,CAAC6C,WAAW;MAC5BrB,SAAS,GAAG,IAAIpB,UAAU,CAACyC,WAAW,CAACvB,GAAG,EAAEC,OAAO,CAAC;MACpD;IAEF,KAAKvB,aAAa,CAAC8C,YAAY;MAC7BtB,SAAS,GAAG,IAAIpB,UAAU,CAAC0C,YAAY,CAACxB,GAAG,EAAEC,OAAO,CAAC;MACrD;IAEF,KAAKvB,aAAa,CAAC+C,eAAe;MAChCvB,SAAS,GAAG,IAAIpB,UAAU,CAAC2C,eAAe,CAACzB,GAAG,EAAEC,OAAO,CAAC;MACxD;EACJ;EAEA,IAAI,OAAOC,SAAS,KAAK,WAAW,EAAE;IACpC,MAAM,IAAIlB,yBAAyB,CAACgB,GAAG,CAACX,IAAI,CAAC;EAC/C;EAEA,OAAOa,SAAS;AAClB;;AAEA;AACA;AACA;AACA,OAAO,SAASwB,SAASA,CACvBtC,KAAY,EACZuC,KAAgB,EAChBC,UAAsB,EACtB3B,OAKC,GAAG;EAAE4B,MAAM,EAAE;AAAU,CAAC,EACzB;EACA;EACA,IAAI5B,OAAO,CAAC4B,MAAM,KAAK,OAAO,EAAE;IAC9B,OAAOC,iBAAiB,CAAC1C,KAAK,EAAEuC,KAAK,EAAEC,UAAU,EAAE;MAAEC,MAAM,EAAE;IAAQ,CAAC,CAAC;EACzE;;EAEA;EACA,IAAI5B,OAAO,CAAC4B,MAAM,KAAK,MAAM,EAAE;IAC7B,MAAME,OAAO,GAAG3C,KAAK,CAAC4C,wBAAwB,CAACL,KAAK,CAAC;IACrD,OAAOI,OAAO,EAAEE,QAAQ,CAAC,CAAC,IAAI,EAAE;EAClC;;EAEA;EACA,IACE7C,KAAK,YAAYR,iBAAiB,IAClCQ,KAAK,YAAYN,UAAU,CAAC8B,kBAAkB,IAC9CxB,KAAK,YAAYN,UAAU,CAACkC,cAAc,IAC1C5B,KAAK,YAAYN,UAAU,CAACqC,oBAAoB,IAChD/B,KAAK,YAAYN,UAAU,CAACwC,YAAY,EACxC;IACA,OAAOvC,QAAQ,CACZmD,KAAK,CACJJ,iBAAiB,CAAC1C,KAAK,EAAEuC,KAAK,EAAEC,UAAU,EAAE;MAAEC,MAAM,EAAE;IAAU,CAAC,CAAC,EAClE;MAAEM,KAAK,EAAE;IAAM,CACjB,CAAC,CACAC,IAAI,CAAC,CAAC;EACX;;EAEA;EACA,OAAOhD,KAAK,CAACiD,yBAAyB,CAACV,KAAK,EAAEC,UAAU,CAAC;AAC3D;;AAEA;AACA;AACA;AACA,OAAO,SAASE,iBAAiBA,CAC/B1C,KAAY,EACZuC,KAAgB,EAChBC,UAAsB,EACtB3B,OAIC,GAAG;EAAE4B,MAAM,EAAE;AAAU,CAAC,EACzB;EACA,MAAMS,MAAM,GAAGlD,KAAK,CAACiD,yBAAyB,CAACV,KAAK,EAAEC,UAAU,CAAC;;EAEjE;EACA,IAAIW,aAAa,GAAG,GAAG1D,cAAc,CAACyD,MAAM,CAAC,IAAI;EAEjD,IAAIlD,KAAK,YAAYN,UAAU,CAACoC,eAAe,EAAE;IAC/C,MAAMsB,KAAK,GAAGpD,KAAK,CAACqD,qBAAqB,CAACd,KAAK,CAAC;;IAEhD;IACA,IAAI,CAACa,KAAK,EAAEE,MAAM,EAAE;MAClB,OAAOH,aAAa;IACtB;IAEAA,aAAa,GAAG,GAAG1D,cAAc,CAACyD,MAAM,CAAC,OAAO;;IAEhD;IACAC,aAAa,IAAIC,KAAK,CACnBG,GAAG,CAAC,CAAC;MAAEC;IAAO,CAAC,KAAK;MACnB,MAAM;QAAEC;MAAK,CAAC,GAAGD,MAAM,CAACE,IAAI;MAC5B,MAAMC,QAAQ,GAAGlE,cAAc,CAACgE,IAAI,CAACE,QAAQ,CAAC;MAC9C,OAAO,MAAMA,QAAQ,KAAK9D,WAAW,kBAAkB4D,IAAI,CAACG,MAAM,KAAK;IACzE,CAAC,CAAC,CACDC,IAAI,CAAC,EAAE,CAAC;EACb,CAAC,MAAM,IAAI7D,KAAK,YAAYR,iBAAiB,EAAE;IAC7C,MAAMsE,MAAM,GAAG,CAAC9D,KAAK,CAAC4C,wBAAwB,CAACL,KAAK,CAAC,CAAC,CAACwB,IAAI,CAAC,CAAC;IAC7D,MAAMC,KAAK,GAAGhE,KAAK,CAACgE,KAAK,CAACC,MAAM,CAAC,CAAC;MAAEC;IAAM,CAAC,KAAKJ,MAAM,CAACpD,QAAQ,CAACwD,KAAK,CAAC,CAAC;;IAEvE;IACA,IAAI,CAACF,KAAK,CAACV,MAAM,EAAE;MACjB,OAAOH,aAAa;IACtB;IAEAA,aAAa,GAAG,EAAE;;IAElB;IACAA,aAAa,IAAIa,KAAK,CACnBT,GAAG,CAAEY,IAAI,IAAK;MACb,MAAMC,YAAY,GAAG5B,UAAU,CAAC6B,SAAS,CAACF,IAAI,EAAE,MAAM,CAAC,IAAIA,IAAI,CAACG,IAAI;MACpE,MAAMC,KAAK,GAAG9E,cAAc,CAAC2E,YAAY,CAAC;MAC1C,MAAMF,KAAK,GAAGzE,cAAc,CAAC,IAAI0E,IAAI,CAACD,KAAK,GAAG,CAAC;MAE/C,IAAIM,IAAI,GAAGD,KAAK;;MAEhB;MACA,IAAIvE,KAAK,YAAYN,UAAU,CAACY,eAAe,EAAE;QAC/CkE,IAAI,GAAG,KAAKA,IAAI,EAAE;MACpB;;MAEA;MACA;MACA,OAAO3D,OAAO,CAAC4B,MAAM,KAAK,OAAO,IAC/B,GAAG0B,IAAI,CAACD,KAAK,EAAE,CAACO,WAAW,CAAC,CAAC,KAAKN,IAAI,CAACG,IAAI,CAACG,WAAW,CAAC,CAAC,GACvD,GAAGD,IAAI,IAAIN,KAAK,IAAI,GACpB,GAAGM,IAAI,IAAI;IACjB,CAAC,CAAC,CACDX,IAAI,CAAC,EAAE,CAAC;EACb,CAAC,MAAM,IAAI7D,KAAK,YAAYN,UAAU,CAAC8B,kBAAkB,EAAE;IACzD;IACA2B,aAAa,GAAGD,MAAM,CACnBwB,KAAK,CAAC,YAAY,CAAC,CACnBnB,GAAG,CAAC9D,cAAc,CAAC,CACnBoE,IAAI,CAAC,IAAI,CAAC,CACVc,MAAM,CAAC,IAAI,CAAC;EACjB,CAAC,MAAM,IAAI3E,KAAK,YAAYN,UAAU,CAACkC,cAAc,EAAE;IACrD;IACAuB,aAAa,GAAG,CAACnD,KAAK,CAAC4C,wBAAwB,CAACL,KAAK,CAAC,IAAI,EAAE,EACzDgB,GAAG,CAAC9D,cAAc,CAAC,CACnBoE,IAAI,CAAC,IAAI,CAAC,CACVc,MAAM,CAAC,IAAI,CAAC;EACjB,CAAC,MAAM,IACL3E,KAAK,YAAYN,UAAU,CAACqC,oBAAoB,IAChD/B,KAAK,YAAYN,UAAU,CAACwC,YAAY,EACxC;IACAiB,aAAa,GAAGD,MAAM,GAAG,GAAGA,MAAM,IAAI,GAAG,EAAE;EAC7C,CAAC,MAAM,IAAIlD,KAAK,YAAYN,UAAU,CAAC2C,eAAe,EAAE;IACtD,MAAMuC,QAAQ,GAAG5E,KAAK,CAACqD,qBAAqB,CAACd,KAAK,CAAC;IACnD,MAAM2B,KAAK,GAAGlE,KAAK,CAAC6E,6BAA6B,CAACD,QAAQ,EAAEpC,UAAU,CAAC;IAEvEW,aAAa,GAAGe,KAAK,GAAG,GAAGA,KAAK,IAAI,GAAG,EAAE;EAC3C;EAEA,OAAOf,aAAa;AACtB","ignoreList":[]}
1
+ {"version":3,"file":"components.js","names":["ComponentType","config","ListFormComponent","escapeMarkdown","Components","markdown","UnknownComponentTypeError","designerUrl","get","hasListFormField","field","type","undefined","isListFieldType","allowedTypes","AutocompleteField","CheckboxesField","RadiosField","SelectField","YesNoField","includes","createComponent","def","options","component","DatePartsField","DeclarationField","Details","EmailAddressField","Html","InsetText","List","Markdown","NotificationBanner","MultilineTextField","NumberField","TelephoneNumberField","TextField","UkAddressField","MonthYearField","FileUploadField","EastingNorthingField","OsGridRefField","NationalGridFieldNumberField","LatLongField","HiddenField","TrackingField","PaymentField","GeospatialField","getAnswer","state","translator","format","getAnswerMarkdown","context","getContextValueFromState","toString","parse","async","trim","getDisplayStringFromState","answer","answerEscaped","files","getFormValueFromState","length","map","status","file","form","filename","fileId","join","values","flat","items","filter","value","item","resolvedText","tListItem","text","label","line","toLowerCase","split","concat","features","getDisplayStringFromFormValue"],"sources":["../../../../../../src/server/plugins/engine/components/helpers/components.ts"],"sourcesContent":["import { ComponentType, type ComponentDef } from '@defra/forms-model'\n\nimport { config } from '~/src/config/index.js'\nimport { type ComponentBase } from '~/src/server/plugins/engine/components/ComponentBase.js'\nimport { ListFormComponent } from '~/src/server/plugins/engine/components/ListFormComponent.js'\nimport { escapeMarkdown } from '~/src/server/plugins/engine/components/helpers/index.js'\nimport * as Components from '~/src/server/plugins/engine/components/index.js'\nimport { markdown } from '~/src/server/plugins/engine/components/markdownParser.js'\nimport { UnknownComponentTypeError } from '~/src/server/plugins/engine/errors.js'\nimport { type Translator } from '~/src/server/plugins/engine/i18n/types.js'\nimport { type FormState } from '~/src/server/plugins/engine/types.js'\n\n// All component instances\nexport type Component = InstanceType<\n (typeof Components)[keyof typeof Components]\n>\n\n// Field component instances only\nexport type Field = InstanceType<\n | typeof Components.AutocompleteField\n | typeof Components.RadiosField\n | typeof Components.YesNoField\n | typeof Components.CheckboxesField\n | typeof Components.DatePartsField\n | typeof Components.DeclarationField\n | typeof Components.EastingNorthingField\n | typeof Components.EmailAddressField\n | typeof Components.LatLongField\n | typeof Components.MonthYearField\n | typeof Components.MultilineTextField\n | typeof Components.NationalGridFieldNumberField\n | typeof Components.NumberField\n | typeof Components.OsGridRefField\n | typeof Components.SelectField\n | typeof Components.TelephoneNumberField\n | typeof Components.TextField\n | typeof Components.UkAddressField\n | typeof Components.FileUploadField\n | typeof Components.HiddenField\n | typeof Components.TrackingField\n | typeof Components.PaymentField\n | typeof Components.GeospatialField\n>\n\n// Guidance component instances only\nexport type Guidance =\n | InstanceType<typeof Components.Details>\n | InstanceType<typeof Components.Html>\n | InstanceType<typeof Components.Markdown>\n | InstanceType<typeof Components.InsetText>\n | InstanceType<typeof Components.List>\n | InstanceType<typeof Components.NotificationBanner>\n\n// List component instances only\nexport type ListField = InstanceType<\n | typeof Components.AutocompleteField\n | typeof Components.CheckboxesField\n | typeof Components.RadiosField\n | typeof Components.SelectField\n | typeof Components.YesNoField\n>\n\nexport const designerUrl = config.get('designerUrl')\n\n// Re-export markdown from its own module to avoid circular dependencies\nexport { markdown } from '~/src/server/plugins/engine/components/markdownParser.js'\n\n/**\n * Filter known components with lists\n */\nexport function hasListFormField(\n field?: Partial<Component>\n): field is ListFormComponent {\n return !!field && field.type !== undefined && isListFieldType(field.type)\n}\n\nexport function isListFieldType(\n type?: ComponentType\n): type is ListField['type'] {\n const allowedTypes = [\n ComponentType.AutocompleteField,\n ComponentType.CheckboxesField,\n ComponentType.RadiosField,\n ComponentType.SelectField,\n ComponentType.YesNoField\n ]\n\n return !!type && allowedTypes.includes(type)\n}\n\n/**\n * Create field instance for each {@link ComponentDef} type\n */\nexport function createComponent(\n def: ComponentDef,\n options: ConstructorParameters<typeof ComponentBase>[1]\n): Component {\n let component: Component | undefined\n\n switch (def.type) {\n case ComponentType.AutocompleteField:\n component = new Components.AutocompleteField(def, options)\n break\n\n case ComponentType.CheckboxesField:\n component = new Components.CheckboxesField(def, options)\n break\n\n case ComponentType.DatePartsField:\n component = new Components.DatePartsField(def, options)\n break\n\n case ComponentType.DeclarationField:\n component = new Components.DeclarationField(def, options)\n break\n\n case ComponentType.Details:\n component = new Components.Details(def, options)\n break\n\n case ComponentType.EmailAddressField:\n component = new Components.EmailAddressField(def, options)\n break\n\n case ComponentType.Html:\n component = new Components.Html(def, options)\n break\n\n case ComponentType.InsetText:\n component = new Components.InsetText(def, options)\n break\n\n case ComponentType.List:\n component = new Components.List(def, options)\n break\n\n case ComponentType.Markdown:\n component = new Components.Markdown(def, options)\n break\n\n case ComponentType.NotificationBanner:\n component = new Components.NotificationBanner(def, options)\n break\n\n case ComponentType.MultilineTextField:\n component = new Components.MultilineTextField(def, options)\n break\n\n case ComponentType.NumberField:\n component = new Components.NumberField(def, options)\n break\n\n case ComponentType.RadiosField:\n component = new Components.RadiosField(def, options)\n break\n\n case ComponentType.SelectField:\n component = new Components.SelectField(def, options)\n break\n\n case ComponentType.TelephoneNumberField:\n component = new Components.TelephoneNumberField(def, options)\n break\n\n case ComponentType.TextField:\n component = new Components.TextField(def, options)\n break\n\n case ComponentType.UkAddressField:\n component = new Components.UkAddressField(def, options)\n break\n\n case ComponentType.YesNoField:\n component = new Components.YesNoField(def, options)\n break\n\n case ComponentType.MonthYearField:\n component = new Components.MonthYearField(def, options)\n break\n\n case ComponentType.FileUploadField:\n component = new Components.FileUploadField(def, options)\n break\n\n case ComponentType.EastingNorthingField:\n component = new Components.EastingNorthingField(def, options)\n break\n\n case ComponentType.OsGridRefField:\n component = new Components.OsGridRefField(def, options)\n break\n\n case ComponentType.NationalGridFieldNumberField:\n component = new Components.NationalGridFieldNumberField(def, options)\n break\n\n case ComponentType.LatLongField:\n component = new Components.LatLongField(def, options)\n break\n\n case ComponentType.HiddenField:\n component = new Components.HiddenField(def, options)\n break\n\n case ComponentType.TrackingField:\n component = new Components.TrackingField(def, options)\n break\n\n case ComponentType.PaymentField:\n component = new Components.PaymentField(def, options)\n break\n\n case ComponentType.GeospatialField:\n component = new Components.GeospatialField(def, options)\n break\n }\n\n if (typeof component === 'undefined') {\n throw new UnknownComponentTypeError(def.type)\n }\n\n return component\n}\n\n/**\n * Get formatted answer for a field\n */\nexport function getAnswer(\n field: Field,\n state: FormState,\n translator: Translator,\n options: {\n format:\n | 'data' // Submission data\n | 'email' // GOV.UK Notify emails\n | 'summary' // Check answers summary\n } = { format: 'summary' }\n) {\n // Use escaped display text for GOV.UK Notify emails\n if (options.format === 'email') {\n return getAnswerMarkdown(field, state, translator, { format: 'email' })\n }\n\n // Use context value for submission data\n if (options.format === 'data') {\n const context = field.getContextValueFromState(state)\n return context?.toString() ?? ''\n }\n\n // Use display HTML for check answers summary (multi line)\n if (\n field instanceof ListFormComponent ||\n field instanceof Components.MultilineTextField ||\n field instanceof Components.UkAddressField ||\n field instanceof Components.EastingNorthingField ||\n field instanceof Components.LatLongField\n ) {\n return markdown\n .parse(\n getAnswerMarkdown(field, state, translator, { format: 'summary' }),\n { async: false }\n )\n .trim()\n }\n\n // Use display text for check answers summary (single line)\n return field.getDisplayStringFromState(state, translator)\n}\n\n/**\n * Get formatted answer for a field (Markdown only)\n */\nexport function getAnswerMarkdown(\n field: Field,\n state: FormState,\n translator: Translator,\n options: {\n format:\n | 'email' // GOV.UK Notify emails\n | 'summary' // Check answers summary\n } = { format: 'summary' }\n) {\n const answer = field.getDisplayStringFromState(state, translator)\n\n // Use escaped display text\n let answerEscaped = `${escapeMarkdown(answer)}\\n`\n\n if (field instanceof Components.FileUploadField) {\n const files = field.getFormValueFromState(state)\n\n // Skip empty files\n if (!files?.length) {\n return answerEscaped\n }\n\n answerEscaped = `${escapeMarkdown(answer)}:\\n\\n`\n\n // Append bullet points\n answerEscaped += files\n .map(({ status }) => {\n const { file } = status.form\n const filename = escapeMarkdown(file.filename)\n return `* [${filename}](${designerUrl}/file-download/${file.fileId})\\n`\n })\n .join('')\n } else if (field instanceof ListFormComponent) {\n const values = [field.getContextValueFromState(state)].flat()\n const items = field.items.filter(({ value }) => values.includes(value))\n\n // Skip empty values\n if (!items.length) {\n return answerEscaped\n }\n\n answerEscaped = ''\n\n // Append bullet points\n answerEscaped += items\n .map((item) => {\n const resolvedText = translator.tListItem(item, 'text') || item.text\n const label = escapeMarkdown(resolvedText)\n const value = escapeMarkdown(`(${item.value})`)\n\n let line = label\n\n // Prepend bullet points for checkboxes only\n if (field instanceof Components.CheckboxesField) {\n line = `* ${line}`\n }\n\n // Append raw values in parentheses\n // e.g. `* None of the above (false)`\n return options.format === 'email' &&\n `${item.value}`.toLowerCase() !== item.text.toLowerCase()\n ? `${line} ${value}\\n`\n : `${line}\\n`\n })\n .join('')\n } else if (field instanceof Components.MultilineTextField) {\n // Preserve Multiline text new lines\n answerEscaped = answer\n .split(/(?:\\r?\\n)+/)\n .map(escapeMarkdown)\n .join('\\n')\n .concat('\\n')\n } else if (field instanceof Components.UkAddressField) {\n // Format UK addresses into new lines\n answerEscaped = (field.getContextValueFromState(state) ?? [])\n .map(escapeMarkdown)\n .join('\\n')\n .concat('\\n')\n } else if (\n field instanceof Components.EastingNorthingField ||\n field instanceof Components.LatLongField\n ) {\n answerEscaped = answer ? `${answer}\\n` : ''\n } else if (field instanceof Components.GeospatialField) {\n const features = field.getFormValueFromState(state)\n const value = field.getDisplayStringFromFormValue(features, translator)\n\n answerEscaped = value ? `${value}\\n` : ''\n }\n\n return answerEscaped\n}\n"],"mappings":"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","ignoreList":[]}
@@ -29,5 +29,6 @@ export { OsGridRefField } from '../../../../server/plugins/engine/components/OsG
29
29
  export { NationalGridFieldNumberField } from '../../../../server/plugins/engine/components/NationalGridFieldNumberField.js';
30
30
  export { LatLongField } from '../../../../server/plugins/engine/components/LatLongField.js';
31
31
  export { HiddenField } from '../../../../server/plugins/engine/components/HiddenField.js';
32
+ export { TrackingField } from '../../../../server/plugins/engine/components/TrackingField.js';
32
33
  export { PaymentField } from '../../../../server/plugins/engine/components/PaymentField.js';
33
34
  export { GeospatialField } from '../../../../server/plugins/engine/components/GeospatialField.js';
@@ -30,6 +30,7 @@ export { OsGridRefField } from "./OsGridRefField.js";
30
30
  export { NationalGridFieldNumberField } from "./NationalGridFieldNumberField.js";
31
31
  export { LatLongField } from "./LatLongField.js";
32
32
  export { HiddenField } from "./HiddenField.js";
33
+ export { TrackingField } from "./TrackingField.js";
33
34
  export { PaymentField } from "./PaymentField.js";
34
35
  export { GeospatialField } from "./GeospatialField.js";
35
36
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["AutocompleteField","CheckboxesField","DatePartsField","DeclarationField","Details","EmailAddressField","FileUploadField","Html","InsetText","List","Markdown","NotificationBanner","MonthYearField","MultilineTextField","NumberField","RadiosField","SelectField","TelephoneNumberField","TextField","UkAddressField","YesNoField","EastingNorthingField","OsGridRefField","NationalGridFieldNumberField","LatLongField","HiddenField","PaymentField","GeospatialField"],"sources":["../../../../../src/server/plugins/engine/components/index.ts"],"sourcesContent":["/**\n * IMPORTANT: Exported Components must follow the naming convention implemented in {@link @defra/forms-model#ComponentType}\n * In the Form JSON, components have a type property which is the name of the components, e.g. DatePartsField.\n * Components are loaded in the ComponentsCollection constructor.\n */\n\nexport { AutocompleteField } from '~/src/server/plugins/engine/components/AutocompleteField.js'\nexport { CheckboxesField } from '~/src/server/plugins/engine/components/CheckboxesField.js'\nexport { DatePartsField } from '~/src/server/plugins/engine/components/DatePartsField.js'\nexport { DeclarationField } from '~/src/server/plugins/engine/components/DeclarationField.js'\nexport { Details } from '~/src/server/plugins/engine/components/Details.js'\nexport { EmailAddressField } from '~/src/server/plugins/engine/components/EmailAddressField.js'\nexport { FileUploadField } from '~/src/server/plugins/engine/components/FileUploadField.js'\nexport { Html } from '~/src/server/plugins/engine/components/Html.js'\nexport { InsetText } from '~/src/server/plugins/engine/components/InsetText.js'\nexport { List } from '~/src/server/plugins/engine/components/List.js'\nexport { Markdown } from '~/src/server/plugins/engine/components/Markdown.js'\nexport { NotificationBanner } from '~/src/server/plugins/engine/components/NotificationBanner.js'\nexport { MonthYearField } from '~/src/server/plugins/engine/components/MonthYearField.js'\nexport { MultilineTextField } from '~/src/server/plugins/engine/components/MultilineTextField.js'\nexport { NumberField } from '~/src/server/plugins/engine/components/NumberField.js'\nexport { RadiosField } from '~/src/server/plugins/engine/components/RadiosField.js'\nexport { SelectField } from '~/src/server/plugins/engine/components/SelectField.js'\nexport { TelephoneNumberField } from '~/src/server/plugins/engine/components/TelephoneNumberField.js'\nexport { TextField } from '~/src/server/plugins/engine/components/TextField.js'\nexport { UkAddressField } from '~/src/server/plugins/engine/components/UkAddressField.js'\nexport { YesNoField } from '~/src/server/plugins/engine/components/YesNoField.js'\nexport { EastingNorthingField } from '~/src/server/plugins/engine/components/EastingNorthingField.js'\nexport { OsGridRefField } from '~/src/server/plugins/engine/components/OsGridRefField.js'\nexport { NationalGridFieldNumberField } from '~/src/server/plugins/engine/components/NationalGridFieldNumberField.js'\nexport { LatLongField } from '~/src/server/plugins/engine/components/LatLongField.js'\nexport { HiddenField } from '~/src/server/plugins/engine/components/HiddenField.js'\nexport { PaymentField } from '~/src/server/plugins/engine/components/PaymentField.js'\nexport { GeospatialField } from '~/src/server/plugins/engine/components/GeospatialField.js'\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;;AAEA,SAASA,iBAAiB;AAC1B,SAASC,eAAe;AACxB,SAASC,cAAc;AACvB,SAASC,gBAAgB;AACzB,SAASC,OAAO;AAChB,SAASC,iBAAiB;AAC1B,SAASC,eAAe;AACxB,SAASC,IAAI;AACb,SAASC,SAAS;AAClB,SAASC,IAAI;AACb,SAASC,QAAQ;AACjB,SAASC,kBAAkB;AAC3B,SAASC,cAAc;AACvB,SAASC,kBAAkB;AAC3B,SAASC,WAAW;AACpB,SAASC,WAAW;AACpB,SAASC,WAAW;AACpB,SAASC,oBAAoB;AAC7B,SAASC,SAAS;AAClB,SAASC,cAAc;AACvB,SAASC,UAAU;AACnB,SAASC,oBAAoB;AAC7B,SAASC,cAAc;AACvB,SAASC,4BAA4B;AACrC,SAASC,YAAY;AACrB,SAASC,WAAW;AACpB,SAASC,YAAY;AACrB,SAASC,eAAe","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["AutocompleteField","CheckboxesField","DatePartsField","DeclarationField","Details","EmailAddressField","FileUploadField","Html","InsetText","List","Markdown","NotificationBanner","MonthYearField","MultilineTextField","NumberField","RadiosField","SelectField","TelephoneNumberField","TextField","UkAddressField","YesNoField","EastingNorthingField","OsGridRefField","NationalGridFieldNumberField","LatLongField","HiddenField","TrackingField","PaymentField","GeospatialField"],"sources":["../../../../../src/server/plugins/engine/components/index.ts"],"sourcesContent":["/**\n * IMPORTANT: Exported Components must follow the naming convention implemented in {@link @defra/forms-model#ComponentType}\n * In the Form JSON, components have a type property which is the name of the components, e.g. DatePartsField.\n * Components are loaded in the ComponentsCollection constructor.\n */\n\nexport { AutocompleteField } from '~/src/server/plugins/engine/components/AutocompleteField.js'\nexport { CheckboxesField } from '~/src/server/plugins/engine/components/CheckboxesField.js'\nexport { DatePartsField } from '~/src/server/plugins/engine/components/DatePartsField.js'\nexport { DeclarationField } from '~/src/server/plugins/engine/components/DeclarationField.js'\nexport { Details } from '~/src/server/plugins/engine/components/Details.js'\nexport { EmailAddressField } from '~/src/server/plugins/engine/components/EmailAddressField.js'\nexport { FileUploadField } from '~/src/server/plugins/engine/components/FileUploadField.js'\nexport { Html } from '~/src/server/plugins/engine/components/Html.js'\nexport { InsetText } from '~/src/server/plugins/engine/components/InsetText.js'\nexport { List } from '~/src/server/plugins/engine/components/List.js'\nexport { Markdown } from '~/src/server/plugins/engine/components/Markdown.js'\nexport { NotificationBanner } from '~/src/server/plugins/engine/components/NotificationBanner.js'\nexport { MonthYearField } from '~/src/server/plugins/engine/components/MonthYearField.js'\nexport { MultilineTextField } from '~/src/server/plugins/engine/components/MultilineTextField.js'\nexport { NumberField } from '~/src/server/plugins/engine/components/NumberField.js'\nexport { RadiosField } from '~/src/server/plugins/engine/components/RadiosField.js'\nexport { SelectField } from '~/src/server/plugins/engine/components/SelectField.js'\nexport { TelephoneNumberField } from '~/src/server/plugins/engine/components/TelephoneNumberField.js'\nexport { TextField } from '~/src/server/plugins/engine/components/TextField.js'\nexport { UkAddressField } from '~/src/server/plugins/engine/components/UkAddressField.js'\nexport { YesNoField } from '~/src/server/plugins/engine/components/YesNoField.js'\nexport { EastingNorthingField } from '~/src/server/plugins/engine/components/EastingNorthingField.js'\nexport { OsGridRefField } from '~/src/server/plugins/engine/components/OsGridRefField.js'\nexport { NationalGridFieldNumberField } from '~/src/server/plugins/engine/components/NationalGridFieldNumberField.js'\nexport { LatLongField } from '~/src/server/plugins/engine/components/LatLongField.js'\nexport { HiddenField } from '~/src/server/plugins/engine/components/HiddenField.js'\nexport { TrackingField } from '~/src/server/plugins/engine/components/TrackingField.js'\nexport { PaymentField } from '~/src/server/plugins/engine/components/PaymentField.js'\nexport { GeospatialField } from '~/src/server/plugins/engine/components/GeospatialField.js'\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;;AAEA,SAASA,iBAAiB;AAC1B,SAASC,eAAe;AACxB,SAASC,cAAc;AACvB,SAASC,gBAAgB;AACzB,SAASC,OAAO;AAChB,SAASC,iBAAiB;AAC1B,SAASC,eAAe;AACxB,SAASC,IAAI;AACb,SAASC,SAAS;AAClB,SAASC,IAAI;AACb,SAASC,QAAQ;AACjB,SAASC,kBAAkB;AAC3B,SAASC,cAAc;AACvB,SAASC,kBAAkB;AAC3B,SAASC,WAAW;AACpB,SAASC,WAAW;AACpB,SAASC,WAAW;AACpB,SAASC,oBAAoB;AAC7B,SAASC,SAAS;AAClB,SAASC,cAAc;AACvB,SAASC,UAAU;AACnB,SAASC,oBAAoB;AAC7B,SAASC,cAAc;AACvB,SAASC,4BAA4B;AACrC,SAASC,YAAY;AACrB,SAASC,WAAW;AACpB,SAASC,aAAa;AACtB,SAASC,YAAY;AACrB,SAASC,eAAe","ignoreList":[]}
@@ -0,0 +1,3 @@
1
+ {% macro TrackingField(component) %}
2
+ <input type="hidden" id="{{ component.model.name }}" name="{{ component.model.name }}" value="true" />
3
+ {% endmacro %}
@@ -3,5 +3,5 @@
3
3
  * @this {NunjucksContext}
4
4
  * @param {string} name - The name of the component
5
5
  */
6
- export function field(this: NunjucksContext, name: string): import("../../engine/components/TextField.js").TextField | import("../../engine/components/SelectField.js").SelectField | import("../../engine/components/RadiosField.js").RadiosField | import("../../engine/components/YesNoField.js").YesNoField | import("../../engine/components/CheckboxesField.js").CheckboxesField | import("../../engine/components/DatePartsField.js").DatePartsField | import("../../engine/components/DeclarationField.js").DeclarationField | import("../../engine/components/EastingNorthingField.js").EastingNorthingField | import("../../engine/components/EmailAddressField.js").EmailAddressField | import("../../engine/components/LatLongField.js").LatLongField | import("../../engine/components/MonthYearField.js").MonthYearField | import("../../engine/components/MultilineTextField.js").MultilineTextField | import("../../engine/components/NationalGridFieldNumberField.js").NationalGridFieldNumberField | import("../../engine/components/NumberField.js").NumberField | import("../../engine/components/OsGridRefField.js").OsGridRefField | import("../../engine/components/TelephoneNumberField.js").TelephoneNumberField | import("../../engine/components/UkAddressField.js").UkAddressField | import("../../engine/components/FileUploadField.js").FileUploadField | import("../../engine/components/HiddenField.js").HiddenField | import("../../engine/components/PaymentField.js").PaymentField | import("../../engine/components/GeospatialField.js").GeospatialField | import("../../engine/components/Details.js").Details | import("../../engine/components/Html.js").Html | import("../../engine/components/InsetText.js").InsetText | import("../../engine/components/List.js").List | import("../../engine/components/Markdown.js").Markdown | import("../../engine/components/NotificationBanner.js").NotificationBanner | undefined;
6
+ export function field(this: NunjucksContext, name: string): import("../../engine/components/TextField.js").TextField | import("../../engine/components/SelectField.js").SelectField | import("../../engine/components/RadiosField.js").RadiosField | import("../../engine/components/YesNoField.js").YesNoField | import("../../engine/components/CheckboxesField.js").CheckboxesField | import("../../engine/components/DatePartsField.js").DatePartsField | import("../../engine/components/DeclarationField.js").DeclarationField | import("../../engine/components/EastingNorthingField.js").EastingNorthingField | import("../../engine/components/EmailAddressField.js").EmailAddressField | import("../../engine/components/LatLongField.js").LatLongField | import("../../engine/components/MonthYearField.js").MonthYearField | import("../../engine/components/MultilineTextField.js").MultilineTextField | import("../../engine/components/NationalGridFieldNumberField.js").NationalGridFieldNumberField | import("../../engine/components/NumberField.js").NumberField | import("../../engine/components/OsGridRefField.js").OsGridRefField | import("../../engine/components/TelephoneNumberField.js").TelephoneNumberField | import("../../engine/components/UkAddressField.js").UkAddressField | import("../../engine/components/FileUploadField.js").FileUploadField | import("../../engine/components/HiddenField.js").HiddenField | import("../../engine/components/TrackingField.js").TrackingField | import("../../engine/components/PaymentField.js").PaymentField | import("../../engine/components/GeospatialField.js").GeospatialField | import("../../engine/components/Details.js").Details | import("../../engine/components/Html.js").Html | import("../../engine/components/InsetText.js").InsetText | import("../../engine/components/List.js").List | import("../../engine/components/Markdown.js").Markdown | import("../../engine/components/NotificationBanner.js").NotificationBanner | undefined;
7
7
  import type { NunjucksContext } from '../../../../server/plugins/nunjucks/types.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defra/forms-engine-plugin",
3
- "version": "5.0.0-alpha.22",
3
+ "version": "5.0.0-alpha.23",
4
4
  "description": "Defra forms engine",
5
5
  "type": "module",
6
6
  "files": [
@@ -92,7 +92,7 @@
92
92
  },
93
93
  "license": "SEE LICENSE IN LICENSE",
94
94
  "dependencies": {
95
- "@defra/forms-model": "^3.0.704",
95
+ "@defra/forms-model": "^3.0.708",
96
96
  "@defra/hapi-tracing": "^1.29.0",
97
97
  "@defra/interactive-map": "0.0.33-alpha",
98
98
  "@elastic/ecs-pino-format": "^1.5.0",
@@ -197,7 +197,7 @@
197
197
  "core-js": "^3.46.0",
198
198
  "cssnano": "^7.1.2",
199
199
  "cssnano-preset-default": "^7.0.10",
200
- "editorconfig-checker": "^6.1.1",
200
+ "editorconfig-checker": "^6.2.0",
201
201
  "eslint": "^9.39.3",
202
202
  "eslint-config-prettier": "^10.1.8",
203
203
  "eslint-plugin-jest": "^28.14.0",
@@ -6,6 +6,14 @@
6
6
  "path": "/all-components",
7
7
  "title": "All Components",
8
8
  "components": [
9
+ {
10
+ "type": "TrackingField",
11
+ "name": "trackingField",
12
+ "title": "Tracking field",
13
+ "hint": "Help text",
14
+ "options": {},
15
+ "schema": {}
16
+ },
9
17
  {
10
18
  "type": "TextField",
11
19
  "name": "textField",
@@ -5,6 +5,10 @@ pages:
5
5
  - path: '/whats-your-name'
6
6
  title: What's your name?
7
7
  components:
8
+ - type: TrackingField
9
+ name: hasSeenNamePage
10
+ title: Tracks if the user has seen the name page
11
+ options: {}
8
12
  - type: TextField
9
13
  name: textField
10
14
  title: Name
@@ -0,0 +1,64 @@
1
+ import { type TrackingFieldComponent } from '@defra/forms-model'
2
+ import joi, { type BooleanSchema } from 'joi'
3
+
4
+ import {
5
+ FormComponent,
6
+ isFormValue
7
+ } from './FormComponent.js'
8
+ import { messageTemplate } from '../pageControllers/validationOptions.js'
9
+ import {
10
+ type ErrorMessageTemplateList,
11
+ type FormState,
12
+ type FormStateValue,
13
+ type FormSubmissionState
14
+ } from '../types.js'
15
+
16
+ export class TrackingField extends FormComponent {
17
+ declare formSchema: BooleanSchema
18
+ declare stateSchema: BooleanSchema
19
+ declare options: TrackingFieldComponent['options']
20
+
21
+ constructor(
22
+ def: TrackingFieldComponent,
23
+ props: ConstructorParameters<typeof FormComponent>[1]
24
+ ) {
25
+ super(def, props)
26
+
27
+ const formSchema = joi.boolean().valid(true).label(this.label).required()
28
+
29
+ this.formSchema = formSchema.default(false)
30
+ this.stateSchema = formSchema.default(null).allow(null)
31
+ this.schema = {}
32
+ this.options = {}
33
+ }
34
+
35
+ getFormValueFromState(state: FormSubmissionState) {
36
+ const { name } = this
37
+ return this.getFormValue(state[name])
38
+ }
39
+
40
+ isValue(value?: FormStateValue | FormState): value is true {
41
+ return TrackingField.isTracking(value)
42
+ }
43
+
44
+ /**
45
+ * For error preview page that shows all possible errors on a component
46
+ */
47
+ getAllPossibleErrors(): ErrorMessageTemplateList {
48
+ return TrackingField.getAllPossibleErrors()
49
+ }
50
+
51
+ static isTracking(value?: FormStateValue | FormState): value is true {
52
+ return isFormValue(value) && typeof value === 'boolean'
53
+ }
54
+
55
+ /**
56
+ * Static version of getAllPossibleErrors that doesn't require a component instance.
57
+ */
58
+ static getAllPossibleErrors(): ErrorMessageTemplateList {
59
+ return {
60
+ baseErrors: [{ type: 'required', template: messageTemplate.required }],
61
+ advancedSettingsErrors: []
62
+ }
63
+ }
64
+ }
@@ -37,6 +37,7 @@ export type Field = InstanceType<
37
37
  | typeof Components.UkAddressField
38
38
  | typeof Components.FileUploadField
39
39
  | typeof Components.HiddenField
40
+ | typeof Components.TrackingField
40
41
  | typeof Components.PaymentField
41
42
  | typeof Components.GeospatialField
42
43
  >
@@ -201,6 +202,10 @@ export function createComponent(
201
202
  component = new Components.HiddenField(def, options)
202
203
  break
203
204
 
205
+ case ComponentType.TrackingField:
206
+ component = new Components.TrackingField(def, options)
207
+ break
208
+
204
209
  case ComponentType.PaymentField:
205
210
  component = new Components.PaymentField(def, options)
206
211
  break
@@ -30,5 +30,6 @@ export { OsGridRefField } from './OsGridRefField.js'
30
30
  export { NationalGridFieldNumberField } from './NationalGridFieldNumberField.js'
31
31
  export { LatLongField } from './LatLongField.js'
32
32
  export { HiddenField } from './HiddenField.js'
33
+ export { TrackingField } from './TrackingField.js'
33
34
  export { PaymentField } from './PaymentField.js'
34
35
  export { GeospatialField } from './GeospatialField.js'
@@ -0,0 +1,3 @@
1
+ {% macro TrackingField(component) %}
2
+ <input type="hidden" id="{{ component.model.name }}" name="{{ component.model.name }}" value="true" />
3
+ {% endmacro %}