@iress-oss/ids-mcp-server 0.0.1-dev.4 → 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +193 -0
- package/README.md +159 -29
- package/build/componentHandlers.js +205 -0
- package/{dist → build}/config.js +5 -5
- package/build/index.js +51 -0
- package/{dist → build}/iressHandlers.js +46 -52
- package/{dist → build}/resourceHandlers.js +22 -23
- package/{dist → build}/searchHandlers.js +92 -107
- package/{dist → build}/toolHandler.js +13 -13
- package/build/tools.js +165 -0
- package/{dist → build}/utils.js +15 -11
- package/docs/api-reference.md +0 -0
- package/docs/best-practices.md +0 -0
- package/docs/configuration.md +0 -0
- package/docs/examples.md +0 -0
- package/docs/guidelines.md +269 -0
- package/{generated/docs → docs/ids}/components-autocomplete-docs.md +5 -5
- package/{generated/docs → docs/ids}/components-autocomplete-recipes-docs.md +51 -17
- package/{generated/docs → docs/ids}/components-card-recipes-docs.md +1 -1
- package/{generated/docs → docs/ids}/components-checkbox-docs.md +19 -6
- package/{generated/docs → docs/ids}/components-checkboxgroup-docs.md +18 -18
- package/{generated/docs → docs/ids}/components-checkboxgroup-recipes-docs.md +9 -9
- package/{generated/docs → docs/ids}/components-col-docs.md +1 -1
- package/{generated/docs → docs/ids}/components-combobox-docs.md +6 -6
- package/{generated/docs → docs/ids}/components-container-docs.md +42 -8
- package/{generated/docs → docs/ids}/components-filter-docs.md +66 -13
- package/{generated/docs → docs/ids}/components-form-docs.md +368 -342
- package/{generated/docs → docs/ids}/components-form-recipes-docs.md +11 -202
- package/{generated/docs → docs/ids}/components-hide-docs.md +70 -16
- package/{generated/docs → docs/ids}/components-icon-docs.md +4 -4
- package/{generated/docs → docs/ids}/components-input-recipes-docs.md +2 -2
- package/{generated/docs → docs/ids}/components-inputcurrency-recipes-docs.md +40 -6
- package/{generated/docs → docs/ids}/components-modal-docs.md +113 -3
- package/docs/ids/components-popover-docs.md +4 -0
- package/{generated/docs → docs/ids}/components-radiogroup-docs.md +21 -21
- package/{generated/docs → docs/ids}/components-richselect-docs.md +111 -149
- package/{generated/docs → docs/ids}/components-row-docs.md +4 -4
- package/{generated/docs → docs/ids}/components-skeleton-docs.md +3 -3
- package/{generated/docs → docs/ids}/components-skeleton-recipes-docs.md +1 -1
- package/{generated/docs → docs/ids}/components-skiplink-docs.md +1 -1
- package/{generated/docs → docs/ids}/components-slideout-docs.md +113 -3
- package/docs/ids/components-table-ag-grid-docs.md +2694 -0
- package/{generated/docs → docs/ids}/components-table-docs.md +597 -92
- package/{generated/docs → docs/ids}/components-tabset-docs.md +2 -2
- package/{generated/docs → docs/ids}/components-tag-docs.md +1 -1
- package/{generated/docs → docs/ids}/components-toaster-docs.md +5 -56
- package/{generated/docs → docs/ids}/extensions-editor-docs.md +5 -5
- package/{generated/docs → docs/ids}/foundations-colours-docs.md +1 -1
- package/{generated/docs → docs/ids}/foundations-typography-docs.md +2 -7
- package/docs/ids/get-started-develop-docs.md +48 -0
- package/{generated/docs → docs/ids}/introduction-docs.md +4 -4
- package/{generated/docs → docs/ids}/patterns-loading-docs.md +2 -332
- package/docs/ids/resources-migration-guides-from-v4-to-v5-docs.md +639 -0
- package/docs/ids/themes-available-themes-docs.md +74 -0
- package/docs/ids/themes-tokens-docs.md +4580 -0
- package/docs/ids/versions-docs.md +27 -0
- package/docs/tutorials/basic-integration.md +0 -0
- package/package.json +15 -44
- package/LICENSE.txt +0 -201
- package/dist/componentHandlers.js +0 -241
- package/dist/componentHandlers.test.js +0 -380
- package/dist/index.js +0 -53
- package/dist/iressHandlers.test.js +0 -316
- package/dist/resourceHandlers.test.js +0 -352
- package/dist/searchHandlers.test.js +0 -524
- package/dist/toolHandler.test.js +0 -369
- package/dist/tools.js +0 -165
- package/dist/utils.test.js +0 -286
- package/generated/docs/components-popover-docs.md +0 -464
- package/generated/docs/components-provider-docs.md +0 -105
- package/generated/docs/components-table-ag-grid-docs.md +0 -1074
- package/generated/docs/foundations-accessibility-docs.md +0 -62
- package/generated/docs/foundations-consistency-docs.md +0 -52
- package/generated/docs/foundations-content-docs.md +0 -23
- package/generated/docs/foundations-introduction-docs.md +0 -17
- package/generated/docs/foundations-principles-docs.md +0 -70
- package/generated/docs/foundations-user-experience-docs.md +0 -63
- package/generated/docs/foundations-visual-design-docs.md +0 -46
- package/generated/docs/get-started-develop-docs.md +0 -209
- package/generated/docs/guidelines.md +0 -812
- package/generated/docs/resources-migration-guides-from-v4-to-v5-docs.md +0 -437
- package/generated/docs/themes-available-themes-docs.md +0 -66
- package/generated/docs/themes-tokens-docs.md +0 -1200
- package/generated/docs/versions-docs.md +0 -17
- /package/{dist → build}/types.js +0 -0
- /package/{generated/docs → docs/ids}/components-alert-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-badge-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-button-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-button-recipes-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-buttongroup-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-card-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-divider-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-expander-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-field-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-inline-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-input-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-inputcurrency-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-label-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-menu-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-menu-menuitem-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-navbar-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-navbar-recipes-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-panel-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-placeholder-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-popover-recipes-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-progress-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-radio-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-readonly-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-select-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-slider-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-spinner-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-stack-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-tabset-tab-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-text-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-toaster-toast-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-toggle-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-tooltip-docs.md +0 -0
- /package/{generated/docs → docs/ids}/components-validationmessage-docs.md +0 -0
- /package/{generated/docs → docs/ids}/contact-us-docs.md +0 -0
- /package/{generated/docs → docs/ids}/extensions-editor-recipes-docs.md +0 -0
- /package/{generated/docs → docs/ids}/frequently-asked-questions-docs.md +0 -0
- /package/{generated/docs → docs/ids}/get-started-using-storybook-docs.md +0 -0
- /package/{generated/docs → docs/ids}/resources-changelog-docs.md +0 -0
- /package/{generated/docs → docs/ids}/resources-code-katas-docs.md +0 -0
- /package/{generated/docs → docs/ids}/themes-introduction-docs.md +0 -0
|
@@ -68,7 +68,231 @@ Mode
|
|
|
68
68
|
|
|
69
69
|
DiffOldNew
|
|
70
70
|
|
|
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 = () => {</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 = () => {</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"> <IressForm></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"> <IressField 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"> <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"> <IressCheckboxGroup value={show} onChange={(newValues) => setShow(newValues)}></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) => (</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"> <IressCheckboxGroup {...controlledProps}></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"> <IressCheckbox value="name">Name</IressCheckbox></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"> <IressCheckbox value="email">Email</IressCheckbox></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"> </IressCheckboxGroup></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"> </IressField></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') && (</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"> <IressField label="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"> {show?.includes('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"> <IressInput name="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"> <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"> </IressField></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') && (</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) => <IressInput {...controlledProps} />}</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"> <IressField 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"> /></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"> <IressInput name="email" type="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"> )}</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"> </IressField></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') && (</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"> <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"> </IressForm></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) => <IressInput {...controlledProps} type="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"> /></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"> </></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 = () => (</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"> <IressForm defaultValues={{ show: ['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"> <ConditionalFields /> </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"> </IressForm></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>
|
|
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
|
+
);
|
|
72
296
|
|
|
73
297
|
### [](#validation)Validation
|
|
74
298
|
|
|
@@ -86,7 +310,105 @@ Mode
|
|
|
86
310
|
|
|
87
311
|
DiffOldNew
|
|
88
312
|
|
|
89
|
-
|
|
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
|
+
);
|
|
90
412
|
|
|
91
413
|
### [](#syncing-state)Syncing state
|
|
92
414
|
|
|
@@ -413,7 +735,39 @@ A boolean which, if `true`, indicates that the input must have a value before th
|
|
|
413
735
|
|
|
414
736
|
Validate
|
|
415
737
|
|
|
416
|
-
|
|
738
|
+
Hide code
|
|
739
|
+
|
|
740
|
+
\[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; }
|
|
741
|
+
|
|
742
|
+
<IressForm\>
|
|
743
|
+
<IressStack gutter\="lg"\>
|
|
744
|
+
<IressFormField
|
|
745
|
+
hint\=""
|
|
746
|
+
label\="Default message"
|
|
747
|
+
name\="IressInput-default"
|
|
748
|
+
render\={(controlledProps) \=> <IressInput {...controlledProps} />}
|
|
749
|
+
rules\={{
|
|
750
|
+
required: true
|
|
751
|
+
}}
|
|
752
|
+
/>
|
|
753
|
+
<IressFormField
|
|
754
|
+
hint\=""
|
|
755
|
+
label\="Custom message"
|
|
756
|
+
name\="IressInput-custom"
|
|
757
|
+
render\={(controlledProps) \=> <IressInput {...controlledProps} />}
|
|
758
|
+
rules\={{
|
|
759
|
+
required: 'Please check this field'
|
|
760
|
+
}}
|
|
761
|
+
/>
|
|
762
|
+
<IressButton
|
|
763
|
+
mode\="primary"
|
|
764
|
+
type\="submit"
|
|
765
|
+
\>
|
|
766
|
+
Validate </IressButton\>
|
|
767
|
+
</IressStack\>
|
|
768
|
+
</IressForm\>
|
|
769
|
+
|
|
770
|
+
Copy
|
|
417
771
|
|
|
418
772
|
#### [](#maxlength)`maxLength`
|
|
419
773
|
|
|
@@ -715,7 +1069,7 @@ Hide code
|
|
|
715
1069
|
name\="IressInputDate-default"
|
|
716
1070
|
render\={(controlledProps) \=> <IressInput {...controlledProps} />}
|
|
717
1071
|
rules\={{
|
|
718
|
-
minDate: new Date('2025-
|
|
1072
|
+
minDate: new Date('2025-05-15T02:18:51.404Z')
|
|
719
1073
|
}}
|
|
720
1074
|
/>
|
|
721
1075
|
<IressFormField
|
|
@@ -726,7 +1080,7 @@ Hide code
|
|
|
726
1080
|
rules\={{
|
|
727
1081
|
minDate: {
|
|
728
1082
|
message: 'Please enter a date after today!',
|
|
729
|
-
value: new Date('2025-
|
|
1083
|
+
value: new Date('2025-05-15T02:18:51.404Z')
|
|
730
1084
|
}
|
|
731
1085
|
}}
|
|
732
1086
|
/>
|
|
@@ -768,7 +1122,7 @@ Hide code
|
|
|
768
1122
|
name\="IressInputDate-default"
|
|
769
1123
|
render\={(controlledProps) \=> <IressInput {...controlledProps} />}
|
|
770
1124
|
rules\={{
|
|
771
|
-
maxDate: new Date('2025-
|
|
1125
|
+
maxDate: new Date('2025-05-15T02:18:51.404Z')
|
|
772
1126
|
}}
|
|
773
1127
|
/>
|
|
774
1128
|
<IressFormField
|
|
@@ -779,7 +1133,7 @@ Hide code
|
|
|
779
1133
|
rules\={{
|
|
780
1134
|
maxDate: {
|
|
781
1135
|
message: 'Please enter a date before today!',
|
|
782
|
-
value: new Date('2025-
|
|
1136
|
+
value: new Date('2025-05-15T02:18:51.404Z')
|
|
783
1137
|
}
|
|
784
1138
|
}}
|
|
785
1139
|
/>
|
|
@@ -942,7 +1296,7 @@ import {
|
|
|
942
1296
|
IressInput,
|
|
943
1297
|
IressStack,
|
|
944
1298
|
IressButton,
|
|
945
|
-
} from '@iress
|
|
1299
|
+
} from '@iress/ids-components';
|
|
946
1300
|
import { useState } from 'react';
|
|
947
1301
|
interface FieldValues {
|
|
948
1302
|
name?: string;
|
|
@@ -1195,7 +1549,7 @@ import {
|
|
|
1195
1549
|
IressFormField,
|
|
1196
1550
|
IressInput,
|
|
1197
1551
|
IressButton,
|
|
1198
|
-
} from '@iress
|
|
1552
|
+
} from '@iress/ids-components';
|
|
1199
1553
|
import { useState } from 'react';
|
|
1200
1554
|
import { FieldErrors } from 'react-hook-form';
|
|
1201
1555
|
interface FieldValues {
|
|
@@ -1443,7 +1797,7 @@ import {
|
|
|
1443
1797
|
IressStack,
|
|
1444
1798
|
IressToasterProvider,
|
|
1445
1799
|
useToaster,
|
|
1446
|
-
} from '@iress
|
|
1800
|
+
} from '@iress/ids-components';
|
|
1447
1801
|
import { useRef } from 'react';
|
|
1448
1802
|
interface FieldValues {
|
|
1449
1803
|
name?: string;
|
|
@@ -1545,7 +1899,7 @@ import {
|
|
|
1545
1899
|
IressStack,
|
|
1546
1900
|
IressFormField,
|
|
1547
1901
|
IressInput,
|
|
1548
|
-
} from '@iress
|
|
1902
|
+
} from '@iress/ids-components';
|
|
1549
1903
|
import { useRef } from 'react';
|
|
1550
1904
|
interface FieldValues {
|
|
1551
1905
|
name?: string;
|
|
@@ -1593,333 +1947,6 @@ export const FormReset \= () \=> {
|
|
|
1593
1947
|
|
|
1594
1948
|
Copy
|
|
1595
1949
|
|
|
1596
|
-
### [](#custom-form-field-components)Custom form field components
|
|
1597
|
-
|
|
1598
|
-
You can integrate custom components within `IressFormField` to create enhanced form experiences.
|
|
1599
|
-
|
|
1600
|
-
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.
|
|
1601
|
-
|
|
1602
|
-
**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.
|
|
1603
|
-
|
|
1604
|
-
Key features demonstrated:
|
|
1605
|
-
|
|
1606
|
-
* **Universal Integration Pattern**: Shows how any custom component can be embedded in IressFormField
|
|
1607
|
-
* **Built-in Validation**: Leverages IressFormField's validation rules with custom validation logic
|
|
1608
|
-
* **Multiple Error Messages**: Displays simultaneous validation errors (e.g., wrong file type AND too large)
|
|
1609
|
-
* **Drag & Drop**: Files can be dragged and dropped directly onto the textarea
|
|
1610
|
-
* **File Upload Button**: Traditional file selection via button click
|
|
1611
|
-
* **Visual Feedback**: UI changes during drag operations with border and background updates
|
|
1612
|
-
* **Form State Management**: Automatically integrates with form context using controlled props
|
|
1613
|
-
* **File Management**: Display uploaded files with remove functionality using `IressPanel`
|
|
1614
|
-
|
|
1615
|
-
Custom FormField Components
|
|
1616
|
-
===========================
|
|
1617
|
-
|
|
1618
|
-
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.
|
|
1619
|
-
|
|
1620
|
-
\*Required Transcript
|
|
1621
|
-
|
|
1622
|
-
Upload or copy and paste transcript here
|
|
1623
|
-
|
|
1624
|
-
Upload
|
|
1625
|
-
|
|
1626
|
-
Submit
|
|
1627
|
-
|
|
1628
|
-
Hide code
|
|
1629
|
-
|
|
1630
|
-
\[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; }
|
|
1631
|
-
|
|
1632
|
-
import React, { useState } from 'react';
|
|
1633
|
-
|
|
1634
|
-
interface TranscriptFormValues {
|
|
1635
|
-
transcript: TranscriptData | string;
|
|
1636
|
-
}
|
|
1637
|
-
interface TranscriptData {
|
|
1638
|
-
content: string;
|
|
1639
|
-
size?: number;
|
|
1640
|
-
type: 'file' | 'text';
|
|
1641
|
-
extension?: string;
|
|
1642
|
-
fileName?: string;
|
|
1643
|
-
rejectedReasons?: REJECTION\_REASONS\[\];
|
|
1644
|
-
}
|
|
1645
|
-
interface TranscriptTextBoxProps {
|
|
1646
|
-
value: TranscriptData | string;
|
|
1647
|
-
onChange: (data: TranscriptData) \=> void;
|
|
1648
|
-
placeholder?: string;
|
|
1649
|
-
rows?: number;
|
|
1650
|
-
style?: React.CSSProperties;
|
|
1651
|
-
allowedExtensions?: string\[\];
|
|
1652
|
-
maxSizeInMB?: number;
|
|
1653
|
-
}
|
|
1654
|
-
interface SubmittedValuesDisplayProps {
|
|
1655
|
-
submittedValues: TranscriptFormValues | null;
|
|
1656
|
-
title?: string;
|
|
1657
|
-
}
|
|
1658
|
-
enum REJECTION\_REASONS {
|
|
1659
|
-
TYPE \= 'type',
|
|
1660
|
-
SIZE \= 'size',
|
|
1661
|
-
}
|
|
1662
|
-
const validateFile \=
|
|
1663
|
-
(allowedExtensions: string\[\], maxSizeInMB: number) \=>
|
|
1664
|
-
(data: TranscriptData | string) \=> {
|
|
1665
|
-
if (
|
|
1666
|
-
!!data &&
|
|
1667
|
-
typeof data \=== 'object' &&
|
|
1668
|
-
data.type \=== 'file' &&
|
|
1669
|
-
Array.isArray(data.rejectedReasons) &&
|
|
1670
|
-
data.rejectedReasons.length \> 0
|
|
1671
|
-
) {
|
|
1672
|
-
const errors: string\[\] \= \[\];
|
|
1673
|
-
if (data.rejectedReasons.includes(REJECTION\_REASONS.TYPE)) {
|
|
1674
|
-
errors.push(\`Only .${allowedExtensions.join(', ')} accepted\`);
|
|
1675
|
-
}
|
|
1676
|
-
if (data.rejectedReasons.includes(REJECTION\_REASONS.SIZE)) {
|
|
1677
|
-
errors.push(\`File size must be less than ${maxSizeInMB}MB\`);
|
|
1678
|
-
}
|
|
1679
|
-
if (errors.length \> 0) {
|
|
1680
|
-
return errors.join('. ');
|
|
1681
|
-
}
|
|
1682
|
-
}
|
|
1683
|
-
return true;
|
|
1684
|
-
};
|
|
1685
|
-
const TranscriptTextBox \= ({
|
|
1686
|
-
value,
|
|
1687
|
-
onChange,
|
|
1688
|
-
placeholder \= 'Copy and paste transcripts OR drag and drop / upload recordings, transcripts or documents here (.txt format).',
|
|
1689
|
-
rows \= 10,
|
|
1690
|
-
style,
|
|
1691
|
-
allowedExtensions \= \['txt'\],
|
|
1692
|
-
maxSizeInMB \= 10,
|
|
1693
|
-
}: TranscriptTextBoxProps) \=> {
|
|
1694
|
-
// Extract content and file info from value
|
|
1695
|
-
const currentData \=
|
|
1696
|
-
typeof value \=== 'string'
|
|
1697
|
-
? { content: value, type: 'text' as const }
|
|
1698
|
-
: value;
|
|
1699
|
-
const currentFile \=
|
|
1700
|
-
currentData?.type \=== 'file' &&
|
|
1701
|
-
(!currentData.rejectedReasons || currentData.rejectedReasons.length \=== 0)
|
|
1702
|
-
? {
|
|
1703
|
-
name: currentData.fileName ?? 'Unknown file',
|
|
1704
|
-
size: currentData.size,
|
|
1705
|
-
}
|
|
1706
|
-
: null;
|
|
1707
|
-
const createTranscriptData \= (
|
|
1708
|
-
content: string,
|
|
1709
|
-
type: 'file' | 'text',
|
|
1710
|
-
additionalData?: Partial<TranscriptData\>,
|
|
1711
|
-
): TranscriptData \=> ({
|
|
1712
|
-
content,
|
|
1713
|
-
type,
|
|
1714
|
-
...additionalData,
|
|
1715
|
-
});
|
|
1716
|
-
const handleFileRead \= (file: File) \=> {
|
|
1717
|
-
const reader \= new FileReader();
|
|
1718
|
-
reader.onload \= (e) \=> {
|
|
1719
|
-
const content \= e.target?.result as string;
|
|
1720
|
-
onChange(
|
|
1721
|
-
createTranscriptData(content, 'file', {
|
|
1722
|
-
size: file.size,
|
|
1723
|
-
extension: file.name.split('.').pop()?.toLowerCase(),
|
|
1724
|
-
fileName: file.name,
|
|
1725
|
-
}),
|
|
1726
|
-
);
|
|
1727
|
-
};
|
|
1728
|
-
reader.onerror \= () \=> {
|
|
1729
|
-
// Let parent handle errors through validation
|
|
1730
|
-
onChange(
|
|
1731
|
-
createTranscriptData('', 'file', {
|
|
1732
|
-
fileName: file.name,
|
|
1733
|
-
}),
|
|
1734
|
-
);
|
|
1735
|
-
};
|
|
1736
|
-
reader.readAsText(file);
|
|
1737
|
-
};
|
|
1738
|
-
const handleTextChange \= (
|
|
1739
|
-
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement\>,
|
|
1740
|
-
textContent: string,
|
|
1741
|
-
) \=> {
|
|
1742
|
-
onChange(createTranscriptData(textContent, 'text'));
|
|
1743
|
-
};
|
|
1744
|
-
const onFileSelected \= (files: File\[\]) \=> {
|
|
1745
|
-
if (files.length \=== 0) return;
|
|
1746
|
-
const file \= files\[0\];
|
|
1747
|
-
handleFileRead(file);
|
|
1748
|
-
};
|
|
1749
|
-
const { getRootProps, getInputProps, open, isDragActive } \= useDropzone({
|
|
1750
|
-
multiple: false,
|
|
1751
|
-
noClick: true,
|
|
1752
|
-
maxSize: maxSizeInMB \* 1024 \* 1024,
|
|
1753
|
-
accept: allowedExtensions.reduce(
|
|
1754
|
-
(acc, ext) \=> {
|
|
1755
|
-
const mimeType \=
|
|
1756
|
-
ext \=== 'txt' ? 'text/plain' : 'application/octet-stream';
|
|
1757
|
-
acc\[mimeType\] \= acc\[mimeType\] || \[\];
|
|
1758
|
-
acc\[mimeType\].push(\`.${ext}\`);
|
|
1759
|
-
return acc;
|
|
1760
|
-
},
|
|
1761
|
-
{} as Record<string, string\[\]\>,
|
|
1762
|
-
),
|
|
1763
|
-
onDrop: (acceptedFiles, rejectedFiles) \=> {
|
|
1764
|
-
if (acceptedFiles.length \> 0) {
|
|
1765
|
-
onFileSelected(acceptedFiles);
|
|
1766
|
-
return;
|
|
1767
|
-
}
|
|
1768
|
-
if (rejectedFiles.length \> 0) {
|
|
1769
|
-
const rejectedFile \= rejectedFiles\[0\];
|
|
1770
|
-
const { file, errors } \= rejectedFile;
|
|
1771
|
-
// Map error codes to rejection reasons
|
|
1772
|
-
const errorCodeMap \= {
|
|
1773
|
-
'file-invalid-type': REJECTION\_REASONS.TYPE,
|
|
1774
|
-
'file-too-large': REJECTION\_REASONS.SIZE,
|
|
1775
|
-
} as const;
|
|
1776
|
-
const rejectedReasons \= errors .map((error) \=> errorCodeMap\[error.code as keyof typeof errorCodeMap\])
|
|
1777
|
-
.filter((reason): reason is REJECTION\_REASONS \=> Boolean(reason));
|
|
1778
|
-
onChange(
|
|
1779
|
-
createTranscriptData('', 'file', {
|
|
1780
|
-
fileName: file.name,
|
|
1781
|
-
rejectedReasons,
|
|
1782
|
-
}),
|
|
1783
|
-
);
|
|
1784
|
-
}
|
|
1785
|
-
},
|
|
1786
|
-
});
|
|
1787
|
-
const handleUploadClick \= () \=> {
|
|
1788
|
-
open();
|
|
1789
|
-
};
|
|
1790
|
-
const removeFile \= () \=> {
|
|
1791
|
-
onChange(createTranscriptData('', 'text'));
|
|
1792
|
-
};
|
|
1793
|
-
return (
|
|
1794
|
-
<IressStack gutter\="sm"\>
|
|
1795
|
-
<div {...getRootProps()} style\={{ position: 'relative' }}\>
|
|
1796
|
-
<input {...getInputProps()} />
|
|
1797
|
-
<IressInput
|
|
1798
|
-
value\={currentData?.content || ''}
|
|
1799
|
-
onChange\={handleTextChange}
|
|
1800
|
-
rows\={rows}
|
|
1801
|
-
placeholder\={isDragActive ? 'Drop your file here...' : placeholder}
|
|
1802
|
-
style\={{
|
|
1803
|
-
boxSizing: 'border-box',
|
|
1804
|
-
border: isDragActive ? '1px dashed #007acc' : undefined,
|
|
1805
|
-
backgroundColor: isDragActive ? '#f0f8ff' : undefined,
|
|
1806
|
-
...style,
|
|
1807
|
-
}}
|
|
1808
|
-
/>
|
|
1809
|
-
</div\>
|
|
1810
|
-
{currentFile && (
|
|
1811
|
-
<IressPanel\>
|
|
1812
|
-
<IressInline horizontalAlign\="between" verticalAlign\="middle"\>
|
|
1813
|
-
<IressText\>📄 {currentFile.name}</IressText\>
|
|
1814
|
-
<IressButton mode\="secondary" onClick\={removeFile}\>
|
|
1815
|
-
Remove </IressButton\>
|
|
1816
|
-
</IressInline\>
|
|
1817
|
-
</IressPanel\>
|
|
1818
|
-
)}
|
|
1819
|
-
<IressButton
|
|
1820
|
-
mode\="secondary"
|
|
1821
|
-
onClick\={handleUploadClick}
|
|
1822
|
-
prepend\={<IressIcon name\="upload" />}
|
|
1823
|
-
\>
|
|
1824
|
-
Upload </IressButton\>
|
|
1825
|
-
</IressStack\>
|
|
1826
|
-
);
|
|
1827
|
-
};
|
|
1828
|
-
const SubmittedValuesDisplay: React.FC<SubmittedValuesDisplayProps\> \= ({
|
|
1829
|
-
submittedValues,
|
|
1830
|
-
title \= 'Submitted Values:',
|
|
1831
|
-
}) \=> {
|
|
1832
|
-
if (!submittedValues) {
|
|
1833
|
-
return null;
|
|
1834
|
-
}
|
|
1835
|
-
return (
|
|
1836
|
-
<IressPanel\>
|
|
1837
|
-
<IressStack gutter\="sm"\>
|
|
1838
|
-
<IressText variant\="bold"\>{title}</IressText\>
|
|
1839
|
-
<IressText\>
|
|
1840
|
-
<strong\>Type:</strong\>
|
|
1841
|
-
{typeof submittedValues.transcript \=== 'string'
|
|
1842
|
-
? 'text'
|
|
1843
|
-
: submittedValues.transcript.type}
|
|
1844
|
-
</IressText\>
|
|
1845
|
-
<IressText\>
|
|
1846
|
-
<strong\>Content:</strong\>
|
|
1847
|
-
{typeof submittedValues.transcript \=== 'string'
|
|
1848
|
-
? submittedValues.transcript
|
|
1849
|
-
: submittedValues.transcript.content}
|
|
1850
|
-
</IressText\>
|
|
1851
|
-
{typeof submittedValues.transcript \=== 'object' &&
|
|
1852
|
-
submittedValues.transcript.fileName && (
|
|
1853
|
-
<IressText\>
|
|
1854
|
-
<strong\>File Name:</strong\> {submittedValues.transcript.fileName}
|
|
1855
|
-
</IressText\>
|
|
1856
|
-
)}
|
|
1857
|
-
{typeof submittedValues.transcript \=== 'object' &&
|
|
1858
|
-
submittedValues.transcript.size && (
|
|
1859
|
-
<IressText\>
|
|
1860
|
-
<strong\>File Size:</strong\>
|
|
1861
|
-
{(submittedValues.transcript.size / 1024).toFixed(2)} KB </IressText\>
|
|
1862
|
-
)}
|
|
1863
|
-
</IressStack\>
|
|
1864
|
-
</IressPanel\>
|
|
1865
|
-
);
|
|
1866
|
-
};
|
|
1867
|
-
const Heading \= () \=> {
|
|
1868
|
-
return (
|
|
1869
|
-
<\>
|
|
1870
|
-
<IressText element\="h1"\>Custom FormField Components</IressText\>
|
|
1871
|
-
<IressText element\="p"\>
|
|
1872
|
-
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\>
|
|
1873
|
-
</\>
|
|
1874
|
-
);
|
|
1875
|
-
};
|
|
1876
|
-
export const CustomFormFieldComponents \= (
|
|
1877
|
-
args: IressFormProps<TranscriptFormValues\>,
|
|
1878
|
-
) \=> {
|
|
1879
|
-
const \[submittedValues, setSubmittedValues\] \=
|
|
1880
|
-
useState<TranscriptFormValues | null\>(null);
|
|
1881
|
-
const allowedExtensions \= \['txt'\];
|
|
1882
|
-
const maxSizeInMB \= 0.1;
|
|
1883
|
-
const handleSubmit \= (data: TranscriptFormValues) \=> {
|
|
1884
|
-
setSubmittedValues(data);
|
|
1885
|
-
console.log('Form submitted:', data);
|
|
1886
|
-
};
|
|
1887
|
-
return (
|
|
1888
|
-
<\>
|
|
1889
|
-
<Heading />
|
|
1890
|
-
<IressForm<TranscriptFormValues> {...args}
|
|
1891
|
-
mode="onChange" hiddenErrorSummary onSubmit={handleSubmit}
|
|
1892
|
-
defaultValues={{ transcript: { content: '', type: 'text' } }}
|
|
1893
|
-
> <IressStack gutter\="md"\>
|
|
1894
|
-
<IressFormField
|
|
1895
|
-
label\="Transcript"
|
|
1896
|
-
name\="transcript"
|
|
1897
|
-
hint\="Upload or copy and paste transcript here"
|
|
1898
|
-
render\={(controlledProps) \=> (
|
|
1899
|
-
<TranscriptTextBox
|
|
1900
|
-
{...controlledProps}
|
|
1901
|
-
allowedExtensions\={allowedExtensions}
|
|
1902
|
-
maxSizeInMB\={maxSizeInMB}
|
|
1903
|
-
/>
|
|
1904
|
-
)}
|
|
1905
|
-
rules\={{
|
|
1906
|
-
required: 'Transcript is required',
|
|
1907
|
-
validate: {
|
|
1908
|
-
file: validateFile(allowedExtensions, maxSizeInMB),
|
|
1909
|
-
},
|
|
1910
|
-
}}
|
|
1911
|
-
/>
|
|
1912
|
-
<IressButton type\="submit" mode\="primary"\>
|
|
1913
|
-
Submit </IressButton\>
|
|
1914
|
-
<SubmittedValuesDisplay submittedValues\={submittedValues} />
|
|
1915
|
-
</IressStack\>
|
|
1916
|
-
</IressForm\>
|
|
1917
|
-
</\>
|
|
1918
|
-
);
|
|
1919
|
-
};
|
|
1920
|
-
|
|
1921
|
-
Copy
|
|
1922
|
-
|
|
1923
1950
|
### [](#forms-in-expanders-lazy-loading)Forms in expanders (lazy loading)
|
|
1924
1951
|
|
|
1925
1952
|
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.
|
|
@@ -1939,7 +1966,7 @@ import {
|
|
|
1939
1966
|
IressFormProps,
|
|
1940
1967
|
IressInput,
|
|
1941
1968
|
IressStack,
|
|
1942
|
-
} from '@iress
|
|
1969
|
+
} from '@iress/ids-components';
|
|
1943
1970
|
import { useState } from 'react';
|
|
1944
1971
|
interface FieldValues {
|
|
1945
1972
|
name?: string;
|
|
@@ -2031,7 +2058,7 @@ import {
|
|
|
2031
2058
|
IressInput,
|
|
2032
2059
|
IressStack,
|
|
2033
2060
|
IressText,
|
|
2034
|
-
} from '@iress
|
|
2061
|
+
} from '@iress/ids-components';
|
|
2035
2062
|
interface FieldValues {
|
|
2036
2063
|
show?: string\[\];
|
|
2037
2064
|
name?: string;
|
|
@@ -2374,7 +2401,7 @@ If you are using React Hook Forms in your application, please ensure it is the s
|
|
|
2374
2401
|
|
|
2375
2402
|
The version we are using in IDS is:
|
|
2376
2403
|
|
|
2377
|
-
yarn add react-hook-form@7.
|
|
2404
|
+
yarn add react-hook-form@7.55.0
|
|
2378
2405
|
|
|
2379
2406
|
On this page
|
|
2380
2407
|
|
|
@@ -2398,7 +2425,6 @@ On this page
|
|
|
2398
2425
|
* [values](#values)
|
|
2399
2426
|
* [Disable validation](#disable-validation)
|
|
2400
2427
|
* [Resetting the form](#resetting-the-form)
|
|
2401
|
-
* [Custom form field components](#custom-form-field-components)
|
|
2402
2428
|
* [Forms in expanders (lazy loading)](#forms-in-expanders-lazy-loading)
|
|
2403
2429
|
* [Conditional fields (useWatch)](#conditional-fields-usewatch)
|
|
2404
2430
|
* [IressHookForm](#iresshookform)
|