@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 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 maskedValueWithExtraSpace = Platform.OS === 'android' && !value ? '*' : value;
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
- var pin = (text.match(/\d/g) || []).join('');
15627
- onChangeText === null || onChangeText === void 0 || onChangeText(pin);
15628
- if (pin.length === length) {
15629
- onFulfill === null || onFulfill === void 0 || onFulfill(pin);
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: value.charAt(index),
15671
+ value: trimmedValue.charAt(index),
15652
15672
  secure: secure,
15653
- focused: focused && index === value.length,
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 maskedValueWithExtraSpace = reactNative.Platform.OS === 'android' && !value ? '*' : value;
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
- var pin = (text.match(/\d/g) || []).join('');
15657
- onChangeText === null || onChangeText === void 0 || onChangeText(pin);
15658
- if (pin.length === length) {
15659
- onFulfill === null || onFulfill === void 0 || onFulfill(pin);
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: value.charAt(index),
15701
+ value: trimmedValue.charAt(index),
15682
15702
  secure: secure,
15683
- focused: focused && index === value.length,
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hero-design/rn",
3
- "version": "8.64.6",
3
+ "version": "8.64.7-alpha.1",
4
4
  "license": "MIT",
5
5
  "main": "lib/index.js",
6
6
  "module": "es/index.js",
@@ -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' && !value ? '*' : value;
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
- const pin = (text.match(/\d/g) || []).join('');
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?.(pin);
167
+ onChangeText?.(trimmedPin);
146
168
 
147
- if (pin.length === length) {
148
- onFulfill?.(pin);
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={value.charAt(index)}
196
+ value={trimmedValue.charAt(index)}
174
197
  secure={secure}
175
- focused={focused && index === value.length}
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;
@@ -1,5 +0,0 @@
1
- 
2
- src/index.ts → lib/index.js, es/index.js...
3
- (!) 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`.
4
- (!) 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
5
- created lib/index.js, es/index.js in 1m 1.2s