react-native-simple-rich-text-editor 0.2.0-beta.0 → 0.3.0

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/README.md CHANGED
@@ -35,10 +35,10 @@ export default function App() {
35
35
  const styles = StyleSheet.create({
36
36
  container: {
37
37
  flex: 1,
38
- alignItems: 'center',
39
38
  justifyContent: 'center',
40
39
  },
41
40
  });
41
+
42
42
  ```
43
43
 
44
44
  ## Roadmap
@@ -41,10 +41,27 @@ var _jsxRuntime = require("react/jsx-runtime");
41
41
  * ```
42
42
  */
43
43
 
44
+ // Debounce utility function
45
+ const debounce = (func, delay) => {
46
+ let timeoutId = null;
47
+ return (...args) => {
48
+ if (timeoutId) {
49
+ clearTimeout(timeoutId);
50
+ }
51
+ timeoutId = setTimeout(() => {
52
+ func(...args);
53
+ timeoutId = null;
54
+ }, delay);
55
+ };
56
+ };
44
57
  const RichTextEditor = ({
45
- text,
46
- onEmitText
58
+ text: externalText,
59
+ onEmitText,
60
+ emitTextAfterMillisecondsOfInactivity = 500
47
61
  }) => {
62
+ // Internal state to track the current text value
63
+ const [internalText, setInternalText] = (0, _react.useState)(externalText);
64
+
48
65
  // Track the current selection (cursor position) in the TextInput.
49
66
  const [selection, setSelection] = (0, _react.useState)({
50
67
  start: 0,
@@ -52,21 +69,37 @@ const RichTextEditor = ({
52
69
  });
53
70
  const [needsBoldEndMarker, setNeedsBoldEndMarker] = (0, _react.useState)(false); // we must count the BOLD_START and BOLD_END markers in text prop => inital state
54
71
  const [needsItalicEndMarker, setNeedsItalicEndMarker] = (0, _react.useState)(false);
72
+
73
+ // Create a debounced version of onEmitText
74
+ const debouncedEmitText = (0, _react.useRef)(debounce(newText => {
75
+ onEmitText(newText);
76
+ }, emitTextAfterMillisecondsOfInactivity)).current;
77
+
78
+ // Update internal text when external text changes
79
+ (0, _react.useEffect)(() => {
80
+ setInternalText(externalText);
81
+ }, [externalText]);
82
+
83
+ // Handle text changes
84
+ const handleTextChange = (0, _react.useCallback)(newText => {
85
+ setInternalText(newText);
86
+ debouncedEmitText(newText);
87
+ }, [debouncedEmitText]);
55
88
  const handleFontStyleMarkerInsertion = style => () => {
56
89
  const isBold = style === 'bold';
57
90
  if (isBold ? needsBoldEndMarker : needsItalicEndMarker) {
58
91
  const {
59
92
  text: newText
60
- } = (0, _textManipulation.addFontStyleEndMarker)(text, selection, style);
93
+ } = (0, _textManipulation.addFontStyleEndMarker)(internalText, selection, style);
61
94
  isBold ? setNeedsBoldEndMarker(false) : setNeedsItalicEndMarker(false);
62
- onEmitText(newText);
95
+ handleTextChange(newText);
63
96
  } else {
64
97
  const {
65
98
  text: newText
66
- } = (0, _textManipulation.addFontStyleMarkers)(text, selection, style);
99
+ } = (0, _textManipulation.addFontStyleMarkers)(internalText, selection, style);
67
100
  // this is a reaction to an implementation detail of addBoldMarkers - TODO: solve it cleanly
68
101
  if (selection.start - selection.end === 0) isBold ? setNeedsBoldEndMarker(true) : setNeedsItalicEndMarker(true);
69
- onEmitText(newText);
102
+ handleTextChange(newText);
70
103
  }
71
104
  };
72
105
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
@@ -75,28 +108,28 @@ const RichTextEditor = ({
75
108
  style: styles.row,
76
109
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
77
110
  style: styles.button,
78
- onPress: () => onEmitText((0, _textManipulation.addHeadlineMarker)(_markers.Markers.H1, text, selection)),
111
+ onPress: () => handleTextChange((0, _textManipulation.addHeadlineMarker)(_markers.Markers.H1, internalText, selection)),
79
112
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
80
113
  style: styles.buttonText,
81
114
  children: "H1"
82
115
  })
83
116
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
84
117
  style: styles.button,
85
- onPress: () => onEmitText((0, _textManipulation.addHeadlineMarker)(_markers.Markers.H2, text, selection)),
118
+ onPress: () => handleTextChange((0, _textManipulation.addHeadlineMarker)(_markers.Markers.H2, internalText, selection)),
86
119
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
87
120
  style: styles.buttonText,
88
121
  children: "H2"
89
122
  })
