@onekeyfe/react-native-text 3.0.108

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 (35) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +17 -0
  3. package/android/build.gradle +109 -0
  4. package/android/gradle.properties +5 -0
  5. package/android/src/main/AndroidManifest.xml +3 -0
  6. package/android/src/main/AndroidManifestNew.xml +2 -0
  7. package/android/src/main/java/com/onekey/text/OneKeyTextPackage.kt +21 -0
  8. package/android/src/main/java/com/onekey/text/OneKeyTextView.kt +6 -0
  9. package/android/src/main/java/com/onekey/text/OneKeyTextViewManager.kt +34 -0
  10. package/android/src/main/jni/CMakeLists.txt +31 -0
  11. package/android/src/main/jni/react/renderer/components/RNOneKeyTextSpec/ComponentDescriptors.h +45 -0
  12. package/lib/module/OneKeyTextNativeComponent.ts +100 -0
  13. package/lib/module/OneKeyTextNativeHost.js +35 -0
  14. package/lib/module/Text.android.js +335 -0
  15. package/lib/module/Text.js +5 -0
  16. package/lib/module/codegen-types.d.js +2 -0
  17. package/lib/module/index.js +5 -0
  18. package/lib/module/package.json +1 -0
  19. package/lib/module/types.js +4 -0
  20. package/lib/typescript/package.json +1 -0
  21. package/lib/typescript/src/OneKeyTextNativeComponent.d.ts +47 -0
  22. package/lib/typescript/src/OneKeyTextNativeHost.d.ts +32 -0
  23. package/lib/typescript/src/Text.android.d.ts +79 -0
  24. package/lib/typescript/src/Text.d.ts +6 -0
  25. package/lib/typescript/src/index.d.ts +4 -0
  26. package/lib/typescript/src/types.d.ts +3 -0
  27. package/package.json +118 -0
  28. package/react-native.config.js +13 -0
  29. package/src/OneKeyTextNativeComponent.ts +100 -0
  30. package/src/OneKeyTextNativeHost.ts +40 -0
  31. package/src/Text.android.tsx +475 -0
  32. package/src/Text.tsx +3 -0
  33. package/src/codegen-types.d.ts +39 -0
  34. package/src/index.ts +4 -0
  35. package/src/types.ts +3 -0
