@cloud-ru/ds-fields 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 (314) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/LICENSE +201 -0
  3. package/README.md +888 -0
  4. package/dist/cjs/components/FieldColor/FieldColor.d.ts +48 -0
  5. package/dist/cjs/components/FieldColor/FieldColor.js +147 -0
  6. package/dist/cjs/components/FieldColor/index.d.ts +1 -0
  7. package/dist/cjs/components/FieldColor/index.js +17 -0
  8. package/dist/cjs/components/FieldColor/styles.module.css +79 -0
  9. package/dist/cjs/components/FieldColor/utils.d.ts +7 -0
  10. package/dist/cjs/components/FieldColor/utils.js +19 -0
  11. package/dist/cjs/components/FieldCombo/FieldCombo.d.ts +91 -0
  12. package/dist/cjs/components/FieldCombo/FieldCombo.js +200 -0
  13. package/dist/cjs/components/FieldCombo/index.d.ts +1 -0
  14. package/dist/cjs/components/FieldCombo/index.js +17 -0
  15. package/dist/cjs/components/FieldDate/FieldDate.d.ts +2 -0
  16. package/dist/cjs/components/FieldDate/FieldDate.js +369 -0
  17. package/dist/cjs/components/FieldDate/constants.d.ts +10 -0
  18. package/dist/cjs/components/FieldDate/constants.js +13 -0
  19. package/dist/cjs/components/FieldDate/index.d.ts +3 -0
  20. package/dist/cjs/components/FieldDate/index.js +19 -0
  21. package/dist/cjs/components/FieldDate/mask.d.ts +20 -0
  22. package/dist/cjs/components/FieldDate/mask.js +117 -0
  23. package/dist/cjs/components/FieldDate/styles.module.css +43 -0
  24. package/dist/cjs/components/FieldDate/types.d.ts +100 -0
  25. package/dist/cjs/components/FieldDate/types.js +2 -0
  26. package/dist/cjs/components/FieldDate/utils.d.ts +3 -0
  27. package/dist/cjs/components/FieldDate/utils.js +8 -0
  28. package/dist/cjs/components/FieldSecure/FieldSecure.d.ts +64 -0
  29. package/dist/cjs/components/FieldSecure/FieldSecure.js +158 -0
  30. package/dist/cjs/components/FieldSecure/index.d.ts +1 -0
  31. package/dist/cjs/components/FieldSecure/index.js +17 -0
  32. package/dist/cjs/components/FieldSelect/FieldSelect.d.ts +2 -0
  33. package/dist/cjs/components/FieldSelect/FieldSelect.js +360 -0
  34. package/dist/cjs/components/FieldSelect/constants.d.ts +4 -0
  35. package/dist/cjs/components/FieldSelect/constants.js +7 -0
  36. package/dist/cjs/components/FieldSelect/index.d.ts +3 -0
  37. package/dist/cjs/components/FieldSelect/index.js +19 -0
  38. package/dist/cjs/components/FieldSelect/styles.module.css +92 -0
  39. package/dist/cjs/components/FieldSelect/types.d.ts +197 -0
  40. package/dist/cjs/components/FieldSelect/types.js +2 -0
  41. package/dist/cjs/components/FieldSelect/utils.d.ts +19 -0
  42. package/dist/cjs/components/FieldSelect/utils.js +104 -0
  43. package/dist/cjs/components/FieldSlider/FieldSlider.d.ts +92 -0
  44. package/dist/cjs/components/FieldSlider/FieldSlider.js +196 -0
  45. package/dist/cjs/components/FieldSlider/index.d.ts +2 -0
  46. package/dist/cjs/components/FieldSlider/index.js +18 -0
  47. package/dist/cjs/components/FieldSlider/styles.module.css +44 -0
  48. package/dist/cjs/components/FieldSlider/types.d.ts +4 -0
  49. package/dist/cjs/components/FieldSlider/types.js +2 -0
  50. package/dist/cjs/components/FieldSlider/utils/generateAllowedValues.d.ts +1 -0
  51. package/dist/cjs/components/FieldSlider/utils/generateAllowedValues.js +16 -0
  52. package/dist/cjs/components/FieldSlider/utils/getClosestMark.d.ts +4 -0
  53. package/dist/cjs/components/FieldSlider/utils/getClosestMark.js +16 -0
  54. package/dist/cjs/components/FieldSlider/utils/getMarkLabel.d.ts +2 -0
  55. package/dist/cjs/components/FieldSlider/utils/getMarkLabel.js +7 -0
  56. package/dist/cjs/components/FieldSlider/utils/getTextFieldValue.d.ts +2 -0
  57. package/dist/cjs/components/FieldSlider/utils/getTextFieldValue.js +9 -0
  58. package/dist/cjs/components/FieldSlider/utils/index.d.ts +5 -0
  59. package/dist/cjs/components/FieldSlider/utils/index.js +21 -0
  60. package/dist/cjs/components/FieldSlider/utils/isMarkObject.d.ts +6 -0
  61. package/dist/cjs/components/FieldSlider/utils/isMarkObject.js +6 -0
  62. package/dist/cjs/components/FieldStepper/FieldStepper.d.ts +81 -0
  63. package/dist/cjs/components/FieldStepper/FieldStepper.js +160 -0
  64. package/dist/cjs/components/FieldStepper/index.d.ts +1 -0
  65. package/dist/cjs/components/FieldStepper/index.js +17 -0
  66. package/dist/cjs/components/FieldStepper/styles.module.css +78 -0
  67. package/dist/cjs/components/FieldStepper/utils.d.ts +14 -0
  68. package/dist/cjs/components/FieldStepper/utils.js +45 -0
  69. package/dist/cjs/components/FieldText/FieldText.d.ts +11 -0
  70. package/dist/cjs/components/FieldText/FieldText.js +14 -0
  71. package/dist/cjs/components/FieldText/index.d.ts +1 -0
  72. package/dist/cjs/components/FieldText/index.js +17 -0
  73. package/dist/cjs/components/FieldTextArea/FieldTextArea.d.ts +95 -0
  74. package/dist/cjs/components/FieldTextArea/FieldTextArea.js +114 -0
  75. package/dist/cjs/components/FieldTextArea/index.d.ts +1 -0
  76. package/dist/cjs/components/FieldTextArea/index.js +17 -0
  77. package/dist/cjs/components/FieldTextArea/styles.module.css +123 -0
  78. package/dist/cjs/components/FieldTime/FieldTime.d.ts +74 -0
  79. package/dist/cjs/components/FieldTime/FieldTime.js +167 -0
  80. package/dist/cjs/components/FieldTime/index.d.ts +2 -0
  81. package/dist/cjs/components/FieldTime/index.js +17 -0
  82. package/dist/cjs/components/FieldTime/mask.d.ts +3 -0
  83. package/dist/cjs/components/FieldTime/mask.js +24 -0
  84. package/dist/cjs/components/FieldTime/styles.module.css +3 -0
  85. package/dist/cjs/components/index.d.ts +14 -0
  86. package/dist/cjs/components/index.js +32 -0
  87. package/dist/cjs/components/shared/helperComponents/FieldElementButton/FieldElementButton.d.ts +35 -0
  88. package/dist/cjs/components/shared/helperComponents/FieldElementButton/FieldElementButton.js +47 -0
  89. package/dist/cjs/components/shared/helperComponents/FieldElementButton/FieldElementButtonList.d.ts +26 -0
  90. package/dist/cjs/components/shared/helperComponents/FieldElementButton/FieldElementButtonList.js +24 -0
  91. package/dist/cjs/components/shared/helperComponents/FieldElementButton/constants.d.ts +9 -0
  92. package/dist/cjs/components/shared/helperComponents/FieldElementButton/constants.js +12 -0
  93. package/dist/cjs/components/shared/helperComponents/FieldElementButton/index.d.ts +4 -0
  94. package/dist/cjs/components/shared/helperComponents/FieldElementButton/index.js +20 -0
  95. package/dist/cjs/components/shared/helperComponents/FieldElementButton/styles.module.css +204 -0
  96. package/dist/cjs/components/shared/helperComponents/FieldElementButton/types.d.ts +4 -0
  97. package/dist/cjs/components/shared/helperComponents/FieldElementButton/types.js +2 -0
  98. package/dist/cjs/components/shared/helperComponents/FieldShell/FieldShell.d.ts +43 -0
  99. package/dist/cjs/components/shared/helperComponents/FieldShell/FieldShell.js +22 -0
  100. package/dist/cjs/components/shared/helperComponents/FieldShell/index.d.ts +1 -0
  101. package/dist/cjs/components/shared/helperComponents/FieldShell/index.js +17 -0
  102. package/dist/cjs/components/shared/helperComponents/FieldShell/styles.module.css +11 -0
  103. package/dist/cjs/components/shared/hooks/useCopyButton.d.ts +20 -0
  104. package/dist/cjs/components/shared/hooks/useCopyButton.js +58 -0
  105. package/dist/cjs/components/shared/index.d.ts +4 -0
  106. package/dist/cjs/components/shared/index.js +20 -0
  107. package/dist/cjs/components/shared/styles.module.css +673 -0
  108. package/dist/cjs/components/shared/utils.d.ts +69 -0
  109. package/dist/cjs/components/shared/utils.js +104 -0
  110. package/dist/cjs/constants.d.ts +61 -0
  111. package/dist/cjs/constants.js +76 -0
  112. package/dist/cjs/hooks/index.d.ts +1 -0
  113. package/dist/cjs/hooks/index.js +17 -0
  114. package/dist/cjs/hooks/useAdaptiveAutoFocus.d.ts +7 -0
  115. package/dist/cjs/hooks/useAdaptiveAutoFocus.js +10 -0
  116. package/dist/cjs/index.d.ts +3 -0
  117. package/dist/cjs/index.js +19 -0
  118. package/dist/cjs/package.json +3 -0
  119. package/dist/cjs/segments/index.d.ts +2 -0
  120. package/dist/cjs/segments/index.js +18 -0
  121. package/dist/cjs/segments/segments.d.ts +22 -0
  122. package/dist/cjs/segments/segments.js +46 -0
  123. package/dist/cjs/segments/useSegmentedMask.d.ts +43 -0
  124. package/dist/cjs/segments/useSegmentedMask.js +282 -0
  125. package/dist/cjs/style.css +1350 -0
  126. package/dist/esm/components/FieldColor/FieldColor.d.ts +48 -0
  127. package/dist/esm/components/FieldColor/FieldColor.js +141 -0
  128. package/dist/esm/components/FieldColor/index.d.ts +1 -0
  129. package/dist/esm/components/FieldColor/index.js +1 -0
  130. package/dist/esm/components/FieldColor/styles.module.css +79 -0
  131. package/dist/esm/components/FieldColor/utils.d.ts +7 -0
  132. package/dist/esm/components/FieldColor/utils.js +16 -0
  133. package/dist/esm/components/FieldCombo/FieldCombo.d.ts +91 -0
  134. package/dist/esm/components/FieldCombo/FieldCombo.js +194 -0
  135. package/dist/esm/components/FieldCombo/index.d.ts +1 -0
  136. package/dist/esm/components/FieldCombo/index.js +1 -0
  137. package/dist/esm/components/FieldDate/FieldDate.d.ts +2 -0
  138. package/dist/esm/components/FieldDate/FieldDate.js +363 -0
  139. package/dist/esm/components/FieldDate/constants.d.ts +10 -0
  140. package/dist/esm/components/FieldDate/constants.js +10 -0
  141. package/dist/esm/components/FieldDate/index.d.ts +3 -0
  142. package/dist/esm/components/FieldDate/index.js +3 -0
  143. package/dist/esm/components/FieldDate/mask.d.ts +20 -0
  144. package/dist/esm/components/FieldDate/mask.js +111 -0
  145. package/dist/esm/components/FieldDate/styles.module.css +43 -0
  146. package/dist/esm/components/FieldDate/types.d.ts +100 -0
  147. package/dist/esm/components/FieldDate/types.js +1 -0
  148. package/dist/esm/components/FieldDate/utils.d.ts +3 -0
  149. package/dist/esm/components/FieldDate/utils.js +5 -0
  150. package/dist/esm/components/FieldSecure/FieldSecure.d.ts +64 -0
  151. package/dist/esm/components/FieldSecure/FieldSecure.js +152 -0
  152. package/dist/esm/components/FieldSecure/index.d.ts +1 -0
  153. package/dist/esm/components/FieldSecure/index.js +1 -0
  154. package/dist/esm/components/FieldSelect/FieldSelect.d.ts +2 -0
  155. package/dist/esm/components/FieldSelect/FieldSelect.js +354 -0
  156. package/dist/esm/components/FieldSelect/constants.d.ts +4 -0
  157. package/dist/esm/components/FieldSelect/constants.js +4 -0
  158. package/dist/esm/components/FieldSelect/index.d.ts +3 -0
  159. package/dist/esm/components/FieldSelect/index.js +3 -0
  160. package/dist/esm/components/FieldSelect/styles.module.css +92 -0
  161. package/dist/esm/components/FieldSelect/types.d.ts +197 -0
  162. package/dist/esm/components/FieldSelect/types.js +1 -0
  163. package/dist/esm/components/FieldSelect/utils.d.ts +19 -0
  164. package/dist/esm/components/FieldSelect/utils.js +93 -0
  165. package/dist/esm/components/FieldSlider/FieldSlider.d.ts +92 -0
  166. package/dist/esm/components/FieldSlider/FieldSlider.js +190 -0
  167. package/dist/esm/components/FieldSlider/index.d.ts +2 -0
  168. package/dist/esm/components/FieldSlider/index.js +2 -0
  169. package/dist/esm/components/FieldSlider/styles.module.css +44 -0
  170. package/dist/esm/components/FieldSlider/types.d.ts +4 -0
  171. package/dist/esm/components/FieldSlider/types.js +1 -0
  172. package/dist/esm/components/FieldSlider/utils/generateAllowedValues.d.ts +1 -0
  173. package/dist/esm/components/FieldSlider/utils/generateAllowedValues.js +13 -0
  174. package/dist/esm/components/FieldSlider/utils/getClosestMark.d.ts +4 -0
  175. package/dist/esm/components/FieldSlider/utils/getClosestMark.js +13 -0
  176. package/dist/esm/components/FieldSlider/utils/getMarkLabel.d.ts +2 -0
  177. package/dist/esm/components/FieldSlider/utils/getMarkLabel.js +4 -0
  178. package/dist/esm/components/FieldSlider/utils/getTextFieldValue.d.ts +2 -0
  179. package/dist/esm/components/FieldSlider/utils/getTextFieldValue.js +6 -0
  180. package/dist/esm/components/FieldSlider/utils/index.d.ts +5 -0
  181. package/dist/esm/components/FieldSlider/utils/index.js +5 -0
  182. package/dist/esm/components/FieldSlider/utils/isMarkObject.d.ts +6 -0
  183. package/dist/esm/components/FieldSlider/utils/isMarkObject.js +3 -0
  184. package/dist/esm/components/FieldStepper/FieldStepper.d.ts +81 -0
  185. package/dist/esm/components/FieldStepper/FieldStepper.js +154 -0
  186. package/dist/esm/components/FieldStepper/index.d.ts +1 -0
  187. package/dist/esm/components/FieldStepper/index.js +1 -0
  188. package/dist/esm/components/FieldStepper/styles.module.css +78 -0
  189. package/dist/esm/components/FieldStepper/utils.d.ts +14 -0
  190. package/dist/esm/components/FieldStepper/utils.js +38 -0
  191. package/dist/esm/components/FieldText/FieldText.d.ts +11 -0
  192. package/dist/esm/components/FieldText/FieldText.js +11 -0
  193. package/dist/esm/components/FieldText/index.d.ts +1 -0
  194. package/dist/esm/components/FieldText/index.js +1 -0
  195. package/dist/esm/components/FieldTextArea/FieldTextArea.d.ts +95 -0
  196. package/dist/esm/components/FieldTextArea/FieldTextArea.js +108 -0
  197. package/dist/esm/components/FieldTextArea/index.d.ts +1 -0
  198. package/dist/esm/components/FieldTextArea/index.js +1 -0
  199. package/dist/esm/components/FieldTextArea/styles.module.css +123 -0
  200. package/dist/esm/components/FieldTime/FieldTime.d.ts +74 -0
  201. package/dist/esm/components/FieldTime/FieldTime.js +161 -0
  202. package/dist/esm/components/FieldTime/index.d.ts +2 -0
  203. package/dist/esm/components/FieldTime/index.js +1 -0
  204. package/dist/esm/components/FieldTime/mask.d.ts +3 -0
  205. package/dist/esm/components/FieldTime/mask.js +20 -0
  206. package/dist/esm/components/FieldTime/styles.module.css +3 -0
  207. package/dist/esm/components/index.d.ts +14 -0
  208. package/dist/esm/components/index.js +12 -0
  209. package/dist/esm/components/shared/helperComponents/FieldElementButton/FieldElementButton.d.ts +35 -0
  210. package/dist/esm/components/shared/helperComponents/FieldElementButton/FieldElementButton.js +41 -0
  211. package/dist/esm/components/shared/helperComponents/FieldElementButton/FieldElementButtonList.d.ts +26 -0
  212. package/dist/esm/components/shared/helperComponents/FieldElementButton/FieldElementButtonList.js +21 -0
  213. package/dist/esm/components/shared/helperComponents/FieldElementButton/constants.d.ts +9 -0
  214. package/dist/esm/components/shared/helperComponents/FieldElementButton/constants.js +9 -0
  215. package/dist/esm/components/shared/helperComponents/FieldElementButton/index.d.ts +4 -0
  216. package/dist/esm/components/shared/helperComponents/FieldElementButton/index.js +4 -0
  217. package/dist/esm/components/shared/helperComponents/FieldElementButton/styles.module.css +204 -0
  218. package/dist/esm/components/shared/helperComponents/FieldElementButton/types.d.ts +4 -0
  219. package/dist/esm/components/shared/helperComponents/FieldElementButton/types.js +1 -0
  220. package/dist/esm/components/shared/helperComponents/FieldShell/FieldShell.d.ts +43 -0
  221. package/dist/esm/components/shared/helperComponents/FieldShell/FieldShell.js +16 -0
  222. package/dist/esm/components/shared/helperComponents/FieldShell/index.d.ts +1 -0
  223. package/dist/esm/components/shared/helperComponents/FieldShell/index.js +1 -0
  224. package/dist/esm/components/shared/helperComponents/FieldShell/styles.module.css +11 -0
  225. package/dist/esm/components/shared/hooks/useCopyButton.d.ts +20 -0
  226. package/dist/esm/components/shared/hooks/useCopyButton.js +55 -0
  227. package/dist/esm/components/shared/index.d.ts +4 -0
  228. package/dist/esm/components/shared/index.js +4 -0
  229. package/dist/esm/components/shared/styles.module.css +673 -0
  230. package/dist/esm/components/shared/utils.d.ts +69 -0
  231. package/dist/esm/components/shared/utils.js +91 -0
  232. package/dist/esm/constants.d.ts +61 -0
  233. package/dist/esm/constants.js +73 -0
  234. package/dist/esm/hooks/index.d.ts +1 -0
  235. package/dist/esm/hooks/index.js +1 -0
  236. package/dist/esm/hooks/useAdaptiveAutoFocus.d.ts +7 -0
  237. package/dist/esm/hooks/useAdaptiveAutoFocus.js +7 -0
  238. package/dist/esm/index.d.ts +3 -0
  239. package/dist/esm/index.js +3 -0
  240. package/dist/esm/segments/index.d.ts +2 -0
  241. package/dist/esm/segments/index.js +2 -0
  242. package/dist/esm/segments/segments.d.ts +22 -0
  243. package/dist/esm/segments/segments.js +43 -0
  244. package/dist/esm/segments/useSegmentedMask.d.ts +43 -0
  245. package/dist/esm/segments/useSegmentedMask.js +279 -0
  246. package/dist/esm/style.css +1350 -0
  247. package/dist/tsconfig.cjs.tsbuildinfo +1 -0
  248. package/dist/tsconfig.esm.tsbuildinfo +1 -0
  249. package/package.json +62 -0
  250. package/src/components/FieldColor/FieldColor.tsx +426 -0
  251. package/src/components/FieldColor/index.ts +1 -0
  252. package/src/components/FieldColor/styles.module.scss +120 -0
  253. package/src/components/FieldColor/utils.ts +17 -0
  254. package/src/components/FieldCombo/FieldCombo.tsx +495 -0
  255. package/src/components/FieldCombo/index.ts +1 -0
  256. package/src/components/FieldDate/FieldDate.tsx +658 -0
  257. package/src/components/FieldDate/constants.ts +11 -0
  258. package/src/components/FieldDate/index.ts +3 -0
  259. package/src/components/FieldDate/mask.ts +123 -0
  260. package/src/components/FieldDate/styles.module.scss +56 -0
  261. package/src/components/FieldDate/types.ts +124 -0
  262. package/src/components/FieldDate/utils.ts +7 -0
  263. package/src/components/FieldSecure/FieldSecure.tsx +398 -0
  264. package/src/components/FieldSecure/index.ts +1 -0
  265. package/src/components/FieldSelect/FieldSelect.tsx +689 -0
  266. package/src/components/FieldSelect/constants.ts +4 -0
  267. package/src/components/FieldSelect/index.ts +3 -0
  268. package/src/components/FieldSelect/styles.module.scss +104 -0
  269. package/src/components/FieldSelect/types.ts +212 -0
  270. package/src/components/FieldSelect/utils.ts +134 -0
  271. package/src/components/FieldSlider/FieldSlider.tsx +502 -0
  272. package/src/components/FieldSlider/index.ts +2 -0
  273. package/src/components/FieldSlider/styles.module.scss +47 -0
  274. package/src/components/FieldSlider/types.ts +5 -0
  275. package/src/components/FieldSlider/utils/generateAllowedValues.ts +13 -0
  276. package/src/components/FieldSlider/utils/getClosestMark.ts +21 -0
  277. package/src/components/FieldSlider/utils/getMarkLabel.ts +7 -0
  278. package/src/components/FieldSlider/utils/getTextFieldValue.ts +8 -0
  279. package/src/components/FieldSlider/utils/index.ts +5 -0
  280. package/src/components/FieldSlider/utils/isMarkObject.ts +7 -0
  281. package/src/components/FieldStepper/FieldStepper.tsx +457 -0
  282. package/src/components/FieldStepper/index.ts +1 -0
  283. package/src/components/FieldStepper/styles.module.scss +98 -0
  284. package/src/components/FieldStepper/utils.ts +44 -0
  285. package/src/components/FieldText/FieldText.tsx +27 -0
  286. package/src/components/FieldText/index.ts +1 -0
  287. package/src/components/FieldTextArea/FieldTextArea.tsx +374 -0
  288. package/src/components/FieldTextArea/index.ts +1 -0
  289. package/src/components/FieldTextArea/styles.module.scss +192 -0
  290. package/src/components/FieldTime/FieldTime.tsx +401 -0
  291. package/src/components/FieldTime/index.ts +2 -0
  292. package/src/components/FieldTime/mask.ts +22 -0
  293. package/src/components/FieldTime/styles.module.scss +3 -0
  294. package/src/components/index.ts +14 -0
  295. package/src/components/shared/helperComponents/FieldElementButton/FieldElementButton.tsx +127 -0
  296. package/src/components/shared/helperComponents/FieldElementButton/FieldElementButtonList.tsx +72 -0
  297. package/src/components/shared/helperComponents/FieldElementButton/constants.ts +10 -0
  298. package/src/components/shared/helperComponents/FieldElementButton/index.ts +4 -0
  299. package/src/components/shared/helperComponents/FieldElementButton/styles.module.scss +137 -0
  300. package/src/components/shared/helperComponents/FieldElementButton/types.ts +6 -0
  301. package/src/components/shared/helperComponents/FieldShell/FieldShell.tsx +100 -0
  302. package/src/components/shared/helperComponents/FieldShell/index.ts +1 -0
  303. package/src/components/shared/helperComponents/FieldShell/styles.module.scss +13 -0
  304. package/src/components/shared/hooks/useCopyButton.tsx +103 -0
  305. package/src/components/shared/index.ts +4 -0
  306. package/src/components/shared/styles.module.scss +409 -0
  307. package/src/components/shared/utils.ts +128 -0
  308. package/src/constants.ts +73 -0
  309. package/src/hooks/index.ts +1 -0
  310. package/src/hooks/useAdaptiveAutoFocus.ts +16 -0
  311. package/src/index.ts +3 -0
  312. package/src/segments/index.ts +2 -0
  313. package/src/segments/segments.ts +74 -0
  314. package/src/segments/useSegmentedMask.ts +361 -0
