public commit

This commit is contained in:
dswbx
2024-11-16 12:01:47 +01:00
commit 90f80c4280
582 changed files with 49291 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
import { useInsertionEffect, useRef } from "react";
import { type LinkProps, Link as WouterLink, useRoute, useRouter } from "wouter";
import { useEvent } from "../../hooks/use-event";
/*
* Transforms `path` into its relative `base` version
* If base isn't part of the path provided returns absolute path e.g. `~/app`
*/
export const relativePath = (base = "", path = "") =>
!path.toLowerCase().indexOf(base.toLowerCase()) ? path.slice(base.length) || "/" : "~" + path;
export const absolutePath = (to, base = "") => (to[0] === "~" ? to.slice(1) : base + to);
/*
* Removes leading question mark
*/
export const stripQm = (str) => (str[0] === "?" ? str.slice(1) : str);
/*
* decodes escape sequences such as %20
*/
// biome-ignore lint/suspicious/noShadowRestrictedNames: <explanation>
export const unescape = (str) => {
try {
return decodeURI(str);
} catch (_e) {
// fail-safe mode: if string can't be decoded do nothing
return str;
}
};
const useLocationFromRouter = (router) => {
const [location, navigate] = router.hook(router);
// the function reference should stay the same between re-renders, so that
// it can be passed down as an element prop without any performance concerns.
// (This is achieved via `useEvent`.)
return [
unescape(relativePath(router.base, location)),
useEvent((to, navOpts) => navigate(absolutePath(to, router.base), navOpts))
];
};
export function Link({ className, ...props }: { className?: string } & LinkProps) {
const router = useRouter();
const [path, navigate] = useLocationFromRouter(router);
function isActive(absPath: string, href: string) {
if (absPath.startsWith(href)) {
const l = absPath.replace(href, "");
return l.length === 0 || l[0] === "/";
}
return false;
}
function handleClick(e) {}
const _href = props.href ?? props.to;
const href = router
.hrefs(
_href[0] === "~" ? _href.slice(1) : router.base + _href,
router // pass router as a second argument for convinience
)
.replace("//", "/");
const absPath = absolutePath(path, router.base).replace("//", "/");
const active =
href.replace(router.base, "").length <= 1 ? href === absPath : isActive(absPath, href);
const a = useRoute(_href);
/*if (active) {
console.log("link", { a, path, absPath, href, to, active, router });
}*/
return (
// @ts-expect-error className is not typed on WouterLink
<WouterLink className={`${active ? "active " : ""}${className}`} {...props} />
);
}