@@ -0,0 +1,475 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * Adapted for the OneKey Android native Text component.
8
+ */
9
+
10
+ /* eslint-disable @react-native/no-deep-imports */
11
+ import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags';
12
+ import * as PressabilityDebug from 'react-native/Libraries/Pressability/PressabilityDebug';
13
+ import {
14
+ Platform,
15
+ StyleSheet,
16
+ Text as ReactNativeText,
17
+ processColor,
18
+ unstable_TextAncestorContext as TextAncestorContext,
19
+ usePressability,
20
+ type GestureResponderEvent,
21
+ type HostInstance,
22
+ type TextStyle,
23
+ } from 'react-native';
24
+ import { forwardRef, useContext, useMemo, useState, type Ref } from 'react';
25
+
26
+ import OneKeyTextNativeComponent from './OneKeyTextNativeHost';
27
+ import type { NativeProps } from './OneKeyTextNativeComponent';
28
+ import type { TextProps } from './types';
29
+
30
+ type TextForwardRef = HostInstance;
31
+
32
+ type TextPressabilityProps = Readonly<{
33
+ onLongPress?: (event: GestureResponderEvent) => unknown;
34
+ onPress?: (event: GestureResponderEvent) => unknown;
35
+ onPressIn?: (event: GestureResponderEvent) => unknown;
36
+ onPressOut?: (event: GestureResponderEvent) => unknown;
37
+ onResponderGrant?: (event: GestureResponderEvent) => void;
38
+ onResponderMove?: (event: GestureResponderEvent) => void;
39
+ onResponderRelease?: (event: GestureResponderEvent) => void;
40
+ onResponderTerminate?: (event: GestureResponderEvent) => void;
41
+ onResponderTerminationRequest?: () => boolean;
42
+ onStartShouldSetResponder?: () => boolean;
43
+ pressRetentionOffset?: TextProps['pressRetentionOffset'];
44
+ suppressHighlighting?: boolean;
45
+ }>;
46
+
47
+ type Mutable<T> = {
48
+ -readonly [Property in keyof T]: T[Property];
49
+ };
50
+
51
+ type NativeTextProps = Mutable<TextProps> &
52
+ Readonly<{
53
+ isHighlighted?: boolean;
54
+ isPressable?: boolean;
55
+ onClick?: (event: GestureResponderEvent) => unknown;
56
+ }>;
57
+
58
+ function useTextPressability({
59
+ onLongPress,
60
+ onPress,
61
+ onPressIn,
62
+ onPressOut,
63
+ onResponderGrant,
64
+ onResponderMove,
65
+ onResponderRelease,
66
+ onResponderTerminate,
67
+ onResponderTerminationRequest,
68
+ onStartShouldSetResponder,
69
+ pressRetentionOffset,
70
+ suppressHighlighting,
71
+ }: TextPressabilityProps) {
72
+ const [isHighlighted, setHighlighted] = useState(false);
73
+
74
+ const config = useMemo(() => {
75
+ let processedOnPressIn = onPressIn;
76
+ let processedOnPressOut = onPressOut;
77
+
78
+ if (Platform.OS === 'ios') {
79
+ processedOnPressIn = (event: GestureResponderEvent) => {
80
+ setHighlighted(suppressHighlighting == null || !suppressHighlighting);
81
+ onPressIn?.(event);
82
+ };
83
+
84
+ processedOnPressOut = (event: GestureResponderEvent) => {
85
+ setHighlighted(false);
86
+ onPressOut?.(event);
87
+ };
88
+ }
89
+
90
+ return {
91
+ disabled: false,
92
+ pressRectOffset: pressRetentionOffset,
93
+ onLongPress,
94
+ onPress,
95
+ onPressIn: processedOnPressIn,
96
+ onPressOut: processedOnPressOut,
97
+ };
98
+ }, [
99
+ onLongPress,
100
+ onPress,
101
+ onPressIn,
102
+ onPressOut,
103
+ pressRetentionOffset,
104
+ suppressHighlighting,
105
+ ]);
106
+
107
+ const eventHandlers = usePressability(config);
108
+
109
+ const eventHandlersForText = useMemo(
110
+ () =>
111
+ eventHandlers == null
112
+ ? null
113
+ : {
114
+ onResponderGrant(event: GestureResponderEvent) {
115
+ eventHandlers.onResponderGrant(event);
116
+ onResponderGrant?.(event);
117
+ },
118
+ onResponderMove(event: GestureResponderEvent) {
119
+ eventHandlers.onResponderMove(event);
120
+ onResponderMove?.(event);
121
+ },
122
+ onResponderRelease(event: GestureResponderEvent) {
123
+ eventHandlers.onResponderRelease(event);
124
+ onResponderRelease?.(event);
125
+ },
126
+ onResponderTerminate(event: GestureResponderEvent) {
127
+ eventHandlers.onResponderTerminate(event);
128
+ onResponderTerminate?.(event);
129
+ },
130
+ onClick: eventHandlers.onClick,
131
+ onResponderTerminationRequest:
132
+ onResponderTerminationRequest ??
133
+ eventHandlers.onResponderTerminationRequest,
134
+ onStartShouldSetResponder:
135
+ onStartShouldSetResponder ??
136
+ eventHandlers.onStartShouldSetResponder,
137
+ },
138
+ [
139
+ eventHandlers,
140
+ onResponderGrant,
141
+ onResponderMove,
142
+ onResponderRelease,
143
+ onResponderTerminate,
144
+ onResponderTerminationRequest,
145
+ onStartShouldSetResponder,
146
+ ]
147
+ );
148
+
149
+ return useMemo(
150
+ () => [isHighlighted, eventHandlersForText] as const,
151
+ [isHighlighted, eventHandlersForText]
152
+ );
153
+ }
154
+
155
+ type PressableTextProps = Readonly<{
156
+ textPressabilityProps: TextPressabilityProps;
157
+ textProps: NativeTextProps;
158
+ }>;
159
+
160
+ const PressableText = forwardRef<TextForwardRef, PressableTextProps>(
161
+ function PressableText(
162
+ { textPressabilityProps, textProps },
163
+ ref: Ref<TextForwardRef>
164
+ ) {
165
+ const [isHighlighted, eventHandlersForText] = useTextPressability(
166
+ textPressabilityProps
167
+ );
168
+
169
+ return (
170
+ <OneKeyTextNativeComponent
171
+ {...(textProps as NativeProps)}
172
+ {...eventHandlersForText}
173
+ isHighlighted={isHighlighted}
174
+ isPressable
175
+ ref={ref}
176
+ />
177
+ );
178
+ }
179
+ );
180
+
181
+ function TextImpl(
182
+ {
183
+ accessible,
184
+ accessibilityLabel,
185
+ accessibilityRole,
186
+ accessibilityState,
187
+ allowFontScaling,
188
+ 'aria-busy': ariaBusy,
189
+ 'aria-checked': ariaChecked,
190
+ 'aria-disabled': ariaDisabled,
191
+ 'aria-expanded': ariaExpanded,
192
+ 'aria-hidden': ariaHidden,
193
+ 'aria-label': ariaLabel,
194
+ 'aria-selected': ariaSelected,
195
+ children,
196
+ ellipsizeMode,
197
+ disabled,
198
+ id,
199
+ nativeID,
200
+ numberOfLines,
201
+ onLongPress,
202
+ onPress,
203
+ onPressIn,
204
+ onPressOut,
205
+ onResponderGrant,
206
+ onResponderMove,
207
+ onResponderRelease,
208
+ onResponderTerminate,
209
+ onResponderTerminationRequest,
210
+ onStartShouldSetResponder,
211
+ pressRetentionOffset,
212
+ role,
213
+ selectable,
214
+ selectionColor,
215
+ suppressHighlighting,
216
+ style,
217
+ ...restProps
218
+ }: TextProps,
219
+ forwardedRef: Ref<TextForwardRef>
220
+ ) {
221
+ const hasTextAncestor = useContext(TextAncestorContext);
222
+ if (hasTextAncestor) {
223
+ return (
224
+ <ReactNativeText
225
+ {...{
226
+ accessible,
227
+ accessibilityLabel,
228
+ accessibilityRole,
229
+ accessibilityState,
230
+ allowFontScaling,
231
+ 'aria-busy': ariaBusy,
232
+ 'aria-checked': ariaChecked,
233
+ 'aria-disabled': ariaDisabled,
234
+ 'aria-expanded': ariaExpanded,
235
+ 'aria-hidden': ariaHidden,
236
+ 'aria-label': ariaLabel,
237
+ 'aria-selected': ariaSelected,
238
+ children,
239
+ disabled,
240
+ ellipsizeMode,
241
+ id,
242
+ nativeID,
243
+ numberOfLines,
244
+ onLongPress,
245
+ onPress,
246
+ onPressIn,
247
+ onPressOut,
248
+ onResponderGrant,
249
+ onResponderMove,
250
+ onResponderRelease,
251
+ onResponderTerminate,
252
+ onResponderTerminationRequest,
253
+ onStartShouldSetResponder,
254
+ pressRetentionOffset,
255
+ role,
256
+ selectable,
257
+ selectionColor,
258
+ style,
259
+ suppressHighlighting,
260
+ ...restProps,
261
+ }}
262
+ ref={forwardedRef}
263
+ />
264
+ );
265
+ }
266
+
267
+ const processedProps = { ...restProps } as NativeTextProps;
268
+ const processedAccessibilityLabel = ariaLabel ?? accessibilityLabel;
269
+ let processedAccessibilityState = accessibilityState;
270
+
271
+ if (
272
+ ariaBusy != null ||
273
+ ariaChecked != null ||
274
+ ariaDisabled != null ||
275
+ ariaExpanded != null ||
276
+ ariaSelected != null
277
+ ) {
278
+ processedAccessibilityState = {
279
+ busy: ariaBusy ?? accessibilityState?.busy,
280
+ checked: ariaChecked ?? accessibilityState?.checked,
281
+ disabled: ariaDisabled ?? accessibilityState?.disabled,
282
+ expanded: ariaExpanded ?? accessibilityState?.expanded,
283
+ selected: ariaSelected ?? accessibilityState?.selected,
284
+ };
285
+ }
286
+
287
+ const accessibilityStateDisabled = processedAccessibilityState?.disabled;
288
+ const processedDisabled = disabled ?? accessibilityStateDisabled;
289
+
290
+ if (
291
+ processedDisabled !== accessibilityStateDisabled &&
292
+ ((processedDisabled != null && processedDisabled !== false) ||
293
+ (accessibilityStateDisabled != null &&
294
+ accessibilityStateDisabled !== false))
295
+ ) {
296
+ processedAccessibilityState = {
297
+ ...processedAccessibilityState,
298
+ disabled: processedDisabled,
299
+ };
300
+ }
301
+
302
+ if (ariaHidden !== undefined) {
303
+ processedProps.accessibilityElementsHidden = ariaHidden;
304
+ if (ariaHidden) {
305
+ processedProps.importantForAccessibility = 'no-hide-descendants';
306
+ }
307
+ }
308
+
309
+ const processedAccessible =
310
+ accessible == null ? onPress != null || onLongPress != null : accessible;
311
+ const isPressable =
312
+ (onPress != null ||
313
+ onLongPress != null ||
314
+ onStartShouldSetResponder != null) &&
315
+ processedDisabled !== true;
316
+ const shouldUseLinkRole =
317
+ isPressable && accessibilityRole == null && role == null;
318
+ const processedAccessibilityRole =
319
+ accessibilityRole ?? (shouldUseLinkRole ? 'link' : undefined);
320
+ const processedRole = shouldUseLinkRole ? undefined : role;
321
+ const processedSelectionColor =
322
+ selectionColor != null ? processColor(selectionColor) : undefined;
323
+
324
+ let processedStyle = style;
325
+ if (__DEV__ && PressabilityDebug.isEnabled() && onPress != null) {
326
+ processedStyle = [style, { color: 'magenta' }];
327
+ }
328
+
329
+ let processedNumberOfLines = numberOfLines;
330
+ if (processedNumberOfLines != null && !(processedNumberOfLines >= 0)) {
331
+ if (__DEV__) {
332
+ console.error(
333
+ `'numberOfLines' in <Text> must be a non-negative number, received: ${processedNumberOfLines}. The value will be set to 0.`
334
+ );
335
+ }
336
+ processedNumberOfLines = 0;
337
+ }
338
+
339
+ let processedSelectable = selectable;
340
+ const flattenedStyle = StyleSheet.flatten(processedStyle);
341
+ if (flattenedStyle != null) {
342
+ let overrides: TextStyle | undefined;
343
+ if (typeof flattenedStyle.fontWeight === 'number') {
344
+ overrides = {
345
+ ...overrides,
346
+ fontWeight: String(
347
+ flattenedStyle.fontWeight
348
+ ) as TextStyle['fontWeight'],
349
+ };
350
+ }
351
+
352
+ if (flattenedStyle.userSelect != null) {
353
+ processedSelectable =
354
+ userSelectToSelectableMap[flattenedStyle.userSelect];
355
+ overrides = { ...overrides, userSelect: undefined };
356
+ }
357
+
358
+ if (flattenedStyle.verticalAlign != null) {
359
+ overrides = {
360
+ ...overrides,
361
+ textAlignVertical:
362
+ verticalAlignToTextAlignVerticalMap[flattenedStyle.verticalAlign],
363
+ verticalAlign: undefined,
364
+ };
365
+ }
366
+
367
+ if (overrides != null) {
368
+ processedStyle = [processedStyle, overrides];
369
+ }
370
+ }
371
+
372
+ if (ReactNativeFeatureFlags.defaultTextToOverflowHidden()) {
373
+ processedStyle = [styles.default, processedStyle];
374
+ }
375
+
376
+ const processedNativeID = id ?? nativeID;
377
+
378
+ if (processedAccessibilityLabel !== undefined) {
379
+ processedProps.accessibilityLabel = processedAccessibilityLabel;
380
+ }
381
+ if (processedAccessibilityRole !== undefined) {
382
+ processedProps.accessibilityRole = processedAccessibilityRole;
383
+ }
384
+ if (processedAccessibilityState !== undefined) {
385
+ processedProps.accessibilityState = processedAccessibilityState;
386
+ }
387
+ if (processedNativeID !== undefined) {
388
+ processedProps.nativeID = processedNativeID;
389
+ }
390
+ if (processedNumberOfLines !== undefined) {
391
+ processedProps.numberOfLines = processedNumberOfLines;
392
+ }
393
+ if (processedSelectable !== undefined) {
394
+ processedProps.selectable = processedSelectable;
395
+ }
396
+ if (processedStyle !== undefined) {
397
+ processedProps.style = processedStyle;
398
+ }
399
+ if (processedSelectionColor !== undefined) {
400
+ processedProps.selectionColor = processedSelectionColor;
401
+ }
402
+ if (processedRole !== undefined) {
403
+ processedProps.role = processedRole;
404
+ }
405
+
406
+ processedProps.accessible = processedAccessible;
407
+ processedProps.allowFontScaling = allowFontScaling !== false;
408
+ processedProps.disabled = processedDisabled;
409
+ processedProps.ellipsizeMode = ellipsizeMode ?? 'tail';
410
+ processedProps.children =
411
+ children == null ? (
412
+ children
413
+ ) : (
414
+ <TextAncestorContext.Provider value>
415
+ <ReactNativeText>{children}</ReactNativeText>
416
+ </TextAncestorContext.Provider>
417
+ );
418
+
419
+ let nativeText;
420
+ if (isPressable) {
421
+ nativeText = (
422
+ <PressableText
423
+ ref={forwardedRef}
424
+ textProps={processedProps}
425
+ textPressabilityProps={{
426
+ onLongPress,
427
+ onPress,
428
+ onPressIn,
429
+ onPressOut,
430
+ onResponderGrant,
431
+ onResponderMove,
432
+ onResponderRelease,
433
+ onResponderTerminate,
434
+ onResponderTerminationRequest,
435
+ onStartShouldSetResponder,
436
+ pressRetentionOffset,
437
+ suppressHighlighting,
438
+ }}
439
+ />
440
+ );
441
+ } else {
442
+ nativeText = (
443
+ <OneKeyTextNativeComponent
444
+ {...(processedProps as NativeProps)}
445
+ ref={forwardedRef}
446
+ />
447
+ );
448
+ }
449
+
450
+ return nativeText;
451
+ }
452
+
453
+ export const Text = forwardRef<TextForwardRef, TextProps>(TextImpl);
454
+ Text.displayName = 'Text';
455
+
456
+ const userSelectToSelectableMap = {
457
+ all: true,
458
+ auto: true,
459
+ contain: true,
460
+ none: false,
461
+ text: true,
462
+ } as const;
463
+
464
+ const verticalAlignToTextAlignVerticalMap = {
465
+ auto: 'auto',
466
+ bottom: 'bottom',
467
+ middle: 'center',
468
+ top: 'top',
469
+ } as const;
470
+
471
+ const styles = StyleSheet.create({
472
+ default: {
473
+ overflow: 'hidden',
474
+ },
475
+ });
package/src/Text.tsx ADDED
@@ -0,0 +1,3 @@
1
+ import { Text as ReactNativeText } from 'react-native';
2
+
3
+ export const Text = ReactNativeText;
@@ -0,0 +1,39 @@
1
+ declare module 'react-native/Libraries/Types/CodegenTypes' {
2
+ import type { NativeSyntheticEvent } from 'react-native';
3
+
4
+ export type DirectEventHandler<T> = (
5
+ event: NativeSyntheticEvent<T>
6
+ ) => void | Promise<void>;
7
+ export type Float = number;
8
+ export type Int32 = number;
9
+ export type WithDefault<T, V extends T> = V extends T ? T : never;
10
+ }
11
+
12
+ declare module 'react-native/Libraries/Pressability/PressabilityDebug' {
13
+ export function isEnabled(): boolean;
14
+ }
15
+
16
+ declare module 'react-native/src/private/featureflags/ReactNativeFeatureFlags' {
17
+ export function defaultTextToOverflowHidden(): boolean;
18
+ }
19
+
20
+ declare module 'react-native/Libraries/NativeComponent/ViewConfig' {
21
+ export type PartialViewConfig = Readonly<{
22
+ directEventTypes?: Readonly<Record<string, unknown>>;
23
+ uiViewClassName: string;
24
+ validAttributes?: Readonly<Record<string, unknown>>;
25
+ }>;
26
+
27
+ export type ViewConfig = Readonly<Record<string, unknown>>;
28
+
29
+ export function createViewConfig(config: PartialViewConfig): ViewConfig;
30
+ }
31
+
32
+ declare module 'react-native/Libraries/Renderer/shims/createReactNativeComponentClass' {
33
+ import type { ViewConfig } from 'react-native/Libraries/NativeComponent/ViewConfig';
34
+
35
+ export default function createReactNativeComponentClass(
36
+ name: string,
37
+ callback: () => ViewConfig
38
+ ): unknown;
39
+ }
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export { Text } from './Text';
2
+ export type { TextProps } from './types';
3
+
4
+ export { Text as default } from './Text';
package/src/types.ts ADDED
@@ -0,0 +1,3 @@
1
+ import type { TextProps as ReactNativeTextProps } from 'react-native';
2
+
3
+ export type TextProps = ReactNativeTextProps;