@dongsuo/react-native-uitextview 1.0.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/LICENSE +20 -0
- package/README.md +225 -0
- package/android/generated/jni/CMakeLists.txt +36 -0
- package/android/generated/jni/RNUITextViewSpec-generated.cpp +22 -0
- package/android/generated/jni/RNUITextViewSpec.h +24 -0
- package/android/generated/jni/react/renderer/components/RNUITextViewSpec/ComponentDescriptors.cpp +23 -0
- package/android/generated/jni/react/renderer/components/RNUITextViewSpec/ComponentDescriptors.h +25 -0
- package/android/generated/jni/react/renderer/components/RNUITextViewSpec/EventEmitters.cpp +61 -0
- package/android/generated/jni/react/renderer/components/RNUITextViewSpec/EventEmitters.h +49 -0
- package/android/generated/jni/react/renderer/components/RNUITextViewSpec/Props.cpp +47 -0
- package/android/generated/jni/react/renderer/components/RNUITextViewSpec/Props.h +182 -0
- package/android/generated/jni/react/renderer/components/RNUITextViewSpec/RNUITextViewSpecJSI-generated.cpp +17 -0
- package/android/generated/jni/react/renderer/components/RNUITextViewSpec/RNUITextViewSpecJSI.h +19 -0
- package/android/generated/jni/react/renderer/components/RNUITextViewSpec/ShadowNodes.cpp +18 -0
- package/android/generated/jni/react/renderer/components/RNUITextViewSpec/ShadowNodes.h +43 -0
- package/android/generated/jni/react/renderer/components/RNUITextViewSpec/States.cpp +16 -0
- package/android/generated/jni/react/renderer/components/RNUITextViewSpec/States.h +41 -0
- package/ios/RNUITextView.h +23 -0
- package/ios/RNUITextView.mm +474 -0
- package/ios/RNUITextViewChild.h +24 -0
- package/ios/RNUITextViewChild.mm +76 -0
- package/ios/RNUITextViewChildComponentDescriptor.h +13 -0
- package/ios/RNUITextViewChildShadowNode.cpp +6 -0
- package/ios/RNUITextViewChildShadowNode.h +16 -0
- package/ios/RNUITextViewComponentDescriptor.h +13 -0
- package/ios/RNUITextViewEventEmitter.h +26 -0
- package/ios/RNUITextViewManager.mm +36 -0
- package/ios/RNUITextViewShadowNode.cpp +127 -0
- package/ios/RNUITextViewShadowNode.h +48 -0
- package/ios/RNUITextViewSpecJSI-generated.cpp +17 -0
- package/ios/RNUITextViewSpecJSI.h +19 -0
- package/ios/generated/RNUITextViewSpec/ComponentDescriptors.cpp +23 -0
- package/ios/generated/RNUITextViewSpec/ComponentDescriptors.h +25 -0
- package/ios/generated/RNUITextViewSpec/EventEmitters.cpp +61 -0
- package/ios/generated/RNUITextViewSpec/EventEmitters.h +49 -0
- package/ios/generated/RNUITextViewSpec/Props.cpp +47 -0
- package/ios/generated/RNUITextViewSpec/Props.h +182 -0
- package/ios/generated/RNUITextViewSpec/RCTComponentViewHelpers.h +24 -0
- package/ios/generated/RNUITextViewSpec/RNUITextViewSpec-generated.mm +16 -0
- package/ios/generated/RNUITextViewSpec/RNUITextViewSpec.h +38 -0
- package/ios/generated/RNUITextViewSpec/ShadowNodes.cpp +18 -0
- package/ios/generated/RNUITextViewSpec/ShadowNodes.h +43 -0
- package/ios/generated/RNUITextViewSpec/States.cpp +16 -0
- package/ios/generated/RNUITextViewSpec/States.h +41 -0
- package/ios/generated/RNUITextViewSpecJSI-generated.cpp +17 -0
- package/ios/generated/RNUITextViewSpecJSI.h +19 -0
- package/lib/commonjs/RNUITextViewChildNativeComponent.ts +48 -0
- package/lib/commonjs/RNUITextViewNativeComponent.ts +47 -0
- package/lib/commonjs/Text.js +140 -0
- package/lib/commonjs/Text.js.map +1 -0
- package/lib/commonjs/index.js +17 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/util.js +64 -0
- package/lib/commonjs/util.js.map +1 -0
- package/lib/module/RNUITextViewChildNativeComponent.ts +48 -0
- package/lib/module/RNUITextViewNativeComponent.ts +47 -0
- package/lib/module/Text.js +136 -0
- package/lib/module/Text.js.map +1 -0
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/util.js +60 -0
- package/lib/module/util.js.map +1 -0
- package/lib/typescript/commonjs/example/src/App.d.ts +2 -0
- package/lib/typescript/commonjs/example/src/App.d.ts.map +1 -0
- package/lib/typescript/commonjs/example/src/CustomMenuExample.d.ts +3 -0
- package/lib/typescript/commonjs/example/src/CustomMenuExample.d.ts.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/src/RNUITextViewChildNativeComponent.d.ts +28 -0
- package/lib/typescript/commonjs/src/RNUITextViewChildNativeComponent.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/RNUITextViewNativeComponent.d.ts +29 -0
- package/lib/typescript/commonjs/src/RNUITextViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/Text.d.ts +17 -0
- package/lib/typescript/commonjs/src/Text.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/index.d.ts +2 -0
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/util.d.ts +160 -0
- package/lib/typescript/commonjs/src/util.d.ts.map +1 -0
- package/lib/typescript/module/example/src/App.d.ts +2 -0
- package/lib/typescript/module/example/src/App.d.ts.map +1 -0
- package/lib/typescript/module/example/src/CustomMenuExample.d.ts +3 -0
- package/lib/typescript/module/example/src/CustomMenuExample.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/src/RNUITextViewChildNativeComponent.d.ts +28 -0
- package/lib/typescript/module/src/RNUITextViewChildNativeComponent.d.ts.map +1 -0
- package/lib/typescript/module/src/RNUITextViewNativeComponent.d.ts +29 -0
- package/lib/typescript/module/src/RNUITextViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/module/src/Text.d.ts +17 -0
- package/lib/typescript/module/src/Text.d.ts.map +1 -0
- package/lib/typescript/module/src/index.d.ts +2 -0
- package/lib/typescript/module/src/index.d.ts.map +1 -0
- package/lib/typescript/module/src/util.d.ts +160 -0
- package/lib/typescript/module/src/util.d.ts.map +1 -0
- package/package.json +187 -0
- package/react-native-uitextview.podspec +21 -0
- package/react-native.config.js +28 -0
- package/src/RNUITextViewChildNativeComponent.ts +48 -0
- package/src/RNUITextViewNativeComponent.ts +47 -0
- package/src/Text.tsx +148 -0
- package/src/index.tsx +1 -0
- package/src/util.ts +65 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { type StyleProp, type TextStyle } from 'react-native';
|
|
2
|
+
import type { NativeFontWeight } from './RNUITextViewChildNativeComponent';
|
|
3
|
+
export declare function flattenStyles(rootStyle: TextStyle, style: StyleProp<TextStyle>): {
|
|
4
|
+
fontWeight: NativeFontWeight;
|
|
5
|
+
backgroundColor: import("react-native").ColorValue;
|
|
6
|
+
shadowOffset: Readonly<{
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
}>;
|
|
10
|
+
color?: import("react-native").ColorValue | undefined;
|
|
11
|
+
fontFamily?: string | undefined;
|
|
12
|
+
fontSize?: number | undefined;
|
|
13
|
+
fontStyle?: "normal" | "italic" | undefined;
|
|
14
|
+
letterSpacing?: number | undefined;
|
|
15
|
+
lineHeight?: number | undefined;
|
|
16
|
+
textAlign?: "auto" | "left" | "right" | "center" | "justify" | undefined;
|
|
17
|
+
textDecorationLine?: "none" | "underline" | "line-through" | "underline line-through" | undefined;
|
|
18
|
+
textDecorationStyle?: "solid" | "double" | "dotted" | "dashed" | undefined;
|
|
19
|
+
textDecorationColor?: import("react-native").ColorValue | undefined;
|
|
20
|
+
textShadowColor?: import("react-native").ColorValue | undefined;
|
|
21
|
+
textShadowOffset?: {
|
|
22
|
+
width: number;
|
|
23
|
+
height: number;
|
|
24
|
+
} | undefined;
|
|
25
|
+
textShadowRadius?: number | undefined;
|
|
26
|
+
textTransform?: "none" | "capitalize" | "uppercase" | "lowercase" | undefined;
|
|
27
|
+
userSelect?: "auto" | "none" | "text" | "contain" | "all" | undefined;
|
|
28
|
+
fontVariant?: import("react-native").FontVariant[] | undefined;
|
|
29
|
+
writingDirection?: "auto" | "ltr" | "rtl" | undefined;
|
|
30
|
+
backfaceVisibility?: "visible" | "hidden" | undefined;
|
|
31
|
+
borderBlockColor?: import("react-native").ColorValue | undefined;
|
|
32
|
+
borderBlockEndColor?: import("react-native").ColorValue | undefined;
|
|
33
|
+
borderBlockStartColor?: import("react-native").ColorValue | undefined;
|
|
34
|
+
borderBottomColor?: import("react-native").ColorValue | undefined;
|
|
35
|
+
borderBottomEndRadius?: import("react-native").AnimatableNumericValue | string | undefined;
|
|
36
|
+
borderBottomLeftRadius?: import("react-native").AnimatableNumericValue | string | undefined;
|
|
37
|
+
borderBottomRightRadius?: import("react-native").AnimatableNumericValue | string | undefined;
|
|
38
|
+
borderBottomStartRadius?: import("react-native").AnimatableNumericValue | string | undefined;
|
|
39
|
+
borderColor?: import("react-native").ColorValue | undefined;
|
|
40
|
+
borderCurve?: "circular" | "continuous" | undefined;
|
|
41
|
+
borderEndColor?: import("react-native").ColorValue | undefined;
|
|
42
|
+
borderEndEndRadius?: import("react-native").AnimatableNumericValue | string | undefined;
|
|
43
|
+
borderEndStartRadius?: import("react-native").AnimatableNumericValue | string | undefined;
|
|
44
|
+
borderLeftColor?: import("react-native").ColorValue | undefined;
|
|
45
|
+
borderRadius?: import("react-native").AnimatableNumericValue | string | undefined;
|
|
46
|
+
borderRightColor?: import("react-native").ColorValue | undefined;
|
|
47
|
+
borderStartColor?: import("react-native").ColorValue | undefined;
|
|
48
|
+
borderStartEndRadius?: import("react-native").AnimatableNumericValue | string | undefined;
|
|
49
|
+
borderStartStartRadius?: import("react-native").AnimatableNumericValue | string | undefined;
|
|
50
|
+
borderStyle?: "solid" | "dotted" | "dashed" | undefined;
|
|
51
|
+
borderTopColor?: import("react-native").ColorValue | undefined;
|
|
52
|
+
borderTopEndRadius?: import("react-native").AnimatableNumericValue | string | undefined;
|
|
53
|
+
borderTopLeftRadius?: import("react-native").AnimatableNumericValue | string | undefined;
|
|
54
|
+
borderTopRightRadius?: import("react-native").AnimatableNumericValue | string | undefined;
|
|
55
|
+
borderTopStartRadius?: import("react-native").AnimatableNumericValue | string | undefined;
|
|
56
|
+
outlineColor?: import("react-native").ColorValue | undefined;
|
|
57
|
+
outlineOffset?: import("react-native").AnimatableNumericValue | undefined;
|
|
58
|
+
outlineStyle?: "solid" | "dotted" | "dashed" | undefined;
|
|
59
|
+
outlineWidth?: import("react-native").AnimatableNumericValue | undefined;
|
|
60
|
+
opacity?: import("react-native").AnimatableNumericValue | undefined;
|
|
61
|
+
elevation?: number | undefined;
|
|
62
|
+
pointerEvents?: "box-none" | "none" | "box-only" | "auto" | undefined;
|
|
63
|
+
isolation?: "auto" | "isolate" | undefined;
|
|
64
|
+
cursor?: import("react-native").CursorValue | undefined;
|
|
65
|
+
boxShadow?: ReadonlyArray<import("react-native").BoxShadowValue> | string | undefined;
|
|
66
|
+
filter?: ReadonlyArray<import("react-native").FilterFunction> | string | undefined;
|
|
67
|
+
mixBlendMode?: import("react-native").BlendMode | undefined;
|
|
68
|
+
experimental_backgroundImage?: ReadonlyArray<import("react-native").GradientValue> | string | undefined;
|
|
69
|
+
alignContent?: "flex-start" | "flex-end" | "center" | "stretch" | "space-between" | "space-around" | "space-evenly" | undefined;
|
|
70
|
+
alignItems?: import("react-native").FlexAlignType | undefined;
|
|
71
|
+
alignSelf?: "auto" | import("react-native").FlexAlignType | undefined;
|
|
72
|
+
aspectRatio?: number | string | undefined;
|
|
73
|
+
borderBottomWidth?: number | undefined;
|
|
74
|
+
borderEndWidth?: number | undefined;
|
|
75
|
+
borderLeftWidth?: number | undefined;
|
|
76
|
+
borderRightWidth?: number | undefined;
|
|
77
|
+
borderStartWidth?: number | undefined;
|
|
78
|
+
borderTopWidth?: number | undefined;
|
|
79
|
+
borderWidth?: number | undefined;
|
|
80
|
+
bottom?: import("react-native").DimensionValue | undefined;
|
|
81
|
+
boxSizing?: "border-box" | "content-box" | undefined;
|
|
82
|
+
display?: "none" | "flex" | "contents" | undefined;
|
|
83
|
+
end?: import("react-native").DimensionValue | undefined;
|
|
84
|
+
flex?: number | undefined;
|
|
85
|
+
flexBasis?: import("react-native").DimensionValue | undefined;
|
|
86
|
+
flexDirection?: "row" | "column" | "row-reverse" | "column-reverse" | undefined;
|
|
87
|
+
rowGap?: number | string | undefined;
|
|
88
|
+
gap?: number | string | undefined;
|
|
89
|
+
columnGap?: number | string | undefined;
|
|
90
|
+
flexGrow?: number | undefined;
|
|
91
|
+
flexShrink?: number | undefined;
|
|
92
|
+
flexWrap?: "wrap" | "nowrap" | "wrap-reverse" | undefined;
|
|
93
|
+
height?: import("react-native").DimensionValue | undefined;
|
|
94
|
+
justifyContent?: "flex-start" | "flex-end" | "center" | "space-between" | "space-around" | "space-evenly" | undefined;
|
|
95
|
+
left?: import("react-native").DimensionValue | undefined;
|
|
96
|
+
margin?: import("react-native").DimensionValue | undefined;
|
|
97
|
+
marginBottom?: import("react-native").DimensionValue | undefined;
|
|
98
|
+
marginEnd?: import("react-native").DimensionValue | undefined;
|
|
99
|
+
marginHorizontal?: import("react-native").DimensionValue | undefined;
|
|
100
|
+
marginLeft?: import("react-native").DimensionValue | undefined;
|
|
101
|
+
marginRight?: import("react-native").DimensionValue | undefined;
|
|
102
|
+
marginStart?: import("react-native").DimensionValue | undefined;
|
|
103
|
+
marginTop?: import("react-native").DimensionValue | undefined;
|
|
104
|
+
marginVertical?: import("react-native").DimensionValue | undefined;
|
|
105
|
+
maxHeight?: import("react-native").DimensionValue | undefined;
|
|
106
|
+
maxWidth?: import("react-native").DimensionValue | undefined;
|
|
107
|
+
minHeight?: import("react-native").DimensionValue | undefined;
|
|
108
|
+
minWidth?: import("react-native").DimensionValue | undefined;
|
|
109
|
+
overflow?: "visible" | "hidden" | "scroll" | undefined;
|
|
110
|
+
padding?: import("react-native").DimensionValue | undefined;
|
|
111
|
+
paddingBottom?: import("react-native").DimensionValue | undefined;
|
|
112
|
+
paddingEnd?: import("react-native").DimensionValue | undefined;
|
|
113
|
+
paddingHorizontal?: import("react-native").DimensionValue | undefined;
|
|
114
|
+
paddingLeft?: import("react-native").DimensionValue | undefined;
|
|
115
|
+
paddingRight?: import("react-native").DimensionValue | undefined;
|
|
116
|
+
paddingStart?: import("react-native").DimensionValue | undefined;
|
|
117
|
+
paddingTop?: import("react-native").DimensionValue | undefined;
|
|
118
|
+
paddingVertical?: import("react-native").DimensionValue | undefined;
|
|
119
|
+
position?: "absolute" | "relative" | "static" | undefined;
|
|
120
|
+
right?: import("react-native").DimensionValue | undefined;
|
|
121
|
+
start?: import("react-native").DimensionValue | undefined;
|
|
122
|
+
top?: import("react-native").DimensionValue | undefined;
|
|
123
|
+
width?: import("react-native").DimensionValue | undefined;
|
|
124
|
+
zIndex?: number | undefined;
|
|
125
|
+
direction?: "inherit" | "ltr" | "rtl" | undefined;
|
|
126
|
+
inset?: import("react-native").DimensionValue | undefined;
|
|
127
|
+
insetBlock?: import("react-native").DimensionValue | undefined;
|
|
128
|
+
insetBlockEnd?: import("react-native").DimensionValue | undefined;
|
|
129
|
+
insetBlockStart?: import("react-native").DimensionValue | undefined;
|
|
130
|
+
insetInline?: import("react-native").DimensionValue | undefined;
|
|
131
|
+
insetInlineEnd?: import("react-native").DimensionValue | undefined;
|
|
132
|
+
insetInlineStart?: import("react-native").DimensionValue | undefined;
|
|
133
|
+
marginBlock?: import("react-native").DimensionValue | undefined;
|
|
134
|
+
marginBlockEnd?: import("react-native").DimensionValue | undefined;
|
|
135
|
+
marginBlockStart?: import("react-native").DimensionValue | undefined;
|
|
136
|
+
marginInline?: import("react-native").DimensionValue | undefined;
|
|
137
|
+
marginInlineEnd?: import("react-native").DimensionValue | undefined;
|
|
138
|
+
marginInlineStart?: import("react-native").DimensionValue | undefined;
|
|
139
|
+
paddingBlock?: import("react-native").DimensionValue | undefined;
|
|
140
|
+
paddingBlockEnd?: import("react-native").DimensionValue | undefined;
|
|
141
|
+
paddingBlockStart?: import("react-native").DimensionValue | undefined;
|
|
142
|
+
paddingInline?: import("react-native").DimensionValue | undefined;
|
|
143
|
+
paddingInlineEnd?: import("react-native").DimensionValue | undefined;
|
|
144
|
+
paddingInlineStart?: import("react-native").DimensionValue | undefined;
|
|
145
|
+
shadowColor?: import("react-native").ColorValue | undefined;
|
|
146
|
+
shadowOpacity?: import("react-native").AnimatableNumericValue | undefined;
|
|
147
|
+
shadowRadius?: number | undefined;
|
|
148
|
+
transform?: Readonly<import("react-native").MaximumOneOf<import("react-native").PerspectiveTransform & import("react-native").RotateTransform & import("react-native").RotateXTransform & import("react-native").RotateYTransform & import("react-native").RotateZTransform & import("react-native").ScaleTransform & import("react-native").ScaleXTransform & import("react-native").ScaleYTransform & import("react-native").TranslateXTransform & import("react-native").TranslateYTransform & import("react-native").SkewXTransform & import("react-native").SkewYTransform & import("react-native").MatrixTransform>[]> | string | undefined;
|
|
149
|
+
transformOrigin?: Array<string | number> | string | undefined;
|
|
150
|
+
transformMatrix?: Array<number> | undefined;
|
|
151
|
+
rotation?: import("react-native").AnimatableNumericValue | undefined;
|
|
152
|
+
scaleX?: import("react-native").AnimatableNumericValue | undefined;
|
|
153
|
+
scaleY?: import("react-native").AnimatableNumericValue | undefined;
|
|
154
|
+
translateX?: import("react-native").AnimatableNumericValue | undefined;
|
|
155
|
+
translateY?: import("react-native").AnimatableNumericValue | undefined;
|
|
156
|
+
textAlignVertical?: "auto" | "top" | "bottom" | "center" | undefined;
|
|
157
|
+
verticalAlign?: "auto" | "top" | "bottom" | "middle" | undefined;
|
|
158
|
+
includeFontPadding?: boolean | undefined;
|
|
159
|
+
};
|
|
160
|
+
//# sourceMappingURL=util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../../src/util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,SAAS,EAAc,KAAK,SAAS,EAAC,MAAM,cAAc,CAAA;AACvE,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,oCAAoC,CAAA;AAExE,wBAAgB,aAAa,CAC3B,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAa5B"}
|
package/package.json
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dongsuo/react-native-uitextview",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Enhanced UITextView for React Native with custom context menu support",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/your-username/react-native-uitextview.git"
|
|
8
|
+
},
|
|
9
|
+
"author": "Your Name <your.email@example.com>",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"homepage": "https://github.com/your-username/react-native-uitextview#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/your-username/react-native-uitextview/issues"
|
|
14
|
+
},
|
|
15
|
+
"source": "./src/index.tsx",
|
|
16
|
+
"main": "./lib/commonjs/index.js",
|
|
17
|
+
"types": "./lib/typescript/commonjs/src/index.d.ts",
|
|
18
|
+
"files": [
|
|
19
|
+
"src",
|
|
20
|
+
"lib",
|
|
21
|
+
"android",
|
|
22
|
+
"ios",
|
|
23
|
+
"cpp",
|
|
24
|
+
"*.podspec",
|
|
25
|
+
"react-native.config.js",
|
|
26
|
+
"!ios/build",
|
|
27
|
+
"!android/build",
|
|
28
|
+
"!android/gradle",
|
|
29
|
+
"!android/gradlew",
|
|
30
|
+
"!android/gradlew.bat",
|
|
31
|
+
"!android/local.properties",
|
|
32
|
+
"!**/__tests__",
|
|
33
|
+
"!**/__fixtures__",
|
|
34
|
+
"!**/__mocks__",
|
|
35
|
+
"!**/.*"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"example": "yarn workspace react-native-uitextview-example",
|
|
39
|
+
"test": "jest",
|
|
40
|
+
"typecheck": "tsc",
|
|
41
|
+
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
42
|
+
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
|
|
43
|
+
"prepare": "bob build",
|
|
44
|
+
"release": "release-it"
|
|
45
|
+
},
|
|
46
|
+
"keywords": [
|
|
47
|
+
"react-native",
|
|
48
|
+
"ios",
|
|
49
|
+
"android"
|
|
50
|
+
],
|
|
51
|
+
"publishConfig": {
|
|
52
|
+
"registry": "https://registry.npmjs.org/"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@commitlint/config-conventional": "^19.6.0",
|
|
56
|
+
"@eslint/compat": "^1.2.7",
|
|
57
|
+
"@eslint/eslintrc": "^3.3.0",
|
|
58
|
+
"@eslint/js": "^9.22.0",
|
|
59
|
+
"@evilmartians/lefthook": "^1.5.0",
|
|
60
|
+
"@react-native-community/cli": "^18.0.0",
|
|
61
|
+
"@react-native/babel-preset": "0.79.1",
|
|
62
|
+
"@react-native/eslint-config": "^0.78.0",
|
|
63
|
+
"@release-it/conventional-changelog": "^9.0.2",
|
|
64
|
+
"@types/jest": "^29.5.5",
|
|
65
|
+
"@types/react": "^19.0.0",
|
|
66
|
+
"commitlint": "^19.6.1",
|
|
67
|
+
"del-cli": "^5.1.0",
|
|
68
|
+
"eslint": "^9.22.0",
|
|
69
|
+
"eslint-config-prettier": "^10.1.1",
|
|
70
|
+
"eslint-plugin-prettier": "^5.2.3",
|
|
71
|
+
"jest": "^29.7.0",
|
|
72
|
+
"prettier": "^3.0.3",
|
|
73
|
+
"react": "19.0.0",
|
|
74
|
+
"react-native": "0.79.2",
|
|
75
|
+
"react-native-builder-bob": "0.40.7",
|
|
76
|
+
"react-native-test-app": "4.0.4",
|
|
77
|
+
"release-it": "^19.0.1",
|
|
78
|
+
"turbo": "^1.10.7",
|
|
79
|
+
"typescript": "^5.2.2"
|
|
80
|
+
},
|
|
81
|
+
"peerDependencies": {
|
|
82
|
+
"react": "*",
|
|
83
|
+
"react-native": "*"
|
|
84
|
+
},
|
|
85
|
+
"workspaces": [
|
|
86
|
+
"example"
|
|
87
|
+
],
|
|
88
|
+
"packageManager": "yarn@3.6.1",
|
|
89
|
+
"jest": {
|
|
90
|
+
"preset": "react-native",
|
|
91
|
+
"modulePathIgnorePatterns": [
|
|
92
|
+
"<rootDir>/example/node_modules",
|
|
93
|
+
"<rootDir>/lib/"
|
|
94
|
+
]
|
|
95
|
+
},
|
|
96
|
+
"commitlint": {
|
|
97
|
+
"extends": [
|
|
98
|
+
"@commitlint/config-conventional"
|
|
99
|
+
]
|
|
100
|
+
},
|
|
101
|
+
"release-it": {
|
|
102
|
+
"git": {
|
|
103
|
+
"commitMessage": "chore: release ${version}",
|
|
104
|
+
"tagName": "v${version}"
|
|
105
|
+
},
|
|
106
|
+
"npm": {
|
|
107
|
+
"publish": false
|
|
108
|
+
},
|
|
109
|
+
"github": {
|
|
110
|
+
"release": true
|
|
111
|
+
},
|
|
112
|
+
"plugins": {
|
|
113
|
+
"@release-it/conventional-changelog": {
|
|
114
|
+
"whatBump": false,
|
|
115
|
+
"preset": {
|
|
116
|
+
"name": "angular"
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"prettier": {
|
|
122
|
+
"semi": false,
|
|
123
|
+
"arrowParens": "avoid",
|
|
124
|
+
"bracketSameLine": true,
|
|
125
|
+
"bracketSpacing": false,
|
|
126
|
+
"quoteProps": "consistent",
|
|
127
|
+
"singleQuote": true,
|
|
128
|
+
"tabWidth": 2,
|
|
129
|
+
"trailingComma": "all",
|
|
130
|
+
"useTabs": false
|
|
131
|
+
},
|
|
132
|
+
"codegenConfig": {
|
|
133
|
+
"name": "RNUITextViewSpec",
|
|
134
|
+
"type": "all",
|
|
135
|
+
"jsSrcsDir": "src",
|
|
136
|
+
"ios": {
|
|
137
|
+
"componentProvider": {
|
|
138
|
+
"RNUITextView": "RNUITextView",
|
|
139
|
+
"RNUITextViewChild": "RNUITextViewChild"
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
"android": {
|
|
143
|
+
"javaPackageName": "xyz.blueskyweb.rnuitextview"
|
|
144
|
+
},
|
|
145
|
+
"outputDir": {
|
|
146
|
+
"android": "android/generated",
|
|
147
|
+
"ios": "ios/generated"
|
|
148
|
+
},
|
|
149
|
+
"includesGeneratedCode": true
|
|
150
|
+
},
|
|
151
|
+
"create-react-native-library": {
|
|
152
|
+
"languages": "kotlin-objc",
|
|
153
|
+
"type": "fabric-view",
|
|
154
|
+
"version": "0.49.8"
|
|
155
|
+
},
|
|
156
|
+
"module": "./lib/module/index.js",
|
|
157
|
+
"react-native-builder-bob": {
|
|
158
|
+
"source": "src",
|
|
159
|
+
"output": "lib",
|
|
160
|
+
"targets": [
|
|
161
|
+
[
|
|
162
|
+
"commonjs",
|
|
163
|
+
{
|
|
164
|
+
"esm": true
|
|
165
|
+
}
|
|
166
|
+
],
|
|
167
|
+
[
|
|
168
|
+
"module",
|
|
169
|
+
{
|
|
170
|
+
"esm": true
|
|
171
|
+
}
|
|
172
|
+
],
|
|
173
|
+
[
|
|
174
|
+
"typescript",
|
|
175
|
+
{}
|
|
176
|
+
],
|
|
177
|
+
"codegen"
|
|
178
|
+
]
|
|
179
|
+
},
|
|
180
|
+
"eslintIgnore": [
|
|
181
|
+
"node_modules/",
|
|
182
|
+
"lib/"
|
|
183
|
+
],
|
|
184
|
+
"dependencies": {
|
|
185
|
+
"arktype": "2.1.15"
|
|
186
|
+
}
|
|
187
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = "react-native-uitextview"
|
|
7
|
+
s.version = package["version"]
|
|
8
|
+
s.summary = package["description"]
|
|
9
|
+
s.homepage = package["homepage"]
|
|
10
|
+
s.license = package["license"]
|
|
11
|
+
s.authors = package["author"]
|
|
12
|
+
|
|
13
|
+
s.platforms = { :ios => min_ios_version_supported }
|
|
14
|
+
s.source = { :git => "https://github.com/bluesky-social/react-native-uitextview.git", :tag => "#{s.version}" }
|
|
15
|
+
|
|
16
|
+
s.source_files = "ios/**/*.{h,m,mm,cpp}"
|
|
17
|
+
|
|
18
|
+
s.private_header_files = "ios/**/*.h"
|
|
19
|
+
|
|
20
|
+
install_modules_dependencies(s)
|
|
21
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const project = (() => {
|
|
2
|
+
const path = require('node:path')
|
|
3
|
+
try {
|
|
4
|
+
const {configureProjects} = require('react-native-test-app')
|
|
5
|
+
|
|
6
|
+
return configureProjects({
|
|
7
|
+
android: {},
|
|
8
|
+
ios: {
|
|
9
|
+
sourceDir: path.join('example', 'ios'),
|
|
10
|
+
},
|
|
11
|
+
})
|
|
12
|
+
} catch (e) {
|
|
13
|
+
return undefined
|
|
14
|
+
}
|
|
15
|
+
})()
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @type {import('@react-native-community/cli-types').UserDependencyConfig}
|
|
19
|
+
*/
|
|
20
|
+
module.exports = {
|
|
21
|
+
dependencies: {
|
|
22
|
+
// Help rn-cli find and autolink this library
|
|
23
|
+
'react-native-uitextview': {
|
|
24
|
+
root: __dirname,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
...(project ? {project} : undefined),
|
|
28
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'
|
|
2
|
+
import type {ColorValue, ViewProps} from 'react-native'
|
|
3
|
+
import type {
|
|
4
|
+
BubblingEventHandler,
|
|
5
|
+
Float,
|
|
6
|
+
Int32,
|
|
7
|
+
WithDefault,
|
|
8
|
+
} from 'react-native/Libraries/Types/CodegenTypes'
|
|
9
|
+
|
|
10
|
+
interface TargetedEvent {
|
|
11
|
+
target: Int32
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type TextDecorationLine = 'none' | 'underline' | 'line-through'
|
|
15
|
+
|
|
16
|
+
type TextDecorationStyle = 'solid' | 'double' | 'dotted' | 'dashed'
|
|
17
|
+
|
|
18
|
+
export type NativeFontWeight =
|
|
19
|
+
| 'normal'
|
|
20
|
+
| 'bold'
|
|
21
|
+
| 'ultraLight'
|
|
22
|
+
| 'light'
|
|
23
|
+
| 'medium'
|
|
24
|
+
| 'semibold'
|
|
25
|
+
| 'heavy'
|
|
26
|
+
|
|
27
|
+
type FontStyle = 'normal' | 'italic'
|
|
28
|
+
|
|
29
|
+
interface NativeProps extends ViewProps {
|
|
30
|
+
text: string
|
|
31
|
+
color?: ColorValue
|
|
32
|
+
fontSize?: Float
|
|
33
|
+
fontStyle?: WithDefault<FontStyle, 'normal'>
|
|
34
|
+
fontWeight?: WithDefault<NativeFontWeight, 'normal'>
|
|
35
|
+
fontFamily?: string
|
|
36
|
+
letterSpacing?: Float
|
|
37
|
+
lineHeight?: Float
|
|
38
|
+
textDecorationLine?: WithDefault<TextDecorationLine, 'none'>
|
|
39
|
+
textDecorationStyle?: WithDefault<TextDecorationStyle, 'solid'>
|
|
40
|
+
textDecorationColor?: ColorValue
|
|
41
|
+
shadowRadius?: WithDefault<Float, 0>
|
|
42
|
+
onPress?: BubblingEventHandler<TargetedEvent>
|
|
43
|
+
onLongPress?: BubblingEventHandler<TargetedEvent>
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default codegenNativeComponent<NativeProps>('RNUITextViewChild', {
|
|
47
|
+
excludedPlatforms: ['android'],
|
|
48
|
+
})
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'
|
|
2
|
+
import type {ViewProps} from 'react-native'
|
|
3
|
+
import type {
|
|
4
|
+
BubblingEventHandler,
|
|
5
|
+
Int32,
|
|
6
|
+
WithDefault,
|
|
7
|
+
DirectEventHandler,
|
|
8
|
+
} from 'react-native/Libraries/Types/CodegenTypes'
|
|
9
|
+
|
|
10
|
+
interface TargetedEvent {
|
|
11
|
+
target: Int32
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface TextLayoutEvent extends TargetedEvent {
|
|
15
|
+
lines: string[]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// 自定义菜单项接口
|
|
19
|
+
interface CustomMenuItem {
|
|
20
|
+
title: string
|
|
21
|
+
actionId: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// 自定义菜单操作事件
|
|
25
|
+
interface CustomMenuActionEvent extends TargetedEvent {
|
|
26
|
+
actionId: string
|
|
27
|
+
selectedText: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
type EllipsizeMode = 'head' | 'middle' | 'tail' | 'clip'
|
|
31
|
+
|
|
32
|
+
interface NativeProps extends ViewProps {
|
|
33
|
+
// 现有属性
|
|
34
|
+
numberOfLines?: Int32
|
|
35
|
+
allowsFontScaling?: boolean
|
|
36
|
+
ellipsizeMode?: WithDefault<EllipsizeMode, 'tail'>
|
|
37
|
+
selectable?: boolean
|
|
38
|
+
onTextLayout?: BubblingEventHandler<TextLayoutEvent>
|
|
39
|
+
|
|
40
|
+
// 新增自定义菜单属性
|
|
41
|
+
customMenuItems?: ReadonlyArray<CustomMenuItem>
|
|
42
|
+
onCustomMenuAction?: DirectEventHandler<CustomMenuActionEvent>
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export default codegenNativeComponent<NativeProps>('RNUITextView', {
|
|
46
|
+
excludedPlatforms: ['android'],
|
|
47
|
+
})
|
package/src/Text.tsx
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import {
|
|
3
|
+
Platform,
|
|
4
|
+
StyleSheet,
|
|
5
|
+
Text as RNText,
|
|
6
|
+
type TextProps,
|
|
7
|
+
type ViewStyle,
|
|
8
|
+
} from 'react-native'
|
|
9
|
+
|
|
10
|
+
// 自定义菜单项接口
|
|
11
|
+
interface CustomMenuItem {
|
|
12
|
+
title: string
|
|
13
|
+
actionId: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// 自定义菜单事件接口
|
|
17
|
+
interface CustomMenuActionEvent {
|
|
18
|
+
actionId: string
|
|
19
|
+
selectedText: string
|
|
20
|
+
}
|
|
21
|
+
import RNUITextViewChildNativeComponent from './RNUITextViewChildNativeComponent'
|
|
22
|
+
import RNUITextViewNativeComponent from './RNUITextViewNativeComponent'
|
|
23
|
+
import {flattenStyles} from './util'
|
|
24
|
+
|
|
25
|
+
const TextAncestorContext = React.createContext<[boolean, ViewStyle]>([
|
|
26
|
+
false,
|
|
27
|
+
StyleSheet.create({}),
|
|
28
|
+
])
|
|
29
|
+
|
|
30
|
+
const textDefaults: TextProps = {
|
|
31
|
+
allowFontScaling: true,
|
|
32
|
+
selectable: true,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const useTextAncestorContext = () => React.useContext(TextAncestorContext)
|
|
36
|
+
|
|
37
|
+
// 扩展 TextProps 类型添加自定义菜单相关属性
|
|
38
|
+
type ExtendedTextProps = TextProps & {
|
|
39
|
+
uiTextView?: boolean
|
|
40
|
+
customMenuItems?: CustomMenuItem[]
|
|
41
|
+
onCustomMenuAction?: (event: CustomMenuActionEvent) => void
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function UITextViewChild({
|
|
45
|
+
style,
|
|
46
|
+
children,
|
|
47
|
+
customMenuItems,
|
|
48
|
+
onCustomMenuAction,
|
|
49
|
+
...rest
|
|
50
|
+
}: ExtendedTextProps) {
|
|
51
|
+
const [isAncestor, rootStyle] = useTextAncestorContext()
|
|
52
|
+
|
|
53
|
+
// Flatten the styles, and apply the root styles when needed
|
|
54
|
+
const flattenedStyle = React.useMemo(
|
|
55
|
+
() => flattenStyles(rootStyle, style),
|
|
56
|
+
[rootStyle, style],
|
|
57
|
+
)
|
|
58
|
+
console.log('customMenuItems', customMenuItems)
|
|
59
|
+
if (!isAncestor) {
|
|
60
|
+
return (
|
|
61
|
+
<TextAncestorContext.Provider value={[true, flattenedStyle]}>
|
|
62
|
+
<RNUITextViewNativeComponent
|
|
63
|
+
{...textDefaults}
|
|
64
|
+
{...rest}
|
|
65
|
+
// ellipsizeMode={rest.ellipsizeMode ?? rest.lineBreakMode ?? 'tail'}
|
|
66
|
+
style={[flattenedStyle]}
|
|
67
|
+
// 自定义菜单相关属性
|
|
68
|
+
customMenuItems={customMenuItems}
|
|
69
|
+
onCustomMenuAction={event => {
|
|
70
|
+
onCustomMenuAction &&
|
|
71
|
+
onCustomMenuAction({
|
|
72
|
+
actionId: event.nativeEvent.actionId,
|
|
73
|
+
selectedText: event.nativeEvent.selectedText,
|
|
74
|
+
})
|
|
75
|
+
}}
|
|
76
|
+
// @ts-expect-error Weirdness
|
|
77
|
+
onPress={undefined}
|
|
78
|
+
onLongPress={undefined}>
|
|
79
|
+
{React.Children.toArray(children).map((c, index) => {
|
|
80
|
+
if (React.isValidElement(c)) {
|
|
81
|
+
return c
|
|
82
|
+
} else if (typeof c === 'string' || typeof c === 'number') {
|
|
83
|
+
return (
|
|
84
|
+
// @ts-expect-error @TODO fix this type
|
|
85
|
+
<RNUITextViewChildNativeComponent
|
|
86
|
+
key={index}
|
|
87
|
+
style={flattenedStyle}
|
|
88
|
+
text={c.toString()}
|
|
89
|
+
{...rest}
|
|
90
|
+
/>
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
return null
|
|
94
|
+
})}
|
|
95
|
+
</RNUITextViewNativeComponent>
|
|
96
|
+
</TextAncestorContext.Provider>
|
|
97
|
+
)
|
|
98
|
+
} else {
|
|
99
|
+
return (
|
|
100
|
+
<>
|
|
101
|
+
{React.Children.toArray(children).map((c, index) => {
|
|
102
|
+
if (React.isValidElement(c)) {
|
|
103
|
+
return c
|
|
104
|
+
} else if (typeof c === 'string' || typeof c === 'number') {
|
|
105
|
+
return (
|
|
106
|
+
// @ts-expect-error @TODO fix this type
|
|
107
|
+
<RNUITextViewChildNativeComponent
|
|
108
|
+
key={index}
|
|
109
|
+
style={flattenedStyle}
|
|
110
|
+
text={c.toString()}
|
|
111
|
+
{...rest}
|
|
112
|
+
/>
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return null
|
|
117
|
+
})}
|
|
118
|
+
</>
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function UITextViewInner(props: ExtendedTextProps) {
|
|
124
|
+
const [isAncestor] = useTextAncestorContext()
|
|
125
|
+
|
|
126
|
+
// Even if the uiTextView prop is set, we can still default to using
|
|
127
|
+
// normal selection (i.e. base RN text) if the text doesn't need to be
|
|
128
|
+
// selectable
|
|
129
|
+
if ((!props.selectable || !props.uiTextView) && !isAncestor) {
|
|
130
|
+
// 当使用原生 RNText 时,自定义菜单功能不可用
|
|
131
|
+
// Using _ prefix to indicate these are intentionally unused
|
|
132
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
133
|
+
const {customMenuItems: _, onCustomMenuAction: __, ...restProps} = props
|
|
134
|
+
return <RNText {...restProps} />
|
|
135
|
+
}
|
|
136
|
+
return <UITextViewChild {...props} />
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function UITextView(props: ExtendedTextProps) {
|
|
140
|
+
if (Platform.OS !== 'ios') {
|
|
141
|
+
// 当不是 iOS 平台时,自定义菜单功能不可用
|
|
142
|
+
// Using _ prefix to indicate these are intentionally unused
|
|
143
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
144
|
+
const {customMenuItems: _, onCustomMenuAction: __, ...restProps} = props
|
|
145
|
+
return <RNText {...restProps} />
|
|
146
|
+
}
|
|
147
|
+
return <UITextViewInner {...props} />
|
|
148
|
+
}
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Text'
|