From 5880ff479bbef792792436c1fbee71ec53a100fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ska=C5=82ka?= Date: Thu, 11 Apr 2024 15:02:50 +0200 Subject: [PATCH 1/3] Add onContentSizeChange prop --- src/MarkdownTextInput.web.tsx | 37 ++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/MarkdownTextInput.web.tsx b/src/MarkdownTextInput.web.tsx index e305c893..d725f2f6 100644 --- a/src/MarkdownTextInput.web.tsx +++ b/src/MarkdownTextInput.web.tsx @@ -8,6 +8,7 @@ import type { TextInputProps, TextInputKeyPressEventData, TextInputFocusEventData, + TextInputContentSizeChangeEventData, } from 'react-native'; import React, {useEffect, useRef, useCallback, useMemo, useLayoutEffect} from 'react'; import type {CSSProperties, MutableRefObject, ReactEventHandler, FocusEventHandler, MouseEvent, KeyboardEvent, SyntheticEvent} from 'react'; @@ -68,6 +69,11 @@ type Selection = { end: number; }; +type Dimensions = { + height: number | null; + width: number | null; +}; + let focusTimeout: NodeJS.Timeout | null = null; // Removes one '\n' from the end of the string that were added by contentEditable div @@ -154,6 +160,7 @@ const MarkdownTextInput = React.forwardRef( style = {}, value, autoFocus = false, + onContentSizeChange, }, ref, ) => { @@ -164,6 +171,8 @@ const MarkdownTextInput = React.forwardRef( const contentSelection = useRef(null); const className = `react-native-live-markdown-input-${multiline ? 'multiline' : 'singleline'}`; const history = useRef(); + const dimensions = React.useRef({height: null, width: null}); + if (!history.current) { history.current = new InputHistory(100); } @@ -296,6 +305,30 @@ const MarkdownTextInput = React.forwardRef( [handleSelectionChange, updateRefSelectionVariables], ); + const handleContentSizeChange = useCallback(() => { + if (!divRef.current || !multiline || !onContentSizeChange) { + return; + } + + const hostNode = (divRef.current.firstChild as HTMLElement) ?? divRef.current; + const newHeight = hostNode.offsetHeight; + const newWidth = hostNode.offsetWidth; + + if (newHeight !== dimensions.current.height || newWidth !== dimensions.current.width) { + dimensions.current.height = newHeight; + dimensions.current.width = newWidth; + + onContentSizeChange({ + nativeEvent: { + contentSize: { + height: dimensions.current.height, + width: dimensions.current.width, + }, + }, + } as NativeSyntheticEvent); + } + }, [multiline, onContentSizeChange]); + const handleOnChangeText = useCallback( (e: SyntheticEvent) => { if (!divRef.current || !(e.target instanceof HTMLElement)) { @@ -336,8 +369,10 @@ const MarkdownTextInput = React.forwardRef( const normalizedText = normalizeValue(text); onChangeText(normalizedText); } + + handleContentSizeChange(); }, - [updateSelection, updateTextColor, onChange, onChangeText, undo, redo, parseText, processedMarkdownStyle, setEventProps], + [updateTextColor, handleContentSizeChange, onChange, onChangeText, undo, redo, parseText, processedMarkdownStyle, updateSelection, setEventProps], ); const handleKeyPress = useCallback( From 7b49ff4407377aa8224d15d07bdbb88d745e3c7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ska=C5=82ka?= Date: Thu, 11 Apr 2024 17:45:26 +0200 Subject: [PATCH 2/3] Add handleContentSizeChange execution on first render --- src/MarkdownTextInput.web.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/MarkdownTextInput.web.tsx b/src/MarkdownTextInput.web.tsx index d725f2f6..29d11d3a 100644 --- a/src/MarkdownTextInput.web.tsx +++ b/src/MarkdownTextInput.web.tsx @@ -587,6 +587,8 @@ const MarkdownTextInput = React.forwardRef( } const currentValue = value ?? ''; history.current.add(currentValue, currentValue.length); + + handleContentSizeChange(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); From 45886126e174635d7a364966a21badadb23d376f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ska=C5=82ka?= Date: Fri, 12 Apr 2024 10:24:02 +0200 Subject: [PATCH 3/3] Add review changes --- src/MarkdownTextInput.web.tsx | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/MarkdownTextInput.web.tsx b/src/MarkdownTextInput.web.tsx index 29d11d3a..31f7a1c5 100644 --- a/src/MarkdownTextInput.web.tsx +++ b/src/MarkdownTextInput.web.tsx @@ -70,8 +70,8 @@ type Selection = { }; type Dimensions = { - height: number | null; - width: number | null; + width: number; + height: number; }; let focusTimeout: NodeJS.Timeout | null = null; @@ -171,7 +171,7 @@ const MarkdownTextInput = React.forwardRef( const contentSelection = useRef(null); const className = `react-native-live-markdown-input-${multiline ? 'multiline' : 'singleline'}`; const history = useRef(); - const dimensions = React.useRef({height: null, width: null}); + const dimensions = React.useRef(null); if (!history.current) { history.current = new InputHistory(100); @@ -311,19 +311,15 @@ const MarkdownTextInput = React.forwardRef( } const hostNode = (divRef.current.firstChild as HTMLElement) ?? divRef.current; - const newHeight = hostNode.offsetHeight; const newWidth = hostNode.offsetWidth; + const newHeight = hostNode.offsetHeight; - if (newHeight !== dimensions.current.height || newWidth !== dimensions.current.width) { - dimensions.current.height = newHeight; - dimensions.current.width = newWidth; + if (newHeight !== dimensions.current?.height || newWidth !== dimensions.current.width) { + dimensions.current = {height: newHeight, width: newWidth}; onContentSizeChange({ nativeEvent: { - contentSize: { - height: dimensions.current.height, - width: dimensions.current.width, - }, + contentSize: dimensions.current, }, } as NativeSyntheticEvent); }