@alfalab/core-components-tabs 8.0.8 → 8.1.1

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 (270) hide show
  1. package/collapsible.d.ts +1 -6
  2. package/collapsible.js +5 -16
  3. package/components/primary-tablist/Component.collapsible.d.ts +2 -2
  4. package/components/primary-tablist/Component.collapsible.js +11 -11
  5. package/components/primary-tablist/Component.d.ts +2 -2
  6. package/components/primary-tablist/Component.desktop.js +8 -2
  7. package/components/primary-tablist/Component.js +8 -2
  8. package/components/primary-tablist/Component.mobile.js +12 -4
  9. package/components/primary-tablist/Component.responsive.js +7 -2
  10. package/components/primary-tablist/index.css +31 -29
  11. package/components/primary-tablist/mobile.css +34 -32
  12. package/components/scroll-controls/Component.d.ts +11 -0
  13. package/components/scroll-controls/Component.js +53 -0
  14. package/components/scroll-controls/index.css +94 -0
  15. package/components/scroll-controls/index.d.ts +1 -0
  16. package/components/scroll-controls/index.js +17 -0
  17. package/components/scroll-controls/utils.d.ts +7 -0
  18. package/components/scroll-controls/utils.js +56 -0
  19. package/components/scrollable-container/Component.d.ts +14 -2
  20. package/components/scrollable-container/Component.js +45 -8
  21. package/components/scrollable-container/index.css +10 -6
  22. package/components/scrollable-container/index.js +7 -0
  23. package/components/secondary-tablist/Component.d.ts +2 -2
  24. package/components/secondary-tablist/Component.desktop.js +8 -2
  25. package/components/secondary-tablist/Component.js +9 -3
  26. package/components/secondary-tablist/Component.mobile.d.ts +2 -2
  27. package/components/secondary-tablist/Component.mobile.js +10 -4
  28. package/components/secondary-tablist/Component.responsive.d.ts +1 -1
  29. package/components/secondary-tablist/Component.responsive.js +9 -3
  30. package/components/secondary-tablist/index.css +11 -11
  31. package/components/secondary-tablist/mobile.css +13 -13
  32. package/components/tab/Component.js +1 -1
  33. package/components/tab/index.css +3 -3
  34. package/components/tabs/Component.collapsible.d.ts +6 -0
  35. package/components/tabs/{Component.collabsible.desktop.js → Component.collapsible.js} +5 -6
  36. package/components/tabs/Component.d.ts +1 -1
  37. package/components/tabs/Component.desktop.js +8 -2
  38. package/components/tabs/Component.js +2 -2
  39. package/components/tabs/Component.mobile.d.ts +1 -1
  40. package/components/tabs/Component.mobile.js +8 -3
  41. package/components/tabs/Component.responsive.js +8 -3
  42. package/cssm/collapsible.d.ts +1 -6
  43. package/cssm/collapsible.js +4 -15
  44. package/cssm/components/primary-tablist/Component.collapsible.d.ts +2 -2
  45. package/cssm/components/primary-tablist/Component.collapsible.js +12 -11
  46. package/cssm/components/primary-tablist/Component.d.ts +2 -2
  47. package/cssm/components/primary-tablist/Component.desktop.js +8 -1
  48. package/cssm/components/primary-tablist/Component.js +9 -2
  49. package/cssm/components/primary-tablist/Component.mobile.js +8 -1
  50. package/cssm/components/primary-tablist/Component.responsive.js +7 -0
  51. package/cssm/components/primary-tablist/index.module.css +2 -0
  52. package/cssm/components/scroll-controls/Component.d.ts +11 -0
  53. package/cssm/components/scroll-controls/Component.js +52 -0
  54. package/cssm/components/scroll-controls/index.d.ts +1 -0
  55. package/cssm/components/scroll-controls/index.js +18 -0
  56. package/cssm/components/scroll-controls/index.module.css +93 -0
  57. package/cssm/components/scroll-controls/utils.d.ts +7 -0
  58. package/cssm/components/scroll-controls/utils.js +56 -0
  59. package/cssm/components/scrollable-container/Component.d.ts +14 -2
  60. package/cssm/components/scrollable-container/Component.js +45 -7
  61. package/cssm/components/scrollable-container/index.js +8 -0
  62. package/cssm/components/scrollable-container/index.module.css +5 -1
  63. package/cssm/components/secondary-tablist/Component.d.ts +2 -2
  64. package/cssm/components/secondary-tablist/Component.desktop.js +8 -1
  65. package/cssm/components/secondary-tablist/Component.js +10 -3
  66. package/cssm/components/secondary-tablist/Component.mobile.d.ts +2 -2
  67. package/cssm/components/secondary-tablist/Component.mobile.js +9 -2
  68. package/cssm/components/secondary-tablist/Component.responsive.d.ts +1 -1
  69. package/cssm/components/secondary-tablist/Component.responsive.js +9 -2
  70. package/cssm/components/tabs/Component.collapsible.d.ts +6 -0
  71. package/cssm/components/tabs/{Component.collabsible.desktop.js → Component.collapsible.js} +4 -5
  72. package/cssm/components/tabs/Component.d.ts +1 -1
  73. package/cssm/components/tabs/Component.desktop.js +7 -0
  74. package/cssm/components/tabs/Component.js +2 -2
  75. package/cssm/components/tabs/Component.mobile.d.ts +1 -1
  76. package/cssm/components/tabs/Component.mobile.js +7 -0
  77. package/cssm/components/tabs/Component.responsive.js +7 -0
  78. package/cssm/desktop.js +7 -0
  79. package/cssm/index-c76d6398.d.ts +0 -1
  80. package/cssm/index.js +7 -0
  81. package/cssm/mobile.js +7 -0
  82. package/cssm/shared.js +8 -1
  83. package/cssm/typings.d.ts +13 -2
  84. package/desktop.js +8 -2
  85. package/esm/collapsible.d.ts +1 -6
  86. package/esm/collapsible.js +4 -10
  87. package/esm/components/primary-tablist/Component.collapsible.d.ts +2 -2
  88. package/esm/components/primary-tablist/Component.collapsible.js +11 -11
  89. package/esm/components/primary-tablist/Component.d.ts +2 -2
  90. package/esm/components/primary-tablist/Component.desktop.js +8 -2
  91. package/esm/components/primary-tablist/Component.js +8 -2
  92. package/esm/components/primary-tablist/Component.mobile.js +11 -3
  93. package/esm/components/primary-tablist/Component.responsive.js +7 -2
  94. package/esm/components/primary-tablist/index.css +31 -29
  95. package/esm/components/primary-tablist/mobile.css +34 -32
  96. package/esm/components/scroll-controls/Component.d.ts +11 -0
  97. package/esm/components/scroll-controls/Component.js +43 -0
  98. package/esm/components/scroll-controls/index.css +94 -0
  99. package/esm/components/scroll-controls/index.d.ts +1 -0
  100. package/esm/components/scroll-controls/index.js +9 -0
  101. package/esm/components/scroll-controls/utils.d.ts +7 -0
  102. package/esm/components/scroll-controls/utils.js +50 -0
  103. package/esm/components/scrollable-container/Component.d.ts +14 -2
  104. package/esm/components/scrollable-container/Component.js +46 -9
  105. package/esm/components/scrollable-container/index.css +10 -6
  106. package/esm/components/scrollable-container/index.js +7 -0
  107. package/esm/components/secondary-tablist/Component.d.ts +2 -2
  108. package/esm/components/secondary-tablist/Component.desktop.js +8 -2
  109. package/esm/components/secondary-tablist/Component.js +9 -3
  110. package/esm/components/secondary-tablist/Component.mobile.d.ts +2 -2
  111. package/esm/components/secondary-tablist/Component.mobile.js +10 -4
  112. package/esm/components/secondary-tablist/Component.responsive.d.ts +1 -1
  113. package/esm/components/secondary-tablist/Component.responsive.js +9 -3
  114. package/esm/components/secondary-tablist/index.css +11 -11
  115. package/esm/components/secondary-tablist/mobile.css +13 -13
  116. package/esm/components/tab/Component.js +1 -1
  117. package/esm/components/tab/index.css +3 -3
  118. package/esm/components/tabs/Component.collapsible.d.ts +6 -0
  119. package/esm/components/tabs/{Component.collabsible.desktop.js → Component.collapsible.js} +5 -6
  120. package/esm/components/tabs/Component.d.ts +1 -1
  121. package/esm/components/tabs/Component.desktop.js +8 -2
  122. package/esm/components/tabs/Component.js +2 -2
  123. package/esm/components/tabs/Component.mobile.d.ts +1 -1
  124. package/esm/components/tabs/Component.mobile.js +8 -3
  125. package/esm/components/tabs/Component.responsive.js +8 -3
  126. package/esm/desktop.js +8 -2
  127. package/esm/index-c76d6398.d.ts +0 -1
  128. package/esm/index.js +8 -3
  129. package/esm/index.module-e0497aa4.js +4 -0
  130. package/esm/index.module-ee44d88b.js +4 -0
  131. package/esm/mobile.js +8 -3
  132. package/esm/shared.js +7 -1
  133. package/esm/typings.d.ts +13 -2
  134. package/index-c76d6398.d.ts +0 -1
  135. package/index-ebda875c.d.ts +86 -21
  136. package/index.js +8 -3
  137. package/index.module-ae0eca4b.js +6 -0
  138. package/index.module-ed812325.js +6 -0
  139. package/mobile.js +8 -3
  140. package/modern/collapsible.d.ts +1 -6
  141. package/modern/collapsible.js +4 -10
  142. package/modern/components/primary-tablist/Component.collapsible.d.ts +2 -2
  143. package/modern/components/primary-tablist/Component.collapsible.js +11 -11
  144. package/modern/components/primary-tablist/Component.d.ts +2 -2
  145. package/modern/components/primary-tablist/Component.desktop.js +8 -2
  146. package/modern/components/primary-tablist/Component.js +8 -2
  147. package/modern/components/primary-tablist/Component.mobile.js +11 -3
  148. package/modern/components/primary-tablist/Component.responsive.js +7 -2
  149. package/modern/components/primary-tablist/index.css +31 -29
  150. package/modern/components/primary-tablist/mobile.css +34 -32
  151. package/modern/components/scroll-controls/Component.d.ts +11 -0
  152. package/modern/components/scroll-controls/Component.js +40 -0
  153. package/modern/components/scroll-controls/index.css +94 -0
  154. package/modern/components/scroll-controls/index.d.ts +1 -0
  155. package/modern/components/scroll-controls/index.js +8 -0
  156. package/modern/components/scroll-controls/utils.d.ts +7 -0
  157. package/modern/components/scroll-controls/utils.js +50 -0
  158. package/modern/components/scrollable-container/Component.d.ts +14 -2
  159. package/modern/components/scrollable-container/Component.js +44 -9
  160. package/modern/components/scrollable-container/index.css +10 -6
  161. package/modern/components/scrollable-container/index.js +6 -0
  162. package/modern/components/secondary-tablist/Component.d.ts +2 -2
  163. package/modern/components/secondary-tablist/Component.desktop.js +8 -2
  164. package/modern/components/secondary-tablist/Component.js +9 -3
  165. package/modern/components/secondary-tablist/Component.mobile.d.ts +2 -2
  166. package/modern/components/secondary-tablist/Component.mobile.js +9 -3
  167. package/modern/components/secondary-tablist/Component.responsive.d.ts +1 -1
  168. package/modern/components/secondary-tablist/Component.responsive.js +9 -3
  169. package/modern/components/secondary-tablist/index.css +11 -11
  170. package/modern/components/secondary-tablist/mobile.css +13 -13
  171. package/modern/components/tab/Component.js +1 -1
  172. package/modern/components/tab/index.css +3 -3
  173. package/modern/components/tabs/Component.collapsible.d.ts +6 -0
  174. package/modern/components/tabs/{Component.collabsible.desktop.js → Component.collapsible.js} +4 -5
  175. package/modern/components/tabs/Component.d.ts +1 -1
  176. package/modern/components/tabs/Component.desktop.js +8 -2
  177. package/modern/components/tabs/Component.js +2 -2
  178. package/modern/components/tabs/Component.mobile.d.ts +1 -1
  179. package/modern/components/tabs/Component.mobile.js +8 -3
  180. package/modern/components/tabs/Component.responsive.js +8 -3
  181. package/modern/desktop.js +8 -2
  182. package/modern/index-c76d6398.d.ts +0 -1
  183. package/modern/index.js +8 -3
  184. package/modern/index.module-0162508b.js +4 -0
  185. package/modern/index.module-1d3d8c31.js +4 -0
  186. package/modern/mobile.js +8 -3
  187. package/modern/shared.js +6 -0
  188. package/modern/typings.d.ts +13 -2
  189. package/package.json +5 -2
  190. package/shared.js +7 -1
  191. package/src/collapsible.ts +1 -9
  192. package/src/components/primary-tablist/Component.collapsible.tsx +6 -7
  193. package/src/components/primary-tablist/Component.desktop.tsx +1 -1
  194. package/src/components/primary-tablist/Component.mobile.tsx +6 -1
  195. package/src/components/primary-tablist/Component.tsx +6 -2
  196. package/src/components/primary-tablist/index.module.css +4 -0
  197. package/src/components/scroll-controls/Component.tsx +78 -0
  198. package/src/components/scroll-controls/index.module.css +68 -0
  199. package/src/components/scroll-controls/index.ts +1 -0
  200. package/src/components/scroll-controls/utils.ts +60 -0
  201. package/src/components/scrollable-container/Component.tsx +81 -12
  202. package/src/components/scrollable-container/index.module.css +7 -1
  203. package/src/components/secondary-tablist/Component.desktop.tsx +1 -0
  204. package/src/components/secondary-tablist/Component.mobile.tsx +4 -2
  205. package/src/components/secondary-tablist/Component.responsive.tsx +1 -2
  206. package/src/components/secondary-tablist/Component.tsx +10 -2
  207. package/src/components/tabs/Component.collapsible.tsx +15 -0
  208. package/src/components/tabs/Component.mobile.tsx +1 -1
  209. package/src/components/tabs/Component.tsx +4 -0
  210. package/src/typings.ts +16 -0
  211. package/typings.d.ts +13 -2
  212. package/components/primary-tablist/Component.collapsible.desktop.d.ts +0 -5
  213. package/components/primary-tablist/Component.collapsible.desktop.js +0 -32
  214. package/components/primary-tablist/Component.collapsible.mobile.d.ts +0 -6
  215. package/components/primary-tablist/Component.collapsible.mobile.js +0 -35
  216. package/components/primary-tablist/Component.collapsible.responsive.d.ts +0 -5
  217. package/components/primary-tablist/Component.collapsible.responsive.js +0 -36
  218. package/components/tabs/Component.collabsible.desktop.d.ts +0 -6
  219. package/components/tabs/Component.collapsible.mobile.d.ts +0 -6
  220. package/components/tabs/Component.collapsible.mobile.js +0 -35
  221. package/components/tabs/Component.collapsible.responsive.d.ts +0 -6
  222. package/components/tabs/Component.collapsible.responsive.js +0 -37
  223. package/cssm/components/primary-tablist/Component.collapsible.desktop.d.ts +0 -5
  224. package/cssm/components/primary-tablist/Component.collapsible.desktop.js +0 -33
  225. package/cssm/components/primary-tablist/Component.collapsible.mobile.d.ts +0 -6
  226. package/cssm/components/primary-tablist/Component.collapsible.mobile.js +0 -37
  227. package/cssm/components/primary-tablist/Component.collapsible.responsive.d.ts +0 -5
  228. package/cssm/components/primary-tablist/Component.collapsible.responsive.js +0 -36
  229. package/cssm/components/tabs/Component.collabsible.desktop.d.ts +0 -6
  230. package/cssm/components/tabs/Component.collapsible.mobile.d.ts +0 -6
  231. package/cssm/components/tabs/Component.collapsible.mobile.js +0 -35
  232. package/cssm/components/tabs/Component.collapsible.responsive.d.ts +0 -6
  233. package/cssm/components/tabs/Component.collapsible.responsive.js +0 -37
  234. package/esm/components/primary-tablist/Component.collapsible.desktop.d.ts +0 -5
  235. package/esm/components/primary-tablist/Component.collapsible.desktop.js +0 -24
  236. package/esm/components/primary-tablist/Component.collapsible.mobile.d.ts +0 -6
  237. package/esm/components/primary-tablist/Component.collapsible.mobile.js +0 -26
  238. package/esm/components/primary-tablist/Component.collapsible.responsive.d.ts +0 -5
  239. package/esm/components/primary-tablist/Component.collapsible.responsive.js +0 -28
  240. package/esm/components/tabs/Component.collabsible.desktop.d.ts +0 -6
  241. package/esm/components/tabs/Component.collapsible.mobile.d.ts +0 -6
  242. package/esm/components/tabs/Component.collapsible.mobile.js +0 -27
  243. package/esm/components/tabs/Component.collapsible.responsive.d.ts +0 -6
  244. package/esm/components/tabs/Component.collapsible.responsive.js +0 -29
  245. package/esm/index.module-511c86f3.js +0 -4
  246. package/esm/index.module-ffeeb976.js +0 -4
  247. package/esm/mobile.module-34deaa77.js +0 -4
  248. package/index.module-0d8ea41a.js +0 -6
  249. package/index.module-38e4686f.js +0 -6
  250. package/mobile.module-a305e8da.js +0 -6
  251. package/modern/components/primary-tablist/Component.collapsible.desktop.d.ts +0 -5
  252. package/modern/components/primary-tablist/Component.collapsible.desktop.js +0 -20
  253. package/modern/components/primary-tablist/Component.collapsible.mobile.d.ts +0 -6
  254. package/modern/components/primary-tablist/Component.collapsible.mobile.js +0 -25
  255. package/modern/components/primary-tablist/Component.collapsible.responsive.d.ts +0 -5
  256. package/modern/components/primary-tablist/Component.collapsible.responsive.js +0 -26
  257. package/modern/components/tabs/Component.collabsible.desktop.d.ts +0 -6
  258. package/modern/components/tabs/Component.collapsible.mobile.d.ts +0 -6
  259. package/modern/components/tabs/Component.collapsible.mobile.js +0 -23
  260. package/modern/components/tabs/Component.collapsible.responsive.d.ts +0 -6
  261. package/modern/components/tabs/Component.collapsible.responsive.js +0 -25
  262. package/modern/index.module-4f82d773.js +0 -4
  263. package/modern/index.module-6f255828.js +0 -4
  264. package/modern/mobile.module-02182f0f.js +0 -4
  265. package/src/components/primary-tablist/Component.collapsible.desktop.tsx +0 -11
  266. package/src/components/primary-tablist/Component.collapsible.mobile.tsx +0 -27
  267. package/src/components/primary-tablist/Component.collapsible.responsive.tsx +0 -34
  268. package/src/components/tabs/Component.collabsible.desktop.tsx +0 -15
  269. package/src/components/tabs/Component.collapsible.mobile.tsx +0 -15
  270. package/src/components/tabs/Component.collapsible.responsive.tsx +0 -12
