@iress-oss/ids-mcp-server 0.0.1 → 5.14.2

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 (122) hide show
  1. package/LICENSE.txt +201 -0
  2. package/README.md +29 -159
  3. package/dist/componentHandlers.js +241 -0
  4. package/dist/componentHandlers.test.js +380 -0
  5. package/{build → dist}/config.js +5 -5
  6. package/dist/index.js +53 -0
  7. package/{build → dist}/iressHandlers.js +52 -46
  8. package/dist/iressHandlers.test.js +316 -0
  9. package/{build → dist}/resourceHandlers.js +23 -22
  10. package/dist/resourceHandlers.test.js +352 -0
  11. package/{build → dist}/searchHandlers.js +107 -92
  12. package/dist/searchHandlers.test.js +524 -0
  13. package/{build → dist}/toolHandler.js +13 -13
  14. package/dist/toolHandler.test.js +369 -0
  15. package/dist/tools.js +165 -0
  16. package/{build → dist}/utils.js +11 -15
  17. package/dist/utils.test.js +286 -0
  18. package/{docs/ids → generated/docs}/components-autocomplete-docs.md +3 -3
  19. package/{docs/ids → generated/docs}/components-autocomplete-recipes-docs.md +17 -51
  20. package/{docs/ids → generated/docs}/components-card-recipes-docs.md +1 -1
  21. package/{docs/ids → generated/docs}/components-checkbox-docs.md +6 -19
  22. package/{docs/ids → generated/docs}/components-checkboxgroup-docs.md +18 -18
  23. package/{docs/ids → generated/docs}/components-checkboxgroup-recipes-docs.md +9 -9
  24. package/{docs/ids → generated/docs}/components-col-docs.md +1 -1
  25. package/{docs/ids → generated/docs}/components-combobox-docs.md +4 -4
  26. package/{docs/ids → generated/docs}/components-container-docs.md +8 -42
  27. package/{docs/ids → generated/docs}/components-filter-docs.md +14 -67
  28. package/{docs/ids → generated/docs}/components-form-docs.md +341 -335
  29. package/{docs/ids → generated/docs}/components-form-recipes-docs.md +198 -1
  30. package/{docs/ids → generated/docs}/components-hide-docs.md +16 -70
  31. package/{docs/ids → generated/docs}/components-icon-docs.md +4 -4
  32. package/{docs/ids → generated/docs}/components-input-recipes-docs.md +2 -2
  33. package/{docs/ids → generated/docs}/components-inputcurrency-recipes-docs.md +6 -40
  34. package/{docs/ids → generated/docs}/components-modal-docs.md +3 -113
  35. package/generated/docs/components-popover-docs.md +464 -0
  36. package/{docs/ids → generated/docs}/components-radiogroup-docs.md +21 -21
  37. package/{docs/ids → generated/docs}/components-richselect-docs.md +149 -111
  38. package/{docs/ids → generated/docs}/components-row-docs.md +4 -4
  39. package/{docs/ids → generated/docs}/components-skeleton-docs.md +3 -3
  40. package/{docs/ids → generated/docs}/components-skeleton-recipes-docs.md +1 -1
  41. package/{docs/ids → generated/docs}/components-skiplink-docs.md +1 -1
  42. package/{docs/ids → generated/docs}/components-slideout-docs.md +3 -113
  43. package/{docs/ids → generated/docs}/components-table-ag-grid-docs.md +109 -137
  44. package/{docs/ids → generated/docs}/components-table-docs.md +92 -597
  45. package/{docs/ids → generated/docs}/components-tabset-docs.md +2 -2
  46. package/{docs/ids → generated/docs}/components-tag-docs.md +1 -1
  47. package/{docs/ids → generated/docs}/components-toaster-docs.md +5 -5
  48. package/{docs/ids → generated/docs}/extensions-editor-docs.md +4 -4
  49. package/generated/docs/foundations-accessibility-docs.md +62 -0
  50. package/{docs/ids → generated/docs}/foundations-colours-docs.md +1 -1
  51. package/generated/docs/foundations-consistency-docs.md +52 -0
  52. package/generated/docs/foundations-content-docs.md +23 -0
  53. package/generated/docs/foundations-introduction-docs.md +17 -0
  54. package/generated/docs/foundations-principles-docs.md +70 -0
  55. package/{docs/ids → generated/docs}/foundations-typography-docs.md +7 -2
  56. package/generated/docs/foundations-user-experience-docs.md +63 -0
  57. package/generated/docs/foundations-visual-design-docs.md +46 -0
  58. package/{docs/ids → generated/docs}/get-started-develop-docs.md +3 -3
  59. package/generated/docs/guidelines.md +812 -0
  60. package/{docs/ids → generated/docs}/introduction-docs.md +4 -4
  61. package/{docs/ids → generated/docs}/patterns-loading-docs.md +332 -2
  62. package/generated/docs/resources-migration-guides-from-v4-to-v5-docs.md +437 -0
  63. package/generated/docs/themes-available-themes-docs.md +66 -0
  64. package/generated/docs/themes-tokens-docs.md +1200 -0
  65. package/generated/docs/versions-docs.md +17 -0
  66. package/package.json +42 -14
  67. package/LICENSE +0 -193
  68. package/build/componentHandlers.js +0 -205
  69. package/build/index.js +0 -51
  70. package/build/tools.js +0 -165
  71. package/docs/api-reference.md +0 -0
  72. package/docs/best-practices.md +0 -0
  73. package/docs/configuration.md +0 -0
  74. package/docs/examples.md +0 -0
  75. package/docs/guidelines.md +0 -269
  76. package/docs/ids/components-popover-docs.md +0 -4
  77. package/docs/ids/resources-migration-guides-from-v4-to-v5-docs.md +0 -639
  78. package/docs/ids/themes-available-themes-docs.md +0 -74
  79. package/docs/ids/themes-tokens-docs.md +0 -4580
  80. package/docs/ids/versions-docs.md +0 -27
  81. package/docs/tutorials/basic-integration.md +0 -0
  82. /package/{build → dist}/types.js +0 -0
  83. /package/{docs/ids → generated/docs}/components-alert-docs.md +0 -0
  84. /package/{docs/ids → generated/docs}/components-badge-docs.md +0 -0
  85. /package/{docs/ids → generated/docs}/components-button-docs.md +0 -0
  86. /package/{docs/ids → generated/docs}/components-button-recipes-docs.md +0 -0
  87. /package/{docs/ids → generated/docs}/components-buttongroup-docs.md +0 -0
  88. /package/{docs/ids → generated/docs}/components-card-docs.md +0 -0
  89. /package/{docs/ids → generated/docs}/components-divider-docs.md +0 -0
  90. /package/{docs/ids → generated/docs}/components-expander-docs.md +0 -0
  91. /package/{docs/ids → generated/docs}/components-field-docs.md +0 -0
  92. /package/{docs/ids → generated/docs}/components-inline-docs.md +0 -0
  93. /package/{docs/ids → generated/docs}/components-input-docs.md +0 -0
  94. /package/{docs/ids → generated/docs}/components-inputcurrency-docs.md +0 -0
  95. /package/{docs/ids → generated/docs}/components-label-docs.md +0 -0
  96. /package/{docs/ids → generated/docs}/components-menu-docs.md +0 -0
  97. /package/{docs/ids → generated/docs}/components-menu-menuitem-docs.md +0 -0
  98. /package/{docs/ids → generated/docs}/components-navbar-docs.md +0 -0
  99. /package/{docs/ids → generated/docs}/components-navbar-recipes-docs.md +0 -0
  100. /package/{docs/ids → generated/docs}/components-panel-docs.md +0 -0
  101. /package/{docs/ids → generated/docs}/components-placeholder-docs.md +0 -0
  102. /package/{docs/ids → generated/docs}/components-popover-recipes-docs.md +0 -0
  103. /package/{docs/ids → generated/docs}/components-progress-docs.md +0 -0
  104. /package/{docs/ids → generated/docs}/components-radio-docs.md +0 -0
  105. /package/{docs/ids → generated/docs}/components-readonly-docs.md +0 -0
  106. /package/{docs/ids → generated/docs}/components-select-docs.md +0 -0
  107. /package/{docs/ids → generated/docs}/components-slider-docs.md +0 -0
  108. /package/{docs/ids → generated/docs}/components-spinner-docs.md +0 -0
  109. /package/{docs/ids → generated/docs}/components-stack-docs.md +0 -0
  110. /package/{docs/ids → generated/docs}/components-tabset-tab-docs.md +0 -0
  111. /package/{docs/ids → generated/docs}/components-text-docs.md +0 -0
  112. /package/{docs/ids → generated/docs}/components-toaster-toast-docs.md +0 -0
  113. /package/{docs/ids → generated/docs}/components-toggle-docs.md +0 -0
  114. /package/{docs/ids → generated/docs}/components-tooltip-docs.md +0 -0
  115. /package/{docs/ids → generated/docs}/components-validationmessage-docs.md +0 -0
  116. /package/{docs/ids → generated/docs}/contact-us-docs.md +0 -0
  117. /package/{docs/ids → generated/docs}/extensions-editor-recipes-docs.md +0 -0
  118. /package/{docs/ids → generated/docs}/frequently-asked-questions-docs.md +0 -0
  119. /package/{docs/ids → generated/docs}/get-started-using-storybook-docs.md +0 -0
  120. /package/{docs/ids → generated/docs}/resources-changelog-docs.md +0 -0
  121. /package/{docs/ids → generated/docs}/resources-code-katas-docs.md +0 -0
  122. /package/{docs/ids → generated/docs}/themes-introduction-docs.md +0 -0
