hof 23.0.0-vite-sourcemap-beta → 23.0.0-vite-sourcemap-beta.3

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.
Files changed (32) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +97 -6
  3. package/build/tasks/vite/index.js +4 -1
  4. package/build/tasks/vite/vite.config.js +1 -4
  5. package/components/amount-with-unit-select/fields.js +15 -0
  6. package/components/amount-with-unit-select/hooks.js +168 -0
  7. package/components/amount-with-unit-select/index.js +107 -0
  8. package/components/amount-with-unit-select/templates/amount-with-unit-select.html +20 -0
  9. package/components/amount-with-unit-select/utils.js +197 -0
  10. package/components/amount-with-unit-select/validation.js +175 -0
  11. package/components/index.js +1 -0
  12. package/controller/controller.js +5 -3
  13. package/controller/validation/index.js +1 -1
  14. package/controller/validation/validators.js +0 -1
  15. package/frontend/template-mixins/mixins/template-mixins.js +55 -5
  16. package/frontend/template-mixins/partials/forms/grouped-inputs-select.html +13 -0
  17. package/frontend/template-mixins/partials/forms/grouped-inputs-text.html +37 -0
  18. package/frontend/themes/gov-uk/styles/_grouped-input.scss +5 -0
  19. package/frontend/themes/gov-uk/styles/govuk.scss +1 -0
  20. package/frontend/toolkit/assets/javascript/form-focus.js +4 -0
  21. package/package.json +2 -1
  22. package/sandbox/apps/sandbox/fields.js +18 -1
  23. package/sandbox/apps/sandbox/index.js +4 -0
  24. package/sandbox/apps/sandbox/sections/summary-data-sections.js +7 -1
  25. package/sandbox/apps/sandbox/translations/en/default.json +33 -0
  26. package/sandbox/apps/sandbox/translations/src/en/fields.json +10 -0
  27. package/sandbox/apps/sandbox/translations/src/en/pages.json +3 -0
  28. package/sandbox/apps/sandbox/translations/src/en/validation.json +12 -0
  29. package/sandbox/public/assets/index-CsI1K_CH.js +60 -0
  30. package/sandbox/public/css/app.css +7 -3
  31. package/sandbox/public/js/bundle.js +1 -1
  32. package/sandbox/public/js/bundle.js.map +1 -0
package/CHANGELOG.md CHANGED
@@ -9,6 +9,21 @@
9
9
  - Updated engine requirements to use node to `>=20.19.0`
10
10
  - Vite uses Rollup in production and requires optional rollup dependencies to be loaded. Setting `--ignore-optional flag` in Dockerfiles will result in "Module not found" errors in CI/CD or Docker.
11
11
 
12
+ ## 2026-01-27, v22.14.0 (Stable), @rayhannurrohmanho
13
+
14
+ ### Added
15
+ - Created the amountWithUnitSelect component.
16
+ - Separated the amountWithUnitSelect component logic into into hooks, utils, and validators - all documented via JSDoc.
17
+ - Created templates and partials for the amountWithUnitSelect component.
18
+ - Configured template mixin for amountWithUnitSelect component.
19
+ - Added sandbox example for the amountWithUnitSelect component.
20
+ - Documented the amountWithUnitSelect component in readme.
21
+ - Added tests for the amountWithUnitSelect components.
22
+
23
+ ### Changed
24
+ - Added optional parent key ('pKey') parameter to the template-mixins.js 'optionGroup' function to allow the assignment of a group component's parent's properties.
25
+ - Modified validation to check if a "groupedFieldsWithOptions" property exists (and is set to true) for a component with "options" before the "equals" validator is applied to the component.
26
+
12
27
  ## 2025-12-09, Version 22.13.0 (Stable), @Rhodine-orleans-lindsay
13
28
  ### Changed
14
29
  - Updated cookie banner view to follow GOV.UK design system. Updated cookieSettings.js to allow for different confirmation text based on whether cookies were accepted or rejected
package/README.md CHANGED
@@ -60,7 +60,8 @@ It is recommended to alias `hof-build` to an npm script in your package.json.
60
60
 
61
61
  ## Tasks
62
62
 
