@astral/ui 4.78.0 → 4.80.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/components/DataGridInfinite/DataGridInfinite.js +11 -3
  2. package/components/DataGridInfinite/Row/Row.js +1 -1
  3. package/components/DataGridInfinite/index.d.ts +1 -1
  4. package/components/DataGridInfinite/public.d.ts +1 -1
  5. package/components/DataGridInfinite/styles.d.ts +4 -0
  6. package/components/DataGridInfinite/styles.js +8 -0
  7. package/components/DataGridInfinite/types.d.ts +20 -0
  8. package/components/DataGridInfinite/useLogic/useLogic.d.ts +10 -4
  9. package/components/DataGridInfinite/useLogic/useLogic.js +52 -3
  10. package/components/ToggleButton/ToggleButton.js +2 -2
  11. package/components/ToggleButton/useLogic/useLogic.d.ts +1 -0
  12. package/components/ToggleButton/useLogic/useLogic.js +3 -1
  13. package/components/ToggleButtonGroup/ToggleButtonGroup.d.ts +2 -23
  14. package/components/ToggleButtonGroup/ToggleButtonGroup.js +5 -4
  15. package/components/ToggleButtonGroup/ToggleButtonGroupContext/ToggleButtonGroupContext.d.ts +1 -0
  16. package/components/ToggleButtonGroup/ToggleButtonGroupContext/ToggleButtonGroupContext.js +1 -0
  17. package/components/ToggleButtonGroup/ToggleButtonGroupContext/ToggleButtonGroupContextProvider/ToggleButtonGroupContextProvider.d.ts +1 -1
  18. package/components/ToggleButtonGroup/ToggleButtonGroupContext/ToggleButtonGroupContextProvider/ToggleButtonGroupContextProvider.js +2 -2
  19. package/components/ToggleButtonGroup/index.d.ts +1 -0
  20. package/components/ToggleButtonGroup/public.d.ts +1 -0
  21. package/components/ToggleButtonGroup/styles.d.ts +5 -0
  22. package/components/ToggleButtonGroup/styles.js +17 -0
  23. package/components/ToggleButtonGroup/types.d.ts +23 -0
  24. package/components/ToggleButtonGroup/types.js +1 -0
  25. package/components/ToggleButtonGroup/useLogic/index.d.ts +1 -0
  26. package/components/ToggleButtonGroup/useLogic/index.js +1 -0
  27. package/components/ToggleButtonGroup/useLogic/useLogic.d.ts +300 -0
  28. package/components/ToggleButtonGroup/useLogic/useLogic.js +16 -0
  29. package/node/components/DataGridInfinite/DataGridInfinite.js +10 -2
  30. package/node/components/DataGridInfinite/Row/Row.js +1 -1
  31. package/node/components/DataGridInfinite/index.d.ts +1 -1
  32. package/node/components/DataGridInfinite/public.d.ts +1 -1
  33. package/node/components/DataGridInfinite/styles.d.ts +4 -0
  34. package/node/components/DataGridInfinite/styles.js +9 -1
  35. package/node/components/DataGridInfinite/types.d.ts +20 -0
  36. package/node/components/DataGridInfinite/useLogic/useLogic.d.ts +10 -4
  37. package/node/components/DataGridInfinite/useLogic/useLogic.js +52 -3
  38. package/node/components/ToggleButton/ToggleButton.js +2 -2
  39. package/node/components/ToggleButton/useLogic/useLogic.d.ts +1 -0
  40. package/node/components/ToggleButton/useLogic/useLogic.js +3 -1
  41. package/node/components/ToggleButtonGroup/ToggleButtonGroup.d.ts +2 -23
  42. package/node/components/ToggleButtonGroup/ToggleButtonGroup.js +4 -3
  43. package/node/components/ToggleButtonGroup/ToggleButtonGroupContext/ToggleButtonGroupContext.d.ts +1 -0
  44. package/node/components/ToggleButtonGroup/ToggleButtonGroupContext/ToggleButtonGroupContext.js +1 -0
  45. package/node/components/ToggleButtonGroup/ToggleButtonGroupContext/ToggleButtonGroupContextProvider/ToggleButtonGroupContextProvider.d.ts +1 -1
  46. package/node/components/ToggleButtonGroup/ToggleButtonGroupContext/ToggleButtonGroupContextProvider/ToggleButtonGroupContextProvider.js +2 -2
  47. package/node/components/ToggleButtonGroup/index.d.ts +1 -0
  48. package/node/components/ToggleButtonGroup/public.d.ts +1 -0
  49. package/node/components/ToggleButtonGroup/styles.d.ts +5 -0
  50. package/node/components/ToggleButtonGroup/styles.js +18 -1
  51. package/node/components/ToggleButtonGroup/types.d.ts +23 -0
  52. package/node/components/ToggleButtonGroup/types.js +2 -0
  53. package/node/components/ToggleButtonGroup/useLogic/index.d.ts +1 -0
  54. package/node/components/ToggleButtonGroup/useLogic/index.js +17 -0
  55. package/node/components/ToggleButtonGroup/useLogic/useLogic.d.ts +300 -0
  56. package/node/components/ToggleButtonGroup/useLogic/useLogic.js +20 -0
  57. package/package.json +1 -1
