@alfalab/core-components-select 19.1.10 → 19.2.0-alfasans

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 (257) hide show
  1. package/components/arrow/index.css +4 -4
  2. package/components/arrow/index.module.css.js +1 -1
  3. package/components/base-checkmark/index.css +9 -9
  4. package/components/base-checkmark/index.module.css.js +1 -1
  5. package/components/base-option/index.css +19 -17
  6. package/components/base-option/index.module.css.js +1 -1
  7. package/components/base-select/Component.js +36 -49
  8. package/components/base-select/Component.js.map +1 -1
  9. package/components/base-select/index.css +70 -20
  10. package/components/base-select/index.module.css.js +1 -1
  11. package/components/base-select/index.module.css.js.map +1 -1
  12. package/components/base-select/mobile.css +12 -11
  13. package/components/base-select/mobile.module.css.js +1 -1
  14. package/components/base-select/mobile.module.css.js.map +1 -1
  15. package/components/checkmark/index.css +11 -11
  16. package/components/checkmark/index.module.css.js +1 -1
  17. package/components/checkmark-mobile/index.css +6 -6
  18. package/components/checkmark-mobile/index.module.css.js +1 -1
  19. package/components/clear-button/index.css +4 -4
  20. package/components/clear-button/index.module.css.js +1 -1
  21. package/components/field/index.css +22 -18
  22. package/components/field/index.module.css.js +1 -1
  23. package/components/footer/index.css +4 -4
  24. package/components/footer/index.module.css.js +1 -1
  25. package/components/optgroup/index.css +8 -7
  26. package/components/optgroup/index.module.css.js +1 -1
  27. package/components/option/desktop/index.css +28 -22
  28. package/components/option/desktop/index.module.css.js +1 -1
  29. package/components/option/desktop/index.module.css.js.map +1 -1
  30. package/components/option/mobile/index.css +25 -19
  31. package/components/option/mobile/index.module.css.js +1 -1
  32. package/components/option/mobile/index.module.css.js.map +1 -1
  33. package/components/options-list/Component.d.ts +4 -0
  34. package/components/options-list/Component.js +32 -53
  35. package/components/options-list/Component.js.map +1 -1
  36. package/components/options-list/index.css +13 -33
  37. package/components/options-list/index.module.css.js +1 -1
  38. package/components/options-list/index.module.css.js.map +1 -1
  39. package/components/search/index.css +1 -1
  40. package/components/search/index.module.css.js +1 -1
  41. package/components/virtual-options-list/Component.d.ts +4 -0
  42. package/components/virtual-options-list/Component.js +61 -48
  43. package/components/virtual-options-list/Component.js.map +1 -1
  44. package/cssm/components/base-option/index.module.css +5 -3
  45. package/cssm/components/base-select/Component.js +36 -49
  46. package/cssm/components/base-select/Component.js.map +1 -1
  47. package/cssm/components/base-select/index.module.css +61 -11
  48. package/cssm/components/base-select/mobile.module.css +1 -0
  49. package/cssm/components/field/index.module.css +9 -5
  50. package/cssm/components/optgroup/index.module.css +4 -3
  51. package/cssm/components/option/desktop/index.module.css +9 -3
  52. package/cssm/components/option/mobile/index.module.css +9 -3
  53. package/cssm/components/options-list/Component.d.ts +4 -0
  54. package/cssm/components/options-list/Component.js +32 -53
  55. package/cssm/components/options-list/Component.js.map +1 -1
  56. package/cssm/components/options-list/index.module.css +6 -26
  57. package/cssm/components/virtual-options-list/Component.d.ts +4 -0
  58. package/cssm/components/virtual-options-list/Component.js +61 -48
  59. package/cssm/components/virtual-options-list/Component.js.map +1 -1
  60. package/cssm/presets/useSelectWithApply/hook.d.ts +12 -0
  61. package/cssm/presets/useSelectWithApply/options-list-with-apply/Component.d.ts +4 -0
  62. package/cssm/presets/useSelectWithApply/options-list-with-apply/footer/index.module.css +0 -5
  63. package/cssm/presets/useSelectWithApply/options-list-with-apply/header/index.module.css +9 -6
  64. package/cssm/shared/index.js +0 -1
  65. package/cssm/shared/index.js.map +1 -1
  66. package/cssm/typings.d.ts +21 -1
  67. package/cssm/utils.d.ts +1 -6
  68. package/cssm/utils.js +19 -28
  69. package/cssm/utils.js.map +1 -1
  70. package/esm/components/arrow/index.css +4 -4
  71. package/esm/components/arrow/index.module.css.js +1 -1
  72. package/esm/components/base-checkmark/index.css +9 -9
  73. package/esm/components/base-checkmark/index.module.css.js +1 -1
  74. package/esm/components/base-option/index.css +19 -17
  75. package/esm/components/base-option/index.module.css.js +1 -1
  76. package/esm/components/base-select/Component.js +37 -50
  77. package/esm/components/base-select/Component.js.map +1 -1
  78. package/esm/components/base-select/index.css +70 -20
  79. package/esm/components/base-select/index.module.css.js +1 -1
  80. package/esm/components/base-select/index.module.css.js.map +1 -1
  81. package/esm/components/base-select/mobile.css +12 -11
  82. package/esm/components/base-select/mobile.module.css.js +1 -1
  83. package/esm/components/base-select/mobile.module.css.js.map +1 -1
  84. package/esm/components/checkmark/index.css +11 -11
  85. package/esm/components/checkmark/index.module.css.js +1 -1
  86. package/esm/components/checkmark-mobile/index.css +6 -6
  87. package/esm/components/checkmark-mobile/index.module.css.js +1 -1
  88. package/esm/components/clear-button/index.css +4 -4
  89. package/esm/components/clear-button/index.module.css.js +1 -1
  90. package/esm/components/field/index.css +22 -18
  91. package/esm/components/field/index.module.css.js +1 -1
  92. package/esm/components/footer/index.css +4 -4
  93. package/esm/components/footer/index.module.css.js +1 -1
  94. package/esm/components/optgroup/index.css +8 -7
  95. package/esm/components/optgroup/index.module.css.js +1 -1
  96. package/esm/components/option/desktop/index.css +28 -22
  97. package/esm/components/option/desktop/index.module.css.js +1 -1
  98. package/esm/components/option/desktop/index.module.css.js.map +1 -1
  99. package/esm/components/option/mobile/index.css +25 -19
  100. package/esm/components/option/mobile/index.module.css.js +1 -1
  101. package/esm/components/option/mobile/index.module.css.js.map +1 -1
  102. package/esm/components/options-list/Component.d.ts +4 -0
  103. package/esm/components/options-list/Component.js +33 -54
  104. package/esm/components/options-list/Component.js.map +1 -1
  105. package/esm/components/options-list/index.css +13 -33
  106. package/esm/components/options-list/index.module.css.js +1 -1
  107. package/esm/components/options-list/index.module.css.js.map +1 -1
  108. package/esm/components/search/index.css +1 -1
  109. package/esm/components/search/index.module.css.js +1 -1
  110. package/esm/components/virtual-options-list/Component.d.ts +4 -0
  111. package/esm/components/virtual-options-list/Component.js +63 -49
  112. package/esm/components/virtual-options-list/Component.js.map +1 -1
  113. package/esm/mobile/modal.mobile.css +1 -1
  114. package/esm/mobile/modal.mobile.module.css.js +1 -1
  115. package/esm/presets/useSelectWithApply/hook.d.ts +12 -0
  116. package/esm/presets/useSelectWithApply/options-list-with-apply/Component.d.ts +4 -0
  117. package/esm/presets/useSelectWithApply/options-list-with-apply/footer/index.css +2 -7
  118. package/esm/presets/useSelectWithApply/options-list-with-apply/footer/index.module.css.js +1 -1
  119. package/esm/presets/useSelectWithApply/options-list-with-apply/footer/index.module.css.js.map +1 -1
  120. package/esm/presets/useSelectWithApply/options-list-with-apply/header/index.css +12 -9
  121. package/esm/presets/useSelectWithApply/options-list-with-apply/header/index.module.css.js +1 -1
  122. package/esm/presets/useSelectWithApply/options-list-with-apply/header/index.module.css.js.map +1 -1
  123. package/esm/presets/useSelectWithLoading/index.css +1 -1
  124. package/esm/presets/useSelectWithLoading/index.module.css.js +1 -1
  125. package/esm/shared/index.js +1 -1
  126. package/esm/typings.d.ts +21 -1
  127. package/esm/utils.d.ts +1 -6
  128. package/esm/utils.js +21 -29
  129. package/esm/utils.js.map +1 -1
  130. package/mobile/modal.mobile.css +1 -1
  131. package/mobile/modal.mobile.module.css.js +1 -1
  132. package/modern/components/arrow/index.css +4 -4
  133. package/modern/components/arrow/index.module.css.js +1 -1
  134. package/modern/components/base-checkmark/index.css +9 -9
  135. package/modern/components/base-checkmark/index.module.css.js +1 -1
  136. package/modern/components/base-option/index.css +19 -17
  137. package/modern/components/base-option/index.module.css.js +1 -1
  138. package/modern/components/base-select/Component.js +34 -47
  139. package/modern/components/base-select/Component.js.map +1 -1
  140. package/modern/components/base-select/index.css +70 -20
  141. package/modern/components/base-select/index.module.css.js +1 -1
  142. package/modern/components/base-select/index.module.css.js.map +1 -1
  143. package/modern/components/base-select/mobile.css +12 -11
  144. package/modern/components/base-select/mobile.module.css.js +1 -1
  145. package/modern/components/base-select/mobile.module.css.js.map +1 -1
  146. package/modern/components/checkmark/index.css +11 -11
  147. package/modern/components/checkmark/index.module.css.js +1 -1
  148. package/modern/components/checkmark-mobile/index.css +6 -6
  149. package/modern/components/checkmark-mobile/index.module.css.js +1 -1
  150. package/modern/components/clear-button/index.css +4 -4
  151. package/modern/components/clear-button/index.module.css.js +1 -1
  152. package/modern/components/field/index.css +22 -18
  153. package/modern/components/field/index.module.css.js +1 -1
  154. package/modern/components/footer/index.css +4 -4
  155. package/modern/components/footer/index.module.css.js +1 -1
  156. package/modern/components/optgroup/index.css +8 -7
  157. package/modern/components/optgroup/index.module.css.js +1 -1
  158. package/modern/components/option/desktop/index.css +28 -22
  159. package/modern/components/option/desktop/index.module.css.js +1 -1
  160. package/modern/components/option/desktop/index.module.css.js.map +1 -1
  161. package/modern/components/option/mobile/index.css +25 -19
  162. package/modern/components/option/mobile/index.module.css.js +1 -1
  163. package/modern/components/option/mobile/index.module.css.js.map +1 -1
  164. package/modern/components/options-list/Component.d.ts +4 -0
  165. package/modern/components/options-list/Component.js +29 -49
  166. package/modern/components/options-list/Component.js.map +1 -1
  167. package/modern/components/options-list/index.css +13 -33
  168. package/modern/components/options-list/index.module.css.js +1 -1
  169. package/modern/components/options-list/index.module.css.js.map +1 -1
  170. package/modern/components/search/index.css +1 -1
  171. package/modern/components/search/index.module.css.js +1 -1
  172. package/modern/components/virtual-options-list/Component.d.ts +4 -0
  173. package/modern/components/virtual-options-list/Component.js +59 -45
  174. package/modern/components/virtual-options-list/Component.js.map +1 -1
  175. package/modern/mobile/modal.mobile.css +1 -1
  176. package/modern/mobile/modal.mobile.module.css.js +1 -1
  177. package/modern/presets/useSelectWithApply/hook.d.ts +12 -0
  178. package/modern/presets/useSelectWithApply/options-list-with-apply/Component.d.ts +4 -0
  179. package/modern/presets/useSelectWithApply/options-list-with-apply/footer/index.css +2 -7
  180. package/modern/presets/useSelectWithApply/options-list-with-apply/footer/index.module.css.js +1 -1
  181. package/modern/presets/useSelectWithApply/options-list-with-apply/footer/index.module.css.js.map +1 -1
  182. package/modern/presets/useSelectWithApply/options-list-with-apply/header/index.css +12 -9
  183. package/modern/presets/useSelectWithApply/options-list-with-apply/header/index.module.css.js +1 -1
  184. package/modern/presets/useSelectWithApply/options-list-with-apply/header/index.module.css.js.map +1 -1
  185. package/modern/presets/useSelectWithLoading/index.css +1 -1
  186. package/modern/presets/useSelectWithLoading/index.module.css.js +1 -1
  187. package/modern/shared/index.js +1 -1
  188. package/modern/typings.d.ts +21 -1
  189. package/modern/utils.d.ts +1 -6
  190. package/modern/utils.js +21 -29
  191. package/modern/utils.js.map +1 -1
  192. package/moderncssm/components/base-option/index.module.css +2 -1
  193. package/moderncssm/components/base-select/Component.js +34 -47
  194. package/moderncssm/components/base-select/Component.js.map +1 -1
  195. package/moderncssm/components/base-select/index.module.css +67 -9
  196. package/moderncssm/components/base-select/mobile.module.css +1 -0
  197. package/moderncssm/components/field/index.module.css +6 -3
  198. package/moderncssm/components/optgroup/index.module.css +1 -1
  199. package/moderncssm/components/option/desktop/index.module.css +5 -1
  200. package/moderncssm/components/option/mobile/index.module.css +5 -1
  201. package/moderncssm/components/options-list/Component.d.ts +4 -0
  202. package/moderncssm/components/options-list/Component.js +29 -49
  203. package/moderncssm/components/options-list/Component.js.map +1 -1
  204. package/moderncssm/components/options-list/index.module.css +7 -32
  205. package/moderncssm/components/virtual-options-list/Component.d.ts +4 -0
  206. package/moderncssm/components/virtual-options-list/Component.js +59 -45
  207. package/moderncssm/components/virtual-options-list/Component.js.map +1 -1
  208. package/moderncssm/presets/useSelectWithApply/hook.d.ts +12 -0
  209. package/moderncssm/presets/useSelectWithApply/options-list-with-apply/Component.d.ts +4 -0
  210. package/moderncssm/presets/useSelectWithApply/options-list-with-apply/footer/index.module.css +0 -4
  211. package/moderncssm/presets/useSelectWithApply/options-list-with-apply/header/index.module.css +8 -6
  212. package/moderncssm/shared/index.js +1 -1
  213. package/moderncssm/typings.d.ts +21 -1
  214. package/moderncssm/utils.d.ts +1 -6
  215. package/moderncssm/utils.js +21 -29
  216. package/moderncssm/utils.js.map +1 -1
  217. package/package.json +15 -16
  218. package/presets/useSelectWithApply/hook.d.ts +12 -0
  219. package/presets/useSelectWithApply/options-list-with-apply/Component.d.ts +4 -0
  220. package/presets/useSelectWithApply/options-list-with-apply/footer/index.css +2 -7
  221. package/presets/useSelectWithApply/options-list-with-apply/footer/index.module.css.js +1 -1
  222. package/presets/useSelectWithApply/options-list-with-apply/footer/index.module.css.js.map +1 -1
  223. package/presets/useSelectWithApply/options-list-with-apply/header/index.css +12 -9
  224. package/presets/useSelectWithApply/options-list-with-apply/header/index.module.css.js +1 -1
  225. package/presets/useSelectWithApply/options-list-with-apply/header/index.module.css.js.map +1 -1
  226. package/presets/useSelectWithLoading/index.css +1 -1
  227. package/presets/useSelectWithLoading/index.module.css.js +1 -1
  228. package/shared/index.js +0 -1
  229. package/shared/index.js.map +1 -1
  230. package/src/components/base-select/Component.tsx +41 -55
  231. package/src/components/base-select/index.module.css +60 -8
  232. package/src/components/base-select/mobile.module.css +1 -0
  233. package/src/components/option/index.module.css +4 -0
  234. package/src/components/options-list/Component.tsx +54 -97
  235. package/src/components/options-list/index.module.css +7 -31
  236. package/src/components/virtual-options-list/Component.tsx +95 -72
  237. package/src/presets/useSelectWithApply/options-list-with-apply/footer/index.module.css +0 -4
  238. package/src/presets/useSelectWithApply/options-list-with-apply/header/index.module.css +4 -4
  239. package/src/typings.ts +26 -0
  240. package/src/utils.ts +30 -34
  241. package/src/vars.css +3 -0
  242. package/typings.d.ts +21 -1
  243. package/utils.d.ts +1 -6
  244. package/utils.js +19 -28
  245. package/utils.js.map +1 -1
  246. package/components/virtual-options-list/index.css +0 -83
  247. package/components/virtual-options-list/index.module.css.js +0 -8
  248. package/components/virtual-options-list/index.module.css.js.map +0 -1
  249. package/cssm/components/virtual-options-list/index.module.css +0 -83
  250. package/esm/components/virtual-options-list/index.css +0 -83
  251. package/esm/components/virtual-options-list/index.module.css.js +0 -6
  252. package/esm/components/virtual-options-list/index.module.css.js.map +0 -1
  253. package/modern/components/virtual-options-list/index.css +0 -83
  254. package/modern/components/virtual-options-list/index.module.css.js +0 -6
  255. package/modern/components/virtual-options-list/index.module.css.js.map +0 -1
  256. package/moderncssm/components/virtual-options-list/index.module.css +0 -81
  257. package/src/components/virtual-options-list/index.module.css +0 -77