63
- - `vite` - compiles client-side js with vite in development and rollup in production. Requires node version `^20.19.0 || >=22.12.0`.
63
+ - `vite` - compiles client-side js with vite.
64
+ Requires node version `^20.19.0 || >=22.12.0`.
64
65
  - `sass` - compiles sass
65
66
  - `images` - copies images from ./assets/images directory to ./public/images
66
67
  - `translate` - compiles translation files
@@ -69,18 +70,21 @@ Note: For SASS compilation it's possible to additionally configure the following
69
70
  - `outputStyle` - Controls whether the CSS output is compressed or not, expanded (default) = non compressed and compressed = compressed CSS output.
70
71
  - `quietDeps` - This controls whether you get deprecation warning shown in the console output, if set to false (default) SASS deprecation warnings will be shown in the console, if set to true then deprecation warnings will not be shown in the console output.
71
72
  - `sourceMaps` - This controls whether the build will output css sourcemaps to help with debugging. These will be output to the same directory as the css output as a .map file. This option is not currently available in production.
72
- For JavaScript compilation, Vite outputs JavaScript sourcemaps as a .js.map file to the same directory as the js bundle.
73
- You can change sourcemaps' default settings in hof.settings or your build config as follows:
74
- ```
73
+
74
+ Vite output JavaScript sourcemaps as a .js.map file to the same directory as the js bundle.
75
+
76
+ Debugging example (in hof.settings or your build config)
77
+ ```js
75
78
  "build": {
76
79
  "sass": {
77
80
  "sourceMaps": true
78
81
  },
79
- "js": {
82
+ "js": {
80
83
  "sourceMaps": true
81
- },
84
+ }
82
85
  }
83
86
  ```
87
+
84
88
  ## Watch
85
89
 
86
90
  You can additionally run a `watch` task to start a server instance, which will automatically restart based on changes to files. This will also re-perform the tasks above when relevant files change.
@@ -115,6 +119,13 @@ Alternatively you can define a path to a local config file by passing a `--confi
115
119
  ```
116
120
  hof-build --config /path/to/my/config.js
117
121
  ```
122
+ Any task can be disabled by setting its configuration to `false` (or any falsy value).
123
+
124
+ ```js
125
+ module.exports = {
126
+ sass: false,
127
+ };
128
+ ```
118
129
 
119
130
  ### Configuration options
120
131
 
@@ -1001,6 +1012,85 @@ Using the translation key `fields.field-name.label` will return different values
1001
1012
 
1002
1013
  # HOF Components
1003
1014
 