@@ -20,7 +20,7 @@ import { ErrorMessage } from './ErrorMessage';
20
20
  import { List } from './List';
21
21
  import { NoData } from './NoData';
22
22
  import { Row } from './Row';
23
- import { Backdrop, DataGridWrapper, DisabledDataGridWrapper, FooterRow, StyledContainer, StyledScrollToTopButton, } from './styles';
23
+ import { Backdrop, DataGridWrapper, DisabledDataGridWrapper, FooterRow, HeaderRow, StyledContainer, StyledScrollToTopButton, } from './styles';
24
24
  import { useLogic } from './useLogic';
25
25
  const dataGridInfiniteCva = cva(dataGridClassnames.root, {
26
26
  variants: {
@@ -42,7 +42,7 @@ const dataGridInfiniteCva = cva(dataGridClassnames.root, {
42
42
  });
43
43
  export const DataGridInfinite = (props) => {
44
44
  const { imagesMap, emptySymbol } = useContext(ConfigContext);
45
- const { isNoData, isDataGridDisabled, treeRenderConfig, virtuosoProps, headProps, rowProps, scrollToTopButtonProps, isEndReached, isHideHead, containerCssVars, isMobile, mobileSkeletonProps, hasGroupedColumns, gridViewMode, gridColumns, handleSelectRow, mobileDisplayVariant, isSelfContained, } = useLogic(props);
45
+ const { isNoData, isDataGridDisabled, treeRenderConfig, virtuosoProps, headProps, rowProps, scrollToTopButtonProps, isEndReached, isHideHead, containerCssVars, isMobile, mobileSkeletonProps, hasGroupedColumns, gridViewMode, gridColumns, handleSelectRow, mobileDisplayVariant, isSelfContained, isNotRenderHeader, initialTopMostItemIndex, } = useLogic(props);
46
46
  const { columns, rows = [], selectedRows = [], sorting, isLoading, isDisabled, keyId, emptyCellValue = emptySymbol, variant = Variant.Tree, subrows, className, isError, endOfScrollMsg, errorMsg, noDataPlaceholder, onRowClick, onSort, onRetry, headPreAddon, activeRowId, isTabularNums, renderRow, } = props;
47
47
  const { moreButtonColumnPosition = 1, isVisibleCollapseButton = true } = subrows || {};
48
48
  const { isInitialExpanded = false, expandedLevel = EXPANDED_LEVEL_BY_DEFAULT, initialVisibleChildrenCount = INITIAL_OPENED_NESTED_CHILDREN_COUNT_BY_DEFAULT, } = treeRenderConfig || {};
@@ -58,7 +58,9 @@ export const DataGridInfinite = (props) => {
58
58
  errorList: [errorMsg || ''],
59
59
  imgSrc: imagesMap.defaultErrorImgSrc,
60
60
  onRetry,
61
- }, children: _jsx(Virtuoso, { ...virtuosoProps, style: { height: '100%' }, overscan: OVERSCAN_COUNT, data: rows, components: {
61
+ }, children: _jsx(Virtuoso, { ...virtuosoProps, ...(initialTopMostItemIndex && {
62
+ initialTopMostItemIndex,
63
+ }), style: { height: '100%' }, overscan: OVERSCAN_COUNT, data: rows, components: {
62
64
  // biome-ignore lint/suspicious/noTsIgnore: Требует HTMLDivElement, а для элемента списка используем HTMLUListElement (https://github.com/petyosi/react-virtuoso/issues/864)
63
65
  // @ts-ignore
64
66
  List,
@@ -70,5 +72,11 @@ export const DataGridInfinite = (props) => {
70
72
  }
71
73
  return (_jsxs(FooterRow, { children: [isLoading && _jsx(Loader, {}), isError && _jsx(ErrorMessage, { onRetry: onRetry }), isEndReached && (_jsx(EndData, { endOfScrollMsg: endOfScrollMsg }))] }));
72
74
  },
75
+ Header: () => {
76
+ if (isNotRenderHeader) {
77
+ return null;
78
+ }
79
+ return (_jsxs(HeaderRow, { children: [isLoading && _jsx(Loader, {}), isError && _jsx(ErrorMessage, { onRetry: onRetry })] }));
80
+ },
73
81
  } }) }), _jsx(StyledScrollToTopButton, { ...scrollToTopButtonProps, className: dataGridInfiniteClassnames.scrollToTopButton }), isDisabled && _jsx(Backdrop, {})] })] }) }) }));
