@whetware/react-native-stroke-text 0.0.2 → 0.0.3
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/CHANGELOG.md +6 -0
- package/README.md +6 -0
- package/android/src/main/java/com/margelo/nitro/stroketext/StrokeTextView.kt +1 -1
- package/lib/StrokeText.js +25 -17
- package/lib/StrokeText.web.js +26 -14
- package/package.json +13 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @whetware/react-native-stroke-text
|
|
2
2
|
|
|
3
|
+
## 0.0.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`dd724fd`](https://github.com/whetware/react-native-stroke-text/commit/dd724fd18055ec28e173029a6d3aa0a5744af919) Thanks [@evelant](https://github.com/evelant)! - fix bounding boxes
|
|
8
|
+
|
|
3
9
|
## 0.0.2
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -39,6 +39,12 @@ export function Example() {
|
|
|
39
39
|
}
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
+
## Layout notes
|
|
43
|
+
|
|
44
|
+
To avoid the outline getting clipped during animations (especially on Android), `StrokeText` keeps the
|
|
45
|
+
stroke inside the component bounds by applying an internal inset of `ceil(strokeWidth) / 2`. It then
|
|
46
|
+
uses matching negative margins so the layout footprint matches a normal `<Text />`.
|
|
47
|
+
|
|
42
48
|
## Development
|
|
43
49
|
|
|
44
50
|
- Generate Nitro bindings: `pnpm specs`
|
|
@@ -113,7 +113,7 @@ internal class StrokeTextView(context: ThemedReactContext) : TextView(context) {
|
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
private fun applyProps() {
|
|
116
|
-
// Padding: apply stroke inset
|
|
116
|
+
// Padding: apply a stroke inset so the outline stays within the view bounds.
|
|
117
117
|
val inset = strokeInsetPx()
|
|
118
118
|
val left = floorToInt(resolvePadding(paddingLeftPx, paddingHorizontalPx, paddingAllPx) + inset)
|
|
119
119
|
val top = floorToInt(resolvePadding(paddingTopPx, paddingVerticalPx, paddingAllPx) + inset)
|
package/lib/StrokeText.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { StyleSheet, Text, View } from 'react-native';
|
|
2
|
+
import { I18nManager, 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);
|
|
@@ -63,6 +63,24 @@ export function StrokeText({ text, children, style, hybridRef, ...rest }) {
|
|
|
63
63
|
const baseRight = firstNumber(paddingRight, stylePaddingRight, paddingHorizontal, stylePaddingHorizontal, padding, stylePadding) ?? 0;
|
|
64
64
|
const baseBottom = firstNumber(paddingBottom, stylePaddingBottom, paddingVertical, stylePaddingVertical, padding, stylePadding) ?? 0;
|
|
65
65
|
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
|
+
};
|
|
66
84
|
const effectiveNumberOfLines = nativeProps.numberOfLines != null && nativeProps.numberOfLines > 0
|
|
67
85
|
? nativeProps.numberOfLines
|
|
68
86
|
: undefined;
|
|
@@ -70,31 +88,21 @@ export function StrokeText({ text, children, style, hybridRef, ...rest }) {
|
|
|
70
88
|
? undefined
|
|
71
89
|
: nativeProps.ellipsizeMode ?? 'tail';
|
|
72
90
|
const effectiveIncludeFontPadding = nativeProps.includeFontPadding ?? styleIncludeFontPadding ?? false;
|
|
73
|
-
return (React.createElement(View, { style: [styles.container, containerStyle] },
|
|
91
|
+
return (React.createElement(View, { style: [styles.container, containerStyle, strokeInsetMarginStyle] },
|
|
74
92
|
React.createElement(Text, { accessible: false, pointerEvents: "none", numberOfLines: effectiveNumberOfLines, ellipsizeMode: effectiveEllipsizeMode, allowFontScaling: nativeProps.allowFontScaling, maxFontSizeMultiplier: nativeProps.maxFontSizeMultiplier, style: [
|
|
75
93
|
style,
|
|
76
94
|
{
|
|
77
|
-
paddingTop: baseTop,
|
|
78
|
-
paddingRight: baseRight,
|
|
79
|
-
paddingBottom: baseBottom,
|
|
80
|
-
paddingLeft: baseLeft,
|
|
95
|
+
paddingTop: baseTop + strokeInset,
|
|
96
|
+
paddingRight: baseRight + strokeInset,
|
|
97
|
+
paddingBottom: baseBottom + strokeInset,
|
|
98
|
+
paddingLeft: baseLeft + strokeInset,
|
|
81
99
|
},
|
|
82
100
|
effectiveIncludeFontPadding == null
|
|
83
101
|
? null
|
|
84
102
|
: { includeFontPadding: effectiveIncludeFontPadding },
|
|
85
103
|
styles.hiddenText,
|
|
86
104
|
] }, resolvedText),
|
|
87
|
-
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: hybridRef ? callback(hybridRef) : undefined, pointerEvents: "none", style:
|
|
88
|
-
styles.overlay,
|
|
89
|
-
strokeInset === 0
|
|
90
|
-
? null
|
|
91
|
-
: {
|
|
92
|
-
top: -strokeInset,
|
|
93
|
-
right: -strokeInset,
|
|
94
|
-
bottom: -strokeInset,
|
|
95
|
-
left: -strokeInset,
|
|
96
|
-
},
|
|
97
|
-
] })));
|
|
105
|
+
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: hybridRef ? callback(hybridRef) : undefined, pointerEvents: "none", style: styles.overlay })));
|
|
98
106
|
}
|
|
99
107
|
const styles = StyleSheet.create({
|
|
100
108
|
container: {
|
package/lib/StrokeText.web.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { StyleSheet, Text, View } from 'react-native';
|
|
2
|
+
import { I18nManager, StyleSheet, Text, View } from 'react-native';
|
|
3
3
|
function resolveText(text, children) {
|
|
4
4
|
if (typeof text === 'string')
|
|
5
5
|
return text;
|
|
@@ -38,6 +38,24 @@ 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
|
+
};
|
|
41
59
|
const baseTop = firstNumber(rest.paddingTop, stylePaddingTop, rest.paddingVertical, stylePaddingVertical, rest.padding, stylePadding) ?? 0;
|
|
42
60
|
const baseRight = firstNumber(rest.paddingRight, stylePaddingRight, rest.paddingHorizontal, stylePaddingHorizontal, rest.padding, stylePadding) ?? 0;
|
|
43
61
|
const baseBottom = firstNumber(rest.paddingBottom, stylePaddingBottom, rest.paddingVertical, stylePaddingVertical, rest.padding, stylePadding) ?? 0;
|
|
@@ -46,15 +64,17 @@ export function StrokeText({ text, children, style, ...rest }) {
|
|
|
46
64
|
? rest.numberOfLines
|
|
47
65
|
: undefined;
|
|
48
66
|
const effectiveEllipsizeMode = effectiveNumberOfLines == null ? undefined : rest.ellipsizeMode ?? 'tail';
|
|
49
|
-
return (React.createElement(View, { style: [styles.container, containerStyle] },
|
|
67
|
+
return (React.createElement(View, { style: [styles.container, containerStyle, strokeInsetMarginStyle] },
|
|
50
68
|
React.createElement(Text, { accessible: false, pointerEvents: "none", numberOfLines: effectiveNumberOfLines, ellipsizeMode: effectiveEllipsizeMode, style: [
|
|
51
69
|
textStyle,
|
|
52
70
|
{
|
|
53
|
-
paddingTop: baseTop,
|
|
54
|
-
paddingRight: baseRight,
|
|
55
|
-
paddingBottom: baseBottom,
|
|
56
|
-
paddingLeft: baseLeft,
|
|
71
|
+
paddingTop: baseTop + strokeInset,
|
|
72
|
+
paddingRight: baseRight + strokeInset,
|
|
73
|
+
paddingBottom: baseBottom + strokeInset,
|
|
74
|
+
paddingLeft: baseLeft + strokeInset,
|
|
57
75
|
},
|
|
76
|
+
strokeInset === 0 ? null : { maxWidth: 'none' },
|
|
77
|
+
strokeInset === 0 ? null : { boxSizing: 'content-box' },
|
|
58
78
|
styles.hiddenText,
|
|
59
79
|
] }, resolvedText),
|
|
60
80
|
React.createElement(Text, { pointerEvents: "none", numberOfLines: effectiveNumberOfLines, ellipsizeMode: effectiveEllipsizeMode, style: [
|
|
@@ -83,14 +103,6 @@ export function StrokeText({ text, children, style, ...rest }) {
|
|
|
83
103
|
}
|
|
84
104
|
: null,
|
|
85
105
|
styles.overlay,
|
|
86
|
-
strokeInset === 0
|
|
87
|
-
? null
|
|
88
|
-
: {
|
|
89
|
-
top: -strokeInset,
|
|
90
|
-
right: -strokeInset,
|
|
91
|
-
bottom: -strokeInset,
|
|
92
|
-
left: -strokeInset,
|
|
93
|
-
},
|
|
94
106
|
] }, resolvedText)));
|
|
95
107
|
}
|
|
96
108
|
const styles = StyleSheet.create({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@whetware/react-native-stroke-text",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
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",
|
|
@@ -28,19 +28,6 @@
|
|
|
28
28
|
"CHANGELOG.md",
|
|
29
29
|
"README.md"
|
|
30
30
|
],
|
|
31
|
-
"scripts": {
|
|
32
|
-
"typecheck": "tsc --noEmit",
|
|
33
|
-
"clean": "rm -rf android/build node_modules/**/android/build lib",
|
|
34
|
-
"lint": "eslint \"**/*.{js,ts,tsx}\" --fix",
|
|
35
|
-
"lint-ci": "eslint \"**/*.{js,ts,tsx}\"",
|
|
36
|
-
"typescript": "tsc",
|
|
37
|
-
"prepare": "npm run prepack",
|
|
38
|
-
"prepack": "tsc",
|
|
39
|
-
"changeset": "changeset",
|
|
40
|
-
"version-packages": "changeset version",
|
|
41
|
-
"release": "changeset publish",
|
|
42
|
-
"specs": "tsc --noEmit false && nitrogen --logLevel=\"debug\""
|
|
43
|
-
},
|
|
44
31
|
"keywords": [
|
|
45
32
|
"react-native",
|
|
46
33
|
"nitro",
|
|
@@ -120,5 +107,16 @@
|
|
|
120
107
|
"trailingComma": "es5",
|
|
121
108
|
"useTabs": false,
|
|
122
109
|
"semi": false
|
|
110
|
+
},
|
|
111
|
+
"scripts": {
|
|
112
|
+
"typecheck": "tsc --noEmit",
|
|
113
|
+
"clean": "rm -rf android/build node_modules/**/android/build lib",
|
|
114
|
+
"lint": "eslint \"**/*.{js,ts,tsx}\" --fix",
|
|
115
|
+
"lint-ci": "eslint \"**/*.{js,ts,tsx}\"",
|
|
116
|
+
"typescript": "tsc",
|
|
117
|
+
"changeset": "changeset",
|
|
118
|
+
"version-packages": "changeset version",
|
|
119
|
+
"release": "changeset publish",
|
|
120
|
+
"specs": "tsc --noEmit false && nitrogen --logLevel=\"debug\""
|
|
123
121
|
}
|
|
124
|
-
}
|
|
122
|
+
}
|