@whetware/react-native-stroke-text 0.0.4 → 0.0.6

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 (28) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/android/src/main/java/com/margelo/nitro/stroketext/HybridStrokeTextView.kt +4 -34
  3. package/android/src/main/java/com/margelo/nitro/stroketext/StrokeTextView.kt +37 -10
  4. package/ios/HybridStrokeTextView.swift +1 -0
  5. package/lib/StrokeText.js +72 -34
  6. package/lib/StrokeText.web.js +15 -33
  7. package/lib/specs/StrokeTextView.nitro.d.ts +2 -0
  8. package/lib/types.d.ts +2 -2
  9. package/nitrogen/generated/android/c++/JHybridStrokeTextViewSpec.cpp +13 -0
  10. package/nitrogen/generated/android/c++/JHybridStrokeTextViewSpec.hpp +2 -0
  11. package/nitrogen/generated/android/c++/JStrokeTextAlignVertical.hpp +64 -0
  12. package/nitrogen/generated/android/c++/views/JHybridStrokeTextViewStateUpdater.cpp +4 -0
  13. package/nitrogen/generated/android/kotlin/com/margelo/nitro/stroketext/HybridStrokeTextViewSpec.kt +6 -0
  14. package/nitrogen/generated/android/kotlin/com/margelo/nitro/stroketext/StrokeTextAlignVertical.kt +25 -0
  15. package/nitrogen/generated/ios/NitroStrokeText-Swift-Cxx-Bridge.hpp +18 -0
  16. package/nitrogen/generated/ios/NitroStrokeText-Swift-Cxx-Umbrella.hpp +3 -0
  17. package/nitrogen/generated/ios/c++/HybridStrokeTextViewSpecSwift.hpp +10 -0
  18. package/nitrogen/generated/ios/c++/views/HybridStrokeTextViewComponent.mm +5 -0
  19. package/nitrogen/generated/ios/swift/HybridStrokeTextViewSpec.swift +1 -0
  20. package/nitrogen/generated/ios/swift/HybridStrokeTextViewSpec_cxx.swift +17 -0
  21. package/nitrogen/generated/ios/swift/StrokeTextAlignVertical.swift +48 -0
  22. package/nitrogen/generated/shared/c++/HybridStrokeTextViewSpec.cpp +2 -0
  23. package/nitrogen/generated/shared/c++/HybridStrokeTextViewSpec.hpp +5 -0
  24. package/nitrogen/generated/shared/c++/StrokeTextAlignVertical.hpp +84 -0
  25. package/nitrogen/generated/shared/c++/views/HybridStrokeTextViewComponent.cpp +12 -0
  26. package/nitrogen/generated/shared/c++/views/HybridStrokeTextViewComponent.hpp +2 -0
  27. package/nitrogen/generated/shared/json/StrokeTextViewConfig.json +1 -0
  28. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @whetware/react-native-stroke-text
2
2
 