74
82
  };
@@ -6,5 +6,5 @@ import { useLogic } from './useLogic';
6
6
  const INITIAL_LEVEL = 0;
7
7
  export const Row = ({ children, ...props }) => {
8
8
  const { item, memoizedItemProps, onSelectRow, renderRow, flattenColumns, gridColumns, options, keyId, variant, isSelectable, isSelected, nestedChildren, isInitialExpanded, expandedLevel, initialVisibleChildrenCount, moreButtonColumnPosition, isVisibleCollapseButton, emptyCellValue, activeRowId, onRowClick, } = useLogic(props);
9
- return (_jsx(RowContextProvider, { row: item, itemProps: memoizedItemProps, onSelectRow: onSelectRow, isSelectable: isSelectable, isSelected: isSelected, children: renderRow ? (_jsx(CustomRowWrapper, { index: memoizedItemProps['data-item-index'], renderRow: renderRow, row: item })) : (_jsx(RowComponent, { ...memoizedItemProps, row: item, columns: flattenColumns, gridColumns: gridColumns, options: options, keyId: keyId, variant: variant, isSelectable: isSelectable, isSelected: isSelected, level: INITIAL_LEVEL, nestedChildren: nestedChildren, isInitialExpanded: isInitialExpanded || false, expandedLevel: expandedLevel || 1, initialVisibleChildrenCount: initialVisibleChildrenCount || 2, activeRowId: activeRowId, moreButtonColumnPosition: moreButtonColumnPosition || 1, isVisibleCollapseButton: isVisibleCollapseButton || true, emptyCellValue: emptyCellValue, onRowClick: onRowClick, onSelectRow: onSelectRow })) }));
9
+ return (_jsx(RowContextProvider, { row: item, itemProps: memoizedItemProps, onSelectRow: onSelectRow, isSelectable: isSelectable, isSelected: isSelected, children: renderRow ? (_jsx(CustomRowWrapper, { index: memoizedItemProps['data-index'], renderRow: renderRow, row: item })) : (_jsx(RowComponent, { ...memoizedItemProps, row: item, columns: flattenColumns, gridColumns: gridColumns, options: options, keyId: keyId, variant: variant, isSelectable: isSelectable, isSelected: isSelected, level: INITIAL_LEVEL, nestedChildren: nestedChildren, isInitialExpanded: isInitialExpanded || false, expandedLevel: expandedLevel || 1, initialVisibleChildrenCount: initialVisibleChildrenCount || 2, activeRowId: activeRowId, moreButtonColumnPosition: moreButtonColumnPosition || 1, isVisibleCollapseButton: isVisibleCollapseButton || true, emptyCellValue: emptyCellValue, onRowClick: onRowClick, onSelectRow: onSelectRow })) }));
10
10
  };
@@ -1,2 +1,2 @@
1
1
  export { DataGridInfinite } from './DataGridInfinite';
2
- export type { DataGridInfiniteProps } from './types';
2
+ export type { DataGridInfiniteProps, DataGridInfiniteVirtuosoHandle, DataGridInfiniteVirtuosoRef, } from './types';
@@ -1,2 +1,2 @@
1
1
  export { DataGridInfinite } from './DataGridInfinite';
2
- export type { DataGridInfiniteProps } from './types';
2
+ export type { DataGridInfiniteProps, DataGridInfiniteVirtuosoHandle, DataGridInfiniteVirtuosoRef, } from './types';
@@ -13,6 +13,10 @@ export declare const FooterRow: import("../styled").StyledComponent<{
13
13
  theme?: import("@emotion/react").Theme | undefined;
14
14
  as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
15
15
  }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLElement>, HTMLElement>, {}>;
