@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.
Files changed (376) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/LICENSE +201 -0
  3. package/README.md +1339 -0
  4. package/dist/cjs/components/FieldChat/FieldChat.d.ts +7 -0
  5. package/dist/cjs/components/FieldChat/FieldChat.js +50 -0
  6. package/dist/cjs/components/FieldChat/components/Attachments/Attachments.d.ts +8 -0
  7. package/dist/cjs/components/FieldChat/components/Attachments/Attachments.js +16 -0
  8. package/dist/cjs/components/FieldChat/components/Attachments/index.d.ts +1 -0
  9. package/dist/cjs/components/FieldChat/components/Attachments/index.js +17 -0
  10. package/dist/cjs/components/FieldChat/components/Attachments/styles.module.css +12 -0
  11. package/dist/cjs/components/FieldChat/components/FieldSubmitButton/FieldSubmitButton.d.ts +18 -0
  12. package/dist/cjs/components/FieldChat/components/FieldSubmitButton/FieldSubmitButton.js +22 -0
  13. package/dist/cjs/components/FieldChat/components/FieldSubmitButton/index.d.ts +1 -0
  14. package/dist/cjs/components/FieldChat/components/FieldSubmitButton/index.js +17 -0
  15. package/dist/cjs/components/FieldChat/components/FieldSubmitButton/styles.module.css +3 -0
  16. package/dist/cjs/components/FieldChat/components/TextAreaActionsFooter/TextAreaActionsFooter.d.ts +8 -0
  17. package/dist/cjs/components/FieldChat/components/TextAreaActionsFooter/TextAreaActionsFooter.js +11 -0
  18. package/dist/cjs/components/FieldChat/components/TextAreaActionsFooter/index.d.ts +1 -0
  19. package/dist/cjs/components/FieldChat/components/TextAreaActionsFooter/index.js +17 -0
  20. package/dist/cjs/components/FieldChat/components/TextAreaActionsFooter/styles.module.css +25 -0
  21. package/dist/cjs/components/FieldChat/index.d.ts +2 -0
  22. package/dist/cjs/components/FieldChat/index.js +18 -0
  23. package/dist/cjs/components/FieldChat/styles.module.css +14 -0
  24. package/dist/cjs/components/FieldChat/types.d.ts +14 -0
  25. package/dist/cjs/components/FieldChat/types.js +2 -0
  26. package/dist/cjs/components/FieldCode/FieldCode.d.ts +30 -0
  27. package/dist/cjs/components/FieldCode/FieldCode.js +42 -0
  28. package/dist/cjs/components/FieldCode/components/Cell/Cell.d.ts +7 -0
  29. package/dist/cjs/components/FieldCode/components/Cell/Cell.js +17 -0
  30. package/dist/cjs/components/FieldCode/components/Cell/index.d.ts +1 -0
  31. package/dist/cjs/components/FieldCode/components/Cell/index.js +17 -0
  32. package/dist/cjs/components/FieldCode/components/Cell/styles.module.css +19 -0
  33. package/dist/cjs/components/FieldCode/components/ResendCode/ResendCode.d.ts +8 -0
  34. package/dist/cjs/components/FieldCode/components/ResendCode/ResendCode.js +19 -0
  35. package/dist/cjs/components/FieldCode/components/ResendCode/index.d.ts +1 -0
  36. package/dist/cjs/components/FieldCode/components/ResendCode/index.js +17 -0
  37. package/dist/cjs/components/FieldCode/components/ResendCode/utils.d.ts +1 -0
  38. package/dist/cjs/components/FieldCode/components/ResendCode/utils.js +8 -0
  39. package/dist/cjs/components/FieldCode/components/index.d.ts +2 -0
  40. package/dist/cjs/components/FieldCode/components/index.js +18 -0
  41. package/dist/cjs/components/FieldCode/constants.d.ts +2 -0
  42. package/dist/cjs/components/FieldCode/constants.js +5 -0
  43. package/dist/cjs/components/FieldCode/hooks/index.d.ts +5 -0
  44. package/dist/cjs/components/FieldCode/hooks/index.js +21 -0
  45. package/dist/cjs/components/FieldCode/hooks/useCodeInput.d.ts +22 -0
  46. package/dist/cjs/components/FieldCode/hooks/useCodeInput.js +97 -0
  47. package/dist/cjs/components/FieldCode/hooks/useFieldCodeOverflow.d.ts +6 -0
  48. package/dist/cjs/components/FieldCode/hooks/useFieldCodeOverflow.js +43 -0
  49. package/dist/cjs/components/FieldCode/hooks/useFieldCodeValidate.d.ts +6 -0
  50. package/dist/cjs/components/FieldCode/hooks/useFieldCodeValidate.js +22 -0
  51. package/dist/cjs/components/FieldCode/hooks/useFieldHelpers.d.ts +12 -0
  52. package/dist/cjs/components/FieldCode/hooks/useFieldHelpers.js +31 -0
  53. package/dist/cjs/components/FieldCode/hooks/useFocusCell.d.ts +5 -0
  54. package/dist/cjs/components/FieldCode/hooks/useFocusCell.js +21 -0
  55. package/dist/cjs/components/FieldCode/hooks/useRefState.d.ts +7 -0
  56. package/dist/cjs/components/FieldCode/hooks/useRefState.js +21 -0
  57. package/dist/cjs/components/FieldCode/index.d.ts +3 -0
  58. package/dist/cjs/components/FieldCode/index.js +19 -0
  59. package/dist/cjs/components/FieldCode/styles.module.css +45 -0
  60. package/dist/cjs/components/FieldCode/utils.d.ts +6 -0
  61. package/dist/cjs/components/FieldCode/utils.js +21 -0
  62. package/dist/cjs/components/FieldDescription/FieldDescription.d.ts +10 -0
  63. package/dist/cjs/components/FieldDescription/FieldDescription.js +55 -0
  64. package/dist/cjs/components/FieldDescription/FieldDescriptionRHF.d.ts +9 -0
  65. package/dist/cjs/components/FieldDescription/FieldDescriptionRHF.js +47 -0
  66. package/dist/cjs/components/FieldDescription/components/FieldWithAddButton.d.ts +7 -0
  67. package/dist/cjs/components/FieldDescription/components/FieldWithAddButton.js +27 -0
  68. package/dist/cjs/components/FieldDescription/components/index.d.ts +1 -0
  69. package/dist/cjs/components/FieldDescription/components/index.js +17 -0
  70. package/dist/cjs/components/FieldDescription/constants.d.ts +1 -0
  71. package/dist/cjs/components/FieldDescription/constants.js +4 -0
  72. package/dist/cjs/components/FieldDescription/index.d.ts +3 -0
  73. package/dist/cjs/components/FieldDescription/index.js +19 -0
  74. package/dist/cjs/components/FieldDescription/types.d.ts +17 -0
  75. package/dist/cjs/components/FieldDescription/types.js +2 -0
  76. package/dist/cjs/components/FieldMask/FieldMask.d.ts +12 -0
  77. package/dist/cjs/components/FieldMask/FieldMask.js +30 -0
  78. package/dist/cjs/components/FieldMask/constants.d.ts +19 -0
  79. package/dist/cjs/components/FieldMask/constants.js +60 -0
  80. package/dist/cjs/components/FieldMask/index.d.ts +3 -0
  81. package/dist/cjs/components/FieldMask/index.js +21 -0
  82. package/dist/cjs/components/FieldMask/types.d.ts +3 -0
  83. package/dist/cjs/components/FieldMask/types.js +2 -0
  84. package/dist/cjs/components/FieldName/FieldName.d.ts +5 -0
  85. package/dist/cjs/components/FieldName/FieldName.js +84 -0
  86. package/dist/cjs/components/FieldName/FieldNameRHF.d.ts +5 -0
  87. package/dist/cjs/components/FieldName/FieldNameRHF.js +68 -0
  88. package/dist/cjs/components/FieldName/constants.d.ts +1 -0
  89. package/dist/cjs/components/FieldName/constants.js +4 -0
  90. package/dist/cjs/components/FieldName/index.d.ts +3 -0
  91. package/dist/cjs/components/FieldName/index.js +19 -0
  92. package/dist/cjs/components/FieldName/types.d.ts +22 -0
  93. package/dist/cjs/components/FieldName/types.js +2 -0
  94. package/dist/cjs/components/FieldPhone/FieldPhone.d.ts +13 -0
  95. package/dist/cjs/components/FieldPhone/FieldPhone.js +166 -0
  96. package/dist/cjs/components/FieldPhone/constants.d.ts +8 -0
  97. package/dist/cjs/components/FieldPhone/constants.js +11 -0
  98. package/dist/cjs/components/FieldPhone/countries.d.ts +3500 -0
  99. package/dist/cjs/components/FieldPhone/countries.js +1441 -0
  100. package/dist/cjs/components/FieldPhone/hooks/index.d.ts +2 -0
  101. package/dist/cjs/components/FieldPhone/hooks/index.js +18 -0
  102. package/dist/cjs/components/FieldPhone/hooks/useCountries.d.ts +2 -0
  103. package/dist/cjs/components/FieldPhone/hooks/useCountries.js +36 -0
  104. package/dist/cjs/components/FieldPhone/hooks/useMapCountryToOptions.d.ts +2 -0
  105. package/dist/cjs/components/FieldPhone/hooks/useMapCountryToOptions.js +20 -0
  106. package/dist/cjs/components/FieldPhone/index.d.ts +5 -0
  107. package/dist/cjs/components/FieldPhone/index.js +24 -0
  108. package/dist/cjs/components/FieldPhone/styles.module.css +3 -0
  109. package/dist/cjs/components/FieldPhone/types.d.ts +31 -0
  110. package/dist/cjs/components/FieldPhone/types.js +2 -0
  111. package/dist/cjs/components/FieldPhone/utils.d.ts +14 -0
  112. package/dist/cjs/components/FieldPhone/utils.js +85 -0
  113. package/dist/cjs/components/FieldSelectCreate/FieldSelectCreate.d.ts +8 -0
  114. package/dist/cjs/components/FieldSelectCreate/FieldSelectCreate.js +66 -0
  115. package/dist/cjs/components/FieldSelectCreate/constants.d.ts +14 -0
  116. package/dist/cjs/components/FieldSelectCreate/constants.js +17 -0
  117. package/dist/cjs/components/FieldSelectCreate/helperComponents/SelectFooter/SelectFooter.d.ts +8 -0
  118. package/dist/cjs/components/FieldSelectCreate/helperComponents/SelectFooter/SelectFooter.js +19 -0
  119. package/dist/cjs/components/FieldSelectCreate/helperComponents/SelectFooter/index.d.ts +1 -0
  120. package/dist/cjs/components/FieldSelectCreate/helperComponents/SelectFooter/index.js +17 -0
  121. package/dist/cjs/components/FieldSelectCreate/helperComponents/SelectFooter/styles.module.css +6 -0
  122. package/dist/cjs/components/FieldSelectCreate/index.d.ts +3 -0
  123. package/dist/cjs/components/FieldSelectCreate/index.js +19 -0
  124. package/dist/cjs/components/FieldSelectCreate/styles.module.css +9 -0
  125. package/dist/cjs/components/FieldSelectCreate/types.d.ts +58 -0
  126. package/dist/cjs/components/FieldSelectCreate/types.js +2 -0
  127. package/dist/cjs/components/FieldSelectCreate/useSelectDataStates.d.ts +11 -0
  128. package/dist/cjs/components/FieldSelectCreate/useSelectDataStates.js +29 -0
  129. package/dist/cjs/components/FieldSelectCreate/utils.d.ts +2 -0
  130. package/dist/cjs/components/FieldSelectCreate/utils.js +7 -0
  131. package/dist/cjs/components/index.d.ts +7 -0
  132. package/dist/cjs/components/index.js +23 -0
  133. package/dist/cjs/constants.d.ts +19 -0
  134. package/dist/cjs/constants.js +22 -0
  135. package/dist/cjs/helpers/getSymbolsRangeFromMask.d.ts +7 -0
  136. package/dist/cjs/helpers/getSymbolsRangeFromMask.js +15 -0
  137. package/dist/cjs/helpers/index.d.ts +1 -0
  138. package/dist/cjs/helpers/index.js +17 -0
  139. package/dist/cjs/hooks/index.d.ts +2 -0
  140. package/dist/cjs/hooks/index.js +18 -0
  141. package/dist/cjs/hooks/useCustomFieldValidation.d.ts +12 -0
  142. package/dist/cjs/hooks/useCustomFieldValidation.js +32 -0
  143. package/dist/cjs/hooks/useOpen.d.ts +5 -0
  144. package/dist/cjs/hooks/useOpen.js +18 -0
  145. package/dist/cjs/index.d.ts +6 -0
  146. package/dist/cjs/index.js +25 -0
  147. package/dist/cjs/locale/index.d.ts +845 -0
  148. package/dist/cjs/locale/index.js +429 -0
  149. package/dist/cjs/package.json +3 -0
  150. package/dist/cjs/style.css +136 -0
  151. package/dist/esm/components/FieldChat/FieldChat.d.ts +7 -0
  152. package/dist/esm/components/FieldChat/FieldChat.js +44 -0
  153. package/dist/esm/components/FieldChat/components/Attachments/Attachments.d.ts +8 -0
  154. package/dist/esm/components/FieldChat/components/Attachments/Attachments.js +10 -0
  155. package/dist/esm/components/FieldChat/components/Attachments/index.d.ts +1 -0
  156. package/dist/esm/components/FieldChat/components/Attachments/index.js +1 -0
  157. package/dist/esm/components/FieldChat/components/Attachments/styles.module.css +12 -0
  158. package/dist/esm/components/FieldChat/components/FieldSubmitButton/FieldSubmitButton.d.ts +18 -0
  159. package/dist/esm/components/FieldChat/components/FieldSubmitButton/FieldSubmitButton.js +16 -0
  160. package/dist/esm/components/FieldChat/components/FieldSubmitButton/index.d.ts +1 -0
  161. package/dist/esm/components/FieldChat/components/FieldSubmitButton/index.js +1 -0
  162. package/dist/esm/components/FieldChat/components/FieldSubmitButton/styles.module.css +3 -0
  163. package/dist/esm/components/FieldChat/components/TextAreaActionsFooter/TextAreaActionsFooter.d.ts +8 -0
  164. package/dist/esm/components/FieldChat/components/TextAreaActionsFooter/TextAreaActionsFooter.js +5 -0
  165. package/dist/esm/components/FieldChat/components/TextAreaActionsFooter/index.d.ts +1 -0
  166. package/dist/esm/components/FieldChat/components/TextAreaActionsFooter/index.js +1 -0
  167. package/dist/esm/components/FieldChat/components/TextAreaActionsFooter/styles.module.css +25 -0
  168. package/dist/esm/components/FieldChat/index.d.ts +2 -0
  169. package/dist/esm/components/FieldChat/index.js +2 -0
  170. package/dist/esm/components/FieldChat/styles.module.css +14 -0
  171. package/dist/esm/components/FieldChat/types.d.ts +14 -0
  172. package/dist/esm/components/FieldChat/types.js +1 -0
  173. package/dist/esm/components/FieldCode/FieldCode.d.ts +30 -0
  174. package/dist/esm/components/FieldCode/FieldCode.js +36 -0
  175. package/dist/esm/components/FieldCode/components/Cell/Cell.d.ts +7 -0
  176. package/dist/esm/components/FieldCode/components/Cell/Cell.js +11 -0
  177. package/dist/esm/components/FieldCode/components/Cell/index.d.ts +1 -0
  178. package/dist/esm/components/FieldCode/components/Cell/index.js +1 -0
  179. package/dist/esm/components/FieldCode/components/Cell/styles.module.css +19 -0
  180. package/dist/esm/components/FieldCode/components/ResendCode/ResendCode.d.ts +8 -0
  181. package/dist/esm/components/FieldCode/components/ResendCode/ResendCode.js +16 -0
  182. package/dist/esm/components/FieldCode/components/ResendCode/index.d.ts +1 -0
  183. package/dist/esm/components/FieldCode/components/ResendCode/index.js +1 -0
  184. package/dist/esm/components/FieldCode/components/ResendCode/utils.d.ts +1 -0
  185. package/dist/esm/components/FieldCode/components/ResendCode/utils.js +5 -0
  186. package/dist/esm/components/FieldCode/components/index.d.ts +2 -0
  187. package/dist/esm/components/FieldCode/components/index.js +2 -0
  188. package/dist/esm/components/FieldCode/constants.d.ts +2 -0
  189. package/dist/esm/components/FieldCode/constants.js +2 -0
  190. package/dist/esm/components/FieldCode/hooks/index.d.ts +5 -0
  191. package/dist/esm/components/FieldCode/hooks/index.js +5 -0
  192. package/dist/esm/components/FieldCode/hooks/useCodeInput.d.ts +22 -0
  193. package/dist/esm/components/FieldCode/hooks/useCodeInput.js +94 -0
  194. package/dist/esm/components/FieldCode/hooks/useFieldCodeOverflow.d.ts +6 -0
  195. package/dist/esm/components/FieldCode/hooks/useFieldCodeOverflow.js +40 -0
  196. package/dist/esm/components/FieldCode/hooks/useFieldCodeValidate.d.ts +6 -0
  197. package/dist/esm/components/FieldCode/hooks/useFieldCodeValidate.js +19 -0
  198. package/dist/esm/components/FieldCode/hooks/useFieldHelpers.d.ts +12 -0
  199. package/dist/esm/components/FieldCode/hooks/useFieldHelpers.js +28 -0
  200. package/dist/esm/components/FieldCode/hooks/useFocusCell.d.ts +5 -0
  201. package/dist/esm/components/FieldCode/hooks/useFocusCell.js +18 -0
  202. package/dist/esm/components/FieldCode/hooks/useRefState.d.ts +7 -0
  203. package/dist/esm/components/FieldCode/hooks/useRefState.js +18 -0
  204. package/dist/esm/components/FieldCode/index.d.ts +3 -0
  205. package/dist/esm/components/FieldCode/index.js +3 -0
  206. package/dist/esm/components/FieldCode/styles.module.css +45 -0
  207. package/dist/esm/components/FieldCode/utils.d.ts +6 -0
  208. package/dist/esm/components/FieldCode/utils.js +13 -0
  209. package/dist/esm/components/FieldDescription/FieldDescription.d.ts +10 -0
  210. package/dist/esm/components/FieldDescription/FieldDescription.js +49 -0
  211. package/dist/esm/components/FieldDescription/FieldDescriptionRHF.d.ts +9 -0
  212. package/dist/esm/components/FieldDescription/FieldDescriptionRHF.js +41 -0
  213. package/dist/esm/components/FieldDescription/components/FieldWithAddButton.d.ts +7 -0
  214. package/dist/esm/components/FieldDescription/components/FieldWithAddButton.js +24 -0
  215. package/dist/esm/components/FieldDescription/components/index.d.ts +1 -0
  216. package/dist/esm/components/FieldDescription/components/index.js +1 -0
  217. package/dist/esm/components/FieldDescription/constants.d.ts +1 -0
  218. package/dist/esm/components/FieldDescription/constants.js +1 -0
  219. package/dist/esm/components/FieldDescription/index.d.ts +3 -0
  220. package/dist/esm/components/FieldDescription/index.js +3 -0
  221. package/dist/esm/components/FieldDescription/types.d.ts +17 -0
  222. package/dist/esm/components/FieldDescription/types.js +1 -0
  223. package/dist/esm/components/FieldMask/FieldMask.d.ts +12 -0
  224. package/dist/esm/components/FieldMask/FieldMask.js +24 -0
  225. package/dist/esm/components/FieldMask/constants.d.ts +19 -0
  226. package/dist/esm/components/FieldMask/constants.js +57 -0
  227. package/dist/esm/components/FieldMask/index.d.ts +3 -0
  228. package/dist/esm/components/FieldMask/index.js +3 -0
  229. package/dist/esm/components/FieldMask/types.d.ts +3 -0
  230. package/dist/esm/components/FieldMask/types.js +1 -0
  231. package/dist/esm/components/FieldName/FieldName.d.ts +5 -0
  232. package/dist/esm/components/FieldName/FieldName.js +78 -0
  233. package/dist/esm/components/FieldName/FieldNameRHF.d.ts +5 -0
  234. package/dist/esm/components/FieldName/FieldNameRHF.js +62 -0
  235. package/dist/esm/components/FieldName/constants.d.ts +1 -0
  236. package/dist/esm/components/FieldName/constants.js +1 -0
  237. package/dist/esm/components/FieldName/index.d.ts +3 -0
  238. package/dist/esm/components/FieldName/index.js +3 -0
  239. package/dist/esm/components/FieldName/types.d.ts +22 -0
  240. package/dist/esm/components/FieldName/types.js +1 -0
  241. package/dist/esm/components/FieldPhone/FieldPhone.d.ts +13 -0
  242. package/dist/esm/components/FieldPhone/FieldPhone.js +160 -0
  243. package/dist/esm/components/FieldPhone/constants.d.ts +8 -0
  244. package/dist/esm/components/FieldPhone/constants.js +8 -0
  245. package/dist/esm/components/FieldPhone/countries.d.ts +3500 -0
  246. package/dist/esm/components/FieldPhone/countries.js +1435 -0
  247. package/dist/esm/components/FieldPhone/hooks/index.d.ts +2 -0
  248. package/dist/esm/components/FieldPhone/hooks/index.js +2 -0
  249. package/dist/esm/components/FieldPhone/hooks/useCountries.d.ts +2 -0
  250. package/dist/esm/components/FieldPhone/hooks/useCountries.js +33 -0
  251. package/dist/esm/components/FieldPhone/hooks/useMapCountryToOptions.d.ts +2 -0
  252. package/dist/esm/components/FieldPhone/hooks/useMapCountryToOptions.js +17 -0
  253. package/dist/esm/components/FieldPhone/index.d.ts +5 -0
  254. package/dist/esm/components/FieldPhone/index.js +5 -0
  255. package/dist/esm/components/FieldPhone/styles.module.css +3 -0
  256. package/dist/esm/components/FieldPhone/types.d.ts +31 -0
  257. package/dist/esm/components/FieldPhone/types.js +1 -0
  258. package/dist/esm/components/FieldPhone/utils.d.ts +14 -0
  259. package/dist/esm/components/FieldPhone/utils.js +78 -0
  260. package/dist/esm/components/FieldSelectCreate/FieldSelectCreate.d.ts +8 -0
  261. package/dist/esm/components/FieldSelectCreate/FieldSelectCreate.js +60 -0
  262. package/dist/esm/components/FieldSelectCreate/constants.d.ts +14 -0
  263. package/dist/esm/components/FieldSelectCreate/constants.js +14 -0
  264. package/dist/esm/components/FieldSelectCreate/helperComponents/SelectFooter/SelectFooter.d.ts +8 -0
  265. package/dist/esm/components/FieldSelectCreate/helperComponents/SelectFooter/SelectFooter.js +13 -0
  266. package/dist/esm/components/FieldSelectCreate/helperComponents/SelectFooter/index.d.ts +1 -0
  267. package/dist/esm/components/FieldSelectCreate/helperComponents/SelectFooter/index.js +1 -0
  268. package/dist/esm/components/FieldSelectCreate/helperComponents/SelectFooter/styles.module.css +6 -0
  269. package/dist/esm/components/FieldSelectCreate/index.d.ts +3 -0
  270. package/dist/esm/components/FieldSelectCreate/index.js +3 -0
  271. package/dist/esm/components/FieldSelectCreate/styles.module.css +9 -0
  272. package/dist/esm/components/FieldSelectCreate/types.d.ts +58 -0
  273. package/dist/esm/components/FieldSelectCreate/types.js +1 -0
  274. package/dist/esm/components/FieldSelectCreate/useSelectDataStates.d.ts +11 -0
  275. package/dist/esm/components/FieldSelectCreate/useSelectDataStates.js +26 -0
  276. package/dist/esm/components/FieldSelectCreate/utils.d.ts +2 -0
  277. package/dist/esm/components/FieldSelectCreate/utils.js +4 -0
  278. package/dist/esm/components/index.d.ts +7 -0
  279. package/dist/esm/components/index.js +7 -0
  280. package/dist/esm/constants.d.ts +19 -0
  281. package/dist/esm/constants.js +19 -0
  282. package/dist/esm/helpers/getSymbolsRangeFromMask.d.ts +7 -0
  283. package/dist/esm/helpers/getSymbolsRangeFromMask.js +12 -0
  284. package/dist/esm/helpers/index.d.ts +1 -0
  285. package/dist/esm/helpers/index.js +1 -0
  286. package/dist/esm/hooks/index.d.ts +2 -0
  287. package/dist/esm/hooks/index.js +2 -0
  288. package/dist/esm/hooks/useCustomFieldValidation.d.ts +12 -0
  289. package/dist/esm/hooks/useCustomFieldValidation.js +28 -0
  290. package/dist/esm/hooks/useOpen.d.ts +5 -0
  291. package/dist/esm/hooks/useOpen.js +15 -0
  292. package/dist/esm/index.d.ts +6 -0
  293. package/dist/esm/index.js +6 -0
  294. package/dist/esm/locale/index.d.ts +845 -0
  295. package/dist/esm/locale/index.js +426 -0
  296. package/dist/esm/style.css +136 -0
  297. package/dist/tsconfig.cjs.tsbuildinfo +1 -0
  298. package/dist/tsconfig.esm.tsbuildinfo +1 -0
  299. package/package.json +74 -0
  300. package/src/components/FieldChat/FieldChat.tsx +113 -0
  301. package/src/components/FieldChat/components/Attachments/Attachments.tsx +31 -0
  302. package/src/components/FieldChat/components/Attachments/index.ts +1 -0
  303. package/src/components/FieldChat/components/Attachments/styles.module.scss +19 -0
  304. package/src/components/FieldChat/components/FieldSubmitButton/FieldSubmitButton.tsx +71 -0
  305. package/src/components/FieldChat/components/FieldSubmitButton/index.ts +1 -0
  306. package/src/components/FieldChat/components/FieldSubmitButton/styles.module.scss +6 -0
  307. package/src/components/FieldChat/components/TextAreaActionsFooter/TextAreaActionsFooter.tsx +19 -0
  308. package/src/components/FieldChat/components/TextAreaActionsFooter/index.ts +1 -0
  309. package/src/components/FieldChat/components/TextAreaActionsFooter/styles.module.scss +29 -0
  310. package/src/components/FieldChat/index.ts +2 -0
  311. package/src/components/FieldChat/styles.module.scss +20 -0
  312. package/src/components/FieldChat/types.ts +29 -0
  313. package/src/components/FieldCode/FieldCode.tsx +138 -0
  314. package/src/components/FieldCode/components/Cell/Cell.tsx +35 -0
  315. package/src/components/FieldCode/components/Cell/index.ts +1 -0
  316. package/src/components/FieldCode/components/Cell/styles.module.scss +27 -0
  317. package/src/components/FieldCode/components/ResendCode/ResendCode.tsx +41 -0
  318. package/src/components/FieldCode/components/ResendCode/index.ts +1 -0
  319. package/src/components/FieldCode/components/ResendCode/utils.ts +5 -0
  320. package/src/components/FieldCode/components/index.ts +2 -0
  321. package/src/components/FieldCode/constants.ts +2 -0
  322. package/src/components/FieldCode/hooks/index.ts +5 -0
  323. package/src/components/FieldCode/hooks/useCodeInput.ts +146 -0
  324. package/src/components/FieldCode/hooks/useFieldCodeOverflow.ts +53 -0
  325. package/src/components/FieldCode/hooks/useFieldCodeValidate.ts +32 -0
  326. package/src/components/FieldCode/hooks/useFieldHelpers.ts +45 -0
  327. package/src/components/FieldCode/hooks/useFocusCell.ts +26 -0
  328. package/src/components/FieldCode/hooks/useRefState.ts +23 -0
  329. package/src/components/FieldCode/index.ts +3 -0
  330. package/src/components/FieldCode/styles.module.scss +51 -0
  331. package/src/components/FieldCode/utils.ts +23 -0
  332. package/src/components/FieldDescription/FieldDescription.tsx +98 -0
  333. package/src/components/FieldDescription/FieldDescriptionRHF.tsx +93 -0
  334. package/src/components/FieldDescription/components/FieldWithAddButton.tsx +51 -0
  335. package/src/components/FieldDescription/components/index.ts +1 -0
  336. package/src/components/FieldDescription/constants.ts +1 -0
  337. package/src/components/FieldDescription/index.ts +3 -0
  338. package/src/components/FieldDescription/types.ts +23 -0
  339. package/src/components/FieldMask/FieldMask.tsx +56 -0
  340. package/src/components/FieldMask/constants.ts +70 -0
  341. package/src/components/FieldMask/index.ts +3 -0
  342. package/src/components/FieldMask/types.ts +5 -0
  343. package/src/components/FieldName/FieldName.tsx +126 -0
  344. package/src/components/FieldName/FieldNameRHF.tsx +114 -0
  345. package/src/components/FieldName/constants.ts +1 -0
  346. package/src/components/FieldName/index.ts +3 -0
  347. package/src/components/FieldName/types.ts +28 -0
  348. package/src/components/FieldPhone/FieldPhone.tsx +264 -0
  349. package/src/components/FieldPhone/constants.ts +10 -0
  350. package/src/components/FieldPhone/countries.tsx +1755 -0
  351. package/src/components/FieldPhone/hooks/index.ts +2 -0
  352. package/src/components/FieldPhone/hooks/useCountries.ts +40 -0
  353. package/src/components/FieldPhone/hooks/useMapCountryToOptions.ts +25 -0
  354. package/src/components/FieldPhone/index.ts +5 -0
  355. package/src/components/FieldPhone/styles.module.scss +9 -0
  356. package/src/components/FieldPhone/types.ts +32 -0
  357. package/src/components/FieldPhone/utils.ts +112 -0
  358. package/src/components/FieldSelectCreate/FieldSelectCreate.tsx +133 -0
  359. package/src/components/FieldSelectCreate/constants.ts +15 -0
  360. package/src/components/FieldSelectCreate/helperComponents/SelectFooter/SelectFooter.tsx +37 -0
  361. package/src/components/FieldSelectCreate/helperComponents/SelectFooter/index.ts +1 -0
  362. package/src/components/FieldSelectCreate/helperComponents/SelectFooter/styles.module.scss +8 -0
  363. package/src/components/FieldSelectCreate/index.ts +3 -0
  364. package/src/components/FieldSelectCreate/styles.module.scss +12 -0
  365. package/src/components/FieldSelectCreate/types.ts +70 -0
  366. package/src/components/FieldSelectCreate/useSelectDataStates.tsx +57 -0
  367. package/src/components/FieldSelectCreate/utils.ts +4 -0
  368. package/src/components/index.ts +7 -0
  369. package/src/constants.ts +19 -0
  370. package/src/helpers/getSymbolsRangeFromMask.ts +15 -0
  371. package/src/helpers/index.ts +1 -0
  372. package/src/hooks/index.ts +2 -0
  373. package/src/hooks/useCustomFieldValidation.ts +38 -0
  374. package/src/hooks/useOpen.ts +22 -0
  375. package/src/index.ts +6 -0
  376. 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-режим) |