@hero-design/rn 8.64.6 → 8.64.7-alpha.1
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/es/index.js +28 -9
- package/lib/index.js +28 -9
- package/package.json +1 -1
- package/src/components/PinInput/__tests__/__snapshots__/index.spec.tsx.snap +0 -5
- package/src/components/PinInput/__tests__/index.spec.tsx +84 -1
- package/src/components/PinInput/index.tsx +31 -9
- package/types/components/PinInput/index.d.ts +1 -0
- package/.turbo/turbo-build.log +0 -5
package/es/index.js
CHANGED
|
@@ -15582,6 +15582,11 @@ function getState(_ref) {
|
|
|
15582
15582
|
}
|
|
15583
15583
|
return 'default';
|
|
15584
15584
|
}
|
|
15585
|
+
// Normalize the value to only contain numbers and limit the length
|
|
15586
|
+
var normalizeValue = function normalizeValue(value) {
|
|
15587
|
+
var length = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 4;
|
|
15588
|
+
return ((value === null || value === void 0 ? void 0 : value.match(/\d/g)) || []).join('').slice(0, length);
|
|
15589
|
+
};
|
|
15585
15590
|
var PinInput = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
15586
15591
|
var _ref2$value = _ref2.value,
|
|
15587
15592
|
value = _ref2$value === void 0 ? '' : _ref2$value,
|
|
@@ -15609,7 +15614,12 @@ var PinInput = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
15609
15614
|
disabled: disabled,
|
|
15610
15615
|
error: error
|
|
15611
15616
|
});
|
|
15612
|
-
var
|
|
15617
|
+
var trimmedValue = normalizeValue(value, length);
|
|
15618
|
+
var maskedValueWithExtraSpace = Platform.OS === 'android' && !trimmedValue ? '*' : trimmedValue;
|
|
15619
|
+
var _useState3 = useState(false),
|
|
15620
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
15621
|
+
hasFulfilled = _useState4[0],
|
|
15622
|
+
setHasFulfilled = _useState4[1];
|
|
15613
15623
|
var focus = useCallback(function () {
|
|
15614
15624
|
if (inputRef !== null && inputRef !== void 0 && inputRef.current) {
|
|
15615
15625
|
inputRef.current.focus();
|
|
@@ -15623,12 +15633,22 @@ var PinInput = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
15623
15633
|
}
|
|
15624
15634
|
}, []);
|
|
15625
15635
|
var changeText = useCallback(function (text) {
|
|
15626
|
-
|
|
15627
|
-
|
|
15628
|
-
|
|
15629
|
-
|
|
15636
|
+
// If the input is already fulfilled and the user tries to remove characters
|
|
15637
|
+
if (hasFulfilled && text.length < length) {
|
|
15638
|
+
setHasFulfilled(false);
|
|
15639
|
+
}
|
|
15640
|
+
// If the input is already fulfilled and the user tries to add more characters
|
|
15641
|
+
if (hasFulfilled && ((text === null || text === void 0 ? void 0 : text.match(/\d/g)) || []).join('').length > length) {
|
|
15642
|
+
return;
|
|
15643
|
+
}
|
|
15644
|
+
// Prevent user from entering more than the length
|
|
15645
|
+
var trimmedPin = normalizeValue(text, length);
|
|
15646
|
+
onChangeText === null || onChangeText === void 0 || onChangeText(trimmedPin);
|
|
15647
|
+
if (trimmedPin.length === length) {
|
|
15648
|
+
onFulfill === null || onFulfill === void 0 || onFulfill(trimmedPin);
|
|
15649
|
+
setHasFulfilled(true);
|
|
15630
15650
|
}
|
|
15631
|
-
}, [length, onChangeText, onFulfill]);
|
|
15651
|
+
}, [length, onChangeText, onFulfill, hasFulfilled]);
|
|
15632
15652
|
useEffect(function () {
|
|
15633
15653
|
// Must run after animations for keyboard to automatically open
|
|
15634
15654
|
if (autoFocus) {
|
|
@@ -15648,9 +15668,9 @@ var PinInput = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
15648
15668
|
return /*#__PURE__*/React__default.createElement(React__default.Fragment, {
|
|
15649
15669
|
key: index
|
|
15650
15670
|
}, index !== 0 && /*#__PURE__*/React__default.createElement(StyledSpacer, null), /*#__PURE__*/React__default.createElement(PinCell, {
|
|
15651
|
-
value:
|
|
15671
|
+
value: trimmedValue.charAt(index),
|
|
15652
15672
|
secure: secure,
|
|
15653
|
-
focused: focused && index ===
|
|
15673
|
+
focused: focused && index === trimmedValue.length,
|
|
15654
15674
|
state: state
|
|
15655
15675
|
}));
|
|
15656
15676
|
})), state === 'error' && /*#__PURE__*/React__default.createElement(StyledErrorContainer, null, /*#__PURE__*/React__default.createElement(Icon, {
|
|
@@ -15668,7 +15688,6 @@ var PinInput = /*#__PURE__*/forwardRef(function (_ref2, ref) {
|
|
|
15668
15688
|
autoFocus: autoFocus,
|
|
15669
15689
|
onFocus: focus,
|
|
15670
15690
|
onBlur: blur,
|
|
15671
|
-
maxLength: length,
|
|
15672
15691
|
pointerEvents: "box-none",
|
|
15673
15692
|
keyboardType: "numeric",
|
|
15674
15693
|
testID: "pin-hidden-input",
|
package/lib/index.js
CHANGED
|
@@ -15612,6 +15612,11 @@ function getState(_ref) {
|
|
|
15612
15612
|
}
|
|
15613
15613
|
return 'default';
|
|
15614
15614
|
}
|
|
15615
|
+
// Normalize the value to only contain numbers and limit the length
|
|
15616
|
+
var normalizeValue = function normalizeValue(value) {
|
|
15617
|
+
var length = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 4;
|
|
15618
|
+
return ((value === null || value === void 0 ? void 0 : value.match(/\d/g)) || []).join('').slice(0, length);
|
|
15619
|
+
};
|
|
15615
15620
|
var PinInput = /*#__PURE__*/React.forwardRef(function (_ref2, ref) {
|
|
15616
15621
|
var _ref2$value = _ref2.value,
|
|
15617
15622
|
value = _ref2$value === void 0 ? '' : _ref2$value,
|
|
@@ -15639,7 +15644,12 @@ var PinInput = /*#__PURE__*/React.forwardRef(function (_ref2, ref) {
|
|
|
15639
15644
|
disabled: disabled,
|
|
15640
15645
|
error: error
|
|
15641
15646
|
});
|
|
15642
|
-
var
|
|
15647
|
+
var trimmedValue = normalizeValue(value, length);
|
|
15648
|
+
var maskedValueWithExtraSpace = reactNative.Platform.OS === 'android' && !trimmedValue ? '*' : trimmedValue;
|
|
15649
|
+
var _useState3 = React.useState(false),
|
|
15650
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
15651
|
+
hasFulfilled = _useState4[0],
|
|
15652
|
+
setHasFulfilled = _useState4[1];
|
|
15643
15653
|
var focus = React.useCallback(function () {
|
|
15644
15654
|
if (inputRef !== null && inputRef !== void 0 && inputRef.current) {
|
|
15645
15655
|
inputRef.current.focus();
|
|
@@ -15653,12 +15663,22 @@ var PinInput = /*#__PURE__*/React.forwardRef(function (_ref2, ref) {
|
|
|
15653
15663
|
}
|
|
15654
15664
|
}, []);
|
|
15655
15665
|
var changeText = React.useCallback(function (text) {
|
|
15656
|
-
|
|
15657
|
-
|
|
15658
|
-
|
|
15659
|
-
|
|
15666
|
+
// If the input is already fulfilled and the user tries to remove characters
|
|
15667
|
+
if (hasFulfilled && text.length < length) {
|
|
15668
|
+
setHasFulfilled(false);
|
|
15669
|
+
}
|
|
15670
|
+
// If the input is already fulfilled and the user tries to add more characters
|
|
15671
|
+
if (hasFulfilled && ((text === null || text === void 0 ? void 0 : text.match(/\d/g)) || []).join('').length > length) {
|
|
15672
|
+
return;
|
|
15673
|
+
}
|
|
15674
|
+
// Prevent user from entering more than the length
|
|
15675
|
+
var trimmedPin = normalizeValue(text, length);
|
|
15676
|
+
onChangeText === null || onChangeText === void 0 || onChangeText(trimmedPin);
|
|
15677
|
+
if (trimmedPin.length === length) {
|
|
15678
|
+
onFulfill === null || onFulfill === void 0 || onFulfill(trimmedPin);
|
|
15679
|
+
setHasFulfilled(true);
|
|
15660
15680
|
}
|
|
15661
|
-
}, [length, onChangeText, onFulfill]);
|
|
15681
|
+
}, [length, onChangeText, onFulfill, hasFulfilled]);
|
|
15662
15682
|
React.useEffect(function () {
|
|
15663
15683
|
// Must run after animations for keyboard to automatically open
|
|
15664
15684
|
if (autoFocus) {
|
|
@@ -15678,9 +15698,9 @@ var PinInput = /*#__PURE__*/React.forwardRef(function (_ref2, ref) {
|
|
|
15678
15698
|
return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, {
|
|
15679
15699
|
key: index
|
|
15680
15700
|
}, index !== 0 && /*#__PURE__*/React__default["default"].createElement(StyledSpacer, null), /*#__PURE__*/React__default["default"].createElement(PinCell, {
|
|
15681
|
-
value:
|
|
15701
|
+
value: trimmedValue.charAt(index),
|
|
15682
15702
|
secure: secure,
|
|
15683
|
-
focused: focused && index ===
|
|
15703
|
+
focused: focused && index === trimmedValue.length,
|
|
15684
15704
|
state: state
|
|
15685
15705
|
}));
|
|
15686
15706
|
})), state === 'error' && /*#__PURE__*/React__default["default"].createElement(StyledErrorContainer, null, /*#__PURE__*/React__default["default"].createElement(Icon, {
|
|
@@ -15698,7 +15718,6 @@ var PinInput = /*#__PURE__*/React.forwardRef(function (_ref2, ref) {
|
|
|
15698
15718
|
autoFocus: autoFocus,
|
|
15699
15719
|
onFocus: focus,
|
|
15700
15720
|
onBlur: blur,
|
|
15701
|
-
maxLength: length,
|
|
15702
15721
|
pointerEvents: "box-none",
|
|
15703
15722
|
keyboardType: "numeric",
|
|
15704
15723
|
testID: "pin-hidden-input",
|
package/package.json
CHANGED
|
@@ -205,7 +205,6 @@ exports[`rendering renders correctly 1`] = `
|
|
|
205
205
|
autoFocus={false}
|
|
206
206
|
editable={true}
|
|
207
207
|
keyboardType="numeric"
|
|
208
|
-
maxLength={4}
|
|
209
208
|
onBlur={[Function]}
|
|
210
209
|
onChangeText={[Function]}
|
|
211
210
|
onFocus={[Function]}
|
|
@@ -462,7 +461,6 @@ exports[`rendering renders correctly when disabled 1`] = `
|
|
|
462
461
|
autoFocus={false}
|
|
463
462
|
editable={false}
|
|
464
463
|
keyboardType="numeric"
|
|
465
|
-
maxLength={4}
|
|
466
464
|
onBlur={[Function]}
|
|
467
465
|
onChangeText={[Function]}
|
|
468
466
|
onFocus={[Function]}
|
|
@@ -837,7 +835,6 @@ exports[`rendering renders correctly when length is 6 and secure is false 1`] =
|
|
|
837
835
|
autoFocus={false}
|
|
838
836
|
editable={true}
|
|
839
837
|
keyboardType="numeric"
|
|
840
|
-
maxLength={6}
|
|
841
838
|
onBlur={[Function]}
|
|
842
839
|
onChangeText={[Function]}
|
|
843
840
|
onFocus={[Function]}
|
|
@@ -1147,7 +1144,6 @@ exports[`rendering renders correctly when there is error 1`] = `
|
|
|
1147
1144
|
autoFocus={false}
|
|
1148
1145
|
editable={true}
|
|
1149
1146
|
keyboardType="numeric"
|
|
1150
|
-
maxLength={4}
|
|
1151
1147
|
onBlur={[Function]}
|
|
1152
1148
|
onChangeText={[Function]}
|
|
1153
1149
|
onFocus={[Function]}
|
|
@@ -1405,7 +1401,6 @@ exports[`rendering renders correctly with textContentType and autoComplete 1`] =
|
|
|
1405
1401
|
autoFocus={false}
|
|
1406
1402
|
editable={true}
|
|
1407
1403
|
keyboardType="numeric"
|
|
1408
|
-
maxLength={4}
|
|
1409
1404
|
onBlur={[Function]}
|
|
1410
1405
|
onChangeText={[Function]}
|
|
1411
1406
|
onFocus={[Function]}
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { fireEvent } from '@testing-library/react-native';
|
|
3
3
|
import { Platform } from 'react-native';
|
|
4
4
|
import renderWithTheme from '../../../testHelpers/renderWithTheme';
|
|
5
|
-
import PinInput, { getState } from '..';
|
|
5
|
+
import PinInput, { getState, normalizeValue } from '..';
|
|
6
6
|
|
|
7
7
|
describe('rendering', () => {
|
|
8
8
|
it('renders correctly', () => {
|
|
@@ -94,6 +94,62 @@ describe('behaviors', () => {
|
|
|
94
94
|
expect(onChangeText).toHaveBeenCalledWith('1234');
|
|
95
95
|
expect(onFulfill).toHaveBeenCalledWith('1234');
|
|
96
96
|
});
|
|
97
|
+
|
|
98
|
+
it.each`
|
|
99
|
+
value | expected
|
|
100
|
+
${'12 34'} | ${'1234'}
|
|
101
|
+
${'1 2 3 4'} | ${'1234'}
|
|
102
|
+
${' 1 2 3 4 '} | ${'1234'}
|
|
103
|
+
`(
|
|
104
|
+
'automatically trims whitespace characters when value is $value',
|
|
105
|
+
({ value, expected }) => {
|
|
106
|
+
const onChangeText = jest.fn();
|
|
107
|
+
const onFulfill = jest.fn();
|
|
108
|
+
const { getByTestId } = renderWithTheme(
|
|
109
|
+
<PinInput
|
|
110
|
+
secure={false}
|
|
111
|
+
value=""
|
|
112
|
+
onChangeText={onChangeText}
|
|
113
|
+
onFulfill={onFulfill}
|
|
114
|
+
/>
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
const pinInput = getByTestId('pin-hidden-input');
|
|
118
|
+
fireEvent.changeText(pinInput, value);
|
|
119
|
+
|
|
120
|
+
expect(onChangeText).toHaveBeenCalledWith(expected);
|
|
121
|
+
expect(onFulfill).toHaveBeenCalledWith(expected);
|
|
122
|
+
}
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
it.each`
|
|
126
|
+
value | length | expected
|
|
127
|
+
${'1234'} | ${4} | ${'1234'}
|
|
128
|
+
${'12345'} | ${4} | ${'1234'}
|
|
129
|
+
${'1234'} | ${6} | ${'1234'}
|
|
130
|
+
`(
|
|
131
|
+
'limits the value when value is $value and length is $length',
|
|
132
|
+
({ value, length, expected }) => {
|
|
133
|
+
const onChangeText = jest.fn();
|
|
134
|
+
const onFulfill = jest.fn();
|
|
135
|
+
const { getByTestId } = renderWithTheme(
|
|
136
|
+
<PinInput
|
|
137
|
+
value=""
|
|
138
|
+
length={length}
|
|
139
|
+
onChangeText={onChangeText}
|
|
140
|
+
onFulfill={onFulfill}
|
|
141
|
+
/>
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
const pinInput = getByTestId('pin-hidden-input');
|
|
145
|
+
fireEvent.changeText(pinInput, value);
|
|
146
|
+
|
|
147
|
+
expect(onChangeText).toHaveBeenCalledWith(expected);
|
|
148
|
+
if (length === expected.legth) {
|
|
149
|
+
expect(onFulfill).toHaveBeenCalledWith(expected);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
);
|
|
97
153
|
});
|
|
98
154
|
|
|
99
155
|
describe('getState', () => {
|
|
@@ -115,3 +171,30 @@ describe('getState', () => {
|
|
|
115
171
|
}
|
|
116
172
|
);
|
|
117
173
|
});
|
|
174
|
+
|
|
175
|
+
describe('normalizeValue', () => {
|
|
176
|
+
it.each`
|
|
177
|
+
value | expected
|
|
178
|
+
${''} | ${''}
|
|
179
|
+
${'1'} | ${'1'}
|
|
180
|
+
${'1234 '} | ${'1234'}
|
|
181
|
+
${' 1234'} | ${'1234'}
|
|
182
|
+
${'1 2 3 4'} | ${'1234'}
|
|
183
|
+
`('returns correct value without any whitespace', ({ value, expected }) => {
|
|
184
|
+
expect(normalizeValue(value)).toBe(expected);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it.each`
|
|
188
|
+
value | length | expected
|
|
189
|
+
${'1234'} | ${undefined} | ${'1234'}
|
|
190
|
+
${'1234'} | ${4} | ${'1234'}
|
|
191
|
+
${'12345'} | ${4} | ${'1234'}
|
|
192
|
+
${'1234'} | ${6} | ${'1234'}
|
|
193
|
+
${'12345'} | ${6} | ${'12345'}
|
|
194
|
+
`(
|
|
195
|
+
'returns correct value when length is $length',
|
|
196
|
+
({ value, length, expected }) => {
|
|
197
|
+
expect(normalizeValue(value, length)).toBe(expected);
|
|
198
|
+
}
|
|
199
|
+
);
|
|
200
|
+
});
|
|
@@ -99,6 +99,10 @@ export interface PinInputHandler {
|
|
|
99
99
|
*/
|
|
100
100
|
blur: () => void;
|
|
101
101
|
}
|
|
102
|
+
// Normalize the value to only contain numbers and limit the length
|
|
103
|
+
export const normalizeValue = (value?: string, length = 4) => {
|
|
104
|
+
return (value?.match(/\d/g) || []).join('').slice(0, length);
|
|
105
|
+
};
|
|
102
106
|
|
|
103
107
|
const PinInput = forwardRef<PinInputHandler, PinInputProps>(
|
|
104
108
|
(
|
|
@@ -121,8 +125,12 @@ const PinInput = forwardRef<PinInputHandler, PinInputProps>(
|
|
|
121
125
|
const inputRef = useRef<TextInput>(null);
|
|
122
126
|
const [focused, setFocused] = useState(autoFocus);
|
|
123
127
|
const state = getState({ disabled, error });
|
|
128
|
+
const trimmedValue = normalizeValue(value, length);
|
|
129
|
+
|
|
124
130
|
const maskedValueWithExtraSpace =
|
|
125
|
-
Platform.OS === 'android' && !
|
|
131
|
+
Platform.OS === 'android' && !trimmedValue ? '*' : trimmedValue;
|
|
132
|
+
|
|
133
|
+
const [hasFulfilled, setHasFulfilled] = useState(false);
|
|
126
134
|
|
|
127
135
|
const focus = useCallback(() => {
|
|
128
136
|
if (inputRef?.current) {
|
|
@@ -140,15 +148,30 @@ const PinInput = forwardRef<PinInputHandler, PinInputProps>(
|
|
|
140
148
|
|
|
141
149
|
const changeText = useCallback(
|
|
142
150
|
(text: string) => {
|
|
143
|
-
|
|
151
|
+
// If the input is already fulfilled and the user tries to remove characters
|
|
152
|
+
if (hasFulfilled && text.length < length) {
|
|
153
|
+
setHasFulfilled(false);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// If the input is already fulfilled and the user tries to add more characters
|
|
157
|
+
if (
|
|
158
|
+
hasFulfilled &&
|
|
159
|
+
(text?.match(/\d/g) || []).join('').length > length
|
|
160
|
+
) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Prevent user from entering more than the length
|
|
165
|
+
const trimmedPin = normalizeValue(text, length);
|
|
144
166
|
|
|
145
|
-
onChangeText?.(
|
|
167
|
+
onChangeText?.(trimmedPin);
|
|
146
168
|
|
|
147
|
-
if (
|
|
148
|
-
onFulfill?.(
|
|
169
|
+
if (trimmedPin.length === length) {
|
|
170
|
+
onFulfill?.(trimmedPin);
|
|
171
|
+
setHasFulfilled(true);
|
|
149
172
|
}
|
|
150
173
|
},
|
|
151
|
-
[length, onChangeText, onFulfill]
|
|
174
|
+
[length, onChangeText, onFulfill, hasFulfilled]
|
|
152
175
|
);
|
|
153
176
|
|
|
154
177
|
useEffect(() => {
|
|
@@ -170,9 +193,9 @@ const PinInput = forwardRef<PinInputHandler, PinInputProps>(
|
|
|
170
193
|
<React.Fragment key={index}>
|
|
171
194
|
{index !== 0 && <StyledSpacer />}
|
|
172
195
|
<PinCell
|
|
173
|
-
value={
|
|
196
|
+
value={trimmedValue.charAt(index)}
|
|
174
197
|
secure={secure}
|
|
175
|
-
focused={focused && index ===
|
|
198
|
+
focused={focused && index === trimmedValue.length}
|
|
176
199
|
state={state}
|
|
177
200
|
/>
|
|
178
201
|
</React.Fragment>
|
|
@@ -199,7 +222,6 @@ const PinInput = forwardRef<PinInputHandler, PinInputProps>(
|
|
|
199
222
|
autoFocus={autoFocus}
|
|
200
223
|
onFocus={focus}
|
|
201
224
|
onBlur={blur}
|
|
202
|
-
maxLength={length}
|
|
203
225
|
pointerEvents="box-none"
|
|
204
226
|
keyboardType="numeric"
|
|
205
227
|
testID="pin-hidden-input"
|
|
@@ -64,5 +64,6 @@ export interface PinInputHandler {
|
|
|
64
64
|
*/
|
|
65
65
|
blur: () => void;
|
|
66
66
|
}
|
|
67
|
+
export declare const normalizeValue: (value?: string, length?: number) => string;
|
|
67
68
|
declare const PinInput: React.ForwardRefExoticComponent<PinInputProps & React.RefAttributes<PinInputHandler>>;
|
|
68
69
|
export default PinInput;
|
package/.turbo/turbo-build.log
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
[36m
|
|
2
|
-
[1msrc/index.ts[22m → [1mlib/index.js, es/index.js[22m...[39m
|
|
3
|
-
[1m[33m(!) Plugin replace: @rollup/plugin-replace: 'preventAssignment' currently defaults to false. It is recommended to set this option to `true`, as the next major version will default this option to `true`.[39m[22m
|
|
4
|
-
[1m[33m(!) Plugin node-resolve: preferring built-in module 'events' over local alternative at '/home/runner/work/hero-design/hero-design/node_modules/events/events.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning[39m[22m
|
|
5
|
-
[32mcreated [1mlib/index.js, es/index.js[22m in [1m1m 1.2s[22m[39m
|