@@ -6,11 +6,13 @@ interface ContentEditableProps {
66 placeholderClassName ?: string
77 placeholder ?: string
88 disabled ?: boolean
9+ updatedContent ?: string
910 onChange : ( content : string ) => void
1011 onKeyUp ?: ( e : React . KeyboardEvent ) => void
1112 onKeyDown ?: ( e : React . KeyboardEvent ) => void
1213 onFocus ?: ( e : React . FocusEvent ) => void
1314 onBlur ?: ( e : React . FocusEvent ) => void
15+ onContentExternalUpdate ?: ( content : string ) => void
1416}
1517
1618const ContentEditable : React . FC < ContentEditableProps > = ( {
@@ -19,26 +21,35 @@ const ContentEditable: React.FC<ContentEditableProps> = ({
1921 placeholderClassName,
2022 placeholder,
2123 disabled,
24+ updatedContent,
2225 onChange,
2326 onKeyUp,
2427 onKeyDown,
2528 onFocus,
2629 onBlur,
30+ onContentExternalUpdate,
2731} ) => {
2832 const [ content , setContent ] = useState ( "" )
2933 const divRef = useRef < HTMLDivElement | null > ( null )
3034
35+ useEffect ( ( ) => {
36+ if ( updatedContent ) {
37+ setContent ( updatedContent )
38+ if ( onContentExternalUpdate ) onContentExternalUpdate ( updatedContent )
39+ }
40+ } , [ updatedContent , onContentExternalUpdate ] )
41+
3142 useEffect ( ( ) => {
3243 if ( divRef . current ) {
3344 divRef . current . style . height = "auto"
34- // divRef.current.style.height = divRef.current.scrollHeight + "px"
3545 onChange ( content )
3646 }
3747 } , [ content , onChange ] )
3848
3949 /**
40- * Check if the caret is on the last line of an element
41- * Returns `false` when the caret is part of a selection
50+ * Checks if the caret is on the last line of a contenteditable element
51+ * @param element - The HTMLDivElement to check
52+ * @returns A boolean indicating whether the caret is on the last line or `false` when the caret is part of a selection
4253 */
4354 const isCaretOnLastLine = useCallback ( ( element : HTMLDivElement ) : boolean => {
4455 if ( element . ownerDocument . activeElement !== element ) return false
@@ -82,6 +93,10 @@ const ContentEditable: React.FC<ContentEditableProps> = ({
8293 return originalCaretRect . bottom === endOfElementRect . bottom
8394 } , [ ] )
8495
96+ /**
97+ * Handles the caret scroll behavior based on keyboard events
98+ * @param e - The keyboard event
99+ */
85100 const handleCaretScroll = useCallback (
86101 ( e : KeyboardEvent ) => {
87102 if ( ! divRef . current ) return
@@ -136,6 +151,10 @@ const ContentEditable: React.FC<ContentEditableProps> = ({
136151 }
137152 }
138153
154+ /**
155+ * Inserts the specified text at the current caret position in the contentEditable element
156+ * @param text - The text to be inserted
157+ */
139158 function insertTextAtCaret ( text : string ) {
140159 if ( ! divRef . current ) return
141160 const currentCaretPos = getCaretPosition ( divRef . current )
@@ -152,6 +171,13 @@ const ContentEditable: React.FC<ContentEditableProps> = ({
152171
153172 // Note: setSelectionRange and createTextRange are not supported by contenteditable elements
154173
174+ /**
175+ * Sets the caret position within the contentEditable element
176+ * If the element is empty, it will be focused
177+ *
178+ * @param elem - The contentEditable element
179+ * @param pos - The position to set the caret to
180+ */
155181 function setCaretPosition ( elem : HTMLElement , pos : number ) {
156182 // Create a new range
157183 const range = document . createRange ( )
@@ -178,6 +204,11 @@ const ContentEditable: React.FC<ContentEditableProps> = ({
178204 }
179205 }
180206
207+ /**
208+ * Retrieves the caret position within the contentEditable element
209+ * @param editableDiv - The contentEditable element
210+ * @returns The caret position as a number
211+ */
181212 function getCaretPosition ( editableDiv : HTMLElement ) {
182213 let caretPos = 0 ,
183214 range
@@ -207,7 +238,6 @@ const ContentEditable: React.FC<ContentEditableProps> = ({
207238 function handleKeyDown ( e : React . KeyboardEvent ) {
208239 if ( onKeyDown ) onKeyDown ( e )
209240 if ( ( e . key === "Delete" || e . key === "Backspace" ) && isAllTextSelected ( ) ) {
210- console . log ( "delete all" , isAllTextSelected ( ) )
211241 e . preventDefault ( )
212242 if ( divRef . current ) {
213243 divRef . current . innerText = ""
@@ -237,13 +267,7 @@ const ContentEditable: React.FC<ContentEditableProps> = ({
237267 return (
238268 < div
239269 className = { containerClassName }
240- style = { {
241- display : "flex" ,
242- justifyContent : "flex-start" ,
243- alignItems : "center" ,
244- width : "calc(100% - 32px)" ,
245- padding : "0 16px" ,
246- } }
270+ style = { { display : "flex" , alignItems : "center" } }
247271 >
248272 < div
249273 ref = { divRef }
@@ -255,15 +279,9 @@ const ContentEditable: React.FC<ContentEditableProps> = ({
255279 aria-label = { placeholder ?? "" }
256280 className = { contentEditableClassName }
257281 style = { {
258- width : "100%" ,
259- border : "1px solid #ccc" ,
260- borderRadius : "0.35rem" ,
261282 padding : "calc((1.5rem * 1.3125)/2) 0 calc((1.5rem * 1.3125)/2) 1rem" ,
262- minHeight : "19px" ,
263- maxHeight : "160px" ,
264283 overflow : "auto" ,
265284 height : "auto" ,
266- lineHeight : 1.3 ,
267285 textAlign : "initial" ,
268286 wordBreak : "break-word" ,
269287 unicodeBidi : "plaintext" ,
@@ -297,10 +315,8 @@ const ContentEditable: React.FC<ContentEditableProps> = ({
297315 className = { placeholderClassName }
298316 style = { {
299317 position : "absolute" ,
300- color : "#a2acb4" ,
301318 pointerEvents : "none" ,
302319 textAlign : "initial" ,
303- marginLeft : "1rem" ,
304320 } }
305321 >
306322 { placeholder ?? "" }
0 commit comments