@lensui/lens-table 0.1.95 → 0.1.98

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,6 +953,42 @@ 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
+ var getLineStart = (value, position) => {
957
+ if (position <= 0) return 0;
958
+ return Math.max(
959
+ value.lastIndexOf("\n", position - 1),
960
+ value.lastIndexOf("\r", position - 1)
961
+ ) + 1;
962
+ };
963
+ var getLineEnd = (value, start) => {
964
+ const carriageReturn = value.indexOf("\r", start);
965
+ const lineFeed = value.indexOf("\n", start);
966
+ if (carriageReturn < 0) return lineFeed < 0 ? value.length : lineFeed;
967
+ if (lineFeed < 0) return carriageReturn;
968
+ return Math.min(carriageReturn, lineFeed);
969
+ };
970
+ var getPreviousLine = (value, currentStart) => {
971
+ if (currentStart <= 0) return null;
972
+ let previousEnd = currentStart - 1;
973
+ if (value[previousEnd] === "\n" && previousEnd > 0 && value[previousEnd - 1] === "\r") {
974
+ previousEnd -= 1;
975
+ }
976
+ return {
977
+ start: getLineStart(value, previousEnd),
978
+ end: previousEnd
979
+ };
980
+ };
981
+ var getNextLine = (value, currentEnd) => {
982
+ if (currentEnd >= value.length) return null;
983
+ let nextStart = currentEnd + 1;
984
+ if (value[currentEnd] === "\r" && nextStart < value.length && value[nextStart] === "\n") {
985
+ nextStart += 1;
986
+ }
987
+ return {
988
+ start: nextStart,
989
+ end: getLineEnd(value, nextStart)
990
+ };
991
+ };
956
992
  function TextAreaEditor({
957
993
  value,
958
994
  title,
@@ -968,6 +1004,11 @@ function TextAreaEditor({
968
1004
  const [open, setOpen] = (0, import_react6.useState)(false);
969
1005
  const inputRef = (0, import_react6.useRef)(null);
970
1006
  const textareaRef = (0, import_react6.useRef)(null);
1007
+ const lastLineStart = inline ? Math.max(value.lastIndexOf("\n"), value.lastIndexOf("\r")) + 1 : 0;
1008
+ const [collapsedLineStart, setCollapsedLineStart] = (0, import_react6.useState)(lastLineStart);
1009
+ const activeLineStart = inline ? Math.min(collapsedLineStart, value.length) : 0;
1010
+ const activeLineEnd = inline ? getLineEnd(value, activeLineStart) : value.length;
1011
+ const collapsedValue = inline ? value.slice(activeLineStart, activeLineEnd) : value;
971
1012
  const selectionRef = (0, import_react6.useRef)(null);
972
1013
  const inlineHeaderHeight = typeof style.height === "number" ? style.height : 34;
973
1014
  const editorStyle = inline && open ? {
@@ -977,15 +1018,41 @@ function TextAreaEditor({
977
1018
  } : style;
978
1019
  const handleKeyDown = (event) => {
979
1020
  event.stopPropagation();
1021
+ if (inline && event.key === "ArrowLeft" && !event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey && event.currentTarget.selectionStart === 0 && event.currentTarget.selectionEnd === 0) {
1022
+ const previousLine = getPreviousLine(value, activeLineStart);
1023
+ if (previousLine) {
1024
+ event.preventDefault();
1025
+ selectionRef.current = {
1026
+ start: previousLine.end,
1027
+ end: previousLine.end,
1028
+ direction: "none"
1029
+ };
1030
+ setCollapsedLineStart(previousLine.start);
1031
+ return;
1032
+ }
1033
+ }
1034
+ if (inline && event.key === "ArrowRight" && !event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey && event.currentTarget.selectionStart === collapsedValue.length && event.currentTarget.selectionEnd === collapsedValue.length) {
1035
+ const nextLine = getNextLine(value, activeLineEnd);
1036
+ if (nextLine) {
1037
+ event.preventDefault();
1038
+ selectionRef.current = {
1039
+ start: nextLine.start,
1040
+ end: nextLine.start,
1041
+ direction: "none"
1042
+ };
1043
+ setCollapsedLineStart(nextLine.start);
1044
+ return;
1045
+ }
1046
+ }
980
1047
  if (event.key === "Enter") onCommit(value);
981
1048
  if (event.key === "Escape") onCancel();
982
1049
  };
983
- const rememberSelection = (control) => {
1050
+ const rememberSelection = (control, offset = 0) => {
984
1051
  if (!control || control.selectionStart === null || control.selectionEnd === null)
985
1052
  return;
986
1053
  selectionRef.current = {
987
- start: control.selectionStart,
988
- end: control.selectionEnd,
1054
+ start: control.selectionStart + offset,
1055
+ end: control.selectionEnd + offset,
989
1056
  direction: control.selectionDirection ?? "none"
990
1057
  };
991
1058
  };
@@ -995,13 +1062,14 @@ function TextAreaEditor({
995
1062
  if (!control) return;
996
1063
  const selection = selectionRef.current;
997
1064
  const length = control.value.length;
1065
+ const offset = open ? 0 : activeLineStart;
998
1066
  control.focus();
999
1067
  control.setSelectionRange(
1000
- Math.min(selection.start, length),
1001
- Math.min(selection.end, length),
1068
+ Math.max(0, Math.min(selection.start - offset, length)),
1069
+ Math.max(0, Math.min(selection.end - offset, length)),
1002
1070
  selection.direction
1003
1071
  );
1004
- }, [inline, open]);
1072
+ }, [activeLineStart, inline, open]);
1005
1073
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1006
1074
  "div",
1007
1075
  {
@@ -1012,14 +1080,16 @@ function TextAreaEditor({
1012
1080
  "input",
1013
1081
  {
1014
1082
  ref: inputRef,
1015
- value,
1083
+ value: collapsedValue,
1016
1084
  autoFocus: true,
1017
1085
  maxLength,
1018
- onChange: (event) => onChange(event.target.value),
1086
+ onChange: (event) => onChange(
1087
+ inline ? `${value.slice(0, activeLineStart)}${event.target.value}${value.slice(activeLineEnd)}` : event.target.value
1088
+ ),
1019
1089
  onKeyDown: handleKeyDown
1020
1090
  }
1021
1091
  ),
1022
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1092
+ (!inline || !open) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1023
1093
  "button",
1024
1094
  {
1025
1095
  type: "button",
@@ -1035,11 +1105,7 @@ function TextAreaEditor({
1035
1105
  setOpen(true);
1036
1106
  return;
1037
1107
  }
1038
- if (open) {
1039
- textareaRef.current?.focus();
1040
- return;
1041
- }
1042
- rememberSelection(inputRef.current);
1108
+ rememberSelection(inputRef.current, activeLineStart);
1043
1109
  setOpen(true);
1044
1110
  },
1045
1111
  children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MultilineEditorIcon, {})
@@ -1056,13 +1122,24 @@ function TextAreaEditor({
1056
1122
  autoFocus: true,
1057
1123
  maxLength,
1058
1124
  onPointerDown: (event) => event.stopPropagation(),
1059
- onChange: (event) => onChange(event.target.value),
1125
+ onChange: (event) => {
1126
+ rememberSelection(event.currentTarget);
1127
+ onChange(event.currentTarget.value);
1128
+ },
1060
1129
  onKeyDown: (event) => {
1061
1130
  event.stopPropagation();
1062
1131
  if ((event.metaKey || event.ctrlKey) && event.key === "Enter")
1063
1132
  onCommit(value);
1064
1133
  if (event.key === "Escape") {
1065
1134
  rememberSelection(event.currentTarget);
1135
+ if (event.currentTarget.selectionStart !== null) {
1136
+ setCollapsedLineStart(
1137
+ getLineStart(
1138
+ event.currentTarget.value,
1139
+ event.currentTarget.selectionStart
1140
+ )
1141
+ );
1142
+ }
1066
1143
  setOpen(false);
1067
1144
  }
1068
1145
  }
package/dist/index.css CHANGED
@@ -2794,9 +2794,6 @@
2794
2794
  cursor: pointer;
2795
2795
  transform: translateY(-50%);
2796
2796
  }
2797
- .rvg-textarea-editor.is-inline-expanded .rvg-textarea-trigger {
2798
- top: calc(var(--rvg-textarea-inline-header-height) / 2);
2799
- }
2800
2797
  .rvg-multiline-icon {
2801
2798
  width: 13px;
2802
2799
  height: 13px;
@@ -2809,7 +2806,7 @@
2809
2806
  min-width: 0;
2810
2807
  min-height: 0;
2811
2808
  margin: 0;
2812
- padding: 0 24px 8px 4px;
2809
+ padding: 0 4px 8px;
2813
2810
  resize: none;
2814
2811
  border: 0;
2815
2812
  border-radius: 0;
@@ -2824,6 +2821,20 @@
2824
2821
  line-height: var(--rvg-textarea-inline-header-height);
2825
2822
  box-shadow: none;
2826
2823
  box-sizing: border-box;
2824
+ scrollbar-width: thin;
2825
+ scrollbar-color: #aeb3b8 transparent;
2826
+ }
2827
+ .rvg-textarea-inline::-webkit-scrollbar {
2828
+ width: 5px;
2829
+ height: 5px;
2830
+ }
2831
+ .rvg-textarea-inline::-webkit-scrollbar-track,
2832
+ .rvg-textarea-inline::-webkit-scrollbar-corner {
2833
+ background: transparent;
2834
+ }
2835
+ .rvg-textarea-inline::-webkit-scrollbar-thumb {
2836
+ border-radius: 999px;
2837
+ background: #aeb3b8;
2827
2838
  }
2828
2839
  .rvg-textarea-backdrop {
2829
2840
  position: fixed;
package/dist/index.js CHANGED
@@ -927,6 +927,42 @@ import {
927
927
  } from "react";
928
928
  import { createPortal } from "react-dom";
929
929
  import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
930
+ var getLineStart = (value, position) => {
931
+ if (position <= 0) return 0;
932
+ return Math.max(
933
+ value.lastIndexOf("\n", position - 1),
934
+ value.lastIndexOf("\r", position - 1)
935
+ ) + 1;
936
+ };
937
+ var getLineEnd = (value, start) => {
938
+ const carriageReturn = value.indexOf("\r", start);
939
+ const lineFeed = value.indexOf("\n", start);
940
+ if (carriageReturn < 0) return lineFeed < 0 ? value.length : lineFeed;
941
+ if (lineFeed < 0) return carriageReturn;
942
+ return Math.min(carriageReturn, lineFeed);
943
+ };
944
+ var getPreviousLine = (value, currentStart) => {
945
+ if (currentStart <= 0) return null;
946
+ let previousEnd = currentStart - 1;
947
+ if (value[previousEnd] === "\n" && previousEnd > 0 && value[previousEnd - 1] === "\r") {
948
+ previousEnd -= 1;
949
+ }
950
+ return {
951
+ start: getLineStart(value, previousEnd),
952
+ end: previousEnd
953
+ };
954
+ };
955
+ var getNextLine = (value, currentEnd) => {
956
+ if (currentEnd >= value.length) return null;
957
+ let nextStart = currentEnd + 1;
958
+ if (value[currentEnd] === "\r" && nextStart < value.length && value[nextStart] === "\n") {
959
+ nextStart += 1;
960
+ }
961
+ return {
962
+ start: nextStart,
963
+ end: getLineEnd(value, nextStart)
964
+ };
965
+ };
930
966
  function TextAreaEditor({
931
967
  value,
932
968
  title,
@@ -942,6 +978,11 @@ function TextAreaEditor({
942
978
  const [open, setOpen] = useState4(false);
943
979
  const inputRef = useRef4(null);
944
980
  const textareaRef = useRef4(null);
981
+ const lastLineStart = inline ? Math.max(value.lastIndexOf("\n"), value.lastIndexOf("\r")) + 1 : 0;
982
+ const [collapsedLineStart, setCollapsedLineStart] = useState4(lastLineStart);
983
+ const activeLineStart = inline ? Math.min(collapsedLineStart, value.length) : 0;
984
+ const activeLineEnd = inline ? getLineEnd(value, activeLineStart) : value.length;
985
+ const collapsedValue = inline ? value.slice(activeLineStart, activeLineEnd) : value;
945
986
  const selectionRef = useRef4(null);
946
987
  const inlineHeaderHeight = typeof style.height === "number" ? style.height : 34;
947
988
  const editorStyle = inline && open ? {
@@ -951,15 +992,41 @@ function TextAreaEditor({
951
992
  } : style;
952
993
  const handleKeyDown = (event) => {
953
994
  event.stopPropagation();
995
+ if (inline && event.key === "ArrowLeft" && !event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey && event.currentTarget.selectionStart === 0 && event.currentTarget.selectionEnd === 0) {
996
+ const previousLine = getPreviousLine(value, activeLineStart);
997
+ if (previousLine) {
998
+ event.preventDefault();
999
+ selectionRef.current = {
1000
+ start: previousLine.end,
1001
+ end: previousLine.end,
1002
+ direction: "none"
1003
+ };
1004
+ setCollapsedLineStart(previousLine.start);
1005
+ return;
1006
+ }
1007
+ }
1008
+ if (inline && event.key === "ArrowRight" && !event.altKey && !event.ctrlKey && !event.metaKey && !event.shiftKey && event.currentTarget.selectionStart === collapsedValue.length && event.currentTarget.selectionEnd === collapsedValue.length) {
1009
+ const nextLine = getNextLine(value, activeLineEnd);
1010
+ if (nextLine) {
1011
+ event.preventDefault();
1012
+ selectionRef.current = {
1013
+ start: nextLine.start,
1014
+ end: nextLine.start,
1015
+ direction: "none"
1016
+ };
1017
+ setCollapsedLineStart(nextLine.start);
1018
+ return;
1019
+ }
1020
+ }
954
1021
  if (event.key === "Enter") onCommit(value);
955
1022
  if (event.key === "Escape") onCancel();
956
1023
  };
957
- const rememberSelection = (control) => {
1024
+ const rememberSelection = (control, offset = 0) => {
958
1025
  if (!control || control.selectionStart === null || control.selectionEnd === null)
959
1026
  return;
960
1027
  selectionRef.current = {
961
- start: control.selectionStart,
962
- end: control.selectionEnd,
1028
+ start: control.selectionStart + offset,
1029
+ end: control.selectionEnd + offset,
963
1030
  direction: control.selectionDirection ?? "none"
964
1031
  };
965
1032
  };
@@ -969,13 +1036,14 @@ function TextAreaEditor({
969
1036
  if (!control) return;
970
1037
  const selection = selectionRef.current;
971
1038
  const length = control.value.length;
1039
+ const offset = open ? 0 : activeLineStart;
972
1040
  control.focus();
973
1041
  control.setSelectionRange(
974
- Math.min(selection.start, length),
975
- Math.min(selection.end, length),
1042
+ Math.max(0, Math.min(selection.start - offset, length)),
1043
+ Math.max(0, Math.min(selection.end - offset, length)),
976
1044
  selection.direction
977
1045
  );
978
- }, [inline, open]);
1046
+ }, [activeLineStart, inline, open]);
979
1047
  return /* @__PURE__ */ jsxs7(
980
1048
  "div",
981
1049
  {
@@ -986,14 +1054,16 @@ function TextAreaEditor({
986
1054
  "input",
987
1055
  {
988
1056
  ref: inputRef,
989
- value,
1057
+ value: collapsedValue,
990
1058
  autoFocus: true,
991
1059
  maxLength,
992
- onChange: (event) => onChange(event.target.value),
1060
+ onChange: (event) => onChange(
1061
+ inline ? `${value.slice(0, activeLineStart)}${event.target.value}${value.slice(activeLineEnd)}` : event.target.value
1062
+ ),
993
1063
  onKeyDown: handleKeyDown
994
1064
  }
995
1065
  ),
996
- /* @__PURE__ */ jsx7(
1066
+ (!inline || !open) && /* @__PURE__ */ jsx7(
997
1067
  "button",
998
1068
  {
999
1069
  type: "button",
@@ -1009,11 +1079,7 @@ function TextAreaEditor({
1009
1079
  setOpen(true);
1010
1080
  return;
1011
1081
  }
1012
- if (open) {
1013
- textareaRef.current?.focus();
1014
- return;
1015
- }
1016
- rememberSelection(inputRef.current);
1082
+ rememberSelection(inputRef.current, activeLineStart);
1017
1083
  setOpen(true);
1018
1084
  },
1019
1085
  children: /* @__PURE__ */ jsx7(MultilineEditorIcon, {})
@@ -1030,13 +1096,24 @@ function TextAreaEditor({
1030
1096
  autoFocus: true,
1031
1097
  maxLength,
1032
1098
  onPointerDown: (event) => event.stopPropagation(),
1033
- onChange: (event) => onChange(event.target.value),
1099
+ onChange: (event) => {
1100
+ rememberSelection(event.currentTarget);
1101
+ onChange(event.currentTarget.value);
1102
+ },
1034
1103
  onKeyDown: (event) => {
1035
1104
  event.stopPropagation();
1036
1105
  if ((event.metaKey || event.ctrlKey) && event.key === "Enter")
1037
1106
  onCommit(value);
1038
1107
  if (event.key === "Escape") {
1039
1108
  rememberSelection(event.currentTarget);
1109
+ if (event.currentTarget.selectionStart !== null) {
1110
+ setCollapsedLineStart(
1111
+ getLineStart(
1112
+ event.currentTarget.value,
1113
+ event.currentTarget.selectionStart
1114
+ )
1115
+ );
1116
+ }
1040
1117
  setOpen(false);
1041
1118
  }
1042
1119
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lensui/lens-table",
3
- "version": "0.1.95",
3
+ "version": "0.1.98",
4
4
  "description": "A lightweight, canvas-rendered React table component for LensUI.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",