package/modern/shared.js CHANGED
@@ -4,6 +4,12 @@ export { useCollapsibleElements } from './hooks/use-collapsible-elements.js';
4
4
  import 'react';
5
5
  import 'classnames';
6
6
  import 'compute-scroll-into-view';
7
+ import './components/scroll-controls/Component.js';
8
+ import 'lodash.debounce';
9
+ import '@alfalab/core-components-icon-button/modern';
10
+ import '@alfalab/icons-glyph/ChevronLeftMIcon';
11
+ import '@alfalab/icons-glyph/ChevronRightMIcon';
12
+ import './components/scroll-controls/utils.js';
7
13
  import '@alfalab/core-components-shared/modern';
8
14
  import '@juggle/resize-observer';
9
15
  import '@alfalab/hooks';
@@ -69,6 +69,14 @@ type TabsProps = {
69
69
  * @default 1024
70
70
  */
71
71
  breakpoint?: number;
72
+ /**
73
+ * Форма тега (для view secondary только)
74
+ */
75
+ tagShape?: TagProps['shape'];
76
+ /**
77
+ * Стиль тега (для view secondary только)
78
+ */
79
+ tagView?: TagProps['view'];
72
80
  };
73
81
  type TabProps = {
74
82
  /**
@@ -123,7 +131,7 @@ type TabListTitle = {
123
131
  collapsed?: boolean;
124
132
  dataTestId?: string;
125
133
  };
126
- type TabListProps = Pick<TabsProps, 'className' | 'containerClassName' | 'size' | 'defaultMatchMediaValue' | 'selectedId' | 'scrollable' | 'collapsedTabsIds' | 'onChange' | 'dataTestId' | 'fullWidthScroll'> & {
134
+ type TabListProps = Pick<TabsProps, 'className' | 'containerClassName' | 'size' | 'defaultMatchMediaValue' | 'selectedId' | 'scrollable' | 'collapsedTabsIds' | 'onChange' | 'dataTestId' | 'fullWidthScroll' | 'tagShape' | 'tagView'> & {
127
135
  /**
128
136
  * Заголовки табов
129
137
  */
@@ -144,4 +152,7 @@ type Styles = {
144
152
  [key: string]: string;
145
153
  };
146
154
  };
