@iress-oss/ids-mcp-server 5.15.0 → 6.0.0-alpha.0

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 (104) hide show
  1. package/generated/docs/components-alert-docs.md +579 -7
  2. package/generated/docs/components-autocomplete-docs.md +694 -15
  3. package/generated/docs/components-autocomplete-recipes-docs.md +1 -1
  4. package/generated/docs/components-badge-docs.md +442 -59
  5. package/generated/docs/components-button-docs.md +1150 -70
  6. package/generated/docs/components-buttongroup-docs.md +441 -3
  7. package/generated/docs/components-card-docs.md +487 -37
  8. package/generated/docs/components-checkbox-docs.md +506 -5
  9. package/generated/docs/components-checkboxgroup-docs.md +586 -191
  10. package/generated/docs/components-checkboxgroup-recipes-docs.md +3 -3
  11. package/generated/docs/components-col-docs.md +451 -36
  12. package/generated/docs/components-container-docs.md +32 -0
  13. package/generated/docs/components-divider-docs.md +427 -27
  14. package/generated/docs/components-expander-docs.md +487 -108
  15. package/generated/docs/components-field-docs.md +1400 -68
  16. package/generated/docs/components-filter-docs.md +268 -55
  17. package/generated/docs/components-hide-docs.md +447 -10
  18. package/generated/docs/components-icon-docs.md +522 -259
  19. package/generated/docs/components-image-docs.md +493 -0
  20. package/generated/docs/components-inline-docs.md +1179 -44
  21. package/generated/docs/components-input-docs.md +544 -12
  22. package/generated/docs/components-input-recipes-docs.md +4 -4
  23. package/generated/docs/components-inputcurrency-docs.md +532 -0
  24. package/generated/docs/components-inputcurrency-recipes-docs.md +4 -5
  25. package/generated/docs/components-introduction-docs.md +450 -0
  26. package/generated/docs/components-label-docs.md +454 -27
  27. package/generated/docs/components-link-docs.md +586 -0
  28. package/generated/docs/components-menu-docs.md +531 -89
  29. package/generated/docs/components-menu-menuitem-docs.md +556 -10
  30. package/generated/docs/components-modal-docs.md +814 -55
  31. package/generated/docs/components-panel-docs.md +418 -198
  32. package/generated/docs/components-placeholder-docs.md +420 -1
  33. package/generated/docs/components-popover-docs.md +1097 -32
  34. package/generated/docs/components-popover-recipes-docs.md +39 -73
  35. package/generated/docs/components-progress-docs.md +464 -0
  36. package/generated/docs/components-provider-docs.md +57 -2
  37. package/generated/docs/components-radio-docs.md +460 -4
  38. package/generated/docs/components-radiogroup-docs.md +586 -116
  39. package/generated/docs/components-readonly-docs.md +450 -4
  40. package/generated/docs/components-richselect-docs.md +4660 -1257
  41. package/generated/docs/components-row-docs.md +2065 -588
  42. package/generated/docs/components-select-docs.md +489 -5
  43. package/generated/docs/components-skeleton-docs.md +399 -16
  44. package/generated/docs/components-skeleton-recipes-docs.md +7 -7
  45. package/generated/docs/components-skiplink-docs.md +548 -27
  46. package/generated/docs/components-slideout-docs.md +648 -150
  47. package/generated/docs/components-slider-docs.md +515 -33
  48. package/generated/docs/components-spinner-docs.md +393 -2
  49. package/generated/docs/components-stack-docs.md +732 -74
  50. package/generated/docs/components-table-ag-grid-docs.md +497 -127
  51. package/generated/docs/components-table-docs.md +1049 -27
  52. package/generated/docs/components-tabset-docs.md +454 -27
  53. package/generated/docs/components-tabset-tab-docs.md +464 -0
  54. package/generated/docs/components-tag-docs.md +452 -19
  55. package/generated/docs/components-text-docs.md +322 -131
  56. package/generated/docs/components-toaster-docs.md +463 -53
  57. package/generated/docs/components-toggle-docs.md +476 -20
  58. package/generated/docs/components-tooltip-docs.md +443 -7
  59. package/generated/docs/components-validationmessage-docs.md +933 -13
  60. package/generated/docs/extensions-editor-docs.md +906 -13
  61. package/generated/docs/extensions-editor-recipes-docs.md +51 -1
  62. package/generated/docs/foundations-accessibility-docs.md +1 -23
  63. package/generated/docs/foundations-grid-docs.md +74 -0
  64. package/generated/docs/foundations-introduction-docs.md +6 -4
  65. package/generated/docs/foundations-responsive-breakpoints-docs.md +193 -0
  66. package/generated/docs/foundations-tokens-colour-docs.md +564 -0
  67. package/generated/docs/foundations-tokens-elevation-docs.md +155 -0
  68. package/generated/docs/foundations-tokens-introduction-docs.md +190 -0
  69. package/generated/docs/foundations-tokens-radius-docs.md +71 -0
  70. package/generated/docs/foundations-tokens-spacing-docs.md +89 -0
  71. package/generated/docs/foundations-tokens-typography-docs.md +322 -0
  72. package/generated/docs/foundations-z-index-stacking-docs.md +31 -0
  73. package/generated/docs/guidelines.md +1537 -295
  74. package/generated/docs/introduction-docs.md +65 -21
  75. package/generated/docs/news-version-6-docs.md +93 -0
  76. package/generated/docs/patterns-form-docs.md +3902 -0
  77. package/generated/docs/patterns-form-recipes-docs.md +1370 -0
  78. package/generated/docs/patterns-introduction-docs.md +24 -0
  79. package/generated/docs/patterns-loading-docs.md +2940 -201
  80. package/generated/docs/resources-introduction-docs.md +38 -0
  81. package/generated/docs/resources-mcp-server-docs.md +27 -0
  82. package/generated/docs/styling-props-colour-docs.md +172 -0
  83. package/generated/docs/styling-props-elevation-docs.md +88 -0
  84. package/generated/docs/styling-props-radius-docs.md +86 -0
  85. package/generated/docs/styling-props-reference-docs.md +160 -0
  86. package/generated/docs/styling-props-screen-readers-docs.md +71 -0
  87. package/generated/docs/styling-props-sizing-docs.md +627 -0
  88. package/generated/docs/styling-props-spacing-docs.md +2282 -0
  89. package/generated/docs/styling-props-typography-docs.md +121 -0
  90. package/generated/docs/themes-available-themes-docs.md +29 -29
  91. package/generated/docs/themes-introduction-docs.md +1 -1
  92. package/package.json +3 -22
  93. package/generated/docs/components-button-recipes-docs.md +0 -76
  94. package/generated/docs/components-card-recipes-docs.md +0 -89
  95. package/generated/docs/components-combobox-docs.md +0 -1016
  96. package/generated/docs/components-form-docs.md +0 -2410
  97. package/generated/docs/components-form-recipes-docs.md +0 -886
  98. package/generated/docs/components-navbar-docs.md +0 -291
  99. package/generated/docs/components-navbar-recipes-docs.md +0 -413
  100. package/generated/docs/components-toaster-toast-docs.md +0 -157
  101. package/generated/docs/foundations-colours-docs.md +0 -257
  102. package/generated/docs/foundations-typography-docs.md +0 -191
  103. package/generated/docs/resources-changelog-docs.md +0 -6
  104. package/generated/docs/themes-tokens-docs.md +0 -1200
@@ -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)