react-native-typerich 1.0.0 → 2.2.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 +251 -10
- package/ReactNativeTypeRich.podspec +41 -0
- package/android/src/main/java/com/typerich/TypeRichTextInputView.kt +37 -10
- package/android/src/main/java/com/typerich/TypeRichTextInputViewManager.kt +5 -0
- package/ios/TypeRichTextInputView.h +27 -7
- package/ios/TypeRichTextInputView.mm +809 -26
- package/ios/cpp/TypeRichTextInputViewComponentDescriptor.h +19 -0
- package/ios/cpp/TypeRichTextInputViewShadowNode.h +44 -0
- package/ios/cpp/TypeRichTextInputViewShadowNode.mm +110 -0
- package/ios/cpp/TypeRichTextInputViewState.cpp +10 -0
- package/ios/cpp/TypeRichTextInputViewState.h +22 -0
- package/ios/inputTextView/TypeRichUITextView.h +14 -0
- package/ios/inputTextView/TypeRichUITextView.mm +100 -0
- package/ios/modules/commands/TypeRichTextInputCommands.h +24 -0
- package/ios/modules/commands/TypeRichTextInputCommands.mm +392 -0
- package/ios/utils/StringUtils.h +19 -0
- package/ios/utils/StringUtils.mm +15 -0
- package/ios/utils/TextInputUtils.h +26 -0
- package/ios/utils/TextInputUtils.mm +58 -0
- package/lib/module/TypeRichTextInput.js +13 -36
- package/lib/module/TypeRichTextInput.js.map +1 -1
- package/lib/module/TypeRichTextInputNativeComponent.ts +266 -52
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/types/TypeRichTextInput.js +4 -0
- package/lib/module/types/TypeRichTextInput.js.map +1 -0
- package/lib/typescript/src/TypeRichTextInput.d.ts +2 -22
- package/lib/typescript/src/TypeRichTextInput.d.ts.map +1 -1
- package/lib/typescript/src/TypeRichTextInputNativeComponent.d.ts +200 -14
- package/lib/typescript/src/TypeRichTextInputNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/types/TypeRichTextInput.d.ts +95 -0
- package/lib/typescript/src/types/TypeRichTextInput.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/TypeRichTextInput.tsx +20 -70
- package/src/TypeRichTextInputNativeComponent.ts +266 -52
- package/src/index.tsx +1 -5
- package/src/types/TypeRichTextInput.tsx +116 -0
- package/TypeRichTextInput.podspec +0 -20
- package/ios/TypeRichTextInputViewManager.mm +0 -27
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TypeRichTextInputNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/TypeRichTextInputNativeComponent.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TypeRichTextInputNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/TypeRichTextInputNativeComponent.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { default as TypeRichTextInput } from './TypeRichTextInput';
|
|
2
2
|
export * from './TypeRichTextInputNativeComponent';
|
|
3
3
|
export * from './TypeRichTextInput';
|
|
4
|
-
export
|
|
4
|
+
export * from './types/TypeRichTextInput';
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACnE,cAAc,oCAAoC,CAAC;AACnD,cAAc,qBAAqB,CAAC;AACpC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACnE,cAAc,oCAAoC,CAAC;AACnD,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { TypeRichTextInputNativeProps } from '../TypeRichTextInputNativeComponent';
|
|
2
|
+
import type { onPasteImageEventData } from '../TypeRichTextInputNativeComponent';
|
|
3
|
+
/**
|
|
4
|
+
* JavaScript-level props for `TypeRichTextInput`.
|
|
5
|
+
*
|
|
6
|
+
* These props normalize native events into ergonomic,
|
|
7
|
+
* idiomatic JavaScript callbacks.
|
|
8
|
+
*/
|
|
9
|
+
export interface TypeRichTextInputProps extends Omit<TypeRichTextInputNativeProps, 'onChangeText' | 'onChangeSelection' | 'onInputFocus' | 'onInputBlur' | 'onPasteImage'> {
|
|
10
|
+
/**
|
|
11
|
+
* Called when the input receives focus.
|
|
12
|
+
*/
|
|
13
|
+
onFocus?: () => void;
|
|
14
|
+
/**
|
|
15
|
+
* Called when the input loses focus.
|
|
16
|
+
*/
|
|
17
|
+
onBlur?: () => void;
|
|
18
|
+
/**
|
|
19
|
+
* Called whenever the text content changes.
|
|
20
|
+
*
|
|
21
|
+
* This callback is **informational only** and should not
|
|
22
|
+
* be used to drive controlled input behavior.
|
|
23
|
+
*
|
|
24
|
+
* Use imperative commands (`setText`, `insertTextAt`)
|
|
25
|
+
* to update the text.
|
|
26
|
+
*/
|
|
27
|
+
onChangeText?: (value: string) => void;
|
|
28
|
+
/**
|
|
29
|
+
* Called when the text selection or cursor position changes.
|
|
30
|
+
*/
|
|
31
|
+
onChangeSelection?: (event: {
|
|
32
|
+
/**
|
|
33
|
+
* Start index of the selection (inclusive).
|
|
34
|
+
*/
|
|
35
|
+
start: number;
|
|
36
|
+
/**
|
|
37
|
+
* End index of the selection (exclusive).
|
|
38
|
+
*/
|
|
39
|
+
end: number;
|
|
40
|
+
/**
|
|
41
|
+
* Full text content at the time of the selection change.
|
|
42
|
+
*/
|
|
43
|
+
text: string;
|
|
44
|
+
}) => void;
|
|
45
|
+
/**
|
|
46
|
+
* Called when an image is pasted into the input.
|
|
47
|
+
*
|
|
48
|
+
* The payload conforms to {@link onPasteImageEventData}.
|
|
49
|
+
*/
|
|
50
|
+
onPasteImageData?: (data: onPasteImageEventData) => void;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Imperative handle exposed via `ref`.
|
|
54
|
+
*
|
|
55
|
+
* This component is **imperative-first**.
|
|
56
|
+
* Text mutations must be performed using these methods.
|
|
57
|
+
*/
|
|
58
|
+
export interface TypeRichTextInputRef {
|
|
59
|
+
/**
|
|
60
|
+
* Focuses the input programmatically.
|
|
61
|
+
*/
|
|
62
|
+
focus: () => void;
|
|
63
|
+
/**
|
|
64
|
+
* Removes focus from the input.
|
|
65
|
+
*/
|
|
66
|
+
blur: () => void;
|
|
67
|
+
/**
|
|
68
|
+
* Replaces the entire text content of the input.
|
|
69
|
+
*
|
|
70
|
+
* This is the primary and recommended way to update text.
|
|
71
|
+
* does not updates selection
|
|
72
|
+
*/
|
|
73
|
+
setText: (text: string) => void;
|
|
74
|
+
/**
|
|
75
|
+
* Inserts text at the specified range.
|
|
76
|
+
*
|
|
77
|
+
* Replaces the text between `start` and `end` with `text`.
|
|
78
|
+
*
|
|
79
|
+
* it updates selection automatically
|
|
80
|
+
*/
|
|
81
|
+
insertTextAt: (start: number, end: number, text: string) => void;
|
|
82
|
+
/**
|
|
83
|
+
* Updates the current text selection.
|
|
84
|
+
*
|
|
85
|
+
* must be called after setText()
|
|
86
|
+
*/
|
|
87
|
+
setSelection: (start: number, end: number) => void;
|
|
88
|
+
/**
|
|
89
|
+
* Returns the underlying native view reference, if available.
|
|
90
|
+
*
|
|
91
|
+
* Intended for advanced or debugging use cases only.
|
|
92
|
+
*/
|
|
93
|
+
getNativeRef: () => any | null;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=TypeRichTextInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TypeRichTextInput.d.ts","sourceRoot":"","sources":["../../../../src/types/TypeRichTextInput.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,qCAAqC,CAAC;AACxF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAGjF;;;;;GAKG;AACH,MAAM,WAAW,sBACf,SAAQ,IAAI,CACV,4BAA4B,EAC1B,cAAc,GACd,mBAAmB,GACnB,cAAc,GACd,aAAa,GACb,cAAc,CACjB;IACD;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAErB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAEpB;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAEvC;;OAEG;IACH,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE;QAC1B;;WAEG;QACH,KAAK,EAAE,MAAM,CAAC;QAEd;;WAEG;QACH,GAAG,EAAE,MAAM,CAAC;QAEZ;;WAEG;QACH,IAAI,EAAE,MAAM,CAAC;KACd,KAAK,IAAI,CAAC;IAEX;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,qBAAqB,KAAK,IAAI,CAAC;CAC1D;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,KAAK,EAAE,MAAM,IAAI,CAAC;IAElB;;OAEG;IACH,IAAI,EAAE,MAAM,IAAI,CAAC;IAEjB;;;;;OAKG;IACH,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAEhC;;;;;;OAMG;IACH,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAEjE;;;;OAIG;IACH,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAEnD;;;;OAIG;IACH,YAAY,EAAE,MAAM,GAAG,GAAG,IAAI,CAAC;CAChC"}
|
package/package.json
CHANGED
|
@@ -1,25 +1,21 @@
|
|
|
1
1
|
import { forwardRef, useImperativeHandle, useRef, type Ref } from 'react';
|
|
2
2
|
|
|
3
3
|
import type { NativeSyntheticEvent } from 'react-native';
|
|
4
|
-
import { Platform, View } from 'react-native';
|
|
5
4
|
|
|
6
|
-
import {
|
|
5
|
+
import NativeTypeRichTextInput, {
|
|
7
6
|
Commands,
|
|
8
|
-
type OnChangeSelectionEvent,
|
|
9
|
-
type OnChangeTextEvent,
|
|
10
|
-
type onPasteImageEventData,
|
|
11
|
-
type TypeRichTextInputNativeProps,
|
|
12
7
|
} from './TypeRichTextInputNativeComponent';
|
|
13
8
|
|
|
14
|
-
|
|
9
|
+
import type {
|
|
10
|
+
OnChangeSelectionEvent,
|
|
11
|
+
OnChangeTextEvent,
|
|
12
|
+
onPasteImageEventData,
|
|
13
|
+
} from './TypeRichTextInputNativeComponent';
|
|
14
|
+
import type {
|
|
15
|
+
TypeRichTextInputProps,
|
|
16
|
+
TypeRichTextInputRef,
|
|
17
|
+
} from './types/TypeRichTextInput';
|
|
15
18
|
|
|
16
|
-
if (Platform.OS === 'android') {
|
|
17
|
-
NativeTypeRichTextInput =
|
|
18
|
-
require('./TypeRichTextInputNativeComponent').default;
|
|
19
|
-
} else {
|
|
20
|
-
// iOS fallback (temporary)
|
|
21
|
-
NativeTypeRichTextInput = View;
|
|
22
|
-
}
|
|
23
19
|
type MaybeNativeEvent<T> = T | { nativeEvent: T };
|
|
24
20
|
|
|
25
21
|
export function normalizeEvent<T>(event: MaybeNativeEvent<T>): T {
|
|
@@ -29,39 +25,6 @@ export function normalizeEvent<T>(event: MaybeNativeEvent<T>): T {
|
|
|
29
25
|
return event as T;
|
|
30
26
|
}
|
|
31
27
|
|
|
32
|
-
// Public facing props (same as NativeProps but events normalized)
|
|
33
|
-
export interface TypeRichTextInputProps
|
|
34
|
-
extends Omit<
|
|
35
|
-
TypeRichTextInputNativeProps,
|
|
36
|
-
| 'onChangeText'
|
|
37
|
-
| 'onChangeSelection'
|
|
38
|
-
| 'onInputFocus'
|
|
39
|
-
| 'onInputBlur'
|
|
40
|
-
| 'onPasteImage'
|
|
41
|
-
> {
|
|
42
|
-
// JS-friendly callbacks
|
|
43
|
-
onFocus?: () => void;
|
|
44
|
-
onBlur?: () => void;
|
|
45
|
-
onChangeText?: (value: string) => void;
|
|
46
|
-
onChangeSelection?: (event: {
|
|
47
|
-
start: number;
|
|
48
|
-
end: number;
|
|
49
|
-
text: string;
|
|
50
|
-
}) => void;
|
|
51
|
-
onPasteImageData?: (data: onPasteImageEventData) => void;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export interface TypeRichTextInputRef {
|
|
55
|
-
focus: () => void;
|
|
56
|
-
blur: () => void;
|
|
57
|
-
setText: (text: string) => void;
|
|
58
|
-
insertTextAt: (start: number, end: number, text: string) => void;
|
|
59
|
-
setSelection: (start: number, end: number) => void;
|
|
60
|
-
getNativeRef: () => any | null;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const isAndroid = Platform.OS === 'android';
|
|
64
|
-
|
|
65
28
|
/**
|
|
66
29
|
* TypeRichTextInput
|
|
67
30
|
*
|
|
@@ -70,36 +33,37 @@ const isAndroid = Platform.OS === 'android';
|
|
|
70
33
|
* - Fabric-based rendering
|
|
71
34
|
* - custom ShadowNode on Android
|
|
72
35
|
*
|
|
73
|
-
* iOS support is currently
|
|
74
|
-
* we are planning to add support for ios too soon
|
|
36
|
+
* iOS support is currently in Beta Stage
|
|
75
37
|
*/
|
|
76
38
|
const TypeRichTextInput = forwardRef(
|
|
77
39
|
(props: TypeRichTextInputProps, ref: Ref<TypeRichTextInputRef>) => {
|
|
78
40
|
const nativeRef = useRef(null);
|
|
79
41
|
|
|
42
|
+
const { scrollEnabled = true, ...restProps } = props;
|
|
43
|
+
|
|
80
44
|
useImperativeHandle(ref, () => ({
|
|
81
45
|
focus: () => {
|
|
82
|
-
if (
|
|
46
|
+
if (nativeRef.current) {
|
|
83
47
|
Commands.focus(nativeRef.current);
|
|
84
48
|
}
|
|
85
49
|
},
|
|
86
50
|
blur: () => {
|
|
87
|
-
if (
|
|
51
|
+
if (nativeRef.current) {
|
|
88
52
|
Commands.blur(nativeRef.current);
|
|
89
53
|
}
|
|
90
54
|
},
|
|
91
55
|
setText: (text: string) => {
|
|
92
|
-
if (
|
|
56
|
+
if (nativeRef.current) {
|
|
93
57
|
Commands.setText(nativeRef.current, text);
|
|
94
58
|
}
|
|
95
59
|
},
|
|
96
60
|
setSelection(start, end) {
|
|
97
|
-
if (
|
|
61
|
+
if (nativeRef.current) {
|
|
98
62
|
Commands.setSelection(nativeRef.current, start, end);
|
|
99
63
|
}
|
|
100
64
|
},
|
|
101
65
|
insertTextAt: (start: number, end: number, text: string) => {
|
|
102
|
-
if (
|
|
66
|
+
if (nativeRef.current) {
|
|
103
67
|
Commands.insertTextAt(nativeRef.current, start, end, text);
|
|
104
68
|
}
|
|
105
69
|
},
|
|
@@ -145,25 +109,11 @@ const TypeRichTextInput = forwardRef(
|
|
|
145
109
|
});
|
|
146
110
|
}
|
|
147
111
|
|
|
148
|
-
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
149
|
-
const {
|
|
150
|
-
// native-only / android-only props we never want on <View />
|
|
151
|
-
androidExperimentalSynchronousEvents,
|
|
152
|
-
onChangeSelection,
|
|
153
|
-
onChangeText,
|
|
154
|
-
onPasteImageData,
|
|
155
|
-
onFocus,
|
|
156
|
-
onBlur,
|
|
157
|
-
|
|
158
|
-
// everything else
|
|
159
|
-
...restProps
|
|
160
|
-
} = props;
|
|
161
|
-
/* eslint-enable @typescript-eslint/no-unused-vars */
|
|
162
|
-
|
|
163
112
|
return (
|
|
164
113
|
<NativeTypeRichTextInput
|
|
165
114
|
ref={nativeRef}
|
|
166
|
-
{...
|
|
115
|
+
{...restProps}
|
|
116
|
+
scrollEnabled={scrollEnabled}
|
|
167
117
|
onInputFocus={() => props.onFocus?.()}
|
|
168
118
|
onInputBlur={() => props.onBlur?.()}
|
|
169
119
|
onChangeText={handleOnChangeTextEvent}
|
|
@@ -1,111 +1,325 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
codegenNativeComponent,
|
|
4
|
-
codegenNativeCommands,
|
|
5
|
-
type ViewProps,
|
|
6
|
-
} from 'react-native';
|
|
1
|
+
import { codegenNativeComponent, codegenNativeCommands } from 'react-native';
|
|
7
2
|
import type { HostComponent } from 'react-native';
|
|
3
|
+
import type { ColorValue, ViewProps } from 'react-native';
|
|
8
4
|
import type {
|
|
9
5
|
BubblingEventHandler,
|
|
10
|
-
Double,
|
|
11
6
|
WithDefault,
|
|
12
7
|
DirectEventHandler,
|
|
13
8
|
Float,
|
|
9
|
+
Double,
|
|
14
10
|
Int32,
|
|
15
11
|
} from 'react-native/Libraries/Types/CodegenTypes';
|
|
16
12
|
|
|
13
|
+
type ComponentType = HostComponent<TypeRichTextInputNativeProps>;
|
|
14
|
+
|
|
15
|
+
interface NativeCommands {
|
|
16
|
+
// General commands
|
|
17
|
+
focus: (viewRef: React.ElementRef<ComponentType>) => void;
|
|
18
|
+
blur: (viewRef: React.ElementRef<ComponentType>) => void;
|
|
19
|
+
setText: (viewRef: React.ElementRef<ComponentType>, text: string) => void;
|
|
20
|
+
insertTextAt: (
|
|
21
|
+
viewRef: React.ElementRef<ComponentType>,
|
|
22
|
+
start: Int32,
|
|
23
|
+
end: Int32,
|
|
24
|
+
text: string
|
|
25
|
+
) => void;
|
|
26
|
+
setSelection: (
|
|
27
|
+
viewRef: React.ElementRef<ComponentType>,
|
|
28
|
+
start: Int32,
|
|
29
|
+
end: Int32
|
|
30
|
+
) => void;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
|
|
34
|
+
supportedCommands: [
|
|
35
|
+
// General commands
|
|
36
|
+
'focus',
|
|
37
|
+
'blur',
|
|
38
|
+
'setText',
|
|
39
|
+
'setSelection',
|
|
40
|
+
'insertTextAt',
|
|
41
|
+
],
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
export default codegenNativeComponent<TypeRichTextInputNativeProps>(
|
|
45
|
+
'TypeRichTextInputView',
|
|
46
|
+
{
|
|
47
|
+
interfaceOnly: true,
|
|
48
|
+
}
|
|
49
|
+
) as HostComponent<TypeRichTextInputNativeProps>;
|
|
50
|
+
|
|
51
|
+
// types ---------------------------------------------------
|
|
52
|
+
/**
|
|
53
|
+
* Payload for the `onChangeText` event.
|
|
54
|
+
*
|
|
55
|
+
* Emitted whenever the text content of the input changes.
|
|
56
|
+
*/
|
|
17
57
|
export interface OnChangeTextEvent {
|
|
58
|
+
/**
|
|
59
|
+
* The current text value of the input.
|
|
60
|
+
*/
|
|
18
61
|
value: string;
|
|
19
62
|
}
|
|
20
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Payload for the `onChangeSelection` event.
|
|
66
|
+
*
|
|
67
|
+
* Emitted when the text selection or cursor position changes.
|
|
68
|
+
*/
|
|
21
69
|
export interface OnChangeSelectionEvent {
|
|
70
|
+
/**
|
|
71
|
+
* Start index of the selection (inclusive).
|
|
72
|
+
*/
|
|
22
73
|
start: Int32;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* End index of the selection (exclusive).
|
|
77
|
+
*/
|
|
23
78
|
end: Int32;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Full text content at the time of the selection change.
|
|
82
|
+
*/
|
|
24
83
|
text: string;
|
|
25
84
|
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Payload for the `onPasteImage` event.
|
|
88
|
+
*
|
|
89
|
+
* Emitted when an image is pasted into the input from the clipboard,
|
|
90
|
+
* keyboard, or context menu.
|
|
91
|
+
*/
|
|
26
92
|
export interface onPasteImageEventData {
|
|
93
|
+
/**
|
|
94
|
+
* Local URI of the pasted image.
|
|
95
|
+
*/
|
|
27
96
|
uri: string;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* MIME type of the image (e.g. `image/png`, `image/jpeg`).
|
|
100
|
+
*/
|
|
28
101
|
type: string;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Original file name of the image, if available.
|
|
105
|
+
*/
|
|
29
106
|
fileName: string;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* File size of the image in bytes.
|
|
110
|
+
*/
|
|
30
111
|
fileSize: Double;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Source from which the image was pasted.
|
|
115
|
+
*
|
|
116
|
+
* - `keyboard` — Inserted via keyboard image/GIF picker
|
|
117
|
+
* - `clipboard` — Pasted directly from the system clipboard and context menu
|
|
118
|
+
* - `context_menu` — Pasted via long-press context menu
|
|
119
|
+
*
|
|
120
|
+
* ⚠️ **Deprecation notice**
|
|
121
|
+
* The `context_menu` source is **temporary** and will be
|
|
122
|
+
* removed in a future release due to platform limitations
|
|
123
|
+
*/
|
|
31
124
|
source: 'keyboard' | 'clipboard' | 'context_menu';
|
|
32
|
-
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Optional error information if the image could not be processed.
|
|
128
|
+
*/
|
|
129
|
+
error?: {
|
|
130
|
+
/**
|
|
131
|
+
* Human-readable error message.
|
|
132
|
+
*/
|
|
133
|
+
message: string;
|
|
134
|
+
};
|
|
33
135
|
}
|
|
34
136
|
|
|
35
137
|
export interface TypeRichTextInputNativeProps extends ViewProps {
|
|
36
|
-
// base props
|
|
138
|
+
// base props ---------------------------------------------------------------
|
|
139
|
+
/**
|
|
140
|
+
* @deprecated
|
|
141
|
+
* ⚠️ Do NOT use this for controlled input.
|
|
142
|
+
*
|
|
143
|
+
* This prop is **not reactive** after mount.
|
|
144
|
+
* Use the `setText()` command instead.
|
|
145
|
+
*/
|
|
37
146
|
value?: string;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Automatically focuses the input when it mounts.
|
|
150
|
+
*/
|
|
38
151
|
autoFocus?: boolean;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Controls whether the input is editable.
|
|
155
|
+
*
|
|
156
|
+
* When set to `false`, the input becomes read-only and cannot be focused.
|
|
157
|
+
*/
|
|
39
158
|
editable?: boolean;
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Initial text value applied on mount.
|
|
162
|
+
*
|
|
163
|
+
* Unlike `value`, this is safe to use and does not imply controlled behavior.
|
|
164
|
+
*/
|
|
40
165
|
defaultValue?: string;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Placeholder text displayed when the input is empty.
|
|
169
|
+
*/
|
|
41
170
|
placeholder?: string;
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Color of the placeholder text.
|
|
174
|
+
*/
|
|
42
175
|
placeholderTextColor?: ColorValue;
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Color of the text cursor (caret).
|
|
179
|
+
* on iOS cursor color will be same as selection color
|
|
180
|
+
*/
|
|
43
181
|
cursorColor?: ColorValue;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Color of the text selection highlight.
|
|
185
|
+
*/
|
|
44
186
|
selectionColor?: ColorValue;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Controls automatic capitalization behavior.
|
|
190
|
+
*
|
|
191
|
+
* values: `"none"`, `"sentences"`, `"words"`, `"characters"`.
|
|
192
|
+
*/
|
|
45
193
|
autoCapitalize?: string;
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Enables or disables vertical scrolling.
|
|
197
|
+
*
|
|
198
|
+
* When disabled, the input will expand to fit its content.
|
|
199
|
+
*/
|
|
46
200
|
scrollEnabled?: boolean;
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Enables multiline text input.
|
|
204
|
+
*
|
|
205
|
+
* When `true`, the input can span multiple lines.
|
|
206
|
+
*/
|
|
47
207
|
multiline?: boolean;
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* ⚠️ **Use with caution**
|
|
211
|
+
*
|
|
212
|
+
* Limits the number of visible text lines.
|
|
213
|
+
*
|
|
214
|
+
* In complex or rich-text scenarios, `numberOfLines` may cause
|
|
215
|
+
* unexpected layout or scrolling issues—especially on iOS.
|
|
216
|
+
*
|
|
217
|
+
* **Recommended approach:**
|
|
218
|
+
* - Set `multiline={true}`
|
|
219
|
+
* - Control height using `maxHeight` instead
|
|
220
|
+
*/
|
|
48
221
|
numberOfLines?: Int32;
|
|
49
|
-
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* **Android only**
|
|
225
|
+
*
|
|
226
|
+
* Enables secure text entry (password mode).
|
|
227
|
+
* Characters are obscured as the user types.
|
|
228
|
+
*/
|
|
229
|
+
secureTextEntry?: boolean; // Android only
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* **iOS only**
|
|
233
|
+
*
|
|
234
|
+
* Controls the keyboard appearance.
|
|
235
|
+
*
|
|
236
|
+
* - `default` — System default appearance
|
|
237
|
+
* - `light` — Light keyboard
|
|
238
|
+
* - `dark` — Dark keyboard
|
|
239
|
+
*/
|
|
50
240
|
keyboardAppearance?: WithDefault<'default' | 'light' | 'dark', 'default'>; // ios only
|
|
51
241
|
|
|
52
|
-
|
|
53
|
-
|
|
242
|
+
/**
|
|
243
|
+
* Disables pasting images from the clipboard.
|
|
244
|
+
*
|
|
245
|
+
* - **iOS:** The “Paste” option is removed from the context menu
|
|
246
|
+
* when the clipboard contains only images.
|
|
247
|
+
* - **Android:** Stickers and GIF inputs are disabled, but the
|
|
248
|
+
* paste option may still appear due to platform limitations.
|
|
249
|
+
*/
|
|
250
|
+
disableImagePasting?: boolean;
|
|
54
251
|
|
|
55
|
-
// event callbacks
|
|
252
|
+
// event callbacks ---------------------------------------------------------------
|
|
253
|
+
/**
|
|
254
|
+
* Called when the input receives focus.
|
|
255
|
+
*/
|
|
56
256
|
onInputFocus?: DirectEventHandler<null>;
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Called when the input loses focus.
|
|
260
|
+
*/
|
|
57
261
|
onInputBlur?: DirectEventHandler<null>;
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Called whenever the text content changes.
|
|
265
|
+
*/
|
|
58
266
|
onChangeText?: DirectEventHandler<OnChangeTextEvent>;
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Called when the text selection changes.
|
|
270
|
+
*/
|
|
59
271
|
onChangeSelection?: DirectEventHandler<OnChangeSelectionEvent>;
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Called when an image is pasted from the clipboard.
|
|
275
|
+
* Emits {@link onPasteImageEventData}.
|
|
276
|
+
*/
|
|
60
277
|
onPasteImage?: BubblingEventHandler<onPasteImageEventData>;
|
|
61
278
|
|
|
62
279
|
// Style related props - used for generating proper setters in component's manager
|
|
63
280
|
// These should not be passed as regular props
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Text color.
|
|
284
|
+
*/
|
|
64
285
|
color?: ColorValue;
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Font size of the text.
|
|
289
|
+
*/
|
|
65
290
|
fontSize?: Float;
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Font family name.
|
|
294
|
+
*/
|
|
66
295
|
fontFamily?: string;
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Font weight.
|
|
299
|
+
*
|
|
300
|
+
* Example values: `"normal"`, `"bold"`, `"100"`–`"900"`.
|
|
301
|
+
*/
|
|
67
302
|
fontWeight?: string;
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Font style.
|
|
306
|
+
*
|
|
307
|
+
* Example values: `"normal"`, `"italic"`.
|
|
308
|
+
*/
|
|
68
309
|
fontStyle?: string;
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Line height of the text.
|
|
313
|
+
*/
|
|
69
314
|
lineHeight?: Float;
|
|
70
315
|
|
|
71
|
-
|
|
316
|
+
/**
|
|
317
|
+
* ⚠️ **Use with caution**
|
|
318
|
+
* Enabling this prop fixes input flickering while auto growing.
|
|
319
|
+
* However, it's still experimental and not tested well.
|
|
320
|
+
* it's causing some strange issues.
|
|
321
|
+
* See: https://github.com/software-mansion/react-native-enriched/issues/229
|
|
322
|
+
* const ANDROID_EXPERIMENTAL_SYNCHRONOUS_EVENTS = false;
|
|
323
|
+
*/
|
|
72
324
|
androidExperimentalSynchronousEvents?: boolean;
|
|
73
325
|
}
|
|
74
|
-
|
|
75
|
-
type ComponentType = HostComponent<TypeRichTextInputNativeProps>;
|
|
76
|
-
|
|
77
|
-
interface NativeCommands {
|
|
78
|
-
// General commands
|
|
79
|
-
focus: (viewRef: React.ElementRef<ComponentType>) => void;
|
|
80
|
-
blur: (viewRef: React.ElementRef<ComponentType>) => void;
|
|
81
|
-
setText: (viewRef: React.ElementRef<ComponentType>, text: string) => void;
|
|
82
|
-
insertTextAt: (
|
|
83
|
-
viewRef: React.ElementRef<ComponentType>,
|
|
84
|
-
start: Int32,
|
|
85
|
-
end: Int32,
|
|
86
|
-
text: string
|
|
87
|
-
) => void;
|
|
88
|
-
setSelection: (
|
|
89
|
-
viewRef: React.ElementRef<ComponentType>,
|
|
90
|
-
start: Int32,
|
|
91
|
-
end: Int32
|
|
92
|
-
) => void;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
|
|
96
|
-
supportedCommands: [
|
|
97
|
-
// General commands
|
|
98
|
-
'focus',
|
|
99
|
-
'blur',
|
|
100
|
-
'setText',
|
|
101
|
-
'setSelection',
|
|
102
|
-
'insertTextAt',
|
|
103
|
-
],
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
export default codegenNativeComponent<TypeRichTextInputNativeProps>(
|
|
107
|
-
'TypeRichTextInputView',
|
|
108
|
-
{
|
|
109
|
-
interfaceOnly: true,
|
|
110
|
-
}
|
|
111
|
-
) as HostComponent<TypeRichTextInputNativeProps>;
|
package/src/index.tsx
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
export { default as TypeRichTextInput } from './TypeRichTextInput';
|
|
2
2
|
export * from './TypeRichTextInputNativeComponent';
|
|
3
3
|
export * from './TypeRichTextInput';
|
|
4
|
-
export
|
|
5
|
-
OnChangeTextEvent,
|
|
6
|
-
OnChangeSelectionEvent,
|
|
7
|
-
onPasteImageEventData,
|
|
8
|
-
} from './TypeRichTextInputNativeComponent';
|
|
4
|
+
export * from './types/TypeRichTextInput';
|