@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
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
|
|
3
|
+
import { ALL_COUNTRY_CODES } from '../countries';
|
|
4
|
+
import { Country, CountrySettings, FieldPhoneOptionsProps } from '../types';
|
|
5
|
+
import { uniqueSet } from '../utils';
|
|
6
|
+
import { useMapCountryToOptions } from './useMapCountryToOptions';
|
|
7
|
+
|
|
8
|
+
export function useCountries(optionsSettings?: CountrySettings): FieldPhoneOptionsProps[] {
|
|
9
|
+
const mapCountryToOption = useMapCountryToOptions();
|
|
10
|
+
|
|
11
|
+
const filterCountries = useMemo(() => {
|
|
12
|
+
if (!optionsSettings) {
|
|
13
|
+
return () => true;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const { includedCountries, excludedCountries } = optionsSettings;
|
|
17
|
+
const uniqueKey = 'value' satisfies keyof Country;
|
|
18
|
+
|
|
19
|
+
if (includedCountries) {
|
|
20
|
+
const includedSet = uniqueSet(includedCountries, uniqueKey);
|
|
21
|
+
return (country: Country) => includedSet.has(country[uniqueKey]);
|
|
22
|
+
}
|
|
23
|
+
if (excludedCountries) {
|
|
24
|
+
const excludedSet = uniqueSet(excludedCountries, uniqueKey);
|
|
25
|
+
return (country: Country) => !excludedSet.has(country[uniqueKey]);
|
|
26
|
+
}
|
|
27
|
+
return () => true;
|
|
28
|
+
}, [optionsSettings]);
|
|
29
|
+
|
|
30
|
+
return useMemo(() => {
|
|
31
|
+
if (optionsSettings?.overriddenOptions) return optionsSettings.overriddenOptions;
|
|
32
|
+
|
|
33
|
+
return ALL_COUNTRY_CODES.reduce<FieldPhoneOptionsProps[]>((result, country) => {
|
|
34
|
+
if (filterCountries(country)) {
|
|
35
|
+
result.push(mapCountryToOption(country));
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
}, []);
|
|
39
|
+
}, [optionsSettings, filterCountries, mapCountryToOption]);
|
|
40
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createElement, useCallback } from 'react';
|
|
2
|
+
|
|
3
|
+
import { fieldsPredefinedLocale } from '../../../locale';
|
|
4
|
+
import { FLAG_ICON_SIZE } from '../constants';
|
|
5
|
+
import { Country, FieldPhoneOptionsProps } from '../types';
|
|
6
|
+
|
|
7
|
+
export function useMapCountryToOptions() {
|
|
8
|
+
const { t } = fieldsPredefinedLocale.useTranslations();
|
|
9
|
+
|
|
10
|
+
const mapCountryToOption = useCallback(
|
|
11
|
+
({ value: id, mask, caption, icon, iso2 }: Country): FieldPhoneOptionsProps => ({
|
|
12
|
+
id,
|
|
13
|
+
mask,
|
|
14
|
+
content: {
|
|
15
|
+
label: t(`FieldPhone.${id}`),
|
|
16
|
+
caption,
|
|
17
|
+
},
|
|
18
|
+
beforeContent: createElement(icon, { size: FLAG_ICON_SIZE }),
|
|
19
|
+
iso2,
|
|
20
|
+
}),
|
|
21
|
+
[t],
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
return mapCountryToOption;
|
|
25
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
@use '@cloud-ru/ds-figma-variables/build/scss/styles/styles.module' as base;
|
|
2
|
+
|
|
3
|
+
.fieldPhone {
|
|
4
|
+
// Маска рендерится всегда (imask lazy:false) — в пустом поле приглушаем её как плейсхолдер.
|
|
5
|
+
// `.fieldPhone` — на корне FieldDecorator, `data-empty` — на вложенном input, поэтому селектор потомковый.
|
|
6
|
+
input[data-empty] {
|
|
7
|
+
color: base.$sn-theme-color-available-version-textDisabled;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { useIMask } from 'react-imask';
|
|
3
|
+
|
|
4
|
+
import { ALL_COUNTRY_CODES } from './countries';
|
|
5
|
+
|
|
6
|
+
export type FieldPhoneOptionsProps = {
|
|
7
|
+
id: string;
|
|
8
|
+
beforeContent: ReactNode;
|
|
9
|
+
content: {
|
|
10
|
+
label: string;
|
|
11
|
+
caption: string;
|
|
12
|
+
};
|
|
13
|
+
mask: string;
|
|
14
|
+
iso2: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type MaskOptions = Parameters<typeof useIMask>[0];
|
|
18
|
+
|
|
19
|
+
export type Country = (typeof ALL_COUNTRY_CODES)[number];
|
|
20
|
+
|
|
21
|
+
type OneOf<T extends object> = {
|
|
22
|
+
[K in keyof T]: { [P in K]: T[P] } & { [P in Exclude<keyof T, K>]?: never };
|
|
23
|
+
}[keyof T];
|
|
24
|
+
|
|
25
|
+
export type CountrySettings = OneOf<{
|
|
26
|
+
/** Список элементов выпадающего списка со странами; переопределяет встроенный список пакета */
|
|
27
|
+
overriddenOptions: FieldPhoneOptionsProps[];
|
|
28
|
+
/** Список стран, которые должны отображаться в селекторе (из встроенного перечня пакета) */
|
|
29
|
+
includedCountries: Country[];
|
|
30
|
+
/** Список стран, которые будут исключены из встроенного перечня пакета */
|
|
31
|
+
excludedCountries: Country[];
|
|
32
|
+
}>;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { parsePhoneNumber } from 'awesome-phonenumber';
|
|
2
|
+
|
|
3
|
+
import { ABKHAZIA_COUNTRY_CODE, RUSSIA_COUNTRY_CODE } from './countries';
|
|
4
|
+
import { FieldPhoneOptionsProps } from './types';
|
|
5
|
+
|
|
6
|
+
export const uniqueSet = <T, K extends keyof T>(arr: T[], key: K): Set<T[K]> => new Set(arr.map(obj => obj[key]));
|
|
7
|
+
|
|
8
|
+
/* Приходит +79878887879/+7987****875, на основании mask возвращается +7 987-888-78-79/+7 987-***-*8-75 */
|
|
9
|
+
export const formatPhoneNumber = <T extends { caption: string; mask: string }>(
|
|
10
|
+
phone: string,
|
|
11
|
+
countries: readonly T[],
|
|
12
|
+
): string => {
|
|
13
|
+
const digits = phone.replace(/[^\d*]/g, '');
|
|
14
|
+
|
|
15
|
+
const country = countries.find(item => digits.startsWith(item.caption.replace('+', '')));
|
|
16
|
+
|
|
17
|
+
if (!country) {
|
|
18
|
+
return phone;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const countryCode = country.caption.replace('+', '');
|
|
22
|
+
const restNumber = digits.slice(countryCode.length);
|
|
23
|
+
|
|
24
|
+
let formatted = '';
|
|
25
|
+
let index = 0;
|
|
26
|
+
for (const char of country.mask) {
|
|
27
|
+
if (char === 'X') {
|
|
28
|
+
formatted += restNumber.charAt(index) || '';
|
|
29
|
+
index++;
|
|
30
|
+
} else {
|
|
31
|
+
formatted += char;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return `${country.caption} ${formatted}`;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const byId = (id: string) => (option: FieldPhoneOptionsProps) => option.id === id;
|
|
39
|
+
|
|
40
|
+
export function detectCountryByPhone(text: string, options: FieldPhoneOptionsProps[]) {
|
|
41
|
+
const cleaned = text.replace(/[^\d+]/g, '');
|
|
42
|
+
|
|
43
|
+
const withPlus = cleaned.startsWith('+') ? cleaned : `+${cleaned}`;
|
|
44
|
+
const parsedNumber = parsePhoneNumber(withPlus);
|
|
45
|
+
const regionCode = parsedNumber.regionCode;
|
|
46
|
+
|
|
47
|
+
/* У Абхазии iso2 совпадает с Россией */
|
|
48
|
+
if (/^\+?7(840|940)/.test(cleaned)) {
|
|
49
|
+
let russia: FieldPhoneOptionsProps | undefined;
|
|
50
|
+
|
|
51
|
+
for (const option of options) {
|
|
52
|
+
const id = option.id;
|
|
53
|
+
const iso = option.iso2;
|
|
54
|
+
|
|
55
|
+
if (id === ABKHAZIA_COUNTRY_CODE.value) {
|
|
56
|
+
return option;
|
|
57
|
+
}
|
|
58
|
+
if (!russia && (id === RUSSIA_COUNTRY_CODE.value || iso === RUSSIA_COUNTRY_CODE.iso2)) {
|
|
59
|
+
russia = option;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return russia;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (regionCode === RUSSIA_COUNTRY_CODE.iso2) {
|
|
67
|
+
return options.find(byId(RUSSIA_COUNTRY_CODE.value));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return options.find(opt => opt.iso2 === regionCode);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const handleAutoInsert = ({
|
|
74
|
+
raw,
|
|
75
|
+
onValueChange,
|
|
76
|
+
onCountryChange,
|
|
77
|
+
country,
|
|
78
|
+
options,
|
|
79
|
+
}: {
|
|
80
|
+
raw: string;
|
|
81
|
+
onValueChange(str: string): void;
|
|
82
|
+
onCountryChange(country: FieldPhoneOptionsProps): void;
|
|
83
|
+
country?: FieldPhoneOptionsProps;
|
|
84
|
+
options: FieldPhoneOptionsProps[];
|
|
85
|
+
}) => {
|
|
86
|
+
if (!raw) return;
|
|
87
|
+
|
|
88
|
+
const parsed = parsePhoneNumber(raw);
|
|
89
|
+
const ok = parsed.valid || parsed.possible;
|
|
90
|
+
if (!ok) return;
|
|
91
|
+
|
|
92
|
+
const detected = detectCountryByPhone(raw, options);
|
|
93
|
+
if (!detected) return;
|
|
94
|
+
|
|
95
|
+
let national = parsed.number?.significant.replace(/\D/g, '');
|
|
96
|
+
if (!national) return;
|
|
97
|
+
|
|
98
|
+
const nextNationalLength = (detected.mask?.match(/X/g) ?? []).length;
|
|
99
|
+
if (nextNationalLength && national.length > nextNationalLength) {
|
|
100
|
+
national = national.slice(-nextNationalLength);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const fullDigits = (parsed.number?.e164 ?? raw).replace(/\D/g, '');
|
|
104
|
+
const countryCodeDigits = String(parsed.countryCode ?? '');
|
|
105
|
+
const expected = countryCodeDigits.length + nextNationalLength;
|
|
106
|
+
if (fullDigits.length < expected) return;
|
|
107
|
+
|
|
108
|
+
if (detected.id !== country?.id) {
|
|
109
|
+
onCountryChange(detected);
|
|
110
|
+
}
|
|
111
|
+
onValueChange(national);
|
|
112
|
+
};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { APPEARANCE, Button, ICON_POSITION, VIEW } from '@cloud-ru/ds-button';
|
|
2
|
+
import { Drawer, DrawerProps, POSITION, Position } from '@cloud-ru/ds-drawer';
|
|
3
|
+
import { FieldSelect } from '@cloud-ru/ds-fields';
|
|
4
|
+
import { PlusSVG } from '@cloud-ru/ds-icons/interface/system';
|
|
5
|
+
import { Modal, ModalProps } from '@cloud-ru/ds-modal';
|
|
6
|
+
import { Tooltip } from '@cloud-ru/ds-tooltip';
|
|
7
|
+
import { extractSupportProps } from '@cloud-ru/ds-utils';
|
|
8
|
+
import cn from 'classnames';
|
|
9
|
+
import { forwardRef, ReactElement, useCallback } from 'react';
|
|
10
|
+
|
|
11
|
+
import { TEST_IDS } from '../../constants';
|
|
12
|
+
import { useOpen } from '../../hooks';
|
|
13
|
+
import { fieldsPredefinedLocale } from '../../locale';
|
|
14
|
+
import { CREATE_LAYOUT_TYPE, PERMISSION } from './constants';
|
|
15
|
+
import { SelectFooter } from './helperComponents/SelectFooter';
|
|
16
|
+
import styles from './styles.module.scss';
|
|
17
|
+
import { FieldSelectCreateProps } from './types';
|
|
18
|
+
import { useSelectDataStates } from './useSelectDataStates';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Поле выбора с действием «создать»: `FieldSelect` из `@cloud-ru/ds-fields` + встроенная форма создания опции
|
|
22
|
+
* в модалке или дровере (`createLayoutType`). Кнопка «Создать <entityName>» — под полем и в футере
|
|
23
|
+
* дроплиста (`SelectFooter`). Пустые состояния и тексты строятся из `entityName`. Доступ рулит `permission`.
|
|
24
|
+
* На mobile дроплист и модалка/дровер — `BottomSheet` (адаптив `@ds`), своего пропа `layoutType` нет.
|
|
25
|
+
*/
|
|
26
|
+
export const FieldSelectCreate = forwardRef<HTMLInputElement, FieldSelectCreateProps>(function FieldSelectCreate(
|
|
27
|
+
{
|
|
28
|
+
selectProps,
|
|
29
|
+
createLayoutProps,
|
|
30
|
+
createLayoutType = CREATE_LAYOUT_TYPE.Drawer,
|
|
31
|
+
entityName,
|
|
32
|
+
submitHandler,
|
|
33
|
+
onRefetch,
|
|
34
|
+
className,
|
|
35
|
+
afterClose,
|
|
36
|
+
entityIcon,
|
|
37
|
+
permission = PERMISSION.CanCreate,
|
|
38
|
+
...rest
|
|
39
|
+
},
|
|
40
|
+
ref,
|
|
41
|
+
) {
|
|
42
|
+
const { t } = fieldsPredefinedLocale.useTranslations();
|
|
43
|
+
const { isOpen, onOpen, onClose } = useOpen();
|
|
44
|
+
const selectDataStates = useSelectDataStates({ entityName, entityIcon, onRefetch });
|
|
45
|
+
|
|
46
|
+
const size = selectProps.size ?? 'm';
|
|
47
|
+
|
|
48
|
+
const isNone = permission === PERMISSION.None;
|
|
49
|
+
const canCreate = permission === PERMISSION.CanCreate;
|
|
50
|
+
|
|
51
|
+
const handleClose = useCallback(() => {
|
|
52
|
+
onClose();
|
|
53
|
+
afterClose?.();
|
|
54
|
+
}, [afterClose, onClose]);
|
|
55
|
+
|
|
56
|
+
const handleCreate = useCallback(async () => {
|
|
57
|
+
const newValue = await submitHandler();
|
|
58
|
+
// Автовыбор новой опции — в single-режиме; в multiple выбор оставляем потребителю.
|
|
59
|
+
if (typeof newValue === 'string' && selectProps.selection !== 'multiple') {
|
|
60
|
+
selectProps.onChange?.(newValue);
|
|
61
|
+
}
|
|
62
|
+
handleClose();
|
|
63
|
+
}, [handleClose, selectProps, submitHandler]);
|
|
64
|
+
|
|
65
|
+
const createButtonLabel = `${t('FieldSelectCreate.create')} ${entityName.single.toLocaleLowerCase()}`;
|
|
66
|
+
const noPermissionTip = t('FieldSelectCreate.noPermission');
|
|
67
|
+
|
|
68
|
+
// createLayoutType и createLayoutProps дискриминируются союзом, но при деструктуризации корреляция
|
|
69
|
+
// теряется — поэтому приводим тип поверхности к целевому внутри ветки (как в легаси).
|
|
70
|
+
const layoutProps = {
|
|
71
|
+
...createLayoutProps,
|
|
72
|
+
open: isOpen,
|
|
73
|
+
onClose: handleClose,
|
|
74
|
+
'data-test-id': TEST_IDS.fieldSelectCreateSurface,
|
|
75
|
+
approveButton: { label: t('FieldSelectCreate.create'), onClick: handleCreate },
|
|
76
|
+
cancelButton: { label: t('FieldSelectCreate.cancel'), onClick: handleClose },
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const formLayout =
|
|
80
|
+
createLayoutType === CREATE_LAYOUT_TYPE.Modal ? (
|
|
81
|
+
<Modal {...(layoutProps as ModalProps)} />
|
|
82
|
+
) : (
|
|
83
|
+
<Drawer
|
|
84
|
+
{...(layoutProps as DrawerProps)}
|
|
85
|
+
position={(createLayoutProps as { position?: Position }).position ?? POSITION.Right}
|
|
86
|
+
/>
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const withTip = (node: ReactElement, show: boolean) =>
|
|
90
|
+
show ? <Tooltip tip={noPermissionTip}>{node}</Tooltip> : node;
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<div
|
|
94
|
+
className={cn(styles.fieldSelectCreate, className)}
|
|
95
|
+
{...extractSupportProps(rest)}
|
|
96
|
+
data-test-id={TEST_IDS.fieldSelectCreate}
|
|
97
|
+
>
|
|
98
|
+
{withTip(
|
|
99
|
+
<FieldSelect
|
|
100
|
+
{...selectProps}
|
|
101
|
+
ref={ref}
|
|
102
|
+
size={size}
|
|
103
|
+
disabled={isNone || selectProps.disabled}
|
|
104
|
+
placeholder={selectProps.placeholder ?? t('FieldSelectCreate.placeholder')}
|
|
105
|
+
{...selectDataStates}
|
|
106
|
+
footer={
|
|
107
|
+
// В состоянии ошибки показываем только «Обновить» из errorDataState — без футера «Создать» (по макету).
|
|
108
|
+
selectProps.dataError ? undefined : (
|
|
109
|
+
<SelectFooter onClick={onOpen} createButtonLabel={createButtonLabel} canCreate={canCreate} />
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
/>,
|
|
113
|
+
isNone,
|
|
114
|
+
)}
|
|
115
|
+
{withTip(
|
|
116
|
+
<Button
|
|
117
|
+
view={VIEW.Function}
|
|
118
|
+
appearance={APPEARANCE.Neutral}
|
|
119
|
+
label={createButtonLabel}
|
|
120
|
+
icon={<PlusSVG />}
|
|
121
|
+
iconPosition={ICON_POSITION.Before}
|
|
122
|
+
onClick={onOpen}
|
|
123
|
+
size={size}
|
|
124
|
+
disabled={!canCreate}
|
|
125
|
+
className={styles.createButton}
|
|
126
|
+
data-test-id={TEST_IDS.fieldSelectCreateButton}
|
|
127
|
+
/>,
|
|
128
|
+
!canCreate,
|
|
129
|
+
)}
|
|
130
|
+
{formLayout}
|
|
131
|
+
</div>
|
|
132
|
+
);
|
|
133
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Поверхность формы создания опции: модальное окно или дровер. */
|
|
2
|
+
export const CREATE_LAYOUT_TYPE = {
|
|
3
|
+
Modal: 'modal',
|
|
4
|
+
Drawer: 'drawer',
|
|
5
|
+
} as const;
|
|
6
|
+
|
|
7
|
+
/** Права пользователя на чтение/создание опций. */
|
|
8
|
+
export const PERMISSION = {
|
|
9
|
+
/** Поле недоступно. */
|
|
10
|
+
None: 'none',
|
|
11
|
+
/** Поле активно, создание опции недоступно. */
|
|
12
|
+
CanRead: 'canRead',
|
|
13
|
+
/** Полный доступ: чтение и создание. */
|
|
14
|
+
CanCreate: 'canCreate',
|
|
15
|
+
} as const;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { APPEARANCE, Button, ICON_POSITION, VIEW } from '@cloud-ru/ds-button';
|
|
2
|
+
import { PlusSVG } from '@cloud-ru/ds-icons/interface/system';
|
|
3
|
+
import { Tooltip } from '@cloud-ru/ds-tooltip';
|
|
4
|
+
|
|
5
|
+
import { TEST_IDS } from '../../../../constants';
|
|
6
|
+
import { fieldsPredefinedLocale } from '../../../../locale';
|
|
7
|
+
import styles from './styles.module.scss';
|
|
8
|
+
|
|
9
|
+
type SelectFooterProps = {
|
|
10
|
+
onClick(): void;
|
|
11
|
+
createButtonLabel: string;
|
|
12
|
+
canCreate: boolean;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/** Персистентный футер дроплиста с кнопкой «Создать» (недоступна и с tooltip при нехватке прав). */
|
|
16
|
+
export function SelectFooter({ onClick, createButtonLabel, canCreate }: SelectFooterProps) {
|
|
17
|
+
const { t } = fieldsPredefinedLocale.useTranslations();
|
|
18
|
+
|
|
19
|
+
const button = (
|
|
20
|
+
<Button
|
|
21
|
+
view={VIEW.Function}
|
|
22
|
+
appearance={APPEARANCE.Neutral}
|
|
23
|
+
label={createButtonLabel}
|
|
24
|
+
icon={<PlusSVG />}
|
|
25
|
+
iconPosition={ICON_POSITION.Before}
|
|
26
|
+
onClick={onClick}
|
|
27
|
+
disabled={!canCreate}
|
|
28
|
+
data-test-id={TEST_IDS.fieldSelectCreateFooterButton}
|
|
29
|
+
/>
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<div className={styles.footerWrapper}>
|
|
34
|
+
{canCreate ? button : <Tooltip tip={t('FieldSelectCreate.noPermission')}>{button}</Tooltip>}
|
|
35
|
+
</div>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './SelectFooter';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
@use '@cloud-ru/ds-figma-variables/build/scss/styles/styles.module' as base;
|
|
2
|
+
|
|
3
|
+
.footerWrapper {
|
|
4
|
+
display: flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
padding-top: base.$sn-primitive-dimension-4;
|
|
7
|
+
border-top: base.$sn-primitive-strokeWeight-strokeRegular solid base.$sn-theme-color-available-borderColor;
|
|
8
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
@use '@cloud-ru/ds-figma-variables/build/scss/styles/styles.module' as base;
|
|
2
|
+
|
|
3
|
+
.fieldSelectCreate {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
gap: base.$sn-primitive-dimension-8;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.createButton {
|
|
10
|
+
// По макету кнопка «Создать» под полем не растянута, а прижата к левому краю.
|
|
11
|
+
align-self: flex-start;
|
|
12
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { DrawerProps, Position } from '@cloud-ru/ds-drawer';
|
|
2
|
+
import { FieldSelectMultipleProps, FieldSelectSingleProps } from '@cloud-ru/ds-fields';
|
|
3
|
+
import { ModalProps } from '@cloud-ru/ds-modal';
|
|
4
|
+
import { ValueOf, WithSupportProps } from '@cloud-ru/ds-utils';
|
|
5
|
+
|
|
6
|
+
import { CREATE_LAYOUT_TYPE, PERMISSION } from './constants';
|
|
7
|
+
|
|
8
|
+
export type CreateLayoutType = ValueOf<typeof CREATE_LAYOUT_TYPE>;
|
|
9
|
+
|
|
10
|
+
export type Permission = ValueOf<typeof PERMISSION>;
|
|
11
|
+
|
|
12
|
+
export type EntityName = {
|
|
13
|
+
/** Единственное число (винительный падеж) — для кнопки «Создать <single>». */
|
|
14
|
+
single: string;
|
|
15
|
+
/** Множественное число — для текстов пустых состояний и ошибки. */
|
|
16
|
+
plural: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// Иконка пустого состояния — как у noDataState.icon.icon базового FieldSelect.
|
|
20
|
+
export type EntityIcon = NonNullable<NonNullable<FieldSelectSingleProps['noDataState']>['icon']>['icon'];
|
|
21
|
+
|
|
22
|
+
// Состояния дроплиста, футер и режим выбора компонент задаёт сам.
|
|
23
|
+
type OmittedSelectKeys = 'footer' | 'noDataState' | 'noResultsState' | 'errorDataState';
|
|
24
|
+
|
|
25
|
+
export type SelectFieldProps =
|
|
26
|
+
| (Omit<FieldSelectSingleProps, OmittedSelectKeys> & { selection?: 'single' })
|
|
27
|
+
| (Omit<FieldSelectMultipleProps, OmittedSelectKeys> & { selection: 'multiple' });
|
|
28
|
+
|
|
29
|
+
// Модалку/дровер создания компонент открывает/закрывает и снабжает кнопками сам.
|
|
30
|
+
type ManagedLayoutKeys = 'open' | 'onClose' | 'approveButton' | 'cancelButton';
|
|
31
|
+
|
|
32
|
+
export type LayoutProps =
|
|
33
|
+
| {
|
|
34
|
+
/** По клику на «Создать» открывается модальное окно. */
|
|
35
|
+
createLayoutType: 'modal';
|
|
36
|
+
/** Пропсы модалки создания (`content` — форма создания опции). */
|
|
37
|
+
createLayoutProps: Omit<ModalProps, ManagedLayoutKeys>;
|
|
38
|
+
}
|
|
39
|
+
| {
|
|
40
|
+
/** По клику на «Создать» открывается дровер (по умолчанию). */
|
|
41
|
+
createLayoutType?: 'drawer';
|
|
42
|
+
/** Пропсы дровера создания (`content` — форма создания опции); `position` по умолчанию `right`. */
|
|
43
|
+
createLayoutProps: Omit<DrawerProps, ManagedLayoutKeys | 'position'> & { position?: Position };
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export type FieldSelectCreateProps = WithSupportProps<
|
|
47
|
+
LayoutProps & {
|
|
48
|
+
/** Название сущности в единственном и множественном числе — для кнопок и пустых состояний. */
|
|
49
|
+
entityName: EntityName;
|
|
50
|
+
/** Действие создания опции: возвращает `value` новой опции, которая выбирается в поле (single-режим). */
|
|
51
|
+
submitHandler(): Promise<string | void>;
|
|
52
|
+
/** Пропсы, прокидываемые в `FieldSelect` (`@cloud-ru/ds-fields`). */
|
|
53
|
+
selectProps: SelectFieldProps;
|
|
54
|
+
/** Повтор загрузки в состоянии ошибки (кнопка «Обновить» в футере `errorDataState`). */
|
|
55
|
+
onRefetch?(): void;
|
|
56
|
+
/** CSS-класс корневой обёртки. */
|
|
57
|
+
className?: string;
|
|
58
|
+
/** Колбэк после закрытия модалки/дровера создания. */
|
|
59
|
+
afterClose?(): void;
|
|
60
|
+
/** Иконка пустого состояния `noData` (по умолчанию — иконка поиска). */
|
|
61
|
+
entityIcon?: EntityIcon;
|
|
62
|
+
/**
|
|
63
|
+
* Права пользователя:
|
|
64
|
+
* - `canCreate` (по умолчанию) — доступны и выбор, и создание;
|
|
65
|
+
* - `canRead` — поле активно, но создание недоступно (кнопки «Создать» с tooltip);
|
|
66
|
+
* - `none` — поле недоступно (с tooltip).
|
|
67
|
+
*/
|
|
68
|
+
permission?: Permission;
|
|
69
|
+
}
|
|
70
|
+
>;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { APPEARANCE, Button, ICON_POSITION, VIEW } from '@cloud-ru/ds-button';
|
|
2
|
+
import { FieldSelectSingleProps } from '@cloud-ru/ds-fields';
|
|
3
|
+
import { CrossCircleSVG, SearchSVG, UpdateSVG } from '@cloud-ru/ds-icons/interface/system';
|
|
4
|
+
import { useMemo } from 'react';
|
|
5
|
+
|
|
6
|
+
import { TEST_IDS } from '../../constants';
|
|
7
|
+
import { fieldsPredefinedLocale } from '../../locale';
|
|
8
|
+
import { EntityIcon, EntityName } from './types';
|
|
9
|
+
import { capitalize } from './utils';
|
|
10
|
+
|
|
11
|
+
type Props = {
|
|
12
|
+
entityName: EntityName;
|
|
13
|
+
entityIcon?: EntityIcon;
|
|
14
|
+
onRefetch?(): void;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type SelectDataStates = Pick<FieldSelectSingleProps, 'noDataState' | 'noResultsState' | 'errorDataState'>;
|
|
18
|
+
|
|
19
|
+
/** Строит пустые/ошибочные состояния дроплиста из `entityName` (единственное/множественное число). */
|
|
20
|
+
export function useSelectDataStates({ entityName, entityIcon, onRefetch }: Props): SelectDataStates {
|
|
21
|
+
const { t } = fieldsPredefinedLocale.useTranslations();
|
|
22
|
+
|
|
23
|
+
return useMemo(
|
|
24
|
+
() => ({
|
|
25
|
+
noDataState: {
|
|
26
|
+
icon: { icon: entityIcon ?? SearchSVG, appearance: 'green' },
|
|
27
|
+
description: `${capitalize(entityName.plural)} ${t('FieldSelectCreate.noData')}`,
|
|
28
|
+
},
|
|
29
|
+
noResultsState: {
|
|
30
|
+
icon: { icon: SearchSVG, appearance: 'green' },
|
|
31
|
+
description: (
|
|
32
|
+
<>
|
|
33
|
+
{capitalize(entityName.plural)} {t('FieldSelectCreate.noResult')}.
|
|
34
|
+
<br />
|
|
35
|
+
{t('FieldSelectCreate.changeRequest')} {entityName.single.toLocaleLowerCase()}
|
|
36
|
+
</>
|
|
37
|
+
),
|
|
38
|
+
},
|
|
39
|
+
errorDataState: {
|
|
40
|
+
icon: { icon: CrossCircleSVG, appearance: 'neutral' },
|
|
41
|
+
description: `${t('FieldSelectCreate.loadError')} ${entityName.plural.toLocaleLowerCase()}`,
|
|
42
|
+
footer: onRefetch ? (
|
|
43
|
+
<Button
|
|
44
|
+
view={VIEW.Tonal}
|
|
45
|
+
appearance={APPEARANCE.Neutral}
|
|
46
|
+
label={t('FieldSelectCreate.refetch')}
|
|
47
|
+
icon={<UpdateSVG />}
|
|
48
|
+
iconPosition={ICON_POSITION.After}
|
|
49
|
+
onClick={onRefetch}
|
|
50
|
+
data-test-id={TEST_IDS.fieldSelectCreateRetry}
|
|
51
|
+
/>
|
|
52
|
+
) : undefined,
|
|
53
|
+
},
|
|
54
|
+
}),
|
|
55
|
+
[entityIcon, entityName, onRefetch, t],
|
|
56
|
+
);
|
|
57
|
+
}
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export const TEST_IDS = {
|
|
2
|
+
fieldMask: 'field-mask',
|
|
3
|
+
fieldName: 'field-name',
|
|
4
|
+
fieldDescription: 'field-description',
|
|
5
|
+
fieldDescriptionAddButton: 'field-description__add-button',
|
|
6
|
+
fieldPhone: 'field-phone',
|
|
7
|
+
fieldPhoneCountrySelect: 'field-phone__country-select',
|
|
8
|
+
fieldChat: 'field-chat',
|
|
9
|
+
fieldCode: 'field-code',
|
|
10
|
+
fieldCodeCell: 'field-code__cell',
|
|
11
|
+
fieldCodeResend: 'field-code__resend',
|
|
12
|
+
fieldChatUpload: 'field-chat__upload',
|
|
13
|
+
fieldChatSubmit: 'field-chat__submit',
|
|
14
|
+
fieldSelectCreate: 'field-select-create',
|
|
15
|
+
fieldSelectCreateButton: 'field-select-create__button',
|
|
16
|
+
fieldSelectCreateFooterButton: 'field-select-create__footer-button',
|
|
17
|
+
fieldSelectCreateRetry: 'field-select-create__retry',
|
|
18
|
+
fieldSelectCreateSurface: 'field-select-create__surface',
|
|
19
|
+
} as const;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Возвращает количество символов для маски — со скобками и без.
|
|
3
|
+
*/
|
|
4
|
+
export function getSymbolsRangeFromMask(mask: string = '') {
|
|
5
|
+
// Считаем все 'X' и цифры в строке.
|
|
6
|
+
const maxNumberLength = (mask.match(/[X\d]/g) || []).length;
|
|
7
|
+
|
|
8
|
+
// Удаляем содержимое внутри скобок (включая сами скобки) для подсчёта без их содержимого.
|
|
9
|
+
const stringWithoutBrackets = mask.replace(/\[[^\]]*\]/g, '');
|
|
10
|
+
|
|
11
|
+
// Считаем 'X' и цифры после удаления содержимого в скобках.
|
|
12
|
+
const minNumberLength = (stringWithoutBrackets.match(/[X\d]/g) || []).length;
|
|
13
|
+
|
|
14
|
+
return { minNumberLength, maxNumberLength };
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './getSymbolsRangeFromMask';
|