@cloud-ru/ds-uikit-product-fields-predefined 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/LICENSE +201 -0
- package/README.md +1339 -0
- package/dist/cjs/components/FieldChat/FieldChat.d.ts +7 -0
- package/dist/cjs/components/FieldChat/FieldChat.js +50 -0
- package/dist/cjs/components/FieldChat/components/Attachments/Attachments.d.ts +8 -0
- package/dist/cjs/components/FieldChat/components/Attachments/Attachments.js +16 -0
- package/dist/cjs/components/FieldChat/components/Attachments/index.d.ts +1 -0
- package/dist/cjs/components/FieldChat/components/Attachments/index.js +17 -0
- package/dist/cjs/components/FieldChat/components/Attachments/styles.module.css +12 -0
- package/dist/cjs/components/FieldChat/components/FieldSubmitButton/FieldSubmitButton.d.ts +18 -0
- package/dist/cjs/components/FieldChat/components/FieldSubmitButton/FieldSubmitButton.js +22 -0
- package/dist/cjs/components/FieldChat/components/FieldSubmitButton/index.d.ts +1 -0
- package/dist/cjs/components/FieldChat/components/FieldSubmitButton/index.js +17 -0
- package/dist/cjs/components/FieldChat/components/FieldSubmitButton/styles.module.css +3 -0
- package/dist/cjs/components/FieldChat/components/TextAreaActionsFooter/TextAreaActionsFooter.d.ts +8 -0
- package/dist/cjs/components/FieldChat/components/TextAreaActionsFooter/TextAreaActionsFooter.js +11 -0
- package/dist/cjs/components/FieldChat/components/TextAreaActionsFooter/index.d.ts +1 -0
- package/dist/cjs/components/FieldChat/components/TextAreaActionsFooter/index.js +17 -0
- package/dist/cjs/components/FieldChat/components/TextAreaActionsFooter/styles.module.css +25 -0
- package/dist/cjs/components/FieldChat/index.d.ts +2 -0
- package/dist/cjs/components/FieldChat/index.js +18 -0
- package/dist/cjs/components/FieldChat/styles.module.css +14 -0
- package/dist/cjs/components/FieldChat/types.d.ts +14 -0
- package/dist/cjs/components/FieldChat/types.js +2 -0
- package/dist/cjs/components/FieldCode/FieldCode.d.ts +30 -0
- package/dist/cjs/components/FieldCode/FieldCode.js +42 -0
- package/dist/cjs/components/FieldCode/components/Cell/Cell.d.ts +7 -0
- package/dist/cjs/components/FieldCode/components/Cell/Cell.js +17 -0
- package/dist/cjs/components/FieldCode/components/Cell/index.d.ts +1 -0
- package/dist/cjs/components/FieldCode/components/Cell/index.js +17 -0
- package/dist/cjs/components/FieldCode/components/Cell/styles.module.css +19 -0
- package/dist/cjs/components/FieldCode/components/ResendCode/ResendCode.d.ts +8 -0
- package/dist/cjs/components/FieldCode/components/ResendCode/ResendCode.js +19 -0
- package/dist/cjs/components/FieldCode/components/ResendCode/index.d.ts +1 -0
- package/dist/cjs/components/FieldCode/components/ResendCode/index.js +17 -0
- package/dist/cjs/components/FieldCode/components/ResendCode/utils.d.ts +1 -0
- package/dist/cjs/components/FieldCode/components/ResendCode/utils.js +8 -0
- package/dist/cjs/components/FieldCode/components/index.d.ts +2 -0
- package/dist/cjs/components/FieldCode/components/index.js +18 -0
- package/dist/cjs/components/FieldCode/constants.d.ts +2 -0
- package/dist/cjs/components/FieldCode/constants.js +5 -0
- package/dist/cjs/components/FieldCode/hooks/index.d.ts +5 -0
- package/dist/cjs/components/FieldCode/hooks/index.js +21 -0
- package/dist/cjs/components/FieldCode/hooks/useCodeInput.d.ts +22 -0
- package/dist/cjs/components/FieldCode/hooks/useCodeInput.js +97 -0
- package/dist/cjs/components/FieldCode/hooks/useFieldCodeOverflow.d.ts +6 -0
- package/dist/cjs/components/FieldCode/hooks/useFieldCodeOverflow.js +43 -0
- package/dist/cjs/components/FieldCode/hooks/useFieldCodeValidate.d.ts +6 -0
- package/dist/cjs/components/FieldCode/hooks/useFieldCodeValidate.js +22 -0
- package/dist/cjs/components/FieldCode/hooks/useFieldHelpers.d.ts +12 -0
- package/dist/cjs/components/FieldCode/hooks/useFieldHelpers.js +31 -0
- package/dist/cjs/components/FieldCode/hooks/useFocusCell.d.ts +5 -0
- package/dist/cjs/components/FieldCode/hooks/useFocusCell.js +21 -0
- package/dist/cjs/components/FieldCode/hooks/useRefState.d.ts +7 -0
- package/dist/cjs/components/FieldCode/hooks/useRefState.js +21 -0
- package/dist/cjs/components/FieldCode/index.d.ts +3 -0
- package/dist/cjs/components/FieldCode/index.js +19 -0
- package/dist/cjs/components/FieldCode/styles.module.css +45 -0
- package/dist/cjs/components/FieldCode/utils.d.ts +6 -0
- package/dist/cjs/components/FieldCode/utils.js +21 -0
- package/dist/cjs/components/FieldDescription/FieldDescription.d.ts +10 -0
- package/dist/cjs/components/FieldDescription/FieldDescription.js +55 -0
- package/dist/cjs/components/FieldDescription/FieldDescriptionRHF.d.ts +9 -0
- package/dist/cjs/components/FieldDescription/FieldDescriptionRHF.js +47 -0
- package/dist/cjs/components/FieldDescription/components/FieldWithAddButton.d.ts +7 -0
- package/dist/cjs/components/FieldDescription/components/FieldWithAddButton.js +27 -0
- package/dist/cjs/components/FieldDescription/components/index.d.ts +1 -0
- package/dist/cjs/components/FieldDescription/components/index.js +17 -0
- package/dist/cjs/components/FieldDescription/constants.d.ts +1 -0
- package/dist/cjs/components/FieldDescription/constants.js +4 -0
- package/dist/cjs/components/FieldDescription/index.d.ts +3 -0
- package/dist/cjs/components/FieldDescription/index.js +19 -0
- package/dist/cjs/components/FieldDescription/types.d.ts +17 -0
- package/dist/cjs/components/FieldDescription/types.js +2 -0
- package/dist/cjs/components/FieldMask/FieldMask.d.ts +12 -0
- package/dist/cjs/components/FieldMask/FieldMask.js +30 -0
- package/dist/cjs/components/FieldMask/constants.d.ts +19 -0
- package/dist/cjs/components/FieldMask/constants.js +60 -0
- package/dist/cjs/components/FieldMask/index.d.ts +3 -0
- package/dist/cjs/components/FieldMask/index.js +21 -0
- package/dist/cjs/components/FieldMask/types.d.ts +3 -0
- package/dist/cjs/components/FieldMask/types.js +2 -0
- package/dist/cjs/components/FieldName/FieldName.d.ts +5 -0
- package/dist/cjs/components/FieldName/FieldName.js +84 -0
- package/dist/cjs/components/FieldName/FieldNameRHF.d.ts +5 -0
- package/dist/cjs/components/FieldName/FieldNameRHF.js +68 -0
- package/dist/cjs/components/FieldName/constants.d.ts +1 -0
- package/dist/cjs/components/FieldName/constants.js +4 -0
- package/dist/cjs/components/FieldName/index.d.ts +3 -0
- package/dist/cjs/components/FieldName/index.js +19 -0
- package/dist/cjs/components/FieldName/types.d.ts +22 -0
- package/dist/cjs/components/FieldName/types.js +2 -0
- package/dist/cjs/components/FieldPhone/FieldPhone.d.ts +13 -0
- package/dist/cjs/components/FieldPhone/FieldPhone.js +166 -0
- package/dist/cjs/components/FieldPhone/constants.d.ts +8 -0
- package/dist/cjs/components/FieldPhone/constants.js +11 -0
- package/dist/cjs/components/FieldPhone/countries.d.ts +3500 -0
- package/dist/cjs/components/FieldPhone/countries.js +1441 -0
- package/dist/cjs/components/FieldPhone/hooks/index.d.ts +2 -0
- package/dist/cjs/components/FieldPhone/hooks/index.js +18 -0
- package/dist/cjs/components/FieldPhone/hooks/useCountries.d.ts +2 -0
- package/dist/cjs/components/FieldPhone/hooks/useCountries.js +36 -0
- package/dist/cjs/components/FieldPhone/hooks/useMapCountryToOptions.d.ts +2 -0
- package/dist/cjs/components/FieldPhone/hooks/useMapCountryToOptions.js +20 -0
- package/dist/cjs/components/FieldPhone/index.d.ts +5 -0
- package/dist/cjs/components/FieldPhone/index.js +24 -0
- package/dist/cjs/components/FieldPhone/styles.module.css +3 -0
- package/dist/cjs/components/FieldPhone/types.d.ts +31 -0
- package/dist/cjs/components/FieldPhone/types.js +2 -0
- package/dist/cjs/components/FieldPhone/utils.d.ts +14 -0
- package/dist/cjs/components/FieldPhone/utils.js +85 -0
- package/dist/cjs/components/FieldSelectCreate/FieldSelectCreate.d.ts +8 -0
- package/dist/cjs/components/FieldSelectCreate/FieldSelectCreate.js +66 -0
- package/dist/cjs/components/FieldSelectCreate/constants.d.ts +14 -0
- package/dist/cjs/components/FieldSelectCreate/constants.js +17 -0
- package/dist/cjs/components/FieldSelectCreate/helperComponents/SelectFooter/SelectFooter.d.ts +8 -0
- package/dist/cjs/components/FieldSelectCreate/helperComponents/SelectFooter/SelectFooter.js +19 -0
- package/dist/cjs/components/FieldSelectCreate/helperComponents/SelectFooter/index.d.ts +1 -0
- package/dist/cjs/components/FieldSelectCreate/helperComponents/SelectFooter/index.js +17 -0
- package/dist/cjs/components/FieldSelectCreate/helperComponents/SelectFooter/styles.module.css +6 -0
- package/dist/cjs/components/FieldSelectCreate/index.d.ts +3 -0
- package/dist/cjs/components/FieldSelectCreate/index.js +19 -0
- package/dist/cjs/components/FieldSelectCreate/styles.module.css +9 -0
- package/dist/cjs/components/FieldSelectCreate/types.d.ts +58 -0
- package/dist/cjs/components/FieldSelectCreate/types.js +2 -0
- package/dist/cjs/components/FieldSelectCreate/useSelectDataStates.d.ts +11 -0
- package/dist/cjs/components/FieldSelectCreate/useSelectDataStates.js +29 -0
- package/dist/cjs/components/FieldSelectCreate/utils.d.ts +2 -0
- package/dist/cjs/components/FieldSelectCreate/utils.js +7 -0
- package/dist/cjs/components/index.d.ts +7 -0
- package/dist/cjs/components/index.js +23 -0
- package/dist/cjs/constants.d.ts +19 -0
- package/dist/cjs/constants.js +22 -0
- package/dist/cjs/helpers/getSymbolsRangeFromMask.d.ts +7 -0
- package/dist/cjs/helpers/getSymbolsRangeFromMask.js +15 -0
- package/dist/cjs/helpers/index.d.ts +1 -0
- package/dist/cjs/helpers/index.js +17 -0
- package/dist/cjs/hooks/index.d.ts +2 -0
- package/dist/cjs/hooks/index.js +18 -0
- package/dist/cjs/hooks/useCustomFieldValidation.d.ts +12 -0
- package/dist/cjs/hooks/useCustomFieldValidation.js +32 -0
- package/dist/cjs/hooks/useOpen.d.ts +5 -0
- package/dist/cjs/hooks/useOpen.js +18 -0
- package/dist/cjs/index.d.ts +6 -0
- package/dist/cjs/index.js +25 -0
- package/dist/cjs/locale/index.d.ts +845 -0
- package/dist/cjs/locale/index.js +429 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/style.css +136 -0
- package/dist/esm/components/FieldChat/FieldChat.d.ts +7 -0
- package/dist/esm/components/FieldChat/FieldChat.js +44 -0
- package/dist/esm/components/FieldChat/components/Attachments/Attachments.d.ts +8 -0
- package/dist/esm/components/FieldChat/components/Attachments/Attachments.js +10 -0
- package/dist/esm/components/FieldChat/components/Attachments/index.d.ts +1 -0
- package/dist/esm/components/FieldChat/components/Attachments/index.js +1 -0
- package/dist/esm/components/FieldChat/components/Attachments/styles.module.css +12 -0
- package/dist/esm/components/FieldChat/components/FieldSubmitButton/FieldSubmitButton.d.ts +18 -0
- package/dist/esm/components/FieldChat/components/FieldSubmitButton/FieldSubmitButton.js +16 -0
- package/dist/esm/components/FieldChat/components/FieldSubmitButton/index.d.ts +1 -0
- package/dist/esm/components/FieldChat/components/FieldSubmitButton/index.js +1 -0
- package/dist/esm/components/FieldChat/components/FieldSubmitButton/styles.module.css +3 -0
- package/dist/esm/components/FieldChat/components/TextAreaActionsFooter/TextAreaActionsFooter.d.ts +8 -0
- package/dist/esm/components/FieldChat/components/TextAreaActionsFooter/TextAreaActionsFooter.js +5 -0
- package/dist/esm/components/FieldChat/components/TextAreaActionsFooter/index.d.ts +1 -0
- package/dist/esm/components/FieldChat/components/TextAreaActionsFooter/index.js +1 -0
- package/dist/esm/components/FieldChat/components/TextAreaActionsFooter/styles.module.css +25 -0
- package/dist/esm/components/FieldChat/index.d.ts +2 -0
- package/dist/esm/components/FieldChat/index.js +2 -0
- package/dist/esm/components/FieldChat/styles.module.css +14 -0
- package/dist/esm/components/FieldChat/types.d.ts +14 -0
- package/dist/esm/components/FieldChat/types.js +1 -0
- package/dist/esm/components/FieldCode/FieldCode.d.ts +30 -0
- package/dist/esm/components/FieldCode/FieldCode.js +36 -0
- package/dist/esm/components/FieldCode/components/Cell/Cell.d.ts +7 -0
- package/dist/esm/components/FieldCode/components/Cell/Cell.js +11 -0
- package/dist/esm/components/FieldCode/components/Cell/index.d.ts +1 -0
- package/dist/esm/components/FieldCode/components/Cell/index.js +1 -0
- package/dist/esm/components/FieldCode/components/Cell/styles.module.css +19 -0
- package/dist/esm/components/FieldCode/components/ResendCode/ResendCode.d.ts +8 -0
- package/dist/esm/components/FieldCode/components/ResendCode/ResendCode.js +16 -0
- package/dist/esm/components/FieldCode/components/ResendCode/index.d.ts +1 -0
- package/dist/esm/components/FieldCode/components/ResendCode/index.js +1 -0
- package/dist/esm/components/FieldCode/components/ResendCode/utils.d.ts +1 -0
- package/dist/esm/components/FieldCode/components/ResendCode/utils.js +5 -0
- package/dist/esm/components/FieldCode/components/index.d.ts +2 -0
- package/dist/esm/components/FieldCode/components/index.js +2 -0
- package/dist/esm/components/FieldCode/constants.d.ts +2 -0
- package/dist/esm/components/FieldCode/constants.js +2 -0
- package/dist/esm/components/FieldCode/hooks/index.d.ts +5 -0
- package/dist/esm/components/FieldCode/hooks/index.js +5 -0
- package/dist/esm/components/FieldCode/hooks/useCodeInput.d.ts +22 -0
- package/dist/esm/components/FieldCode/hooks/useCodeInput.js +94 -0
- package/dist/esm/components/FieldCode/hooks/useFieldCodeOverflow.d.ts +6 -0
- package/dist/esm/components/FieldCode/hooks/useFieldCodeOverflow.js +40 -0
- package/dist/esm/components/FieldCode/hooks/useFieldCodeValidate.d.ts +6 -0
- package/dist/esm/components/FieldCode/hooks/useFieldCodeValidate.js +19 -0
- package/dist/esm/components/FieldCode/hooks/useFieldHelpers.d.ts +12 -0
- package/dist/esm/components/FieldCode/hooks/useFieldHelpers.js +28 -0
- package/dist/esm/components/FieldCode/hooks/useFocusCell.d.ts +5 -0
- package/dist/esm/components/FieldCode/hooks/useFocusCell.js +18 -0
- package/dist/esm/components/FieldCode/hooks/useRefState.d.ts +7 -0
- package/dist/esm/components/FieldCode/hooks/useRefState.js +18 -0
- package/dist/esm/components/FieldCode/index.d.ts +3 -0
- package/dist/esm/components/FieldCode/index.js +3 -0
- package/dist/esm/components/FieldCode/styles.module.css +45 -0
- package/dist/esm/components/FieldCode/utils.d.ts +6 -0
- package/dist/esm/components/FieldCode/utils.js +13 -0
- package/dist/esm/components/FieldDescription/FieldDescription.d.ts +10 -0
- package/dist/esm/components/FieldDescription/FieldDescription.js +49 -0
- package/dist/esm/components/FieldDescription/FieldDescriptionRHF.d.ts +9 -0
- package/dist/esm/components/FieldDescription/FieldDescriptionRHF.js +41 -0
- package/dist/esm/components/FieldDescription/components/FieldWithAddButton.d.ts +7 -0
- package/dist/esm/components/FieldDescription/components/FieldWithAddButton.js +24 -0
- package/dist/esm/components/FieldDescription/components/index.d.ts +1 -0
- package/dist/esm/components/FieldDescription/components/index.js +1 -0
- package/dist/esm/components/FieldDescription/constants.d.ts +1 -0
- package/dist/esm/components/FieldDescription/constants.js +1 -0
- package/dist/esm/components/FieldDescription/index.d.ts +3 -0
- package/dist/esm/components/FieldDescription/index.js +3 -0
- package/dist/esm/components/FieldDescription/types.d.ts +17 -0
- package/dist/esm/components/FieldDescription/types.js +1 -0
- package/dist/esm/components/FieldMask/FieldMask.d.ts +12 -0
- package/dist/esm/components/FieldMask/FieldMask.js +24 -0
- package/dist/esm/components/FieldMask/constants.d.ts +19 -0
- package/dist/esm/components/FieldMask/constants.js +57 -0
- package/dist/esm/components/FieldMask/index.d.ts +3 -0
- package/dist/esm/components/FieldMask/index.js +3 -0
- package/dist/esm/components/FieldMask/types.d.ts +3 -0
- package/dist/esm/components/FieldMask/types.js +1 -0
- package/dist/esm/components/FieldName/FieldName.d.ts +5 -0
- package/dist/esm/components/FieldName/FieldName.js +78 -0
- package/dist/esm/components/FieldName/FieldNameRHF.d.ts +5 -0
- package/dist/esm/components/FieldName/FieldNameRHF.js +62 -0
- package/dist/esm/components/FieldName/constants.d.ts +1 -0
- package/dist/esm/components/FieldName/constants.js +1 -0
- package/dist/esm/components/FieldName/index.d.ts +3 -0
- package/dist/esm/components/FieldName/index.js +3 -0
- package/dist/esm/components/FieldName/types.d.ts +22 -0
- package/dist/esm/components/FieldName/types.js +1 -0
- package/dist/esm/components/FieldPhone/FieldPhone.d.ts +13 -0
- package/dist/esm/components/FieldPhone/FieldPhone.js +160 -0
- package/dist/esm/components/FieldPhone/constants.d.ts +8 -0
- package/dist/esm/components/FieldPhone/constants.js +8 -0
- package/dist/esm/components/FieldPhone/countries.d.ts +3500 -0
- package/dist/esm/components/FieldPhone/countries.js +1435 -0
- package/dist/esm/components/FieldPhone/hooks/index.d.ts +2 -0
- package/dist/esm/components/FieldPhone/hooks/index.js +2 -0
- package/dist/esm/components/FieldPhone/hooks/useCountries.d.ts +2 -0
- package/dist/esm/components/FieldPhone/hooks/useCountries.js +33 -0
- package/dist/esm/components/FieldPhone/hooks/useMapCountryToOptions.d.ts +2 -0
- package/dist/esm/components/FieldPhone/hooks/useMapCountryToOptions.js +17 -0
- package/dist/esm/components/FieldPhone/index.d.ts +5 -0
- package/dist/esm/components/FieldPhone/index.js +5 -0
- package/dist/esm/components/FieldPhone/styles.module.css +3 -0
- package/dist/esm/components/FieldPhone/types.d.ts +31 -0
- package/dist/esm/components/FieldPhone/types.js +1 -0
- package/dist/esm/components/FieldPhone/utils.d.ts +14 -0
- package/dist/esm/components/FieldPhone/utils.js +78 -0
- package/dist/esm/components/FieldSelectCreate/FieldSelectCreate.d.ts +8 -0
- package/dist/esm/components/FieldSelectCreate/FieldSelectCreate.js +60 -0
- package/dist/esm/components/FieldSelectCreate/constants.d.ts +14 -0
- package/dist/esm/components/FieldSelectCreate/constants.js +14 -0
- package/dist/esm/components/FieldSelectCreate/helperComponents/SelectFooter/SelectFooter.d.ts +8 -0
- package/dist/esm/components/FieldSelectCreate/helperComponents/SelectFooter/SelectFooter.js +13 -0
- package/dist/esm/components/FieldSelectCreate/helperComponents/SelectFooter/index.d.ts +1 -0
- package/dist/esm/components/FieldSelectCreate/helperComponents/SelectFooter/index.js +1 -0
- package/dist/esm/components/FieldSelectCreate/helperComponents/SelectFooter/styles.module.css +6 -0
- package/dist/esm/components/FieldSelectCreate/index.d.ts +3 -0
- package/dist/esm/components/FieldSelectCreate/index.js +3 -0
- package/dist/esm/components/FieldSelectCreate/styles.module.css +9 -0
- package/dist/esm/components/FieldSelectCreate/types.d.ts +58 -0
- package/dist/esm/components/FieldSelectCreate/types.js +1 -0
- package/dist/esm/components/FieldSelectCreate/useSelectDataStates.d.ts +11 -0
- package/dist/esm/components/FieldSelectCreate/useSelectDataStates.js +26 -0
- package/dist/esm/components/FieldSelectCreate/utils.d.ts +2 -0
- package/dist/esm/components/FieldSelectCreate/utils.js +4 -0
- package/dist/esm/components/index.d.ts +7 -0
- package/dist/esm/components/index.js +7 -0
- package/dist/esm/constants.d.ts +19 -0
- package/dist/esm/constants.js +19 -0
- package/dist/esm/helpers/getSymbolsRangeFromMask.d.ts +7 -0
- package/dist/esm/helpers/getSymbolsRangeFromMask.js +12 -0
- package/dist/esm/helpers/index.d.ts +1 -0
- package/dist/esm/helpers/index.js +1 -0
- package/dist/esm/hooks/index.d.ts +2 -0
- package/dist/esm/hooks/index.js +2 -0
- package/dist/esm/hooks/useCustomFieldValidation.d.ts +12 -0
- package/dist/esm/hooks/useCustomFieldValidation.js +28 -0
- package/dist/esm/hooks/useOpen.d.ts +5 -0
- package/dist/esm/hooks/useOpen.js +15 -0
- package/dist/esm/index.d.ts +6 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/locale/index.d.ts +845 -0
- package/dist/esm/locale/index.js +426 -0
- package/dist/esm/style.css +136 -0
- package/dist/tsconfig.cjs.tsbuildinfo +1 -0
- package/dist/tsconfig.esm.tsbuildinfo +1 -0
- package/package.json +74 -0
- package/src/components/FieldChat/FieldChat.tsx +113 -0
- package/src/components/FieldChat/components/Attachments/Attachments.tsx +31 -0
- package/src/components/FieldChat/components/Attachments/index.ts +1 -0
- package/src/components/FieldChat/components/Attachments/styles.module.scss +19 -0
- package/src/components/FieldChat/components/FieldSubmitButton/FieldSubmitButton.tsx +71 -0
- package/src/components/FieldChat/components/FieldSubmitButton/index.ts +1 -0
- package/src/components/FieldChat/components/FieldSubmitButton/styles.module.scss +6 -0
- package/src/components/FieldChat/components/TextAreaActionsFooter/TextAreaActionsFooter.tsx +19 -0
- package/src/components/FieldChat/components/TextAreaActionsFooter/index.ts +1 -0
- package/src/components/FieldChat/components/TextAreaActionsFooter/styles.module.scss +29 -0
- package/src/components/FieldChat/index.ts +2 -0
- package/src/components/FieldChat/styles.module.scss +20 -0
- package/src/components/FieldChat/types.ts +29 -0
- package/src/components/FieldCode/FieldCode.tsx +138 -0
- package/src/components/FieldCode/components/Cell/Cell.tsx +35 -0
- package/src/components/FieldCode/components/Cell/index.ts +1 -0
- package/src/components/FieldCode/components/Cell/styles.module.scss +27 -0
- package/src/components/FieldCode/components/ResendCode/ResendCode.tsx +41 -0
- package/src/components/FieldCode/components/ResendCode/index.ts +1 -0
- package/src/components/FieldCode/components/ResendCode/utils.ts +5 -0
- package/src/components/FieldCode/components/index.ts +2 -0
- package/src/components/FieldCode/constants.ts +2 -0
- package/src/components/FieldCode/hooks/index.ts +5 -0
- package/src/components/FieldCode/hooks/useCodeInput.ts +146 -0
- package/src/components/FieldCode/hooks/useFieldCodeOverflow.ts +53 -0
- package/src/components/FieldCode/hooks/useFieldCodeValidate.ts +32 -0
- package/src/components/FieldCode/hooks/useFieldHelpers.ts +45 -0
- package/src/components/FieldCode/hooks/useFocusCell.ts +26 -0
- package/src/components/FieldCode/hooks/useRefState.ts +23 -0
- package/src/components/FieldCode/index.ts +3 -0
- package/src/components/FieldCode/styles.module.scss +51 -0
- package/src/components/FieldCode/utils.ts +23 -0
- package/src/components/FieldDescription/FieldDescription.tsx +98 -0
- package/src/components/FieldDescription/FieldDescriptionRHF.tsx +93 -0
- package/src/components/FieldDescription/components/FieldWithAddButton.tsx +51 -0
- package/src/components/FieldDescription/components/index.ts +1 -0
- package/src/components/FieldDescription/constants.ts +1 -0
- package/src/components/FieldDescription/index.ts +3 -0
- package/src/components/FieldDescription/types.ts +23 -0
- package/src/components/FieldMask/FieldMask.tsx +56 -0
- package/src/components/FieldMask/constants.ts +70 -0
- package/src/components/FieldMask/index.ts +3 -0
- package/src/components/FieldMask/types.ts +5 -0
- package/src/components/FieldName/FieldName.tsx +126 -0
- package/src/components/FieldName/FieldNameRHF.tsx +114 -0
- package/src/components/FieldName/constants.ts +1 -0
- package/src/components/FieldName/index.ts +3 -0
- package/src/components/FieldName/types.ts +28 -0
- package/src/components/FieldPhone/FieldPhone.tsx +264 -0
- package/src/components/FieldPhone/constants.ts +10 -0
- package/src/components/FieldPhone/countries.tsx +1755 -0
- package/src/components/FieldPhone/hooks/index.ts +2 -0
- package/src/components/FieldPhone/hooks/useCountries.ts +40 -0
- package/src/components/FieldPhone/hooks/useMapCountryToOptions.ts +25 -0
- package/src/components/FieldPhone/index.ts +5 -0
- package/src/components/FieldPhone/styles.module.scss +9 -0
- package/src/components/FieldPhone/types.ts +32 -0
- package/src/components/FieldPhone/utils.ts +112 -0
- package/src/components/FieldSelectCreate/FieldSelectCreate.tsx +133 -0
- package/src/components/FieldSelectCreate/constants.ts +15 -0
- package/src/components/FieldSelectCreate/helperComponents/SelectFooter/SelectFooter.tsx +37 -0
- package/src/components/FieldSelectCreate/helperComponents/SelectFooter/index.ts +1 -0
- package/src/components/FieldSelectCreate/helperComponents/SelectFooter/styles.module.scss +8 -0
- package/src/components/FieldSelectCreate/index.ts +3 -0
- package/src/components/FieldSelectCreate/styles.module.scss +12 -0
- package/src/components/FieldSelectCreate/types.ts +70 -0
- package/src/components/FieldSelectCreate/useSelectDataStates.tsx +57 -0
- package/src/components/FieldSelectCreate/utils.ts +4 -0
- package/src/components/index.ts +7 -0
- package/src/constants.ts +19 -0
- package/src/helpers/getSymbolsRangeFromMask.ts +15 -0
- package/src/helpers/index.ts +1 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useCustomFieldValidation.ts +38 -0
- package/src/hooks/useOpen.ts +22 -0
- package/src/index.ts +6 -0
- package/src/locale/index.ts +431 -0
package/README.md
ADDED
|
@@ -0,0 +1,1339 @@
|
|
|
1
|
+
# Fields Predefined
|
|
2
|
+
|
|
3
|
+
`@cloud-ru/ds-uikit-product-fields-predefined` — Набор предопределённых полей формы поверх @cloud-ru/ds-fields — телефон, маски, имя, описание, код и другие готовые сценарии ввода.
|
|
4
|
+
|
|
5
|
+
Пакет `@cloud-ru/ds-uikit-product-fields-predefined` — это готовые поля формы поверх `@cloud-ru/ds-fields` с заранее настроенным поведением: маски ввода, телефон с выбором страны, валидация имени и описания (yup + react-hook-form), код подтверждения. Каждое поле инкапсулирует свою логику (маскирование, детект страны, validation) и предоставляет чистое API в стиле `@ds`.
|
|
6
|
+
|
|
7
|
+
## Установка
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add @cloud-ru/ds-uikit-product-fields-predefined
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { FieldMask, FieldPhone } from '@cloud-ru/ds-uikit-product-fields-predefined'
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Состав пакета
|
|
18
|
+
|
|
19
|
+
- **`FieldMask`** — поле с предустановленной маской (uuid, code, passport, snils, ipv4).
|
|
20
|
+
- **`FieldName`** — имя с yup-валидацией символов и длины; standalone и react-hook-form варианты.
|
|
21
|
+
- **`FieldDescription`** — многострочное описание с валидацией длины, опциональным раскрытием по кнопке и react-hook-form вариантом.
|
|
22
|
+
- **`FieldPhone`** — телефон с выбором страны, динамической маской и авто-детектом страны при вставке.
|
|
23
|
+
- **`FieldChat`** — поле чата с многострочным вводом, прикреплением файлов и отправкой по Enter.
|
|
24
|
+
- **`FieldSelectCreate`** — выбор из списка с действием «Создать» и состояниями загрузки/ошибки/пустого результата.
|
|
25
|
+
- **`FieldCode`** — OTP-поле: код по ячейкам с автопереходом фокуса, resend-таймером и imperative ref.
|
|
26
|
+
|
|
27
|
+
## FieldMask
|
|
28
|
+
|
|
29
|
+
Поле ввода с предустановленной маской — uuid, code, passport, snils, ipv4 — поверх @cloud-ru/ds-fields FieldText.
|
|
30
|
+
|
|
31
|
+
Обёртка над `FieldText` из `@cloud-ru/ds-fields` с предустановленной маской ввода на `react-imask`. Маска, плейсхолдер и `inputMode` выбираются по пропу `mask` — поле само форматирует ввод и отдаёт значение через `onChange(value, mask)`.
|
|
32
|
+
|
|
33
|
+
### Когда использовать
|
|
34
|
+
|
|
35
|
+
- Нужен ввод строго форматированного значения: идентификатор (UUID), код, паспорт, СНИЛС, IPv4-адрес.
|
|
36
|
+
- Хочется готовую маску без ручной настройки `react-imask`.
|
|
37
|
+
|
|
38
|
+
Когда **не** нужен `FieldMask`:
|
|
39
|
+
|
|
40
|
+
- Произвольный текст без формата — **`FieldText`** напрямую.
|
|
41
|
+
- Телефон с выбором страны — **`FieldPhone`**.
|
|
42
|
+
|
|
43
|
+
### Анатомия
|
|
44
|
+
|
|
45
|
+
#### Mask
|
|
46
|
+
|
|
47
|
+
Предустановленный набор масок (проп `mask`, константа `MASK`):
|
|
48
|
+
|
|
49
|
+
- `uuid` — `XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX` (hex).
|
|
50
|
+
- `code` — `XXXX` (числовой код).
|
|
51
|
+
- `passport` — `XXXX XXXXXX`.
|
|
52
|
+
- `snils` — `XXXXXX-XXX XX`.
|
|
53
|
+
- `ip-v4-address` — `0[00].0[00].0[00].0[00]`.
|
|
54
|
+
- `ip-v4-address-with-mask` — IPv4 с CIDR-суффиксом `/NN`.
|
|
55
|
+
|
|
56
|
+
#### Size (default `m`)
|
|
57
|
+
|
|
58
|
+
Размер поля наследуется от `FieldText`:
|
|
59
|
+
|
|
60
|
+
- `s` — компактный.
|
|
61
|
+
- `m` — средний.
|
|
62
|
+
- `l` — крупный.
|
|
63
|
+
|
|
64
|
+
### Примеры использования
|
|
65
|
+
|
|
66
|
+
#### Типы масок
|
|
67
|
+
|
|
68
|
+
Разные предустановленные маски в одном ряду.
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
import { FieldMask, MASK } from '@cloud-ru/ds-uikit-product-fields-predefined';
|
|
72
|
+
|
|
73
|
+
export function FieldMaskMasks() {
|
|
74
|
+
return (
|
|
75
|
+
<div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', alignItems: 'flex-start' }}>
|
|
76
|
+
<FieldMask label='UUID' mask={MASK.Uuid} />
|
|
77
|
+
<FieldMask label='СНИЛС' mask={MASK.Snils} />
|
|
78
|
+
<FieldMask label='IPv4' mask={MASK.IpV4Address} />
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
#### Controlled
|
|
85
|
+
|
|
86
|
+
Контролируемое значение через value + onChange.
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
import { FieldMask, MASK } from '@cloud-ru/ds-uikit-product-fields-predefined';
|
|
90
|
+
import { useState } from 'react';
|
|
91
|
+
|
|
92
|
+
export function FieldMaskControlled() {
|
|
93
|
+
const [value, setValue] = useState('');
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<FieldMask
|
|
97
|
+
label='Код'
|
|
98
|
+
mask={MASK.Code}
|
|
99
|
+
value={value}
|
|
100
|
+
onChange={next => setValue(next)}
|
|
101
|
+
caption={`value: ${value || '—'}`}
|
|
102
|
+
/>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Props
|
|
108
|
+
|
|
109
|
+
**FieldMaskProps**
|
|
110
|
+
|
|
111
|
+
| Prop | Type | Default | Description |
|
|
112
|
+
|------|------|---------|-------------|
|
|
113
|
+
| `allowMoreThanMaxLength` | `boolean` | `false` | Разрешить ввод свыше `maxLength` символов (счётчик продолжит расти). |
|
|
114
|
+
| `autoComplete` | `string \| boolean` | `false` | Включен ли автокомплит для поля |
|
|
115
|
+
| `autoFocus` | `boolean` | `false` | Включен ли авто-фокус для поля |
|
|
116
|
+
| `background` | `boolean` | `true` | Фон поля (acrylic) |
|
|
117
|
+
| `caption` | `string` | — | Вторичная подпись справа |
|
|
118
|
+
| `className` | `string` | — | CSS-класс <br/> CSS-класс корня `FieldDecorator` |
|
|
119
|
+
| `data-test-id` | `string` | — | |
|
|
120
|
+
| `defaultValue` | `string` | — | Начальное значение (uncontrolled-режим) |
|
|
121
|
+
| `disabled` | `boolean` | `false` | Поле выключено <br/> Является ли поле деактивированным |
|
|
122
|
+
| `elementAfter` | `FieldElementButtonProps` \| `FieldElementSlot` | — | Слот справа (кнопка / селект с опциональным выпадающим списком) |
|
|
123
|
+
| `elementBefore` | `FieldElementButtonProps` \| `FieldElementSlot` | — | Слот слева (кнопка / селект с опциональным выпадающим списком) |
|
|
124
|
+
| `error` | `string` | — | Ошибка (приоритетнее `hint`; форсит `validationState=error`) |
|
|
125
|
+
| `fieldClassName` | `string` | — | CSS-класс оболочки поля ввода |
|
|
126
|
+
| `hint` | `string` | — | Подсказка |
|
|
127
|
+
| `iconAfter` | `ReactNode` | — | Иконка справа от строки ввода |
|
|
128
|
+
| `iconBefore` | `ReactNode` | — | Иконка слева от строки ввода |
|
|
129
|
+
| `id` | `string` | — | Значение html-атрибута id |
|
|
130
|
+
| `innerRef` | `Ref<HTMLDivElement>` | — | Ref на корневой DOM-элемент |
|
|
131
|
+
| `innerTestIds` | `{ shell?: string; input?: string; } \| undefined` | — | Идентификаторы внутренних слотов — оболочки и строки ввода. Нужны компонентам, которые <br/> рендерят `FieldCombo` под собственным именем (`FieldText`): их e2e адресует свои слоты, <br/> а не слоты `FieldCombo`. |
|
|
132
|
+
| `label` | `string` | — | Заголовок |
|
|
133
|
+
| `labelFor` | `string` | — | HTML-атрибут `for` для `<label>` |
|
|
134
|
+
| `labelTooltip` | `QuestionTooltipProps` | — | Подсказка (question-tooltip) у заголовка |
|
|
135
|
+
| `layoutPresets` | `FieldLayoutPresets` | — | Переопределение адаптивных дефолтов по раскладке. Участвует `autoFocus`: на mobile он выключен <br/> (открывает клавиатуру без действия). Вернуть на mobile — `layoutPresets={{ mobile: { autoFocus: true } }}`. |
|
|
136
|
+
| `length` | `FieldLength` | — | Счётчик длины `current/max` |
|
|
137
|
+
| `mask` | `"code"` \| `"ip-v4-address"` \| `"ip-v4-address-with-mask"` \| `"passport"` \| `"snils"` \| `"uuid"` | — | Предустановленная маска поля |
|
|
138
|
+
| `max` | `number` | — | Максимальное значение поля |
|
|
139
|
+
| `maxLength` | `number` | — | Максимальная длина вводимого значения |
|
|
140
|
+
| `min` | `number` | — | Минимальное значение поля |
|
|
141
|
+
| `name` | `string` | — | Значение html-атрибута name |
|
|
142
|
+
| `onBlur` | `FocusEventHandler<HTMLInputElement>` | — | Колбек обработки потери фокуса |
|
|
143
|
+
| `onChange` | `((value: string, mask: InputMask<Record<string, unknown>>) => void)` | — | Колбек смены значения; вторым аргументом — экземпляр маски imask |
|
|
144
|
+
| `onClearButtonClick` | `(() => void)` | — | Колбек клика по кнопке очистки |
|
|
145
|
+
| `onClick` | `MouseEventHandler<HTMLInputElement>` | — | Колбек обработки клика |
|
|
146
|
+
| `onCopyButtonClick` | `(() => void)` | — | Колбек после копирования значения в буфер |
|
|
147
|
+
| `onFocus` | `FocusEventHandler<HTMLInputElement>` | — | Колбек обработки получения фокуса |
|
|
148
|
+
| `onKeyDown` | `KeyboardEventHandler<HTMLInputElement>` | — | Колбек обработки начала нажатия клавиши клавиатуры |
|
|
149
|
+
| `onMouseDown` | `MouseEventHandler<HTMLInputElement>` | — | Колбек обработки нажатия кнопки мыши |
|
|
150
|
+
| `onPaste` | `ClipboardEventHandler<HTMLInputElement>` | — | Колбек обработки вставки значения |
|
|
151
|
+
| `outline` | `boolean` | `true` | Разделитель между основным полем и слотами `elementBefore` / `elementAfter` |
|
|
152
|
+
| `pattern` | `string` | — | Регулярное выражение валидного инпута |
|
|
153
|
+
| `placeholder` | `string` | — | Значение плейсхолдера |
|
|
154
|
+
| `postfix` | `ReactNode` | — | Постфикс (текст или нода) |
|
|
155
|
+
| `prefix` | `ReactNode` | — | Префикс (текст или нода) |
|
|
156
|
+
| `prefixIcon` | `ReactNode` | — | Ведущая иконка. <br/> @deprecated Используйте `iconBefore` — он приоритетнее, если заданы оба. |
|
|
157
|
+
| `readonly` | `boolean` | `false` | Только для чтения <br/> Является ли поле доступным только для чтения |
|
|
158
|
+
| `required` | `boolean` | — | Показать знак обязательности `*` |
|
|
159
|
+
| `showClearButton` | `boolean` | `true` | Показывать кнопку очистки значения (как в Search) |
|
|
160
|
+
| `showCopyButton` | `boolean` | `true` | Показывать кнопку копирования значения (только при `readonly = true` и непустом `value`) |
|
|
161
|
+
| `showHintIcon` | `boolean` | — | Отображение статус-иконки у подсказки (по умолчанию `true`) |
|
|
162
|
+
| `size` | `"l"` \| `"m"` \| `"s"` | `m` | Размер |
|
|
163
|
+
| `spellCheck` | `boolean` | `true` | Значение атрибута spellcheck (проверка орфографии) |
|
|
164
|
+
| `step` | `string \| number` | — | Максимальное значение поля |
|
|
165
|
+
| `tabIndex` | `number` | `0` | Значение атрибута tab-index |
|
|
166
|
+
| `type` | `"email"` \| `"number"` \| `"password"` \| `"tel"` \| `"text"` \| `"url"` | — | Тип инпута |
|
|
167
|
+
| `validationState` | `"default"` \| `"error"` \| `"success"` \| `"warning"` | — | Состояние валидации |
|
|
168
|
+
| `value` | `string` | — | Значение поля (controlled-режим) |
|
|
169
|
+
|
|
170
|
+
### Адаптивность
|
|
171
|
+
|
|
172
|
+
`autoFocus` на mobile выключается (наследуется из `@cloud-ru/ds-fields`) — автофокус там открывает экранную клавиатуру без действия пользователя. Раскладка читается из `AdaptiveProvider` (`@cloud-ru/ds-adaptive`); отдельного пропа `layoutType` нет. Вернуть автофокус на mobile — пропом `layoutPresets`:
|
|
173
|
+
|
|
174
|
+
```tsx
|
|
175
|
+
<FieldMask mask='uuid' autoFocus layoutPresets={{ mobile: { autoFocus: true } }} />
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
`size` от раскладки не зависит — задаётся пропом (по умолчанию `m`) одинаково на всех раскладках.
|
|
179
|
+
|
|
180
|
+
## FieldPhone
|
|
181
|
+
|
|
182
|
+
Телефонное поле с выбором страны, динамической маской по стране и авто-детектом страны при вставке номера.
|
|
183
|
+
|
|
184
|
+
Телефонное поле поверх `FieldText`. В ведущем слоте — селектор страны (`AdaptiveDroplist` из `@cloud-ru/ds-list`) с флагом и кодом; маска ввода динамически подстраивается под выбранную страну. При вставке номера из буфера страна определяется автоматически (`awesome-phonenumber`).
|
|
185
|
+
|
|
186
|
+
### Когда использовать
|
|
187
|
+
|
|
188
|
+
- Ввод телефона с международным выбором страны.
|
|
189
|
+
- Нужен авто-детект страны по вставленному номеру и маскирование под формат страны.
|
|
190
|
+
|
|
191
|
+
Когда **не** нужен `FieldPhone`:
|
|
192
|
+
|
|
193
|
+
- Произвольный форматированный ввод без телефона — **`FieldMask`**.
|
|
194
|
+
|
|
195
|
+
### Анатомия
|
|
196
|
+
|
|
197
|
+
#### Селектор страны
|
|
198
|
+
|
|
199
|
+
Ведущий слот (`elementBefore`) — флаг выбранной страны + код (`+7`, `+1`, …). Клик открывает `AdaptiveDroplist` со списком стран и поиском. Если доступна одна страна — селектор скрывается, остаётся только код в префиксе.
|
|
200
|
+
|
|
201
|
+
#### Mask
|
|
202
|
+
|
|
203
|
+
Маска ввода определяется выбранной страной (`country.mask`) и меняется при смене страны. Префикс с кодом страны добавляется к итоговому значению.
|
|
204
|
+
|
|
205
|
+
#### options — настройка списка стран
|
|
206
|
+
|
|
207
|
+
Проп `options` (`CountrySettings`) ограничивает или переопределяет список (взаимоисключающие поля):
|
|
208
|
+
|
|
209
|
+
- `includedCountries` — оставить только перечисленные страны.
|
|
210
|
+
- `excludedCountries` — исключить перечисленные из встроенного списка.
|
|
211
|
+
- `overriddenOptions` — полностью заменить список собственными опциями.
|
|
212
|
+
|
|
213
|
+
#### Size (default `m`)
|
|
214
|
+
|
|
215
|
+
Размер поля наследуется от `FieldText`: `s`, `m`, `l`.
|
|
216
|
+
|
|
217
|
+
### Примеры использования
|
|
218
|
+
|
|
219
|
+
#### Базовый
|
|
220
|
+
|
|
221
|
+
Телефон с полным списком стран и поиском.
|
|
222
|
+
|
|
223
|
+
```tsx
|
|
224
|
+
import { PortalContextProvider } from '@cloud-ru/ds-portal-context';
|
|
225
|
+
import { FieldPhone } from '@cloud-ru/ds-uikit-product-fields-predefined';
|
|
226
|
+
import { useRef, useState } from 'react';
|
|
227
|
+
|
|
228
|
+
export function FieldPhoneBasic() {
|
|
229
|
+
const hostRef = useRef<HTMLDivElement>(null);
|
|
230
|
+
const [value, setValue] = useState('');
|
|
231
|
+
|
|
232
|
+
return (
|
|
233
|
+
<PortalContextProvider root={hostRef}>
|
|
234
|
+
<div ref={hostRef} style={{ position: 'relative', width: 320 }}>
|
|
235
|
+
<FieldPhone label='Телефон' value={value} onChange={setValue} searchPlaceholder='Поиск страны' />
|
|
236
|
+
</div>
|
|
237
|
+
</PortalContextProvider>
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
#### Ограниченный список стран
|
|
243
|
+
|
|
244
|
+
options.includedCountries оставляет только страны СНГ.
|
|
245
|
+
|
|
246
|
+
```tsx
|
|
247
|
+
import { PortalContextProvider } from '@cloud-ru/ds-portal-context';
|
|
248
|
+
import {
|
|
249
|
+
ARMENIA_COUNTRY_CODE,
|
|
250
|
+
BELARUS_COUNTRY_CODE,
|
|
251
|
+
FieldPhone,
|
|
252
|
+
KAZAKHSTAN_COUNTRY_CODE,
|
|
253
|
+
RUSSIA_COUNTRY_CODE,
|
|
254
|
+
} from '@cloud-ru/ds-uikit-product-fields-predefined';
|
|
255
|
+
import { useRef, useState } from 'react';
|
|
256
|
+
|
|
257
|
+
export function FieldPhoneCountrySettings() {
|
|
258
|
+
const hostRef = useRef<HTMLDivElement>(null);
|
|
259
|
+
const [value, setValue] = useState('');
|
|
260
|
+
|
|
261
|
+
return (
|
|
262
|
+
<PortalContextProvider root={hostRef}>
|
|
263
|
+
<div ref={hostRef} style={{ position: 'relative', width: 320 }}>
|
|
264
|
+
<FieldPhone
|
|
265
|
+
label='Телефон (СНГ)'
|
|
266
|
+
value={value}
|
|
267
|
+
onChange={setValue}
|
|
268
|
+
options={{
|
|
269
|
+
includedCountries: [
|
|
270
|
+
RUSSIA_COUNTRY_CODE,
|
|
271
|
+
BELARUS_COUNTRY_CODE,
|
|
272
|
+
KAZAKHSTAN_COUNTRY_CODE,
|
|
273
|
+
ARMENIA_COUNTRY_CODE,
|
|
274
|
+
],
|
|
275
|
+
}}
|
|
276
|
+
/>
|
|
277
|
+
</div>
|
|
278
|
+
</PortalContextProvider>
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Props
|
|
284
|
+
|
|
285
|
+
**FieldPhoneProps**
|
|
286
|
+
|
|
287
|
+
| Prop | Type | Default | Description |
|
|
288
|
+
|------|------|---------|-------------|
|
|
289
|
+
| `autoComplete` | `string \| boolean` | `false` | Включен ли автокомплит для поля |
|
|
290
|
+
| `autoFocus` | `boolean` | `false` | Включен ли авто-фокус для поля |
|
|
291
|
+
| `background` | `boolean` | `true` | Фон поля (acrylic) |
|
|
292
|
+
| `caption` | `string` | — | Вторичная подпись справа |
|
|
293
|
+
| `className` | `string` | — | CSS-класс <br/> CSS-класс корня `FieldDecorator` |
|
|
294
|
+
| `data-test-id` | `string` | — | |
|
|
295
|
+
| `defaultValue` | `string` | — | Начальное значение (uncontrolled-режим) |
|
|
296
|
+
| `disabled` | `boolean` | `false` | Поле выключено <br/> Является ли поле деактивированным |
|
|
297
|
+
| `error` | `string` | — | Ошибка (приоритетнее `hint`; форсит `validationState=error`) |
|
|
298
|
+
| `fieldClassName` | `string` | — | CSS-класс оболочки поля ввода |
|
|
299
|
+
| `hint` | `string` | — | Подсказка |
|
|
300
|
+
| `iconAfter` | `ReactNode` | — | Иконка справа от строки ввода |
|
|
301
|
+
| `iconBefore` | `ReactNode` | — | Иконка слева от строки ввода |
|
|
302
|
+
| `id` | `string` | — | Значение html-атрибута id |
|
|
303
|
+
| `innerRef` | `Ref<HTMLDivElement>` | — | Ref на корневой DOM-элемент |
|
|
304
|
+
| `innerTestIds` | `{ shell?: string; input?: string; } \| undefined` | — | Идентификаторы внутренних слотов — оболочки и строки ввода. Нужны компонентам, которые <br/> рендерят `FieldCombo` под собственным именем (`FieldText`): их e2e адресует свои слоты, <br/> а не слоты `FieldCombo`. |
|
|
305
|
+
| `label` | `string` | — | Заголовок |
|
|
306
|
+
| `labelFor` | `string` | — | HTML-атрибут `for` для `<label>` |
|
|
307
|
+
| `labelTooltip` | `QuestionTooltipProps` | — | Подсказка (question-tooltip) у заголовка |
|
|
308
|
+
| `layoutPresets` | `FieldLayoutPresets` | — | Переопределение адаптивных дефолтов по раскладке. Участвует `autoFocus`: на mobile он выключен <br/> (открывает клавиатуру без действия). Вернуть на mobile — `layoutPresets={{ mobile: { autoFocus: true } }}`. |
|
|
309
|
+
| `length` | `FieldLength` | — | Счётчик длины `current/max` |
|
|
310
|
+
| `max` | `number` | — | Максимальное значение поля |
|
|
311
|
+
| `maxLength` | `number` | — | Максимальная длина вводимого значения |
|
|
312
|
+
| `min` | `number` | — | Минимальное значение поля |
|
|
313
|
+
| `name` | `string` | — | Значение html-атрибута name |
|
|
314
|
+
| `onBlur` | `FocusEventHandler<HTMLInputElement>` | — | Колбек обработки потери фокуса |
|
|
315
|
+
| `onChange` | `(((value: string) => void) & ((value: string) => void))` | — | Колбек смены значения |
|
|
316
|
+
| `onChangeCountry` | `((country: FieldPhoneOptionsProps) => void)` | — | |
|
|
317
|
+
| `onClearButtonClick` | `(() => void)` | — | Колбек клика по кнопке очистки |
|
|
318
|
+
| `onClick` | `MouseEventHandler<HTMLInputElement>` | — | Колбек обработки клика |
|
|
319
|
+
| `onCopyButtonClick` | `(() => void)` | — | Колбек после копирования значения в буфер |
|
|
320
|
+
| `onFocus` | `FocusEventHandler<HTMLInputElement>` | — | Колбек обработки получения фокуса |
|
|
321
|
+
| `onKeyDown` | `KeyboardEventHandler<HTMLInputElement>` | — | Колбек обработки начала нажатия клавиши клавиатуры |
|
|
322
|
+
| `onMouseDown` | `MouseEventHandler<HTMLInputElement>` | — | Колбек обработки нажатия кнопки мыши |
|
|
323
|
+
| `onPaste` | `ClipboardEventHandler<HTMLInputElement>` | — | Колбек обработки вставки значения |
|
|
324
|
+
| `options` | `CountrySettings` | — | Конфигурация для изменения стандартного списка стран |
|
|
325
|
+
| `outline` | `boolean` | `true` | Разделитель между основным полем и слотами `elementBefore` / `elementAfter` |
|
|
326
|
+
| `pattern` | `string` | — | Регулярное выражение валидного инпута |
|
|
327
|
+
| `readonly` | `boolean` | `false` | Только для чтения <br/> Является ли поле доступным только для чтения |
|
|
328
|
+
| `required` | `boolean` | — | Показать знак обязательности `*` |
|
|
329
|
+
| `scrollList` | `boolean` | — | Скролл с ограничением высоты для списка стран. По умолчанию включён. |
|
|
330
|
+
| `searchPlaceholder` | `string` | — | Плейсхолдер поля поиска в выпадающем списке стран |
|
|
331
|
+
| `showClearButton` | `boolean` | `true` | Показывать кнопку очистки значения (как в Search) |
|
|
332
|
+
| `showCopyButton` | `boolean` | `true` | Показывать кнопку копирования значения (только при `readonly = true` и непустом `value`) |
|
|
333
|
+
| `showHintIcon` | `boolean` | — | Отображение статус-иконки у подсказки (по умолчанию `true`) |
|
|
334
|
+
| `size` | `"l"` \| `"m"` \| `"s"` | — | Размер |
|
|
335
|
+
| `spellCheck` | `boolean` | `true` | Значение атрибута spellcheck (проверка орфографии) |
|
|
336
|
+
| `step` | `string \| number` | — | Максимальное значение поля |
|
|
337
|
+
| `tabIndex` | `number` | `0` | Значение атрибута tab-index |
|
|
338
|
+
| `type` | `"email"` \| `"number"` \| `"password"` \| `"tel"` \| `"text"` \| `"url"` | — | Тип инпута |
|
|
339
|
+
| `validationState` | `"default"` \| `"error"` \| `"success"` \| `"warning"` | — | Состояние валидации |
|
|
340
|
+
| `value` | `string` | — | Значение поля (controlled-режим) |
|
|
341
|
+
|
|
342
|
+
##### Related types
|
|
343
|
+
|
|
344
|
+
- `CountrySettings` = `({ overriddenOptions: FieldPhoneOptionsProps[]; } & { includedCountries?: undefined; excludedCountries?: undefined; }) | ({ includedCountries: Country[]; } & { overriddenOptions?: undefined; excludedCountries?: undefined; }) | ({ excludedCountries: Country[]; } & { overriddenOptions?: undefined; includedCountries?: undefined; })`
|
|
345
|
+
|
|
346
|
+
### Адаптивность
|
|
347
|
+
|
|
348
|
+
Выбор страны — адаптивный `Droplist` из `@cloud-ru/ds-list`: на desktop анкорный popover, на mobile — список в `BottomSheet`. Раскладку даёт `AdaptiveProvider` (`@cloud-ru/ds-adaptive`); отдельного пропа `layoutType` нет.
|
|
349
|
+
|
|
350
|
+
`autoFocus` на mobile выключается (наследуется из `@cloud-ru/ds-fields`) — вернуть можно пропом `layoutPresets={{ mobile: { autoFocus: true } }}`.
|
|
351
|
+
|
|
352
|
+
## FieldName
|
|
353
|
+
|
|
354
|
+
Поле «Имя» с встроенной yup-валидацией (латиница/цифры/.-_, до 64 символов) и режимом react-hook-form.
|
|
355
|
+
|
|
356
|
+
Поле ввода имени поверх `FieldText` с предустановленной yup-валидацией: только латиница, цифры, точка, дефис и подчёркивание; длина до 64 символов; по умолчанию обязательное. Лейбл и подпись подставляются из локали. Доступно в двух вариантах: standalone (`FieldName`, локальный стейт + `onValidationError`) и `FieldNameRHF` (интеграция с react-hook-form через `Controller`).
|
|
357
|
+
|
|
358
|
+
### Когда использовать
|
|
359
|
+
|
|
360
|
+
- Ввод технического имени сущности (сервис, ресурс, ключ) с ограничением на символы и длину.
|
|
361
|
+
- В форме на react-hook-form — вариант `FieldNameRHF`.
|
|
362
|
+
|
|
363
|
+
Когда **не** нужен `FieldName`:
|
|
364
|
+
|
|
365
|
+
- Произвольный текст без правил валидации — **`FieldText`**.
|
|
366
|
+
- Многострочное описание — **`FieldDescription`**.
|
|
367
|
+
|
|
368
|
+
### Анатомия
|
|
369
|
+
|
|
370
|
+
#### Валидация
|
|
371
|
+
|
|
372
|
+
Встроенная схема (yup):
|
|
373
|
+
|
|
374
|
+
- символы — `^[a-zA-Z0-9.\-_]*$` (иначе ошибка «недопустимые символы»);
|
|
375
|
+
- длина — до `maxLength` (по умолчанию 64), счётчик показывается при ошибке длины;
|
|
376
|
+
- `required` (по умолчанию `true`) — ошибка обязательности появляется после blur.
|
|
377
|
+
|
|
378
|
+
Через `customSchema` к встроенной схеме конкатенируются дополнительные правила. Так подключают data-зависимые проверки, которые компонент не может выполнить сам — например, уникальность имени по данным потребителя. Текст ошибки для этого случая уже есть в локали пакета (`FieldName.errorDuplicate` — «Такое название уже существует»):
|
|
379
|
+
|
|
380
|
+
```tsx
|
|
381
|
+
import { string } from 'yup'
|
|
382
|
+
import { fieldsPredefinedLocale } from '@cloud-ru/ds-uikit-product-fields-predefined/locale'
|
|
383
|
+
|
|
384
|
+
const { t } = fieldsPredefinedLocale.useTranslations()
|
|
385
|
+
|
|
386
|
+
const uniqueSchema = string().test('unique', t('FieldName.errorDuplicate'), value => !existingNames.includes(value ?? ''))
|
|
387
|
+
|
|
388
|
+
<FieldName customSchema={uniqueSchema} />
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
#### Режимы
|
|
392
|
+
|
|
393
|
+
- `FieldName` — локальный стейт, ошибка отдаётся через `onValidationError(error)`.
|
|
394
|
+
- `FieldNameRHF` — `controllerProps` для react-hook-form; валидация регистрируется как `validate` в `Controller`.
|
|
395
|
+
|
|
396
|
+
#### Size (default `m`)
|
|
397
|
+
|
|
398
|
+
Размер поля наследуется от `FieldText`: `s`, `m`, `l`.
|
|
399
|
+
|
|
400
|
+
### Примеры использования
|
|
401
|
+
|
|
402
|
+
#### Базовый
|
|
403
|
+
|
|
404
|
+
Standalone-режим с локальным стейтом и валидацией.
|
|
405
|
+
|
|
406
|
+
```tsx
|
|
407
|
+
import { FieldName } from '@cloud-ru/ds-uikit-product-fields-predefined';
|
|
408
|
+
import { useState } from 'react';
|
|
409
|
+
|
|
410
|
+
export function FieldNameBasic() {
|
|
411
|
+
const [value, setValue] = useState('');
|
|
412
|
+
|
|
413
|
+
return <FieldName value={value} onChange={setValue} />;
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
#### React Hook Form
|
|
418
|
+
|
|
419
|
+
FieldNameRHF внутри FormProvider.
|
|
420
|
+
|
|
421
|
+
```tsx
|
|
422
|
+
import { Button } from '@cloud-ru/ds-button';
|
|
423
|
+
import { FieldNameRHF } from '@cloud-ru/ds-uikit-product-fields-predefined';
|
|
424
|
+
import { FormProvider, useForm } from 'react-hook-form';
|
|
425
|
+
|
|
426
|
+
type FormValues = { serviceName: string };
|
|
427
|
+
|
|
428
|
+
export function FieldNameRHFExample() {
|
|
429
|
+
const methods = useForm<FormValues>({ defaultValues: { serviceName: '' }, mode: 'onBlur' });
|
|
430
|
+
|
|
431
|
+
return (
|
|
432
|
+
<FormProvider {...methods}>
|
|
433
|
+
<form
|
|
434
|
+
onSubmit={methods.handleSubmit(values => alert(`name: ${values.serviceName}`))}
|
|
435
|
+
style={{ display: 'flex', flexDirection: 'column', gap: 12, width: 320 }}
|
|
436
|
+
>
|
|
437
|
+
<FieldNameRHF controllerProps={{ name: 'serviceName' }} />
|
|
438
|
+
<Button type='submit' label='Отправить' />
|
|
439
|
+
</form>
|
|
440
|
+
</FormProvider>
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### Props
|
|
446
|
+
|
|
447
|
+
**FieldNameProps**
|
|
448
|
+
|
|
449
|
+
| Prop | Type | Default | Description |
|
|
450
|
+
|------|------|---------|-------------|
|
|
451
|
+
| `allowMoreThanMaxLength` | `boolean` | `false` | Разрешить ввод свыше `maxLength` символов (счётчик продолжит расти). |
|
|
452
|
+
| `autoComplete` | `string \| boolean` | `false` | Включен ли автокомплит для поля |
|
|
453
|
+
| `autoFocus` | `boolean` | `false` | Включен ли авто-фокус для поля |
|
|
454
|
+
| `background` | `boolean` | `true` | Фон поля (acrylic) |
|
|
455
|
+
| `className` | `string` | — | CSS-класс <br/> CSS-класс корня `FieldDecorator` |
|
|
456
|
+
| `customSchema` | `StringSchema<string, AnyObject, undefined, "">` | — | Дополнительная yup-схема, конкатенируется к встроенной (обязательность, длина, допустимые символы). <br/> Через неё подключают data-зависимые проверки, которые компонент не может выполнить сам — например, <br/> проверку уникальности имени по данным потребителя. Текст ошибки можно взять из локали пакета: <br/> `fieldsPredefinedLocale.useTranslations().t('FieldName.errorDuplicate')`. |
|
|
457
|
+
| `data-test-id` | `string` | — | |
|
|
458
|
+
| `defaultValue` | `string` | — | Начальное значение (uncontrolled-режим) |
|
|
459
|
+
| `disabled` | `boolean` | `false` | Поле выключено <br/> Является ли поле деактивированным |
|
|
460
|
+
| `elementAfter` | `FieldElementButtonProps` \| `FieldElementSlot` | — | Слот справа (кнопка / селект с опциональным выпадающим списком) |
|
|
461
|
+
| `elementBefore` | `FieldElementButtonProps` \| `FieldElementSlot` | — | Слот слева (кнопка / селект с опциональным выпадающим списком) |
|
|
462
|
+
| `error` | `string` | — | Ошибка (приоритетнее `hint`; форсит `validationState=error`) |
|
|
463
|
+
| `fieldClassName` | `string` | — | CSS-класс оболочки поля ввода |
|
|
464
|
+
| `iconAfter` | `ReactNode` | — | Иконка справа от строки ввода |
|
|
465
|
+
| `iconBefore` | `ReactNode` | — | Иконка слева от строки ввода |
|
|
466
|
+
| `id` | `string` | — | Значение html-атрибута id |
|
|
467
|
+
| `innerRef` | `Ref<HTMLDivElement>` | — | Ref на корневой DOM-элемент |
|
|
468
|
+
| `innerTestIds` | `{ shell?: string; input?: string; } \| undefined` | — | Идентификаторы внутренних слотов — оболочки и строки ввода. Нужны компонентам, которые <br/> рендерят `FieldCombo` под собственным именем (`FieldText`): их e2e адресует свои слоты, <br/> а не слоты `FieldCombo`. |
|
|
469
|
+
| `labelFor` | `string` | — | HTML-атрибут `for` для `<label>` |
|
|
470
|
+
| `labelTooltip` | `QuestionTooltipProps` | — | Подсказка (question-tooltip) у заголовка |
|
|
471
|
+
| `layoutPresets` | `FieldLayoutPresets` | — | Переопределение адаптивных дефолтов по раскладке. Участвует `autoFocus`: на mobile он выключен <br/> (открывает клавиатуру без действия). Вернуть на mobile — `layoutPresets={{ mobile: { autoFocus: true } }}`. |
|
|
472
|
+
| `length` | `FieldLength` | — | Счётчик длины `current/max` |
|
|
473
|
+
| `max` | `number` | — | Максимальное значение поля |
|
|
474
|
+
| `maxLength` | `number` | — | Максимальная длина вводимого значения |
|
|
475
|
+
| `min` | `number` | — | Минимальное значение поля |
|
|
476
|
+
| `name` | `string` | — | Значение html-атрибута name |
|
|
477
|
+
| `onBlur` | `FocusEventHandler<HTMLInputElement>` | — | Колбек обработки потери фокуса |
|
|
478
|
+
| `onChange` | `((value: string) => void)` | — | Колбек смены значения |
|
|
479
|
+
| `onClearButtonClick` | `(() => void)` | — | Колбек клика по кнопке очистки |
|
|
480
|
+
| `onClick` | `MouseEventHandler<HTMLInputElement>` | — | Колбек обработки клика |
|
|
481
|
+
| `onCopyButtonClick` | `(() => void)` | — | Колбек после копирования значения в буфер |
|
|
482
|
+
| `onFocus` | `FocusEventHandler<HTMLInputElement>` | — | Колбек обработки получения фокуса |
|
|
483
|
+
| `onKeyDown` | `KeyboardEventHandler<HTMLInputElement>` | — | Колбек обработки начала нажатия клавиши клавиатуры |
|
|
484
|
+
| `onMouseDown` | `MouseEventHandler<HTMLInputElement>` | — | Колбек обработки нажатия кнопки мыши |
|
|
485
|
+
| `onPaste` | `ClipboardEventHandler<HTMLInputElement>` | — | Колбек обработки вставки значения |
|
|
486
|
+
| `onValidationError` | `((error: ValidationError \| null) => void)` | — | Колбэк, вызываемый при изменении ошибки валидации |
|
|
487
|
+
| `outline` | `boolean` | `true` | Разделитель между основным полем и слотами `elementBefore` / `elementAfter` |
|
|
488
|
+
| `pattern` | `string` | — | Регулярное выражение валидного инпута |
|
|
489
|
+
| `postfix` | `ReactNode` | — | Постфикс (текст или нода) |
|
|
490
|
+
| `prefix` | `ReactNode` | — | Префикс (текст или нода) |
|
|
491
|
+
| `prefixIcon` | `ReactNode` | — | Ведущая иконка. <br/> @deprecated Используйте `iconBefore` — он приоритетнее, если заданы оба. |
|
|
492
|
+
| `readonly` | `boolean` | `false` | Только для чтения <br/> Является ли поле доступным только для чтения |
|
|
493
|
+
| `required` | `boolean` | — | Показать знак обязательности `*` |
|
|
494
|
+
| `showClearButton` | `boolean` | `true` | Показывать кнопку очистки значения (как в Search) |
|
|
495
|
+
| `showCopyButton` | `boolean` | `true` | Показывать кнопку копирования значения (только при `readonly = true` и непустом `value`) |
|
|
496
|
+
| `showHintIcon` | `boolean` | — | Отображение статус-иконки у подсказки (по умолчанию `true`) |
|
|
497
|
+
| `showLabel` | `boolean` | — | Показывать предустановленный лейбл «Имя» |
|
|
498
|
+
| `size` | `"l"` \| `"m"` \| `"s"` | — | Размер |
|
|
499
|
+
| `spellCheck` | `boolean` | `true` | Значение атрибута spellcheck (проверка орфографии) |
|
|
500
|
+
| `step` | `string \| number` | — | Максимальное значение поля |
|
|
501
|
+
| `tabIndex` | `number` | `0` | Значение атрибута tab-index |
|
|
502
|
+
| `validationState` | `"default"` \| `"error"` \| `"success"` \| `"warning"` | — | Состояние валидации |
|
|
503
|
+
| `value` | `string` | — | Значение поля (controlled-режим) |
|
|
504
|
+
|
|
505
|
+
### Адаптивность
|
|
506
|
+
|
|
507
|
+
`autoFocus` на mobile выключается (наследуется из `@cloud-ru/ds-fields`) — автофокус там открывает экранную клавиатуру без действия пользователя. Раскладка читается из `AdaptiveProvider` (`@cloud-ru/ds-adaptive`); отдельного пропа `layoutType` нет. Вернуть автофокус на mobile — пропом `layoutPresets`:
|
|
508
|
+
|
|
509
|
+
```tsx
|
|
510
|
+
<FieldName autoFocus layoutPresets={{ mobile: { autoFocus: true } }} />
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
`size` от раскладки не зависит — задаётся пропом (по умолчанию `m`) одинаково на всех раскладках.
|
|
514
|
+
|
|
515
|
+
## FieldDescription
|
|
516
|
+
|
|
517
|
+
Многострочное поле описания с yup-валидацией длины, опциональным раскрытием по кнопке и режимом react-hook-form.
|
|
518
|
+
|
|
519
|
+
Многострочное поле описания поверх `FieldTextArea` с встроенной yup-валидацией длины (до 255 символов, со счётчиком). По умолчанию необязательное. Доступно в двух вариантах: standalone (`FieldDescription`, локальный стейт + `onValidationError`) и `FieldDescriptionRHF` (react-hook-form через `Controller`). Опционально может сворачиваться в кнопку «Добавить описание».
|
|
520
|
+
|
|
521
|
+
### Когда использовать
|
|
522
|
+
|
|
523
|
+
- Ввод необязательного/обязательного описания сущности с ограничением длины.
|
|
524
|
+
- В форме на react-hook-form — вариант `FieldDescriptionRHF`.
|
|
525
|
+
- Когда описание необязательно и его лучше скрыть до клика — `addButton`.
|
|
526
|
+
|
|
527
|
+
Когда **не** нужен `FieldDescription`:
|
|
528
|
+
|
|
529
|
+
- Короткое однострочное имя — **`FieldName`**.
|
|
530
|
+
|
|
531
|
+
### Анатомия
|
|
532
|
+
|
|
533
|
+
#### Валидация
|
|
534
|
+
|
|
535
|
+
Встроенная схема (yup): обрезка пробелов (`trim`) и ограничение длины `maxLength` (по умолчанию 255) с сообщением и счётчиком. `customSchema` конкатенируется к встроенной. При `required` добавляется проверка обязательности.
|
|
536
|
+
|
|
537
|
+
#### addButton
|
|
538
|
+
|
|
539
|
+
Если `addButton` и поле необязательное (`required={false}`) — вместо textarea показывается кнопка «Добавить описание». Клик раскрывает поле и ставит в него фокус.
|
|
540
|
+
|
|
541
|
+
#### Режимы
|
|
542
|
+
|
|
543
|
+
- `FieldDescription` — локальный стейт, ошибка отдаётся через `onValidationError(error)`.
|
|
544
|
+
- `FieldDescriptionRHF` — `controllerProps` для react-hook-form.
|
|
545
|
+
|
|
546
|
+
#### Size (default `m`)
|
|
547
|
+
|
|
548
|
+
Размер поля наследуется от `FieldTextArea`: `s`, `m`, `l`.
|
|
549
|
+
|
|
550
|
+
### Примеры использования
|
|
551
|
+
|
|
552
|
+
#### Базовый
|
|
553
|
+
|
|
554
|
+
Standalone-режим с валидацией длины.
|
|
555
|
+
|
|
556
|
+
```tsx
|
|
557
|
+
import { FieldDescription } from '@cloud-ru/ds-uikit-product-fields-predefined';
|
|
558
|
+
|
|
559
|
+
export function FieldDescriptionBasic() {
|
|
560
|
+
return <FieldDescription />;
|
|
561
|
+
}
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
#### С кнопкой «Добавить»
|
|
565
|
+
|
|
566
|
+
Необязательное поле, свёрнутое в кнопку.
|
|
567
|
+
|
|
568
|
+
```tsx
|
|
569
|
+
import { FieldDescription } from '@cloud-ru/ds-uikit-product-fields-predefined';
|
|
570
|
+
|
|
571
|
+
export function FieldDescriptionWithAddButton() {
|
|
572
|
+
return <FieldDescription addButton />;
|
|
573
|
+
}
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
#### React Hook Form
|
|
577
|
+
|
|
578
|
+
FieldDescriptionRHF внутри FormProvider.
|
|
579
|
+
|
|
580
|
+
```tsx
|
|
581
|
+
import { Button } from '@cloud-ru/ds-button';
|
|
582
|
+
import { FieldDescriptionRHF } from '@cloud-ru/ds-uikit-product-fields-predefined';
|
|
583
|
+
import { FormProvider, useForm } from 'react-hook-form';
|
|
584
|
+
|
|
585
|
+
type FormValues = { description: string };
|
|
586
|
+
|
|
587
|
+
export function FieldDescriptionRHFExample() {
|
|
588
|
+
const methods = useForm<FormValues>({ defaultValues: { description: '' }, mode: 'onBlur' });
|
|
589
|
+
|
|
590
|
+
return (
|
|
591
|
+
<FormProvider {...methods}>
|
|
592
|
+
<form
|
|
593
|
+
onSubmit={methods.handleSubmit(values => alert(`description: ${values.description}`))}
|
|
594
|
+
style={{ display: 'flex', flexDirection: 'column', gap: 12, width: 360 }}
|
|
595
|
+
>
|
|
596
|
+
<FieldDescriptionRHF controllerProps={{ name: 'description' }} />
|
|
597
|
+
<Button type='submit' label='Отправить' />
|
|
598
|
+
</form>
|
|
599
|
+
</FormProvider>
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
### Props
|
|
605
|
+
|
|
606
|
+
**FieldDescriptionProps**
|
|
607
|
+
|
|
608
|
+
| Prop | Type | Default | Description |
|
|
609
|
+
|------|------|---------|-------------|
|
|
610
|
+
| `addButton` | `boolean` | — | Поле появляется по кнопке «Добавить описание» (только для опционального поля) |
|
|
611
|
+
| `allowMoreThanMaxLength` | `boolean` | `true` | Разрешить ввод свыше `maxLength` символов (счётчик продолжит расти). |
|
|
612
|
+
| `autoFocus` | `boolean` | — | Автофокус. На mobile выключается адаптивно (см. `layoutPresets`) |
|
|
613
|
+
| `background` | `boolean` | `true` | Фон поля (acrylic) |
|
|
614
|
+
| `className` | `string` | — | CSS-класс <br/> CSS-класс корня `FieldDecorator` |
|
|
615
|
+
| `customSchema` | `StringSchema<string, AnyObject, undefined, "">` | — | Дополнительная yup-схема, которая конкатенируется к встроенной |
|
|
616
|
+
| `data-test-id` | `string` | — | |
|
|
617
|
+
| `defaultValue` | `string` | — | Начальное значение (uncontrolled-режим) |
|
|
618
|
+
| `disabled` | `boolean` | — | Поле выключено |
|
|
619
|
+
| `error` | `string` | — | Ошибка (приоритетнее `hint`; форсит `validationState=error`) |
|
|
620
|
+
| `fieldClassName` | `string` | — | CSS-класс оболочки поля |
|
|
621
|
+
| `header` | `ReactNode` | — | Нода над textarea — ряд элементов до контента (Figma `elementWrapperBefore` / <br/> `slotBeforeContent`): тулбар с кнопками, чипами и т.п. |
|
|
622
|
+
| `id` | `string` | — | HTML id |
|
|
623
|
+
| `innerRef` | `Ref<HTMLDivElement>` | — | Ref на корневой DOM-элемент |
|
|
624
|
+
| `labelFor` | `string` | — | HTML-атрибут `for` для `<label>` |
|
|
625
|
+
| `labelTooltip` | `QuestionTooltipProps` | — | Подсказка (question-tooltip) у заголовка |
|
|
626
|
+
| `layoutPresets` | `FieldLayoutPresets` | — | Переопределение адаптивных дефолтов по раскладке. Участвует `autoFocus`: на mobile он выключен <br/> (открывает клавиатуру без действия). Вернуть на mobile — `layoutPresets={{ mobile: { autoFocus: true } }}`. |
|
|
627
|
+
| `length` | `FieldLength` | — | Счётчик длины `current/max` |
|
|
628
|
+
| `maxLength` | `number` | `255` | Максимальное количество символов |
|
|
629
|
+
| `maxRows` | `number` | `1000` | Максимальное количество строк (после — появляется скролл) |
|
|
630
|
+
| `minRows` | `number` | `3` | Минимальное количество строк |
|
|
631
|
+
| `onBlur` | `((event: FocusEvent<HTMLTextAreaElement, Element>) => void)` | — | Колбек блюра |
|
|
632
|
+
| `onChange` | `((value: string, event?: ChangeEvent<HTMLTextAreaElement>) => void)` | — | Колбек смены значения |
|
|
633
|
+
| `onCopyButtonClick` | `(() => void)` | — | Колбек после копирования |
|
|
634
|
+
| `onFocus` | `((event: FocusEvent<HTMLTextAreaElement, Element>) => void)` | — | Колбек фокуса |
|
|
635
|
+
| `onKeyDown` | `((event: KeyboardEvent<HTMLTextAreaElement>) => void)` | — | Колбек нажатия клавиши |
|
|
636
|
+
| `onValidationError` | `((error: ValidationError \| null) => void)` | — | Колбэк, вызываемый при изменении ошибки валидации (только в standalone-режиме) |
|
|
637
|
+
| `readonly` | `boolean` | — | Только для чтения |
|
|
638
|
+
| `required` | `boolean` | `false` | Показать знак обязательности `*` |
|
|
639
|
+
| `resizable` | `boolean` | `true` | Можно ли менять высоту мышкой за нижний угол. Игнорируется при `disabled` или `readonly`. |
|
|
640
|
+
| `showClearButton` | `boolean` | `true` | Кнопка очистки (видна при value && !readonly) |
|
|
641
|
+
| `showCopyButton` | `boolean` | `true` | Кнопка копирования (видна при value && !disabled, независимо от readonly) |
|
|
642
|
+
| `showHintIcon` | `boolean` | — | Отображение статус-иконки у подсказки (по умолчанию `true`) |
|
|
643
|
+
| `size` | `"l"` \| `"m"` \| `"s"` | `m` | Размер |
|
|
644
|
+
| `spellCheck` | `boolean` | — | Проверка орфографии |
|
|
645
|
+
| `validationState` | `"default"` \| `"error"` \| `"success"` \| `"warning"` | — | Состояние валидации |
|
|
646
|
+
| `value` | `string` | — | Значение (controlled-режим) |
|
|
647
|
+
|
|
648
|
+
### Адаптивность
|
|
649
|
+
|
|
650
|
+
`autoFocus` на mobile выключается (наследуется из `@cloud-ru/ds-fields`) — автофокус там открывает экранную клавиатуру без действия пользователя. Раскладка читается из `AdaptiveProvider` (`@cloud-ru/ds-adaptive`); отдельного пропа `layoutType` нет. Вернуть автофокус на mobile — пропом `layoutPresets`:
|
|
651
|
+
|
|
652
|
+
```tsx
|
|
653
|
+
<FieldDescription autoFocus layoutPresets={{ mobile: { autoFocus: true } }} />
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
`size` от раскладки не зависит — задаётся пропом (по умолчанию `m`) одинаково на всех раскладках.
|
|
657
|
+
|
|
658
|
+
## FieldSelectCreate
|
|
659
|
+
|
|
660
|
+
Поле выбора из списка с действием «Создать» — под полем и в футере пустых состояний дроплиста; состояния data/error/noData/noResult и поиск.
|
|
661
|
+
|
|
662
|
+
Поле выбора поверх `FieldSelect` из `@cloud-ru/ds-fields` со встроенной формой создания опции. Кнопка `+ Создать <entityName>` показывается под полем и в футере дроплиста; по клику открывается форма в `Drawer` или `Modal`. Пропсы поля передаются через `selectProps`, состояния списка и поиск — из `@cloud-ru/ds-list`.
|
|
663
|
+
|
|
664
|
+
### Когда использовать
|
|
665
|
+
|
|
666
|
+
- Выбор из списка, где пользователь может тут же создать новый объект, если нужного нет.
|
|
667
|
+
- Асинхронная подгрузка с состояниями загрузки/ошибки/пустого результата.
|
|
668
|
+
|
|
669
|
+
Когда **не** нужен `FieldSelectCreate`:
|
|
670
|
+
|
|
671
|
+
- Простой выбор без создания — используйте `FieldSelect` из `@cloud-ru/ds-fields`.
|
|
672
|
+
|
|
673
|
+
### Анатомия
|
|
674
|
+
|
|
675
|
+
#### Действие «Создать»
|
|
676
|
+
|
|
677
|
+
Кнопка `+ Создать <entityName>` рендерится в двух местах: под полем и в футере дроплиста (`SelectFooter`). По клику открывается форма создания:
|
|
678
|
+
|
|
679
|
+
- `Drawer` (по умолчанию) или `Modal` — задаётся через `createLayoutType`.
|
|
680
|
+
- Содержимое формы и заголовок задаются в `createLayoutProps` (`content` — форма, `title` — заголовок).
|
|
681
|
+
- Кнопки «Создать» / «Отмена» добавляет сам компонент; на «Создать» вызывается `submitHandler`.
|
|
682
|
+
- `submitHandler` возвращает `value` новой опции — в single-режиме она выбирается в поле; `afterClose` — колбэк после закрытия.
|
|
683
|
+
|
|
684
|
+
#### entityName
|
|
685
|
+
|
|
686
|
+
Название сущности в единственном (`single`, вин. падеж) и множественном (`plural`) числе. Из них собираются тексты: кнопка «Создать `single`», пустые состояния «`plural` не обнаружены / не найдены», ошибка «Не удалось загрузить `plural`».
|
|
687
|
+
|
|
688
|
+
#### Права (`permission`, default `canCreate`)
|
|
689
|
+
|
|
690
|
+
Ограничивает доступ к чтению и созданию:
|
|
691
|
+
|
|
692
|
+
- `canCreate` — доступны и выбор, и создание.
|
|
693
|
+
- `canRead` — поле активно, но кнопки «Создать» недоступны (с tooltip причины).
|
|
694
|
+
- `none` — поле недоступно (с tooltip).
|
|
695
|
+
|
|
696
|
+
#### Состояния списка
|
|
697
|
+
|
|
698
|
+
Управляются `@cloud-ru/ds-list` по флагам `loading` / `dataError` / `dataFiltered` (передаются через `selectProps`):
|
|
699
|
+
|
|
700
|
+
- `data` — список опций.
|
|
701
|
+
- `error` — «Не удалось загрузить `plural`» + кнопка «Обновить» (`onRefetch`).
|
|
702
|
+
- `noData` — «`plural` не обнаружены»; иконку задаёт `entityIcon` (по умолчанию — поиск).
|
|
703
|
+
- `noResult` — «`plural` не найдены. Измените запрос или создайте `single`».
|
|
704
|
+
|
|
705
|
+
#### Режим выбора (`selectProps.selection`, default `single`)
|
|
706
|
+
|
|
707
|
+
Наследуется от `FieldSelect`: `single` — одна опция, `multiple` — несколько. В `multiple` возвращённое из `submitHandler` значение **не** выбирается автоматически — выбор оставляется потребителю.
|
|
708
|
+
|
|
709
|
+
#### Size (default `m`)
|
|
710
|
+
|
|
711
|
+
Размер поля задаётся через `selectProps.size`: `s`, `m`, `l`.
|
|
712
|
+
|
|
713
|
+
#### Открытие на выбранном элементе (`selectProps.scrollToSelectedItem`)
|
|
714
|
+
|
|
715
|
+
`FieldSelect` проксирует `scrollToSelectedItem` из `@cloud-ru/ds-list` в дроплист — при открытии список прокручивается до выбранной опции:
|
|
716
|
+
|
|
717
|
+
```tsx
|
|
718
|
+
<FieldSelectCreate selectProps={{ scrollToSelectedItem: true }} … />
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
Работает и с `selectProps={{ virtualized: true }}`.
|
|
722
|
+
|
|
723
|
+
### Примеры использования
|
|
724
|
+
|
|
725
|
+
#### Базовый
|
|
726
|
+
|
|
727
|
+
«Создать» открывает форму создания; submitHandler добавляет опцию и выбирает её.
|
|
728
|
+
|
|
729
|
+
```tsx
|
|
730
|
+
import { FieldText } from '@cloud-ru/ds-fields';
|
|
731
|
+
import { ItemId } from '@cloud-ru/ds-list';
|
|
732
|
+
import { FieldSelectCreate } from '@cloud-ru/ds-uikit-product-fields-predefined';
|
|
733
|
+
import { useState } from 'react';
|
|
734
|
+
|
|
735
|
+
export function FieldSelectCreateBasic() {
|
|
736
|
+
const [items, setItems] = useState([
|
|
737
|
+
{ id: '1', content: { label: 'Production' } },
|
|
738
|
+
{ id: '2', content: { label: 'Staging' } },
|
|
739
|
+
]);
|
|
740
|
+
const [value, setValue] = useState<ItemId>();
|
|
741
|
+
const [name, setName] = useState('');
|
|
742
|
+
|
|
743
|
+
const submitHandler = () => {
|
|
744
|
+
const id = String(items.length + 1);
|
|
745
|
+
setItems(prev => [...prev, { id, content: { label: name.trim() || `Окружение ${id}` } }]);
|
|
746
|
+
setName('');
|
|
747
|
+
return Promise.resolve(id);
|
|
748
|
+
};
|
|
749
|
+
|
|
750
|
+
return (
|
|
751
|
+
<div style={{ width: 320 }}>
|
|
752
|
+
<FieldSelectCreate
|
|
753
|
+
entityName={{ single: 'Окружение', plural: 'Окружения' }}
|
|
754
|
+
selectProps={{ label: 'Окружение', items, value, onChange: setValue }}
|
|
755
|
+
createLayoutProps={{
|
|
756
|
+
title: 'Создание окружения',
|
|
757
|
+
content: <FieldText label='Название' value={name} onChange={setName} />,
|
|
758
|
+
}}
|
|
759
|
+
submitHandler={submitHandler}
|
|
760
|
+
/>
|
|
761
|
+
</div>
|
|
762
|
+
);
|
|
763
|
+
}
|
|
764
|
+
```
|
|
765
|
+
|
|
766
|
+
#### Асинхронная загрузка
|
|
767
|
+
|
|
768
|
+
Состояние ошибки с кнопкой «Обновить» (onRefetch).
|
|
769
|
+
|
|
770
|
+
```tsx
|
|
771
|
+
import { ItemId } from '@cloud-ru/ds-list';
|
|
772
|
+
import { FieldSelectCreate } from '@cloud-ru/ds-uikit-product-fields-predefined';
|
|
773
|
+
import { useState } from 'react';
|
|
774
|
+
|
|
775
|
+
export function FieldSelectCreateAsync() {
|
|
776
|
+
const [value, setValue] = useState<ItemId>();
|
|
777
|
+
const [loading, setLoading] = useState(false);
|
|
778
|
+
const [dataError, setDataError] = useState(true);
|
|
779
|
+
|
|
780
|
+
const load = () => {
|
|
781
|
+
setDataError(false);
|
|
782
|
+
setLoading(true);
|
|
783
|
+
setTimeout(() => setLoading(false), 800);
|
|
784
|
+
};
|
|
785
|
+
|
|
786
|
+
return (
|
|
787
|
+
<div style={{ width: 320 }}>
|
|
788
|
+
<FieldSelectCreate
|
|
789
|
+
entityName={{ single: 'Окружение', plural: 'Окружения' }}
|
|
790
|
+
selectProps={{
|
|
791
|
+
label: 'Окружение',
|
|
792
|
+
items: [{ id: '1', content: { label: 'Production' } }],
|
|
793
|
+
value,
|
|
794
|
+
onChange: setValue,
|
|
795
|
+
loading,
|
|
796
|
+
dataError,
|
|
797
|
+
}}
|
|
798
|
+
onRefetch={load}
|
|
799
|
+
createLayoutProps={{ title: 'Создание окружения', content: 'Форма создания' }}
|
|
800
|
+
submitHandler={() => Promise.resolve('1')}
|
|
801
|
+
/>
|
|
802
|
+
</div>
|
|
803
|
+
);
|
|
804
|
+
}
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
#### Форма в модальном окне
|
|
808
|
+
|
|
809
|
+
createLayoutType=modal — форма создания открывается в модальном окне.
|
|
810
|
+
|
|
811
|
+
```tsx
|
|
812
|
+
import { FieldText } from '@cloud-ru/ds-fields';
|
|
813
|
+
import { ItemId } from '@cloud-ru/ds-list';
|
|
814
|
+
import { CREATE_LAYOUT_TYPE, FieldSelectCreate } from '@cloud-ru/ds-uikit-product-fields-predefined';
|
|
815
|
+
import { useState } from 'react';
|
|
816
|
+
|
|
817
|
+
export function FieldSelectCreateModal() {
|
|
818
|
+
const [items, setItems] = useState([
|
|
819
|
+
{ id: '1', content: { label: 'Production' } },
|
|
820
|
+
{ id: '2', content: { label: 'Staging' } },
|
|
821
|
+
]);
|
|
822
|
+
const [value, setValue] = useState<ItemId>();
|
|
823
|
+
const [name, setName] = useState('');
|
|
824
|
+
|
|
825
|
+
const submitHandler = () => {
|
|
826
|
+
const id = String(items.length + 1);
|
|
827
|
+
setItems(prev => [...prev, { id, content: { label: name.trim() || `Окружение ${id}` } }]);
|
|
828
|
+
setName('');
|
|
829
|
+
return Promise.resolve(id);
|
|
830
|
+
};
|
|
831
|
+
|
|
832
|
+
return (
|
|
833
|
+
<div style={{ width: 320 }}>
|
|
834
|
+
<FieldSelectCreate
|
|
835
|
+
entityName={{ single: 'Окружение', plural: 'Окружения' }}
|
|
836
|
+
selectProps={{ label: 'Окружение', items, value, onChange: setValue }}
|
|
837
|
+
createLayoutType={CREATE_LAYOUT_TYPE.Modal}
|
|
838
|
+
createLayoutProps={{
|
|
839
|
+
title: 'Создание окружения',
|
|
840
|
+
content: <FieldText label='Название' value={name} onChange={setName} />,
|
|
841
|
+
}}
|
|
842
|
+
submitHandler={submitHandler}
|
|
843
|
+
/>
|
|
844
|
+
</div>
|
|
845
|
+
);
|
|
846
|
+
}
|
|
847
|
+
```
|
|
848
|
+
|
|
849
|
+
### Props
|
|
850
|
+
|
|
851
|
+
**FieldSelectCreateProps**
|
|
852
|
+
|
|
853
|
+
| Prop | Type | Default | Description |
|
|
854
|
+
|------|------|---------|-------------|
|
|
855
|
+
| `afterClose` | `(() => void)` | — | Колбэк после закрытия модалки/дровера создания. |
|
|
856
|
+
| `className` | `string` | — | CSS-класс корневой обёртки. |
|
|
857
|
+
| `createLayoutProps` | `ManagedLayoutKeys` \| `ModalProps` | — | Пропсы модалки создания (`content` — форма создания опции). <br/> Пропсы дровера создания (`content` — форма создания опции); `position` по умолчанию `right`. |
|
|
858
|
+
| `createLayoutType` | `"drawer"` \| `"modal"` | `drawer` | По клику на «Создать» открывается модальное окно. <br/> По клику на «Создать» открывается дровер (по умолчанию). |
|
|
859
|
+
| `data-test-id` | `string` | — | |
|
|
860
|
+
| `entityIcon` | `EntityIcon` | — | Иконка пустого состояния `noData` (по умолчанию — иконка поиска). |
|
|
861
|
+
| `entityName` | `EntityName` | — | Название сущности в единственном и множественном числе — для кнопок и пустых состояний. |
|
|
862
|
+
| `onRefetch` | `(() => void)` | — | Повтор загрузки в состоянии ошибки (кнопка «Обновить» в футере `errorDataState`). |
|
|
863
|
+
| `permission` | `"canCreate"` \| `"canRead"` \| `"none"` | `canCreate` | Права пользователя: <br/> - `canCreate` (по умолчанию) — доступны и выбор, и создание; <br/> - `canRead` — поле активно, но создание недоступно (кнопки «Создать» с tooltip); <br/> - `none` — поле недоступно (с tooltip). |
|
|
864
|
+
| `selectProps` | `DroplistListProps` \| `DroplistMobileSlots` \| `EmptyState` \| `FieldSelectDecoratorProps` \| `PublicListContextType` \| `ScrollProps` \| `SelectFieldProps` \| `SelectionState` | — | Пропсы, прокидываемые в `FieldSelect` (`@cloud-ru/ds-fields`). |
|
|
865
|
+
| `submitHandler` | `() => Promise<string \| void>` | — | Действие создания опции: возвращает `value` новой опции, которая выбирается в поле (single-режим). |
|
|
866
|
+
|
|
867
|
+
##### Related types
|
|
868
|
+
|
|
869
|
+
**EntityName**
|
|
870
|
+
|
|
871
|
+
| Prop | Type | Default | Description |
|
|
872
|
+
|------|------|---------|-------------|
|
|
873
|
+
| `plural` | `string` | — | Множественное число — для текстов пустых состояний и ошибки. |
|
|
874
|
+
| `single` | `string` | — | Единственное число (винительный падеж) — для кнопки «Создать <single>». |
|
|
875
|
+
|
|
876
|
+
- `ManagedLayoutKeys` = `"approveButton"` \| `"cancelButton"` \| `"onClose"` \| `"open"`
|
|
877
|
+
|
|
878
|
+
### Адаптивность
|
|
879
|
+
|
|
880
|
+
Дроплист — адаптивный `Droplist` из `@cloud-ru/ds-list`: на desktop анкорный popover, на mobile — список в `BottomSheet`. Раскладку даёт `AdaptiveProvider` (`@cloud-ru/ds-adaptive`); отдельного пропа `layoutType` нет.
|
|
881
|
+
|
|
882
|
+
`size` на всех раскладках — база `m`. Автофокус поля выключается на mobile (наследуется из `FieldSelect` / `@cloud-ru/ds-fields`); вернуть — через `selectProps={{ layoutPresets: { mobile: { autoFocus: true } } }}`.
|
|
883
|
+
|
|
884
|
+
## FieldChat
|
|
885
|
+
|
|
886
|
+
Поле чата с многострочным вводом, прикреплением файлов и кнопкой отправки (Enter — отправка, Shift+Enter — перенос строки).
|
|
887
|
+
|
|
888
|
+
Поле чата поверх `FieldTextArea`. Многострочный ввод с автоматическим ростом высоты (1–4 строки), футером действий (прикрепление файлов и отправка) и списком прикреплённых вложений. Enter отправляет сообщение, Shift+Enter переносит строку. Прикреплённые файлы на desktop показываются под полем, на mobile — над ним.
|
|
889
|
+
|
|
890
|
+
### Когда использовать
|
|
891
|
+
|
|
892
|
+
- Поле ввода сообщения в чате или диалоге с ассистентом.
|
|
893
|
+
- Нужно прикрепление файлов рядом с вводом и отправка по Enter.
|
|
894
|
+
|
|
895
|
+
Когда **не** нужен `FieldChat`:
|
|
896
|
+
|
|
897
|
+
- Многострочное описание сущности без отправки/вложений — **`FieldDescription`**.
|
|
898
|
+
- Произвольный многострочный текст — **`FieldTextArea`**.
|
|
899
|
+
|
|
900
|
+
### Анатомия
|
|
901
|
+
|
|
902
|
+
#### Ввод
|
|
903
|
+
|
|
904
|
+
`FieldTextArea` с `minRows=1` и `maxRows=4`: поле растёт по мере набора текста и дальше скроллится. Плейсхолдер берётся из локали.
|
|
905
|
+
|
|
906
|
+
#### Футер действий
|
|
907
|
+
|
|
908
|
+
- Скрепка (`FileUpload`) — прикрепление файлов; видна только при переданном `attachment`. Тип допустимых файлов задаётся через `attachment.accept`.
|
|
909
|
+
- Кнопка отправки — активна, когда есть непустой текст или хотя бы один файл; иначе disabled.
|
|
910
|
+
|
|
911
|
+
#### Вложения
|
|
912
|
+
|
|
913
|
+
`attachment.files` рендерятся карточками: `AttachmentSquare` на desktop, полноширинный `Attachment` на mobile. Удаление — через `attachment.onFileDelete`.
|
|
914
|
+
|
|
915
|
+
#### Клавиатура
|
|
916
|
+
|
|
917
|
+
- Enter — отправка (вызывает `handleSubmit(value)`), если ввод валиден.
|
|
918
|
+
- Shift+Enter — перенос строки без отправки.
|
|
919
|
+
|
|
920
|
+
### Примеры использования
|
|
921
|
+
|
|
922
|
+
#### Базовый
|
|
923
|
+
|
|
924
|
+
Многострочный ввод с отправкой по Enter.
|
|
925
|
+
|
|
926
|
+
```tsx
|
|
927
|
+
import { FieldChat } from '@cloud-ru/ds-uikit-product-fields-predefined';
|
|
928
|
+
import { useState } from 'react';
|
|
929
|
+
|
|
930
|
+
export function FieldChatBasic() {
|
|
931
|
+
const [value, setValue] = useState('');
|
|
932
|
+
|
|
933
|
+
return <FieldChat value={value} onChange={setValue} handleSubmit={() => setValue('')} />;
|
|
934
|
+
}
|
|
935
|
+
```
|
|
936
|
+
|
|
937
|
+
#### С вложениями
|
|
938
|
+
|
|
939
|
+
Прикрепление и удаление файлов, отправка очищает поле и список.
|
|
940
|
+
|
|
941
|
+
```tsx
|
|
942
|
+
import { FieldChat } from '@cloud-ru/ds-uikit-product-fields-predefined';
|
|
943
|
+
import { useState } from 'react';
|
|
944
|
+
|
|
945
|
+
export function FieldChatWithAttachments() {
|
|
946
|
+
const [value, setValue] = useState('');
|
|
947
|
+
const [files, setFiles] = useState<File[]>([]);
|
|
948
|
+
|
|
949
|
+
return (
|
|
950
|
+
<FieldChat
|
|
951
|
+
value={value}
|
|
952
|
+
onChange={setValue}
|
|
953
|
+
handleSubmit={() => {
|
|
954
|
+
setValue('');
|
|
955
|
+
setFiles([]);
|
|
956
|
+
}}
|
|
957
|
+
attachment={{
|
|
958
|
+
files,
|
|
959
|
+
accept: 'image/*,.pdf',
|
|
960
|
+
onFilesUpload: uploaded => setFiles(prev => [...prev, ...uploaded]),
|
|
961
|
+
onFileDelete: file => setFiles(prev => prev.filter(item => item !== file)),
|
|
962
|
+
}}
|
|
963
|
+
/>
|
|
964
|
+
);
|
|
965
|
+
}
|
|
966
|
+
```
|
|
967
|
+
|
|
968
|
+
### Props
|
|
969
|
+
|
|
970
|
+
**FieldChatProps**
|
|
971
|
+
|
|
972
|
+
| Prop | Type | Default | Description |
|
|
973
|
+
|------|------|---------|-------------|
|
|
974
|
+
| `allowMoreThanMaxLength` | `boolean` | `true` | Разрешить ввод свыше `maxLength` символов (счётчик продолжит расти). |
|
|
975
|
+
| `attachment` | `AttachmentSquareProps` \| `FileUploadProps` \| `NativeInputProps` | — | Прикрепление файлов |
|
|
976
|
+
| `autoFocus` | `boolean` | — | Автофокус. На mobile выключается адаптивно (см. `layoutPresets`) |
|
|
977
|
+
| `background` | `boolean` | `true` | Фон поля (acrylic) |
|
|
978
|
+
| `caption` | `string` | — | Вторичная подпись справа |
|
|
979
|
+
| `className` | `string` | — | CSS-класс <br/> CSS-класс корня `FieldDecorator` |
|
|
980
|
+
| `data-test-id` | `string` | — | |
|
|
981
|
+
| `defaultValue` | `string` | — | Начальное значение (uncontrolled-режим) |
|
|
982
|
+
| `disabled` | `boolean` | — | Поле выключено |
|
|
983
|
+
| `error` | `string` | — | Ошибка (приоритетнее `hint`; форсит `validationState=error`) |
|
|
984
|
+
| `fieldClassName` | `string` | — | CSS-класс оболочки поля |
|
|
985
|
+
| `handleSubmit` | `(value: string) => void` | — | Колбек действия при отправке |
|
|
986
|
+
| `header` | `ReactNode` | — | Нода над textarea — ряд элементов до контента (Figma `elementWrapperBefore` / <br/> `slotBeforeContent`): тулбар с кнопками, чипами и т.п. |
|
|
987
|
+
| `id` | `string` | — | HTML id |
|
|
988
|
+
| `innerRef` | `Ref<HTMLDivElement>` | — | Ref на корневой DOM-элемент |
|
|
989
|
+
| `inputMode` | `"decimal"` \| `"email"` \| `"none"` \| `"numeric"` \| `"search"` \| `"tel"` \| `"text"` \| `"url"` | — | Режим виртуальной клавиатуры (`inputmode` нативного `<textarea>`) |
|
|
990
|
+
| `labelFor` | `string` | — | HTML-атрибут `for` для `<label>` |
|
|
991
|
+
| `labelTooltip` | `QuestionTooltipProps` | — | Подсказка (question-tooltip) у заголовка |
|
|
992
|
+
| `layoutPresets` | `FieldLayoutPresets` | — | Переопределение адаптивных дефолтов по раскладке. Участвует `autoFocus`: на mobile он выключен <br/> (открывает клавиатуру без действия). Вернуть на mobile — `layoutPresets={{ mobile: { autoFocus: true } }}`. |
|
|
993
|
+
| `length` | `FieldLength` | — | Счётчик длины `current/max` |
|
|
994
|
+
| `maxLength` | `number` | — | Максимальное количество символов |
|
|
995
|
+
| `name` | `string` | — | HTML name |
|
|
996
|
+
| `onBlur` | `((event: FocusEvent<HTMLTextAreaElement, Element>) => void)` | — | Колбек блюра |
|
|
997
|
+
| `onChange` | `((value: string, event?: ChangeEvent<HTMLTextAreaElement>) => void)` | — | Колбек смены значения |
|
|
998
|
+
| `onCopyButtonClick` | `(() => void)` | — | Колбек после копирования |
|
|
999
|
+
| `onFocus` | `((event: FocusEvent<HTMLTextAreaElement, Element>) => void)` | — | Колбек фокуса |
|
|
1000
|
+
| `readonly` | `boolean` | — | Только для чтения |
|
|
1001
|
+
| `resizable` | `boolean` | `false` | Можно ли менять высоту мышкой за нижний угол. Игнорируется при `disabled` или `readonly`. |
|
|
1002
|
+
| `showClearButton` | `boolean` | `true` | Кнопка очистки (видна при value && !readonly) |
|
|
1003
|
+
| `showHintIcon` | `boolean` | — | Отображение статус-иконки у подсказки (по умолчанию `true`) |
|
|
1004
|
+
| `validationState` | `"default"` \| `"error"` \| `"success"` \| `"warning"` | — | Состояние валидации |
|
|
1005
|
+
| `value` | `string` | — | Значение (controlled-режим) |
|
|
1006
|
+
|
|
1007
|
+
### Адаптивность
|
|
1008
|
+
|
|
1009
|
+
Раскладку компонент берёт из `AdaptiveProvider` (`@cloud-ru/ds-adaptive`) — отдельного пропа `layoutType` нет. На mobile прикреплённые файлы показываются **над** полем полноширинными карточками `Attachment` (на desktop — под полем, `AttachmentSquare`). Размер поля от раскладки не зависит.
|
|
1010
|
+
|
|
1011
|
+
`autoFocus` на mobile выключается (наследуется из `@cloud-ru/ds-fields`) — он открывает экранную клавиатуру без действия пользователя. Вернуть на mobile — через `layoutPresets`:
|
|
1012
|
+
|
|
1013
|
+
```tsx
|
|
1014
|
+
<FieldChat autoFocus layoutPresets={{ mobile: { autoFocus: true } }} />
|
|
1015
|
+
```
|
|
1016
|
+
|
|
1017
|
+
Mobile включается автоматически при одном `<AdaptiveProvider>` в корне приложения (desktop-first).
|
|
1018
|
+
|
|
1019
|
+
## FieldCode
|
|
1020
|
+
|
|
1021
|
+
OTP-поле — код по ячейкам с автопереходом фокуса, вставкой кода целиком, resend-таймером и imperative ref.
|
|
1022
|
+
|
|
1023
|
+
Поле ввода одноразового кода (OTP): `codeLength` ячеек на `FieldText` из `@cloud-ru/ds-fields`, автопереход фокуса при вводе, вставка кода целиком из буфера, колбек `onComplete` при заполнении всех ячеек. Опционально — кнопка повторной отправки кода с таймером (`resendCode`) и хук валидации `useFieldCodeValidate`.
|
|
1024
|
+
|
|
1025
|
+
### Когда использовать
|
|
1026
|
+
|
|
1027
|
+
- Подтверждение по SMS/email-коду: пользователь вводит фиксированное число цифр.
|
|
1028
|
+
- Нужен автопереход фокуса между ячейками и вставка кода целиком.
|
|
1029
|
+
|
|
1030
|
+
Когда **не** нужен `FieldCode`:
|
|
1031
|
+
|
|
1032
|
+
- Числовой код как обычная строка без ячеек — **`FieldMask`** с маской `code`.
|
|
1033
|
+
|
|
1034
|
+
### Анатомия
|
|
1035
|
+
|
|
1036
|
+
#### Size (default `m`)
|
|
1037
|
+
|
|
1038
|
+
Размер ячеек и подписи наследуется от `FieldDecorator`:
|
|
1039
|
+
|
|
1040
|
+
- `s` — компактный (ячейка 32px).
|
|
1041
|
+
- `m` — средний (ячейка 40px).
|
|
1042
|
+
- `l` — крупный (ячейка 52px).
|
|
1043
|
+
|
|
1044
|
+
#### Слоты и состояния
|
|
1045
|
+
|
|
1046
|
+
- `label` — заголовок поля.
|
|
1047
|
+
- `error` / `invalidCode` — текст ошибки; `error` приоритетнее.
|
|
1048
|
+
- `showEmptyChars` — подсветка пустых ячеек (состояние «код не дописан»).
|
|
1049
|
+
- `spacing` — визуальный разрыв после указанных индексов (`[2]` для формата `XXX XXX`).
|
|
1050
|
+
- `stretchCells` — ячейки делят всю ширину контейнера; иначе фиксированная ширина по `size`.
|
|
1051
|
+
- `resendCode` — кнопка повторной отправки: заблокирована с таймером `mm:ss`, пока `secondsToNextResend > 0`.
|
|
1052
|
+
|
|
1053
|
+
#### Imperative ref (`FieldCodeRef`)
|
|
1054
|
+
|
|
1055
|
+
- `moveFocus(index)` — перенести фокус на ячейку.
|
|
1056
|
+
- `blurFields()` — снять фокус со всех ячеек.
|
|
1057
|
+
- `resetCode()` — сбросить значение.
|
|
1058
|
+
|
|
1059
|
+
### Примеры использования
|
|
1060
|
+
|
|
1061
|
+
#### Базовый
|
|
1062
|
+
|
|
1063
|
+
Uncontrolled-ввод кода с onComplete.
|
|
1064
|
+
|
|
1065
|
+
```tsx
|
|
1066
|
+
import { FieldCode } from '@cloud-ru/ds-uikit-product-fields-predefined';
|
|
1067
|
+
import { useState } from 'react';
|
|
1068
|
+
|
|
1069
|
+
export function FieldCodeBasic() {
|
|
1070
|
+
const [value, setValue] = useState('');
|
|
1071
|
+
const [completed, setCompleted] = useState('');
|
|
1072
|
+
|
|
1073
|
+
return (
|
|
1074
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 12, alignItems: 'center' }}>
|
|
1075
|
+
<FieldCode codeLength={6} label='Код подтверждения' value={value} onChange={setValue} onComplete={setCompleted} />
|
|
1076
|
+
<span>{completed ? `Код введён: ${completed}` : 'Введите 6 цифр'}</span>
|
|
1077
|
+
</div>
|
|
1078
|
+
);
|
|
1079
|
+
}
|
|
1080
|
+
```
|
|
1081
|
+
|
|
1082
|
+
#### Валидация
|
|
1083
|
+
|
|
1084
|
+
Хук useFieldCodeValidate: пустое значение и неполный код.
|
|
1085
|
+
|
|
1086
|
+
```tsx
|
|
1087
|
+
import { FieldCode, useFieldCodeValidate } from '@cloud-ru/ds-uikit-product-fields-predefined';
|
|
1088
|
+
import { useState } from 'react';
|
|
1089
|
+
|
|
1090
|
+
const CODE_LENGTH = 6;
|
|
1091
|
+
|
|
1092
|
+
export function FieldCodeValidation() {
|
|
1093
|
+
const [value, setValue] = useState('');
|
|
1094
|
+
const [touched, setTouched] = useState(false);
|
|
1095
|
+
const validateCode = useFieldCodeValidate({ codeLength: CODE_LENGTH });
|
|
1096
|
+
|
|
1097
|
+
const handleChange = (next: string) => {
|
|
1098
|
+
setValue(next);
|
|
1099
|
+
setTouched(true);
|
|
1100
|
+
};
|
|
1101
|
+
|
|
1102
|
+
return (
|
|
1103
|
+
<FieldCode
|
|
1104
|
+
codeLength={CODE_LENGTH}
|
|
1105
|
+
label='Код подтверждения'
|
|
1106
|
+
value={value}
|
|
1107
|
+
onChange={handleChange}
|
|
1108
|
+
error={touched ? validateCode(value) : undefined}
|
|
1109
|
+
showEmptyChars={touched}
|
|
1110
|
+
/>
|
|
1111
|
+
);
|
|
1112
|
+
}
|
|
1113
|
+
```
|
|
1114
|
+
|
|
1115
|
+
#### Повторная отправка
|
|
1116
|
+
|
|
1117
|
+
resendCode c таймером обратного отсчёта.
|
|
1118
|
+
|
|
1119
|
+
```tsx
|
|
1120
|
+
import { FieldCode } from '@cloud-ru/ds-uikit-product-fields-predefined';
|
|
1121
|
+
import { useEffect, useState } from 'react';
|
|
1122
|
+
|
|
1123
|
+
const RESEND_COUNTDOWN_SECONDS = 10;
|
|
1124
|
+
|
|
1125
|
+
export function FieldCodeResend() {
|
|
1126
|
+
const [value, setValue] = useState('');
|
|
1127
|
+
const [secondsToNextResend, setSecondsToNextResend] = useState(RESEND_COUNTDOWN_SECONDS);
|
|
1128
|
+
|
|
1129
|
+
useEffect(() => {
|
|
1130
|
+
if (secondsToNextResend <= 0) {
|
|
1131
|
+
return;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
const timerId = window.setTimeout(() => setSecondsToNextResend(seconds => seconds - 1), 1000);
|
|
1135
|
+
|
|
1136
|
+
return () => window.clearTimeout(timerId);
|
|
1137
|
+
}, [secondsToNextResend]);
|
|
1138
|
+
|
|
1139
|
+
const handleResend = () => {
|
|
1140
|
+
setValue('');
|
|
1141
|
+
setSecondsToNextResend(RESEND_COUNTDOWN_SECONDS);
|
|
1142
|
+
};
|
|
1143
|
+
|
|
1144
|
+
return (
|
|
1145
|
+
<FieldCode
|
|
1146
|
+
codeLength={6}
|
|
1147
|
+
label='Код подтверждения'
|
|
1148
|
+
value={value}
|
|
1149
|
+
onChange={setValue}
|
|
1150
|
+
resendCode={{ onResend: handleResend, secondsToNextResend }}
|
|
1151
|
+
/>
|
|
1152
|
+
);
|
|
1153
|
+
}
|
|
1154
|
+
```
|
|
1155
|
+
|
|
1156
|
+
### Props
|
|
1157
|
+
|
|
1158
|
+
**FieldCodeProps**
|
|
1159
|
+
|
|
1160
|
+
| Prop | Type | Default | Description |
|
|
1161
|
+
|------|------|---------|-------------|
|
|
1162
|
+
| `cellClassName` | `string` | — | CSS-класс ячейки кода |
|
|
1163
|
+
| `className` | `string` | — | CSS-класс компонента |
|
|
1164
|
+
| `codeLength` | `number` | — | Количество цифр в коде (целое ≥ 1) |
|
|
1165
|
+
| `data-test-id` | `string` | — | |
|
|
1166
|
+
| `disabled` | `boolean` | — | Поле выключено |
|
|
1167
|
+
| `error` | `string` | — | Ошибка (приоритетнее `hint`; форсит `validationState=error`) |
|
|
1168
|
+
| `invalidCode` | `string` | — | Сообщение при неверном коде, если не передан свой `error` |
|
|
1169
|
+
| `label` | `string` | — | Заголовок |
|
|
1170
|
+
| `onChange` | `((code: string) => void)` | — | Колбек изменения значения |
|
|
1171
|
+
| `onComplete` | `((code: string) => void)` | — | Колбек ввода всех символов кода |
|
|
1172
|
+
| `resendCode` | `ResendCodeProps` | —
|
|
1173
|
+
|
|
1174
|
+
##### Related types
|
|
1175
|
+
|
|
1176
|
+
**ResendCodeProps**
|
|
1177
|
+
|
|
1178
|
+
| Prop | Type | Default | Description |
|
|
1179
|
+
|------|------|---------|-------------|
|
|
1180
|
+
| `disabled` | `boolean \| undefined` | — | Отключена |
|
|
1181
|
+
| `onResend` | `() => void` | — | Колбек отправки нового кода |
|
|
1182
|
+
| `secondsToNextResend` | `number` | — | Количество секунд до следующей отправки кода |
|
|
1183
|
+
| `size` | `"l"` \| `"m"` \| `"s"` | — | Размер |
|
|
1184
|
+
|
|
1185
|
+
### Адаптивность
|
|
1186
|
+
|
|
1187
|
+
Раскладка читается из `AdaptiveProvider` (`@cloud-ru/ds-adaptive`); отдельного пропа `layoutType` нет. На mobile компонент не переносит фокус автоматически (ни при монтировании, ни при `resetCode`) — чтобы экранная клавиатура не открывалась без действия пользователя. Размер на mobile не меняется — база `m`.
|
|
1188
|
+
|
|
1189
|
+
## FieldDescriptionRHF
|
|
1190
|
+
|
|
1191
|
+
```tsx
|
|
1192
|
+
import { Button } from '@cloud-ru/ds-button';
|
|
1193
|
+
import { FieldDescriptionRHF } from '@cloud-ru/ds-uikit-product-fields-predefined';
|
|
1194
|
+
import { FormProvider, useForm } from 'react-hook-form';
|
|
1195
|
+
|
|
1196
|
+
type FormValues = { description: string };
|
|
1197
|
+
|
|
1198
|
+
export function FieldDescriptionRHFExample() {
|
|
1199
|
+
const methods = useForm<FormValues>({ defaultValues: { description: '' }, mode: 'onBlur' });
|
|
1200
|
+
|
|
1201
|
+
return (
|
|
1202
|
+
<FormProvider {...methods}>
|
|
1203
|
+
<form
|
|
1204
|
+
onSubmit={methods.handleSubmit(values => alert(`description: ${values.description}`))}
|
|
1205
|
+
style={{ display: 'flex', flexDirection: 'column', gap: 12, width: 360 }}
|
|
1206
|
+
>
|
|
1207
|
+
<FieldDescriptionRHF controllerProps={{ name: 'description' }} />
|
|
1208
|
+
<Button type='submit' label='Отправить' />
|
|
1209
|
+
</form>
|
|
1210
|
+
</FormProvider>
|
|
1211
|
+
);
|
|
1212
|
+
}
|
|
1213
|
+
```
|
|
1214
|
+
|
|
1215
|
+
### Props `FieldDescriptionRHFProps`
|
|
1216
|
+
|
|
1217
|
+
| Prop | Type | Default | Description |
|
|
1218
|
+
|------|------|---------|-------------|
|
|
1219
|
+
| `addButton` | `boolean` | — | Поле появляется по кнопке «Добавить описание» (только для опционального поля) |
|
|
1220
|
+
| `allowMoreThanMaxLength` | `boolean` | `true` | Разрешить ввод свыше `maxLength` символов (счётчик продолжит расти). |
|
|
1221
|
+
| `autoFocus` | `boolean` | — | Автофокус. На mobile выключается адаптивно (см. `layoutPresets`) |
|
|
1222
|
+
| `background` | `boolean` | `true` | Фон поля (acrylic) |
|
|
1223
|
+
| `className` | `string` | — | CSS-класс <br/> CSS-класс корня `FieldDecorator` |
|
|
1224
|
+
| `controllerProps` | `Omit<ControllerProps<FieldValues>, "disabled" \| "rules" \| "render">` | — | Режим контроллера с использованием react-hook-form |
|
|
1225
|
+
| `customSchema` | `StringSchema<string, AnyObject, undefined, "">` | — | Дополнительная yup-схема, которая конкатенируется к встроенной |
|
|
1226
|
+
| `data-test-id` | `string` | — | |
|
|
1227
|
+
| `defaultValue` | `string` | — | Начальное значение (uncontrolled-режим) |
|
|
1228
|
+
| `disabled` | `boolean` | — | Поле выключено |
|
|
1229
|
+
| `error` | `string` | — | Ошибка (приоритетнее `hint`; форсит `validationState=error`) |
|
|
1230
|
+
| `fieldClassName` | `string` | — | CSS-класс оболочки поля |
|
|
1231
|
+
| `header` | `ReactNode` | — | Нода над textarea — ряд элементов до контента (Figma `elementWrapperBefore` / <br/> `slotBeforeContent`): тулбар с кнопками, чипами и т.п. |
|
|
1232
|
+
| `id` | `string` | — | HTML id |
|
|
1233
|
+
| `innerRef` | `Ref<HTMLDivElement>` | — | Ref на корневой DOM-элемент |
|
|
1234
|
+
| `labelFor` | `string` | — | HTML-атрибут `for` для `<label>` |
|
|
1235
|
+
| `labelTooltip` | `QuestionTooltipProps` | — | Подсказка (question-tooltip) у заголовка |
|
|
1236
|
+
| `layoutPresets` | `FieldLayoutPresets` | — | Переопределение адаптивных дефолтов по раскладке. Участвует `autoFocus`: на mobile он выключен <br/> (открывает клавиатуру без действия). Вернуть на mobile — `layoutPresets={{ mobile: { autoFocus: true } }}`. |
|
|
1237
|
+
| `length` | `FieldLength` | — | Счётчик длины `current/max` |
|
|
1238
|
+
| `maxLength` | `number` | `255` | Максимальное количество символов |
|
|
1239
|
+
| `maxRows` | `number` | `1000` | Максимальное количество строк (после — появляется скролл) |
|
|
1240
|
+
| `minRows` | `number` | `3` | Минимальное количество строк |
|
|
1241
|
+
| `onBlur` | `((event: FocusEvent<HTMLTextAreaElement, Element>) => void)` | — | Колбек блюра |
|
|
1242
|
+
| `onChange` | `((value: string, event?: ChangeEvent<HTMLTextAreaElement>) => void)` | — | Колбек смены значения |
|
|
1243
|
+
| `onCopyButtonClick` | `(() => void)` | — | Колбек после копирования |
|
|
1244
|
+
| `onFocus` | `((event: FocusEvent<HTMLTextAreaElement, Element>) => void)` | — | Колбек фокуса |
|
|
1245
|
+
| `onKeyDown` | `((event: KeyboardEvent<HTMLTextAreaElement>) => void)` | — | Колбек нажатия клавиши |
|
|
1246
|
+
| `readonly` | `boolean` | — | Только для чтения |
|
|
1247
|
+
| `required` | `boolean` | `false` | Показать знак обязательности `*` |
|
|
1248
|
+
| `resizable` | `boolean` | `true` | Можно ли менять высоту мышкой за нижний угол. Игнорируется при `disabled` или `readonly`. |
|
|
1249
|
+
| `showClearButton` | `boolean` | `true` | Кнопка очистки (видна при value && !readonly) |
|
|
1250
|
+
| `showCopyButton` | `boolean` | `true` | Кнопка копирования (видна при value && !disabled, независимо от readonly) |
|
|
1251
|
+
| `showHintIcon` | `boolean` | — | Отображение статус-иконки у подсказки (по умолчанию `true`) |
|
|
1252
|
+
| `size` | `"l"` \| `"m"` \| `"s"` | `m` | Размер |
|
|
1253
|
+
| `spellCheck` | `boolean` | — | Проверка орфографии |
|
|
1254
|
+
| `validationState` | `"default"` \| `"error"` \| `"success"` \| `"warning"` | — | Состояние валидации |
|
|
1255
|
+
| `value` | `string` | — | Значение (controlled-режим) |
|
|
1256
|
+
|
|
1257
|
+
## FieldNameRHF
|
|
1258
|
+
|
|
1259
|
+
```tsx
|
|
1260
|
+
import { Button } from '@cloud-ru/ds-button';
|
|
1261
|
+
import { FieldNameRHF } from '@cloud-ru/ds-uikit-product-fields-predefined';
|
|
1262
|
+
import { FormProvider, useForm } from 'react-hook-form';
|
|
1263
|
+
|
|
1264
|
+
type FormValues = { serviceName: string };
|
|
1265
|
+
|
|
1266
|
+
export function FieldNameRHFExample() {
|
|
1267
|
+
const methods = useForm<FormValues>({ defaultValues: { serviceName: '' }, mode: 'onBlur' });
|
|
1268
|
+
|
|
1269
|
+
return (
|
|
1270
|
+
<FormProvider {...methods}>
|
|
1271
|
+
<form
|
|
1272
|
+
onSubmit={methods.handleSubmit(values => alert(`name: ${values.serviceName}`))}
|
|
1273
|
+
style={{ display: 'flex', flexDirection: 'column', gap: 12, width: 320 }}
|
|
1274
|
+
>
|
|
1275
|
+
<FieldNameRHF controllerProps={{ name: 'serviceName' }} />
|
|
1276
|
+
<Button type='submit' label='Отправить' />
|
|
1277
|
+
</form>
|
|
1278
|
+
</FormProvider>
|
|
1279
|
+
);
|
|
1280
|
+
}
|
|
1281
|
+
```
|
|
1282
|
+
|
|
1283
|
+
### Props `FieldNameRHFProps`
|
|
1284
|
+
|
|
1285
|
+
| Prop | Type | Default | Description |
|
|
1286
|
+
|------|------|---------|-------------|
|
|
1287
|
+
| `allowMoreThanMaxLength` | `boolean` | `false` | Разрешить ввод свыше `maxLength` символов (счётчик продолжит расти). |
|
|
1288
|
+
| `autoComplete` | `string \| boolean` | `false` | Включен ли автокомплит для поля |
|
|
1289
|
+
| `autoFocus` | `boolean` | `false` | Включен ли авто-фокус для поля |
|
|
1290
|
+
| `background` | `boolean` | `true` | Фон поля (acrylic) |
|
|
1291
|
+
| `className` | `string` | — | CSS-класс <br/> CSS-класс корня `FieldDecorator` |
|
|
1292
|
+
| `controllerProps` | `Omit<ControllerProps<FieldValues>, "disabled" \| "rules" \| "render">` | — | Режим контроллера с использованием react-hook-form |
|
|
1293
|
+
| `customSchema` | `StringSchema<string, AnyObject, undefined, "">` | — | Дополнительная yup-схема, конкатенируется к встроенной (обязательность, длина, допустимые символы). <br/> Через неё подключают data-зависимые проверки, которые компонент не может выполнить сам — например, <br/> проверку уникальности имени по данным потребителя. Текст ошибки можно взять из локали пакета: <br/> `fieldsPredefinedLocale.useTranslations().t('FieldName.errorDuplicate')`. |
|
|
1294
|
+
| `data-test-id` | `string` | — | |
|
|
1295
|
+
| `defaultValue` | `string` | — | Начальное значение (uncontrolled-режим) |
|
|
1296
|
+
| `disabled` | `boolean` | `false` | Поле выключено <br/> Является ли поле деактивированным |
|
|
1297
|
+
| `elementAfter` | `FieldElementButtonProps` \| `FieldElementSlot` | — | Слот справа (кнопка / селект с опциональным выпадающим списком) |
|
|
1298
|
+
| `elementBefore` | `FieldElementButtonProps` \| `FieldElementSlot` | — | Слот слева (кнопка / селект с опциональным выпадающим списком) |
|
|
1299
|
+
| `error` | `string` | — | Ошибка (приоритетнее `hint`; форсит `validationState=error`) |
|
|
1300
|
+
| `fieldClassName` | `string` | — | CSS-класс оболочки поля ввода |
|
|
1301
|
+
| `iconAfter` | `ReactNode` | — | Иконка справа от строки ввода |
|
|
1302
|
+
| `iconBefore` | `ReactNode` | — | Иконка слева от строки ввода |
|
|
1303
|
+
| `id` | `string` | — | Значение html-атрибута id |
|
|
1304
|
+
| `innerRef` | `Ref<HTMLDivElement>` | — | Ref на корневой DOM-элемент |
|
|
1305
|
+
| `innerTestIds` | `{ shell?: string; input?: string; } \| undefined` | — | Идентификаторы внутренних слотов — оболочки и строки ввода. Нужны компонентам, которые <br/> рендерят `FieldCombo` под собственным именем (`FieldText`): их e2e адресует свои слоты, <br/> а не слоты `FieldCombo`. |
|
|
1306
|
+
| `labelFor` | `string` | — | HTML-атрибут `for` для `<label>` |
|
|
1307
|
+
| `labelTooltip` | `QuestionTooltipProps` | — | Подсказка (question-tooltip) у заголовка |
|
|
1308
|
+
| `layoutPresets` | `FieldLayoutPresets` | — | Переопределение адаптивных дефолтов по раскладке. Участвует `autoFocus`: на mobile он выключен <br/> (открывает клавиатуру без действия). Вернуть на mobile — `layoutPresets={{ mobile: { autoFocus: true } }}`. |
|
|
1309
|
+
| `length` | `FieldLength` | — | Счётчик длины `current/max` |
|
|
1310
|
+
| `max` | `number` | — | Максимальное значение поля |
|
|
1311
|
+
| `maxLength` | `number` | — | Максимальная длина вводимого значения |
|
|
1312
|
+
| `min` | `number` | — | Минимальное значение поля |
|
|
1313
|
+
| `name` | `string` | — | Значение html-атрибута name |
|
|
1314
|
+
| `onBlur` | `FocusEventHandler<HTMLInputElement>` | — | Колбек обработки потери фокуса |
|
|
1315
|
+
| `onChange` | `((value: string) => void)` | — | Колбек смены значения |
|
|
1316
|
+
| `onClearButtonClick` | `(() => void)` | — | Колбек клика по кнопке очистки |
|
|
1317
|
+
| `onClick` | `MouseEventHandler<HTMLInputElement>` | — | Колбек обработки клика |
|
|
1318
|
+
| `onCopyButtonClick` | `(() => void)` | — | Колбек после копирования значения в буфер |
|
|
1319
|
+
| `onFocus` | `FocusEventHandler<HTMLInputElement>` | — | Колбек обработки получения фокуса |
|
|
1320
|
+
| `onKeyDown` | `KeyboardEventHandler<HTMLInputElement>` | — | Колбек обработки начала нажатия клавиши клавиатуры |
|
|
1321
|
+
| `onMouseDown` | `MouseEventHandler<HTMLInputElement>` | — | Колбек обработки нажатия кнопки мыши |
|
|
1322
|
+
| `onPaste` | `ClipboardEventHandler<HTMLInputElement>` | — | Колбек обработки вставки значения |
|
|
1323
|
+
| `outline` | `boolean` | `true` | Разделитель между основным полем и слотами `elementBefore` / `elementAfter` |
|
|
1324
|
+
| `pattern` | `string` | — | Регулярное выражение валидного инпута |
|
|
1325
|
+
| `postfix` | `ReactNode` | — | Постфикс (текст или нода) |
|
|
1326
|
+
| `prefix` | `ReactNode` | — | Префикс (текст или нода) |
|
|
1327
|
+
| `prefixIcon` | `ReactNode` | — | Ведущая иконка. <br/> @deprecated Используйте `iconBefore` — он приоритетнее, если заданы оба. |
|
|
1328
|
+
| `readonly` | `boolean` | `false` | Только для чтения <br/> Является ли поле доступным только для чтения |
|
|
1329
|
+
| `required` | `boolean` | — | Показать знак обязательности `*` |
|
|
1330
|
+
| `showClearButton` | `boolean` | `true` | Показывать кнопку очистки значения (как в Search) |
|
|
1331
|
+
| `showCopyButton` | `boolean` | `true` | Показывать кнопку копирования значения (только при `readonly = true` и непустом `value`) |
|
|
1332
|
+
| `showHintIcon` | `boolean` | — | Отображение статус-иконки у подсказки (по умолчанию `true`) |
|
|
1333
|
+
| `showLabel` | `boolean` | — | Показывать предустановленный лейбл «Имя» |
|
|
1334
|
+
| `size` | `"l"` \| `"m"` \| `"s"` | — | Размер |
|
|
1335
|
+
| `spellCheck` | `boolean` | `true` | Значение атрибута spellcheck (проверка орфографии) |
|
|
1336
|
+
| `step` | `string \| number` | — | Максимальное значение поля |
|
|
1337
|
+
| `tabIndex` | `number` | `0` | Значение атрибута tab-index |
|
|
1338
|
+
| `validationState` | `"default"` \| `"error"` \| `"success"` \| `"warning"` | — | Состояние валидации |
|
|
1339
|
+
| `value` | `string` | — | Значение поля (controlled-режим) |
|