diff --git a/src/components/Inputs/Button.tsx b/src/components/Inputs/Button.tsx
index e24569e..078bbfa 100644
--- a/src/components/Inputs/Button.tsx
+++ b/src/components/Inputs/Button.tsx
@@ -1,8 +1,7 @@
-import React, { MouseEventHandler, useCallback } from "react";
+import { MouseEventHandler, useCallback } from "react";
import { Link } from "./Link";
import { Ico, Icon } from "components/Ico";
import { cIf, cJoin } from "helpers/className";
-import { ConditionalWrapper, Wrapper } from "helpers/component";
import { isDefined, isDefinedAndNotEmpty } from "helpers/others";
import { TranslatedProps } from "types/TranslatedProps";
import { useSmartLanguage } from "hooks/useSmartLanguage";
@@ -45,10 +44,7 @@ export const Button = ({
disabled,
size = "normal",
}: Props): JSX.Element => (
-
+
-
+
);
/*
@@ -110,19 +106,3 @@ export const TranslatedButton = ({
return ;
};
-
-/*
- * ╭──────────────────────╮
- * ───────────────────────────────────╯ PRIVATE COMPONENTS ╰──────────────────────────────────────
- */
-
-interface LinkWrapperProps {
- href: string;
- alwaysNewTab: boolean;
-}
-
-const LinkWrapper = ({ children, alwaysNewTab, href }: LinkWrapperProps & Wrapper) => (
-
- {children}
-
-);
diff --git a/src/components/Inputs/Link.tsx b/src/components/Inputs/Link.tsx
index 0f35f14..da27dae 100644
--- a/src/components/Inputs/Link.tsx
+++ b/src/components/Inputs/Link.tsx
@@ -1,74 +1,81 @@
-import router from "next/router";
-import { MouseEventHandler, useState } from "react";
-import { isDefined } from "helpers/others";
+import React, { MouseEventHandler } from "react";
+import NextLink from "next/link";
+import { ConditionalWrapper, Wrapper } from "helpers/component";
+import { isDefinedAndNotEmpty } from "helpers/others";
+import { cIf, cJoin } from "helpers/className";
interface Props {
- href: string;
+ href: string | null | undefined;
className?: string;
- allowNewTab?: boolean;
alwaysNewTab?: boolean;
children: React.ReactNode;
onClick?: MouseEventHandler;
onFocusChanged?: (isFocused: boolean) => void;
disabled?: boolean;
+ linkStyled?: boolean;
}
export const Link = ({
href,
- allowNewTab = true,
- alwaysNewTab = false,
- disabled = false,
children,
className,
- onClick,
+ alwaysNewTab,
+ disabled,
+ linkStyled = false,
onFocusChanged,
-}: Props): JSX.Element => {
- const [isValidClick, setIsValidClick] = useState(false);
+}: Props): JSX.Element => (
+
+ {children}
+
+);
- return (
- {
- setIsValidClick(false);
- onFocusChanged?.(false);
- }}
- onContextMenu={(event) => event.preventDefault()}
- onMouseDown={(event) => {
- if (!disabled) {
- event.preventDefault();
- onFocusChanged?.(true);
- setIsValidClick(true);
- }
- }}
- onMouseUp={(event) => {
- onFocusChanged?.(false);
- if (!disabled) {
- if (isDefined(onClick)) {
- onClick(event);
- } else if (isValidClick && href) {
- if (event.button !== MouseButton.Right) {
- if (alwaysNewTab) {
- window.open(href, "_blank", "noopener");
- } else if (event.button === MouseButton.Left) {
- if (href.startsWith("#")) {
- router.replace(href);
- } else {
- router.push(href);
- }
- } else if (allowNewTab) {
- window.open(href, "_blank");
- }
- }
- }
- }
- }}>
- {children}
-
- );
-};
-
-enum MouseButton {
- Left = 0,
- Middle = 1,
- Right = 2,
+interface LinkWrapperProps {
+ href: string;
+ className?: string;
+ alwaysNewTab?: boolean;
+ onFocusChanged?: (isFocused: boolean) => void;
}
+
+const LinkWrapper = ({
+ children,
+ className,
+ onFocusChanged,
+ alwaysNewTab = false,
+ href,
+}: LinkWrapperProps & Wrapper) => (
+ onFocusChanged?.(false)}
+ onMouseDown={() => onFocusChanged?.(true)}
+ onMouseUp={() => onFocusChanged?.(false)}>
+ {children}
+
+);
+
+interface DisabledWrapperProps {
+ className?: string;
+}
+
+const DisabledWrapper = ({ children, className }: DisabledWrapperProps & Wrapper) => (
+ {children}
+);
diff --git a/src/components/Library/PreviewCardCTAs.tsx b/src/components/Library/PreviewCardCTAs.tsx
index c2fe8e0..1c2bb30 100644
--- a/src/components/Library/PreviewCardCTAs.tsx
+++ b/src/components/Library/PreviewCardCTAs.tsx
@@ -34,8 +34,8 @@ export const PreviewCardCTAs = ({ id, expand = false }: Props): JSX.Element => {
icon={Icon.Favorite}
text={expand ? langui.want_it : undefined}
active={libraryItemUserStatus[id] === LibraryItemUserStatus.Want}
- onMouseUp={(event) => event.stopPropagation()}
- onClick={() => {
+ onClick={(event) => {
+ event.preventDefault();
setLibraryItemUserStatus((current) => {
const newLibraryItemUserStatus = { ...current };
newLibraryItemUserStatus[id] =
@@ -52,8 +52,8 @@ export const PreviewCardCTAs = ({ id, expand = false }: Props): JSX.Element => {
icon={Icon.BackHand}
text={expand ? langui.have_it : undefined}
active={libraryItemUserStatus[id] === LibraryItemUserStatus.Have}
- onMouseUp={(event) => event.stopPropagation()}
- onClick={() => {
+ onClick={(event) => {
+ event.preventDefault();
setLibraryItemUserStatus((current) => {
const newLibraryItemUserStatus = { ...current };
newLibraryItemUserStatus[id] =
diff --git a/src/components/Markdown/Markdawn.tsx b/src/components/Markdown/Markdawn.tsx
index 0b2dc89..8a86e54 100644
--- a/src/components/Markdown/Markdawn.tsx
+++ b/src/components/Markdown/Markdawn.tsx
@@ -1,6 +1,5 @@
import Markdown from "markdown-to-jsx";
-import { useRouter } from "next/router";
-import React, { Fragment } from "react";
+import React, { Fragment, useMemo } from "react";
import ReactDOMServer from "react-dom/server";
import { HorizontalLine } from "components/HorizontalLine";
import { Img } from "components/Img";
@@ -15,6 +14,7 @@ import { Ico, Icon } from "components/Ico";
import { useDeviceSupportsHover } from "hooks/useMediaQuery";
import { atoms } from "contexts/atoms";
import { useAtomGetter } from "helpers/atoms";
+import { Link } from "components/Inputs/Link";
/*
* ╭─────────────╮
@@ -30,7 +30,6 @@ interface MarkdawnProps {
export const Markdawn = ({ className, text: rawText }: MarkdawnProps): JSX.Element => {
const playerName = useAtomGetter(atoms.settings.playerName);
- const router = useRouter();
const isContentPanelAtLeastLg = useAtomGetter(atoms.containerQueries.isContentPanelAtLeastLg);
const { showLightBox } = useAtomGetter(atoms.lightBox);
@@ -53,13 +52,15 @@ export const Markdawn = ({ className, text: rawText }: MarkdawnProps): JSX.Eleme
component: (compProps: { href: string; children: React.ReactNode }) => {
if (compProps.href.startsWith("/") || compProps.href.startsWith("#")) {
return (
- router.push(compProps.href)}>{compProps.children}
+
+ {compProps.children}
+
);
}
return (
-
+
{compProps.children}
-
+
);
},
},
@@ -95,9 +96,9 @@ export const Markdawn = ({ className, text: rawText }: MarkdawnProps): JSX.Eleme
? slugify(compProps.target)
: slugify(compProps.children?.toString());
return (
- router.replace(`${compProps.page ?? ""}#${slug}`)}>
+
{compProps.children}
-
+
);
},
},
@@ -224,7 +225,6 @@ export const TableOfContents = ({
title,
horizontalLine = false,
}: TableOfContentsProps): JSX.Element => {
- const router = useRouter();
const langui = useAtomGetter(atoms.localData.langui);
const toc = getTocFromMarkdawn(preprocessMarkDawn(text), title);
@@ -238,9 +238,9 @@ export const TableOfContents = ({
- router.replace(`#${toc.slug}`)}>
+
{{toc.title}}
-
+
@@ -340,8 +340,7 @@ const TocLevel = ({
parentNumbering,
allowIntersection = true,
}: LevelProps): JSX.Element => {
- const router = useRouter();
- const ids = tocchildren.map((child) => child.slug);
+ const ids = useMemo(() => tocchildren.map((child) => child.slug), [tocchildren]);
const currentIntersection = useIntersectionList(ids);
return (
@@ -354,9 +353,9 @@ const TocLevel = ({
cIf(allowIntersection && currentIntersection === childIndex, "text-dark")
)}>
{`${parentNumbering}${childIndex + 1}.`}{" "}
- router.replace(`#${child.slug}`)}>
+
{{child.title}}
-
+
{
)}
{isDefinedAndNotEmpty(langui.copyright_notice) && (
@@ -195,39 +196,36 @@ export const MainPanel = (): JSX.Element => {
)}
diff --git a/src/components/SmartList.tsx b/src/components/SmartList.tsx
index b994936..21b2db0 100644
--- a/src/components/SmartList.tsx
+++ b/src/components/SmartList.tsx
@@ -73,7 +73,7 @@ export const SmartList = ({
const [page, setPage] = useState(0);
const langui = useAtomGetter(atoms.localData.langui);
useScrollTopOnChange(Ids.ContentPanel, [page], paginationScroolTop);
- useEffect(() => setPage(0), [searchingTerm, groupingFunction, groupSortingFunction, items]);
+ useEffect(() => setPage(0), [searchingTerm, groupingFunction, groupSortingFunction]);
const searchFilter = useCallback(() => {
if (isDefinedAndNotEmpty(searchingTerm) && isDefined(searchingBy)) {
diff --git a/src/helpers/component.tsx b/src/helpers/component.tsx
index eeaca69..c887de1 100644
--- a/src/helpers/component.tsx
+++ b/src/helpers/component.tsx
@@ -1,18 +1,30 @@
+import { isDefined } from "./others";
+
export interface Wrapper {
children: React.ReactNode;
}
-interface ConditionalWrapperProps {
+interface ConditionalWrapperProps {
isWrapping: boolean;
children: React.ReactNode;
wrapper: (wrapperProps: T & Wrapper) => JSX.Element;
wrapperProps: T;
+ wrapperFalse?: (wrapperProps: U & Wrapper) => JSX.Element;
+ wrapperFalseProps?: U;
}
-export const ConditionalWrapper = ({
+export const ConditionalWrapper = ({
isWrapping,
children,
wrapper: Wrapper,
+ wrapperFalse: WrapperFalse,
wrapperProps,
-}: ConditionalWrapperProps): JSX.Element =>
- isWrapping ? {children} : <>{children}>;
+ wrapperFalseProps,
+}: ConditionalWrapperProps): JSX.Element =>
+ isWrapping ? (
+ {children}
+ ) : isDefined(WrapperFalse) && isDefined(wrapperFalseProps) ? (
+ {children}
+ ) : (
+ <>{children}>
+ );
diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx
index c5c93d8..e0af11c 100644
--- a/src/pages/_app.tsx
+++ b/src/pages/_app.tsx
@@ -36,10 +36,9 @@ const AccordsLibraryApp = (props: AppProps): JSX.Element => {
>
diff --git a/src/pages/archives/videos/v/[uid].tsx b/src/pages/archives/videos/v/[uid].tsx
index a7eca34..3537ebc 100644
--- a/src/pages/archives/videos/v/[uid].tsx
+++ b/src/pages/archives/videos/v/[uid].tsx
@@ -18,6 +18,7 @@ import { getOpenGraph } from "helpers/openGraph";
import { getLangui } from "graphql/fetchLocalData";
import { atoms } from "contexts/atoms";
import { useAtomGetter } from "helpers/atoms";
+import { Link } from "components/Inputs/Link";
/*
* ╭────────╮
@@ -95,9 +96,9 @@ const Video = ({ video, ...otherProps }: Props): JSX.Element => {
: prettyShortenNumber(video.likes)}
)}
-
-
-
+
+
+
diff --git a/src/pages/library/[slug]/index.tsx b/src/pages/library/[slug]/index.tsx
index 080330c..903feeb 100644
--- a/src/pages/library/[slug]/index.tsx
+++ b/src/pages/library/[slug]/index.tsx
@@ -53,6 +53,7 @@ import { getLangui } from "graphql/fetchLocalData";
import { Ids } from "types/ids";
import { atoms } from "contexts/atoms";
import { useAtomGetter } from "helpers/atoms";
+import { Link } from "components/Inputs/Link";
/*
* ╭─────────────╮
@@ -713,7 +714,7 @@ const ContentLine = ({
cIf(isOpened, "my-2 h-auto bg-mid py-3 shadow-inner-sm shadow-shade")
)}>