@jobber/components-native 0.31.0 → 0.32.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.
@@ -0,0 +1,82 @@
1
+ import React, { forwardRef, useState } from "react";
2
+ import { Platform } from "react-native";
3
+ import { useIntl } from "react-intl";
4
+ import flow from "lodash/flow";
5
+ import identity from "lodash/identity";
6
+ import { messages } from "./messages";
7
+ import { InputText } from "../InputText";
8
+ const NUMBER_VALIDATION_REGEX = /^[-+]?(([0-9]*\.[0-9]+)|([0-9]+)|([0-9]+(\.?[0-9]+)?e[-+]?[0-9]+))$/;
9
+ export const InputNumber = forwardRef(InputNumberInternal);
10
+ function InputNumberInternal(props, ref) {
11
+ var _a, _b, _c, _d;
12
+ const getKeyboard = () => {
13
+ var _a;
14
+ if (Platform.OS === "ios") {
15
+ //since we are checking for which keyboard to use here here, just implement default keyboard here instead of in params
16
+ return (_a = props.keyboard) !== null && _a !== void 0 ? _a : "numbers-and-punctuation";
17
+ }
18
+ else {
19
+ return "numeric";
20
+ }
21
+ };
22
+ const { formatMessage } = useIntl();
23
+ const handleChange = (newValue) => {
24
+ var _a;
25
+ (_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, newValue);
26
+ };
27
+ const { inputTransform: convertToString, outputTransform: convertToNumber } = useNumberTransform(props.value);
28
+ return (React.createElement(InputText, Object.assign({}, props, { keyboard: getKeyboard(), transform: {
29
+ input: flow(convertToString, ((_a = props.transform) === null || _a === void 0 ? void 0 : _a.input) || identity),
30
+ output: flow(convertToNumber, ((_b = props.transform) === null || _b === void 0 ? void 0 : _b.output) || identity),
31
+ }, ref: ref, value: (_c = props.value) === null || _c === void 0 ? void 0 : _c.toString(), defaultValue: (_d = props.defaultValue) === null || _d === void 0 ? void 0 : _d.toString(), onChangeText: handleChange, validations: Object.assign({ pattern: {
32
+ value: NUMBER_VALIDATION_REGEX,
33
+ message: formatMessage(messages.notANumberError),
34
+ } }, props.validations) })));
35
+ }
36
+ function hasPeriodAtEnd(value) {
37
+ // matches patterns like ".", "0.", "12.", "+1.", and "-0."
38
+ return !!(value === null || value === void 0 ? void 0 : value.match(/^[-+]?[0-9]*\.$/));
39
+ }
40
+ function hasScientificNotationAtEnd(value) {
41
+ // matches patterns like "1e", "+2e", "1.2e" and "-3e"
42
+ return !!(value === null || value === void 0 ? void 0 : value.match(/^[-+]?[0-9]+(\.?[0-9]+)?e$/));
43
+ }
44
+ function hasPlusMinusAtEnd(value) {
45
+ // matches "+" and "-"
46
+ return !!(value === null || value === void 0 ? void 0 : value.match(/^[-+]+$/));
47
+ }
48
+ function hasZeroDecimalAtEnd(value) {
49
+ // matches patterns like "0.0", "+0.00000", "-3.00000", "2.100", ".0", and ".00000"
50
+ return !!(value === null || value === void 0 ? void 0 : value.match(/^[-+]?[0-9]*\.[0-9]*0+$/));
51
+ }
52
+ export function shouldShowUserValue(value) {
53
+ const specialCasesFn = [
54
+ hasPeriodAtEnd,
55
+ hasScientificNotationAtEnd,
56
+ hasPlusMinusAtEnd,
57
+ hasZeroDecimalAtEnd,
58
+ ];
59
+ const isSpecial = (v) => specialCasesFn.reduce((acc, fn) => acc || fn(v), false);
60
+ return isSpecial(value);
61
+ }
62
+ export function useNumberTransform(controlledValue) {
63
+ const [typedValue, setTypedValue] = useState((controlledValue === null || controlledValue === void 0 ? void 0 : controlledValue.toString()) || "");
64
+ const convertToNumber = (newValue) => {
65
+ var _a;
66
+ setTypedValue(newValue);
67
+ if ((_a = newValue === null || newValue === void 0 ? void 0 : newValue.match) === null || _a === void 0 ? void 0 : _a.call(newValue, NUMBER_VALIDATION_REGEX)) {
68
+ return parseFloat(newValue);
69
+ }
70
+ return newValue;
71
+ };
72
+ const convertToString = (internalValue) => {
73
+ if (shouldShowUserValue(typedValue)) {
74
+ return typedValue;
75
+ }
76
+ return (internalValue === null || internalValue === void 0 ? void 0 : internalValue.toString()) || undefined;
77
+ };
78
+ return {
79
+ inputTransform: convertToString,
80
+ outputTransform: convertToNumber,
81
+ };
82
+ }
@@ -0,0 +1 @@
1
+ export { InputNumber } from "./InputNumber";
@@ -0,0 +1,8 @@
1
+ import { defineMessages } from "react-intl";
2
+ export const messages = defineMessages({
3
+ notANumberError: {
4
+ id: "notANumberError",
5
+ defaultMessage: "Enter a number",
6
+ description: "Error message shown when a non-numeric value is typed in number input",
7
+ },
8
+ });
package/dist/src/index.js CHANGED
@@ -17,6 +17,7 @@ export * from "./Heading";
17
17
  export * from "./Icon";
18
18
  export * from "./IconButton";
19
19
  export * from "./InputFieldWrapper";
20
+ export * from "./InputNumber";
20
21
  export * from "./InputPassword";
21
22
  export * from "./InputPressable";
22
23
  export * from "./InputSearch";