UNPKG

@activecollab/components

Version:

ActiveCollab Components

537 lines (517 loc) 27.9 kB
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