@@ -68,231 +68,7 @@ Mode
68
68
 
69
69
  DiffOldNew
70
70
 
71
- \-
72
-
73
- import { IressForm, IressField, IressInput, IressCheckboxGroup, IressCheckbox } from '@iress/components';
74
-
75
- +
76
-
77
- import { IressForm, IressFormField, IressInput, IressCheckboxGroup, IressCheckbox } from '@iress/ids-components';
78
-
79
- \-
80
-
81
- export const App = () => {
82
-
83
- +
84
-
85
- const ConditionalFields = () => {
86
-
87
- \-
88
-
89
- // We need to create our own state to manage the visibility of the fields,
90
-
91
- +
92
-
93
- // Instead of creating our own state, we can now use the form state via the useWatch hook,
94
-
95
- \-
96
-
97
- // which means we have two sources of truth potentially making our code harder to maintain
98
-
99
- +
100
-
101
- // meaning we still have a single source of truth
102
-
103
- \-
104
-
105
- const \[show, setShow\] = useState(\['name'\]);
106
-
107
- +
108
-
109
- const show = IressForm.useWatch({ name: 'show'});
110
-
111
- return (
112
-
113
- \-
114
-
115
- <IressForm>
116
-
117
- +
118
-
119
- <>
120
-
121
- \-
122
-
123
- <IressField label="Show fields">
124
-
125
- +
126
-
127
- <IressFormField
128
-
129
- \-
130
-
131
- <IressCheckboxGroup value={show} onChange={(newValues) => setShow(newValues)}>
132
-
133
- +
134
-
135
- label="Show fields"
136
-
137
- +
138
-
139
- name="show"
140
-
141
- +
142
-
143
- render={(controlledProps) => (
144
-
145
- +
146
-
147
- <IressCheckboxGroup {...controlledProps}>
148
-
149
- <IressCheckbox value="name">Name</IressCheckbox>
150
-
151
- <IressCheckbox value="email">Email</IressCheckbox>
152
-
153
- </IressCheckboxGroup>
154
-
155
- \-
156
-
157
- </IressField>
158
-
159
- +
160
-
161
- )}
162
-
163
- \-
164
-
165
- {show.includes('name') && (
166
-
167
- +
168
-
169
- />
170
-
171
- \-
172
-
173
- <IressField label="Name">
174
-
175
- +
176
-
177
- {show?.includes('name') && (
178
-
179
- \-
180
-
181
- <IressInput name="name" />
182
-
183
- +
184
-
185
- <IressFormField
186
-
187
- \-
188
-
189
- </IressField>
190
-
191
- +
192
-
193
- label="Name"
194
-
195
- \-
196
-
197
- )}
198
-
199
- +
200
-
201
- name="name"
202
-
203
- \-
204
-
205
- {show.includes('email') && (
206
-
207
- +
208
-
209
- render={(controlledProps) => <IressInput {...controlledProps} />}
210
-
211
- \-
212
-
213
- <IressField label="Email">
214
-
215
- +
216
-
217
- />
218
-
219
- \-
220
-
221
- <IressInput name="email" type="email" />
222
-
223
- +
224
-
225
- )}
226
-
227
- \-
228
-
229
- </IressField>
230
-
231
- +
232
-
233
- {show?.includes('email') && (
234
-
235
- \-
236
-
237
- )}
238
-
239
- +
240
-
241
- <IressFormField
242
-
243
- \-
244
-
245
- </IressForm>
246
-
247
- +
248
-
249
- label="Email"
250
-
251
- +
252
-
253
- name="email"
254
-
255
- +
256
-
257
- render={(controlledProps) => <IressInput {...controlledProps} type="email" />}
258
-
259
- +
260
-
261
- />
262
-
263
- +
264
-
265
- )}
266
-
267
- +
268
-
269
- </>
270
-
271
- );
272
-
273
- };
274
-
275
- +
276
-
277
- +
278
-
279
- export const App = () => (
280
-
281
- +
282
-
283
- <IressForm defaultValues={{ show: \['name'\] }}>
284
-
285
- +
286
-
287
- <ConditionalFields />
288
-
289
- +
290
-
291
- </IressForm>
292
-
293
- +
294
-
295
- );
71
+ <table class="css-1n5o7vh-diff-container"><tbody><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text">import { IressForm, IressField, IressInput, IressCheckboxGroup, IressCheckbox } from '@iress/components';</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text">import { IressForm, IressFormField, IressInput, IressCheckboxGroup, IressCheckbox } from '@iress-oss/ids-components';</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-10regm7-empty-line"><pre></pre></td><td class="css-vl0irh-content css-10regm7-empty-line"><pre class="css-o1u8iu-content-text"></pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-10regm7-empty-line"><pre></pre></td><td class="css-vl0irh-content css-10regm7-empty-line"><pre class="css-o1u8iu-content-text"></pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text">export const App = () =&gt; {</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text">const ConditionalFields = () =&gt; {</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> // We need to create our own state to manage the visibility of the fields, </pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> // Instead of creating our own state, we can now use the form state via the useWatch hook, </pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> // which means we have two sources of truth potentially making our code harder to maintain</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> // meaning we still have a single source of truth</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> const [show, setShow] = useState(['name']);</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> const show = IressForm.useWatch({ name: 'show'});</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-10regm7-empty-line"><pre></pre></td><td class="css-vl0irh-content css-10regm7-empty-line"><pre class="css-o1u8iu-content-text"></pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker"><pre></pre></td><td class="css-vl0irh-content"><pre class="css-o1u8iu-content-text"> return (</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> &lt;IressForm&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> &lt;&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> &lt;IressField label="Show fields"&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> &lt;IressFormField </pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> &lt;IressCheckboxGroup value={show} onChange={(newValues) =&gt; setShow(newValues)}&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> label="Show fields" </pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> name="show"</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> render={(controlledProps) =&gt; (</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> &lt;IressCheckboxGroup {...controlledProps}&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker"><pre></pre></td><td class="css-vl0irh-content"><pre class="css-o1u8iu-content-text"> &lt;IressCheckbox value="name"&gt;Name&lt;/IressCheckbox&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker"><pre></pre></td><td class="css-vl0irh-content"><pre class="css-o1u8iu-content-text"> &lt;IressCheckbox value="email"&gt;Email&lt;/IressCheckbox&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker"><pre></pre></td><td class="css-vl0irh-content"><pre class="css-o1u8iu-content-text"> &lt;/IressCheckboxGroup&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> &lt;/IressField&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> )}</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> {show.includes('name') &amp;&amp; (</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> /&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> &lt;IressField label="Name"&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> {show?.includes('name') &amp;&amp; (</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> &lt;IressInput name="name" /&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> &lt;IressFormField </pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> &lt;/IressField&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> label="Name" </pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> )}</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> name="name"</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> {show.includes('email') &amp;&amp; (</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> render={(controlledProps) =&gt; &lt;IressInput {...controlledProps} /&gt;}</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> &lt;IressField label="Email"&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> /&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> &lt;IressInput name="email" type="email" /&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> )}</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> &lt;/IressField&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> {show?.includes('email') &amp;&amp; (</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> )}</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> &lt;IressFormField </pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> &lt;/IressForm&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> label="Email" </pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> name="email"</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> render={(controlledProps) =&gt; &lt;IressInput {...controlledProps} type="email" /&gt;}</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> /&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> )}</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> &lt;/&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker"><pre></pre></td><td class="css-vl0irh-content"><pre class="css-o1u8iu-content-text"> );</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker"><pre></pre></td><td class="css-vl0irh-content"><pre class="css-o1u8iu-content-text">};</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-10regm7-empty-line css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-10regm7-empty-line css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"></pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text">export const App = () =&gt; (</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> &lt;IressForm defaultValues={{ show: ['name'] }}&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> &lt;ConditionalFields /&gt; </pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> &lt;/IressForm&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text">);</pre></td></tr></tbody></table>
296
72
 
297
73
  ### [](#validation)Validation
298
74
 
@@ -310,105 +86,7 @@ Mode
310
86
 
311
87
  DiffOldNew
312
88
 
313
- \-
314
-
315
- import { IressForm, IressField, IressInput, IressButton } from '@iress/components';
316
-
317
- +
318
-
319
- import { IressForm, IressFormField, IressInput, IressButton } from '@iress/ids-components';
320
-
321
- export const App = () => (
322
-
323
- \-
324
-
325
- <IressForm valueMissing="{{fieldName}} needs to be filled in!">
326
-
327
- +
328
-
329
- <IressForm>
330
-
331
- \-
332
-
333
- <IressField label="Name">
334
-
335
- +
336
-
337
- <IressFormField
338
-
339
- \-
340
-
341
- <IressInput name="name" required />
342
-
343
- +
344
-
345
- label="Name"
346
-
347
- \-
348
-
349
- </IressField>
350
-
351
- +
352
-
353
- name="name"
354
-
355
- \-
356
-
357
- <IressField label="Email">
358
-
359
- +
360
-
361
- render={(controlledProps) => <IressInput {...controlledProps} />}
362
-
363
- \-
364
-
365
- <IressInput name="email" maxLength={10} />
366
-
367
- +
368
-
369
- rules={{ required: 'Name needs to be filled in!' }}
370
-
371
- \-
372
-
373
- </IressField>
374
-
375
- +
376
-
377
- />
378
-
379
- +
380
-
381
- <IressFormField
382
-
383
- +
384
-
385
- label="Email"
386
-
387
- +
388
-
389
- name="email"
390
-
391
- +
392
-
393
- render={(controlledProps) => <IressInput {...controlledProps} type="email" maxLength={10} />}
394
-
395
- +
396
-
397
- rules={{ maxLength: 10 }}
398
-
399
- +
400
-
401
- />
402
-
403
- <IressButton type="submit" mode="primary">
404
-
405
- Sign up
406
-
407
- </IressButton>
408
-
409
- </IressForm>
410
-
411
- );
89
+ <table class="css-1n5o7vh-diff-container"><tbody><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text">import { IressForm, IressField, IressInput, IressButton } from '@iress/components';</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text">import { IressForm, IressFormField, IressInput, IressButton } from '@iress-oss/ids-components';</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-10regm7-empty-line"><pre></pre></td><td class="css-vl0irh-content css-10regm7-empty-line"><pre class="css-o1u8iu-content-text"></pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker"><pre></pre></td><td class="css-vl0irh-content"><pre class="css-o1u8iu-content-text">export const App = () =&gt; (</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> &lt;IressForm valueMissing="{{fieldName}} needs to be filled in!"&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> &lt;IressForm&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> &lt;IressField label="Name"&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> &lt;IressFormField </pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> &lt;IressInput name="name" required /&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> label="Name"</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> &lt;/IressField&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> name="name"</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> &lt;IressField label="Email"&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> render={(controlledProps) =&gt; &lt;IressInput {...controlledProps} /&gt;}</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> &lt;IressInput name="email" maxLength={10} /&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> rules={{ required: 'Name needs to be filled in!' }}</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-rq9a2a-diff-removed"><pre>-</pre></td><td class="css-vl0irh-content css-rq9a2a-diff-removed"><pre class="css-o1u8iu-content-text"> &lt;/IressField&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> /&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> &lt;IressFormField </pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> label="Email"</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> name="email"</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> render={(controlledProps) =&gt; &lt;IressInput {...controlledProps} type="email" maxLength={10} /&gt;}</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> rules={{ maxLength: 10 }}</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker css-cnnxkz-diff-added"><pre>+</pre></td><td class="css-vl0irh-content css-cnnxkz-diff-added"><pre class="css-o1u8iu-content-text"> /&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker"><pre></pre></td><td class="css-vl0irh-content"><pre class="css-o1u8iu-content-text"> &lt;IressButton type="submit" mode="primary"&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker"><pre></pre></td><td class="css-vl0irh-content"><pre class="css-o1u8iu-content-text"> Sign up</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker"><pre></pre></td><td class="css-vl0irh-content"><pre class="css-o1u8iu-content-text"> &lt;/IressButton&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker"><pre></pre></td><td class="css-vl0irh-content"><pre class="css-o1u8iu-content-text"> &lt;/IressForm&gt;</pre></td></tr><tr class="css-1n7ec1i-line"><td class="css-17vezug-marker"><pre></pre></td><td class="css-vl0irh-content"><pre class="css-o1u8iu-content-text">);</pre></td></tr></tbody></table>
412
90
 
413
91
  ### [](#syncing-state)Syncing state
414
92
 
@@ -1069,7 +747,7 @@ Hide code
1069
747
  name\="IressInputDate-default"
1070
748
  render\={(controlledProps) \=> <IressInput {...controlledProps} />}
1071
749
  rules\={{
1072
- minDate: new Date('2025-05-15T02:18:51.404Z')
750
+ minDate: new Date('2025-06-24T20:58:59.990Z')
1073
751
  }}
1074
752
  />
1075
753
  <IressFormField
@@ -1080,7 +758,7 @@ Hide code
1080
758
  rules\={{
1081
759
  minDate: {
1082
760
  message: 'Please enter a date after today!',
1083
- value: new Date('2025-05-15T02:18:51.404Z')
761
+ value: new Date('2025-06-24T20:58:59.990Z')
1084
762
  }
1085
763
  }}
1086
764
  />
@@ -1122,7 +800,7 @@ Hide code
1122
800
  name\="IressInputDate-default"
1123
801
  render\={(controlledProps) \=> <IressInput {...controlledProps} />}
1124
802
  rules\={{
1125
- maxDate: new Date('2025-05-15T02:18:51.404Z')
803
+ maxDate: new Date('2025-06-24T20:58:59.990Z')
1126
804
  }}
1127
805
  />
1128
806
  <IressFormField
@@ -1133,7 +811,7 @@ Hide code
1133
811
  rules\={{
1134
812
  maxDate: {
1135
813
  message: 'Please enter a date before today!',
1136
- value: new Date('2025-05-15T02:18:51.404Z')
814
+ value: new Date('2025-06-24T20:58:59.990Z')
1137
815
  }
1138
816
  }}
1139
817
  />
@@ -1296,7 +974,7 @@ import {
1296
974
  IressInput,
1297
975
  IressStack,
1298
976
  IressButton,
1299
- } from '@iress/ids-components';
977
+ } from '@iress-oss/ids-components';
1300
978
  import { useState } from 'react';
1301
979
  interface FieldValues {
1302
980
  name?: string;
@@ -1549,7 +1227,7 @@ import {
1549
1227
  IressFormField,
1550
1228
  IressInput,
1551
1229
  IressButton,
1552
- } from '@iress/ids-components';
1230
+ } from '@iress-oss/ids-components';
1553
1231
  import { useState } from 'react';
1554
1232
  import { FieldErrors } from 'react-hook-form';
1555
1233
  interface FieldValues {
@@ -1797,7 +1475,7 @@ import {
1797
1475
  IressStack,
1798
1476
  IressToasterProvider,
1799
1477
  useToaster,
1800
- } from '@iress/ids-components';
1478
+ } from '@iress-oss/ids-components';
1801
1479
  import { useRef } from 'react';
1802
1480
  interface FieldValues {
1803
1481
  name?: string;
@@ -1899,7 +1577,7 @@ import {
1899
1577
  IressStack,
1900
1578
  IressFormField,
1901
1579
  IressInput,
1902
- } from '@iress/ids-components';
1580
+ } from '@iress-oss/ids-components';
1903
1581
  import { useRef } from 'react';
1904
1582
  interface FieldValues {
1905
1583
  name?: string;
@@ -1947,6 +1625,333 @@ export const FormReset \= () \=> {
1947
1625
 
1948
1626
  Copy
1949
1627
 
1628
+ ### [](#custom-form-field-components)Custom form field components
1629
+
1630
+ You can integrate custom components within `IressFormField` to create enhanced form experiences.
1631
+
1632
+ This demo showcases how to embed a custom `TranscriptTextBox` component into `IressFormField` while leveraging its built-in validation rules, error handling, and state management without additional implementation.
1633
+
1634
+ **Reminder:** When building custom form components, avoid managing error message state internally. This helps maintain the IressForm as the single source of truth and ensures consistent, predictable UI behavior.
1635
+
1636
+ Key features demonstrated:
1637
+
1638
+ * **Universal Integration Pattern**: Shows how any custom component can be embedded in IressFormField
1639
+ * **Built-in Validation**: Leverages IressFormField's validation rules with custom validation logic
1640
+ * **Multiple Error Messages**: Displays simultaneous validation errors (e.g., wrong file type AND too large)
1641
+ * **Drag & Drop**: Files can be dragged and dropped directly onto the textarea
1642
+ * **File Upload Button**: Traditional file selection via button click
1643
+ * **Visual Feedback**: UI changes during drag operations with border and background updates
1644
+ * **Form State Management**: Automatically integrates with form context using controlled props
1645
+ * **File Management**: Display uploaded files with remove functionality using `IressPanel`
1646
+
1647
+ Custom FormField Components
1648
+ ===========================
1649
+
1650
+ This demo showcases how to embed any custom component (TranscriptTextBox) into IressFormField while leveraging its form validation, error handling, and state management without additional implementation. When building custom form components, avoid managing error message state internally. This helps maintain the IressForm as the single source of truth and ensures consistent, predictable UI behavior.
1651
+
1652
+ \*Required Transcript
1653
+
1654
+ Upload or copy and paste transcript here
1655
+
1656
+ Upload
1657
+
1658
+ Submit
1659
+
1660
+ Hide code
1661
+
1662
+ \[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; }
1663
+
1664
+ import React, { useState } from 'react';
1665
+
1666
+ interface TranscriptFormValues {
1667
+ transcript: TranscriptData | string;
1668
+ }
1669
+ interface TranscriptData {
1670
+ content: string;
1671
+ size?: number;
1672
+ type: 'file' | 'text';
1673
+ extension?: string;
1674
+ fileName?: string;
1675
+ rejectedReasons?: REJECTION\_REASONS\[\];
1676
+ }
1677
+ interface TranscriptTextBoxProps {
1678
+ value: TranscriptData | string;
1679
+ onChange: (data: TranscriptData) \=> void;
1680
+ placeholder?: string;
1681
+ rows?: number;
1682
+ style?: React.CSSProperties;
1683
+ allowedExtensions?: string\[\];
1684
+ maxSizeInMB?: number;
1685
+ }
1686
+ interface SubmittedValuesDisplayProps {
1687
+ submittedValues: TranscriptFormValues | null;
1688
+ title?: string;
1689
+ }
1690
+ enum REJECTION\_REASONS {
1691
+ TYPE \= 'type',
1692
+ SIZE \= 'size',
1693
+ }
1694
+ const validateFile \=
1695
+ (allowedExtensions: string\[\], maxSizeInMB: number) \=>
1696
+ (data: TranscriptData | string) \=> {
1697
+ if (
1698
+ !!data &&
1699
+ typeof data \=== 'object' &&
1700
+ data.type \=== 'file' &&
1701
+ Array.isArray(data.rejectedReasons) &&
1702
+ data.rejectedReasons.length \> 0
1703
+ ) {
1704
+ const errors: string\[\] \= \[\];
1705
+ if (data.rejectedReasons.includes(REJECTION\_REASONS.TYPE)) {
1706
+ errors.push(\`Only .${allowedExtensions.join(', ')} accepted\`);
1707
+ }
1708
+ if (data.rejectedReasons.includes(REJECTION\_REASONS.SIZE)) {
1709
+ errors.push(\`File size must be less than ${maxSizeInMB}MB\`);
1710
+ }
1711
+ if (errors.length \> 0) {
1712
+ return errors.join('. ');
1713
+ }
1714
+ }
1715
+ return true;
1716
+ };
1717
+ const TranscriptTextBox \= ({
1718
+ value,
1719
+ onChange,
1720
+ placeholder \= 'Copy and paste transcripts OR drag and drop / upload recordings, transcripts or documents here (.txt format).',
1721
+ rows \= 10,
1722
+ style,
1723
+ allowedExtensions \= \['txt'\],
1724
+ maxSizeInMB \= 10,
1725
+ }: TranscriptTextBoxProps) \=> {
1726
+ // Extract content and file info from value
1727
+ const currentData \=
1728
+ typeof value \=== 'string'
1729
+ ? { content: value, type: 'text' as const }
1730
+ : value;
1731
+ const currentFile \=
1732
+ currentData?.type \=== 'file' &&
1733
+ (!currentData.rejectedReasons || currentData.rejectedReasons.length \=== 0)
1734
+ ? {
1735
+ name: currentData.fileName ?? 'Unknown file',
1736
+ size: currentData.size,
1737
+ }
1738
+ : null;
1739
+ const createTranscriptData \= (
1740
+ content: string,
1741
+ type: 'file' | 'text',
1742
+ additionalData?: Partial<TranscriptData\>,
1743
+ ): TranscriptData \=> ({
1744
+ content,
1745
+ type,
1746
+ ...additionalData,
1747
+ });
1748
+ const handleFileRead \= (file: File) \=> {
1749
+ const reader \= new FileReader();
1750
+ reader.onload \= (e) \=> {
1751
+ const content \= e.target?.result as string;
1752
+ onChange(
1753
+ createTranscriptData(content, 'file', {
1754
+ size: file.size,
1755
+ extension: file.name.split('.').pop()?.toLowerCase(),
1756
+ fileName: file.name,
1757
+ }),
1758
+ );
1759
+ };
1760
+ reader.onerror \= () \=> {
1761
+ // Let parent handle errors through validation
1762
+ onChange(
1763
+ createTranscriptData('', 'file', {
1764
+ fileName: file.name,
1765
+ }),
1766
+ );
1767
+ };
1768
+ reader.readAsText(file);
1769
+ };
1770
+ const handleTextChange \= (
1771
+ e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement\>,
1772
+ textContent: string,
1773
+ ) \=> {
1774
+ onChange(createTranscriptData(textContent, 'text'));
1775
+ };
1776
+ const onFileSelected \= (files: File\[\]) \=> {
1777
+ if (files.length \=== 0) return;
1778
+ const file \= files\[0\];
1779
+ handleFileRead(file);
1780
+ };
1781
+ const { getRootProps, getInputProps, open, isDragActive } \= useDropzone({
1782
+ multiple: false,
1783
+ noClick: true,
1784
+ maxSize: maxSizeInMB \* 1024 \* 1024,
1785
+ accept: allowedExtensions.reduce(
1786
+ (acc, ext) \=> {
1787
+ const mimeType \=
1788
+ ext \=== 'txt' ? 'text/plain' : 'application/octet-stream';
1789
+ acc\[mimeType\] \= acc\[mimeType\] || \[\];
1790
+ acc\[mimeType\].push(\`.${ext}\`);
1791
+ return acc;
1792
+ },
1793
+ {} as Record<string, string\[\]\>,
1794
+ ),
1795
+ onDrop: (acceptedFiles, rejectedFiles) \=> {
1796
+ if (acceptedFiles.length \> 0) {
1797
+ onFileSelected(acceptedFiles);
1798
+ return;
1799
+ }
1800
+ if (rejectedFiles.length \> 0) {
1801
+ const rejectedFile \= rejectedFiles\[0\];
1802
+ const { file, errors } \= rejectedFile;
1803
+ // Map error codes to rejection reasons
1804
+ const errorCodeMap \= {
1805
+ 'file-invalid-type': REJECTION\_REASONS.TYPE,
1806
+ 'file-too-large': REJECTION\_REASONS.SIZE,
1807
+ } as const;
1808
+ const rejectedReasons \= errors .map((error) \=> errorCodeMap\[error.code as keyof typeof errorCodeMap\])
1809
+ .filter((reason): reason is REJECTION\_REASONS \=> Boolean(reason));
1810
+ onChange(
1811
+ createTranscriptData('', 'file', {
1812
+ fileName: file.name,
1813
+ rejectedReasons,
1814
+ }),
1815
+ );
1816
+ }
1817
+ },
1818
+ });
1819
+ const handleUploadClick \= () \=> {
1820
+ open();
1821
+ };
1822
+ const removeFile \= () \=> {
1823
+ onChange(createTranscriptData('', 'text'));
1824
+ };
1825
+ return (
1826
+ <IressStack gutter\="sm"\>
1827
+ <div {...getRootProps()} style\={{ position: 'relative' }}\>
1828
+ <input {...getInputProps()} />
1829
+ <IressInput
1830
+ value\={currentData?.content || ''}
1831
+ onChange\={handleTextChange}
1832
+ rows\={rows}
1833
+ placeholder\={isDragActive ? 'Drop your file here...' : placeholder}
1834
+ style\={{
1835
+ boxSizing: 'border-box',
1836
+ border: isDragActive ? '1px dashed #007acc' : undefined,
1837
+ backgroundColor: isDragActive ? '#f0f8ff' : undefined,
1838
+ ...style,
1839
+ }}
1840
+ />
1841
+ </div\>
1842
+ {currentFile && (
1843
+ <IressPanel\>
1844
+ <IressInline horizontalAlign\="between" verticalAlign\="middle"\>
1845
+ <IressText\>📄 {currentFile.name}</IressText\>
1846
+ <IressButton mode\="secondary" onClick\={removeFile}\>
1847
+ Remove </IressButton\>
1848
+ </IressInline\>
1849
+ </IressPanel\>
1850
+ )}
1851
+ <IressButton
1852
+ mode\="secondary"
1853
+ onClick\={handleUploadClick}
1854
+ prepend\={<IressIcon name\="upload" />}
1855
+ \>
1856
+ Upload </IressButton\>
1857
+ </IressStack\>
1858
+ );
1859
+ };
1860
+ const SubmittedValuesDisplay: React.FC<SubmittedValuesDisplayProps\> \= ({
1861
+ submittedValues,
1862
+ title \= 'Submitted Values:',
1863
+ }) \=> {
1864
+ if (!submittedValues) {
1865
+ return null;
1866
+ }
1867
+ return (
1868
+ <IressPanel\>
1869
+ <IressStack gutter\="sm"\>
1870
+ <IressText variant\="bold"\>{title}</IressText\>
1871
+ <IressText\>
1872
+ <strong\>Type:</strong\>
1873
+ {typeof submittedValues.transcript \=== 'string'
1874
+ ? 'text'
1875
+ : submittedValues.transcript.type}
1876
+ </IressText\>
1877
+ <IressText\>
1878
+ <strong\>Content:</strong\>
1879
+ {typeof submittedValues.transcript \=== 'string'
1880
+ ? submittedValues.transcript
1881
+ : submittedValues.transcript.content}
1882
+ </IressText\>
1883
+ {typeof submittedValues.transcript \=== 'object' &&
1884
+ submittedValues.transcript.fileName && (
1885
+ <IressText\>
1886
+ <strong\>File Name:</strong\> {submittedValues.transcript.fileName}
1887
+ </IressText\>
1888
+ )}
1889
+ {typeof submittedValues.transcript \=== 'object' &&
1890
+ submittedValues.transcript.size && (
1891
+ <IressText\>
1892
+ <strong\>File Size:</strong\>
1893
+ {(submittedValues.transcript.size / 1024).toFixed(2)} KB </IressText\>
1894
+ )}
1895
+ </IressStack\>
1896
+ </IressPanel\>
1897
+ );
1898
+ };
1899
+ const Heading \= () \=> {
1900
+ return (
1901
+ <\>
1902
+ <IressText element\="h1"\>Custom FormField Components</IressText\>
1903
+ <IressText element\="p"\>
1904
+ This demo showcases how to embed any custom component (TranscriptTextBox) into IressFormField while leveraging its form validation, error handling, and state management without additional implementation. When building custom form components, avoid managing error message state internally. This helps maintain the IressForm as the single source of truth and ensures consistent, predictable UI behavior. </IressText\>
1905
+ </\>
1906
+ );
1907
+ };
1908
+ export const CustomFormFieldComponents \= (
1909
+ args: IressFormProps<TranscriptFormValues\>,
1910
+ ) \=> {
1911
+ const \[submittedValues, setSubmittedValues\] \=
1912
+ useState<TranscriptFormValues | null\>(null);
1913
+ const allowedExtensions \= \['txt'\];
1914
+ const maxSizeInMB \= 0.1;
1915
+ const handleSubmit \= (data: TranscriptFormValues) \=> {
1916
+ setSubmittedValues(data);
1917
+ console.log('Form submitted:', data);
1918
+ };
1919
+ return (
1920
+ <\>
1921
+ <Heading />
1922
+ <IressForm<TranscriptFormValues> {...args}
1923
+ mode="onChange" hiddenErrorSummary onSubmit={handleSubmit}
1924
+ defaultValues={{ transcript: { content: '', type: 'text' } }}
1925
+ > <IressStack gutter\="md"\>
1926
+ <IressFormField
1927
+ label\="Transcript"
1928
+ name\="transcript"
1929
+ hint\="Upload or copy and paste transcript here"
1930
+ render\={(controlledProps) \=> (
1931
+ <TranscriptTextBox
1932
+ {...controlledProps}
1933
+ allowedExtensions\={allowedExtensions}
1934
+ maxSizeInMB\={maxSizeInMB}
1935
+ />
1936
+ )}
1937
+ rules\={{
1938
+ required: 'Transcript is required',
1939
+ validate: {
1940
+ file: validateFile(allowedExtensions, maxSizeInMB),
1941
+ },
1942
+ }}
1943
+ />
1944
+ <IressButton type\="submit" mode\="primary"\>
1945
+ Submit </IressButton\>
1946
+ <SubmittedValuesDisplay submittedValues\={submittedValues} />
1947
+ </IressStack\>
1948
+ </IressForm\>
1949
+ </\>
1950
+ );
1951
+ };
1952
+
1953
+ Copy
1954
+
1950
1955
  ### [](#forms-in-expanders-lazy-loading)Forms in expanders (lazy loading)
1951
1956
 
1952
1957
  If you are using forms in expanders, or in other scenarios when the loading of the form may be delayed, it is recommended to only load the form when it is required. This will improve performance of your application, and make it more predictable. It may also fix act warnings in tests if you are seeing some appearing due to conditionally loaded `IressForm` elements.
@@ -1966,7 +1971,7 @@ import {
1966
1971
  IressFormProps,
1967
1972
  IressInput,
1968
1973
  IressStack,
1969
- } from '@iress/ids-components';
1974
+ } from '@iress-oss/ids-components';
1970
1975
  import { useState } from 'react';
1971
1976
  interface FieldValues {
1972
1977
  name?: string;
@@ -2058,7 +2063,7 @@ import {
2058
2063
  IressInput,
2059
2064
  IressStack,
2060
2065
  IressText,
2061
- } from '@iress/ids-components';
2066
+ } from '@iress-oss/ids-components';
2062
2067
  interface FieldValues {
2063
2068
  show?: string\[\];
2064
2069
  name?: string;
@@ -2401,7 +2406,7 @@ If you are using React Hook Forms in your application, please ensure it is the s
2401
2406
 
2402
2407
  The version we are using in IDS is:
2403
2408
 
2404
- yarn add react-hook-form@7.55.0
2409
+ yarn add react-hook-form@7.53.1
2405
2410
 
2406
2411
  On this page
2407
2412
 
@@ -2425,6 +2430,7 @@ On this page
2425
2430
  * [values](#values)
2426
2431
  * [Disable validation](#disable-validation)
2427
2432
  * [Resetting the form](#resetting-the-form)
2433
+ * [Custom form field components](#custom-form-field-components)
2428
2434
  * [Forms in expanders (lazy loading)](#forms-in-expanders-lazy-loading)
2429
2435
  * [Conditional fields (useWatch)](#conditional-fields-usewatch)
2430
2436
  * [IressHookForm](#iresshookform)