90
123
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
91
124
  style: styles.button,
92
- onPress: () => onEmitText((0, _textManipulation.addHeadlineMarker)(_markers.Markers.H3, text, selection)),
125
+ onPress: () => handleTextChange((0, _textManipulation.addHeadlineMarker)(_markers.Markers.H3, internalText, selection)),
93
126
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
94
127
  style: styles.buttonText,
95
128
  children: "H3"
96
129
  })
97
130
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
98
131
  style: styles.button,
99
- onPress: () => onEmitText((0, _textManipulation.addBulletPointMarker)(text, selection)),
132
+ onPress: () => handleTextChange((0, _textManipulation.addBulletPointMarker)(internalText, selection)),
100
133
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
101
134
  style: styles.buttonText,
102
135
  children: "List"
@@ -122,9 +155,9 @@ const RichTextEditor = ({
122
155
  autoCorrect: false,
123
156
  style: styles.input,
124
157
  onSelectionChange: e => setSelection(e.nativeEvent.selection),
125
- onChangeText: onEmitText,
158
+ onChangeText: handleTextChange,
126
159
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Render.Render, {
127
- encodedText: text
160
+ encodedText: internalText
128
161
  })
129
162
  })]
130
163
  });
@@ -1 +1 @@
1
- {"version":3,"names":["_react","require","_reactNative","_Render","_textManipulation","_markers","_jsxRuntime","RichTextEditor","text","onEmitText","selection","setSelection","useState","start","end","needsBoldEndMarker","setNeedsBoldEndMarker","needsItalicEndMarker","setNeedsItalicEndMarker","handleFontStyleMarkerInsertion","style","isBold","newText","addFontStyleEndMarker","addFontStyleMarkers","jsxs","View","styles","container","children","row","jsx","TouchableOpacity","button","onPress","addHeadlineMarker","Markers","H1","Text","buttonText","H2","H3","addBulletPointMarker","fixedWidth","TextInput","multiline","autoFocus","autoCorrect","input","onSelectionChange","e","nativeEvent","onChangeText","Render","encodedText","exports","electricBlueHex","StyleSheet","create","flex","margin","flexDirection","justifyContent","flexWrap","textAlignVertical","paddingVertical","paddingHorizontal","borderRadius","borderWidth","borderColor","backgroundColor","flexShrink","textAlign","color","width","_default","default"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_react","require","_reactNative","_Render","_textManipulation","_markers","_jsxRuntime","debounce","func","delay","timeoutId","args","clearTimeout","setTimeout","RichTextEditor","text","externalText","onEmitText","emitTextAfterMillisecondsOfInactivity","internalText","setInternalText","useState","selection","setSelection","start","end","needsBoldEndMarker","setNeedsBoldEndMarker","needsItalicEndMarker","setNeedsItalicEndMarker","debouncedEmitText","useRef","newText","current","useEffect","handleTextChange","useCallback","handleFontStyleMarkerInsertion","style","isBold","addFontStyleEndMarker","addFontStyleMarkers","jsxs","View","styles","container","children","row","jsx","TouchableOpacity","button","onPress","addHeadlineMarker","Markers","H1","Text","buttonText","H2","H3","addBulletPointMarker","fixedWidth","TextInput","multiline","autoFocus","autoCorrect","input","onSelectionChange","e","nativeEvent","onChangeText","Render","encodedText","exports","electricBlueHex","StyleSheet","create","flex","margin","flexDirection","justifyContent","flexWrap","textAlignVertical","paddingVertical","paddingHorizontal","borderRadius","borderWidth","borderColor","backgroundColor","flexShrink","textAlign","color","width","_default","default"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
@@ -31,16 +31,34 @@
31
31
  * ```
32
32
  */
33
33
 
34
- import { useState } from 'react';
34
+ import { useState, useEffect, useRef, useCallback } from 'react';
35
35
  import { StyleSheet, TextInput, TouchableOpacity, View, Text } from 'react-native';
36
36
  import { Render } from "./internal/rendering/components/Render.js";
37
37
  import { addFontStyleMarkers, addFontStyleEndMarker, addHeadlineMarker, addBulletPointMarker } from "./internal/text-formats/unicode-markers-format/text-manipulation.js";
38
38
  import { Markers } from "./internal/text-formats/unicode-markers-format/markers.js";
39
+
40
+ // Debounce utility function
39
41
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
42
+ const debounce = (func, delay) => {
43
+ let timeoutId = null;
44
+ return (...args) => {
45
+ if (timeoutId) {
46
+ clearTimeout(timeoutId);
47
+ }
48
+ timeoutId = setTimeout(() => {
49
+ func(...args);
50
+ timeoutId = null;
51
+ }, delay);
52
+ };
53
+ };
40
54
  const RichTextEditor = ({
41
- text,
42
- onEmitText
55
+ text: externalText,
56
+ onEmitText,
57
+ emitTextAfterMillisecondsOfInactivity = 500
43
58
  }) => {
59
+ // Internal state to track the current text value
60
+ const [internalText, setInternalText] = useState(externalText);
61
+
44
62
  // Track the current selection (cursor position) in the TextInput.
45
63
  const [selection, setSelection] = useState({
46
64
  start: 0,
@@ -48,21 +66,37 @@ const RichTextEditor = ({
48
66
  });
49
67
  const [needsBoldEndMarker, setNeedsBoldEndMarker] = useState(false); // we must count the BOLD_START and BOLD_END markers in text prop => inital state
50
68
  const [needsItalicEndMarker, setNeedsItalicEndMarker] = useState(false);
69
+
70
+ // Create a debounced version of onEmitText
71
+ const debouncedEmitText = useRef(debounce(newText => {
72
+ onEmitText(newText);
73
+ }, emitTextAfterMillisecondsOfInactivity)).current;
74
+
75
+ // Update internal text when external text changes
76
+ useEffect(() => {
77
+ setInternalText(externalText);
78
+ }, [externalText]);
79
+
80
+ // Handle text changes
81
+ const handleTextChange = useCallback(newText => {
82
+ setInternalText(newText);
83
+ debouncedEmitText(newText);
84
+ }, [debouncedEmitText]);
51
85
  const handleFontStyleMarkerInsertion = style => () => {
52
86
  const isBold = style === 'bold';
53
87
  if (isBold ? needsBoldEndMarker : needsItalicEndMarker) {
54
88
  const {
55
89
  text: newText
56
- } = addFontStyleEndMarker(text, selection, style);
90
+ } = addFontStyleEndMarker(internalText, selection, style);
57
91
  isBold ? setNeedsBoldEndMarker(false) : setNeedsItalicEndMarker(false);
58
- onEmitText(newText);
92
+ handleTextChange(newText);
59
93
  } else {
60
94
  const {
61
95
  text: newText
62
- } = addFontStyleMarkers(text, selection, style);
96
+ } = addFontStyleMarkers(internalText, selection, style);
63
97
  // this is a reaction to an implementation detail of addBoldMarkers - TODO: solve it cleanly
64
98
  if (selection.start - selection.end === 0) isBold ? setNeedsBoldEndMarker(true) : setNeedsItalicEndMarker(true);
65
- onEmitText(newText);
99
+ handleTextChange(newText);
66
100
  }
67
101
  };
68
102
  return /*#__PURE__*/_jsxs(View, {
@@ -71,28 +105,28 @@ const RichTextEditor = ({
71
105
  style: styles.row,
72
106
  children: [/*#__PURE__*/_jsx(TouchableOpacity, {
73
107
  style: styles.button,
74
- onPress: () => onEmitText(addHeadlineMarker(Markers.H1, text, selection)),
108
+ onPress: () => handleTextChange(addHeadlineMarker(Markers.H1, internalText, selection)),
75
109
  children: /*#__PURE__*/_jsx(Text, {
76
110
  style: styles.buttonText,
77
111
  children: "H1"
78
112
  })
79
113
  }), /*#__PURE__*/_jsx(TouchableOpacity, {
80
114
  style: styles.button,
81
- onPress: () => onEmitText(addHeadlineMarker(Markers.H2, text, selection)),
115
+ onPress: () => handleTextChange(addHeadlineMarker(Markers.H2, internalText, selection)),
82
116
  children: /*#__PURE__*/_jsx(Text, {
83
117
  style: styles.buttonText,
84
118
  children: "H2"
85
119
  })
86
120
  }), /*#__PURE__*/_jsx(TouchableOpacity, {
87
121
  style: styles.button,
88
- onPress: () => onEmitText(addHeadlineMarker(Markers.H3, text, selection)),
122
+ onPress: () => handleTextChange(addHeadlineMarker(Markers.H3, internalText, selection)),
89
123
  children: /*#__PURE__*/_jsx(Text, {
90
124
  style: styles.buttonText,
91
125
  children: "H3"
92
126
  })
93
127
  }), /*#__PURE__*/_jsx(TouchableOpacity, {
94
128
  style: styles.button,
95
- onPress: () => onEmitText(addBulletPointMarker(text, selection)),
129
+ onPress: () => handleTextChange(addBulletPointMarker(internalText, selection)),
96
130
  children: /*#__PURE__*/_jsx(Text, {
97
131
  style: styles.buttonText,
98
132
  children: "List"
@@ -118,9 +152,9 @@ const RichTextEditor = ({
118
152
  autoCorrect: false,
119
153
  style: styles.input,
120
154
  onSelectionChange: e => setSelection(e.nativeEvent.selection),
121
- onChangeText: onEmitText,
155
+ onChangeText: handleTextChange,
122
156
  children: /*#__PURE__*/_jsx(Render, {
123
- encodedText: text
157
+ encodedText: internalText
124
158
  })
125
159
  })]
126
160
  });
@@ -1 +1 @@
1
- {"version":3,"names":["useState","StyleSheet","TextInput","TouchableOpacity","View","Text","Render","addFontStyleMarkers","addFontStyleEndMarker","addHeadlineMarker","addBulletPointMarker","Markers","jsx","_jsx","jsxs","_jsxs","RichTextEditor","text","onEmitText","selection","setSelection","start","end","needsBoldEndMarker","setNeedsBoldEndMarker","needsItalicEndMarker","setNeedsItalicEndMarker","handleFontStyleMarkerInsertion","style","isBold","newText","styles","container","children","row","button","onPress","H1","buttonText","H2","H3","fixedWidth","multiline","autoFocus","autoCorrect","input","onSelectionChange","e","nativeEvent","onChangeText","encodedText","electricBlueHex","create","flex","margin","flexDirection","justifyContent","flexWrap","textAlignVertical","paddingVertical","paddingHorizontal","borderRadius","borderWidth","borderColor","backgroundColor","flexShrink","textAlign","color","width"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["useState","useEffect","useRef","useCallback","StyleSheet","TextInput","TouchableOpacity","View","Text","Render","addFontStyleMarkers","addFontStyleEndMarker","addHeadlineMarker","addBulletPointMarker","Markers","jsx","_jsx","jsxs","_jsxs","debounce","func","delay","timeoutId","args","clearTimeout","setTimeout","RichTextEditor","text","externalText","onEmitText","emitTextAfterMillisecondsOfInactivity","internalText","setInternalText","selection","setSelection","start","end","needsBoldEndMarker","setNeedsBoldEndMarker","needsItalicEndMarker","setNeedsItalicEndMarker","debouncedEmitText","newText","current","handleTextChange","handleFontStyleMarkerInsertion","style","isBold","styles","container","children","row","button","onPress","H1","buttonText","H2","H3","fixedWidth","multiline","autoFocus","autoCorrect","input","onSelectionChange","e","nativeEvent","onChangeText","encodedText","electricBlueHex","create","flex","margin","flexDirection","justifyContent","flexWrap","textAlignVertical","paddingVertical","paddingHorizontal","borderRadius","borderWidth","borderColor","backgroundColor","flexShrink","textAlign","color","width"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
@@ -29,9 +29,10 @@
29
29
  * ```
30
30
  */
31
31
  import type { Dispatch, SetStateAction } from 'react';
32
- declare const RichTextEditor: ({ text, onEmitText, }: {
32
+ declare const RichTextEditor: ({ text: externalText, onEmitText, emitTextAfterMillisecondsOfInactivity, }: {
33
33
  text: string;
34
34
  onEmitText: Dispatch<SetStateAction<string>>;
35
+ emitTextAfterMillisecondsOfInactivity?: number;
35
36
  }) => import("react/jsx-runtime").JSX.Element;
36
37
  export default RichTextEditor;
37
38
  export { RichTextEditor };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAoBtD,QAAA,MAAM,cAAc,GAAI,uBAGrB;IACD,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;CAC9C,4CAwFA,CAAC;AAgCF,eAAe,cAAc,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAuCtD,QAAA,MAAM,cAAc,GAAI,4EAIrB;IACD,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7C,qCAAqC,CAAC,EAAE,MAAM,CAAC;CAChD,4CAgIA,CAAC;AAgCF,eAAe,cAAc,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -29,9 +29,10 @@
29
29
  * ```
30
30
  */
31
31
  import type { Dispatch, SetStateAction } from 'react';
32
- declare const RichTextEditor: ({ text, onEmitText, }: {
32
+ declare const RichTextEditor: ({ text: externalText, onEmitText, emitTextAfterMillisecondsOfInactivity, }: {
33
33
  text: string;
34
34
  onEmitText: Dispatch<SetStateAction<string>>;
35
+ emitTextAfterMillisecondsOfInactivity?: number;
35
36
  }) => import("react/jsx-runtime").JSX.Element;
36
37
  export default RichTextEditor;
37
38
  export { RichTextEditor };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAoBtD,QAAA,MAAM,cAAc,GAAI,uBAGrB;IACD,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;CAC9C,4CAwFA,CAAC;AAgCF,eAAe,cAAc,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAuCtD,QAAA,MAAM,cAAc,GAAI,4EAIrB;IACD,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7C,qCAAqC,CAAC,EAAE,MAAM,CAAC;CAChD,4CAgIA,CAAC;AAgCF,eAAe,cAAc,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-simple-rich-text-editor",
3
- "version": "0.2.0-beta.0",
3
+ "version": "0.3.0",
4
4
  "description": "A lean Rich Text Editor for React Native built upon TextInput outputting Markdown",
5
5
  "source": "./src/index.tsx",
6
6
  "main": "./lib/commonjs/index.js",
@@ -38,7 +38,7 @@
38
38
  "!**/.*"
39
39
  ],
40
40
  "scripts": {
41
- "example": "yarn workspace react-native-simple-rich-text-editor-example",
41
+ "example": "yarn workspace react-native-simple-rich-text-editor-example start",
42
42
  "test": "jest",
43
43
  "typecheck": "tsc",
44
44
  "lint": "eslint \"**/*.{js,ts,tsx}\"",
@@ -84,7 +84,7 @@
84
84
  "react": "18.3.1",
85
85
  "react-native": "0.76.7",
86
86
  "react-native-builder-bob": "^0.37.0",
87
- "release-it": "^17.10.0",
87
+ "release-it": "^18",
88
88
  "typescript": "^5.2.2"
89
89
  },
90
90
  "resolutions": {
package/src/index.tsx CHANGED
@@ -29,7 +29,7 @@
29
29
  * ```
30
30
  */
31
31
  import type { Dispatch, SetStateAction } from 'react';
32
- import { useState } from 'react';
32
+ import { useState, useEffect, useRef, useCallback } from 'react';
33
33
  import {
34
34
  StyleSheet,
35
35
  TextInput,
@@ -48,13 +48,37 @@ import {
48
48
  } from './internal/text-formats/unicode-markers-format/text-manipulation.ts';
49
49
  import { Markers } from './internal/text-formats/unicode-markers-format/markers.ts';
50
50
 
51
+ // Debounce utility function
52
+ const debounce = <T extends (...args: any[]) => any>(
53
+ func: T,
54
+ delay: number
55
+ ): ((...args: Parameters<T>) => void) => {
56
+ let timeoutId: NodeJS.Timeout | null = null;
57
+
58
+ return (...args: Parameters<T>) => {
59
+ if (timeoutId) {
60
+ clearTimeout(timeoutId);
61
+ }
62
+
63
+ timeoutId = setTimeout(() => {
64
+ func(...args);
65
+ timeoutId = null;
66
+ }, delay);
67
+ };
68
+ };
69
+
51
70
  const RichTextEditor = ({
52
- text,
71
+ text: externalText,
53
72
  onEmitText,
73
+ emitTextAfterMillisecondsOfInactivity = 500,
54
74
  }: {
55
75
  text: string;
56
76
  onEmitText: Dispatch<SetStateAction<string>>;
77
+ emitTextAfterMillisecondsOfInactivity?: number;
57
78
  }) => {
79
+ // Internal state to track the current text value
80
+ const [internalText, setInternalText] = useState(externalText);
81
+
58
82
  // Track the current selection (cursor position) in the TextInput.
59
83
  const [selection, setSelection] = useState<{ start: number; end: number }>({
60
84
  start: 0,
@@ -63,18 +87,47 @@ const RichTextEditor = ({
63
87
  const [needsBoldEndMarker, setNeedsBoldEndMarker] = useState(false); // we must count the BOLD_START and BOLD_END markers in text prop => inital state
64
88
  const [needsItalicEndMarker, setNeedsItalicEndMarker] = useState(false);
65
89
 
90
+ // Create a debounced version of onEmitText
91
+ const debouncedEmitText = useRef(
92
+ debounce((newText: string) => {
93
+ onEmitText(newText);
94
+ }, emitTextAfterMillisecondsOfInactivity)
95
+ ).current;
96
+
97
+ // Update internal text when external text changes
98
+ useEffect(() => {
99
+ setInternalText(externalText);
100
+ }, [externalText]);
101
+
102
+ // Handle text changes
103
+ const handleTextChange = useCallback(
104
+ (newText: string) => {
105
+ setInternalText(newText);
106
+ debouncedEmitText(newText);
107
+ },
108
+ [debouncedEmitText]
109
+ );
110
+
66
111
  const handleFontStyleMarkerInsertion = (style: 'bold' | 'italic') => () => {
67
112
  const isBold = style === 'bold';
68
113
  if (isBold ? needsBoldEndMarker : needsItalicEndMarker) {
69
- const { text: newText } = addFontStyleEndMarker(text, selection, style);
114
+ const { text: newText } = addFontStyleEndMarker(
115
+ internalText,
116
+ selection,
117
+ style
118
+ );
70
119
  isBold ? setNeedsBoldEndMarker(false) : setNeedsItalicEndMarker(false);
71
- onEmitText(newText);
120
+ handleTextChange(newText);
72
121
  } else {
73
- const { text: newText } = addFontStyleMarkers(text, selection, style);
122
+ const { text: newText } = addFontStyleMarkers(
123
+ internalText,
124
+ selection,
125
+ style
126
+ );
74
127
  // this is a reaction to an implementation detail of addBoldMarkers - TODO: solve it cleanly
75
128
  if (selection.start - selection.end === 0)
76
129
  isBold ? setNeedsBoldEndMarker(true) : setNeedsItalicEndMarker(true);
77
- onEmitText(newText);
130
+ handleTextChange(newText);
78
131
  }
79
132
  };
80
133
 
@@ -84,7 +137,9 @@ const RichTextEditor = ({
84
137
  <TouchableOpacity
85
138
  style={styles.button}
86
139
  onPress={() =>
87
- onEmitText(addHeadlineMarker(Markers.H1, text, selection))
140
+ handleTextChange(
141
+ addHeadlineMarker(Markers.H1, internalText, selection)
142
+ )
88
143
  }
89
144
  >
90
145
  <Text style={styles.buttonText}>H1</Text>
@@ -92,7 +147,9 @@ const RichTextEditor = ({
92
147
  <TouchableOpacity
93
148
  style={styles.button}
94
149
  onPress={() =>
95
- onEmitText(addHeadlineMarker(Markers.H2, text, selection))
150
+ handleTextChange(
151
+ addHeadlineMarker(Markers.H2, internalText, selection)
152
+ )
96
153
  }
97
154
  >
98
155
  <Text style={styles.buttonText}>H2</Text>
@@ -100,14 +157,18 @@ const RichTextEditor = ({
100
157
  <TouchableOpacity
101
158
  style={styles.button}
102
159
  onPress={() =>
103
- onEmitText(addHeadlineMarker(Markers.H3, text, selection))
160
+ handleTextChange(
161
+ addHeadlineMarker(Markers.H3, internalText, selection)
162
+ )
104
163
  }
105
164
  >
106
165
  <Text style={styles.buttonText}>H3</Text>
107
166
  </TouchableOpacity>
108
167
  <TouchableOpacity
109
168
  style={styles.button}
110
- onPress={() => onEmitText(addBulletPointMarker(text, selection))}
169
+ onPress={() =>
170
+ handleTextChange(addBulletPointMarker(internalText, selection))
171
+ }
111
172
  >
112
173
  <Text style={styles.buttonText}>List</Text>
113
174
  </TouchableOpacity>
@@ -136,9 +197,9 @@ const RichTextEditor = ({
136
197
  onSelectionChange={(
137
198
  e: NativeSyntheticEvent<TextInputSelectionChangeEventData>
138
199
  ) => setSelection(e.nativeEvent.selection)}
139
- onChangeText={onEmitText}
200
+ onChangeText={handleTextChange}
140
201
  >
141
- <Render encodedText={text} />
202
+ <Render encodedText={internalText} />
142
203
  </TextInput>
143
204
  </View>
144
205
  );