react-native-typerich 0.1.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 +28 -0
- package/README.md +37 -0
- package/TypeRichTextInput.podspec +20 -0
- package/android/build.gradle +99 -0
- package/android/generated/android/app/build/generated/source/codegen/java/com/facebook/react/viewmanagers/TypeRichTextInputViewManagerDelegate.java +100 -0
- package/android/generated/android/app/build/generated/source/codegen/java/com/facebook/react/viewmanagers/TypeRichTextInputViewManagerInterface.java +38 -0
- package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/TypeRichTextInputViewSpec/ComponentDescriptors.cpp +22 -0
- package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/TypeRichTextInputViewSpec/ComponentDescriptors.h +24 -0
- package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/TypeRichTextInputViewSpec/EventEmitters.cpp +70 -0
- package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/TypeRichTextInputViewSpec/EventEmitters.h +59 -0
- package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/TypeRichTextInputViewSpec/Props.cpp +132 -0
- package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/TypeRichTextInputViewSpec/Props.h +51 -0
- package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/TypeRichTextInputViewSpec/ShadowNodes.cpp +17 -0
- package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/TypeRichTextInputViewSpec/ShadowNodes.h +23 -0
- package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/TypeRichTextInputViewSpec/States.cpp +16 -0
- package/android/generated/android/app/build/generated/source/codegen/jni/react/renderer/components/TypeRichTextInputViewSpec/States.h +20 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/AndroidManifestNew.xml +2 -0
- package/android/src/main/java/com/typerich/MeasurementStore.kt +148 -0
- package/android/src/main/java/com/typerich/TypeRichTextInputView.kt +503 -0
- package/android/src/main/java/com/typerich/TypeRichTextInputViewLayoutManager.kt +30 -0
- package/android/src/main/java/com/typerich/TypeRichTextInputViewManager.kt +188 -0
- package/android/src/main/java/com/typerich/TypeRichTextInputViewPackage.kt +19 -0
- package/android/src/main/java/com/typerich/events/OnChangeSelectionEvent.kt +29 -0
- package/android/src/main/java/com/typerich/events/OnChangeTextEvent.kt +35 -0
- package/android/src/main/java/com/typerich/events/OnInputBlurEvent.kt +27 -0
- package/android/src/main/java/com/typerich/events/OnInputFocusEvent.kt +27 -0
- package/android/src/main/java/com/typerich/events/OnPasteImageEvent.kt +45 -0
- package/android/src/main/new_arch/CMakeLists.txt +73 -0
- package/android/src/main/new_arch/TypeRichTextInputViewSpec.cpp +22 -0
- package/android/src/main/new_arch/TypeRichTextInputViewSpec.h +26 -0
- package/android/src/main/new_arch/react/renderer/components/TypeRichTextInputView/TypeRichTextInputViewComponentDescriptor.h +36 -0
- package/android/src/main/new_arch/react/renderer/components/TypeRichTextInputView/TypeRichTextInputViewMeasurementManager.cpp +83 -0
- package/android/src/main/new_arch/react/renderer/components/TypeRichTextInputView/TypeRichTextInputViewMeasurementManager.h +25 -0
- package/android/src/main/new_arch/react/renderer/components/TypeRichTextInputView/TypeRichTextInputViewShadowNode.cpp +132 -0
- package/android/src/main/new_arch/react/renderer/components/TypeRichTextInputView/TypeRichTextInputViewShadowNode.h +54 -0
- package/android/src/main/new_arch/react/renderer/components/TypeRichTextInputView/TypeRichTextInputViewState.cpp +9 -0
- package/android/src/main/new_arch/react/renderer/components/TypeRichTextInputView/TypeRichTextInputViewState.h +28 -0
- package/android/src/main/new_arch/react/renderer/components/TypeRichTextInputView/conversions.h +21 -0
- package/ios/TypeRichTextInputView.h +14 -0
- package/ios/TypeRichTextInputView.mm +71 -0
- package/ios/generated/build/generated/ios/react/renderer/components/TypeRichTextInputViewSpec/ComponentDescriptors.cpp +22 -0
- package/ios/generated/build/generated/ios/react/renderer/components/TypeRichTextInputViewSpec/ComponentDescriptors.h +24 -0
- package/ios/generated/build/generated/ios/react/renderer/components/TypeRichTextInputViewSpec/EventEmitters.cpp +70 -0
- package/ios/generated/build/generated/ios/react/renderer/components/TypeRichTextInputViewSpec/EventEmitters.h +59 -0
- package/ios/generated/build/generated/ios/react/renderer/components/TypeRichTextInputViewSpec/Props.cpp +132 -0
- package/ios/generated/build/generated/ios/react/renderer/components/TypeRichTextInputViewSpec/Props.h +51 -0
- package/ios/generated/build/generated/ios/react/renderer/components/TypeRichTextInputViewSpec/RCTComponentViewHelpers.h +80 -0
- package/ios/generated/build/generated/ios/react/renderer/components/TypeRichTextInputViewSpec/ShadowNodes.cpp +17 -0
- package/ios/generated/build/generated/ios/react/renderer/components/TypeRichTextInputViewSpec/ShadowNodes.h +23 -0
- package/ios/generated/build/generated/ios/react/renderer/components/TypeRichTextInputViewSpec/States.cpp +16 -0
- package/ios/generated/build/generated/ios/react/renderer/components/TypeRichTextInputViewSpec/States.h +20 -0
- package/lib/module/TypeRichTextInput.js +50 -0
- package/lib/module/TypeRichTextInput.js.map +1 -0
- package/lib/module/TypeRichTextInputNativeComponent.ts +92 -0
- package/lib/module/index.js +5 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/types/react-native-codegen.d.js +2 -0
- package/lib/module/types/react-native-codegen.d.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/TypeRichTextInput.d.ts +35 -0
- package/lib/typescript/src/TypeRichTextInput.d.ts.map +1 -0
- package/lib/typescript/src/TypeRichTextInputNativeComponent.d.ts +57 -0
- package/lib/typescript/src/TypeRichTextInputNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +4 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/package.json +180 -0
- package/react-native.config.js +13 -0
- package/src/TypeRichTextInput.tsx +115 -0
- package/src/TypeRichTextInputNativeComponent.ts +92 -0
- package/src/index.tsx +6 -0
- package/src/types/react-native-codegen.d.ts +11 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
|
4
|
+
*
|
|
5
|
+
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
|
6
|
+
* once the code is regenerated.
|
|
7
|
+
*
|
|
8
|
+
* @generated by codegen project: GenerateShadowNodeCpp.js
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
#include <react/renderer/components/TypeRichTextInputViewSpec/ShadowNodes.h>
|
|
12
|
+
|
|
13
|
+
namespace facebook::react {
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
|
4
|
+
*
|
|
5
|
+
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
|
6
|
+
* once the code is regenerated.
|
|
7
|
+
*
|
|
8
|
+
* @generated by codegen project: GenerateShadowNodeH.js
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
#pragma once
|
|
12
|
+
|
|
13
|
+
#include <react/renderer/components/TypeRichTextInputViewSpec/EventEmitters.h>
|
|
14
|
+
#include <react/renderer/components/TypeRichTextInputViewSpec/Props.h>
|
|
15
|
+
#include <react/renderer/components/TypeRichTextInputViewSpec/States.h>
|
|
16
|
+
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
|
17
|
+
#include <jsi/jsi.h>
|
|
18
|
+
|
|
19
|
+
namespace facebook::react {
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
|
4
|
+
*
|
|
5
|
+
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
|
6
|
+
* once the code is regenerated.
|
|
7
|
+
*
|
|
8
|
+
* @generated by codegen project: GenerateStateCpp.js
|
|
9
|
+
*/
|
|
10
|
+
#include <react/renderer/components/TypeRichTextInputViewSpec/States.h>
|
|
11
|
+
|
|
12
|
+
namespace facebook::react {
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
|
3
|
+
*
|
|
4
|
+
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
|
5
|
+
* once the code is regenerated.
|
|
6
|
+
*
|
|
7
|
+
* @generated by codegen project: GenerateStateH.js
|
|
8
|
+
*/
|
|
9
|
+
#pragma once
|
|
10
|
+
|
|
11
|
+
#include <react/renderer/core/StateData.h>
|
|
12
|
+
#ifdef RN_SERIALIZABLE_STATE
|
|
13
|
+
#include <folly/dynamic.h>
|
|
14
|
+
#endif
|
|
15
|
+
|
|
16
|
+
namespace facebook::react {
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
package com.typerich
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.graphics.Typeface
|
|
5
|
+
import android.graphics.text.LineBreaker
|
|
6
|
+
import android.os.Build
|
|
7
|
+
import android.text.StaticLayout
|
|
8
|
+
import android.text.TextPaint
|
|
9
|
+
import android.util.Log
|
|
10
|
+
import com.facebook.react.bridge.ReadableMap
|
|
11
|
+
import com.facebook.react.uimanager.PixelUtil
|
|
12
|
+
import com.facebook.react.views.text.ReactTypefaceUtils.applyStyles
|
|
13
|
+
import com.facebook.react.views.text.ReactTypefaceUtils.parseFontStyle
|
|
14
|
+
import com.facebook.react.views.text.ReactTypefaceUtils.parseFontWeight
|
|
15
|
+
import com.facebook.yoga.YogaMeasureOutput
|
|
16
|
+
import java.util.concurrent.ConcurrentHashMap
|
|
17
|
+
import kotlin.math.ceil
|
|
18
|
+
|
|
19
|
+
object MeasurementStore {
|
|
20
|
+
data class PaintParams(
|
|
21
|
+
val typeface: Typeface,
|
|
22
|
+
val fontSize: Float,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
data class MeasurementParams(
|
|
26
|
+
val initialized: Boolean,
|
|
27
|
+
|
|
28
|
+
val cachedWidth: Float,
|
|
29
|
+
val cachedSize: Long,
|
|
30
|
+
|
|
31
|
+
val spannable: CharSequence?,
|
|
32
|
+
val paintParams: PaintParams,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
private val data = ConcurrentHashMap<Int, MeasurementParams>()
|
|
36
|
+
|
|
37
|
+
fun store(id: Int, spannable: CharSequence?, paint: TextPaint): Boolean {
|
|
38
|
+
val cachedWidth = data[id]?.cachedWidth ?: 0f
|
|
39
|
+
val cachedSize = data[id]?.cachedSize ?: 0L
|
|
40
|
+
val initialized = data[id]?.initialized ?: true
|
|
41
|
+
|
|
42
|
+
val size = measure(cachedWidth, spannable, paint)
|
|
43
|
+
val paintParams = PaintParams(paint.typeface, paint.textSize)
|
|
44
|
+
|
|
45
|
+
data[id] = MeasurementParams(initialized, cachedWidth, size, spannable, paintParams)
|
|
46
|
+
return cachedSize != size
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
fun release(id: Int) {
|
|
50
|
+
data.remove(id)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private fun measure(maxWidth: Float, spannable: CharSequence?, paintParams: PaintParams): Long {
|
|
54
|
+
val paint = TextPaint().apply {
|
|
55
|
+
typeface = paintParams.typeface
|
|
56
|
+
textSize = paintParams.fontSize
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return measure(maxWidth, spannable, paint)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private fun measure(maxWidth: Float, spannable: CharSequence?, paint: TextPaint): Long {
|
|
63
|
+
val text = spannable ?: ""
|
|
64
|
+
val textLength = text.length
|
|
65
|
+
val builder = StaticLayout.Builder
|
|
66
|
+
.obtain(text, 0, textLength, paint, maxWidth.toInt())
|
|
67
|
+
.setIncludePad(true)
|
|
68
|
+
.setLineSpacing(0f, 1f)
|
|
69
|
+
|
|
70
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
71
|
+
builder.setBreakStrategy(LineBreaker.BREAK_STRATEGY_HIGH_QUALITY)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
75
|
+
builder.setUseLineSpacingFromFallbacks(true)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
val staticLayout = builder.build()
|
|
79
|
+
val heightInSP = PixelUtil.toDIPFromPixel(staticLayout.height.toFloat())
|
|
80
|
+
val widthInSP = PixelUtil.toDIPFromPixel(maxWidth)
|
|
81
|
+
return YogaMeasureOutput.make(widthInSP, heightInSP)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Returns plain text defaultValue, or "I" if no defaultValue
|
|
85
|
+
private fun getInitialText(defaultView: TypeRichTextInputView, props: ReadableMap?): CharSequence {
|
|
86
|
+
val defaultValue = props?.getString("defaultValue")
|
|
87
|
+
|
|
88
|
+
// If there is no default value, assume text is one line, "I" is a good approximation of height
|
|
89
|
+
if (defaultValue == null) return "I"
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
return defaultValue
|
|
93
|
+
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private fun getInitialFontSize(defaultView: TypeRichTextInputView, props: ReadableMap?): Float {
|
|
97
|
+
val propsFontSize = props?.getDouble("fontSize")?.toFloat()
|
|
98
|
+
if (propsFontSize == null) return defaultView.textSize
|
|
99
|
+
|
|
100
|
+
return ceil(PixelUtil.toPixelFromSP(propsFontSize))
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Called when view measurements are not available in the store
|
|
104
|
+
// Most likely first measurement, we can use defaultValue, as no native state is set yet
|
|
105
|
+
private fun initialMeasure(context: Context, id: Int?, width: Float, props: ReadableMap?): Long {
|
|
106
|
+
val defaultView = TypeRichTextInputView(context)
|
|
107
|
+
|
|
108
|
+
val text = getInitialText(defaultView, props)
|
|
109
|
+
val fontSize = getInitialFontSize(defaultView, props)
|
|
110
|
+
|
|
111
|
+
val fontFamily = props?.getString("fontFamily")
|
|
112
|
+
val fontStyle = parseFontStyle(props?.getString("fontStyle"))
|
|
113
|
+
val fontWeight = parseFontWeight(props?.getString("fontWeight"))
|
|
114
|
+
|
|
115
|
+
val typeface = applyStyles(defaultView.typeface, fontStyle, fontWeight, fontFamily, context.assets)
|
|
116
|
+
val paintParams = PaintParams(typeface, fontSize)
|
|
117
|
+
val size = measure(width, text, PaintParams(typeface, fontSize))
|
|
118
|
+
|
|
119
|
+
if (id != null) {
|
|
120
|
+
data[id] = MeasurementParams(true, width, size, text, paintParams)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return size
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
fun getMeasureById(context: Context, id: Int?, width: Float, props: ReadableMap?): Long {
|
|
127
|
+
val resolvedId = id ?: return initialMeasure(context, id, width, props)
|
|
128
|
+
val value = data[resolvedId] ?: return initialMeasure(context, resolvedId, width, props)
|
|
129
|
+
|
|
130
|
+
if (!value.initialized) {
|
|
131
|
+
return initialMeasure(context, resolvedId, width, props)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (width == value.cachedWidth) {
|
|
135
|
+
return value.cachedSize
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
val paint = TextPaint().apply {
|
|
139
|
+
typeface = value.paintParams.typeface
|
|
140
|
+
textSize = value.paintParams.fontSize
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
val size = measure(width, value.spannable, paint)
|
|
144
|
+
data[resolvedId] = MeasurementParams(true, width, size, value.spannable, value.paintParams)
|
|
145
|
+
return size
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
}
|