@@ -1 +1 @@
1
- {"version":3,"file":"Component.js","sources":["../../../src/components/options-list/Component.tsx"],"sourcesContent":["import React, { forwardRef, useCallback, useRef, useState } from 'react';\nimport mergeRefs from 'react-merge-refs';\nimport cn from 'classnames';\n\nimport { Scrollbar } from '@alfalab/core-components-scrollbar';\n\nimport { DEFAULT_VISIBLE_OPTIONS } from '../../consts';\nimport { useNativeScrollbar } from '../../hooks/use-native-scrollbar';\nimport { type GroupShape, type OptionShape, type OptionsListProps } from '../../typings';\nimport { isGroup, useVisibleOptions } from '../../utils';\nimport { Optgroup as DefaultOptgroup } from '../optgroup';\n\nimport styles from './index.module.css';\n\nconst createCounter = () => {\n let count = 0;\n\n // eslint-disable-next-line no-plusplus\n return () => count++;\n};\n\nexport const OptionsList = forwardRef<HTMLDivElement, OptionsListProps>(\n (\n {\n size = 48,\n className,\n optionGroupClassName,\n footerClassName,\n scrollbarClassName,\n Option,\n getOptionProps,\n groupOptionProps = {},\n options = [],\n Optgroup = DefaultOptgroup,\n dataTestId,\n emptyPlaceholder,\n visibleOptions = DEFAULT_VISIBLE_OPTIONS,\n onScroll,\n open,\n header,\n footer,\n showFooter = true,\n optionsListWidth,\n nativeScrollbar: nativeScrollbarProp,\n flatOptions = [],\n setHighlightedIndex,\n selectedItems,\n search,\n setSelectedItems,\n multiple,\n limitDynamicOptionGroupSize = false,\n client,\n },\n ref,\n ) => {\n const [scrollTop, setScrollTop] = useState(true);\n const [scrollBottom, setScrollBottom] = useState(false);\n\n const nativeScrollbar = useNativeScrollbar({\n nativeScrollbar: nativeScrollbarProp,\n client,\n });\n\n const handleScroll = useCallback(\n (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {\n const scrolledToHeader = event.currentTarget.scrollTop <= 0;\n const scrolledToFooter =\n event.currentTarget.scrollHeight - event.currentTarget.offsetHeight <=\n event.currentTarget.scrollTop;\n\n setScrollTop(scrolledToHeader);\n setScrollBottom(scrolledToFooter);\n\n onScroll?.(event);\n },\n [onScroll],\n );\n\n const renderOption = (option: OptionShape, index: number) => (\n <Option key={option.key} {...getOptionProps(option, index)} />\n );\n\n const listRef = useRef<HTMLDivElement>(null);\n const scrollbarRef = useRef<HTMLDivElement>(null);\n const counter = createCounter();\n const renderGroup = (group: GroupShape) => {\n const groupSelectedItems = selectedItems?.filter(({ key: selectedItemKey }) =>\n group.options.some((option) => option.key === selectedItemKey),\n );\n const handleSelectedItems = (items: OptionShape[]) => {\n setSelectedItems(\n (\n selectedItems?.filter(\n ({ key: selectedItemKey }) =>\n !group.options.some((option) => option.key === selectedItemKey),\n ) ?? []\n ).concat(items),\n );\n };\n\n return (\n <Optgroup\n className={optionGroupClassName}\n label={group.label}\n key={group.label}\n size={size}\n options={group.options}\n selectedItems={groupSelectedItems}\n setSelectedItems={handleSelectedItems}\n search={search}\n multiple={multiple}\n {...groupOptionProps}\n >\n {group.options.map((option) => renderOption(option, counter()))}\n </Optgroup>\n );\n };\n\n const actualOptionsCount = limitDynamicOptionGroupSize && options.length > 0;\n\n const [measured, maxHeight] = useVisibleOptions({\n visibleOptions,\n listRef,\n open,\n options,\n actualOptionsCount,\n size: actualOptionsCount\n ? (() => {\n switch (typeof size) {\n case 'string':\n throw new Error(\n 'OptionsList with `limitDynamicOptionGroupSize` enabled needs a `size` with number type',\n );\n default:\n return size;\n }\n })()\n : undefined,\n });\n\n if (options.length === 0 && !emptyPlaceholder && !header && !footer) {\n return null;\n }\n\n const renderListItems = () => (\n <React.Fragment>\n {options.map((option) =>\n isGroup(option) ? renderGroup(option) : renderOption(option, counter()),\n )}\n\n {emptyPlaceholder && options.length === 0 && (\n <div className={styles.emptyPlaceholder}>{emptyPlaceholder}</div>\n )}\n </React.Fragment>\n );\n\n const renderWithCustomScrollbar = () => {\n const scrollableNodeProps = {\n onScroll: handleScroll,\n 'data-test-id': dataTestId,\n ref: ref as React.RefObject<HTMLDivElement>,\n };\n\n return (\n <Scrollbar\n className={cn(styles.scrollable, scrollbarClassName)}\n verticalBarClassName={cn(styles.verticalBar, {\n [styles.verticalBarWithHeader]: Boolean(header),\n [styles.verticalBarWithFooter]: Boolean(footer),\n })}\n ref={scrollbarRef}\n style={{ maxHeight }}\n horizontalAutoStretch={optionsListWidth === 'content'}\n scrollableNodeProps={scrollableNodeProps}\n contentNodeProps={{ ref: listRef }}\n maskProps={{\n /*\n * Для корректного подсчета высоты опций(иначе для optionsListWidth: 'field'\n * высота опции всегда будет равна высоте одной строчки)\n */\n className: cn({\n [styles.mask]: optionsListWidth === 'content' && !measured,\n }),\n }}\n >\n {renderListItems()}\n </Scrollbar>\n );\n };\n\n const renderWithNativeScrollbar = () => (\n <div\n className={cn(styles.scrollable, scrollbarClassName)}\n ref={mergeRefs([listRef, ref])}\n onScroll={handleScroll}\n style={{ maxHeight }}\n >\n {renderListItems()}\n </div>\n );\n\n const resetHighlightedIndex = () => setHighlightedIndex?.(-1);\n\n return (\n <div\n {...(nativeScrollbar && { 'data-test-id': dataTestId })}\n className={cn(styles.optionsList, styles[`size-${size}`], className)}\n >\n {header && (\n <div\n className={cn(styles.optionsListHeader, {\n [styles.headerHighlighted]: !scrollTop,\n })}\n onMouseEnter={resetHighlightedIndex}\n >\n {header}\n </div>\n )}\n\n {nativeScrollbar ? renderWithNativeScrollbar() : renderWithCustomScrollbar()}\n\n {showFooter && footer && (\n <div\n onMouseEnter={resetHighlightedIndex}\n className={cn(styles.optionsListFooter, footerClassName, {\n [styles.withBorder]:\n visibleOptions &&\n flatOptions.length > visibleOptions &&\n !scrollBottom,\n })}\n >\n {footer}\n </div>\n )}\n </div>\n );\n },\n);\n"],"names":["Optgroup","DefaultOptgroup"],"mappings":"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"}
1
+ {"version":3,"file":"Component.js","sources":["../../../src/components/options-list/Component.tsx"],"sourcesContent":["import React, { forwardRef, useRef, useState } from 'react';\nimport mergeRefs from 'react-merge-refs';\nimport cn from 'classnames';\n\nimport { ScrollbarPrivate } from '@alfalab/core-components-scrollbar-private';\n\nimport { DEFAULT_VISIBLE_OPTIONS } from '../../consts';\nimport { useNativeScrollbar } from '../../hooks/use-native-scrollbar';\nimport { type GroupShape, type OptionShape, type OptionsListProps } from '../../typings';\nimport { isGroup, useVisibleOptions } from '../../utils';\nimport { Optgroup as DefaultOptgroup } from '../optgroup';\n\nimport styles from './index.module.css';\n\nconst createCounter = () => {\n let count = 0;\n\n // eslint-disable-next-line no-plusplus\n return () => count++;\n};\n\nexport const OptionsList = forwardRef<HTMLDivElement, OptionsListProps>(\n (\n {\n size = 48,\n className,\n optionGroupClassName,\n footerClassName,\n scrollbarClassName,\n Option,\n getOptionProps,\n groupOptionProps = {},\n options = [],\n Optgroup = DefaultOptgroup,\n dataTestId,\n emptyPlaceholder,\n visibleOptions = DEFAULT_VISIBLE_OPTIONS,\n onScroll,\n open,\n header,\n footer,\n showFooter = true,\n nativeScrollbar: nativeScrollbarProp,\n flatOptions = [],\n setHighlightedIndex,\n selectedItems,\n search,\n setSelectedItems,\n multiple,\n limitDynamicOptionGroupSize = false,\n client,\n scrollableNodeClassName,\n contentNodeClassName,\n listNodeClassName,\n },\n ref,\n ) => {\n const actualOptionsCount = limitDynamicOptionGroupSize && options.length > 0;\n const listRef = useRef<HTMLDivElement>(null);\n const scrollableNodeRef = useRef<HTMLDivElement>(null);\n const [, maxHeight] = useVisibleOptions({\n visibleOptions,\n listRef,\n open,\n options,\n actualOptionsCount,\n size: actualOptionsCount ? size : undefined,\n });\n const noOptions = options.length === 0;\n const [scrollTop, setScrollTop] = useState(true);\n const [scrollBottom, setScrollBottom] = useState(false);\n\n const nativeScrollbar = useNativeScrollbar({\n nativeScrollbar: nativeScrollbarProp,\n client,\n });\n\n const handleScroll: React.MouseEventHandler<HTMLDivElement> = (event) => {\n const scrolledToHeader = event.currentTarget.scrollTop <= 0;\n const scrolledToFooter =\n event.currentTarget.scrollHeight - event.currentTarget.offsetHeight <=\n event.currentTarget.scrollTop;\n\n setScrollTop(scrolledToHeader);\n setScrollBottom(scrolledToFooter);\n\n onScroll?.(event);\n };\n\n const renderOption = (option: OptionShape, index: number) => (\n <Option key={option.key} {...getOptionProps(option, index)} />\n );\n\n const counter = createCounter();\n const renderGroup = (group: GroupShape) => {\n const groupSelectedItems = selectedItems?.filter(({ key: selectedItemKey }) =>\n group.options.some((option) => option.key === selectedItemKey),\n );\n const handleSelectedItems = (items: OptionShape[]) => {\n setSelectedItems(\n (\n selectedItems?.filter(\n ({ key: selectedItemKey }) =>\n !group.options.some((option) => option.key === selectedItemKey),\n ) ?? []\n ).concat(items),\n );\n };\n\n return (\n <Optgroup\n className={optionGroupClassName}\n label={group.label}\n key={group.label}\n size={size}\n options={group.options}\n selectedItems={groupSelectedItems}\n setSelectedItems={handleSelectedItems}\n search={search}\n multiple={multiple}\n {...groupOptionProps}\n >\n {group.options.map((option) => renderOption(option, counter()))}\n </Optgroup>\n );\n };\n\n if (options.length === 0 && !emptyPlaceholder && !header && !footer) {\n return null;\n }\n\n const resetHighlightedIndex = () => setHighlightedIndex?.(-1);\n\n return (\n <div\n {...(nativeScrollbar && { 'data-test-id': dataTestId })}\n className={cn(styles.optionsList, styles[`size-${size}`], className)}\n >\n {header && (\n <div\n className={cn(styles.optionsListHeader, {\n [styles.headerHighlighted]: !scrollTop,\n })}\n onMouseEnter={resetHighlightedIndex}\n >\n {header}\n </div>\n )}\n\n {!noOptions && (\n <ScrollbarPrivate\n native={nativeScrollbar}\n className={scrollbarClassName}\n style={{ maxHeight }}\n scrollableNodeProps={{\n ref: mergeRefs([scrollableNodeRef, ref]),\n onScroll: handleScroll,\n className: scrollableNodeClassName,\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n 'data-test-id': nativeScrollbar ? undefined : dataTestId,\n }}\n contentNodeProps={{ className: contentNodeClassName }}\n >\n <div className={listNodeClassName} ref={listRef}>\n {options.map((option) =>\n isGroup(option)\n ? renderGroup(option)\n : renderOption(option, counter()),\n )}\n </div>\n </ScrollbarPrivate>\n )}\n\n {emptyPlaceholder && noOptions && (\n <div className={styles.emptyPlaceholder}>{emptyPlaceholder}</div>\n )}\n\n {showFooter && footer && (\n <div\n onMouseEnter={resetHighlightedIndex}\n className={cn(styles.optionsListFooter, footerClassName, {\n [styles.withBorder]:\n visibleOptions &&\n flatOptions.length > visibleOptions &&\n !scrollBottom,\n })}\n >\n {footer}\n </div>\n )}\n </div>\n );\n },\n);\n"],"names":["Optgroup","DefaultOptgroup"],"mappings":"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"}
@@ -1,5 +1,4 @@
1
1
  :root {
2
- --select-options-list-scrollbar-gap: var(--gap-12);
3
2
  --select-options-list-empty-placeholder-color: var(--color-light-text-secondary);
4
3
  }
