@trackunit/react-form-components 0.0.1 → 0.0.4
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/index.cjs +185 -100
- package/index.js +183 -100
- package/package.json +2 -2
- package/src/components/OptionCard/OptionCard.d.ts +24 -0
- package/src/components/PhoneInput/CountryCodeSelect.d.ts +11 -4
- package/src/components/PhoneInput/PhoneInput.d.ts +1 -0
- package/src/components/PhoneInput/PhoneNumberUtilities.d.ts +13 -0
- package/src/components/PhoneInput/usePhoneInput.d.ts +42 -0
- package/src/index.d.ts +1 -0
package/index.cjs
CHANGED
|
@@ -10,10 +10,10 @@ var React = require('react');
|
|
|
10
10
|
var uuid = require('uuid');
|
|
11
11
|
var dateFns = require('date-fns');
|
|
12
12
|
var ReactSelect = require('react-select');
|
|
13
|
-
var ReactAsyncSelect = require('react-select/async');
|
|
14
|
-
var libphonenumberJs = require('libphonenumber-js');
|
|
15
13
|
var ReactAsyncCreatableSelect = require('react-select/async-creatable');
|
|
16
14
|
var ReactCreatableSelect = require('react-select/creatable');
|
|
15
|
+
var ReactAsyncSelect = require('react-select/async');
|
|
16
|
+
var parsePhoneNumberFromString = require('libphonenumber-js');
|
|
17
17
|
|
|
18
18
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
19
19
|
|
|
@@ -38,9 +38,10 @@ function _interopNamespace(e) {
|
|
|
38
38
|
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
39
39
|
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
40
40
|
var ReactSelect__default = /*#__PURE__*/_interopDefaultLegacy(ReactSelect);
|
|
41
|
-
var ReactAsyncSelect__default = /*#__PURE__*/_interopDefaultLegacy(ReactAsyncSelect);
|
|
42
41
|
var ReactAsyncCreatableSelect__default = /*#__PURE__*/_interopDefaultLegacy(ReactAsyncCreatableSelect);
|
|
43
42
|
var ReactCreatableSelect__default = /*#__PURE__*/_interopDefaultLegacy(ReactCreatableSelect);
|
|
43
|
+
var ReactAsyncSelect__default = /*#__PURE__*/_interopDefaultLegacy(ReactAsyncSelect);
|
|
44
|
+
var parsePhoneNumberFromString__default = /*#__PURE__*/_interopDefaultLegacy(parsePhoneNumberFromString);
|
|
44
45
|
|
|
45
46
|
var defaultTranslations = {
|
|
46
47
|
|
|
@@ -201,7 +202,7 @@ const InputContainer$1 = tailwindStyledComponents.tw.label `
|
|
|
201
202
|
* @param {LabelProps} props - The props for the Label component
|
|
202
203
|
* @returns {JSX.Element} Label component
|
|
203
204
|
*/
|
|
204
|
-
const Label = ({ id, htmlFor, children, className, dataTestId, disabled, isInvalid, }) => {
|
|
205
|
+
const Label$1 = ({ id, htmlFor, children, className, dataTestId, disabled, isInvalid, }) => {
|
|
205
206
|
return (jsxRuntime.jsx(Root$2, Object.assign({ id: id || "", htmlFor: htmlFor || "", className: className, "data-testid": dataTestId, "$disabled": disabled, "$isInvalid": isInvalid }, { children: children })));
|
|
206
207
|
};
|
|
207
208
|
const Root$2 = tailwindStyledComponents.tw.label `
|
|
@@ -254,7 +255,7 @@ const Checkbox = React__namespace.forwardRef((_a, ref) => {
|
|
|
254
255
|
}
|
|
255
256
|
};
|
|
256
257
|
const uuid = rest.id || dataTestId;
|
|
257
|
-
return (jsxRuntime.jsxs(CheckboxContainer, Object.assign({ "data-testid": dataTestId && `${dataTestId}Container`, htmlFor: uuid, className: className }, { children: [jsxRuntime.jsx(HiddenInput$1, Object.assign({ type: "checkbox", checked: !indeterminate && checked, onChange: onChange, disabled: disabled, "data-testid": dataTestId, readOnly: readOnly, "aria-checked": !indeterminate && checked, role: "checkbox", id: uuid }, rest, { ref: ref })), jsxRuntime.jsx(CheckboxWrapper, Object.assign({ id: uuid, "$disabled": isReadonly, "$checked": checked, "$indeterminate": indeterminate, "$isInvalid": isReadonly ? false : isInvalid, tabIndex: isReadonly ? -1 : tabIndex, onKeyPress: onKeyPress }, { children: icon })), label && (jsxRuntime.jsx(Label, Object.assign({ className: tailwindStyledComponents.tws `cursor-pointer`, htmlFor: uuid, disabled: isReadonly, isInvalid: isReadonly ? false : isInvalid, dataTestId: dataTestId && `${dataTestId}-Label` }, { children: label }))), children] })));
|
|
258
|
+
return (jsxRuntime.jsxs(CheckboxContainer, Object.assign({ "data-testid": dataTestId && `${dataTestId}Container`, htmlFor: uuid, className: className }, { children: [jsxRuntime.jsx(HiddenInput$1, Object.assign({ type: "checkbox", checked: !indeterminate && checked, onChange: onChange, disabled: disabled, "data-testid": dataTestId, readOnly: readOnly, "aria-checked": !indeterminate && checked, role: "checkbox", id: uuid }, rest, { ref: ref })), jsxRuntime.jsx(CheckboxWrapper, Object.assign({ id: uuid, "$disabled": isReadonly, "$checked": checked, "$indeterminate": indeterminate, "$isInvalid": isReadonly ? false : isInvalid, tabIndex: isReadonly ? -1 : tabIndex, onKeyPress: onKeyPress }, { children: icon })), label && (jsxRuntime.jsx(Label$1, Object.assign({ className: tailwindStyledComponents.tws `cursor-pointer`, htmlFor: uuid, disabled: isReadonly, isInvalid: isReadonly ? false : isInvalid, dataTestId: dataTestId && `${dataTestId}-Label` }, { children: label }))), children] })));
|
|
258
259
|
});
|
|
259
260
|
const StyledCheckIcon = tailwindStyledComponents.twx(CheckIcon) `tu-checkbox--icon`;
|
|
260
261
|
const StyledIndeterminateIcon = tailwindStyledComponents.twx(IndeterminateIcon) `tu-checkbox--icon`;
|
|
@@ -311,7 +312,7 @@ const FormGroupRoot = tailwindStyledComponents.tw.div `
|
|
|
311
312
|
const ContainerBefore = tailwindStyledComponents.tw.div `
|
|
312
313
|
tu-form-group__container-before
|
|
313
314
|
`;
|
|
314
|
-
const FormGroupLabel = tailwindStyledComponents.twx(Label) `
|
|
315
|
+
const FormGroupLabel = tailwindStyledComponents.twx(Label$1) `
|
|
315
316
|
component-formGroup-font
|
|
316
317
|
`;
|
|
317
318
|
const ContainerAfter = tailwindStyledComponents.tw.div `
|
|
@@ -454,6 +455,58 @@ const NumberField = React.forwardRef((_a, ref) => {
|
|
|
454
455
|
return (jsxRuntime.jsx(FormGroup, Object.assign({ htmlFor: htmlForId, label: label, tip: tip, isInvalid: renderAsInvalid, helpText: (renderAsInvalid && errorMessage) || helpText, helpAddon: helpAddon, dataTestId: dataTestId && `${dataTestId}-FormGroup` }, { children: jsxRuntime.jsx(NumberInput, Object.assign({ id: htmlForId, "aria-labelledby": htmlForId + "-label", ref: ref, maxLength: maxLength, value: value, isInvalid: renderAsInvalid }, rest, { className: className, dataTestId: dataTestId })) })));
|
|
455
456
|
});
|
|
456
457
|
|
|
458
|
+
/**
|
|
459
|
+
* A card version of a radio button that includes an icon, headings and a description.
|
|
460
|
+
*/
|
|
461
|
+
const OptionCard = React.forwardRef((_a, ref) => {
|
|
462
|
+
var { icon, heading, subheading, description, disabled, id, value, className, dataTestId } = _a, rest = __rest(_a, ["icon", "heading", "subheading", "description", "disabled", "id", "value", "className", "dataTestId"]);
|
|
463
|
+
return (jsxRuntime.jsxs(Container$3, Object.assign({ "data-testid": dataTestId }, { children: [jsxRuntime.jsx("input", Object.assign({ ref: ref, id: id, type: "radio", value: value, className: "hidden peer" }, rest)), jsxRuntime.jsxs(Label, Object.assign({ htmlFor: id, className: className, "$disabled": disabled }, { children: [disabled && icon && React.cloneElement(icon, { className: `${icon.props.className} text-secondary-400` }), !disabled && icon, heading && (jsxRuntime.jsx(reactComponents.Heading, Object.assign({ variant: "secondary", subtle: disabled }, { children: heading }))), (subheading || description) && (jsxRuntime.jsxs(Content, { children: [subheading && (jsxRuntime.jsx(reactComponents.Text, Object.assign({ weight: "thick", align: "center", subtle: disabled }, { children: subheading }))), description && (jsxRuntime.jsx(reactComponents.Text, Object.assign({ subtle: true, align: "center" }, { children: description })))] }))] }))] })));
|
|
464
|
+
});
|
|
465
|
+
const Container$3 = tailwindStyledComponents.tw.div `
|
|
466
|
+
contents
|
|
467
|
+
`;
|
|
468
|
+
const Label = tailwindStyledComponents.tw.label `
|
|
469
|
+
tu-input-base
|
|
470
|
+
${p => (p.$disabled ? "tu-input--disabled" : "")}
|
|
471
|
+
${p => (p.$disabled ? "cursor-not-allowed" : "cursor-pointer")}
|
|
472
|
+
aspect-square
|
|
473
|
+
flex
|
|
474
|
+
flex-col
|
|
475
|
+
gap-2
|
|
476
|
+
justify-center
|
|
477
|
+
items-center
|
|
478
|
+
p-6
|
|
479
|
+
w-full
|
|
480
|
+
peer-checked:bg-primary-50
|
|
481
|
+
peer-checked:border-primary-600
|
|
482
|
+
peer-checked:border-2
|
|
483
|
+
`;
|
|
484
|
+
const Content = tailwindStyledComponents.tw.div `
|
|
485
|
+
flex
|
|
486
|
+
flex-col
|
|
487
|
+
items-center
|
|
488
|
+
`;
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* The SelectContainer component.
|
|
492
|
+
*
|
|
493
|
+
* @param {SelectContainerProps} props - The props for the SelectContainer component
|
|
494
|
+
* @returns {JSX.Element} SelectContainer component
|
|
495
|
+
*/
|
|
496
|
+
const SelectContainer$1 = ({ children, label, hideLabel, id, hasError, error, description, info, dataTestId, isDisabled, }) => {
|
|
497
|
+
return (jsxRuntime.jsxs(Container$2, Object.assign({ "data-testid": dataTestId, "$hasError": hasError, "$isDisabled": isDisabled }, { children: [label && !hideLabel && jsxRuntime.jsx(Label$1, Object.assign({ htmlFor: id }, { children: label })), children, (hasError || info) && (jsxRuntime.jsx(InformativeText, Object.assign({ size: "small", "$hasError": hasError !== null && hasError !== void 0 ? hasError : false }, { children: hasError ? error : info })))] })));
|
|
498
|
+
};
|
|
499
|
+
const Container$2 = tailwindStyledComponents.tw.label `
|
|
500
|
+
tu-select__container
|
|
501
|
+
tu-select
|
|
502
|
+
${({ $hasError }) => ($hasError ? tailwindStyledComponents.tws `tu-select--invalid` : null)}
|
|
503
|
+
${({ $isDisabled }) => ($isDisabled ? tailwindStyledComponents.tws `tu-select--disabled` : null)}
|
|
504
|
+
`;
|
|
505
|
+
const InformativeText = tailwindStyledComponents.twx(reactComponents.Text) `
|
|
506
|
+
tu-informative-text
|
|
507
|
+
${p => (p.$hasError ? `tu-informative-text--error` : null)}
|
|
508
|
+
`;
|
|
509
|
+
|
|
457
510
|
/**
|
|
458
511
|
* @param {MultiValue<Option> | SingleValue<Option>} arg option to check type
|
|
459
512
|
* @returns {arg is MultiValue<Option> } is Multivalue
|
|
@@ -602,11 +655,11 @@ const TagsContainer = ({ items, width = "100%", itemsGap = 5, postFix }) => {
|
|
|
602
655
|
return null;
|
|
603
656
|
})
|
|
604
657
|
.filter(element => element !== null);
|
|
605
|
-
return (jsxRuntime.jsxs(Container$
|
|
658
|
+
return (jsxRuntime.jsxs(Container$1, Object.assign({ style: {
|
|
606
659
|
width: `${width}`,
|
|
607
660
|
}, "$ready": isReady, ref: containerRef }, { children: [renderedElements, postFix] })));
|
|
608
661
|
};
|
|
609
|
-
const Container$
|
|
662
|
+
const Container$1 = tailwindStyledComponents.tw.div `
|
|
610
663
|
tu-select__dynamic-tag--container
|
|
611
664
|
${({ $ready }) => {
|
|
612
665
|
return $ready ? tailwindStyledComponents.tws `visible` : tailwindStyledComponents.tws `invisible`;
|
|
@@ -786,6 +839,51 @@ const useSelect = (_a) => {
|
|
|
786
839
|
};
|
|
787
840
|
};
|
|
788
841
|
|
|
842
|
+
/**
|
|
843
|
+
* The CreatableSelect component.
|
|
844
|
+
*
|
|
845
|
+
* @param {CreateableSelectProps} props - The props for the CreatableSelect component
|
|
846
|
+
* @returns {JSX.Element} CreatableSelect component
|
|
847
|
+
*/
|
|
848
|
+
const CreatableSelect = (props) => {
|
|
849
|
+
const { id, dataTestId = "select", async, maxMenuHeight = 200, label, error, disabled, isMulti, value, hideLabel, description, info, options, onChange, isLoading, classNamePrefix = "", filterOption, prefix, } = props;
|
|
850
|
+
const hasError = !!error;
|
|
851
|
+
const { refPrefix, customStyles, menuIsOpen, customComponents, menuPlacement, openMenuHandler, closeMenuHandler, orderedOptions, } = useSelect(props);
|
|
852
|
+
const selectProps = {
|
|
853
|
+
value,
|
|
854
|
+
menuPlacement,
|
|
855
|
+
maxMenuHeight,
|
|
856
|
+
onChange,
|
|
857
|
+
"aria-label": label,
|
|
858
|
+
"data-testid": dataTestId,
|
|
859
|
+
components: customComponents,
|
|
860
|
+
styles: customStyles,
|
|
861
|
+
tabSelectsValue: false,
|
|
862
|
+
blurInputOnSelect: !isMulti,
|
|
863
|
+
menuPortalTarget: document.body,
|
|
864
|
+
isSearchable: disabled ? false : true,
|
|
865
|
+
menuShouldBlockScroll: true,
|
|
866
|
+
menuShouldScrollIntoView: true,
|
|
867
|
+
openMenuOnFocus: disabled ? false : true,
|
|
868
|
+
menuIsOpen: disabled ? false : menuIsOpen,
|
|
869
|
+
openMenuOnClick: true,
|
|
870
|
+
closeMenuOnSelect: false,
|
|
871
|
+
isMulti: isMulti,
|
|
872
|
+
classNamePrefix,
|
|
873
|
+
isLoading,
|
|
874
|
+
id,
|
|
875
|
+
};
|
|
876
|
+
return (jsxRuntime.jsx(SelectContainer$1, Object.assign({ label: label, hideLabel: hideLabel, id: id, hasError: hasError, error: error, description: description, info: info, dataTestId: dataTestId, isDisabled: disabled }, { children: jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [prefix !== undefined && (jsxRuntime.jsx(SelectPrefix, Object.assign({ "data-testid": dataTestId && `${dataTestId}-prefix`, ref: refPrefix }, { children: prefix }))), async ? (jsxRuntime.jsx(ReactAsyncCreatableSelect__default["default"], Object.assign({ "aria-label": label, maxMenuHeight: maxMenuHeight, "data-testid": dataTestId, components: customComponents }, props, { onMenuOpen: () => {
|
|
877
|
+
!disabled && openMenuHandler();
|
|
878
|
+
}, onMenuClose: () => {
|
|
879
|
+
closeMenuHandler();
|
|
880
|
+
} }))) : (jsxRuntime.jsx(ReactCreatableSelect__default["default"], Object.assign({}, selectProps, { options: filterOption ? orderedOptions : options, isMulti: isMulti, onMenuOpen: () => {
|
|
881
|
+
!disabled && openMenuHandler();
|
|
882
|
+
}, onMenuClose: () => {
|
|
883
|
+
closeMenuHandler();
|
|
884
|
+
} })))] }) })));
|
|
885
|
+
};
|
|
886
|
+
|
|
789
887
|
/**
|
|
790
888
|
* Selects are input components used to choose a value from a set.
|
|
791
889
|
*
|
|
@@ -823,9 +921,9 @@ const Select = (props) => {
|
|
|
823
921
|
onMenuScrollToBottom,
|
|
824
922
|
onInputChange,
|
|
825
923
|
};
|
|
826
|
-
return (jsxRuntime.jsxs(SelectContainer
|
|
924
|
+
return (jsxRuntime.jsxs(SelectContainer, Object.assign({ ref: refContainer, className: className, "data-testid": dataTestId, "$hasError": hasError, "$isDisabled": disabled }, { children: [prefix !== undefined && (jsxRuntime.jsx(SelectPrefix, Object.assign({ "data-testid": dataTestId && `${dataTestId}-prefix`, ref: refPrefix }, { children: prefix }))), async ? (jsxRuntime.jsx(ReactAsyncSelect__default["default"], Object.assign({}, propsNoClassName, selectProps, async, { onMenuOpen: openMenuHandler, onMenuClose: closeMenuHandler }))) : (jsxRuntime.jsx(ReactSelect__default["default"], Object.assign({}, propsNoClassName, selectProps, { options: filterOption ? orderedOptions : options, hideSelectedOptions: false, isMulti: isMulti, onMenuOpen: openMenuHandler, onMenuClose: closeMenuHandler })))] })));
|
|
827
925
|
};
|
|
828
|
-
const SelectContainer
|
|
926
|
+
const SelectContainer = tailwindStyledComponents.tw.div `
|
|
829
927
|
tu-select
|
|
830
928
|
${({ $hasError }) => ($hasError ? tailwindStyledComponents.tws `tu-select--invalid` : null)}
|
|
831
929
|
${({ $isDisabled }) => ($isDisabled ? tailwindStyledComponents.tws `tu-select--disabled` : null)}
|
|
@@ -863,12 +961,12 @@ const ADDITIONAL_COUNTRY_CODES_SUPPORTED_BY_BACKEND = [
|
|
|
863
961
|
"883",
|
|
864
962
|
];
|
|
865
963
|
const countryCodesSet = [
|
|
866
|
-
...new Set(
|
|
964
|
+
...new Set(parsePhoneNumberFromString.getCountries().map(code => parsePhoneNumberFromString.getCountryCallingCode(code))),
|
|
867
965
|
...ADDITIONAL_COUNTRY_CODES_SUPPORTED_BY_BACKEND,
|
|
868
966
|
]
|
|
869
967
|
.filter(code => !COUNTRY_CODES_NOT_SUPPORTED_BY_BACKEND.includes(code))
|
|
870
968
|
.sort((a, b) => Number(a) - Number(b));
|
|
871
|
-
const countryCodes = countryCodesSet.map(code => ({ label: `+${code}`, value: code }));
|
|
969
|
+
const countryCodes = countryCodesSet.map(code => ({ label: `+${code}`, value: `+${code}` })); // We add the + sign to the value so that the google libphonenumber-js can parse it correctly.
|
|
872
970
|
|
|
873
971
|
/**
|
|
874
972
|
* The CountryCodeSelect component is used to select a country code for a phone number.
|
|
@@ -876,7 +974,7 @@ const countryCodes = countryCodesSet.map(code => ({ label: `+${code}`, value: co
|
|
|
876
974
|
* @param {CountryCodeSelectProps} props - The props for the CountryCodeSelect component
|
|
877
975
|
* @returns {JSX.Element} CountryCodeSelect component
|
|
878
976
|
*/
|
|
879
|
-
const CountryCodeSelect = ({ excludedCountries, countryCode, isInvalid,
|
|
977
|
+
const CountryCodeSelect = ({ excludedCountries, countryCode, isInvalid, onChange, disabled, dataTestId, placeholder, }) => {
|
|
880
978
|
const [isCountryCodeMissing, setIsCountryCodeMissing] = React.useState(false);
|
|
881
979
|
React.useEffect(() => {
|
|
882
980
|
countryCode && setIsCountryCodeMissing(false);
|
|
@@ -884,37 +982,88 @@ const CountryCodeSelect = ({ excludedCountries, countryCode, isInvalid, setCount
|
|
|
884
982
|
const filteredCodes = countryCodes.filter(code => {
|
|
885
983
|
return !(excludedCountries === null || excludedCountries === void 0 ? void 0 : excludedCountries.some(excludedCode => excludedCode.value === code.value));
|
|
886
984
|
});
|
|
887
|
-
return (jsxRuntime.jsx(Select, { className: "w-28", "aria-invalid": isCountryCodeMissing, options: filteredCodes.map(code => code), value: filteredCodes.find(({ value
|
|
888
|
-
|
|
889
|
-
|
|
985
|
+
return (jsxRuntime.jsx(Select, { dataTestId: dataTestId, className: "w-28", "aria-invalid": isCountryCodeMissing, options: filteredCodes.map(code => code), value: filteredCodes.find(({ value }) => value === `+${countryCode}`), placeholder: placeholder, hasError: isCountryCodeMissing || isInvalid, maxMenuHeight: 200, onChange: onChange, disabled: disabled }));
|
|
986
|
+
};
|
|
987
|
+
|
|
988
|
+
/**
|
|
989
|
+
* @param phoneNumber - a phone number as a string
|
|
990
|
+
* @returns {boolean} true if the phone number starts with a plus sign
|
|
991
|
+
* @example checkIfPhoneNumberHasPlus("123456789") // false
|
|
992
|
+
* checkIfPhoneNumberHasPlus("+123456789") // true
|
|
993
|
+
*/
|
|
994
|
+
const checkIfPhoneNumberHasPlus = (phoneNumber) => {
|
|
995
|
+
return phoneNumber.startsWith("+");
|
|
996
|
+
};
|
|
997
|
+
/**
|
|
998
|
+
* @param phoneNumber - a phone number as a string
|
|
999
|
+
* @returns {string|number} the phone number with a plus sign in front of it
|
|
1000
|
+
* @example getPhoneNumberWithPlus("123456789") // "+123456789"
|
|
1001
|
+
*/
|
|
1002
|
+
const getPhoneNumberWithPlus = (phoneNumber) => {
|
|
1003
|
+
const stringPhoneNumber = phoneNumber.toString();
|
|
1004
|
+
return checkIfPhoneNumberHasPlus(stringPhoneNumber) ? stringPhoneNumber : `+${stringPhoneNumber}`;
|
|
1005
|
+
};
|
|
1006
|
+
|
|
1007
|
+
/**
|
|
1008
|
+
* A custom hook for managing phone number input state and validation.
|
|
1009
|
+
*
|
|
1010
|
+
* @returns {object} - An object containing state values and event handler functions.
|
|
1011
|
+
* @property {string} countryCode - The current country code value.
|
|
1012
|
+
* @property {string} phoneNumber - The current phone number value.
|
|
1013
|
+
* @property {boolean} isCountryCodeInvalid - Whether the country code value is invalid.
|
|
1014
|
+
* @property {boolean} isPhoneNumberInvalid - Whether the phone number value is invalid.
|
|
1015
|
+
* @property {Function} handleCountryCodeChange - A function for handling changes to the country code input.
|
|
1016
|
+
* @property {Function} handlePhoneNumberChange - A function for handling changes to the phone number input.
|
|
1017
|
+
*/
|
|
1018
|
+
const usePhoneInput = (initialValue) => {
|
|
1019
|
+
const [countryCode, setCountryCode] = React.useState("");
|
|
1020
|
+
const [phoneNumber, setPhoneNumber] = React.useState("");
|
|
1021
|
+
const [isCountryCodeInvalid, setIsCountryCodeInvalid] = React.useState(false);
|
|
1022
|
+
const [isPhoneNumberInvalid, setIsPhoneNumberInvalid] = React.useState(false);
|
|
1023
|
+
React.useEffect(() => {
|
|
1024
|
+
var _a, _b;
|
|
1025
|
+
if (initialValue) {
|
|
1026
|
+
const safePhoneNumber = getPhoneNumberWithPlus(initialValue);
|
|
1027
|
+
const number = parsePhoneNumberFromString__default["default"](safePhoneNumber);
|
|
1028
|
+
setCountryCode((_a = number === null || number === void 0 ? void 0 : number.countryCallingCode.toString()) !== null && _a !== void 0 ? _a : "");
|
|
1029
|
+
setPhoneNumber((_b = number === null || number === void 0 ? void 0 : number.nationalNumber.toString()) !== null && _b !== void 0 ? _b : "");
|
|
1030
|
+
}
|
|
1031
|
+
}, [initialValue]);
|
|
1032
|
+
const handleCountryCodeChange = (option) => {
|
|
1033
|
+
var _a;
|
|
1034
|
+
setCountryCode((_a = option === null || option === void 0 ? void 0 : option.value) !== null && _a !== void 0 ? _a : "");
|
|
1035
|
+
setIsCountryCodeInvalid(!Boolean(option === null || option === void 0 ? void 0 : option.value));
|
|
1036
|
+
};
|
|
1037
|
+
const handlePhoneNumberChange = (event) => {
|
|
1038
|
+
setPhoneNumber(event.target.value);
|
|
1039
|
+
setIsPhoneNumberInvalid(!event.target.value || !Boolean(event.target.value.trim()));
|
|
1040
|
+
};
|
|
1041
|
+
return {
|
|
1042
|
+
countryCode,
|
|
1043
|
+
phoneNumber,
|
|
1044
|
+
isCountryCodeInvalid,
|
|
1045
|
+
isPhoneNumberInvalid,
|
|
1046
|
+
handleCountryCodeChange,
|
|
1047
|
+
handlePhoneNumberChange,
|
|
1048
|
+
};
|
|
890
1049
|
};
|
|
891
1050
|
|
|
892
1051
|
/**
|
|
893
1052
|
* A component for inputting phone numbers with an optional action button for initiating a phone call.
|
|
894
1053
|
*
|
|
895
1054
|
* @param {string} [dataTestId] - The data test ID for the component.
|
|
1055
|
+
* @param {string|number} [value] - The value of the input field. The value should include the country code as well.
|
|
896
1056
|
* @param {boolean} [disabled=false] - Whether the component is disabled or not.
|
|
897
1057
|
* @param {string} [fieldSize="medium"] - The size of the input field.
|
|
898
1058
|
* @param {boolean} [disableAction=false] - Whether the action button is disabled or not.
|
|
899
1059
|
* @returns {JSX.Element} - The PhoneInput component.
|
|
900
1060
|
*/
|
|
901
1061
|
const PhoneInput = React.forwardRef((_a, ref) => {
|
|
902
|
-
var { dataTestId, isInvalid, disabled = false, fieldSize = "medium", disableAction = false } = _a, rest = __rest(_a, ["dataTestId", "isInvalid", "disabled", "fieldSize", "disableAction"]);
|
|
903
|
-
const
|
|
904
|
-
|
|
905
|
-
const [countryCode, setCountryCode] = React.useState(undefined);
|
|
906
|
-
const [isPhoneNumberInvalid, setIsPhoneNumberInvalid] = React.useState(false);
|
|
907
|
-
const handlePhoneNumberChange = (e) => {
|
|
908
|
-
const input = e.target.value;
|
|
909
|
-
setIsPhoneNumberInvalid(!Boolean(input));
|
|
910
|
-
setPhoneNumber(input);
|
|
911
|
-
};
|
|
912
|
-
React.useEffect(() => {
|
|
913
|
-
setRenderAsInvalid(isInvalid || isPhoneNumberInvalid);
|
|
914
|
-
}, [isInvalid, isPhoneNumberInvalid]);
|
|
915
|
-
return (jsxRuntime.jsxs(Container$1, { children: [jsxRuntime.jsx(CountryCodeSelect, { isInvalid: renderAsInvalid, countryCode: countryCode, setCountryCode: setCountryCode }), jsxRuntime.jsx(BaseInput, Object.assign({ ref: ref, dataTestId: dataTestId, isInvalid: renderAsInvalid, fieldSize: fieldSize, type: "tel", value: phoneNumber, onChange: handlePhoneNumberChange, disabled: disabled, actions: !disableAction && (jsxRuntime.jsx(ActionButton, { disabled: !countryCode || !phoneNumber || disabled || renderAsInvalid, value: `${countryCode}${phoneNumber}`, type: "PHONE_NUMBER", dataTestId: dataTestId && `${dataTestId}-phoneIcon`, iconSize: fieldSize })) }, rest))] }));
|
|
1062
|
+
var { dataTestId, isInvalid, disabled = false, value, fieldSize = "medium", disableAction = false, onChange } = _a, rest = __rest(_a, ["dataTestId", "isInvalid", "disabled", "value", "fieldSize", "disableAction", "onChange"]);
|
|
1063
|
+
const { countryCode, phoneNumber, isCountryCodeInvalid, isPhoneNumberInvalid, handleCountryCodeChange, handlePhoneNumberChange, } = usePhoneInput(value);
|
|
1064
|
+
return (jsxRuntime.jsxs(Container, Object.assign({ "data-testid": `${dataTestId}-container` }, { children: [jsxRuntime.jsx("input", { hidden: true, id: "phone-input", "data-testid": dataTestId && `${dataTestId}`, value: value, ref: ref, onChange: onChange }), jsxRuntime.jsx(CountryCodeSelect, { dataTestId: dataTestId && `${dataTestId}-countryCodeSelect`, countryCode: countryCode, onChange: handleCountryCodeChange, disabled: disabled, isInvalid: isCountryCodeInvalid || isInvalid, placeholder: "+45" }), jsxRuntime.jsx(BaseInput, Object.assign({ id: "phoneInput-number", dataTestId: dataTestId && `${dataTestId}-phoneNumberInput`, fieldSize: fieldSize, type: "tel", value: phoneNumber, disabled: disabled, onChange: handlePhoneNumberChange, isInvalid: isPhoneNumberInvalid || isInvalid, actions: !disableAction && (jsxRuntime.jsx(ActionButton, { disabled: disabled || isInvalid || isCountryCodeInvalid || isPhoneNumberInvalid, value: `${countryCode}${phoneNumber}`, type: "PHONE_NUMBER", dataTestId: dataTestId && `${dataTestId}-phoneIcon`, iconSize: fieldSize })) }, rest))] })));
|
|
916
1065
|
});
|
|
917
|
-
const Container
|
|
1066
|
+
const Container = tailwindStyledComponents.tw.div `
|
|
918
1067
|
grid
|
|
919
1068
|
grid-cols-min-fr
|
|
920
1069
|
gap-2
|
|
@@ -940,7 +1089,7 @@ const PhoneField = React.forwardRef((_a, ref) => {
|
|
|
940
1089
|
var { label, id, tip, helpText, isInvalid, errorMessage, value, helpAddon, className, defaultValue, dataTestId } = _a, rest = __rest(_a, ["label", "id", "tip", "helpText", "isInvalid", "errorMessage", "value", "helpAddon", "className", "defaultValue", "dataTestId"]);
|
|
941
1090
|
const renderAsInvalid = isInvalid || Boolean(errorMessage);
|
|
942
1091
|
const htmlForId = id ? id : "phoneField-" + uuid.v4();
|
|
943
|
-
return (jsxRuntime.jsx(FormGroup, Object.assign({ htmlFor: htmlForId, label: label, tip: tip, isInvalid: renderAsInvalid, helpText: (renderAsInvalid && errorMessage) || helpText, helpAddon: helpAddon, disabled: rest.disabled, className: className, dataTestId: dataTestId && `${dataTestId}-FormGroup` }, { children: jsxRuntime.jsx(PhoneInput, Object.assign({ id: htmlForId, "aria-labelledby": htmlForId + "-label", value: value
|
|
1092
|
+
return (jsxRuntime.jsx(FormGroup, Object.assign({ htmlFor: htmlForId, label: label, tip: tip, isInvalid: renderAsInvalid, helpText: (renderAsInvalid && errorMessage) || helpText, helpAddon: helpAddon, disabled: rest.disabled, className: className, dataTestId: dataTestId && `${dataTestId}-FormGroup` }, { children: jsxRuntime.jsx(PhoneInput, Object.assign({ id: htmlForId, "aria-labelledby": htmlForId + "-label", value: value !== null && value !== void 0 ? value : defaultValue, isInvalid: renderAsInvalid }, rest)) })));
|
|
944
1093
|
});
|
|
945
1094
|
|
|
946
1095
|
const RadioGroupContext = React__namespace.createContext(null);
|
|
@@ -981,7 +1130,7 @@ ${({ $inline }) => ($inline ? tailwindStyledComponents.tws `tu-radiogroup--inlin
|
|
|
981
1130
|
const RadioItem = ({ label, value, dataTestId, className, description }) => {
|
|
982
1131
|
const groupCtx = React__namespace.useContext(RadioGroupContext);
|
|
983
1132
|
const isChecked = (groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.value) === value;
|
|
984
|
-
return (jsxRuntime.jsxs(InputWrapper, Object.assign({ className: className, htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, "data-testid": dataTestId && `${dataTestId}-Wrapper` }, { children: [jsxRuntime.jsx(Input, { id: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, type: "radio", role: "radio", value: value, checked: isChecked, "$disabled": groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.disabled, "$isInvalid": groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.isInvalid, onChange: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.onChange, "data-testid": dataTestId, "$checked": isChecked }), jsxRuntime.jsxs(LabelContainer$1, { children: [jsxRuntime.jsx(Label, Object.assign({ htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, dataTestId: dataTestId && `${dataTestId}-Label`, disabled: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.disabled, isInvalid: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.isInvalid }, { children: label })), description && (jsxRuntime.jsx(Description$1, Object.assign({ htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, "data-testid": dataTestId && `${dataTestId}-Description`, "$disabled": groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.disabled }, { children: description })))] })] })));
|
|
1133
|
+
return (jsxRuntime.jsxs(InputWrapper, Object.assign({ className: className, htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, "data-testid": dataTestId && `${dataTestId}-Wrapper` }, { children: [jsxRuntime.jsx(Input, { id: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, type: "radio", role: "radio", value: value, checked: isChecked, "$disabled": groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.disabled, "$isInvalid": groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.isInvalid, onChange: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.onChange, "data-testid": dataTestId, "$checked": isChecked }), jsxRuntime.jsxs(LabelContainer$1, { children: [jsxRuntime.jsx(Label$1, Object.assign({ htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, dataTestId: dataTestId && `${dataTestId}-Label`, disabled: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.disabled, isInvalid: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.isInvalid }, { children: label })), description && (jsxRuntime.jsx(Description$1, Object.assign({ htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, "data-testid": dataTestId && `${dataTestId}-Description`, "$disabled": groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.disabled }, { children: description })))] })] })));
|
|
985
1134
|
};
|
|
986
1135
|
const InputWrapper = tailwindStyledComponents.tw.label `tu-radioitem__wrapper`;
|
|
987
1136
|
const Input = tailwindStyledComponents.tw.input `
|
|
@@ -1021,71 +1170,6 @@ const StyledTextInput = tailwindStyledComponents.twx(TextInput) `
|
|
|
1021
1170
|
${({ $widenOnFocus }) => $widenOnFocus && tailwindStyledComponents.tws `tu-search--widen-on-focus`}
|
|
1022
1171
|
`;
|
|
1023
1172
|
|
|
1024
|
-
/**
|
|
1025
|
-
* The SelectContainer component.
|
|
1026
|
-
*
|
|
1027
|
-
* @param {SelectContainerProps} props - The props for the SelectContainer component
|
|
1028
|
-
* @returns {JSX.Element} SelectContainer component
|
|
1029
|
-
*/
|
|
1030
|
-
const SelectContainer = ({ children, label, hideLabel, id, hasError, error, description, info, dataTestId, isDisabled, }) => {
|
|
1031
|
-
return (jsxRuntime.jsxs(Container, Object.assign({ "data-testid": dataTestId, "$hasError": hasError, "$isDisabled": isDisabled }, { children: [label && !hideLabel && jsxRuntime.jsx(Label, Object.assign({ htmlFor: id }, { children: label })), children, (hasError || info) && (jsxRuntime.jsx(InformativeText, Object.assign({ size: "small", "$hasError": hasError !== null && hasError !== void 0 ? hasError : false }, { children: hasError ? error : info })))] })));
|
|
1032
|
-
};
|
|
1033
|
-
const Container = tailwindStyledComponents.tw.label `
|
|
1034
|
-
tu-select__container
|
|
1035
|
-
tu-select
|
|
1036
|
-
${({ $hasError }) => ($hasError ? tailwindStyledComponents.tws `tu-select--invalid` : null)}
|
|
1037
|
-
${({ $isDisabled }) => ($isDisabled ? tailwindStyledComponents.tws `tu-select--disabled` : null)}
|
|
1038
|
-
`;
|
|
1039
|
-
const InformativeText = tailwindStyledComponents.twx(reactComponents.Text) `
|
|
1040
|
-
tu-informative-text
|
|
1041
|
-
${p => (p.$hasError ? `tu-informative-text--error` : null)}
|
|
1042
|
-
`;
|
|
1043
|
-
|
|
1044
|
-
/**
|
|
1045
|
-
* The CreatableSelect component.
|
|
1046
|
-
*
|
|
1047
|
-
* @param {CreateableSelectProps} props - The props for the CreatableSelect component
|
|
1048
|
-
* @returns {JSX.Element} CreatableSelect component
|
|
1049
|
-
*/
|
|
1050
|
-
const CreatableSelect = (props) => {
|
|
1051
|
-
const { id, dataTestId = "select", async, maxMenuHeight = 200, label, error, disabled, isMulti, value, hideLabel, description, info, options, onChange, isLoading, classNamePrefix = "", filterOption, prefix, } = props;
|
|
1052
|
-
const hasError = !!error;
|
|
1053
|
-
const { refPrefix, customStyles, menuIsOpen, customComponents, menuPlacement, openMenuHandler, closeMenuHandler, orderedOptions, } = useSelect(props);
|
|
1054
|
-
const selectProps = {
|
|
1055
|
-
value,
|
|
1056
|
-
menuPlacement,
|
|
1057
|
-
maxMenuHeight,
|
|
1058
|
-
onChange,
|
|
1059
|
-
"aria-label": label,
|
|
1060
|
-
"data-testid": dataTestId,
|
|
1061
|
-
components: customComponents,
|
|
1062
|
-
styles: customStyles,
|
|
1063
|
-
tabSelectsValue: false,
|
|
1064
|
-
blurInputOnSelect: !isMulti,
|
|
1065
|
-
menuPortalTarget: document.body,
|
|
1066
|
-
isSearchable: disabled ? false : true,
|
|
1067
|
-
menuShouldBlockScroll: true,
|
|
1068
|
-
menuShouldScrollIntoView: true,
|
|
1069
|
-
openMenuOnFocus: disabled ? false : true,
|
|
1070
|
-
menuIsOpen: disabled ? false : menuIsOpen,
|
|
1071
|
-
openMenuOnClick: true,
|
|
1072
|
-
closeMenuOnSelect: false,
|
|
1073
|
-
isMulti: isMulti,
|
|
1074
|
-
classNamePrefix,
|
|
1075
|
-
isLoading,
|
|
1076
|
-
id,
|
|
1077
|
-
};
|
|
1078
|
-
return (jsxRuntime.jsx(SelectContainer, Object.assign({ label: label, hideLabel: hideLabel, id: id, hasError: hasError, error: error, description: description, info: info, dataTestId: dataTestId, isDisabled: disabled }, { children: jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [prefix !== undefined && (jsxRuntime.jsx(SelectPrefix, Object.assign({ "data-testid": dataTestId && `${dataTestId}-prefix`, ref: refPrefix }, { children: prefix }))), async ? (jsxRuntime.jsx(ReactAsyncCreatableSelect__default["default"], Object.assign({ "aria-label": label, maxMenuHeight: maxMenuHeight, "data-testid": dataTestId, components: customComponents }, props, { onMenuOpen: () => {
|
|
1079
|
-
!disabled && openMenuHandler();
|
|
1080
|
-
}, onMenuClose: () => {
|
|
1081
|
-
closeMenuHandler();
|
|
1082
|
-
} }))) : (jsxRuntime.jsx(ReactCreatableSelect__default["default"], Object.assign({}, selectProps, { options: filterOption ? orderedOptions : options, isMulti: isMulti, onMenuOpen: () => {
|
|
1083
|
-
!disabled && openMenuHandler();
|
|
1084
|
-
}, onMenuClose: () => {
|
|
1085
|
-
closeMenuHandler();
|
|
1086
|
-
} })))] }) })));
|
|
1087
|
-
};
|
|
1088
|
-
|
|
1089
1173
|
/**
|
|
1090
1174
|
* The TextArea is a base component, and should not be used very often.
|
|
1091
1175
|
* For most cases the TextAreaField is the correct component.
|
|
@@ -1179,7 +1263,7 @@ const Toggle = React__namespace.forwardRef(({ toggled = false, onChange, disable
|
|
|
1179
1263
|
return (jsxRuntime.jsxs(ToggleWrapper, { children: [jsxRuntime.jsxs(InputContainer, Object.assign({ htmlFor: id }, { children: [jsxRuntime.jsx(HiddenInput, { name: name, type: "checkbox", checked: toggled, disabled: disabled, onChange: e => {
|
|
1180
1264
|
e.stopPropagation();
|
|
1181
1265
|
onChange(!toggled, e);
|
|
1182
|
-
}, id: id, "aria-checked": toggled, role: "checkbox", tabIndex: tabIndex, required: required, ref: ref, "data-testid": dataTestId && `${dataTestId}-Input`, onBlur: onBlur }), jsxRuntime.jsx(SwitchContainer, Object.assign({ "$toggled": toggled, htmlFor: id, "$disabled": disabled, "$size": size }, { children: jsxRuntime.jsx(Switch, { "$toggled": toggled, htmlFor: id, "data-testid": dataTestId && `${dataTestId}-Switch` }) }))] })), jsxRuntime.jsxs(LabelContainer, { children: [jsxRuntime.jsx(Label, Object.assign({ htmlFor: id, dataTestId: dataTestId && `${dataTestId}-Label`, disabled: disabled }, { children: name })), description && (jsxRuntime.jsx(Description, Object.assign({ htmlFor: id, "data-testid": dataTestId && `${dataTestId}-Description`, "$disabled": disabled }, { children: description })))] })] }));
|
|
1266
|
+
}, id: id, "aria-checked": toggled, role: "checkbox", tabIndex: tabIndex, required: required, ref: ref, "data-testid": dataTestId && `${dataTestId}-Input`, onBlur: onBlur }), jsxRuntime.jsx(SwitchContainer, Object.assign({ "$toggled": toggled, htmlFor: id, "$disabled": disabled, "$size": size }, { children: jsxRuntime.jsx(Switch, { "$toggled": toggled, htmlFor: id, "data-testid": dataTestId && `${dataTestId}-Switch` }) }))] })), jsxRuntime.jsxs(LabelContainer, { children: [jsxRuntime.jsx(Label$1, Object.assign({ htmlFor: id, dataTestId: dataTestId && `${dataTestId}-Label`, disabled: disabled }, { children: name })), description && (jsxRuntime.jsx(Description, Object.assign({ htmlFor: id, "data-testid": dataTestId && `${dataTestId}-Description`, "$disabled": disabled }, { children: description })))] })] }));
|
|
1183
1267
|
});
|
|
1184
1268
|
Toggle.displayName = "Toggle";
|
|
1185
1269
|
const ToggleWrapper = tailwindStyledComponents.tw.div `tu-toggle__wrapper`;
|
|
@@ -1250,10 +1334,11 @@ exports.DropZone = DropZone;
|
|
|
1250
1334
|
exports.EmailField = EmailField;
|
|
1251
1335
|
exports.EmailInput = EmailInput;
|
|
1252
1336
|
exports.FormGroup = FormGroup;
|
|
1253
|
-
exports.Label = Label;
|
|
1337
|
+
exports.Label = Label$1;
|
|
1254
1338
|
exports.MultiSelectMenuItem = MultiSelectMenuItem;
|
|
1255
1339
|
exports.NumberField = NumberField;
|
|
1256
1340
|
exports.NumberInput = NumberInput;
|
|
1341
|
+
exports.OptionCard = OptionCard;
|
|
1257
1342
|
exports.PhoneField = PhoneField;
|
|
1258
1343
|
exports.PhoneInput = PhoneInput;
|
|
1259
1344
|
exports.RadioGroup = RadioGroup;
|
package/index.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import { registerTranslations } from '@trackunit/i18n-library-translation';
|
|
3
|
-
import { IconButton, Icon, Tip, MenuItem, Tag, Spinner
|
|
3
|
+
import { IconButton, Icon, Tip, Heading, Text, MenuItem, Tag, Spinner } from '@trackunit/react-components';
|
|
4
4
|
import { tw, twx, tws } from '@trackunit/tailwind-styled-components';
|
|
5
5
|
import * as React from 'react';
|
|
6
|
-
import React__default, { forwardRef, useState, useEffect } from 'react';
|
|
6
|
+
import React__default, { forwardRef, useState, cloneElement, useEffect } from 'react';
|
|
7
7
|
import { v4 } from 'uuid';
|
|
8
8
|
import { format } from 'date-fns';
|
|
9
9
|
import ReactSelect, { components } from 'react-select';
|
|
10
10
|
export { default as ValueType } from 'react-select';
|
|
11
|
-
import ReactAsyncSelect from 'react-select/async';
|
|
12
|
-
import { getCountries, getCountryCallingCode } from 'libphonenumber-js';
|
|
13
11
|
import ReactAsyncCreatableSelect from 'react-select/async-creatable';
|
|
14
12
|
import ReactCreatableSelect from 'react-select/creatable';
|
|
13
|
+
import ReactAsyncSelect from 'react-select/async';
|
|
14
|
+
import parsePhoneNumberFromString, { getCountries, getCountryCallingCode } from 'libphonenumber-js';
|
|
15
15
|
|
|
16
16
|
var defaultTranslations = {
|
|
17
17
|
|
|
@@ -172,7 +172,7 @@ const InputContainer$1 = tw.label `
|
|
|
172
172
|
* @param {LabelProps} props - The props for the Label component
|
|
173
173
|
* @returns {JSX.Element} Label component
|
|
174
174
|
*/
|
|
175
|
-
const Label = ({ id, htmlFor, children, className, dataTestId, disabled, isInvalid, }) => {
|
|
175
|
+
const Label$1 = ({ id, htmlFor, children, className, dataTestId, disabled, isInvalid, }) => {
|
|
176
176
|
return (jsx(Root$2, Object.assign({ id: id || "", htmlFor: htmlFor || "", className: className, "data-testid": dataTestId, "$disabled": disabled, "$isInvalid": isInvalid }, { children: children })));
|
|
177
177
|
};
|
|
178
178
|
const Root$2 = tw.label `
|
|
@@ -225,7 +225,7 @@ const Checkbox = React.forwardRef((_a, ref) => {
|
|
|
225
225
|
}
|
|
226
226
|
};
|
|
227
227
|
const uuid = rest.id || dataTestId;
|
|
228
|
-
return (jsxs(CheckboxContainer, Object.assign({ "data-testid": dataTestId && `${dataTestId}Container`, htmlFor: uuid, className: className }, { children: [jsx(HiddenInput$1, Object.assign({ type: "checkbox", checked: !indeterminate && checked, onChange: onChange, disabled: disabled, "data-testid": dataTestId, readOnly: readOnly, "aria-checked": !indeterminate && checked, role: "checkbox", id: uuid }, rest, { ref: ref })), jsx(CheckboxWrapper, Object.assign({ id: uuid, "$disabled": isReadonly, "$checked": checked, "$indeterminate": indeterminate, "$isInvalid": isReadonly ? false : isInvalid, tabIndex: isReadonly ? -1 : tabIndex, onKeyPress: onKeyPress }, { children: icon })), label && (jsx(Label, Object.assign({ className: tws `cursor-pointer`, htmlFor: uuid, disabled: isReadonly, isInvalid: isReadonly ? false : isInvalid, dataTestId: dataTestId && `${dataTestId}-Label` }, { children: label }))), children] })));
|
|
228
|
+
return (jsxs(CheckboxContainer, Object.assign({ "data-testid": dataTestId && `${dataTestId}Container`, htmlFor: uuid, className: className }, { children: [jsx(HiddenInput$1, Object.assign({ type: "checkbox", checked: !indeterminate && checked, onChange: onChange, disabled: disabled, "data-testid": dataTestId, readOnly: readOnly, "aria-checked": !indeterminate && checked, role: "checkbox", id: uuid }, rest, { ref: ref })), jsx(CheckboxWrapper, Object.assign({ id: uuid, "$disabled": isReadonly, "$checked": checked, "$indeterminate": indeterminate, "$isInvalid": isReadonly ? false : isInvalid, tabIndex: isReadonly ? -1 : tabIndex, onKeyPress: onKeyPress }, { children: icon })), label && (jsx(Label$1, Object.assign({ className: tws `cursor-pointer`, htmlFor: uuid, disabled: isReadonly, isInvalid: isReadonly ? false : isInvalid, dataTestId: dataTestId && `${dataTestId}-Label` }, { children: label }))), children] })));
|
|
229
229
|
});
|
|
230
230
|
const StyledCheckIcon = twx(CheckIcon) `tu-checkbox--icon`;
|
|
231
231
|
const StyledIndeterminateIcon = twx(IndeterminateIcon) `tu-checkbox--icon`;
|
|
@@ -282,7 +282,7 @@ const FormGroupRoot = tw.div `
|
|
|
282
282
|
const ContainerBefore = tw.div `
|
|
283
283
|
tu-form-group__container-before
|
|
284
284
|
`;
|
|
285
|
-
const FormGroupLabel = twx(Label) `
|
|
285
|
+
const FormGroupLabel = twx(Label$1) `
|
|
286
286
|
component-formGroup-font
|
|
287
287
|
`;
|
|
288
288
|
const ContainerAfter = tw.div `
|
|
@@ -425,6 +425,58 @@ const NumberField = forwardRef((_a, ref) => {
|
|
|
425
425
|
return (jsx(FormGroup, Object.assign({ htmlFor: htmlForId, label: label, tip: tip, isInvalid: renderAsInvalid, helpText: (renderAsInvalid && errorMessage) || helpText, helpAddon: helpAddon, dataTestId: dataTestId && `${dataTestId}-FormGroup` }, { children: jsx(NumberInput, Object.assign({ id: htmlForId, "aria-labelledby": htmlForId + "-label", ref: ref, maxLength: maxLength, value: value, isInvalid: renderAsInvalid }, rest, { className: className, dataTestId: dataTestId })) })));
|
|
426
426
|
});
|
|
427
427
|
|
|
428
|
+
/**
|
|
429
|
+
* A card version of a radio button that includes an icon, headings and a description.
|
|
430
|
+
*/
|
|
431
|
+
const OptionCard = forwardRef((_a, ref) => {
|
|
432
|
+
var { icon, heading, subheading, description, disabled, id, value, className, dataTestId } = _a, rest = __rest(_a, ["icon", "heading", "subheading", "description", "disabled", "id", "value", "className", "dataTestId"]);
|
|
433
|
+
return (jsxs(Container$3, Object.assign({ "data-testid": dataTestId }, { children: [jsx("input", Object.assign({ ref: ref, id: id, type: "radio", value: value, className: "hidden peer" }, rest)), jsxs(Label, Object.assign({ htmlFor: id, className: className, "$disabled": disabled }, { children: [disabled && icon && cloneElement(icon, { className: `${icon.props.className} text-secondary-400` }), !disabled && icon, heading && (jsx(Heading, Object.assign({ variant: "secondary", subtle: disabled }, { children: heading }))), (subheading || description) && (jsxs(Content, { children: [subheading && (jsx(Text, Object.assign({ weight: "thick", align: "center", subtle: disabled }, { children: subheading }))), description && (jsx(Text, Object.assign({ subtle: true, align: "center" }, { children: description })))] }))] }))] })));
|
|
434
|
+
});
|
|
435
|
+
const Container$3 = tw.div `
|
|
436
|
+
contents
|
|
437
|
+
`;
|
|
438
|
+
const Label = tw.label `
|
|
439
|
+
tu-input-base
|
|
440
|
+
${p => (p.$disabled ? "tu-input--disabled" : "")}
|
|
441
|
+
${p => (p.$disabled ? "cursor-not-allowed" : "cursor-pointer")}
|
|
442
|
+
aspect-square
|
|
443
|
+
flex
|
|
444
|
+
flex-col
|
|
445
|
+
gap-2
|
|
446
|
+
justify-center
|
|
447
|
+
items-center
|
|
448
|
+
p-6
|
|
449
|
+
w-full
|
|
450
|
+
peer-checked:bg-primary-50
|
|
451
|
+
peer-checked:border-primary-600
|
|
452
|
+
peer-checked:border-2
|
|
453
|
+
`;
|
|
454
|
+
const Content = tw.div `
|
|
455
|
+
flex
|
|
456
|
+
flex-col
|
|
457
|
+
items-center
|
|
458
|
+
`;
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* The SelectContainer component.
|
|
462
|
+
*
|
|
463
|
+
* @param {SelectContainerProps} props - The props for the SelectContainer component
|
|
464
|
+
* @returns {JSX.Element} SelectContainer component
|
|
465
|
+
*/
|
|
466
|
+
const SelectContainer$1 = ({ children, label, hideLabel, id, hasError, error, description, info, dataTestId, isDisabled, }) => {
|
|
467
|
+
return (jsxs(Container$2, Object.assign({ "data-testid": dataTestId, "$hasError": hasError, "$isDisabled": isDisabled }, { children: [label && !hideLabel && jsx(Label$1, Object.assign({ htmlFor: id }, { children: label })), children, (hasError || info) && (jsx(InformativeText, Object.assign({ size: "small", "$hasError": hasError !== null && hasError !== void 0 ? hasError : false }, { children: hasError ? error : info })))] })));
|
|
468
|
+
};
|
|
469
|
+
const Container$2 = tw.label `
|
|
470
|
+
tu-select__container
|
|
471
|
+
tu-select
|
|
472
|
+
${({ $hasError }) => ($hasError ? tws `tu-select--invalid` : null)}
|
|
473
|
+
${({ $isDisabled }) => ($isDisabled ? tws `tu-select--disabled` : null)}
|
|
474
|
+
`;
|
|
475
|
+
const InformativeText = twx(Text) `
|
|
476
|
+
tu-informative-text
|
|
477
|
+
${p => (p.$hasError ? `tu-informative-text--error` : null)}
|
|
478
|
+
`;
|
|
479
|
+
|
|
428
480
|
/**
|
|
429
481
|
* @param {MultiValue<Option> | SingleValue<Option>} arg option to check type
|
|
430
482
|
* @returns {arg is MultiValue<Option> } is Multivalue
|
|
@@ -573,11 +625,11 @@ const TagsContainer = ({ items, width = "100%", itemsGap = 5, postFix }) => {
|
|
|
573
625
|
return null;
|
|
574
626
|
})
|
|
575
627
|
.filter(element => element !== null);
|
|
576
|
-
return (jsxs(Container$
|
|
628
|
+
return (jsxs(Container$1, Object.assign({ style: {
|
|
577
629
|
width: `${width}`,
|
|
578
630
|
}, "$ready": isReady, ref: containerRef }, { children: [renderedElements, postFix] })));
|
|
579
631
|
};
|
|
580
|
-
const Container$
|
|
632
|
+
const Container$1 = tw.div `
|
|
581
633
|
tu-select__dynamic-tag--container
|
|
582
634
|
${({ $ready }) => {
|
|
583
635
|
return $ready ? tws `visible` : tws `invisible`;
|
|
@@ -757,6 +809,51 @@ const useSelect = (_a) => {
|
|
|
757
809
|
};
|
|
758
810
|
};
|
|
759
811
|
|
|
812
|
+
/**
|
|
813
|
+
* The CreatableSelect component.
|
|
814
|
+
*
|
|
815
|
+
* @param {CreateableSelectProps} props - The props for the CreatableSelect component
|
|
816
|
+
* @returns {JSX.Element} CreatableSelect component
|
|
817
|
+
*/
|
|
818
|
+
const CreatableSelect = (props) => {
|
|
819
|
+
const { id, dataTestId = "select", async, maxMenuHeight = 200, label, error, disabled, isMulti, value, hideLabel, description, info, options, onChange, isLoading, classNamePrefix = "", filterOption, prefix, } = props;
|
|
820
|
+
const hasError = !!error;
|
|
821
|
+
const { refPrefix, customStyles, menuIsOpen, customComponents, menuPlacement, openMenuHandler, closeMenuHandler, orderedOptions, } = useSelect(props);
|
|
822
|
+
const selectProps = {
|
|
823
|
+
value,
|
|
824
|
+
menuPlacement,
|
|
825
|
+
maxMenuHeight,
|
|
826
|
+
onChange,
|
|
827
|
+
"aria-label": label,
|
|
828
|
+
"data-testid": dataTestId,
|
|
829
|
+
components: customComponents,
|
|
830
|
+
styles: customStyles,
|
|
831
|
+
tabSelectsValue: false,
|
|
832
|
+
blurInputOnSelect: !isMulti,
|
|
833
|
+
menuPortalTarget: document.body,
|
|
834
|
+
isSearchable: disabled ? false : true,
|
|
835
|
+
menuShouldBlockScroll: true,
|
|
836
|
+
menuShouldScrollIntoView: true,
|
|
837
|
+
openMenuOnFocus: disabled ? false : true,
|
|
838
|
+
menuIsOpen: disabled ? false : menuIsOpen,
|
|
839
|
+
openMenuOnClick: true,
|
|
840
|
+
closeMenuOnSelect: false,
|
|
841
|
+
isMulti: isMulti,
|
|
842
|
+
classNamePrefix,
|
|
843
|
+
isLoading,
|
|
844
|
+
id,
|
|
845
|
+
};
|
|
846
|
+
return (jsx(SelectContainer$1, Object.assign({ label: label, hideLabel: hideLabel, id: id, hasError: hasError, error: error, description: description, info: info, dataTestId: dataTestId, isDisabled: disabled }, { children: jsxs(Fragment, { children: [prefix !== undefined && (jsx(SelectPrefix, Object.assign({ "data-testid": dataTestId && `${dataTestId}-prefix`, ref: refPrefix }, { children: prefix }))), async ? (jsx(ReactAsyncCreatableSelect, Object.assign({ "aria-label": label, maxMenuHeight: maxMenuHeight, "data-testid": dataTestId, components: customComponents }, props, { onMenuOpen: () => {
|
|
847
|
+
!disabled && openMenuHandler();
|
|
848
|
+
}, onMenuClose: () => {
|
|
849
|
+
closeMenuHandler();
|
|
850
|
+
} }))) : (jsx(ReactCreatableSelect, Object.assign({}, selectProps, { options: filterOption ? orderedOptions : options, isMulti: isMulti, onMenuOpen: () => {
|
|
851
|
+
!disabled && openMenuHandler();
|
|
852
|
+
}, onMenuClose: () => {
|
|
853
|
+
closeMenuHandler();
|
|
854
|
+
} })))] }) })));
|
|
855
|
+
};
|
|
856
|
+
|
|
760
857
|
/**
|
|
761
858
|
* Selects are input components used to choose a value from a set.
|
|
762
859
|
*
|
|
@@ -794,9 +891,9 @@ const Select = (props) => {
|
|
|
794
891
|
onMenuScrollToBottom,
|
|
795
892
|
onInputChange,
|
|
796
893
|
};
|
|
797
|
-
return (jsxs(SelectContainer
|
|
894
|
+
return (jsxs(SelectContainer, Object.assign({ ref: refContainer, className: className, "data-testid": dataTestId, "$hasError": hasError, "$isDisabled": disabled }, { children: [prefix !== undefined && (jsx(SelectPrefix, Object.assign({ "data-testid": dataTestId && `${dataTestId}-prefix`, ref: refPrefix }, { children: prefix }))), async ? (jsx(ReactAsyncSelect, Object.assign({}, propsNoClassName, selectProps, async, { onMenuOpen: openMenuHandler, onMenuClose: closeMenuHandler }))) : (jsx(ReactSelect, Object.assign({}, propsNoClassName, selectProps, { options: filterOption ? orderedOptions : options, hideSelectedOptions: false, isMulti: isMulti, onMenuOpen: openMenuHandler, onMenuClose: closeMenuHandler })))] })));
|
|
798
895
|
};
|
|
799
|
-
const SelectContainer
|
|
896
|
+
const SelectContainer = tw.div `
|
|
800
897
|
tu-select
|
|
801
898
|
${({ $hasError }) => ($hasError ? tws `tu-select--invalid` : null)}
|
|
802
899
|
${({ $isDisabled }) => ($isDisabled ? tws `tu-select--disabled` : null)}
|
|
@@ -839,7 +936,7 @@ const countryCodesSet = [
|
|
|
839
936
|
]
|
|
840
937
|
.filter(code => !COUNTRY_CODES_NOT_SUPPORTED_BY_BACKEND.includes(code))
|
|
841
938
|
.sort((a, b) => Number(a) - Number(b));
|
|
842
|
-
const countryCodes = countryCodesSet.map(code => ({ label: `+${code}`, value: code }));
|
|
939
|
+
const countryCodes = countryCodesSet.map(code => ({ label: `+${code}`, value: `+${code}` })); // We add the + sign to the value so that the google libphonenumber-js can parse it correctly.
|
|
843
940
|
|
|
844
941
|
/**
|
|
845
942
|
* The CountryCodeSelect component is used to select a country code for a phone number.
|
|
@@ -847,7 +944,7 @@ const countryCodes = countryCodesSet.map(code => ({ label: `+${code}`, value: co
|
|
|
847
944
|
* @param {CountryCodeSelectProps} props - The props for the CountryCodeSelect component
|
|
848
945
|
* @returns {JSX.Element} CountryCodeSelect component
|
|
849
946
|
*/
|
|
850
|
-
const CountryCodeSelect = ({ excludedCountries, countryCode, isInvalid,
|
|
947
|
+
const CountryCodeSelect = ({ excludedCountries, countryCode, isInvalid, onChange, disabled, dataTestId, placeholder, }) => {
|
|
851
948
|
const [isCountryCodeMissing, setIsCountryCodeMissing] = useState(false);
|
|
852
949
|
useEffect(() => {
|
|
853
950
|
countryCode && setIsCountryCodeMissing(false);
|
|
@@ -855,37 +952,88 @@ const CountryCodeSelect = ({ excludedCountries, countryCode, isInvalid, setCount
|
|
|
855
952
|
const filteredCodes = countryCodes.filter(code => {
|
|
856
953
|
return !(excludedCountries === null || excludedCountries === void 0 ? void 0 : excludedCountries.some(excludedCode => excludedCode.value === code.value));
|
|
857
954
|
});
|
|
858
|
-
return (jsx(Select, { className: "w-28", "aria-invalid": isCountryCodeMissing, options: filteredCodes.map(code => code), value: filteredCodes.find(({ value
|
|
859
|
-
|
|
860
|
-
|
|
955
|
+
return (jsx(Select, { dataTestId: dataTestId, className: "w-28", "aria-invalid": isCountryCodeMissing, options: filteredCodes.map(code => code), value: filteredCodes.find(({ value }) => value === `+${countryCode}`), placeholder: placeholder, hasError: isCountryCodeMissing || isInvalid, maxMenuHeight: 200, onChange: onChange, disabled: disabled }));
|
|
956
|
+
};
|
|
957
|
+
|
|
958
|
+
/**
|
|
959
|
+
* @param phoneNumber - a phone number as a string
|
|
960
|
+
* @returns {boolean} true if the phone number starts with a plus sign
|
|
961
|
+
* @example checkIfPhoneNumberHasPlus("123456789") // false
|
|
962
|
+
* checkIfPhoneNumberHasPlus("+123456789") // true
|
|
963
|
+
*/
|
|
964
|
+
const checkIfPhoneNumberHasPlus = (phoneNumber) => {
|
|
965
|
+
return phoneNumber.startsWith("+");
|
|
966
|
+
};
|
|
967
|
+
/**
|
|
968
|
+
* @param phoneNumber - a phone number as a string
|
|
969
|
+
* @returns {string|number} the phone number with a plus sign in front of it
|
|
970
|
+
* @example getPhoneNumberWithPlus("123456789") // "+123456789"
|
|
971
|
+
*/
|
|
972
|
+
const getPhoneNumberWithPlus = (phoneNumber) => {
|
|
973
|
+
const stringPhoneNumber = phoneNumber.toString();
|
|
974
|
+
return checkIfPhoneNumberHasPlus(stringPhoneNumber) ? stringPhoneNumber : `+${stringPhoneNumber}`;
|
|
975
|
+
};
|
|
976
|
+
|
|
977
|
+
/**
|
|
978
|
+
* A custom hook for managing phone number input state and validation.
|
|
979
|
+
*
|
|
980
|
+
* @returns {object} - An object containing state values and event handler functions.
|
|
981
|
+
* @property {string} countryCode - The current country code value.
|
|
982
|
+
* @property {string} phoneNumber - The current phone number value.
|
|
983
|
+
* @property {boolean} isCountryCodeInvalid - Whether the country code value is invalid.
|
|
984
|
+
* @property {boolean} isPhoneNumberInvalid - Whether the phone number value is invalid.
|
|
985
|
+
* @property {Function} handleCountryCodeChange - A function for handling changes to the country code input.
|
|
986
|
+
* @property {Function} handlePhoneNumberChange - A function for handling changes to the phone number input.
|
|
987
|
+
*/
|
|
988
|
+
const usePhoneInput = (initialValue) => {
|
|
989
|
+
const [countryCode, setCountryCode] = useState("");
|
|
990
|
+
const [phoneNumber, setPhoneNumber] = useState("");
|
|
991
|
+
const [isCountryCodeInvalid, setIsCountryCodeInvalid] = useState(false);
|
|
992
|
+
const [isPhoneNumberInvalid, setIsPhoneNumberInvalid] = useState(false);
|
|
993
|
+
useEffect(() => {
|
|
994
|
+
var _a, _b;
|
|
995
|
+
if (initialValue) {
|
|
996
|
+
const safePhoneNumber = getPhoneNumberWithPlus(initialValue);
|
|
997
|
+
const number = parsePhoneNumberFromString(safePhoneNumber);
|
|
998
|
+
setCountryCode((_a = number === null || number === void 0 ? void 0 : number.countryCallingCode.toString()) !== null && _a !== void 0 ? _a : "");
|
|
999
|
+
setPhoneNumber((_b = number === null || number === void 0 ? void 0 : number.nationalNumber.toString()) !== null && _b !== void 0 ? _b : "");
|
|
1000
|
+
}
|
|
1001
|
+
}, [initialValue]);
|
|
1002
|
+
const handleCountryCodeChange = (option) => {
|
|
1003
|
+
var _a;
|
|
1004
|
+
setCountryCode((_a = option === null || option === void 0 ? void 0 : option.value) !== null && _a !== void 0 ? _a : "");
|
|
1005
|
+
setIsCountryCodeInvalid(!Boolean(option === null || option === void 0 ? void 0 : option.value));
|
|
1006
|
+
};
|
|
1007
|
+
const handlePhoneNumberChange = (event) => {
|
|
1008
|
+
setPhoneNumber(event.target.value);
|
|
1009
|
+
setIsPhoneNumberInvalid(!event.target.value || !Boolean(event.target.value.trim()));
|
|
1010
|
+
};
|
|
1011
|
+
return {
|
|
1012
|
+
countryCode,
|
|
1013
|
+
phoneNumber,
|
|
1014
|
+
isCountryCodeInvalid,
|
|
1015
|
+
isPhoneNumberInvalid,
|
|
1016
|
+
handleCountryCodeChange,
|
|
1017
|
+
handlePhoneNumberChange,
|
|
1018
|
+
};
|
|
861
1019
|
};
|
|
862
1020
|
|
|
863
1021
|
/**
|
|
864
1022
|
* A component for inputting phone numbers with an optional action button for initiating a phone call.
|
|
865
1023
|
*
|
|
866
1024
|
* @param {string} [dataTestId] - The data test ID for the component.
|
|
1025
|
+
* @param {string|number} [value] - The value of the input field. The value should include the country code as well.
|
|
867
1026
|
* @param {boolean} [disabled=false] - Whether the component is disabled or not.
|
|
868
1027
|
* @param {string} [fieldSize="medium"] - The size of the input field.
|
|
869
1028
|
* @param {boolean} [disableAction=false] - Whether the action button is disabled or not.
|
|
870
1029
|
* @returns {JSX.Element} - The PhoneInput component.
|
|
871
1030
|
*/
|
|
872
1031
|
const PhoneInput = forwardRef((_a, ref) => {
|
|
873
|
-
var { dataTestId, isInvalid, disabled = false, fieldSize = "medium", disableAction = false } = _a, rest = __rest(_a, ["dataTestId", "isInvalid", "disabled", "fieldSize", "disableAction"]);
|
|
874
|
-
const
|
|
875
|
-
|
|
876
|
-
const [countryCode, setCountryCode] = useState(undefined);
|
|
877
|
-
const [isPhoneNumberInvalid, setIsPhoneNumberInvalid] = useState(false);
|
|
878
|
-
const handlePhoneNumberChange = (e) => {
|
|
879
|
-
const input = e.target.value;
|
|
880
|
-
setIsPhoneNumberInvalid(!Boolean(input));
|
|
881
|
-
setPhoneNumber(input);
|
|
882
|
-
};
|
|
883
|
-
useEffect(() => {
|
|
884
|
-
setRenderAsInvalid(isInvalid || isPhoneNumberInvalid);
|
|
885
|
-
}, [isInvalid, isPhoneNumberInvalid]);
|
|
886
|
-
return (jsxs(Container$1, { children: [jsx(CountryCodeSelect, { isInvalid: renderAsInvalid, countryCode: countryCode, setCountryCode: setCountryCode }), jsx(BaseInput, Object.assign({ ref: ref, dataTestId: dataTestId, isInvalid: renderAsInvalid, fieldSize: fieldSize, type: "tel", value: phoneNumber, onChange: handlePhoneNumberChange, disabled: disabled, actions: !disableAction && (jsx(ActionButton, { disabled: !countryCode || !phoneNumber || disabled || renderAsInvalid, value: `${countryCode}${phoneNumber}`, type: "PHONE_NUMBER", dataTestId: dataTestId && `${dataTestId}-phoneIcon`, iconSize: fieldSize })) }, rest))] }));
|
|
1032
|
+
var { dataTestId, isInvalid, disabled = false, value, fieldSize = "medium", disableAction = false, onChange } = _a, rest = __rest(_a, ["dataTestId", "isInvalid", "disabled", "value", "fieldSize", "disableAction", "onChange"]);
|
|
1033
|
+
const { countryCode, phoneNumber, isCountryCodeInvalid, isPhoneNumberInvalid, handleCountryCodeChange, handlePhoneNumberChange, } = usePhoneInput(value);
|
|
1034
|
+
return (jsxs(Container, Object.assign({ "data-testid": `${dataTestId}-container` }, { children: [jsx("input", { hidden: true, id: "phone-input", "data-testid": dataTestId && `${dataTestId}`, value: value, ref: ref, onChange: onChange }), jsx(CountryCodeSelect, { dataTestId: dataTestId && `${dataTestId}-countryCodeSelect`, countryCode: countryCode, onChange: handleCountryCodeChange, disabled: disabled, isInvalid: isCountryCodeInvalid || isInvalid, placeholder: "+45" }), jsx(BaseInput, Object.assign({ id: "phoneInput-number", dataTestId: dataTestId && `${dataTestId}-phoneNumberInput`, fieldSize: fieldSize, type: "tel", value: phoneNumber, disabled: disabled, onChange: handlePhoneNumberChange, isInvalid: isPhoneNumberInvalid || isInvalid, actions: !disableAction && (jsx(ActionButton, { disabled: disabled || isInvalid || isCountryCodeInvalid || isPhoneNumberInvalid, value: `${countryCode}${phoneNumber}`, type: "PHONE_NUMBER", dataTestId: dataTestId && `${dataTestId}-phoneIcon`, iconSize: fieldSize })) }, rest))] })));
|
|
887
1035
|
});
|
|
888
|
-
const Container
|
|
1036
|
+
const Container = tw.div `
|
|
889
1037
|
grid
|
|
890
1038
|
grid-cols-min-fr
|
|
891
1039
|
gap-2
|
|
@@ -911,7 +1059,7 @@ const PhoneField = forwardRef((_a, ref) => {
|
|
|
911
1059
|
var { label, id, tip, helpText, isInvalid, errorMessage, value, helpAddon, className, defaultValue, dataTestId } = _a, rest = __rest(_a, ["label", "id", "tip", "helpText", "isInvalid", "errorMessage", "value", "helpAddon", "className", "defaultValue", "dataTestId"]);
|
|
912
1060
|
const renderAsInvalid = isInvalid || Boolean(errorMessage);
|
|
913
1061
|
const htmlForId = id ? id : "phoneField-" + v4();
|
|
914
|
-
return (jsx(FormGroup, Object.assign({ htmlFor: htmlForId, label: label, tip: tip, isInvalid: renderAsInvalid, helpText: (renderAsInvalid && errorMessage) || helpText, helpAddon: helpAddon, disabled: rest.disabled, className: className, dataTestId: dataTestId && `${dataTestId}-FormGroup` }, { children: jsx(PhoneInput, Object.assign({ id: htmlForId, "aria-labelledby": htmlForId + "-label", value: value
|
|
1062
|
+
return (jsx(FormGroup, Object.assign({ htmlFor: htmlForId, label: label, tip: tip, isInvalid: renderAsInvalid, helpText: (renderAsInvalid && errorMessage) || helpText, helpAddon: helpAddon, disabled: rest.disabled, className: className, dataTestId: dataTestId && `${dataTestId}-FormGroup` }, { children: jsx(PhoneInput, Object.assign({ id: htmlForId, "aria-labelledby": htmlForId + "-label", value: value !== null && value !== void 0 ? value : defaultValue, isInvalid: renderAsInvalid }, rest)) })));
|
|
915
1063
|
});
|
|
916
1064
|
|
|
917
1065
|
const RadioGroupContext = React.createContext(null);
|
|
@@ -952,7 +1100,7 @@ ${({ $inline }) => ($inline ? tws `tu-radiogroup--inline` : tws `tu-radiogroup`)
|
|
|
952
1100
|
const RadioItem = ({ label, value, dataTestId, className, description }) => {
|
|
953
1101
|
const groupCtx = React.useContext(RadioGroupContext);
|
|
954
1102
|
const isChecked = (groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.value) === value;
|
|
955
|
-
return (jsxs(InputWrapper, Object.assign({ className: className, htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, "data-testid": dataTestId && `${dataTestId}-Wrapper` }, { children: [jsx(Input, { id: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, type: "radio", role: "radio", value: value, checked: isChecked, "$disabled": groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.disabled, "$isInvalid": groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.isInvalid, onChange: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.onChange, "data-testid": dataTestId, "$checked": isChecked }), jsxs(LabelContainer$1, { children: [jsx(Label, Object.assign({ htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, dataTestId: dataTestId && `${dataTestId}-Label`, disabled: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.disabled, isInvalid: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.isInvalid }, { children: label })), description && (jsx(Description$1, Object.assign({ htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, "data-testid": dataTestId && `${dataTestId}-Description`, "$disabled": groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.disabled }, { children: description })))] })] })));
|
|
1103
|
+
return (jsxs(InputWrapper, Object.assign({ className: className, htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, "data-testid": dataTestId && `${dataTestId}-Wrapper` }, { children: [jsx(Input, { id: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, type: "radio", role: "radio", value: value, checked: isChecked, "$disabled": groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.disabled, "$isInvalid": groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.isInvalid, onChange: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.onChange, "data-testid": dataTestId, "$checked": isChecked }), jsxs(LabelContainer$1, { children: [jsx(Label$1, Object.assign({ htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, dataTestId: dataTestId && `${dataTestId}-Label`, disabled: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.disabled, isInvalid: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.isInvalid }, { children: label })), description && (jsx(Description$1, Object.assign({ htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, "data-testid": dataTestId && `${dataTestId}-Description`, "$disabled": groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.disabled }, { children: description })))] })] })));
|
|
956
1104
|
};
|
|
957
1105
|
const InputWrapper = tw.label `tu-radioitem__wrapper`;
|
|
958
1106
|
const Input = tw.input `
|
|
@@ -992,71 +1140,6 @@ const StyledTextInput = twx(TextInput) `
|
|
|
992
1140
|
${({ $widenOnFocus }) => $widenOnFocus && tws `tu-search--widen-on-focus`}
|
|
993
1141
|
`;
|
|
994
1142
|
|
|
995
|
-
/**
|
|
996
|
-
* The SelectContainer component.
|
|
997
|
-
*
|
|
998
|
-
* @param {SelectContainerProps} props - The props for the SelectContainer component
|
|
999
|
-
* @returns {JSX.Element} SelectContainer component
|
|
1000
|
-
*/
|
|
1001
|
-
const SelectContainer = ({ children, label, hideLabel, id, hasError, error, description, info, dataTestId, isDisabled, }) => {
|
|
1002
|
-
return (jsxs(Container, Object.assign({ "data-testid": dataTestId, "$hasError": hasError, "$isDisabled": isDisabled }, { children: [label && !hideLabel && jsx(Label, Object.assign({ htmlFor: id }, { children: label })), children, (hasError || info) && (jsx(InformativeText, Object.assign({ size: "small", "$hasError": hasError !== null && hasError !== void 0 ? hasError : false }, { children: hasError ? error : info })))] })));
|
|
1003
|
-
};
|
|
1004
|
-
const Container = tw.label `
|
|
1005
|
-
tu-select__container
|
|
1006
|
-
tu-select
|
|
1007
|
-
${({ $hasError }) => ($hasError ? tws `tu-select--invalid` : null)}
|
|
1008
|
-
${({ $isDisabled }) => ($isDisabled ? tws `tu-select--disabled` : null)}
|
|
1009
|
-
`;
|
|
1010
|
-
const InformativeText = twx(Text) `
|
|
1011
|
-
tu-informative-text
|
|
1012
|
-
${p => (p.$hasError ? `tu-informative-text--error` : null)}
|
|
1013
|
-
`;
|
|
1014
|
-
|
|
1015
|
-
/**
|
|
1016
|
-
* The CreatableSelect component.
|
|
1017
|
-
*
|
|
1018
|
-
* @param {CreateableSelectProps} props - The props for the CreatableSelect component
|
|
1019
|
-
* @returns {JSX.Element} CreatableSelect component
|
|
1020
|
-
*/
|
|
1021
|
-
const CreatableSelect = (props) => {
|
|
1022
|
-
const { id, dataTestId = "select", async, maxMenuHeight = 200, label, error, disabled, isMulti, value, hideLabel, description, info, options, onChange, isLoading, classNamePrefix = "", filterOption, prefix, } = props;
|
|
1023
|
-
const hasError = !!error;
|
|
1024
|
-
const { refPrefix, customStyles, menuIsOpen, customComponents, menuPlacement, openMenuHandler, closeMenuHandler, orderedOptions, } = useSelect(props);
|
|
1025
|
-
const selectProps = {
|
|
1026
|
-
value,
|
|
1027
|
-
menuPlacement,
|
|
1028
|
-
maxMenuHeight,
|
|
1029
|
-
onChange,
|
|
1030
|
-
"aria-label": label,
|
|
1031
|
-
"data-testid": dataTestId,
|
|
1032
|
-
components: customComponents,
|
|
1033
|
-
styles: customStyles,
|
|
1034
|
-
tabSelectsValue: false,
|
|
1035
|
-
blurInputOnSelect: !isMulti,
|
|
1036
|
-
menuPortalTarget: document.body,
|
|
1037
|
-
isSearchable: disabled ? false : true,
|
|
1038
|
-
menuShouldBlockScroll: true,
|
|
1039
|
-
menuShouldScrollIntoView: true,
|
|
1040
|
-
openMenuOnFocus: disabled ? false : true,
|
|
1041
|
-
menuIsOpen: disabled ? false : menuIsOpen,
|
|
1042
|
-
openMenuOnClick: true,
|
|
1043
|
-
closeMenuOnSelect: false,
|
|
1044
|
-
isMulti: isMulti,
|
|
1045
|
-
classNamePrefix,
|
|
1046
|
-
isLoading,
|
|
1047
|
-
id,
|
|
1048
|
-
};
|
|
1049
|
-
return (jsx(SelectContainer, Object.assign({ label: label, hideLabel: hideLabel, id: id, hasError: hasError, error: error, description: description, info: info, dataTestId: dataTestId, isDisabled: disabled }, { children: jsxs(Fragment, { children: [prefix !== undefined && (jsx(SelectPrefix, Object.assign({ "data-testid": dataTestId && `${dataTestId}-prefix`, ref: refPrefix }, { children: prefix }))), async ? (jsx(ReactAsyncCreatableSelect, Object.assign({ "aria-label": label, maxMenuHeight: maxMenuHeight, "data-testid": dataTestId, components: customComponents }, props, { onMenuOpen: () => {
|
|
1050
|
-
!disabled && openMenuHandler();
|
|
1051
|
-
}, onMenuClose: () => {
|
|
1052
|
-
closeMenuHandler();
|
|
1053
|
-
} }))) : (jsx(ReactCreatableSelect, Object.assign({}, selectProps, { options: filterOption ? orderedOptions : options, isMulti: isMulti, onMenuOpen: () => {
|
|
1054
|
-
!disabled && openMenuHandler();
|
|
1055
|
-
}, onMenuClose: () => {
|
|
1056
|
-
closeMenuHandler();
|
|
1057
|
-
} })))] }) })));
|
|
1058
|
-
};
|
|
1059
|
-
|
|
1060
1143
|
/**
|
|
1061
1144
|
* The TextArea is a base component, and should not be used very often.
|
|
1062
1145
|
* For most cases the TextAreaField is the correct component.
|
|
@@ -1150,7 +1233,7 @@ const Toggle = React.forwardRef(({ toggled = false, onChange, disabled, size = "
|
|
|
1150
1233
|
return (jsxs(ToggleWrapper, { children: [jsxs(InputContainer, Object.assign({ htmlFor: id }, { children: [jsx(HiddenInput, { name: name, type: "checkbox", checked: toggled, disabled: disabled, onChange: e => {
|
|
1151
1234
|
e.stopPropagation();
|
|
1152
1235
|
onChange(!toggled, e);
|
|
1153
|
-
}, id: id, "aria-checked": toggled, role: "checkbox", tabIndex: tabIndex, required: required, ref: ref, "data-testid": dataTestId && `${dataTestId}-Input`, onBlur: onBlur }), jsx(SwitchContainer, Object.assign({ "$toggled": toggled, htmlFor: id, "$disabled": disabled, "$size": size }, { children: jsx(Switch, { "$toggled": toggled, htmlFor: id, "data-testid": dataTestId && `${dataTestId}-Switch` }) }))] })), jsxs(LabelContainer, { children: [jsx(Label, Object.assign({ htmlFor: id, dataTestId: dataTestId && `${dataTestId}-Label`, disabled: disabled }, { children: name })), description && (jsx(Description, Object.assign({ htmlFor: id, "data-testid": dataTestId && `${dataTestId}-Description`, "$disabled": disabled }, { children: description })))] })] }));
|
|
1236
|
+
}, id: id, "aria-checked": toggled, role: "checkbox", tabIndex: tabIndex, required: required, ref: ref, "data-testid": dataTestId && `${dataTestId}-Input`, onBlur: onBlur }), jsx(SwitchContainer, Object.assign({ "$toggled": toggled, htmlFor: id, "$disabled": disabled, "$size": size }, { children: jsx(Switch, { "$toggled": toggled, htmlFor: id, "data-testid": dataTestId && `${dataTestId}-Switch` }) }))] })), jsxs(LabelContainer, { children: [jsx(Label$1, Object.assign({ htmlFor: id, dataTestId: dataTestId && `${dataTestId}-Label`, disabled: disabled }, { children: name })), description && (jsx(Description, Object.assign({ htmlFor: id, "data-testid": dataTestId && `${dataTestId}-Description`, "$disabled": disabled }, { children: description })))] })] }));
|
|
1154
1237
|
});
|
|
1155
1238
|
Toggle.displayName = "Toggle";
|
|
1156
1239
|
const ToggleWrapper = tw.div `tu-toggle__wrapper`;
|
|
@@ -1207,4 +1290,4 @@ const UploadField = forwardRef((_a, ref) => {
|
|
|
1207
1290
|
*/
|
|
1208
1291
|
setupLibraryTranslations();
|
|
1209
1292
|
|
|
1210
|
-
export { ActionButton, BaseInput, Checkbox, CreatableSelect, DateField, DateInput, DropZone, EmailField, EmailInput, FormGroup, Label, MultiSelectMenuItem, NumberField, NumberInput, PhoneField, PhoneInput, RadioGroup, RadioItem, Search, Select, SelectPrefix, SingleSelectMenuItem, TextArea, TextAreaField, TextField, TextInput, Toggle, UploadField, UploadInput, getOrderedOptions, isMultiValue, useCustomComponents };
|
|
1293
|
+
export { ActionButton, BaseInput, Checkbox, CreatableSelect, DateField, DateInput, DropZone, EmailField, EmailInput, FormGroup, Label$1 as Label, MultiSelectMenuItem, NumberField, NumberInput, OptionCard, PhoneField, PhoneInput, RadioGroup, RadioItem, Search, Select, SelectPrefix, SingleSelectMenuItem, TextArea, TextAreaField, TextField, TextInput, Toggle, UploadField, UploadInput, getOrderedOptions, isMultiValue, useCustomComponents };
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-form-components",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@trackunit/react-components": "0.1.
|
|
7
|
+
"@trackunit/react-components": "0.1.78",
|
|
8
8
|
"@trackunit/tailwind-styled-components": "0.0.55",
|
|
9
9
|
"react": "18.2.0",
|
|
10
10
|
"uuid": "8.3.2",
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { CommonProps, IconProps } from "@trackunit/react-components";
|
|
2
|
+
import { InputHTMLAttributes, ReactElement } from "react";
|
|
3
|
+
export interface IOptionCardProps extends InputHTMLAttributes<HTMLInputElement>, CommonProps {
|
|
4
|
+
/**
|
|
5
|
+
* Icon displayed at the top inside the OptionCard.
|
|
6
|
+
*/
|
|
7
|
+
icon?: ReactElement<IconProps>;
|
|
8
|
+
/**
|
|
9
|
+
* Heading displayed below the icon.
|
|
10
|
+
*/
|
|
11
|
+
heading?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Subheading displayed above the description.
|
|
14
|
+
*/
|
|
15
|
+
subheading?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Descriptive text displayed inside the OptionCard.
|
|
18
|
+
*/
|
|
19
|
+
description?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A card version of a radio button that includes an icon, headings and a description.
|
|
23
|
+
*/
|
|
24
|
+
export declare const OptionCard: import("react").ForwardRefExoticComponent<IOptionCardProps & import("react").RefAttributes<HTMLInputElement>>;
|
|
@@ -1,10 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { CommonProps } from "@trackunit/react-components";
|
|
3
|
+
import { SingleValue } from "react-select";
|
|
2
4
|
import { CountryCode } from "./CountryCodes";
|
|
3
|
-
interface CountryCodeSelectProps {
|
|
5
|
+
interface CountryCodeSelectProps extends CommonProps {
|
|
4
6
|
excludedCountries?: CountryCode;
|
|
5
7
|
countryCode?: string;
|
|
6
|
-
setCountryCode: Dispatch<SetStateAction<string | undefined>>;
|
|
7
8
|
isInvalid?: boolean;
|
|
9
|
+
onChange?: (option: SingleValue<{
|
|
10
|
+
label: string;
|
|
11
|
+
value: string;
|
|
12
|
+
}>) => void;
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
placeholder?: string;
|
|
8
15
|
}
|
|
9
16
|
/**
|
|
10
17
|
* The CountryCodeSelect component is used to select a country code for a phone number.
|
|
@@ -12,5 +19,5 @@ interface CountryCodeSelectProps {
|
|
|
12
19
|
* @param {CountryCodeSelectProps} props - The props for the CountryCodeSelect component
|
|
13
20
|
* @returns {JSX.Element} CountryCodeSelect component
|
|
14
21
|
*/
|
|
15
|
-
export declare const CountryCodeSelect: ({ excludedCountries, countryCode, isInvalid,
|
|
22
|
+
export declare const CountryCodeSelect: ({ excludedCountries, countryCode, isInvalid, onChange, disabled, dataTestId, placeholder, }: CountryCodeSelectProps) => JSX.Element;
|
|
16
23
|
export {};
|
|
@@ -16,6 +16,7 @@ export interface PhoneInputProps extends BaseInputExposedProps {
|
|
|
16
16
|
* A component for inputting phone numbers with an optional action button for initiating a phone call.
|
|
17
17
|
*
|
|
18
18
|
* @param {string} [dataTestId] - The data test ID for the component.
|
|
19
|
+
* @param {string|number} [value] - The value of the input field. The value should include the country code as well.
|
|
19
20
|
* @param {boolean} [disabled=false] - Whether the component is disabled or not.
|
|
20
21
|
* @param {string} [fieldSize="medium"] - The size of the input field.
|
|
21
22
|
* @param {boolean} [disableAction=false] - Whether the action button is disabled or not.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param phoneNumber - a phone number as a string
|
|
3
|
+
* @returns {boolean} true if the phone number starts with a plus sign
|
|
4
|
+
* @example checkIfPhoneNumberHasPlus("123456789") // false
|
|
5
|
+
* checkIfPhoneNumberHasPlus("+123456789") // true
|
|
6
|
+
*/
|
|
7
|
+
export declare const checkIfPhoneNumberHasPlus: (phoneNumber: string) => boolean;
|
|
8
|
+
/**
|
|
9
|
+
* @param phoneNumber - a phone number as a string
|
|
10
|
+
* @returns {string|number} the phone number with a plus sign in front of it
|
|
11
|
+
* @example getPhoneNumberWithPlus("123456789") // "+123456789"
|
|
12
|
+
*/
|
|
13
|
+
export declare const getPhoneNumberWithPlus: (phoneNumber: string | number | readonly string[]) => string;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
export interface usePhoneInputProps {
|
|
3
|
+
/**
|
|
4
|
+
* The current country code value.
|
|
5
|
+
*/
|
|
6
|
+
countryCode: string;
|
|
7
|
+
/**
|
|
8
|
+
* The current phone number value.
|
|
9
|
+
*/
|
|
10
|
+
phoneNumber: string;
|
|
11
|
+
/**
|
|
12
|
+
* Whether the country code value is invalid.
|
|
13
|
+
*/
|
|
14
|
+
isCountryCodeInvalid: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Whether the phone number value is invalid.
|
|
17
|
+
*/
|
|
18
|
+
isPhoneNumberInvalid: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* A function for handling changes to the country code input.
|
|
21
|
+
*/
|
|
22
|
+
handleCountryCodeChange: (option: {
|
|
23
|
+
label: string;
|
|
24
|
+
value: string;
|
|
25
|
+
} | null) => void;
|
|
26
|
+
/**
|
|
27
|
+
* A function for handling changes to the phone number input.
|
|
28
|
+
*/
|
|
29
|
+
handlePhoneNumberChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* A custom hook for managing phone number input state and validation.
|
|
33
|
+
*
|
|
34
|
+
* @returns {object} - An object containing state values and event handler functions.
|
|
35
|
+
* @property {string} countryCode - The current country code value.
|
|
36
|
+
* @property {string} phoneNumber - The current phone number value.
|
|
37
|
+
* @property {boolean} isCountryCodeInvalid - Whether the country code value is invalid.
|
|
38
|
+
* @property {boolean} isPhoneNumberInvalid - Whether the phone number value is invalid.
|
|
39
|
+
* @property {Function} handleCountryCodeChange - A function for handling changes to the country code input.
|
|
40
|
+
* @property {Function} handlePhoneNumberChange - A function for handling changes to the phone number input.
|
|
41
|
+
*/
|
|
42
|
+
export declare const usePhoneInput: (initialValue: string | number | readonly string[] | undefined) => usePhoneInputProps;
|
package/src/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export * from "./components/FormGroup/FormGroup";
|
|
|
10
10
|
export * from "./components/Label/Label";
|
|
11
11
|
export * from "./components/NumberField/NumberField";
|
|
12
12
|
export * from "./components/NumberInput/NumberInput";
|
|
13
|
+
export * from "./components/OptionCard/OptionCard";
|
|
13
14
|
export * from "./components/PhoneField/PhoneField";
|
|
14
15
|
export * from "./components/PhoneInput/PhoneInput";
|
|
15
16
|
export * from "./components/RadioGroup";
|