@defra/forms-model 3.0.502 → 3.0.503

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 (33) hide show
  1. package/dist/module/__stubs__/pages.js +14 -1
  2. package/dist/module/__stubs__/pages.js.map +1 -1
  3. package/dist/module/form/form-editor/preview/controller/guidance-page-controller.js +58 -0
  4. package/dist/module/form/form-editor/preview/controller/guidance-page-controller.js.map +1 -0
  5. package/dist/module/form/form-editor/preview/controller/page-controller-base.js +363 -0
  6. package/dist/module/form/form-editor/preview/controller/page-controller-base.js.map +1 -0
  7. package/dist/module/form/form-editor/preview/controller/page-controller.js +26 -265
  8. package/dist/module/form/form-editor/preview/controller/page-controller.js.map +1 -1
  9. package/dist/module/form/form-editor/preview/index.js +2 -0
  10. package/dist/module/form/form-editor/preview/index.js.map +1 -1
  11. package/dist/module/form/form-editor/preview/types.js.map +1 -1
  12. package/dist/module/pages/helpers.js +2 -1
  13. package/dist/module/pages/helpers.js.map +1 -1
  14. package/dist/types/__stubs__/pages.d.ts +14 -0
  15. package/dist/types/__stubs__/pages.d.ts.map +1 -1
  16. package/dist/types/form/form-editor/preview/controller/guidance-page-controller.d.ts +10 -0
  17. package/dist/types/form/form-editor/preview/controller/guidance-page-controller.d.ts.map +1 -0
  18. package/dist/types/form/form-editor/preview/controller/page-controller-base.d.ts +198 -0
  19. package/dist/types/form/form-editor/preview/controller/page-controller-base.d.ts.map +1 -0
  20. package/dist/types/form/form-editor/preview/controller/page-controller.d.ts +3 -150
  21. package/dist/types/form/form-editor/preview/controller/page-controller.d.ts.map +1 -1
  22. package/dist/types/form/form-editor/preview/index.d.ts +2 -0
  23. package/dist/types/form/form-editor/preview/types.d.ts +3 -1
  24. package/dist/types/form/form-editor/preview/types.d.ts.map +1 -1
  25. package/dist/types/pages/helpers.d.ts.map +1 -1
  26. package/package.json +1 -1
  27. package/src/__stubs__/pages.ts +20 -1
  28. package/src/form/form-editor/preview/controller/guidance-page-controller.js +64 -0
  29. package/src/form/form-editor/preview/controller/page-controller-base.js +388 -0
  30. package/src/form/form-editor/preview/controller/page-controller.js +28 -288
  31. package/src/form/form-editor/preview/index.js +2 -0
  32. package/src/form/form-editor/preview/types.ts +4 -1
  33. package/src/pages/helpers.ts +2 -1
