Full cleanup pass
This commit is contained in:
@@ -1,10 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { memo } from "react";
|
||||
import { memo, useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useCreateFlowSm2Up } from "../../../(app)/create/hooks/useCreateFlowSm2Up";
|
||||
import { useTranslation } from "../../../contexts/MessagesContext";
|
||||
import { CreateFlowTopNavView } from "./CreateFlowTopNav.view";
|
||||
import type { CreateFlowTopNavProps } from "./CreateFlowTopNav.types";
|
||||
import type {
|
||||
CreateFlowTopNavActionMenuItem,
|
||||
CreateFlowTopNavProps,
|
||||
} from "./CreateFlowTopNav.types";
|
||||
|
||||
/**
|
||||
* Figma: Utility / CreateFlowTopNav — wizard header (create-flow chrome).
|
||||
@@ -34,15 +38,168 @@ const CreateFlowTopNavContainer = memo<CreateFlowTopNavProps>(
|
||||
const router = useRouter();
|
||||
const t = useTranslation("create.topNav");
|
||||
const tPopover = useTranslation("modals.popoverExport");
|
||||
const sm2Up = useCreateFlowSm2Up();
|
||||
const exitButtonText =
|
||||
exitLabel ?? (saveDraftOnExit ? t("saveAndExit") : t("exit"));
|
||||
const [exportMenuOpen, setExportMenuOpen] = useState(false);
|
||||
const [actionsMenuOpen, setActionsMenuOpen] = useState(false);
|
||||
const exportWrapRef = useRef<HTMLDivElement>(null);
|
||||
const actionsWrapRef = useRef<HTMLDivElement>(null);
|
||||
const exportMenuId = useId();
|
||||
const actionsMenuId = useId();
|
||||
|
||||
const handleExit = (options?: { saveDraft?: boolean }) => {
|
||||
if (onExit) {
|
||||
onExit(options);
|
||||
} else {
|
||||
// Default behavior: navigate to home
|
||||
router.push("/");
|
||||
const handleExit = useCallback(
|
||||
(options?: { saveDraft?: boolean }) => {
|
||||
if (onExit) {
|
||||
onExit(options);
|
||||
} else {
|
||||
// Default behavior: navigate to home
|
||||
router.push("/");
|
||||
}
|
||||
},
|
||||
[onExit, router],
|
||||
);
|
||||
|
||||
const hasSecondaryActions =
|
||||
hasShare ||
|
||||
hasExport ||
|
||||
hasEdit ||
|
||||
hasDuplicate ||
|
||||
hasManageStakeholders;
|
||||
const useKebabMenu = hasSecondaryActions && !sm2Up;
|
||||
|
||||
const actionMenuItems = useMemo((): CreateFlowTopNavActionMenuItem[] => {
|
||||
const items: CreateFlowTopNavActionMenuItem[] = [];
|
||||
|
||||
if (hasShare && onShare) {
|
||||
items.push({
|
||||
id: "share",
|
||||
label: t("share"),
|
||||
leadingIcon: "mail",
|
||||
onClick: onShare,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (hasExport && onSelectExportFormat) {
|
||||
items.push(
|
||||
{
|
||||
id: "export-pdf",
|
||||
label: tPopover("downloadPdf"),
|
||||
leadingIcon: "picture_as_pdf",
|
||||
onClick: () => onSelectExportFormat("pdf"),
|
||||
},
|
||||
{
|
||||
id: "export-csv",
|
||||
label: tPopover("downloadCsv"),
|
||||
leadingIcon: "csv",
|
||||
onClick: () => onSelectExportFormat("csv"),
|
||||
},
|
||||
{
|
||||
id: "export-markdown",
|
||||
label: tPopover("downloadMarkdown"),
|
||||
leadingIcon: "markdown_copy",
|
||||
onClick: () => onSelectExportFormat("markdown"),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (hasDuplicate && onDuplicate) {
|
||||
items.push({
|
||||
id: "duplicate",
|
||||
label: duplicateLabel ?? t("edit"),
|
||||
leadingIcon: "content_copy",
|
||||
onClick: onDuplicate,
|
||||
});
|
||||
} else if (hasEdit && onEdit) {
|
||||
items.push({
|
||||
id: "edit",
|
||||
label: t("edit"),
|
||||
leadingIcon: "edit",
|
||||
onClick: onEdit,
|
||||
});
|
||||
}
|
||||
|
||||
if (hasManageStakeholders && onManageStakeholders) {
|
||||
items.push({
|
||||
id: "manage-stakeholders",
|
||||
label: t("manageStakeholders"),
|
||||
leadingIcon: "tags",
|
||||
onClick: onManageStakeholders,
|
||||
});
|
||||
}
|
||||
|
||||
items.push({
|
||||
id: "exit",
|
||||
label: exitButtonText,
|
||||
leadingIcon: "log_out",
|
||||
onClick: () => void handleExit({ saveDraft: saveDraftOnExit }),
|
||||
});
|
||||
|
||||
return items;
|
||||
}, [
|
||||
duplicateLabel,
|
||||
exitButtonText,
|
||||
handleExit,
|
||||
hasDuplicate,
|
||||
hasEdit,
|
||||
hasExport,
|
||||
hasManageStakeholders,
|
||||
hasShare,
|
||||
onDuplicate,
|
||||
onEdit,
|
||||
onManageStakeholders,
|
||||
onSelectExportFormat,
|
||||
onShare,
|
||||
saveDraftOnExit,
|
||||
t,
|
||||
tPopover,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!exportMenuOpen) return;
|
||||
const onDoc = (e: MouseEvent) => {
|
||||
if (
|
||||
exportWrapRef.current &&
|
||||
!exportWrapRef.current.contains(e.target as Node)
|
||||
) {
|
||||
setExportMenuOpen(false);
|
||||
}
|
||||
};
|
||||
document.addEventListener("mousedown", onDoc);
|
||||
return () => document.removeEventListener("mousedown", onDoc);
|
||||
}, [exportMenuOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!actionsMenuOpen) return;
|
||||
const onDoc = (e: MouseEvent) => {
|
||||
if (
|
||||
actionsWrapRef.current &&
|
||||
!actionsWrapRef.current.contains(e.target as Node)
|
||||
) {
|
||||
setActionsMenuOpen(false);
|
||||
}
|
||||
};
|
||||
document.addEventListener("mousedown", onDoc);
|
||||
return () => document.removeEventListener("mousedown", onDoc);
|
||||
}, [actionsMenuOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!exportMenuOpen) return;
|
||||
const onKey = (e: KeyboardEvent) => {
|
||||
if (e.key === "Escape") setExportMenuOpen(false);
|
||||
};
|
||||
window.addEventListener("keydown", onKey);
|
||||
return () => window.removeEventListener("keydown", onKey);
|
||||
}, [exportMenuOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!actionsMenuOpen) return;
|
||||
const onKey = (e: KeyboardEvent) => {
|
||||
if (e.key === "Escape") setActionsMenuOpen(false);
|
||||
};
|
||||
window.addEventListener("keydown", onKey);
|
||||
return () => window.removeEventListener("keydown", onKey);
|
||||
}, [actionsMenuOpen]);
|
||||
|
||||
return (
|
||||
<CreateFlowTopNavView
|
||||
@@ -63,6 +220,17 @@ const CreateFlowTopNavContainer = memo<CreateFlowTopNavProps>(
|
||||
duplicateAriaLabel={duplicateAriaLabel}
|
||||
buttonPalette={buttonPalette}
|
||||
className={className}
|
||||
exitButtonText={exitButtonText}
|
||||
useKebabMenu={useKebabMenu}
|
||||
exportMenuOpen={exportMenuOpen}
|
||||
setExportMenuOpen={setExportMenuOpen}
|
||||
actionsMenuOpen={actionsMenuOpen}
|
||||
setActionsMenuOpen={setActionsMenuOpen}
|
||||
exportWrapRef={exportWrapRef}
|
||||
actionsWrapRef={actionsWrapRef}
|
||||
exportMenuId={exportMenuId}
|
||||
actionsMenuId={actionsMenuId}
|
||||
actionMenuItems={actionMenuItems}
|
||||
exportPopoverMenuAriaLabel={tPopover("menuAriaLabel")}
|
||||
exportPopoverPdfLabel={tPopover("downloadPdf")}
|
||||
exportPopoverCsvLabel={tPopover("downloadCsv")}
|
||||
|
||||
Reference in New Issue
Block a user