@verifiedinc-public/shared-ui-elements 1.3.2 → 2.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/README.md +4 -24
- package/dist/components/index.mjs +1 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.mjs +1 -0
- package/dist/hooks/useSearchParams.d.ts +5 -0
- package/dist/index.mjs +1 -0
- package/dist/shared/index-CTvz4BbG.mjs +105 -0
- package/dist/shared/phone.schema-XBbyizhq.mjs +1 -0
- package/dist/shared/shadows-fgmuXym6.mjs +1 -0
- package/dist/shared/unix.schema-CMYTtXco.mjs +1 -0
- package/dist/shared/useQRCode-DXiPIj-D.mjs +1 -0
- package/dist/shared/useSearchParams-CW9y02Ym.mjs +1 -0
- package/dist/styles/index.mjs +1 -0
- package/dist/utils/masks/index.mjs +1 -0
- package/dist/utils/string/index.mjs +1 -0
- package/dist/validations/index.mjs +1 -0
- package/package.json +29 -8
- package/dist/shared-ui-elements.mjs +0 -105
- package/src/components/Alert/Alert.tsx +0 -8
- package/src/components/Alert/FullWidthAlert.tsx +0 -27
- package/src/components/Alert/index.ts +0 -2
- package/src/components/Backdrop/index.tsx +0 -34
- package/src/components/Banners/Banner.tsx +0 -42
- package/src/components/Banners/ExactBirthdayBanner.tsx +0 -18
- package/src/components/Banners/ResendPhoneBanner.tsx +0 -55
- package/src/components/Banners/TestPhoneNumbersBanner.tsx +0 -25
- package/src/components/Banners/index.tsx +0 -4
- package/src/components/Button/index.tsx +0 -8
- package/src/components/CredentialRequestsEditor/CredentialRequestsEditor.context.tsx +0 -98
- package/src/components/CredentialRequestsEditor/components/CredentialRequestsField.tsx +0 -103
- package/src/components/CredentialRequestsEditor/components/DataFieldAccordion.tsx +0 -337
- package/src/components/CredentialRequestsEditor/components/DataFieldDeleteModal.tsx +0 -64
- package/src/components/CredentialRequestsEditor/components/DataFieldDescription.tsx +0 -68
- package/src/components/CredentialRequestsEditor/components/DataFieldMandatory.tsx +0 -84
- package/src/components/CredentialRequestsEditor/components/DataFieldMulti.tsx +0 -74
- package/src/components/CredentialRequestsEditor/components/DataFieldOptionType.tsx +0 -84
- package/src/components/CredentialRequestsEditor/components/DataFieldSection.tsx +0 -48
- package/src/components/CredentialRequestsEditor/components/DataFieldUserInput.tsx +0 -71
- package/src/components/CredentialRequestsEditor/components/RadioOption.tsx +0 -89
- package/src/components/CredentialRequestsEditor/contexts/CredentialRequestFieldContext.tsx +0 -36
- package/src/components/CredentialRequestsEditor/index.tsx +0 -15
- package/src/components/CredentialRequestsEditor/types/compositeCredentialSchema.ts +0 -1
- package/src/components/CredentialRequestsEditor/types/credentialSchemasDto.ts +0 -3
- package/src/components/CredentialRequestsEditor/types/form.ts +0 -28
- package/src/components/CredentialRequestsEditor/types/mandatoryEnum.ts +0 -5
- package/src/components/CredentialRequestsEditor/utils/buildDataFieldValue.ts +0 -65
- package/src/components/CredentialRequestsEditor/utils/prettyField.ts +0 -16
- package/src/components/Image.tsx +0 -10
- package/src/components/QRCodeDisplay/index.tsx +0 -50
- package/src/components/RequiredLabel/index.tsx +0 -15
- package/src/components/Snackbar/index.tsx +0 -156
- package/src/components/TextField/index.tsx +0 -8
- package/src/components/Tip/index.tsx +0 -18
- package/src/components/Typography/index.tsx +0 -8
- package/src/components/When.tsx +0 -28
- package/src/components/form/CountrySelector.tsx +0 -96
- package/src/components/form/DataFieldClearAdornment.tsx +0 -28
- package/src/components/form/DateInput.tsx +0 -78
- package/src/components/form/DefaultInput.tsx +0 -26
- package/src/components/form/InputMask.tsx +0 -41
- package/src/components/form/OTPInput.tsx +0 -254
- package/src/components/form/PhoneInput.tsx +0 -152
- package/src/components/form/SSNInput.tsx +0 -99
- package/src/components/form/SelectInput.tsx +0 -101
- package/src/components/form/TextMaskCustom.tsx +0 -48
- package/src/components/form/index.ts +0 -5
- package/src/components/index.ts +0 -13
- package/src/components/terms/AcceptTermsNotice.tsx +0 -27
- package/src/components/terms/LegalLink.tsx +0 -22
- package/src/components/verified/VerifiedImage.tsx +0 -272
- package/src/components/verified/VerifiedIncLogo.tsx +0 -11
- package/src/components/verified/index.ts +0 -2
- package/src/hooks/index.ts +0 -5
- package/src/hooks/useCallbackRef.ts +0 -22
- package/src/hooks/useCopyToClipboard.ts +0 -76
- package/src/hooks/useDisclosure.ts +0 -96
- package/src/hooks/useLocalStorage.ts +0 -24
- package/src/hooks/usePrevious.ts +0 -17
- package/src/hooks/useQRCode.ts +0 -62
- package/src/index.ts +0 -13
- package/src/stories/components/Alert.stories.tsx +0 -41
- package/src/stories/components/Button.stories.ts +0 -49
- package/src/stories/components/CredentialRequestsEditor.stories.tsx +0 -98
- package/src/stories/components/QRCodeDisplay.stories.tsx +0 -60
- package/src/stories/components/TextField.stories.ts +0 -59
- package/src/stories/components/Typography.stories.ts +0 -140
- package/src/stories/components/VerifiedImage.stories.tsx +0 -32
- package/src/stories/components/form/DateInput.stories.ts +0 -36
- package/src/stories/components/form/OTPInput.stories.tsx +0 -90
- package/src/stories/components/form/PhoneInput.stories.tsx +0 -34
- package/src/stories/components/form/SSNInput.stories.ts +0 -30
- package/src/stories/components/form/SelectInput.stories.ts +0 -39
- package/src/stories/hooks/useCopyToClipboard.stories.tsx +0 -45
- package/src/styles/colors.ts +0 -60
- package/src/styles/index.ts +0 -3
- package/src/styles/shadows.ts +0 -6
- package/src/styles/theme.ts +0 -257
- package/src/styles/typography.ts +0 -86
- package/src/utils/date.ts +0 -32
- package/src/utils/index.ts +0 -6
- package/src/utils/masks/index.ts +0 -6
- package/src/utils/omitProperty.ts +0 -19
- package/src/utils/phone.ts +0 -76
- package/src/utils/ssn.ts +0 -8
- package/src/utils/string/index.ts +0 -2
- package/src/utils/string/toCapitalize.ts +0 -13
- package/src/utils/string/toSentenceCase.ts +0 -7
- package/src/utils/wrapPromise.ts +0 -19
- package/src/validations/date.schema.ts +0 -18
- package/src/validations/description.schema.ts +0 -5
- package/src/validations/email.schema.ts +0 -3
- package/src/validations/field.schema.ts +0 -3
- package/src/validations/index.ts +0 -8
- package/src/validations/phone.schema.ts +0 -6
- package/src/validations/ssn.schema.ts +0 -24
- package/src/validations/state.schema.ts +0 -3
- package/src/validations/unix.schema.ts +0 -11
@@ -1,254 +0,0 @@
|
|
1
|
-
import {
|
2
|
-
type ChangeEvent,
|
3
|
-
type ForwardedRef,
|
4
|
-
forwardRef,
|
5
|
-
type KeyboardEvent,
|
6
|
-
useCallback,
|
7
|
-
useEffect,
|
8
|
-
useImperativeHandle,
|
9
|
-
useMemo,
|
10
|
-
useRef,
|
11
|
-
useState,
|
12
|
-
} from 'react';
|
13
|
-
import {
|
14
|
-
Box,
|
15
|
-
Stack,
|
16
|
-
type StackProps,
|
17
|
-
type SxProps,
|
18
|
-
TextField,
|
19
|
-
InputBase,
|
20
|
-
type InputBaseProps,
|
21
|
-
Typography,
|
22
|
-
useTheme,
|
23
|
-
FormControl,
|
24
|
-
} from '@mui/material';
|
25
|
-
import { v4 as uuid } from 'uuid';
|
26
|
-
|
27
|
-
interface OTPInputProps {
|
28
|
-
name?: string;
|
29
|
-
onChange?: (event: { target: { value: string } }) => void;
|
30
|
-
disabled?: boolean;
|
31
|
-
sx?: SxProps;
|
32
|
-
}
|
33
|
-
|
34
|
-
export type OTPInputInstance = Readonly<{
|
35
|
-
focus: () => void;
|
36
|
-
blur: () => void;
|
37
|
-
clear: () => void;
|
38
|
-
}> & { get value(): string; set value(newValue: string) };
|
39
|
-
|
40
|
-
/**
|
41
|
-
* OTP input component that displays individual field for each value.
|
42
|
-
* @param props
|
43
|
-
* @param ref
|
44
|
-
* @constructor
|
45
|
-
*/
|
46
|
-
function OTPInputComponent(
|
47
|
-
props: OTPInputProps,
|
48
|
-
ref: ForwardedRef<OTPInputInstance> | null,
|
49
|
-
): React.JSX.Element {
|
50
|
-
const theme = useTheme();
|
51
|
-
// Generate unique ids for each input.
|
52
|
-
const ids = useRef(Array.from({ length: 6 }, () => uuid()));
|
53
|
-
const [values, setValues] = useState<string[]>([]);
|
54
|
-
const inputRef = useRef<HTMLInputElement | null>(null);
|
55
|
-
const inputsRef = useRef<Array<HTMLInputElement | null>>([]);
|
56
|
-
|
57
|
-
const [isFocused, setIsFocused] = useState(false);
|
58
|
-
|
59
|
-
// Control inputs from outside via ref.
|
60
|
-
useImperativeHandle(
|
61
|
-
ref,
|
62
|
-
() => ({
|
63
|
-
get value() {
|
64
|
-
return values.join('');
|
65
|
-
},
|
66
|
-
set value(newValue: string) {
|
67
|
-
setValues(newValue.split(''));
|
68
|
-
// Trigger onChange when the value is set from outside.
|
69
|
-
props.onChange?.({ target: { value: newValue } });
|
70
|
-
},
|
71
|
-
focus() {
|
72
|
-
inputsRef.current[0]?.click();
|
73
|
-
inputsRef.current[0]?.focus();
|
74
|
-
},
|
75
|
-
blur() {
|
76
|
-
inputsRef.current.forEach((input) => input?.blur());
|
77
|
-
},
|
78
|
-
clear() {
|
79
|
-
setValues([]);
|
80
|
-
},
|
81
|
-
}),
|
82
|
-
[props, values],
|
83
|
-
);
|
84
|
-
|
85
|
-
const inputContainerProps: StackProps = {
|
86
|
-
boxSizing: 'content-box',
|
87
|
-
direction: 'row',
|
88
|
-
alignItems: 'center',
|
89
|
-
spacing: 1.25,
|
90
|
-
sx: {
|
91
|
-
'& input': {
|
92
|
-
textAlign: 'center',
|
93
|
-
fontWeight: 500,
|
94
|
-
height: 30,
|
95
|
-
[theme.breakpoints.down('xs')]: {
|
96
|
-
height: 16,
|
97
|
-
fontSize: 16,
|
98
|
-
pt: 1,
|
99
|
-
pb: 1,
|
100
|
-
px: 1,
|
101
|
-
},
|
102
|
-
[theme.breakpoints.up('xs')]: {
|
103
|
-
fontSize: 28,
|
104
|
-
px: 1,
|
105
|
-
},
|
106
|
-
fontSize: 32,
|
107
|
-
py: 1.75,
|
108
|
-
},
|
109
|
-
},
|
110
|
-
};
|
111
|
-
const inputProps: InputBaseProps = useMemo(
|
112
|
-
() => ({
|
113
|
-
inputProps: {
|
114
|
-
inputMode: 'numeric',
|
115
|
-
pattern: '[0-9]*',
|
116
|
-
autoCorrect: 'off',
|
117
|
-
autoCapitalize: 'off',
|
118
|
-
},
|
119
|
-
sx: {
|
120
|
-
'& input': {
|
121
|
-
borderRadius: 1,
|
122
|
-
borderStyle: 'solid',
|
123
|
-
borderColor: 'rgba(0, 0, 0, 0.23)',
|
124
|
-
borderWidth: 1,
|
125
|
-
},
|
126
|
-
...(isFocused && {
|
127
|
-
'& input': {
|
128
|
-
borderRadius: 1,
|
129
|
-
borderStyle: 'solid',
|
130
|
-
borderWidth: 1,
|
131
|
-
borderColor: theme.palette.primary.main,
|
132
|
-
boxShadow: `inset 0 0 0 1px ${theme.palette.primary.main}`,
|
133
|
-
},
|
134
|
-
}),
|
135
|
-
},
|
136
|
-
}),
|
137
|
-
[isFocused, theme.palette.primary.main],
|
138
|
-
);
|
139
|
-
|
140
|
-
const focusFirstEmptyInput = useCallback(() => {
|
141
|
-
const valuesString = values.join('');
|
142
|
-
const firstEmptyInput = inputsRef.current[valuesString.length];
|
143
|
-
|
144
|
-
firstEmptyInput?.focus();
|
145
|
-
firstEmptyInput?.select();
|
146
|
-
}, [values]);
|
147
|
-
|
148
|
-
const handleChange = useCallback(
|
149
|
-
(event: ChangeEvent<HTMLInputElement>) => {
|
150
|
-
const value = event.target.value;
|
151
|
-
|
152
|
-
// Allow up to 6 digits only.
|
153
|
-
if (!value.length || !/^[0-9]{1,6}$/.test(value)) return;
|
154
|
-
|
155
|
-
setValues((prev) => {
|
156
|
-
const newValue = value.length === 6 ? [...value] : [...prev, ...value];
|
157
|
-
const newValueString = newValue.join('');
|
158
|
-
|
159
|
-
if (inputRef.current) {
|
160
|
-
inputRef.current.value = newValue.join('');
|
161
|
-
}
|
162
|
-
|
163
|
-
// Calls onChange when all OTP fields are filled.
|
164
|
-
if (newValueString.length === 6) {
|
165
|
-
inputsRef.current.forEach((input) => input?.blur());
|
166
|
-
props.onChange?.({ target: { value: newValueString } });
|
167
|
-
}
|
168
|
-
|
169
|
-
return newValue;
|
170
|
-
});
|
171
|
-
},
|
172
|
-
[props],
|
173
|
-
);
|
174
|
-
|
175
|
-
const handleKeyUp = useCallback((event: KeyboardEvent<HTMLInputElement>) => {
|
176
|
-
if (event.key === 'Backspace') {
|
177
|
-
setValues((prev) => {
|
178
|
-
const newValue = [...prev.slice(0, -1)];
|
179
|
-
if (inputRef.current) {
|
180
|
-
inputRef.current.value = newValue.join('');
|
181
|
-
}
|
182
|
-
return newValue;
|
183
|
-
});
|
184
|
-
}
|
185
|
-
}, []);
|
186
|
-
|
187
|
-
const handleFocus = useCallback(() => {
|
188
|
-
focusFirstEmptyInput();
|
189
|
-
setIsFocused(true);
|
190
|
-
}, [focusFirstEmptyInput]);
|
191
|
-
|
192
|
-
const renderInputGroup = useCallback(
|
193
|
-
(startIndex: number) => {
|
194
|
-
return new Array(3).fill(undefined).map((_, index) => {
|
195
|
-
return (
|
196
|
-
// FormControl is required for InputBase to avoid bad setState in handleBlur event, and it is one per input.
|
197
|
-
<FormControl key={ids.current[index + startIndex]}>
|
198
|
-
<InputBase
|
199
|
-
inputRef={(input) =>
|
200
|
-
((inputsRef.current[index + startIndex] as any) = input)
|
201
|
-
}
|
202
|
-
autoComplete='one-time-code'
|
203
|
-
autoFocus={index + startIndex === 0}
|
204
|
-
value={values[index + startIndex] || ''}
|
205
|
-
disabled={props.disabled}
|
206
|
-
onChange={handleChange}
|
207
|
-
onKeyUp={handleKeyUp}
|
208
|
-
onFocus={handleFocus}
|
209
|
-
onBlur={() => setIsFocused(false)}
|
210
|
-
{...inputProps}
|
211
|
-
data-testid={`otp-input-${index + startIndex}`}
|
212
|
-
/>
|
213
|
-
</FormControl>
|
214
|
-
);
|
215
|
-
});
|
216
|
-
},
|
217
|
-
[
|
218
|
-
handleChange,
|
219
|
-
handleFocus,
|
220
|
-
handleKeyUp,
|
221
|
-
inputProps,
|
222
|
-
props.disabled,
|
223
|
-
values,
|
224
|
-
],
|
225
|
-
);
|
226
|
-
|
227
|
-
// Focus the first empty input when the value changes.
|
228
|
-
useEffect(() => {
|
229
|
-
focusFirstEmptyInput();
|
230
|
-
}, [focusFirstEmptyInput]);
|
231
|
-
|
232
|
-
return (
|
233
|
-
<Box width='100%' sx={props.sx}>
|
234
|
-
{/* Use input facade to update the value and listen to changes */}
|
235
|
-
<div style={{ display: 'none!important', pointerEvents: 'none' }}>
|
236
|
-
<TextField
|
237
|
-
inputRef={inputRef}
|
238
|
-
name={props.name}
|
239
|
-
type='text'
|
240
|
-
value={values.join('') || ''}
|
241
|
-
sx={{ pointerEvents: 'none', display: 'none' }}
|
242
|
-
inputProps={{ hidden: true }}
|
243
|
-
/>
|
244
|
-
</div>
|
245
|
-
<Stack {...inputContainerProps} onClick={focusFirstEmptyInput}>
|
246
|
-
{renderInputGroup(0)}
|
247
|
-
<Typography sx={{ fontWeight: '700', fontSize: 32 }}>-</Typography>
|
248
|
-
{renderInputGroup(3)}
|
249
|
-
</Stack>
|
250
|
-
</Box>
|
251
|
-
);
|
252
|
-
}
|
253
|
-
|
254
|
-
export const OTPInput = forwardRef(OTPInputComponent);
|
@@ -1,152 +0,0 @@
|
|
1
|
-
import { Box, InputAdornment, type InputProps } from '@mui/material';
|
2
|
-
import { type TextFieldProps } from '../TextField';
|
3
|
-
import { useEffect, useMemo, useRef, useState } from 'react';
|
4
|
-
|
5
|
-
import { getPhoneDataByFieldName } from '../../utils/phone';
|
6
|
-
import { phoneSchema } from '../../validations/phone.schema';
|
7
|
-
|
8
|
-
import { TextMaskCustom } from './TextMaskCustom';
|
9
|
-
import CountrySelector from './CountrySelector';
|
10
|
-
import DefaultInput from './DefaultInput';
|
11
|
-
import { DataFieldClearAdornment } from './DataFieldClearAdornment';
|
12
|
-
|
13
|
-
export interface PhoneInputProps {
|
14
|
-
label?: string;
|
15
|
-
name?: string;
|
16
|
-
helperText?: string;
|
17
|
-
initialValue?: string;
|
18
|
-
onChange?: (value: string) => void;
|
19
|
-
onValidPhone?: (value: string) => void;
|
20
|
-
error?: boolean;
|
21
|
-
handleChangeCountry?: (newCountry: string) => void;
|
22
|
-
value?: string;
|
23
|
-
shouldShowOnlyNorthAmericanCountries?: boolean;
|
24
|
-
shouldHaveClearButton?: boolean;
|
25
|
-
variant?: TextFieldProps['variant'];
|
26
|
-
InputProps?: InputProps;
|
27
|
-
}
|
28
|
-
|
29
|
-
/**
|
30
|
-
* Renders a phone input component with country selector and masking.
|
31
|
-
*
|
32
|
-
* @param label - The label for the phone input. Defaults to 'Phone'.
|
33
|
-
* @param name - The name of the phone input. Defaults to 'phone'.
|
34
|
-
* @param helperText - The helper text for the phone input.
|
35
|
-
* @param onChange - The callback function to handle the change event of the phone input.
|
36
|
-
* @param initialValue - The initial value for the phone input. Defaults to ''.
|
37
|
-
* @param error - Whether the phone input has an error. Defaults to false.
|
38
|
-
* @param handleChangeCountry - The callback function to handle the change event of the country selector.
|
39
|
-
* @param value - The value of the phone input. If passed, it will be used instead of the value from component state.
|
40
|
-
*/
|
41
|
-
export function PhoneInput({
|
42
|
-
label = 'Phone',
|
43
|
-
name = 'phone',
|
44
|
-
helperText,
|
45
|
-
onChange,
|
46
|
-
onValidPhone,
|
47
|
-
initialValue = '',
|
48
|
-
error = false,
|
49
|
-
handleChangeCountry,
|
50
|
-
value: valueProp,
|
51
|
-
InputProps,
|
52
|
-
shouldHaveClearButton = false,
|
53
|
-
}: Readonly<PhoneInputProps>): React.JSX.Element {
|
54
|
-
const inputRef = useRef<HTMLInputElement | null>(null);
|
55
|
-
|
56
|
-
/**
|
57
|
-
* Represents the country selected for the phone input. Defaults to US.
|
58
|
-
*/
|
59
|
-
const [country, setCountry] = useState<string>('US');
|
60
|
-
|
61
|
-
/**
|
62
|
-
* Represents the value of the phone input. Initially set to the initialValue passed in the props.
|
63
|
-
*/
|
64
|
-
const [value, setValue] = useState<string>(initialValue);
|
65
|
-
|
66
|
-
const phoneData = useMemo(
|
67
|
-
() => getPhoneDataByFieldName('countryCode', country),
|
68
|
-
[country],
|
69
|
-
);
|
70
|
-
|
71
|
-
/**
|
72
|
-
* Handles the change of the selected country in the phone input.
|
73
|
-
* @param newCountry - The selected country.
|
74
|
-
*/
|
75
|
-
const _handleChangeCountry = (newCountry: string): void => {
|
76
|
-
setCountry(newCountry);
|
77
|
-
|
78
|
-
if (handleChangeCountry) {
|
79
|
-
handleChangeCountry(newCountry);
|
80
|
-
}
|
81
|
-
|
82
|
-
// HACK alert:
|
83
|
-
// Wait a while so focus can take effect.
|
84
|
-
setTimeout(() => {
|
85
|
-
inputRef.current?.focus();
|
86
|
-
}, 10);
|
87
|
-
};
|
88
|
-
|
89
|
-
const checkIsValidPhone = (phone: string): void => {
|
90
|
-
const validation = phoneSchema.safeParse(value);
|
91
|
-
if (validation.success) {
|
92
|
-
onValidPhone?.(phone);
|
93
|
-
}
|
94
|
-
};
|
95
|
-
|
96
|
-
const handleChange = (value: string): void => {
|
97
|
-
setValue(value);
|
98
|
-
onChange?.(value);
|
99
|
-
};
|
100
|
-
|
101
|
-
useEffect(() => {
|
102
|
-
checkIsValidPhone(value);
|
103
|
-
}, [value]);
|
104
|
-
|
105
|
-
const inputProps: TextFieldProps = {
|
106
|
-
inputRef,
|
107
|
-
label,
|
108
|
-
name: `_${name}`,
|
109
|
-
helperText,
|
110
|
-
// if the value prop is passed, use it, otherwise use the value from component state
|
111
|
-
// this allows the parent component to control the value of the input field
|
112
|
-
value: valueProp ?? value,
|
113
|
-
error,
|
114
|
-
onChange: (e) => {
|
115
|
-
handleChange(e.target.value);
|
116
|
-
},
|
117
|
-
inputProps: {
|
118
|
-
// Receive unmasked value on change.
|
119
|
-
unmask: true,
|
120
|
-
// Make placeholder always visible
|
121
|
-
lazy: false,
|
122
|
-
mask: phoneData?.mask,
|
123
|
-
placeholderChar: '_',
|
124
|
-
// Tab index for each block.
|
125
|
-
tabIndex: 0,
|
126
|
-
},
|
127
|
-
InputProps: {
|
128
|
-
...InputProps,
|
129
|
-
inputComponent: TextMaskCustom as any,
|
130
|
-
startAdornment: (
|
131
|
-
<InputAdornment position='start'>
|
132
|
-
<CountrySelector value={country} onChange={_handleChangeCountry} />
|
133
|
-
</InputAdornment>
|
134
|
-
),
|
135
|
-
endAdornment: shouldHaveClearButton && (
|
136
|
-
<DataFieldClearAdornment
|
137
|
-
handleClear={() => {
|
138
|
-
handleChange('');
|
139
|
-
}}
|
140
|
-
/>
|
141
|
-
),
|
142
|
-
},
|
143
|
-
fullWidth: true,
|
144
|
-
};
|
145
|
-
|
146
|
-
return (
|
147
|
-
<Box width='100%'>
|
148
|
-
<input name={name} value={value} readOnly type='hidden' hidden />
|
149
|
-
<DefaultInput {...inputProps} />
|
150
|
-
</Box>
|
151
|
-
);
|
152
|
-
}
|
@@ -1,99 +0,0 @@
|
|
1
|
-
import { useState } from 'react';
|
2
|
-
import { Box, TextField, type TextFieldProps } from '@mui/material';
|
3
|
-
|
4
|
-
import { usePrevious } from '../../hooks/usePrevious';
|
5
|
-
import { DataFieldClearAdornment } from './DataFieldClearAdornment';
|
6
|
-
import { TextMaskCustom } from './TextMaskCustom';
|
7
|
-
|
8
|
-
type TextStyles = Omit<TextFieldProps, 'onChange'> & { onChange: any };
|
9
|
-
|
10
|
-
export interface SSNInputProps {
|
11
|
-
onChange?: (event: { target: { value: string } }) => void;
|
12
|
-
name?: string;
|
13
|
-
value?: string;
|
14
|
-
label?: string;
|
15
|
-
error?: boolean;
|
16
|
-
helperText?: string;
|
17
|
-
shouldHaveCloseAdornment?: boolean;
|
18
|
-
}
|
19
|
-
|
20
|
-
/**
|
21
|
-
* This component manages the input of type SSN.
|
22
|
-
* @constructor
|
23
|
-
*/
|
24
|
-
export function SSNInput({
|
25
|
-
onChange,
|
26
|
-
label = 'Social Security number',
|
27
|
-
shouldHaveCloseAdornment = false,
|
28
|
-
...rest
|
29
|
-
}: SSNInputProps): React.JSX.Element {
|
30
|
-
// Arbitrary states to allow to empty input field.
|
31
|
-
const [value, setValue] = useState<string | undefined>('');
|
32
|
-
const previousValue = usePrevious(value);
|
33
|
-
|
34
|
-
const handleChange = (value: string): void => {
|
35
|
-
setValue(value);
|
36
|
-
onChange?.({ target: { value } });
|
37
|
-
};
|
38
|
-
|
39
|
-
const handleClear = (): void => {
|
40
|
-
handleChange('');
|
41
|
-
onChange?.({ target: { value: '' } });
|
42
|
-
};
|
43
|
-
|
44
|
-
const textFieldStyle: TextStyles = {
|
45
|
-
value,
|
46
|
-
onChange: (e: any, nativeEvent: any) => {
|
47
|
-
if (!nativeEvent) return;
|
48
|
-
handleChange(e.target.value);
|
49
|
-
},
|
50
|
-
inputProps: {
|
51
|
-
onFocus: () => {
|
52
|
-
handleChange('');
|
53
|
-
},
|
54
|
-
onBlur: () => {
|
55
|
-
if (value?.length) return;
|
56
|
-
handleChange(previousValue ?? '');
|
57
|
-
},
|
58
|
-
|
59
|
-
// Use onChange event.
|
60
|
-
useOnComplete: false,
|
61
|
-
// Use unmasked value.
|
62
|
-
unmask: true,
|
63
|
-
// Mask in the pattern of SSN.
|
64
|
-
mask: 'XXX-XX-0000',
|
65
|
-
|
66
|
-
definitions: {
|
67
|
-
X: {
|
68
|
-
mask: /[0-9•]/,
|
69
|
-
displayChar: '•',
|
70
|
-
},
|
71
|
-
},
|
72
|
-
|
73
|
-
// Set input mode to numeric, so mobile virtual keyboards just show numeric keys.
|
74
|
-
inputMode: 'numeric',
|
75
|
-
|
76
|
-
overwrite: false,
|
77
|
-
// Tab index for each block.
|
78
|
-
tabIndex: 0,
|
79
|
-
},
|
80
|
-
InputProps: {
|
81
|
-
inputComponent: TextMaskCustom as any,
|
82
|
-
|
83
|
-
endAdornment: !!shouldHaveCloseAdornment && (
|
84
|
-
<DataFieldClearAdornment
|
85
|
-
onClick={handleClear}
|
86
|
-
handleClear={handleClear}
|
87
|
-
/>
|
88
|
-
),
|
89
|
-
},
|
90
|
-
fullWidth: true,
|
91
|
-
label,
|
92
|
-
};
|
93
|
-
|
94
|
-
return (
|
95
|
-
<Box width='100%'>
|
96
|
-
<TextField {...textFieldStyle} {...rest} />
|
97
|
-
</Box>
|
98
|
-
);
|
99
|
-
}
|
@@ -1,101 +0,0 @@
|
|
1
|
-
import {
|
2
|
-
Autocomplete,
|
3
|
-
TextField,
|
4
|
-
type TextFieldProps as InternalFieldProps,
|
5
|
-
} from '@mui/material';
|
6
|
-
import { useState } from 'react';
|
7
|
-
|
8
|
-
interface TextFieldProps extends Omit<InternalFieldProps, 'onChange'> {}
|
9
|
-
|
10
|
-
interface Option {
|
11
|
-
label: string;
|
12
|
-
id: string;
|
13
|
-
}
|
14
|
-
|
15
|
-
interface SelectInputProps {
|
16
|
-
name?: string;
|
17
|
-
onChange?: (value: Option | null) => void;
|
18
|
-
onClear?: () => void;
|
19
|
-
options: Option[];
|
20
|
-
value?: Option | null; // Controlled value
|
21
|
-
defaultOption?: Option;
|
22
|
-
InputProps?: TextFieldProps;
|
23
|
-
disableClearable?: boolean;
|
24
|
-
}
|
25
|
-
|
26
|
-
/**
|
27
|
-
* This component manages the input of type Select.
|
28
|
-
* @constructor
|
29
|
-
*/
|
30
|
-
export function SelectInput({
|
31
|
-
options,
|
32
|
-
defaultOption,
|
33
|
-
value: controlledValue,
|
34
|
-
onChange,
|
35
|
-
onClear,
|
36
|
-
disableClearable,
|
37
|
-
...props
|
38
|
-
}: SelectInputProps): React.JSX.Element {
|
39
|
-
const [internalValue, setInternalValue] = useState<Option | null>(
|
40
|
-
defaultOption ?? null,
|
41
|
-
);
|
42
|
-
|
43
|
-
// Determine the value to display
|
44
|
-
const isControlled = controlledValue !== undefined;
|
45
|
-
const value = isControlled ? controlledValue : internalValue;
|
46
|
-
|
47
|
-
const handleChange = (option: Option | null): void => {
|
48
|
-
if (!isControlled) {
|
49
|
-
setInternalValue(option); // Update internal state only if uncontrolled
|
50
|
-
}
|
51
|
-
if (onChange) {
|
52
|
-
onChange(option);
|
53
|
-
}
|
54
|
-
};
|
55
|
-
|
56
|
-
const handleClear = (): void => {
|
57
|
-
handleChange(null);
|
58
|
-
if (onClear) {
|
59
|
-
onClear();
|
60
|
-
}
|
61
|
-
};
|
62
|
-
|
63
|
-
const textFieldStyle: TextFieldProps = {
|
64
|
-
inputProps: {
|
65
|
-
tabIndex: 0,
|
66
|
-
},
|
67
|
-
fullWidth: true,
|
68
|
-
...props.InputProps,
|
69
|
-
};
|
70
|
-
|
71
|
-
return (
|
72
|
-
<Autocomplete
|
73
|
-
disablePortal
|
74
|
-
autoHighlight
|
75
|
-
defaultValue={defaultOption}
|
76
|
-
options={options}
|
77
|
-
disableClearable={disableClearable}
|
78
|
-
isOptionEqualToValue={(option, value) => option?.id === value?.id}
|
79
|
-
value={value}
|
80
|
-
onChange={(_event, newInputValue) => {
|
81
|
-
// User clicked on clear button.
|
82
|
-
if (!newInputValue) {
|
83
|
-
handleClear();
|
84
|
-
return;
|
85
|
-
}
|
86
|
-
|
87
|
-
handleChange(newInputValue);
|
88
|
-
}}
|
89
|
-
renderInput={(params) => (
|
90
|
-
<TextField
|
91
|
-
{...params}
|
92
|
-
{...textFieldStyle}
|
93
|
-
inputProps={{
|
94
|
-
...params.inputProps,
|
95
|
-
...textFieldStyle.inputProps,
|
96
|
-
}}
|
97
|
-
/>
|
98
|
-
)}
|
99
|
-
/>
|
100
|
-
);
|
101
|
-
}
|
@@ -1,48 +0,0 @@
|
|
1
|
-
import { forwardRef, type Ref } from 'react';
|
2
|
-
import { IMaskInput } from 'react-imask';
|
3
|
-
|
4
|
-
export type ChangeEvent = (
|
5
|
-
event: { target: { name: string; value: string } },
|
6
|
-
nativeEvent?: InputEvent,
|
7
|
-
) => void;
|
8
|
-
|
9
|
-
interface TextMaskCustomProps {
|
10
|
-
onChange: ChangeEvent;
|
11
|
-
name: string;
|
12
|
-
mask: string;
|
13
|
-
definitions?: Record<string, RegExp>;
|
14
|
-
// Value to define which event to handle onAccept(default) or onComplete.
|
15
|
-
useOnComplete?: boolean;
|
16
|
-
}
|
17
|
-
|
18
|
-
/**
|
19
|
-
* Component that mask the input with the given mask pattern.
|
20
|
-
* @param props {TextMaskCustomProps}
|
21
|
-
* @param ref {Ref<HTMLInputElement>}
|
22
|
-
* @constructor
|
23
|
-
*/
|
24
|
-
function TextMaskCustomComponent(
|
25
|
-
props: TextMaskCustomProps,
|
26
|
-
ref: Ref<HTMLInputElement>,
|
27
|
-
): React.JSX.Element {
|
28
|
-
const { onChange, useOnComplete, ...other } = props;
|
29
|
-
return (
|
30
|
-
<IMaskInput
|
31
|
-
{...other}
|
32
|
-
inputRef={ref}
|
33
|
-
onAccept={(value, _, event) => {
|
34
|
-
if (useOnComplete) return;
|
35
|
-
onChange({ target: { name: props.name, value } }, event);
|
36
|
-
}}
|
37
|
-
onComplete={(value, _, event) => {
|
38
|
-
if (!useOnComplete) return;
|
39
|
-
onChange({ target: { name: props.name, value } }, event);
|
40
|
-
}}
|
41
|
-
overwrite
|
42
|
-
/>
|
43
|
-
);
|
44
|
-
}
|
45
|
-
|
46
|
-
export const TextMaskCustom = forwardRef<HTMLInputElement, TextMaskCustomProps>(
|
47
|
-
TextMaskCustomComponent,
|
48
|
-
);
|
package/src/components/index.ts
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
export * from './Button';
|
2
|
-
export * from './Typography';
|
3
|
-
export * from './CredentialRequestsEditor';
|
4
|
-
export * from './terms/AcceptTermsNotice';
|
5
|
-
export * from './When';
|
6
|
-
export * from './Alert';
|
7
|
-
export * from './Image';
|
8
|
-
export * from './form/';
|
9
|
-
export * from './verified';
|
10
|
-
export * from './QRCodeDisplay';
|
11
|
-
export * from './Snackbar';
|
12
|
-
export * from './Banners';
|
13
|
-
export * from './Backdrop';
|
@@ -1,27 +0,0 @@
|
|
1
|
-
import { Box, type Theme, Typography, useTheme } from '@mui/material';
|
2
|
-
|
3
|
-
import LegalLink from './LegalLink';
|
4
|
-
interface AcceptTermsNoticeProps {
|
5
|
-
legalLinkUrl?: string;
|
6
|
-
}
|
7
|
-
export const AcceptTermsNotice = ({
|
8
|
-
legalLinkUrl = 'https://www.verified.inc/legal#terms-of-use',
|
9
|
-
}: AcceptTermsNoticeProps): React.JSX.Element => {
|
10
|
-
const theme: Theme = useTheme();
|
11
|
-
return (
|
12
|
-
<Box display='inline-block'>
|
13
|
-
<Typography
|
14
|
-
align='center'
|
15
|
-
sx={{
|
16
|
-
fontSize: '.75rem',
|
17
|
-
fontWeight: 400,
|
18
|
-
color: theme.palette.neutral.main,
|
19
|
-
lineHeight: 1.25,
|
20
|
-
}}
|
21
|
-
>
|
22
|
-
By continuing, you agree to Verified’s{' '}
|
23
|
-
<LegalLink href={legalLinkUrl}>Terms of Use</LegalLink>.
|
24
|
-
</Typography>
|
25
|
-
</Box>
|
26
|
-
);
|
27
|
-
};
|