mirror of
https://github.com/element-hq/matrix-authentication-service.git
synced 2026-06-04 21:11:54 +00:00
Extract the navigation link to a useNavigationLink hook
This commit is contained in:
@@ -12,18 +12,9 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { useAtomValue, useSetAtom } from "jotai";
|
||||
import { useTransition } from "react";
|
||||
|
||||
import styles from "./Link.module.css";
|
||||
import { appConfigAtom, routeAtom } from "./atoms";
|
||||
import { Route, routeToPath } from "./routes";
|
||||
|
||||
// Filter out clicks with modifiers or that have been prevented
|
||||
const shouldHandleClick = (e: React.MouseEvent): boolean =>
|
||||
!e.defaultPrevented &&
|
||||
e.button === 0 &&
|
||||
!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
|
||||
import { Route } from "./routes";
|
||||
import { useNavigationLink } from "./useNavigationLink";
|
||||
|
||||
const Link: React.FC<
|
||||
{
|
||||
@@ -32,13 +23,7 @@ const Link: React.FC<
|
||||
kind?: "button";
|
||||
} & React.HTMLProps<HTMLAnchorElement>
|
||||
> = ({ route, children, kind, className, ...props }) => {
|
||||
const config = useAtomValue(appConfigAtom);
|
||||
const path = routeToPath(route);
|
||||
const fullUrl = config.root + path;
|
||||
const setRoute = useSetAtom(routeAtom);
|
||||
|
||||
// TODO: we should probably have more user control over this
|
||||
const [isPending, startTransition] = useTransition();
|
||||
const { onClick, href, pending } = useNavigationLink(route);
|
||||
|
||||
const classNames = [
|
||||
kind === "button" ? styles.linkButton : "",
|
||||
@@ -46,23 +31,8 @@ const Link: React.FC<
|
||||
].join("");
|
||||
|
||||
return (
|
||||
<a
|
||||
href={fullUrl}
|
||||
onClick={(e: React.MouseEvent): void => {
|
||||
// Only handle left clicks without modifiers
|
||||
if (!shouldHandleClick(e)) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
startTransition(() => {
|
||||
setRoute(route);
|
||||
});
|
||||
}}
|
||||
className={classNames}
|
||||
{...props}
|
||||
>
|
||||
{isPending ? "Loading..." : children}
|
||||
<a href={href} onClick={onClick} className={classNames} {...props}>
|
||||
{pending ? "Loading..." : children}
|
||||
</a>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -18,3 +18,4 @@ export type { Route, Location } from "./routes";
|
||||
export { pathToRoute, routeToPath } from "./routes";
|
||||
export { getRouteActionRedirection } from "./actions";
|
||||
export { routeAtom, locationAtom, appConfigAtom } from "./atoms";
|
||||
export { useNavigationLink } from "./useNavigationLink";
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
// Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { useAtomValue, useSetAtom } from "jotai";
|
||||
import { useTransition } from "react";
|
||||
|
||||
import { appConfigAtom, routeAtom } from "./atoms";
|
||||
import { Route, routeToPath } from "./routes";
|
||||
|
||||
// Filter out clicks with modifiers or that have been prevented
|
||||
const shouldHandleClick = (e: React.MouseEvent): boolean =>
|
||||
!e.defaultPrevented &&
|
||||
e.button === 0 &&
|
||||
!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
|
||||
|
||||
/**
|
||||
* A hook which controls a navigation link to a given route
|
||||
*/
|
||||
export const useNavigationLink = (
|
||||
route: Route,
|
||||
): {
|
||||
onClick: (event: React.MouseEvent) => void;
|
||||
href: string;
|
||||
pending: boolean;
|
||||
} => {
|
||||
const config = useAtomValue(appConfigAtom);
|
||||
const path = routeToPath(route);
|
||||
const href = config.root + path;
|
||||
const setRoute = useSetAtom(routeAtom);
|
||||
const [pending, startTransition] = useTransition();
|
||||
|
||||
const onClick = (e: React.MouseEvent): void => {
|
||||
// Only handle left clicks without modifiers
|
||||
if (!shouldHandleClick(e)) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
startTransition(() => {
|
||||
setRoute(route);
|
||||
});
|
||||
};
|
||||
|
||||
return { onClick, href, pending };
|
||||
};
|
||||
Reference in New Issue
Block a user