project-booster-vue 9.54.0 → 9.55.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 +1 -1
- package/src/components/rework/question/city-search/MPbCitySearch.vue +33 -52
- package/src/components/rework/question/name-input/MPbNameInput.stories.mdx +308 -0
- package/src/components/rework/question/name-input/MPbNameInput.vue +349 -0
- package/src/components/rework/question/name-input/NameInput.ts +22 -0
- package/src/components/rework/question/name-input/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-name-input-/360/237/246/240-101-sandbox-1-snap.png +0 -0
- package/src/components/rework/question/name-input/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-name-input-/360/237/246/240-showcase-feature-customize-1-snap.png +0 -0
- package/src/components/rework/question/name-input/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-name-input-/360/237/246/240-showcase-feature-optin-1-snap.png +0 -0
- package/src/components/rework/question/name-input/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-name-input-/360/237/246/240-showcase-feature-previous-value-from-answer-1-snap.png +0 -0
- package/src/components/rework/question/name-input/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-name-input-/360/237/246/240-showcase-feature-previous-value-from-answer-with-optin-1-snap.png +0 -0
- package/src/components/rework/question/name-input/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-name-input-/360/237/246/240-showcase-feature-previous-value-from-default-1-snap.png +0 -0
- package/src/components/rework/question/name-input/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-name-input-/360/237/246/240-showcase-feature-previous-value-from-default-with-optin-1-snap.png +0 -0
- package/src/components/rework/question/name-input/default-payload.json +13 -0
- package/src/components/rework/question/space-input/MPbSpaceInput.stories.mdx +297 -0
- package/src/components/rework/question/space-input/MPbSpaceInput.vue +511 -0
- package/src/components/rework/question/space-input/SpaceInput.ts +29 -0
- package/src/components/rework/question/space-input/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-space-input-/360/237/246/240-101-sandbox-1-snap.png +0 -0
- package/src/components/rework/question/space-input/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-space-input-/360/237/246/240-showcase-feature-custom-footer-1-snap.png +0 -0
- package/src/components/rework/question/space-input/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-space-input-/360/237/246/240-showcase-feature-customize-1-snap.png +0 -0
- package/src/components/rework/question/space-input/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-space-input-/360/237/246/240-showcase-feature-previous-value-from-answer-1-snap.png +0 -0
- package/src/components/rework/question/space-input/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-space-input-/360/237/246/240-showcase-feature-previous-value-from-default-1-snap.png +0 -0
- package/src/components/rework/question/space-input/__snapshots__/storyshots-puppeteer-test-puppeteer-ts-image-storyshots-project-booster-scenario-questions-pb-space-input-/360/237/246/240-showcase-feature-with-modal-1-snap.png +0 -0
- package/src/components/rework/question/space-input/default-payload.json +15 -0
- package/src/components/rework/ui/progress/MPbProgress.vue +4 -1
- package/src/components/scenario/PbScenario.vue +5 -0
- package/src/components/scenario/scenarii/floor-insulation.json +31 -13
- package/src/components/trezor/PbTrezor.vue +12 -2
- package/src/components/trezor/default-payload.json +1 -1
package/package.json
CHANGED
|
@@ -115,7 +115,7 @@ const BACK_ICON =
|
|
|
115
115
|
'https://storage.googleapis.com/project-booster-media/mozaic-icons/svg/Navigation_Arrow_Arrow--Left_16px.svg';
|
|
116
116
|
|
|
117
117
|
export default defineComponent({
|
|
118
|
-
name: '
|
|
118
|
+
name: 'PbCitySearch',
|
|
119
119
|
|
|
120
120
|
components: {
|
|
121
121
|
MFlex,
|
|
@@ -257,16 +257,12 @@ export default defineComponent({
|
|
|
257
257
|
updateHeaderHeight() {
|
|
258
258
|
this.headerHeight = this.$refs?.pbCitySearchHeader?.$el?.offsetHeight;
|
|
259
259
|
},
|
|
260
|
-
formatSuggestion(suggestion:
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
let text = '';
|
|
265
|
-
for (let i = 0; i < suggestion.terms.length - 1; i++) {
|
|
266
|
-
text = `${text} ${suggestion.terms[i].value}`;
|
|
267
|
-
}
|
|
268
|
-
return text;
|
|
260
|
+
formatSuggestion(suggestion: google.maps.places.AutocompletePrediction) {
|
|
261
|
+
let text = '';
|
|
262
|
+
for (let i = 0; i < suggestion.terms.length - 1; i++) {
|
|
263
|
+
text = `${text} ${suggestion.terms[i].value}`;
|
|
269
264
|
}
|
|
265
|
+
return text;
|
|
270
266
|
},
|
|
271
267
|
handleSearchKeywordChange() {
|
|
272
268
|
this.updateHeaderHeight();
|
|
@@ -293,39 +289,24 @@ export default defineComponent({
|
|
|
293
289
|
return;
|
|
294
290
|
}
|
|
295
291
|
|
|
296
|
-
|
|
297
|
-
this.
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
types: ['(regions)'],
|
|
304
|
-
componentRestrictions: {
|
|
305
|
-
country: 'fr',
|
|
306
|
-
},
|
|
307
|
-
};
|
|
308
|
-
|
|
309
|
-
this.googlePlacesAutocompleteService?.getPlacePredictions(request, (results, status) => {
|
|
310
|
-
this.loadingSuggestions = false;
|
|
311
|
-
this.displaySuggestions = true;
|
|
312
|
-
if (status === 'OK') {
|
|
313
|
-
this.suggestions = results;
|
|
314
|
-
} else if (status === 'ZERO_RESULTS') {
|
|
315
|
-
this.suggestions = null;
|
|
316
|
-
}
|
|
317
|
-
});
|
|
318
|
-
} else {
|
|
319
|
-
const results = await this.getPlaceFromGeoGouvAPI(this.searchKeyword);
|
|
292
|
+
const request = {
|
|
293
|
+
input: this.searchKeyword,
|
|
294
|
+
types: ['(regions)'],
|
|
295
|
+
componentRestrictions: {
|
|
296
|
+
country: 'fr',
|
|
297
|
+
},
|
|
298
|
+
};
|
|
320
299
|
|
|
300
|
+
try {
|
|
301
|
+
this.googlePlacesAutocompleteService?.getPlacePredictions(request, (results, status) => {
|
|
321
302
|
this.loadingSuggestions = false;
|
|
322
303
|
this.displaySuggestions = true;
|
|
323
|
-
if (
|
|
304
|
+
if (status === 'OK') {
|
|
324
305
|
this.suggestions = results;
|
|
325
|
-
} else {
|
|
306
|
+
} else if (status === 'ZERO_RESULTS') {
|
|
326
307
|
this.suggestions = null;
|
|
327
308
|
}
|
|
328
|
-
}
|
|
309
|
+
});
|
|
329
310
|
} catch (error) {
|
|
330
311
|
console.error(`Could not get city search suggestions for ${this.searchKeyword}`, error);
|
|
331
312
|
}
|
|
@@ -352,10 +333,14 @@ export default defineComponent({
|
|
|
352
333
|
const selectedCity = results[0];
|
|
353
334
|
this.suggestions = null;
|
|
354
335
|
|
|
355
|
-
const
|
|
356
|
-
|
|
336
|
+
const placeData = await this.getPlaceFromGeoGouvAPI(
|
|
337
|
+
selectedCity.geometry.location.lat(),
|
|
338
|
+
selectedCity.geometry.location.lng(),
|
|
339
|
+
);
|
|
357
340
|
|
|
358
|
-
const
|
|
341
|
+
const postalCode =
|
|
342
|
+
selectedCity.address_components.filter((field) => field.types.includes('postal_code'))[0]?.short_name ||
|
|
343
|
+
placeData.postalCode;
|
|
359
344
|
|
|
360
345
|
const region =
|
|
361
346
|
selectedCity.address_components.filter((field) => field.types.includes('administrative_area_level_1'))[0]
|
|
@@ -389,26 +374,22 @@ export default defineComponent({
|
|
|
389
374
|
],
|
|
390
375
|
});
|
|
391
376
|
},
|
|
392
|
-
async getPlaceFromGeoGouvAPI(
|
|
377
|
+
async getPlaceFromGeoGouvAPI(lat: number, lng: number) {
|
|
393
378
|
const placeData = await axios.get('https://geo.api.gouv.fr/communes', {
|
|
394
379
|
params: {
|
|
395
|
-
|
|
380
|
+
lat: lat,
|
|
381
|
+
lon: lng,
|
|
396
382
|
fields: 'nom,code,codesPostaux',
|
|
397
383
|
format: 'json',
|
|
398
384
|
geometry: 'centre',
|
|
399
385
|
},
|
|
400
386
|
});
|
|
401
|
-
let placeDataFormatted: any = [];
|
|
402
387
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
});
|
|
409
|
-
});
|
|
410
|
-
|
|
411
|
-
return placeDataFormatted;
|
|
388
|
+
return {
|
|
389
|
+
inseeCode: placeData.data[0].code,
|
|
390
|
+
postalCode: placeData.data[0].codesPostaux[0],
|
|
391
|
+
name: placeData.data[0].nom,
|
|
392
|
+
};
|
|
412
393
|
},
|
|
413
394
|
selectedCityToKeyword(): string {
|
|
414
395
|
return this.selectedCity?.postalCode + ' ' + this.selectedCity?.name + ', ' + this.selectedCity?.region;
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { nestedAppDecorator } from '../../../../../.storybook/nested-app-decorator';
|
|
2
|
+
import { Story, Preview, Meta, Props, ArgsTable, Source, Canvas } from '@storybook/addon-docs';
|
|
3
|
+
import MPbNameInput from './MPbNameInput';
|
|
4
|
+
import DEFAULT_PAYLOAD from './default-payload.json';
|
|
5
|
+
import dedent from 'ts-dedent';
|
|
6
|
+
|
|
7
|
+
<Meta
|
|
8
|
+
title="Project Booster/Rework/Questions/MPbNameInput 🦠"
|
|
9
|
+
component={MPbNameInput}
|
|
10
|
+
argTypes={{
|
|
11
|
+
'payload': {
|
|
12
|
+
table: {
|
|
13
|
+
defaultValue: {
|
|
14
|
+
summary: 'object',
|
|
15
|
+
detail: JSON.stringify(DEFAULT_PAYLOAD, null, ' '),
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
control: {
|
|
19
|
+
type: 'object',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
'dynamic event name according to completedEventName prop': {
|
|
23
|
+
table: {
|
|
24
|
+
defaultValue: {
|
|
25
|
+
summary: 'Event payload',
|
|
26
|
+
detail: JSON.stringify({ answers: [{ projectName: 'My project name', optin: false }] }, null, ' '),
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
'onStepCompleted': {
|
|
31
|
+
action: 'Step completed',
|
|
32
|
+
table: { disable: true },
|
|
33
|
+
},
|
|
34
|
+
}}
|
|
35
|
+
decorators={[
|
|
36
|
+
nestedAppDecorator(
|
|
37
|
+
{
|
|
38
|
+
actions: {
|
|
39
|
+
sendEventToBus({}, payload) {
|
|
40
|
+
console.log('Event sent to bus', payload);
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
[],
|
|
45
|
+
),
|
|
46
|
+
]}
|
|
47
|
+
parameters={{ layout: 'fullscreen' }}
|
|
48
|
+
/>
|
|
49
|
+
|
|
50
|
+
# 🦠 `MPbNameInput` - Components
|
|
51
|
+
|
|
52
|
+
[](https://github.com/adeo/project-booster-vue/tree/master/src/components/question)
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
The `MPbNameInput` Vue component allows to ask for a name. It
|
|
57
|
+
is customizable through the payload property. It has the same
|
|
58
|
+
behaviour as the `PbQuestion` component and is designed to work in scenarii.
|
|
59
|
+
|
|
60
|
+
It also provides the debrayable optin collect feature.
|
|
61
|
+
|
|
62
|
+
It has a default provided payload, used in the Sandbox below.
|
|
63
|
+
|
|
64
|
+
The input field is automatically focused.
|
|
65
|
+
|
|
66
|
+
The back button will make `vue-router` trigger the history back feature from the browser. It can be hidden with the
|
|
67
|
+
`showBackButton` flag.
|
|
68
|
+
|
|
69
|
+
# `MPbNameInput` - Component props
|
|
70
|
+
|
|
71
|
+
export const TemplateSandbox = (args, { argTypes }) => ({
|
|
72
|
+
props: Object.keys(argTypes),
|
|
73
|
+
components: { MPbNameInput },
|
|
74
|
+
setup() {
|
|
75
|
+
return { args };
|
|
76
|
+
},
|
|
77
|
+
template: `<m-pb-name-input :payload="args.payload" :show-back-button="args.showBackButton" :answers="args.answers" :runtime-options="args.runtimeOptions" :completed-event-name="args.completedEventName" @step-completed="args.onStepCompleted" />`,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
<Canvas>
|
|
81
|
+
<Story name="101 Sandbox" args={{ payload: DEFAULT_PAYLOAD }}>
|
|
82
|
+
{TemplateSandbox.bind({})}
|
|
83
|
+
</Story>
|
|
84
|
+
</Canvas>
|
|
85
|
+
|
|
86
|
+
<ArgsTable story="101 Sandbox" />
|
|
87
|
+
|
|
88
|
+
# `MPbNameInput` - Features
|
|
89
|
+
|
|
90
|
+
## Customization
|
|
91
|
+
|
|
92
|
+
It is possible to customize the component default behaviour by **overriding** a property in the provided `payload` property.
|
|
93
|
+
|
|
94
|
+
Here is the default payload:
|
|
95
|
+
|
|
96
|
+
<Source language="json" code={JSON.stringify(DEFAULT_PAYLOAD, null, ' ')} />
|
|
97
|
+
|
|
98
|
+
Here is the payload with overriden values:
|
|
99
|
+
|
|
100
|
+
export const overridenLabelsPayload = {
|
|
101
|
+
viewModel: {
|
|
102
|
+
backLabel: 'Retour',
|
|
103
|
+
label: 'Quelle est le montant de votre bien ?',
|
|
104
|
+
placeholder: 'Montant de votre bien',
|
|
105
|
+
actionLabel: 'Enregistrer',
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
<Source language="json" code={JSON.stringify(overridenLabelsPayload, null, ' ')} />
|
|
110
|
+
|
|
111
|
+
<Canvas>
|
|
112
|
+
<Story
|
|
113
|
+
name="Showcase - Feature customize"
|
|
114
|
+
parameters={{ controls: { disable: true } }}
|
|
115
|
+
args={{ payload: overridenLabelsPayload }}
|
|
116
|
+
>
|
|
117
|
+
{TemplateSandbox.bind({})}
|
|
118
|
+
</Story>
|
|
119
|
+
</Canvas>
|
|
120
|
+
|
|
121
|
+
## Optin management with runtime options
|
|
122
|
+
|
|
123
|
+
The optin toggle display is managed with the `runtimeOptions` property :
|
|
124
|
+
|
|
125
|
+
export const runtimeOptions = {
|
|
126
|
+
displayOptin: true,
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
<Source language="json" code={JSON.stringify(runtimeOptions, null, ' ')} />
|
|
130
|
+
|
|
131
|
+
<Canvas>
|
|
132
|
+
<Story
|
|
133
|
+
name="Showcase - Feature Optin"
|
|
134
|
+
parameters={{ controls: { disable: true } }}
|
|
135
|
+
args={{ runtimeOptions: runtimeOptions }}
|
|
136
|
+
>
|
|
137
|
+
{TemplateSandbox.bind({})}
|
|
138
|
+
</Story>
|
|
139
|
+
</Canvas>
|
|
140
|
+
|
|
141
|
+
## Value injection from a previous answer with default value fallback
|
|
142
|
+
|
|
143
|
+
It is possible to inject a value for the component from a previous answer. To do so, add a `value` to the component
|
|
144
|
+
`payload`. The value should have the same structure as the component anwser when completed (See event payload in the
|
|
145
|
+
[Sandbox story](#pbnameinput---component-props)) :
|
|
146
|
+
|
|
147
|
+
export const valuePayload = {
|
|
148
|
+
value: {
|
|
149
|
+
projectName: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForProjectName')}",
|
|
150
|
+
optin: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForOptin')}",
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
<Source language="json" code={JSON.stringify(valuePayload, null, ' ')} />
|
|
155
|
+
|
|
156
|
+
The `getAnswerValue` function allows to retrieve a value from one provided answer. To retrieve a value, the first
|
|
157
|
+
parameter is the answer Id, the second is an optionnal path to extract a spcific value.
|
|
158
|
+
|
|
159
|
+
A `defaultDecoratorValue` value can be added as a fallback when no previous answer is found. When no default value is provided and no answer
|
|
160
|
+
is found, the component value will be empty :
|
|
161
|
+
|
|
162
|
+
export const valueWithFallbackPayload = {
|
|
163
|
+
defaultDecoratorValue: {
|
|
164
|
+
projectName: 'Rénover la salle de bain',
|
|
165
|
+
optin: true,
|
|
166
|
+
},
|
|
167
|
+
value: {
|
|
168
|
+
projectName: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForProjectName') || defaultValue.projectName}",
|
|
169
|
+
optin: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForOptin') || defaultValue.optin}",
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
<Source language="json" code={JSON.stringify(valueWithFallbackPayload, null, ' ')} />
|
|
174
|
+
|
|
175
|
+
It will try to find a value in a previous answer for a question with id `LMFR_PREVIOUS_QUESTION`,
|
|
176
|
+
provided thanks to the `answers` prop. If no value is found, it will use the `defaultDecoratorValue` as a fallback.
|
|
177
|
+
|
|
178
|
+
export const previousAnswers = new Map(
|
|
179
|
+
Object.entries({
|
|
180
|
+
LMFR_PREVIOUS_QUESTION: [
|
|
181
|
+
{
|
|
182
|
+
pathForProjectName: 'Rénover la cuisine',
|
|
183
|
+
},
|
|
184
|
+
],
|
|
185
|
+
}),
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
<Source language="json" code={JSON.stringify(previousAnswers, null, ' ')} />
|
|
189
|
+
|
|
190
|
+
<Canvas>
|
|
191
|
+
<Story
|
|
192
|
+
name="Showcase - Feature previous value from answer with optin"
|
|
193
|
+
parameters={{ controls: { disable: true } }}
|
|
194
|
+
args={{
|
|
195
|
+
payload: valuePayload,
|
|
196
|
+
answers: previousAnswers,
|
|
197
|
+
}}
|
|
198
|
+
>
|
|
199
|
+
{TemplateSandbox.bind({})}
|
|
200
|
+
</Story>
|
|
201
|
+
</Canvas>
|
|
202
|
+
|
|
203
|
+
When no answer is found, the default value fallback is used:
|
|
204
|
+
|
|
205
|
+
<Canvas>
|
|
206
|
+
<Story
|
|
207
|
+
name="Showcase - Feature previous value from default with optin"
|
|
208
|
+
parameters={{ controls: { disable: true } }}
|
|
209
|
+
args={{ payload: valueWithFallbackPayload }}
|
|
210
|
+
>
|
|
211
|
+
{TemplateSandbox.bind({})}
|
|
212
|
+
</Story>
|
|
213
|
+
</Canvas>
|
|
214
|
+
|
|
215
|
+
With optin value :
|
|
216
|
+
|
|
217
|
+
`runtimeOptions` prop to add option :
|
|
218
|
+
|
|
219
|
+
<Source language="json" code={JSON.stringify(runtimeOptions, null, ' ')} />
|
|
220
|
+
|
|
221
|
+
`answers` prop to add a previous answer :
|
|
222
|
+
|
|
223
|
+
export const previousAnswersWithOptin = {
|
|
224
|
+
LMFR_PREVIOUS_QUESTION: [
|
|
225
|
+
{
|
|
226
|
+
pathForProjectName: 'Rénover la cuisine',
|
|
227
|
+
pathForOptin: true,
|
|
228
|
+
},
|
|
229
|
+
],
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
<Source language="json" code={JSON.stringify(previousAnswersWithOptin, null, ' ')} />
|
|
233
|
+
|
|
234
|
+
<Canvas>
|
|
235
|
+
<Story
|
|
236
|
+
name="Showcase - Feature previous value from answer"
|
|
237
|
+
parameters={{ controls: { disable: true } }}
|
|
238
|
+
args={{
|
|
239
|
+
payload: valuePayload,
|
|
240
|
+
answers: new Map(Object.entries(previousAnswersWithOptin)),
|
|
241
|
+
runtimeOptions: runtimeOptions,
|
|
242
|
+
}}
|
|
243
|
+
>
|
|
244
|
+
{TemplateSandbox.bind({})}
|
|
245
|
+
</Story>
|
|
246
|
+
</Canvas>
|
|
247
|
+
|
|
248
|
+
When no answer is found, the default value fallback is used:
|
|
249
|
+
|
|
250
|
+
export const valueWithFallbackPayloadAndOptin = {
|
|
251
|
+
defaultDecoratorValue: {
|
|
252
|
+
projectName: 'Rénover la salle de bain',
|
|
253
|
+
optin: true,
|
|
254
|
+
},
|
|
255
|
+
value: {
|
|
256
|
+
projectName: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForProjectName') || defaultValue.projectName}",
|
|
257
|
+
optin: "${getAnswerValue('LMFR_PREVIOUS_QUESTION', 'pathForOptin') || defaultValue.optin}",
|
|
258
|
+
},
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
<Source language="json" code={JSON.stringify(valueWithFallbackPayloadAndOptin, null, ' ')} />
|
|
262
|
+
|
|
263
|
+
<Canvas>
|
|
264
|
+
<Story
|
|
265
|
+
name="Showcase - Feature previous value from default"
|
|
266
|
+
parameters={{ controls: { disable: true } }}
|
|
267
|
+
args={{
|
|
268
|
+
payload: valueWithFallbackPayloadAndOptin,
|
|
269
|
+
runtimeOptions: runtimeOptions,
|
|
270
|
+
}}
|
|
271
|
+
>
|
|
272
|
+
{TemplateSandbox.bind({})}
|
|
273
|
+
</Story>
|
|
274
|
+
</Canvas>
|
|
275
|
+
|
|
276
|
+
## Custom validation
|
|
277
|
+
|
|
278
|
+
It is possible to customize the input field validation. To do so, provide a `validation` property to the `viewModel`.
|
|
279
|
+
|
|
280
|
+
The default `validation` object is:
|
|
281
|
+
|
|
282
|
+
<Source language="json" code={JSON.stringify(DEFAULT_PAYLOAD.viewModel.validation, null, ' ')} />
|
|
283
|
+
|
|
284
|
+
It is possible to customize those values:
|
|
285
|
+
|
|
286
|
+
export const customValidation = {
|
|
287
|
+
viewModel: {
|
|
288
|
+
validation: {
|
|
289
|
+
minLength: 5,
|
|
290
|
+
minErrorMessage: 'Plus de 5 caractères',
|
|
291
|
+
maxLength: 10,
|
|
292
|
+
maxErrorMessage: 'Moins de 10 caractères',
|
|
293
|
+
requiredErrorMessage: 'Champ obligatoire',
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
<Source language="json" code={JSON.stringify(customValidation, null, ' ')} />
|
|
299
|
+
|
|
300
|
+
<Canvas>
|
|
301
|
+
<Story
|
|
302
|
+
name="Showcase - Feature custom validation"
|
|
303
|
+
parameters={{ controls: { disable: true }, storyshots: { disable: true } }}
|
|
304
|
+
args={{ payload: customValidation }}
|
|
305
|
+
>
|
|
306
|
+
{TemplateSandbox.bind({})}
|
|
307
|
+
</Story>
|
|
308
|
+
</Canvas>
|