5
4
 
@@ -10,35 +9,9 @@
10
9
  position: relative;
11
10
  }
12
11
 
13
- .optionsList .scrollable {
14
- overflow: auto;
15
- width: 100%;
16
- }
17
-
18
- .optionsList .scrollable .verticalBar.verticalBar {
19
- top: var(--select-options-list-scrollbar-gap);
20
- height: calc(100% - 2 * var(--select-options-list-scrollbar-gap));
21
- }
22
-
23
- .optionsList .scrollable .verticalBar.verticalBar.verticalBarWithHeader {
24
- top: 0;
25
- height: calc(100% - var(--select-options-list-scrollbar-gap));
26
- }
27
-
28
- .optionsList .scrollable .verticalBar.verticalBar.verticalBarWithFooter {
29
- top: var(--select-options-list-scrollbar-gap);
30
- height: calc(100% - var(--select-options-list-scrollbar-gap));
31
- }
32
-
33
- .optionsList .scrollable .verticalBar.verticalBar.verticalBarWithHeader.verticalBarWithFooter {
34
- top: 0;
35
- height: 100%;
36
- }
37
-
38
12
  .optionsListHeader {
39
13
  box-sizing: border-box;
40
14
  border-bottom: 1px solid transparent;
41
- transition: border-color 0.2s ease;
42
15
  }
