react-native-enriched-markdown 0.5.0 → 0.6.0-nightly-20260424-4080a3393
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/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +7 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +2 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +7 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +2 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +20 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +4 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +21 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +16 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockquoteRenderer.kt +5 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/BlockquoteSpan.kt +23 -5
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/span/SpanFlags.kt +12 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/TextSelectionColors.kt +48 -0
- package/ios/EnrichedMarkdown.mm +14 -0
- package/ios/EnrichedMarkdownText.mm +6 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +20 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +4 -0
- package/ios/input/EnrichedMarkdownTextInput.mm +2 -3
- package/ios/utils/ENRMUIKit.h +6 -2
- package/ios/utils/SelectionColorUtils.h +14 -0
- package/lib/module/EnrichedMarkdownNativeComponent.ts +17 -0
- package/lib/module/EnrichedMarkdownTextNativeComponent.ts +17 -0
- package/lib/module/native/EnrichedMarkdownText.js +4 -0
- package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/web/EnrichedMarkdownText.js +9 -2
- package/lib/module/web/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/web/globalStyles.js +10 -0
- package/lib/module/web/globalStyles.js.map +1 -0
- package/lib/module/web/injectStyle.js +20 -0
- package/lib/module/web/injectStyle.js.map +1 -0
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +17 -0
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +17 -0
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +1 -1
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.d.ts +18 -1
- package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts +5 -0
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts.map +1 -1
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts +1 -1
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts.map +1 -1
- package/lib/typescript/src/web/globalStyles.d.ts +3 -0
- package/lib/typescript/src/web/globalStyles.d.ts.map +1 -0
- package/lib/typescript/src/web/injectStyle.d.ts +9 -0
- package/lib/typescript/src/web/injectStyle.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/EnrichedMarkdownNativeComponent.ts +17 -0
- package/src/EnrichedMarkdownTextNativeComponent.ts +17 -0
- package/src/native/EnrichedMarkdownText.tsx +4 -0
- package/src/types/MarkdownTextProps.ts +18 -1
- package/src/types/MarkdownTextProps.web.ts +5 -0
- package/src/web/EnrichedMarkdownText.tsx +8 -3
- package/src/web/globalStyles.ts +15 -0
- package/src/web/injectStyle.ts +17 -0
package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java
CHANGED
|
@@ -11,6 +11,7 @@ package com.facebook.react.viewmanagers;
|
|
|
11
11
|
|
|
12
12
|
import android.view.View;
|
|
13
13
|
import androidx.annotation.Nullable;
|
|
14
|
+
import com.facebook.react.bridge.ColorPropConverter;
|
|
14
15
|
import com.facebook.react.bridge.ReadableArray;
|
|
15
16
|
import com.facebook.react.bridge.ReadableMap;
|
|
16
17
|
import com.facebook.react.uimanager.BaseViewManager;
|
|
@@ -37,6 +38,12 @@ public class EnrichedMarkdownManagerDelegate<T extends View, U extends BaseViewM
|
|
|
37
38
|
case "selectable":
|
|
38
39
|
mViewManager.setSelectable(view, value == null ? false : (boolean) value);
|
|
39
40
|
break;
|
|
41
|
+
case "selectionColor":
|
|
42
|
+
mViewManager.setSelectionColor(view, ColorPropConverter.getColor(value, view.getContext()));
|
|
43
|
+
break;
|
|
44
|
+
case "selectionHandleColor":
|
|
45
|
+
mViewManager.setSelectionHandleColor(view, ColorPropConverter.getColor(value, view.getContext()));
|
|
46
|
+
break;
|
|
40
47
|
case "md4cFlags":
|
|
41
48
|
mViewManager.setMd4cFlags(view, (ReadableMap) value);
|
|
42
49
|
break;
|
package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java
CHANGED
|
@@ -20,6 +20,8 @@ public interface EnrichedMarkdownManagerInterface<T extends View> extends ViewMa
|
|
|
20
20
|
void setMarkdownStyle(T view, @Nullable ReadableMap value);
|
|
21
21
|
void setEnableLinkPreview(T view, boolean value);
|
|
22
22
|
void setSelectable(T view, boolean value);
|
|
23
|
+
void setSelectionColor(T view, @Nullable Integer value);
|
|
24
|
+
void setSelectionHandleColor(T view, @Nullable Integer value);
|
|
23
25
|
void setMd4cFlags(T view, @Nullable ReadableMap value);
|
|
24
26
|
void setAllowFontScaling(T view, boolean value);
|
|
25
27
|
void setMaxFontSizeMultiplier(T view, float value);
|
|
@@ -11,6 +11,7 @@ package com.facebook.react.viewmanagers;
|
|
|
11
11
|
|
|
12
12
|
import android.view.View;
|
|
13
13
|
import androidx.annotation.Nullable;
|
|
14
|
+
import com.facebook.react.bridge.ColorPropConverter;
|
|
14
15
|
import com.facebook.react.bridge.ReadableArray;
|
|
15
16
|
import com.facebook.react.bridge.ReadableMap;
|
|
16
17
|
import com.facebook.react.uimanager.BaseViewManager;
|
|
@@ -37,6 +38,12 @@ public class EnrichedMarkdownTextManagerDelegate<T extends View, U extends BaseV
|
|
|
37
38
|
case "selectable":
|
|
38
39
|
mViewManager.setSelectable(view, value == null ? false : (boolean) value);
|
|
39
40
|
break;
|
|
41
|
+
case "selectionColor":
|
|
42
|
+
mViewManager.setSelectionColor(view, ColorPropConverter.getColor(value, view.getContext()));
|
|
43
|
+
break;
|
|
44
|
+
case "selectionHandleColor":
|
|
45
|
+
mViewManager.setSelectionHandleColor(view, ColorPropConverter.getColor(value, view.getContext()));
|
|
46
|
+
break;
|
|
40
47
|
case "md4cFlags":
|
|
41
48
|
mViewManager.setMd4cFlags(view, (ReadableMap) value);
|
|
42
49
|
break;
|
|
@@ -20,6 +20,8 @@ public interface EnrichedMarkdownTextManagerInterface<T extends View> extends Vi
|
|
|
20
20
|
void setMarkdownStyle(T view, @Nullable ReadableMap value);
|
|
21
21
|
void setEnableLinkPreview(T view, boolean value);
|
|
22
22
|
void setSelectable(T view, boolean value);
|
|
23
|
+
void setSelectionColor(T view, @Nullable Integer value);
|
|
24
|
+
void setSelectionHandleColor(T view, @Nullable Integer value);
|
|
23
25
|
void setMd4cFlags(T view, @Nullable ReadableMap value);
|
|
24
26
|
void setAllowFontScaling(T view, boolean value);
|
|
25
27
|
void setMaxFontSizeMultiplier(T view, float value);
|
|
@@ -23,6 +23,8 @@ EnrichedMarkdownProps::EnrichedMarkdownProps(
|
|
|
23
23
|
markdownStyle(convertRawProp(context, rawProps, "markdownStyle", sourceProps.markdownStyle, {})),
|
|
24
24
|
enableLinkPreview(convertRawProp(context, rawProps, "enableLinkPreview", sourceProps.enableLinkPreview, {true})),
|
|
25
25
|
selectable(convertRawProp(context, rawProps, "selectable", sourceProps.selectable, {false})),
|
|
26
|
+
selectionColor(convertRawProp(context, rawProps, "selectionColor", sourceProps.selectionColor, {})),
|
|
27
|
+
selectionHandleColor(convertRawProp(context, rawProps, "selectionHandleColor", sourceProps.selectionHandleColor, {})),
|
|
26
28
|
md4cFlags(convertRawProp(context, rawProps, "md4cFlags", sourceProps.md4cFlags, {})),
|
|
27
29
|
allowFontScaling(convertRawProp(context, rawProps, "allowFontScaling", sourceProps.allowFontScaling, {true})),
|
|
28
30
|
maxFontSizeMultiplier(convertRawProp(context, rawProps, "maxFontSizeMultiplier", sourceProps.maxFontSizeMultiplier, {0.0})),
|
|
@@ -63,6 +65,14 @@ folly::dynamic EnrichedMarkdownProps::getDiffProps(
|
|
|
63
65
|
result["selectable"] = selectable;
|
|
64
66
|
}
|
|
65
67
|
|
|
68
|
+
if (selectionColor != oldProps->selectionColor) {
|
|
69
|
+
result["selectionColor"] = *selectionColor;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (selectionHandleColor != oldProps->selectionHandleColor) {
|
|
73
|
+
result["selectionHandleColor"] = *selectionHandleColor;
|
|
74
|
+
}
|
|
75
|
+
|
|
66
76
|
if (md4cFlags != oldProps->md4cFlags) {
|
|
67
77
|
result["md4cFlags"] = toDynamic(md4cFlags);
|
|
68
78
|
}
|
|
@@ -221,6 +231,8 @@ EnrichedMarkdownTextProps::EnrichedMarkdownTextProps(
|
|
|
221
231
|
markdownStyle(convertRawProp(context, rawProps, "markdownStyle", sourceProps.markdownStyle, {})),
|
|
222
232
|
enableLinkPreview(convertRawProp(context, rawProps, "enableLinkPreview", sourceProps.enableLinkPreview, {true})),
|
|
223
233
|
selectable(convertRawProp(context, rawProps, "selectable", sourceProps.selectable, {false})),
|
|
234
|
+
selectionColor(convertRawProp(context, rawProps, "selectionColor", sourceProps.selectionColor, {})),
|
|
235
|
+
selectionHandleColor(convertRawProp(context, rawProps, "selectionHandleColor", sourceProps.selectionHandleColor, {})),
|
|
224
236
|
md4cFlags(convertRawProp(context, rawProps, "md4cFlags", sourceProps.md4cFlags, {})),
|
|
225
237
|
allowFontScaling(convertRawProp(context, rawProps, "allowFontScaling", sourceProps.allowFontScaling, {true})),
|
|
226
238
|
maxFontSizeMultiplier(convertRawProp(context, rawProps, "maxFontSizeMultiplier", sourceProps.maxFontSizeMultiplier, {0.0})),
|
|
@@ -261,6 +273,14 @@ folly::dynamic EnrichedMarkdownTextProps::getDiffProps(
|
|
|
261
273
|
result["selectable"] = selectable;
|
|
262
274
|
}
|
|
263
275
|
|
|
276
|
+
if (selectionColor != oldProps->selectionColor) {
|
|
277
|
+
result["selectionColor"] = *selectionColor;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (selectionHandleColor != oldProps->selectionHandleColor) {
|
|
281
|
+
result["selectionHandleColor"] = *selectionHandleColor;
|
|
282
|
+
}
|
|
283
|
+
|
|
264
284
|
if (md4cFlags != oldProps->md4cFlags) {
|
|
265
285
|
result["md4cFlags"] = toDynamic(md4cFlags);
|
|
266
286
|
}
|
|
@@ -1954,6 +1954,8 @@ class EnrichedMarkdownProps final : public ViewProps {
|
|
|
1954
1954
|
EnrichedMarkdownMarkdownStyleStruct markdownStyle{};
|
|
1955
1955
|
bool enableLinkPreview{true};
|
|
1956
1956
|
bool selectable{false};
|
|
1957
|
+
SharedColor selectionColor{};
|
|
1958
|
+
SharedColor selectionHandleColor{};
|
|
1957
1959
|
EnrichedMarkdownMd4cFlagsStruct md4cFlags{};
|
|
1958
1960
|
bool allowFontScaling{true};
|
|
1959
1961
|
Float maxFontSizeMultiplier{0.0};
|
|
@@ -4250,6 +4252,8 @@ class EnrichedMarkdownTextProps final : public ViewProps {
|
|
|
4250
4252
|
EnrichedMarkdownTextMarkdownStyleStruct markdownStyle{};
|
|
4251
4253
|
bool enableLinkPreview{true};
|
|
4252
4254
|
bool selectable{false};
|
|
4255
|
+
SharedColor selectionColor{};
|
|
4256
|
+
SharedColor selectionHandleColor{};
|
|
4253
4257
|
EnrichedMarkdownTextMd4cFlagsStruct md4cFlags{};
|
|
4254
4258
|
bool allowFontScaling{true};
|
|
4255
4259
|
Float maxFontSizeMultiplier{0.0};
|
|
@@ -18,6 +18,7 @@ import com.swmansion.enriched.markdown.utils.common.FeatureFlags
|
|
|
18
18
|
import com.swmansion.enriched.markdown.utils.common.MarkdownSegmentRenderer
|
|
19
19
|
import com.swmansion.enriched.markdown.utils.common.RenderedSegment
|
|
20
20
|
import com.swmansion.enriched.markdown.utils.common.splitASTIntoSegments
|
|
21
|
+
import com.swmansion.enriched.markdown.utils.text.view.applySelectionColors
|
|
21
22
|
import com.swmansion.enriched.markdown.utils.text.view.emitLinkLongPressEvent
|
|
22
23
|
import com.swmansion.enriched.markdown.utils.text.view.emitLinkPressEvent
|
|
23
24
|
import com.swmansion.enriched.markdown.views.BlockSegmentView
|
|
@@ -54,6 +55,8 @@ class EnrichedMarkdown
|
|
|
54
55
|
private var maxFontSizeMultiplier: Float = 0f
|
|
55
56
|
private var allowTrailingMargin: Boolean = false
|
|
56
57
|
private var selectable: Boolean = true
|
|
58
|
+
private var selectionColor: Int? = null
|
|
59
|
+
private var selectionHandleColor: Int? = null
|
|
57
60
|
|
|
58
61
|
private var onLinkPressCallback: ((String) -> Unit)? = null
|
|
59
62
|
private var onLinkLongPressCallback: ((String) -> Unit)? = null
|
|
@@ -128,6 +131,22 @@ class EnrichedMarkdown
|
|
|
128
131
|
}
|
|
129
132
|
}
|
|
130
133
|
|
|
134
|
+
fun setSelectionColor(color: Int?) {
|
|
135
|
+
selectionColor = color
|
|
136
|
+
applySelectionColorsToSegments()
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
fun setSelectionHandleColor(color: Int?) {
|
|
140
|
+
selectionHandleColor = color
|
|
141
|
+
applySelectionColorsToSegments()
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private fun applySelectionColorsToSegments() {
|
|
145
|
+
segmentViews.filterIsInstance<EnrichedMarkdownInternalText>().forEach {
|
|
146
|
+
it.applySelectionColors(selectionColor, selectionHandleColor)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
131
150
|
fun setOnLinkPressCallback(callback: (String) -> Unit) {
|
|
132
151
|
onLinkPressCallback = callback
|
|
133
152
|
}
|
|
@@ -234,6 +253,8 @@ class EnrichedMarkdown
|
|
|
234
253
|
if (contextMenuItemTexts.isNotEmpty()) {
|
|
235
254
|
setContextMenuItems(contextMenuItemTexts, ::forwardContextMenuItemPress)
|
|
236
255
|
}
|
|
256
|
+
|
|
257
|
+
applySelectionColors(selectionColor, selectionHandleColor)
|
|
237
258
|
}
|
|
238
259
|
|
|
239
260
|
private fun createTableView(
|
|
@@ -80,6 +80,20 @@ class EnrichedMarkdownManager :
|
|
|
80
80
|
view?.setIsSelectable(selectable)
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
override fun setSelectionColor(
|
|
84
|
+
view: EnrichedMarkdown?,
|
|
85
|
+
value: Int?,
|
|
86
|
+
) {
|
|
87
|
+
view?.setSelectionColor(value)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
override fun setSelectionHandleColor(
|
|
91
|
+
view: EnrichedMarkdown?,
|
|
92
|
+
value: Int?,
|
|
93
|
+
) {
|
|
94
|
+
view?.setSelectionHandleColor(value)
|
|
95
|
+
}
|
|
96
|
+
|
|
83
97
|
@ReactProp(name = "md4cFlags")
|
|
84
98
|
override fun setMd4cFlags(
|
|
85
99
|
view: EnrichedMarkdown?,
|
|
@@ -23,6 +23,7 @@ import com.swmansion.enriched.markdown.utils.text.TailFadeInAnimator
|
|
|
23
23
|
import com.swmansion.enriched.markdown.utils.text.interaction.CheckboxTouchHelper
|
|
24
24
|
import com.swmansion.enriched.markdown.utils.text.view.LinkLongPressMovementMethod
|
|
25
25
|
import com.swmansion.enriched.markdown.utils.text.view.applySelectableState
|
|
26
|
+
import com.swmansion.enriched.markdown.utils.text.view.applySelectionColors
|
|
26
27
|
import com.swmansion.enriched.markdown.utils.text.view.cancelJSTouchForCheckboxTap
|
|
27
28
|
import com.swmansion.enriched.markdown.utils.text.view.cancelJSTouchForLinkTap
|
|
28
29
|
import com.swmansion.enriched.markdown.utils.text.view.createSelectionActionModeCallback
|
|
@@ -81,6 +82,9 @@ class EnrichedMarkdownText
|
|
|
81
82
|
private set
|
|
82
83
|
var spoilerOverlay: SpoilerOverlay = SpoilerOverlay.PARTICLES
|
|
83
84
|
|
|
85
|
+
private var selectionColor: Int? = null
|
|
86
|
+
private var selectionHandleColor: Int? = null
|
|
87
|
+
|
|
84
88
|
init {
|
|
85
89
|
setupAsMarkdownTextView()
|
|
86
90
|
customSelectionActionModeCallback =
|
|
@@ -248,6 +252,8 @@ class EnrichedMarkdownText
|
|
|
248
252
|
fadeAnimator?.animate(tailStart, styledText.length)
|
|
249
253
|
previousTextLength = styledText.length
|
|
250
254
|
}
|
|
255
|
+
|
|
256
|
+
applySelectionColors(selectionColor, selectionHandleColor)
|
|
251
257
|
}
|
|
252
258
|
|
|
253
259
|
fun setContextMenuItems(items: List<String>) {
|
|
@@ -258,6 +264,16 @@ class EnrichedMarkdownText
|
|
|
258
264
|
applySelectableState(selectable)
|
|
259
265
|
}
|
|
260
266
|
|
|
267
|
+
fun setSelectionColor(color: Int?) {
|
|
268
|
+
selectionColor = color
|
|
269
|
+
applySelectionColors(selectionColor, selectionHandleColor)
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
fun setSelectionHandleColor(color: Int?) {
|
|
273
|
+
selectionHandleColor = color
|
|
274
|
+
applySelectionColors(selectionColor, selectionHandleColor)
|
|
275
|
+
}
|
|
276
|
+
|
|
261
277
|
fun emitOnLinkPress(url: String) {
|
|
262
278
|
emitLinkPressEvent(url)
|
|
263
279
|
}
|
package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt
CHANGED
|
@@ -100,6 +100,20 @@ class EnrichedMarkdownTextManager :
|
|
|
100
100
|
view?.setIsSelectable(selectable)
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
override fun setSelectionColor(
|
|
104
|
+
view: EnrichedMarkdownText?,
|
|
105
|
+
value: Int?,
|
|
106
|
+
) {
|
|
107
|
+
view?.setSelectionColor(value)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
override fun setSelectionHandleColor(
|
|
111
|
+
view: EnrichedMarkdownText?,
|
|
112
|
+
value: Int?,
|
|
113
|
+
) {
|
|
114
|
+
view?.setSelectionHandleColor(value)
|
|
115
|
+
}
|
|
116
|
+
|
|
103
117
|
@ReactProp(name = "md4cFlags")
|
|
104
118
|
override fun setMd4cFlags(
|
|
105
119
|
view: EnrichedMarkdownText?,
|
package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockquoteRenderer.kt
CHANGED
|
@@ -3,6 +3,7 @@ package com.swmansion.enriched.markdown.renderer
|
|
|
3
3
|
import android.text.SpannableStringBuilder
|
|
4
4
|
import com.swmansion.enriched.markdown.parser.MarkdownASTNode
|
|
5
5
|
import com.swmansion.enriched.markdown.spans.BlockquoteSpan
|
|
6
|
+
import com.swmansion.enriched.markdown.utils.text.span.SPAN_FLAGS_CONTAINER_BACKGROUND
|
|
6
7
|
import com.swmansion.enriched.markdown.utils.text.span.SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE
|
|
7
8
|
import com.swmansion.enriched.markdown.utils.text.span.applyMarginBottom
|
|
8
9
|
import com.swmansion.enriched.markdown.utils.text.span.applyMarginTop
|
|
@@ -45,12 +46,14 @@ class BlockquoteRenderer(
|
|
|
45
46
|
.map { builder.getSpanStart(it) to builder.getSpanEnd(it) }
|
|
46
47
|
.sortedBy { it.first }
|
|
47
48
|
|
|
48
|
-
// The
|
|
49
|
+
// The accent bar span covers the full range for visual continuity.
|
|
50
|
+
// SPAN_FLAGS_CONTAINER_BACKGROUND keeps the blockquote fill under any
|
|
51
|
+
// inline chip/pill backgrounds on the same line.
|
|
49
52
|
builder.setSpan(
|
|
50
53
|
BlockquoteSpan(style, depth, factory.context, factory.styleCache),
|
|
51
54
|
start,
|
|
52
55
|
end,
|
|
53
|
-
|
|
56
|
+
SPAN_FLAGS_CONTAINER_BACKGROUND,
|
|
54
57
|
)
|
|
55
58
|
|
|
56
59
|
// Apply styling only to segments that are NOT nested quotes
|
|
@@ -10,6 +10,7 @@ import android.text.Layout
|
|
|
10
10
|
import android.text.Spanned
|
|
11
11
|
import android.text.TextPaint
|
|
12
12
|
import android.text.style.LeadingMarginSpan
|
|
13
|
+
import android.text.style.LineBackgroundSpan
|
|
13
14
|
import android.text.style.MetricAffectingSpan
|
|
14
15
|
import com.swmansion.enriched.markdown.renderer.BlockStyle
|
|
15
16
|
import com.swmansion.enriched.markdown.renderer.SpanStyleCache
|
|
@@ -23,7 +24,8 @@ class BlockquoteSpan(
|
|
|
23
24
|
private val context: Context,
|
|
24
25
|
private val styleCache: SpanStyleCache,
|
|
25
26
|
) : MetricAffectingSpan(),
|
|
26
|
-
LeadingMarginSpan
|
|
27
|
+
LeadingMarginSpan,
|
|
28
|
+
LineBackgroundSpan {
|
|
27
29
|
private val levelSpacing: Float = blockquoteStyle.borderWidth + blockquoteStyle.gapWidth
|
|
28
30
|
private val blockStyle =
|
|
29
31
|
BlockStyle(
|
|
@@ -60,8 +62,6 @@ class BlockquoteSpan(
|
|
|
60
62
|
// Essential check from original: only the deepest span draws to prevent over-rendering background
|
|
61
63
|
if (shouldSkipDrawing(text, start)) return
|
|
62
64
|
|
|
63
|
-
drawBackground(c, top, bottom, layout)
|
|
64
|
-
|
|
65
65
|
val borderPaint = configureBorderPaint()
|
|
66
66
|
val borderTop = top.toFloat()
|
|
67
67
|
val borderBottom = bottom.toFloat()
|
|
@@ -73,6 +73,23 @@ class BlockquoteSpan(
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
override fun drawBackground(
|
|
77
|
+
canvas: Canvas,
|
|
78
|
+
paint: Paint,
|
|
79
|
+
left: Int,
|
|
80
|
+
right: Int,
|
|
81
|
+
top: Int,
|
|
82
|
+
baseline: Int,
|
|
83
|
+
bottom: Int,
|
|
84
|
+
text: CharSequence,
|
|
85
|
+
start: Int,
|
|
86
|
+
end: Int,
|
|
87
|
+
lineNum: Int,
|
|
88
|
+
) {
|
|
89
|
+
if (shouldSkipDrawing(text, start)) return
|
|
90
|
+
drawBackground(canvas, left, top, bottom, right)
|
|
91
|
+
}
|
|
92
|
+
|
|
76
93
|
@SuppressLint("WrongConstant") // Result of mask is always valid: 0, 1, 2, or 3
|
|
77
94
|
private fun applyTextStyle(tp: TextPaint) {
|
|
78
95
|
tp.textSize = blockStyle.fontSize
|
|
@@ -123,12 +140,13 @@ class BlockquoteSpan(
|
|
|
123
140
|
|
|
124
141
|
private fun drawBackground(
|
|
125
142
|
c: Canvas,
|
|
143
|
+
left: Int,
|
|
126
144
|
top: Int,
|
|
127
145
|
bottom: Int,
|
|
128
|
-
|
|
146
|
+
right: Int,
|
|
129
147
|
) {
|
|
130
148
|
val bgColor = blockquoteStyle.backgroundColor?.takeIf { it != Color.TRANSPARENT } ?: return
|
|
131
149
|
val backgroundPaint = configureBackgroundPaint(bgColor)
|
|
132
|
-
c.drawRect(
|
|
150
|
+
c.drawRect(left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat(), backgroundPaint)
|
|
133
151
|
}
|
|
134
152
|
}
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
package com.swmansion.enriched.markdown.utils.text.span
|
|
2
2
|
|
|
3
3
|
import android.text.SpannableString
|
|
4
|
+
import android.text.Spanned
|
|
4
5
|
|
|
5
6
|
const val SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE = SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* `SPAN_EXCLUSIVE_EXCLUSIVE` with the maximum span priority.
|
|
10
|
+
*
|
|
11
|
+
* Higher-priority spans are iterated — and therefore drawn — first, so any
|
|
12
|
+
* lower-priority span on the same line ends up painted *on top* visually.
|
|
13
|
+
* Use this for full-width container backgrounds (e.g. blockquote fill in
|
|
14
|
+
* [BlockquoteSpan]) that must sit under inline pill/chip backgrounds.
|
|
15
|
+
*/
|
|
16
|
+
const val SPAN_FLAGS_CONTAINER_BACKGROUND =
|
|
17
|
+
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE or Spanned.SPAN_PRIORITY
|
package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/TextSelectionColors.kt
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.utils.text.view
|
|
2
|
+
|
|
3
|
+
import android.graphics.drawable.Drawable
|
|
4
|
+
import android.os.Build
|
|
5
|
+
import android.util.Log
|
|
6
|
+
import android.widget.TextView
|
|
7
|
+
import androidx.annotation.ColorInt
|
|
8
|
+
import androidx.core.graphics.drawable.DrawableCompat
|
|
9
|
+
|
|
10
|
+
private const val TAG = "TextSelectionColors"
|
|
11
|
+
|
|
12
|
+
private typealias HandleGetter = (TextView) -> Drawable?
|
|
13
|
+
private typealias HandleSetter = (TextView, Drawable) -> Unit
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Applies selection highlight and (where supported) handle tinting to a [TextView].
|
|
17
|
+
*
|
|
18
|
+
* Handle drawables are only tinted on API 29+ where the framework exposes getters;
|
|
19
|
+
* on older versions the handle theme defaults remain unchanged.
|
|
20
|
+
*/
|
|
21
|
+
fun TextView.applySelectionColors(
|
|
22
|
+
selectionColor: Int?,
|
|
23
|
+
selectionHandleColor: Int?,
|
|
24
|
+
) {
|
|
25
|
+
selectionColor?.let { highlightColor = it }
|
|
26
|
+
selectionHandleColor?.let { applySelectionHandleTint(it) }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private fun TextView.applySelectionHandleTint(
|
|
30
|
+
@ColorInt color: Int,
|
|
31
|
+
) {
|
|
32
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return
|
|
33
|
+
|
|
34
|
+
val handles: List<Pair<HandleGetter, HandleSetter>> =
|
|
35
|
+
listOf(
|
|
36
|
+
TextView::getTextSelectHandleLeft to { tv, d -> tv.setTextSelectHandleLeft(d) },
|
|
37
|
+
TextView::getTextSelectHandle to { tv, d -> tv.setTextSelectHandle(d) },
|
|
38
|
+
TextView::getTextSelectHandleRight to { tv, d -> tv.setTextSelectHandleRight(d) },
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
handles.forEach { (getter, setter) ->
|
|
42
|
+
try {
|
|
43
|
+
getter(this)?.mutate()?.also { DrawableCompat.setTint(it, color) }?.let { setter(this, it) }
|
|
44
|
+
} catch (e: LinkageError) {
|
|
45
|
+
Log.w(TAG, "Selection handle tint skipped: ${e.message}")
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
package/ios/EnrichedMarkdown.mm
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
#import "EditMenuUtils.h"
|
|
8
8
|
|
|
9
9
|
#import "ENRMFeatureFlags.h"
|
|
10
|
+
#import "ENRMUIKit.h"
|
|
10
11
|
|
|
11
12
|
#if ENRICHED_MARKDOWN_MATH
|
|
12
13
|
#import "ENRMMathContainerView.h"
|
|
@@ -25,6 +26,7 @@
|
|
|
25
26
|
#import "MarkdownExtractor.h"
|
|
26
27
|
#import "ParagraphStyleUtils.h"
|
|
27
28
|
#import "RuntimeKeys.h"
|
|
29
|
+
#import "SelectionColorUtils.h"
|
|
28
30
|
#import "StyleConfig.h"
|
|
29
31
|
#import "StylePropsUtils.h"
|
|
30
32
|
#import "TableContainerView.h"
|
|
@@ -493,6 +495,9 @@ using namespace facebook::react;
|
|
|
493
495
|
view.textView.selectable = _selectable;
|
|
494
496
|
[view applyAttributedText:segment.attributedText context:segment.context];
|
|
495
497
|
|
|
498
|
+
const auto &selectionProps = *std::static_pointer_cast<EnrichedMarkdownProps const>(self->_props);
|
|
499
|
+
ENRMApplySelectionColor(view.textView, selectionProps.selectionColor);
|
|
500
|
+
|
|
496
501
|
ENRMTapRecognizer *tapRecognizer = [[ENRMTapRecognizer alloc] initWithTarget:self action:@selector(textTapped:)];
|
|
497
502
|
[view.textView addGestureRecognizer:tapRecognizer];
|
|
498
503
|
|
|
@@ -657,6 +662,15 @@ using namespace facebook::react;
|
|
|
657
662
|
}
|
|
658
663
|
}
|
|
659
664
|
|
|
665
|
+
if (newViewProps.selectionColor != oldViewProps.selectionColor) {
|
|
666
|
+
for (RCTUIView *segment in _segmentViews) {
|
|
667
|
+
if ([segment isKindOfClass:[EnrichedMarkdownInternalText class]]) {
|
|
668
|
+
ENRMPlatformTextView *tv = ((EnrichedMarkdownInternalText *)segment).textView;
|
|
669
|
+
ENRMApplySelectionColor(tv, newViewProps.selectionColor);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
660
674
|
if (markdownChanged || stylePropChanged || md4cFlagsChanged || allowTrailingMarginChanged) {
|
|
661
675
|
NSString *markdownString = [[NSString alloc] initWithUTF8String:newViewProps.markdown.c_str()];
|
|
662
676
|
[self renderMarkdownContent:markdownString];
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
#import "ENRMTailFadeInAnimator.h"
|
|
10
10
|
#import "ENRMTextRenderer.h"
|
|
11
11
|
#import "ENRMTextViewSetup.h"
|
|
12
|
+
#import "ENRMUIKit.h"
|
|
12
13
|
#import "EditMenuUtils.h"
|
|
13
14
|
#import "FontScaleObserver.h"
|
|
14
15
|
#import "FontUtils.h"
|
|
@@ -19,6 +20,7 @@
|
|
|
19
20
|
#import "MarkdownExtractor.h"
|
|
20
21
|
#import "ParagraphStyleUtils.h"
|
|
21
22
|
#import "RuntimeKeys.h"
|
|
23
|
+
#import "SelectionColorUtils.h"
|
|
22
24
|
#import "StylePropsUtils.h"
|
|
23
25
|
#import "TaskListTapUtils.h"
|
|
24
26
|
|
|
@@ -411,6 +413,10 @@ using namespace facebook::react;
|
|
|
411
413
|
_textView.selectable = newViewProps.selectable;
|
|
412
414
|
}
|
|
413
415
|
|
|
416
|
+
if (newViewProps.selectionColor != oldViewProps.selectionColor) {
|
|
417
|
+
ENRMApplySelectionColor(_textView, newViewProps.selectionColor);
|
|
418
|
+
}
|
|
419
|
+
|
|
414
420
|
if (newViewProps.allowFontScaling != oldViewProps.allowFontScaling) {
|
|
415
421
|
_fontScaleObserver.allowFontScaling = newViewProps.allowFontScaling;
|
|
416
422
|
|
|
@@ -23,6 +23,8 @@ EnrichedMarkdownProps::EnrichedMarkdownProps(
|
|
|
23
23
|
markdownStyle(convertRawProp(context, rawProps, "markdownStyle", sourceProps.markdownStyle, {})),
|
|
24
24
|
enableLinkPreview(convertRawProp(context, rawProps, "enableLinkPreview", sourceProps.enableLinkPreview, {true})),
|
|
25
25
|
selectable(convertRawProp(context, rawProps, "selectable", sourceProps.selectable, {false})),
|
|
26
|
+
selectionColor(convertRawProp(context, rawProps, "selectionColor", sourceProps.selectionColor, {})),
|
|
27
|
+
selectionHandleColor(convertRawProp(context, rawProps, "selectionHandleColor", sourceProps.selectionHandleColor, {})),
|
|
26
28
|
md4cFlags(convertRawProp(context, rawProps, "md4cFlags", sourceProps.md4cFlags, {})),
|
|
27
29
|
allowFontScaling(convertRawProp(context, rawProps, "allowFontScaling", sourceProps.allowFontScaling, {true})),
|
|
28
30
|
maxFontSizeMultiplier(convertRawProp(context, rawProps, "maxFontSizeMultiplier", sourceProps.maxFontSizeMultiplier, {0.0})),
|
|
@@ -63,6 +65,14 @@ folly::dynamic EnrichedMarkdownProps::getDiffProps(
|
|
|
63
65
|
result["selectable"] = selectable;
|
|
64
66
|
}
|
|
65
67
|
|
|
68
|
+
if (selectionColor != oldProps->selectionColor) {
|
|
69
|
+
result["selectionColor"] = *selectionColor;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (selectionHandleColor != oldProps->selectionHandleColor) {
|
|
73
|
+
result["selectionHandleColor"] = *selectionHandleColor;
|
|
74
|
+
}
|
|
75
|
+
|
|
66
76
|
if (md4cFlags != oldProps->md4cFlags) {
|
|
67
77
|
result["md4cFlags"] = toDynamic(md4cFlags);
|
|
68
78
|
}
|
|
@@ -221,6 +231,8 @@ EnrichedMarkdownTextProps::EnrichedMarkdownTextProps(
|
|
|
221
231
|
markdownStyle(convertRawProp(context, rawProps, "markdownStyle", sourceProps.markdownStyle, {})),
|
|
222
232
|
enableLinkPreview(convertRawProp(context, rawProps, "enableLinkPreview", sourceProps.enableLinkPreview, {true})),
|
|
223
233
|
selectable(convertRawProp(context, rawProps, "selectable", sourceProps.selectable, {false})),
|
|
234
|
+
selectionColor(convertRawProp(context, rawProps, "selectionColor", sourceProps.selectionColor, {})),
|
|
235
|
+
selectionHandleColor(convertRawProp(context, rawProps, "selectionHandleColor", sourceProps.selectionHandleColor, {})),
|
|
224
236
|
md4cFlags(convertRawProp(context, rawProps, "md4cFlags", sourceProps.md4cFlags, {})),
|
|
225
237
|
allowFontScaling(convertRawProp(context, rawProps, "allowFontScaling", sourceProps.allowFontScaling, {true})),
|
|
226
238
|
maxFontSizeMultiplier(convertRawProp(context, rawProps, "maxFontSizeMultiplier", sourceProps.maxFontSizeMultiplier, {0.0})),
|
|
@@ -261,6 +273,14 @@ folly::dynamic EnrichedMarkdownTextProps::getDiffProps(
|
|
|
261
273
|
result["selectable"] = selectable;
|
|
262
274
|
}
|
|
263
275
|
|
|
276
|
+
if (selectionColor != oldProps->selectionColor) {
|
|
277
|
+
result["selectionColor"] = *selectionColor;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (selectionHandleColor != oldProps->selectionHandleColor) {
|
|
281
|
+
result["selectionHandleColor"] = *selectionHandleColor;
|
|
282
|
+
}
|
|
283
|
+
|
|
264
284
|
if (md4cFlags != oldProps->md4cFlags) {
|
|
265
285
|
result["md4cFlags"] = toDynamic(md4cFlags);
|
|
266
286
|
}
|
|
@@ -1954,6 +1954,8 @@ class EnrichedMarkdownProps final : public ViewProps {
|
|
|
1954
1954
|
EnrichedMarkdownMarkdownStyleStruct markdownStyle{};
|
|
1955
1955
|
bool enableLinkPreview{true};
|
|
1956
1956
|
bool selectable{false};
|
|
1957
|
+
SharedColor selectionColor{};
|
|
1958
|
+
SharedColor selectionHandleColor{};
|
|
1957
1959
|
EnrichedMarkdownMd4cFlagsStruct md4cFlags{};
|
|
1958
1960
|
bool allowFontScaling{true};
|
|
1959
1961
|
Float maxFontSizeMultiplier{0.0};
|
|
@@ -4250,6 +4252,8 @@ class EnrichedMarkdownTextProps final : public ViewProps {
|
|
|
4250
4252
|
EnrichedMarkdownTextMarkdownStyleStruct markdownStyle{};
|
|
4251
4253
|
bool enableLinkPreview{true};
|
|
4252
4254
|
bool selectable{false};
|
|
4255
|
+
SharedColor selectionColor{};
|
|
4256
|
+
SharedColor selectionHandleColor{};
|
|
4253
4257
|
EnrichedMarkdownTextMd4cFlagsStruct md4cFlags{};
|
|
4254
4258
|
bool allowFontScaling{true};
|
|
4255
4259
|
Float maxFontSizeMultiplier{0.0};
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
#import "ENRMStyleMergingConfig.h"
|
|
16
16
|
#import "ENRMUIKit.h"
|
|
17
17
|
#import "InputStylePropsUtils.h"
|
|
18
|
+
#import "SelectionColorUtils.h"
|
|
18
19
|
#if TARGET_OS_OSX
|
|
19
20
|
#import <React/RCTBackedTextInputDelegate.h>
|
|
20
21
|
#endif
|
|
@@ -290,9 +291,7 @@ using namespace facebook::react;
|
|
|
290
291
|
}
|
|
291
292
|
|
|
292
293
|
if (newViewProps.selectionColor != oldViewProps.selectionColor) {
|
|
293
|
-
|
|
294
|
-
ENRMSetSelectionColor(_textView, RCTUIColorFromSharedColor(newViewProps.selectionColor));
|
|
295
|
-
}
|
|
294
|
+
ENRMApplySelectionColor(_textView, newViewProps.selectionColor);
|
|
296
295
|
}
|
|
297
296
|
|
|
298
297
|
_emitMarkdown = newViewProps.isOnChangeMarkdownSet;
|
package/ios/utils/ENRMUIKit.h
CHANGED
|
@@ -203,12 +203,16 @@ static inline void ENRMSetCursorColor(ENRMPlatformTextView *textView, RCTUIColor
|
|
|
203
203
|
#endif
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
-
/// Cross-platform selection color: iOS uses tintColor (affects
|
|
207
|
-
///
|
|
206
|
+
/// Cross-platform selection color: iOS uses tintColor (also affects the caret
|
|
207
|
+
/// and selection handles); macOS sets the selection background via
|
|
208
|
+
/// `selectedTextAttributes`. Pass `nil` to restore the system default.
|
|
208
209
|
static inline void ENRMSetSelectionColor(ENRMPlatformTextView *textView, RCTUIColor *color)
|
|
209
210
|
{
|
|
210
211
|
#if !TARGET_OS_OSX
|
|
211
212
|
textView.tintColor = color;
|
|
213
|
+
#else
|
|
214
|
+
RCTUIColor *resolved = color ?: [NSColor selectedTextBackgroundColor];
|
|
215
|
+
textView.selectedTextAttributes = @{NSBackgroundColorAttributeName : resolved};
|
|
212
216
|
#endif
|
|
213
217
|
}
|
|
214
218
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#import "ENRMUIKit.h"
|
|
4
|
+
#import <React/RCTConversions.h>
|
|
5
|
+
|
|
6
|
+
/// Applies a codegen `selectionColor` to `textView`, falling back to the
|
|
7
|
+
/// system tint when the color is unset. Obj-C++ only — `.mm` consumers only.
|
|
8
|
+
static inline void ENRMApplySelectionColor(ENRMPlatformTextView *textView, const facebook::react::SharedColor &color) {
|
|
9
|
+
if (isColorMeaningful(color)) {
|
|
10
|
+
ENRMSetSelectionColor(textView, RCTUIColorFromSharedColor(color));
|
|
11
|
+
} else {
|
|
12
|
+
ENRMSetSelectionColor(textView, nil);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -273,6 +273,23 @@ export interface NativeProps extends ViewProps {
|
|
|
273
273
|
* @default true
|
|
274
274
|
*/
|
|
275
275
|
selectable?: boolean;
|
|
276
|
+
/**
|
|
277
|
+
* Color of the text selection highlight.
|
|
278
|
+
*
|
|
279
|
+
* On iOS, this also affects the caret and selection handle colors
|
|
280
|
+
* (they share a single tint). On macOS, only the selection background
|
|
281
|
+
* is affected.
|
|
282
|
+
*
|
|
283
|
+
* @platform ios, android, macos, web
|
|
284
|
+
*/
|
|
285
|
+
selectionColor?: ColorValue;
|
|
286
|
+
/**
|
|
287
|
+
* Color of the selection handles (drag anchors).
|
|
288
|
+
* No-op on API levels below 29.
|
|
289
|
+
*
|
|
290
|
+
* @platform android
|
|
291
|
+
*/
|
|
292
|
+
selectionHandleColor?: ColorValue;
|
|
276
293
|
/**
|
|
277
294
|
* MD4C parser flags configuration.
|
|
278
295
|
* Controls how the markdown parser interprets certain syntax.
|
|
@@ -273,6 +273,23 @@ export interface NativeProps extends ViewProps {
|
|
|
273
273
|
* @default true
|
|
274
274
|
*/
|
|
275
275
|
selectable?: boolean;
|
|
276
|
+
/**
|
|
277
|
+
* Color of the text selection highlight.
|
|
278
|
+
*
|
|
279
|
+
* On iOS, this also affects the caret and selection handle colors
|
|
280
|
+
* (they share a single tint). On macOS, only the selection background
|
|
281
|
+
* is affected.
|
|
282
|
+
*
|
|
283
|
+
* @platform ios, android, macos, web
|
|
284
|
+
*/
|
|
285
|
+
selectionColor?: ColorValue;
|
|
286
|
+
/**
|
|
287
|
+
* Color of the selection handles (drag anchors).
|
|
288
|
+
* No-op on API levels below 29.
|
|
289
|
+
*
|
|
290
|
+
* @platform android
|
|
291
|
+
*/
|
|
292
|
+
selectionHandleColor?: ColorValue;
|
|
276
293
|
/**
|
|
277
294
|
* MD4C parser flags configuration.
|
|
278
295
|
* Controls how the markdown parser interprets certain syntax.
|