mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-08-24 12:06:54 -05:00
Close modal on click outside
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import * as React from "react";
|
||||
import { Link } from "remix";
|
||||
import { Link, useNavigate } from "remix";
|
||||
import { useOnClickOutside } from "~/hooks/common";
|
||||
|
||||
export default function Modal({
|
||||
closeUrl,
|
||||
@@ -10,9 +11,18 @@ export default function Modal({
|
||||
title: React.ReactNode;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const navigate = useNavigate();
|
||||
const ref = React.useRef<HTMLDivElement>(null);
|
||||
|
||||
const useOnClickOutsideHandler = React.useCallback(
|
||||
() => navigate(closeUrl),
|
||||
[closeUrl]
|
||||
);
|
||||
useOnClickOutside(ref, useOnClickOutsideHandler);
|
||||
|
||||
return (
|
||||
<div className="modal">
|
||||
<div>
|
||||
<div ref={ref}>
|
||||
<Link to={closeUrl} className="modal-close">
|
||||
Close
|
||||
</Link>
|
||||
|
||||
@@ -76,3 +76,24 @@ export const useTimeoutState = <T>(
|
||||
);
|
||||
return [state, setState];
|
||||
};
|
||||
|
||||
/** @link https://usehooks.com/useOnClickOutside/ */
|
||||
export function useOnClickOutside<T extends HTMLElement = HTMLElement>(
|
||||
ref: React.RefObject<T>,
|
||||
handler: (event: MouseEvent | TouchEvent) => void
|
||||
) {
|
||||
React.useEffect(() => {
|
||||
const listener = (event: MouseEvent | TouchEvent) => {
|
||||
if (!ref.current || ref.current.contains(event.target as Node)) {
|
||||
return;
|
||||
}
|
||||
handler(event);
|
||||
};
|
||||
document.addEventListener("mousedown", listener);
|
||||
document.addEventListener("touchstart", listener);
|
||||
return () => {
|
||||
document.removeEventListener("mousedown", listener);
|
||||
document.removeEventListener("touchstart", listener);
|
||||
};
|
||||
}, [ref, handler]);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ export function requireEvents(ctx: unknown) {
|
||||
try {
|
||||
const data = z.object({ events: z.unknown() }).parse(ctx);
|
||||
|
||||
// TODO:
|
||||
// TODO: fix type assertion
|
||||
return data.events as EventTargetRecorder;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
@@ -41,6 +41,7 @@ export function requireEvents(ctx: unknown) {
|
||||
}
|
||||
|
||||
/** Asserts condition is truthy. Throws a new `Response` with status code 400 and given message if falsy. */
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- same format as TS docs: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions
|
||||
export function validate(condition: any, message: string): asserts condition {
|
||||
if (condition) return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user