43
16
 
44
17
  .optionsListHeader.headerHighlighted {
@@ -50,22 +23,24 @@
50
23
  bottom: var(--gap-0);
51
24
  box-sizing: border-box;
52
25
  border-top: 1px solid transparent;
53
- transition: border-color 0.2s ease;
54
26
  }
55
27
 
56
28
  .optionsListFooter.withBorder {
57
29
  border-top-color: var(--color-light-neutral-300);
58
30
  }
59
31
 
60
- .mask {
61
- min-width: 4000px;
62
- }
63
-
64
32
  .emptyPlaceholder {
65
33
  padding: var(--gap-16) var(--gap-12);
66
34
  color: var(--select-options-list-empty-placeholder-color);
35
+ flex: 1;
67
36
  }
68
37
 
38
+ .size-64 .emptyPlaceholder,
69
39
  .size-72 .emptyPlaceholder {
70
40
  padding: var(--gap-24) var(--gap-16);
71
41
  }
42
+
43
+ .list {
44
+ will-change: transform;
45
+ height: auto;
46
+ }
@@ -33,4 +33,8 @@ export declare const VirtualOptionsList: React.ForwardRefExoticComponent<Pick<im
33
33
  search?: string;
34
34
  multiple?: boolean;
35
35
  limitDynamicOptionGroupSize?: import("../../typings").BaseSelectProps["limitDynamicOptionGroupSize"];
36
+ scrollableNodeClassName?: string;
37
+ contentNodeClassName?: string;
38
+ listNodeClassName?: string;
39
+ ctrlRef?: React.Ref<import("../../typings").OptionsListController>;
36
40
  } & React.RefAttributes<HTMLDivElement>>;
@@ -1,23 +1,39 @@
1
- import React, { forwardRef, useRef, useState, useEffect, useMemo } from 'react';
2
- import mergeRefs from 'react-merge-refs';
1
+ import React, { forwardRef, useRef, useState, useEffect, useImperativeHandle, useMemo } from 'react';
3
2
  import { useVirtual } from 'react-virtual';
4
3
  import cn from 'classnames';
5
- import { Scrollbar } from '@alfalab/core-components-scrollbar/moderncssm';
4
+ import { ScrollbarPrivate } from '@alfalab/core-components-scrollbar-private/moderncssm';
5
+ import { getElementWindow } from '@alfalab/core-components-shared/moderncssm';
6
6
  import { DEFAULT_VISIBLE_OPTIONS } from '../../consts.js';
7
7
  import { useNativeScrollbar } from '../../hooks/use-native-scrollbar.js';
8
- import { usePrevious, lastIndexOf, useVirtualVisibleOptions, isGroup } from '../../utils.js';
8
+ import { usePrevious, useVirtualVisibleOptions, isGroup } from '../../utils.js';
9
9
  import { Optgroup } from '../optgroup/Component.js';
10
- import styles from './index.module.css';
10
+ import styles from '../options-list/index.module.css';
11
11
 
