Skip to content

Commit 15d2266

Browse files
authored
feat: focus events (#44)
1 parent 892b7d3 commit 15d2266

7 files changed

Lines changed: 90 additions & 4 deletions

File tree

android/src/main/java/com/swmansion/reactnativerichtexteditor/ReactNativeRichTextEditorView.kt

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.content.Context
44
import android.graphics.BlendMode
55
import android.graphics.BlendModeColorFilter
66
import android.graphics.Color
7+
import android.graphics.Rect
78
import android.os.Build
89
import android.text.Spannable
910
import android.text.StaticLayout
@@ -15,14 +16,18 @@ import android.view.MotionEvent
1516
import android.view.inputmethod.InputMethodManager
1617
import androidx.appcompat.widget.AppCompatEditText
1718
import com.facebook.react.bridge.Arguments
19+
import com.facebook.react.bridge.ReactContext
1820
import com.facebook.react.common.ReactConstants
1921
import com.facebook.react.uimanager.PixelUtil
2022
import com.facebook.react.uimanager.StateWrapper
23+
import com.facebook.react.uimanager.UIManagerHelper
2124
import com.facebook.react.views.text.ReactTypefaceUtils.applyStyles
2225
import com.facebook.react.views.text.ReactTypefaceUtils.parseFontStyle
2326
import com.facebook.react.views.text.ReactTypefaceUtils.parseFontWeight
2427
import com.swmansion.reactnativerichtexteditor.events.LinkHandler
2528
import com.swmansion.reactnativerichtexteditor.events.MentionHandler
29+
import com.swmansion.reactnativerichtexteditor.events.OnBlurEvent
30+
import com.swmansion.reactnativerichtexteditor.events.OnFocusEvent
2631
import com.swmansion.reactnativerichtexteditor.spans.EditorSpans
2732
import com.swmansion.reactnativerichtexteditor.styles.InlineStyles
2833
import com.swmansion.reactnativerichtexteditor.styles.ListStyles
@@ -129,15 +134,28 @@ class ReactNativeRichTextEditorView : AppCompatEditText {
129134
selection?.onSelection(selStart, selEnd)
130135
}
131136

132-
fun setStateWrapper(sw: StateWrapper?) {
133-
stateWrapper = sw
134-
}
135-
136137
override fun clearFocus() {
137138
super.clearFocus()
138139
inputMethodManager?.hideSoftInputFromWindow(windowToken, 0)
139140
}
140141

142+
override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) {
143+
super.onFocusChanged(focused, direction, previouslyFocusedRect)
144+
val context = context as ReactContext
145+
val surfaceId = UIManagerHelper.getSurfaceId(context)
146+
val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(context, id)
147+
148+
if (focused) {
149+
dispatcher?.dispatchEvent(OnFocusEvent(surfaceId, id))
150+
} else {
151+
dispatcher?.dispatchEvent(OnBlurEvent(surfaceId, id))
152+
}
153+
}
154+
155+
fun setStateWrapper(sw: StateWrapper?) {
156+
stateWrapper = sw
157+
}
158+
141159
fun requestFocusProgrammatically() {
142160
requestFocus()
143161
inputMethodManager?.showSoftInput(this, 0)

android/src/main/java/com/swmansion/reactnativerichtexteditor/ReactNativeRichTextEditorViewManager.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ import com.facebook.react.viewmanagers.ReactNativeRichTextEditorViewManagerInter
1616
import com.facebook.react.viewmanagers.ReactNativeRichTextEditorViewManagerDelegate
1717
import com.facebook.yoga.YogaMeasureMode
1818
import com.facebook.yoga.YogaMeasureOutput
19+
import com.swmansion.reactnativerichtexteditor.events.OnBlurEvent
1920
import com.swmansion.reactnativerichtexteditor.events.OnChangeHtmlEvent
2021
import com.swmansion.reactnativerichtexteditor.events.OnChangeStateEvent
2122
import com.swmansion.reactnativerichtexteditor.events.OnChangeTextEvent
23+
import com.swmansion.reactnativerichtexteditor.events.OnFocusEvent
2224
import com.swmansion.reactnativerichtexteditor.events.OnLinkDetectedEvent
2325
import com.swmansion.reactnativerichtexteditor.events.OnMentionEvent
2426
import com.swmansion.reactnativerichtexteditor.events.OnPressLinkEvent
@@ -61,6 +63,8 @@ class ReactNativeRichTextEditorViewManager : SimpleViewManager<ReactNativeRichTe
6163

6264
override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> {
6365
val map = mutableMapOf<String, Any>()
66+
map.put(OnFocusEvent.EVENT_NAME, mapOf("registrationName" to OnFocusEvent.EVENT_NAME))
67+
map.put(OnBlurEvent.EVENT_NAME, mapOf("registrationName" to OnBlurEvent.EVENT_NAME))
6468
map.put(OnChangeTextEvent.EVENT_NAME, mapOf("registrationName" to OnChangeTextEvent.EVENT_NAME))
6569
map.put(OnChangeHtmlEvent.EVENT_NAME, mapOf("registrationName" to OnChangeHtmlEvent.EVENT_NAME))
6670
map.put(OnChangeStateEvent.EVENT_NAME, mapOf("registrationName" to OnChangeStateEvent.EVENT_NAME))
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.swmansion.reactnativerichtexteditor.events
2+
3+
import com.facebook.react.bridge.Arguments
4+
import com.facebook.react.bridge.WritableMap
5+
import com.facebook.react.uimanager.events.Event
6+
7+
class OnBlurEvent(surfaceId: Int, viewId: Int) :
8+
Event<OnBlurEvent>(surfaceId, viewId) {
9+
10+
override fun getEventName(): String {
11+
return EVENT_NAME
12+
}
13+
14+
override fun getEventData(): WritableMap {
15+
val eventData: WritableMap = Arguments.createMap()
16+
17+
return eventData
18+
}
19+
20+
companion object {
21+
const val EVENT_NAME: String = "onBlur"
22+
}
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.swmansion.reactnativerichtexteditor.events
2+
3+
import com.facebook.react.bridge.Arguments
4+
import com.facebook.react.bridge.WritableMap
5+
import com.facebook.react.uimanager.events.Event
6+
7+
class OnFocusEvent(surfaceId: Int, viewId: Int) :
8+
Event<OnFocusEvent>(surfaceId, viewId) {
9+
10+
override fun getEventName(): String {
11+
return EVENT_NAME
12+
}
13+
14+
override fun getEventData(): WritableMap {
15+
val eventData: WritableMap = Arguments.createMap()
16+
17+
return eventData
18+
}
19+
20+
companion object {
21+
const val EVENT_NAME: String = "onFocus"
22+
}
23+
}

example/src/App.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,14 @@ export default function App() {
158158
);
159159
};
160160

161+
const handleFocusEvent = () => {
162+
console.log('Input focused');
163+
};
164+
165+
const handleBlurEvent = () => {
166+
console.log('Input blurred');
167+
};
168+
161169
return (
162170
<>
163171
<ScrollView
@@ -185,6 +193,8 @@ export default function App() {
185193
onChangeMention={handleChangeMention}
186194
onEndMention={closeMentionPopup}
187195
onPressMention={handleMentionPress}
196+
onFocus={handleFocusEvent}
197+
onBlur={handleBlurEvent}
188198
/>
189199
<Toolbar
190200
stylesState={stylesState}

src/ReactNativeRichTextEditorViewNativeComponent.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ export interface NativeProps extends ViewProps {
6464
selectionColor?: ColorValue;
6565

6666
// event callbacks
67+
onFocus?: DirectEventHandler<null>;
68+
onBlur?: DirectEventHandler<null>;
6769
onChangeText?: DirectEventHandler<OnChangeTextEvent>;
6870
onChangeHtml?: DirectEventHandler<OnChangeHtmlEvent>;
6971
onChangeState?: DirectEventHandler<OnChangeStateEvent>;

src/RichTextInput.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ export interface RichTextInputProps extends Omit<ViewProps, 'children'> {
6969
cursorColor?: ColorValue;
7070
selectionColor?: ColorValue;
7171
style?: ViewStyle | TextStyle;
72+
onFocus?: () => void;
73+
onBlur?: () => void;
7274
onChangeText?: (e: NativeSyntheticEvent<OnChangeTextEvent>) => void;
7375
onChangeHtml?: (e: NativeSyntheticEvent<OnChangeHtmlEvent>) => void;
7476
onChangeState?: (e: NativeSyntheticEvent<OnChangeStateEvent>) => void;
@@ -107,6 +109,8 @@ export const RichTextInput = ({
107109
cursorColor,
108110
selectionColor,
109111
style,
112+
onFocus,
113+
onBlur,
110114
onChangeText,
111115
onChangeHtml,
112116
onChangeState,
@@ -242,6 +246,8 @@ export const RichTextInput = ({
242246
cursorColor={cursorColor}
243247
selectionColor={selectionColor}
244248
style={style}
249+
onFocus={onFocus}
250+
onBlur={onBlur}
245251
onChangeText={onChangeText}
246252
onChangeHtml={onChangeHtml}
247253
onChangeState={onChangeState}

0 commit comments

Comments
 (0)