1015
+ ## AmountWithUnitSelect Component
1016
+
1017
+ > **Available from version 22.14.0**
1018
+
1019
+ A component for handling the rendering, processing, and validation of a text input (amount) field and a select-dropdown input field (unit) used in HOF applications.
1020
+
1021
+ ### Usage
1022
+
1023
+ In your fields config:
1024
+
1025
+ ```js
1026
+ const amountWithUnitSelectComponent = require("hof").components.amountWithUnitSelect;
1027
+
1028
+ module.exports = {
1029
+ "amountWithUnitSelect-field": amountWithUnitSelectComponent("amountWithUnitSelect", {
1030
+ mixin: 'input-amount-with-unit-select',
1031
+ amountLabel: "Amount:", // If not specified, defaults to 'Amount'
1032
+ unitLabel: "Unit:", // If not specified, defaults to 'Unit'
1033
+ options: [
1034
+ { "null": "Select..." }, // If a null option is not specified, a default null option with the label 'Select...' is included in the options
1035
+ { "label": "untranslated option label 1", "value": "1" },
1036
+ { "label": "untranslated option label 2", "value": "2" }
1037
+ ],
1038
+ hint: "E.g: 5 Kilogram",
1039
+ legend: 'Enter An Amount',
1040
+ isPageHeading: 'true',
1041
+ amountOptional: 'false', // If not specified, defaults to false if the required validator is not applied, otherwise true
1042
+ unitOptional: 'true', // If not specified, defaults to false if the required validator is not applied, otherwise true
1043
+ validate: ['alphanum']
1044
+ }),
1045
+ };
1046
+ ```
1047
+
1048
+ The above example will create a new AmountWithUnitSelect component with the key `'amountWithUnitSelect-field'`.
1049
+ It will set the AmountWithUnitSelect component's text input label to `'Amount:'` (instead of the default `'Amount'`) and the select input label to `'Unit:'` (instead of the default `'Unit'`).
1050
+ The component's Select input will have the dropdown options `'Select...'` (mapping to the value `'null'`), `'untranslated option label 1'` (mapping to the value `'1'`), and `'untranslated option label 2'` (mapping to the value `'2'`).
1051
+ The component's hint text will be set to `'E.G: 5 Kilogram'`, the field title/legend will be set to `'Enter An Amount'`, and the page heading will be the field's title.
1052
+ In terms of validation, the text input (amount) will have the `'required'` validator applied, but the select input (unit) will not (a value will not be required to be selected), and the text field will have the `'alphanum'` validator applied.
1053
+
1054
+ ### Configuration
1055
+
1056
+ The following optional configuration options are supported:
1057
+
1058
+ - `validate {String|Array}` – Validators to use on the text input field. The `'alphanum'` and `'required'` validators are likely to be used.
1059
+ - `template` – An absolute path to an alternate template.
1060
+ - `amountLabel {String}` – A custom label for the text input field (amount). Defaults to `'Amount'` if omitted. This can also be specified and defined in the field translations.
1061
+ - `unitLabel {String}` – A custom label for the select input field (unit). Defaults to `'Unit'` if omitted. This can also be specified and defined in the field translations.
1062
+ - `options {Array}` – A list of labels and corresponding values (options) for the select input field to present. Each option has the format `{ "label": "", "value": ""}`. The default/null option is defined with the format `{ "null": "Select" }` (where the text `'Select'` is the label and can be modified). If the null option is not defined, a default null option will be included in the options with the label `'Select...'`. This can also be specified and defined in the field translations.
1063
+ - `hint {String}` – Hint text displayed for both fields. This can also be specified and defined in the field translations.
1064
+ - `legend {String}` – Legend text displayed for both fields. This can also be specified and defined in the field translations.
1065
+ - `isPageHeading {Boolean}` – Sets the legend as the page heading on single-page questions.
1066
+ - `amountOptional {Boolean}` – The text input (amount) defaults to `''` (empty string) if omitted. Defaults to `false`. If the `'required'` validator is defined in the `validate` configuration option, then this configuration is ignored (both fields are made mandatory).
1067
+ - `unitOptional {Boolean}` – The select input (unit) defaults to `null` if omitted. Defaults to `false`. If the `'required'` validator is defined in the `validate` configuration option, then this configuration is ignored (both fields are made mandatory).
1068
+
1069
+ ### Validation Error Messages
1070
+
1071
+ In Validation.json (within the translations):
1072
+
1073
+ ```js
1074
+ "amountWithUnitSelect": {
1075
+ "default": "Enter the amount in the correct format; for example, 10 Litres",
1076
+ "alphanum": "The amount must not contain any special characters",
1077
+ "required": "Enter an amount and a unit value"
1078
+ },
1079
+ "amountWithUnitSelect-unit": {
1080
+ "default": "A valid value must be selected as the amount unit",
1081
+ "required": "A unit must be selected for the amount"
1082
+ },
1083
+ "amountWithUnitSelect-amount": {
1084
+ "alphanum": "The amount must not be an alphanum"
1085
+ }
1086
+ ```
1087
+
1088
+ Validation error messages can be defined for a specific child component that errored by adding a JSON object with a key that has the component's name (I.E. `'amountWithUnitSelect'`) followed by a hyphen and the child component's name (I.E. '-amount' or '-unit'). So to define an error message, for the `'required'` validation error, for specifically the unit component, an `'amountWithUnitSelect-unit'` object can be created (like in the example above) with a validator's name and the error message to show for it respectively, set as a key:value pair in the object (E.G. `"required": "A unit must be selected for the amount" within "amountWithUnitSelect-unit"` - like in the example).
1089
+ Validation error messages defined specifically for child components, for a given type of validation error, (such as `'required'` for `'amountWithUnitSelect-unit'`) will take precedence over error messages defined for the same validation error in the parent. So in this case, the `"required": "Enter an amount and a unit value"` validation message defined in the `"amountWithUnitSelect"` JSON object in the above example will not show when the `"amountWithUnitSelect-unit"` `'required'` validation error message is defined. If there was no `'required'` error message defined for, say, the `"amountWithUnitSelect-amount"` object (like in the example above), the `"amountWithUnitSelect"` object's `'required'` error message would show if the `'required'` validation error is triggered on the 'amount' child component (I.E. When an amount value is not provided).
1090
+ The `'default'` catch all validation error message can also be defined in a similar manner for the child components to override the parent component's defined `'default'` error message.
1091
+
1092
+ So the example above will create a scenario where `'required'` validation errors triggered on the 'unit' field will display the error message `"A unit must be selected for the amount"` (specified in the `"amountWithUnitSelect-unit"` JSON object). Any `'required'` validation errors triggered on the 'amount' field will display the error message `"Enter an amount and a unit value"` (specified in the `"amountWithUnitSelect"` JSON object - as there is no `'required'` error message defined specifically for the 'amount' field (withing `"amountWithUnitSelect-amount"`)).
1093
+
1004
1094
  ## Date Component
