@servicetitan/form 31.2.0 → 32.0.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/dist/color-picker/color-palette.js +8 -9
- package/dist/color-picker/color-palette.js.map +1 -1
- package/dist/color-picker/color-picker.js +46 -9
- package/dist/color-picker/color-picker.js.map +1 -1
- package/dist/color-picker/color-picker.module.css.d.ts +4 -0
- package/dist/color-picker/index.js +1 -0
- package/dist/color-picker/index.js.map +1 -1
- package/dist/date-range-picker/date-range-picker.js +205 -174
- package/dist/date-range-picker/date-range-picker.js.map +1 -1
- package/dist/date-range-picker/date-range-picker.module.css.d.ts +8 -0
- package/dist/date-range-picker/index.js +1 -0
- package/dist/date-range-picker/index.js.map +1 -1
- package/dist/demo/color-picker.js +39 -4
- package/dist/demo/color-picker.js.map +1 -1
- package/dist/demo/date-range-picker.js +18 -2
- package/dist/demo/date-range-picker.js.map +1 -1
- package/dist/demo/file-uploader.js +94 -12
- package/dist/demo/file-uploader.js.map +1 -1
- package/dist/demo/index.js +1 -0
- package/dist/demo/index.js.map +1 -1
- package/dist/demo/input-date-mask.js +18 -2
- package/dist/demo/input-date-mask.js.map +1 -1
- package/dist/demo/number-input.js +121 -3
- package/dist/demo/number-input.js.map +1 -1
- package/dist/demo/original-number-input.js +18 -2
- package/dist/demo/original-number-input.js.map +1 -1
- package/dist/demo/phone-number-input.js +5 -1
- package/dist/demo/phone-number-input.js.map +1 -1
- package/dist/file-uploader/config.js +10 -1
- package/dist/file-uploader/config.js.map +1 -1
- package/dist/file-uploader/file-uploader.js +189 -192
- package/dist/file-uploader/file-uploader.js.map +1 -1
- package/dist/file-uploader/index.js +3 -1
- package/dist/file-uploader/index.js.map +1 -1
- package/dist/file-uploader/uploader.js +57 -41
- package/dist/file-uploader/uploader.js.map +1 -1
- package/dist/form-state-error-banner/form-state-error-banner.js +15 -5
- package/dist/form-state-error-banner/form-state-error-banner.js.map +1 -1
- package/dist/form-state-error-banner/index.js +1 -0
- package/dist/form-state-error-banner/index.js.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/input-date-mask/index.js +1 -0
- package/dist/input-date-mask/index.js.map +1 -1
- package/dist/input-date-mask/input-date-mask.js +47 -28
- package/dist/input-date-mask/input-date-mask.js.map +1 -1
- package/dist/input-date-mask/input-date-mask.module.css.d.ts +4 -0
- package/dist/label/index.js +1 -0
- package/dist/label/index.js.map +1 -1
- package/dist/label/label.js +29 -1
- package/dist/label/label.js.map +1 -1
- package/dist/label/label.module.css.d.ts +7 -0
- package/dist/masked-input.js +17 -4
- package/dist/masked-input.js.map +1 -1
- package/dist/number-input/common-interfaces.js +2 -1
- package/dist/number-input/common-interfaces.js.map +1 -1
- package/dist/number-input/get-formatted-string.js +2 -3
- package/dist/number-input/get-formatted-string.js.map +1 -1
- package/dist/number-input/index.js +1 -0
- package/dist/number-input/index.js.map +1 -1
- package/dist/number-input/number-input.js +53 -42
- package/dist/number-input/number-input.js.map +1 -1
- package/dist/number-input/process-value.js +10 -16
- package/dist/number-input/process-value.js.map +1 -1
- package/dist/original-number-input/index.js +1 -0
- package/dist/original-number-input/index.js.map +1 -1
- package/dist/original-number-input/ordinal-number-input.js +54 -59
- package/dist/original-number-input/ordinal-number-input.js.map +1 -1
- package/dist/phone-number-input/index.js +1 -0
- package/dist/phone-number-input/index.js.map +1 -1
- package/dist/phone-number-input/phone-number-input.js +13 -1
- package/dist/phone-number-input/phone-number-input.js.map +1 -1
- package/package.json +13 -13
- package/dist/form.stories.js +0 -20
- package/dist/form.stories.js.map +0 -1
- package/dist/number-input/__tests__/get-formatted-string.test.js +0 -41
- package/dist/number-input/__tests__/get-formatted-string.test.js.map +0 -1
- package/dist/number-input/__tests__/process-value.test.js +0 -283
- package/dist/number-input/__tests__/process-value.test.js.map +0 -1
- package/dist/original-number-input/__tests__/ordinal-number-input.test.js +0 -51
- package/dist/original-number-input/__tests__/ordinal-number-input.test.js.map +0 -1
@@ -1,5 +1,5 @@
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
2
|
-
import { useCallback, useState, useEffect, useRef
|
2
|
+
import { useCallback, useState, useEffect, useRef } from 'react';
|
3
3
|
import { useOptionalDependencies } from '@servicetitan/react-ioc';
|
4
4
|
import { Input } from '@servicetitan/design-system';
|
5
5
|
import { CULTURE_TOKEN } from '@servicetitan/culture';
|
@@ -10,45 +10,49 @@ import debounce from 'debounce';
|
|
10
10
|
const ARROW_UP_KEY = 38;
|
11
11
|
const ARROW_DOWN_KEY = 40;
|
12
12
|
const DEBOUNCE_WAIT = 300;
|
13
|
-
export const NumberInput = ({ value, onChange, onFocus, onBlur, emptyValue, decimalPlaces, useEmptyThousandsSeparator, min, max, useKeyboardNavigation, formatNumber = formatNumberDefault, ...props })
|
14
|
-
const [{ NumberFormat: { NumberGroupSeparator: thousandsSeparator = ',', NumberDecimalSeparator: decimalSeparator = '.'
|
15
|
-
const getFormattedValue = useCallback(()
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
13
|
+
export const NumberInput = ({ value, onChange, onFocus, onBlur, emptyValue, decimalPlaces, useEmptyThousandsSeparator, min, max, useKeyboardNavigation, formatNumber = formatNumberDefault, ...props })=>{
|
14
|
+
const [{ NumberFormat: { NumberGroupSeparator: thousandsSeparator = ',', NumberDecimalSeparator: decimalSeparator = '.' } = {} } = {}] = useOptionalDependencies(CULTURE_TOKEN);
|
15
|
+
const getFormattedValue = useCallback(()=>getFormattedString(value, {
|
16
|
+
emptyValue,
|
17
|
+
precision: decimalPlaces,
|
18
|
+
separators: {
|
19
|
+
thousand: useEmptyThousandsSeparator ? '' : thousandsSeparator,
|
20
|
+
decimal: decimalSeparator
|
21
|
+
}
|
22
|
+
}, formatNumber), [
|
23
23
|
decimalPlaces,
|
24
24
|
decimalSeparator,
|
25
25
|
emptyValue,
|
26
26
|
thousandsSeparator,
|
27
27
|
useEmptyThousandsSeparator,
|
28
28
|
value,
|
29
|
-
formatNumber
|
29
|
+
formatNumber
|
30
30
|
]);
|
31
31
|
const [isFocused, setIsFocused] = useState(false);
|
32
32
|
const [state, setState] = useState({
|
33
33
|
numberValue: value,
|
34
|
-
stringValue: getFormattedValue()
|
34
|
+
stringValue: getFormattedValue()
|
35
35
|
});
|
36
|
-
useEffect(()
|
36
|
+
useEffect(()=>{
|
37
37
|
if (isFocused) {
|
38
38
|
return;
|
39
39
|
}
|
40
40
|
setState({
|
41
41
|
numberValue: value,
|
42
|
-
stringValue: getFormattedValue()
|
42
|
+
stringValue: getFormattedValue()
|
43
43
|
});
|
44
|
-
}, [
|
45
|
-
|
44
|
+
}, [
|
45
|
+
value,
|
46
|
+
getFormattedValue,
|
47
|
+
isFocused
|
48
|
+
]);
|
49
|
+
const handleChange = (_0, { value })=>{
|
46
50
|
updateValue(value);
|
47
51
|
};
|
48
|
-
const handleKeyDown = (event)
|
49
|
-
var _a;
|
52
|
+
const handleKeyDown = (event)=>{
|
50
53
|
if (event.keyCode === ARROW_UP_KEY || event.keyCode === ARROW_DOWN_KEY) {
|
51
|
-
|
54
|
+
var _state_numberValue;
|
55
|
+
const newValue = ((_state_numberValue = state.numberValue) !== null && _state_numberValue !== void 0 ? _state_numberValue : 0) + (event.keyCode === ARROW_UP_KEY ? 1 : -1);
|
52
56
|
updateValue(String(newValue));
|
53
57
|
event.preventDefault();
|
54
58
|
}
|
@@ -58,15 +62,14 @@ export const NumberInput = ({ value, onChange, onFocus, onBlur, emptyValue, deci
|
|
58
62
|
** then "updateClampedValueDebounced" updates applying the min/max after debounce delay
|
59
63
|
**
|
60
64
|
** Example: User can type "100" if min is "5" without the "1" immediately being clamped
|
61
|
-
*/
|
62
|
-
const updateImmediateValue = (value, silent = false) => {
|
65
|
+
*/ const updateImmediateValue = (value, silent = false)=>{
|
63
66
|
const newState = processValue(value, {
|
64
67
|
emptyValue,
|
65
68
|
precision: decimalPlaces,
|
66
69
|
separators: {
|
67
70
|
thousand: thousandsSeparator,
|
68
|
-
decimal: decimalSeparator
|
69
|
-
}
|
71
|
+
decimal: decimalSeparator
|
72
|
+
}
|
70
73
|
}, formatNumber);
|
71
74
|
setState(newState);
|
72
75
|
if (!silent) {
|
@@ -74,18 +77,21 @@ export const NumberInput = ({ value, onChange, onFocus, onBlur, emptyValue, deci
|
|
74
77
|
}
|
75
78
|
};
|
76
79
|
const updateClampedValueDebounced = useRef();
|
77
|
-
useEffect(()
|
80
|
+
useEffect(()=>{
|
78
81
|
let isCurrent = true;
|
79
|
-
const updateClampedValue = (value, silent = false)
|
82
|
+
const updateClampedValue = (value, silent = false)=>{
|
80
83
|
if (isCurrent) {
|
81
84
|
const newState = processValue(value, {
|
82
85
|
emptyValue,
|
83
86
|
precision: decimalPlaces,
|
84
87
|
separators: {
|
85
88
|
thousand: thousandsSeparator,
|
86
|
-
decimal: decimalSeparator
|
89
|
+
decimal: decimalSeparator
|
87
90
|
},
|
88
|
-
range: {
|
91
|
+
range: {
|
92
|
+
min,
|
93
|
+
max
|
94
|
+
}
|
89
95
|
}, formatNumber);
|
90
96
|
setState(newState);
|
91
97
|
if (!silent) {
|
@@ -94,7 +100,7 @@ export const NumberInput = ({ value, onChange, onFocus, onBlur, emptyValue, deci
|
|
94
100
|
}
|
95
101
|
};
|
96
102
|
updateClampedValueDebounced.current = debounce(updateClampedValue, DEBOUNCE_WAIT);
|
97
|
-
return ()
|
103
|
+
return ()=>{
|
98
104
|
isCurrent = false;
|
99
105
|
};
|
100
106
|
}, [
|
@@ -105,36 +111,41 @@ export const NumberInput = ({ value, onChange, onFocus, onBlur, emptyValue, deci
|
|
105
111
|
min,
|
106
112
|
max,
|
107
113
|
formatNumber,
|
108
|
-
onChange
|
114
|
+
onChange
|
109
115
|
]);
|
110
|
-
const updateValue = (value, silent = false)
|
111
|
-
var
|
116
|
+
const updateValue = (value, silent = false)=>{
|
117
|
+
var _updateClampedValueDebounced_current;
|
112
118
|
updateImmediateValue(value, silent);
|
113
|
-
(
|
119
|
+
(_updateClampedValueDebounced_current = updateClampedValueDebounced.current) === null || _updateClampedValueDebounced_current === void 0 ? void 0 : _updateClampedValueDebounced_current.call(updateClampedValueDebounced, value, silent);
|
114
120
|
};
|
115
|
-
const handleFocus = (event)
|
121
|
+
const handleFocus = (event)=>{
|
116
122
|
if (state.stringValue.length) {
|
117
|
-
updateValue(
|
118
|
-
|
119
|
-
decimalPlaces
|
120
|
-
? state.stringValue.replace(new RegExp(`[${decimalSeparator}]?0+$`), '')
|
121
|
-
: state.stringValue, true);
|
123
|
+
updateValue(// prepare the value which user does see (rounded), but without trailing zeroes after decimal and separator
|
124
|
+
decimalPlaces ? state.stringValue.replace(new RegExp(`[${decimalSeparator}]?0+$`), '') : state.stringValue, true);
|
122
125
|
}
|
123
126
|
setIsFocused(true);
|
124
127
|
if (onFocus) {
|
125
128
|
onFocus(event);
|
126
129
|
}
|
127
130
|
};
|
128
|
-
const handleBlur = (event)
|
131
|
+
const handleBlur = (event)=>{
|
129
132
|
setState({
|
130
133
|
numberValue: value,
|
131
|
-
stringValue: getFormattedValue()
|
134
|
+
stringValue: getFormattedValue()
|
132
135
|
});
|
133
136
|
setIsFocused(false);
|
134
137
|
if (onBlur) {
|
135
138
|
onBlur(event);
|
136
139
|
}
|
137
140
|
};
|
138
|
-
return
|
141
|
+
return /*#__PURE__*/ _jsx(Input, {
|
142
|
+
...props,
|
143
|
+
value: state.stringValue,
|
144
|
+
onChange: handleChange,
|
145
|
+
onFocus: handleFocus,
|
146
|
+
onBlur: handleBlur,
|
147
|
+
onKeyDown: useKeyboardNavigation ? handleKeyDown : undefined
|
148
|
+
});
|
139
149
|
};
|
150
|
+
|
140
151
|
//# sourceMappingURL=number-input.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"number-input.js","sourceRoot":"","sources":["../../src/number-input/number-input.tsx"],"names":[],"mappings":"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"}
|
1
|
+
{"version":3,"sources":["../../src/number-input/number-input.tsx"],"sourcesContent":["import {\n useCallback,\n useState,\n useEffect,\n useRef,\n SyntheticEvent,\n KeyboardEvent,\n FocusEvent,\n} from 'react';\n\nimport { useOptionalDependencies } from '@servicetitan/react-ioc';\n\nimport { Input, InputProps, InputOnChangeData } from '@servicetitan/design-system';\nimport { CULTURE_TOKEN } from '@servicetitan/culture';\n\nimport { processValue } from './process-value';\nimport { FormatNumber, getFormattedString } from './get-formatted-string';\nimport { EmptyValue, NumberValue } from './common-interfaces';\nimport { formatNumber as formatNumberDefault } from 'accounting';\n\nimport debounce from 'debounce';\n\nconst ARROW_UP_KEY = 38;\nconst ARROW_DOWN_KEY = 40;\nconst DEBOUNCE_WAIT = 300;\n\nexport interface NumberInputProps<TEmpty extends EmptyValue>\n extends Omit<InputProps, 'value' | 'onChange'> {\n value: NumberValue<TEmpty>;\n emptyValue: TEmpty;\n decimalPlaces?: number;\n useEmptyThousandsSeparator?: boolean;\n min?: number;\n max?: number;\n useKeyboardNavigation?: boolean;\n formatNumber?: FormatNumber;\n onChange(value: NumberValue<TEmpty>): void;\n}\n\nexport const NumberInput = <TEmpty extends EmptyValue>({\n value,\n onChange,\n onFocus,\n onBlur,\n emptyValue,\n decimalPlaces,\n useEmptyThousandsSeparator,\n min,\n max,\n useKeyboardNavigation,\n formatNumber = formatNumberDefault,\n ...props\n}: NumberInputProps<TEmpty>) => {\n const [\n {\n NumberFormat: {\n NumberGroupSeparator: thousandsSeparator = ',',\n NumberDecimalSeparator: decimalSeparator = '.',\n } = {},\n } = {},\n ] = useOptionalDependencies(CULTURE_TOKEN);\n\n const getFormattedValue = useCallback(\n () =>\n getFormattedString(\n value,\n {\n emptyValue,\n precision: decimalPlaces,\n separators: {\n thousand: useEmptyThousandsSeparator ? '' : thousandsSeparator,\n decimal: decimalSeparator,\n },\n },\n formatNumber\n ),\n [\n decimalPlaces,\n decimalSeparator,\n emptyValue,\n thousandsSeparator,\n useEmptyThousandsSeparator,\n value,\n formatNumber,\n ]\n );\n\n const [isFocused, setIsFocused] = useState(false);\n const [state, setState] = useState({\n numberValue: value,\n stringValue: getFormattedValue(),\n });\n\n useEffect(() => {\n if (isFocused) {\n return;\n }\n\n setState({\n numberValue: value,\n stringValue: getFormattedValue(),\n });\n }, [value, getFormattedValue, isFocused]);\n\n const handleChange = (_0: SyntheticEvent<HTMLInputElement>, { value }: InputOnChangeData) => {\n updateValue(value);\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.keyCode === ARROW_UP_KEY || event.keyCode === ARROW_DOWN_KEY) {\n const newValue = (state.numberValue ?? 0) + (event.keyCode === ARROW_UP_KEY ? 1 : -1);\n\n updateValue(String(newValue));\n event.preventDefault();\n }\n };\n\n /*\n ** \"updateImmediateValue\" updates the value immediately without clamping min/max,\n ** then \"updateClampedValueDebounced\" updates applying the min/max after debounce delay\n **\n ** Example: User can type \"100\" if min is \"5\" without the \"1\" immediately being clamped\n */\n const updateImmediateValue = (value: string, silent = false) => {\n const newState = processValue(\n value,\n {\n emptyValue,\n precision: decimalPlaces,\n separators: {\n thousand: thousandsSeparator,\n decimal: decimalSeparator,\n },\n },\n formatNumber\n );\n\n setState(newState);\n\n if (!silent) {\n onChange(newState.numberValue);\n }\n };\n\n const updateClampedValueDebounced = useRef<(value: string, silent: boolean) => void>();\n\n useEffect(() => {\n let isCurrent = true;\n\n const updateClampedValue = (value: string, silent = false) => {\n if (isCurrent) {\n const newState = processValue(\n value,\n {\n emptyValue,\n precision: decimalPlaces,\n separators: {\n thousand: thousandsSeparator,\n decimal: decimalSeparator,\n },\n range: { min, max },\n },\n formatNumber\n );\n\n setState(newState);\n\n if (!silent) {\n onChange(newState.numberValue);\n }\n }\n };\n\n updateClampedValueDebounced.current = debounce(updateClampedValue, DEBOUNCE_WAIT);\n\n return () => {\n isCurrent = false;\n };\n }, [\n emptyValue,\n decimalPlaces,\n thousandsSeparator,\n decimalSeparator,\n min,\n max,\n formatNumber,\n onChange,\n ]);\n\n const updateValue = (value: string, silent = false) => {\n updateImmediateValue(value, silent);\n updateClampedValueDebounced.current?.(value, silent);\n };\n\n const handleFocus = (event: FocusEvent<HTMLInputElement>) => {\n if (state.stringValue.length) {\n updateValue(\n // prepare the value which user does see (rounded), but without trailing zeroes after decimal and separator\n decimalPlaces\n ? state.stringValue.replace(new RegExp(`[${decimalSeparator}]?0+$`), '')\n : state.stringValue,\n true\n );\n }\n\n setIsFocused(true);\n\n if (onFocus) {\n onFocus(event);\n }\n };\n\n const handleBlur = (event: FocusEvent<HTMLInputElement>) => {\n setState({\n numberValue: value,\n stringValue: getFormattedValue(),\n });\n\n setIsFocused(false);\n\n if (onBlur) {\n onBlur(event);\n }\n };\n\n return (\n <Input\n {...props}\n value={state.stringValue}\n onChange={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={useKeyboardNavigation ? handleKeyDown : undefined}\n />\n );\n};\n"],"names":["useCallback","useState","useEffect","useRef","useOptionalDependencies","Input","CULTURE_TOKEN","processValue","getFormattedString","formatNumber","formatNumberDefault","debounce","ARROW_UP_KEY","ARROW_DOWN_KEY","DEBOUNCE_WAIT","NumberInput","value","onChange","onFocus","onBlur","emptyValue","decimalPlaces","useEmptyThousandsSeparator","min","max","useKeyboardNavigation","props","NumberFormat","NumberGroupSeparator","thousandsSeparator","NumberDecimalSeparator","decimalSeparator","getFormattedValue","precision","separators","thousand","decimal","isFocused","setIsFocused","state","setState","numberValue","stringValue","handleChange","_0","updateValue","handleKeyDown","event","keyCode","newValue","String","preventDefault","updateImmediateValue","silent","newState","updateClampedValueDebounced","isCurrent","updateClampedValue","range","current","handleFocus","length","replace","RegExp","handleBlur","onKeyDown","undefined"],"mappings":"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"}
|
@@ -9,15 +9,14 @@ export function processValue(value, { emptyValue, precision, separators, range =
|
|
9
9
|
if (range.min && clampedNumber < range.min) {
|
10
10
|
clampedNumber = range.min;
|
11
11
|
clampedString = formatNumber(range.min, 0, '', separators.decimal);
|
12
|
-
}
|
13
|
-
else if (range.max && clampedNumber > range.max) {
|
12
|
+
} else if (range.max && clampedNumber > range.max) {
|
14
13
|
clampedNumber = range.max;
|
15
14
|
clampedString = formatNumber(range.max, 0, '', separators.decimal);
|
16
15
|
}
|
17
16
|
}
|
18
17
|
return {
|
19
18
|
numberValue: clampedNumber,
|
20
|
-
stringValue: clampedString
|
19
|
+
stringValue: clampedString
|
21
20
|
};
|
22
21
|
}
|
23
22
|
// Trim decimal places
|
@@ -26,12 +25,10 @@ export function processValue(value, { emptyValue, precision, separators, range =
|
|
26
25
|
const inputNumberValue = parseFloat(inputValue);
|
27
26
|
const numberValue = clamp(inputNumberValue, range);
|
28
27
|
// if not out of bound, use inputValue to preserve punctuation, otherwise use numberValue
|
29
|
-
const stringValue = numberValue === inputNumberValue
|
30
|
-
? inputValue
|
31
|
-
: formatNumber(numberValue, 0, '', separators.decimal);
|
28
|
+
const stringValue = numberValue === inputNumberValue ? inputValue : formatNumber(numberValue, 0, '', separators.decimal);
|
32
29
|
return {
|
33
30
|
stringValue,
|
34
|
-
numberValue: numberValue
|
31
|
+
numberValue: numberValue
|
35
32
|
};
|
36
33
|
}
|
37
34
|
function trimDecimalPlace(value, separator, formatNumber, precision) {
|
@@ -58,15 +55,12 @@ function cleanValue(value, separators) {
|
|
58
55
|
const thousandsSeparatorRegEx = new RegExp(`[${separators.thousand}]{1,}`, 'g');
|
59
56
|
const decimalSeparatorRegEx = new RegExp(`[${separators.decimal}+]{1,}`, 'g');
|
60
57
|
const excessiveMinusSignRegEx = /(?!^)-/g;
|
61
|
-
const cleanedValue = value
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
// Remove excessive decimal separators
|
67
|
-
.replace(decimalSeparatorRegEx, separators.decimal)
|
68
|
-
// Remove excessive minus signs
|
69
|
-
.replace(excessiveMinusSignRegEx, '');
|
58
|
+
const cleanedValue = value// Remove invalid characters
|
59
|
+
.replace(/[^0-9.,-]/g, '')// Remove thousand separators
|
60
|
+
.replace(thousandsSeparatorRegEx, '')// Remove excessive decimal separators
|
61
|
+
.replace(decimalSeparatorRegEx, separators.decimal)// Remove excessive minus signs
|
62
|
+
.replace(excessiveMinusSignRegEx, '');
|
70
63
|
return cleanedValue;
|
71
64
|
}
|
65
|
+
|
72
66
|
//# sourceMappingURL=process-value.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"
|
1
|
+
{"version":3,"sources":["../../src/number-input/process-value.ts"],"sourcesContent":["import { formatNumber as formatNumberDefault } from 'accounting';\n\nimport { EmptyValue, NumberValue, Range, Separators } from './common-interfaces';\nimport { FormatNumber } from './get-formatted-string';\n\ninterface ProcessValueOptions<TEmpty extends EmptyValue> {\n emptyValue: TEmpty;\n precision?: number;\n separators: Separators;\n range?: Range;\n}\n\nexport function processValue<TEmpty extends EmptyValue>(\n value: string,\n { emptyValue, precision, separators, range = {} }: ProcessValueOptions<TEmpty>,\n formatNumber: FormatNumber = formatNumberDefault\n) {\n let inputValue = cleanValue(value, separators);\n\n // Handle empty string\n if (inputValue === '' || inputValue === '-') {\n let clampedNumber = emptyValue as number | undefined;\n let clampedString = inputValue;\n if (clampedNumber === 0) {\n if (range.min && clampedNumber < range.min) {\n clampedNumber = range.min;\n clampedString = formatNumber(range.min, 0, '', separators.decimal);\n } else if (range.max && clampedNumber > range.max) {\n clampedNumber = range.max;\n clampedString = formatNumber(range.max, 0, '', separators.decimal);\n }\n }\n return {\n numberValue: clampedNumber as NumberValue<TEmpty>,\n stringValue: clampedString,\n };\n }\n\n // Trim decimal places\n inputValue = trimDecimalPlace(inputValue, separators.decimal, formatNumber, precision);\n\n // Parse string to number and clamp\n const inputNumberValue = parseFloat(inputValue);\n const numberValue = clamp(inputNumberValue, range);\n\n // if not out of bound, use inputValue to preserve punctuation, otherwise use numberValue\n const stringValue =\n numberValue === inputNumberValue\n ? inputValue\n : formatNumber(numberValue, 0, '', separators.decimal);\n\n return {\n stringValue,\n numberValue: numberValue as NumberValue<TEmpty>,\n };\n}\n\nfunction trimDecimalPlace(\n value: string,\n separator: string,\n formatNumber: FormatNumber,\n precision?: number\n) {\n const decimalPosition = value.indexOf(separator);\n if (decimalPosition >= 0) {\n if (precision) {\n const isNegative = value.startsWith('-');\n const splitValue = value.split(separator);\n const intPart = (isNegative ? '-' : '') + String(Math.abs(+splitValue[0]));\n let fracPart = splitValue[1];\n if (fracPart && fracPart.length > precision) {\n fracPart = fracPart.slice(0, precision);\n }\n return `${intPart}.${fracPart}`;\n }\n\n return value.substr(0, decimalPosition);\n }\n return String(+value);\n}\n\nfunction clamp(value: number, { min = -Infinity, max = Infinity }: Range) {\n return Math.max(Math.min(value, max), min);\n}\n\nfunction cleanValue(value: string, separators: Separators) {\n const thousandsSeparatorRegEx = new RegExp(`[${separators.thousand}]{1,}`, 'g');\n const decimalSeparatorRegEx = new RegExp(`[${separators.decimal}+]{1,}`, 'g');\n const excessiveMinusSignRegEx = /(?!^)-/g;\n const cleanedValue = value\n // Remove invalid characters\n .replace(/[^0-9.,-]/g, '')\n // Remove thousand separators\n .replace(thousandsSeparatorRegEx, '')\n // Remove excessive decimal separators\n .replace(decimalSeparatorRegEx, separators.decimal)\n // Remove excessive minus signs\n .replace(excessiveMinusSignRegEx, '');\n\n return cleanedValue;\n}\n"],"names":["formatNumber","formatNumberDefault","processValue","value","emptyValue","precision","separators","range","inputValue","cleanValue","clampedNumber","clampedString","min","decimal","max","numberValue","stringValue","trimDecimalPlace","inputNumberValue","parseFloat","clamp","separator","decimalPosition","indexOf","isNegative","startsWith","splitValue","split","intPart","String","Math","abs","fracPart","length","slice","substr","Infinity","thousandsSeparatorRegEx","RegExp","thousand","decimalSeparatorRegEx","excessiveMinusSignRegEx","cleanedValue","replace"],"mappings":"AAAA,SAASA,gBAAgBC,mBAAmB,QAAQ,aAAa;AAYjE,OAAO,SAASC,aACZC,KAAa,EACb,EAAEC,UAAU,EAAEC,SAAS,EAAEC,UAAU,EAAEC,QAAQ,CAAC,CAAC,EAA+B,EAC9EP,eAA6BC,mBAAmB;IAEhD,IAAIO,aAAaC,WAAWN,OAAOG;IAEnC,sBAAsB;IACtB,IAAIE,eAAe,MAAMA,eAAe,KAAK;QACzC,IAAIE,gBAAgBN;QACpB,IAAIO,gBAAgBH;QACpB,IAAIE,kBAAkB,GAAG;YACrB,IAAIH,MAAMK,GAAG,IAAIF,gBAAgBH,MAAMK,GAAG,EAAE;gBACxCF,gBAAgBH,MAAMK,GAAG;gBACzBD,gBAAgBX,aAAaO,MAAMK,GAAG,EAAE,GAAG,IAAIN,WAAWO,OAAO;YACrE,OAAO,IAAIN,MAAMO,GAAG,IAAIJ,gBAAgBH,MAAMO,GAAG,EAAE;gBAC/CJ,gBAAgBH,MAAMO,GAAG;gBACzBH,gBAAgBX,aAAaO,MAAMO,GAAG,EAAE,GAAG,IAAIR,WAAWO,OAAO;YACrE;QACJ;QACA,OAAO;YACHE,aAAaL;YACbM,aAAaL;QACjB;IACJ;IAEA,sBAAsB;IACtBH,aAAaS,iBAAiBT,YAAYF,WAAWO,OAAO,EAAEb,cAAcK;IAE5E,mCAAmC;IACnC,MAAMa,mBAAmBC,WAAWX;IACpC,MAAMO,cAAcK,MAAMF,kBAAkBX;IAE5C,yFAAyF;IACzF,MAAMS,cACFD,gBAAgBG,mBACVV,aACAR,aAAae,aAAa,GAAG,IAAIT,WAAWO,OAAO;IAE7D,OAAO;QACHG;QACAD,aAAaA;IACjB;AACJ;AAEA,SAASE,iBACLd,KAAa,EACbkB,SAAiB,EACjBrB,YAA0B,EAC1BK,SAAkB;IAElB,MAAMiB,kBAAkBnB,MAAMoB,OAAO,CAACF;IACtC,IAAIC,mBAAmB,GAAG;QACtB,IAAIjB,WAAW;YACX,MAAMmB,aAAarB,MAAMsB,UAAU,CAAC;YACpC,MAAMC,aAAavB,MAAMwB,KAAK,CAACN;YAC/B,MAAMO,UAAU,AAACJ,CAAAA,aAAa,MAAM,EAAC,IAAKK,OAAOC,KAAKC,GAAG,CAAC,CAACL,UAAU,CAAC,EAAE;YACxE,IAAIM,WAAWN,UAAU,CAAC,EAAE;YAC5B,IAAIM,YAAYA,SAASC,MAAM,GAAG5B,WAAW;gBACzC2B,WAAWA,SAASE,KAAK,CAAC,GAAG7B;YACjC;YACA,OAAO,GAAGuB,QAAQ,CAAC,EAAEI,UAAU;QACnC;QAEA,OAAO7B,MAAMgC,MAAM,CAAC,GAAGb;IAC3B;IACA,OAAOO,OAAO,CAAC1B;AACnB;AAEA,SAASiB,MAAMjB,KAAa,EAAE,EAAES,MAAM,CAACwB,QAAQ,EAAEtB,MAAMsB,QAAQ,EAAS;IACpE,OAAON,KAAKhB,GAAG,CAACgB,KAAKlB,GAAG,CAACT,OAAOW,MAAMF;AAC1C;AAEA,SAASH,WAAWN,KAAa,EAAEG,UAAsB;IACrD,MAAM+B,0BAA0B,IAAIC,OAAO,CAAC,CAAC,EAAEhC,WAAWiC,QAAQ,CAAC,KAAK,CAAC,EAAE;IAC3E,MAAMC,wBAAwB,IAAIF,OAAO,CAAC,CAAC,EAAEhC,WAAWO,OAAO,CAAC,MAAM,CAAC,EAAE;IACzE,MAAM4B,0BAA0B;IAChC,MAAMC,eAAevC,KACjB,4BAA4B;KAC3BwC,OAAO,CAAC,cAAc,GACvB,6BAA6B;KAC5BA,OAAO,CAACN,yBAAyB,GAClC,sCAAsC;KACrCM,OAAO,CAACH,uBAAuBlC,WAAWO,OAAO,CAClD,+BAA+B;KAC9B8B,OAAO,CAACF,yBAAyB;IAEtC,OAAOC;AACX"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"
|
1
|
+
{"version":3,"sources":["../../src/original-number-input/index.ts"],"sourcesContent":["export * from './ordinal-number-input';\n"],"names":[],"mappings":"AAAA,cAAc,yBAAyB"}
|
@@ -1,54 +1,41 @@
|
|
1
|
-
|
1
|
+
function _define_property(obj, key, value) {
|
2
|
+
if (key in obj) {
|
3
|
+
Object.defineProperty(obj, key, {
|
4
|
+
value: value,
|
5
|
+
enumerable: true,
|
6
|
+
configurable: true,
|
7
|
+
writable: true
|
8
|
+
});
|
9
|
+
} else {
|
10
|
+
obj[key] = value;
|
11
|
+
}
|
12
|
+
return obj;
|
13
|
+
}
|
14
|
+
function _ts_decorate(decorators, target, key, desc) {
|
2
15
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
3
16
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
4
|
-
else for
|
17
|
+
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
5
18
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
6
|
-
}
|
7
|
-
|
19
|
+
}
|
20
|
+
function _ts_metadata(k, v) {
|
8
21
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
9
|
-
}
|
22
|
+
}
|
10
23
|
import { jsx as _jsx } from "react/jsx-runtime";
|
11
24
|
import { Input } from '@servicetitan/design-system';
|
12
25
|
import { action, observable, makeObservable } from 'mobx';
|
13
26
|
import { observer } from 'mobx-react';
|
14
27
|
import { Component } from 'react';
|
15
|
-
|
16
|
-
constructor(props) {
|
17
|
-
super(props);
|
18
|
-
Object.defineProperty(this, "hasFocus", {
|
19
|
-
enumerable: true,
|
20
|
-
configurable: true,
|
21
|
-
writable: true,
|
22
|
-
value: false
|
23
|
-
});
|
24
|
-
Object.defineProperty(this, "handleFocus", {
|
25
|
-
enumerable: true,
|
26
|
-
configurable: true,
|
27
|
-
writable: true,
|
28
|
-
value: () => (this.hasFocus = true)
|
29
|
-
});
|
30
|
-
Object.defineProperty(this, "handleBlur", {
|
31
|
-
enumerable: true,
|
32
|
-
configurable: true,
|
33
|
-
writable: true,
|
34
|
-
value: () => (this.hasFocus = false)
|
35
|
-
});
|
36
|
-
Object.defineProperty(this, "handleChange", {
|
37
|
-
enumerable: true,
|
38
|
-
configurable: true,
|
39
|
-
writable: true,
|
40
|
-
value: (e) => {
|
41
|
-
const parsed = parseIntIntoRange(e.currentTarget.value, this.props.min, this.props.max);
|
42
|
-
if (this.props.onChange) {
|
43
|
-
this.props.onChange(parsed);
|
44
|
-
}
|
45
|
-
}
|
46
|
-
});
|
47
|
-
makeObservable(this);
|
48
|
-
}
|
28
|
+
export class OrdinalNumberInput extends Component {
|
49
29
|
render() {
|
50
30
|
const { min, max, value, onChange, ...props } = this.props;
|
51
|
-
return
|
31
|
+
return /*#__PURE__*/ _jsx(Input, {
|
32
|
+
placeholder: this.getPlaceholder(),
|
33
|
+
...props,
|
34
|
+
value: this.getDisplayValue(),
|
35
|
+
onFocus: this.handleFocus,
|
36
|
+
onBlur: this.handleBlur,
|
37
|
+
onChange: this.handleChange
|
38
|
+
});
|
52
39
|
}
|
53
40
|
getPlaceholder() {
|
54
41
|
return `${this.props.min}‒${this.props.max}`;
|
@@ -60,24 +47,32 @@ let OrdinalNumberInput = class OrdinalNumberInput extends Component {
|
|
60
47
|
}
|
61
48
|
return this.hasFocus ? value.toString() : ordinalString(value);
|
62
49
|
}
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
50
|
+
constructor(props){
|
51
|
+
super(props), _define_property(this, "hasFocus", false), _define_property(this, "handleFocus", ()=>this.hasFocus = true), _define_property(this, "handleBlur", ()=>this.hasFocus = false), _define_property(this, "handleChange", (e)=>{
|
52
|
+
const parsed = parseIntIntoRange(e.currentTarget.value, this.props.min, this.props.max);
|
53
|
+
if (this.props.onChange) {
|
54
|
+
this.props.onChange(parsed);
|
55
|
+
}
|
56
|
+
});
|
57
|
+
makeObservable(this);
|
58
|
+
}
|
59
|
+
}
|
60
|
+
_ts_decorate([
|
61
|
+
observable
|
67
62
|
], OrdinalNumberInput.prototype, "hasFocus", void 0);
|
68
|
-
|
69
|
-
action
|
70
|
-
__metadata("design:type", Object)
|
63
|
+
_ts_decorate([
|
64
|
+
action
|
71
65
|
], OrdinalNumberInput.prototype, "handleFocus", void 0);
|
72
|
-
|
73
|
-
action
|
74
|
-
__metadata("design:type", Object)
|
66
|
+
_ts_decorate([
|
67
|
+
action
|
75
68
|
], OrdinalNumberInput.prototype, "handleBlur", void 0);
|
76
|
-
OrdinalNumberInput =
|
69
|
+
OrdinalNumberInput = _ts_decorate([
|
77
70
|
observer,
|
78
|
-
|
71
|
+
_ts_metadata("design:type", Function),
|
72
|
+
_ts_metadata("design:paramtypes", [
|
73
|
+
typeof OrdinalNumberInputProps === "undefined" ? Object : OrdinalNumberInputProps
|
74
|
+
])
|
79
75
|
], OrdinalNumberInput);
|
80
|
-
export { OrdinalNumberInput };
|
81
76
|
export function parseIntIntoRange(input, min, max) {
|
82
77
|
let parsed = parseInt(input, 10);
|
83
78
|
if (Number.isNaN(parsed)) {
|
@@ -85,20 +80,19 @@ export function parseIntIntoRange(input, min, max) {
|
|
85
80
|
}
|
86
81
|
if (parsed < min) {
|
87
82
|
parsed = min;
|
88
|
-
}
|
89
|
-
else if (parsed > max) {
|
83
|
+
} else if (parsed > max) {
|
90
84
|
parsed = max;
|
91
85
|
}
|
92
86
|
return parsed;
|
93
87
|
}
|
94
88
|
export function ordinalString(num) {
|
95
|
-
switch
|
89
|
+
switch(num % 100){
|
96
90
|
case 11:
|
97
91
|
case 12:
|
98
92
|
case 13:
|
99
93
|
return num.toString() + 'th';
|
100
94
|
default:
|
101
|
-
switch
|
95
|
+
switch(num % 10){
|
102
96
|
case 1:
|
103
97
|
return num.toString() + 'st';
|
104
98
|
case 2:
|
@@ -111,13 +105,13 @@ export function ordinalString(num) {
|
|
111
105
|
}
|
112
106
|
}
|
113
107
|
export function ordinalSuffix(num) {
|
114
|
-
switch
|
108
|
+
switch(num % 100){
|
115
109
|
case 11:
|
116
110
|
case 12:
|
117
111
|
case 13:
|
118
112
|
return 'th';
|
119
113
|
default:
|
120
|
-
switch
|
114
|
+
switch(num % 10){
|
121
115
|
case 1:
|
122
116
|
return 'st';
|
123
117
|
case 2:
|
@@ -129,4 +123,5 @@ export function ordinalSuffix(num) {
|
|
129
123
|
}
|
130
124
|
}
|
131
125
|
}
|
126
|
+
|
132
127
|
//# sourceMappingURL=ordinal-number-input.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"
|
1
|
+
{"version":3,"sources":["../../src/original-number-input/ordinal-number-input.tsx"],"sourcesContent":["import { Input, InputProps } from '@servicetitan/design-system';\nimport { action, observable, makeObservable } from 'mobx';\nimport { observer } from 'mobx-react';\nimport { Component, ChangeEvent } from 'react';\n\nexport interface OrdinalNumberInputProps extends Omit<InputProps, 'onChange'> {\n min: number;\n max: number;\n value?: number;\n onChange?(value?: number): void;\n}\n\n@observer\nexport class OrdinalNumberInput extends Component<OrdinalNumberInputProps> {\n @observable hasFocus = false;\n\n constructor(props: OrdinalNumberInputProps) {\n super(props);\n makeObservable(this);\n }\n\n render() {\n const { min, max, value, onChange, ...props } = this.props;\n\n return (\n <Input\n placeholder={this.getPlaceholder()}\n {...props}\n value={this.getDisplayValue()}\n onFocus={this.handleFocus}\n onBlur={this.handleBlur}\n onChange={this.handleChange}\n />\n );\n }\n\n @action private handleFocus = () => (this.hasFocus = true);\n @action private handleBlur = () => (this.hasFocus = false);\n\n private handleChange = (e: ChangeEvent<HTMLInputElement>): void => {\n const parsed = parseIntIntoRange(e.currentTarget.value, this.props.min, this.props.max);\n if (this.props.onChange) {\n this.props.onChange(parsed);\n }\n };\n\n private getPlaceholder() {\n return `${this.props.min}‒${this.props.max}`;\n }\n\n private getDisplayValue() {\n const value = this.props.value;\n if (typeof value !== 'number') {\n return '';\n }\n return this.hasFocus ? value.toString() : ordinalString(value);\n }\n}\n\nexport function parseIntIntoRange(input: string, min: number, max: number) {\n let parsed = parseInt(input, 10);\n if (Number.isNaN(parsed)) {\n return undefined;\n }\n if (parsed < min) {\n parsed = min;\n } else if (parsed > max) {\n parsed = max;\n }\n return parsed;\n}\n\nexport function ordinalString(num: number): string {\n switch (num % 100) {\n case 11:\n case 12:\n case 13:\n return num.toString() + 'th';\n default:\n switch (num % 10) {\n case 1:\n return num.toString() + 'st';\n case 2:\n return num.toString() + 'nd';\n case 3:\n return num.toString() + 'rd';\n default:\n return num.toString() + 'th';\n }\n }\n}\n\nexport function ordinalSuffix(num: number): string {\n switch (num % 100) {\n case 11:\n case 12:\n case 13:\n return 'th';\n default:\n switch (num % 10) {\n case 1:\n return 'st';\n case 2:\n return 'nd';\n case 3:\n return 'rd';\n default:\n return 'th';\n }\n }\n}\n"],"names":["Input","action","observable","makeObservable","observer","Component","OrdinalNumberInput","render","min","max","value","onChange","props","placeholder","getPlaceholder","getDisplayValue","onFocus","handleFocus","onBlur","handleBlur","handleChange","hasFocus","toString","ordinalString","constructor","e","parsed","parseIntIntoRange","currentTarget","input","parseInt","Number","isNaN","undefined","num","ordinalSuffix"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAAA,SAASA,KAAK,QAAoB,8BAA8B;AAChE,SAASC,MAAM,EAAEC,UAAU,EAAEC,cAAc,QAAQ,OAAO;AAC1D,SAASC,QAAQ,QAAQ,aAAa;AACtC,SAASC,SAAS,QAAqB,QAAQ;AAU/C,OAAO,MAAMC,2BAA2BD;IAQpCE,SAAS;QACL,MAAM,EAAEC,GAAG,EAAEC,GAAG,EAAEC,KAAK,EAAEC,QAAQ,EAAE,GAAGC,OAAO,GAAG,IAAI,CAACA,KAAK;QAE1D,qBACI,KAACZ;YACGa,aAAa,IAAI,CAACC,cAAc;YAC/B,GAAGF,KAAK;YACTF,OAAO,IAAI,CAACK,eAAe;YAC3BC,SAAS,IAAI,CAACC,WAAW;YACzBC,QAAQ,IAAI,CAACC,UAAU;YACvBR,UAAU,IAAI,CAACS,YAAY;;IAGvC;IAYQN,iBAAiB;QACrB,OAAO,GAAG,IAAI,CAACF,KAAK,CAACJ,GAAG,CAAC,CAAC,EAAE,IAAI,CAACI,KAAK,CAACH,GAAG,EAAE;IAChD;IAEQM,kBAAkB;QACtB,MAAML,QAAQ,IAAI,CAACE,KAAK,CAACF,KAAK;QAC9B,IAAI,OAAOA,UAAU,UAAU;YAC3B,OAAO;QACX;QACA,OAAO,IAAI,CAACW,QAAQ,GAAGX,MAAMY,QAAQ,KAAKC,cAAcb;IAC5D;IAxCAc,YAAYZ,KAA8B,CAAE;QACxC,KAAK,CAACA,QAHV,uBAAYS,YAAW,QAsBvB,uBAAgBJ,eAAc,IAAO,IAAI,CAACI,QAAQ,GAAG,OACrD,uBAAgBF,cAAa,IAAO,IAAI,CAACE,QAAQ,GAAG,QAEpD,uBAAQD,gBAAe,CAACK;YACpB,MAAMC,SAASC,kBAAkBF,EAAEG,aAAa,CAAClB,KAAK,EAAE,IAAI,CAACE,KAAK,CAACJ,GAAG,EAAE,IAAI,CAACI,KAAK,CAACH,GAAG;YACtF,IAAI,IAAI,CAACG,KAAK,CAACD,QAAQ,EAAE;gBACrB,IAAI,CAACC,KAAK,CAACD,QAAQ,CAACe;YACxB;QACJ;QA1BIvB,eAAe,IAAI;IACvB;AAsCJ;;;;;;;;;;;;;;;;;AAEA,OAAO,SAASwB,kBAAkBE,KAAa,EAAErB,GAAW,EAAEC,GAAW;IACrE,IAAIiB,SAASI,SAASD,OAAO;IAC7B,IAAIE,OAAOC,KAAK,CAACN,SAAS;QACtB,OAAOO;IACX;IACA,IAAIP,SAASlB,KAAK;QACdkB,SAASlB;IACb,OAAO,IAAIkB,SAASjB,KAAK;QACrBiB,SAASjB;IACb;IACA,OAAOiB;AACX;AAEA,OAAO,SAASH,cAAcW,GAAW;IACrC,OAAQA,MAAM;QACV,KAAK;QACL,KAAK;QACL,KAAK;YACD,OAAOA,IAAIZ,QAAQ,KAAK;QAC5B;YACI,OAAQY,MAAM;gBACV,KAAK;oBACD,OAAOA,IAAIZ,QAAQ,KAAK;gBAC5B,KAAK;oBACD,OAAOY,IAAIZ,QAAQ,KAAK;gBAC5B,KAAK;oBACD,OAAOY,IAAIZ,QAAQ,KAAK;gBAC5B;oBACI,OAAOY,IAAIZ,QAAQ,KAAK;YAChC;IACR;AACJ;AAEA,OAAO,SAASa,cAAcD,GAAW;IACrC,OAAQA,MAAM;QACV,KAAK;QACL,KAAK;QACL,KAAK;YACD,OAAO;QACX;YACI,OAAQA,MAAM;gBACV,KAAK;oBACD,OAAO;gBACX,KAAK;oBACD,OAAO;gBACX,KAAK;oBACD,OAAO;gBACX;oBACI,OAAO;YACf;IACR;AACJ"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"
|
1
|
+
{"version":3,"sources":["../../src/phone-number-input/index.ts"],"sourcesContent":["export * from './phone-number-input';\n"],"names":[],"mappings":"AAAA,cAAc,uBAAuB"}
|
@@ -2,5 +2,17 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef } from 'react';
|
3
3
|
import InputMask from 'react-input-mask';
|
4
4
|
import { Form } from '@servicetitan/design-system';
|
5
|
-
export const PhoneNumberInput = forwardRef(({ sip, ...props }, ref)
|
5
|
+
export const PhoneNumberInput = /*#__PURE__*/ forwardRef(({ sip, ...props }, ref)=>sip ? /*#__PURE__*/ _jsx(Form.Input, {
|
6
|
+
...props,
|
7
|
+
ref: ref
|
8
|
+
}) : /*#__PURE__*/ _jsx(InputMask, {
|
9
|
+
maskChar: null,
|
10
|
+
mask: "(999) 999-9999",
|
11
|
+
...props,
|
12
|
+
children: ()=>/*#__PURE__*/ _jsx(Form.Input, {
|
13
|
+
ref: ref,
|
14
|
+
...props
|
15
|
+
})
|
16
|
+
}));
|
17
|
+
|
6
18
|
//# sourceMappingURL=phone-number-input.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"
|
1
|
+
{"version":3,"sources":["../../src/phone-number-input/phone-number-input.tsx"],"sourcesContent":["import { forwardRef } from 'react';\nimport InputMask from 'react-input-mask';\n\nimport { Form, FormInputProps } from '@servicetitan/design-system';\n\nexport interface PhoneNumberInputProps extends FormInputProps {\n sip?: boolean;\n}\n\nexport const PhoneNumberInput = forwardRef<HTMLInputElement, PhoneNumberInputProps>(\n ({ sip, ...props }, ref) =>\n sip ? (\n <Form.Input {...props} ref={ref} />\n ) : (\n <InputMask maskChar={null} mask=\"(999) 999-9999\" {...props}>\n {(() => <Form.Input ref={ref} {...props} />) as any}\n </InputMask>\n )\n);\n"],"names":["forwardRef","InputMask","Form","PhoneNumberInput","sip","props","ref","Input","maskChar","mask"],"mappings":";AAAA,SAASA,UAAU,QAAQ,QAAQ;AACnC,OAAOC,eAAe,mBAAmB;AAEzC,SAASC,IAAI,QAAwB,8BAA8B;AAMnE,OAAO,MAAMC,iCAAmBH,WAC5B,CAAC,EAAEI,GAAG,EAAE,GAAGC,OAAO,EAAEC,MAChBF,oBACI,KAACF,KAAKK,KAAK;QAAE,GAAGF,KAAK;QAAEC,KAAKA;uBAE5B,KAACL;QAAUO,UAAU;QAAMC,MAAK;QAAkB,GAAGJ,KAAK;kBACpD,kBAAM,KAACH,KAAKK,KAAK;gBAACD,KAAKA;gBAAM,GAAGD,KAAK;;QAGrD"}
|