@evergis/react 4.0.144 → 4.0.145

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/index.js CHANGED
@@ -8170,6 +8170,47 @@ const useProjectDashboardInit = () => {
8170
8170
  }, [projectInfo, updateProject]);
8171
8171
  };
8172
8172
 
8173
+ /**
8174
+ * Перетаскивание границы: подписка на ручку, снимок на старте, предпросмотр на движении,
8175
+ * запись результата на отпускании.
8176
+ *
8177
+ * Общий для сетки дашборда и колонок таблицы. Различаются они только тем, что именно меряют и
8178
+ * куда пишут; сам жест обязан ощущаться одинаково — включая то, что мышь ведут по документу, а
8179
+ * не по самой ручке, и отпускание за пределами окна тоже завершает жест.
8180
+ */
8181
+ const useResizeDrag = ({ onStart, onMove, onEnd }) => {
8182
+ const [handle, setHandle] = React.useState(null);
8183
+ const [dragging, setDragging] = React.useState(false);
8184
+ const stateRef = React.useRef(null);
8185
+ const mouseDown = React.useCallback((event) => {
8186
+ const state = onStart(event);
8187
+ if (state === null) {
8188
+ return;
8189
+ }
8190
+ // Гасим выделение текста: жест ведут мышью по документу, и без этого он выделял бы всё,
8191
+ // над чем проходит курсор.
8192
+ event.preventDefault();
8193
+ stateRef.current = state;
8194
+ setDragging(true);
8195
+ }, [onStart]);
8196
+ const mouseMove = React.useCallback((event) => {
8197
+ if (stateRef.current !== null) {
8198
+ onMove(stateRef.current, event);
8199
+ }
8200
+ }, [onMove]);
8201
+ const mouseUp = React.useCallback((event) => {
8202
+ const state = stateRef.current;
8203
+ if (state === null) {
8204
+ return;
8205
+ }
8206
+ stateRef.current = null;
8207
+ setDragging(false);
8208
+ onEnd(state, event);
8209
+ }, [onEnd]);
8210
+ uilibGl.useDragAndDropEffect(handle, { mouseDown, mouseMove, mouseUp });
8211
+ return { setHandle, dragging };
8212
+ };
8213
+
8173
8214
  const useRelatedDataSourceAttributes = ({ type = exports.WidgetType.Dashboard, elementConfig, dataSources, feature, }) => {
8174
8215
  const { layerInfos } = useWidgetContext(type);
8175
8216
  const { currentPage } = useWidgetPage(type);
@@ -9604,6 +9645,92 @@ const FiltersContainer = React.memo(({ elementConfig, config, type, renderElemen
9604
9645
  return (jsxRuntime.jsxs(ContainerRoot, { ...root, children: [jsxRuntime.jsx(ContainerBackground, { elementConfig: elementConfig, renderElement: renderElement }), jsxRuntime.jsx(uilibGl.Flex, { mb: !isVisible && selectedItems.length ? "2rem" : 0, children: jsxRuntime.jsx(ExpandableTitle, { elementConfig: elementConfig, type: type, renderElement: renderElement }) }), isLoading && jsxRuntime.jsx(ContainerLoading, {}), !isLoading && isVisible && (jsxRuntime.jsx(FiltersContainerWrapper, { ...body, "$padding": padding, "$bgColor": bgColor, "$fontSize": fontSize, "$fontColor": fontColor, children: filterItems?.map(renderFilter) })), jsxRuntime.jsx(HiddenTitleItems, { elementConfig: elementConfig, config: config, type: type, filter: filterItems[0]?.options?.filterName })] }));
9605
9646
  });
9606
9647
 
9648
+ /**
9649
+ * Заход зоны захвата на содержимое с каждой стороны границы, px.
9650
+ *
9651
+ * Без него попасть курсором ровно в границу невозможно: у таблицы её толщина — один пиксель,
9652
+ * а у сетки зазора может не быть вовсе. Ручка абсолютная и в раскладке не участвует, поэтому
9653
+ * расширение ничего не сдвигает.
9654
+ */
9655
+ const HANDLE_BLEED_PX = 3;
9656
+ /**
9657
+ * Маркер ручки: нажатие на ней тянет границу, а не ячейку сетки.
9658
+ *
9659
+ * Ставит его сам компонент. Ручка колонки таблицы, оказавшейся внутри ячейки сетки, обязана
9660
+ * помечаться так же — иначе нажатие на ней начинало бы перетаскивание всей ячейки.
9661
+ */
9662
+ const RESIZE_HANDLE_ATTR = "data-grid-handle";
9663
+
9664
+ /**
9665
+ * Зона захвата = зазор плюс небольшой заход на содержимое с обеих сторон.
9666
+ *
9667
+ * Смещение уводит дальний край ручки за зазор ровно на `HANDLE_BLEED_PX`, поэтому вместе с
9668
+ * шириной она оказывается симметрично «надета» на границу: от `-bleed` до `gap + bleed`.
9669
+ */
9670
+ const handleSize = `calc(var(--grid-gap, 0px) + ${HANDLE_BLEED_PX * 2}px)`;
9671
+ const handleOffset = `calc(-1 * (var(--grid-gap, 0px) + ${HANDLE_BLEED_PX}px))`;
9672
+ /**
9673
+ * Ручка перетаскивания границы. Общая для сетки дашборда и колонок таблицы: жест один и тот же,
9674
+ * и выглядеть он обязан одинаково.
9675
+ *
9676
+ * Абсолютная и целиком лежит в зазоре, поэтому включение режима редактирования не сдвигает
9677
+ * раскладку ни на пиксель. Сам ползунок (`::after`) появляется только при наведении и во время
9678
+ * перетаскивания — в покое раскладка выглядит как обычно.
9679
+ *
9680
+ * Ширину зазора берёт из переменной: у сетки её объявляет тело сетки, у таблицы зазора нет вовсе,
9681
+ * и зона захвата сжимается до одного захода на содержимое с каждой стороны.
9682
+ */
9683
+ const ResizeHandle = styled.div.attrs({ [RESIZE_HANDLE_ATTR]: true }).withConfig({ displayName: "ResizeHandle", componentId: "sc-1n6ja5b" }) `
9684
+ position: absolute;
9685
+ z-index: 3;
9686
+ touch-action: none;
9687
+
9688
+ ::after {
9689
+ content: "";
9690
+ position: absolute;
9691
+ border-radius: 0.0625rem;
9692
+ background: transparent;
9693
+ transition: background-color 120ms ease;
9694
+ }
9695
+
9696
+ :hover::after,
9697
+ &[data-dragging="true"]::after {
9698
+ background: ${({ theme: { palette } }) => palette.primary};
9699
+ }
9700
+
9701
+ ${({ $axis }) => $axis === "column"
9702
+ ? styled.css `
9703
+ top: 0;
9704
+ bottom: 0;
9705
+ right: ${handleOffset};
9706
+ width: ${handleSize};
9707
+ cursor: col-resize;
9708
+
9709
+ ::after {
9710
+ top: 20%;
9711
+ bottom: 20%;
9712
+ left: 50%;
9713
+ width: 0.125rem;
9714
+ transform: translateX(-50%);
9715
+ }
9716
+ `
9717
+ : styled.css `
9718
+ left: 0;
9719
+ right: 0;
9720
+ bottom: ${handleOffset};
9721
+ height: ${handleSize};
9722
+ cursor: row-resize;
9723
+
9724
+ ::after {
9725
+ left: 20%;
9726
+ right: 20%;
9727
+ top: 50%;
9728
+ height: 0.125rem;
9729
+ transform: translateY(-50%);
9730
+ }
9731
+ `};
9732
+ `;
9733
+
9607
9734
  /** Размер, при котором контейнер занимает всю ячейку родителя. */
9608
9735
  const FILL_SIZE = "100%";
9609
9736
  /** Собственные горизонтальные дефолты обёртки, мешающие контейнеру занять всю ширину ячейки. */
@@ -9683,6 +9810,7 @@ const getWrapperSizeStyle = ({ style, width: widthOption, height: heightOption,
9683
9810
  };
9684
9811
  };
9685
9812
 
9813
+ // Прямой импорт листового модуля, а не барреля components: тот тянет за собой контейнеры.
9686
9814
  /**
9687
9815
  * Минимальный размер трека, px. Ниже него ресайз не пускает — иначе ячейку не за что схватить.
9688
9816
  *
@@ -9718,14 +9846,6 @@ const GRID_AUTO_FILL_DEFAULTS = { ...CONTAINERS_GROUP_DEFAULTS, minHeight: FILL_
9718
9846
  * раскладки, поэтому задаётся явно через `options.gap`, а не навязывается всем сеткам.
9719
9847
  */
9720
9848
  const DEFAULT_GRID_GAP = 0;
9721
- /**
9722
- * Насколько ручка ресайза заходит на содержимое с каждой стороны, px.
9723
- *
9724
- * По умолчанию зазора нет вовсе, так что попасть курсором ровно в границу невозможно — зона
9725
- * захвата всегда шире зазора на эту величину с каждой стороны. Ручка абсолютная и в раскладке
9726
- * не участвует, поэтому расширение ничего не сдвигает.
9727
- */
9728
- const HANDLE_BLEED_PX = 3;
9729
9849
  /**
9730
9850
  * Сдвиг курсора, после которого нажатие на ячейке считается перетаскиванием, px.
9731
9851
  *
@@ -9735,17 +9855,13 @@ const HANDLE_BLEED_PX = 3;
9735
9855
  const DRAG_THRESHOLD_PX = 4;
9736
9856
  /** Маркер ячейки в DOM: по нему ищется цель перетаскивания под курсором. */
9737
9857
  const GRID_CELL_ATTR = "data-grid-cell";
9738
- /** Маркер ручки ресайза: нажатие на ней тянет границу, а не ячейку. */
9739
- const GRID_HANDLE_ATTR = "data-grid-handle";
9740
- /** Тот же маркер пропсами: имя атрибута вычисляемое, а в JSX такое подставляется только спредом. */
9741
- const GRID_HANDLE_PROPS = { [GRID_HANDLE_ATTR]: true };
9742
9858
  /**
9743
9859
  * Нажатия, которые перетаскиванием ячейки не считаются.
9744
9860
  *
9745
9861
  * Ручка тянет границу трека, а поля ввода живут своей жизнью: там нажатие ставит каретку и
9746
9862
  * выделяет текст, и подменять это перестановкой ячеек нельзя.
9747
9863
  */
9748
- const NO_CELL_DRAG_SELECTOR = `[${GRID_HANDLE_ATTR}], input, textarea, select, [contenteditable="true"]`;
9864
+ const NO_CELL_DRAG_SELECTOR = `[${RESIZE_HANDLE_ATTR}], input, textarea, select, [contenteditable="true"]`;
9749
9865
  /**
9750
9866
  * Разметка идущего жеста: ячейка-источник, цель под курсором и сам факт перетаскивания.
9751
9867
  *
@@ -9766,72 +9882,6 @@ const FR_PRECISION = 1000;
9766
9882
  const GRID_ROW_ID_PREFIX = "gridRow_";
9767
9883
  const GRID_CELL_ID_PREFIX = "gridCell_";
9768
9884
 
9769
- /**
9770
- * Зона захвата = зазор плюс небольшой заход на содержимое с обеих сторон.
9771
- *
9772
- * Смещение уводит дальний край ручки за зазор ровно на `HANDLE_BLEED_PX`, поэтому вместе с
9773
- * шириной она оказывается симметрично «надета» на границу: от `-bleed` до `gap + bleed`.
9774
- */
9775
- const handleSize = `calc(var(--grid-gap, 0px) + ${HANDLE_BLEED_PX * 2}px)`;
9776
- const handleOffset = `calc(-1 * (var(--grid-gap, 0px) + ${HANDLE_BLEED_PX}px))`;
9777
- /**
9778
- * Ручка перетаскивания границы треков.
9779
- *
9780
- * Абсолютная и целиком лежит в зазоре, поэтому включение режима редактирования не сдвигает
9781
- * раскладку ни на пиксель. Сам ползунок (`::after`) появляется только при наведении и во время
9782
- * перетаскивания — в покое сетка выглядит как обычно.
9783
- */
9784
- const ResizeHandle = styled.div.withConfig({ displayName: "ResizeHandle", componentId: "sc-1dtcak4" }) `
9785
- position: absolute;
9786
- z-index: 3;
9787
- touch-action: none;
9788
-
9789
- ::after {
9790
- content: "";
9791
- position: absolute;
9792
- border-radius: 0.0625rem;
9793
- background: transparent;
9794
- transition: background-color 120ms ease;
9795
- }
9796
-
9797
- :hover::after,
9798
- &[data-dragging="true"]::after {
9799
- background: ${({ theme: { palette } }) => palette.primary};
9800
- }
9801
-
9802
- ${({ $axis }) => $axis === "column"
9803
- ? styled.css `
9804
- top: 0;
9805
- bottom: 0;
9806
- right: ${handleOffset};
9807
- width: ${handleSize};
9808
- cursor: col-resize;
9809
-
9810
- ::after {
9811
- top: 20%;
9812
- bottom: 20%;
9813
- left: 50%;
9814
- width: 0.125rem;
9815
- transform: translateX(-50%);
9816
- }
9817
- `
9818
- : styled.css `
9819
- left: 0;
9820
- right: 0;
9821
- bottom: ${handleOffset};
9822
- height: ${handleSize};
9823
- cursor: row-resize;
9824
-
9825
- ::after {
9826
- left: 20%;
9827
- right: 20%;
9828
- top: 50%;
9829
- height: 0.125rem;
9830
- transform: translateY(-50%);
9831
- }
9832
- `};
9833
- `;
9834
-
9835
9885
  const getTemplateProperty = (axis) => axis === "row" ? "gridTemplateRows" : "gridTemplateColumns";
9836
9886
  /**
9837
9887
  * Пиксельные размеры треков отрисованной сетки.
@@ -9919,29 +9969,24 @@ const toShares = (pixels, total) => {
9919
9969
  * снова раздувалась содержимым.
9920
9970
  */
9921
9971
  const useGridHeightResize = ({ sizes, autoHeight, getGrid, onCommit, }) => {
9922
- const [handle, setHandle] = React.useState(null);
9923
- const [dragging, setDragging] = React.useState(false);
9924
- const dragRef = React.useRef(null);
9925
9972
  const sizesRef = React.useRef(sizes);
9926
9973
  sizesRef.current = sizes;
9927
9974
  /** Свойство корня, которым жест двигает нижнюю границу: жёсткая высота либо её минимум. */
9928
9975
  const heightProperty = autoHeight ? "minHeight" : "height";
9929
- const mouseDown = React.useCallback((event) => {
9976
+ const onStart = React.useCallback((event) => {
9930
9977
  const grid = getGrid();
9931
9978
  const root = grid?.parentElement;
9932
9979
  if (!grid || !root)
9933
- return;
9980
+ return null;
9934
9981
  const pixels = readTrackPixels(grid, "row");
9935
9982
  if (!pixels?.length || pixels.length !== sizesRef.current.length)
9936
- return;
9937
- event.preventDefault();
9938
- dragRef.current = {
9983
+ return null;
9984
+ return {
9939
9985
  start: event.clientY,
9940
9986
  pixels,
9941
9987
  root,
9942
9988
  rootHeight: root.getBoundingClientRect().height,
9943
9989
  };
9944
- setDragging(true);
9945
9990
  }, [getGrid]);
9946
9991
  /** Пиксели треков после сдвига: меняется только последний, минимум — текущий, если он уже мал. */
9947
9992
  const getNextPixels = React.useCallback((state, event) => {
@@ -9949,22 +9994,16 @@ const useGridHeightResize = ({ sizes, autoHeight, getGrid, onCommit, }) => {
9949
9994
  const min = Math.min(MIN_TRACK_PX, last);
9950
9995
  return [...state.pixels.slice(0, -1), Math.max(last + event.clientY - state.start, min)];
9951
9996
  }, []);
9952
- const mouseMove = React.useCallback((event) => {
9953
- const state = dragRef.current;
9997
+ const onMove = React.useCallback((state, event) => {
9954
9998
  const grid = getGrid();
9955
- if (!state || !grid)
9999
+ if (!grid)
9956
10000
  return;
9957
10001
  const pixels = getNextPixels(state, event);
9958
10002
  const delta = pixels[pixels.length - 1] - state.pixels[state.pixels.length - 1];
9959
10003
  state.root.style[heightProperty] = `${state.rootHeight + delta}px`;
9960
10004
  grid.style[getTemplateProperty("row")] = buildTrackTemplate(pixels.map(size => `${size}px`), autoHeight);
9961
10005
  }, [autoHeight, getGrid, getNextPixels, heightProperty]);
9962
- const mouseUp = React.useCallback((event) => {
9963
- const state = dragRef.current;
9964
- if (!state)
9965
- return;
9966
- dragRef.current = null;
9967
- setDragging(false);
10006
+ const onEnd = React.useCallback((state, event) => {
9968
10007
  const grid = getGrid();
9969
10008
  if (grid)
9970
10009
  grid.style[getTemplateProperty("row")] = "";
@@ -9976,8 +10015,7 @@ const useGridHeightResize = ({ sizes, autoHeight, getGrid, onCommit, }) => {
9976
10015
  const total = sizesRef.current.reduce((value, size) => value + size, 0);
9977
10016
  onCommit(`${Math.round(state.rootHeight + delta)}px`, toShares(pixels, total));
9978
10017
  }, [getGrid, getNextPixels, heightProperty, onCommit]);
9979
- uilibGl.useDragAndDropEffect(handle, { mouseDown, mouseMove, mouseUp });
9980
- return { setHandle, dragging };
10018
+ return useResizeDrag({ onStart, onMove, onEnd });
9981
10019
  };
9982
10020
 
9983
10021
  /**
@@ -9990,7 +10028,7 @@ const GridHeightResizer = React.memo(({ sizes, autoHeight, getGrid, onCommit })
9990
10028
  // Ручка лежит внутри трека: без остановки всплытия перетаскивание границы заканчивалось бы
9991
10029
  // кликом по ячейке, то есть меняло бы выделение.
9992
10030
  const stopPropagation = React.useCallback((event) => event.stopPropagation(), []);
9993
- return (jsxRuntime.jsx(ResizeHandle, { ...GRID_HANDLE_PROPS, ref: setHandle, "$axis": "row", "data-dragging": dragging, onClick: stopPropagation }));
10031
+ return (jsxRuntime.jsx(ResizeHandle, { ref: setHandle, "$axis": "row", "data-dragging": dragging, onClick: stopPropagation }));
9994
10032
  });
9995
10033
 
9996
10034
  const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
@@ -10011,31 +10049,26 @@ const buildPreviewTemplate = (pixels, index, first, second) => buildTrackTemplat
10011
10049
  /**
10012
10050
  * Перетаскивание границы между двумя соседними треками.
10013
10051
  *
10014
- * Во время жеста раскладка меняется ИНЛАЙН-стилем на самом гриде, без обновления состояния:
10015
- * каждый `mousemove` иначе перерисовывал бы всё поддерево сетки. В конфиг доли уходят один раз,
10016
- * на отпускание мыши.
10052
+ * Сам жест общий {@link useResizeDrag}: он же двигает и границы колонок таблицы, поэтому
10053
+ * ощущаются они одинаково. Здесь остаётся только грид-специфичное: во время жеста раскладка
10054
+ * меняется ИНЛАЙН-стилем на самом гриде, а в конфиг доли уходят один раз, на отпускание мыши.
10017
10055
  *
10018
- * Пиксельный снимок треков берётся однократно на `mousedown` — если пересчитывать его на каждом
10056
+ * Пиксельный снимок треков берётся однократно на нажатии — если пересчитывать его на каждом
10019
10057
  * шаге уже после применения новых долей, округление `fr → px → fr` даёт дрейф границы.
10020
10058
  */
10021
10059
  const useGridResize = ({ axis, index, sizes, getGrid, onCommit }) => {
10022
- const [handle, setHandle] = React.useState(null);
10023
- const [dragging, setDragging] = React.useState(false);
10024
- const dragRef = React.useRef(null);
10025
10060
  const sizesRef = React.useRef(sizes);
10026
10061
  sizesRef.current = sizes;
10027
10062
  const isRow = axis === "row";
10028
10063
  const getPosition = React.useCallback((event) => (isRow ? event.clientY : event.clientX), [isRow]);
10029
- const mouseDown = React.useCallback((event) => {
10064
+ const onStart = React.useCallback((event) => {
10030
10065
  const grid = getGrid();
10031
10066
  if (!grid)
10032
- return;
10067
+ return null;
10033
10068
  const pixels = readTrackPixels(grid, axis);
10034
10069
  if (!pixels || index + 1 >= pixels.length)
10035
- return;
10036
- event.preventDefault();
10037
- dragRef.current = { start: getPosition(event), pixels };
10038
- setDragging(true);
10070
+ return null;
10071
+ return { start: getPosition(event), pixels };
10039
10072
  }, [axis, getGrid, getPosition, index]);
10040
10073
  /** Новый пиксельный размер первого трека пары с учётом минимального размера обоих. */
10041
10074
  const getNextFirstSize = React.useCallback((state, event) => {
@@ -10046,10 +10079,9 @@ const useGridResize = ({ axis, index, sizes, getGrid, onCommit }) => {
10046
10079
  const min = getMinTrackSize(total);
10047
10080
  return clamp(first + getPosition(event) - state.start, min, total - min);
10048
10081
  }, [getPosition, index]);
10049
- const mouseMove = React.useCallback((event) => {
10050
- const state = dragRef.current;
10082
+ const onMove = React.useCallback((state, event) => {
10051
10083
  const grid = getGrid();
10052
- if (!state || !grid)
10084
+ if (!grid)
10053
10085
  return;
10054
10086
  const first = getNextFirstSize(state, event);
10055
10087
  if (first === null)
@@ -10057,12 +10089,7 @@ const useGridResize = ({ axis, index, sizes, getGrid, onCommit }) => {
10057
10089
  const total = state.pixels[index] + state.pixels[index + 1];
10058
10090
  grid.style[getTemplateProperty(axis)] = buildPreviewTemplate(state.pixels, index, first, total - first);
10059
10091
  }, [axis, getGrid, getNextFirstSize, index]);
10060
- const mouseUp = React.useCallback((event) => {
10061
- const state = dragRef.current;
10062
- if (!state)
10063
- return;
10064
- dragRef.current = null;
10065
- setDragging(false);
10092
+ const onEnd = React.useCallback((state, event) => {
10066
10093
  const grid = getGrid();
10067
10094
  if (grid)
10068
10095
  grid.style[getTemplateProperty(axis)] = "";
@@ -10077,8 +10104,7 @@ const useGridResize = ({ axis, index, sizes, getGrid, onCommit }) => {
10077
10104
  return;
10078
10105
  onCommit(index, [nextFirst, roundFr(share - nextFirst)]);
10079
10106
  }, [axis, getGrid, getNextFirstSize, index, onCommit]);
10080
- uilibGl.useDragAndDropEffect(handle, { mouseDown, mouseMove, mouseUp });
10081
- return { setHandle, dragging };
10107
+ return useResizeDrag({ onStart, onMove, onEnd });
10082
10108
  };
10083
10109
 
10084
10110
  const GridResizer = React.memo(({ axis, index, sizes, getGrid, onCommit }) => {
@@ -10086,7 +10112,7 @@ const GridResizer = React.memo(({ axis, index, sizes, getGrid, onCommit }) => {
10086
10112
  // Ручка лежит внутри трека, и без этого перетаскивание границы заканчивалось бы кликом
10087
10113
  // по ячейке — то есть меняло бы выделение.
10088
10114
  const stopPropagation = React.useCallback((event) => event.stopPropagation(), []);
10089
- return (jsxRuntime.jsx(ResizeHandle, { ...GRID_HANDLE_PROPS, ref: setHandle, "$axis": axis, "data-dragging": dragging, onClick: stopPropagation }));
10115
+ return (jsxRuntime.jsx(ResizeHandle, { ref: setHandle, "$axis": axis, "data-dragging": dragging, onClick: stopPropagation }));
10090
10116
  });
10091
10117
 
10092
10118
  /**
@@ -15506,7 +15532,7 @@ const TableHead = styled.thead.withConfig({ displayName: "TableHead", componentI
15506
15532
  z-index: 1;
15507
15533
  `;
15508
15534
  const TableHeadCell = styled.th.withConfig({ displayName: "TableHeadCell", componentId: "sc-1m6xil2" }) `
15509
- /* Относительное позиционирование держит захват границы колонки (TableResizeHandle). */
15535
+ /* Относительное позиционирование держит захват границы колонки. */
15510
15536
  position: relative;
15511
15537
  padding: 0.375rem 0.5rem;
15512
15538
  text-align: left;
@@ -15535,33 +15561,13 @@ const TableHeadContent = styled.span.withConfig({ displayName: "TableHeadContent
15535
15561
  overflow: hidden;
15536
15562
  text-overflow: ellipsis;
15537
15563
  `;
15538
- /**
15539
- * Захват правой границы колонки. Лежит поверх края ячейки и ловит указатель сам, поэтому
15540
- * перетаскивание не доходит до заголовка и не переключает сортировку.
15541
- *
15542
- * Ширина в пикселах, а не в rem: это зона попадания курсора, и от размера шрифта она не зависит.
15543
- */
15544
- const TableResizeHandle = styled.span.withConfig({ displayName: "TableResizeHandle", componentId: "sc-1g0q105" }) `
15545
- position: absolute;
15546
- top: 0;
15547
- right: 0;
15548
- bottom: 0;
15549
- width: 8px;
15550
- cursor: col-resize;
15551
- touch-action: none;
15552
- user-select: none;
15553
-
15554
- :hover {
15555
- background: ${({ theme }) => theme.palette.elementDeep};
15556
- }
15557
- `;
15558
15564
  /**
15559
15565
  * Место под значок сортировки. Занято всегда, пока сортировка включена, а сам значок только
15560
15566
  * прячется: появляясь и исчезая, он менял бы ширину колонки — и таблицу дёргало бы на каждый
15561
15567
  * клик по заголовку, вместе с телом. Оба направления рисуются значком в 1rem, поэтому
15562
15568
  * переключение asc/des ширину тоже не трогает.
15563
15569
  */
15564
- const TableSortSlot = styled.span.withConfig({ displayName: "TableSortSlot", componentId: "sc-1ceykgw" }) `
15570
+ const TableSortSlot = styled.span.withConfig({ displayName: "TableSortSlot", componentId: "sc-z378vf" }) `
15565
15571
  display: inline-flex;
15566
15572
  visibility: ${({ $active }) => ($active ? "visible" : "hidden")};
15567
15573
  `;
@@ -15570,26 +15576,26 @@ const TableSortSlot = styled.span.withConfig({ displayName: "TableSortSlot", com
15570
15576
  * её нижнюю кромку и сквозь прозрачную шапку не проступают. Величину пишет {@link useHeadOverlap},
15571
15577
  * без неё отсечка нулевая и разметка не меняется.
15572
15578
  */
15573
- const TableBody = styled.tbody.withConfig({ displayName: "TableBody", componentId: "sc-c9drzt" }) `
15579
+ const TableBody = styled.tbody.withConfig({ displayName: "TableBody", componentId: "sc-1pxpl5v" }) `
15574
15580
  clip-path: inset(var(${HEAD_OVERLAP_VARIABLE}, 0px) 0 0 0);
15575
15581
  `;
15576
15582
  /**
15577
15583
  * Строка. Разделитель рисуют её ячейки: собственная рамка строки при раздельных рамках не
15578
15584
  * рисуется вовсе, а при схлопнутых её рисовала бы таблица — и отсечка тела её бы не резала.
15579
15585
  */
15580
- const TableRow = styled.tr.withConfig({ displayName: "TableRow", componentId: "sc-155nkv8" }) `
15586
+ const TableRow = styled.tr.withConfig({ displayName: "TableRow", componentId: "sc-j62zvd" }) `
15581
15587
  td {
15582
15588
  border-bottom: 1px solid ${({ theme }) => theme.palette.elementDeep};
15583
15589
  }
15584
15590
  `;
15585
- const TableCellWrapper = styled.td.withConfig({ displayName: "TableCellWrapper", componentId: "sc-7ueth1" }) `
15591
+ const TableCellWrapper = styled.td.withConfig({ displayName: "TableCellWrapper", componentId: "sc-ziu5rk" }) `
15586
15592
  padding: 0.125rem 0.25rem;
15587
15593
  vertical-align: middle;
15588
15594
  /* Предел снимает заданная ширина: с колонками по содержимому обрезать значение незачем. */
15589
15595
  max-width: var(--table-cell-max-width, 20rem);
15590
15596
  `;
15591
15597
  /** Колонка действий: узкая, не растягивается содержимым. */
15592
- const TableActionsCell = styled(TableCellWrapper).withConfig({ displayName: "TableActionsCell", componentId: "sc-1m7p53b" }) `
15598
+ const TableActionsCell = styled(TableCellWrapper).withConfig({ displayName: "TableActionsCell", componentId: "sc-18w13t3" }) `
15593
15599
  width: 2rem;
15594
15600
  text-align: right;
15595
15601
  `;
@@ -15612,7 +15618,7 @@ const cellWrapMixin = styled.css `
15612
15618
  white-space: nowrap;
15613
15619
  `}
15614
15620
  `;
15615
- const CellText = styled.div.withConfig({ displayName: "CellText", componentId: "sc-19uakee" }) `
15621
+ const CellText = styled.div.withConfig({ displayName: "CellText", componentId: "sc-ok630s" }) `
15616
15622
  padding: 0.375rem 0.25rem;
15617
15623
  /* Та же высота строки, что у редактора — иначе строка подпрыгивала бы по вертикали. */
15618
15624
  line-height: 1.25rem;
@@ -15626,7 +15632,7 @@ const CellText = styled.div.withConfig({ displayName: "CellText", componentId: "
15626
15632
  * Кнопка, а не просто текст, именно ради фокуса: она — таб-стоп ячейки, и Tab по таблице
15627
15633
  * открывает редактор с курсором внутри.
15628
15634
  */
15629
- const CellButton = styled.button.withConfig({ displayName: "CellButton", componentId: "sc-16lgve4" }) `
15635
+ const CellButton = styled.button.withConfig({ displayName: "CellButton", componentId: "sc-98k9cz" }) `
15630
15636
  width: 100%;
15631
15637
  padding: 0.375rem 0.25rem;
15632
15638
  line-height: 1.25rem;
@@ -15644,7 +15650,7 @@ const CellButton = styled.button.withConfig({ displayName: "CellButton", compone
15644
15650
  border-color: ${({ theme }) => theme.palette.elementDeep};
15645
15651
  }
15646
15652
  `;
15647
- const CellPlaceholder = styled.span.withConfig({ displayName: "CellPlaceholder", componentId: "sc-1jnsjad" }) `
15653
+ const CellPlaceholder = styled.span.withConfig({ displayName: "CellPlaceholder", componentId: "sc-7tff41" }) `
15648
15654
  color: ${({ theme }) => theme.palette.textSecondary};
15649
15655
  `;
15650
15656
  /**
@@ -15653,11 +15659,11 @@ const CellPlaceholder = styled.span.withConfig({ displayName: "CellPlaceholder",
15653
15659
  * Копия остаётся в потоке и держит ширину колонки ровно такой, какой она была до клика, —
15654
15660
  * иначе таблица дёргалась бы на каждый вход в правку и выход из неё.
15655
15661
  */
15656
- const CellEditor = styled.div.withConfig({ displayName: "CellEditor", componentId: "sc-ee08kh" }) `
15662
+ const CellEditor = styled.div.withConfig({ displayName: "CellEditor", componentId: "sc-qa22du" }) `
15657
15663
  position: relative;
15658
15664
  min-height: 2rem;
15659
15665
  `;
15660
- const CellGhost = styled.span.withConfig({ displayName: "CellGhost", componentId: "sc-1p10qm6" }) `
15666
+ const CellGhost = styled.span.withConfig({ displayName: "CellGhost", componentId: "sc-1i1yvb2" }) `
15661
15667
  display: block;
15662
15668
  padding: 0.375rem 0.25rem;
15663
15669
  /* Рамка повторяет CellButton — с ней высота ячейки в правке совпадает с высотой на чтении. */
@@ -15667,7 +15673,7 @@ const CellGhost = styled.span.withConfig({ displayName: "CellGhost", componentId
15667
15673
 
15668
15674
  ${cellWrapMixin};
15669
15675
  `;
15670
- const CellField = styled.div.withConfig({ displayName: "CellField", componentId: "sc-cnkcp6" }) `
15676
+ const CellField = styled.div.withConfig({ displayName: "CellField", componentId: "sc-1ww3875" }) `
15671
15677
  position: absolute;
15672
15678
  inset: 0;
15673
15679
  display: flex;
@@ -15689,14 +15695,14 @@ const CellField = styled.div.withConfig({ displayName: "CellField", componentId:
15689
15695
  * Отступы те же, что у текстовой ячейки (`CellText`): в одном ряду с обычными колонками значения
15690
15696
  * обязаны стоять на одной линии.
15691
15697
  */
15692
- const AttachmentsCellBox = styled.div.withConfig({ displayName: "AttachmentsCellBox", componentId: "sc-9n5afp" }) `
15698
+ const AttachmentsCellBox = styled.div.withConfig({ displayName: "AttachmentsCellBox", componentId: "sc-1ayq7sq" }) `
15693
15699
  display: flex;
15694
15700
  flex-direction: column;
15695
15701
  align-items: flex-start;
15696
15702
  gap: 0.25rem;
15697
15703
  padding: 0.375rem 0.25rem;
15698
15704
  `;
15699
- const TableEmpty = styled.div.withConfig({ displayName: "TableEmpty", componentId: "sc-1c196zb" }) `
15705
+ const TableEmpty = styled.div.withConfig({ displayName: "TableEmpty", componentId: "sc-dmdhrv" }) `
15700
15706
  padding: 0.75rem 0.25rem;
15701
15707
  color: ${({ theme }) => theme.palette.textSecondary};
15702
15708
  `;
@@ -15919,15 +15925,89 @@ const TableCell = React.memo(({ attribute, row, canEdit, onChange }) => {
15919
15925
  });
15920
15926
 
15921
15927
  /**
15922
- * Инлайн-размер ячейки колонки с заданной шириной.
15928
+ * Имя переменной ширины колонки.
15929
+ *
15930
+ * Через неё идёт и предпросмотр перетаскивания, и итоговая ширина: пока переменная не задана,
15931
+ * работает запасное значение из стиля ячейки, а жест на время перетаскивания объявляет её на
15932
+ * самой таблице — одним свойством на один узел, как сетка меняет свой шаблон треков.
15933
+ */
15934
+ const getColumnWidthVariable = (index) => `--table-col-${index}`;
15935
+ /**
15936
+ * Инлайн-размер ячейки колонки с заданной или изменяемой шириной.
15923
15937
  *
15924
15938
  * Раскладка таблицы автоматическая (ширину колонок выбирает содержимое), и одной `width` ей мало —
15925
15939
  * она для неё лишь пожелание. Жёстко колонку держат все три предела сразу, поэтому и ставим их
15926
15940
  * втроём, на каждую ячейку колонки.
15927
15941
  *
15928
- * Ширины нет — стиля нет: колонка остаётся на попечении раскладки, как и была.
15942
+ * Ни ширины, ни разрешения тянуть — стиля нет: колонка остаётся на попечении раскладки, как и была.
15943
+ */
15944
+ const getColumnStyle = (index, width, resizable) => {
15945
+ if (width == null && !resizable) {
15946
+ return undefined;
15947
+ }
15948
+ const variable = getColumnWidthVariable(index);
15949
+ const fixed = width == null ? null : `${width}px`;
15950
+ return {
15951
+ width: `var(${variable}, ${fixed ?? "auto"})`,
15952
+ minWidth: `var(${variable}, ${fixed ?? "0"})`,
15953
+ // Без заданной ширины предел остаётся общим для всех ячеек — тем, что задан стилем таблицы.
15954
+ maxWidth: `var(${variable}, ${fixed ?? "var(--table-cell-max-width, 20rem)"})`,
15955
+ };
15956
+ };
15957
+
15958
+ /**
15959
+ * Перетаскивание правой границы колонки.
15960
+ *
15961
+ * Жест — общий {@link useResizeDrag}, тот же, что двигает границы ячеек сетки дашборда. Здесь
15962
+ * остаётся только табличное: во время жеста ширина рисуется переменной на самой таблице, а в
15963
+ * состояние уходит один раз, на отпускание мыши. Так шаг жеста меняет одно свойство одного узла,
15964
+ * а не перерисовывает таблицу целиком.
15965
+ *
15966
+ * Стартовая ширина берётся с самой ячейки заголовка: у колонки без `width` её выбрала раскладка
15967
+ * таблицы, и тянуть надо от того, что видно.
15968
+ */
15969
+ const useColumnResize = ({ index, onCommit }) => {
15970
+ const variable = getColumnWidthVariable(index);
15971
+ const onStart = React.useCallback((event) => {
15972
+ // Обработчик нажатия висит на самой ручке, поэтому её ячейка и таблица достаются отсюда —
15973
+ // отдельный ref на них не нужен.
15974
+ const cell = event.currentTarget?.closest("th");
15975
+ if (!cell) {
15976
+ return null;
15977
+ }
15978
+ return {
15979
+ start: event.clientX,
15980
+ width: cell.getBoundingClientRect().width,
15981
+ table: cell.closest("table"),
15982
+ };
15983
+ }, []);
15984
+ const getNextWidth = React.useCallback((state, event) => Math.max(MIN_COLUMN_WIDTH, Math.round(state.width + event.clientX - state.start)), []);
15985
+ const onMove = React.useCallback((state, event) => state.table?.style.setProperty(variable, `${getNextWidth(state, event)}px`), [getNextWidth, variable]);
15986
+ const onEnd = React.useCallback((state, event) => {
15987
+ state.table?.style.removeProperty(variable);
15988
+ const next = getNextWidth(state, event);
15989
+ // Клик по границе без перетаскивания ширину менять не должен.
15990
+ if (next === Math.round(state.width)) {
15991
+ return;
15992
+ }
15993
+ onCommit(next);
15994
+ }, [getNextWidth, onCommit, variable]);
15995
+ return useResizeDrag({ onStart, onMove, onEnd });
15996
+ };
15997
+
15998
+ /**
15999
+ * Ручка ширины колонки на правой границе заголовка.
16000
+ *
16001
+ * Тот же компонент и тот же жест, что двигают границы ячеек сетки дашборда: пользователю это одно
16002
+ * и то же действие, и выглядеть оно обязано одинаково.
15929
16003
  */
15930
- const getColumnStyle = (width) => width == null ? undefined : { width, minWidth: width, maxWidth: width };
16004
+ const TableColumnResizer = React.memo(({ index, onCommit }) => {
16005
+ const { setHandle, dragging } = useColumnResize({ index, onCommit });
16006
+ // Ручка лежит внутри заголовка, и без остановки всплытия перетаскивание границы заканчивалось бы
16007
+ // кликом по нему — то есть переключало бы сортировку.
16008
+ const stopPropagation = React.useCallback((event) => event.stopPropagation(), []);
16009
+ return jsxRuntime.jsx(ResizeHandle, { ref: setHandle, "$axis": "column", "data-dragging": dragging, onClick: stopPropagation });
16010
+ });
15931
16011
 
15932
16012
  /**
15933
16013
  * Шапка таблицы: заголовки колонок, сортировка кликом и захват границы для ручной ширины.
@@ -15935,9 +16015,9 @@ const getColumnStyle = (width) => width == null ? undefined : { width, minWidth:
15935
16015
  * Захват рисуется по разрешению атрибута (`resizable`) и не смотрит на режим правки контейнера:
15936
16016
  * ширина колонки — это вид, а не данные.
15937
16017
  */
15938
- const TableHeadRow = ({ columns, sort, sortEnabled, columnWidths, withActionsColumn, onSortToggle, onResizeStart, onResizeMove, onResizeEnd, }) => (jsxRuntime.jsxs("tr", { children: [columns.map(({ attributeName, alias, description, resizable }) => {
16018
+ const TableHeadRow = ({ columns, sort, sortEnabled, columnWidths, withActionsColumn, onSortToggle, onColumnResize, }) => (jsxRuntime.jsxs("tr", { children: [columns.map(({ attributeName, alias, description, resizable }, index) => {
15939
16019
  const sorted = sort?.attributeName === attributeName;
15940
- return (jsxRuntime.jsxs(TableHeadCell, { title: description || alias, style: getColumnStyle(columnWidths[attributeName]), "$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(TableResizeHandle, { onPointerDown: event => onResizeStart(attributeName, event), onPointerMove: onResizeMove, onPointerUp: onResizeEnd, onPointerCancel: onResizeEnd }))] }, 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));
15941
16021
  }), withActionsColumn && jsxRuntime.jsx(TableHeadCell, {})] }));
15942
16022
 
15943
16023
  const ContainerLoading = () => (jsxRuntime.jsx(uilibGl.Flex, { alignContent: "center", justifyContent: "center", width: "100%", children: jsxRuntime.jsx(uilibGl.CircularProgress, { diameter: 1.5, mono: true }) }));
@@ -16043,53 +16123,6 @@ const getTableBoxStyle = (width, height) => {
16043
16123
  };
16044
16124
  };
16045
16125
 
16046
- /**
16047
- * Ручное изменение ширины колонок.
16048
- *
16049
- * Растянутые ширины живут только здесь: тянут их в рантайме, а `width` атрибута в конфиге задаёт
16050
- * лишь стартовое значение — записывать растянутое обратно в конфиг незачем.
16051
- *
16052
- * Разрешение (`resizable`) от `options.editMode` не зависит: ширина колонки — это вид таблицы,
16053
- * а не правка данных, и тянуть её должно быть можно и на таблице только для чтения.
16054
- *
16055
- * Стартовую ширину берём с самой ячейки, а не из конфига: у колонки без `width` её выбрала
16056
- * раскладка таблицы, и тянуть надо ровно от того, что видно.
16057
- */
16058
- const useColumnResize = (columns) => {
16059
- const [widths, setWidths] = React.useState({});
16060
- const dragRef = React.useRef(null);
16061
- const onResizeStart = React.useCallback((attributeName, event) => {
16062
- const handle = event.currentTarget;
16063
- // Захват границы — не клик по заголовку: иначе каждое перетаскивание переключало бы сортировку.
16064
- event.preventDefault();
16065
- event.stopPropagation();
16066
- dragRef.current = {
16067
- attributeName,
16068
- startX: event.clientX,
16069
- startWidth: handle.closest("th")?.getBoundingClientRect().width ?? MIN_COLUMN_WIDTH,
16070
- };
16071
- handle.setPointerCapture(event.pointerId);
16072
- }, []);
16073
- const onResizeMove = React.useCallback((event) => {
16074
- const drag = dragRef.current;
16075
- if (!drag) {
16076
- return;
16077
- }
16078
- const next = Math.max(MIN_COLUMN_WIDTH, Math.round(drag.startWidth + event.clientX - drag.startX));
16079
- setWidths(current => current[drag.attributeName] === next ? current : { ...current, [drag.attributeName]: next });
16080
- }, []);
16081
- const onResizeEnd = React.useCallback((event) => {
16082
- const handle = event.currentTarget;
16083
- dragRef.current = null;
16084
- if (handle.hasPointerCapture(event.pointerId)) {
16085
- handle.releasePointerCapture(event.pointerId);
16086
- }
16087
- }, []);
16088
- // Растянутая ширина перебивает конфигурационную: последнее слово за тем, кто тянул.
16089
- const columnWidths = React.useMemo(() => columns.reduce((acc, { attributeName, width }) => ({ ...acc, [attributeName]: widths[attributeName] ?? width }), {}), [columns, widths]);
16090
- return { columnWidths, onResizeStart, onResizeMove, onResizeEnd };
16091
- };
16092
-
16093
16126
  /**
16094
16127
  * Вид таблицы: колонки плюс локальная сортировка.
16095
16128
  *
@@ -16103,19 +16136,23 @@ const useColumnResize = (columns) => {
16103
16136
  * `width`/`height` — размер собственного бокса таблицы: он ограничивает её саму и прокручивает
16104
16137
  * то, что не влезло. Место, отведённое контейнеру, задаётся его же опциями и живёт отдельно.
16105
16138
  *
16106
- * Ширины колонок — тоже вид: конфиг задаёт стартовую, растянутая мышью живёт в
16107
- * {@link useColumnResize} и в конфиг не возвращается.
16139
+ * Ширины колонок — тоже вид: конфиг задаёт стартовую, растянутая мышью живёт здесь и в конфиг
16140
+ * не возвращается.
16108
16141
  */
16109
16142
  const useTableView = (elementConfig) => {
16110
16143
  const context = React.useContext(StructuredDataContext);
16111
16144
  const { sort: sortEnabled, width, height } = elementConfig?.options || {};
16112
16145
  const [sort, setSort] = React.useState(null);
16146
+ const [widths, setWidths] = React.useState({});
16113
16147
  const schema = context?.schema;
16114
16148
  const rows = context?.rows;
16115
16149
  const columns = React.useMemo(() => schema ?? [], [schema]);
16116
16150
  const sortedRows = React.useMemo(() => sortRows(rows ?? [], sort, schema ?? []), [rows, schema, sort]);
16117
16151
  const sizeCss = React.useMemo(() => getTableBoxStyle(width, height), [height, width]);
16118
- const { columnWidths, onResizeStart, onResizeMove, onResizeEnd } = useColumnResize(columns);
16152
+ // Растянутая мышью ширина живёт только в рантайме и перебивает конфигурационную: последнее
16153
+ // слово за тем, кто тянул. Обратно в конфиг она не пишется.
16154
+ const columnWidths = React.useMemo(() => columns.reduce((acc, attribute) => ({ ...acc, [attribute.attributeName]: widths[attribute.attributeName] ?? attribute.width }), {}), [columns, widths]);
16155
+ const onColumnResize = React.useCallback((attributeName, nextWidth) => setWidths(current => ({ ...current, [attributeName]: nextWidth })), []);
16119
16156
  const onSortToggle = React.useCallback((attributeName) => setSort(current => getNextSort(current, attributeName)), []);
16120
16157
  return {
16121
16158
  context,
@@ -16128,9 +16165,7 @@ const useTableView = (elementConfig) => {
16128
16165
  contentWidth: width != null,
16129
16166
  columnWidths,
16130
16167
  onSortToggle,
16131
- onResizeStart,
16132
- onResizeMove,
16133
- onResizeEnd,
16168
+ onColumnResize,
16134
16169
  };
16135
16170
  };
16136
16171
 
@@ -16142,7 +16177,7 @@ const useTableView = (elementConfig) => {
16142
16177
  */
16143
16178
  const ElementTable = React.memo(({ elementConfig }) => {
16144
16179
  const { t } = useGlobalContext();
16145
- const { context, columns, rows, sort, sortEnabled, sizeCss, contentWidth, columnWidths, onSortToggle, onResizeStart, onResizeMove, onResizeEnd, } = useTableView(elementConfig);
16180
+ const { context, columns, rows, sort, sortEnabled, sizeCss, contentWidth, columnWidths, onSortToggle, onColumnResize, } = useTableView(elementConfig);
16146
16181
  // Узел таблицы держим состоянием, а не ref: отсечка должна встать сразу, как он появится.
16147
16182
  const [table, setTable] = React.useState(null);
16148
16183
  useHeadOverlap(table);
@@ -16158,10 +16193,13 @@ const ElementTable = React.memo(({ elementConfig }) => {
16158
16193
  defaultValue: "Схема данных не задана",
16159
16194
  }) }));
16160
16195
  }
16161
- 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, onResizeStart: onResizeStart, onResizeMove: onResizeMove, onResizeEnd: onResizeEnd }) }), jsxRuntime.jsx(TableBody, { children: rows.map(row => (jsxRuntime.jsxs(TableRow, { children: [columns.map(attribute => (jsxRuntime.jsx(TableCellWrapper, {
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, {
16162
16197
  // Стиль колонки из конфига идёт последним: шрифт задан для значений, и ширину
16163
16198
  // он не трогает — своих размеров у него нет.
16164
- style: { ...getColumnStyle(columnWidths[attribute.attributeName]), ...attribute.style }, 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))) })] }) }));
16199
+ style: {
16200
+ ...getColumnStyle(columnIndex, columnWidths[attribute.attributeName], attribute.resizable),
16201
+ ...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))) })] }) }));
16165
16203
  });
16166
16204
 
16167
16205
  const TooltipIcon = styled(uilibGl.Icon).withConfig({ displayName: "TooltipIcon", componentId: "sc-1lkxudm" }) `
@@ -19630,8 +19668,6 @@ exports.GRID_DRAGGING_ATTR = GRID_DRAGGING_ATTR;
19630
19668
  exports.GRID_DRAG_SOURCE_ATTR = GRID_DRAG_SOURCE_ATTR;
19631
19669
  exports.GRID_DROP_TARGET_ATTR = GRID_DROP_TARGET_ATTR;
19632
19670
  exports.GRID_FILL_DEFAULTS = GRID_FILL_DEFAULTS;
19633
- exports.GRID_HANDLE_ATTR = GRID_HANDLE_ATTR;
19634
- exports.GRID_HANDLE_PROPS = GRID_HANDLE_PROPS;
19635
19671
  exports.GRID_ROW_ID_PREFIX = GRID_ROW_ID_PREFIX;
19636
19672
  exports.GlobalContext = GlobalContext;
19637
19673
  exports.GlobalProvider = GlobalProvider;
@@ -19695,6 +19731,8 @@ exports.PresentationPanelWrapper = PresentationPanelWrapper;
19695
19731
  exports.PresentationWrapper = PresentationWrapper;
19696
19732
  exports.ProgressContainer = ProgressContainer;
19697
19733
  exports.QUERY_DESCRIPTION_CACHE_TTL = QUERY_DESCRIPTION_CACHE_TTL;
19734
+ exports.RESIZE_HANDLE_ATTR = RESIZE_HANDLE_ATTR;
19735
+ exports.ResizeHandle = ResizeHandle;
19698
19736
  exports.RoundedBackgroundContainer = RoundedBackgroundContainer;
19699
19737
  exports.SAVE_HOOK_RESULT_DURATION = SAVE_HOOK_RESULT_DURATION;
19700
19738
  exports.SERVER_NOTIFICATION_EVENT = SERVER_NOTIFICATION_EVENT;
@@ -19925,6 +19963,7 @@ exports.useRelatedDataSourceAttributes = useRelatedDataSourceAttributes;
19925
19963
  exports.useRemoteTask = useRemoteTask;
19926
19964
  exports.useRenderElement = useRenderElement;
19927
19965
  exports.useResizeBox = useResizeBox;
19966
+ exports.useResizeDrag = useResizeDrag;
19928
19967
  exports.useSavePrototypeBuilder = useSavePrototypeBuilder;
19929
19968
  exports.useServerNotificationsContext = useServerNotificationsContext;
19930
19969
  exports.useShownOtherItems = useShownOtherItems;