mirror of
https://github.com/teamhanko/hanko.git
synced 2025-10-27 14:17:56 +08:00
152 lines
3.5 KiB
TypeScript
152 lines
3.5 KiB
TypeScript
import * as preact from "preact";
|
|
import { ComponentChildren, createContext, h } from "preact";
|
|
import { TranslateProvider } from "@denysvuika/preact-translate";
|
|
|
|
import {
|
|
StateUpdater,
|
|
useState,
|
|
useCallback,
|
|
useMemo,
|
|
useRef,
|
|
} from "preact/compat";
|
|
|
|
import {
|
|
Hanko,
|
|
User,
|
|
UserInfo,
|
|
Passcode,
|
|
Emails,
|
|
Config,
|
|
WebauthnCredentials,
|
|
} from "@teamhanko/hanko-frontend-sdk";
|
|
|
|
import { translations } from "../Translations";
|
|
|
|
import Container from "../components/wrapper/Container";
|
|
|
|
import InitPage from "../pages/InitPage";
|
|
import { JSXInternal } from "preact/src/jsx";
|
|
import SignalLike = JSXInternal.SignalLike;
|
|
|
|
type ExperimentalFeature = "conditionalMediation";
|
|
type ExperimentalFeatures = ExperimentalFeature[];
|
|
type ComponentName = "auth" | "profile";
|
|
|
|
interface Props {
|
|
api?: string;
|
|
lang?: string | SignalLike<string>;
|
|
fallbackLang?: string;
|
|
experimental?: string;
|
|
componentName: ComponentName;
|
|
children?: ComponentChildren;
|
|
}
|
|
|
|
interface States {
|
|
config: Config;
|
|
setConfig: StateUpdater<Config>;
|
|
userInfo: UserInfo;
|
|
setUserInfo: StateUpdater<UserInfo>;
|
|
passcode: Passcode;
|
|
setPasscode: StateUpdater<Passcode>;
|
|
user: User;
|
|
setUser: StateUpdater<User>;
|
|
emails: Emails;
|
|
setEmails: StateUpdater<Emails>;
|
|
webauthnCredentials: WebauthnCredentials;
|
|
setWebauthnCredentials: StateUpdater<WebauthnCredentials>;
|
|
page: h.JSX.Element;
|
|
setPage: StateUpdater<h.JSX.Element>;
|
|
}
|
|
|
|
interface Context extends States {
|
|
hanko: Hanko;
|
|
componentName: ComponentName;
|
|
experimentalFeatures?: ExperimentalFeatures;
|
|
emitSuccessEvent: () => void;
|
|
}
|
|
|
|
export const AppContext = createContext<Context>(null);
|
|
|
|
const AppProvider = ({
|
|
api,
|
|
lang,
|
|
fallbackLang = "en",
|
|
componentName,
|
|
experimental = "",
|
|
}: Props) => {
|
|
const ref = useRef<HTMLElement>(null);
|
|
|
|
const hanko = useMemo(() => {
|
|
if (api) {
|
|
return new Hanko(api, 13000);
|
|
}
|
|
return null;
|
|
}, [api]);
|
|
|
|
const experimentalFeatures = useMemo(
|
|
() =>
|
|
experimental
|
|
.split(" ")
|
|
.filter((feature) => feature.length)
|
|
.map((feature) => feature as ExperimentalFeature),
|
|
[experimental]
|
|
);
|
|
|
|
const emitSuccessEvent = useCallback(() => {
|
|
const event = new Event("hankoAuthSuccess", {
|
|
bubbles: true,
|
|
composed: true,
|
|
});
|
|
|
|
const fn = setTimeout(() => {
|
|
ref.current.dispatchEvent(event);
|
|
}, 500);
|
|
|
|
return () => clearTimeout(fn);
|
|
}, []);
|
|
|
|
const [config, setConfig] = useState<Config>();
|
|
const [userInfo, setUserInfo] = useState<UserInfo>(null);
|
|
const [passcode, setPasscode] = useState<Passcode>();
|
|
const [user, setUser] = useState<User>();
|
|
const [emails, setEmails] = useState<Emails>();
|
|
const [webauthnCredentials, setWebauthnCredentials] =
|
|
useState<WebauthnCredentials>();
|
|
const [page, setPage] = useState<h.JSX.Element>(<InitPage />);
|
|
|
|
return (
|
|
<AppContext.Provider
|
|
value={{
|
|
hanko,
|
|
componentName,
|
|
experimentalFeatures,
|
|
emitSuccessEvent,
|
|
config,
|
|
setConfig,
|
|
userInfo,
|
|
setUserInfo,
|
|
passcode,
|
|
setPasscode,
|
|
user,
|
|
setUser,
|
|
emails,
|
|
setEmails,
|
|
webauthnCredentials,
|
|
setWebauthnCredentials,
|
|
page,
|
|
setPage,
|
|
}}
|
|
>
|
|
<TranslateProvider
|
|
translations={translations}
|
|
lang={lang?.toString()}
|
|
fallbackLang={fallbackLang}
|
|
>
|
|
<Container ref={ref}>{page}</Container>
|
|
</TranslateProvider>
|
|
</AppContext.Provider>
|
|
);
|
|
};
|
|
|
|
export default AppProvider;
|