@kopexa/editable-text 0.0.3 → 0.0.4

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.
@@ -76,17 +76,22 @@ var EditableText = ({
76
76
  showButtons = false,
77
77
  buttonPosition = "end",
78
78
  buttonVisibility = "hover",
79
- inputProps
79
+ multiline = false,
80
+ rows = 3,
81
+ inputProps,
82
+ textareaProps
80
83
  }) => {
81
84
  const [isEditing, setIsEditing] = useState(false);
82
85
  const [editedValue, setEditedValue] = useState(value);
83
86
  const inputRef = useRef(null);
87
+ const textareaRef = useRef(null);
84
88
  const styles = editableText({
85
89
  size,
86
90
  weight,
87
91
  disabled,
88
92
  showButtons,
89
- buttonVisibility
93
+ buttonVisibility,
94
+ multiline
90
95
  });
91
96
  useEffect(() => {
92
97
  if (!isEditing) {
@@ -94,11 +99,16 @@ var EditableText = ({
94
99
  }
95
100
  }, [value, isEditing]);
96
101
  useEffect(() => {
97
- if (isEditing && inputRef.current) {
98
- inputRef.current.focus();
99
- inputRef.current.select();
102
+ if (isEditing) {
103
+ if (multiline && textareaRef.current) {
104
+ textareaRef.current.focus();
105
+ textareaRef.current.select();
106
+ } else if (inputRef.current) {
107
+ inputRef.current.focus();
108
+ inputRef.current.select();
109
+ }
100
110
  }
101
- }, [isEditing]);
111
+ }, [isEditing, multiline]);
102
112
  const handleSave = useCallback(() => {
103
113
  const trimmedValue = editedValue.trim();
104
114
  setIsEditing(false);
@@ -112,15 +122,22 @@ var EditableText = ({
112
122
  }, [value]);
113
123
  const handleKeyDown = useCallback(
114
124
  (e) => {
115
- if (e.key === "Enter") {
116
- e.preventDefault();
117
- handleSave();
118
- } else if (e.key === "Escape") {
125
+ if (e.key === "Escape") {
119
126
  e.preventDefault();
120
127
  handleCancel();
128
+ } else if (e.key === "Enter") {
129
+ if (multiline) {
130
+ if (e.metaKey || e.ctrlKey) {
131
+ e.preventDefault();
132
+ handleSave();
133
+ }
134
+ } else {
135
+ e.preventDefault();
136
+ handleSave();
137
+ }
121
138
  }
122
139
  },
123
- [handleSave, handleCancel]
140
+ [handleSave, handleCancel, multiline]
124
141
  );
125
142
  const handleChange = useCallback(
126
143
  (e) => {
@@ -165,7 +182,19 @@ var EditableText = ({
165
182
  );
166
183
  if (isEditing) {
167
184
  return /* @__PURE__ */ jsxs("div", { className: styles.root({ className }), children: [
168
- /* @__PURE__ */ jsx(
185
+ multiline ? /* @__PURE__ */ jsx(
186
+ "textarea",
187
+ {
188
+ ref: textareaRef,
189
+ value: editedValue,
190
+ onChange: handleChange,
191
+ onBlur: handleBlur,
192
+ onKeyDown: handleKeyDown,
193
+ className: styles.textarea(),
194
+ rows,
195
+ ...textareaProps
196
+ }
197
+ ) : /* @__PURE__ */ jsx(
169
198
  "input",
170
199
  {
171
200
  ref: inputRef,
@@ -3,10 +3,10 @@ import { EditableTextVariantProps } from '@kopexa/theme';
3
3
  import { ComponentProps } from 'react';
4
4
 
5
5
  type ElementType = "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "span";
6
- type EditableTextProps = Omit<EditableTextVariantProps, "disabled"> & {
6
+ type EditableTextProps = Omit<EditableTextVariantProps, "disabled" | "multiline"> & {
7
7
  /** The current value */
8
8
  value: string;
9
- /** Called when the value is saved (on blur or Enter) */
9
+ /** Called when the value is saved (on blur or Enter/Cmd+Enter) */
10
10
  onSave?: (value: string) => void;
11
11
  /** Called on every change while editing */
12
12
  onChange?: (value: string) => void;
@@ -24,9 +24,15 @@ type EditableTextProps = Omit<EditableTextVariantProps, "disabled"> & {
24
24
  buttonPosition?: "end" | "inline";
25
25
  /** When to show the edit button: "hover" (default) or "always" */
26
26
  buttonVisibility?: "hover" | "always";
27
+ /** Enable multiline editing with textarea */
28
+ multiline?: boolean;
29
+ /** Number of rows for textarea (only when multiline is true) */
30
+ rows?: number;
27
31
  /** Props passed to the underlying input element */
28
32
  inputProps?: Omit<ComponentProps<"input">, "value" | "onChange" | "onBlur" | "onKeyDown" | "className" | "type">;
33
+ /** Props passed to the underlying textarea element (only when multiline is true) */
34
+ textareaProps?: Omit<ComponentProps<"textarea">, "value" | "onChange" | "onBlur" | "onKeyDown" | "className" | "rows">;
29
35
  };
30
- declare const EditableText: ({ value, onSave, onChange, as: Component, placeholder, disabled, size, weight, className, showButtons, buttonPosition, buttonVisibility, inputProps, }: EditableTextProps) => react_jsx_runtime.JSX.Element;
36
+ declare const EditableText: ({ value, onSave, onChange, as: Component, placeholder, disabled, size, weight, className, showButtons, buttonPosition, buttonVisibility, multiline, rows, inputProps, textareaProps, }: EditableTextProps) => react_jsx_runtime.JSX.Element;
31
37
 
32
38
  export { EditableText, type EditableTextProps };
@@ -3,10 +3,10 @@ import { EditableTextVariantProps } from '@kopexa/theme';
3
3
  import { ComponentProps } from 'react';
4
4
 
5
5
  type ElementType = "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "span";
6
- type EditableTextProps = Omit<EditableTextVariantProps, "disabled"> & {
6
+ type EditableTextProps = Omit<EditableTextVariantProps, "disabled" | "multiline"> & {
7
7
  /** The current value */
8
8
  value: string;
9
- /** Called when the value is saved (on blur or Enter) */
9
+ /** Called when the value is saved (on blur or Enter/Cmd+Enter) */
10
10
  onSave?: (value: string) => void;
11
11
  /** Called on every change while editing */
12
12
  onChange?: (value: string) => void;
@@ -24,9 +24,15 @@ type EditableTextProps = Omit<EditableTextVariantProps, "disabled"> & {
24
24
  buttonPosition?: "end" | "inline";
25
25
  /** When to show the edit button: "hover" (default) or "always" */
26
26
  buttonVisibility?: "hover" | "always";
27
+ /** Enable multiline editing with textarea */
28
+ multiline?: boolean;
29
+ /** Number of rows for textarea (only when multiline is true) */
30
+ rows?: number;
27
31
  /** Props passed to the underlying input element */
28
32
  inputProps?: Omit<ComponentProps<"input">, "value" | "onChange" | "onBlur" | "onKeyDown" | "className" | "type">;
33
+ /** Props passed to the underlying textarea element (only when multiline is true) */
34
+ textareaProps?: Omit<ComponentProps<"textarea">, "value" | "onChange" | "onBlur" | "onKeyDown" | "className" | "rows">;
29
35
  };
30
- declare const EditableText: ({ value, onSave, onChange, as: Component, placeholder, disabled, size, weight, className, showButtons, buttonPosition, buttonVisibility, inputProps, }: EditableTextProps) => react_jsx_runtime.JSX.Element;
36
+ declare const EditableText: ({ value, onSave, onChange, as: Component, placeholder, disabled, size, weight, className, showButtons, buttonPosition, buttonVisibility, multiline, rows, inputProps, textareaProps, }: EditableTextProps) => react_jsx_runtime.JSX.Element;
31
37
 
32
38
  export { EditableText, type EditableTextProps };
@@ -95,17 +95,22 @@ var EditableText = ({
95
95
  showButtons = false,
96
96
  buttonPosition = "end",
97
97
  buttonVisibility = "hover",
98
- inputProps
98
+ multiline = false,
99
+ rows = 3,
100
+ inputProps,
101
+ textareaProps
99
102
  }) => {
100
103
  const [isEditing, setIsEditing] = (0, import_react.useState)(false);
101
104
  const [editedValue, setEditedValue] = (0, import_react.useState)(value);
102
105
  const inputRef = (0, import_react.useRef)(null);
106
+ const textareaRef = (0, import_react.useRef)(null);
103
107
  const styles = (0, import_theme.editableText)({
104
108
  size,
105
109
  weight,
106
110
  disabled,
107
111
  showButtons,
108
- buttonVisibility
112
+ buttonVisibility,
113
+ multiline
109
114
  });
110
115
  (0, import_react.useEffect)(() => {
111
116
  if (!isEditing) {
@@ -113,11 +118,16 @@ var EditableText = ({
113
118
  }
114
119
  }, [value, isEditing]);
115
120
  (0, import_react.useEffect)(() => {
116
- if (isEditing && inputRef.current) {
117
- inputRef.current.focus();
118
- inputRef.current.select();
121
+ if (isEditing) {
122
+ if (multiline && textareaRef.current) {
123
+ textareaRef.current.focus();
124
+ textareaRef.current.select();
125
+ } else if (inputRef.current) {
126
+ inputRef.current.focus();
127
+ inputRef.current.select();
128
+ }
119
129
  }
120
- }, [isEditing]);
130
+ }, [isEditing, multiline]);
121
131
  const handleSave = (0, import_react.useCallback)(() => {
122
132
  const trimmedValue = editedValue.trim();
123
133
  setIsEditing(false);
@@ -131,15 +141,22 @@ var EditableText = ({
131
141
  }, [value]);
132
142
  const handleKeyDown = (0, import_react.useCallback)(
133
143
  (e) => {
134
- if (e.key === "Enter") {
135
- e.preventDefault();
136
- handleSave();
137
- } else if (e.key === "Escape") {
144
+ if (e.key === "Escape") {
138
145
  e.preventDefault();
139
146
  handleCancel();
147
+ } else if (e.key === "Enter") {
148
+ if (multiline) {
149
+ if (e.metaKey || e.ctrlKey) {
150
+ e.preventDefault();
151
+ handleSave();
152
+ }
153
+ } else {
154
+ e.preventDefault();
155
+ handleSave();
156
+ }
140
157
  }
141
158
  },
142
- [handleSave, handleCancel]
159
+ [handleSave, handleCancel, multiline]
143
160
  );
144
161
  const handleChange = (0, import_react.useCallback)(
145
162
  (e) => {
@@ -184,7 +201,19 @@ var EditableText = ({
184
201
  );
185
202
  if (isEditing) {
186
203
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.root({ className }), children: [
187
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
204
+ multiline ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
205
+ "textarea",
206
+ {
207
+ ref: textareaRef,
208
+ value: editedValue,
209
+ onChange: handleChange,
210
+ onBlur: handleBlur,
211
+ onKeyDown: handleKeyDown,
212
+ className: styles.textarea(),
213
+ rows,
214
+ ...textareaProps
215
+ }
216
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
188
217
  "input",
189
218
  {
190
219
  ref: inputRef,
@@ -2,7 +2,7 @@
2
2
  "use client";
3
3
  import {
4
4
  EditableText
5
- } from "./chunk-GBMODWXQ.mjs";
5
+ } from "./chunk-BPK7SFVL.mjs";
6
6
  export {
7
7
  EditableText
8
8
  };
package/dist/index.js CHANGED
@@ -96,17 +96,22 @@ var EditableText = ({
96
96
  showButtons = false,
97
97
  buttonPosition = "end",
98
98
  buttonVisibility = "hover",
99
- inputProps
99
+ multiline = false,
100
+ rows = 3,
101
+ inputProps,
102
+ textareaProps
100
103
  }) => {
101
104
  const [isEditing, setIsEditing] = (0, import_react.useState)(false);
102
105
  const [editedValue, setEditedValue] = (0, import_react.useState)(value);
103
106
  const inputRef = (0, import_react.useRef)(null);
107
+ const textareaRef = (0, import_react.useRef)(null);
104
108
  const styles = (0, import_theme.editableText)({
105
109
  size,
106
110
  weight,
107
111
  disabled,
108
112
  showButtons,
109
- buttonVisibility
113
+ buttonVisibility,
114
+ multiline
110
115
  });
111
116
  (0, import_react.useEffect)(() => {
112
117
  if (!isEditing) {
@@ -114,11 +119,16 @@ var EditableText = ({
114
119
  }
115
120
  }, [value, isEditing]);
116
121
  (0, import_react.useEffect)(() => {
117
- if (isEditing && inputRef.current) {
118
- inputRef.current.focus();
119
- inputRef.current.select();
122
+ if (isEditing) {
123
+ if (multiline && textareaRef.current) {
124
+ textareaRef.current.focus();
125
+ textareaRef.current.select();
126
+ } else if (inputRef.current) {
127
+ inputRef.current.focus();
128
+ inputRef.current.select();
129
+ }
120
130
  }
121
- }, [isEditing]);
131
+ }, [isEditing, multiline]);
122
132
  const handleSave = (0, import_react.useCallback)(() => {
123
133
  const trimmedValue = editedValue.trim();
124
134
  setIsEditing(false);
@@ -132,15 +142,22 @@ var EditableText = ({
132
142
  }, [value]);
133
143
  const handleKeyDown = (0, import_react.useCallback)(
134
144
  (e) => {
135
- if (e.key === "Enter") {
136
- e.preventDefault();
137
- handleSave();
138
- } else if (e.key === "Escape") {
145
+ if (e.key === "Escape") {
139
146
  e.preventDefault();
140
147
  handleCancel();
148
+ } else if (e.key === "Enter") {
149
+ if (multiline) {
150
+ if (e.metaKey || e.ctrlKey) {
151
+ e.preventDefault();
152
+ handleSave();
153
+ }
154
+ } else {
155
+ e.preventDefault();
156
+ handleSave();
157
+ }
141
158
  }
142
159
  },
143
- [handleSave, handleCancel]
160
+ [handleSave, handleCancel, multiline]
144
161
  );
145
162
  const handleChange = (0, import_react.useCallback)(
146
163
  (e) => {
@@ -185,7 +202,19 @@ var EditableText = ({
185
202
  );
186
203
  if (isEditing) {
187
204
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.root({ className }), children: [
188
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
205
+ multiline ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
206
+ "textarea",
207
+ {
208
+ ref: textareaRef,
209
+ value: editedValue,
210
+ onChange: handleChange,
211
+ onBlur: handleBlur,
212
+ onKeyDown: handleKeyDown,
213
+ className: styles.textarea(),
214
+ rows,
215
+ ...textareaProps
216
+ }
217
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
189
218
  "input",
190
219
  {
191
220
  ref: inputRef,
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  EditableText
4
- } from "./chunk-GBMODWXQ.mjs";
4
+ } from "./chunk-BPK7SFVL.mjs";
5
5
  export {
6
6
  EditableText
7
7
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kopexa/editable-text",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "description": "Inline editable text component",
5
5
  "keywords": [
6
6
  "editable-text",
@@ -28,11 +28,11 @@
28
28
  "peerDependencies": {
29
29
  "react": ">=19.0.0-rc.0",
30
30
  "react-dom": ">=19.0.0-rc.0",
31
- "@kopexa/theme": "17.21.1"
31
+ "@kopexa/theme": "17.22.0"
32
32
  },
33
33
  "dependencies": {
34
- "@kopexa/shared-utils": "17.0.38",
35
- "@kopexa/react-utils": "17.0.38"
34
+ "@kopexa/shared-utils": "17.0.39",
35
+ "@kopexa/react-utils": "17.0.39"
36
36
  },
37
37
  "clean-package": "../../../clean-package.config.json",
38
38
  "module": "dist/index.mjs",