147
- export { SelectedId, TabsProps, TabProps, TabListTitle, TabListProps, SecondaryTabListProps, UseTabsProps, Styles };
155
+ type PlatformProps = {
156
+ platform: 'desktop' | 'mobile';
157
+ };
158
+ export { SelectedId, TabsProps, TabProps, TabListTitle, TabListProps, SecondaryTabListProps, UseTabsProps, Styles, PlatformProps };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfalab/core-components-tabs",
3
- "version": "8.0.8",
3
+ "version": "8.1.1",
4
4
  "description": "Tabs components",
5
5
  "keywords": [],
6
6
  "license": "MIT",
@@ -44,13 +44,16 @@
44
44
  "dependencies": {
45
45
  "@alfalab/core-components-keyboard-focusable": "^4.1.0",
46
46
  "@alfalab/core-components-tag": "^6.0.1",
47
- "@alfalab/core-components-picker-button": "^11.1.3",
47
+ "@alfalab/core-components-picker-button": "^11.1.5",
48
48
  "@alfalab/core-components-badge": "^5.2.0",
49
49
  "@alfalab/core-components-mq": "^4.2.0",
50
50
  "@alfalab/hooks": "^1.13.0",
51
51
  "@alfalab/core-components-shared": "^0.4.0",
52
+ "@alfalab/core-components-icon-button": "^6.2.3",
53
+ "@alfalab/icons-glyph": "^2.108.0",
52
54
  "classnames": "^2.3.1",
53
55
  "compute-scroll-into-view": "^1.0.20",
56
+ "lodash.debounce": "^4.0.8",
54
57
  "@juggle/resize-observer": "^3.3.1",
55
58
  "tslib": "^2.4.0"
56
59
  },
