@iress-oss/ids-mcp-server 5.15.0 → 6.0.0-alpha.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.
Files changed (91) hide show
  1. package/package.json +28 -46
  2. package/generated/docs/components-alert-docs.md +0 -130
  3. package/generated/docs/components-autocomplete-docs.md +0 -754
  4. package/generated/docs/components-autocomplete-recipes-docs.md +0 -104
  5. package/generated/docs/components-badge-docs.md +0 -148
  6. package/generated/docs/components-button-docs.md +0 -362
  7. package/generated/docs/components-button-recipes-docs.md +0 -76
  8. package/generated/docs/components-buttongroup-docs.md +0 -310
  9. package/generated/docs/components-card-docs.md +0 -494
  10. package/generated/docs/components-card-recipes-docs.md +0 -89
  11. package/generated/docs/components-checkbox-docs.md +0 -193
  12. package/generated/docs/components-checkboxgroup-docs.md +0 -692
  13. package/generated/docs/components-checkboxgroup-recipes-docs.md +0 -119
  14. package/generated/docs/components-col-docs.md +0 -466
  15. package/generated/docs/components-combobox-docs.md +0 -1016
  16. package/generated/docs/components-container-docs.md +0 -91
  17. package/generated/docs/components-divider-docs.md +0 -176
  18. package/generated/docs/components-expander-docs.md +0 -215
  19. package/generated/docs/components-field-docs.md +0 -675
  20. package/generated/docs/components-filter-docs.md +0 -1109
  21. package/generated/docs/components-form-docs.md +0 -2410
  22. package/generated/docs/components-form-recipes-docs.md +0 -886
  23. package/generated/docs/components-hide-docs.md +0 -265
  24. package/generated/docs/components-icon-docs.md +0 -553
  25. package/generated/docs/components-inline-docs.md +0 -868
  26. package/generated/docs/components-input-docs.md +0 -335
  27. package/generated/docs/components-input-recipes-docs.md +0 -140
  28. package/generated/docs/components-inputcurrency-docs.md +0 -157
  29. package/generated/docs/components-inputcurrency-recipes-docs.md +0 -116
  30. package/generated/docs/components-label-docs.md +0 -135
  31. package/generated/docs/components-menu-docs.md +0 -704
  32. package/generated/docs/components-menu-menuitem-docs.md +0 -193
  33. package/generated/docs/components-modal-docs.md +0 -587
  34. package/generated/docs/components-navbar-docs.md +0 -291
  35. package/generated/docs/components-navbar-recipes-docs.md +0 -413
  36. package/generated/docs/components-panel-docs.md +0 -380
  37. package/generated/docs/components-placeholder-docs.md +0 -27
  38. package/generated/docs/components-popover-docs.md +0 -464
  39. package/generated/docs/components-popover-recipes-docs.md +0 -245
  40. package/generated/docs/components-progress-docs.md +0 -104
  41. package/generated/docs/components-provider-docs.md +0 -105
  42. package/generated/docs/components-radio-docs.md +0 -107
  43. package/generated/docs/components-radiogroup-docs.md +0 -683
  44. package/generated/docs/components-readonly-docs.md +0 -89
  45. package/generated/docs/components-richselect-docs.md +0 -2433
  46. package/generated/docs/components-row-docs.md +0 -877
  47. package/generated/docs/components-select-docs.md +0 -456
  48. package/generated/docs/components-skeleton-docs.md +0 -214
  49. package/generated/docs/components-skeleton-recipes-docs.md +0 -76
  50. package/generated/docs/components-skiplink-docs.md +0 -66
  51. package/generated/docs/components-slideout-docs.md +0 -538
  52. package/generated/docs/components-slider-docs.md +0 -346
  53. package/generated/docs/components-spinner-docs.md +0 -59
  54. package/generated/docs/components-stack-docs.md +0 -265
  55. package/generated/docs/components-table-ag-grid-docs.md +0 -1074
  56. package/generated/docs/components-table-docs.md +0 -1305
  57. package/generated/docs/components-tabset-docs.md +0 -341
  58. package/generated/docs/components-tabset-tab-docs.md +0 -86
  59. package/generated/docs/components-tag-docs.md +0 -115
  60. package/generated/docs/components-text-docs.md +0 -394
  61. package/generated/docs/components-toaster-docs.md +0 -345
  62. package/generated/docs/components-toaster-toast-docs.md +0 -157
  63. package/generated/docs/components-toggle-docs.md +0 -158
  64. package/generated/docs/components-tooltip-docs.md +0 -311
  65. package/generated/docs/components-validationmessage-docs.md +0 -241
  66. package/generated/docs/contact-us-docs.md +0 -27
  67. package/generated/docs/extensions-editor-docs.md +0 -288
  68. package/generated/docs/extensions-editor-recipes-docs.md +0 -39
  69. package/generated/docs/foundations-accessibility-docs.md +0 -62
  70. package/generated/docs/foundations-colours-docs.md +0 -257
  71. package/generated/docs/foundations-consistency-docs.md +0 -52
  72. package/generated/docs/foundations-content-docs.md +0 -23
  73. package/generated/docs/foundations-introduction-docs.md +0 -17
  74. package/generated/docs/foundations-principles-docs.md +0 -70
  75. package/generated/docs/foundations-typography-docs.md +0 -191
  76. package/generated/docs/foundations-user-experience-docs.md +0 -63
  77. package/generated/docs/foundations-visual-design-docs.md +0 -46
  78. package/generated/docs/frequently-asked-questions-docs.md +0 -53
  79. package/generated/docs/get-started-develop-docs.md +0 -209
  80. package/generated/docs/get-started-using-storybook-docs.md +0 -68
  81. package/generated/docs/guidelines.md +0 -812
  82. package/generated/docs/introduction-docs.md +0 -43
  83. package/generated/docs/patterns-loading-docs.md +0 -1304
  84. package/generated/docs/resources-changelog-docs.md +0 -6
  85. package/generated/docs/resources-code-katas-docs.md +0 -29
  86. package/generated/docs/resources-migration-guides-from-v4-to-v5-docs.md +0 -437
  87. package/generated/docs/themes-available-themes-docs.md +0 -66
  88. package/generated/docs/themes-introduction-docs.md +0 -121
  89. package/generated/docs/themes-tokens-docs.md +0 -1200
  90. package/generated/docs/versions-docs.md +0 -17
  91. /package/{LICENSE.txt → LICENSE} +0 -0