1005
1095
 
1006
1096
  A component for handling the rendering and processing of 3-input date fields used in HOF Applications.
@@ -1632,6 +1722,7 @@ currency
1632
1722
  select
1633
1723
  input-text
1634
1724
  input-date
1725
+ input-amount-with-unit-select
1635
1726
  input-text-compound
1636
1727
  input-text-code
1637
1728
  input-number
@@ -11,7 +11,10 @@ module.exports = config => {
11
11
  if(!config.production) {
12
12
  return vite.build({
13
13
  configFile: viteConfig,
14
- mode: 'development'
14
+ mode: 'development',
15
+ build: {
16
+ sourcemap: config.js.sourceMaps
17
+ }
15
18
  });
16
19
  }
17
20
  return vite.build({
@@ -6,7 +6,6 @@ import { resolve } from 'path';
6
6
  import fs from 'fs';
7
7
  import { nodeResolve } from '@rollup/plugin-node-resolve';
8
8
  import commonjs from '@rollup/plugin-commonjs';
9
- import config from '../../../config/builder-defaults';
10
9
 
11
10
  const publicDirectory = resolve(process.cwd(), 'public');
12
11
  const entryFile = (() => {
@@ -16,7 +15,6 @@ const entryFile = (() => {
16
15
  throw new Error(`vite: entry file not found. Checked: ${src}`);
17
16
  })();
18
17
 
19
-
20
18
  export default defineConfig({
21
19
  plugins: [
22
20
  commonjs({
@@ -53,7 +51,7 @@ export default defineConfig({
53
51
  build: {
54
52
  outDir: publicDirectory,
55
53
  emptyOutDir: false,
56
- sourcemap: config.js.sourceMaps, // Enable JS/TS sourcemaps in dev
54
+ sourcemap: false,
57
55
  rollupOptions: {
58
56
  input: {
59
57
  index: entryFile
@@ -71,7 +69,6 @@ export default defineConfig({
71
69
  }
72
70
  },
73
71
  css: {
74
- // devSourcemap: isDev,
75
72
  preprocessorOptions: {
76
73
  scss: {
77
74
  includes: ['node_modules']
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ module.exports = key => ({
4
+ [`${key}-amount`]: {
5
+ label: 'Amount',
6
+ autocomplete: 'off',
7
+ validate: []
8
+ },
9
+ [`${key}-unit`]: {
10
+ label: 'Unit',
11
+ groupedFieldsWithOptions: true,
12
+ options: {},
13
+ validate: []
14
+ }
15
+ });
@@ -0,0 +1,168 @@
1
+ 'use strict';
2
+
3
+ const _ = require('lodash');
4
+ const utils = require('./utils');
5
+ const validation = require('./validation');
6
+
7
+ /**
8
+ * Pre-process hook. This function:
9
+ * - Splits the amountWithUnitSelect value into its parts (amount and unit in the format [Amount]-[Unit],
10
+ * E.G. 5-Kilograms) and assigns them to the request body (req.body).
11
+ * @param {Object} req - The form's request object.
12
+ * @param {Object} fields - The component's child field definitions and configurations.
13
+ * @param {string} key - The parent component's key.
14
+ */
15
+ const preProcess = (req, fields, key) => {
16
+ const parts = utils.getParts(req.body, fields, key);
17
+ if (_.some(parts, part => part !== '')) {
18
+ req.body[key] = `${(parts.amount || '')}-${(parts.unit || '')}`;
19
+ }
20
+ };
21
+
22
+ /**
23
+ * Post-process hook. This function:
24
+ * - Copies the field value from the request body (req.body) to the form values (req.form.values)
25
+ * if a reference to the field exists in the form values.
26
+ * @param {Object} req - The form's request object.
27
+ * @param {string} key - The parent component's key.
28
+ */
29
+ const postProcess = (req, key) => {
30
+ if (req.form.values[key]) {
31
+ req.form.values[key] = req.body[key];
32
+ }
33
+ };
34
+
35
+ /**
36
+ * Pre-validate hook. This function:
37
+ * - Prevents default select component assignment of 'equal' validator to the parent component.
38
+ * - Resolves required validators and optional configurations for child components.
39
+ * - Propagates child component field data and values to the request to enable their validation.
40
+ * - Adds a custom 'equal' validator to the unit child component.
41
+ * - Adds a custom 'twoHyphenSeparatedValues' validator to the parent component to validate value format.
42
+ * - Moves excess validators that do not apply to the parent component to the 'amount' child component.
43
+ * @param {Object} req - The form's request object.
44
+ * @param {Object} fields - The component's child field definitions and configurations.
45
+ * @param {string} key - The parent component's key.
46
+ * @param {Object} options - The component's configuration options.
47
+ */
48
+ const preValidate = (req, fields, key, options) => {
49
+ // Prevents auto assignment of 'equal' validator to parent component
50
+ validation.addGroupedFieldsWithOptionsProperty(req.form.options.fields[key]);
51
+ // resolves required validators and optional configurations for child components
52
+ validation.resolveOptionalFields(req.form.options.fields, fields, options.validate, key);
53
+ // propagates child component field data and values to the request to enable validation
54
+ validation.propagateChildFieldValidation(req.form, fields, key);
55
+ // adds custom 'equal' validator to the unit child component
56
+ validation.addValidator(fields[`${key}-unit`], validation.createCustomEqualValidator(fields[`${key}-unit`].options));
57
+ // adds custom 'twoHyphenSeparatedValues' validator to the parent component to validate overall value format
58
+ validation.addValidator(options, validation.isTwoHyphenSeparatedValues);
59
+ // moves excess validators that do not apply to the parent component to the 'amount' child component
60
+ validation.moveExcessValidatorToChildComponent(req.form.options.fields, fields, key);
61
+ };
62
+
63
+ /**
64
+ * Pre-getErrors hook. This function:
65
+ * - If the parent component has a flagged error, this extends the session model's error values with
66
+ * the child components' error values.
67
+ * @param {Object} req - The form's request object.
68
+ * @param {Object} fields - The component's child field definitions and configurations.
69
+ * @param {string} key - The parent component's key.
70
+ */
71
+ const preGetErrors = (req, fields, key) => {
72
+ // if the amountWithUnitSelect field is included in errorValues (E.G. if there was a validation error),
73
+ // extend errorValues with the individual components
74
+ // (I.E. add the child components' K:V pair to the request sessionModel's attributes)
75
+ const errorValues = req.sessionModel.get('errorValues');
76
+ if (errorValues && errorValues[key]) {
77
+ req.sessionModel.set('errorValues',
78
+ Object.assign({}, errorValues, utils.getPartsFromAmountWithUnitSelect(errorValues[key], Object.keys(fields)))
79
+ );
80
+ }
81
+ };
82
+
83
+ /**
84
+ * Post-getErrors hook. This function:
85
+ * - Ensures only one error is associated with the components in the request form errors
86
+ * (by setting excess errors' type to null) when either the parent or child components have
87
+ * (jointly) multiple errors in the session model.
88
+ * - If there is no parent component error, one of the child component errors (if any) is inserted.
89
+ * @param {Object} req - The form's request object.
90
+ * @param {Object} res - The form's response object.
91
+ * @param {Object} fields - The component's child field definitions and configurations.
92
+ * @param {string} key - The parent component's key.
93
+ */
94
+ const postGetErrors = (req, res, fields, key) => {
95
+ // if the amountWithUnitSelect field or its child fields have any recorded validation error,
96
+ // the remaining errors are added to req.form.errors
97
+ // and their type is set to null to avoid duplicate error messages
98
+ const errors = req.sessionModel.get('errors');
99
+ if (errors && (errors[key] || errors[`${key}-amount`] || errors[`${key}-unit`])) {
100
+ Object.assign(req.form.errors, Object.keys(fields).reduce((obj, field) =>
101
+ Object.assign({}, obj, { [field]: { type: null } })
102
+ , {}));
103
+ }
104
+
105
+ // inserts child component validation errors into req.form.errors
106
+ validation.insertChildValidationErrors(req, res, key, errors);
107
+ };
108
+
109
+ /**
110
+ * Post-getValues hook. This function:
111
+ * - Splits the component's value into its parts and assigns them to the request object's form values (req.form.values).
112
+ * @param {Object} req - The form's request object.
113
+ * @param {Object} fields - The component's child field definitions and configurations.
114
+ * @param {string} key - The parent component's key.
115
+ */
116
+ const postGetValues = (req, fields, key) => {
117
+ // if amountWithUnitSelect value is set, split it into its parts and assign to req.form.values
118
+ // extends the session model's error values, if any
119
+ const amountWithUnitSelect = req.form.values[key];
120
+ if (amountWithUnitSelect) {
121
+ Object.assign(
122
+ req.form.values,
123
+ utils.getPartsFromAmountWithUnitSelect(amountWithUnitSelect, Object.keys(fields)),
124
+ req.sessionModel.get('errorValues') || {}
125
+ );
126
+ }
127
+ };
128
+
129
+ /**
130
+ * Pre-render hook. This function:
131
+ * - Translates the unit options and child component labels.
132
+ * - Renders the component's template to a string
133
+ * and assigns the HTML output to the component field in res.locals.fields.
134
+ * @param {Object} req - The form's request object.
135
+ * @param {Object} res - The form's response object.
136
+ * @param {Object} fields - The component's child field definitions and configurations.
137
+ * @param {Object} options - The component's configuration options.
138
+ * @param {string} template - The component's template path.
139
+ * @param {string} key - The parent component's key.
140
+ * @param {Function} next - The next middleware function in the chain.
141
+ */
142
+ const preRender = (req, res, fields, options, template, key, next) => {
143
+ // applies translations
144
+ utils.translateUnitOptions(req, fields, options, key);
145
+ utils.translateLabels(req, fields, key, ['amount', 'unit']);
146
+
147
+ // renders the template to a string and assign the html output
148
+ // to the amountWithUnitSelect field (in res.locals.fields)
149
+ res.render(template, utils.constructFieldToRender(req, fields, options, key), (err, html) => {
150
+ if (err) {
151
+ next(err);
152
+ } else {
153
+ const field = res.locals.fields.find(f => f.key === key);
154
+ Object.assign(field, { html });
155
+ next();
156
+ }
157
+ });
158
+ };
159
+
160
+ module.exports = {
161
+ preProcess,
162
+ postProcess,
163
+ preValidate,
164
+ preGetErrors,
165
+ postGetErrors,
166
+ postGetValues,
167
+ preRender
168
+ };
@@ -0,0 +1,107 @@
1
+ 'use strict';
2
+
3
+ const hooks = require('./hooks');
4
+ const path = require('path');
5
+ const getFields = require('./fields');
6
+
7
+ const TEMPLATE = path.resolve(__dirname, './templates/amount-with-unit-select.html');
8
+
9
+ module.exports = (key, opts) => {
10
+ if (!key) {
11
+ throw new Error('Key must be passed to amountWithUnitSelect component');
12
+ }
13
+
14
+ const fields = getFields(key); // the child field definitions and configurations
15
+ const options = opts || {}; // the component's configuration options
16
+ const template = options.template ? // the field template path
17
+ path.resolve(__dirname, options.template) :
18
+ TEMPLATE;
19
+
20
+ /**
21
+ * Pre-process hook.
22
+ * @param {Object} req - The form's request object.
23
+ * @param {Object} res - The form's response object.
24
+ * @param {Function} next - The next middleware function in the chain.
25
+ */
26
+ const preProcess = (req, res, next) => {
27
+ hooks.preProcess(req, fields, key);
28
+ next();
29
+ };
30
+
31
+ /**
32
+ * Post-process hook.
33
+ * @param {Object} req - The form's request object.
34
+ * @param {Object} res - The form's response object.
35
+ * @param {Function} next - The next middleware function in the chain.
36
+ */
37
+ const postProcess = (req, res, next) => {
38
+ hooks.postProcess(req, key);
39
+ next();
40
+ };
41
+
42
+ /**
43
+ * Pre-validate hook.
44
+ * @param {Object} req - The form's request object.
45
+ * @param {Object} res - The form's response object.
46
+ * @param {Function} next - The next middleware function in the chain.
47
+ */
48
+ const preValidate = (req, res, next) => {
49
+ hooks.preValidate(req, fields, key, options);
50
+ next();
51
+ };
52
+
53
+ /**
54
+ * Pre-getErrors hook.
55
+ * @param {Object} req - The form's request object.
56
+ * @param {Object} res - The form's response object.
57
+ * @param {Function} next - The next middleware function in the chain.
58
+ */
59
+ const preGetErrors = (req, res, next) => {
60
+ hooks.preGetErrors(req, fields, key);
61
+ next();
62
+ };
63
+
64
+ /**
65
+ * Post-getErrors hook.
66
+ * @param {Object} req - The form's request object.
67
+ * @param {Object} res - The form's response object.
68
+ * @param {Function} next - The next middleware function in the chain.
69
+ */
70
+ const postGetErrors = (req, res, next) => {
71
+ hooks.postGetErrors(req, res, fields, key);
72
+ next();
73
+ };
74
+
75
+ /**
76
+ * Post-getValues hook.
77
+ * @param {Object} req - The form's request object.
78
+ * @param {Object} res - The form's response object.
79
+ * @param {Function} next - The next middleware function in the chain.
80
+ */
81
+ const postGetValues = (req, res, next) => {
82
+ hooks.postGetValues(req, fields, key);
83
+ next();
84
+ };
85
+
86
+ /**
87
+ * Pre-render hook.
88
+ * @param {Object} req - The form's request object.
89
+ * @param {Object} res - The form's response object.
90
+ * @param {Function} next - The next middleware function in the chain.
91
+ */
92
+ const preRender = (req, res, next) => {
93
+ hooks.preRender(req, res, fields, options, template, key, next);
94
+ };
95
+
96
+ return Object.assign({}, options, {
97
+ hooks: {
98
+ 'pre-process': preProcess,
99
+ 'post-process': postProcess,
100
+ 'pre-validate': preValidate,
101
+ 'pre-getErrors': preGetErrors,
102
+ 'post-getErrors': postGetErrors,
103
+ 'post-getValues': postGetValues,
104
+ 'pre-render': preRender
105
+ }
106
+ });
107
+ };
@@ -0,0 +1,20 @@
1
+ <div class="govuk-form-group {{#error}}govuk-form-group--error{{/error}}">
2
+ <fieldset id="{{key}}-group" class="govuk-fieldset{{#className}} {{className}}{{/className}}" role="group">
3
+ <legend class="govuk-fieldset__legend {{#isPageHeading}}govuk-fieldset__legend--l{{/isPageHeading}}{{#legendClassName}} {{legendClassName}}{{/legendClassName}}">
4
+ {{#isPageHeading}}<h1 class="govuk-fieldset__heading">{{/isPageHeading}}
5
+ {{legend}}
6
+ {{#isPageHeading}}</h1>{{/isPageHeading}}
7
+ </legend>
8
+ {{#hint}}
9
+ <span id="{{key}}-hint" class="govuk-hint">{{hint}}</span>
10
+ {{/hint}}
11
+ {{#error}}
12
+ <p id="{{key}}-error" class="govuk-error-message">
13
+ <span class="govuk-visually-hidden">Error:</span> {{error.message}}
14
+ </p>
15
+ {{/error}}
16
+ <div id="{{key}}" class="govuk-amount-with-unit-select-input">
17
+ {{#input-amount-with-unit-select}}{{key}}{{/input-amount-with-unit-select}}
18
+ </div>
19
+ </fieldset>
20
+ </div>