package/shared.js CHANGED
@@ -8,8 +8,14 @@ var hooks_useCollapsibleElements = require('./hooks/use-collapsible-elements.js'
8
8
  require('react');
9
9
  require('classnames');
10
10
  require('compute-scroll-into-view');
11
- require('@alfalab/core-components-shared');
11
+ require('./components/scroll-controls/Component.js');
12
12
  require('tslib');
13
+ require('lodash.debounce');
14
+ require('@alfalab/core-components-icon-button');
15
+ require('@alfalab/icons-glyph/ChevronLeftMIcon');
16
+ require('@alfalab/icons-glyph/ChevronRightMIcon');
17
+ require('./components/scroll-controls/utils.js');
18
+ require('@alfalab/core-components-shared');
13
19
  require('@juggle/resize-observer');
14
20
  require('@alfalab/hooks');
15
21
 
@@ -1,10 +1,2 @@
1
- export {
2
- TabsCollapsibleResponsive as TabsCollapsible,
3
- TabsCollapsibleResponsiveProps as TabsCollapsibleProps,
4
- } from './components/tabs/Component.collapsible.responsive';
5
- export * from './components/tabs/Component.collabsible.desktop';
6
- export * from './components/tabs/Component.collapsible.mobile';
7
- export * from './components/primary-tablist/Component.collapsible.responsive';
8
- export * from './components/primary-tablist/Component.collapsible.desktop';
9
- export * from './components/primary-tablist/Component.collapsible.mobile';
1
+ export { TabsCollapsible, TabsCollapsibleProps } from './components/tabs/Component.collapsible';
10
2
  export * from './components/tab';
@@ -10,17 +10,16 @@ import {
10
10
 
11
11
  import { useTablistTitles } from '../../hooks/use-tablist-titles';
12
12
  import { createSyntheticMouseEvent } from '../../synthetic-events';
13
- import { Styles, TabListProps } from '../../typings';
13
+ import { TabListProps } from '../../typings';
14
14
  import { Title } from '../title';
15
15
 
16
- const DEFAULT_STYLES = {};
16
+ import styles from './index.module.css';
17
17
 
18
18
  export const CollapsiblePrimaryTabList = ({
19
- size,
19
+ size = 'm',
20
20
  className,
21
21
  containerClassName,
22
22
  titles = [],
23
- styles = DEFAULT_STYLES,
24
23
  selectedId = titles.length ? titles[0].id : undefined,
25
24
  collapsedTabsIds,
26
25
  fullWidthScroll,
@@ -28,7 +27,7 @@ export const CollapsiblePrimaryTabList = ({
28
27
  dataTestId,
29
28
  breakpoint = 1024,
30
29
  defaultMatchMediaValue,
31
- }: TabListProps & Styles) => {
30
+ }: TabListProps) => {
32
31
  const lineRef = useRef<HTMLDivElement>(null);
33
32
 
34
33
  const { containerRef, addonRef, tablistTitles, selectedTab, getTabListItemProps } =
@@ -61,7 +60,7 @@ export const CollapsiblePrimaryTabList = ({
61
60
 
62
61
  return options;
63
62
  }, []),
64
- [tablistTitles, styles],
63
+ [tablistTitles],
65
64
  );
66
65
 
67
66
  const collapsedAddonsLength = tablistTitles.filter(
@@ -112,7 +111,7 @@ export const CollapsiblePrimaryTabList = ({
112
111
  <Badge view='count' content={collapsedAddonsLength} />
113
112
  ) : null
114
113
  }
115
- size='l'
114
+ size='m'
116
115
  view='ghost'
117
116
  label='Ещё'
118
117
  popoverPosition='bottom-end'
@@ -7,5 +7,5 @@ import { PrimaryTabList } from './Component';
7
7
  import styles from './index.module.css';
8
8
 
9
9
  export const PrimaryTabListDesktop = ({ size = 'm', ...restProps }: TabListProps) => (
10
- <PrimaryTabList {...restProps} size={size} styles={styles} />
10
+ <PrimaryTabList {...restProps} size={size} styles={styles} platform='desktop' />
11
11
  );
@@ -16,5 +16,10 @@ const styles = {
16
16
  export type PrimaryTabListMobileProps = Omit<TabListProps, 'size' | 'collapsedTabsIds'>;
17
17
 
18
18
  export const PrimaryTabListMobile = ({ className, ...restProps }: PrimaryTabListMobileProps) => (
19
- <PrimaryTabList {...restProps} styles={styles} className={cn(className, styles.mobile)} />
19
+ <PrimaryTabList
20
+ {...restProps}
21
+ styles={styles}
22
+ className={cn(className, styles.mobile)}
23
+ platform='mobile'
24
+ />
20
25
  );
@@ -4,7 +4,7 @@ import cn from 'classnames';
4
4
  import { KeyboardFocusable } from '@alfalab/core-components-keyboard-focusable';
5
5
 
6
6
  import { useTabs } from '../../hooks/use-tabs';
7
- import { Styles, TabListProps } from '../../typings';
7
+ import { PlatformProps, Styles, TabListProps } from '../../typings';
8
8
  import { ScrollableContainer } from '../scrollable-container';
9
9
  import { Title } from '../title';
10
10
 
@@ -19,7 +19,8 @@ export const PrimaryTabList = ({
19
19
  fullWidthScroll,
20
20
  onChange,
21
21
  dataTestId,
22
- }: TabListProps & Styles) => {
22
+ platform,
23
+ }: TabListProps & Styles & PlatformProps) => {
23
24
  const lineRef = useRef<HTMLDivElement>(null);
24
25
 
25
26
  const { selectedTab, focusedTab, getTabListItemProps } = useTabs({
@@ -65,6 +66,9 @@ export const PrimaryTabList = ({
65
66
  activeChild={focusedTab || selectedTab}
66
67
  containerClassName={containerClassName}
67
68
  fullWidthScroll={fullWidthScroll}
69
+ view='primary'
70
+ size={size}
71
+ platform={platform}
68
72
  >
69
73
  {renderContent()}
70
74
  </ScrollableContainer>
@@ -81,6 +81,10 @@
81
81
  transition: transform 0.2s ease, width 0.2s ease;
82
82
  }
83
83
 
84
+ .option {
85
+ color: var(--color-light-text-primary);
86
+ }
87
+
84
88
  /* sizes */
85
89
 
86
90
  .s,
@@ -0,0 +1,78 @@
1
+ import React, { forwardRef, RefObject, useEffect, useState } from 'react';
2
+ import cn from 'classnames';
3
+ import _debounce from 'lodash.debounce';
4
+
5
+ import { IconButton } from '@alfalab/core-components-icon-button';
6
+ import { ChevronLeftMIcon } from '@alfalab/icons-glyph/ChevronLeftMIcon';
7
+ import { ChevronRightMIcon } from '@alfalab/icons-glyph/ChevronRightMIcon';
8
+
9
+ import { TabsProps } from '../../typings';
10
+
11
+ import { getDisabledState, scrollIntoFirstTab, scrollIntoLastTab } from './utils';
12
+
13
+ import styles from './index.module.css';
14
+
15
+ type ScrollControlsProps = {
16
+ view: Exclude<TabsProps['view'], undefined>;
17
+ size: TabsProps['size'];
18
+ containerRef: RefObject<HTMLDivElement>;
19
+ };
20
+
21
+ export const ScrollControls = forwardRef<HTMLDivElement, ScrollControlsProps>(
22
+ ({ containerRef, view, size: sizeProp }, ref) => {
23
+ const container = containerRef.current;
24
+ const [disabledState, updateDisabledState] = useState(() => getDisabledState(container));
25
+
26
+ useEffect(() => {
27
+ const handleScroll = _debounce(
28
+ () => updateDisabledState(getDisabledState(container)),
29
+ 100,
30
+ { leading: true, maxWait: 100, trailing: true },
31
+ );
32
+
33
+ container?.addEventListener('scroll', handleScroll);
34
+
35
+ return () => container?.removeEventListener('scroll', handleScroll);
36
+ }, [container]);
37
+
38
+ const getSize = () => {
39
+ if (view === 'primary') {
40
+ return sizeProp === 'xl' ? 'xs' : 'xxs';
41
+ }
42
+
43
+ return sizeProp && ['s', 'm', 'l', 'xl'].includes(sizeProp) ? 's' : 'xs';
44
+ };
45
+
46
+ const handleScrollLeft = () => scrollIntoFirstTab(container);
47
+
48
+ const handleScrollRight = () => scrollIntoLastTab(container);
49
+
50
+ const commonButtonProps = {
51
+ className: styles.button,
52
+ size: getSize(),
53
+ view: 'secondary',
54
+ } as const;
55
+
56
+ return (
57
+ <div
58
+ ref={ref}
59
+ className={cn(styles.component, styles[view], sizeProp && styles[sizeProp], {
60
+ [styles.borderVisible]: !disabledState.toRight,
61
+ })}
62
+ >
63
+ <IconButton
64
+ {...commonButtonProps}
65
+ icon={ChevronLeftMIcon}
66
+ disabled={disabledState.toLeft}
67
+ onClick={handleScrollLeft}
68
+ />
69
+ <IconButton
70
+ {...commonButtonProps}
71
+ icon={ChevronRightMIcon}
72
+ disabled={disabledState.toRight}
73
+ onClick={handleScrollRight}
74
+ />
75
+ </div>
76
+ );
77
+ },
78
+ );
@@ -0,0 +1,68 @@
1
+ @import '@alfalab/core-components-themes/src/default.css';
2
+ @import '../../vars.css';
3
+
4
+ .component {
5
+ position: relative;
6
+ display: flex;
7
+ flex-shrink: 0;
8
+
9
+ &:before {
10
+ content: '';
11
+ display: block;
12
+ position: absolute;
13
+ top: 0;
14
+ left: 0;
15
+ width: 1px;
16
+ background-color: transparent;
17
+ transition: background-color 0.3s ease;
18
+ }
19
+ }
20
+
21
+ .borderVisible:before {
22
+ background-color: var(--color-light-specialbg-tertiary-transparent);
23
+ }
24
+
25
+ .primary {
26
+ align-items: flex-start;
27
+ justify-content: flex-end;
28
+
29
+ &:after {
30
+ content: '';
31
+ display: block;
32
+ position: absolute;
33
+ bottom: 1px;
34
+ height: 1px;
35
+ width: 100%;
36
+ background-color: var(--primary-tablist-bottom-border-color);
37
+ }
38
+
39
+ &:before {
40
+ bottom: 2px;
41
+ }
42
+
43
+ .button:first-child {
44
+ padding-left: var(--gap-xs);
45
+ margin-right: var(--gap-xs);
46
+ }
47
+
48
+ &.xl .button:first-child {
49
+ margin-right: var(--gap-2xs);
50
+ }
51
+ }
52
+
53
+ .secondary {
54
+ align-items: center;
55
+ justify-content: center;
56
+
57
+ &:before {
58
+ bottom: 0;
59
+ }
60
+
61
+ &.xs {
62
+ width: 76px;
63
+
64
+ .button:first-child {
65
+ margin-right: var(--gap-2xs);
66
+ }
67
+ }
68
+ }
@@ -0,0 +1 @@
1
+ export { ScrollControls } from './Component';
@@ -0,0 +1,60 @@
1
+ const ADDITIONAL_OFFSET = 15;
2
+
3
+ function getTabs(container: HTMLDivElement) {
4
+ return Array.from(container.querySelectorAll('button[role="tab"]')) as HTMLButtonElement[];
5
+ }
6
+
7
+ function findLastVisibleTab(container: HTMLDivElement) {
8
+ const tabs = getTabs(container);
9
+
10
+ return tabs.reduce((res, tab) => {
11
+ if (tab.offsetLeft + ADDITIONAL_OFFSET < container.clientWidth + container.scrollLeft) {
12
+ return tab;
13
+ }
14
+
15
+ return res;
16
+ }, tabs[0]);
17
+ }
18
+
19
+ function findFirstVisibleTab(container: HTMLDivElement) {
20
+ const tabs = getTabs(container);
21
+
22
+ return tabs.reduceRight((res, tab) => {
23
+ if (tab.offsetLeft + tab.clientWidth > container.scrollLeft + ADDITIONAL_OFFSET) {
24
+ return tab;
25
+ }
26
+
27
+ return res;
28
+ }, tabs[tabs.length - 1]);
29
+ }
30
+
31
+ export function scrollIntoLastTab(container: HTMLDivElement | null) {
32
+ if (!container) return;
33
+
34
+ findLastVisibleTab(container).scrollIntoView({
35
+ behavior: 'smooth',
36
+ block: 'nearest',
37
+ inline: 'start',
38
+ });
39
+ }
40
+
41
+ export function scrollIntoFirstTab(container: HTMLDivElement | null) {
42
+ if (!container) return;
43
+
44
+ findFirstVisibleTab(container).scrollIntoView({
45
+ behavior: 'smooth',
46
+ block: 'nearest',
47
+ inline: 'end',
48
+ });
49
+ }
50
+
51
+ export function getDisabledState(container: HTMLDivElement | null) {
52
+ if (!container) return { toLeft: false, toRight: false };
53
+ const scrollOffset = 2;
54
+
55
+ const toLeft = container.scrollLeft <= scrollOffset;
56
+ const toRight =
57
+ container.scrollLeft + container.clientWidth >= container.scrollWidth - scrollOffset;
58
+
59
+ return { toLeft, toRight };
60
+ }
@@ -1,17 +1,23 @@
1
- import React, { ReactNode, useEffect } from 'react';
1
+ import React, { ReactNode, useEffect, useRef, useState } from 'react';
2
2
  import cn from 'classnames';
3
3
  import computeScrollIntoView from 'compute-scroll-into-view';
4
4
 
5
- import { TabsProps } from '../../typings';
5
+ import { PlatformProps, TabsProps } from '../../typings';
6
+ import { ScrollControls } from '../scroll-controls';
6
7
 
7
8
  import styles from './index.module.css';
8
9
 
9
10
  /**
10
11
  * Дополнительная прокрутка при клике на не поместившийся таб
11
12
  */
12
- const ADDITIONAL_SCROLLLEFT_VALUE = 40;
13
+ const ADDITIONAL_SCROLL_LEFT_VALUE = 50;
13
14
 
14
15
  export type ScrollableContainerProps = {
16
+ /**
17
+ * Дополнительный класс враппера контейнера
18
+ */
19
+ containerWrapperClassName?: string;
20
+
15
21
  /**
16
22
  * Дополнительный класс контейнера
17
23
  */
@@ -26,20 +32,48 @@ export type ScrollableContainerProps = {
26
32
  * Активный элемент (всегда будет в видимой области)
27
33
  */
28
34
  activeChild: HTMLElement | null;
35
+
36
+ /**
37
+ * Внешний вид заголовков табов
38
+ */
39
+ view: Exclude<TabsProps['view'], undefined>;
40
+
41
+ /**
42
+ * Размер
43
+ */
44
+ size: TabsProps['size'];
45
+ };
46
+
47
+ const isOverflown = (
48
+ { clientWidth, scrollWidth }: HTMLDivElement,
49
+ controlsNode: HTMLDivElement | null,
50
+ ) => {
51
+ const controlsWidth = controlsNode?.offsetWidth || 0;
52
+
53
+ return scrollWidth > clientWidth + controlsWidth;
29
54
  };
30
55
 
31
56
  export const ScrollableContainer = ({
57
+ containerWrapperClassName,
32
58
  containerClassName,
33
59
  children,
34
60
  activeChild,
35
61
  fullWidthScroll,
36
- }: ScrollableContainerProps & Pick<TabsProps, 'fullWidthScroll'>) => {
62
+ view,
63
+ size,
64
+ platform,
65
+ }: ScrollableContainerProps & Pick<TabsProps, 'fullWidthScroll'> & PlatformProps) => {
66
+ const containerRef = useRef<HTMLDivElement>(null);
67
+ const controlsRef = useRef<HTMLDivElement>(null);
68
+ const [overflown, setOverflown] = useState(false);
69
+
37
70
  useEffect(() => {
38
71
  if (activeChild) {
39
72
  const actions = computeScrollIntoView(activeChild, {
40
73
  scrollMode: 'if-needed',
41
74
  block: 'nearest',
42
75
  inline: 'nearest',
76
+ boundary: (parent) => !parent.isSameNode(containerRef.current),
43
77
  });
44
78
 
45
79
  // TODO: animate?
@@ -47,19 +81,54 @@ export const ScrollableContainer = ({
47
81
  // eslint-disable-next-line no-param-reassign
48
82
  el.scrollLeft =
49
83
  el.scrollLeft > left
50
- ? left - ADDITIONAL_SCROLLLEFT_VALUE
51
- : left + ADDITIONAL_SCROLLLEFT_VALUE;
84
+ ? left - ADDITIONAL_SCROLL_LEFT_VALUE
85
+ : left + ADDITIONAL_SCROLL_LEFT_VALUE;
52
86
  });
53
87
  }
54
88
  }, [activeChild]);
55
89
 
90
+ useEffect(() => {
91
+ const scrollableNode = containerRef.current;
92
+ const tabsContainer = scrollableNode?.firstElementChild;
93
+
94
+ if (platform === 'desktop' && scrollableNode && tabsContainer && window.ResizeObserver) {
95
+ const observerCb = () => {
96
+ if (isOverflown(scrollableNode, controlsRef.current)) {
97
+ setOverflown(true);
98
+ } else {
99
+ setOverflown(false);
100
+ }
101
+ };
102
+
103
+ const observer = new ResizeObserver(observerCb);
104
+
105
+ observer.observe(scrollableNode);
106
+ observer.observe(tabsContainer);
107
+
108
+ return () => observer.disconnect();
109
+ }
110
+
111
+ return () => {};
112
+ }, [platform]);
113
+
56
114
  return (
57
- <div
58
- className={cn(styles.container, containerClassName, {
59
- [styles.fullWidthScroll]: fullWidthScroll,
60
- })}
61
- >
62
- {children}
115
+ <div className={cn(styles.scrollableContainerWrapper, containerWrapperClassName)}>
116
+ <div
117
+ ref={containerRef}
118
+ className={cn(styles.container, containerClassName, {
119
+ [styles.fullWidthScroll]: fullWidthScroll,
120
+ })}
121
+ >
122
+ {children}
123
+ </div>
124
+ {overflown && platform === 'desktop' ? (
125
+ <ScrollControls
126
+ ref={controlsRef}
127
+ containerRef={containerRef}
128
+ view={view}
129
+ size={size}
130
+ />
131
+ ) : null}
63
132
  </div>
64
133
  );
65
134
  };
@@ -1,12 +1,17 @@
1
1
  @import '@alfalab/core-components-themes/src/default.css';
2
2
  @import '../../vars.css';
3
3
 
4
+ .scrollableContainerWrapper {
5
+ display: flex;
6
+ }
7
+
4
8
  .container {
5
9
  position: relative;
6
10
  overflow-x: auto;
7
11
  overflow-y: hidden;
8
12
  scroll-behavior: smooth;
9
13
  scrollbar-width: none;
14
+ flex: 1;
10
15
 
11
16
  /* focus-outline fix */
12
17
  margin: var(--gap-2xs-neg) 0 var(--gap-2xs-neg) var(--gap-2xs-neg);
@@ -22,5 +27,6 @@
22
27
  }
23
28
 
24
29
  .fullWidthScroll {
25
- margin: 0 var(--gap-m-neg);
30
+ padding-left: 0;
31
+ margin: var(--gap-2xs-neg) var(--gap-m-neg);
26
32
  }
@@ -20,5 +20,6 @@ export const SecondaryTabListDesktop = ({
20
20
  size={size}
21
21
  styles={commonStyles}
22
22
  tagSize={size}
23
+ platform='desktop'
23
24
  />
24
25
  );
@@ -15,10 +15,11 @@ const styles = {
15
15
  ...mobileStyles,
16
16
  };
17
17
 
18
- export type SecondaryTabListMobileProps = Omit<SecondaryTabListProps, 'size' | 'tagSize'>;
18
+ export type SecondaryTabListMobileProps = Omit<SecondaryTabListProps, 'tagSize'>;
19
19
 
20
20
  export const SecondaryTabListMobile = ({
21
21
  className,
22
+ size,
22
23
  ...restProps
23
24
  }: SecondaryTabListMobileProps) => (
24
25
  <SecondaryTabList
@@ -26,6 +27,7 @@ export const SecondaryTabListMobile = ({
26
27
  TagComponent={TagMobile}
27
28
  styles={styles}
28
29
  className={cn(className, styles.mobile)}
29
- tagSize='xs'
30
+ tagSize={size}
31
+ platform='mobile'
30
32
  />
31
33
  );
@@ -8,7 +8,6 @@ import { SecondaryTabListDesktop } from './Component.desktop';
8
8
  import { SecondaryTabListMobile } from './Component.mobile';
9
9
 
10
10
  export const SecondaryTabListResponsive = ({
11
- size,
12
11
  defaultMatchMediaValue,
13
12
  fullWidthScroll,
14
13
  breakpoint = 1024,
@@ -17,7 +16,7 @@ export const SecondaryTabListResponsive = ({
17
16
  const [isDesktop] = useMatchMedia(`(min-width: ${breakpoint}px)`, defaultMatchMediaValue);
18
17
 
19
18
  return isDesktop ? (
20
- <SecondaryTabListDesktop size={size} {...restProps} />
19
+ <SecondaryTabListDesktop {...restProps} />
21
20
  ) : (
22
21
  <SecondaryTabListMobile fullWidthScroll={fullWidthScroll} {...restProps} />
23
22
  );
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import cn from 'classnames';
3
3
 
4
4
  import { useTabs } from '../../hooks/use-tabs';
5
- import { SecondaryTabListProps, Styles } from '../../typings';
5
+ import { PlatformProps, SecondaryTabListProps, Styles } from '../../typings';
6
6
  import { ScrollableContainer } from '../scrollable-container';
7
7
 
8
8
  export const SecondaryTabList = ({
@@ -18,7 +18,10 @@ export const SecondaryTabList = ({
18
18
  onChange,
19
19
  dataTestId,
20
20
  TagComponent,
21
- }: SecondaryTabListProps & Styles) => {
21
+ platform,
22
+ tagShape,
23
+ tagView,
24
+ }: SecondaryTabListProps & Styles & PlatformProps) => {
22
25
  const { focusedTab, selectedTab, getTabListItemProps } = useTabs({
23
26
  titles,
24
27
  selectedId,
@@ -42,6 +45,8 @@ export const SecondaryTabList = ({
42
45
  return (
43
46
  <TagComponent
44
47
  {...getTabListItemProps(index)}
48
+ shape={tagShape}
49
+ view={tagView}
45
50
  key={item.id}
46
51
  className={cn(styles.title, item.toggleClassName)}
47
52
  checked={item.id === selectedId}
@@ -61,6 +66,9 @@ export const SecondaryTabList = ({
61
66
  activeChild={focusedTab || selectedTab}
62
67
  containerClassName={containerClassName}
63
68
  fullWidthScroll={fullWidthScroll}
69
+ view='secondary'
70
+ size={size}
71
+ platform={platform}
64
72
  >
65
73
  {renderContent()}
66
74
  </ScrollableContainer>