Skip to content

Commit f575edc

Browse files
committed
feat: enhance content change handling in ContentEditable component
1 parent 3f632c3 commit f575edc

2 files changed

Lines changed: 18 additions & 12 deletions

File tree

lib/ContentEditable.tsx

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ const ContentEditable = forwardRef<ContentEditableHandle, ContentEditableProps>(
110110
if (!divRef.current) return
111111
divRef.current.innerText = ""
112112
setContent("")
113+
fireOnChange("", 0)
113114
},
114115
getCaretPosition: () => {
115116
if (!divRef.current) return 0
@@ -120,21 +121,14 @@ const ContentEditable = forwardRef<ContentEditableHandle, ContentEditableProps>(
120121

121122
useEffect(() => {
122123
if (updatedContent !== null && updatedContent !== undefined) {
123-
setContent(updatedContent)
124-
if (divRef.current) divRef.current.innerText = updatedContent
124+
setContent((prev) => prev === updatedContent ? prev : updatedContent)
125+
if (divRef.current && divRef.current.innerText !== updatedContent) {
126+
divRef.current.innerText = updatedContent
127+
}
125128
if (onContentExternalUpdate) onContentExternalUpdate(updatedContent)
126129
}
127130
}, [updatedContent, onContentExternalUpdate])
128131

129-
useEffect(() => {
130-
if (divRef.current) {
131-
divRef.current.style.height = "auto"
132-
if (onChange && isContentWithinMaxLength(content, maxLength)) {
133-
onChange(content, { caretPosition: lastCaretPosition.current })
134-
}
135-
}
136-
}, [content, onChange, maxLength])
137-
138132
useEffect(() => {
139133
if (divRef.current && autoFocus) {
140134
divRef.current.focus()
@@ -157,6 +151,12 @@ const ContentEditable = forwardRef<ContentEditableHandle, ContentEditableProps>(
157151

158152
// --- Helper functions ---
159153

154+
function fireOnChange(newContent: string, caretPos?: number) {
155+
if (onChange && isContentWithinMaxLength(newContent, maxLength)) {
156+
onChange(newContent, { caretPosition: caretPos ?? lastCaretPosition.current })
157+
}
158+
}
159+
160160
function getCaretPositionFromElement(editableDiv: HTMLElement): number {
161161
const sel = window.getSelection()
162162
if (!sel || sel.rangeCount === 0) return -1
@@ -235,6 +235,7 @@ const ContentEditable = forwardRef<ContentEditableHandle, ContentEditableProps>(
235235

236236
const newPos = currentCaretPos + text.length
237237
lastCaretPosition.current = newPos
238+
fireOnChange(divRef.current.innerText, newPos)
238239
}
239240

240241
function isCaretOnLastLine(element: HTMLElement): boolean {
@@ -312,6 +313,7 @@ const ContentEditable = forwardRef<ContentEditableHandle, ContentEditableProps>(
312313
const pos = getCaretPositionFromElement(divRef.current)
313314
if (pos >= 0) lastCaretPosition.current = pos
314315
}
316+
fireOnChange(newContent)
315317
}
316318
} else {
317319
const availableSpace = maxLength
@@ -358,6 +360,7 @@ const ContentEditable = forwardRef<ContentEditableHandle, ContentEditableProps>(
358360
divRef.current.innerText = previousContent
359361
setCaretAtTheEnd(divRef.current)
360362
}
363+
fireOnChange(previousContent)
361364
}
362365
return
363366
}
@@ -376,6 +379,7 @@ const ContentEditable = forwardRef<ContentEditableHandle, ContentEditableProps>(
376379
divRef.current.innerText = nextContent
377380
setCaretAtTheEnd(divRef.current)
378381
}
382+
fireOnChange(nextContent)
379383
}
380384
return
381385
}
@@ -397,6 +401,7 @@ const ContentEditable = forwardRef<ContentEditableHandle, ContentEditableProps>(
397401
e.preventDefault()
398402
divRef.current.innerText = ""
399403
setContent("")
404+
fireOnChange("", 0)
400405
}
401406
}
402407

@@ -459,6 +464,7 @@ const ContentEditable = forwardRef<ContentEditableHandle, ContentEditableProps>(
459464
if (pos >= 0) lastCaretPosition.current = pos
460465
}
461466
}
467+
fireOnChange(processed)
462468
}}
463469
onPaste={(e: React.ClipboardEvent<HTMLElement>) => {
464470
if (disabled) return

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "react-basic-contenteditable",
33
"description": "React contenteditable component. Super-customizable!",
4-
"version": "1.2.0",
4+
"version": "1.2.1",
55
"type": "module",
66
"main": "dist/main.js",
77
"types": "dist/main.d.ts",

0 commit comments

Comments
 (0)