3
+ ## 0.0.6
4
+
5
+ ### Patch Changes
6
+
7
+ - [`f8a9483`](https://github.com/whetware/react-native-stroke-text/commit/f8a9483d80eebe2149b84a47da7a2178341c5c9f) Thanks [@evelant](https://github.com/evelant)! - Fix layout on Android
8
+
9
+ ## 0.0.5
10
+
11
+ ### Patch Changes
12
+
13
+ - [`1bfd35a`](https://github.com/whetware/react-native-stroke-text/commit/1bfd35ada98c9dc39e76510c2f239bc2719eac61) Thanks [@evelant](https://github.com/evelant)! - Fix layout issues
14
+
3
15
  ## 0.0.4
4
16
 
5
17
  ### Patch Changes
@@ -3,9 +3,8 @@ package com.margelo.nitro.stroketext
3
3
  import android.view.View
4
4
  import com.facebook.jni.HybridData
5
5
  import com.facebook.react.uimanager.ThemedReactContext
6
- import com.margelo.nitro.views.RecyclableView
7
6
 
8
- class HybridStrokeTextView(context: ThemedReactContext) : HybridStrokeTextViewSpec(), RecyclableView {
7
+ class HybridStrokeTextView(context: ThemedReactContext) : HybridStrokeTextViewSpec() {
9
8
  private val strokeTextView = StrokeTextView(context)
10
9
  override val view: View = strokeTextView
11
10
 
@@ -22,6 +21,7 @@ class HybridStrokeTextView(context: ThemedReactContext) : HybridStrokeTextViewSp
22
21
  override var lineHeight: Double? = null
23
22
  override var letterSpacing: Double? = null
24
23
  override var textAlign: StrokeTextAlign? = null
24
+ override var textAlignVertical: StrokeTextAlignVertical? = null
25
25
  override var textDecorationLine: StrokeTextDecorationLine? = null
26
26
  override var textTransform: StrokeTextTransform? = null
27
27
  override var opacity: Double? = null
@@ -55,37 +55,6 @@ class HybridStrokeTextView(context: ThemedReactContext) : HybridStrokeTextViewSp
55
55
  }
56
56
  }
57
57
 
58
- override fun prepareForRecycle() {
59
- text = ""
60
- color = null
61
- strokeColor = null
62
- strokeWidth = null
63
- fontSize = null
64
- fontWeight = null
65
- fontFamily = null
66
- fontStyle = null
67
- lineHeight = null
68
- letterSpacing = null
69
- textAlign = null
70
- textDecorationLine = null
71
- textTransform = null
72
- opacity = null
73
- allowFontScaling = null
74
- maxFontSizeMultiplier = null
75
- includeFontPadding = null
76
- numberOfLines = null
77
- ellipsizeMode = null
78
- padding = null
79
- paddingVertical = null
80
- paddingHorizontal = null
81
- paddingTop = null
82
- paddingRight = null
83
- paddingBottom = null
84
- paddingLeft = null
85
-
86
- afterUpdate()
87
- }
88
-
89
58
  override fun afterUpdate() {
90
59
  val displayMetrics = strokeTextView.resources.displayMetrics
91
60
  val resolvedAllowFontScaling = allowFontScaling ?: true
@@ -137,10 +106,11 @@ class HybridStrokeTextView(context: ThemedReactContext) : HybridStrokeTextViewSp
137
106
  }
138
107
 
139
108
  strokeTextView.textAlign = textAlign ?: StrokeTextAlign.AUTO
109
+ strokeTextView.textAlignVertical = textAlignVertical ?: StrokeTextAlignVertical.AUTO
140
110
  strokeTextView.textDecorationLine = textDecorationLine ?: StrokeTextDecorationLine.NONE
141
111
  strokeTextView.textTransform = textTransform ?: StrokeTextTransform.NONE
142
112
 
143
- strokeTextView.includeFontPadding = includeFontPadding ?: false
113
+ strokeTextView.includeFontPadding = includeFontPadding ?: true
144
114
  strokeTextView.numberOfLines = (numberOfLines ?: 0.0).toInt()
145
115
  strokeTextView.ellipsizeMode = ellipsizeMode
146
116
 
@@ -7,12 +7,14 @@ import android.graphics.Paint.FontMetricsInt
7
7
  import android.graphics.Typeface
8
8
  import android.os.Build
9
9
  import android.text.Layout
10
+ import android.text.TextDirectionHeuristics
10
11
  import android.text.Spannable
11
12
  import android.text.SpannableString
12
13
  import android.text.TextUtils
13
14
  import android.text.style.LineHeightSpan
14
15
  import android.util.TypedValue
15
16
  import android.view.Gravity
17
+ import android.view.View
16
18
  import android.widget.TextView
17
19
  import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
18
20
  import com.facebook.react.uimanager.ThemedReactContext
@@ -38,6 +40,7 @@ internal class StrokeTextView(context: ThemedReactContext) : TextView(context) {
38
40
  var letterSpacingPx: Float? = null
39
41
 
40
42
  var textAlign: StrokeTextAlign = StrokeTextAlign.AUTO
43
+ var textAlignVertical: StrokeTextAlignVertical = StrokeTextAlignVertical.AUTO
41
44
  var textDecorationLine: StrokeTextDecorationLine = StrokeTextDecorationLine.NONE
42
45
  var textTransform: StrokeTextTransform = StrokeTextTransform.NONE
43
46
 
@@ -53,11 +56,8 @@ internal class StrokeTextView(context: ThemedReactContext) : TextView(context) {
53
56
  var paddingLeftPx: Float? = null
54
57
 
55
58
  init {
56
- // Default to no font padding to avoid Android's extra ascent/descent insets shifting the
57
- // glyphs downward. (React Native <Text> defaults includeFontPadding=true, but most designs
58
- // expect iOS/web-like top alignment.)
59
59
  gravity = Gravity.TOP or Gravity.START
60
- includeFontPadding = false
60
+ includeFontPadding = true
61
61
  }
62
62
 
63
63
  fun invalidateTextLayout() {
@@ -113,6 +113,8 @@ internal class StrokeTextView(context: ThemedReactContext) : TextView(context) {
113
113
  }
114
114
 
115
115
  private fun applyProps() {
116
+ val transformedText = applyTextTransform(rawText, textTransform)
117
+
116
118
  // Padding: apply a stroke inset so the outline stays within the view bounds.
117
119
  val inset = strokeInsetPx()
118
120
  val left = floorToInt(resolvePadding(paddingLeftPx, paddingHorizontalPx, paddingAllPx) + inset)
@@ -148,13 +150,39 @@ internal class StrokeTextView(context: ThemedReactContext) : TextView(context) {
148
150
  paint.isStrikeThruText = strike
149
151
 
150
152
  // Alignment
151
- val horizontalGravity =
153
+ val isParagraphRtl = layoutDirection == View.LAYOUT_DIRECTION_RTL
154
+ val isScriptRtl =
155
+ transformedText.isNotEmpty() &&
156
+ TextDirectionHeuristics.FIRSTSTRONG_LTR.isRtl(transformedText, 0, transformedText.length)
157
+ val swapNormalAndOpposite = isParagraphRtl != isScriptRtl
158
+
159
+ val textAlignment =
152
160
  when (textAlign) {
153
- StrokeTextAlign.RIGHT -> Gravity.END
154
- StrokeTextAlign.CENTER -> Gravity.CENTER_HORIZONTAL
155
- else -> Gravity.START
161
+ StrokeTextAlign.CENTER -> Layout.Alignment.ALIGN_CENTER
162
+ StrokeTextAlign.RIGHT ->
163
+ if (swapNormalAndOpposite) Layout.Alignment.ALIGN_NORMAL
164
+ else Layout.Alignment.ALIGN_OPPOSITE
165
+ else ->
166
+ if (swapNormalAndOpposite) Layout.Alignment.ALIGN_OPPOSITE
167
+ else Layout.Alignment.ALIGN_NORMAL
156
168
  }
157
- gravity = Gravity.TOP or horizontalGravity
169
+
170
+ val horizontalGravity =
171
+ when (textAlignment) {
172
+ Layout.Alignment.ALIGN_NORMAL -> if (isScriptRtl) Gravity.RIGHT else Gravity.LEFT
173
+ Layout.Alignment.ALIGN_OPPOSITE -> if (isScriptRtl) Gravity.LEFT else Gravity.RIGHT
174
+ Layout.Alignment.ALIGN_CENTER -> Gravity.CENTER_HORIZONTAL
175
+ }
176
+
177
+ val verticalGravity =
178
+ when (textAlignVertical) {
179
+ StrokeTextAlignVertical.BOTTOM -> Gravity.BOTTOM
180
+ StrokeTextAlignVertical.CENTER -> Gravity.CENTER_VERTICAL
181
+ StrokeTextAlignVertical.TOP,
182
+ StrokeTextAlignVertical.AUTO -> Gravity.TOP
183
+ }
184
+
185
+ gravity = verticalGravity or horizontalGravity
158
186
 
159
187
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
160
188
  justificationMode =
@@ -181,7 +209,6 @@ internal class StrokeTextView(context: ThemedReactContext) : TextView(context) {
181
209
  setTextColor(color)
182
210
 
183
211
  // Text + transform + line height (set last so layout is created with the final paint settings).
184
- val transformedText = applyTextTransform(rawText, textTransform)
185
212
  val textForLayout: CharSequence =
186
213
  if (lineHeightPx != null && !lineHeightPx!!.isNaN() && transformedText.isNotEmpty()) {
187
214
  SpannableString(transformedText).apply {
@@ -17,6 +17,7 @@ final class HybridStrokeTextView: HybridStrokeTextViewSpec {
17
17
  var lineHeight: Double? = nil
18
18
  var letterSpacing: Double? = nil
19
19
  var textAlign: StrokeTextAlign? = nil
20
+ var textAlignVertical: StrokeTextAlignVertical? = nil
20
21
  var textDecorationLine: StrokeTextDecorationLine? = nil
21
22
  var textTransform: StrokeTextTransform? = nil
22
23
  var opacity: Double? = nil
package/lib/StrokeText.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { I18nManager, StyleSheet, Text, View } from 'react-native';
2
+ import { StyleSheet, Text, View } from 'react-native';
3
3
  import { callback, getHostComponent } from 'react-native-nitro-modules';
4
4
  import StrokeTextViewConfig from '../nitrogen/generated/shared/json/StrokeTextViewConfig.json';
5
5
  const NativeStrokeTextView = getHostComponent('StrokeTextView', () => StrokeTextViewConfig);
@@ -41,6 +41,14 @@ function toColorString(value) {
41
41
  }
42
42
  return undefined;
43
43
  }
44
+ function toTextAlignVertical(value) {
45
+ return value === 'auto' ||
46
+ value === 'top' ||
47
+ value === 'bottom' ||
48
+ value === 'center'
49
+ ? value
50
+ : undefined;
51
+ }
44
52
  function warnOnInvalidChildren(children) {
45
53
  if (!__DEV__)
46
54
  return;
@@ -56,59 +64,89 @@ export function StrokeText({ text, children, style, hybridRef, ...rest }) {
56
64
  const resolvedText = resolveText(text, children);
57
65
  const flattened = StyleSheet.flatten(style);
58
66
  const { padding, paddingVertical, paddingHorizontal, paddingTop, paddingRight, paddingBottom, paddingLeft, ...nativeProps } = rest;
59
- const { color: styleColor, fontSize: styleFontSize, fontWeight: styleFontWeight, fontFamily: styleFontFamily, fontStyle: styleFontStyle, lineHeight: styleLineHeight, letterSpacing: styleLetterSpacing, textAlign: styleTextAlign, textDecorationLine: styleTextDecorationLine, textTransform: styleTextTransform, opacity: styleOpacity, includeFontPadding: styleIncludeFontPadding, padding: stylePadding, paddingVertical: stylePaddingVertical, paddingHorizontal: stylePaddingHorizontal, paddingTop: stylePaddingTop, paddingRight: stylePaddingRight, paddingBottom: stylePaddingBottom, paddingLeft: stylePaddingLeft, ...containerStyle } = flattened ?? {};
67
+ const { color: styleColor, fontSize: styleFontSize, fontWeight: styleFontWeight, fontFamily: styleFontFamily, fontStyle: styleFontStyle, lineHeight: styleLineHeight, letterSpacing: styleLetterSpacing, textAlign: styleTextAlign, textAlignVertical: styleTextAlignVertical, verticalAlign: styleVerticalAlign, textDecorationLine: styleTextDecorationLine, textTransform: styleTextTransform, opacity: styleOpacity, includeFontPadding: styleIncludeFontPadding, padding: stylePadding, paddingVertical: stylePaddingVertical, paddingHorizontal: stylePaddingHorizontal, paddingTop: stylePaddingTop, paddingRight: stylePaddingRight, paddingBottom: stylePaddingBottom, paddingLeft: stylePaddingLeft, ...containerStyle } = flattened ?? {};
60
68
  const strokeWidth = Math.max(0, nativeProps.strokeWidth ?? 0);
61
69
  const strokeInset = Math.ceil(strokeWidth) / 2;
62
70
  const baseTop = firstNumber(paddingTop, stylePaddingTop, paddingVertical, stylePaddingVertical, padding, stylePadding) ?? 0;
63
71
  const baseRight = firstNumber(paddingRight, stylePaddingRight, paddingHorizontal, stylePaddingHorizontal, padding, stylePadding) ?? 0;
64
72
  const baseBottom = firstNumber(paddingBottom, stylePaddingBottom, paddingVertical, stylePaddingVertical, padding, stylePadding) ?? 0;
65
73
  const baseLeft = firstNumber(paddingLeft, stylePaddingLeft, paddingHorizontal, stylePaddingHorizontal, padding, stylePadding) ?? 0;
66
- const baseMarginTop = firstNumber(containerStyle.marginTop, containerStyle.marginVertical, containerStyle.margin) ?? 0;
67
- const baseMarginRight = firstNumber(containerStyle.marginRight, I18nManager.isRTL ? containerStyle.marginStart : containerStyle.marginEnd, containerStyle.marginHorizontal, containerStyle.margin) ?? 0;
68
- const baseMarginBottom = firstNumber(containerStyle.marginBottom, containerStyle.marginVertical, containerStyle.margin) ?? 0;
69
- const baseMarginLeft = firstNumber(containerStyle.marginLeft, I18nManager.isRTL ? containerStyle.marginEnd : containerStyle.marginStart, containerStyle.marginHorizontal, containerStyle.margin) ?? 0;
70
- const baseMarginStart = toNumber(containerStyle.marginStart);
71
- const baseMarginEnd = toNumber(containerStyle.marginEnd);
72
- const strokeInsetMarginStyle = strokeInset === 0
73
- ? null
74
- : {
75
- marginTop: baseMarginTop - strokeInset,
76
- marginRight: baseMarginRight - strokeInset,
77
- marginBottom: baseMarginBottom - strokeInset,
78
- marginLeft: baseMarginLeft - strokeInset,
79
- ...(baseMarginStart == null
80
- ? {}
81
- : { marginStart: baseMarginStart - strokeInset }),
82
- ...(baseMarginEnd == null ? {} : { marginEnd: baseMarginEnd - strokeInset }),
83
- };
84
74
  const effectiveNumberOfLines = nativeProps.numberOfLines != null && nativeProps.numberOfLines > 0
85
75
  ? nativeProps.numberOfLines
86
76
  : undefined;
87
77
  const effectiveEllipsizeMode = effectiveNumberOfLines == null
88
78
  ? undefined
89
79
  : nativeProps.ellipsizeMode ?? 'tail';
90
- const effectiveIncludeFontPadding = nativeProps.includeFontPadding ?? styleIncludeFontPadding ?? false;
80
+ const mappedTextAlignVerticalFromVerticalAlign = styleVerticalAlign === 'middle'
81
+ ? 'center'
82
+ : toTextAlignVertical(styleVerticalAlign);
83
+ const effectiveTextAlignVertical = nativeProps.textAlignVertical ??
84
+ toTextAlignVertical(styleTextAlignVertical) ??
85
+ mappedTextAlignVerticalFromVerticalAlign;
86
+ const effectiveIncludeFontPadding = nativeProps.includeFontPadding ?? styleIncludeFontPadding ?? true;
87
+ const effectiveFontWeight = nativeProps.fontWeight ?? toFontWeightString(styleFontWeight);
88
+ const effectiveFontSize = nativeProps.fontSize ?? toNumber(styleFontSize);
89
+ const effectiveFontFamily = nativeProps.fontFamily ?? styleFontFamily;
90
+ const effectiveFontStyle = nativeProps.fontStyle ?? styleFontStyle;
91
+ const effectiveLineHeight = nativeProps.lineHeight ?? toNumber(styleLineHeight);
92
+ const effectiveLetterSpacing = nativeProps.letterSpacing ?? toNumber(styleLetterSpacing);
93
+ const effectiveTextAlign = nativeProps.textAlign ?? styleTextAlign;
94
+ const effectiveTextDecorationLine = nativeProps.textDecorationLine ?? styleTextDecorationLine;
95
+ const effectiveTextTransform = nativeProps.textTransform ?? styleTextTransform;
96
+ const effectiveColor = nativeProps.color ?? toColorString(styleColor);
91
97
  const wrappedHybridRef = React.useMemo(() => (hybridRef ? callback(hybridRef) : undefined), [hybridRef]);
92
- return (React.createElement(View, { style: [styles.container, containerStyle, strokeInsetMarginStyle] },
98
+ const measurerTextStyle = React.useMemo(() => ({
99
+ color: effectiveColor,
100
+ fontSize: effectiveFontSize,
101
+ fontWeight: effectiveFontWeight,
102
+ fontFamily: effectiveFontFamily,
103
+ fontStyle: effectiveFontStyle,
104
+ lineHeight: effectiveLineHeight,
105
+ letterSpacing: effectiveLetterSpacing,
106
+ textAlign: effectiveTextAlign,
107
+ textAlignVertical: effectiveTextAlignVertical,
108
+ textDecorationLine: effectiveTextDecorationLine,
109
+ textTransform: effectiveTextTransform,
110
+ includeFontPadding: effectiveIncludeFontPadding,
111
+ }), [
112
+ effectiveColor,
113
+ effectiveFontSize,
114
+ effectiveFontWeight,
115
+ effectiveFontFamily,
116
+ effectiveFontStyle,
117
+ effectiveLineHeight,
118
+ effectiveLetterSpacing,
119
+ effectiveTextAlign,
120
+ effectiveTextAlignVertical,
121
+ effectiveTextDecorationLine,
122
+ effectiveTextTransform,
123
+ effectiveIncludeFontPadding,
124
+ ]);
125
+ return (React.createElement(View, { style: [styles.container, containerStyle] },
93
126
  React.createElement(Text, { accessible: false, pointerEvents: "none", numberOfLines: effectiveNumberOfLines, ellipsizeMode: effectiveEllipsizeMode, allowFontScaling: nativeProps.allowFontScaling, maxFontSizeMultiplier: nativeProps.maxFontSizeMultiplier, style: [
94
- style,
127
+ measurerTextStyle,
95
128
  {
96
- paddingTop: baseTop + strokeInset,
97
- paddingRight: baseRight + strokeInset,
98
- paddingBottom: baseBottom + strokeInset,
99
- paddingLeft: baseLeft + strokeInset,
129
+ paddingTop: baseTop,
130
+ paddingRight: baseRight,
131
+ paddingBottom: baseBottom,
132
+ paddingLeft: baseLeft,
100
133
  },
101
- effectiveIncludeFontPadding == null
102
- ? null
103
- : { includeFontPadding: effectiveIncludeFontPadding },
104
134
  styles.hiddenText,
105
135
  ] }, resolvedText),
106
- React.createElement(NativeStrokeTextView, { ...nativeProps, text: resolvedText, color: nativeProps.color ?? toColorString(styleColor), fontSize: nativeProps.fontSize ?? toNumber(styleFontSize), fontWeight: nativeProps.fontWeight ?? toFontWeightString(styleFontWeight), fontFamily: nativeProps.fontFamily ?? styleFontFamily, fontStyle: nativeProps.fontStyle ?? styleFontStyle, lineHeight: nativeProps.lineHeight ?? toNumber(styleLineHeight), letterSpacing: nativeProps.letterSpacing ?? toNumber(styleLetterSpacing), textAlign: nativeProps.textAlign ?? styleTextAlign, textDecorationLine: nativeProps.textDecorationLine ?? styleTextDecorationLine, textTransform: nativeProps.textTransform ?? styleTextTransform, opacity: nativeProps.opacity ?? toNumber(styleOpacity), includeFontPadding: effectiveIncludeFontPadding, numberOfLines: nativeProps.numberOfLines, ellipsizeMode: effectiveEllipsizeMode, paddingTop: baseTop, paddingRight: baseRight, paddingBottom: baseBottom, paddingLeft: baseLeft, hybridRef: wrappedHybridRef, pointerEvents: "none", style: styles.overlay })));
136
+ React.createElement(NativeStrokeTextView, { ...nativeProps, text: resolvedText, color: effectiveColor, fontSize: effectiveFontSize, fontWeight: effectiveFontWeight, fontFamily: effectiveFontFamily, fontStyle: effectiveFontStyle, lineHeight: effectiveLineHeight, letterSpacing: effectiveLetterSpacing, textAlign: effectiveTextAlign, textAlignVertical: effectiveTextAlignVertical, textDecorationLine: effectiveTextDecorationLine, textTransform: effectiveTextTransform, opacity: nativeProps.opacity ?? toNumber(styleOpacity), includeFontPadding: effectiveIncludeFontPadding, numberOfLines: nativeProps.numberOfLines, ellipsizeMode: effectiveEllipsizeMode, paddingTop: baseTop, paddingRight: baseRight, paddingBottom: baseBottom, paddingLeft: baseLeft, hybridRef: wrappedHybridRef, pointerEvents: "none", style: [
137
+ styles.overlay,
138
+ strokeInset === 0
139
+ ? null
140
+ : {
141
+ top: -strokeInset,
142
+ right: -strokeInset,
143
+ bottom: -strokeInset,
144
+ left: -strokeInset,
145
+ },
146
+ ] })));
107
147
  }
108
148
  const styles = StyleSheet.create({
109
- container: {
110
- alignSelf: 'flex-start',
111
- },
149
+ container: {},
112
150
  overlay: {
113
151
  ...StyleSheet.absoluteFillObject,
114
152
  },
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { I18nManager, StyleSheet, Text, View } from 'react-native';
2
+ import { StyleSheet, Text, View } from 'react-native';
3
3
  function resolveText(text, children) {
4
4
  if (typeof text === 'string')
5
5
  return text;
@@ -38,24 +38,6 @@ export function StrokeText({ text, children, style, ...rest }) {
38
38
  const strokeColor = rest.strokeColor ?? 'transparent';
39
39
  const strokeWidth = Math.max(0, rest.strokeWidth ?? 0);
40
40
  const strokeInset = Math.ceil(strokeWidth) / 2;
41
- const baseMarginTop = firstNumber(containerStyle.marginTop, containerStyle.marginVertical, containerStyle.margin) ?? 0;
42
- const baseMarginRight = firstNumber(containerStyle.marginRight, I18nManager.isRTL ? containerStyle.marginStart : containerStyle.marginEnd, containerStyle.marginHorizontal, containerStyle.margin) ?? 0;
43
- const baseMarginBottom = firstNumber(containerStyle.marginBottom, containerStyle.marginVertical, containerStyle.margin) ?? 0;
44
- const baseMarginLeft = firstNumber(containerStyle.marginLeft, I18nManager.isRTL ? containerStyle.marginEnd : containerStyle.marginStart, containerStyle.marginHorizontal, containerStyle.margin) ?? 0;
45
- const baseMarginStart = toNumber(containerStyle.marginStart);
46
- const baseMarginEnd = toNumber(containerStyle.marginEnd);
47
- const strokeInsetMarginStyle = strokeInset === 0
48
- ? null
49
- : {
50
- marginTop: baseMarginTop - strokeInset,
51
- marginRight: baseMarginRight - strokeInset,
52
- marginBottom: baseMarginBottom - strokeInset,
53
- marginLeft: baseMarginLeft - strokeInset,
54
- ...(baseMarginStart == null
55
- ? {}
56
- : { marginStart: baseMarginStart - strokeInset }),
57
- ...(baseMarginEnd == null ? {} : { marginEnd: baseMarginEnd - strokeInset }),
58
- };
59
41
  const baseTop = firstNumber(rest.paddingTop, stylePaddingTop, rest.paddingVertical, stylePaddingVertical, rest.padding, stylePadding) ?? 0;
60
42
  const baseRight = firstNumber(rest.paddingRight, stylePaddingRight, rest.paddingHorizontal, stylePaddingHorizontal, rest.padding, stylePadding) ?? 0;
61
43
  const baseBottom = firstNumber(rest.paddingBottom, stylePaddingBottom, rest.paddingVertical, stylePaddingVertical, rest.padding, stylePadding) ?? 0;
@@ -64,17 +46,15 @@ export function StrokeText({ text, children, style, ...rest }) {
64
46
  ? rest.numberOfLines
65
47
  : undefined;
66
48
  const effectiveEllipsizeMode = effectiveNumberOfLines == null ? undefined : rest.ellipsizeMode ?? 'tail';
67
- return (React.createElement(View, { style: [styles.container, containerStyle, strokeInsetMarginStyle] },
49
+ return (React.createElement(View, { style: [styles.container, containerStyle] },
68
50
  React.createElement(Text, { accessible: false, pointerEvents: "none", numberOfLines: effectiveNumberOfLines, ellipsizeMode: effectiveEllipsizeMode, style: [
69
51
  textStyle,
70
52
  {
71
- paddingTop: baseTop + strokeInset,
72
- paddingRight: baseRight + strokeInset,
73
- paddingBottom: baseBottom + strokeInset,
74
- paddingLeft: baseLeft + strokeInset,
53
+ paddingTop: baseTop,
54
+ paddingRight: baseRight,
55
+ paddingBottom: baseBottom,
56
+ paddingLeft: baseLeft,
75
57
  },
76
- strokeInset === 0 ? null : { maxWidth: 'none' },
77
- strokeInset === 0 ? null : { boxSizing: 'content-box' },
78
58
  styles.hiddenText,
79
59
  ] }, resolvedText),
80
60
  React.createElement(Text, { pointerEvents: "none", numberOfLines: effectiveNumberOfLines, ellipsizeMode: effectiveEllipsizeMode, style: [
@@ -87,10 +67,6 @@ export function StrokeText({ text, children, style, ...rest }) {
87
67
  paddingLeft: baseLeft + strokeInset,
88
68
  },
89
69
  strokeInset === 0 ? null : { maxWidth: 'none' },
90
- // react-native-web uses `box-sizing: border-box` globally; with ellipsizing enabled
91
- // (`overflow: hidden` + `text-overflow: ellipsis`), the extra stroke padding can reduce
92
- // the content box by a couple pixels and cause false-positive ellipses for some fonts.
93
- // Use `content-box` so padding doesn't shrink the text's available width.
94
70
  strokeInset === 0 ? null : { boxSizing: 'content-box' },
95
71
  strokeWidth > 0 && strokeColor !== 'transparent'
96
72
  ? {
@@ -103,12 +79,18 @@ export function StrokeText({ text, children, style, ...rest }) {
103
79
  }
104
80
  : null,
105
81
  styles.overlay,
82
+ strokeInset === 0
83
+ ? null
84
+ : {
85
+ top: -strokeInset,
86
+ right: -strokeInset,
87
+ bottom: -strokeInset,
88
+ left: -strokeInset,
89
+ },
106
90
  ] }, resolvedText)));
107
91
  }
108
92
  const styles = StyleSheet.create({
109
- container: {
110
- alignSelf: 'flex-start',
111
- },
93
+ container: {},
112
94
  overlay: {
113
95
  ...StyleSheet.absoluteFillObject,
114
96
  },
@@ -1,5 +1,6 @@
1
1
  import type { HybridView, HybridViewMethods, HybridViewProps } from 'react-native-nitro-modules';
2
2
  export type StrokeTextAlign = 'auto' | 'left' | 'right' | 'center' | 'justify';
3
+ export type StrokeTextAlignVertical = 'auto' | 'top' | 'bottom' | 'center';
3
4
  export type StrokeTextDecorationLine = 'none' | 'underline' | 'line-through' | 'underline line-through';
4
5
  export type StrokeTextTransform = 'none' | 'uppercase' | 'lowercase' | 'capitalize';
5
6
  export type StrokeTextFontStyle = 'normal' | 'italic';
@@ -16,6 +17,7 @@ export interface StrokeTextProps extends HybridViewProps {
16
17
  lineHeight?: number;
17
18
  letterSpacing?: number;
18
19
  textAlign?: StrokeTextAlign;
20
+ textAlignVertical?: StrokeTextAlignVertical;
19
21
  textDecorationLine?: StrokeTextDecorationLine;
20
22
  textTransform?: StrokeTextTransform;
21
23
  opacity?: number;
package/lib/types.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import type { StyleProp, TextStyle } from 'react-native';
3
- import type { StrokeTextAlign, StrokeTextDecorationLine, StrokeTextEllipsizeMode, StrokeTextFontStyle, StrokeTextMethods, StrokeTextProps as StrokeTextNitroProps, StrokeTextTransform, StrokeTextView } from './specs/StrokeTextView.nitro';
4
- export type { StrokeTextAlign, StrokeTextDecorationLine, StrokeTextEllipsizeMode, StrokeTextFontStyle, StrokeTextMethods, StrokeTextTransform, StrokeTextView, };
3
+ import type { StrokeTextAlign, StrokeTextAlignVertical, StrokeTextDecorationLine, StrokeTextEllipsizeMode, StrokeTextFontStyle, StrokeTextMethods, StrokeTextProps as StrokeTextNitroProps, StrokeTextTransform, StrokeTextView } from './specs/StrokeTextView.nitro';
4
+ export type { StrokeTextAlign, StrokeTextAlignVertical, StrokeTextDecorationLine, StrokeTextEllipsizeMode, StrokeTextFontStyle, StrokeTextMethods, StrokeTextTransform, StrokeTextView, };
5
5
  type OptionalKeys<T> = {
6
6
  [K in keyof T]-?: {} extends Pick<T, K> ? K : never;
7
7
  }[keyof T];
@@ -11,6 +11,8 @@
11
11
  namespace margelo::nitro::stroketext { enum class StrokeTextFontStyle; }
12
12
  // Forward declaration of `StrokeTextAlign` to properly resolve imports.
13
13
  namespace margelo::nitro::stroketext { enum class StrokeTextAlign; }
14
+ // Forward declaration of `StrokeTextAlignVertical` to properly resolve imports.
15
+ namespace margelo::nitro::stroketext { enum class StrokeTextAlignVertical; }
14
16
  // Forward declaration of `StrokeTextDecorationLine` to properly resolve imports.
15
17
  namespace margelo::nitro::stroketext { enum class StrokeTextDecorationLine; }
16
18
  // Forward declaration of `StrokeTextTransform` to properly resolve imports.
@@ -24,6 +26,8 @@ namespace margelo::nitro::stroketext { enum class StrokeTextEllipsizeMode; }
24
26
  #include "JStrokeTextFontStyle.hpp"
25
27
  #include "StrokeTextAlign.hpp"
26
28
  #include "JStrokeTextAlign.hpp"
29
+ #include "StrokeTextAlignVertical.hpp"
30
+ #include "JStrokeTextAlignVertical.hpp"
27
31
  #include "StrokeTextDecorationLine.hpp"
28
32
  #include "JStrokeTextDecorationLine.hpp"
29
33
  #include "StrokeTextTransform.hpp"
@@ -166,6 +170,15 @@ namespace margelo::nitro::stroketext {
166
170
  static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<JStrokeTextAlign> /* textAlign */)>("setTextAlign");
167
171
  method(_javaPart, textAlign.has_value() ? JStrokeTextAlign::fromCpp(textAlign.value()) : nullptr);
168
172
  }
173
+ std::optional<StrokeTextAlignVertical> JHybridStrokeTextViewSpec::getTextAlignVertical() {
174
+ static const auto method = javaClassStatic()->getMethod<jni::local_ref<JStrokeTextAlignVertical>()>("getTextAlignVertical");
175
+ auto __result = method(_javaPart);
176
+ return __result != nullptr ? std::make_optional(__result->toCpp()) : std::nullopt;
177
+ }
178
+ void JHybridStrokeTextViewSpec::setTextAlignVertical(std::optional<StrokeTextAlignVertical> textAlignVertical) {
179
+ static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<JStrokeTextAlignVertical> /* textAlignVertical */)>("setTextAlignVertical");
180
+ method(_javaPart, textAlignVertical.has_value() ? JStrokeTextAlignVertical::fromCpp(textAlignVertical.value()) : nullptr);
181
+ }
169
182
  std::optional<StrokeTextDecorationLine> JHybridStrokeTextViewSpec::getTextDecorationLine() {
170
183
  static const auto method = javaClassStatic()->getMethod<jni::local_ref<JStrokeTextDecorationLine>()>("getTextDecorationLine");
171
184
  auto __result = method(_javaPart);
@@ -73,6 +73,8 @@ namespace margelo::nitro::stroketext {
73
73
  void setLetterSpacing(std::optional<double> letterSpacing) override;
74
74
  std::optional<StrokeTextAlign> getTextAlign() override;
75
75
  void setTextAlign(std::optional<StrokeTextAlign> textAlign) override;
76
+ std::optional<StrokeTextAlignVertical> getTextAlignVertical() override;
77
+ void setTextAlignVertical(std::optional<StrokeTextAlignVertical> textAlignVertical) override;
76
78
  std::optional<StrokeTextDecorationLine> getTextDecorationLine() override;
77
79
  void setTextDecorationLine(std::optional<StrokeTextDecorationLine> textDecorationLine) override;
78
80
  std::optional<StrokeTextTransform> getTextTransform() override;
@@ -0,0 +1,64 @@
1
+ ///
2
+ /// JStrokeTextAlignVertical.hpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #pragma once
9
+
10
+ #include <fbjni/fbjni.h>
11
+ #include "StrokeTextAlignVertical.hpp"
12
+
13
+ namespace margelo::nitro::stroketext {
14
+
15
+ using namespace facebook;
16
+
17
+ /**
18
+ * The C++ JNI bridge between the C++ enum "StrokeTextAlignVertical" and the the Kotlin enum "StrokeTextAlignVertical".
19
+ */
20
+ struct JStrokeTextAlignVertical final: public jni::JavaClass<JStrokeTextAlignVertical> {
21
+ public:
22
+ static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/stroketext/StrokeTextAlignVertical;";
23
+
24
+ public:
25
+ /**
26
+ * Convert this Java/Kotlin-based enum to the C++ enum StrokeTextAlignVertical.
27
+ */
28
+ [[maybe_unused]]
29
+ [[nodiscard]]
30
+ StrokeTextAlignVertical toCpp() const {
31
+ static const auto clazz = javaClassStatic();
32
+ static const auto fieldOrdinal = clazz->getField<int>("value");
33
+ int ordinal = this->getFieldValue(fieldOrdinal);
34
+ return static_cast<StrokeTextAlignVertical>(ordinal);
35
+ }
36
+
37
+ public:
38
+ /**
39
+ * Create a Java/Kotlin-based enum with the given C++ enum's value.
40
+ */
41
+ [[maybe_unused]]
42
+ static jni::alias_ref<JStrokeTextAlignVertical> fromCpp(StrokeTextAlignVertical value) {
43
+ static const auto clazz = javaClassStatic();
44
+ switch (value) {
45
+ case StrokeTextAlignVertical::AUTO:
46
+ static const auto fieldAUTO = clazz->getStaticField<JStrokeTextAlignVertical>("AUTO");
47
+ return clazz->getStaticFieldValue(fieldAUTO);
48
+ case StrokeTextAlignVertical::CENTER:
49
+ static const auto fieldCENTER = clazz->getStaticField<JStrokeTextAlignVertical>("CENTER");
50
+ return clazz->getStaticFieldValue(fieldCENTER);
51
+ case StrokeTextAlignVertical::TOP:
52
+ static const auto fieldTOP = clazz->getStaticField<JStrokeTextAlignVertical>("TOP");
53
+ return clazz->getStaticFieldValue(fieldTOP);
54
+ case StrokeTextAlignVertical::BOTTOM:
55
+ static const auto fieldBOTTOM = clazz->getStaticField<JStrokeTextAlignVertical>("BOTTOM");
56
+ return clazz->getStaticFieldValue(fieldBOTTOM);
57
+ default:
58
+ std::string stringValue = std::to_string(static_cast<int>(value));
59
+ throw std::invalid_argument("Invalid enum value (" + stringValue + "!");
60
+ }
61
+ }
62
+ };
63
+
64
+ } // namespace margelo::nitro::stroketext
@@ -80,6 +80,10 @@ void JHybridStrokeTextViewStateUpdater::updateViewProps(jni::alias_ref<jni::JCla
80
80
  view->setTextAlign(props.textAlign.value);
81
81
  // TODO: Set isDirty = false
82
82
  }
83
+ if (props.textAlignVertical.isDirty) {
84
+ view->setTextAlignVertical(props.textAlignVertical.value);
85
+ // TODO: Set isDirty = false
86
+ }
83
87
  if (props.textDecorationLine.isDirty) {
84
88
  view->setTextDecorationLine(props.textDecorationLine.value);
85
89
  // TODO: Set isDirty = false
@@ -108,6 +108,12 @@ abstract class HybridStrokeTextViewSpec: HybridView() {
108
108
  @set:Keep
109
109
  abstract var textAlign: StrokeTextAlign?
110
110
 
111
+ @get:DoNotStrip
112
+ @get:Keep
113
+ @set:DoNotStrip
114
+ @set:Keep
115
+ abstract var textAlignVertical: StrokeTextAlignVertical?
116
+
111
117
  @get:DoNotStrip
112
118
  @get:Keep
113
119
  @set:DoNotStrip
@@ -0,0 +1,25 @@
1
+ ///
2
+ /// StrokeTextAlignVertical.kt
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ package com.margelo.nitro.stroketext
9
+
10
+ import androidx.annotation.Keep
11
+ import com.facebook.proguard.annotations.DoNotStrip
12
+
13
+ /**
14
+ * Represents the JavaScript enum/union "StrokeTextAlignVertical".
15
+ */
16
+ @DoNotStrip
17
+ @Keep
18
+ enum class StrokeTextAlignVertical(@DoNotStrip @Keep val value: Int) {
19
+ AUTO(0),
20
+ CENTER(1),
21
+ TOP(2),
22
+ BOTTOM(3);
23
+
24
+ companion object
25
+ }
@@ -10,6 +10,8 @@
10
10
  // Forward declarations of C++ defined types
11
11
  // Forward declaration of `HybridStrokeTextViewSpec` to properly resolve imports.
12
12
  namespace margelo::nitro::stroketext { class HybridStrokeTextViewSpec; }
13
+ // Forward declaration of `StrokeTextAlignVertical` to properly resolve imports.
14
+ namespace margelo::nitro::stroketext { enum class StrokeTextAlignVertical; }
13
15
  // Forward declaration of `StrokeTextAlign` to properly resolve imports.
14
16
  namespace margelo::nitro::stroketext { enum class StrokeTextAlign; }
15
17
  // Forward declaration of `StrokeTextDecorationLine` to properly resolve imports.
@@ -28,6 +30,7 @@ namespace NitroStrokeText { class HybridStrokeTextViewSpec_cxx; }
28
30
  // Include C++ defined types
29
31
  #include "HybridStrokeTextViewSpec.hpp"
30
32
  #include "StrokeTextAlign.hpp"
33
+ #include "StrokeTextAlignVertical.hpp"
31
34
  #include "StrokeTextDecorationLine.hpp"
32
35
  #include "StrokeTextEllipsizeMode.hpp"
33
36
  #include "StrokeTextFontStyle.hpp"
@@ -102,6 +105,21 @@ namespace margelo::nitro::stroketext::bridge::swift {
102
105
  return *optional;
103
106
  }
104
107
 
108
+ // pragma MARK: std::optional<StrokeTextAlignVertical>
109
+ /**
110
+ * Specialized version of `std::optional<StrokeTextAlignVertical>`.
111
+ */
112
+ using std__optional_StrokeTextAlignVertical_ = std::optional<StrokeTextAlignVertical>;
113
+ inline std::optional<StrokeTextAlignVertical> create_std__optional_StrokeTextAlignVertical_(const StrokeTextAlignVertical& value) noexcept {
114
+ return std::optional<StrokeTextAlignVertical>(value);
115
+ }
116
+ inline bool has_value_std__optional_StrokeTextAlignVertical_(const std::optional<StrokeTextAlignVertical>& optional) noexcept {
117
+ return optional.has_value();
118
+ }
119
+ inline StrokeTextAlignVertical get_std__optional_StrokeTextAlignVertical_(const std::optional<StrokeTextAlignVertical>& optional) noexcept {
120
+ return *optional;
121
+ }
122
+
105
123
  // pragma MARK: std::optional<StrokeTextDecorationLine>
106
124
  /**
107
125
  * Specialized version of `std::optional<StrokeTextDecorationLine>`.
@@ -10,6 +10,8 @@
10
10
  // Forward declarations of C++ defined types
11
11
  // Forward declaration of `HybridStrokeTextViewSpec` to properly resolve imports.
12
12
  namespace margelo::nitro::stroketext { class HybridStrokeTextViewSpec; }
13
+ // Forward declaration of `StrokeTextAlignVertical` to properly resolve imports.
14
+ namespace margelo::nitro::stroketext { enum class StrokeTextAlignVertical; }
13
15
  // Forward declaration of `StrokeTextAlign` to properly resolve imports.
14
16
  namespace margelo::nitro::stroketext { enum class StrokeTextAlign; }
15
17
  // Forward declaration of `StrokeTextDecorationLine` to properly resolve imports.
@@ -24,6 +26,7 @@ namespace margelo::nitro::stroketext { enum class StrokeTextTransform; }
24
26
  // Include C++ defined types
25
27
  #include "HybridStrokeTextViewSpec.hpp"
26
28
  #include "StrokeTextAlign.hpp"
29
+ #include "StrokeTextAlignVertical.hpp"
27
30
  #include "StrokeTextDecorationLine.hpp"
28
31
  #include "StrokeTextEllipsizeMode.hpp"
29
32
  #include "StrokeTextFontStyle.hpp"
@@ -16,6 +16,8 @@ namespace NitroStrokeText { class HybridStrokeTextViewSpec_cxx; }
16
16
  namespace margelo::nitro::stroketext { enum class StrokeTextFontStyle; }
17
17
  // Forward declaration of `StrokeTextAlign` to properly resolve imports.
18
18
  namespace margelo::nitro::stroketext { enum class StrokeTextAlign; }
19
+ // Forward declaration of `StrokeTextAlignVertical` to properly resolve imports.
20
+ namespace margelo::nitro::stroketext { enum class StrokeTextAlignVertical; }
19
21
  // Forward declaration of `StrokeTextDecorationLine` to properly resolve imports.
20
22
  namespace margelo::nitro::stroketext { enum class StrokeTextDecorationLine; }
21
23
  // Forward declaration of `StrokeTextTransform` to properly resolve imports.
@@ -27,6 +29,7 @@ namespace margelo::nitro::stroketext { enum class StrokeTextEllipsizeMode; }
27
29
  #include <optional>
28
30
  #include "StrokeTextFontStyle.hpp"
29
31
  #include "StrokeTextAlign.hpp"
32
+ #include "StrokeTextAlignVertical.hpp"
30
33
  #include "StrokeTextDecorationLine.hpp"
31
34
  #include "StrokeTextTransform.hpp"
32
35
  #include "StrokeTextEllipsizeMode.hpp"
@@ -154,6 +157,13 @@ namespace margelo::nitro::stroketext {
154
157
  inline void setTextAlign(std::optional<StrokeTextAlign> textAlign) noexcept override {
155
158
  _swiftPart.setTextAlign(textAlign);
156
159
  }
160
+ inline std::optional<StrokeTextAlignVertical> getTextAlignVertical() noexcept override {
161
+ auto __result = _swiftPart.getTextAlignVertical();
162
+ return __result;
163
+ }
164
+ inline void setTextAlignVertical(std::optional<StrokeTextAlignVertical> textAlignVertical) noexcept override {
165
+ _swiftPart.setTextAlignVertical(textAlignVertical);
166
+ }
157
167
  inline std::optional<StrokeTextDecorationLine> getTextDecorationLine() noexcept override {
158
168
  auto __result = _swiftPart.getTextDecorationLine();
159
169
  return __result;
@@ -127,6 +127,11 @@ using namespace margelo::nitro::stroketext::views;
127
127
  swiftPart.setTextAlign(newViewProps.textAlign.value);
128
128
  newViewProps.textAlign.isDirty = false;
129
129
  }
130
+ // textAlignVertical: optional
131
+ if (newViewProps.textAlignVertical.isDirty) {
132
+ swiftPart.setTextAlignVertical(newViewProps.textAlignVertical.value);
133
+ newViewProps.textAlignVertical.isDirty = false;
134
+ }
130
135
  // textDecorationLine: optional
131
136
  if (newViewProps.textDecorationLine.isDirty) {
132
137
  swiftPart.setTextDecorationLine(newViewProps.textDecorationLine.value);
@@ -22,6 +22,7 @@ public protocol HybridStrokeTextViewSpec_protocol: HybridObject, HybridView {
22
22
  var lineHeight: Double? { get set }
23
23
  var letterSpacing: Double? { get set }
24
24
  var textAlign: StrokeTextAlign? { get set }
25
+ var textAlignVertical: StrokeTextAlignVertical? { get set }
25
26
  var textDecorationLine: StrokeTextDecorationLine? { get set }
26
27
  var textTransform: StrokeTextTransform? { get set }
27
28
  var opacity: Double? { get set }
@@ -331,6 +331,23 @@ open class HybridStrokeTextViewSpec_cxx {
331
331
  }
332
332
  }
333
333
 
334
+ public final var textAlignVertical: bridge.std__optional_StrokeTextAlignVertical_ {
335
+ @inline(__always)
336
+ get {
337
+ return { () -> bridge.std__optional_StrokeTextAlignVertical_ in
338
+ if let __unwrappedValue = self.__implementation.textAlignVertical {
339
+ return bridge.create_std__optional_StrokeTextAlignVertical_(__unwrappedValue)
340
+ } else {
341
+ return .init()
342
+ }
343
+ }()
344
+ }
345
+ @inline(__always)
346
+ set {
347
+ self.__implementation.textAlignVertical = newValue.value
348
+ }
349
+ }
350
+
334
351
  public final var textDecorationLine: bridge.std__optional_StrokeTextDecorationLine_ {
335
352
  @inline(__always)
336
353
  get {
@@ -0,0 +1,48 @@
1
+ ///
2
+ /// StrokeTextAlignVertical.swift
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ /**
9
+ * Represents the JS union `StrokeTextAlignVertical`, backed by a C++ enum.
10
+ */
11
+ public typealias StrokeTextAlignVertical = margelo.nitro.stroketext.StrokeTextAlignVertical
12
+
13
+ public extension StrokeTextAlignVertical {
14
+ /**
15
+ * Get a StrokeTextAlignVertical for the given String value, or
16
+ * return `nil` if the given value was invalid/unknown.
17
+ */
18
+ init?(fromString string: String) {
19
+ switch string {
20
+ case "auto":
21
+ self = .auto
22
+ case "center":
23
+ self = .center
24
+ case "top":
25
+ self = .top
26
+ case "bottom":
27
+ self = .bottom
28
+ default:
29
+ return nil
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Get the String value this StrokeTextAlignVertical represents.
35
+ */
36
+ var stringValue: String {
37
+ switch self {
38
+ case .auto:
39
+ return "auto"
40
+ case .center:
41
+ return "center"
42
+ case .top:
43
+ return "top"
44
+ case .bottom:
45
+ return "bottom"
46
+ }
47
+ }
48
+ }
@@ -36,6 +36,8 @@ namespace margelo::nitro::stroketext {
36
36
  prototype.registerHybridSetter("letterSpacing", &HybridStrokeTextViewSpec::setLetterSpacing);
37
37
  prototype.registerHybridGetter("textAlign", &HybridStrokeTextViewSpec::getTextAlign);
38
38
  prototype.registerHybridSetter("textAlign", &HybridStrokeTextViewSpec::setTextAlign);
39
+ prototype.registerHybridGetter("textAlignVertical", &HybridStrokeTextViewSpec::getTextAlignVertical);
40
+ prototype.registerHybridSetter("textAlignVertical", &HybridStrokeTextViewSpec::setTextAlignVertical);
39
41
  prototype.registerHybridGetter("textDecorationLine", &HybridStrokeTextViewSpec::getTextDecorationLine);
40
42
  prototype.registerHybridSetter("textDecorationLine", &HybridStrokeTextViewSpec::setTextDecorationLine);
41
43
  prototype.registerHybridGetter("textTransform", &HybridStrokeTextViewSpec::getTextTransform);
@@ -17,6 +17,8 @@
17
17
  namespace margelo::nitro::stroketext { enum class StrokeTextFontStyle; }
18
18
  // Forward declaration of `StrokeTextAlign` to properly resolve imports.
19
19
  namespace margelo::nitro::stroketext { enum class StrokeTextAlign; }
20
+ // Forward declaration of `StrokeTextAlignVertical` to properly resolve imports.
21
+ namespace margelo::nitro::stroketext { enum class StrokeTextAlignVertical; }
20
22
  // Forward declaration of `StrokeTextDecorationLine` to properly resolve imports.
21
23
  namespace margelo::nitro::stroketext { enum class StrokeTextDecorationLine; }
22
24
  // Forward declaration of `StrokeTextTransform` to properly resolve imports.
@@ -28,6 +30,7 @@ namespace margelo::nitro::stroketext { enum class StrokeTextEllipsizeMode; }
28
30
  #include <optional>
29
31
  #include "StrokeTextFontStyle.hpp"
30
32
  #include "StrokeTextAlign.hpp"
33
+ #include "StrokeTextAlignVertical.hpp"
31
34
  #include "StrokeTextDecorationLine.hpp"
32
35
  #include "StrokeTextTransform.hpp"
33
36
  #include "StrokeTextEllipsizeMode.hpp"
@@ -81,6 +84,8 @@ namespace margelo::nitro::stroketext {
81
84
  virtual void setLetterSpacing(std::optional<double> letterSpacing) = 0;
82
85
  virtual std::optional<StrokeTextAlign> getTextAlign() = 0;
83
86
  virtual void setTextAlign(std::optional<StrokeTextAlign> textAlign) = 0;
87
+ virtual std::optional<StrokeTextAlignVertical> getTextAlignVertical() = 0;
88
+ virtual void setTextAlignVertical(std::optional<StrokeTextAlignVertical> textAlignVertical) = 0;
84
89
  virtual std::optional<StrokeTextDecorationLine> getTextDecorationLine() = 0;
85
90
  virtual void setTextDecorationLine(std::optional<StrokeTextDecorationLine> textDecorationLine) = 0;
86
91
  virtual std::optional<StrokeTextTransform> getTextTransform() = 0;
@@ -0,0 +1,84 @@
1
+ ///
2
+ /// StrokeTextAlignVertical.hpp
3
+ /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
+ /// https://github.com/mrousavy/nitro
5
+ /// Copyright © Marc Rousavy @ Margelo
6
+ ///
7
+
8
+ #pragma once
9
+
10
+ #if __has_include(<NitroModules/NitroHash.hpp>)
11
+ #include <NitroModules/NitroHash.hpp>
12
+ #else
13
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
14
+ #endif
15
+ #if __has_include(<NitroModules/JSIConverter.hpp>)
16
+ #include <NitroModules/JSIConverter.hpp>
17
+ #else
18
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
19
+ #endif
20
+ #if __has_include(<NitroModules/NitroDefines.hpp>)
21
+ #include <NitroModules/NitroDefines.hpp>
22
+ #else
23
+ #error NitroModules cannot be found! Are you sure you installed NitroModules properly?
24
+ #endif
25
+
26
+ namespace margelo::nitro::stroketext {
27
+
28
+ /**
29
+ * An enum which can be represented as a JavaScript union (StrokeTextAlignVertical).
30
+ */
31
+ enum class StrokeTextAlignVertical {
32
+ AUTO SWIFT_NAME(auto) = 0,
33
+ CENTER SWIFT_NAME(center) = 1,
34
+ TOP SWIFT_NAME(top) = 2,
35
+ BOTTOM SWIFT_NAME(bottom) = 3,
36
+ } CLOSED_ENUM;
37
+
38
+ } // namespace margelo::nitro::stroketext
39
+
40
+ namespace margelo::nitro {
41
+
42
+ // C++ StrokeTextAlignVertical <> JS StrokeTextAlignVertical (union)
43
+ template <>
44
+ struct JSIConverter<margelo::nitro::stroketext::StrokeTextAlignVertical> final {
45
+ static inline margelo::nitro::stroketext::StrokeTextAlignVertical fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
46
+ std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, arg);
47
+ switch (hashString(unionValue.c_str(), unionValue.size())) {
48
+ case hashString("auto"): return margelo::nitro::stroketext::StrokeTextAlignVertical::AUTO;
49
+ case hashString("center"): return margelo::nitro::stroketext::StrokeTextAlignVertical::CENTER;
50
+ case hashString("top"): return margelo::nitro::stroketext::StrokeTextAlignVertical::TOP;
51
+ case hashString("bottom"): return margelo::nitro::stroketext::StrokeTextAlignVertical::BOTTOM;
52
+ default: [[unlikely]]
53
+ throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum StrokeTextAlignVertical - invalid value!");
54
+ }
55
+ }
56
+ static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::stroketext::StrokeTextAlignVertical arg) {
57
+ switch (arg) {
58
+ case margelo::nitro::stroketext::StrokeTextAlignVertical::AUTO: return JSIConverter<std::string>::toJSI(runtime, "auto");
59
+ case margelo::nitro::stroketext::StrokeTextAlignVertical::CENTER: return JSIConverter<std::string>::toJSI(runtime, "center");
60
+ case margelo::nitro::stroketext::StrokeTextAlignVertical::TOP: return JSIConverter<std::string>::toJSI(runtime, "top");
61
+ case margelo::nitro::stroketext::StrokeTextAlignVertical::BOTTOM: return JSIConverter<std::string>::toJSI(runtime, "bottom");
62
+ default: [[unlikely]]
63
+ throw std::invalid_argument("Cannot convert StrokeTextAlignVertical to JS - invalid value: "
64
+ + std::to_string(static_cast<int>(arg)) + "!");
65
+ }
66
+ }
67
+ static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
68
+ if (!value.isString()) {
69
+ return false;
70
+ }
71
+ std::string unionValue = JSIConverter<std::string>::fromJSI(runtime, value);
72
+ switch (hashString(unionValue.c_str(), unionValue.size())) {
73
+ case hashString("auto"):
74
+ case hashString("center"):
75
+ case hashString("top"):
76
+ case hashString("bottom"):
77
+ return true;
78
+ default:
79
+ return false;
80
+ }
81
+ }
82
+ };
83
+
84
+ } // namespace margelo::nitro
@@ -136,6 +136,16 @@ namespace margelo::nitro::stroketext::views {
136
136
  throw std::runtime_error(std::string("StrokeTextView.textAlign: ") + exc.what());
137
137
  }
138
138
  }()),
139
+ textAlignVertical([&]() -> CachedProp<std::optional<StrokeTextAlignVertical>> {
140
+ try {
141
+ const react::RawValue* rawValue = rawProps.at("textAlignVertical", nullptr, nullptr);
142
+ if (rawValue == nullptr) return sourceProps.textAlignVertical;
143
+ const auto& [runtime, value] = (std::pair<jsi::Runtime*, jsi::Value>)*rawValue;
144
+ return CachedProp<std::optional<StrokeTextAlignVertical>>::fromRawValue(*runtime, value, sourceProps.textAlignVertical);
145
+ } catch (const std::exception& exc) {
146
+ throw std::runtime_error(std::string("StrokeTextView.textAlignVertical: ") + exc.what());
147
+ }
148
+ }()),
139
149
  textDecorationLine([&]() -> CachedProp<std::optional<StrokeTextDecorationLine>> {
140
150
  try {
141
151
  const react::RawValue* rawValue = rawProps.at("textDecorationLine", nullptr, nullptr);
@@ -310,6 +320,7 @@ namespace margelo::nitro::stroketext::views {
310
320
  lineHeight(other.lineHeight),
311
321
  letterSpacing(other.letterSpacing),
312
322
  textAlign(other.textAlign),
323
+ textAlignVertical(other.textAlignVertical),
313
324
  textDecorationLine(other.textDecorationLine),
314
325
  textTransform(other.textTransform),
315
326
  opacity(other.opacity),
@@ -340,6 +351,7 @@ namespace margelo::nitro::stroketext::views {
340
351
  case hashString("lineHeight"): return true;
341
352
  case hashString("letterSpacing"): return true;
342
353
  case hashString("textAlign"): return true;
354
+ case hashString("textAlignVertical"): return true;
343
355
  case hashString("textDecorationLine"): return true;
344
356
  case hashString("textTransform"): return true;
345
357
  case hashString("opacity"): return true;
@@ -20,6 +20,7 @@
20
20
  #include <optional>
21
21
  #include "StrokeTextFontStyle.hpp"
22
22
  #include "StrokeTextAlign.hpp"
23
+ #include "StrokeTextAlignVertical.hpp"
23
24
  #include "StrokeTextDecorationLine.hpp"
24
25
  #include "StrokeTextTransform.hpp"
25
26
  #include "StrokeTextEllipsizeMode.hpp"
@@ -59,6 +60,7 @@ namespace margelo::nitro::stroketext::views {
59
60
  CachedProp<std::optional<double>> lineHeight;
60
61
  CachedProp<std::optional<double>> letterSpacing;
61
62
  CachedProp<std::optional<StrokeTextAlign>> textAlign;
63
+ CachedProp<std::optional<StrokeTextAlignVertical>> textAlignVertical;
62
64
  CachedProp<std::optional<StrokeTextDecorationLine>> textDecorationLine;
63
65
  CachedProp<std::optional<StrokeTextTransform>> textTransform;
64
66
  CachedProp<std::optional<double>> opacity;
@@ -15,6 +15,7 @@
15
15
  "lineHeight": true,
16
16
  "letterSpacing": true,
17
17
  "textAlign": true,
18
+ "textAlignVertical": true,
18
19
  "textDecorationLine": true,
19
20
  "textTransform": true,
20
21
  "opacity": true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whetware/react-native-stroke-text",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "Stroke/outline text for React Native (New Architecture) on iOS, Android, and Web.",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",