@evergis/react 4.0.145 → 4.0.147
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.
- package/dist/components/Dashboard/elements/ElementTable/components/TableColumnResizer.d.ts +3 -2
- package/dist/components/Dashboard/elements/ElementTable/hooks/useColumnResize.d.ts +11 -7
- package/dist/components/Dashboard/elements/ElementTable/hooks/useTableView.d.ts +1 -1
- package/dist/components/Dashboard/elements/ElementTable/styled.d.ts +9 -5
- package/dist/components/Dashboard/elements/ElementTable/types.d.ts +3 -2
- package/dist/components/Dashboard/elements/ElementTable/utils/columnStyle.d.ts +10 -8
- package/dist/index.js +110 -62
- package/dist/index.js.map +1 -1
- package/dist/react.esm.js +110 -62
- package/dist/react.esm.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { FC } from 'react';
|
|
2
2
|
import { TableColumnResizerProps } from '../types';
|
|
3
3
|
/**
|
|
4
|
-
* Ручка ширины колонки на правой границе
|
|
4
|
+
* Ручка ширины колонки на правой границе ячейки.
|
|
5
5
|
*
|
|
6
6
|
* Тот же компонент и тот же жест, что двигают границы ячеек сетки дашборда: пользователю это одно
|
|
7
|
-
* и то же действие, и выглядеть оно обязано одинаково.
|
|
7
|
+
* и то же действие, и выглядеть оно обязано одинаково. Поэтому и стоит она у КАЖДОЙ ячейки
|
|
8
|
+
* колонки, как в сетке, — тянуть границу можно на любой строке, а не только в шапке.
|
|
8
9
|
*/
|
|
9
10
|
export declare const TableColumnResizer: FC<TableColumnResizerProps>;
|
|
@@ -2,18 +2,22 @@ import { ResizeDrag } from '../../../hooks/useResizeDrag';
|
|
|
2
2
|
interface UseColumnResizeParams {
|
|
3
3
|
/** Позиция колонки: по ней собрано имя переменной, которой колонка задаёт свою ширину. */
|
|
4
4
|
index: number;
|
|
5
|
-
|
|
5
|
+
/** Итог жеста — ширины ВСЕХ колонок по их позициям. */
|
|
6
|
+
onResize: (widths: number[]) => void;
|
|
6
7
|
}
|
|
7
8
|
/**
|
|
8
9
|
* Перетаскивание правой границы колонки.
|
|
9
10
|
*
|
|
10
11
|
* Жест — общий {@link useResizeDrag}, тот же, что двигает границы ячеек сетки дашборда. Здесь
|
|
11
|
-
* остаётся только табличное: во время жеста
|
|
12
|
-
* состояние
|
|
13
|
-
* а не перерисовывает таблицу целиком.
|
|
12
|
+
* остаётся только табличное: во время жеста ширины рисуются переменными на самой таблице, а в
|
|
13
|
+
* состояние уходят один раз, на отпускание мыши.
|
|
14
14
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
15
|
+
* Снимок берётся по ВСЕМ колонкам, и все они на время жеста фиксируются — так же, как сетка
|
|
16
|
+
* фиксирует все треки. Иначе автоматическая раскладка перераспределяла бы соседние колонки на
|
|
17
|
+
* первом же шаге, и таблицу дёргало бы в самом начале перетаскивания. По той же причине в
|
|
18
|
+
* состояние уходят ширины всех колонок: без этого соседи прыгнули бы обратно на отпускании.
|
|
19
|
+
*
|
|
20
|
+
* Ширины снимаются с ячеек шапки: колонка одна на всю таблицу, а строк в ней сколько угодно.
|
|
17
21
|
*/
|
|
18
|
-
export declare const useColumnResize: ({ index,
|
|
22
|
+
export declare const useColumnResize: ({ index, onResize }: UseColumnResizeParams) => ResizeDrag;
|
|
19
23
|
export {};
|
|
@@ -26,5 +26,5 @@ export declare const useTableView: (elementConfig?: ElementTableConfig) => {
|
|
|
26
26
|
contentWidth: boolean;
|
|
27
27
|
columnWidths: Record<string, number>;
|
|
28
28
|
onSortToggle: (attributeName: string) => void;
|
|
29
|
-
onColumnResize: (
|
|
29
|
+
onColumnResize: (next: number[]) => void;
|
|
30
30
|
};
|
|
@@ -31,14 +31,18 @@ export declare const TableWrapper: import('styled-components').StyledComponent<"
|
|
|
31
31
|
* (см. TableBody и useHeadOverlap).
|
|
32
32
|
*/
|
|
33
33
|
export declare const TableHead: import('styled-components').StyledComponent<"thead", any, {}, never>;
|
|
34
|
-
export declare const TableHeadCell: import('styled-components').StyledComponent<"th", any, {
|
|
35
|
-
$sortable?: boolean;
|
|
36
|
-
}, never>;
|
|
37
34
|
/**
|
|
38
|
-
* Содержимое
|
|
39
|
-
*
|
|
35
|
+
* Содержимое заголовка: псевдоним и место под значок сортировки.
|
|
36
|
+
*
|
|
37
|
+
* Само по себе не сжимается и ничего не обрезает — иначе перестало бы задавать минимальную
|
|
38
|
+
* ширину колонки, и раскладка считала бы её по одному лишь телу таблицы. Обрезку включает
|
|
39
|
+
* заголовок, и только когда ширина колонки задана явно (см. `TableHeadCell`).
|
|
40
40
|
*/
|
|
41
41
|
export declare const TableHeadContent: import('styled-components').StyledComponent<"span", any, {}, never>;
|
|
42
|
+
export declare const TableHeadCell: import('styled-components').StyledComponent<"th", any, {
|
|
43
|
+
$sortable?: boolean;
|
|
44
|
+
$fixedWidth?: boolean;
|
|
45
|
+
}, never>;
|
|
42
46
|
/**
|
|
43
47
|
* Место под значок сортировки. Занято всегда, пока сортировка включена, а сам значок только
|
|
44
48
|
* прячется: появляясь и исчезая, он менял бы ширину колонки — и таблицу дёргало бы на каждый
|
|
@@ -21,7 +21,8 @@ export interface TableCellProps {
|
|
|
21
21
|
export interface TableColumnResizerProps {
|
|
22
22
|
/** Позиция колонки: по ней собрано имя переменной, которой колонка задаёт свою ширину. */
|
|
23
23
|
index: number;
|
|
24
|
-
|
|
24
|
+
/** Итог жеста — ширины всех колонок по их позициям. */
|
|
25
|
+
onResize: (widths: number[]) => void;
|
|
25
26
|
}
|
|
26
27
|
export interface TableHeadRowProps {
|
|
27
28
|
columns: StructuredDataAttribute[];
|
|
@@ -32,5 +33,5 @@ export interface TableHeadRowProps {
|
|
|
32
33
|
/** У таблицы есть колонка действий — шапке нужна пустая ячейка над ней. */
|
|
33
34
|
withActionsColumn: boolean;
|
|
34
35
|
onSortToggle: (attributeName: string) => void;
|
|
35
|
-
onColumnResize: (
|
|
36
|
+
onColumnResize: (widths: number[]) => void;
|
|
36
37
|
}
|
|
@@ -3,17 +3,19 @@ import { CSSProperties } from 'react';
|
|
|
3
3
|
* Имя переменной ширины колонки.
|
|
4
4
|
*
|
|
5
5
|
* Через неё идёт и предпросмотр перетаскивания, и итоговая ширина: пока переменная не задана,
|
|
6
|
-
* работает запасное
|
|
7
|
-
*
|
|
6
|
+
* работает запасное значение, а жест на время перетаскивания объявляет её на самой таблице —
|
|
7
|
+
* одним свойством на один узел, как сетка меняет свой шаблон треков.
|
|
8
8
|
*/
|
|
9
9
|
export declare const getColumnWidthVariable: (index: number) => string;
|
|
10
10
|
/**
|
|
11
|
-
* Инлайн-размер ячейки
|
|
11
|
+
* Инлайн-размер ячейки колонки.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* Ставится всем колонкам, а не только тем, у кого ширина задана: жест фиксирует на время
|
|
14
|
+
* перетаскивания ВСЕ колонки, иначе соседние перераспределялись бы на первом же шаге и таблицу
|
|
15
|
+
* дёргало бы. Пока переменной нет, каждый предел падает на своё запасное значение и колонка
|
|
16
|
+
* ведёт себя ровно так, как вела бы без инлайн-стиля вовсе.
|
|
16
17
|
*
|
|
17
|
-
*
|
|
18
|
+
* Раскладка таблицы автоматическая (ширину колонок выбирает содержимое), и одной `width` ей мало —
|
|
19
|
+
* она для неё лишь пожелание. Жёстко колонку держат все три предела сразу.
|
|
18
20
|
*/
|
|
19
|
-
export declare const getColumnStyle: (index: number, width?: number,
|
|
21
|
+
export declare const getColumnStyle: (index: number, width?: number, isHead?: boolean) => CSSProperties;
|
package/dist/index.js
CHANGED
|
@@ -8170,6 +8170,23 @@ const useProjectDashboardInit = () => {
|
|
|
8170
8170
|
}, [projectInfo, updateProject]);
|
|
8171
8171
|
};
|
|
8172
8172
|
|
|
8173
|
+
/**
|
|
8174
|
+
* Съесть клик, которым закончилось перетаскивание.
|
|
8175
|
+
*
|
|
8176
|
+
* Мышь отпускают уже за пределами ручки, поэтому браузер шлёт `click` не ей, а общему предку —
|
|
8177
|
+
* ячейке или заголовку. Без этого перетаскивание границы заканчивалось бы сортировкой таблицы
|
|
8178
|
+
* по колонке или сменой выделения в сетке.
|
|
8179
|
+
*/
|
|
8180
|
+
const swallowNextClick = () => {
|
|
8181
|
+
const swallow = (event) => {
|
|
8182
|
+
event.stopPropagation();
|
|
8183
|
+
event.preventDefault();
|
|
8184
|
+
};
|
|
8185
|
+
window.addEventListener("click", swallow, { capture: true, once: true });
|
|
8186
|
+
// Клика может и не быть — например, мышь отпустили за пределами окна. Тогда снимаем слушатель
|
|
8187
|
+
// сами, иначе он съел бы следующий, уже осмысленный клик.
|
|
8188
|
+
window.setTimeout(() => window.removeEventListener("click", swallow, { capture: true }), 0);
|
|
8189
|
+
};
|
|
8173
8190
|
/**
|
|
8174
8191
|
* Перетаскивание границы: подписка на ручку, снимок на старте, предпросмотр на движении,
|
|
8175
8192
|
* запись результата на отпускании.
|
|
@@ -8182,6 +8199,7 @@ const useResizeDrag = ({ onStart, onMove, onEnd }) => {
|
|
|
8182
8199
|
const [handle, setHandle] = React.useState(null);
|
|
8183
8200
|
const [dragging, setDragging] = React.useState(false);
|
|
8184
8201
|
const stateRef = React.useRef(null);
|
|
8202
|
+
const movedRef = React.useRef(false);
|
|
8185
8203
|
const mouseDown = React.useCallback((event) => {
|
|
8186
8204
|
const state = onStart(event);
|
|
8187
8205
|
if (state === null) {
|
|
@@ -8191,10 +8209,12 @@ const useResizeDrag = ({ onStart, onMove, onEnd }) => {
|
|
|
8191
8209
|
// над чем проходит курсор.
|
|
8192
8210
|
event.preventDefault();
|
|
8193
8211
|
stateRef.current = state;
|
|
8212
|
+
movedRef.current = false;
|
|
8194
8213
|
setDragging(true);
|
|
8195
8214
|
}, [onStart]);
|
|
8196
8215
|
const mouseMove = React.useCallback((event) => {
|
|
8197
8216
|
if (stateRef.current !== null) {
|
|
8217
|
+
movedRef.current = true;
|
|
8198
8218
|
onMove(stateRef.current, event);
|
|
8199
8219
|
}
|
|
8200
8220
|
}, [onMove]);
|
|
@@ -8205,6 +8225,9 @@ const useResizeDrag = ({ onStart, onMove, onEnd }) => {
|
|
|
8205
8225
|
}
|
|
8206
8226
|
stateRef.current = null;
|
|
8207
8227
|
setDragging(false);
|
|
8228
|
+
if (movedRef.current) {
|
|
8229
|
+
swallowNextClick();
|
|
8230
|
+
}
|
|
8208
8231
|
onEnd(state, event);
|
|
8209
8232
|
}, [onEnd]);
|
|
8210
8233
|
uilibGl.useDragAndDropEffect(handle, { mouseDown, mouseMove, mouseUp });
|
|
@@ -15531,14 +15554,26 @@ const TableHead = styled.thead.withConfig({ displayName: "TableHead", componentI
|
|
|
15531
15554
|
top: 0;
|
|
15532
15555
|
z-index: 1;
|
|
15533
15556
|
`;
|
|
15534
|
-
|
|
15557
|
+
/**
|
|
15558
|
+
* Содержимое заголовка: псевдоним и место под значок сортировки.
|
|
15559
|
+
*
|
|
15560
|
+
* Само по себе не сжимается и ничего не обрезает — иначе перестало бы задавать минимальную
|
|
15561
|
+
* ширину колонки, и раскладка считала бы её по одному лишь телу таблицы. Обрезку включает
|
|
15562
|
+
* заголовок, и только когда ширина колонки задана явно (см. `TableHeadCell`).
|
|
15563
|
+
*/
|
|
15564
|
+
const TableHeadContent = styled.span.withConfig({ displayName: "TableHeadContent", componentId: "sc-19t325s" }) `
|
|
15565
|
+
display: flex;
|
|
15566
|
+
align-items: center;
|
|
15567
|
+
gap: 0.25rem;
|
|
15568
|
+
`;
|
|
15569
|
+
const TableHeadCell = styled.th.withConfig({ displayName: "TableHeadCell", componentId: "sc-19bpg7s" }) `
|
|
15535
15570
|
/* Относительное позиционирование держит захват границы колонки. */
|
|
15536
15571
|
position: relative;
|
|
15572
|
+
box-sizing: border-box;
|
|
15537
15573
|
padding: 0.375rem 0.5rem;
|
|
15538
15574
|
text-align: left;
|
|
15539
15575
|
font-weight: 600;
|
|
15540
15576
|
white-space: nowrap;
|
|
15541
|
-
overflow: hidden;
|
|
15542
15577
|
color: ${({ theme }) => theme.palette.textSecondary};
|
|
15543
15578
|
/* Рамка принадлежит ячейке (рамки раздельные), поэтому едет вместе с липкой шапкой. */
|
|
15544
15579
|
border-bottom: 1px solid ${({ theme }) => theme.palette.elementDeep};
|
|
@@ -15548,18 +15583,22 @@ const TableHeadCell = styled.th.withConfig({ displayName: "TableHeadCell", compo
|
|
|
15548
15583
|
cursor: pointer;
|
|
15549
15584
|
user-select: none;
|
|
15550
15585
|
`}
|
|
15551
|
-
|
|
15552
|
-
|
|
15553
|
-
|
|
15554
|
-
|
|
15555
|
-
|
|
15556
|
-
|
|
15557
|
-
|
|
15558
|
-
|
|
15559
|
-
|
|
15560
|
-
|
|
15561
|
-
|
|
15562
|
-
|
|
15586
|
+
|
|
15587
|
+
/*
|
|
15588
|
+
* Обрезка только у колонки с заданной шириной: там длинный псевдоним иначе выдавил бы значок
|
|
15589
|
+
* сортировки за край. У колонки без ширины обрезать нечего — её ширину и задаёт заголовок,
|
|
15590
|
+
* а сжатое содержимое отдало бы этот расчёт телу таблицы, и заголовок схлопнулся бы в ноль.
|
|
15591
|
+
*/
|
|
15592
|
+
${({ $fixedWidth }) => $fixedWidth &&
|
|
15593
|
+
styled.css `
|
|
15594
|
+
overflow: hidden;
|
|
15595
|
+
|
|
15596
|
+
${TableHeadContent} {
|
|
15597
|
+
min-width: 0;
|
|
15598
|
+
overflow: hidden;
|
|
15599
|
+
text-overflow: ellipsis;
|
|
15600
|
+
}
|
|
15601
|
+
`}
|
|
15563
15602
|
`;
|
|
15564
15603
|
/**
|
|
15565
15604
|
* Место под значок сортировки. Занято всегда, пока сортировка включена, а сам значок только
|
|
@@ -15589,6 +15628,10 @@ const TableRow = styled.tr.withConfig({ displayName: "TableRow", componentId: "s
|
|
|
15589
15628
|
}
|
|
15590
15629
|
`;
|
|
15591
15630
|
const TableCellWrapper = styled.td.withConfig({ displayName: "TableCellWrapper", componentId: "sc-ziu5rk" }) `
|
|
15631
|
+
/* Относительное позиционирование держит захват границы колонки. */
|
|
15632
|
+
position: relative;
|
|
15633
|
+
/* Как и у заголовка: ширина колонки считается по внешнему краю ячейки. */
|
|
15634
|
+
box-sizing: border-box;
|
|
15592
15635
|
padding: 0.125rem 0.25rem;
|
|
15593
15636
|
vertical-align: middle;
|
|
15594
15637
|
/* Предел снимает заданная ширина: с колонками по содержимому обрезать значение незачем. */
|
|
@@ -15928,30 +15971,30 @@ const TableCell = React.memo(({ attribute, row, canEdit, onChange }) => {
|
|
|
15928
15971
|
* Имя переменной ширины колонки.
|
|
15929
15972
|
*
|
|
15930
15973
|
* Через неё идёт и предпросмотр перетаскивания, и итоговая ширина: пока переменная не задана,
|
|
15931
|
-
* работает запасное
|
|
15932
|
-
*
|
|
15974
|
+
* работает запасное значение, а жест на время перетаскивания объявляет её на самой таблице —
|
|
15975
|
+
* одним свойством на один узел, как сетка меняет свой шаблон треков.
|
|
15933
15976
|
*/
|
|
15934
15977
|
const getColumnWidthVariable = (index) => `--table-col-${index}`;
|
|
15935
15978
|
/**
|
|
15936
|
-
* Инлайн-размер ячейки
|
|
15979
|
+
* Инлайн-размер ячейки колонки.
|
|
15937
15980
|
*
|
|
15938
|
-
*
|
|
15939
|
-
*
|
|
15940
|
-
*
|
|
15981
|
+
* Ставится всем колонкам, а не только тем, у кого ширина задана: жест фиксирует на время
|
|
15982
|
+
* перетаскивания ВСЕ колонки, иначе соседние перераспределялись бы на первом же шаге и таблицу
|
|
15983
|
+
* дёргало бы. Пока переменной нет, каждый предел падает на своё запасное значение и колонка
|
|
15984
|
+
* ведёт себя ровно так, как вела бы без инлайн-стиля вовсе.
|
|
15941
15985
|
*
|
|
15942
|
-
*
|
|
15986
|
+
* Раскладка таблицы автоматическая (ширину колонок выбирает содержимое), и одной `width` ей мало —
|
|
15987
|
+
* она для неё лишь пожелание. Жёстко колонку держат все три предела сразу.
|
|
15943
15988
|
*/
|
|
15944
|
-
const getColumnStyle = (index, width,
|
|
15945
|
-
if (width == null && !resizable) {
|
|
15946
|
-
return undefined;
|
|
15947
|
-
}
|
|
15989
|
+
const getColumnStyle = (index, width, isHead) => {
|
|
15948
15990
|
const variable = getColumnWidthVariable(index);
|
|
15949
15991
|
const fixed = width == null ? null : `${width}px`;
|
|
15950
15992
|
return {
|
|
15951
15993
|
width: `var(${variable}, ${fixed ?? "auto"})`,
|
|
15952
15994
|
minWidth: `var(${variable}, ${fixed ?? "0"})`,
|
|
15953
|
-
// Без заданной ширины предел остаётся
|
|
15954
|
-
|
|
15995
|
+
// Без заданной ширины предел остаётся тем, что задан стилем: у ячейки тела — общий предел
|
|
15996
|
+
// таблицы, у заголовка его нет вовсе.
|
|
15997
|
+
maxWidth: `var(${variable}, ${fixed ?? (isHead ? "none" : "var(--table-cell-max-width, 20rem)")})`,
|
|
15955
15998
|
};
|
|
15956
15999
|
};
|
|
15957
16000
|
|
|
@@ -15959,52 +16002,55 @@ const getColumnStyle = (index, width, resizable) => {
|
|
|
15959
16002
|
* Перетаскивание правой границы колонки.
|
|
15960
16003
|
*
|
|
15961
16004
|
* Жест — общий {@link useResizeDrag}, тот же, что двигает границы ячеек сетки дашборда. Здесь
|
|
15962
|
-
* остаётся только табличное: во время жеста
|
|
15963
|
-
* состояние
|
|
15964
|
-
* а не перерисовывает таблицу целиком.
|
|
16005
|
+
* остаётся только табличное: во время жеста ширины рисуются переменными на самой таблице, а в
|
|
16006
|
+
* состояние уходят один раз, на отпускание мыши.
|
|
15965
16007
|
*
|
|
15966
|
-
*
|
|
15967
|
-
*
|
|
16008
|
+
* Снимок берётся по ВСЕМ колонкам, и все они на время жеста фиксируются — так же, как сетка
|
|
16009
|
+
* фиксирует все треки. Иначе автоматическая раскладка перераспределяла бы соседние колонки на
|
|
16010
|
+
* первом же шаге, и таблицу дёргало бы в самом начале перетаскивания. По той же причине в
|
|
16011
|
+
* состояние уходят ширины всех колонок: без этого соседи прыгнули бы обратно на отпускании.
|
|
16012
|
+
*
|
|
16013
|
+
* Ширины снимаются с ячеек шапки: колонка одна на всю таблицу, а строк в ней сколько угодно.
|
|
15968
16014
|
*/
|
|
15969
|
-
const useColumnResize = ({ index,
|
|
15970
|
-
const variable = getColumnWidthVariable(index);
|
|
16015
|
+
const useColumnResize = ({ index, onResize }) => {
|
|
15971
16016
|
const onStart = React.useCallback((event) => {
|
|
15972
|
-
// Обработчик нажатия висит на самой ручке, поэтому
|
|
15973
|
-
//
|
|
15974
|
-
const
|
|
15975
|
-
|
|
16017
|
+
// Обработчик нажатия висит на самой ручке, поэтому таблица достаётся отсюда — отдельный
|
|
16018
|
+
// ref на неё не нужен.
|
|
16019
|
+
const table = event.currentTarget?.closest("table");
|
|
16020
|
+
const head = table?.querySelector("thead tr");
|
|
16021
|
+
if (!head) {
|
|
15976
16022
|
return null;
|
|
15977
16023
|
}
|
|
15978
|
-
|
|
15979
|
-
|
|
15980
|
-
|
|
15981
|
-
|
|
15982
|
-
|
|
15983
|
-
|
|
15984
|
-
const
|
|
15985
|
-
const onMove = React.useCallback((state, event) => state.table?.style.setProperty(variable, `${getNextWidth(state, event)}px`), [getNextWidth, variable]);
|
|
16024
|
+
const widths = Array.from(head.children).map(cell => cell.getBoundingClientRect().width);
|
|
16025
|
+
return widths[index] === undefined ? null : { start: event.clientX, widths, table };
|
|
16026
|
+
}, [index]);
|
|
16027
|
+
const getNextWidths = React.useCallback((state, event) => state.widths.map((width, position) => position === index
|
|
16028
|
+
? Math.max(MIN_COLUMN_WIDTH, Math.round(width + event.clientX - state.start))
|
|
16029
|
+
: Math.round(width)), [index]);
|
|
16030
|
+
const onMove = React.useCallback((state, event) => getNextWidths(state, event).forEach((width, position) => state.table?.style.setProperty(getColumnWidthVariable(position), `${width}px`)), [getNextWidths]);
|
|
15986
16031
|
const onEnd = React.useCallback((state, event) => {
|
|
15987
|
-
state.table?.style.removeProperty(
|
|
15988
|
-
const
|
|
16032
|
+
state.widths.forEach((_width, position) => state.table?.style.removeProperty(getColumnWidthVariable(position)));
|
|
16033
|
+
const widths = getNextWidths(state, event);
|
|
15989
16034
|
// Клик по границе без перетаскивания ширину менять не должен.
|
|
15990
|
-
if (
|
|
16035
|
+
if (widths[index] === Math.round(state.widths[index])) {
|
|
15991
16036
|
return;
|
|
15992
16037
|
}
|
|
15993
|
-
|
|
15994
|
-
}, [
|
|
16038
|
+
onResize(widths);
|
|
16039
|
+
}, [getNextWidths, index, onResize]);
|
|
15995
16040
|
return useResizeDrag({ onStart, onMove, onEnd });
|
|
15996
16041
|
};
|
|
15997
16042
|
|
|
15998
16043
|
/**
|
|
15999
|
-
* Ручка ширины колонки на правой границе
|
|
16044
|
+
* Ручка ширины колонки на правой границе ячейки.
|
|
16000
16045
|
*
|
|
16001
16046
|
* Тот же компонент и тот же жест, что двигают границы ячеек сетки дашборда: пользователю это одно
|
|
16002
|
-
* и то же действие, и выглядеть оно обязано одинаково.
|
|
16047
|
+
* и то же действие, и выглядеть оно обязано одинаково. Поэтому и стоит она у КАЖДОЙ ячейки
|
|
16048
|
+
* колонки, как в сетке, — тянуть границу можно на любой строке, а не только в шапке.
|
|
16003
16049
|
*/
|
|
16004
|
-
const TableColumnResizer = React.memo(({ index,
|
|
16005
|
-
const { setHandle, dragging } = useColumnResize({ index,
|
|
16006
|
-
// Ручка лежит внутри
|
|
16007
|
-
// кликом по
|
|
16050
|
+
const TableColumnResizer = React.memo(({ index, onResize }) => {
|
|
16051
|
+
const { setHandle, dragging } = useColumnResize({ index, onResize });
|
|
16052
|
+
// Ручка лежит внутри ячейки, и без остановки всплытия перетаскивание границы заканчивалось бы
|
|
16053
|
+
// кликом по ней — то есть переключало бы сортировку в шапке и открывало бы правку в теле.
|
|
16008
16054
|
const stopPropagation = React.useCallback((event) => event.stopPropagation(), []);
|
|
16009
16055
|
return jsxRuntime.jsx(ResizeHandle, { ref: setHandle, "$axis": "column", "data-dragging": dragging, onClick: stopPropagation });
|
|
16010
16056
|
});
|
|
@@ -16017,7 +16063,7 @@ const TableColumnResizer = React.memo(({ index, onCommit }) => {
|
|
|
16017
16063
|
*/
|
|
16018
16064
|
const TableHeadRow = ({ columns, sort, sortEnabled, columnWidths, withActionsColumn, onSortToggle, onColumnResize, }) => (jsxRuntime.jsxs("tr", { children: [columns.map(({ attributeName, alias, description, resizable }, index) => {
|
|
16019
16065
|
const sorted = sort?.attributeName === attributeName;
|
|
16020
|
-
return (jsxRuntime.jsxs(TableHeadCell, { title: description || alias, style: getColumnStyle(index, columnWidths[attributeName],
|
|
16066
|
+
return (jsxRuntime.jsxs(TableHeadCell, { title: description || alias, style: getColumnStyle(index, columnWidths[attributeName], true), "$sortable": sortEnabled, "$fixedWidth": columnWidths[attributeName] != null, onClick: sortEnabled ? () => onSortToggle(attributeName) : undefined, children: [jsxRuntime.jsxs(TableHeadContent, { children: [alias, sortEnabled && (jsxRuntime.jsx(TableSortSlot, { "$active": sorted, children: jsxRuntime.jsx(uilibGl.Icon, { kind: sorted && sort?.direction === "desc" ? "sorting_des" : "sorting_asc" }) }))] }), resizable && jsxRuntime.jsx(TableColumnResizer, { index: index, onResize: onColumnResize })] }, attributeName));
|
|
16021
16067
|
}), withActionsColumn && jsxRuntime.jsx(TableHeadCell, {})] }));
|
|
16022
16068
|
|
|
16023
16069
|
const ContainerLoading = () => (jsxRuntime.jsx(uilibGl.Flex, { alignContent: "center", justifyContent: "center", width: "100%", children: jsxRuntime.jsx(uilibGl.CircularProgress, { diameter: 1.5, mono: true }) }));
|
|
@@ -16152,7 +16198,9 @@ const useTableView = (elementConfig) => {
|
|
|
16152
16198
|
// Растянутая мышью ширина живёт только в рантайме и перебивает конфигурационную: последнее
|
|
16153
16199
|
// слово за тем, кто тянул. Обратно в конфиг она не пишется.
|
|
16154
16200
|
const columnWidths = React.useMemo(() => columns.reduce((acc, attribute) => ({ ...acc, [attribute.attributeName]: widths[attribute.attributeName] ?? attribute.width }), {}), [columns, widths]);
|
|
16155
|
-
|
|
16201
|
+
// Жест отдаёт ширины всех колонок разом: соседние он тоже фиксировал, и вернуть их к
|
|
16202
|
+
// автоподбору значило бы дёрнуть таблицу сразу после отпускания.
|
|
16203
|
+
const onColumnResize = React.useCallback((next) => setWidths(columns.reduce((acc, { attributeName }, position) => next[position] === undefined ? acc : { ...acc, [attributeName]: next[position] }, {})), [columns]);
|
|
16156
16204
|
const onSortToggle = React.useCallback((attributeName) => setSort(current => getNextSort(current, attributeName)), []);
|
|
16157
16205
|
return {
|
|
16158
16206
|
context,
|
|
@@ -16193,13 +16241,13 @@ const ElementTable = React.memo(({ elementConfig }) => {
|
|
|
16193
16241
|
defaultValue: "Схема данных не задана",
|
|
16194
16242
|
}) }));
|
|
16195
16243
|
}
|
|
16196
|
-
return (jsxRuntime.jsx(TableBox, { "$sizeCss": sizeCss, children: jsxRuntime.jsxs(TableWrapper, { ref: setTable, "$contentWidth": contentWidth, children: [jsxRuntime.jsx(TableHead, { children: jsxRuntime.jsx(TableHeadRow, { columns: columns, sort: sort, sortEnabled: sortEnabled, columnWidths: columnWidths, withActionsColumn: context.canDelete, onSortToggle: onSortToggle, onColumnResize: onColumnResize }) }), jsxRuntime.jsx(TableBody, { children: rows.map(row => (jsxRuntime.jsxs(TableRow, { children: [columns.map((attribute, columnIndex) => (jsxRuntime.
|
|
16244
|
+
return (jsxRuntime.jsx(TableBox, { "$sizeCss": sizeCss, children: jsxRuntime.jsxs(TableWrapper, { ref: setTable, "$contentWidth": contentWidth, children: [jsxRuntime.jsx(TableHead, { children: jsxRuntime.jsx(TableHeadRow, { columns: columns, sort: sort, sortEnabled: sortEnabled, columnWidths: columnWidths, withActionsColumn: context.canDelete, onSortToggle: onSortToggle, onColumnResize: onColumnResize }) }), jsxRuntime.jsx(TableBody, { children: rows.map(row => (jsxRuntime.jsxs(TableRow, { children: [columns.map((attribute, columnIndex) => (jsxRuntime.jsxs(TableCellWrapper, {
|
|
16197
16245
|
// Стиль колонки из конфига идёт последним: шрифт задан для значений, и ширину
|
|
16198
16246
|
// он не трогает — своих размеров у него нет.
|
|
16199
16247
|
style: {
|
|
16200
|
-
...getColumnStyle(columnIndex, columnWidths[attribute.attributeName]
|
|
16248
|
+
...getColumnStyle(columnIndex, columnWidths[attribute.attributeName]),
|
|
16201
16249
|
...attribute.style,
|
|
16202
|
-
}, children: jsxRuntime.jsx(TableCell, { attribute: attribute, row: row, canEdit: context.canEdit, onChange: context.onCellChange }) }, attribute.attributeName))), context.canDelete && (jsxRuntime.jsx(TableActionsCell, { children: jsxRuntime.jsx(uilibGl.IconButton, { kind: "delete", title: t("actions.delete", { ns: "common", defaultValue: "Удалить" }), onClick: () => context.onRowDelete(row.key) }) }))] }, row.key))) })] }) }));
|
|
16250
|
+
}, children: [jsxRuntime.jsx(TableCell, { attribute: attribute, row: row, canEdit: context.canEdit, onChange: context.onCellChange }), attribute.resizable && (jsxRuntime.jsx(TableColumnResizer, { index: columnIndex, onResize: onColumnResize }))] }, attribute.attributeName))), context.canDelete && (jsxRuntime.jsx(TableActionsCell, { children: jsxRuntime.jsx(uilibGl.IconButton, { kind: "delete", title: t("actions.delete", { ns: "common", defaultValue: "Удалить" }), onClick: () => context.onRowDelete(row.key) }) }))] }, row.key))) })] }) }));
|
|
16203
16251
|
});
|
|
16204
16252
|
|
|
16205
16253
|
const TooltipIcon = styled(uilibGl.Icon).withConfig({ displayName: "TooltipIcon", componentId: "sc-1lkxudm" }) `
|