import { useAtomValue } from "jotai";
import { treeDataAtom } from "@/features/page/tree/atoms/tree-data-atom.ts";
import React, { useCallback, useEffect, useState } from "react";
import { computeBreadcrumbState } from "./breadcrumb.utils";
import {
Button,
Anchor,
Popover,
Breadcrumbs,
ActionIcon,
Text,
Tooltip,
} from "@mantine/core";
import { IconCornerDownRightDouble, IconDots } from "@tabler/icons-react";
import { Link, useParams } from "react-router-dom";
import classes from "./breadcrumb.module.css";
import { SpaceTreeNode } from "@/features/page/tree/types.ts";
import { IPage } from "@/features/page/types/page.types.ts";
import { buildPageUrl } from "@/features/page/page.utils.ts";
import {
usePageQuery,
usePageBreadcrumbsQuery,
} from "@/features/page/queries/page-query.ts";
import { extractPageSlugId } from "@/lib";
import { useMediaQuery } from "@mantine/hooks";
import { useTranslation } from "react-i18next";
function getTitle(name: string, icon: string) {
if (icon) {
return `${icon} ${name}`;
}
return name;
}
export default function Breadcrumb() {
const { t } = useTranslation();
const treeData = useAtomValue(treeDataAtom);
const [breadcrumbNodes, setBreadcrumbNodes] = useState<
SpaceTreeNode[] | null
>(null);
const { pageSlug, spaceSlug } = useParams();
const { data: currentPage } = usePageQuery({
pageId: extractPageSlugId(pageSlug),
});
// The page's own ancestor chain, fetched independently of the lazily-built
// sidebar tree so a deep page doesn't render a blank breadcrumb for seconds
// while the tree backfills (#218).
const { data: ancestors } = usePageBreadcrumbsQuery(currentPage?.id);
const isMobile = useMediaQuery("(max-width: 48em)");
useEffect(() => {
if (!currentPage) return;
// Selection/mapping + stale-clearing live in a pure, unit-tested helper
// (#218). It resolves the correct chain when possible and, on a transient
// miss, clears a chain left over from a previously-viewed page instead of
// showing the wrong trail — while keeping a chain already resolved for THIS
// page to avoid a blank flash.
setBreadcrumbNodes((previous) =>
computeBreadcrumbState(
treeData,
ancestors as IPage[] | undefined,
currentPage.id,
previous,
),
);
}, [currentPage?.id, treeData, ancestors]);
const HiddenNodesTooltipContent = () =>
breadcrumbNodes?.slice(1, -1).map((node) => (
));
const MobileHiddenNodesTooltipContent = () =>
breadcrumbNodes?.map((node) => (
));
const renderAnchor = useCallback(
(node: SpaceTreeNode, isCurrent = false) => (
{getTitle(node.name, node.icon)}
),
[spaceSlug],
);
const getBreadcrumbItems = () => {
if (!breadcrumbNodes) return [];
if (breadcrumbNodes.length > 3) {
const firstNode = breadcrumbNodes[0];
//const secondLastNode = breadcrumbNodes[breadcrumbNodes.length - 2];
const lastNode = breadcrumbNodes[breadcrumbNodes.length - 1];
return [
renderAnchor(firstNode),
,
//renderAnchor(secondLastNode),
renderAnchor(lastNode, true),
];
}
return breadcrumbNodes.map((node, i) =>
renderAnchor(node, i === breadcrumbNodes.length - 1),
);
};
const getMobileBreadcrumbItems = () => {
if (!breadcrumbNodes) return [];
if (breadcrumbNodes.length > 0) {
return [
,
];
}
return breadcrumbNodes.map((node, i) =>
renderAnchor(node, i === breadcrumbNodes.length - 1),
);
};
return (
);
}