@@ -0,0 +1,388 @@
1
+ import { ComponentType } from '~/src/components/enums.js'
2
+ import { HIGHLIGHT_CLASS } from '~/src/form/form-editor/preview/constants.js'
3
+ import { ContentElements } from '~/src/form/form-editor/preview/content.js'
4
+ import { Markdown } from '~/src/form/form-editor/preview/markdown.js'
5
+ import { hasComponents, hasRepeater } from '~/src/pages/helpers.js'
6
+
7
+ /**
8
+ * @type {QuestionRenderer}
9
+ */
10
+ const questionRenderer = {
11
+ /**
12
+ * @param {string} _questionTemplate
13
+ * @param {QuestionBaseModel} _questionBaseModel
14
+ */
15
+ render(_questionTemplate, _questionBaseModel) {
16
+ //
17
+ }
18
+ }
19
+ /**
20
+ * Enum for Highlight classes
21
+ * @readonly
22
+ * @enum {string}
23
+ */
24
+ const HighlightClass = {
25
+ TITLE: 'title',
26
+ GUIDANCE: 'guidance',
27
+ REPEATER: 'repeater'
28
+ }
29
+
30
+ /**
31
+ * @implements {PageOverviewElements}
32
+ */
33
+ export class PagePreviewElements {
34
+ /**
35
+ * @type {Page | { title: string }}
36
+ * @private
37
+ */
38
+ _page = {
39
+ title: ''
40
+ }
41
+
42
+ /**
43
+ * @param {Page|undefined} page
44
+ */
45
+ constructor(page) {
46
+ if (page !== undefined) {
47
+ this._page = page
48
+ }
49
+ }
50
+
51
+ get heading() {
52
+ return this._page.title
53
+ }
54
+
55
+ get guidance() {
56
+ if (!hasComponents(this._page) || !this._page.components.length) {
57
+ return ''
58
+ }
59
+
60
+ const [possibleGuidanceComponent] = this._page.components
61
+
62
+ return possibleGuidanceComponent.type === ComponentType.Markdown
63
+ ? possibleGuidanceComponent.content
64
+ : ''
65
+ }
66
+
67
+ get addHeading() {
68
+ return this._page.title.length > 0
69
+ }
70
+
71
+ get repeatQuestion() {
72
+ if (hasRepeater(this._page)) {
73
+ return this._page.repeat.options.title
74
+ }
75
+ return undefined
76
+ }
77
+
78
+ get hasRepeater() {
79
+ return hasRepeater(this._page)
80
+ }
81
+ }
82
+
83
+ /**
84
+ * @abstract
85
+ * @implements {PagePreviewPanelMacro}
86
+ */
87
+ export class PreviewPageControllerBase {
88
+ static PATH = 'preview-controllers/'
89
+ /**
90
+ * @type {string}
91
+ * @protected
92
+ */
93
+ _pageTemplate = PreviewPageControllerBase.PATH + 'page-controller.njk'
94
+ /**
95
+ * @protected
96
+ * @type {Question[]}
97
+ */
98
+ _components = []
99
+ /**
100
+ * @type {boolean}
101
+ * @protected
102
+ */
103
+ _showTitle = true
104
+ /**
105
+ * @protected
106
+ * @type {string}
107
+ */
108
+ _title = ''
109
+ /**
110
+ *
111
+ * @type {PageRenderer}
112
+ */
113
+ #pageRenderer
114
+ /**
115
+ * @type { undefined | HighlightClass }
116
+ * @protected
117
+ */
118
+ _highlighted = undefined
119
+ /**
120
+ * @type {string}
121
+ * @protected
122
+ */
123
+ _guidanceText = ''
124
+ /**
125
+ * @type { string }
126
+ * @protected
127
+ */
128
+ _sectionTitle = ''
129
+ /**
130
+ * @type {Markdown}
131
+ * @protected
132
+ */
133
+ _emptyGuidance = PreviewPageControllerBase.createGuidanceComponent()
134
+ /**
135
+ * @type {Markdown}
136
+ * @protected
137
+ */
138
+ _guidanceComponent = PreviewPageControllerBase.createGuidanceComponent()
139
+ /**
140
+ * @protected
141
+ * @type {boolean}
142
+ */
143
+ _isRepeater = false
144
+
145
+ /**
146
+ * @param {PagePreviewBaseElements} elements
147
+ * @param {PageRenderer} renderer
148
+ */
149
+ constructor(elements, renderer) {
150
+ this._guidanceText = elements.guidance
151
+ this.#pageRenderer = renderer
152
+ this._title = elements.heading
153
+ }
154
+
155
+ /**
156
+ * @type {typeof HighlightClass}
157
+ */
158
+ static HighlightClass = HighlightClass
159
+
160
+ /**
161
+ * @returns {Markdown[]}
162
+ * @protected
163
+ */
164
+ _getGuidanceComponents() {
165
+ if (this._guidanceText.length) {
166
+ return [this._guidanceComponent]
167
+ }
168
+ if (this._highlighted === 'guidance') {
169
+ return [this._emptyGuidance]
170
+ }
171
+ return []
172
+ }
173
+
174
+ /**
175
+ * @returns {Markdown[]}
176
+ * @protected
177
+ */
178
+ get _guidanceComponents() {
179
+ return this._getGuidanceComponents()
180
+ }
181
+
182
+ /**
183
+ * @returns {PagePreviewComponent[]}
184
+ */
185
+ get components() {
186
+ const componentsWithGuidance = /** @type {Question[]} */ ([
187
+ ...this._guidanceComponents,
188
+ ...this._components
189
+ ])
190
+
191
+ return componentsWithGuidance.map((component) => {
192
+ return {
193
+ model: component.renderInput,
194
+ questionType: component.componentType
195
+ }
196
+ })
197
+ }
198
+
199
+ /**
200
+ * @returns {string}
201
+ * @protected
202
+ */
203
+ _getGuidanceText() {
204
+ return this._guidanceText
205
+ }
206
+
207
+ set guidanceText(text) {
208
+ this._guidanceText = text
209
+ this._guidanceComponent.content = text
210
+ this.render()
211
+ }
212
+
213
+ /**
214
+ * @returns {string}
215
+ */
216
+ get guidanceText() {
217
+ return this._getGuidanceText()
218
+ }
219
+
220
+ get guidance() {
221
+ return {
222
+ text: this.guidanceText,
223
+ classes: this._isHighlighted(HighlightClass.GUIDANCE)
224
+ }
225
+ }
226
+
227
+ /**
228
+ * @param {boolean} showTitle
229
+ */
230
+ set showTitle(showTitle) {
231
+ this._showTitle = showTitle
232
+ this.render()
233
+ }
234
+
235
+ get showTitle() {
236
+ return this._showTitle
237
+ }
238
+
239
+ /**
240
+ * @returns {{ text: string, classes: string }}
241
+ */
242
+ get pageTitle() {
243
+ return {
244
+ text: this.title,
245
+ classes: this._isHighlighted(HighlightClass.TITLE)
246
+ }
247
+ }
248
+
249
+ setRepeater() {
250
+ this._isRepeater = true
251
+ this.render()
252
+ }
253
+
254
+ unsetRepeater() {
255
+ this._isRepeater = false
256
+ this.render()
257
+ }
258
+
259
+ get isRepeater() {
260
+ return this._isRepeater
261
+ }
262
+
263
+ render() {
264
+ this.#pageRenderer.render(this._pageTemplate, this)
265
+ }
266
+
267
+ /**
268
+ * @returns {string}
269
+ * @protected
270
+ */
271
+ _getTitle() {
272
+ if (this._title.length) {
273
+ return this._title
274
+ }
275
+ return 'Page heading'
276
+ }
277
+
278
+ /**
279
+ * @returns {string}
280
+ */
281
+ get title() {
282
+ return this._getTitle()
283
+ }
284
+
285
+ /**
286
+ * @param {string} value
287
+ */
288
+ set title(value) {
289
+ this._title = value
290
+ this.render()
291
+ }
292
+
293
+ highlightTitle() {
294
+ this.setHighLighted(HighlightClass.TITLE)
295
+ }
296
+
297
+ /**
298
+ * @returns {{classes: string, text: string} | undefined}
299
+ */
300
+ get sectionTitle() {
301
+ if (this.sectionTitleText === undefined) {
302
+ return undefined
303
+ }
304
+ return {
305
+ classes: this._isHighlighted(HighlightClass.REPEATER),
306
+ text: this.sectionTitleText
307
+ }
308
+ }
309
+
310
+ /**
311
+ * @returns {string|undefined}
312
+ * @protected
313
+ */
314
+ _getSectionTitleText() {
315
+ return this._sectionTitle
316
+ }
317
+
318
+ /**
319
+ * @param {string | undefined} val
320
+ */
321
+ set sectionTitleText(val) {
322
+ this._sectionTitle = val ?? ''
323
+ this.render()
324
+ }
325
+
326
+ get sectionTitleText() {
327
+ return this._getSectionTitleText()
328
+ }
329
+
330
+ /**
331
+ * Creates a dummy component for when guidance is highlighted
332
+ * but no guidance text exists
333
+ * @returns {Markdown}
334
+ */
335
+ static createGuidanceComponent(highlight = true) {
336
+ const guidanceElement = new ContentElements({
337
+ type: ComponentType.Markdown,
338
+ title: 'Guidance component',
339
+ name: 'guidanceComponent',
340
+ content: 'Guidance text',
341
+ options: {}
342
+ })
343
+ const guidanceComponent = new Markdown(guidanceElement, questionRenderer)
344
+
345
+ if (highlight) {
346
+ guidanceComponent.highlightContent()
347
+ }
348
+ return guidanceComponent
349
+ }
350
+
351
+ highlightGuidance() {
352
+ this._guidanceComponent.highlightContent()
353
+ this.setHighLighted(HighlightClass.GUIDANCE)
354
+ }
355
+
356
+ /**
357
+ * @param {HighlightClass} highlightSection
358
+ */
359
+ setHighLighted(highlightSection) {
360
+ this._highlighted = highlightSection
361
+ this.render()
362
+ }
363
+
364
+ clearHighlight() {
365
+ this._highlighted = undefined
366
+
367
+ this._guidanceComponent.unHighlightContent()
368
+ this.render()
369
+ }
370
+
371
+ /**
372
+ * @param {string} field
373
+ * @protected
374
+ * @returns {string}
375
+ */
376
+ _isHighlighted(field) {
377
+ return this._highlighted === field ? HIGHLIGHT_CLASS : ''
378
+ }
379
+ }
380
+
381
+ /**
382
+ * @import { PageRenderer, PageOverviewElements, PagePreviewBaseElements, QuestionRenderer, QuestionBaseModel } from '~/src/form/form-editor/preview/types.js'
383
+ * @import { Question } from '~/src/form/form-editor/preview/question.js'
384
+ * @import { PreviewComponent } from '~/src/form/form-editor/preview/preview.js'
385
+ * @import { FormDefinition, Page } from '~/src/form/form-definition/types.js'
386
+ * @import { ComponentDef, MarkdownComponent } from '~/src/components/types.js'
387
+ * @import { PagePreviewComponent, PagePreviewPanelMacro } from '~/src/form/form-editor/macros/types.js'
388
+ */