@scbt-ecom/ui 0.4.0 → 0.4.2

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 (298) hide show
  1. package/.env +3 -0
  2. package/.github/workflows/publish.yml +61 -0
  3. package/.github/workflows/setup-node/action.yml +22 -0
  4. package/.husky/pre-commit +1 -0
  5. package/.prettierignore +1 -0
  6. package/.prettierrc +20 -0
  7. package/.releaserc +18 -0
  8. package/.storybook/main.ts +44 -0
  9. package/.storybook/preview.tsx +37 -0
  10. package/chromatic.config.json +5 -0
  11. package/eslint.config.mjs +193 -0
  12. package/index.html +13 -0
  13. package/lib/client.ts +12 -0
  14. package/lib/configs/index.ts +2 -0
  15. package/lib/configs/tailwindConfigBase.ts +110 -0
  16. package/lib/configs/tailwindPresets/extendsPreset.ts +43 -0
  17. package/lib/configs/tailwindPresets/index.ts +2 -0
  18. package/lib/configs/tailwindPresets/resetPreset.ts +71 -0
  19. package/lib/hybrid.ts +25 -0
  20. package/lib/shared/constants/api.ts +2 -0
  21. package/lib/shared/constants/designSystem/colors.ts +121 -0
  22. package/lib/shared/constants/designSystem/index.ts +3 -0
  23. package/lib/shared/constants/designSystem/others.ts +30 -0
  24. package/lib/shared/constants/designSystem/typography.ts +88 -0
  25. package/lib/shared/constants/index.ts +2 -0
  26. package/lib/shared/hooks/index.ts +5 -0
  27. package/lib/shared/hooks/useBoolean.ts +12 -0
  28. package/lib/shared/hooks/useClickOutside.ts +22 -0
  29. package/lib/shared/hooks/useCombineRef.ts +23 -0
  30. package/lib/shared/hooks/useControlledForm.ts +16 -0
  31. package/lib/shared/hooks/useDebounce.ts +38 -0
  32. package/lib/shared/hooks/useMediaQuery.tsx +42 -0
  33. package/lib/shared/style.css +118 -0
  34. package/lib/shared/ui/Badge.tsx +20 -0
  35. package/lib/shared/ui/Breadcrumbs.tsx +57 -0
  36. package/lib/shared/ui/ButtonIcon.tsx +50 -0
  37. package/lib/shared/ui/CustomLink.tsx +76 -0
  38. package/lib/shared/ui/Document.tsx +51 -0
  39. package/lib/shared/ui/Heading.tsx +33 -0
  40. package/lib/shared/ui/Hint.tsx +72 -0
  41. package/lib/shared/ui/Loader.tsx +58 -0
  42. package/lib/shared/ui/PhoneView.tsx +23 -0
  43. package/lib/shared/ui/ProgressBar.tsx +43 -0
  44. package/lib/shared/ui/ResponsiveContainer.tsx +15 -0
  45. package/lib/shared/ui/Section.tsx +15 -0
  46. package/lib/shared/ui/Skeleton.tsx +9 -0
  47. package/lib/shared/ui/TabsSwitcher.tsx +87 -0
  48. package/lib/shared/ui/accordion/Accordion.tsx +36 -0
  49. package/lib/shared/ui/accordion/index.ts +1 -0
  50. package/lib/shared/ui/accordion/model/types.ts +20 -0
  51. package/lib/shared/ui/accordion/ui/AccordionHeader.tsx +35 -0
  52. package/lib/shared/ui/brandLogos.tsx +14 -0
  53. package/lib/shared/ui/button/Button.tsx +117 -0
  54. package/lib/shared/ui/button/index.ts +1 -0
  55. package/lib/shared/ui/button/model/helpers.ts +16 -0
  56. package/lib/shared/ui/formControlElements/CheckboxControl.tsx +92 -0
  57. package/lib/shared/ui/formControlElements/FormControl.tsx +5 -0
  58. package/lib/shared/ui/formControlElements/InputControlMask.tsx +90 -0
  59. package/lib/shared/ui/formControlElements/RadioControl.tsx +130 -0
  60. package/lib/shared/ui/formControlElements/SwitchControl.tsx +79 -0
  61. package/lib/shared/ui/formControlElements/TextareaControl.tsx +96 -0
  62. package/lib/shared/ui/formControlElements/calendarControl/CalendarControl.tsx +178 -0
  63. package/lib/shared/ui/formControlElements/calendarControl/hooks/index.ts +2 -0
  64. package/lib/shared/ui/formControlElements/calendarControl/hooks/useCalendar.tsx +86 -0
  65. package/lib/shared/ui/formControlElements/calendarControl/hooks/useCalendarDropdowns.ts +38 -0
  66. package/lib/shared/ui/formControlElements/calendarControl/index.ts +1 -0
  67. package/lib/shared/ui/formControlElements/calendarControl/model/helpers.ts +60 -0
  68. package/lib/shared/ui/formControlElements/calendarControl/model/types.ts +44 -0
  69. package/lib/shared/ui/formControlElements/calendarControl/ui/DaysOfMonth.tsx +53 -0
  70. package/lib/shared/ui/formControlElements/calendarControl/ui/DaysOfWeek.tsx +28 -0
  71. package/lib/shared/ui/formControlElements/calendarControl/ui/Dropdown.tsx +62 -0
  72. package/lib/shared/ui/formControlElements/calendarControl/ui/Header.tsx +51 -0
  73. package/lib/shared/ui/formControlElements/calendarControl/ui/Navigation.tsx +32 -0
  74. package/lib/shared/ui/formControlElements/calendarControl/ui/OptionsList.tsx +44 -0
  75. package/lib/shared/ui/formControlElements/calendarControl/ui/index.ts +4 -0
  76. package/lib/shared/ui/formControlElements/comboboxControl/ComboboxControl.tsx +134 -0
  77. package/lib/shared/ui/formControlElements/comboboxControl/index.ts +1 -0
  78. package/lib/shared/ui/formControlElements/comboboxControl/model/selectClassnames.ts +51 -0
  79. package/lib/shared/ui/formControlElements/comboboxControl/model/types.ts +42 -0
  80. package/lib/shared/ui/formControlElements/comboboxControl/ui/ComboboxOption.tsx +38 -0
  81. package/lib/shared/ui/formControlElements/comboboxControl/ui/DropdownIndicator.tsx +23 -0
  82. package/lib/shared/ui/formControlElements/comboboxControl/ui/MultiValueRemove.tsx +16 -0
  83. package/lib/shared/ui/formControlElements/comboboxControl/ui/index.ts +3 -0
  84. package/lib/shared/ui/formControlElements/dadata/DadataInputControl.tsx +137 -0
  85. package/lib/shared/ui/formControlElements/dadata/index.ts +1 -0
  86. package/lib/shared/ui/formControlElements/dadata/model/api.ts +25 -0
  87. package/lib/shared/ui/formControlElements/dadata/model/helpers.ts +76 -0
  88. package/lib/shared/ui/formControlElements/dadata/model/types.ts +52 -0
  89. package/lib/shared/ui/formControlElements/dadata/model/useDadata.ts +25 -0
  90. package/lib/shared/ui/formControlElements/editorControl/EditorControl.tsx +82 -0
  91. package/lib/shared/ui/formControlElements/editorControl/components/conrols.tsx +136 -0
  92. package/lib/shared/ui/formControlElements/editorControl/components/menu.tsx +107 -0
  93. package/lib/shared/ui/formControlElements/editorControl/index.ts +60 -0
  94. package/lib/shared/ui/formControlElements/editorControl/ui/RemoveBlockButton.tsx +23 -0
  95. package/lib/shared/ui/formControlElements/editorControl/ui/ResetBlockType.tsx +17 -0
  96. package/lib/shared/ui/formControlElements/index.ts +14 -0
  97. package/lib/shared/ui/formControlElements/inputControl/InputControl.tsx +87 -0
  98. package/lib/shared/ui/formControlElements/inputControl/index.ts +1 -0
  99. package/lib/shared/ui/formControlElements/inputControl/model/hooks.tsx +26 -0
  100. package/lib/shared/ui/formControlElements/inputControlUploader/InputControlUploader.tsx +47 -0
  101. package/lib/shared/ui/formControlElements/inputControlUploader/index.ts +1 -0
  102. package/lib/shared/ui/formControlElements/inputControlUploader/model/helpers.ts +18 -0
  103. package/lib/shared/ui/formControlElements/inputControlUploader/model/hooks/useUploader.tsx +66 -0
  104. package/lib/shared/ui/formControlElements/inputControlUploader/model/index.ts +1 -0
  105. package/lib/shared/ui/formControlElements/inputControlUploader/model/types.ts +22 -0
  106. package/lib/shared/ui/formControlElements/inputControlUploader/ui/File.tsx +35 -0
  107. package/lib/shared/ui/formControlElements/inputControlUploader/ui/Filename.tsx +40 -0
  108. package/lib/shared/ui/formControlElements/inputControlUploader/ui/Files.tsx +30 -0
  109. package/lib/shared/ui/formControlElements/inputControlUploader/ui/Input.tsx +48 -0
  110. package/lib/shared/ui/formControlElements/inputControlUploader/ui/Uploader.tsx +58 -0
  111. package/lib/shared/ui/formControlElements/inputControlUploader/ui/index.ts +3 -0
  112. package/lib/shared/ui/formControlElements/inputCurrencyControl/InputCurrencyControl.tsx +88 -0
  113. package/lib/shared/ui/formControlElements/inputCurrencyControl/index.ts +1 -0
  114. package/lib/shared/ui/formControlElements/inputCurrencyControl/model/helpers.ts +46 -0
  115. package/lib/shared/ui/formControlElements/inputCurrencyControl/model/useInputCurrency.tsx +33 -0
  116. package/lib/shared/ui/formControlElements/inputCurrencyControl/ui/MenuTrigger.tsx +20 -0
  117. package/lib/shared/ui/formControlElements/inputCurrencyControl/ui/OptionList.tsx +29 -0
  118. package/lib/shared/ui/formControlElements/inputCurrencyControl/ui/index.ts +2 -0
  119. package/lib/shared/ui/formControlElements/inputSliderControl/InputSliderControl.tsx +144 -0
  120. package/lib/shared/ui/formControlElements/inputSliderControl/index.ts +1 -0
  121. package/lib/shared/ui/formControlElements/inputSliderControl/model/helpers/dates/getEndWordMonth.ts +14 -0
  122. package/lib/shared/ui/formControlElements/inputSliderControl/model/helpers/dates/getYearEnding.ts +13 -0
  123. package/lib/shared/ui/formControlElements/inputSliderControl/model/helpers/dates/index.ts +2 -0
  124. package/lib/shared/ui/formControlElements/inputSliderControl/model/helpers/formatNumber.ts +6 -0
  125. package/lib/shared/ui/formControlElements/inputSliderControl/model/helpers/getInputSliderSuffix.ts +20 -0
  126. package/lib/shared/ui/formControlElements/inputSliderControl/model/helpers/getStepByVariant.ts +29 -0
  127. package/lib/shared/ui/formControlElements/inputSliderControl/model/helpers/index.ts +4 -0
  128. package/lib/shared/ui/formControlElements/inputSliderControl/model/types.ts +1 -0
  129. package/lib/shared/ui/formControlElements/inputSliderControl/model/useSlider.ts +26 -0
  130. package/lib/shared/ui/formControlElements/inputSliderControl/ui/SliderControl.tsx +47 -0
  131. package/lib/shared/ui/formControlElements/inputSliderControl/ui/index.ts +1 -0
  132. package/lib/shared/ui/formControlElements/model/classes-types.ts +22 -0
  133. package/lib/shared/ui/formControlElements/model/index.ts +2 -0
  134. package/lib/shared/ui/formControlElements/model/message-view-animation.ts +6 -0
  135. package/lib/shared/ui/formControlElements/model/props-types.ts +31 -0
  136. package/lib/shared/ui/formControlElements/ui/FieldAttachment.tsx +76 -0
  137. package/lib/shared/ui/formControlElements/ui/FieldContainer.tsx +37 -0
  138. package/lib/shared/ui/formControlElements/ui/FieldWrapper.tsx +33 -0
  139. package/lib/shared/ui/formControlElements/ui/Label.tsx +32 -0
  140. package/lib/shared/ui/formControlElements/ui/MessageView.tsx +41 -0
  141. package/lib/shared/ui/formControlElements/ui/index.ts +4 -0
  142. package/lib/shared/ui/icon/Icon.tsx +41 -0
  143. package/lib/shared/ui/icon/index.ts +2 -0
  144. package/lib/shared/ui/icon/sprite.gen.ts +177 -0
  145. package/lib/shared/ui/index.ts +68 -0
  146. package/lib/shared/ui/modal/Modal.tsx +68 -0
  147. package/lib/shared/ui/modal/index.ts +1 -0
  148. package/lib/shared/ui/modal/model/helpers.ts +13 -0
  149. package/lib/shared/ui/modal/ui/ModalHeader.tsx +33 -0
  150. package/lib/shared/ui/notification/Notification.tsx +31 -0
  151. package/lib/shared/ui/notification/index.ts +1 -0
  152. package/lib/shared/ui/notification/ui/CustomToast.tsx +42 -0
  153. package/lib/shared/ui/popover/Popover.tsx +74 -0
  154. package/lib/shared/ui/popover/index.ts +1 -0
  155. package/lib/shared/ui/providers/NotificationProvider.tsx +29 -0
  156. package/lib/shared/ui/providers/index.ts +1 -0
  157. package/lib/shared/ui/table/Table.tsx +144 -0
  158. package/lib/shared/ui/table/index.ts +1 -0
  159. package/lib/shared/ui/table/type.ts +30 -0
  160. package/lib/shared/utils/capitalize.ts +6 -0
  161. package/lib/shared/utils/cn.ts +6 -0
  162. package/lib/shared/utils/deepCompare.ts +1 -0
  163. package/lib/shared/utils/formatToDate.ts +5 -0
  164. package/lib/shared/utils/index.ts +5 -0
  165. package/lib/shared/utils/isClient.ts +1 -0
  166. package/lib/shared/validation/index.ts +3 -0
  167. package/lib/shared/validation/messages.ts +12 -0
  168. package/lib/shared/validation/regExp.ts +5 -0
  169. package/lib/shared/validation/zodValidation/calendar.ts +32 -0
  170. package/lib/shared/validation/zodValidation/dadataFio.ts +67 -0
  171. package/lib/shared/validation/zodValidation/index.ts +2 -0
  172. package/lib/vite-env.d.ts +2 -0
  173. package/lib/widgets/Advantages.tsx +45 -0
  174. package/lib/widgets/banner/Banner.tsx +74 -0
  175. package/lib/widgets/banner/index.ts +1 -0
  176. package/lib/widgets/banner/model/helpers.ts +159 -0
  177. package/lib/widgets/banner/money.png +0 -0
  178. package/lib/widgets/banner/saif.jpg +0 -0
  179. package/lib/widgets/banner/saifMob.jpg +0 -0
  180. package/lib/widgets/banner/seif.jpg +0 -0
  181. package/lib/widgets/banner/shield.jpg +0 -0
  182. package/lib/widgets/banner/shield.png +0 -0
  183. package/lib/widgets/banner/ui/BannerButtonsGroup.tsx +44 -0
  184. package/lib/widgets/banner/ui/banners/BannerImageFull.tsx +82 -0
  185. package/lib/widgets/banner/ui/banners/BannerWithSeparateImg.tsx +60 -0
  186. package/lib/widgets/banner/ui/banners/index.ts +1 -0
  187. package/lib/widgets/footer/Footer.tsx +95 -0
  188. package/lib/widgets/footer/index.ts +1 -0
  189. package/lib/widgets/footer/model/defaultValues.tsx +105 -0
  190. package/lib/widgets/footer/model/types.ts +19 -0
  191. package/lib/widgets/footer/ui/Copyright.tsx +15 -0
  192. package/lib/widgets/footer/ui/Ligal.tsx +50 -0
  193. package/lib/widgets/footer/ui/NavLinks.tsx +41 -0
  194. package/lib/widgets/footer/ui/PhonesBlock.tsx +34 -0
  195. package/lib/widgets/footer/ui/SocialLinks.tsx +30 -0
  196. package/lib/widgets/footer/ui/index.ts +5 -0
  197. package/lib/widgets/index.ts +5 -0
  198. package/lib/widgets/pageHeader/PageHeader.tsx +54 -0
  199. package/lib/widgets/pageHeader/index.ts +1 -0
  200. package/lib/widgets/stepper/Stepper.tsx +43 -0
  201. package/lib/widgets/stepper/index.ts +1 -0
  202. package/lib/widgets/stepper/ui/SingleStep.tsx +42 -0
  203. package/package.json +1 -4
  204. package/postcss.config.mjs +8 -0
  205. package/public/sprites/arrows.svg +1 -0
  206. package/public/sprites/brandLogos.svg +1 -0
  207. package/public/sprites/files.svg +1 -0
  208. package/public/sprites/general.svg +1 -0
  209. package/public/sprites/info.svg +1 -0
  210. package/public/sprites/social.svg +1 -0
  211. package/src/App.tsx +9 -0
  212. package/src/app/providers/RootProvider.tsx +11 -0
  213. package/src/app/providers/index.ts +1 -0
  214. package/src/app/providers/model/types.ts +5 -0
  215. package/src/configs/setup.ts +9 -0
  216. package/src/configs/storybook.config.ts +23 -0
  217. package/src/main.tsx +10 -0
  218. package/src/stories/primitives/Accordion.stories.tsx +66 -0
  219. package/src/stories/primitives/Badge.stories.tsx +28 -0
  220. package/src/stories/primitives/Breadcrumbs.stories.tsx +29 -0
  221. package/src/stories/primitives/Button/Button.stories.tsx +149 -0
  222. package/src/stories/primitives/Button/Button.test.tsx +150 -0
  223. package/src/stories/primitives/ButtonIcon.stories.tsx +75 -0
  224. package/src/stories/primitives/CustomLink.stories.tsx +64 -0
  225. package/src/stories/primitives/Document.stories.tsx +36 -0
  226. package/src/stories/primitives/Heading.stories.tsx +29 -0
  227. package/src/stories/primitives/Hint.stories.tsx +82 -0
  228. package/src/stories/primitives/Icon.stories.tsx +36 -0
  229. package/src/stories/primitives/Loader.stories.tsx +39 -0
  230. package/src/stories/primitives/Modal.stories.tsx +106 -0
  231. package/src/stories/primitives/Notification.stories.tsx +102 -0
  232. package/src/stories/primitives/PhoneView.stories.tsx +22 -0
  233. package/src/stories/primitives/Popover.stories.tsx +41 -0
  234. package/src/stories/primitives/ProgressBar.stories.tsx +68 -0
  235. package/src/stories/primitives/Skeleton.stories.tsx +21 -0
  236. package/src/stories/primitives/Table.stories.tsx +44 -0
  237. package/src/stories/primitives/TabsSwitcher.stories.tsx +45 -0
  238. package/src/stories/primitives/formControl/CalendarControl.stories.tsx +45 -0
  239. package/src/stories/primitives/formControl/CheckboxControl.stories.tsx +64 -0
  240. package/src/stories/primitives/formControl/ComboboxControl.stories.tsx +67 -0
  241. package/src/stories/primitives/formControl/DadataInputControl.stories.tsx +79 -0
  242. package/src/stories/primitives/formControl/EditorControl.stories.tsx +31 -0
  243. package/src/stories/primitives/formControl/FormControlAllFields.stories.tsx +25 -0
  244. package/src/stories/primitives/formControl/InputControl.stories.tsx +84 -0
  245. package/src/stories/primitives/formControl/InputControlPassword.stories.tsx +38 -0
  246. package/src/stories/primitives/formControl/InputControlUploader.stories.tsx +44 -0
  247. package/src/stories/primitives/formControl/InputCurrencyControl.stories.tsx +73 -0
  248. package/src/stories/primitives/formControl/InputSliderControl.stories.tsx +62 -0
  249. package/src/stories/primitives/formControl/RadioContol.stories.tsx +61 -0
  250. package/src/stories/primitives/formControl/SwitchControl.stories.tsx +51 -0
  251. package/src/stories/primitives/formControl/TextareaControl.stories.tsx +55 -0
  252. package/src/stories/primitives/formControl/inputControlMask.stories.tsx +67 -0
  253. package/src/stories/widgets/Advantages.stories.tsx +42 -0
  254. package/src/stories/widgets/Banner.stories.tsx +94 -0
  255. package/src/stories/widgets/Footer.stories.tsx +36 -0
  256. package/src/stories/widgets/PageHeader.stories.tsx +33 -0
  257. package/src/stories/widgets/Stepper.stories.tsx +24 -0
  258. package/src/storybookHelpers/actions.tsx +5 -0
  259. package/src/storybookHelpers/index.ts +2 -0
  260. package/src/storybookHelpers/reactHookForm/index.ts +3 -0
  261. package/src/storybookHelpers/reactHookForm/model/mockData.ts +19 -0
  262. package/src/storybookHelpers/reactHookForm/model/mocks.tsx +105 -0
  263. package/src/storybookHelpers/reactHookForm/model/renderFields.tsx +58 -0
  264. package/src/storybookHelpers/reactHookForm/model/types.ts +86 -0
  265. package/src/storybookHelpers/reactHookForm/ui/StorybookFieldsMapper.tsx +32 -0
  266. package/src/storybookHelpers/reactHookForm/ui/StorybookFormProvider.tsx +43 -0
  267. package/src/storybookHelpers/reactHookForm/ui/index.ts +2 -0
  268. package/src/storybookHelpers/table/utils/defaultValue.ts +51 -0
  269. package/static/arrows/arrowCircle.svg +18 -0
  270. package/static/arrows/arrowLink.svg +3 -0
  271. package/static/arrows/arrowRight.svg +3 -0
  272. package/static/brandLogos/logoBlack.svg +14 -0
  273. package/static/brandLogos/logoBusiness.svg +80 -0
  274. package/static/brandLogos/logoGray.svg +56 -0
  275. package/static/brandLogos/logoInsurance.svg +124 -0
  276. package/static/brandLogos/logoMain.svg +14 -0
  277. package/static/brandLogos/logoWhite.svg +56 -0
  278. package/static/files/border.svg +6 -0
  279. package/static/files/borderError.svg +6 -0
  280. package/static/files/documentFilled.svg +4 -0
  281. package/static/files/documentOutline.svg +4 -0
  282. package/static/files/upload.svg +3 -0
  283. package/static/general/calendar.svg +3 -0
  284. package/static/general/check.svg +6 -0
  285. package/static/general/close.svg +12 -0
  286. package/static/general/edit.svg +4 -0
  287. package/static/general/hiddenEye.svg +4 -0
  288. package/static/general/plus.svg +3 -0
  289. package/static/general/showEye.svg +4 -0
  290. package/static/info/warningCircle.svg +5 -0
  291. package/static/social/classmates.svg +3 -0
  292. package/static/social/telegram.svg +3 -0
  293. package/static/social/vk.svg +3 -0
  294. package/tailwind.config.ts +10 -0
  295. package/tsconfig.json +33 -0
  296. package/tsconfig.node.json +11 -0
  297. package/vite.config.ts +68 -0
  298. package/vitest.config.mjs +12 -0
