@evergis/react 4.0.145 → 4.0.146

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.
@@ -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>;
@@ -12,8 +12,8 @@ interface UseColumnResizeParams {
12
12
  * состояние уходит один раз, на отпускание мыши. Так шаг жеста меняет одно свойство одного узла,
13
13
  * а не перерисовывает таблицу целиком.
14
14
  *
15
- * Стартовая ширина берётся с самой ячейки заголовка: у колонки без `width` её выбрала раскладка
16
- * таблицы, и тянуть надо от того, что видно.
15
+ * Стартовая ширина берётся с той ячейки, за границу которой потянули: у колонки без `width` её
16
+ * выбрала раскладка таблицы, и тянуть надо от того, что видно.
17
17
  */
18
18
  export declare const useColumnResize: ({ index, onCommit }: UseColumnResizeParams) => ResizeDrag;
19
19
  export {};
@@ -21,7 +21,8 @@ export interface TableCellProps {
21
21
  export interface TableColumnResizerProps {
22
22
  /** Позиция колонки: по ней собрано имя переменной, которой колонка задаёт свою ширину. */
23
23
  index: number;
24
- onCommit: (width: number) => void;
24
+ attributeName: string;
25
+ onResize: (attributeName: string, width: number) => void;
25
26
  }
26
27
  export interface TableHeadRowProps {
27
28
  columns: StructuredDataAttribute[];
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 });
@@ -15534,6 +15557,7 @@ const TableHead = styled.thead.withConfig({ displayName: "TableHead", componentI
15534
15557
  const TableHeadCell = styled.th.withConfig({ displayName: "TableHeadCell", componentId: "sc-1m6xil2" }) `
15535
15558
  /* Относительное позиционирование держит захват границы колонки. */
15536
15559
  position: relative;
15560
+ box-sizing: border-box;
15537
15561
  padding: 0.375rem 0.5rem;
15538
15562
  text-align: left;
15539
15563
  font-weight: 600;
@@ -15589,6 +15613,10 @@ const TableRow = styled.tr.withConfig({ displayName: "TableRow", componentId: "s
15589
15613
  }
15590
15614
  `;
15591
15615
  const TableCellWrapper = styled.td.withConfig({ displayName: "TableCellWrapper", componentId: "sc-ziu5rk" }) `
15616
+ /* Относительное позиционирование держит захват границы колонки. */
15617
+ position: relative;
15618
+ /* Как и у заголовка: ширина колонки считается по внешнему краю ячейки. */
15619
+ box-sizing: border-box;
15592
15620
  padding: 0.125rem 0.25rem;
15593
15621
  vertical-align: middle;
15594
15622
  /* Предел снимает заданная ширина: с колонками по содержимому обрезать значение незачем. */
@@ -15963,15 +15991,15 @@ const getColumnStyle = (index, width, resizable) => {
15963
15991
  * состояние уходит один раз, на отпускание мыши. Так шаг жеста меняет одно свойство одного узла,
15964
15992
  * а не перерисовывает таблицу целиком.
15965
15993
  *
15966
- * Стартовая ширина берётся с самой ячейки заголовка: у колонки без `width` её выбрала раскладка
15967
- * таблицы, и тянуть надо от того, что видно.
15994
+ * Стартовая ширина берётся с той ячейки, за границу которой потянули: у колонки без `width` её
15995
+ * выбрала раскладка таблицы, и тянуть надо от того, что видно.
15968
15996
  */
15969
15997
  const useColumnResize = ({ index, onCommit }) => {
15970
15998
  const variable = getColumnWidthVariable(index);
15971
15999
  const onStart = React.useCallback((event) => {
15972
16000
  // Обработчик нажатия висит на самой ручке, поэтому её ячейка и таблица достаются отсюда —
15973
- // отдельный ref на них не нужен.
15974
- const cell = event.currentTarget?.closest("th");
16001
+ // отдельный ref на них не нужен. Ячейка любая: ручки стоят и в шапке, и в каждой строке.
16002
+ const cell = event.currentTarget?.closest("th, td");
15975
16003
  if (!cell) {
15976
16004
  return null;
15977
16005
  }
@@ -15996,15 +16024,17 @@ const useColumnResize = ({ index, onCommit }) => {
15996
16024
  };
15997
16025
 
15998
16026
  /**
15999
- * Ручка ширины колонки на правой границе заголовка.
16027
+ * Ручка ширины колонки на правой границе ячейки.
16000
16028
  *
16001
16029
  * Тот же компонент и тот же жест, что двигают границы ячеек сетки дашборда: пользователю это одно
16002
- * и то же действие, и выглядеть оно обязано одинаково.
16030
+ * и то же действие, и выглядеть оно обязано одинаково. Поэтому и стоит она у КАЖДОЙ ячейки
16031
+ * колонки, как в сетке, — тянуть границу можно на любой строке, а не только в шапке.
16003
16032
  */
16004
- const TableColumnResizer = React.memo(({ index, onCommit }) => {
16033
+ const TableColumnResizer = React.memo(({ index, attributeName, onResize }) => {
16034
+ const onCommit = React.useCallback((width) => onResize(attributeName, width), [attributeName, onResize]);
16005
16035
  const { setHandle, dragging } = useColumnResize({ index, onCommit });
16006
- // Ручка лежит внутри заголовка, и без остановки всплытия перетаскивание границы заканчивалось бы
16007
- // кликом по нему — то есть переключало бы сортировку.
16036
+ // Ручка лежит внутри ячейки, и без остановки всплытия перетаскивание границы заканчивалось бы
16037
+ // кликом по ней — то есть переключало бы сортировку в шапке и открывало бы правку в теле.
16008
16038
  const stopPropagation = React.useCallback((event) => event.stopPropagation(), []);
16009
16039
  return jsxRuntime.jsx(ResizeHandle, { ref: setHandle, "$axis": "column", "data-dragging": dragging, onClick: stopPropagation });
16010
16040
  });
@@ -16017,7 +16047,7 @@ const TableColumnResizer = React.memo(({ index, onCommit }) => {
16017
16047
  */
16018
16048
  const TableHeadRow = ({ columns, sort, sortEnabled, columnWidths, withActionsColumn, onSortToggle, onColumnResize, }) => (jsxRuntime.jsxs("tr", { children: [columns.map(({ attributeName, alias, description, resizable }, index) => {
16019
16049
  const sorted = sort?.attributeName === attributeName;
16020
- return (jsxRuntime.jsxs(TableHeadCell, { title: description || alias, style: getColumnStyle(index, columnWidths[attributeName], resizable), "$sortable": sortEnabled, 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, onCommit: nextWidth => onColumnResize(attributeName, nextWidth) }))] }, attributeName));
16050
+ return (jsxRuntime.jsxs(TableHeadCell, { title: description || alias, style: getColumnStyle(index, columnWidths[attributeName], resizable), "$sortable": sortEnabled, 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, attributeName: attributeName, onResize: onColumnResize })] }, attributeName));
16021
16051
  }), withActionsColumn && jsxRuntime.jsx(TableHeadCell, {})] }));
16022
16052
 
16023
16053
  const ContainerLoading = () => (jsxRuntime.jsx(uilibGl.Flex, { alignContent: "center", justifyContent: "center", width: "100%", children: jsxRuntime.jsx(uilibGl.CircularProgress, { diameter: 1.5, mono: true }) }));
@@ -16193,13 +16223,13 @@ const ElementTable = React.memo(({ elementConfig }) => {
16193
16223
  defaultValue: "Схема данных не задана",
16194
16224
  }) }));
16195
16225
  }
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.jsx(TableCellWrapper, {
16226
+ 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
16227
  // Стиль колонки из конфига идёт последним: шрифт задан для значений, и ширину
16198
16228
  // он не трогает — своих размеров у него нет.
16199
16229
  style: {
16200
16230
  ...getColumnStyle(columnIndex, columnWidths[attribute.attributeName], attribute.resizable),
16201
16231
  ...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))) })] }) }));
16232
+ }, children: [jsxRuntime.jsx(TableCell, { attribute: attribute, row: row, canEdit: context.canEdit, onChange: context.onCellChange }), attribute.resizable && (jsxRuntime.jsx(TableColumnResizer, { index: columnIndex, attributeName: attribute.attributeName, 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
16233
  });
16204
16234
 
16205
16235
  const TooltipIcon = styled(uilibGl.Icon).withConfig({ displayName: "TooltipIcon", componentId: "sc-1lkxudm" }) `