@activecollab/components
Version:
ActiveCollab Components
537 lines (517 loc) • 27.9 kB
JavaScript
import React, { useCallback, useState } from "react";
import styled, { createGlobalStyle } from "styled-components";
import { ConnectRepositoryDialog } from "./ConnectRepositoryDialog";
import { RoundAvatar } from "./RoundAvatar";
import { AVATAR_COLORS, MD, SM, TRANSITION } from "./tokens";
import { WEBHOOK_CONNECTIONS, WEBHOOK_REPOSITORIES, WebhookLogsDialog } from "./WebhookLogsDialog";
import { Badge } from "../../components/Badge";
import { Button } from "../../components/Button";
import { GlobalAddButton } from "../../components/Button/GlobalAddButton";
import { CompleteCheckbox } from "../../components/CompleteCheckbox";
import { CounterButton } from "../../components/CounterButton";
import { Dialog } from "../../components/Dialog";
import { Header } from "../../components/Header";
import { IconButton } from "../../components/IconButton";
import { AccessLogIcon, AddCrossTinyIcon, ArrowLeftIcon, CaretRightIcon, CheckboxBlankTogglerIcon, CloseSmallIcon, CrownBlankIcon, CrownSelectedIcon, DownloadIcon, DuplicateIcon, EditIcon, EditMultipleIcon, FilterIcon, GitHubIcon, GitIcon, GitLabIcon, GitRepositoryConnectIcon, GitRepositoryIcon, InfoIcon, InsertLinkIcon, LabelsIcon, NotificationBellIcon, PeopleIcon, ProjectTemplateConvertIcon, ProjectTemplateIcon, StarIcon, TrashIcon, TreeDotsIcon, ViewListIcon, ViewTimelineIcon } from "../../components/Icons";
import { List, ListItem, ListSeparator } from "../../components/List";
import { Menu, MenuHeader } from "../../components/Menu";
import { Item, Nav } from "../../components/Nav";
import { ProgressPie } from "../../components/ProgressPie";
import { ToastMessage } from "../../components/ToastMessage";
import { Tooltip } from "../../components/Tooltip";
import { ResizeTransition, SlideFromTop, SlideLeftRightTransition } from "../../components/Transitions";
import { Body2, Caption1, Header2, Title2 } from "../../components/Typography";
/** Gold used for the project-leader cues (a data colour, not a theme token). */
const LEADER_GOLD = "#FFCC6B";
/* ------------------------------------------------------------------ */
/* Page header row (mirrors PageHeader.jsx) */
/* ------------------------------------------------------------------ */
const StyledPageHeader = styled.div.withConfig({
displayName: "headers__StyledPageHeader",
componentId: "sc-yf6o6n-0"
})(["display:flex;align-items:center;justify-content:space-between;margin:12px 0;width:100%;height:40px;flex-shrink:0;.page-header-left{display:flex;align-items:center;width:100%;max-width:100%;@media (min-width:", "){min-width:0;}}.back-button{flex-shrink:0;margin-right:4px;@media (min-width:", "){margin-right:8px;}}.page-title-desktop{display:none;margin-right:8px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;@media (min-width:", "){display:block;}}.page-title-mobile{display:block;margin-right:8px;font-weight:300;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;@media (min-width:", "){display:none;}}.page-header-children{flex-shrink:0;display:flex;align-items:center;}.page-header-spacer{display:none;height:100%;width:208px;flex-shrink:0;@media (min-width:", "){display:flex;}}"], SM, MD, MD, MD, SM);
/** Generic page header (title + optional controls), mirrors PageHeader.jsx. */
export const PageHeader = _ref => {
let title = _ref.title,
children = _ref.children;
return /*#__PURE__*/React.createElement(StyledPageHeader, null, /*#__PURE__*/React.createElement("div", {
className: "page-header-left"
}, /*#__PURE__*/React.createElement(Title2, {
className: "page-title-desktop"
}, title), /*#__PURE__*/React.createElement(Header2, {
className: "page-title-mobile"
}, title), /*#__PURE__*/React.createElement("div", {
className: "page-header-children"
}, children)), /*#__PURE__*/React.createElement("div", {
className: "page-header-spacer"
}));
};
PageHeader.displayName = "PageHeader";
/* ------------------------------------------------------------------ */
/* Project page header (mirrors ProjectPage.js Page.Header children) */
/* ------------------------------------------------------------------ */
const StyledProjectHeaderChildren = styled.div.withConfig({
displayName: "headers__StyledProjectHeaderChildren",
componentId: "sc-yf6o6n-1"
})(["display:flex;align-items:center;gap:8px;.project-progress{display:flex;align-items:center;margin-left:4px;}"]);
/* Project "..." options menu (Menu + List with leading-icon items). Two items
(Favorite, Subscribe) have a checkbox on the right. Clicks are no-ops. */
const StyledProjectMenu = styled.div.withConfig({
displayName: "headers__StyledProjectMenu",
componentId: "sc-yf6o6n-2"
})([".toggle-item{justify-content:space-between;}.toggle-item .opt-left{display:flex;align-items:center;min-width:0;}.toggle-item .opt-left svg{margin-right:8px;flex-shrink:0;}.toggle-item .c-complete-checkbox{width:16px;height:16px;border-radius:3px;align-self:center;flex-shrink:0;}.submenu-item{justify-content:space-between;}.submenu-item .repo-right{display:flex;align-items:center;gap:8px;flex-shrink:0;}.submenu-item .repo-right .c-badge{background-color:var(--color-theme-300);color:var(--color-theme-700);}.submenu-item .repo-caret{flex-shrink:0;fill:var(--color-theme-600);}.repo-row{min-width:0;}.repo-row > svg{flex-shrink:0;}.repo-name{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}"]);
/* The project "..." menu shares the Webhook Logs dialog's repository /
* connection universe, so a repository connected here is one that dialog can
* pre-filter by. `WebhookConnection` and `Connection` share a shape, and a
* `WebhookRepository`'s `path` maps onto a `Repository`'s `name`. */
const PROJECT_MENU_CONNECTIONS = WEBHOOK_CONNECTIONS;
const PROJECT_MENU_REPOSITORIES = WEBHOOK_REPOSITORIES.map(repo => ({
id: repo.id,
name: repo.path,
connectionId: repo.connectionId
}));
/** Submenu row label for a connected repository: "path (Connection)". The
* service type is omitted because the leading provider icon already conveys
* it. */
const repositoryMenuLabel = repo => {
const connection = PROJECT_MENU_CONNECTIONS.find(c => c.id === repo.connectionId);
return connection ? repo.name + " (" + connection.name + ")" : repo.name;
};
/** Provider glyph for a connected repository: GitHub / GitLab for those
* services, and the generic Git mark for anything else (e.g. an upcoming
* Bitbucket connection). */
const repositoryIcon = repo => {
const connection = PROJECT_MENU_CONNECTIONS.find(c => c.id === repo.connectionId);
switch (connection == null ? void 0 : connection.service) {
case "github":
return GitHubIcon;
case "gitlab":
return GitLabIcon;
default:
return GitIcon;
}
};
/** Width of the project "..." menu (matches the DS "normal" menu mode). */
const PROJECT_MENU_WIDTH = 260;
/* The menu drills in place (index → Repositories), so the paper must clip the
sliding panels and give them a positioning context. */
const ProjectMenuSliderStyle = createGlobalStyle([".c-simple-menu__paper.project-options-menu{overflow:hidden;position:relative;}"]);
/* Toast anchor — fixed, upper-right corner (the toast slides down from the
top). The wrapper ignores pointer events so it never blocks the page; only
the toast itself is interactive. */
const StyledToastAnchor = styled.div.withConfig({
displayName: "headers__StyledToastAnchor",
componentId: "sc-yf6o6n-3"
})(["position:fixed;top:16px;right:16px;z-index:10000;pointer-events:none;.c-toast-message{pointer-events:auto;}"]);
/**
* The project "..." options menu. When the `source` module is loaded it gains
* a **Repositories** item that, instead of flying out to the side, **drills in
* within the same menu** (the pattern used across the app — see `Filter`): the
* index slides out to the left and the Repositories view (a back-arrow header,
* the connected repositories sorted by name, and a **Connect Repository**
* action) slides in. Connecting adds a repository to the list; clicking one
* would, in production, open it in a new tab (surfaced here via a dialog).
*/
const ProjectOptionsMenu = _ref2 => {
let _ref2$sourceModuleLoa = _ref2.sourceModuleLoaded,
sourceModuleLoaded = _ref2$sourceModuleLoa === void 0 ? false : _ref2$sourceModuleLoa,
_ref2$initialConnecte = _ref2.initialConnectedRepositories,
initialConnectedRepositories = _ref2$initialConnecte === void 0 ? [] : _ref2$initialConnecte,
_ref2$canManageProjec = _ref2.canManageProjectRepositories,
canManageProjectRepositories = _ref2$canManageProjec === void 0 ? true : _ref2$canManageProjec;
const _useState = useState(false),
open = _useState[0],
setOpen = _useState[1];
const _useState2 = useState("index"),
view = _useState2[0],
setView = _useState2[1];
const _useState3 = useState(false),
webhookLogsOpen = _useState3[0],
setWebhookLogsOpen = _useState3[1];
const _useState4 = useState(true),
isLeft = _useState4[0],
setIsLeft = _useState4[1];
const _useState5 = useState(0),
height = _useState5[0],
setHeight = _useState5[1];
// Connected repositories drive the count badge on the Repositories item. In
// production this count comes from the project's `count_repositories` counter,
// kept current via pusher/websocket events, so the badge reflects repositories
// connected or disconnected by anyone — not just the current user's actions.
const _useState6 = useState(initialConnectedRepositories),
connectedRepos = _useState6[0],
setConnectedRepos = _useState6[1];
const _useState7 = useState(false),
connectOpen = _useState7[0],
setConnectOpen = _useState7[1];
const _useState8 = useState(false),
infoOpen = _useState8[0],
setInfoOpen = _useState8[1];
const _useState9 = useState(false),
toastOpen = _useState9[0],
setToastOpen = _useState9[1];
// Bumped on each connect so the toast remounts and its auto-hide timer
// restarts from the moment it is shown.
const _useState0 = useState(0),
toastKey = _useState0[0],
setToastKey = _useState0[1];
// Repositories still available to connect (not already on the project).
const connectableRepos = PROJECT_MENU_REPOSITORIES.filter(r => !connectedRepos.some(c => c.id === r.id));
// Connected repositories are listed in the submenu sorted by name.
const sortedRepos = [...connectedRepos].sort((a, b) => a.name.localeCompare(b.name));
// Each view measures itself as it mounts so the paper can animate its height.
const measure = useCallback(node => {
if (node) {
setHeight(node.offsetHeight);
}
}, []);
const goToRepositories = () => {
setView("repositories");
setIsLeft(true);
};
const backToIndex = () => {
setView("index");
setIsLeft(false);
};
const handleClose = () => {
setOpen(false);
// Reset to the index so the next open starts at the top level.
setView("index");
setIsLeft(true);
};
const handleConnected = repo => {
setConnectedRepos(prev => prev.some(r => r.id === repo.id) ? prev : [...prev, repo]);
setToastOpen(true);
setToastKey(k => k + 1);
};
const handleConnect = () => {
handleClose();
setConnectOpen(true);
};
// In production this closes the menu and opens the repository in a new tab;
// in the mock we surface that behaviour in a small dialog instead.
const handleOpenRepository = () => {
handleClose();
setInfoOpen(true);
};
const handleOpenWebhookLogs = () => {
handleClose();
setWebhookLogsOpen(true);
};
const indexView = /*#__PURE__*/React.createElement(StyledProjectMenu, null, /*#__PURE__*/React.createElement(List, {
style: {
padding: "8px 0"
},
tabIndex: -1
}, /*#__PURE__*/React.createElement(ListItem, null, /*#__PURE__*/React.createElement(EditIcon, null), "Edit"), /*#__PURE__*/React.createElement(ListItem, {
className: "toggle-item"
}, /*#__PURE__*/React.createElement("span", {
className: "opt-left"
}, /*#__PURE__*/React.createElement(StarIcon, null), "Mark as Favorite"), /*#__PURE__*/React.createElement(CompleteCheckbox, {
primary: true,
completed: true
})), /*#__PURE__*/React.createElement(ListItem, {
className: "toggle-item"
}, /*#__PURE__*/React.createElement("span", {
className: "opt-left"
}, /*#__PURE__*/React.createElement(NotificationBellIcon, null), "Subscribe to Everything"), /*#__PURE__*/React.createElement(CompleteCheckbox, {
primary: true,
completed: false
})), /*#__PURE__*/React.createElement(ListItem, null, /*#__PURE__*/React.createElement(LabelsIcon, null), "Manage Task Labels"), /*#__PURE__*/React.createElement(ListItem, null, /*#__PURE__*/React.createElement(InsertLinkIcon, null), "Copy Link"), /*#__PURE__*/React.createElement(ListSeparator, null), /*#__PURE__*/React.createElement(ListItem, null, /*#__PURE__*/React.createElement(CheckboxBlankTogglerIcon, null), "Complete"), /*#__PURE__*/React.createElement(ListItem, null, /*#__PURE__*/React.createElement(DownloadIcon, null), "Export"), sourceModuleLoaded ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ListSeparator, null), /*#__PURE__*/React.createElement(ListItem, {
className: "toggle-item submenu-item",
onClick: goToRepositories
}, /*#__PURE__*/React.createElement("span", {
className: "opt-left"
}, /*#__PURE__*/React.createElement(GitRepositoryIcon, null), "Repositories"), /*#__PURE__*/React.createElement("span", {
className: "repo-right"
}, connectedRepos.length > 0 ? /*#__PURE__*/React.createElement(Badge, {
isStandalone: true,
dimension: 16,
value: connectedRepos.length
}) : null, /*#__PURE__*/React.createElement(CaretRightIcon, {
className: "repo-caret",
width: 16,
height: 16
})))) : null, /*#__PURE__*/React.createElement(ListSeparator, null), /*#__PURE__*/React.createElement(ListItem, null, /*#__PURE__*/React.createElement(DuplicateIcon, null), "Duplicate"), /*#__PURE__*/React.createElement(ListItem, null, /*#__PURE__*/React.createElement(ProjectTemplateIcon, null), "Apply Template"), /*#__PURE__*/React.createElement(ListItem, null, /*#__PURE__*/React.createElement(ProjectTemplateConvertIcon, null), "Convert to Template"), /*#__PURE__*/React.createElement(ListSeparator, null), /*#__PURE__*/React.createElement(ListItem, null, /*#__PURE__*/React.createElement(TrashIcon, null), "Delete")));
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ProjectMenuSliderStyle, null), /*#__PURE__*/React.createElement(Menu, {
open: open,
onOpen: () => setOpen(true),
onClose: handleClose,
position: "bottom-end",
menuClassName: sourceModuleLoaded ? "project-options-menu" : undefined,
target: /*#__PURE__*/React.createElement(IconButton, {
type: "button",
variant: "text gray",
active: open
}, /*#__PURE__*/React.createElement(TreeDotsIcon, null))
}, sourceModuleLoaded ? /*#__PURE__*/React.createElement(ResizeTransition, {
in: true,
style: {
height,
width: PROJECT_MENU_WIDTH
}
}, /*#__PURE__*/React.createElement("div", {
style: {
position: "relative",
overflow: "hidden"
}
}, /*#__PURE__*/React.createElement(SlideLeftRightTransition, {
in: view === "index",
direction: isLeft ? "left" : "right"
}, /*#__PURE__*/React.createElement("div", {
ref: measure,
style: {
width: PROJECT_MENU_WIDTH
}
}, indexView)), /*#__PURE__*/React.createElement(SlideLeftRightTransition, {
in: view === "repositories",
direction: isLeft ? "left" : "right"
}, /*#__PURE__*/React.createElement("div", {
ref: measure,
style: {
width: PROJECT_MENU_WIDTH
}
}, /*#__PURE__*/React.createElement(MenuHeader, {
title: "Repositories",
leftElement: /*#__PURE__*/React.createElement(IconButton, {
type: "button",
variant: "text gray",
size: "small",
onClick: backToIndex,
"aria-label": "Back"
}, /*#__PURE__*/React.createElement(ArrowLeftIcon, null))
}), /*#__PURE__*/React.createElement(StyledProjectMenu, null, /*#__PURE__*/React.createElement(List, {
style: {
padding: "8px 0"
},
tabIndex: -1
}, sortedRepos.map(repo => {
const RepoIcon = repositoryIcon(repo);
return /*#__PURE__*/React.createElement(ListItem, {
key: repo.id,
className: "repo-row",
onClick: () => handleOpenRepository()
}, /*#__PURE__*/React.createElement(RepoIcon, null), /*#__PURE__*/React.createElement("span", {
className: "repo-name"
}, repositoryMenuLabel(repo)));
}), sortedRepos.length > 0 ? /*#__PURE__*/React.createElement(ListSeparator, null) : null, sortedRepos.length > 0 && canManageProjectRepositories ? /*#__PURE__*/React.createElement(ListItem, {
onClick: handleOpenWebhookLogs
}, /*#__PURE__*/React.createElement(AccessLogIcon, null), "Webhook Logs") : null, /*#__PURE__*/React.createElement(ListItem, {
onClick: handleConnect
}, /*#__PURE__*/React.createElement(GitRepositoryConnectIcon, null), "Connect Repository"))))))) : indexView), /*#__PURE__*/React.createElement(ConnectRepositoryDialog, {
open: connectOpen,
onClose: () => setConnectOpen(false),
onConnect: handleConnected,
repositories: connectableRepos,
connections: PROJECT_MENU_CONNECTIONS
}), /*#__PURE__*/React.createElement(WebhookLogsDialog, {
open: webhookLogsOpen,
onClose: () => setWebhookLogsOpen(false),
repositoryIds: sortedRepos.map(repo => repo.id)
}), /*#__PURE__*/React.createElement(Dialog, {
open: infoOpen,
onClose: () => setInfoOpen(false),
enableBackgroundClick: true
}, /*#__PURE__*/React.createElement(Dialog.Title, null, "Open Repository"), /*#__PURE__*/React.createElement(Dialog.ContentDivider, null), /*#__PURE__*/React.createElement(Dialog.Content, null, /*#__PURE__*/React.createElement(Body2, null, "In production, this click would close the menu and open the repository in a new browser tab.")), /*#__PURE__*/React.createElement(Dialog.ContentDivider, null), /*#__PURE__*/React.createElement(Dialog.Actions, null, /*#__PURE__*/React.createElement(Button, {
variant: "primary",
onClick: () => setInfoOpen(false)
}, "Got it"))), /*#__PURE__*/React.createElement(StyledToastAnchor, null, /*#__PURE__*/React.createElement(SlideFromTop, {
in: toastOpen
}, /*#__PURE__*/React.createElement(ToastMessage, {
key: toastKey,
className: "c-toast-message",
type: "success",
text: "Repository connected.",
dismissible: true,
dropShadow: true,
timeout: 3000,
onClose: () => setToastOpen(false)
}))));
};
/* People popover (mirrors the project header People dropdown): a header row
("People" + add button), a "Members" section and a row per member. The
project leader shows a gold crown; other members reveal a "set as leader"
crown and a remove button on hover. Clicks are no-ops. */
const PROJECT_MEMBERS = [{
name: "Theo Brandt",
initials: "TB",
color: AVATAR_COLORS.blue,
leader: true
}, {
name: "Iris Calloway",
initials: "IC",
color: AVATAR_COLORS.purple
}, {
name: "Account Director",
initials: "AD",
color: "#8A8F98"
}, {
name: "Grace Bennett",
initials: "GB",
color: AVATAR_COLORS.orange
}];
const StyledPeopleMenu = styled.div.withConfig({
displayName: "headers__StyledPeopleMenu",
componentId: "sc-yf6o6n-4"
})(["width:256px;.members-label{display:block;margin:8px 0;padding:0 16px;}.member-row{position:relative;display:flex;align-items:center;min-height:40px;margin:0 8px;padding:2px 8px;border-radius:4px;cursor:default;transition:background-color ", ";}.member-row:hover{background-color:var(--color-theme-200);}.member-row.leader::before{content:\"\";position:absolute;top:4px;bottom:4px;left:0;width:4px;border-radius:4px;background-color:", ";}.member-row.leader .member-avatar{outline:2px solid ", ";outline-offset:-2px;}.member-name{flex:1;margin-left:12px;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.member-right{display:flex;align-items:center;gap:2px;flex-shrink:0;margin-left:8px;}.leader-crown{flex-shrink:0;}.member-options{display:none;align-items:center;gap:2px;}.member-row:hover .member-options{display:flex;}"], TRANSITION, LEADER_GOLD, LEADER_GOLD);
const PeoplePopover = () => {
const _useState1 = useState(false),
open = _useState1[0],
setOpen = _useState1[1];
return /*#__PURE__*/React.createElement(Menu, {
open: open,
onOpen: () => setOpen(true),
onClose: () => setOpen(false),
position: "bottom-end",
target: /*#__PURE__*/React.createElement(CounterButton, {
label: String(PROJECT_MEMBERS.length),
icon: /*#__PURE__*/React.createElement(PeopleIcon, null),
active: open,
onClearAll: () => undefined
})
}, /*#__PURE__*/React.createElement(StyledPeopleMenu, null, /*#__PURE__*/React.createElement(MenuHeader, {
title: "People",
rightElement: /*#__PURE__*/React.createElement(IconButton, {
type: "button",
variant: "text gray",
size: "small",
"aria-label": "Add People"
}, /*#__PURE__*/React.createElement(AddCrossTinyIcon, null))
}), /*#__PURE__*/React.createElement(Caption1, {
weight: "bold",
className: "members-label"
}, "Members"), PROJECT_MEMBERS.map(member => /*#__PURE__*/React.createElement("div", {
className: member.leader ? "member-row leader" : "member-row",
key: member.name
}, /*#__PURE__*/React.createElement(RoundAvatar, {
className: "member-avatar",
$bg: member.color,
$bordered: false
}, member.initials), /*#__PURE__*/React.createElement(Body2, {
className: "member-name"
}, member.name), /*#__PURE__*/React.createElement("span", {
className: "member-right"
}, member.leader && /*#__PURE__*/React.createElement(CrownSelectedIcon, {
className: "leader-crown",
style: {
fill: LEADER_GOLD
}
}), /*#__PURE__*/React.createElement("span", {
className: "member-options"
}, !member.leader && /*#__PURE__*/React.createElement(Tooltip, {
title: "Set as Project Leader"
}, /*#__PURE__*/React.createElement(IconButton, {
type: "button",
variant: "text gray",
size: "small"
}, /*#__PURE__*/React.createElement(CrownBlankIcon, null))), /*#__PURE__*/React.createElement(Tooltip, {
title: "Remove from Project"
}, /*#__PURE__*/React.createElement(IconButton, {
type: "button",
variant: "text gray",
size: "small"
}, /*#__PURE__*/React.createElement(CloseSmallIcon, null)))))))));
};
/** The project page header: back arrow, title, progress, info, people, options. */
export const ProjectPageHeader = _ref3 => {
let _ref3$title = _ref3.title,
title = _ref3$title === void 0 ? "#131: Ime projekta" : _ref3$title,
_ref3$sourceModuleLoa = _ref3.sourceModuleLoaded,
sourceModuleLoaded = _ref3$sourceModuleLoa === void 0 ? false : _ref3$sourceModuleLoa,
initialConnectedRepositories = _ref3.initialConnectedRepositories,
canManageProjectRepositories = _ref3.canManageProjectRepositories;
return /*#__PURE__*/React.createElement(StyledPageHeader, null, /*#__PURE__*/React.createElement("div", {
className: "page-header-left"
}, /*#__PURE__*/React.createElement(IconButton, {
variant: "text gray",
className: "back-button"
}, /*#__PURE__*/React.createElement(ArrowLeftIcon, null)), /*#__PURE__*/React.createElement(Title2, {
className: "page-title-desktop"
}, title), /*#__PURE__*/React.createElement(Header2, {
className: "page-title-mobile"
}, title), /*#__PURE__*/React.createElement("div", {
className: "page-header-children"
}, /*#__PURE__*/React.createElement(StyledProjectHeaderChildren, null, /*#__PURE__*/React.createElement("span", {
className: "project-progress"
}, /*#__PURE__*/React.createElement(ProgressPie, {
radius: 11,
progress: 64,
progressColor: "var(--color-secondary)",
backgroundColor: "var(--color-theme-300)"
})), /*#__PURE__*/React.createElement(Tooltip, {
title: "Project Info"
}, /*#__PURE__*/React.createElement(IconButton, {
variant: "text gray"
}, /*#__PURE__*/React.createElement(InfoIcon, null))), /*#__PURE__*/React.createElement(PeoplePopover, null), /*#__PURE__*/React.createElement(ProjectOptionsMenu, {
sourceModuleLoaded: sourceModuleLoaded,
initialConnectedRepositories: initialConnectedRepositories,
canManageProjectRepositories: canManageProjectRepositories
})))), /*#__PURE__*/React.createElement("div", {
className: "page-header-spacer"
}));
};
ProjectPageHeader.displayName = "ProjectPageHeader";
/* ------------------------------------------------------------------ */
/* Tab bar (mirrors the <Header> with <Nav> on ProjectPage.js) */
/* ------------------------------------------------------------------ */
const NAV_TABS = ["Tasks", "Discussions", "Files", "Notes", "Activity"];
const StyledTabHeader = styled(Header).withConfig({
displayName: "headers__StyledTabHeader",
componentId: "sc-yf6o6n-5"
})(["justify-content:space-between;align-items:center;margin-bottom:16px;min-height:64px;flex-shrink:0;"]);
const StyledTabControls = styled.div.withConfig({
displayName: "headers__StyledTabControls",
componentId: "sc-yf6o6n-6"
})(["display:flex;align-items:center;flex-shrink:0;gap:4px;.vertical-separator{width:1px;height:24px;background-color:var(--color-theme-400);margin:0 8px;}.filter-button{display:flex;align-items:center;gap:6px;}"]);
/** The Tasks/Discussions/… tab bar plus the right-hand view toolbar. */
export const TabHeader = _ref4 => {
let _ref4$activeView = _ref4.activeView,
activeView = _ref4$activeView === void 0 ? "list" : _ref4$activeView;
const _useState10 = useState(0),
active = _useState10[0],
setActive = _useState10[1];
return /*#__PURE__*/React.createElement(StyledTabHeader, null, /*#__PURE__*/React.createElement(Nav, {
onSelect: setActive
}, NAV_TABS.map((label, index) => /*#__PURE__*/React.createElement(Item, {
active: index === active,
key: label,
name: label
}, /*#__PURE__*/React.createElement(Body2, {
color: "secondary",
weight: "medium"
}, label)))), /*#__PURE__*/React.createElement(StyledTabControls, null, /*#__PURE__*/React.createElement(Tooltip, {
title: "Batch Edit"
}, /*#__PURE__*/React.createElement(IconButton, {
variant: "text gray"
}, /*#__PURE__*/React.createElement(EditMultipleIcon, null))), /*#__PURE__*/React.createElement("span", {
className: "vertical-separator"
}), /*#__PURE__*/React.createElement(Button, {
variant: "text gray",
className: "filter-button"
}, /*#__PURE__*/React.createElement(FilterIcon, null), "Filter"), /*#__PURE__*/React.createElement(Tooltip, {
title: "List view"
}, /*#__PURE__*/React.createElement(IconButton, {
variant: "text gray",
active: activeView === "list"
}, /*#__PURE__*/React.createElement(ViewListIcon, null))), /*#__PURE__*/React.createElement(Tooltip, {
title: "Column view"
}, /*#__PURE__*/React.createElement(IconButton, {
variant: "text gray",
active: activeView === "column"
}, /*#__PURE__*/React.createElement(ViewListIcon, {
style: {
transform: "rotate(90deg)"
}
}))), /*#__PURE__*/React.createElement(Tooltip, {
title: "Timeline view"
}, /*#__PURE__*/React.createElement(IconButton, {
variant: "text gray",
active: activeView === "timeline"
}, /*#__PURE__*/React.createElement(ViewTimelineIcon, null))), /*#__PURE__*/React.createElement("span", {
className: "vertical-separator"
}), /*#__PURE__*/React.createElement(Tooltip, {
title: "Add New"
}, /*#__PURE__*/React.createElement(GlobalAddButton, null))));
};
TabHeader.displayName = "TabHeader";
//# sourceMappingURL=headers.js.map