@@ -1,886 +0,0 @@
1
- [](#recipes)Recipes
2
- ===================
3
-
4
- [](#with-readonly-data)With readonly data
5
- -----------------------------------------
6
-
7
- You can use `IressForm` with readonly data by setting the `readonly` prop to `true` on controlled elements. This will disable those form controls, but will include the values in the form submission.
8
-
9
- Please take note of the following when displaying read only data.
10
-
11
- * It is best to keep readonly data in a separate section of the form, to further avoid confusion with editable fields.
12
-
13
- User Details
14
- ------------
15
-
16
- First Name
17
-
18
- Leia
19
-
20
- Last Name
21
-
22
- Skywalker
23
-
24
- * * *
25
-
26
- Email
27
-
28
- Submit
29
-
30
- Hide code
31
-
32
- \[data-radix-scroll-area-viewport\] { scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; } \[data-radix-scroll-area-viewport\]::-webkit-scrollbar { display: none; } :where(\[data-radix-scroll-area-viewport\]) { display: flex; flex-direction: column; align-items: stretch; } :where(\[data-radix-scroll-area-content\]) { flex-grow: 1; }
33
-
34
- export const WithReadonlyDataForm \= () \=> {
35
- const \[values, setValues\] \= useState<FieldValues\>({
36
- firstName: 'Leia',
37
- lastName: 'Skywalker',
38
- email: 'leia.skywalker@iress.com',
39
- });
40
- const \[preview, setPreview\] \= useState(false);
41
- return (
42
- <\>
43
- <IressForm
44
- onSubmit\={(data) \=> {
45
- setValues(data);
46
- setPreview(true);
47
- }}
48
- values\={values}
49
- \>
50
- <IressContainer\>
51
- <IressText element\="h2"\>User Details</IressText\>
52
- <IressStack gutter\="md"\>
53
- <IressRow gutter\="md"\>
54
- <IressCol\>
55
- <IressFormField
56
- name\="firstName"
57
- label\="First Name"
58
- render\={(controlledProps) \=> (
59
- <IressInput {...controlledProps} readOnly />
60
- )}
61
- />
62
- </IressCol\>
63
- <IressCol\>
64
- <IressFormField
65
- name\="lastName"
66
- label\="Last Name"
67
- render\={(controlledProps) \=> (
68
- <IressInput {...controlledProps} readOnly />
69
- )}
70
- />
71
- </IressCol\>
72
- </IressRow\>
73
- <IressDivider gutter\="none" />
74
- <IressRow\>
75
- <IressCol\>
76
- <IressFormField
77
- name\="email"
78
- label\="Email"
79
- render\={(controlledProps) \=> (
80
- <IressInput {...controlledProps} type\="email" />
81
- )}
82
- />
83
- </IressCol\>
84
- </IressRow\>
85
- <IressButton type\="submit" mode\="primary"\>
86
- Submit </IressButton\>
87
- </IressStack\>
88
- </IressContainer\>
89
- </IressForm\>
90
- <IressModal show\={!!preview} onShowChange\={(show) \=> setPreview(show)}\>
91
- <IressTable
92
- caption\="Submitted"
93
- rows\={Object.entries(values).map((entry) \=> ({
94
- name: entry\[0\],
95
- value: JSON.stringify(entry\[1\], null, 2),
96
- }))}
97
- />
98
- </IressModal\>
99
- </\>
100
- );
101
- };
102
-
103
- Copy
104
-
105
- [](#switching-between-readonly-and-edit-modes)Switching between readonly and edit modes
106
- ---------------------------------------------------------------------------------------
107
-
108
- It is recommended to use a button to toggle between read-only and editable input modes.
109
-
110
- Please take note of the following when switching between modes:
111
-
112
- * Switching is done on a per-section basis, not on a per-field basis.
113
- * When the user saves the data, it should switch back to read-only mode to avoid any confusion about whether the changes have been saved.
114
-
115
- User Details
116
- ------------
117
-
118
- First Name
119
-
120
- Leia
121
-
122
- Last Name
123
-
124
- Skywalker
125
-
126
- Email
127
-
128
- leia.skywalker@iress.com
129
-
130
- dependents
131
-
132
- 0
133
-
134
- Edit
135
-
136
- Hide code
137
-
138
- \[data-radix-scroll-area-viewport\] { scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; } \[data-radix-scroll-area-viewport\]::-webkit-scrollbar { display: none; } :where(\[data-radix-scroll-area-viewport\]) { display: flex; flex-direction: column; align-items: stretch; } :where(\[data-radix-scroll-area-content\]) { flex-grow: 1; }
139
-
140
- export const SwitchEditReadonlyForm \= () \=> {
141
- const dependentOptions \= \[
142
- { value: 0, label: '0' },
143
- { value: 1, label: '1' },
144
- { value: 2, label: '2' },
145
- { value: 3, label: '3' },
146
- { value: 4, label: '4' },
147
- { value: 5, label: '5' },
148
- { value: 6, label: '6' },
149
- { value: 7, label: '7' },
150
- { value: 8, label: '8' },
151
- { value: 9, label: '9' },
152
- { value: 10, label: '10' },
153
- \];
154
- const \[values, setValues\] \= useState<FieldValues\>({
155
- firstName: 'Leia',
156
- lastName: 'Skywalker',
157
- email: 'leia.skywalker@iress.com',
158
- dependents: 0,
159
- });
160
- const \[preview, setPreview\] \= useState(false);
161
- const \[editable, setEditable\] \= useState(false);
162
- return (
163
- <\>
164
- <IressForm
165
- onSubmit\={(data) \=> {
166
- setValues(data);
167
- setPreview(true);
168
- setEditable(false);
169
- }}
170
- values\={values}
171
- \>
172
- <IressContainer\>
173
- <IressStack gutter\="md"\>
174
- <IressText element\="h2"\>User Details</IressText\>
175
- <IressRow gutter\="md"\>
176
- <IressCol\>
177
- <IressFormField
178
- name\="firstName"
179
- label\="First Name"
180
- render\={(controlledProps) \=> (
181
- <IressInput {...controlledProps} readOnly\={!editable} />
182
- )}
183
- />
184
- </IressCol\>
185
- <IressCol\>
186
- <IressFormField
187
- name\="lastName"
188
- label\="Last Name"
189
- render\={(controlledProps) \=> (
190
- <IressInput {...controlledProps} readOnly\={!editable} />
191
- )}
192
- />
193
- </IressCol\>
194
- </IressRow\>
195
- <IressRow gutter\="md"\>
196
- <IressCol\>
197
- <IressFormField
198
- name\="email"
199
- label\="Email"
200
- render\={(controlledProps) \=> (
201
- <IressInput
202
- {...controlledProps}
203
- readOnly\={!editable}
204
- type\="email"
205
- />
206
- )}
207
- />
208
- </IressCol\>
209
- <IressCol\>
210
- <IressFormField
211
- name\="dependents"
212
- label\="dependents"
213
- render\={(controlledProps) \=> (
214
- <IressSelect
215
- {...controlledProps}
216
- readonly\={!editable}
217
- onChange\={(
218
- e: React.ChangeEvent<HTMLSelectElement\>,
219
- value?: FormControlValue,
220
- ) \=> controlledProps.onChange(value)}
221
- \>
222
- {dependentOptions.map((option) \=> (
223
- <option key\={option.value} value\={option.value}\>
224
- {option.label}
225
- </option\>
226
- ))}
227
- </IressSelect\>
228
- )}
229
- />
230
- </IressCol\>
231
- </IressRow\>
232
- {editable ? (
233
- <IressInline gutter\="sm"\>
234
- <IressButton type\="submit" mode\="primary"\>
235
- Save </IressButton\>
236
- <IressButton onClick\={() \=> setEditable(false)}\>
237
- Cancel </IressButton\>
238
- </IressInline\>
239
- ) : (
240
- <IressButton
241
- onClick\={() \=> setEditable(true)}
242
- prepend\={<IressIcon name\="pencil" />}
243
- \>
244
- Edit </IressButton\>
245
- )}
246
- </IressStack\>
247
- </IressContainer\>
248
- </IressForm\>
249
- <IressModal show\={!!preview} onShowChange\={(show) \=> setPreview(show)}\>
250
- <IressTable
251
- caption\="Submitted"
252
- rows\={Object.entries(values).map((entry) \=> ({
253
- name: entry\[0\],
254
- value: JSON.stringify(entry\[1\], null, 2),
255
- }))}
256
- />
257
- </IressModal\>
258
- </\>
259
- );
260
- };
261
-
262
- Copy
263
-
264
- [](#alternative-form-validation)Alternative form validation
265
- -----------------------------------------------------------
266
-
267
- `IressForm` is always recommended for all validation, as it is the cleanest way (least code) to provide the best form user experience for your users. Please visit the [`IressForm` documentation](./?path=/docs/components-form--docs) for different validation examples.
268
-
269
- However, if you have more complex requirements and you find `IressForm` too opinionated for your needs, you can always bring your own form validation using a native `form` element and the other IDS components such as `IressField`.
270
-
271
- Here is an example showcasing a form using the native form constraints API to achieve validation using IDS components. There are other libraries such as: [Yup](https://github.com/jquense/yup), [Joi](https://github.com/hapijs/joi) or [Zod](https://zod.dev/)) which can improve scalability, with the downside being you will have to maintain all validation yourself.
272
-
273
- **\*Required Name**
274
-
275
- **\*Required Email address**
276
-
277
- Sign up
278
-
279
- Hide code
280
-
281
- \[data-radix-scroll-area-viewport\] { scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; } \[data-radix-scroll-area-viewport\]::-webkit-scrollbar { display: none; } :where(\[data-radix-scroll-area-viewport\]) { display: flex; flex-direction: column; align-items: stretch; } :where(\[data-radix-scroll-area-content\]) { flex-grow: 1; }
282
-
283
- export const NativeValidationForm \= () \=> {
284
- const \[formData, setFormData\] \= useState({
285
- name: '',
286
- email: '',
287
- });
288
- const \[errors, setErrors\] \= useState<Record<string, boolean\>>({
289
- name: false,
290
- email: false,
291
- });
292
- const \[isSubmitted, setIsSubmitted\] \= useState(false);
293
- const hasErrors \= Object.values(errors).some((error) \=> !!error);
294
- const handleInputChange \= (e: React.ChangeEvent<InputBaseElement\>) \=> {
295
- setFormData({ ...formData, \[e.target.name\]: e.target.value });
296
- setErrors({
297
- ...errors,
298
- \[e.target.name\]: !e.currentTarget.reportValidity(),
299
- });
300
- };
301
- const handleSubmit \= (e: React.FormEvent<HTMLFormElement\>) \=> {
302
- e.preventDefault();
303
- const form \= e.currentTarget;
304
- setIsSubmitted(true);
305
- if (!form.checkValidity()) {
306
- const fieldData \= Object.fromEntries(new FormData(form).entries());
307
- const fieldNames \= Object.keys(fieldData);
308
- setErrors(
309
- fieldNames.reduce(
310
- (newErrors, fieldName) \=> {
311
- newErrors\[fieldName\] \= !form
312
- .querySelector<HTMLInputElement\>(\`\[name=${fieldName}\]\`)
313
- ?.checkValidity();
314
- return newErrors;
315
- },
316
- {} as Record<string, boolean\>,
317
- ),
318
- );
319
- }
320
- console.log(formData);
321
- };
322
- return (
323
- <form onSubmit\={handleSubmit} noValidate\>
324
- <IressStack gutter\="md"\>
325
- {isSubmitted && hasErrors && (
326
- <IressAlert status\="danger"\>
327
- There's a problem with your submission. </IressAlert\>
328
- )}
329
- <IressField
330
- label\="Name"
331
- error\={
332
- errors.name && (
333
- <IressValidationMessage\>Name is required</IressValidationMessage\>
334
- )
335
- }
336
- required
337
- \>
338
- <IressInput name\="name" onChange\={handleInputChange} required />
339
- </IressField\>
340
- <IressField
341
- label\="Email address"
342
- error\={
343
- errors.email && (
344
- <IressValidationMessage\>Email is required</IressValidationMessage\>
345
- )
346
- }
347
- required
348
- \>
349
- <IressInput name\="email" onChange\={handleInputChange} required />
350
- </IressField\>
351
- <IressButton mode\="primary" type\="submit"\>
352
- Sign up </IressButton\>
353
- </IressStack\>
354
- </form\>
355
- );
356
- };
357
-
358
- Copy
359
-
360
- [](#nested-forms)Nested forms
361
- -----------------------------
362
-
363
- Unfortunately, it is [forbidden to nest form elements as per the HTML specifications](https://developer.mozilla.org/en-US/docs/Learn/Forms/How_to_structure_a_web_form).
364
-
365
- To achieve a similar effect, you can use multiple `IressForm` components, and trigger validation in multiple ways:
366
-
367
- 1. You can trigger specific forms using the `form` attribute of `IressButton`. The [`form` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#form) allows you to specify the form ID to submit when the button is clicked, which can be any form on the page, and will take precedence over the parent form of a button.
368
- 2. If you need to trigger multiple forms, you can use the [`requestSubmit` method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/requestSubmit) on the form element to trigger the validation of multiple forms.
369
- 3. If you only want to trigger validation and not trigger submission even if the validation passes, you can use the `ref` attribute of `IressForm` and trigger validation manually using `ref.current?.api.trigger()`, which is based on the [React Hook Form API](https://react-hook-form.com/docs/useform/trigger).
370
-
371
- The example here showcases triggering validation using the `form` attribute of `IressButton` and the `requestSubmit` method on the form element.
372
-
373
- \*Required Name
374
-
375
- Add new dependant
376
-
377
- \*Required Name
378
-
379
- Save
380
-
381
- * * *
382
-
383
- Submit main formSubmit all forms
384
-
385
- Hide code
386
-
387
- \[data-radix-scroll-area-viewport\] { scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; } \[data-radix-scroll-area-viewport\]::-webkit-scrollbar { display: none; } :where(\[data-radix-scroll-area-viewport\]) { display: flex; flex-direction: column; align-items: stretch; } :where(\[data-radix-scroll-area-content\]) { flex-grow: 1; }
388
-
389
- interface FormData {
390
- name: string;
391
- }
392
- const MainForm \= () \=> {
393
- const \[details, setDetails\] \= useState<FormData | undefined\>();
394
- return (
395
- <\>
396
- <IressForm<FormData> errorSummaryHeading="Please correct the following errors for the main form" id="mainForm" onSubmit={(data) \=> {
397
- setDetails(data);
398
- }}
399
- > <IressFormField<FormData> name="name" label="Name" render={(controlledProps) \=> <IressInput {...controlledProps} />}
400
- rules={{ required: true }}
401
- /> </IressForm\>
402
- <IressModal
403
- show\={!!details}
404
- onShowChange\={(show) \=> !show && setDetails(undefined)}
405
- \>
406
- {details && (
407
- <IressTable
408
- caption\="Submitted main form"
409
- rows\={Object.entries(details).map((entry) \=> ({
410
- name: entry\[0\],
411
- value: JSON.stringify(entry\[1\], null, 2),
412
- }))}
413
- />
414
- )}
415
- </IressModal\>
416
- </\>
417
- );
418
- };
419
- const SubForm \= () \=> {
420
- const \[details, setDetails\] \= useState<FormData | undefined\>();
421
- return (
422
- <IressPanel\>
423
- <IressStack gutter\="md"\>
424
- <IressForm<FormData> errorSummaryHeading="Please correct the following errors found for the dependant" gutter="sm" id="subForm" onSubmit={(data) \=> {
425
- setDetails(data);
426
- }}
427
- > <IressFieldGroup label\="Add new dependant" inline\>
428
- <IressFormField
429
- name\="name"
430
- label\="Name"
431
- render\={(controlledProps) \=> <IressInput {...controlledProps} />}
432
- rules\={{ required: true }}
433
- />
434
- <IressButton type\="submit"\>Save</IressButton\>
435
- </IressFieldGroup\>
436
- </IressForm\>
437
- <IressTable
438
- caption\="Dependants"
439
- columns\={\[
440
- { key: 'name', label: 'Name' },
441
- { key: 'value', label: 'Value' },
442
- \]}
443
- rows\={Object.entries(details ?? {}).map((entry) \=> ({
444
- name: entry\[0\],
445
- value: JSON.stringify(entry\[1\], null, 2),
446
- }))}
447
- />
448
- </IressStack\>
449
- </IressPanel\>
450
- );
451
- };
452
- export const NestedFormsExample \= () \=> {
453
- const submitAllForms \= () \=> {
454
- document.querySelector<HTMLFormElement\>('\[id=mainForm\]')?.requestSubmit();
455
- document.querySelector<HTMLFormElement\>('\[id=subForm\]')?.requestSubmit();
456
- };
457
- return (
458
- <IressStack gutter\="md"\>
459
- <MainForm />
460
- <SubForm />
461
- <IressDivider />
462
- <IressInline gutter\="md"\>
463
- <IressButton type\="submit" form\="mainForm"\>
464
- Submit main form </IressButton\>
465
- <IressButton onClick\={submitAllForms}\>Submit all forms</IressButton\>
466
- </IressInline\>
467
- </IressStack\>
468
- );
469
- };
470
-
471
- Copy
472
-
473
- [](#form-groups)Form Groups
474
- ---------------------------
475
-
476
- Powered by [React Hook Form](https://react-hook-form.com/docs/usefieldarray)'s `useFieldArray`, this example allows you add/edit/delete multiple children sections within ONE form (not nested form).
477
-
478
- Form groups
479
- ===========
480
-
481
- This is one form with child sections (not nested forms). Play around to add/edit/delete child form sections:
482
-
483
- Client
484
- ------
485
-
486
- \*Required Name
487
-
488
- \*Required Salary
489
-
490
- \*Required Goal
491
-
492
- Dependant 1
493
- -----------
494
-
495
- \*Required Name
496
-
497
- \*Required Relationship
498
-
499
- \*Required Age
500
-
501
- Save
502
-
503
- Add Dependant
504
-
505
- * * *
506
-
507
- Submit All
508
-
509
- Hide code
510
-
511
- \[data-radix-scroll-area-viewport\] { scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; } \[data-radix-scroll-area-viewport\]::-webkit-scrollbar { display: none; } :where(\[data-radix-scroll-area-viewport\]) { display: flex; flex-direction: column; align-items: stretch; } :where(\[data-radix-scroll-area-content\]) { flex-grow: 1; }
512
-
513
- interface Client {
514
- name: string | undefined;
515
- salary: number | undefined;
516
- goal: string | undefined;
517
- }
518
- interface Dependant {
519
- name: string | undefined;
520
- relationship: string | undefined;
521
- age: number | undefined;
522
- }
523
- interface FormValues {
524
- client: Client;
525
- dependants: Dependant\[\];
526
- }
527
- interface ClientProps {
528
- control: Control<FormValues\> | undefined;
529
- }
530
- interface DependantProps {
531
- index: number;
532
- control: Control<FormValues\> | undefined;
533
- update: (index: number, data: Dependant) \=> void;
534
- remove: (index: number) \=> void;
535
- getValues: UseFormGetValues<FormValues\>;
536
- }
537
- const defaultValues \= {
538
- client: {
539
- name: '',
540
- salary: undefined,
541
- goal: '',
542
- },
543
- dependants: \[
544
- {
545
- name: '',
546
- relationship: '',
547
- age: undefined,
548
- },
549
- \],
550
- };
551
- const ClientSection: React.FC<ClientProps\> \= ({ control }) \=> {
552
- return (
553
- <IressFieldGroup label\={<IressText element\="h2"\>Client</IressText\>}\>
554
- <IressStack gutter\="md"\>
555
- <IressFormField
556
- name\="client.name"
557
- label\="Name"
558
- control\={control}
559
- render\={(controlledProps) \=> <IressInput {...controlledProps} />}
560
- rules\={{ required: true }}
561
- />
562
- <IressFormField
563
- name\="client.salary"
564
- label\="Salary"
565
- control\={control}
566
- render\={(controlledProps) \=> <IressInput {...controlledProps} />}
567
- rules\={{ required: true }}
568
- />
569
- <IressFormField
570
- name\="client.goal"
571
- label\="Goal"
572
- control\={control}
573
- render\={(controlledProps) \=> <IressInput {...controlledProps} />}
574
- rules\={{ required: true }}
575
- />
576
- </IressStack\>
577
- </IressFieldGroup\>
578
- );
579
- };
580
- const DependantSection: React.FC<DependantProps\> \= ({
581
- index,
582
- update,
583
- remove,
584
- control,
585
- getValues,
586
- }: DependantProps) \=> {
587
- return (
588
- <IressPanel\>
589
- <IressInline horizontalAlign\="right"\>
590
- <IressCloseButton onClick\={() \=> remove(index)} />
591
- </IressInline\>
592
- <IressStack gutter\="md"\>
593
- <IressFieldGroup
594
- label\={<IressText element\="h2"\>Dependant {index + 1}</IressText\>}
595
- \>
596
- <IressStack gutter\="md"\>
597
- <IressFormField
598
- name\={\`dependants.${index}.name\`}
599
- label\="Name"
600
- control\={control}
601
- render\={(controlledProps) \=> <IressInput {...controlledProps} />}
602
- rules\={{ required: true }}
603
- />
604
- <IressFormField
605
- name\={\`dependants.${index}.relationship\`}
606
- label\="Relationship"
607
- control\={control}
608
- render\={(controlledProps) \=> <IressInput {...controlledProps} />}
609
- rules\={{ required: true }}
610
- />
611
- <IressFormField
612
- name\={\`dependants.${index}.age\`}
613
- label\="Age"
614
- control\={control}
615
- render\={(controlledProps) \=> <IressInput {...controlledProps} />}
616
- rules\={{ required: true }}
617
- />
618
- <IressButton
619
- type\="button"
620
- prepend\={<IressIcon name\="check" />}
621
- onClick\={() \=> {
622
- const data \= getValues();
623
- const value \= data?.dependants\[index\];
624
- update(index, value);
625
- }}
626
- \>
627
- Save </IressButton\>
628
- </IressStack\>
629
- </IressFieldGroup\>
630
- </IressStack\>
631
- </IressPanel\>
632
- );
633
- };
634
- export const FormGroups \= () \=> {
635
- const form \= useForm<FormValues\>({
636
- defaultValues: defaultValues,
637
- mode: 'onBlur',
638
- });
639
- const { control, getValues } \= form;
640
- const { fields, append, update, remove } \= useFieldArray({
641
- name: 'dependants',
642
- control,
643
- });
644
- const onSubmit \= (data: FormValues) \=> console.log(data);
645
- return (
646
- <IressStack gutter\="md"\>
647
- <IressText element\="h1"\>Form groups</IressText\>
648
- <IressText element\="p"\>
649
- This is one form with child sections (not nested forms). Play around to add/edit/delete child form sections: </IressText\>
650
- <IressHookForm<FormValues> gutter="md" form={form}
651
- onSubmit={onSubmit}
652
- errorSummaryHeading="Please correct the following errors found for the form:" > <IressStack gutter\="md"\>
653
- <ClientSection control\={control} />
654
- {fields.map((field, index) \=> (
655
- <DependantSection
656
- key\={field.id}
657
- index\={index}
658
- control\={control}
659
- update\={update}
660
- remove\={remove}
661
- getValues\={getValues}
662
- />
663
- ))}
664
- <IressButton
665
- type\="button"
666
- prepend\={<IressIcon name\="plus" />}
667
- onClick\={() \=> {
668
- append({ name: '', relationship: '', age: undefined });
669
- }}
670
- \>
671
- Add Dependant </IressButton\>
672
- </IressStack\>
673
- <IressDivider />
674
- <IressButton type\="submit" mode\="primary"\>
675
- Submit All </IressButton\>
676
- </IressHookForm\>
677
- </IressStack\>
678
- );
679
- };
680
-
681
- Copy
682
-
683
- [](#hidden-inputs)Hidden inputs
684
- -------------------------------
685
-
686
- You can use hidden inputs to store data that you do not want to display to the user, but still need to include in the form submission. This is useful for storing metadata or other information that is not editable by the user.
687
-
688
- Warning
689
- -------
690
-
691
- This is not a recommended practice, as it can lead to security issues if sensitive data is stored in hidden inputs. It is better to use a variable to store your data, and include it in the form submission using the `onSubmit` handler.
692
-
693
- Visible Input
694
-
695
- Submit
696
-
697
- Hide code
698
-
699
- \[data-radix-scroll-area-viewport\] { scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; } \[data-radix-scroll-area-viewport\]::-webkit-scrollbar { display: none; } :where(\[data-radix-scroll-area-viewport\]) { display: flex; flex-direction: column; align-items: stretch; } :where(\[data-radix-scroll-area-content\]) { flex-grow: 1; }
700
-
701
- export const HiddenInputsForm \= () \=> {
702
- const form \= IressForm.useForm();
703
- const { register } \= form;
704
- // This is a hidden input field that the user cannot see or interact with.
705
- // This is the recommended way to handle hidden inputs in Iress forms.
706
- const hiddenInputStoredInVariable \= 'hiddenValue';
707
- return (
708
- <IressHookForm
709
- form\={form}
710
- onSubmit\={(data) \=> {
711
- console.log('Form submitted with data:', {
712
- ...data,
713
- hiddenInputStoredInVariable,
714
- });
715
- }}
716
- \>
717
- <IressStack gutter\="md"\>
718
- <IressFormField
719
- label\="Visible Input"
720
- name\="visibleInput"
721
- render\={(controlledProps) \=> <IressInput {...controlledProps} />}
722
- />
723
- {/\* Hidden field - NOT RECOMMENDED \*/}
724
- <input
725
- type\="hidden"
726
- {...register('hiddenField')} // Manually register the hidden field with react-hook-form
727
- value\="hiddenValue"
728
- />
729
- <IressButton type\="submit"\>Submit</IressButton\>
730
- </IressStack\>
731
- </IressHookForm\>
732
- );
733
- };
734
-
735
- Copy
736
-
737
- [](#validation-depend-on-other-fields)Validation depend on other fields
738
- -----------------------------------------------------------------------
739
-
740
- This example shows how to validate one field based on another field's value.
741
-
742
- The budget amount input validates against the selected budget range using the custom `validateBudgetInput` rules.
743
-
744
- Validation depend on other fields
745
- =================================
746
-
747
- This form demonstrates how to validate a field based on the value of another field. The budget amount field is validated against the selected budget range.
748
-
749
- \*Required Monthly investment budget
750
-
751
- Select your budget rangeLess than $499Between $500 to $999More than $1000
752
-
753
- \*Required Enter your budget amount ($)
754
-
755
- AUD
756
-
757
- Submit
758
-
759
- * * *
760
-
761
- Hide code
762
-
763
- \[data-radix-scroll-area-viewport\] { scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; } \[data-radix-scroll-area-viewport\]::-webkit-scrollbar { display: none; } :where(\[data-radix-scroll-area-viewport\]) { display: flex; flex-direction: column; align-items: stretch; } :where(\[data-radix-scroll-area-content\]) { flex-grow: 1; }
764
-
765
- interface FormData {
766
- primaryField: string;
767
- dependentField: string;
768
- }
769
- const budgetOptions \= \[
770
- { value: 'less-than-499', label: 'Less than $499' },
771
- { value: 'between-500-999', label: 'Between $500 to $999' },
772
- { value: 'more-than-1000', label: 'More than $1000' },
773
- \];
774
- const validateBudgetInput \= (
775
- value: string,
776
- selectedBudget: string,
777
- ): string | true \=> {
778
- if (!selectedBudget) return 'Select budget range first';
779
- const numericValue \= parseFloat(value);
780
- if (isNaN(numericValue)) return 'Enter a valid number';
781
- switch (selectedBudget) {
782
- case 'less-than-499':
783
- return numericValue < 499 || 'Must be less than $499';
784
- case 'between-500-999':
785
- return (
786
- (numericValue \>= 500 && numericValue <= 999) ||
787
- 'Must be between $500-$999'
788
- );
789
- case 'more-than-1000':
790
- return numericValue \> 1000 || 'Must be more than $1000';
791
- default:
792
- return true;
793
- }
794
- };
795
- export const ValidationDependOnOtherFields \= () \=> {
796
- const \[submitted, setSubmitted\] \= useState<FormData | undefined\>(undefined);
797
- const form \= IressForm.useForm<FormData\>({
798
- defaultValues: {
799
- primaryField: '',
800
- dependentField: '',
801
- },
802
- });
803
- const onSubmit \= (data: FormData) \=> {
804
- console.log(data);
805
- setSubmitted(data);
806
- };
807
- const onError \= (errors: Record<string, unknown\>) \=> {
808
- console.log('Form validation errors:', errors);
809
- };
810
- return (
811
- <\>
812
- <IressText element\="h1"\>Validation depend on other fields</IressText\>
813
- <IressText element\="p"\>
814
- This form demonstrates how to validate a field based on the value of another field. The budget amount field is validated against the selected budget range. </IressText\>
815
- <IressHookForm form\={form} onSubmit\={onSubmit} onError\={onError}\>
816
- <IressStack gutter\="md"\>
817
- <IressRow\>
818
- <IressCol\>
819
- <IressFormField
820
- name\="primaryField"
821
- label\="Monthly investment budget"
822
- rules\={{
823
- required: 'Budget range is required',
824
- }}
825
- render\={(field) \=> (
826
- <IressSelect
827
- {...field}
828
- placeholder\="Select your budget range"
829
- \>
830
- {budgetOptions.map((option) \=> (
831
- <option key\={option.value} value\={option.value}\>
832
- {option.label}
833
- </option\>
834
- ))}
835
- </IressSelect\>
836
- )}
837
- />
838
- </IressCol\>
839
- </IressRow\>
840
- <IressRow\>
841
- <IressCol\>
842
- <IressFormField
843
- name\="dependentField"
844
- label\="Enter your budget amount ($)"
845
- rules\={{
846
- required: 'Budget amount is required',
847
- validate: (value: string, formValues: FormData) \=>
848
- validateBudgetInput(value, formValues.primaryField),
849
- }}
850
- render\={(field) \=> (
851
- <IressInputCurrency {...field} type\="number" />
852
- )}
853
- />
854
- </IressCol\>
855
- </IressRow\>
856
- <IressButton type\="submit"\>Submit</IressButton\>
857
- </IressStack\>
858
- </IressHookForm\>
859
- <IressDivider />
860
- {submitted && (
861
- <IressStack gutter\="md"\>
862
- <IressText variant\="bold"\>Submitted Values:</IressText\>
863
- <IressText\>
864
- Budget Range:{' '}
865
- {budgetOptions.find(
866
- (option) \=> option.value \=== submitted.primaryField,
867
- )?.label ?? submitted.primaryField}
868
- </IressText\>
869
- <IressText\>Budget Amount: ${submitted.dependentField}</IressText\>
870
- </IressStack\>
871
- )}
872
- </\>
873
- );
874
- };
875
-
876
- Copy
877
-
878
- On this page
879
-
880
- * [With readonly data](#with-readonly-data)
881
- * [Switching between readonly and edit modes](#switching-between-readonly-and-edit-modes)
882
- * [Alternative form validation](#alternative-form-validation)
883
- * [Nested forms](#nested-forms)
884
- * [Form Groups](#form-groups)
885
- * [Hidden inputs](#hidden-inputs)
886
- * [Validation depend on other fields](#validation-depend-on-other-fields)