@@ -0,0 +1,48 @@
1
+ import { ColorPickerProps } from '@cloud-ru/ds-color-picker';
2
+ import { FieldDecoratorProps } from '@cloud-ru/ds-field-decorator';
3
+ import { InputPrivateProps } from '@cloud-ru/ds-input-private';
4
+ import { FieldLayoutPresets } from '../../hooks';
5
+ type FieldColorDecoratorProps = Omit<FieldDecoratorProps, 'children'>;
6
+ type FieldColorOwnProps = {
7
+ /** CSS-класс корня `FieldDecorator` */
8
+ className?: string;
9
+ /** CSS-класс оболочки поля */
10
+ fieldClassName?: string;
11
+ /** Текущее значение (hex/rgb/hsl-строка, controlled-режим). */
12
+ value?: string;
13
+ /** Начальное значение (uncontrolled-режим). */
14
+ defaultValue?: string;
15
+ /** Колбек смены значения. */
16
+ onChange?(value: string): void;
17
+ /** Открыт color-picker. */
18
+ open?: boolean;
19
+ /** Колбек смены состояния открытия. */
20
+ onOpenChange?(open: boolean): void;
21
+ /**
22
+ * Показывать кнопку очистки (видна при value && !readonly && !disabled).
23
+ * @default true
24
+ */
25
+ showClearButton?: boolean;
26
+ /** Колбек после клика по кнопке очистки. */
27
+ onClearButtonClick?(): void;
28
+ /**
29
+ * Показывать кнопку копирования (видна при readonly && value && !disabled).
30
+ * @default true
31
+ */
32
+ showCopyButton?: boolean;
33
+ /** Колбек после копирования значения. */
34
+ onCopyButtonClick?(): void;
35
+ /**
36
+ * Переопределение адаптивных дефолтов по раскладке. Участвует `autoFocus`: на mobile он выключен
37
+ * (открывает клавиатуру без действия). Вернуть на mobile — `layoutPresets={{ mobile: { autoFocus: true } }}`.
38
+ */
39
+ layoutPresets?: FieldLayoutPresets;
40
+ /**
41
+ * Фон поля (acrylic).
42
+ * @default true
43
+ */
44
+ background?: boolean;
45
+ } & Pick<ColorPickerProps, 'withAlpha' | 'autoApply' | 'availableModes'>;
46
+ export type FieldColorProps = FieldColorDecoratorProps & Omit<InputPrivateProps, 'className' | 'value' | 'onChange'> & FieldColorOwnProps;
47
+ export declare const FieldColor: import("react").ForwardRefExoticComponent<Omit<FieldColorProps, "ref"> & import("react").RefAttributes<HTMLInputElement>>;
48
+ export {};
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FieldColor = void 0;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const adaptive_1 = require("@cloud-ru/ds-adaptive");
9
+ const bottom_sheet_1 = require("@cloud-ru/ds-bottom-sheet");
10
+ const button_1 = require("@cloud-ru/ds-button");
11
+ const color_picker_1 = require("@cloud-ru/ds-color-picker");
12
+ const dropdown_1 = require("@cloud-ru/ds-dropdown");
13
+ const field_decorator_1 = require("@cloud-ru/ds-field-decorator");
14
+ const system_1 = require("@cloud-ru/ds-icons/interface/system");
15
+ const input_private_1 = require("@cloud-ru/ds-input-private");
16
+ const utils_1 = require("@cloud-ru/ds-utils");
17
+ const classnames_1 = __importDefault(require("classnames"));
18
+ const merge_refs_1 = __importDefault(require("merge-refs"));
19
+ const react_1 = require("react");
20
+ const constants_1 = require("../../constants");
21
+ const hooks_1 = require("../../hooks");
22
+ const shared_1 = require("../shared");
23
+ const styles_module_scss_1 = __importDefault(require('../shared/styles.module.css'));
24
+ const styles_module_scss_2 = __importDefault(require('./styles.module.css'));
25
+ const utils_2 = require("./utils");
26
+ exports.FieldColor = (0, react_1.forwardRef)(function FieldColor({ label = '', labelTooltip, caption, hint, error, validationState = field_decorator_1.VALIDATION_STATE.Default, showHintIcon, length, required, size = field_decorator_1.SIZE.M, className, fieldClassName, background = true, value: valueProp, defaultValue = '', onChange: onChangeProp, open: openProp, onOpenChange, showClearButton: showClearButtonProp = true, onClearButtonClick, showCopyButton: showCopyButtonProp = true, onCopyButtonClick, withAlpha, autoApply, availableModes, layoutPresets, disabled, readonly: readOnly, placeholder, 'data-test-id': dataTestId = constants_1.TEST_IDS.fieldColor, ...inputProps }, ref) {
27
+ const { onFocus: onFocusProp, onBlur: onBlurProp, onKeyDown: onKeyDownProp, tabIndex: tabIndexProp, autoFocus, ...restInputProps } = inputProps;
28
+ const localRef = (0, react_1.useRef)(null);
29
+ const clearButtonRef = (0, react_1.useRef)(null);
30
+ const copyButtonRef = (0, react_1.useRef)(null);
31
+ const [focusVisible, setFocusVisible] = (0, react_1.useState)(false);
32
+ const [hover, setHover] = (0, react_1.useState)(false);
33
+ const [openLocal, setOpenLocal] = (0, react_1.useState)(false);
34
+ const open = openProp ?? openLocal;
35
+ const { layoutType } = (0, adaptive_1.useAdaptiveLayout)();
36
+ const mobile = (0, adaptive_1.isMobileLayout)(layoutType);
37
+ const resolvedAutoFocus = (0, hooks_1.useAdaptiveAutoFocus)(autoFocus, layoutPresets);
38
+ const [value = '', onChange] = (0, utils_1.useValueControl)({
39
+ value: valueProp,
40
+ defaultValue,
41
+ onChange: onChangeProp,
42
+ });
43
+ const effectiveValidationState = (0, react_1.useMemo)(() => (error ? field_decorator_1.VALIDATION_STATE.Error : validationState), [error, validationState]);
44
+ const showOpen = open && !disabled && !readOnly;
45
+ const showClearUi = Boolean(showClearButtonProp && value && !readOnly && !disabled);
46
+ const showCopyUi = Boolean(showCopyButtonProp && value && !disabled && readOnly);
47
+ const handleOpenChange = (0, react_1.useCallback)((next) => {
48
+ if (openProp === undefined)
49
+ setOpenLocal(next);
50
+ onOpenChange?.(next);
51
+ }, [openProp, onOpenChange]);
52
+ // Фокус в поле при открытии пикера (паритет с легаси `@snack-uikit/fields`). На mobile пикер
53
+ // открывается в `BottomSheet` поверх поля — фокус на скрытый под ним input не уводим.
54
+ (0, react_1.useEffect)(() => {
55
+ if (open && !mobile) {
56
+ localRef.current?.focus();
57
+ }
58
+ }, [open, mobile]);
59
+ const onClear = (0, react_1.useCallback)(() => {
60
+ onChange?.('');
61
+ onClearButtonClick?.();
62
+ if (required) {
63
+ localRef.current?.focus();
64
+ }
65
+ }, [onChange, onClearButtonClick, required]);
66
+ const onCopy = (0, react_1.useCallback)(async () => {
67
+ const copied = await (0, shared_1.copyTextToClipboard)(value);
68
+ if (copied) {
69
+ onCopyButtonClick?.();
70
+ }
71
+ return copied;
72
+ }, [onCopyButtonClick, value]);
73
+ const clearButtonSettings = (0, input_private_1.useClearButton)({
74
+ clearButtonRef,
75
+ showClearButton: showClearUi,
76
+ size: (0, shared_1.toInputSize)(size),
77
+ onClear,
78
+ disabled: Boolean(disabled || readOnly),
79
+ });
80
+ const copyButtonSettings = (0, shared_1.useCopyButton)({
81
+ copyButtonRef,
82
+ showCopyButton: showCopyUi,
83
+ size: (0, shared_1.toInputSize)(size),
84
+ onCopy,
85
+ disabled: Boolean(disabled),
86
+ });
87
+ const { postfixButtons, inputTabIndex, onInputKeyDown } = (0, input_private_1.useButtonNavigation)({
88
+ inputRef: localRef,
89
+ postfixButtons: (0, react_1.useMemo)(() => [clearButtonSettings, copyButtonSettings], [clearButtonSettings, copyButtonSettings]),
90
+ readonly: Boolean(readOnly),
91
+ submitKeys: ['Enter', 'Space', 'Tab'],
92
+ });
93
+ const handleKeyDown = (0, react_1.useCallback)((event) => {
94
+ onInputKeyDown(event);
95
+ onKeyDownProp?.(event);
96
+ }, [onInputKeyDown, onKeyDownProp]);
97
+ const handleInputChange = (0, react_1.useCallback)((next) => {
98
+ onChange?.((0, utils_2.normalizeHexInput)(next, withAlpha));
99
+ }, [onChange, withAlpha]);
100
+ const handlePickerChange = (0, react_1.useCallback)((raw) => {
101
+ onChange?.(raw.hex);
102
+ }, [onChange]);
103
+ const { t } = color_picker_1.colorPickerLocale.useTranslations();
104
+ // Mobile: палитра в BottomSheet с явным Apply — правки в черновик, коммит в поле по Apply.
105
+ const [draft, setDraft] = (0, react_1.useState)(value);
106
+ const prevOpenRef = (0, react_1.useRef)(open);
107
+ (0, react_1.useEffect)(() => {
108
+ if (open && !prevOpenRef.current && mobile) {
109
+ setDraft(value);
110
+ }
111
+ prevOpenRef.current = open;
112
+ }, [open, mobile, value]);
113
+ const handleMobileApply = (0, react_1.useCallback)(() => {
114
+ onChange?.(draft ?? '');
115
+ handleOpenChange(false);
116
+ }, [onChange, draft, handleOpenChange]);
117
+ const handleMobileCancel = (0, react_1.useCallback)(() => {
118
+ handleOpenChange(false);
119
+ }, [handleOpenChange]);
120
+ const handleMouseEnter = (0, react_1.useCallback)(() => {
121
+ if (!readOnly && !disabled) {
122
+ setHover(true);
123
+ }
124
+ }, [readOnly, disabled]);
125
+ const handleMouseLeave = (0, react_1.useCallback)(() => {
126
+ setHover(false);
127
+ }, []);
128
+ const handleInputFocus = (0, react_1.useCallback)((event) => {
129
+ setFocusVisible(event.target.matches(':focus-visible'));
130
+ onFocusProp?.(event);
131
+ }, [onFocusProp]);
132
+ const handleInputBlur = (0, react_1.useCallback)((event) => {
133
+ setFocusVisible(false);
134
+ onBlurProp?.(event);
135
+ }, [onBlurProp]);
136
+ const trigger = ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.fieldWrapper, styles_module_scss_2.default.trigger, fieldClassName), "data-size": size, "data-validation-state": effectiveValidationState, "data-disabled": disabled || undefined, "data-readonly": readOnly || undefined, "data-withbackground": background || undefined, "data-focusvisible": focusVisible || showOpen || undefined, "data-hover": !readOnly && !disabled && hover ? true : undefined, "data-test-id": dataTestId, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [(0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.backgroundWrapper, children: [(0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.materialLayer, ...(0, shared_1.getAcrylicProps)({
137
+ validationState: effectiveValidationState,
138
+ disabled,
139
+ readonly: readOnly,
140
+ hover,
141
+ focusVisible: focusVisible || showOpen,
142
+ }), children: (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.acrylicBg, "aria-hidden": true }) }), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.borderStateLayer, "data-state": 'borderOnBackground' }), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.focusLayer })] }), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.fieldContainer, children: (0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.contentWrapper, children: [(0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.iconSlot, children: (0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_2.default.swatch, "data-test-id": constants_1.TEST_IDS.fieldColorSwatch, style: { '--field-color-swatch-color': value || 'transparent' }, "aria-hidden": true }) }), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.inputLine, children: (0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.inputArea, children: [(0, jsx_runtime_1.jsx)(input_private_1.InputPrivate, { ref: (0, merge_refs_1.default)(ref, localRef), className: styles_module_scss_1.default.fieldInput, value: value, onChange: handleInputChange, disabled: disabled, readonly: readOnly, placeholder: placeholder, autoFocus: resolvedAutoFocus, tabIndex: tabIndexProp ?? inputTabIndex, onKeyDown: handleKeyDown, onFocus: handleInputFocus, onBlur: handleInputBlur, ...restInputProps, "data-test-id": constants_1.TEST_IDS.fieldColorInput }), postfixButtons && (0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_1.default.postfixButtonsSlot, children: postfixButtons })] }) }), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.iconSlot, children: (0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_2.default.chevron, "data-test-id": constants_1.TEST_IDS.fieldColorChevron, "aria-hidden": true, children: showOpen ? (0, jsx_runtime_1.jsx)(system_1.ChevronUpSVG, {}) : (0, jsx_runtime_1.jsx)(system_1.ChevronDownSVG, {}) }) })] }) })] }));
143
+ return ((0, jsx_runtime_1.jsx)(field_decorator_1.FieldDecorator, { className: className, label: label, labelTooltip: labelTooltip, caption: caption, hint: hint, error: error, validationState: validationState, showHintIcon: showHintIcon, length: length, required: required, labelFor: inputProps.id, disabled: disabled, readonly: readOnly, size: size, children: (0, jsx_runtime_1.jsx)(dropdown_1.Dropdown, { trigger: 'click', widthStrategy: 'auto', open: showOpen, onOpenChange: handleOpenChange, headerDivider: mobile, footerDivider: mobile, title: mobile ? ((0, jsx_runtime_1.jsxs)("span", { className: styles_module_scss_2.default.sheetTitle, "data-test-id": constants_1.TEST_IDS.fieldColorSheetTitle, children: [(draft || '').toUpperCase(), (0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_2.default.sheetSwatch, style: { '--field-color-swatch-color': draft || 'transparent' }, "aria-hidden": true })] })) : undefined, footer: mobile ? ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_2.default.sheetFooter, children: [(0, jsx_runtime_1.jsx)(button_1.Button, { label: t('cancel'), size: size, view: button_1.VIEW.Function, appearance: button_1.APPEARANCE.Neutral, onClick: handleMobileCancel, "data-test-id": constants_1.TEST_IDS.fieldColorCancel }), (0, jsx_runtime_1.jsx)(button_1.Button, { label: t('apply'), size: size, view: button_1.VIEW.Filled, appearance: button_1.APPEARANCE.Primary, onClick: handleMobileApply, "data-test-id": constants_1.TEST_IDS.fieldColorApply })] })) : undefined, content:
144
+ // На mobile палитра живёт в `BottomSheet`: помечаем её no-drag, иначе drag по слайдеру/области
145
+ // цвета одновременно потащил бы sheet к закрытию (свайп-дисмисс перехватывал бы жест контрола).
146
+ (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_2.default.pickerHost, ...(mobile ? { [bottom_sheet_1.NO_DRAG_ATTRIBUTE]: '' } : {}), children: (0, jsx_runtime_1.jsx)(color_picker_1.ColorPicker, { value: (mobile ? draft : value) || undefined, size: size, withAlpha: withAlpha, withColorArea: mobile ? false : undefined, autoApply: mobile ? true : autoApply, availableModes: availableModes, onChange: mobile ? raw => setDraft(raw.hex) : handlePickerChange, "data-test-id": constants_1.TEST_IDS.fieldColorPicker }) }), children: trigger }) }));
147
+ });
@@ -0,0 +1 @@
1
+ export * from './FieldColor';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./FieldColor"), exports);
@@ -0,0 +1,79 @@
1
+ .trigger{
2
+ cursor:pointer;
3
+ }
4
+
5
+ .swatch{
6
+ position:relative;
7
+ flex:0 0 auto;
8
+ background-color:var(--field-color-swatch-color, transparent);
9
+ background-image:linear-gradient(45deg, var(--sn-theme-color-available-borderColor, var(--sn-brand-color-state-neutralBorder-forLightMode-default-borderColor, rgba(159, 166, 198, 0.3019607843))) 25%, transparent 25%), linear-gradient(-45deg, var(--sn-theme-color-available-borderColor, var(--sn-brand-color-state-neutralBorder-forLightMode-default-borderColor, rgba(159, 166, 198, 0.3019607843))) 25%, transparent 25%), linear-gradient(45deg, transparent 75%, var(--sn-theme-color-available-borderColor, var(--sn-brand-color-state-neutralBorder-forLightMode-default-borderColor, rgba(159, 166, 198, 0.3019607843))) 75%), linear-gradient(-45deg, transparent 75%, var(--sn-theme-color-available-borderColor, var(--sn-brand-color-state-neutralBorder-forLightMode-default-borderColor, rgba(159, 166, 198, 0.3019607843))) 75%);
10
+ background-position:0 0, 0 4px, 4px -4px, -4px 0;
11
+ background-size:8px 8px;
12
+ }
13
+ .swatch::after{
14
+ content:"";
15
+ position:absolute;
16
+ inset:0;
17
+ border-radius:inherit;
18
+ background-color:var(--field-color-swatch-color, transparent);
19
+ }
20
+
21
+ .chevron{
22
+ display:inline-flex;
23
+ align-items:center;
24
+ justify-content:center;
25
+ color:var(--sn-theme-color-available-version-textTertiary, var(--sn-brand-color-text-version-tertiary, rgba(65, 66, 78, 0.5490196078)));
26
+ }
27
+
28
+ .trigger[data-size=s] .swatch{
29
+ width:var(--sn-colorPicker-anatomy-size-s-previewColor-width, var(--sn-density-size-icon-xs, var(--sn-primitive-dimension-24, 24px)));
30
+ height:var(--sn-colorPicker-anatomy-size-s-previewColor-height, var(--sn-density-size-icon-xs, var(--sn-primitive-dimension-24, 24px)));
31
+ border-radius:var(--sn-colorPicker-anatomy-size-s-previewColor-borderRadius, var(--sn-density-radius-2xs, var(--sn-primitive-dimension-4, 4px)));
32
+ }
33
+
34
+ .trigger[data-size=m] .swatch{
35
+ width:var(--sn-colorPicker-anatomy-size-m-previewColor-width, var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px)));
36
+ height:var(--sn-colorPicker-anatomy-size-m-previewColor-height, var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px)));
37
+ border-radius:var(--sn-colorPicker-anatomy-size-m-previewColor-borderRadius, var(--sn-density-radius-s, var(--sn-primitive-dimension-16, 16px)));
38
+ }
39
+
40
+ .trigger[data-size=l] .swatch{
41
+ width:var(--sn-colorPicker-anatomy-size-m-previewColor-width, var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px)));
42
+ height:var(--sn-colorPicker-anatomy-size-m-previewColor-height, var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px)));
43
+ border-radius:var(--sn-colorPicker-anatomy-size-m-previewColor-borderRadius, var(--sn-density-radius-s, var(--sn-primitive-dimension-16, 16px)));
44
+ }
45
+
46
+ .sheetTitle{
47
+ display:inline-flex;
48
+ gap:var(--sn-primitive-dimension-8, 8px);
49
+ align-items:center;
50
+ }
51
+
52
+ .sheetSwatch{
53
+ position:relative;
54
+ flex:0 0 auto;
55
+ width:var(--sn-primitive-dimension-24, 24px);
56
+ height:var(--sn-primitive-dimension-24, 24px);
57
+ border-radius:50%;
58
+ background-color:var(--field-color-swatch-color, transparent);
59
+ background-image:linear-gradient(45deg, var(--sn-theme-color-available-borderColor, var(--sn-brand-color-state-neutralBorder-forLightMode-default-borderColor, rgba(159, 166, 198, 0.3019607843))) 25%, transparent 25%), linear-gradient(-45deg, var(--sn-theme-color-available-borderColor, var(--sn-brand-color-state-neutralBorder-forLightMode-default-borderColor, rgba(159, 166, 198, 0.3019607843))) 25%, transparent 25%), linear-gradient(45deg, transparent 75%, var(--sn-theme-color-available-borderColor, var(--sn-brand-color-state-neutralBorder-forLightMode-default-borderColor, rgba(159, 166, 198, 0.3019607843))) 75%), linear-gradient(-45deg, transparent 75%, var(--sn-theme-color-available-borderColor, var(--sn-brand-color-state-neutralBorder-forLightMode-default-borderColor, rgba(159, 166, 198, 0.3019607843))) 75%);
60
+ background-position:0 0, 0 4px, 4px -4px, -4px 0;
61
+ background-size:8px 8px;
62
+ }
63
+ .sheetSwatch::after{
64
+ content:"";
65
+ position:absolute;
66
+ inset:0;
67
+ border-radius:inherit;
68
+ background-color:var(--field-color-swatch-color, transparent);
69
+ }
70
+
71
+ .sheetFooter{
72
+ display:flex;
73
+ gap:var(--sn-primitive-dimension-8, 8px);
74
+ justify-content:space-between;
75
+ }
76
+
77
+ .pickerHost{
78
+ display:contents;
79
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Нормализует пользовательский ввод цвета в потенциально валидную hex-строку:
3
+ * при наличии hex-цифр ведущая `#` обязательна (добавляется всегда), за ней — не более
4
+ * 8 hex-цифр (`rrggbbaa`) при `withAlpha`, иначе 6 (`rrggbb`). Лишние/внутренние `#` и
5
+ * любые не-hex символы отбрасываются. Пустой ввод (очистка поля) остаётся пустым.
6
+ */
7
+ export declare function normalizeHexInput(raw: string, withAlpha?: boolean): string;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeHexInput = normalizeHexInput;
4
+ /** Всё, что не hex-цифра. */
5
+ const NON_HEX_CHARS = /[^0-9a-fA-F]/g;
6
+ /** Hex-цифр с альфой: `rrggbbaa` (8); без альфы: `rrggbb` (6). `#` не считается. */
7
+ const HEX_DIGITS_WITH_ALPHA = 8;
8
+ const HEX_DIGITS_NO_ALPHA = 6;
9
+ /**
10
+ * Нормализует пользовательский ввод цвета в потенциально валидную hex-строку:
11
+ * при наличии hex-цифр ведущая `#` обязательна (добавляется всегда), за ней — не более
12
+ * 8 hex-цифр (`rrggbbaa`) при `withAlpha`, иначе 6 (`rrggbb`). Лишние/внутренние `#` и
13
+ * любые не-hex символы отбрасываются. Пустой ввод (очистка поля) остаётся пустым.
14
+ */
15
+ function normalizeHexInput(raw, withAlpha = true) {
16
+ const maxDigits = withAlpha ? HEX_DIGITS_WITH_ALPHA : HEX_DIGITS_NO_ALPHA;
17
+ const digits = raw.replace(NON_HEX_CHARS, '').slice(0, maxDigits);
18
+ return digits ? `#${digits}` : '';
19
+ }
@@ -0,0 +1,91 @@
1
+ import { FieldDecoratorProps } from '@cloud-ru/ds-field-decorator';
2
+ import { InputPrivateProps } from '@cloud-ru/ds-input-private';
3
+ import { ReactNode } from 'react';
4
+ import { FieldLayoutPresets } from '../../hooks';
5
+ import { FieldElementButtonProps, FieldElementDroplistProps } from '../shared';
6
+ /**
7
+ * Слот-кнопка поля (`elementBefore` / `elementAfter`). Помимо обычной кнопки-действия
8
+ * может нести встроенный выпадающий список (`droplist`) на `@cloud-ru/ds-list`.
9
+ */
10
+ type FieldElementSlot = Omit<FieldElementButtonProps, 'variant' | 'open' | 'onKeyDown'> & {
11
+ /** Встроенный выпадающий список (действия / выбор) на `@cloud-ru/ds-list` `Droplist` */
12
+ droplist?: FieldElementDroplistProps;
13
+ };
14
+ type FieldComboDecoratorProps = Omit<FieldDecoratorProps, 'children'>;
15
+ type FieldComboSlotProps = {
16
+ /** CSS-класс корня `FieldDecorator` */
17
+ className?: string;
18
+ /** CSS-класс оболочки поля ввода */
19
+ fieldClassName?: string;
20
+ /**
21
+ * Фон поля (acrylic)
22
+ * @default true
23
+ */
24
+ background?: boolean;
25
+ /**
26
+ * Разделитель между основным полем и слотами `elementBefore` / `elementAfter`
27
+ * @default true
28
+ */
29
+ outline?: boolean;
30
+ /** Префикс (текст или нода) */
31
+ prefix?: ReactNode;
32
+ /** Постфикс (текст или нода) */
33
+ postfix?: ReactNode;
34
+ /** Иконка слева от строки ввода */
35
+ iconBefore?: ReactNode;
36
+ /** Иконка справа от строки ввода */
37
+ iconAfter?: ReactNode;
38
+ /**
39
+ * Ведущая иконка.
40
+ * @deprecated Используйте `iconBefore` — он приоритетнее, если заданы оба.
41
+ */
42
+ prefixIcon?: ReactNode;
43
+ /** Слот слева (кнопка / селект с опциональным выпадающим списком) */
44
+ elementBefore?: FieldElementSlot;
45
+ /** Слот справа (кнопка / селект с опциональным выпадающим списком) */
46
+ elementAfter?: FieldElementSlot;
47
+ /**
48
+ * Показывать кнопку очистки значения (как в Search)
49
+ * @default true
50
+ */
51
+ showClearButton?: boolean;
52
+ /** Колбек клика по кнопке очистки */
53
+ onClearButtonClick?(): void;
54
+ /**
55
+ * Показывать кнопку копирования значения (только при `readonly = true` и непустом `value`)
56
+ * @default true
57
+ */
58
+ showCopyButton?: boolean;
59
+ /** Колбек после копирования значения в буфер */
60
+ onCopyButtonClick?(): void;
61
+ /**
62
+ * Разрешить ввод свыше `maxLength` символов (счётчик продолжит расти).
63
+ * @default false
64
+ */
65
+ allowMoreThanMaxLength?: boolean;
66
+ /** Значение поля (controlled-режим) */
67
+ value?: string;
68
+ /** Начальное значение (uncontrolled-режим) */
69
+ defaultValue?: string;
70
+ /** Колбек смены значения */
71
+ onChange?(value: string): void;
72
+ /**
73
+ * Переопределение адаптивных дефолтов по раскладке. Участвует `autoFocus`: на mobile он выключен
74
+ * (открывает клавиатуру без действия). Вернуть на mobile — `layoutPresets={{ mobile: { autoFocus: true } }}`.
75
+ */
76
+ layoutPresets?: FieldLayoutPresets;
77
+ /**
78
+ * Идентификаторы внутренних слотов — оболочки и строки ввода. Нужны компонентам, которые
79
+ * рендерят `FieldCombo` под собственным именем (`FieldText`): их e2e адресует свои слоты,
80
+ * а не слоты `FieldCombo`.
81
+ */
82
+ innerTestIds?: {
83
+ /** `data-test-id` оболочки поля */
84
+ shell?: string;
85
+ /** `data-test-id` строки ввода */
86
+ input?: string;
87
+ };
88
+ };
89
+ export type FieldComboProps = FieldComboDecoratorProps & Omit<InputPrivateProps, 'className' | 'value' | 'onChange'> & FieldComboSlotProps;
90
+ export declare const FieldCombo: import("react").ForwardRefExoticComponent<Omit<FieldComboProps, "ref"> & import("react").RefAttributes<HTMLInputElement>>;
91
+ export {};
@@ -0,0 +1,200 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FieldCombo = void 0;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const divider_1 = require("@cloud-ru/ds-divider");
9
+ const field_decorator_1 = require("@cloud-ru/ds-field-decorator");
10
+ const input_private_1 = require("@cloud-ru/ds-input-private");
11
+ const utils_1 = require("@cloud-ru/ds-utils");
12
+ const classnames_1 = __importDefault(require("classnames"));
13
+ const merge_refs_1 = __importDefault(require("merge-refs"));
14
+ const react_1 = require("react");
15
+ const constants_1 = require("../../constants");
16
+ const hooks_1 = require("../../hooks");
17
+ const shared_1 = require("../shared");
18
+ const styles_module_scss_1 = __importDefault(require('../shared/styles.module.css'));
19
+ exports.FieldCombo = (0, react_1.forwardRef)(function FieldCombo({ label = '', labelTooltip, caption, hint, error, validationState = field_decorator_1.VALIDATION_STATE.Default, showHintIcon, length, required, size = field_decorator_1.SIZE.M, className, fieldClassName, background = true, outline = true, prefix, postfix, iconBefore: iconBeforeProp, iconAfter, prefixIcon, elementBefore, elementAfter, showClearButton: showClearButtonProp = true, onClearButtonClick, showCopyButton: showCopyButtonProp = true, onCopyButtonClick, allowMoreThanMaxLength = false, disabled, readonly: readOnly, value: valueProp, defaultValue = '', onChange: onChangeProp, placeholder, 'data-test-id': dataTestId, innerTestIds, ...inputProps }, ref) {
20
+ const { onFocus: onFocusProp, onBlur: onBlurProp, onKeyDown: onKeyDownProp, tabIndex: tabIndexProp, maxLength, autoFocus, layoutPresets, ...restInputProps } = inputProps;
21
+ const resolvedAutoFocus = (0, hooks_1.useAdaptiveAutoFocus)(autoFocus, layoutPresets);
22
+ // `prefixIcon` — легаси-псевдоним ведущей иконки; `iconBefore` приоритетнее.
23
+ const iconBefore = iconBeforeProp ?? prefixIcon;
24
+ const [value = '', onChange] = (0, utils_1.useValueControl)({
25
+ value: valueProp,
26
+ defaultValue,
27
+ onChange: onChangeProp,
28
+ });
29
+ const localRef = (0, react_1.useRef)(null);
30
+ const clearButtonRef = (0, react_1.useRef)(null);
31
+ const copyButtonRef = (0, react_1.useRef)(null);
32
+ const elementBeforeRef = (0, react_1.useRef)(null);
33
+ const elementAfterRef = (0, react_1.useRef)(null);
34
+ const [focusVisible, setFocusVisible] = (0, react_1.useState)(false);
35
+ const [hover, setHover] = (0, react_1.useState)(false);
36
+ const effectiveValidationState = (0, react_1.useMemo)(() => (error ? field_decorator_1.VALIDATION_STATE.Error : validationState), [error, validationState]);
37
+ const slotSize = (s) => (s ?? size ?? field_decorator_1.SIZE.M);
38
+ const showClearUi = Boolean(showClearButtonProp && value && !readOnly && !disabled);
39
+ const showCopyUi = Boolean(showCopyButtonProp && value && !disabled && readOnly);
40
+ const stringValue = String(value ?? '');
41
+ const textToCopy = (0, react_1.useMemo)(() => `${typeof prefix === 'string' ? prefix : ''}${stringValue}${typeof postfix === 'string' ? postfix : ''}`, [postfix, prefix, stringValue]);
42
+ const effectiveMaxLength = allowMoreThanMaxLength ? undefined : maxLength;
43
+ const effectiveLength = (0, react_1.useMemo)(() => length ?? (maxLength ? { current: stringValue.length, max: maxLength } : undefined), [length, maxLength, stringValue.length]);
44
+ const onClear = (0, react_1.useCallback)(() => {
45
+ onChange?.('');
46
+ // Возврат фокуса в поле после очистки: clear-кнопка исчезает (значение пусто),
47
+ // фокус не должен «упасть» на body — паритет с легаси (focusedRef) и FieldTextArea.
48
+ localRef.current?.focus();
49
+ onClearButtonClick?.();
50
+ }, [onChange, onClearButtonClick]);
51
+ const onCopy = (0, react_1.useCallback)(async () => {
52
+ const copied = await (0, shared_1.copyTextToClipboard)(textToCopy);
53
+ if (copied) {
54
+ onCopyButtonClick?.();
55
+ }
56
+ return copied;
57
+ }, [onCopyButtonClick, textToCopy]);
58
+ const clearButtonSettings = (0, input_private_1.useClearButton)({
59
+ clearButtonRef,
60
+ showClearButton: showClearUi,
61
+ size: (0, shared_1.toInputSize)(size),
62
+ onClear,
63
+ disabled: Boolean(disabled || readOnly),
64
+ });
65
+ const copyButtonSettings = (0, shared_1.useCopyButton)({
66
+ copyButtonRef,
67
+ showCopyButton: showCopyUi,
68
+ size: (0, shared_1.toInputSize)(size),
69
+ onCopy,
70
+ disabled: Boolean(disabled),
71
+ });
72
+ // ArrowRight с последней postfix-кнопки (clear/copy — взаимоисключающие) уводит фокус
73
+ // на правый слот-элемент, продолжая roving-цепочку input → clear/copy → elementAfter.
74
+ const onPostfixButtonKeyDown = (0, react_1.useCallback)((event) => {
75
+ if (event.key === 'ArrowRight' && elementAfterRef.current) {
76
+ event.preventDefault();
77
+ elementAfterRef.current.focus();
78
+ }
79
+ }, []);
80
+ const { postfixButtons, inputTabIndex, onInputKeyDown, setInitialTabIndices } = (0, input_private_1.useButtonNavigation)({
81
+ inputRef: localRef,
82
+ postfixButtons: (0, react_1.useMemo)(() => [clearButtonSettings, copyButtonSettings], [clearButtonSettings, copyButtonSettings]),
83
+ onButtonKeyDown: onPostfixButtonKeyDown,
84
+ readonly: Boolean(readOnly),
85
+ submitKeys: ['Enter', 'Space', 'Tab'],
86
+ });
87
+ const focusInput = (0, react_1.useCallback)(() => {
88
+ setInitialTabIndices();
89
+ localRef.current?.focus();
90
+ }, [setInitialTabIndices]);
91
+ const handleKeyDown = (0, react_1.useCallback)((event) => {
92
+ onInputKeyDown(event);
93
+ const atStart = Boolean(readOnly) || (0, shared_1.isCursorAtStart)(localRef.current);
94
+ const atEnd = Boolean(readOnly) || (0, shared_1.isCursorAtEnd)(localRef.current);
95
+ // ← к левому слоту; → к правому слоту (если справа нет видимой clear/copy — иначе
96
+ // их обрабатывает useButtonNavigation, а цепочку дальше ведёт onPostfixButtonKeyDown).
97
+ if (elementBefore && event.key === 'ArrowLeft' && atStart && elementBeforeRef.current) {
98
+ event.preventDefault();
99
+ elementBeforeRef.current.focus();
100
+ }
101
+ if (elementAfter &&
102
+ event.key === 'ArrowRight' &&
103
+ atEnd &&
104
+ !showClearUi &&
105
+ !showCopyUi &&
106
+ elementAfterRef.current) {
107
+ event.preventDefault();
108
+ elementAfterRef.current.focus();
109
+ }
110
+ onKeyDownProp?.(event);
111
+ }, [elementAfter, elementBefore, onInputKeyDown, onKeyDownProp, readOnly, showClearUi, showCopyUi]);
112
+ const onElementKeyDown = (0, react_1.useCallback)((variant) => (event) => {
113
+ // Возврат в поле: ArrowRight с левого слота, ArrowLeft с правого.
114
+ if (variant === 'before' && event.key === 'ArrowRight') {
115
+ event.preventDefault();
116
+ focusInput();
117
+ }
118
+ if (variant === 'after' && event.key === 'ArrowLeft') {
119
+ event.preventDefault();
120
+ const visiblePostfixButton = (showCopyUi && copyButtonRef.current) || (showClearUi && clearButtonRef.current);
121
+ (visiblePostfixButton || localRef.current)?.focus();
122
+ }
123
+ }, [focusInput, showClearUi, showCopyUi]);
124
+ const handleFocus = (0, react_1.useCallback)((event) => {
125
+ setFocusVisible(event.target.matches(':focus-visible'));
126
+ onFocusProp?.(event);
127
+ }, [onFocusProp]);
128
+ const handleBlur = (0, react_1.useCallback)((event) => {
129
+ setFocusVisible(false);
130
+ // Не пробрасываем consumer onBlur, если фокус ушёл на собственную кнопку поля (clear/copy/слот).
131
+ // `next != null` обязателен: при blur «в никуда» relatedTarget и нерендеренные кнопки-рефы оба null,
132
+ // без него null === null ложно срабатывает и глотает onBlur.
133
+ const next = event.relatedTarget;
134
+ const movedToOwnButton = next != null &&
135
+ (next === clearButtonRef.current ||
136
+ next === copyButtonRef.current ||
137
+ next === elementBeforeRef.current ||
138
+ next === elementAfterRef.current);
139
+ if (!movedToOwnButton) {
140
+ onBlurProp?.(event);
141
+ }
142
+ }, [onBlurProp]);
143
+ const handleMouseEnter = (0, react_1.useCallback)(() => {
144
+ if (!readOnly) {
145
+ setHover(true);
146
+ }
147
+ }, [readOnly]);
148
+ const handleMouseLeave = (0, react_1.useCallback)(() => {
149
+ setHover(false);
150
+ }, []);
151
+ const renderElement = (slot, variant) => {
152
+ const commonProps = {
153
+ variant,
154
+ size: slotSize(slot.size),
155
+ loading: slot.loading,
156
+ disabled: disabled || slot.disabled || Boolean(readOnly),
157
+ onClick: slot.onClick,
158
+ action: slot.action,
159
+ onKeyDown: onElementKeyDown(variant),
160
+ ref: variant === 'before' ? elementBeforeRef : elementAfterRef,
161
+ 'data-test-id': slot['data-test-id'],
162
+ };
163
+ if (!slot.droplist) {
164
+ return (0, jsx_runtime_1.jsx)(shared_1.FieldElementButton, { ...commonProps, withDropdownList: slot.withDropdownList });
165
+ }
166
+ // Возврат фокуса в поле после выбора пункта (паритет с легаси `@snack-uikit/fields`).
167
+ const { selection } = slot.droplist;
168
+ const returnFocus = () => setTimeout(() => localRef.current?.focus(), 0);
169
+ // selection — дискриминированный union по `mode`; оборачиваем onChange в каждой ветке
170
+ // отдельно, чтобы значение сохраняло свой точный тип (ItemId vs ItemId[]).
171
+ const wrapSelection = (sel) => {
172
+ if (sel.mode === 'multiple') {
173
+ return {
174
+ ...sel,
175
+ onChange: (value) => {
176
+ sel.onChange?.(value);
177
+ returnFocus();
178
+ },
179
+ };
180
+ }
181
+ return {
182
+ ...sel,
183
+ onChange: (value) => {
184
+ sel.onChange?.(value);
185
+ returnFocus();
186
+ },
187
+ };
188
+ };
189
+ const droplist = selection ? { ...slot.droplist, selection: wrapSelection(selection) } : slot.droplist;
190
+ return (0, jsx_runtime_1.jsx)(shared_1.FieldElementButtonList, { ...commonProps, droplist: droplist });
191
+ };
192
+ const shell = ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.fieldWrapper, fieldClassName), "data-test-id": innerTestIds?.shell ?? constants_1.TEST_IDS.fieldComboShell, "data-size": size, "data-validation-state": effectiveValidationState, "data-disabled": disabled || undefined, "data-readonly": readOnly || undefined, "data-withbackground": background || undefined, "data-focusvisible": focusVisible || undefined, "data-hover": !readOnly && hover ? true : undefined, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [(0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.backgroundWrapper, children: [(0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.materialLayer, ...(0, shared_1.getAcrylicProps)({
193
+ validationState: effectiveValidationState,
194
+ disabled,
195
+ readonly: readOnly,
196
+ hover,
197
+ focusVisible,
198
+ }), children: (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.acrylicBg, "aria-hidden": true }) }), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.borderStateLayer, "data-state": 'borderOnBackground' }), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.focusLayer })] }), elementBefore && ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.elementWrapperBefore, children: [renderElement(elementBefore, 'before'), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.lineWrapper, "data-outline": outline, children: (0, jsx_runtime_1.jsx)(divider_1.Divider, { orientation: 'vertical', variant: 'regular' }) })] })), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.fieldContainer, children: (0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.contentWrapper, children: [iconBefore && (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.iconSlot, children: iconBefore }), (0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.inputLine, children: [prefix && (0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_1.default.prefix, children: prefix }), (0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.inputArea, children: [(0, jsx_runtime_1.jsx)(input_private_1.InputPrivate, { ref: (0, merge_refs_1.default)(ref, localRef), className: styles_module_scss_1.default.fieldInput, value: value, disabled: disabled, readonly: readOnly, onChange: onChange, placeholder: placeholder, tabIndex: tabIndexProp ?? inputTabIndex, onKeyDown: handleKeyDown, maxLength: effectiveMaxLength, onFocus: handleFocus, onBlur: handleBlur, ...restInputProps, autoFocus: resolvedAutoFocus, "data-test-id": innerTestIds?.input ?? constants_1.TEST_IDS.fieldComboInput }), postfixButtons && (0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_1.default.postfixButtonsSlot, children: postfixButtons })] }), postfix && (0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_1.default.postfix, children: postfix })] }), iconAfter && (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.iconSlot, children: iconAfter })] }) }), elementAfter && ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.elementWrapperAfter, children: [(0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.lineWrapper, "data-outline": outline, children: (0, jsx_runtime_1.jsx)(divider_1.Divider, { orientation: 'vertical', variant: 'regular' }) }), renderElement(elementAfter, 'after')] }))] }));
199
+ return ((0, jsx_runtime_1.jsx)(field_decorator_1.FieldDecorator, { className: className, label: label, labelTooltip: labelTooltip, caption: caption, hint: hint, error: error, validationState: validationState, showHintIcon: showHintIcon, length: effectiveLength, required: required, labelFor: inputProps.id, disabled: disabled, readonly: readOnly, size: size, "data-test-id": dataTestId, children: shell }));
200
+ });
@@ -0,0 +1 @@
1
+ export * from './FieldCombo';