mirror of
https://github.com/LukeHagar/unicorn-utterances.git
synced 2025-12-06 04:21:55 +00:00
merge with softNavigate pagination changes from #601
This commit is contained in:
26
src/components/pagination/on-click-base.ts
Normal file
26
src/components/pagination/on-click-base.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
export const onSoftNavClick =
|
||||
(softNavigate: (href: string) => void) => (e: MouseEvent) => {
|
||||
let link = e.target as HTMLElement;
|
||||
// Could click on a child element of an anchor
|
||||
while (link && !(link instanceof HTMLAnchorElement)) {
|
||||
link = link.parentElement;
|
||||
}
|
||||
|
||||
if (!link) return;
|
||||
|
||||
if (
|
||||
link instanceof HTMLAnchorElement &&
|
||||
link.href &&
|
||||
(!link.target || link.target === "_self") &&
|
||||
link.origin === location.origin &&
|
||||
e.button === 0 && // left click only
|
||||
!e.metaKey && // open in new tab (mac)
|
||||
!e.ctrlKey && // open in new tab (windows)
|
||||
!e.altKey && // download
|
||||
!e.shiftKey && // open in new window
|
||||
!e.defaultPrevented
|
||||
) {
|
||||
e.preventDefault();
|
||||
softNavigate(link.href);
|
||||
}
|
||||
};
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
} from "@floating-ui/react";
|
||||
import { useRef, useState } from "preact/hooks";
|
||||
import { Fragment } from "preact";
|
||||
import { createPortal } from "preact/compat";
|
||||
import { createPortal, StateUpdater } from "preact/compat";
|
||||
import mainStyles from "./pagination.module.scss";
|
||||
import more from "src/icons/more_horiz.svg?raw";
|
||||
import { PaginationProps } from "components/pagination/types";
|
||||
@@ -21,14 +21,23 @@ import subtract from "../../icons/subtract.svg?raw";
|
||||
import add from "../../icons/add.svg?raw";
|
||||
import { Input } from "components/input/input";
|
||||
|
||||
function PopupContents(props: Pick<PaginationProps, "page" | "getPageHref">) {
|
||||
function PopupContents(
|
||||
props: Pick<PaginationProps, "page" | "getPageHref" | "softNavigate"> & {
|
||||
setIsOpen: StateUpdater<boolean>;
|
||||
}
|
||||
) {
|
||||
const [count, setCount] = useState(props.page.currentPage);
|
||||
return (
|
||||
<form
|
||||
class={style.popupInner}
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
location.href = `/page/${count}`;
|
||||
if (props.softNavigate) {
|
||||
props.softNavigate(props.getPageHref(count));
|
||||
props.setIsOpen(false);
|
||||
return;
|
||||
}
|
||||
location.href = props.getPageHref(count);
|
||||
}}
|
||||
>
|
||||
<div class={style.popupTopArea}>
|
||||
@@ -80,7 +89,7 @@ function PopupContents(props: Pick<PaginationProps, "page" | "getPageHref">) {
|
||||
}
|
||||
|
||||
export function PaginationMenuAndPopover(
|
||||
props: Pick<PaginationProps, "page" | "getPageHref">
|
||||
props: Pick<PaginationProps, "page" | "getPageHref" | "softNavigate">
|
||||
) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const arrowRef = useRef(null);
|
||||
@@ -90,7 +99,7 @@ export function PaginationMenuAndPopover(
|
||||
placement: "top",
|
||||
onOpenChange: setIsOpen,
|
||||
middleware: [
|
||||
offset(32 - (14 / 2)),
|
||||
offset(32 - 14 / 2),
|
||||
arrow({
|
||||
element: arrowRef,
|
||||
}),
|
||||
@@ -120,7 +129,7 @@ export function PaginationMenuAndPopover(
|
||||
{...getFloatingProps()}
|
||||
class={style.popup}
|
||||
>
|
||||
<PopupContents {...props} />
|
||||
<PopupContents {...props} setIsOpen={setIsOpen} />
|
||||
<FloatingArrow
|
||||
ref={arrowRef}
|
||||
context={context}
|
||||
|
||||
@@ -5,12 +5,14 @@ import { PaginationMenuAndPopover } from "components/pagination/pagination-popov
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
import { PaginationButtonProps, PaginationProps } from "components/pagination/types";
|
||||
import { usePagination } from "./use-pagination";
|
||||
import { onSoftNavClick } from "./on-click-base";
|
||||
|
||||
function PaginationButton({
|
||||
pageInfo,
|
||||
pageNum,
|
||||
href,
|
||||
selected
|
||||
selected,
|
||||
softNavigate,
|
||||
}: PaginationButtonProps) {
|
||||
const pageOptionalMin = Math.min(Math.max(1, pageInfo.currentPage - 1), pageInfo.lastPage - 3);
|
||||
const isOptional = pageNum < pageOptionalMin || pageNum > pageOptionalMin + 3;
|
||||
@@ -22,6 +24,7 @@ function PaginationButton({
|
||||
selected ? styles.selected : ""
|
||||
}`}
|
||||
href={href}
|
||||
onClick={softNavigate ? onSoftNavClick(softNavigate) : undefined}
|
||||
aria-label={`Go to page ${pageNum}`}
|
||||
aria-current={selected || undefined}
|
||||
>
|
||||
@@ -35,7 +38,7 @@ function PaginationButton({
|
||||
* This prevents the pagination menu from rendering on SSR, which throws errors
|
||||
*/
|
||||
function PaginationMenuWrapper(
|
||||
props: Pick<PaginationProps, "page" | "getPageHref">
|
||||
props: Pick<PaginationProps, "page" | "getPageHref" | "softNavigate">
|
||||
) {
|
||||
const [shouldRender, setShouldRender] = useState(false);
|
||||
|
||||
@@ -54,6 +57,7 @@ export const Pagination = ({
|
||||
class: className = "",
|
||||
id = "post-list-pagination",
|
||||
getPageHref = (pageNum: number) => `${rootURL}${pageNum}`,
|
||||
softNavigate,
|
||||
}: PaginationProps) => {
|
||||
// if there's only one page, don't render anything
|
||||
if (page.currentPage === 1 && page.lastPage < 2) return <></>;
|
||||
@@ -68,7 +72,12 @@ export const Pagination = ({
|
||||
<a
|
||||
className={`text-style-body-medium-bold ${styles.paginationButton} ${styles.paginationIconButton}`}
|
||||
aria-label="Previous"
|
||||
href={!isPreviousEnabled ? "javascript:void(0)" : getPageHref(page.currentPage - 1)}
|
||||
href={
|
||||
!isPreviousEnabled
|
||||
? "javascript:void(0)"
|
||||
: getPageHref(page.currentPage - 1)
|
||||
}
|
||||
onClick={softNavigate ? onSoftNavClick(softNavigate) : undefined}
|
||||
aria-disabled={!isPreviousEnabled}
|
||||
dangerouslySetInnerHTML={{ __html: back }}
|
||||
/>
|
||||
@@ -81,16 +90,26 @@ export const Pagination = ({
|
||||
pageNum={pageNum}
|
||||
selected={pageNum === page.currentPage}
|
||||
href={getPageHref(pageNum)}
|
||||
softNavigate={softNavigate}
|
||||
/>
|
||||
) : (
|
||||
<PaginationMenuWrapper page={page} getPageHref={getPageHref} />
|
||||
<PaginationMenuWrapper
|
||||
page={page}
|
||||
getPageHref={getPageHref}
|
||||
softNavigate={softNavigate}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
<li className={`${styles.paginationItem}`}>
|
||||
<a
|
||||
className={`text-style-body-medium-bold ${styles.paginationButton} ${styles.paginationIconButton}`}
|
||||
href={!isNextEnabled ? "javascript:void(0)" : getPageHref(page.currentPage + 1)}
|
||||
href={
|
||||
!isNextEnabled
|
||||
? "javascript:void(0)"
|
||||
: getPageHref(page.currentPage + 1)
|
||||
}
|
||||
onClick={softNavigate ? onSoftNavClick(softNavigate) : undefined}
|
||||
aria-label="Next"
|
||||
aria-disabled={!isNextEnabled}
|
||||
dangerouslySetInnerHTML={{ __html: forward }}
|
||||
|
||||
@@ -8,6 +8,7 @@ export interface PaginationButtonProps {
|
||||
pageNum: number;
|
||||
selected: boolean;
|
||||
href: string;
|
||||
softNavigate?: (href: string) => void;
|
||||
}
|
||||
|
||||
export interface PaginationProps {
|
||||
@@ -16,4 +17,5 @@ export interface PaginationProps {
|
||||
id?: string;
|
||||
rootURL?: string;
|
||||
getPageHref?: (pageNum: number) => string;
|
||||
softNavigate?: (href: string) => void;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user