16
+ export declare const HeaderRow: import("../styled").StyledComponent<{
17
+ theme?: import("@emotion/react").Theme | undefined;
18
+ as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
19
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLElement>, HTMLElement>, {}>;
16
20
  export declare const Backdrop: import("../styled").StyledComponent<{
17
21
  theme?: import("@emotion/react").Theme | undefined;
18
22
  as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
@@ -26,6 +26,14 @@ export const FooterRow = styled.footer `
26
26
 
27
27
  min-height: 68px;
28
28
  `;
29
+ export const HeaderRow = styled.header `
30
+ display: flex;
31
+ flex-shrink: 0;
32
+ align-items: center;
33
+ justify-content: center;
34
+
35
+ min-height: 68px;
36
+ `;
29
37
  export const Backdrop = styled.div `
30
38
  position: absolute;
31
39
  top: 0;
@@ -1,6 +1,14 @@
1
+ import { type Ref, type RefObject } from 'react';
2
+ import { type VirtuosoHandle } from 'react-virtuoso';
1
3
  import type { DataGridProps, DataGridRow } from '../DataGrid';
2
4
  import { type CellValue } from '../DataGrid/types';
5
+ export type DataGridInfiniteVirtuosoHandle = VirtuosoHandle;
6
+ export type DataGridInfiniteVirtuosoRef = RefObject<DataGridInfiniteVirtuosoHandle | null>;
3
7
  export type DataGridInfiniteProps<TData extends Record<string, CellValue> = DataGridRow, TSortField extends keyof TData = keyof TData> = Omit<DataGridProps<TData, TSortField>, 'footer' | 'minDisplayRows'> & {
8
+ /**
9
+ * Ref для доступа к методам Virtuoso
10
+ */
11
+ virtuosoRef?: Ref<DataGridInfiniteVirtuosoHandle>;
4
12
  /**
5
13
  * Флаг достижения конца списка
6
14
  */
@@ -17,4 +25,16 @@ export type DataGridInfiniteProps<TData extends Record<string, CellValue> = Data
17
25
  * Убирает шапку таблицы, когда нет данных
18
26
  */
19
27
  isHideHeaderIfNoData?: boolean;
28
+ /**
29
+ * Обработчик подгрузки данных при скроле до начала списка
30
+ */
31
+ onStartReached?: () => void;
32
+ /**
33
+ * Флаг достижения начала списка
34
+ */
35
+ isStartReached?: boolean;
36
+ /**
37
+ * Индекс первого видимого элемента
38
+ */
39
+ initialVisibleItemIndex?: number;
20
40
  };
@@ -1,10 +1,10 @@
1
1
  import { type ChangeEvent } from 'react';
2
- import type { ListRange, VirtuosoHandle } from 'react-virtuoso';
2
+ import type { ListRange } from 'react-virtuoso';
3
3
  import { type DataGridRow } from '../../DataGrid';
4
4
  import { type CellValue } from '../../DataGrid/types';
5
- import { type DataGridInfiniteProps } from '../types';
5
+ import { type DataGridInfiniteProps, type DataGridInfiniteVirtuosoHandle } from '../types';
6
6
  type UseLogicParams<TData extends Record<string, CellValue> = DataGridRow, TSortField extends keyof TData = keyof TData> = DataGridInfiniteProps<TData, TSortField>;
7
- export declare const useLogic: <TData extends Record<string, unknown> = DataGridRow, TSortField extends keyof TData = keyof TData>({ keyId, columns, rows, variant, tree, subrows, selectedRows, maxHeight, isLoading, isDisabled, isEndReached, onEndReached, onSelectRow, isHideSelectAll, isHideHeaderIfNoData, gridViewMode: gridViewModeProp, mobileDisplayVariant, }: UseLogicParams<TData, TSortField>) => {
7
+ export declare const useLogic: <TData extends Record<string, unknown> = DataGridRow, TSortField extends keyof TData = keyof TData>({ keyId, columns, rows, variant, tree, subrows, selectedRows, maxHeight, isLoading, isError, isDisabled, isEndReached, onEndReached, onStartReached, isStartReached, onSelectRow, isHideSelectAll, initialVisibleItemIndex, isHideHeaderIfNoData, gridViewMode: gridViewModeProp, mobileDisplayVariant, virtuosoRef, }: UseLogicParams<TData, TSortField>) => {
8
8
  containerCssVars: import("react").CSSProperties;
9
9
  mobileSkeletonProps: {
10
10
  cellsCount: number;
@@ -24,12 +24,17 @@ export declare const useLogic: <TData extends Record<string, unknown> = DataGrid
24
24
  hasGroupedColumns: boolean;
25
25
  gridViewMode: "standard" | "full";
26
26
  gridColumns: string;
27
+ isStartReached: boolean | undefined;
28
+ isNotRenderHeader: boolean | undefined;
29
+ initialTopMostItemIndex: number | undefined;
27
30
  virtuosoProps: {
28
31
  id: string;
29
- ref: import("react").RefObject<VirtuosoHandle | null>;
32
+ ref: (node: DataGridInfiniteVirtuosoHandle | null) => void;
30
33
  endReached: () => void;
31
34
  rangeChanged: (range: ListRange) => void;
32
35
  totalListHeightChanged: () => void;
36
+ startReached: () => void;
37
+ firstItemIndex: number;
33
38
  };
34
39
  headProps: {
35
40
  rowsCount: number;
@@ -50,5 +55,6 @@ export declare const useLogic: <TData extends Record<string, unknown> = DataGrid
50
55
  handleSelectRow: (row: TData) => (event: ChangeEvent<HTMLInputElement>) => void;
51
56
  mobileDisplayVariant: "list" | "cards";
52
57
  isSelfContained: boolean;
58
+ firstItemIndex: number;
53
59
  };
54
60
  export {};
@@ -7,12 +7,45 @@ import { useViewportType } from '../../useViewportType';
7
7
  import { prop } from '../../utils/prop';
8
8
  import { uniqueBy } from '../../utils/uniqueBy';
9
9
  import { dataGridInfiniteClassnames, VIRTUOSO_CONTAINER_ID, VIRTUOSO_LIST_ID, } from '../constants';
10
- export const useLogic = ({ keyId, columns, rows, variant, tree, subrows, selectedRows = [], maxHeight, isLoading, isDisabled, isEndReached, onEndReached, onSelectRow, isHideSelectAll, isHideHeaderIfNoData = false, gridViewMode: gridViewModeProp = 'standard', mobileDisplayVariant = variant === 'subrows' ? 'cards' : 'list', }) => {
10
+ export const useLogic = ({ keyId, columns, rows, variant, tree, subrows, selectedRows = [], maxHeight, isLoading, isError, isDisabled, isEndReached, onEndReached, onStartReached, isStartReached, onSelectRow, isHideSelectAll, initialVisibleItemIndex, isHideHeaderIfNoData = false, gridViewMode: gridViewModeProp = 'standard', mobileDisplayVariant = variant === 'subrows' ? 'cards' : 'list', virtuosoRef, }) => {
11
11
  const virtuoso = useRef(null);
12
+ const handleVirtuosoRef = useCallback((node) => {
13
+ virtuoso.current = node;
14
+ if (virtuosoRef) {
15
+ virtuosoRef.current = node;
16
+ }
17
+ }, [virtuosoRef]);
12
18
  const scrollToTopButtonRef = useRef(null);
13
19
  const { isMobile } = useViewportType();
14
20
  // Реф добавлен для избежания замыкания selectedRows в handleSelectRow (иначе в handleSelectRow приходят некорректные значения selectedRows).
15
21
  const selectedRowsRef = useRef(selectedRows);
22
+ // Рефы для вычисления firstItemIndex
23
+ // baseIndex - базовый индекс для вычисления firstItemIndex. Делаем очень большим, что бы при подгрузке данных вверх(начало списка) virtuoso ставил им индексы меньше чем этот.
24
+ const baseIndex = useRef(10000);
25
+ const initialLength = useRef(rows.length);
26
+ const firstRowId = useRef(rows[0]?.[keyId]);
27
+ // Вычисляем firstItemIndex для динамической подгрузки данных вверх. Что бы virtuoso понимал что данные сверху еще есть и не надо скролить до верха списка.
28
+ const firstItemIndex = useMemo(() => {
29
+ const currentLength = rows.length;
30
+ const currentFirstId = rows[0]?.[keyId];
31
+ if (currentLength !== initialLength.current) {
32
+ // Если первый элемент изменился и длина увеличилась → подгрузка вверх
33
+ if (currentFirstId !== firstRowId.current &&
34
+ currentLength > initialLength.current) {
35
+ const addedCount = currentLength - initialLength.current;
36
+ baseIndex.current -= addedCount;
37
+ firstRowId.current = currentFirstId;
38
+ }
39
+ else if (currentLength < initialLength.current) {
40
+ baseIndex.current = 10000;
41
+ firstRowId.current = currentFirstId;
42
+ }
43
+ // Если длина увеличилась, но первый элемент не изменился → подгрузка вниз
44
+ // baseIndex не меняем
45
+ initialLength.current = currentLength;
46
+ }
47
+ return baseIndex.current;
48
+ }, [rows.length]);
16
49
  useEffect(() => {
17
50
  selectedRowsRef.current = selectedRows;
18
51
  }, [selectedRows]);
@@ -43,12 +76,17 @@ export const useLogic = ({ keyId, columns, rows, variant, tree, subrows, selecte
43
76
  onEndReached();
44
77
  }
45
78
  }, [isEndReached, onEndReached]);
79
+ const handleStartReach = useCallback(() => {
80
+ if (!isStartReached && onStartReached) {
81
+ onStartReached();
82
+ }
83
+ }, [isStartReached, onStartReached]);
46
84
  const uncheckedRowsCount = useMemo(() => {
47
85
  return availableRows.filter((row) => !selectedRows.find((selectedRow) => selectedRow[keyId] === row[keyId])).length;
48
86
  }, [availableRows, selectedRows, keyId]);
49
87
  const handleRangeChanged = useCallback((range) => {
50
88
  if (scrollToTopButtonRef.current) {
51
- scrollToTopButtonRef.current.classList.toggle(dataGridInfiniteClassnames.visibleScrollToTopButton, range.startIndex > 2);
89
+ scrollToTopButtonRef.current.classList.toggle(dataGridInfiniteClassnames.visibleScrollToTopButton, range.startIndex > baseIndex.current + 2);
52
90
  }
53
91
  }, []);
54
92
  const handleSelectAllRows = (event) => {
@@ -87,6 +125,11 @@ export const useLogic = ({ keyId, columns, rows, variant, tree, subrows, selecte
87
125
  mobileDisplayVariant,
88
126
  });
89
127
  const containerCssVars = getDataGridCssVars(maxHeight);
128
+ const foundIndex = rows.findIndex((row) => String(row[keyId]) === String(initialVisibleItemIndex));
129
+ const initialTopMostItemIndex = foundIndex === -1 ? undefined : foundIndex;
130
+ const isNotRenderHeader = (!isLoading && !isError && !isStartReached) ||
131
+ !onStartReached ||
132
+ isStartReached;
90
133
  return {
91
134
  containerCssVars,
92
135
  mobileSkeletonProps,
@@ -99,12 +142,17 @@ export const useLogic = ({ keyId, columns, rows, variant, tree, subrows, selecte
99
142
  hasGroupedColumns,
100
143
  gridViewMode,
101
144
  gridColumns,
145
+ isStartReached,
146
+ isNotRenderHeader,
147
+ initialTopMostItemIndex,
102
148
  virtuosoProps: {
103
149
  id: VIRTUOSO_CONTAINER_ID,
104
- ref: virtuoso,
150
+ ref: handleVirtuosoRef,
105
151
  endReached: handleEndReach,
106
152
  rangeChanged: handleRangeChanged,
107
153
  totalListHeightChanged: recalculateVerticalScroll,
154
+ startReached: handleStartReach,
155
+ firstItemIndex,
108
156
  },
109
157
  headProps: {
110
158
  rowsCount: availableRows.length,
@@ -125,5 +173,6 @@ export const useLogic = ({ keyId, columns, rows, variant, tree, subrows, selecte
125
173
  handleSelectRow,
126
174
  mobileDisplayVariant,
127
175
  isSelfContained: mobileDisplayVariant === 'cards',
176
+ firstItemIndex,
128
177
  };
129
178
  };
@@ -3,6 +3,6 @@ import { forwardRef } from 'react';
3
3
  import { StyledToggleButton } from './styles';
4
4
  import { useLogic } from './useLogic';
5
5
  export const ToggleButton = forwardRef((props, ref) => {
6
- const { isVisibleCounter, children, disabled, counterLabel, color, selected, restProps, variant, } = useLogic(props);
7
- return (_jsxs(StyledToggleButton, { ref: ref, disabled: disabled, selected: selected, ...restProps, "$color": color, "$variant": variant, children: [children, isVisibleCounter && _jsxs(_Fragment, { children: [" \u00B7 ", counterLabel] })] }));
6
+ const { isVisibleCounter, children, disabled, counterLabel, color, selected, isSelected, restProps, variant, } = useLogic(props);
7
+ return (_jsxs(StyledToggleButton, { ref: ref, disabled: disabled, selected: selected, ...restProps, "$color": color, "$variant": variant, "aria-selected": isSelected, children: [children, isVisibleCounter && _jsxs(_Fragment, { children: [" \u00B7 ", counterLabel] })] }));
8
8
  });
@@ -8,6 +8,7 @@ export declare const useLogic: ({ selected, color, counter, children, disabled,
8
8
  disabled: boolean | undefined;
9
9
  color: "primary" | "success" | "warning" | "error" | "grey";
10
10
  selected: boolean | undefined;
11
+ isSelected: boolean;
11
12
  counterLabel: string | number | undefined;
12
13
  restProps: {
13
14
  classes?: (Partial<import("@mui/material").ToggleButtonClasses> & Partial<import("@mui/material").ClassNameMap<never>>) | undefined;
@@ -2,7 +2,7 @@ import { useContext, useMemo } from 'react';
2
2
  import { ToggleButtonGroupContext } from '../../ToggleButtonGroup';
3
3
  export const useLogic = ({ selected, color = 'primary', counter, children, disabled, counterMax = 99, ...restProps }) => {
4
4
  const isVisibleCounter = Boolean(counter);
5
- const { variant } = useContext(ToggleButtonGroupContext);
5
+ const { variant, value } = useContext(ToggleButtonGroupContext);
6
6
  const counterLabel = useMemo(() => {
7
7
  if (!isVisibleCounter) {
8
8
  return undefined;
@@ -14,12 +14,14 @@ export const useLogic = ({ selected, color = 'primary', counter, children, disab
14
14
  }
15
15
  return counterValue;
16
16
  }, [isVisibleCounter, counter, counterMax]);
17
+ const isSelected = restProps.value === value;
17
18
  return {
18
19
  isVisibleCounter,
19
20
  children,
20
21
  disabled,
21
22
  color,
22
23
  selected,
24
+ isSelected,
23
25
  counterLabel,
24
26
  restProps,
25
27
  variant,
@@ -1,24 +1,3 @@
1
- import { type ToggleButtonGroupProps as MuiToggleButtonGroupProps } from '@mui/material/ToggleButtonGroup';
2
- import { type ReactNode } from 'react';
3
- import type { WithoutEmotionSpecific } from '../types/WithoutEmotionSpecific';
4
- export type ToggleButtonGroupProps = WithoutEmotionSpecific<Omit<MuiToggleButtonGroupProps, 'orientation'>> & {
5
- /**
6
- * Если `true`, компонент будет отображаться в состоянии ошибки
7
- */
8
- isError?: boolean;
9
- /**
10
- * Текстовая информация об ошибке, будет отображен в тултипе при isError: true
11
- */
12
- errorText?: ReactNode;
13
- /**
14
- * Определяет стиль отображения группы кнопок
15
- *
16
- * - `transparent` — прозрачный фон кнопок ToggleButton
17
- *
18
- * - `plain` — белый фон кнопок ToggleButton
19
- *
20
- * @default transparent
21
- */
22
- variant?: 'transparent' | 'plain';
23
- };
1
+ /// <reference types="react" />
2
+ import { type ToggleButtonGroupProps } from './types';
24
3
  export declare const ToggleButtonGroup: import("react").ForwardRefExoticComponent<Omit<ToggleButtonGroupProps, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
@@ -1,9 +1,10 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { forwardRef } from 'react';
3
3
  import { Tooltip } from '../Tooltip';
4
- import { StyledToggleButtonGroup } from './styles';
4
+ import { ScrollContainer, StyledToggleButtonGroup } from './styles';
5
5
  import { ToggleButtonGroupContextProvider } from './ToggleButtonGroupContext';
6
- export const ToggleButtonGroup = forwardRef((props, ref) => {
7
- const { size = 'medium', isError, errorText, variant = 'transparent', ...restProps } = props;
8
- return (_jsx(ToggleButtonGroupContextProvider, { isError: isError, variant: variant, children: _jsx(Tooltip, { title: isError && errorText, followCursor: true, arrow: false, children: _jsx(StyledToggleButtonGroup, { ref: ref, size: size, ...restProps, "$isError": isError }) }) }));
6
+ import { useLogic } from './useLogic';
7
+ export const ToggleButtonGroup = forwardRef((props, forwardedRef) => {
8
+ const { size, isError, variant, restProps, title, containerRef } = useLogic(props, forwardedRef);
9
+ return (_jsx(ToggleButtonGroupContextProvider, { isError: isError, variant: variant, value: restProps.value, children: _jsx(Tooltip, { title: title, followCursor: true, arrow: false, children: _jsx(ScrollContainer, { children: _jsx(StyledToggleButtonGroup, { ref: containerRef, size: size, ...restProps, "$isError": isError }) }) }) }));
9
10
  });
@@ -2,5 +2,6 @@
2
2
  export type ToggleButtonGroupContextProps = {
3
3
  isError?: boolean;
4
4
  variant: 'transparent' | 'plain';
5
+ value: unknown;
5
6
  };
6
7
  export declare const ToggleButtonGroupContext: import("react").Context<ToggleButtonGroupContextProps>;
@@ -2,4 +2,5 @@ import { createContext } from 'react';
2
2
  export const ToggleButtonGroupContext = createContext({
3
3
  isError: false,
4
4
  variant: 'transparent',
5
+ value: '',
5
6
  });
@@ -3,4 +3,4 @@ import { type ToggleButtonGroupContextProps } from '../ToggleButtonGroupContext'
3
3
  export type Props = ToggleButtonGroupContextProps & {
4
4
  children: ReactNode;
5
5
  };
6
- export declare const ToggleButtonGroupContextProvider: ({ children, isError, variant, }: Props) => import("react/jsx-runtime").JSX.Element;
6
+ export declare const ToggleButtonGroupContextProvider: ({ children, isError, variant, value, }: Props) => import("react/jsx-runtime").JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { ToggleButtonGroupContext, } from '../ToggleButtonGroupContext';
3
- export const ToggleButtonGroupContextProvider = ({ children, isError, variant, }) => {
4
- return (_jsx(ToggleButtonGroupContext.Provider, { value: { isError, variant }, children: children }));
3
+ export const ToggleButtonGroupContextProvider = ({ children, isError, variant, value, }) => {
4
+ return (_jsx(ToggleButtonGroupContext.Provider, { value: { isError, variant, value }, children: children }));
5
5
  };
@@ -1,2 +1,3 @@
1
1
  export * from './ToggleButtonGroup';
2
2
  export * from './ToggleButtonGroupContext';
3
+ export type { ToggleButtonGroupProps } from './types';
@@ -1,2 +1,3 @@
1
1
  export * from './ToggleButtonGroup';
2
2
  export * from './ToggleButtonGroupContext';
3
+ export type { ToggleButtonGroupProps } from './types';
@@ -1,3 +1,8 @@
1
+ /// <reference types="react" />
2
+ export declare const ScrollContainer: import("../styled").StyledComponent<{
3
+ theme?: import("@emotion/react").Theme | undefined;
4
+ as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
5
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
1
6
  export declare const StyledToggleButtonGroup: import("../styled").StyledComponent<import("@mui/material/ToggleButtonGroup").ToggleButtonGroupProps & {
2
7
  theme?: import("@emotion/react").Theme | undefined;
3
8
  } & {
@@ -1,10 +1,27 @@
1
1
  import MuiToggleButtonGroup from '@mui/material/ToggleButtonGroup';
2
2
  import { styled } from '../styled';
3
+ export const ScrollContainer = styled.div `
4
+ overflow-x: auto;
5
+
6
+ ${({ theme }) => theme.breakpoints.down('sm')} {
7
+ /* Убираем видимую полосу прокрутки в firefox */
8
+ scrollbar-width: none;
9
+
10
+ width: 100%;
11
+
12
+ /* Убираем видимую полосу прокрутки в chrome */
13
+ &::-webkit-scrollbar {
14
+ display: none;
15
+ }
16
+ }
17
+ `;
3
18
  export const StyledToggleButtonGroup = styled(MuiToggleButtonGroup, {
4
19
  shouldForwardProp: (prop) => !['$isError'].includes(prop),
5
20
  }) `
6
21
  position: relative;
7
22
 
23
+ white-space: nowrap;
24
+
8
25
  /* Border для ToggleButtonGroup рисуется через ::after что бы не нарушать обводку кнопок внутри компонента и корректно отображать состояние ошибки */
9
26
  &::after {
10
27
  pointer-events: none;
@@ -0,0 +1,23 @@
1
+ import { type ToggleButtonGroupProps as MuiToggleButtonGroupProps } from '@mui/material/ToggleButtonGroup';
2
+ import { type ReactNode } from 'react';
3
+ import type { WithoutEmotionSpecific } from '../types/WithoutEmotionSpecific';
4
+ export type ToggleButtonGroupProps = WithoutEmotionSpecific<Omit<MuiToggleButtonGroupProps, 'orientation'>> & {
5
+ /**
6
+ * Если `true`, компонент будет отображаться в состоянии ошибки
7
+ */
8
+ isError?: boolean;
9
+ /**
10
+ * Текстовая информация об ошибке, будет отображен в тултипе при isError: true
11
+ */
12
+ errorText?: ReactNode;
13
+ /**
14
+ * Определяет стиль отображения группы кнопок
15
+ *
16
+ * - `transparent` — прозрачный фон кнопок ToggleButton
17
+ *
18
+ * - `plain` — белый фон кнопок ToggleButton
19
+ *
20
+ * @default transparent
21
+ */
22
+ variant?: 'transparent' | 'plain';
23
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export * from './useLogic';
@@ -0,0 +1 @@
1
+ export * from './useLogic';