@@ -0,0 +1 @@
1
+ export { Table } from './Table'
@@ -0,0 +1,30 @@
1
+ import type { ReactElement } from 'react'
2
+
3
+ export type TTableColumnCount = 'twoColumns' | 'threeColumns'
4
+
5
+ export type TableRows<C extends TTableColumnCount> = ColumnsCount<C>[]
6
+
7
+ export type Ceil = {
8
+ text: string | ReactElement
9
+ }
10
+
11
+ export type ColumnsCount<C extends TTableColumnCount> = C extends 'twoColumns'
12
+ ? [Ceil, Ceil]
13
+ : C extends 'threeColumns'
14
+ ? [Ceil, Ceil, Ceil]
15
+ : never
16
+
17
+ export type TTableClasses = {
18
+ tableRootWrapper: string
19
+ tableHeading: string
20
+ tableBody: string
21
+ tableRowTitles: string
22
+ tableCell: string
23
+ tableAdditionalText: string
24
+ tableTitlesContainer: string
25
+ tableTitleCeil: string
26
+ tableBodyContainer: string
27
+ tableTitleRow: string
28
+ tableBodyRow: string
29
+ tableBodyCeil: string
30
+ }
@@ -0,0 +1,6 @@
1
+ export const capitalize = (str: string) => {
2
+ return str
3
+ .split('-')
4
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
5
+ .join('-')
6
+ }
@@ -0,0 +1,6 @@
1
+ import { type ClassValue, clsx } from 'clsx'
2
+ import { twMerge } from 'tailwind-merge'
3
+
4
+ export const cn = (...inputs: ClassValue[]) => {
5
+ return twMerge(clsx(inputs))
6
+ }
@@ -0,0 +1 @@
1
+ export const deepCompare = <A, B>(dataA: A, dataB: B): boolean => JSON.stringify(dataA) === JSON.stringify(dataB)
@@ -0,0 +1,5 @@
1
+ import { parse } from 'date-fns'
2
+
3
+ export const formatToDate = (value: string, format = 'dd.MM.yyyy') => {
4
+ return parse(value, format, new Date())
5
+ }
@@ -0,0 +1,5 @@
1
+ export { cn } from './cn'
2
+ export { deepCompare } from './deepCompare'
3
+ export { isClient } from './isClient'
4
+ export { capitalize } from './capitalize'
5
+ export { formatToDate } from './formatToDate'
@@ -0,0 +1 @@
1
+ export const isClient = typeof window !== 'undefined' && window.document !== undefined
@@ -0,0 +1,3 @@
1
+ export * from './regExp'
2
+ export * from './messages'
3
+ export * from './zodValidation'
@@ -0,0 +1,12 @@
1
+ export const VALIDATION_MESSAGES = {
2
+ REQUIRED: 'Поле обязательно к заполнению',
3
+ MIN_LENGTH: 'Минимальная длина символов должна быть не менее',
4
+ MAX_LENGTH: 'Максимальная длина символов должна быть не более',
5
+ FIX_LENGTH: 'Длина символов должна быть равна',
6
+ MAX_LENGTH_ELEMENTS: 'Максимальное количество элементов должно быть не более',
7
+ MIN_LENGTH_ELEMENTS: 'Минимальное количество элементов должно быть не менее',
8
+ FIX_LENGTH_ELEMENTS: 'Количество элементов должно быть равно',
9
+ INVALID_VALUE: 'Поле заполнено некорректно',
10
+ INVALID_DATE: 'Введите корректную дату',
11
+ FUTURE_DATE_NOT_ALLOWED: 'Нельзя выбрать дату позже текущей'
12
+ } as const
@@ -0,0 +1,5 @@
1
+ /* eslint-disable operator-linebreak */
2
+ export const RgxUnicode = /^[\u0400-\u04FF\u00CB\u00EB -]+$/ // Диапазон символов Unicode, включающий кириллические символы.*
3
+ export const RgxCheckForHyphen = /^(?:[^-]+(?:-[^-]+){0,4}|[^-]+)$/ // Проверяет количество дефисов a-b-c-d-e Валидный (до 4 дефисов), не валидный*
4
+ export const RgxPatronymic =
5
+ /^[a-zA-Zа-яА-ЯёЁ]+(?:\s*-\s*[a-zA-Zа-яА-ЯёЁ]+){0,4}(?:\s+[a-zA-Zа-яА-ЯёЁ]+(?:\s*-\s*[a-zA-Zа-яА-ЯёЁ]+){0,4})?$/i
@@ -0,0 +1,32 @@
1
+ import { isValid, parse } from 'date-fns'
2
+ import { z } from 'zod'
3
+ import { VALIDATION_MESSAGES } from '../messages'
4
+
5
+ export const zodCalendarValidate = z
6
+ .string()
7
+ .length(10, { message: VALIDATION_MESSAGES.INVALID_DATE })
8
+ .superRefine((val, ctx) => {
9
+ const [day, month, year] = val?.split('.') ?? ''
10
+ const parsed = parse(`${day}/${month}/${year}`, 'dd/MM/yyyy', new Date())
11
+
12
+ if (+year <= 1950) {
13
+ ctx.addIssue({
14
+ code: z.ZodIssueCode.custom,
15
+ message: VALIDATION_MESSAGES.INVALID_DATE
16
+ })
17
+ }
18
+
19
+ if (!isValid(parsed)) {
20
+ ctx.addIssue({
21
+ code: z.ZodIssueCode.custom,
22
+ message: VALIDATION_MESSAGES.INVALID_DATE
23
+ })
24
+ }
25
+
26
+ if (new Date().getTime() < new Date(parsed).getTime()) {
27
+ ctx.addIssue({
28
+ code: z.ZodIssueCode.custom,
29
+ message: VALIDATION_MESSAGES.FUTURE_DATE_NOT_ALLOWED
30
+ })
31
+ }
32
+ })
@@ -0,0 +1,67 @@
1
+ import { z } from 'zod'
2
+ import { RgxCheckForHyphen, RgxPatronymic, RgxUnicode } from '../regExp'
3
+ import { capitalize } from '$/shared/utils'
4
+
5
+ const formattedFio = (value: string) => {
6
+ const parts = value.trim().replace(/\s+/g, ' ').split(' ')
7
+ const [surname, name, ...patronymicArr] = parts
8
+ const patronymic = patronymicArr?.join(' ')
9
+
10
+ return {
11
+ surname,
12
+ name,
13
+ patronymic
14
+ }
15
+ }
16
+
17
+ export const zodDadataFioValidate = z
18
+ .string({ invalid_type_error: 'Обязательно к заполнению', required_error: 'Обязательно к заполнению' })
19
+ .superRefine((value, ctx) => {
20
+ if (!RgxUnicode.test(value)) {
21
+ ctx.addIssue({
22
+ code: z.ZodIssueCode.custom,
23
+ message: 'Должна быть только кириллица'
24
+ })
25
+ }
26
+
27
+ const { surname, name, patronymic } = formattedFio(value)
28
+
29
+ if (!surname || !name) {
30
+ ctx.addIssue({
31
+ code: z.ZodIssueCode.custom,
32
+ message: 'Введите имя и фамилию'
33
+ })
34
+ }
35
+
36
+ if (!RgxCheckForHyphen.test(name)) {
37
+ ctx.addIssue({
38
+ code: z.ZodIssueCode.custom,
39
+ message: 'Неверно введено имя'
40
+ })
41
+ }
42
+
43
+ if (!RgxCheckForHyphen.test(surname)) {
44
+ ctx.addIssue({
45
+ code: z.ZodIssueCode.custom,
46
+ message: 'Неверно введена фамилия'
47
+ })
48
+ }
49
+
50
+ if (patronymic) {
51
+ if (!RgxPatronymic.test(patronymic)) {
52
+ ctx.addIssue({
53
+ code: z.ZodIssueCode.custom,
54
+ message: 'Неверно введено отчество'
55
+ })
56
+ }
57
+ }
58
+ })
59
+ .transform((value) => {
60
+ const { surname, name, patronymic } = formattedFio(value)
61
+
62
+ return {
63
+ surname: capitalize(surname),
64
+ name: capitalize(name),
65
+ patronymic: patronymic ? capitalize(patronymic) : undefined
66
+ }
67
+ })
@@ -0,0 +1,2 @@
1
+ export * from './dadataFio'
2
+ export * from './calendar'
@@ -0,0 +1,2 @@
1
+ /// <reference types="vite/client" />
2
+ /// <reference types="vite-plugin-svgr/client" />
@@ -0,0 +1,45 @@
1
+ import * as React from 'react'
2
+ import { Heading } from '$/shared/ui'
3
+ import { cn } from '$/shared/utils'
4
+
5
+ interface IAdvantageClasses {
6
+ wrapper: string
7
+ advantage: string
8
+ title: string
9
+ description: string
10
+ }
11
+ export interface IAdvantage {
12
+ title: string
13
+ description: string | React.ReactElement
14
+ }
15
+
16
+ export interface IAdvantagesProps {
17
+ advantagesList: IAdvantage[]
18
+ classes?: Partial<IAdvantageClasses>
19
+ }
20
+
21
+ export const Advantages = ({ advantagesList, classes }: IAdvantagesProps) => {
22
+ return (
23
+ <div
24
+ className={cn(
25
+ 'flex w-[328px] flex-col gap-8 rounded-md bg-color-white shadow-sm mobile:p-6 desktop:w-full desktop:flex-row desktop:items-start desktop:gap-0 desktop:py-6',
26
+ classes?.wrapper
27
+ )}
28
+ >
29
+ {advantagesList?.map(({ title, description }) => (
30
+ <div
31
+ key={title}
32
+ className={cn(
33
+ 'after:content-[" "] relative flex h-full w-[285px] flex-col gap-2 after:absolute after:h-[1px] after:w-[280px] after:bg-color-blue-grey-300 last:after:hidden mobile:after:-bottom-4 mobile:after:left-1/2 mobile:after:-translate-x-1/2 desktop:px-8 desktop:after:right-0 desktop:after:top-1/2 desktop:after:h-10 desktop:after:w-[1px] desktop:after:-translate-y-1/2',
34
+ classes?.advantage
35
+ )}
36
+ >
37
+ <Heading as='h4' className={cn('text-color-dark', classes?.title)}>
38
+ {title}
39
+ </Heading>
40
+ <p className={cn('desk-body-regular-l text-color-tetriary', classes?.description)}>{description}</p>
41
+ </div>
42
+ ))}
43
+ </div>
44
+ )
45
+ }
@@ -0,0 +1,74 @@
1
+ import { type IAdvantage } from '../Advantages'
2
+ import { type IBannerButtonsGroupClasses } from './ui/BannerButtonsGroup'
3
+ import { BannerWithSeparateImg } from './ui/banners'
4
+ import { BannerImageFull } from './ui/banners/BannerImageFull'
5
+ import { type IButtonProps } from '$/shared/ui'
6
+
7
+ interface IBannerClasses extends IBannerButtonsGroupClasses {
8
+ section: string
9
+ container: string
10
+ wrapper: string
11
+ content: string
12
+ textBlock: string
13
+ title: string
14
+ subtitle: string
15
+ imageContainer: string
16
+ image: string
17
+ advantages: string
18
+ }
19
+
20
+ export type TButtonsConfig = {
21
+ primary: IButtonProps
22
+ secondary?: IButtonProps
23
+ }
24
+
25
+ export interface IBannerProps {
26
+ headTitle: string
27
+ subtitle: string
28
+ buttonsConfig: TButtonsConfig
29
+ advantagesList?: IAdvantage[]
30
+ classes?: Partial<IBannerClasses>
31
+ bannerVariant?: 'sepatateImg' | 'fullImg'
32
+ }
33
+
34
+ export const Banner = ({ bannerVariant, ...props }: IBannerProps) => {
35
+ switch (bannerVariant) {
36
+ case 'sepatateImg':
37
+ return <BannerWithSeparateImg {...props} />
38
+ case 'fullImg':
39
+ return <BannerImageFull {...props} />
40
+ default:
41
+ return <BannerWithSeparateImg {...props} />
42
+ }
43
+ }
44
+
45
+ // export const Banner = ({ headTitle, subtitle, buttonsConfig, advantagesList, classes }: IBannerProps) => {
46
+ // return (
47
+ // <section className={cn('h-[456px] bg-banner-skyblue-300 relative', classes?.section)}>
48
+ // <ResponsiveContainer className={cn(classes?.container)}>
49
+ // <div className={cn('flex flex-col desktop:flex-row desktop:justify-between', classes?.wrapper)}>
50
+ // <div className={cn('z-10 flex flex-col gap-10 pt-6 desktop:pt-20', classes?.content)}>
51
+ // <div className={cn('flex flex-col gap-4', classes?.textBlock)}>
52
+ // <Heading as='h1' className={cn('text-color-dark', classes?.title)}>
53
+ // {headTitle}
54
+ // </Heading>
55
+ // <p className={cn('desk-body-regular-l text-color-dark', classes?.subtitle)}>{subtitle}</p>
56
+ // </div>
57
+ // <BannerButtonsGroup buttonsConfig={buttonsConfig} classes={classes} />
58
+ // </div>
59
+ // <div
60
+ // className={cn(
61
+ // 'w-full h-[410px] mobile:absolute mobile:left-1/2 mobile:bottom-0 mobile:-translate-x-1/2 desktop:w-[550px] desktop:h-full',
62
+ // classes?.imageContainer
63
+ // )}
64
+ // >
65
+ // <img src={money} alt='money' className={cn('w-full h-full object-contain', classes?.image)} />
66
+ // </div>
67
+ // </div>
68
+ // <div className={cn('absolute bottom-[-400px] desktop:bottom-[-50px]', classes?.advantages)}>
69
+ // {advantagesList && advantagesList?.length > 0 && <Advantages advantagesList={advantagesList} />}
70
+ // </div>
71
+ // </ResponsiveContainer>
72
+ // </section>
73
+ // )
74
+ // }
@@ -0,0 +1 @@
1
+ export { Banner } from './Banner'
@@ -0,0 +1,159 @@
1
+ import toast from 'react-hot-toast'
2
+ import { type IBannerProps } from '../Banner'
3
+
4
+ export const mockBannerBase: IBannerProps = {
5
+ headTitle: 'Кредит на любые цели',
6
+ subtitle: 'до 5 млн рублей',
7
+ buttonsConfig: {
8
+ primary: {
9
+ onClick: () => toast.success('@click on primary btn'),
10
+ children: 'Primary',
11
+ size: 'lg'
12
+ },
13
+ secondary: {
14
+ onClick: () => toast.success('@click on secondary btn'),
15
+ children: 'Secondary',
16
+ size: 'lg'
17
+ }
18
+ }
19
+ }
20
+ export const mockBannerOnlyPrimaryButton: IBannerProps = {
21
+ headTitle: 'Кредит на любые цели',
22
+ subtitle: 'до 5 млн рублей',
23
+ buttonsConfig: {
24
+ primary: {
25
+ onClick: () => toast.success('@click on primary btn'),
26
+ children: 'Primary',
27
+ size: 'lg'
28
+ }
29
+ }
30
+ }
31
+
32
+ export const mockWithAdvantages: IBannerProps = {
33
+ headTitle: 'Кредит на любые цели',
34
+ subtitle: 'до 5 млн рублей',
35
+ buttonsConfig: {
36
+ primary: {
37
+ onClick: () => toast.success('@click on primary btn'),
38
+ children: 'Primary',
39
+ size: 'lg'
40
+ }
41
+ },
42
+ advantagesList: [
43
+ { title: 'До 5 млн ₽', description: 'сумма кредита' },
44
+ { title: 'До 5 лет', description: 'срок кредита' },
45
+ { title: 'От 5 минут', description: 'быстрое одобрение' },
46
+ { title: 'От 20 минут', description: 'сумма одобрения' }
47
+ ]
48
+ }
49
+ export const mockBannerBaseFullImage: IBannerProps = {
50
+ headTitle: 'Кредит на любые цели',
51
+ subtitle: 'до 5 млн рублей',
52
+ buttonsConfig: {
53
+ primary: {
54
+ onClick: () => toast.success('@click on primary btn'),
55
+ children: 'Primary',
56
+ size: 'lg'
57
+ },
58
+ secondary: {
59
+ onClick: () => toast.success('@click on secondary btn'),
60
+ children: 'Secondary',
61
+ size: 'lg'
62
+ }
63
+ },
64
+ classes: {
65
+ primary: 'bg-color-negative',
66
+ secondary: 'bg-color-negative text-color-white'
67
+ },
68
+ bannerVariant: 'fullImg'
69
+ }
70
+
71
+ export const mockBannerFullImageOnlyPrimaryButton: IBannerProps = {
72
+ headTitle: 'Кредит на любые цели',
73
+ subtitle: 'до 5 млн рублей',
74
+ buttonsConfig: {
75
+ primary: {
76
+ onClick: () => toast.success('@click on primary btn'),
77
+ children: 'Primary',
78
+ size: 'lg'
79
+ }
80
+ },
81
+ classes: {
82
+ primary: 'bg-color-negative'
83
+ },
84
+ bannerVariant: 'fullImg'
85
+ }
86
+
87
+ export const mockBannerFullImageWithAdvantages: IBannerProps = {
88
+ headTitle: 'Кредит на любые цели',
89
+ subtitle: 'до 5 млн рублей',
90
+ buttonsConfig: {
91
+ primary: {
92
+ onClick: () => toast.success('@click on primary btn'),
93
+ children: 'Primary',
94
+ size: 'lg'
95
+ },
96
+ secondary: {
97
+ onClick: () => toast.success('@click on secondary btn'),
98
+ children: 'Secondary',
99
+ size: 'lg'
100
+ }
101
+ },
102
+ classes: {
103
+ primary: 'bg-color-negative',
104
+ secondary: 'bg-color-negative text-color-white'
105
+ },
106
+ bannerVariant: 'fullImg',
107
+ advantagesList: [
108
+ { title: 'До 5 млн ₽', description: 'сумма кредита' },
109
+ { title: 'До 5 лет', description: 'срок кредита' },
110
+ { title: 'От 5 минут', description: 'быстрое одобрение' },
111
+ { title: 'От 20 минут', description: 'сумма одобрения' }
112
+ ]
113
+ }
114
+
115
+ export const mockBannerBaseGradient: IBannerProps = {
116
+ headTitle: 'Кредит на любые цели',
117
+ subtitle: 'до 5 млн рублей',
118
+ buttonsConfig: {
119
+ primary: {
120
+ onClick: () => toast.success('@click on primary btn'),
121
+ children: 'Primary',
122
+ size: 'lg'
123
+ },
124
+ secondary: {
125
+ onClick: () => toast.success('@click on secondary btn'),
126
+ children: 'Secondary',
127
+ size: 'lg'
128
+ }
129
+ },
130
+ classes: {
131
+ section: 'bg-color-transparent bg-[linear-gradient(97.94deg,_#dae4f2_-14.21%,_#afcffc_47.44%,_#79aef8_107.86%);]'
132
+ }
133
+ }
134
+
135
+ export const mockBannerBaseGradientAdvantages: IBannerProps = {
136
+ headTitle: 'Кредит на любые цели',
137
+ subtitle: 'до 5 млн рублей',
138
+ buttonsConfig: {
139
+ primary: {
140
+ onClick: () => toast.success('@click on primary btn'),
141
+ children: 'Primary',
142
+ size: 'lg'
143
+ },
144
+ secondary: {
145
+ onClick: () => toast.success('@click on secondary btn'),
146
+ children: 'Secondary',
147
+ size: 'lg'
148
+ }
149
+ },
150
+ classes: {
151
+ section: 'bg-color-transparent gradient-apply'
152
+ },
153
+ advantagesList: [
154
+ { title: 'До 5 млн ₽', description: 'сумма кредита' },
155
+ { title: 'До 5 лет', description: 'срок кредита' },
156
+ { title: 'От 5 минут', description: 'быстрое одобрение' },
157
+ { title: 'От 20 минут', description: 'сумма одобрения' }
158
+ ]
159
+ }
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,44 @@
1
+ import { type TButtonsConfig } from '../Banner'
2
+ import { Button } from '$/shared/ui'
3
+ import { cn } from '$/shared/utils'
4
+
5
+ export interface IBannerButtonsGroupClasses {
6
+ group: string
7
+ primary: string
8
+ secondary: string
9
+ }
10
+ interface IBannerButtonsGroupProps {
11
+ buttonsConfig: TButtonsConfig
12
+ classes?: Partial<IBannerButtonsGroupClasses>
13
+ className?: string
14
+ }
15
+
16
+ export const BannerButtonsGroup = ({ buttonsConfig, classes, className }: IBannerButtonsGroupProps) => {
17
+ const withSecondaryBtn = buttonsConfig?.secondary && buttonsConfig.secondary.children
18
+
19
+ return (
20
+ <div
21
+ data-id='banner-buttons-group'
22
+ className={cn(
23
+ 'grid-buttons-apply absolute bottom-6 flex w-full flex-col mobile:max-w-[328px] mobile:justify-self-center desktop:static desktop:flex-row',
24
+ { 'flex items-center gap-4': withSecondaryBtn },
25
+ classes?.group,
26
+ className
27
+ )}
28
+ >
29
+ <Button intent='primary' {...buttonsConfig.primary} isFull className={cn('desktop:max-w-[216px]', classes?.primary)}>
30
+ {buttonsConfig.primary.children}
31
+ </Button>
32
+ {withSecondaryBtn && (
33
+ <Button
34
+ intent='secondary'
35
+ {...buttonsConfig?.secondary}
36
+ isFull
37
+ className={cn('desktop:max-w-[216px]', classes?.secondary)}
38
+ >
39
+ {buttonsConfig?.secondary?.children}
40
+ </Button>
41
+ )}
42
+ </div>
43
+ )
44
+ }
@@ -0,0 +1,82 @@
1
+ import { type IBannerProps } from '../../Banner'
2
+ import saif from '../../saif.jpg'
3
+ import { BannerButtonsGroup } from '../BannerButtonsGroup'
4
+ import { Heading, ResponsiveContainer } from '$/shared/ui'
5
+ import { cn } from '$/shared/utils'
6
+ import { Advantages } from '$/widgets/Advantages'
7
+
8
+ export const BannerImageFull = ({
9
+ headTitle,
10
+ subtitle,
11
+ buttonsConfig,
12
+ advantagesList,
13
+ classes
14
+ }: Omit<IBannerProps, 'bannerVariant'>) => {
15
+ return (
16
+ <section data-id='banner-section' className={cn('relative h-[552px] desktop:h-[456px]', classes?.section)}>
17
+ <div
18
+ data-id='banner-img-wrapper'
19
+ className='absolute bottom-0 left-0 right-0 top-0 z-[-1] mx-auto h-full max-w-[1920px] desktop:h-[456px]'
20
+ >
21
+ <picture>
22
+ <source
23
+ media='(min-width: 1128px)'
24
+ srcSet='https://sovcombank.ru/apply/credit/static/5a216aa0b1aa395335e71cb69fc3059f/7eb38/large.avif'
25
+ type='image/avif'
26
+ />
27
+ <source
28
+ media='(max-width: 1127px)'
29
+ srcSet='https://sovcombank.ru/apply/credit/static/e71c554abd4a3a92ff79f048568de883/73d21/mob.avif'
30
+ type='image/avif'
31
+ />
32
+ <img
33
+ data-id='banner-image'
34
+ src={saif}
35
+ alt=' '
36
+ className={cn('h-full w-full object-cover object-center', classes?.image)}
37
+ />
38
+ </picture>
39
+ </div>
40
+ <ResponsiveContainer data-id='banner-container' className={cn('h-full pb-6', classes?.container)}>
41
+ <div
42
+ data-id='banner-grid'
43
+ className={cn(
44
+ 'grid-mob-full-img-apply desktop:grid-desk-full-img-apply grid h-full grid-rows-[repeat(2,_min-content)]',
45
+ classes?.wrapper
46
+ )}
47
+ >
48
+ <div
49
+ data-id='banner-text-block'
50
+ className={cn(
51
+ 'grid-text-apply flex flex-col gap-4 pt-6 mobile:w-[328px] desktop:pb-10 desktop:pt-20',
52
+ classes?.textBlock
53
+ )}
54
+ >
55
+ <Heading data-id='banner-title' as='h1' className={cn('text-color-white', classes?.title)}>
56
+ {headTitle}
57
+ </Heading>
58
+ <p data-id='banner-subtitle' className={cn('desk-body-regular-l text-color-white', classes?.subtitle)}>
59
+ {subtitle}
60
+ </p>
61
+ </div>
62
+
63
+ <BannerButtonsGroup
64
+ className='mobile:self-end'
65
+ data-id='banner-buttons-group'
66
+ buttonsConfig={buttonsConfig}
67
+ classes={classes}
68
+ />
69
+ </div>
70
+
71
+ <div
72
+ data-id='banner-advantages'
73
+ className={cn('absolute bottom-[-400px] right-1/2 translate-x-1/2 desktop:bottom-[-50px]', classes?.advantages)}
74
+ >
75
+ {advantagesList && advantagesList?.length > 0 && (
76
+ <Advantages data-id='banner-advantages-list' advantagesList={advantagesList} />
77
+ )}
78
+ </div>
79
+ </ResponsiveContainer>
80
+ </section>
81
+ )
82
+ }