12
- const VirtualOptionsList = forwardRef(({ size = 48, flatOptions = [], highlightedIndex = -1, optionGroupClassName, className, getOptionProps, groupOptionProps = {}, Option, open, options = [], Optgroup: Optgroup$1 = Optgroup, dataTestId, emptyPlaceholder, visibleOptions = DEFAULT_VISIBLE_OPTIONS, header, footer, showFooter = true, optionsListWidth, onScroll, nativeScrollbar: nativeScrollbarProp, setHighlightedIndex, selectedItems, setSelectedItems, search, multiple, scrollbarClassName, client, }, ref) => {
12
+ const VirtualOptionsList = forwardRef(({ size = 48, flatOptions = [], highlightedIndex = -1, optionGroupClassName, className, getOptionProps, groupOptionProps = {}, Option, open, options = [], Optgroup: Optgroup$1 = Optgroup, dataTestId, emptyPlaceholder, visibleOptions = DEFAULT_VISIBLE_OPTIONS, header, footer, showFooter = true, onScroll, nativeScrollbar: nativeScrollbarProp, setHighlightedIndex, selectedItems, setSelectedItems, search, multiple, scrollbarClassName, client, scrollableNodeClassName, contentNodeClassName, listNodeClassName, footerClassName, ctrlRef, }, ref) => {
13
13
  const listRef = useRef(null);
14
- const parentRef = useRef(null);
15
- const scrollbarRef = useRef(null);
14
+ const scrollableNodeRef = useRef(null);
15
+ const noOptions = options.length === 0;
16
+ const [scrollTop, setScrollTop] = useState(true);
17
+ const [scrollBottom, setScrollBottom] = useState(false);
16
18
  const [visibleOptionsInvalidateKey, setVisibleOptionsInvalidateKey] = useState('');
17
19
  const prevHighlightedIndex = usePrevious(highlightedIndex) || -1;
18
20
  const rowVirtualizer = useVirtual({
21
+ scrollToFn(offset, defaultScrollToFn) {
22
+ let delta = 0;
23
+ const list = listRef.current;
24
+ if (list) {
25
+ const win = getElementWindow(list);
26
+ delta = ['::before', '::after']
27
+ .map((pseudo) => {
28
+ const { paddingTop } = win.getComputedStyle(list, pseudo);
29
+ return parseFloat(paddingTop) || 0;
30
+ })
31
+ .reduce((a, b) => a + b);
32
+ }
33
+ defaultScrollToFn?.(offset === 0 ? offset : offset + delta);
34
+ },
19
35
  size: flatOptions.length,
20
- parentRef: (ref || parentRef),
36
+ parentRef: ref || scrollableNodeRef,
21
37
  overscan: 15,
22
38
  });
23
39
  const nativeScrollbar = useNativeScrollbar({
@@ -31,20 +47,12 @@ const VirtualOptionsList = forwardRef(({ size = 48, flatOptions = [], highlighte
31
47
  }
32
48
  // eslint-disable-next-line react-hooks/exhaustive-deps
33
49
  }, [open]);
34
- // Скролл к пункту, которого нет на экране
35
- useEffect(() => {
36
- if (highlightedIndex === -1)
37
- return;
38
- if (!rowVirtualizer.virtualItems.some((option) => option.index === highlightedIndex)) {
39
- rowVirtualizer.scrollToIndex(highlightedIndex, { align: 'end' });
40
- }
41
- // eslint-disable-next-line react-hooks/exhaustive-deps
42
- }, [highlightedIndex]);
50
+ useImperativeHandle(ctrlRef, () => rowVirtualizer, [rowVirtualizer]);
43
51
  // Циклическая навигация
44
52
  useEffect(() => {
45
53
  const notDisabled = (option) => !option.disabled;
46
54
  const firstNonDisabled = flatOptions.findIndex(notDisabled);
47
- const lastNonDisabled = lastIndexOf(flatOptions, notDisabled);
55
+ const lastNonDisabled = flatOptions.findLastIndex(notDisabled);
48
56
  if (prevHighlightedIndex <= firstNonDisabled &&
49
57
  highlightedIndex === flatOptions.length - 1) {
50
58
  rowVirtualizer.scrollToIndex(lastNonDisabled);
@@ -67,11 +75,10 @@ const VirtualOptionsList = forwardRef(({ size = 48, flatOptions = [], highlighte
67
75
  .join('_'));
68
76
  // eslint-disable-next-line react-hooks/exhaustive-deps
69
77
  }, [rowVirtualizer.virtualItems.length, flatOptions]);
70
- useVirtualVisibleOptions({
78
+ const maxHeight = useVirtualVisibleOptions({
71
79
  visibleOptions,
72
80
  invalidate: visibleOptionsInvalidateKey,
73
81
  listRef,
74
- styleTargetRef: nativeScrollbar ? parentRef : scrollbarRef,
75
82
  open,
76
83
  });
77
84
  // Т.к. рендерится плоский список, необходимо знать индекс, когда начинается новая группа
@@ -88,6 +95,14 @@ const VirtualOptionsList = forwardRef(({ size = 48, flatOptions = [], highlighte
88
95
  return acc;
89
96
  }, {});
90
97
  }, [options]);
98
+ const handleScroll = (event) => {
99
+ const scrolledToHeader = event.currentTarget.scrollTop <= 0;
100
+ const scrolledToFooter = event.currentTarget.scrollHeight - event.currentTarget.offsetHeight <=
101
+ event.currentTarget.scrollTop;
102
+ setScrollTop(scrolledToHeader);
103
+ setScrollBottom(scrolledToFooter);
104
+ onScroll?.(event);
105
+ };
91
106
  const renderList = () => rowVirtualizer.virtualItems.map((virtualRow) => {
92
107
  const option = flatOptions[virtualRow.index];
93
108
  const renderGroup = () => {
@@ -100,37 +115,36 @@ const VirtualOptionsList = forwardRef(({ size = 48, flatOptions = [], highlighte
100
115
  };
101
116
  return (React.createElement(Optgroup$1, { label: group.label, size: size, className: optionGroupClassName, options: group.options, selectedItems: groupSelectedItems, setSelectedItems: handleSelectedItems, search: search, multiple: multiple, ...groupOptionProps }));
102
117
  };
103
- return (React.createElement("div", { key: virtualRow.index, ref: virtualRow.measureRef, className: cn(styles.virtualRow, {
104
- [styles.highlighted]: highlightedIndex === virtualRow.index,
105
- }), style: {
106
- transform: `translateY(${virtualRow.start}px)`,
107
- } },
118
+ return (React.createElement("div", { key: virtualRow.index, ref: virtualRow.measureRef },
108
119
  renderGroup(),
109
120
  !isGroup(option) && (React.createElement(Option, { ...getOptionProps(option, virtualRow.index) }))));
110
121
  });
111
- const contentNodeProps = {
112
- className: styles.inner,
113
- style: { height: `${rowVirtualizer.totalSize}px` },
114
- ref: listRef,
115
- };
116
- const renderWithCustomScrollbar = () => (React.createElement(Scrollbar, { className: cn(styles.scrollable, scrollbarClassName), ref: scrollbarRef, horizontalAutoStretch: optionsListWidth === 'content', scrollableNodeProps: { onScroll, ref: parentRef }, contentNodeProps: contentNodeProps }, renderList()));
117
- const renderWithNativeScrollbar = () => {
118
- if (visibleOptions) {
119
- return (React.createElement("div", { className: cn(styles.scrollable, scrollbarClassName), ref: mergeRefs([parentRef, ref]), onScroll: onScroll },
120
- React.createElement("div", { ...contentNodeProps }, renderList())));
121
- }
122
- return React.createElement("div", { ...contentNodeProps }, renderList());
123
- };
124
122
  const resetHighlightedIndex = () => setHighlightedIndex?.(-1);
125
123
  if (options.length === 0 && !emptyPlaceholder) {
126
124
  return null;
127
125
  }
128
- return (React.createElement("div", { className: cn(styles.virtualOptionsList, styles[`size-${size}`], className), "data-test-id": dataTestId },
129
- header && (React.createElement("div", { className: styles.virtualOptionsListHeader, onMouseEnter: resetHighlightedIndex }, header)),
130
- nativeScrollbar ? renderWithNativeScrollbar() : renderWithCustomScrollbar(),
131
- emptyPlaceholder && options.length === 0 && (React.createElement("div", { className: styles.emptyPlaceholder }, emptyPlaceholder)),
132
- showFooter && footer && (React.createElement("div", { onMouseEnter: resetHighlightedIndex, className: cn(styles.virtualOptionsListFooter, {
133
- [styles.withBorder]: visibleOptions && flatOptions.length > visibleOptions,
126
+ const [firstVirualRow] = rowVirtualizer.virtualItems;
127
+ return (React.createElement("div", { ...(nativeScrollbar && { 'data-test-id': dataTestId }), className: cn(styles.optionsList, styles[`size-${size}`], className) },
128
+ header && (React.createElement("div", { className: cn(styles.optionsListHeader, {
129
+ [styles.headerHighlighted]: !scrollTop,
130
+ }), onMouseEnter: resetHighlightedIndex }, header)),
131
+ !noOptions && (React.createElement(ScrollbarPrivate, { native: nativeScrollbar, className: scrollbarClassName, style: { maxHeight }, scrollableNodeProps: {
132
+ ref: scrollableNodeRef,
133
+ onScroll: handleScroll,
134
+ className: scrollableNodeClassName,
135
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
136
+ // @ts-expect-error
137
+ 'data-test-id': nativeScrollbar ? undefined : dataTestId,
138
+ }, contentNodeProps: {
139
+ className: contentNodeClassName,
140
+ style: { minHeight: rowVirtualizer.totalSize },
141
+ } },
142
+ React.createElement("div", { className: cn(styles.list, listNodeClassName), ref: listRef, style: { transform: `translateY(${firstVirualRow?.start ?? 0}px)` } }, renderList()))),
143
+ emptyPlaceholder && noOptions && (React.createElement("div", { className: styles.emptyPlaceholder }, emptyPlaceholder)),
144
+ showFooter && footer && (React.createElement("div", { onMouseEnter: resetHighlightedIndex, className: cn(styles.optionsListFooter, footerClassName, {
145
+ [styles.withBorder]: visibleOptions &&
146
+ flatOptions.length > visibleOptions &&
147
+ !scrollBottom,
134
148
  }) }, footer))));
135
149
  });
136
150
 
@@ -1 +1 @@
1
- {"version":3,"file":"Component.js","sources":["../../../src/components/virtual-options-list/Component.tsx"],"sourcesContent":["import React, { forwardRef, useEffect, useMemo, useRef, useState } from 'react';\nimport mergeRefs from 'react-merge-refs';\nimport { useVirtual } from 'react-virtual';\nimport cn from 'classnames';\n\nimport { Scrollbar } from '@alfalab/core-components-scrollbar';\n\nimport { DEFAULT_VISIBLE_OPTIONS } from '../../consts';\nimport { useNativeScrollbar } from '../../hooks/use-native-scrollbar';\nimport { type GroupShape, type OptionShape, type OptionsListProps } from '../../typings';\nimport { isGroup, lastIndexOf, usePrevious, useVirtualVisibleOptions } from '../../utils';\nimport { Optgroup as DefaultOptgroup } from '../optgroup';\n\nimport styles from './index.module.css';\n\nexport const VirtualOptionsList = forwardRef<HTMLDivElement, OptionsListProps>(\n (\n {\n size = 48,\n flatOptions = [],\n highlightedIndex = -1,\n optionGroupClassName,\n className,\n getOptionProps,\n groupOptionProps = {},\n Option,\n open,\n options = [],\n Optgroup = DefaultOptgroup,\n dataTestId,\n emptyPlaceholder,\n visibleOptions = DEFAULT_VISIBLE_OPTIONS,\n header,\n footer,\n showFooter = true,\n optionsListWidth,\n onScroll,\n nativeScrollbar: nativeScrollbarProp,\n setHighlightedIndex,\n selectedItems,\n setSelectedItems,\n search,\n multiple,\n scrollbarClassName,\n client,\n },\n ref,\n ) => {\n const listRef = useRef<HTMLDivElement>(null);\n const parentRef = useRef<HTMLDivElement>(null);\n const scrollbarRef = useRef<HTMLDivElement>(null);\n const [visibleOptionsInvalidateKey, setVisibleOptionsInvalidateKey] = useState('');\n const prevHighlightedIndex = usePrevious(highlightedIndex) || -1;\n\n const rowVirtualizer = useVirtual({\n size: flatOptions.length,\n parentRef: (ref || parentRef) as React.RefObject<HTMLDivElement>,\n overscan: 15,\n });\n\n const nativeScrollbar = useNativeScrollbar({\n nativeScrollbar: nativeScrollbarProp,\n client,\n });\n\n // Сколл к выбранному пункту при открытии меню\n useEffect(() => {\n if (open) {\n rowVirtualizer.scrollToIndex(highlightedIndex, { align: 'end' });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open]);\n\n // Скролл к пункту, которого нет на экране\n useEffect(() => {\n if (highlightedIndex === -1) return;\n\n if (!rowVirtualizer.virtualItems.some((option) => option.index === highlightedIndex)) {\n rowVirtualizer.scrollToIndex(highlightedIndex, { align: 'end' });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [highlightedIndex]);\n\n // Циклическая навигация\n useEffect(() => {\n const notDisabled = (option: OptionShape) => !option.disabled;\n const firstNonDisabled = flatOptions.findIndex(notDisabled);\n const lastNonDisabled = lastIndexOf(flatOptions, notDisabled);\n\n if (\n prevHighlightedIndex <= firstNonDisabled &&\n highlightedIndex === flatOptions.length - 1\n ) {\n rowVirtualizer.scrollToIndex(lastNonDisabled);\n }\n\n if (prevHighlightedIndex >= lastNonDisabled && highlightedIndex === 0) {\n rowVirtualizer.scrollToIndex(0);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [prevHighlightedIndex, highlightedIndex]);\n\n useEffect(() => {\n setVisibleOptionsInvalidateKey(\n /**\n * react-virtual может несколько раз отрендерить список с одним элементом,\n * поэтому нужно еще раз пересчитать высоту, когда список ВИДИМЫХ пунктов будет отрендерен полностью\n * Также, высоту нужно пересчитывать при изменении пунктов меню\n */\n rowVirtualizer.virtualItems\n .slice(0, Math.min(rowVirtualizer.virtualItems.length, visibleOptions + 1))\n .map((item) => flatOptions[item.index].key)\n .join('_'),\n );\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [rowVirtualizer.virtualItems.length, flatOptions]);\n\n useVirtualVisibleOptions({\n visibleOptions,\n invalidate: visibleOptionsInvalidateKey,\n listRef,\n styleTargetRef: nativeScrollbar ? parentRef : scrollbarRef,\n open,\n });\n\n // Т.к. рендерится плоский список, необходимо знать индекс, когда начинается новая группа\n const groupStartIndexes = useMemo(() => {\n let currentIndex = 0;\n\n return options.reduce((acc: { [key: number]: number }, option, index) => {\n if (isGroup(option)) {\n acc[currentIndex] = index;\n currentIndex += option.options.length;\n } else {\n currentIndex += 1;\n }\n\n return acc;\n }, {});\n }, [options]);\n\n const renderList = () =>\n rowVirtualizer.virtualItems.map((virtualRow) => {\n const option = flatOptions[virtualRow.index];\n const renderGroup = () => {\n const group = options[groupStartIndexes[virtualRow.index]] as GroupShape;\n\n if (!group) return null;\n\n const groupSelectedItems = selectedItems?.filter(({ key: selectedItemKey }) =>\n group.options.some((opt) => opt.key === selectedItemKey),\n );\n const handleSelectedItems = (items: OptionShape[]) => {\n setSelectedItems(\n (\n selectedItems?.filter(\n ({ key: selectedItemKey }) =>\n !group.options.some((opt) => opt.key === selectedItemKey),\n ) ?? []\n ).concat(items),\n );\n };\n\n return (\n <Optgroup\n label={group.label}\n size={size}\n className={optionGroupClassName}\n options={group.options}\n selectedItems={groupSelectedItems}\n setSelectedItems={handleSelectedItems}\n search={search}\n multiple={multiple}\n {...groupOptionProps}\n />\n );\n };\n\n return (\n <div\n key={virtualRow.index}\n ref={virtualRow.measureRef}\n className={cn(styles.virtualRow, {\n [styles.highlighted]: highlightedIndex === virtualRow.index,\n })}\n style={{\n transform: `translateY(${virtualRow.start}px)`,\n }}\n >\n {renderGroup()}\n {!isGroup(option) && (\n <Option {...getOptionProps(option, virtualRow.index)} />\n )}\n </div>\n );\n });\n\n const contentNodeProps = {\n className: styles.inner,\n style: { height: `${rowVirtualizer.totalSize}px` },\n ref: listRef,\n };\n\n const renderWithCustomScrollbar = () => (\n <Scrollbar\n className={cn(styles.scrollable, scrollbarClassName)}\n ref={scrollbarRef}\n horizontalAutoStretch={optionsListWidth === 'content'}\n scrollableNodeProps={{ onScroll, ref: parentRef }}\n contentNodeProps={contentNodeProps}\n >\n {renderList()}\n </Scrollbar>\n );\n\n const renderWithNativeScrollbar = () => {\n if (visibleOptions) {\n return (\n <div\n className={cn(styles.scrollable, scrollbarClassName)}\n ref={mergeRefs([parentRef, ref])}\n onScroll={onScroll}\n >\n <div {...contentNodeProps}>{renderList()}</div>\n </div>\n );\n }\n\n return <div {...contentNodeProps}>{renderList()}</div>;\n };\n\n const resetHighlightedIndex = () => setHighlightedIndex?.(-1);\n\n if (options.length === 0 && !emptyPlaceholder) {\n return null;\n }\n\n return (\n <div\n className={cn(styles.virtualOptionsList, styles[`size-${size}`], className)}\n data-test-id={dataTestId}\n >\n {header && (\n <div\n className={styles.virtualOptionsListHeader}\n onMouseEnter={resetHighlightedIndex}\n >\n {header}\n </div>\n )}\n\n {nativeScrollbar ? renderWithNativeScrollbar() : renderWithCustomScrollbar()}\n\n {emptyPlaceholder && options.length === 0 && (\n <div className={styles.emptyPlaceholder}>{emptyPlaceholder}</div>\n )}\n\n {showFooter && footer && (\n <div\n onMouseEnter={resetHighlightedIndex}\n className={cn(styles.virtualOptionsListFooter, {\n [styles.withBorder]:\n visibleOptions && flatOptions.length > visibleOptions,\n })}\n >\n {footer}\n </div>\n )}\n </div>\n );\n },\n);\n"],"names":["Optgroup","DefaultOptgroup"],"mappings":"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"}
1
+ {"version":3,"file":"Component.js","sources":["../../../src/components/virtual-options-list/Component.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { useVirtual } from 'react-virtual';\nimport cn from 'classnames';\n\nimport { ScrollbarPrivate } from '@alfalab/core-components-scrollbar-private';\nimport { getElementWindow } from '@alfalab/core-components-shared';\n\nimport { DEFAULT_VISIBLE_OPTIONS } from '../../consts';\nimport { useNativeScrollbar } from '../../hooks/use-native-scrollbar';\nimport { type GroupShape, type OptionShape, type OptionsListProps } from '../../typings';\nimport { isGroup, usePrevious, useVirtualVisibleOptions } from '../../utils';\nimport { Optgroup as DefaultOptgroup } from '../optgroup';\n\nimport styles from '../options-list/index.module.css';\n\nexport const VirtualOptionsList = forwardRef<HTMLDivElement, OptionsListProps>(\n (\n {\n size = 48,\n flatOptions = [],\n highlightedIndex = -1,\n optionGroupClassName,\n className,\n getOptionProps,\n groupOptionProps = {},\n Option,\n open,\n options = [],\n Optgroup = DefaultOptgroup,\n dataTestId,\n emptyPlaceholder,\n visibleOptions = DEFAULT_VISIBLE_OPTIONS,\n header,\n footer,\n showFooter = true,\n onScroll,\n nativeScrollbar: nativeScrollbarProp,\n setHighlightedIndex,\n selectedItems,\n setSelectedItems,\n search,\n multiple,\n scrollbarClassName,\n client,\n scrollableNodeClassName,\n contentNodeClassName,\n listNodeClassName,\n footerClassName,\n ctrlRef,\n },\n ref,\n ) => {\n const listRef = useRef<HTMLDivElement>(null);\n const scrollableNodeRef = useRef<HTMLDivElement>(null);\n const noOptions = options.length === 0;\n const [scrollTop, setScrollTop] = useState(true);\n const [scrollBottom, setScrollBottom] = useState(false);\n const [visibleOptionsInvalidateKey, setVisibleOptionsInvalidateKey] = useState('');\n const prevHighlightedIndex = usePrevious(highlightedIndex) || -1;\n\n const rowVirtualizer = useVirtual({\n scrollToFn(offset, defaultScrollToFn) {\n let delta = 0;\n const list = listRef.current;\n\n if (list) {\n const win = getElementWindow(list);\n\n delta = ['::before', '::after']\n .map((pseudo) => {\n const { paddingTop } = win.getComputedStyle(list, pseudo);\n\n return parseFloat(paddingTop) || 0;\n })\n .reduce((a, b) => a + b);\n }\n\n defaultScrollToFn?.(offset === 0 ? offset : offset + delta);\n },\n size: flatOptions.length,\n parentRef: (ref as React.RefObject<HTMLDivElement>) || scrollableNodeRef,\n overscan: 15,\n });\n\n const nativeScrollbar = useNativeScrollbar({\n nativeScrollbar: nativeScrollbarProp,\n client,\n });\n\n // Сколл к выбранному пункту при открытии меню\n useEffect(() => {\n if (open) {\n rowVirtualizer.scrollToIndex(highlightedIndex, { align: 'end' });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open]);\n\n useImperativeHandle(ctrlRef, () => rowVirtualizer, [rowVirtualizer]);\n\n // Циклическая навигация\n useEffect(() => {\n const notDisabled = (option: OptionShape) => !option.disabled;\n const firstNonDisabled = flatOptions.findIndex(notDisabled);\n const lastNonDisabled = flatOptions.findLastIndex(notDisabled);\n\n if (\n prevHighlightedIndex <= firstNonDisabled &&\n highlightedIndex === flatOptions.length - 1\n ) {\n rowVirtualizer.scrollToIndex(lastNonDisabled);\n }\n\n if (prevHighlightedIndex >= lastNonDisabled && highlightedIndex === 0) {\n rowVirtualizer.scrollToIndex(0);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [prevHighlightedIndex, highlightedIndex]);\n\n useEffect(() => {\n setVisibleOptionsInvalidateKey(\n /**\n * react-virtual может несколько раз отрендерить список с одним элементом,\n * поэтому нужно еще раз пересчитать высоту, когда список ВИДИМЫХ пунктов будет отрендерен полностью\n * Также, высоту нужно пересчитывать при изменении пунктов меню\n */\n rowVirtualizer.virtualItems\n .slice(0, Math.min(rowVirtualizer.virtualItems.length, visibleOptions + 1))\n .map((item) => flatOptions[item.index].key)\n .join('_'),\n );\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [rowVirtualizer.virtualItems.length, flatOptions]);\n\n const maxHeight = useVirtualVisibleOptions({\n visibleOptions,\n invalidate: visibleOptionsInvalidateKey,\n listRef,\n open,\n });\n\n // Т.к. рендерится плоский список, необходимо знать индекс, когда начинается новая группа\n const groupStartIndexes = useMemo(() => {\n let currentIndex = 0;\n\n return options.reduce((acc: { [key: number]: number }, option, index) => {\n if (isGroup(option)) {\n acc[currentIndex] = index;\n currentIndex += option.options.length;\n } else {\n currentIndex += 1;\n }\n\n return acc;\n }, {});\n }, [options]);\n\n const handleScroll: React.MouseEventHandler<HTMLDivElement> = (event) => {\n const scrolledToHeader = event.currentTarget.scrollTop <= 0;\n const scrolledToFooter =\n event.currentTarget.scrollHeight - event.currentTarget.offsetHeight <=\n event.currentTarget.scrollTop;\n\n setScrollTop(scrolledToHeader);\n setScrollBottom(scrolledToFooter);\n\n onScroll?.(event);\n };\n\n const renderList = () =>\n rowVirtualizer.virtualItems.map((virtualRow) => {\n const option = flatOptions[virtualRow.index];\n const renderGroup = () => {\n const group = options[groupStartIndexes[virtualRow.index]] as GroupShape;\n\n if (!group) return null;\n\n const groupSelectedItems = selectedItems?.filter(({ key: selectedItemKey }) =>\n group.options.some((opt) => opt.key === selectedItemKey),\n );\n const handleSelectedItems = (items: OptionShape[]) => {\n setSelectedItems(\n (\n selectedItems?.filter(\n ({ key: selectedItemKey }) =>\n !group.options.some((opt) => opt.key === selectedItemKey),\n ) ?? []\n ).concat(items),\n );\n };\n\n return (\n <Optgroup\n label={group.label}\n size={size}\n className={optionGroupClassName}\n options={group.options}\n selectedItems={groupSelectedItems}\n setSelectedItems={handleSelectedItems}\n search={search}\n multiple={multiple}\n {...groupOptionProps}\n />\n );\n };\n\n return (\n <div key={virtualRow.index} ref={virtualRow.measureRef}>\n {renderGroup()}\n {!isGroup(option) && (\n <Option {...getOptionProps(option, virtualRow.index)} />\n )}\n </div>\n );\n });\n\n const resetHighlightedIndex = () => setHighlightedIndex?.(-1);\n\n if (options.length === 0 && !emptyPlaceholder) {\n return null;\n }\n\n const [firstVirualRow] = rowVirtualizer.virtualItems;\n\n return (\n <div\n {...(nativeScrollbar && { 'data-test-id': dataTestId })}\n className={cn(styles.optionsList, styles[`size-${size}`], className)}\n >\n {header && (\n <div\n className={cn(styles.optionsListHeader, {\n [styles.headerHighlighted]: !scrollTop,\n })}\n onMouseEnter={resetHighlightedIndex}\n >\n {header}\n </div>\n )}\n\n {!noOptions && (\n <ScrollbarPrivate\n native={nativeScrollbar}\n className={scrollbarClassName}\n style={{ maxHeight }}\n scrollableNodeProps={{\n ref: scrollableNodeRef,\n onScroll: handleScroll,\n className: scrollableNodeClassName,\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n 'data-test-id': nativeScrollbar ? undefined : dataTestId,\n }}\n contentNodeProps={{\n className: contentNodeClassName,\n style: { minHeight: rowVirtualizer.totalSize },\n }}\n >\n <div\n className={cn(styles.list, listNodeClassName)}\n ref={listRef}\n style={{ transform: `translateY(${firstVirualRow?.start ?? 0}px)` }}\n >\n {renderList()}\n </div>\n </ScrollbarPrivate>\n )}\n\n {emptyPlaceholder && noOptions && (\n <div className={styles.emptyPlaceholder}>{emptyPlaceholder}</div>\n )}\n\n {showFooter && footer && (\n <div\n onMouseEnter={resetHighlightedIndex}\n className={cn(styles.optionsListFooter, footerClassName, {\n [styles.withBorder]:\n visibleOptions &&\n flatOptions.length > visibleOptions &&\n !scrollBottom,\n })}\n >\n {footer}\n </div>\n )}\n </div>\n );\n },\n);\n"],"names":["Optgroup","DefaultOptgroup"],"mappings":"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"}
@@ -94,6 +94,10 @@ export declare function useSelectWithApply({ options, selected, onChange, onSele
94
94
  search?: string;
95
95
  multiple?: boolean;
96
96
  limitDynamicOptionGroupSize?: BaseSelectProps["limitDynamicOptionGroupSize"];
97
+ scrollableNodeClassName?: string;
98
+ contentNodeClassName?: string;
99
+ listNodeClassName?: string;
100
+ ctrlRef?: import("react").Ref<import("../../typings").OptionsListController>;
97
101
  } & {
98
102
  showClear?: boolean;
99
103
  onClose?: () => void;
@@ -139,6 +143,10 @@ export declare function useSelectWithApply({ options, selected, onChange, onSele
139
143
  search?: string;
140
144
  multiple?: boolean;
141
145
  limitDynamicOptionGroupSize?: BaseSelectProps["limitDynamicOptionGroupSize"];
146
+ scrollableNodeClassName?: string;
147
+ contentNodeClassName?: string;
148
+ listNodeClassName?: string;
149
+ ctrlRef?: import("react").Ref<import("../../typings").OptionsListController>;
142
150
  } & import("react").RefAttributes<HTMLDivElement>> | undefined;
143
151
  showClear: boolean;
144
152
  onClear: () => void;
@@ -203,6 +211,10 @@ export declare function useSelectWithApply({ options, selected, onChange, onSele
203
211
  search?: string;
204
212
  multiple?: boolean;
205
213
  limitDynamicOptionGroupSize?: BaseSelectProps["limitDynamicOptionGroupSize"];
214
+ scrollableNodeClassName?: string;
215
+ contentNodeClassName?: string;
216
+ listNodeClassName?: string;
217
+ ctrlRef?: import("react").Ref<import("../../typings").OptionsListController>;
206
218
  } & import("react").RefAttributes<HTMLDivElement>> | undefined;
207
219
  optionsListProps: unknown;
208
220
  showClear: boolean;
@@ -35,6 +35,10 @@ export declare const OptionsListWithApply: React.ForwardRefExoticComponent<Pick<
35
35
  search?: string;
36
36
  multiple?: boolean;
37
37
  limitDynamicOptionGroupSize?: import("../../../typings").BaseSelectProps["limitDynamicOptionGroupSize"];
38
+ scrollableNodeClassName?: string;
39
+ contentNodeClassName?: string;
40
+ listNodeClassName?: string;
41
+ ctrlRef?: React.Ref<import("../../../typings").OptionsListController>;
38
42
  } & {
39
43
  showClear?: boolean;
40
44
  onClose?: () => void;
@@ -8,10 +8,6 @@
8
8
  outline: none;
9
9
  }
10
10
 
11
- .footer.size-72 {
12
- padding: var(--gap-12) var(--gap-16);
13
- }
14
-
15
11
  .footer > .button + .button {
16
12
  margin-left: var(--select-option-list-footer-button-gap);
17
13
  }
@@ -1,13 +1,15 @@
1
-
1
+ :root {
2
+ --select-options-list-top-padding: var(--gap-0);
3
+ --select-options-list-right-padding: var(--gap-0);
4
+ --select-options-list-left-padding: var(--gap-0);
5
+ }
2
6
 
3
7
  .desktop {
4
- padding: var(--gap-12);
8
+ padding: calc(var(--gap-12) + var(--select-options-list-top-padding))
9
+ calc(var(--gap-12) + var(--select-options-list-right-padding)) var(--gap-12)
10
+ calc(var(--gap-12) + var(--select-options-list-left-padding));
5
11
  }
6
12
 
7
- .desktop.size-72 {
8
- padding-left: var(--gap-16);
9
- }
10
-
11
13
  .mobile {
12
14
  padding: var(--gap-12) var(--gap-12) var(--gap-12) var(--gap-8);
13
15
  }
@@ -1,7 +1,7 @@
1
1
  export { useSelectWithLoading } from '../presets/useSelectWithLoading/hook.js';
2
2
  export { useLazyLoading } from '../presets/useLazyLoading/hook.js';
3
3
  export { useSelectWithApply } from '../presets/useSelectWithApply/hook.js';
4
- export { defaultAccessor, defaultFilterFn, defaultGroupAccessor, getSelectTestIds, isGroup, isOptionShape, joinOptions, lastIndexOf, processOptions, usePrevious, useVirtualVisibleOptions, useVisibleOptions } from '../utils.js';
4
+ export { defaultAccessor, defaultFilterFn, defaultGroupAccessor, getSelectTestIds, isGroup, isOptionShape, joinOptions, processOptions, usePrevious, useVirtualVisibleOptions, useVisibleOptions } from '../utils.js';
5
5
  export { OptionDesktop } from '../components/option/desktop/Component.js';
6
6
  export { OptionMobile } from '../components/option/mobile/Component.js';
7
7
  export { OptionResponsive as Option } from '../components/option/Component.responsive.js';
@@ -1,4 +1,4 @@
1
- import { type AriaAttributes, type ComponentType, type FC, type FocusEvent, type MouseEvent, type ReactElement, type ReactNode, type RefAttributes, type SVGProps } from 'react';
1
+ import { type AriaAttributes, type ComponentType, type FC, type FocusEvent, type MouseEvent, type ReactElement, type ReactNode, type Ref, type RefAttributes, type SVGProps } from 'react';
2
2
  import { type Environment } from 'downshift';
3
3
  import { type BottomSheetProps } from '@alfalab/core-components-bottom-sheet/moderncssm';
4
4
  import { type FormControlProps } from '@alfalab/core-components-form-control/moderncssm';
@@ -113,6 +113,7 @@ export interface BaseSelectProps {
113
113
  size?: FormControlProps['size'];
114
114
  /**
115
115
  * Размер пунктов меню
116
+ * @deprecated Управление размером пунктов меню через отдельный проп не поддерживается дизайн-контрактом. Размер пункта должен определяться его контентом.
116
117
  */
117
118
  optionsSize?: 40 | 48 | 56 | 64 | 72;
118
119
  /**
@@ -539,6 +540,22 @@ export type OptionsListProps = Pick<SelectProps, 'client'> & {
539
540
  * Ограничение динамического размера группы вариантов выбора
540
541
  */
541
542
  limitDynamicOptionGroupSize?: BaseSelectProps['limitDynamicOptionGroupSize'];
543
+ /**
544
+ *
545
+ */
546
+ scrollableNodeClassName?: string;
547
+ /**
548
+ *
549
+ */
550
+ contentNodeClassName?: string;
551
+ /**
552
+ *
553
+ */
554
+ listNodeClassName?: string;
555
+ /**
556
+ *
557
+ */
558
+ ctrlRef?: Ref<OptionsListController>;
542
559
  };
543
560
  export type OptgroupProps = {
544
561
  /**
@@ -789,4 +806,7 @@ export type ClearButtonProps = {
789
806
  */
790
807
  size?: FormControlProps['size'];
791
808
  };
809
+ export interface OptionsListController {
810
+ scrollToIndex(index: number): void;
811
+ }
792
812
  export {};
@@ -21,10 +21,6 @@ type useVisibleOptionsArgs = {
21
21
  * Реф на контейнер с пунтами меню
22
22
  */
23
23
  listRef: RefObject<HTMLElement>;
24
- /**
25
- * Реф на контейнер, которому нужно установить высоту
26
- */
27
- styleTargetRef?: RefObject<HTMLElement>;
28
24
  /**
29
25
  * Флаг открытия меню
30
26
  */
@@ -46,13 +42,12 @@ type useVisibleOptionsArgs = {
46
42
  */
47
43
  actualOptionsCount?: boolean;
48
44
  };
49
- export declare function useVirtualVisibleOptions({ visibleOptions, listRef, styleTargetRef, open, invalidate, options, size, actualOptionsCount, }: useVisibleOptionsArgs): void;
45
+ export declare function useVirtualVisibleOptions({ visibleOptions, listRef, open, invalidate, options, size, actualOptionsCount, }: useVisibleOptionsArgs): number | undefined;
50
46
  export declare function useVisibleOptions({ visibleOptions, listRef, open, options, size, actualOptionsCount, }: useVisibleOptionsArgs): readonly [boolean, number | undefined];
51
47
  export declare function defaultFilterFn(optionText: string, search: string): boolean;
52
48
  export declare function defaultGroupAccessor(option: GroupShape): string | undefined;
53
49
  export declare function defaultAccessor(option: OptionShape): string;
54
50
  export declare function usePrevious<T>(value: T): T | undefined;
55
- export declare const lastIndexOf: <T>(array: T[], predicate: (item: T) => boolean) => number;
56
51
  export declare function getSelectTestIds(dataTestId: string): {
57
52
  select: string;
58
53
  option: string;