mirror of
https://github.com/logto-io/logto.git
synced 2024-12-30 20:33:54 -05:00
fix(experience): smart input field should have correct initial type (#6477)
This commit is contained in:
parent
d4674833c8
commit
818e2c61f2
2 changed files with 61 additions and 38 deletions
|
@ -7,6 +7,8 @@ import useUpdateEffect from '@/hooks/use-update-effect';
|
||||||
import { getDefaultCountryCallingCode } from '@/utils/country-code';
|
import { getDefaultCountryCallingCode } from '@/utils/country-code';
|
||||||
import { parseIdentifierValue } from '@/utils/form';
|
import { parseIdentifierValue } from '@/utils/form';
|
||||||
|
|
||||||
|
import { detectIdentifierType } from './utils';
|
||||||
|
|
||||||
export type IdentifierInputType =
|
export type IdentifierInputType =
|
||||||
| SignInIdentifier.Email
|
| SignInIdentifier.Email
|
||||||
| SignInIdentifier.Phone
|
| SignInIdentifier.Phone
|
||||||
|
@ -24,8 +26,6 @@ export type IdentifierInputValue = {
|
||||||
value: string;
|
value: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const digitsRegex = /^\d*$/;
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
defaultValue?: string;
|
defaultValue?: string;
|
||||||
_defaultType?: IdentifierInputType;
|
_defaultType?: IdentifierInputType;
|
||||||
|
@ -56,7 +56,14 @@ const useSmartInputField = ({ _defaultType, defaultValue, enabledTypes }: Props)
|
||||||
[defaultType, defaultValue]
|
[defaultType, defaultValue]
|
||||||
);
|
);
|
||||||
|
|
||||||
const [currentType, setCurrentType] = useState(defaultType);
|
const [currentType, setCurrentType] = useState(
|
||||||
|
detectIdentifierType({
|
||||||
|
value: defaultValue ?? '',
|
||||||
|
enabledTypeSet,
|
||||||
|
defaultType,
|
||||||
|
currentType: defaultType,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
const [countryCode, setCountryCode] = useState<string>(
|
const [countryCode, setCountryCode] = useState<string>(
|
||||||
defaultCountryCode ?? getDefaultCountryCallingCode()
|
defaultCountryCode ?? getDefaultCountryCallingCode()
|
||||||
|
@ -65,41 +72,7 @@ const useSmartInputField = ({ _defaultType, defaultValue, enabledTypes }: Props)
|
||||||
const [inputValue, setInputValue] = useState<string>(defaultInputValue ?? '');
|
const [inputValue, setInputValue] = useState<string>(defaultInputValue ?? '');
|
||||||
|
|
||||||
const detectInputType = useCallback(
|
const detectInputType = useCallback(
|
||||||
(value: string) => {
|
(value: string) => detectIdentifierType({ value, enabledTypeSet, defaultType, currentType }),
|
||||||
// Reset InputType
|
|
||||||
if (!value && enabledTypeSet.size > 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enabledTypeSet.size === 1) {
|
|
||||||
return defaultType;
|
|
||||||
}
|
|
||||||
|
|
||||||
const hasAtSymbol = value.includes('@');
|
|
||||||
const isAllDigits = digitsRegex.test(value);
|
|
||||||
|
|
||||||
if (enabledTypeSet.has(SignInIdentifier.Phone) && value.length >= 3 && isAllDigits) {
|
|
||||||
return SignInIdentifier.Phone;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enabledTypeSet.has(SignInIdentifier.Email) && hasAtSymbol) {
|
|
||||||
return SignInIdentifier.Email;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentType === SignInIdentifier.Phone && isAllDigits) {
|
|
||||||
return SignInIdentifier.Phone;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enabledTypeSet.has(SignInIdentifier.Username)) {
|
|
||||||
return SignInIdentifier.Username;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enabledTypeSet.has(SignInIdentifier.Email)) {
|
|
||||||
return SignInIdentifier.Email;
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentType;
|
|
||||||
},
|
|
||||||
[defaultType, currentType, enabledTypeSet]
|
[defaultType, currentType, enabledTypeSet]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -40,3 +40,53 @@ export const getInputHtmlProps = (
|
||||||
label: enabledTypes.map((type) => i18next.t(identifierInputPlaceholderMap[type])).join(' / '),
|
label: enabledTypes.map((type) => i18next.t(identifierInputPlaceholderMap[type])).join(' / '),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const digitsRegex = /^\d*$/;
|
||||||
|
|
||||||
|
type DetectIdentifierTypeParams = {
|
||||||
|
value: string;
|
||||||
|
enabledTypeSet: Set<IdentifierInputType>;
|
||||||
|
defaultType?: IdentifierInputType;
|
||||||
|
currentType?: IdentifierInputType;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const detectIdentifierType = ({
|
||||||
|
value,
|
||||||
|
enabledTypeSet,
|
||||||
|
defaultType,
|
||||||
|
currentType,
|
||||||
|
}: DetectIdentifierTypeParams) => {
|
||||||
|
// Reset InputType
|
||||||
|
if (!value && enabledTypeSet.size > 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enabledTypeSet.size === 1) {
|
||||||
|
return defaultType;
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasAtSymbol = value.includes('@');
|
||||||
|
const isAllDigits = digitsRegex.test(value);
|
||||||
|
|
||||||
|
if (enabledTypeSet.has(SignInIdentifier.Phone) && value.length >= 3 && isAllDigits) {
|
||||||
|
return SignInIdentifier.Phone;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enabledTypeSet.has(SignInIdentifier.Email) && hasAtSymbol) {
|
||||||
|
return SignInIdentifier.Email;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentType === SignInIdentifier.Phone && isAllDigits) {
|
||||||
|
return SignInIdentifier.Phone;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enabledTypeSet.has(SignInIdentifier.Username)) {
|
||||||
|
return SignInIdentifier.Username;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enabledTypeSet.has(SignInIdentifier.Email)) {
|
||||||
|
return SignInIdentifier.Email;
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentType;
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in a new issue