95 lines
2.7 KiB
TypeScript
95 lines
2.7 KiB
TypeScript
import type { InertiaLinkProps } from '@inertiajs/react';
|
|
import { usePage } from '@inertiajs/react';
|
|
import { toUrl } from '@/lib/utils';
|
|
|
|
export type IsCurrentUrlFn = (
|
|
urlToCheck: NonNullable<InertiaLinkProps['href']>,
|
|
currentUrl?: string,
|
|
startsWith?: boolean,
|
|
) => boolean;
|
|
|
|
export type IsCurrentOrParentUrlFn = (
|
|
urlToCheck: NonNullable<InertiaLinkProps['href']>,
|
|
currentUrl?: string,
|
|
) => boolean;
|
|
|
|
export type WhenCurrentUrlFn = <TIfTrue, TIfFalse = null>(
|
|
urlToCheck: NonNullable<InertiaLinkProps['href']>,
|
|
ifTrue: TIfTrue,
|
|
ifFalse?: TIfFalse,
|
|
) => TIfTrue | TIfFalse;
|
|
|
|
export type UseCurrentUrlReturn = {
|
|
currentUrl: string;
|
|
isCurrentUrl: IsCurrentUrlFn;
|
|
isCurrentOrParentUrl: IsCurrentOrParentUrlFn;
|
|
whenCurrentUrl: WhenCurrentUrlFn;
|
|
};
|
|
|
|
export function useCurrentUrl(): UseCurrentUrlReturn {
|
|
const page = usePage();
|
|
const currentUrlPath = new URL(
|
|
page.url,
|
|
typeof window !== 'undefined'
|
|
? window.location.origin
|
|
: 'http://localhost',
|
|
).pathname;
|
|
|
|
const isCurrentUrl: IsCurrentUrlFn = (
|
|
urlToCheck: NonNullable<InertiaLinkProps['href']>,
|
|
currentUrl?: string,
|
|
startsWith: boolean = false,
|
|
) => {
|
|
const urlString = toUrl(urlToCheck);
|
|
const currentPath = currentUrl ?? currentUrlPath;
|
|
|
|
const clean = (p: string) => {
|
|
if (!p) return '/';
|
|
// Remove query and hash, then trailing slash
|
|
let path = p.split('?')[0].split('#')[0];
|
|
if (path.startsWith('http')) {
|
|
try {
|
|
path = new URL(path).pathname;
|
|
} catch {
|
|
// Ignore
|
|
}
|
|
}
|
|
return path.replace(/\/+$/, '') || '/';
|
|
};
|
|
|
|
const normCurrent = clean(currentPath);
|
|
const normCheck = clean(urlString);
|
|
|
|
if (startsWith) {
|
|
if (normCheck === '/') {
|
|
return normCurrent === '/';
|
|
}
|
|
return normCurrent.startsWith(normCheck);
|
|
}
|
|
|
|
return normCurrent === normCheck;
|
|
};
|
|
|
|
const isCurrentOrParentUrl: IsCurrentOrParentUrlFn = (
|
|
urlToCheck: NonNullable<InertiaLinkProps['href']>,
|
|
currentUrl?: string,
|
|
) => {
|
|
return isCurrentUrl(urlToCheck, currentUrl, true);
|
|
};
|
|
|
|
const whenCurrentUrl: WhenCurrentUrlFn = <TIfTrue, TIfFalse = null>(
|
|
urlToCheck: NonNullable<InertiaLinkProps['href']>,
|
|
ifTrue: TIfTrue,
|
|
ifFalse: TIfFalse = null as TIfFalse,
|
|
): TIfTrue | TIfFalse => {
|
|
return isCurrentUrl(urlToCheck) ? ifTrue : ifFalse;
|
|
};
|
|
|
|
return {
|
|
currentUrl: currentUrlPath,
|
|
isCurrentUrl,
|
|
isCurrentOrParentUrl,
|
|
whenCurrentUrl,
|
|
};
|
|
}
|