@defra/forms-engine-plugin 0.0.4 → 0.0.5

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 (224) hide show
  1. package/package.json +3 -2
  2. package/src/client/javascripts/application.js +87 -0
  3. package/src/client/javascripts/file-upload.js +386 -0
  4. package/src/client/stylesheets/_code.scss +33 -0
  5. package/src/client/stylesheets/_govuk-frontend.scss +4 -0
  6. package/src/client/stylesheets/_prose.scss +56 -0
  7. package/src/client/stylesheets/_service-banner.scss +24 -0
  8. package/src/client/stylesheets/_summary-list.scss +28 -0
  9. package/src/client/stylesheets/_tag-env.scss +24 -0
  10. package/src/client/stylesheets/application.scss +14 -0
  11. package/src/common/cookies.js +58 -0
  12. package/src/common/cookies.test.js +23 -0
  13. package/src/common/types.js +5 -0
  14. package/src/config/index.ts +271 -0
  15. package/src/index.ts +31 -0
  16. package/src/server/common/helpers/logging/logger-options.test.ts +50 -0
  17. package/src/server/common/helpers/logging/logger-options.ts +46 -0
  18. package/src/server/common/helpers/logging/logger.ts +7 -0
  19. package/src/server/common/helpers/logging/request-logger.ts +9 -0
  20. package/src/server/common/helpers/logging/request-tracing.js +10 -0
  21. package/src/server/common/helpers/redis-client.js +70 -0
  22. package/src/server/constants.js +1 -0
  23. package/src/server/forms/README.md +10 -0
  24. package/src/server/forms/components.json +1015 -0
  25. package/src/server/forms/report-a-terrorist.json +270 -0
  26. package/src/server/forms/runner-components-test.json +365 -0
  27. package/src/server/forms/test.json +581 -0
  28. package/src/server/index.test.ts +582 -0
  29. package/src/server/index.ts +140 -0
  30. package/src/server/plugins/blankie.test.ts +73 -0
  31. package/src/server/plugins/blankie.ts +48 -0
  32. package/src/server/plugins/crumb.ts +20 -0
  33. package/src/server/plugins/engine/README.md +87 -0
  34. package/src/server/plugins/engine/components/AutocompleteField.test.ts +294 -0
  35. package/src/server/plugins/engine/components/AutocompleteField.ts +49 -0
  36. package/src/server/plugins/engine/components/CheckboxesField.test.ts +379 -0
  37. package/src/server/plugins/engine/components/CheckboxesField.ts +106 -0
  38. package/src/server/plugins/engine/components/ComponentBase.ts +97 -0
  39. package/src/server/plugins/engine/components/ComponentCollection.ts +278 -0
  40. package/src/server/plugins/engine/components/DatePartsField.test.ts +822 -0
  41. package/src/server/plugins/engine/components/DatePartsField.ts +264 -0
  42. package/src/server/plugins/engine/components/Details.test.ts +49 -0
  43. package/src/server/plugins/engine/components/Details.ts +30 -0
  44. package/src/server/plugins/engine/components/EmailAddressField.test.ts +395 -0
  45. package/src/server/plugins/engine/components/EmailAddressField.ts +55 -0
  46. package/src/server/plugins/engine/components/FileUploadField.test.ts +778 -0
  47. package/src/server/plugins/engine/components/FileUploadField.ts +262 -0
  48. package/src/server/plugins/engine/components/FormComponent.ts +249 -0
  49. package/src/server/plugins/engine/components/Html.test.ts +48 -0
  50. package/src/server/plugins/engine/components/Html.ts +29 -0
  51. package/src/server/plugins/engine/components/InsetText.test.ts +48 -0
  52. package/src/server/plugins/engine/components/InsetText.ts +27 -0
  53. package/src/server/plugins/engine/components/List.test.ts +76 -0
  54. package/src/server/plugins/engine/components/List.ts +72 -0
  55. package/src/server/plugins/engine/components/ListFormComponent.ts +140 -0
  56. package/src/server/plugins/engine/components/MonthYearField.test.ts +567 -0
  57. package/src/server/plugins/engine/components/MonthYearField.ts +222 -0
  58. package/src/server/plugins/engine/components/MultilineTextField.test.ts +558 -0
  59. package/src/server/plugins/engine/components/MultilineTextField.ts +138 -0
  60. package/src/server/plugins/engine/components/NumberField.test.ts +701 -0
  61. package/src/server/plugins/engine/components/NumberField.ts +163 -0
  62. package/src/server/plugins/engine/components/RadiosField.test.ts +288 -0
  63. package/src/server/plugins/engine/components/RadiosField.ts +24 -0
  64. package/src/server/plugins/engine/components/SelectField.test.ts +288 -0
  65. package/src/server/plugins/engine/components/SelectField.ts +47 -0
  66. package/src/server/plugins/engine/components/SelectionControlField.ts +43 -0
  67. package/src/server/plugins/engine/components/TelephoneNumberField.test.ts +356 -0
  68. package/src/server/plugins/engine/components/TelephoneNumberField.ts +67 -0
  69. package/src/server/plugins/engine/components/TextField.test.ts +489 -0
  70. package/src/server/plugins/engine/components/TextField.ts +96 -0
  71. package/src/server/plugins/engine/components/UkAddressField.test.ts +623 -0
  72. package/src/server/plugins/engine/components/UkAddressField.ts +172 -0
  73. package/src/server/plugins/engine/components/YesNoField.test.ts +248 -0
  74. package/src/server/plugins/engine/components/YesNoField.ts +31 -0
  75. package/src/server/plugins/engine/components/constants.ts +1 -0
  76. package/src/server/plugins/engine/components/helpers.ts +330 -0
  77. package/src/server/plugins/engine/components/index.ts +24 -0
  78. package/src/server/plugins/engine/components/types.ts +117 -0
  79. package/src/server/plugins/engine/configureEnginePlugin.ts +47 -0
  80. package/src/server/plugins/engine/helpers.test.ts +791 -0
  81. package/src/server/plugins/engine/helpers.ts +379 -0
  82. package/src/server/plugins/engine/index.ts +7 -0
  83. package/src/server/plugins/engine/models/FormModel.test.ts +42 -0
  84. package/src/server/plugins/engine/models/FormModel.ts +443 -0
  85. package/src/server/plugins/engine/models/RepeatingSummaryViewModel.ts +0 -0
  86. package/src/server/plugins/engine/models/Section.ts +0 -0
  87. package/src/server/plugins/engine/models/SummaryViewModel.test.ts +209 -0
  88. package/src/server/plugins/engine/models/SummaryViewModel.ts +220 -0
  89. package/src/server/plugins/engine/models/index.ts +2 -0
  90. package/src/server/plugins/engine/models/types.ts +114 -0
  91. package/src/server/plugins/engine/outputFormatters/human/v1.test.ts +143 -0
  92. package/src/server/plugins/engine/outputFormatters/human/v1.ts +73 -0
  93. package/src/server/plugins/engine/outputFormatters/index.test.ts +17 -0
  94. package/src/server/plugins/engine/outputFormatters/index.ts +44 -0
  95. package/src/server/plugins/engine/outputFormatters/machine/v1.test.ts +229 -0
  96. package/src/server/plugins/engine/outputFormatters/machine/v1.ts +140 -0
  97. package/src/server/plugins/engine/outputFormatters/machine/v2.test.ts +229 -0
  98. package/src/server/plugins/engine/outputFormatters/machine/v2.ts +153 -0
  99. package/src/server/plugins/engine/pageControllers/FileUploadPageController.test.ts +1108 -0
  100. package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +446 -0
  101. package/src/server/plugins/engine/pageControllers/PageController.test.ts +205 -0
  102. package/src/server/plugins/engine/pageControllers/PageController.ts +176 -0
  103. package/src/server/plugins/engine/pageControllers/QuestionPageController.test.ts +1264 -0
  104. package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +561 -0
  105. package/src/server/plugins/engine/pageControllers/README.md +28 -0
  106. package/src/server/plugins/engine/pageControllers/RepeatPageController.test.ts +264 -0
  107. package/src/server/plugins/engine/pageControllers/RepeatPageController.ts +458 -0
  108. package/src/server/plugins/engine/pageControllers/StartPageController.ts +18 -0
  109. package/src/server/plugins/engine/pageControllers/StatusPageController.ts +50 -0
  110. package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +261 -0
  111. package/src/server/plugins/engine/pageControllers/TerminalController.test.ts +28 -0
  112. package/src/server/plugins/engine/pageControllers/TerminalPageController.ts +19 -0
  113. package/src/server/plugins/engine/pageControllers/helpers.test.ts +198 -0
  114. package/src/server/plugins/engine/pageControllers/helpers.ts +101 -0
  115. package/src/server/plugins/engine/pageControllers/index.ts +10 -0
  116. package/src/server/plugins/engine/pageControllers/validationOptions.ts +89 -0
  117. package/src/server/plugins/engine/plugin.ts +673 -0
  118. package/src/server/plugins/engine/services/formSubmissionService.js +46 -0
  119. package/src/server/plugins/engine/services/formsService.js +46 -0
  120. package/src/server/plugins/engine/services/formsService.test.js +90 -0
  121. package/src/server/plugins/engine/services/index.js +3 -0
  122. package/src/server/plugins/engine/services/notifyService.test.ts +132 -0
  123. package/src/server/plugins/engine/services/notifyService.ts +64 -0
  124. package/src/server/plugins/engine/services/uploadService.js +60 -0
  125. package/src/server/plugins/engine/types.ts +315 -0
  126. package/src/server/plugins/engine/views/components/autocompletefield.html +5 -0
  127. package/src/server/plugins/engine/views/components/checkboxesfield.html +5 -0
  128. package/src/server/plugins/engine/views/components/datepartsfield.html +5 -0
  129. package/src/server/plugins/engine/views/components/details.html +6 -0
  130. package/src/server/plugins/engine/views/components/emailaddressfield.html +5 -0
  131. package/src/server/plugins/engine/views/components/fileuploadfield-key.html +8 -0
  132. package/src/server/plugins/engine/views/components/fileuploadfield-value.html +3 -0
  133. package/src/server/plugins/engine/views/components/fileuploadfield.html +24 -0
  134. package/src/server/plugins/engine/views/components/html.html +3 -0
  135. package/src/server/plugins/engine/views/components/insettext.html +7 -0
  136. package/src/server/plugins/engine/views/components/list.html +36 -0
  137. package/src/server/plugins/engine/views/components/monthyearfield.html +5 -0
  138. package/src/server/plugins/engine/views/components/multilinetextfield.html +10 -0
  139. package/src/server/plugins/engine/views/components/numberfield.html +5 -0
  140. package/src/server/plugins/engine/views/components/radiosfield.html +5 -0
  141. package/src/server/plugins/engine/views/components/selectfield.html +5 -0
  142. package/src/server/plugins/engine/views/components/telephonenumberfield.html +5 -0
  143. package/src/server/plugins/engine/views/components/textfield.html +5 -0
  144. package/src/server/plugins/engine/views/components/ukaddressfield.html +25 -0
  145. package/src/server/plugins/engine/views/components/yesnofield.html +5 -0
  146. package/src/server/plugins/engine/views/file-upload.html +45 -0
  147. package/src/server/plugins/engine/views/index.html +39 -0
  148. package/src/server/plugins/engine/views/item-delete.html +56 -0
  149. package/src/server/plugins/engine/views/partials/components.html +6 -0
  150. package/src/server/plugins/engine/views/partials/conditional-components.html +3 -0
  151. package/src/server/plugins/engine/views/partials/debug.html +44 -0
  152. package/src/server/plugins/engine/views/partials/form.html +15 -0
  153. package/src/server/plugins/engine/views/partials/heading.html +16 -0
  154. package/src/server/plugins/engine/views/partials/preview-banner.html +32 -0
  155. package/src/server/plugins/engine/views/partials/preview-banner.test.js +122 -0
  156. package/src/server/plugins/engine/views/partials/warn-missing-notification-email.html +10 -0
  157. package/src/server/plugins/engine/views/repeat-list-summary.html +53 -0
  158. package/src/server/plugins/errorPages.ts +58 -0
  159. package/src/server/plugins/nunjucks/context.js +88 -0
  160. package/src/server/plugins/nunjucks/context.test.js +142 -0
  161. package/src/server/plugins/nunjucks/enviroment.test.js +201 -0
  162. package/src/server/plugins/nunjucks/environment.js +116 -0
  163. package/src/server/plugins/nunjucks/filters/answer.js +27 -0
  164. package/src/server/plugins/nunjucks/filters/answer.test.js +89 -0
  165. package/src/server/plugins/nunjucks/filters/evaluate.js +21 -0
  166. package/src/server/plugins/nunjucks/filters/field.js +28 -0
  167. package/src/server/plugins/nunjucks/filters/field.test.js +75 -0
  168. package/src/server/plugins/nunjucks/filters/highlight.js +11 -0
  169. package/src/server/plugins/nunjucks/filters/href.js +30 -0
  170. package/src/server/plugins/nunjucks/filters/href.test.js +80 -0
  171. package/src/server/plugins/nunjucks/filters/index.js +8 -0
  172. package/src/server/plugins/nunjucks/filters/inspect.js +15 -0
  173. package/src/server/plugins/nunjucks/filters/page.js +24 -0
  174. package/src/server/plugins/nunjucks/filters/page.test.js +65 -0
  175. package/src/server/plugins/nunjucks/index.js +3 -0
  176. package/src/server/plugins/nunjucks/plugin.js +40 -0
  177. package/src/server/plugins/nunjucks/render.js +42 -0
  178. package/src/server/plugins/nunjucks/types.js +40 -0
  179. package/src/server/plugins/pulse.ts +11 -0
  180. package/src/server/plugins/router.ts +201 -0
  181. package/src/server/plugins/session.ts +28 -0
  182. package/src/server/routes/health.js +13 -0
  183. package/src/server/routes/health.test.js +35 -0
  184. package/src/server/routes/index.test.ts +125 -0
  185. package/src/server/routes/index.ts +2 -0
  186. package/src/server/routes/public.ts +47 -0
  187. package/src/server/routes/types.ts +48 -0
  188. package/src/server/schemas/index.ts +34 -0
  189. package/src/server/secure-context.js +43 -0
  190. package/src/server/services/cacheService.test.ts +276 -0
  191. package/src/server/services/cacheService.ts +131 -0
  192. package/src/server/services/httpService.test.js +491 -0
  193. package/src/server/services/httpService.ts +50 -0
  194. package/src/server/services/index.ts +1 -0
  195. package/src/server/types.ts +54 -0
  196. package/src/server/utils/notify.test.ts +37 -0
  197. package/src/server/utils/notify.ts +50 -0
  198. package/src/server/utils/secure-context/get-trust-store-certs.js +11 -0
  199. package/src/server/utils/secure-context/get-trust-store-certs.test.js +19 -0
  200. package/src/server/utils/utils.js +24 -0
  201. package/src/server/utils/utils.test.js +54 -0
  202. package/src/server/views/404.html +16 -0
  203. package/src/server/views/500.html +19 -0
  204. package/src/server/views/components/debug/macro.njk +3 -0
  205. package/src/server/views/components/debug/template.njk +13 -0
  206. package/src/server/views/components/service-banner/macro.njk +3 -0
  207. package/src/server/views/components/service-banner/template.njk +20 -0
  208. package/src/server/views/components/service-banner/template.test.js +43 -0
  209. package/src/server/views/components/tag-env/macro.njk +3 -0
  210. package/src/server/views/components/tag-env/template.njk +30 -0
  211. package/src/server/views/components/tag-env/template.test.js +66 -0
  212. package/src/server/views/confirmation.html +19 -0
  213. package/src/server/views/help/accessibility-statement.html +58 -0
  214. package/src/server/views/help/cookie-preferences.html +57 -0
  215. package/src/server/views/help/cookies.html +71 -0
  216. package/src/server/views/help/get-support.html +37 -0
  217. package/src/server/views/help/privacy-notice.html +68 -0
  218. package/src/server/views/help/terms-and-conditions.html +83 -0
  219. package/src/server/views/layout.html +199 -0
  220. package/src/server/views/summary.html +50 -0
  221. package/src/typings/hapi/index.d.ts +95 -0
  222. package/src/typings/hapi-tracing/index.d.ts +6 -0
  223. package/src/typings/index.d.ts +3 -0
  224. package/src/typings/joi/index.d.ts +22 -0
