@lensui/lens-table 0.1.92 → 0.1.94

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.cjs CHANGED
@@ -953,18 +953,55 @@ function TextEditor({ value, type, min, max, integer = false, style, labels, onC
953
953
  var import_react6 = require("react");
954
954
  var import_react_dom = require("react-dom");
955
955
  var import_jsx_runtime7 = require("react/jsx-runtime");
956
- function TextAreaEditor({ value, title, maxLength, inline = false, style, labels, onChange, onCommit, onCancel }) {
956
+ function TextAreaEditor({
957
+ value,
958
+ title,
959
+ maxLength,
960
+ inline = false,
961
+ keepRightBorderVisible = false,
962
+ style,
963
+ labels,
964
+ onChange,
965
+ onCommit,
966
+ onCancel
967
+ }) {
957
968
  const [open, setOpen] = (0, import_react6.useState)(false);
969
+ const inputRef = (0, import_react6.useRef)(null);
970
+ const textareaRef = (0, import_react6.useRef)(null);
971
+ const selectionRef = (0, import_react6.useRef)(null);
958
972
  const inlineHeaderHeight = typeof style.height === "number" ? style.height : 34;
959
973
  const editorStyle = inline && open ? {
960
974
  ...style,
961
- "--rvg-textarea-inline-header-height": `${inlineHeaderHeight}px`
975
+ "--rvg-textarea-inline-header-height": `${inlineHeaderHeight}px`,
976
+ "--rvg-textarea-inline-outline-right": keepRightBorderVisible ? "0px" : "-1px"
962
977
  } : style;
963
978
  const handleKeyDown = (event) => {
964
979
  event.stopPropagation();
965
980
  if (event.key === "Enter") onCommit(value);
966
981
  if (event.key === "Escape") onCancel();
967
982
  };
983
+ const rememberSelection = (control) => {
984
+ if (!control || control.selectionStart === null || control.selectionEnd === null)
985
+ return;
986
+ selectionRef.current = {
987
+ start: control.selectionStart,
988
+ end: control.selectionEnd,
989
+ direction: control.selectionDirection ?? "none"
990
+ };
991
+ };
992
+ (0, import_react6.useLayoutEffect)(() => {
993
+ if (!inline || !selectionRef.current) return;
994
+ const control = open ? textareaRef.current : inputRef.current;
995
+ if (!control) return;
996
+ const selection = selectionRef.current;
997
+ const length = control.value.length;
998
+ control.focus();
999
+ control.setSelectionRange(
1000
+ Math.min(selection.start, length),
1001
+ Math.min(selection.end, length),
1002
+ selection.direction
1003
+ );
1004
+ }, [inline, open]);
968
1005
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
969
1006
  "div",
970
1007
  {
@@ -974,6 +1011,7 @@ function TextAreaEditor({ value, title, maxLength, inline = false, style, labels
974
1011
  !(inline && open) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
975
1012
  "input",
976
1013
  {
1014
+ ref: inputRef,
977
1015
  value,
978
1016
  autoFocus: true,
979
1017
  maxLength,
@@ -992,13 +1030,21 @@ function TextAreaEditor({ value, title, maxLength, inline = false, style, labels
992
1030
  event.preventDefault();
993
1031
  event.stopPropagation();
994
1032
  },
995
- onClick: () => setOpen((current) => inline ? !current : true),
1033
+ onClick: () => {
1034
+ if (!inline) {
1035
+ setOpen(true);
1036
+ return;
1037
+ }
1038
+ rememberSelection(open ? textareaRef.current : inputRef.current);
1039
+ setOpen((current) => !current);
1040
+ },
996
1041
  children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MultilineEditorIcon, {})
997
1042
  }
998
1043
  ),
999
1044
  open && inline && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1000
1045
  "textarea",
1001
1046
  {
1047
+ ref: textareaRef,
1002
1048
  className: "rvg-textarea-inline",
1003
1049
  "aria-label": title,
1004
1050
  "data-rvg-preserve-edit": true,
@@ -1009,30 +1055,44 @@ function TextAreaEditor({ value, title, maxLength, inline = false, style, labels
1009
1055
  onChange: (event) => onChange(event.target.value),
1010
1056
  onKeyDown: (event) => {
1011
1057
  event.stopPropagation();
1012
- if ((event.metaKey || event.ctrlKey) && event.key === "Enter") onCommit(value);
1013
- if (event.key === "Escape") setOpen(false);
1058
+ if ((event.metaKey || event.ctrlKey) && event.key === "Enter")
1059
+ onCommit(value);
1060
+ if (event.key === "Escape") {
1061
+ rememberSelection(event.currentTarget);
1062
+ setOpen(false);
1063
+ }
1014
1064
  }
1015
1065
  }
1016
1066
  ),
1017
1067
  open && !inline && (0, import_react_dom.createPortal)(
1018
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "rvg-textarea-backdrop", role: "presentation", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("section", { className: "rvg-textarea-dialog", role: "dialog", "aria-modal": "true", "aria-label": title, children: [
1019
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("header", { children: title }),
1020
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1021
- "textarea",
1022
- {
1023
- value,
1024
- autoFocus: true,
1025
- maxLength,
1026
- onChange: (event) => onChange(event.target.value),
1027
- onKeyDown: (event) => {
1028
- event.stopPropagation();
1029
- if ((event.metaKey || event.ctrlKey) && event.key === "Enter") onCommit(value);
1030
- if (event.key === "Escape") setOpen(false);
1031
- }
1032
- }
1033
- ),
1034
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("footer", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", onClick: () => onCommit(value), children: labels.confirm }) })
1035
- ] }) }),
1068
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "rvg-textarea-backdrop", role: "presentation", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1069
+ "section",
1070
+ {
1071
+ className: "rvg-textarea-dialog",
1072
+ role: "dialog",
1073
+ "aria-modal": "true",
1074
+ "aria-label": title,
1075
+ children: [
1076
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("header", { children: title }),
1077
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1078
+ "textarea",
1079
+ {
1080
+ value,
1081
+ autoFocus: true,
1082
+ maxLength,
1083
+ onChange: (event) => onChange(event.target.value),
1084
+ onKeyDown: (event) => {
1085
+ event.stopPropagation();
1086
+ if ((event.metaKey || event.ctrlKey) && event.key === "Enter")
1087
+ onCommit(value);
1088
+ if (event.key === "Escape") setOpen(false);
1089
+ }
1090
+ }
1091
+ ),
1092
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("footer", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", onClick: () => onCommit(value), children: labels.confirm }) })
1093
+ ]
1094
+ }
1095
+ ) }),
1036
1096
  document.body
1037
1097
  )
1038
1098
  ]
@@ -1198,11 +1258,12 @@ function getSelectionOutlineBounds({
1198
1258
  horizontalEnd,
1199
1259
  verticalStart,
1200
1260
  verticalEnd,
1201
- borderWidth = 2
1261
+ borderWidth = 2,
1262
+ keepRightBorderVisible = false
1202
1263
  }) {
1203
1264
  return {
1204
1265
  left: Math.max(left - borderWidth, horizontalStart - borderWidth),
1205
- right: Math.min(right + 1, horizontalEnd + 1),
1266
+ right: Math.min(right + 1, horizontalEnd + (keepRightBorderVisible ? 0 : 1)),
1206
1267
  top: Math.max(top - borderWidth, verticalStart - borderWidth),
1207
1268
  bottom: Math.min(bottom + borderWidth, verticalEnd + borderWidth)
1208
1269
  };
@@ -3302,7 +3363,8 @@ function TableInner({
3302
3363
  horizontalStart,
3303
3364
  horizontalEnd,
3304
3365
  verticalStart,
3305
- verticalEnd: renderHeight
3366
+ verticalEnd: renderHeight,
3367
+ keepRightBorderVisible: horizontalEnd === viewport.width
3306
3368
  });
3307
3369
  const left = Math.round(bounds.left);
3308
3370
  const right = Math.round(bounds.right);
@@ -3861,6 +3923,7 @@ function TableInner({
3861
3923
  title: column.editor.title ?? column.title,
3862
3924
  maxLength: column.editor.maxLength,
3863
3925
  inline: column.editor.inline,
3926
+ keepRightBorderVisible: typeof editorStyle.left === "number" && typeof editorStyle.width === "number" && editorStyle.left + editorStyle.width >= viewport.width,
3864
3927
  style: editorStyle,
3865
3928
  labels,
3866
3929
  onChange: setDraft,
@@ -4856,7 +4919,8 @@ function TableInner({
4856
4919
  horizontalStart,
4857
4920
  horizontalEnd,
4858
4921
  verticalStart,
4859
- verticalEnd: renderHeight
4922
+ verticalEnd: renderHeight,
4923
+ keepRightBorderVisible: horizontalEnd === viewport.width
4860
4924
  });
4861
4925
  const left = Math.round(bounds.left);
4862
4926
  const right = Math.round(bounds.right);
package/dist/index.css CHANGED
@@ -2753,14 +2753,30 @@
2753
2753
  .rvg-textarea-editor {
2754
2754
  padding-right: 24px;
2755
2755
  }
2756
+ .rvg-root:has(.rvg-textarea-editor.is-inline-expanded) .rvg-selection-focus {
2757
+ display: none;
2758
+ }
2756
2759
  .rvg-textarea-editor.is-inline-expanded {
2757
2760
  z-index: 8;
2758
2761
  display: block;
2759
2762
  height: calc(var(--rvg-textarea-inline-header-height) + 116px) !important;
2760
2763
  padding: 0;
2761
- overflow: hidden;
2762
- border: 2px solid var(--rvg-color-primary);
2764
+ overflow: visible;
2765
+ border: 0;
2763
2766
  background: var(--rvg-color-bg);
2767
+ box-shadow: none;
2768
+ }
2769
+ .rvg-textarea-editor.is-inline-expanded::before {
2770
+ position: absolute;
2771
+ z-index: 1;
2772
+ top: -2px;
2773
+ right: var(--rvg-textarea-inline-outline-right, -1px);
2774
+ bottom: -2px;
2775
+ left: -2px;
2776
+ border: 2px solid var(--rvg-color-primary);
2777
+ content: "";
2778
+ pointer-events: none;
2779
+ box-sizing: border-box;
2764
2780
  }
2765
2781
  .rvg-textarea-trigger {
2766
2782
  position: absolute;
@@ -2793,7 +2809,7 @@
2793
2809
  min-width: 0;
2794
2810
  min-height: 0;
2795
2811
  margin: 0;
2796
- padding: 8px 24px 8px 4px;
2812
+ padding: 0 24px 8px 4px;
2797
2813
  resize: none;
2798
2814
  border: 0;
2799
2815
  border-radius: 0;
@@ -2801,10 +2817,12 @@
2801
2817
  background: transparent;
2802
2818
  color: var(--rvg-color-text);
2803
2819
  font:
2804
- var(--rvg-font-size-body)/1.5 Inter,
2820
+ var(--rvg-font-size-body) Inter,
2805
2821
  ui-sans-serif,
2806
2822
  system-ui,
2807
2823
  sans-serif;
2824
+ line-height: var(--rvg-textarea-inline-header-height);
2825
+ box-shadow: none;
2808
2826
  box-sizing: border-box;
2809
2827
  }
2810
2828
  .rvg-textarea-backdrop {
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/Table.tsx
2
- import { forwardRef, useImperativeHandle, Fragment as Fragment2, useCallback as useCallback3, useEffect as useEffect3, useLayoutEffect as useLayoutEffect3, useMemo as useMemo2, useRef as useRef4, useState as useState6 } from "react";
2
+ import { forwardRef, useImperativeHandle, Fragment as Fragment2, useCallback as useCallback3, useEffect as useEffect3, useLayoutEffect as useLayoutEffect4, useMemo as useMemo2, useRef as useRef5, useState as useState6 } from "react";
3
3
  import { flushSync } from "react-dom";
4
4
 
5
5
  // src/components/EmptyState.tsx
@@ -920,21 +920,62 @@ function TextEditor({ value, type, min, max, integer = false, style, labels, onC
920
920
  }
921
921
 
922
922
  // src/components/editors/TextAreaEditor.tsx
923
- import { useState as useState4 } from "react";
923
+ import {
924
+ useLayoutEffect as useLayoutEffect3,
925
+ useRef as useRef4,
926
+ useState as useState4
927
+ } from "react";
924
928
  import { createPortal } from "react-dom";
925
929
  import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
926
- function TextAreaEditor({ value, title, maxLength, inline = false, style, labels, onChange, onCommit, onCancel }) {
930
+ function TextAreaEditor({
931
+ value,
932
+ title,
933
+ maxLength,
934
+ inline = false,
935
+ keepRightBorderVisible = false,
936
+ style,
937
+ labels,
938
+ onChange,
939
+ onCommit,
940
+ onCancel
941
+ }) {
927
942
  const [open, setOpen] = useState4(false);
943
+ const inputRef = useRef4(null);
944
+ const textareaRef = useRef4(null);
945
+ const selectionRef = useRef4(null);
928
946
  const inlineHeaderHeight = typeof style.height === "number" ? style.height : 34;
929
947
  const editorStyle = inline && open ? {
930
948
  ...style,
931
- "--rvg-textarea-inline-header-height": `${inlineHeaderHeight}px`
949
+ "--rvg-textarea-inline-header-height": `${inlineHeaderHeight}px`,
950
+ "--rvg-textarea-inline-outline-right": keepRightBorderVisible ? "0px" : "-1px"
932
951
  } : style;
933
952
  const handleKeyDown = (event) => {
934
953
  event.stopPropagation();
935
954
  if (event.key === "Enter") onCommit(value);
936
955
  if (event.key === "Escape") onCancel();
937
956
  };
957
+ const rememberSelection = (control) => {
958
+ if (!control || control.selectionStart === null || control.selectionEnd === null)
959
+ return;
960
+ selectionRef.current = {
961
+ start: control.selectionStart,
962
+ end: control.selectionEnd,
963
+ direction: control.selectionDirection ?? "none"
964
+ };
965
+ };
966
+ useLayoutEffect3(() => {
967
+ if (!inline || !selectionRef.current) return;
968
+ const control = open ? textareaRef.current : inputRef.current;
969
+ if (!control) return;
970
+ const selection = selectionRef.current;
971
+ const length = control.value.length;
972
+ control.focus();
973
+ control.setSelectionRange(
974
+ Math.min(selection.start, length),
975
+ Math.min(selection.end, length),
976
+ selection.direction
977
+ );
978
+ }, [inline, open]);
938
979
  return /* @__PURE__ */ jsxs7(
939
980
  "div",
940
981
  {
@@ -944,6 +985,7 @@ function TextAreaEditor({ value, title, maxLength, inline = false, style, labels
944
985
  !(inline && open) && /* @__PURE__ */ jsx7(
945
986
  "input",
946
987
  {
988
+ ref: inputRef,
947
989
  value,
948
990
  autoFocus: true,
949
991
  maxLength,
@@ -962,13 +1004,21 @@ function TextAreaEditor({ value, title, maxLength, inline = false, style, labels
962
1004
  event.preventDefault();
963
1005
  event.stopPropagation();
964
1006
  },
965
- onClick: () => setOpen((current) => inline ? !current : true),
1007
+ onClick: () => {
1008
+ if (!inline) {
1009
+ setOpen(true);
1010
+ return;
1011
+ }
1012
+ rememberSelection(open ? textareaRef.current : inputRef.current);
1013
+ setOpen((current) => !current);
1014
+ },
966
1015
  children: /* @__PURE__ */ jsx7(MultilineEditorIcon, {})
967
1016
  }
968
1017
  ),
969
1018
  open && inline && /* @__PURE__ */ jsx7(
970
1019
  "textarea",
971
1020
  {
1021
+ ref: textareaRef,
972
1022
  className: "rvg-textarea-inline",
973
1023
  "aria-label": title,
974
1024
  "data-rvg-preserve-edit": true,
@@ -979,30 +1029,44 @@ function TextAreaEditor({ value, title, maxLength, inline = false, style, labels
979
1029
  onChange: (event) => onChange(event.target.value),
980
1030
  onKeyDown: (event) => {
981
1031
  event.stopPropagation();
982
- if ((event.metaKey || event.ctrlKey) && event.key === "Enter") onCommit(value);
983
- if (event.key === "Escape") setOpen(false);
1032
+ if ((event.metaKey || event.ctrlKey) && event.key === "Enter")
1033
+ onCommit(value);
1034
+ if (event.key === "Escape") {
1035
+ rememberSelection(event.currentTarget);
1036
+ setOpen(false);
1037
+ }
984
1038
  }
985
1039
  }
986
1040
  ),
987
1041
  open && !inline && createPortal(
988
- /* @__PURE__ */ jsx7("div", { className: "rvg-textarea-backdrop", role: "presentation", children: /* @__PURE__ */ jsxs7("section", { className: "rvg-textarea-dialog", role: "dialog", "aria-modal": "true", "aria-label": title, children: [
989
- /* @__PURE__ */ jsx7("header", { children: title }),
990
- /* @__PURE__ */ jsx7(
991
- "textarea",
992
- {
993
- value,
994
- autoFocus: true,
995
- maxLength,
996
- onChange: (event) => onChange(event.target.value),
997
- onKeyDown: (event) => {
998
- event.stopPropagation();
999
- if ((event.metaKey || event.ctrlKey) && event.key === "Enter") onCommit(value);
1000
- if (event.key === "Escape") setOpen(false);
1001
- }
1002
- }
1003
- ),
1004
- /* @__PURE__ */ jsx7("footer", { children: /* @__PURE__ */ jsx7("button", { type: "button", onClick: () => onCommit(value), children: labels.confirm }) })
1005
- ] }) }),
1042
+ /* @__PURE__ */ jsx7("div", { className: "rvg-textarea-backdrop", role: "presentation", children: /* @__PURE__ */ jsxs7(
1043
+ "section",
1044
+ {
1045
+ className: "rvg-textarea-dialog",
1046
+ role: "dialog",
1047
+ "aria-modal": "true",
1048
+ "aria-label": title,
1049
+ children: [
1050
+ /* @__PURE__ */ jsx7("header", { children: title }),
1051
+ /* @__PURE__ */ jsx7(
1052
+ "textarea",
1053
+ {
1054
+ value,
1055
+ autoFocus: true,
1056
+ maxLength,
1057
+ onChange: (event) => onChange(event.target.value),
1058
+ onKeyDown: (event) => {
1059
+ event.stopPropagation();
1060
+ if ((event.metaKey || event.ctrlKey) && event.key === "Enter")
1061
+ onCommit(value);
1062
+ if (event.key === "Escape") setOpen(false);
1063
+ }
1064
+ }
1065
+ ),
1066
+ /* @__PURE__ */ jsx7("footer", { children: /* @__PURE__ */ jsx7("button", { type: "button", onClick: () => onCommit(value), children: labels.confirm }) })
1067
+ ]
1068
+ }
1069
+ ) }),
1006
1070
  document.body
1007
1071
  )
1008
1072
  ]
@@ -1168,11 +1232,12 @@ function getSelectionOutlineBounds({
1168
1232
  horizontalEnd,
1169
1233
  verticalStart,
1170
1234
  verticalEnd,
1171
- borderWidth = 2
1235
+ borderWidth = 2,
1236
+ keepRightBorderVisible = false
1172
1237
  }) {
1173
1238
  return {
1174
1239
  left: Math.max(left - borderWidth, horizontalStart - borderWidth),
1175
- right: Math.min(right + 1, horizontalEnd + 1),
1240
+ right: Math.min(right + 1, horizontalEnd + (keepRightBorderVisible ? 0 : 1)),
1176
1241
  top: Math.max(top - borderWidth, verticalStart - borderWidth),
1177
1242
  bottom: Math.min(bottom + borderWidth, verticalEnd + borderWidth)
1178
1243
  };
@@ -2066,8 +2131,8 @@ function TableInner({
2066
2131
  const baseHeaderHeight = layout?.headerHeight ?? headerHeightProp ?? 40;
2067
2132
  const headerDepth = useMemo2(() => Math.max(1, ...sourceColumns.map(getColumnDepth)), [sourceColumns]);
2068
2133
  const { language, labels } = useMemo2(() => resolveGridLocale(locale), [locale]);
2069
- const customHeaderContentRefs = useRef4(/* @__PURE__ */ new Map());
2070
- const customHeaderMeasurementsRef = useRef4(/* @__PURE__ */ new Map());
2134
+ const customHeaderContentRefs = useRef5(/* @__PURE__ */ new Map());
2135
+ const customHeaderMeasurementsRef = useRef5(/* @__PURE__ */ new Map());
2071
2136
  const [measuredHeaderRowHeights, setMeasuredHeaderRowHeights] = useState6([]);
2072
2137
  const headerRowHeights = useMemo2(() => Array.from({ length: headerDepth }, (_, level) => Math.max(baseHeaderHeight, measuredHeaderRowHeights[level] ?? 0)), [baseHeaderHeight, headerDepth, measuredHeaderRowHeights]);
2073
2138
  const headerRowOffsets = useMemo2(() => {
@@ -2103,7 +2168,7 @@ function TableInner({
2103
2168
  const customContextMenuConfig = typeof contextMenuConfig === "object" ? contextMenuConfig : void 0;
2104
2169
  const [resizedColumnWidths, setResizedColumnWidths] = useState6({});
2105
2170
  const leafSourceColumns = useMemo2(() => flattenDataColumns(sourceColumns), [sourceColumns]);
2106
- const sourceColumnWidthsRef = useRef4(new Map(leafSourceColumns.map((column) => [column.key, column.width])));
2171
+ const sourceColumnWidthsRef = useRef5(new Map(leafSourceColumns.map((column) => [column.key, column.width])));
2107
2172
  const showRowCheckbox = Boolean(rowSelection) && (typeof rowSelection !== "object" || rowSelection.showCheckbox !== false);
2108
2173
  const rowSelectionIndicator = typeof rowSelection === "object" ? rowSelection.indicator ?? "checkbox" : "checkbox";
2109
2174
  const rowSelectionColumnWidth = typeof rowSelection === "object" ? Math.max(24, rowSelection.columnWidth ?? 44) : 44;
@@ -2156,54 +2221,54 @@ function TableInner({
2156
2221
  });
2157
2222
  return levels;
2158
2223
  }, [columns, headerCells, headerDepth]);
2159
- const canvasRef = useRef4(null);
2160
- const scrollerRef = useRef4(null);
2161
- const rootRef = useRef4(null);
2162
- const frameRef = useRef4(null);
2163
- const textFrameRef = useRef4(null);
2164
- const textLayoutScrollTopRef = useRef4(0);
2165
- const toastTimerRef = useRef4(null);
2166
- const headerTooltipTimerRef = useRef4(null);
2167
- const cellTooltipTimerRef = useRef4(null);
2168
- const pendingHeaderTooltipKeyRef = useRef4("");
2169
- const pendingCellTooltipKeyRef = useRef4("");
2170
- const clickedCellRef = useRef4(null);
2171
- const rowAnchorRef = useRef4(null);
2172
- const columnAnchorRef = useRef4(null);
2173
- const columnDragRef = useRef4(null);
2174
- const columnOrderDragRef = useRef4(null);
2175
- const columnOrderLongPressTimerRef = useRef4(null);
2176
- const rowOrderDragRef = useRef4(null);
2177
- const dragGuideRef = useRef4(null);
2178
- const rowDragGuideRef = useRef4(null);
2179
- const selectionFocusRef = useRef4(null);
2180
- const selectionEdgeTargetRef = useRef4(null);
2181
- const verticalScrollbarRef = useRef4(null);
2182
- const verticalScrollbarThumbRef = useRef4(null);
2183
- const verticalScrollbarDragRef = useRef4(null);
2184
- const horizontalScrollbarRef = useRef4(null);
2185
- const horizontalScrollbarThumbRef = useRef4(null);
2186
- const horizontalScrollbarDragRef = useRef4(null);
2187
- const verticalScrollbarVisibilityTimerRef = useRef4(null);
2188
- const horizontalScrollbarVisibilityTimerRef = useRef4(null);
2189
- const rowByKeyRef = useRef4(/* @__PURE__ */ new Map());
2190
- const rowIndexByKeyRef = useRef4(/* @__PURE__ */ new Map());
2191
- const headerIconsRef = useRef4(null);
2192
- const scrollingHeaderIconsRef = useRef4(null);
2193
- const scrollingTextRef = useRef4(null);
2194
- const filterRef = useRef4(null);
2195
- const contextMenuRef = useRef4(null);
2196
- const suppressClickRef = useRef4(false);
2197
- const hasCompletedLoadRef = useRef4(!loading);
2198
- const validColumnDropRef = useRef4(null);
2199
- const hoveredHeaderActionRef = useRef4(null);
2200
- const hoveredRowIndexRef = useRef4(null);
2224
+ const canvasRef = useRef5(null);
2225
+ const scrollerRef = useRef5(null);
2226
+ const rootRef = useRef5(null);
2227
+ const frameRef = useRef5(null);
2228
+ const textFrameRef = useRef5(null);
2229
+ const textLayoutScrollTopRef = useRef5(0);
2230
+ const toastTimerRef = useRef5(null);
2231
+ const headerTooltipTimerRef = useRef5(null);
2232
+ const cellTooltipTimerRef = useRef5(null);
2233
+ const pendingHeaderTooltipKeyRef = useRef5("");
2234
+ const pendingCellTooltipKeyRef = useRef5("");
2235
+ const clickedCellRef = useRef5(null);
2236
+ const rowAnchorRef = useRef5(null);
2237
+ const columnAnchorRef = useRef5(null);
2238
+ const columnDragRef = useRef5(null);
2239
+ const columnOrderDragRef = useRef5(null);
2240
+ const columnOrderLongPressTimerRef = useRef5(null);
2241
+ const rowOrderDragRef = useRef5(null);
2242
+ const dragGuideRef = useRef5(null);
2243
+ const rowDragGuideRef = useRef5(null);
2244
+ const selectionFocusRef = useRef5(null);
2245
+ const selectionEdgeTargetRef = useRef5(null);
2246
+ const verticalScrollbarRef = useRef5(null);
2247
+ const verticalScrollbarThumbRef = useRef5(null);
2248
+ const verticalScrollbarDragRef = useRef5(null);
2249
+ const horizontalScrollbarRef = useRef5(null);
2250
+ const horizontalScrollbarThumbRef = useRef5(null);
2251
+ const horizontalScrollbarDragRef = useRef5(null);
2252
+ const verticalScrollbarVisibilityTimerRef = useRef5(null);
2253
+ const horizontalScrollbarVisibilityTimerRef = useRef5(null);
2254
+ const rowByKeyRef = useRef5(/* @__PURE__ */ new Map());
2255
+ const rowIndexByKeyRef = useRef5(/* @__PURE__ */ new Map());
2256
+ const headerIconsRef = useRef5(null);
2257
+ const scrollingHeaderIconsRef = useRef5(null);
2258
+ const scrollingTextRef = useRef5(null);
2259
+ const filterRef = useRef5(null);
2260
+ const contextMenuRef = useRef5(null);
2261
+ const suppressClickRef = useRef5(false);
2262
+ const hasCompletedLoadRef = useRef5(!loading);
2263
+ const validColumnDropRef = useRef5(null);
2264
+ const hoveredHeaderActionRef = useRef5(null);
2265
+ const hoveredRowIndexRef = useRef5(null);
2201
2266
  const [viewport, setViewport] = useState6({ width: 0, height: typeof height === "number" ? height : FALLBACK_HEIGHT });
2202
2267
  const [horizontalScrollbarHeight, setHorizontalScrollbarHeight] = useState6(0);
2203
2268
  const [availableHeight, setAvailableHeight] = useState6(FALLBACK_HEIGHT);
2204
2269
  const resolvedHeight = typeof height === "number" ? height : availableHeight;
2205
2270
  const [scrollPosition, setScrollPosition] = useState6({ left: 0, top: 0 });
2206
- const scrollRef = useRef4({ left: 0, top: 0 });
2271
+ const scrollRef = useRef5({ left: 0, top: 0 });
2207
2272
  const [rowKeys, setRowKeys] = useControllableKeys(selectedRowKeys, defaultSelectedRowKeys, (keys) => {
2208
2273
  if (!onSelectedRowChange) return;
2209
2274
  const missing = new Set(keys.filter((key) => !rowByKeyRef.current.has(key)));
@@ -2303,7 +2368,7 @@ function TableInner({
2303
2368
  return changed ? nextHeights : current;
2304
2369
  });
2305
2370
  }, [activeCustomHeaderLevels, baseHeaderHeight, headerDepth]);
2306
- useLayoutEffect3(() => {
2371
+ useLayoutEffect4(() => {
2307
2372
  customHeaderContentRefs.current.forEach((_, key) => {
2308
2373
  if (!activeCustomHeaderLevels.has(key)) customHeaderContentRefs.current.delete(key);
2309
2374
  });
@@ -2357,12 +2422,12 @@ function TableInner({
2357
2422
  const [annotationContent, setAnnotationContent] = useState6("");
2358
2423
  const [annotationOpen, setAnnotationOpen] = useState6(false);
2359
2424
  const [annotationPlacement, setAnnotationPlacement] = useState6("right-down");
2360
- const originalCellValuesRef = useRef4(/* @__PURE__ */ new Map());
2425
+ const originalCellValuesRef = useRef5(/* @__PURE__ */ new Map());
2361
2426
  const [pendingDeletedRowKeys, setPendingDeletedRowKeys] = useState6(() => /* @__PURE__ */ new Set());
2362
2427
  const [pendingInserts, setPendingInserts] = useState6(() => []);
2363
2428
  const [insertedRowKeys, setInsertedRowKeys] = useState6(() => /* @__PURE__ */ new Set());
2364
2429
  const [rowOrderKeys, setRowOrderKeys] = useState6(null);
2365
- const settledPendingInsertIdsRef = useRef4(/* @__PURE__ */ new Set());
2430
+ const settledPendingInsertIdsRef = useRef5(/* @__PURE__ */ new Set());
2366
2431
  const getDataRowKey = useCallback3((row, index) => {
2367
2432
  return typeof rowKey === "function" ? rowKey(row, index) : rowKey ? row[rowKey] : getDefaultRowKey(row, index);
2368
2433
  }, [rowKey]);
@@ -2465,7 +2530,7 @@ function TableInner({
2465
2530
  }, [columns, onSelectedCellChange, rows]);
2466
2531
  const [selection, setSelection] = useControllableValue(resolvedSelectedCell, resolvedDefaultSelectedCell, handleSelectedCellChange);
2467
2532
  const [selectionRange, setSelectionRange] = useState6(null);
2468
- const rangeDragRef = useRef4(null);
2533
+ const rangeDragRef = useRef5(null);
2469
2534
  useEffect3(() => {
2470
2535
  if (!selection) return void 0;
2471
2536
  const handleOutsidePointerDown = (event) => {
@@ -2520,7 +2585,7 @@ function TableInner({
2520
2585
  return changed ? next : current;
2521
2586
  });
2522
2587
  }, [getDataRowKey, pendingDeletedRowKeys.size, sourceRows]);
2523
- useLayoutEffect3(() => {
2588
+ useLayoutEffect4(() => {
2524
2589
  if (!editing) return;
2525
2590
  if (selection?.rowKey === editing.rowKey && selection.columnKey === editing.columnKey) return;
2526
2591
  setEditing(null);
@@ -2926,7 +2991,7 @@ function TableInner({
2926
2991
  target.classList.remove("is-shape-syncing");
2927
2992
  }
2928
2993
  }, [getSelectionEdgeIndicator]);
2929
- useLayoutEffect3(() => {
2994
+ useLayoutEffect4(() => {
2930
2995
  const element = scrollerRef.current;
2931
2996
  if (!element) return;
2932
2997
  const root = element.parentElement;
@@ -3099,7 +3164,7 @@ function TableInner({
3099
3164
  horizontalThumb.style.width = `${Math.min(trackWidth, thumbWidth)}px`;
3100
3165
  horizontalThumb.style.transform = `translateX(${thumbLeft}px)`;
3101
3166
  }, [autoHeight, bodyTop, bottomSummaryHeight, effectiveHeight, fixedHeader, fixedWidth, realContentHeight, renderHeight, rightFixedWidth, viewport.width]);
3102
- useLayoutEffect3(() => {
3167
+ useLayoutEffect4(() => {
3103
3168
  updateCustomScrollbars();
3104
3169
  }, [contentHeight, contentWidth, updateCustomScrollbars, viewport.height, viewport.width]);
3105
3170
  const handleVerticalScrollbarPointerDown = useCallback3((event) => {
@@ -3222,7 +3287,7 @@ function TableInner({
3222
3287
  horizontalScrollbarDragRef.current = null;
3223
3288
  showCustomScrollbar("horizontal");
3224
3289
  }, [showCustomScrollbar]);
3225
- useLayoutEffect3(() => {
3290
+ useLayoutEffect4(() => {
3226
3291
  textLayoutScrollTopRef.current = scrollPosition.top;
3227
3292
  const clips = rootRef.current?.querySelectorAll(".rvg-body-text-clip");
3228
3293
  clips?.forEach((clip) => {
@@ -3272,7 +3337,8 @@ function TableInner({
3272
3337
  horizontalStart,
3273
3338
  horizontalEnd,
3274
3339
  verticalStart,
3275
- verticalEnd: renderHeight
3340
+ verticalEnd: renderHeight,
3341
+ keepRightBorderVisible: horizontalEnd === viewport.width
3276
3342
  });
3277
3343
  const left = Math.round(bounds.left);
3278
3344
  const right = Math.round(bounds.right);
@@ -3831,6 +3897,7 @@ function TableInner({
3831
3897
  title: column.editor.title ?? column.title,
3832
3898
  maxLength: column.editor.maxLength,
3833
3899
  inline: column.editor.inline,
3900
+ keepRightBorderVisible: typeof editorStyle.left === "number" && typeof editorStyle.width === "number" && editorStyle.left + editorStyle.width >= viewport.width,
3834
3901
  style: editorStyle,
3835
3902
  labels,
3836
3903
  onChange: setDraft,
@@ -4826,7 +4893,8 @@ function TableInner({
4826
4893
  horizontalStart,
4827
4894
  horizontalEnd,
4828
4895
  verticalStart,
4829
- verticalEnd: renderHeight
4896
+ verticalEnd: renderHeight,
4897
+ keepRightBorderVisible: horizontalEnd === viewport.width
4830
4898
  });
4831
4899
  const left = Math.round(bounds.left);
4832
4900
  const right = Math.round(bounds.right);
@@ -4850,7 +4918,7 @@ function TableInner({
4850
4918
  "--rvg-corner-hover-height-extension": "4px"
4851
4919
  } : null
4852
4920
  } : void 0;
4853
- useLayoutEffect3(() => {
4921
+ useLayoutEffect4(() => {
4854
4922
  syncSelectionEdgeTarget(scrollPosition.left, scrollPosition.top);
4855
4923
  }, [scrollPosition.left, scrollPosition.top, syncSelectionEdgeTarget]);
4856
4924
  const handleContextMenu = (event) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lensui/lens-table",
3
- "version": "0.1.92",
3
+ "version": "0.1.94",
4
4
  "description": "A lightweight, canvas-rendered React table component for LensUI.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",