@whetware/react-native-stroke-text 0.0.13 → 0.0.16
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
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @whetware/react-native-stroke-text
|
|
2
2
|
|
|
3
|
+
## 0.0.15
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`57b743f`](https://github.com/whetware/react-native-stroke-text/commit/57b743f53c5ef6777be9564d38d2d95c5facb13b) Thanks [@evelant](https://github.com/evelant)! - Keep the native `textTransform` prop concrete during Android measured-line updates so Fabric never sends Nitro a null enum value.
|
|
8
|
+
|
|
3
9
|
## 0.0.13
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/lib/StrokeText.js
CHANGED
|
@@ -2,6 +2,8 @@ import React from 'react';
|
|
|
2
2
|
import { Platform, 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
|
+
import { createNativePropPresenceKey, normalizeNativeOptionalProps, } from './createNativePropPresenceKey';
|
|
6
|
+
import { resolveNativeTextTransform } from './resolveNativeTextTransform';
|
|
5
7
|
const NativeStrokeTextView = getHostComponent('StrokeTextView', () => StrokeTextViewConfig);
|
|
6
8
|
function resolveText(text, children) {
|
|
7
9
|
if (typeof text === 'string')
|
|
@@ -113,7 +115,7 @@ export function StrokeText({ text, children, style, hybridRef, ...rest }) {
|
|
|
113
115
|
const shouldSyncMeasuredLineBreaks = Platform.OS === 'android' && effectiveNumberOfLines == null;
|
|
114
116
|
const [measuredNativeText, setMeasuredNativeText] = React.useState(undefined);
|
|
115
117
|
const nativeText = measuredNativeText ?? resolvedText;
|
|
116
|
-
const nativeTextTransform = measuredNativeText
|
|
118
|
+
const nativeTextTransform = resolveNativeTextTransform(effectiveTextTransform, measuredNativeText != null);
|
|
117
119
|
// RN's hidden Text owns measurement, but Android TextView gets its own layout pass.
|
|
118
120
|
// Compensate for the native stroke inset on every edge, then give that native
|
|
119
121
|
// pass extra right-side room so one-pixel/font-metric drift cannot turn an RN
|
|
@@ -121,6 +123,39 @@ export function StrokeText({ text, children, style, hybridRef, ...rest }) {
|
|
|
121
123
|
const nativeOverlayInset = Platform.OS === 'android' && strokeInset > 0 ? strokeInset : 0;
|
|
122
124
|
const nativeOverlayRightInset = nativeOverlayInset > 0 ? nativeOverlayInset * 2 : 0;
|
|
123
125
|
const wrappedHybridRef = React.useMemo(() => (hybridRef ? callback(hybridRef) : undefined), [hybridRef]);
|
|
126
|
+
const nativeOptionalProps = normalizeNativeOptionalProps({
|
|
127
|
+
color: effectiveColor,
|
|
128
|
+
strokeColor: nativeProps.strokeColor,
|
|
129
|
+
strokeWidth,
|
|
130
|
+
fontSize: effectiveFontSize,
|
|
131
|
+
fontWeight: effectiveFontWeight,
|
|
132
|
+
fontFamily: effectiveFontFamily,
|
|
133
|
+
fontStyle: effectiveFontStyle,
|
|
134
|
+
lineHeight: effectiveLineHeight,
|
|
135
|
+
letterSpacing: effectiveLetterSpacing,
|
|
136
|
+
textAlign: effectiveTextAlign,
|
|
137
|
+
textAlignVertical: effectiveTextAlignVertical,
|
|
138
|
+
textDecorationLine: effectiveTextDecorationLine,
|
|
139
|
+
textTransform: nativeTextTransform,
|
|
140
|
+
opacity: nativeProps.opacity ?? toNumber(styleOpacity),
|
|
141
|
+
allowFontScaling: nativeProps.allowFontScaling,
|
|
142
|
+
maxFontSizeMultiplier: nativeProps.maxFontSizeMultiplier,
|
|
143
|
+
includeFontPadding: effectiveIncludeFontPadding,
|
|
144
|
+
numberOfLines: effectiveNumberOfLines ?? 0,
|
|
145
|
+
ellipsizeMode: effectiveEllipsizeMode ?? 'tail',
|
|
146
|
+
padding: undefined,
|
|
147
|
+
paddingVertical: undefined,
|
|
148
|
+
paddingHorizontal: undefined,
|
|
149
|
+
paddingTop: baseTop,
|
|
150
|
+
paddingRight: baseRight,
|
|
151
|
+
paddingBottom: baseBottom,
|
|
152
|
+
paddingLeft: baseLeft,
|
|
153
|
+
hybridRef: wrappedHybridRef,
|
|
154
|
+
});
|
|
155
|
+
// Fabric encodes a removed view prop as null, but Nitro 0.36's optional
|
|
156
|
+
// converter accepts only undefined. Remount the native host when any optional
|
|
157
|
+
// prop changes definedness so Fabric never sends a value-to-null update.
|
|
158
|
+
const nativePropPresenceKey = createNativePropPresenceKey(nativeOptionalProps);
|
|
124
159
|
React.useEffect(() => {
|
|
125
160
|
setMeasuredNativeText(undefined);
|
|
126
161
|
}, [
|
|
@@ -200,7 +235,7 @@ export function StrokeText({ text, children, style, hybridRef, ...rest }) {
|
|
|
200
235
|
},
|
|
201
236
|
styles.hiddenText,
|
|
202
237
|
] }, resolvedText),
|
|
203
|
-
React.createElement(NativeStrokeTextView, {
|
|
238
|
+
React.createElement(NativeStrokeTextView, { key: nativePropPresenceKey, text: nativeText, ...nativeOptionalProps, pointerEvents: "none", style: [
|
|
204
239
|
styles.overlay,
|
|
205
240
|
nativeOverlayInset > 0
|
|
206
241
|
? {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function normalizeNativeOptionalProps(props) {
|
|
2
|
+
return Object.fromEntries(Object.entries(props).map(([propName, value]) => [
|
|
3
|
+
propName,
|
|
4
|
+
value ?? undefined,
|
|
5
|
+
]));
|
|
6
|
+
}
|
|
7
|
+
export function createNativePropPresenceKey(props) {
|
|
8
|
+
return Object.keys(props)
|
|
9
|
+
.sort()
|
|
10
|
+
.map((propName) => (props[propName] == null ? '0' : '1'))
|
|
11
|
+
.join('');
|
|
12
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { StrokeTextTransform } from './specs/StrokeTextView.nitro';
|
|
2
|
+
/**
|
|
3
|
+
* Keep the Fabric host prop concrete across text-measurement state changes.
|
|
4
|
+
* React Native represents a removed prop as null during native updates, while
|
|
5
|
+
* Nitro's optional enum converter accepts undefined but rejects null.
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolveNativeTextTransform(effectiveTextTransform: StrokeTextTransform | undefined, hasMeasuredNativeText: boolean): StrokeTextTransform;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keep the Fabric host prop concrete across text-measurement state changes.
|
|
3
|
+
* React Native represents a removed prop as null during native updates, while
|
|
4
|
+
* Nitro's optional enum converter accepts undefined but rejects null.
|
|
5
|
+
*/
|
|
6
|
+
export function resolveNativeTextTransform(effectiveTextTransform, hasMeasuredNativeText) {
|
|
7
|
+
return hasMeasuredNativeText ? 'none' : (effectiveTextTransform ?? 'none');
|
|
8
|
+
}
|
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.16",
|
|
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",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"clean": "rm -rf android/build node_modules/**/android/build lib",
|
|
34
34
|
"lint": "eslint \"**/*.{js,ts,tsx}\" --fix",
|
|
35
35
|
"lint-ci": "eslint \"**/*.{js,ts,tsx}\"",
|
|
36
|
+
"test": "tsc && node --test test/*.test.mjs",
|
|
36
37
|
"typescript": "tsc",
|
|
37
38
|
"prepare": "npm run prepack",
|
|
38
39
|
"prepack": "tsc",
|
|
@@ -121,4 +122,4 @@
|
|
|
121
122
|
"useTabs": false,
|
|
122
123
|
"semi": false
|
|
123
124
|
}
|
|
124
|
-
}
|
|
125
|
+
}
|