@planning-inspectorate/dynamic-forms 3.6.2 → 3.7.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@planning-inspectorate/dynamic-forms",
3
- "version": "3.6.2",
3
+ "version": "3.7.1",
4
4
  "description": "This package is for building GDS forms using a configuration-based approach.",
5
5
  "main": "./src/index.js",
6
6
  "type": "module",
@@ -29,9 +29,9 @@
29
29
  <div class="govuk-grid-row">
30
30
  <div class="govuk-grid-column-full">
31
31
  {% if summaryListData.sections | length > 1 %}
32
- {{ multiTaskList(summaryListData.sections, journeyComplete, beforeSubmitButton) }}
32
+ {{ multiTaskList(summaryListData.sections, journeyComplete, beforeSubmitButton, submitButtonText) }}
33
33
  {% elif summaryListData.sections | length == 1 %}
34
- {{ singleTaskList(summaryListData.sections | first, journeyComplete, beforeSubmitButton) }}
34
+ {{ singleTaskList(summaryListData.sections | first, journeyComplete, beforeSubmitButton, submitButtonText) }}
35
35
  {% endif %}
36
36
  </div>
37
37
  </div>
@@ -2,7 +2,7 @@
2
2
  {% from "govuk/components/tag/macro.njk" import govukTag %}
3
3
  {% from "govuk/components/button/macro.njk" import govukButton %}
4
4
 
5
- {% macro multiTaskList(sections, journeyComplete, beforeSubmitButton) %}
5
+ {% macro multiTaskList(sections, journeyComplete, beforeSubmitButton, submitButtonText) %}
6
6
  <ol class="app-task-list">
7
7
  {% for section in sections %}
8
8
  <li class="govuk-body govuk-!-margin-bottom-9">
@@ -46,7 +46,7 @@
46
46
  <form action method="post">
47
47
  <input type="hidden" name="_csrf" value="{{_csrf}}">
48
48
  {{ govukButton({
49
- text: "Accept & Submit",
49
+ text: submitButtonText | default("Accept & Submit", true),
50
50
  type: "submit"
51
51
  }) }}
52
52
  </form>
@@ -3,7 +3,7 @@
3
3
  {% from "govuk/components/button/macro.njk" import govukButton %}
4
4
  {% from "govuk/components/warning-text/macro.njk" import govukWarningText %}
5
5
 
6
- {% macro singleTaskList(section, journeyComplete, beforeSubmitButton) %}
6
+ {% macro singleTaskList(section, journeyComplete, beforeSubmitButton, submitButtonText) %}
7
7
  {% if section.list.rows.length %}
8
8
  {{ govukSummaryList(section.list) }}
9
9
  {% endif %}
@@ -15,7 +15,7 @@
15
15
  <form action method="post">
16
16
  <input type="hidden" name="_csrf" value="{{_csrf}}">
17
17
  {{ govukButton({
18
- text: "Accept & Submit",
18
+ text: submitButtonText | default("Accept & Submit", true),
19
19
  type: "submit"
20
20
  }) }}
21
21
  </form>
@@ -1,6 +1,7 @@
1
1
  import nunjucks from 'nunjucks';
2
2
  import { Question } from '../../questions/question.js';
3
3
  import { conditionalIsJustHTML } from '../utils/question-utils.js';
4
+ import { toArray } from '#src/lib/utils.js';
4
5
 
5
6
  const defaultOptionJoinString = ',';
6
7
 
