react-native-transformer-text-input 0.1.0-alpha.0
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/LICENSE +20 -0
- package/README.md +141 -0
- package/RNTransformerTextInput.podspec +35 -0
- package/android/build.gradle +96 -0
- package/android/gradle.properties +5 -0
- package/android/spotless.gradle +19 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/appandflow/transformertextinput/TextState.kt +15 -0
- package/android/src/main/java/com/appandflow/transformertextinput/TransformerTextInputDecoratorView.kt +160 -0
- package/android/src/main/java/com/appandflow/transformertextinput/TransformerTextInputDecoratorViewManager.kt +44 -0
- package/android/src/main/java/com/appandflow/transformertextinput/TransformerTextInputJni.kt +25 -0
- package/android/src/main/java/com/appandflow/transformertextinput/TransformerTextInputModule.kt +22 -0
- package/android/src/main/java/com/appandflow/transformertextinput/TransformerTextInputPackage.kt +53 -0
- package/android/src/main/jni/CMakeLists.txt +62 -0
- package/android/src/main/jni/TransformerTextInputJni.cpp +94 -0
- package/android/src/main/jni/rntti.h +17 -0
- package/cpp/TransformerTextInputDecoratorViewComponentDescriptor.h +16 -0
- package/cpp/TransformerTextInputDecoratorViewShadowNode.cpp +21 -0
- package/cpp/TransformerTextInputDecoratorViewShadowNode.h +40 -0
- package/cpp/TransformerTextInputRuntime.cpp +86 -0
- package/cpp/TransformerTextInputRuntime.h +31 -0
- package/ios/TransformerTextInputDecoratorView.h +9 -0
- package/ios/TransformerTextInputDecoratorView.mm +256 -0
- package/ios/TransformerTextInputModule.h +8 -0
- package/ios/TransformerTextInputModule.mm +28 -0
- package/lib/module/NativeTransformerTextInputModule.js +5 -0
- package/lib/module/NativeTransformerTextInputModule.js.map +1 -0
- package/lib/module/Transformer.js +15 -0
- package/lib/module/Transformer.js.map +1 -0
- package/lib/module/TransformerTextInput.js +86 -0
- package/lib/module/TransformerTextInput.js.map +1 -0
- package/lib/module/TransformerTextInputDecoratorViewNativeComponent.ts +31 -0
- package/lib/module/formatters/phone-number.js +315 -0
- package/lib/module/formatters/phone-number.js.map +1 -0
- package/lib/module/index.js +5 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/registry.js +83 -0
- package/lib/module/registry.js.map +1 -0
- package/lib/module/selection.js +48 -0
- package/lib/module/selection.js.map +1 -0
- package/lib/module/utils/useMergeRefs.js +49 -0
- package/lib/module/utils/useMergeRefs.js.map +1 -0
- package/lib/module/utils/useRefEffect.js +37 -0
- package/lib/module/utils/useRefEffect.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/NativeTransformerTextInputModule.d.ts +7 -0
- package/lib/typescript/src/NativeTransformerTextInputModule.d.ts.map +1 -0
- package/lib/typescript/src/Transformer.d.ts +19 -0
- package/lib/typescript/src/Transformer.d.ts.map +1 -0
- package/lib/typescript/src/TransformerTextInput.d.ts +247 -0
- package/lib/typescript/src/TransformerTextInput.d.ts.map +1 -0
- package/lib/typescript/src/TransformerTextInputDecoratorViewNativeComponent.d.ts +12 -0
- package/lib/typescript/src/TransformerTextInputDecoratorViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/formatters/phone-number.d.ts +18 -0
- package/lib/typescript/src/formatters/phone-number.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +3 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/registry.d.ts +17 -0
- package/lib/typescript/src/registry.d.ts.map +1 -0
- package/lib/typescript/src/selection.d.ts +4 -0
- package/lib/typescript/src/selection.d.ts.map +1 -0
- package/lib/typescript/src/utils/useMergeRefs.d.ts +20 -0
- package/lib/typescript/src/utils/useMergeRefs.d.ts.map +1 -0
- package/lib/typescript/src/utils/useRefEffect.d.ts +24 -0
- package/lib/typescript/src/utils/useRefEffect.d.ts.map +1 -0
- package/package.json +199 -0
- package/react-native.config.js +13 -0
- package/src/NativeTransformerTextInputModule.ts +10 -0
- package/src/Transformer.ts +32 -0
- package/src/TransformerTextInput.tsx +147 -0
- package/src/TransformerTextInputDecoratorViewNativeComponent.ts +31 -0
- package/src/formatters/phone-number.ts +327 -0
- package/src/index.tsx +10 -0
- package/src/registry.ts +120 -0
- package/src/selection.ts +62 -0
- package/src/utils/useMergeRefs.ts +59 -0
- package/src/utils/useRefEffect.ts +42 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
export class Transformer {
|
|
4
|
+
constructor(worklet) {
|
|
5
|
+
const workletHash = worklet.__workletHash;
|
|
6
|
+
if (workletHash == null) {
|
|
7
|
+
throw new Error('[rntti] Transformer must be a worklet. Did you forget to add the "worklet" directive?');
|
|
8
|
+
}
|
|
9
|
+
this._worklet = worklet;
|
|
10
|
+
}
|
|
11
|
+
get worklet() {
|
|
12
|
+
return this._worklet;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=Transformer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["Transformer","constructor","worklet","workletHash","__workletHash","Error","_worklet"],"sourceRoot":"../../src","sources":["Transformer.ts"],"mappings":";;AAeA,OAAO,MAAMA,WAAW,CAAC;EAGvBC,WAAWA,CAACC,OAA2B,EAAE;IACvC,MAAMC,WAAW,GAAID,OAAO,CAAgCE,aAAa;IACzE,IAAID,WAAW,IAAI,IAAI,EAAE;MACvB,MAAM,IAAIE,KAAK,CACb,uFACF,CAAC;IACH;IACA,IAAI,CAACC,QAAQ,GAAGJ,OAAO;EACzB;EAEA,IAAIA,OAAOA,CAAA,EAAG;IACZ,OAAO,IAAI,CAACI,QAAQ;EACtB;AACF","ignoreList":[]}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { forwardRef, useCallback, useEffect, useMemo, useRef } from 'react';
|
|
4
|
+
import { StyleSheet, TextInput } from 'react-native';
|
|
5
|
+
import TransformerTextInputDecoratorViewNativeComponent, { Commands } from './TransformerTextInputDecoratorViewNativeComponent';
|
|
6
|
+
import { registerTransformer, unregisterTransformer } from "./registry.js";
|
|
7
|
+
import useMergeRefs from "./utils/useMergeRefs.js";
|
|
8
|
+
import { validateSelection } from "./selection.js";
|
|
9
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
10
|
+
export const TransformerTextInput = /*#__PURE__*/forwardRef(({
|
|
11
|
+
transformer,
|
|
12
|
+
onChangeText,
|
|
13
|
+
...others
|
|
14
|
+
}, forwardedRef) => {
|
|
15
|
+
const transformerId = useMemo(() => {
|
|
16
|
+
return registerTransformer(transformer);
|
|
17
|
+
}, [transformer]);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
return () => {
|
|
20
|
+
unregisterTransformer(transformerId);
|
|
21
|
+
};
|
|
22
|
+
}, [transformerId]);
|
|
23
|
+
const decoratorRef = useRef(null);
|
|
24
|
+
const textRef = useRef('');
|
|
25
|
+
const setInputRef = useCallback(instance => {
|
|
26
|
+
if (instance != null) {
|
|
27
|
+
Object.assign(instance, {
|
|
28
|
+
getValue() {
|
|
29
|
+
return textRef.current;
|
|
30
|
+
},
|
|
31
|
+
update({
|
|
32
|
+
value,
|
|
33
|
+
selection,
|
|
34
|
+
transform
|
|
35
|
+
}) {
|
|
36
|
+
const nativeRef = decoratorRef.current;
|
|
37
|
+
if (!nativeRef) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
let newSelection;
|
|
41
|
+
const newValue = value ?? textRef.current;
|
|
42
|
+
if (selection != null) {
|
|
43
|
+
validateSelection(selection, newValue.length);
|
|
44
|
+
newSelection = selection;
|
|
45
|
+
} else {
|
|
46
|
+
// When changing value without selection, move cursor to end.
|
|
47
|
+
newSelection = {
|
|
48
|
+
start: newValue.length,
|
|
49
|
+
end: newValue.length
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
Commands.update(nativeRef, transform ?? true, value ?? null, newSelection.start, newSelection.end);
|
|
53
|
+
},
|
|
54
|
+
clear() {
|
|
55
|
+
this.update({
|
|
56
|
+
value: '',
|
|
57
|
+
transform: false
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}, []);
|
|
63
|
+
const inputRef = useMergeRefs(setInputRef, forwardedRef);
|
|
64
|
+
const handleChangeText = useCallback(text => {
|
|
65
|
+
textRef.current = text;
|
|
66
|
+
onChangeText?.(text);
|
|
67
|
+
}, [onChangeText]);
|
|
68
|
+
return /*#__PURE__*/_jsx(TransformerTextInputDecoratorViewNativeComponent, {
|
|
69
|
+
ref: decoratorRef,
|
|
70
|
+
style: styles.decorator,
|
|
71
|
+
transformerId: transformerId,
|
|
72
|
+
children: /*#__PURE__*/_jsx(TextInput
|
|
73
|
+
// @ts-expect-error
|
|
74
|
+
, {
|
|
75
|
+
ref: inputRef,
|
|
76
|
+
onChangeText: handleChangeText,
|
|
77
|
+
...others
|
|
78
|
+
})
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
const styles = StyleSheet.create({
|
|
82
|
+
decorator: {
|
|
83
|
+
display: 'contents'
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
//# sourceMappingURL=TransformerTextInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["forwardRef","useCallback","useEffect","useMemo","useRef","StyleSheet","TextInput","TransformerTextInputDecoratorViewNativeComponent","Commands","registerTransformer","unregisterTransformer","useMergeRefs","validateSelection","jsx","_jsx","TransformerTextInput","transformer","onChangeText","others","forwardedRef","transformerId","decoratorRef","textRef","setInputRef","instance","Object","assign","getValue","current","update","value","selection","transform","nativeRef","newSelection","newValue","length","start","end","clear","inputRef","handleChangeText","text","ref","style","styles","decorator","children","create","display"],"sourceRoot":"../../src","sources":["TransformerTextInput.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
codegenNativeCommands,
|
|
4
|
+
codegenNativeComponent,
|
|
5
|
+
type HostComponent,
|
|
6
|
+
type ViewProps,
|
|
7
|
+
type CodegenTypes,
|
|
8
|
+
} from 'react-native';
|
|
9
|
+
|
|
10
|
+
interface NativeProps extends ViewProps {
|
|
11
|
+
transformerId: CodegenTypes.Int32;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface NativeCommands {
|
|
15
|
+
update: (
|
|
16
|
+
viewRef: React.ElementRef<HostComponent<NativeProps>>,
|
|
17
|
+
transform: boolean,
|
|
18
|
+
value: string | null,
|
|
19
|
+
selectionStart: CodegenTypes.Int32,
|
|
20
|
+
selectionEnd: CodegenTypes.Int32,
|
|
21
|
+
) => void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
|
|
25
|
+
supportedCommands: ['update'],
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export default codegenNativeComponent<NativeProps>(
|
|
29
|
+
'TransformerTextInputDecoratorView',
|
|
30
|
+
{ interfaceOnly: true },
|
|
31
|
+
);
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { Transformer } from "../Transformer.js";
|
|
4
|
+
// Check if char is a digit
|
|
5
|
+
const isDigit = char => {
|
|
6
|
+
'worklet';
|
|
7
|
+
|
|
8
|
+
return char !== undefined && char >= '0' && char <= '9';
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// Count national digits before a position
|
|
12
|
+
// Always skips the first "1" digit when we have/will have +1 prefix
|
|
13
|
+
const countNationalDigitsBefore = (text, pos) => {
|
|
14
|
+
'worklet';
|
|
15
|
+
|
|
16
|
+
let count = 0;
|
|
17
|
+
let skippedCountryOne = false;
|
|
18
|
+
for (let i = 0; i < Math.min(pos, text.length); i++) {
|
|
19
|
+
if (isDigit(text[i])) {
|
|
20
|
+
// Skip the "1" in "+1" prefix
|
|
21
|
+
if (!skippedCountryOne && text[i] === '1' && i > 0 && text[i - 1] === '+') {
|
|
22
|
+
skippedCountryOne = true;
|
|
23
|
+
} else {
|
|
24
|
+
count++;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return count;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// Find position in formatted text after N national digits
|
|
32
|
+
const positionAfterNationalDigit = (text, targetCount) => {
|
|
33
|
+
'worklet';
|
|
34
|
+
|
|
35
|
+
if (targetCount <= 0) {
|
|
36
|
+
// Position after "+1 " prefix if present, else 0
|
|
37
|
+
if (text.startsWith('+1 ')) return 3;
|
|
38
|
+
if (text.startsWith('+1')) return 2;
|
|
39
|
+
return 0;
|
|
40
|
+
}
|
|
41
|
+
let count = 0;
|
|
42
|
+
let skippedCountryOne = false;
|
|
43
|
+
for (let i = 0; i < text.length; i++) {
|
|
44
|
+
if (isDigit(text[i])) {
|
|
45
|
+
if (!skippedCountryOne && text[i] === '1' && i > 0 && text[i - 1] === '+') {
|
|
46
|
+
skippedCountryOne = true;
|
|
47
|
+
} else {
|
|
48
|
+
count++;
|
|
49
|
+
if (count === targetCount) return i + 1;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return text.length;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// Format national digits into US phone format
|
|
57
|
+
const formatUSPhoneNumber = digits => {
|
|
58
|
+
'worklet';
|
|
59
|
+
|
|
60
|
+
const area = digits.slice(0, 3);
|
|
61
|
+
const exchange = digits.slice(3, 6);
|
|
62
|
+
const subscriber = digits.slice(6, 10);
|
|
63
|
+
let formatted = '+1 ';
|
|
64
|
+
if (area.length > 0) {
|
|
65
|
+
formatted += '(' + area;
|
|
66
|
+
if (area.length === 3) {
|
|
67
|
+
formatted += ') ';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (exchange.length > 0) {
|
|
71
|
+
formatted += exchange;
|
|
72
|
+
if (exchange.length === 3 && subscriber.length > 0) {
|
|
73
|
+
formatted += '-';
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (subscriber.length > 0) {
|
|
77
|
+
formatted += subscriber;
|
|
78
|
+
}
|
|
79
|
+
return formatted;
|
|
80
|
+
};
|
|
81
|
+
export class PhoneNumberTransformer extends Transformer {
|
|
82
|
+
constructor({
|
|
83
|
+
country = 'US',
|
|
84
|
+
debug = false
|
|
85
|
+
} = {}) {
|
|
86
|
+
if (country !== 'US') {
|
|
87
|
+
throw new Error(`[PhoneNumberTransformer] Country "${country}" is not supported. Only "US" is currently supported.`);
|
|
88
|
+
}
|
|
89
|
+
const worklet = input => {
|
|
90
|
+
'worklet';
|
|
91
|
+
|
|
92
|
+
const {
|
|
93
|
+
value,
|
|
94
|
+
selection,
|
|
95
|
+
previousValue,
|
|
96
|
+
previousSelection
|
|
97
|
+
} = input;
|
|
98
|
+
|
|
99
|
+
// Extract all digits from input
|
|
100
|
+
const allDigits = value.replace(/\D/g, '');
|
|
101
|
+
|
|
102
|
+
// Empty input - clear everything
|
|
103
|
+
if (allDigits.length === 0) {
|
|
104
|
+
return {
|
|
105
|
+
value: '',
|
|
106
|
+
selection: {
|
|
107
|
+
start: 0,
|
|
108
|
+
end: 0
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Get national digits - strip leading "1" if enabled since we always add +1 prefix
|
|
114
|
+
const nationalDigits = (allDigits.startsWith('1') ? allDigits.slice(1) : allDigits).slice(0, 10);
|
|
115
|
+
|
|
116
|
+
// If no national digits left, check if user is deleting
|
|
117
|
+
if (nationalDigits.length === 0) {
|
|
118
|
+
// If value got shorter (user is deleting), clear everything
|
|
119
|
+
if (value.length < previousValue.length) {
|
|
120
|
+
if (debug) {
|
|
121
|
+
console.log('[PhoneNumberTransformer] -> case: deleted to empty');
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
value: '',
|
|
125
|
+
selection: {
|
|
126
|
+
start: 0,
|
|
127
|
+
end: 0
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
// Otherwise user just typed "1", show the prefix
|
|
132
|
+
return {
|
|
133
|
+
value: '+1 ',
|
|
134
|
+
selection: {
|
|
135
|
+
start: 3,
|
|
136
|
+
end: 3
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
const formatted = formatUSPhoneNumber(nationalDigits);
|
|
141
|
+
|
|
142
|
+
// Calculate cursor position
|
|
143
|
+
const isCaret = selection.start === selection.end;
|
|
144
|
+
const cursorAtEnd = selection.end >= value.length;
|
|
145
|
+
const prevCursorAtEnd = previousSelection.end >= previousValue.length;
|
|
146
|
+
|
|
147
|
+
// Count national digits
|
|
148
|
+
const digitsBeforeCursor = countNationalDigitsBefore(value, selection.start);
|
|
149
|
+
const prevDigitsBeforeCursor = countNationalDigitsBefore(previousValue, previousSelection.start);
|
|
150
|
+
const totalDigits = countNationalDigitsBefore(value, value.length);
|
|
151
|
+
const prevTotalDigits = countNationalDigitsBefore(previousValue, previousValue.length);
|
|
152
|
+
const isDeleting = totalDigits < prevTotalDigits;
|
|
153
|
+
const isInserting = totalDigits > prevTotalDigits;
|
|
154
|
+
|
|
155
|
+
// Detect deletion of formatting character (e.g., deleting space, dash, or paren)
|
|
156
|
+
// User expects this to delete the digit before cursor
|
|
157
|
+
const deletedFormattingChar = isCaret && value.length < previousValue.length && totalDigits === prevTotalDigits && totalDigits > 0;
|
|
158
|
+
|
|
159
|
+
// Log for debugging
|
|
160
|
+
if (debug) {
|
|
161
|
+
console.log('[PhoneNumberTransformer]', {
|
|
162
|
+
input: {
|
|
163
|
+
value,
|
|
164
|
+
selection
|
|
165
|
+
},
|
|
166
|
+
prev: {
|
|
167
|
+
previousValue,
|
|
168
|
+
previousSelection
|
|
169
|
+
},
|
|
170
|
+
digits: {
|
|
171
|
+
nationalDigits,
|
|
172
|
+
totalDigits,
|
|
173
|
+
prevTotalDigits
|
|
174
|
+
},
|
|
175
|
+
cursor: {
|
|
176
|
+
digitsBeforeCursor,
|
|
177
|
+
prevDigitsBeforeCursor
|
|
178
|
+
},
|
|
179
|
+
flags: {
|
|
180
|
+
isCaret,
|
|
181
|
+
cursorAtEnd,
|
|
182
|
+
prevCursorAtEnd,
|
|
183
|
+
isDeleting,
|
|
184
|
+
isInserting,
|
|
185
|
+
deletedFormattingChar
|
|
186
|
+
},
|
|
187
|
+
output: formatted
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Case 0: Deleted a formatting char - remove the digit before cursor
|
|
192
|
+
if (deletedFormattingChar) {
|
|
193
|
+
// Figure out which digit to remove: the one before the cursor
|
|
194
|
+
const digitToRemove = digitsBeforeCursor;
|
|
195
|
+
if (digitToRemove <= 0) {
|
|
196
|
+
// Cursor was before all digits, nothing to delete
|
|
197
|
+
if (debug) {
|
|
198
|
+
console.log('[PhoneNumberTransformer] -> case: deleted formatting char but cursor before all digits');
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
value: formatted,
|
|
202
|
+
selection: {
|
|
203
|
+
start: 3,
|
|
204
|
+
end: 3
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Remove the digit at position (digitToRemove - 1) from nationalDigits
|
|
210
|
+
const trimmedDigits = nationalDigits.slice(0, digitToRemove - 1) + nationalDigits.slice(digitToRemove);
|
|
211
|
+
if (debug) {
|
|
212
|
+
console.log('[PhoneNumberTransformer] -> case: deleted formatting char', {
|
|
213
|
+
digitToRemove,
|
|
214
|
+
trimmedDigits
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
if (trimmedDigits.length === 0) {
|
|
218
|
+
return {
|
|
219
|
+
value: '',
|
|
220
|
+
selection: {
|
|
221
|
+
start: 0,
|
|
222
|
+
end: 0
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
const trimmedFormatted = formatUSPhoneNumber(trimmedDigits);
|
|
227
|
+
|
|
228
|
+
// Position cursor where the deleted digit was
|
|
229
|
+
const newCursorDigits = digitToRemove - 1;
|
|
230
|
+
const newPos = positionAfterNationalDigit(trimmedFormatted, newCursorDigits);
|
|
231
|
+
return {
|
|
232
|
+
value: trimmedFormatted,
|
|
233
|
+
selection: {
|
|
234
|
+
start: newPos,
|
|
235
|
+
end: newPos
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Case 1: Typing at end (most common)
|
|
241
|
+
if (isCaret && cursorAtEnd && prevCursorAtEnd) {
|
|
242
|
+
if (debug) {
|
|
243
|
+
console.log('[PhoneNumberTransformer] -> case: typing at end');
|
|
244
|
+
}
|
|
245
|
+
return {
|
|
246
|
+
value: formatted,
|
|
247
|
+
selection: {
|
|
248
|
+
start: formatted.length,
|
|
249
|
+
end: formatted.length
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Case 2: Deletion - use current cursor position (previous is stale if user moved cursor)
|
|
255
|
+
if (isDeleting && isCaret) {
|
|
256
|
+
const newPos = positionAfterNationalDigit(formatted, digitsBeforeCursor);
|
|
257
|
+
if (debug) {
|
|
258
|
+
console.log('[PhoneNumberTransformer] -> case: deletion', {
|
|
259
|
+
digitsBeforeCursor,
|
|
260
|
+
newPos
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
return {
|
|
264
|
+
value: formatted,
|
|
265
|
+
selection: {
|
|
266
|
+
start: newPos,
|
|
267
|
+
end: newPos
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Case 3: Insertion in middle - use current cursor position
|
|
273
|
+
if (isInserting && isCaret) {
|
|
274
|
+
const newPos = positionAfterNationalDigit(formatted, digitsBeforeCursor);
|
|
275
|
+
if (debug) {
|
|
276
|
+
console.log('[PhoneNumberTransformer] -> case: insertion', {
|
|
277
|
+
digitsBeforeCursor,
|
|
278
|
+
newPos
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
return {
|
|
282
|
+
value: formatted,
|
|
283
|
+
selection: {
|
|
284
|
+
start: newPos,
|
|
285
|
+
end: newPos
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Case 4: Default / selection handling
|
|
291
|
+
const clampedDigits = Math.min(digitsBeforeCursor, nationalDigits.length);
|
|
292
|
+
const newStart = positionAfterNationalDigit(formatted, clampedDigits);
|
|
293
|
+
const endDigits = countNationalDigitsBefore(value, selection.end);
|
|
294
|
+
const clampedEndDigits = Math.min(endDigits, nationalDigits.length);
|
|
295
|
+
const newEnd = positionAfterNationalDigit(formatted, clampedEndDigits);
|
|
296
|
+
if (debug) {
|
|
297
|
+
console.log('[PhoneNumberTransformer] -> case: default', {
|
|
298
|
+
clampedDigits,
|
|
299
|
+
newStart,
|
|
300
|
+
clampedEndDigits,
|
|
301
|
+
newEnd
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
return {
|
|
305
|
+
value: formatted,
|
|
306
|
+
selection: {
|
|
307
|
+
start: newStart,
|
|
308
|
+
end: newEnd
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
};
|
|
312
|
+
super(worklet);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
//# sourceMappingURL=phone-number.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["Transformer","isDigit","char","undefined","countNationalDigitsBefore","text","pos","count","skippedCountryOne","i","Math","min","length","positionAfterNationalDigit","targetCount","startsWith","formatUSPhoneNumber","digits","area","slice","exchange","subscriber","formatted","PhoneNumberTransformer","constructor","country","debug","Error","worklet","input","value","selection","previousValue","previousSelection","allDigits","replace","start","end","nationalDigits","console","log","isCaret","cursorAtEnd","prevCursorAtEnd","digitsBeforeCursor","prevDigitsBeforeCursor","totalDigits","prevTotalDigits","isDeleting","isInserting","deletedFormattingChar","prev","cursor","flags","output","digitToRemove","trimmedDigits","trimmedFormatted","newCursorDigits","newPos","clampedDigits","newStart","endDigits","clampedEndDigits","newEnd"],"sourceRoot":"../../../src","sources":["formatters/phone-number.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["Transformer","TransformerTextInput"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SACEA,WAAW,QAGN,kBAAe;AACtB,SACEC,oBAAoB,QAGf,2BAAwB","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { runOnUI } from 'react-native-worklets';
|
|
4
|
+
import NativeTransformerTextInputModule from "./NativeTransformerTextInputModule.js";
|
|
5
|
+
import { computeUncontrolledSelection, validateSelection } from "./selection.js";
|
|
6
|
+
let initialized = false;
|
|
7
|
+
function initializeIfNeeded() {
|
|
8
|
+
if (initialized) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Important that `runOnUI` is called first to make sure the UI runtime is initialized.
|
|
13
|
+
runOnUI(() => {
|
|
14
|
+
'worklet';
|
|
15
|
+
|
|
16
|
+
const transformersMap = new Map();
|
|
17
|
+
globalThis.__rntti_registerTransformerRegistry = {
|
|
18
|
+
register(id, transformer) {
|
|
19
|
+
transformersMap.set(id, transformer);
|
|
20
|
+
},
|
|
21
|
+
unregister(transformerId) {
|
|
22
|
+
transformersMap.delete(transformerId);
|
|
23
|
+
},
|
|
24
|
+
get(transformerId) {
|
|
25
|
+
return transformersMap.get(transformerId);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
})();
|
|
29
|
+
NativeTransformerTextInputModule.install();
|
|
30
|
+
initialized = true;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Start counting ids at 1 to avoid using 0 as it is the default int value.
|
|
34
|
+
let currentId = 1;
|
|
35
|
+
export function registerTransformer(transformer) {
|
|
36
|
+
initializeIfNeeded();
|
|
37
|
+
const id = currentId++;
|
|
38
|
+
const worklet = transformer.worklet;
|
|
39
|
+
runOnUI(() => {
|
|
40
|
+
'worklet';
|
|
41
|
+
|
|
42
|
+
let previousValue = null;
|
|
43
|
+
let previousSelection = null;
|
|
44
|
+
const transformerWrapper = (value, selectionStart, selectionEnd) => {
|
|
45
|
+
const result = worklet({
|
|
46
|
+
value,
|
|
47
|
+
previousValue: previousValue ?? value,
|
|
48
|
+
selection: {
|
|
49
|
+
start: selectionStart,
|
|
50
|
+
end: selectionEnd
|
|
51
|
+
},
|
|
52
|
+
previousSelection: previousSelection ?? {
|
|
53
|
+
start: selectionStart,
|
|
54
|
+
end: selectionEnd
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
const newValue = result?.value ?? value;
|
|
58
|
+
let newSelection;
|
|
59
|
+
if (result?.selection != null) {
|
|
60
|
+
newSelection = result.selection;
|
|
61
|
+
validateSelection(newSelection, newValue.length);
|
|
62
|
+
} else {
|
|
63
|
+
newSelection = computeUncontrolledSelection(value, newValue, selectionStart, selectionEnd);
|
|
64
|
+
}
|
|
65
|
+
previousValue = newValue;
|
|
66
|
+
previousSelection = newSelection;
|
|
67
|
+
return {
|
|
68
|
+
value: newValue,
|
|
69
|
+
selection: newSelection
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
globalThis.__rntti_registerTransformerRegistry?.register(id, transformerWrapper);
|
|
73
|
+
})();
|
|
74
|
+
return id;
|
|
75
|
+
}
|
|
76
|
+
export function unregisterTransformer(transformerId) {
|
|
77
|
+
runOnUI(() => {
|
|
78
|
+
'worklet';
|
|
79
|
+
|
|
80
|
+
global.__rntti_registerTransformerRegistry?.unregister(transformerId);
|
|
81
|
+
})();
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["runOnUI","NativeTransformerTextInputModule","computeUncontrolledSelection","validateSelection","initialized","initializeIfNeeded","transformersMap","Map","globalThis","__rntti_registerTransformerRegistry","register","id","transformer","set","unregister","transformerId","delete","get","install","currentId","registerTransformer","worklet","previousValue","previousSelection","transformerWrapper","value","selectionStart","selectionEnd","result","selection","start","end","newValue","newSelection","length","unregisterTransformer","global"],"sourceRoot":"../../src","sources":["registry.ts"],"mappings":";;AAAA,SAASA,OAAO,QAAQ,uBAAuB;AAC/C,OAAOC,gCAAgC,MAAM,uCAAoC;AAEjF,SAASC,4BAA4B,EAAEC,iBAAiB,QAAQ,gBAAa;AAoB7E,IAAIC,WAAW,GAAG,KAAK;AAEvB,SAASC,kBAAkBA,CAAA,EAAG;EAC5B,IAAID,WAAW,EAAE;IACf;EACF;;EAEA;EACAJ,OAAO,CAAC,MAAM;IACZ,SAAS;;IAET,MAAMM,eAAe,GAAG,IAAIC,GAAG,CAA6B,CAAC;IAE7DC,UAAU,CAACC,mCAAmC,GAAG;MAC/CC,QAAQA,CAACC,EAAE,EAAEC,WAAW,EAAE;QACxBN,eAAe,CAACO,GAAG,CAACF,EAAE,EAAEC,WAAW,CAAC;MACtC,CAAC;MACDE,UAAUA,CAACC,aAAa,EAAE;QACxBT,eAAe,CAACU,MAAM,CAACD,aAAa,CAAC;MACvC,CAAC;MACDE,GAAGA,CAACF,aAAa,EAAE;QACjB,OAAOT,eAAe,CAACW,GAAG,CAACF,aAAa,CAAC;MAC3C;IACF,CAAC;EACH,CAAC,CAAC,CAAC,CAAC;EAEJd,gCAAgC,CAACiB,OAAO,CAAC,CAAC;EAE1Cd,WAAW,GAAG,IAAI;AACpB;;AAEA;AACA,IAAIe,SAAS,GAAG,CAAC;AAEjB,OAAO,SAASC,mBAAmBA,CAACR,WAAwB,EAAU;EACpEP,kBAAkB,CAAC,CAAC;EAEpB,MAAMM,EAAE,GAAGQ,SAAS,EAAE;EACtB,MAAME,OAAO,GAAGT,WAAW,CAACS,OAAO;EAEnCrB,OAAO,CAAC,MAAM;IACZ,SAAS;;IAET,IAAIsB,aAA4B,GAAG,IAAI;IACvC,IAAIC,iBAAmC,GAAG,IAAI;IAE9C,MAAMC,kBAAsC,GAAGA,CAC7CC,KAAK,EACLC,cAAc,EACdC,YAAY,KACT;MACH,MAAMC,MAAM,GAAGP,OAAO,CAAC;QACrBI,KAAK;QACLH,aAAa,EAAEA,aAAa,IAAIG,KAAK;QACrCI,SAAS,EAAE;UAAEC,KAAK,EAAEJ,cAAc;UAAEK,GAAG,EAAEJ;QAAa,CAAC;QACvDJ,iBAAiB,EAAEA,iBAAiB,IAAI;UACtCO,KAAK,EAAEJ,cAAc;UACrBK,GAAG,EAAEJ;QACP;MACF,CAAC,CAAC;MACF,MAAMK,QAAQ,GAAGJ,MAAM,EAAEH,KAAK,IAAIA,KAAK;MACvC,IAAIQ,YAAuB;MAC3B,IAAIL,MAAM,EAAEC,SAAS,IAAI,IAAI,EAAE;QAC7BI,YAAY,GAAGL,MAAM,CAACC,SAAS;QAC/B1B,iBAAiB,CAAC8B,YAAY,EAAED,QAAQ,CAACE,MAAM,CAAC;MAClD,CAAC,MAAM;QACLD,YAAY,GAAG/B,4BAA4B,CACzCuB,KAAK,EACLO,QAAQ,EACRN,cAAc,EACdC,YACF,CAAC;MACH;MACAL,aAAa,GAAGU,QAAQ;MACxBT,iBAAiB,GAAGU,YAAY;MAChC,OAAO;QACLR,KAAK,EAAEO,QAAQ;QACfH,SAAS,EAAEI;MACb,CAAC;IACH,CAAC;IAEDzB,UAAU,CAACC,mCAAmC,EAAEC,QAAQ,CACtDC,EAAE,EACFa,kBACF,CAAC;EACH,CAAC,CAAC,CAAC,CAAC;EAEJ,OAAOb,EAAE;AACX;AAEA,OAAO,SAASwB,qBAAqBA,CAACpB,aAAqB,EAAE;EAC3Df,OAAO,CAAC,MAAM;IACZ,SAAS;;IAEToC,MAAM,CAAC3B,mCAAmC,EAAEK,UAAU,CAACC,aAAa,CAAC;EACvE,CAAC,CAAC,CAAC,CAAC;AACN","ignoreList":[]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
export const computeUncontrolledSelection = (oldValue, newValue, selectionStart, selectionEnd) => {
|
|
4
|
+
'worklet';
|
|
5
|
+
|
|
6
|
+
const oldLength = oldValue.length;
|
|
7
|
+
const newLength = newValue.length;
|
|
8
|
+
const delta = newLength - oldLength;
|
|
9
|
+
let rawStart;
|
|
10
|
+
let rawEnd;
|
|
11
|
+
if (selectionStart === selectionEnd) {
|
|
12
|
+
if (selectionEnd >= oldLength) {
|
|
13
|
+
rawStart = newLength;
|
|
14
|
+
rawEnd = newLength;
|
|
15
|
+
} else {
|
|
16
|
+
const next = selectionEnd + delta;
|
|
17
|
+
rawStart = next;
|
|
18
|
+
rawEnd = next;
|
|
19
|
+
}
|
|
20
|
+
} else {
|
|
21
|
+
rawStart = selectionStart + delta;
|
|
22
|
+
rawEnd = selectionEnd + delta;
|
|
23
|
+
}
|
|
24
|
+
if (rawStart < 0 || rawEnd < 0 || rawStart > newLength || rawEnd > newLength || rawStart > rawEnd) {
|
|
25
|
+
return {
|
|
26
|
+
start: newLength,
|
|
27
|
+
end: newLength
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
start: rawStart,
|
|
32
|
+
end: rawEnd
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
export const validateSelection = (selection, valueLength) => {
|
|
36
|
+
'worklet';
|
|
37
|
+
|
|
38
|
+
if (selection.start < 0 || selection.end < 0) {
|
|
39
|
+
throw new Error(`[rntti] Returned selection must be non-negative. Received start=${selection.start}, end=${selection.end}, valueLength=${valueLength}`);
|
|
40
|
+
}
|
|
41
|
+
if (selection.end < selection.start) {
|
|
42
|
+
throw new Error(`[rntti] Returned selection end must be >= selection start. Received start=${selection.start}, end=${selection.end}, valueLength=${valueLength}`);
|
|
43
|
+
}
|
|
44
|
+
if (selection.start > valueLength || selection.end > valueLength) {
|
|
45
|
+
throw new Error(`[rntti] Returned selection is out of bounds for the returned value. Received start=${selection.start}, end=${selection.end}, valueLength=${valueLength}`);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=selection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["computeUncontrolledSelection","oldValue","newValue","selectionStart","selectionEnd","oldLength","length","newLength","delta","rawStart","rawEnd","next","start","end","validateSelection","selection","valueLength","Error"],"sourceRoot":"../../src","sources":["selection.ts"],"mappings":";;AAEA,OAAO,MAAMA,4BAA4B,GAAGA,CAC1CC,QAAgB,EAChBC,QAAgB,EAChBC,cAAsB,EACtBC,YAAoB,KACN;EACd,SAAS;;EACT,MAAMC,SAAS,GAAGJ,QAAQ,CAACK,MAAM;EACjC,MAAMC,SAAS,GAAGL,QAAQ,CAACI,MAAM;EACjC,MAAME,KAAK,GAAGD,SAAS,GAAGF,SAAS;EACnC,IAAII,QAAgB;EACpB,IAAIC,MAAc;EAClB,IAAIP,cAAc,KAAKC,YAAY,EAAE;IACnC,IAAIA,YAAY,IAAIC,SAAS,EAAE;MAC7BI,QAAQ,GAAGF,SAAS;MACpBG,MAAM,GAAGH,SAAS;IACpB,CAAC,MAAM;MACL,MAAMI,IAAI,GAAGP,YAAY,GAAGI,KAAK;MACjCC,QAAQ,GAAGE,IAAI;MACfD,MAAM,GAAGC,IAAI;IACf;EACF,CAAC,MAAM;IACLF,QAAQ,GAAGN,cAAc,GAAGK,KAAK;IACjCE,MAAM,GAAGN,YAAY,GAAGI,KAAK;EAC/B;EAEA,IACEC,QAAQ,GAAG,CAAC,IACZC,MAAM,GAAG,CAAC,IACVD,QAAQ,GAAGF,SAAS,IACpBG,MAAM,GAAGH,SAAS,IAClBE,QAAQ,GAAGC,MAAM,EACjB;IACA,OAAO;MAAEE,KAAK,EAAEL,SAAS;MAAEM,GAAG,EAAEN;IAAU,CAAC;EAC7C;EAEA,OAAO;IAAEK,KAAK,EAAEH,QAAQ;IAAEI,GAAG,EAAEH;EAAO,CAAC;AACzC,CAAC;AAED,OAAO,MAAMI,iBAAiB,GAAGA,CAC/BC,SAAoB,EACpBC,WAAmB,KAChB;EACH,SAAS;;EACT,IAAID,SAAS,CAACH,KAAK,GAAG,CAAC,IAAIG,SAAS,CAACF,GAAG,GAAG,CAAC,EAAE;IAC5C,MAAM,IAAII,KAAK,CACb,mEAAmEF,SAAS,CAACH,KAAK,SAASG,SAAS,CAACF,GAAG,iBAAiBG,WAAW,EACtI,CAAC;EACH;EACA,IAAID,SAAS,CAACF,GAAG,GAAGE,SAAS,CAACH,KAAK,EAAE;IACnC,MAAM,IAAIK,KAAK,CACb,6EAA6EF,SAAS,CAACH,KAAK,SAASG,SAAS,CAACF,GAAG,iBAAiBG,WAAW,EAChJ,CAAC;EACH;EACA,IAAID,SAAS,CAACH,KAAK,GAAGI,WAAW,IAAID,SAAS,CAACF,GAAG,GAAGG,WAAW,EAAE;IAChE,MAAM,IAAIC,KAAK,CACb,sFAAsFF,SAAS,CAACH,KAAK,SAASG,SAAS,CAACF,GAAG,iBAAiBG,WAAW,EACzJ,CAAC;EACH;AACF,CAAC","ignoreList":[]}
|