@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.
Files changed (102) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +225 -0
  3. package/android/generated/jni/CMakeLists.txt +36 -0
  4. package/android/generated/jni/RNUITextViewSpec-generated.cpp +22 -0
  5. package/android/generated/jni/RNUITextViewSpec.h +24 -0
  6. package/android/generated/jni/react/renderer/components/RNUITextViewSpec/ComponentDescriptors.cpp +23 -0
  7. package/android/generated/jni/react/renderer/components/RNUITextViewSpec/ComponentDescriptors.h +25 -0
  8. package/android/generated/jni/react/renderer/components/RNUITextViewSpec/EventEmitters.cpp +61 -0
  9. package/android/generated/jni/react/renderer/components/RNUITextViewSpec/EventEmitters.h +49 -0
  10. package/android/generated/jni/react/renderer/components/RNUITextViewSpec/Props.cpp +47 -0
  11. package/android/generated/jni/react/renderer/components/RNUITextViewSpec/Props.h +182 -0
  12. package/android/generated/jni/react/renderer/components/RNUITextViewSpec/RNUITextViewSpecJSI-generated.cpp +17 -0
  13. package/android/generated/jni/react/renderer/components/RNUITextViewSpec/RNUITextViewSpecJSI.h +19 -0
  14. package/android/generated/jni/react/renderer/components/RNUITextViewSpec/ShadowNodes.cpp +18 -0
  15. package/android/generated/jni/react/renderer/components/RNUITextViewSpec/ShadowNodes.h +43 -0
  16. package/android/generated/jni/react/renderer/components/RNUITextViewSpec/States.cpp +16 -0
  17. package/android/generated/jni/react/renderer/components/RNUITextViewSpec/States.h +41 -0
  18. package/ios/RNUITextView.h +23 -0
  19. package/ios/RNUITextView.mm +474 -0
  20. package/ios/RNUITextViewChild.h +24 -0
  21. package/ios/RNUITextViewChild.mm +76 -0
  22. package/ios/RNUITextViewChildComponentDescriptor.h +13 -0
  23. package/ios/RNUITextViewChildShadowNode.cpp +6 -0
  24. package/ios/RNUITextViewChildShadowNode.h +16 -0
  25. package/ios/RNUITextViewComponentDescriptor.h +13 -0
  26. package/ios/RNUITextViewEventEmitter.h +26 -0
  27. package/ios/RNUITextViewManager.mm +36 -0
  28. package/ios/RNUITextViewShadowNode.cpp +127 -0
  29. package/ios/RNUITextViewShadowNode.h +48 -0
  30. package/ios/RNUITextViewSpecJSI-generated.cpp +17 -0
  31. package/ios/RNUITextViewSpecJSI.h +19 -0
  32. package/ios/generated/RNUITextViewSpec/ComponentDescriptors.cpp +23 -0
  33. package/ios/generated/RNUITextViewSpec/ComponentDescriptors.h +25 -0
  34. package/ios/generated/RNUITextViewSpec/EventEmitters.cpp +61 -0
  35. package/ios/generated/RNUITextViewSpec/EventEmitters.h +49 -0
  36. package/ios/generated/RNUITextViewSpec/Props.cpp +47 -0
  37. package/ios/generated/RNUITextViewSpec/Props.h +182 -0
  38. package/ios/generated/RNUITextViewSpec/RCTComponentViewHelpers.h +24 -0
  39. package/ios/generated/RNUITextViewSpec/RNUITextViewSpec-generated.mm +16 -0
  40. package/ios/generated/RNUITextViewSpec/RNUITextViewSpec.h +38 -0
  41. package/ios/generated/RNUITextViewSpec/ShadowNodes.cpp +18 -0
  42. package/ios/generated/RNUITextViewSpec/ShadowNodes.h +43 -0
  43. package/ios/generated/RNUITextViewSpec/States.cpp +16 -0
  44. package/ios/generated/RNUITextViewSpec/States.h +41 -0
  45. package/ios/generated/RNUITextViewSpecJSI-generated.cpp +17 -0
  46. package/ios/generated/RNUITextViewSpecJSI.h +19 -0
  47. package/lib/commonjs/RNUITextViewChildNativeComponent.ts +48 -0
  48. package/lib/commonjs/RNUITextViewNativeComponent.ts +47 -0
  49. package/lib/commonjs/Text.js +140 -0
  50. package/lib/commonjs/Text.js.map +1 -0
  51. package/lib/commonjs/index.js +17 -0
  52. package/lib/commonjs/index.js.map +1 -0
  53. package/lib/commonjs/package.json +1 -0
  54. package/lib/commonjs/util.js +64 -0
  55. package/lib/commonjs/util.js.map +1 -0
  56. package/lib/module/RNUITextViewChildNativeComponent.ts +48 -0
  57. package/lib/module/RNUITextViewNativeComponent.ts +47 -0
  58. package/lib/module/Text.js +136 -0
  59. package/lib/module/Text.js.map +1 -0
  60. package/lib/module/index.js +4 -0
  61. package/lib/module/index.js.map +1 -0
  62. package/lib/module/package.json +1 -0
  63. package/lib/module/util.js +60 -0
  64. package/lib/module/util.js.map +1 -0
  65. package/lib/typescript/commonjs/example/src/App.d.ts +2 -0
  66. package/lib/typescript/commonjs/example/src/App.d.ts.map +1 -0
  67. package/lib/typescript/commonjs/example/src/CustomMenuExample.d.ts +3 -0
  68. package/lib/typescript/commonjs/example/src/CustomMenuExample.d.ts.map +1 -0
  69. package/lib/typescript/commonjs/package.json +1 -0
  70. package/lib/typescript/commonjs/src/RNUITextViewChildNativeComponent.d.ts +28 -0
  71. package/lib/typescript/commonjs/src/RNUITextViewChildNativeComponent.d.ts.map +1 -0
  72. package/lib/typescript/commonjs/src/RNUITextViewNativeComponent.d.ts +29 -0
  73. package/lib/typescript/commonjs/src/RNUITextViewNativeComponent.d.ts.map +1 -0
  74. package/lib/typescript/commonjs/src/Text.d.ts +17 -0
  75. package/lib/typescript/commonjs/src/Text.d.ts.map +1 -0
  76. package/lib/typescript/commonjs/src/index.d.ts +2 -0
  77. package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
  78. package/lib/typescript/commonjs/src/util.d.ts +160 -0
  79. package/lib/typescript/commonjs/src/util.d.ts.map +1 -0
  80. package/lib/typescript/module/example/src/App.d.ts +2 -0
  81. package/lib/typescript/module/example/src/App.d.ts.map +1 -0
  82. package/lib/typescript/module/example/src/CustomMenuExample.d.ts +3 -0
  83. package/lib/typescript/module/example/src/CustomMenuExample.d.ts.map +1 -0
  84. package/lib/typescript/module/package.json +1 -0
  85. package/lib/typescript/module/src/RNUITextViewChildNativeComponent.d.ts +28 -0
  86. package/lib/typescript/module/src/RNUITextViewChildNativeComponent.d.ts.map +1 -0
  87. package/lib/typescript/module/src/RNUITextViewNativeComponent.d.ts +29 -0
  88. package/lib/typescript/module/src/RNUITextViewNativeComponent.d.ts.map +1 -0
  89. package/lib/typescript/module/src/Text.d.ts +17 -0
  90. package/lib/typescript/module/src/Text.d.ts.map +1 -0
  91. package/lib/typescript/module/src/index.d.ts +2 -0
  92. package/lib/typescript/module/src/index.d.ts.map +1 -0
  93. package/lib/typescript/module/src/util.d.ts +160 -0
  94. package/lib/typescript/module/src/util.d.ts.map +1 -0
  95. package/package.json +187 -0
  96. package/react-native-uitextview.podspec +21 -0
  97. package/react-native.config.js +28 -0
  98. package/src/RNUITextViewChildNativeComponent.ts +48 -0
  99. package/src/RNUITextViewNativeComponent.ts +47 -0
  100. package/src/Text.tsx +148 -0
  101. package/src/index.tsx +1 -0
  102. 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'