@@ -0,0 +1,76 @@
1
+ import { ComponentType, type ListComponent } from '@defra/forms-model'
2
+
3
+ import { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'
4
+ import { type Guidance } from '~/src/server/plugins/engine/components/helpers.js'
5
+ import { FormModel } from '~/src/server/plugins/engine/models/FormModel.js'
6
+ import definition from '~/test/form/definitions/basic.js'
7
+
8
+ describe('List', () => {
9
+ let model: FormModel
10
+
11
+ beforeEach(() => {
12
+ model = new FormModel(definition, {
13
+ basePath: 'test'
14
+ })
15
+ })
16
+
17
+ describe('Defaults', () => {
18
+ let def: ListComponent
19
+ let collection: ComponentCollection
20
+ let guidance: Guidance
21
+
22
+ beforeEach(() => {
23
+ def = {
24
+ title: 'List guidance',
25
+ name: 'myComponent',
26
+ type: ComponentType.List,
27
+ list: 'licenceLengthDays',
28
+ options: {}
29
+ } satisfies ListComponent
30
+
31
+ collection = new ComponentCollection([def], { model })
32
+ guidance = collection.guidance[0]
33
+ })
34
+
35
+ describe('View model', () => {
36
+ it('sets Nunjucks component defaults', () => {
37
+ const viewModel = guidance.getViewModel()
38
+
39
+ expect(viewModel).toEqual(
40
+ expect.objectContaining({
41
+ attributes: {},
42
+ content: {
43
+ title: def.title,
44
+ text: ''
45
+ }
46
+ })
47
+ )
48
+ })
49
+ })
50
+
51
+ describe('List items', () => {
52
+ it('returns list items', () => {
53
+ expect(guidance).toHaveProperty('items', [
54
+ {
55
+ text: '1 day',
56
+ value: 1,
57
+ description:
58
+ 'Valid for 24 hours from the start time that you select'
59
+ },
60
+ {
61
+ text: '8 day',
62
+ value: 8,
63
+ description:
64
+ 'Valid for 8 consecutive days from the start time that you select'
65
+ },
66
+ {
67
+ text: '12 months',
68
+ value: 365,
69
+ description:
70
+ '12-month licences are now valid for 365 days from their start date and can be purchased at any time during the year'
71
+ }
72
+ ])
73
+ })
74
+ })
75
+ })
76
+ })
@@ -0,0 +1,72 @@
1
+ import {
2
+ type Item,
3
+ type List as ListType,
4
+ type ListComponent
5
+ } from '@defra/forms-model'
6
+
7
+ import { ComponentBase } from '~/src/server/plugins/engine/components/ComponentBase.js'
8
+ import { type ListItem } from '~/src/server/plugins/engine/components/types.js'
9
+
10
+ export class List extends ComponentBase {
11
+ declare options: ListComponent['options']
12
+ hint: ListComponent['hint']
13
+ list?: ListType
14
+
15
+ get items(): Item[] {
16
+ return this.list?.items ?? []
17
+ }
18
+
19
+ constructor(
20
+ def: ListComponent,
21
+ props: ConstructorParameters<typeof ComponentBase>[1]
22
+ ) {
23
+ super(def, props)
24
+
25
+ const { hint, list, options } = def
26
+ const { model } = props
27
+
28
+ this.hint = hint
29
+ this.list = model.getList(list)
30
+ this.options = options
31
+ }
32
+
33
+ getViewModel() {
34
+ const { items: listItems, options, viewModel } = this
35
+
36
+ let { classes, content, items, type } = viewModel
37
+
38
+ if (options.type) {
39
+ type = options.type
40
+ }
41
+
42
+ if (options.bold) {
43
+ classes ??= ''
44
+ classes = `${classes} govuk-!-font-weight-bold`.trim()
45
+ }
46
+
47
+ content = {
48
+ title: !options.hideTitle ? this.title : undefined,
49
+ text: this.hint ?? ''
50
+ }
51
+
52
+ items = listItems.map((item) => {
53
+ const itemModel: ListItem = { ...item }
54
+
55
+ if (item.description) {
56
+ itemModel.hint = {
57
+ text: item.description
58
+ }
59
+ }
60
+
61
+ return itemModel
62
+ })
63
+
64
+ return {
65
+ ...viewModel,
66
+ type,
67
+ classes,
68
+ content,
69
+ items
70
+ }
71
+ }
72
+ }
@@ -0,0 +1,140 @@
1
+ import {
2
+ type Item,
3
+ type List,
4
+ type ListComponentsDef,
5
+ type SelectionComponentsDef,
6
+ type YesNoFieldComponent
7
+ } from '@defra/forms-model'
8
+ import joi, {
9
+ type ArraySchema,
10
+ type BooleanSchema,
11
+ type NumberSchema,
12
+ type StringSchema
13
+ } from 'joi'
14
+
15
+ import { FormComponent } from '~/src/server/plugins/engine/components/FormComponent.js'
16
+ import { type ListItem } from '~/src/server/plugins/engine/components/types.js'
17
+ import {
18
+ type FormPayload,
19
+ type FormSubmissionError,
20
+ type FormSubmissionState
21
+ } from '~/src/server/plugins/engine/types.js'
22
+
23
+ export class ListFormComponent extends FormComponent {
24
+ declare options: Extract<
25
+ SelectionComponentsDef,
26
+ { options: object }
27
+ >['options']
28
+
29
+ declare formSchema:
30
+ | ArraySchema<string>
31
+ | ArraySchema<number>
32
+ | BooleanSchema<string>
33
+ | NumberSchema<string>
34
+ | NumberSchema
35
+ | StringSchema
36
+
37
+ declare stateSchema:
38
+ | ArraySchema<string>
39
+ | ArraySchema<number>
40
+ | BooleanSchema<string>
41
+ | NumberSchema<string>
42
+ | NumberSchema
43
+ | StringSchema
44
+
45
+ list?: List
46
+ listType: List['type'] = 'string'
47
+
48
+ get items(): Item[] {
49
+ return this.list?.items ?? []
50
+ }
51
+
52
+ get values(): Item['value'][] {
53
+ return this.items.map(({ value }) => value)
54
+ }
55
+
56
+ constructor(
57
+ def:
58
+ | SelectionComponentsDef // Allow for Yes/No field custom list
59
+ | (YesNoFieldComponent & Pick<ListComponentsDef, 'list'>),
60
+ props: ConstructorParameters<typeof FormComponent>[1]
61
+ ) {
62
+ super(def, props)
63
+
64
+ const { options, title } = def
65
+ const { model } = props
66
+
67
+ if ('list' in def) {
68
+ this.list = model.getList(def.list)
69
+ this.listType = this.list?.type ?? 'string'
70
+ }
71
+
72
+ let formSchema = joi[this.listType]()
73
+ .valid(...this.values)
74
+ .label(title)
75
+ .required()
76
+
77
+ if (options.customValidationMessages) {
78
+ formSchema = formSchema.messages(options.customValidationMessages)
79
+ }
80
+
81
+ this.formSchema = formSchema
82
+ this.stateSchema = formSchema.default(null).allow(null)
83
+ this.options = options
84
+ }
85
+
86
+ getFormValueFromState(
87
+ state: FormSubmissionState
88
+ ): Item['value'] | Item['value'][] | undefined {
89
+ const { name, items } = this
90
+
91
+ const value = state[name]
92
+
93
+ // Allow for array values via subclass
94
+ const values = this.isValue(value) ? [value].flat() : []
95
+ const selected = items.filter((item) => values.includes(item.value))
96
+
97
+ return selected.at(0)?.value
98
+ }
99
+
100
+ getDisplayStringFromState(state: FormSubmissionState) {
101
+ const { items } = this
102
+
103
+ // Allow for array values via subclass
104
+ const value = this.getFormValueFromState(state)
105
+ const values = [value ?? []].flat()
106
+
107
+ return items
108
+ .filter((item) => values.includes(item.value))
109
+ .map((item) => item.text)
110
+ .join(', ')
111
+ }
112
+
113
+ getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {
114
+ const { items: listItems } = this
115
+
116
+ const viewModel = super.getViewModel(payload, errors)
117
+ const { value } = viewModel
118
+
119
+ // Support multiple values for checkboxes
120
+ const values = this.isValue(value) ? [value].flat() : []
121
+
122
+ const items = listItems.map((item) => {
123
+ const selected = values.includes(item.value)
124
+ const itemModel: ListItem = { ...item, selected }
125
+
126
+ if (item.description) {
127
+ itemModel.hint = {
128
+ text: item.description
129
+ }
130
+ }
131
+
132
+ return itemModel
133
+ })
134
+
135
+ return {
136
+ ...viewModel,
137
+ items
138
+ }
139
+ }
140
+ }