@@ -132,7 +133,7 @@ export default class UnitOptionEntryQuestion extends Question {
132
133
  const answers = {};
133
134
 
134
135
  /** @type {string[]} */
135
- const fields = Array.isArray(req.body[this.fieldName]) ? req.body[this.fieldName] : [req.body[this.fieldName]];
136
+ const fields = toArray(req.body[this.fieldName]);
136
137
  const fieldValues = fields.map((x) => x.trim());
137
138
 
138
139
  const selectedOptions = this.options.filter(({ value }) => {
@@ -1,18 +1,18 @@
1
1
  export const COMPONENT_TYPES = Object.freeze({
2
- CHECKBOX: 'checkbox',
2
+ ADDRESS: 'site-address',
3
3
  BOOLEAN: 'boolean',
4
- RADIO: 'radio',
4
+ CHECKBOX: 'checkbox',
5
5
  DATE: 'date',
6
6
  DATE_PERIOD: 'date-period',
7
7
  DATE_TIME: 'date-time',
8
- TEXT_ENTRY: 'text-entry',
9
- TEXT_ENTRY_REDACT: 'text-entry-redact',
10
- SELECT: 'select',
11
- SINGLE_LINE_INPUT: 'single-line-input',
8
+ EMAIL: 'email',
9
+ MANAGE_LIST: 'manage-list',
12
10
  MULTI_FIELD_INPUT: 'multi-field-input',
13
11
  NUMBER: 'number',
14
- ADDRESS: 'site-address',
15
- UNIT_OPTION: 'unit-option',
16
- EMAIL: 'email',
17
- MANAGE_LIST: 'manage-list'
12
+ RADIO: 'radio',
13
+ SELECT: 'select',
14
+ SINGLE_LINE_INPUT: 'single-line-input',
15
+ TEXT_ENTRY: 'text-entry',
16
+ TEXT_ENTRY_REDACT: 'text-entry-redact',
17
+ UNIT_OPTION: 'unit-option'
18
18
  });
package/src/controller.js CHANGED
@@ -3,6 +3,7 @@ import questionUtils from './components/utils/question-utils.js';
3
3
  import { answerObjectForManageListSaving } from '#src/components/manage-list/utils.js';
4
4
  import { booleanToYesNoValue } from '#src/components/boolean/question.js';
5
5
  import { MANAGE_LIST_ACTIONS } from '#src/components/manage-list/manage-list-actions.js';
6
+ import { toArray } from '#src/lib/utils.js';
6
7
 
7
8
  /**
8
9
  * @typedef {import('./journey/journey.js').Journey} Journey
@@ -64,7 +65,7 @@ function buildSectionRowViewModel(key, value, action) {
64
65
  html: value
65
66
  },
66
67
  actions: {
67
- items: Array.isArray(action) ? action : [action]
68
+ items: toArray(action)
68
69
  }
69
70
  };
70
71
  }
package/src/lib/utils.js CHANGED
@@ -28,3 +28,13 @@ export function trimTrailingSlash(str) {
28
28
  if (typeof str !== 'string') return str;
29
29
  return str.replace(/\/$/, '');
30
30
  }
31
+
32
+ /**
33
+ * Convert a value to an array, unless it is already
34
+ *
35
+ * @param {T|T[]} value
36
+ * @template T
37
+ */
38
+ export function toArray(value) {
39
+ return Array.isArray(value) ? value : [value];
40
+ }
@@ -1,6 +1,6 @@
1
1
  import { describe, it } from 'node:test';
2
2
  import assert from 'node:assert';
3
- import { trimTrailingSlash } from '#src/lib/utils.js';
3
+ import { toArray, trimTrailingSlash } from '#src/lib/utils.js';
4
4
 
5
5
  describe('utils', () => {
6
6
  describe('trimTrailingSlash', () => {
@@ -16,4 +16,20 @@ describe('utils', () => {
16
16
  assert.strictEqual(trimTrailingSlash(5), 5);
17
17
  });
18
18
  });
19
+ describe('toArray', () => {
20
+ it('should create an array if a value is provided', () => {
21
+ const values = [true, false, 'string', 123, null, { hello: 'world' }];
22
+ for (const value of values) {
23
+ const asArray = toArray(value);
24
+ assert.ok(Array.isArray(asArray));
25
+ assert.strictEqual(asArray.length, 1);
26
+ assert.strictEqual(asArray[0], value);
27
+ }
28
+ });
29
+ it('should leave an array as-is', () => {
30
+ const array = [1, 'string', 2];
31
+ const asArray = toArray(array);
32
+ assert.strictEqual(array, asArray);
33
+ });
34
+ });
19
35
  });
@@ -2,6 +2,7 @@ import nunjucks from 'nunjucks';
2
2
  import { Question } from './question.js';
3
3
  import ValidOptionValidator from '../validator/valid-option-validator.js';
4
4
  import { getConditionalFieldName } from '../components/utils/question-utils.js';
5
+ import { toArray } from '#src/lib/utils.js';
5
6
 
6
7
  const defaultOptionJoinString = ',';
7
8
 
@@ -124,14 +125,14 @@ export default class OptionsQuestion extends Question {
124
125
  async getDataToSave(req, journeyResponse) {
125
126
  const answers = {};
126
127
 
127
- const fields = Array.isArray(req.body[this.fieldName]) ? req.body[this.fieldName] : [req.body[this.fieldName]];
128
+ const fields = req.body[this.fieldName] !== undefined ? toArray(req.body[this.fieldName]) : [];
128
129
  const fieldValues = fields.map((x) => x.trim());
129
130
 
130
131
  const selectedOptions = this.options.filter(({ value }) => {
131
132
  return fieldValues.includes(value);
132
133
  });
133
134
 
134
- if (!selectedOptions.length)
135
+ if (selectedOptions.length !== fieldValues.length)
135
136
  throw new Error(`User submitted option(s) did not correlate with valid answers to ${this.fieldName} question`);
136
137
 
137
138
  answers[this.fieldName] = fieldValues.join(this.optionJoinString);
@@ -220,4 +220,87 @@ describe('./src/dynamic-forms/question.js', () => {
220
220
  assert.strictEqual(result.hello, 'hi');
221
221
  });
222
222
  });
223
+ describe('getDataToSave', () => {
224
+ it('should return selected options in object format', async () => {
225
+ const mockReq = {
226
+ body: {
227
+ [FIELDNAME]: 'blue'
228
+ }
229
+ };
230
+ const options = [
231
+ {
232
+ text: 'Blue',
233
+ value: 'blue'
234
+ },
235
+ {
236
+ text: 'Red',
237
+ value: 'red'
238
+ }
239
+ ];
240
+ const expectedAnswer = {
241
+ answers: {
242
+ [FIELDNAME]: 'blue'
243
+ }
244
+ };
245
+
246
+ const question = getTestQuestion({ options });
247
+ const result = await question.getDataToSave(mockReq, {});
248
+ assert.deepStrictEqual(result, expectedAnswer);
249
+ });
250
+ it('if req.body field name is undefined then pass through with an empty answer', async () => {
251
+ const mockReq = {
252
+ body: {
253
+ [FIELDNAME]: undefined
254
+ }
255
+ };
256
+ const options = [
257
+ {
258
+ text: 'Blue',
259
+ value: 'blue'
260
+ },
261
+ {
262
+ text: 'Red',
263
+ value: 'red'
264
+ }
265
+ ];
266
+ const expectedAnswer = {
267
+ answers: {
268
+ [FIELDNAME]: ''
269
+ }
270
+ };
271
+
272
+ const question = getTestQuestion({ options });
273
+ const result = await question.getDataToSave(mockReq, {});
274
+ assert.deepStrictEqual(result, expectedAnswer);
275
+ });
276
+ it('if submitted options contains invalid answers then throw error', async () => {
277
+ const mockReq = {
278
+ body: {
279
+ [FIELDNAME]: ['blue', 'green']
280
+ }
281
+ };
282
+ const options = [
283
+ {
284
+ text: 'Blue',
285
+ value: 'blue'
286
+ },
287
+ {
288
+ text: 'Red',
289
+ value: 'red'
290
+ }
291
+ ];
292
+
293
+ const question = getTestQuestion({ options });
294
+ assert.rejects(
295
+ async () => question.getDataToSave(mockReq, {}),
296
+ (thrown) => {
297
+ assert.strictEqual(
298
+ thrown.message,
299
+ `User submitted option(s) did not correlate with valid answers to ${FIELDNAME} question`
300
+ );
301
+ return true;
302
+ }
303
+ );
304
+ });
305
+ });
223
306
  });
@@ -1,40 +1,27 @@
1
1
  import { DocType } from '@pins/common/src/document-types';
2
- import { JourneyResponse } from '../journey/journey-response';
3
- import BaseValidator from '../validator/base-validator';
2
+ import { QuestionParameters } from '#question-types';
4
3
 
5
4
  type QuestionTypes =
6
- | 'checkbox'
7
- | 'multi-file-upload'
8
5
  | 'boolean'
9
- | 'radio'
6
+ | 'checkbox'
10
7
  | 'date'
11
8
  | 'date-period'
12
- | 'text-entry'
13
- | 'text-entry-redact'
14
- | 'select'
15
- | 'single-line-input'
9
+ | 'date-time'
10
+ | 'email'
11
+ | 'manage-list'
16
12
  | 'multi-field-input'
17
13
  | 'number'
14
+ | 'radio'
15
+ | 'select'
16
+ | 'single-line-input'
18
17
  | 'site-address'
19
- | 'unit-option'
20
- | 'manage-list';
18
+ | 'text-entry'
19
+ | 'text-entry-redact'
20
+ | 'unit-option';
21
21
 
22
- interface CommonQuestionProps {
22
+ type CommonQuestionProps = QuestionParameters & {
23
23
  type: QuestionTypes;
24
- title: string;
25
- question: string;
26
- viewFolder?: string;
27
- fieldName: string;
28
- url?: string;
29
- pageTitle?: string;
30
- description?: string;
31
- label?: string;
32
- validators?: BaseValidator[];
33
- html?: string;
34
- hint?: string;
35
- shouldDisplay?: (response: JourneyResponse) => boolean;
36
- autocomplete?: string;
37
- }
24
+ };
38
25
 
39
26
  type Option =
40
27
  | {
@@ -92,24 +79,14 @@ interface UnitOption {
92
79
  };
93
80
  }
94
81
 
95
- type CheckboxQuestionProps = CommonQuestionProps & {
96
- type: 'checkbox';
97
- options: Option[];
98
- };
99
-
100
- type MultiFileUploadQuestionProps = CommonQuestionProps & {
101
- type: 'multi-file-upload';
102
- documentType: DocType;
103
- };
104
-
105
82
  type BooleanQuestionProps = CommonQuestionProps & {
106
83
  type: 'boolean';
107
84
  options?: Option[];
108
85
  interfaceType?: 'checkbox' | 'radio';
109
86
  };
110
87
 
111
- type RadioQuestionProps = CommonQuestionProps & {
112
- type: 'radio';
88
+ type CheckboxQuestionProps = CommonQuestionProps & {
89
+ type: 'checkbox';
113
90
  options: Option[];
114
91
  };
115
92
 
@@ -117,51 +94,86 @@ type DateQuestionProps = CommonQuestionProps & {
117
94
  type: 'date';
118
95
  };
119
96
 
120
- type TextEntryQuestionProps = CommonQuestionProps & {
121
- type: 'text-entry';
122
- label?: string;
97
+ type DatePeriodQuestionProps = CommonQuestionProps & {
98
+ type: 'date-period';
123
99
  };
124
100
 
125
- type SingleLineInputQuestionProps = CommonQuestionProps & {
126
- type: 'single-line-input';
127
- label?: string;
128
- inputAttributes?: Record<string, string>;
101
+ type DateTimeQuestionProps = CommonQuestionProps & {
102
+ type: 'date-time';
103
+ };
104
+
105
+ type ManageListQuestionProps = CommonQuestionProps & {
106
+ type: 'manage-list';
107
+ };
108
+
109
+ type EmailQuestionProps = CommonQuestionProps & {
110
+ type: 'email';
129
111
  };
130
112
 
131
113
  type MultiFieldInputQuestionProps = CommonQuestionProps & {
132
114
  type: 'multi-field-input';
133
- label?: string;
134
115
  inputAttributes?: Record<string, string>;
135
116
  inputFields: InputField[];
136
117
  formatType?: 'contactDetails' | 'standard';
137
118
  };
138
119
 
120
+ type MultiFileUploadQuestionProps = CommonQuestionProps & {
121
+ type: 'multi-file-upload';
122
+ documentType: DocType;
123
+ };
124
+
139
125
  type NumberEntryQuestionProps = CommonQuestionProps & {
140
126
  type: 'number';
141
- label?: string;
142
127
  suffix?: string;
143
128
  };
144
129
 
130
+ type RadioQuestionProps = CommonQuestionProps & {
131
+ type: 'radio';
132
+ options: Option[];
133
+ };
134
+
135
+ type SelectQuestionProps = CommonQuestionProps & {
136
+ type: 'select';
137
+ options: Option[];
138
+ };
139
+
140
+ type SingleLineInputQuestionProps = CommonQuestionProps & {
141
+ type: 'single-line-input';
142
+ inputAttributes?: Record<string, string>;
143
+ };
144
+
145
145
  type SiteAddressQuestionProps = CommonQuestionProps & {
146
146
  type: 'site-address';
147
147
  };
148
148
 
149
+ type TextEntryQuestionProps = CommonQuestionProps & {
150
+ type: 'text-entry';
151
+ };
152
+
153
+ type TextEntryRedactQuestionProps = CommonQuestionProps & {
154
+ type: 'text-entry-redact';
155
+ };
156
+
149
157
  type UnitOptionEntryQuestionProps = CommonQuestionProps & {
150
158
  type: 'unit-option';
151
159
  conditionalFieldName: string;
152
160
  options: UnitOption[];
153
- label?: string;
154
161
  };
155
162
 
156
163
  export type QuestionProps =
157
- | CheckboxQuestionProps
158
- | MultiFileUploadQuestionProps
159
164
  | BooleanQuestionProps
160
- | RadioQuestionProps
165
+ | CheckboxQuestionProps
161
166
  | DateQuestionProps
162
- | TextEntryQuestionProps
163
- | SingleLineInputQuestionProps
167
+ | DatePeriodQuestionProps
168
+ | DateTimeQuestionProps
169
+ | ManageListQuestionProps
170
+ | EmailQuestionProps
164
171
  | MultiFieldInputQuestionProps
165
172
  | NumberEntryQuestionProps
173
+ | RadioQuestionProps
174
+ | SelectQuestionProps
175
+ | SingleLineInputQuestionProps
166
176
  | SiteAddressQuestionProps
177
+ | TextEntryQuestionProps
178
+ | TextEntryRedactQuestionProps
167
179
  | UnitOptionEntryQuestionProps;
@@ -1,6 +1,7 @@
1
1
  import { body } from 'express-validator';
2
2
 
3
3
  import BaseValidator from './base-validator.js';
4
+ import { toArray } from '#src/lib/utils.js';
4
5
 
5
6
  /**
6
7
  * @typedef {import('../questions/question.js')} Question
@@ -52,7 +53,7 @@ export default class ConditionalRequiredValidator extends BaseValidator {
52
53
 
53
54
  isValueIncluded(questionObj, value) {
54
55
  return body(questionObj.fieldName).custom((existingValues) => {
55
- existingValues = Array.isArray(existingValues) ? existingValues : [existingValues];
56
+ existingValues = toArray(existingValues);
56
57
  return existingValues.includes(value);
57
58
  });
58
59
  }
@@ -1,6 +1,7 @@
1
1
  import { body } from 'express-validator';
2
2
 
3
3
  import BaseValidator from './base-validator.js';
4
+ import { toArray } from '#src/lib/utils.js';
4
5
 
5
6
  /**
6
7
  * @typedef {import('../questions/question.js')} Question
@@ -81,7 +82,7 @@ export default class UnitOptionEntryValidator extends BaseValidator {
81
82
 
82
83
  isValueIncluded(questionObj, value) {
83
84
  return body(questionObj.fieldName).custom((existingValues) => {
84
- existingValues = Array.isArray(existingValues) ? existingValues : [existingValues];
85
+ existingValues = toArray(existingValues);
85
86
  return existingValues.includes(value);
86
87
  });
87
88
  }
@@ -1,6 +1,7 @@
1
1
  import { body } from 'express-validator';
2
2
 
3
3
  import BaseValidator from './base-validator.js';
4
+ import { toArray } from '#src/lib/utils.js';
4
5
 
5
6
  /**
6
7
  * @typedef {import('../questions/options-question.js')} OptionsQuestion
@@ -33,7 +34,7 @@ export default class ValidOptionValidator extends BaseValidator {
33
34
  return body(questionObj.fieldName)
34
35
  .custom((value) => {
35
36
  if (!value) return true;
36
- value = Array.isArray(value) ? value : [value];
37
+ value = toArray(value);
37
38
  return value.every((element) => questionObj.options.map((option) => option.value).includes(element));
38
39
  })
39
40
  .withMessage(this.errorMessage);
@@ -1 +1 @@
1
- {"version":3,"file":"question.d.ts","sourceRoot":"","sources":["../../../../src/components/unit-option-entry/question.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;IACC,gCAAgC;IAChC,SADW,KAAK,CAAC,UAAU,CAAC,CACpB;IAqBP,0BAAgD;IAEhD,WAAkB;IAClB,yBAA+C;IAGhD;;;;;;;;;;;;OAYG;IACH,gDAVW,OAAO,UAAU,EAAE,OAAO,mBAC1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,WACvB,OAAO,oCAAoC,EAAE,+BAA+B,GAC1E,OAAO,WAAW,EAAE,iBAAiB,GAAG;QAChD,QAAQ,EAAE,OAAO,WAAW,EAAE,iBAAiB,CAAC,UAAU,CAAC,GAAG;YAC5D,OAAO,EAAC,UAAU,EAAE,CAAA;SACrB,CAAA;KACF,CAmDH;IAED;;;;;OAKG,CACH,yCAHW,eAAe,GACb,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAgCzD;CAoBD;;;;;;;;;yBAvKY;IACR,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,WAAW,EAAE;QACX,SAAS,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,OAAO,CAAC;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAA;CACH;yBA3BsB,6BAA6B"}
1
+ {"version":3,"file":"question.d.ts","sourceRoot":"","sources":["../../../../src/components/unit-option-entry/question.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;IACC,gCAAgC;IAChC,SADW,KAAK,CAAC,UAAU,CAAC,CACpB;IAqBP,0BAAgD;IAEhD,WAAkB;IAClB,yBAA+C;IAGhD;;;;;;;;;;;;OAYG;IACH,gDAVW,OAAO,UAAU,EAAE,OAAO,mBAC1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,WACvB,OAAO,oCAAoC,EAAE,+BAA+B,GAC1E,OAAO,WAAW,EAAE,iBAAiB,GAAG;QAChD,QAAQ,EAAE,OAAO,WAAW,EAAE,iBAAiB,CAAC,UAAU,CAAC,GAAG;YAC5D,OAAO,EAAC,UAAU,EAAE,CAAA;SACrB,CAAA;KACF,CAmDH;IAED;;;;;OAKG,CACH,yCAHW,eAAe,GACb,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAgCzD;CAoBD;;;;;;;;;yBAvKY;IACR,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,WAAW,EAAE;QACX,SAAS,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,OAAO,CAAC;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAA;CACH;yBA5BsB,6BAA6B"}
@@ -1,19 +1,19 @@
1
1
  export const COMPONENT_TYPES: Readonly<{
2
- CHECKBOX: "checkbox";
2
+ ADDRESS: "site-address";
3
3
  BOOLEAN: "boolean";
4
- RADIO: "radio";
4
+ CHECKBOX: "checkbox";
5
5
  DATE: "date";
6
6
  DATE_PERIOD: "date-period";
7
7
  DATE_TIME: "date-time";
8
- TEXT_ENTRY: "text-entry";
9
- TEXT_ENTRY_REDACT: "text-entry-redact";
10
- SELECT: "select";
11
- SINGLE_LINE_INPUT: "single-line-input";
8
+ EMAIL: "email";
9
+ MANAGE_LIST: "manage-list";
12
10
  MULTI_FIELD_INPUT: "multi-field-input";
13
11
  NUMBER: "number";
14
- ADDRESS: "site-address";
12
+ RADIO: "radio";
13
+ SELECT: "select";
14
+ SINGLE_LINE_INPUT: "single-line-input";
15
+ TEXT_ENTRY: "text-entry";
16
+ TEXT_ENTRY_REDACT: "text-entry-redact";
15
17
  UNIT_OPTION: "unit-option";
16
- EMAIL: "email";
17
- MANAGE_LIST: "manage-list";
18
18
  }>;
19
19
  //# sourceMappingURL=component-types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/controller.js"],"names":[],"mappings":"AAuEA;;;GAGG;AACH,qCAHW,MAAM,OAKhB;AAED;;;;;GAKG;AACH,sDAHW,MAAM,YACN,MAAM,gBA8DhB;AAED;;;;GAIG;AACH,2DA0CC;AAED;;;;;;;;;;GAUG;AAEH;;GAEG;AAEH;;;;GAIG;AACH,oCAJW,UAAU,gCACV,OAAO,OAuFjB;sBAtSY,OAAO,sBAAsB,EAAE,OAAO;uBACtC,OAAO,yBAAyB,EAAE,QAAQ;;;aAMzC,MAAM;YACN,MAAM;UAEjB;QAAiC,IAAI,EAA1B,KAAK,CAAE,OAAO,CAAC;KAC5B;;;SAIa;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;WAChB;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;;eAC1B,UAAU,EAAE;;;;UAKrB,MAAM;UACN,MAAM;;;;;;eA0KN,MAAM;iBACN,MAAM;sBACN,OAAO;;;;;;;yBAOR,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC"}
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/controller.js"],"names":[],"mappings":"AAwEA;;;GAGG;AACH,qCAHW,MAAM,OAKhB;AAED;;;;;GAKG;AACH,sDAHW,MAAM,YACN,MAAM,gBA8DhB;AAED;;;;GAIG;AACH,2DA0CC;AAED;;;;;;;;;;GAUG;AAEH;;GAEG;AAEH;;;;GAIG;AACH,oCAJW,UAAU,gCACV,OAAO,OAuFjB;sBAtSY,OAAO,sBAAsB,EAAE,OAAO;uBACtC,OAAO,yBAAyB,EAAE,QAAQ;;;aAMzC,MAAM;YACN,MAAM;UAEjB;QAAiC,IAAI,EAA1B,KAAK,CAAE,OAAO,CAAC;KAC5B;;;SAIa;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;WAChB;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;;eAC1B,UAAU,EAAE;;;;UAKrB,MAAM;UACN,MAAM;;;;;;eA0KN,MAAM;iBACN,MAAM;sBACN,OAAO;;;;;;;yBAOR,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC"}
@@ -16,4 +16,11 @@ export function capitalize(str: string | any): string;
16
16
  * @returns {string}
17
17
  */
18
18
  export function trimTrailingSlash(str?: string): string;
19
+ /**
20
+ * Convert a value to an array, unless it is already
21
+ *
22
+ * @param {T|T[]} value
23
+ * @template T
24
+ */
25
+ export function toArray<T>(value: T | T[]): T[];
19
26
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils.js"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,8BAHW,MAAM,GACJ,MAAM,CAMlB;AAED;;;GAGG;AACH,gCAHW,MAAM,GAAC,GAAG,GACR,MAAM,CAKlB;AAED;;;;;GAKG;AACH,wCAHW,MAAM,GACJ,MAAM,CAKlB"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/utils.js"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,8BAHW,MAAM,GACJ,MAAM,CAMlB;AAED;;;GAGG;AACH,gCAHW,MAAM,GAAC,GAAG,GACR,MAAM,CAKlB;AAED;;;;;GAKG;AACH,wCAHW,MAAM,GACJ,MAAM,CAKlB;AAED;;;;;GAKG;AACH,wBAFa,CAAC,SADH,CAAC,GAAC,CAAC,EAAE,OAKf"}
@@ -1 +1 @@
1
- {"version":3,"file":"options-question.d.ts","sourceRoot":"","sources":["../../../src/questions/options-question.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH;;GAEG;AAEH;IAIC;;;OAGG;IACH,oBAHW,OAAO,iBAAiB,EAAE,kBAAkB,EAgBtD;IApBD,4BAA4B;IAC5B,SADW,KAAK,CAAC,MAAM,CAAC,CAChB;IAkBP,yBAA+C;IAGhD;;;;;;;;OAQG;IACH,kCAPW,OAAO,UAAU,EAAE,OAAO,WAC1B,OAAO,UAAU,EAAE,OAAO,mBAC1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,WACvB,OAAO,oCAAoC,EAAE,+BAA+B,OAmDtF;CAmCD;qBA9IY;IACR,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,WAAW,CAAC,EAAE;QACZ,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QACd,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,IAAI,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,OAAO,CAAC;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAA;KAClB,CAAC;IACA,eAAe,CAAC,EAAE;QAChB,IAAI,EAAE,MAAM,CAAC;KAChB,CAAA;CACH;+BAIU,GAAsC,GAAG;IAAE,QAAQ,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;CAAE;yBA/BhE,eAAe"}
1
+ {"version":3,"file":"options-question.d.ts","sourceRoot":"","sources":["../../../src/questions/options-question.js"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH;;GAEG;AAEH;IAIC;;;OAGG;IACH,oBAHW,OAAO,iBAAiB,EAAE,kBAAkB,EAgBtD;IApBD,4BAA4B;IAC5B,SADW,KAAK,CAAC,MAAM,CAAC,CAChB;IAkBP,yBAA+C;IAGhD;;;;;;;;OAQG;IACH,kCAPW,OAAO,UAAU,EAAE,OAAO,WAC1B,OAAO,UAAU,EAAE,OAAO,mBAC1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,WACvB,OAAO,oCAAoC,EAAE,+BAA+B,OAmDtF;CAmCD;qBA9IY;IACR,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,WAAW,CAAC,EAAE;QACZ,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QACd,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,IAAI,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,OAAO,CAAC;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAA;KAClB,CAAC;IACA,eAAe,CAAC,EAAE;QAChB,IAAI,EAAE,MAAM,CAAC;KAChB,CAAA;CACH;+BAIU,GAAsC,GAAG;IAAE,QAAQ,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;CAAE;yBAhChE,eAAe"}
@@ -1 +1 @@
1
- {"version":3,"file":"conditional-required-validator.d.ts","sourceRoot":"","sources":["../../../src/validator/conditional-required-validator.js"],"names":[],"mappings":"AAIA;;GAEG;AAEH;;;GAGG;AACH;IAMC;;;OAGG;IACH,2BAFW,MAAM,EAQhB;IAED;;;OAGG;IACH,sBAFW,QAAQ,OAclB;IAED,+DAEC;IAED,2FAKC;CACD;;0BAxDyB,qBAAqB"}
1
+ {"version":3,"file":"conditional-required-validator.d.ts","sourceRoot":"","sources":["../../../src/validator/conditional-required-validator.js"],"names":[],"mappings":"AAKA;;GAEG;AAEH;;;GAGG;AACH;IAMC;;;OAGG;IACH,2BAFW,MAAM,EAQhB;IAED;;;OAGG;IACH,sBAFW,QAAQ,OAclB;IAED,+DAEC;IAED,2FAKC;CACD;;0BAzDyB,qBAAqB"}
@@ -1 +1 @@
1
- {"version":3,"file":"unit-option-entry-validator.d.ts","sourceRoot":"","sources":["../../../src/validator/unit-option-entry-validator.js"],"names":[],"mappings":"AAIA;;GAEG;AAEH;;;GAGG;AACH;IACC;;;;;;;;OAQG;IAEH,oEARG;QAAwB,YAAY;QACZ,IAAI;QACJ,GAAG;QACH,GAAG;QACJ,KAAK;QACJ,YAAY;KAAC,EAWvC;IALA,aAA2B;IAC3B,wBAAc;IACd,wBAAc;IACd,WAAkB;IAClB,qBAA0D;IAG3D;;;OAGG;IACH,sBAFW,QAAQ,OA4ClB;IAED,2FAKC;CACD;;0BArFyB,qBAAqB"}
1
+ {"version":3,"file":"unit-option-entry-validator.d.ts","sourceRoot":"","sources":["../../../src/validator/unit-option-entry-validator.js"],"names":[],"mappings":"AAKA;;GAEG;AAEH;;;GAGG;AACH;IACC;;;;;;;;OAQG;IAEH,oEARG;QAAwB,YAAY;QACZ,IAAI;QACJ,GAAG;QACH,GAAG;QACJ,KAAK;QACJ,YAAY;KAAC,EAWvC;IALA,aAA2B;IAC3B,wBAAc;IACd,wBAAc;IACd,WAAkB;IAClB,qBAA0D;IAG3D;;;OAGG;IACH,sBAFW,QAAQ,OA4ClB;IAED,2FAKC;CACD;;0BAtFyB,qBAAqB"}
@@ -1 +1 @@
1
- {"version":3,"file":"valid-option-validator.d.ts","sourceRoot":"","sources":["../../../src/validator/valid-option-validator.js"],"names":[],"mappings":"AAIA;;GAEG;AAEH;;;GAGG;AACH;IACC;;;OAGG;IACH,2BAFW,MAAM,EAUhB;IAED;;;OAGG;IACH,sBAFW,eAAe,+CAUzB;CACD;;0BAtCyB,qBAAqB"}
1
+ {"version":3,"file":"valid-option-validator.d.ts","sourceRoot":"","sources":["../../../src/validator/valid-option-validator.js"],"names":[],"mappings":"AAKA;;GAEG;AAEH;;;GAGG;AACH;IACC;;;OAGG;IACH,2BAFW,MAAM,EAUhB;IAED;;;OAGG;IACH,sBAFW,eAAe,+CAUzB;CACD;;0BAvCyB,qBAAqB"}