@mcp-b/react-components 0.40.0 → 0.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{AgentChat-CVO7xyLC.d.ts → AgentChat-DVr2giwD.d.ts} +1 -1
- package/dist/{AgentToolRunsContext-BCVqCtJ1.d.ts → AgentToolRunsContext-daY67hFM.d.ts} +12 -0
- package/dist/{CodeBlock-CWk1FVtm.js → CodeBlock-BjELA-_s.js} +1 -1
- package/dist/{FileTree-xqHYBw4g.js → FileTree-DMYRdT6R.js} +1 -1
- package/dist/McpConnectorForm-MRm1r59e.d.ts +39 -0
- package/dist/{Message-DBsHHhcM.d.ts → Message-D_vCVEGB.d.ts} +20 -1
- package/dist/{ThinkChatActivity-D6-_5Phw.d.ts → ThinkChatActivity-CsDql-ER.d.ts} +4 -1
- package/dist/{ThinkExecutionRun-lYYgyeE1.d.ts → ThinkExecutionRun-k8bpyXqt.d.ts} +3 -3
- package/dist/{WorkspaceFileView-Lab3om3F.js → WorkspaceFileView-DwdXiKku.js} +17 -22
- package/dist/{WorkspaceMessageResponse-Cy28WGSz.d.ts → WorkspaceMessageResponse-D66ty4FO.d.ts} +1 -1
- package/dist/components/agents-sdk/AgentActivity.js +4 -3
- package/dist/components/agents-sdk/AgentChat.d.ts +1 -1
- package/dist/components/agents-sdk/AgentChat.js +42 -18
- package/dist/components/agents-sdk/AgentToolRunsContext.d.ts +1 -1
- package/dist/components/agents-sdk/AgentToolRunsContext.js +12 -0
- package/dist/components/agents-sdk/BrowserLiveScreen.d.ts +135 -0
- package/dist/components/agents-sdk/BrowserLiveScreen.js +637 -0
- package/dist/components/agents-sdk/BrowserLiveView.d.ts +2 -2
- package/dist/components/agents-sdk/BrowserLiveView.js +6 -9
- package/dist/components/agents-sdk/BrowserReplay.js +1 -1
- package/dist/components/agents-sdk/BrowserRunPanel.d.ts +1 -1
- package/dist/components/agents-sdk/BrowserRunPanel.js +8 -13
- package/dist/components/agents-sdk/ManagerOffice.d.ts +168 -0
- package/dist/components/agents-sdk/ManagerOffice.js +698 -0
- package/dist/components/agents-sdk/McpConnectionRequest.js +3 -3
- package/dist/components/agents-sdk/McpConnectorForm.d.ts +1 -38
- package/dist/components/agents-sdk/McpPluginCatalog.d.ts +8 -2
- package/dist/components/agents-sdk/McpPluginCatalog.js +82 -62
- package/dist/components/agents-sdk/McpServerPicker.d.ts +1 -1
- package/dist/components/agents-sdk/McpServerPicker.js +2 -2
- package/dist/components/agents-sdk/ModelSelector.js +1 -1
- package/dist/components/agents-sdk/PromptInputCommands.js +1 -1
- package/dist/components/agents-sdk/SubagentRunDetails.d.ts +1 -9
- package/dist/components/agents-sdk/SubagentRunDetails.js +1 -9
- package/dist/components/agents-sdk/SubagentRunIndicator.js +1 -1
- package/dist/components/agents-sdk/SubagentRunSelector.d.ts +4 -2
- package/dist/components/agents-sdk/SubagentRunSelector.js +7 -6
- package/dist/components/agents-sdk/ThinkChat.d.ts +4 -4
- package/dist/components/agents-sdk/ThinkChatActivity.d.ts +1 -1
- package/dist/components/agents-sdk/ThinkChatActivity.js +18 -4
- package/dist/components/agents-sdk/ThinkChatToolPanels.js +7 -3
- package/dist/components/agents-sdk/ThinkExecutionDetail.d.ts +1 -1
- package/dist/components/agents-sdk/ThinkExecutionDetail.js +45 -43
- package/dist/components/agents-sdk/ThinkExecutionRun.d.ts +2 -2
- package/dist/components/agents-sdk/ThinkExecutionRun.js +5 -6
- package/dist/components/agents-sdk/ThinkExecutionStatus.d.ts +1 -1
- package/dist/components/agents-sdk/ThinkExecutionStatus.js +8 -12
- package/dist/components/agents-sdk/ThinkExecutionWorkbench.d.ts +8 -1
- package/dist/components/agents-sdk/ThinkExecutionWorkbench.js +43 -37
- package/dist/components/agents-sdk/ThinkFullApp.d.ts +42 -78
- package/dist/components/agents-sdk/ThinkFullApp.js +121 -202
- package/dist/components/agents-sdk/ThinkFullAppViewSwitch.d.ts +1 -1
- package/dist/components/agents-sdk/ThinkRoutine.d.ts +1 -1
- package/dist/components/agents-sdk/ThinkRoutineBrowser.js +1 -1
- package/dist/components/agents-sdk/ThinkRoutineDetail.js +4 -15
- package/dist/components/agents-sdk/ThinkRoutineForm.js +1 -1
- package/dist/components/agents-sdk/ThinkRoutineLibrary.d.ts +7 -6
- package/dist/components/agents-sdk/ThinkRoutineLibrary.js +112 -140
- package/dist/components/agents-sdk/ThinkRoutineRuns.d.ts +1 -1
- package/dist/components/agents-sdk/ThinkRoutineRuns.js +3 -10
- package/dist/components/agents-sdk/ThinkThreadPicker.js +2 -1
- package/dist/components/agents-sdk/WorkspaceBrowser.js +1 -1
- package/dist/components/agents-sdk/WorkspaceExplorer.js +2 -1
- package/dist/components/agents-sdk/WorkspaceFileView.js +1 -1
- package/dist/components/agents-sdk/WorkspaceHeader.js +2 -1
- package/dist/components/agents-sdk/WorkspaceMessageResponse.d.ts +1 -1
- package/dist/components/agents-sdk/WorkspaceMountManager.js +11 -11
- package/dist/components/ai-sdk/Activity.js +1 -1
- package/dist/components/ai-sdk/AgentAttention.d.ts +1 -1
- package/dist/components/ai-sdk/AgentChatStartScreen.js +1 -1
- package/dist/components/ai-sdk/Approval.js +1 -1
- package/dist/components/ai-sdk/Artifact.js +1 -1
- package/dist/components/ai-sdk/ChainOfThought.d.ts +1 -1
- package/dist/components/ai-sdk/ChainOfThought.js +1 -1
- package/dist/components/ai-sdk/Checkpoint.js +1 -1
- package/dist/components/ai-sdk/CodeBlock.js +1 -1
- package/dist/components/ai-sdk/Conversation.js +1 -1
- package/dist/components/ai-sdk/Goal.js +1 -1
- package/dist/components/ai-sdk/MediaPreviewCard.js +1 -1
- package/dist/components/ai-sdk/Message.d.ts +2 -2
- package/dist/components/ai-sdk/Message.js +25 -3
- package/dist/components/ai-sdk/MessageScroller.js +3 -2
- package/dist/components/ai-sdk/MessageScrollerVirtual.js +2 -1
- package/dist/components/ai-sdk/Plan.js +1 -1
- package/dist/components/ai-sdk/PromptInput.js +21 -15
- package/dist/components/ai-sdk/Queue.d.ts +4 -4
- package/dist/components/ai-sdk/Queue.js +6 -15
- package/dist/components/ai-sdk/Reasoning.js +1 -1
- package/dist/components/ai-sdk/Sources.js +1 -1
- package/dist/components/ai-sdk/Task.d.ts +2 -2
- package/dist/components/ai-sdk/Task.js +2 -2
- package/dist/components/extension/ChatGptSignInScreen.js +2 -1
- package/dist/components/extension/CodexModelSelector.js +1 -1
- package/dist/components/extension/ConversationTabPicker.js +1 -1
- package/dist/components/foundations/Avatar.d.ts +1 -10
- package/dist/components/foundations/Avatar.js +1 -10
- package/dist/components/foundations/Checkbox.js +1 -1
- package/dist/components/foundations/CheckboxGroup.js +1 -0
- package/dist/components/foundations/ContextMenu.js +1 -1
- package/dist/components/foundations/LinkButton.d.ts +12 -10
- package/dist/components/foundations/LinkButton.js +15 -11
- package/dist/components/foundations/Menubar.js +1 -1
- package/dist/components/foundations/SearchField.js +1 -1
- package/dist/components/foundations/Select.js +1 -1
- package/dist/components/foundations/Stepper.js +1 -1
- package/dist/components/foundations/Toast.js +1 -1
- package/dist/components/foundations/ToggleGroup.d.ts +79 -1
- package/dist/components/foundations/icons.d.ts +2 -2
- package/dist/components/foundations/icons.js +2 -2
- package/dist/components/general-purpose/AppFrame.js +1 -0
- package/dist/components/general-purpose/AppTopBar.d.ts +6 -0
- package/dist/components/general-purpose/AppTopBar.js +2 -1
- package/dist/components/general-purpose/Commit.d.ts +2 -2
- package/dist/components/general-purpose/Commit.js +5 -13
- package/dist/components/general-purpose/EnvironmentVariables.d.ts +2 -2
- package/dist/components/general-purpose/EnvironmentVariables.js +4 -7
- package/dist/components/general-purpose/FileTree.js +1 -1
- package/dist/components/general-purpose/PricingBillingToggle.js +4 -9
- package/dist/components/general-purpose/PricingPlanCard.js +15 -14
- package/dist/components/general-purpose/ResizableSidePanel.d.ts +8 -0
- package/dist/components/general-purpose/ResizableSidePanel.js +3 -2
- package/dist/components/general-purpose/ResponsiveSidebarShell.d.ts +105 -2
- package/dist/components/general-purpose/ResponsiveSidebarShell.js +112 -56
- package/dist/components/general-purpose/SetupChecklist.js +1 -1
- package/dist/components/general-purpose/Terminal.d.ts +1 -1
- package/dist/components/general-purpose/Terminal.js +4 -12
- package/dist/components/general-purpose/TestResults.d.ts +1 -1
- package/dist/components/general-purpose/TestResults.js +8 -21
- package/dist/components/general-purpose/ThemeModeControl.js +1 -1
- package/dist/components/general-purpose/WebPreview.d.ts +4 -1
- package/dist/components/general-purpose/WebPreview.js +6 -14
- package/dist/components/nanites/AgentConnection.js +2 -2
- package/dist/components/nanites/AgentToolDetail.d.ts +1 -1
- package/dist/components/nanites/AgentToolDetail.js +6 -5
- package/dist/components/nanites/NaniteScene.js +11 -11
- package/dist/{copy-button-Bc7jsYv_.js → copy-button-lys9N_aI.js} +1 -1
- package/dist/{icons-DwgNir1Q.d.ts → icons-0corjfxR.d.ts} +1 -16
- package/dist/{icons-MmIXciMO.js → icons-CVFSeTJn.js} +2 -5
- package/dist/styles/accordion.css +1 -0
- package/dist/styles/action-guide.css +8 -7
- package/dist/styles/activity-header.css +13 -39
- package/dist/styles/activity.css +40 -55
- package/dist/styles/agent-attention.css +19 -19
- package/dist/styles/agent-chat.css +94 -42
- package/dist/styles/agent-connection.css +10 -4
- package/dist/styles/agent-tool-detail.css +5 -15
- package/dist/styles/alert-dialog.css +4 -4
- package/dist/styles/app-frame.css +1 -3
- package/dist/styles/app-icon.css +12 -18
- package/dist/styles/app-top-bar.css +31 -9
- package/dist/styles/approval.css +1 -0
- package/dist/styles/artifact.css +6 -6
- package/dist/styles/attachment-preview.css +5 -4
- package/dist/styles/avatar.css +6 -22
- package/dist/styles/base.css +2 -8
- package/dist/styles/browser-live-screen.css +38 -0
- package/dist/styles/browser-live-view.css +12 -4
- package/dist/styles/browser-replay.css +6 -6
- package/dist/styles/browser-run-panel.css +21 -18
- package/dist/styles/button.css +15 -6
- package/dist/styles/card.css +5 -5
- package/dist/styles/chatgpt-sign-in-screen.css +6 -6
- package/dist/styles/code-block.css +14 -13
- package/dist/styles/codex-model-selector.css +2 -0
- package/dist/styles/collapsible.css +1 -0
- package/dist/styles/commit.css +30 -7
- package/dist/styles/context.css +9 -9
- package/dist/styles/conversation-tab-picker.css +1 -1
- package/dist/styles/conversation.css +6 -8
- package/dist/styles/dialog.css +4 -4
- package/dist/styles/empty-state.css +3 -3
- package/dist/styles/environment-variables.css +12 -9
- package/dist/styles/field.css +2 -1
- package/dist/styles/fieldset.css +2 -2
- package/dist/styles/index.css +8 -7
- package/dist/styles/manager-office.css +480 -0
- package/dist/styles/mcp-plugin-catalog.css +44 -39
- package/dist/styles/mcp-server-picker.css +4 -4
- package/dist/styles/message-scroller.css +9 -11
- package/dist/styles/message.css +74 -28
- package/dist/styles/nanite-scene.css +9 -9
- package/dist/styles/navigation-menu.css +1 -0
- package/dist/styles/plan.css +13 -12
- package/dist/styles/pricing-page.css +37 -30
- package/dist/styles/prompt-input.css +26 -18
- package/dist/styles/queue.css +1 -0
- package/dist/styles/reasoning.css +1 -9
- package/dist/styles/recipes.css +29 -58
- package/dist/styles/responsive-sidebar-shell.css +107 -29
- package/dist/styles/separator.css +5 -5
- package/dist/styles/sources.css +4 -4
- package/dist/styles/stepper.css +1 -0
- package/dist/styles/streamdown.css +31 -21
- package/dist/styles/subagent-run.css +20 -3
- package/dist/styles/tabs.css +1 -0
- package/dist/styles/task.css +5 -17
- package/dist/styles/terminal.css +29 -10
- package/dist/styles/test-results.css +16 -7
- package/dist/styles/think-execution-status.css +10 -26
- package/dist/styles/think-execution-workbench.css +98 -108
- package/dist/styles/think-full-app.css +75 -225
- package/dist/styles/think-routine-library.css +26 -95
- package/dist/styles/think-thread-picker.css +17 -12
- package/dist/styles/transition-surface.css +7 -8
- package/dist/styles/utilities.css +75 -0
- package/dist/styles/web-preview.css +46 -22
- package/dist/styles/workspace-explorer.css +22 -44
- package/dist/styles/workspace-mount-manager.css +24 -2
- package/dist/utils/favicon.d.ts +6 -1
- package/dist/utils/favicon.js +18 -1
- package/package.json +37 -35
- package/dist/ResponsiveSidebarShell-DWjULskY.d.ts +0 -68
- package/dist/ToggleGroup-_pQMyHGM.d.ts +0 -80
- package/dist/components/agents-sdk/AgentActivityPreview.d.ts +0 -46
- package/dist/components/agents-sdk/AgentActivityPreview.js +0 -93
- package/dist/components/agents-sdk/ThinkThreadShell.d.ts +0 -38
- package/dist/components/agents-sdk/ThinkThreadShell.js +0 -27
- package/dist/components/foundations/Badge.d.ts +0 -62
- package/dist/components/foundations/Badge.js +0 -55
- package/dist/components/foundations/StatusPill.d.ts +0 -43
- package/dist/components/foundations/StatusPill.js +0 -35
- package/dist/components/general-purpose/Shell.d.ts +0 -149
- package/dist/components/general-purpose/Shell.js +0 -116
- package/dist/styles/agent-activity-preview-overlay.css +0 -169
- package/dist/styles/agent-activity-preview.css +0 -209
- package/dist/styles/badge.css +0 -120
- package/dist/styles/shell.css +0 -122
- package/dist/styles/status-pill.css +0 -39
|
@@ -0,0 +1,698 @@
|
|
|
1
|
+
import { t as cx } from "../../class-names-BiMDVpUo.js";
|
|
2
|
+
import { Collapsible } from "../foundations/Collapsible.js";
|
|
3
|
+
import { $ as WarningIcon, A as MessageSquareIcon, B as PlusIcon, C as FolderIcon, D as LinkIcon, H as RefreshIcon, K as SpinnerIcon, L as PauseIcon, N as MonitorIcon, R as PencilIcon, T as InfoIcon, _ as DotIcon, a as ArrowUpIcon, d as CheckIcon, f as ChevronDownIcon, n as ArrowDownIcon, p as ChevronRightIcon, tt as XIcon, u as CalendarIcon } from "../../icons-CVFSeTJn.js";
|
|
4
|
+
import { Button } from "../foundations/Button.js";
|
|
5
|
+
import { AgentAttention, AgentAttentionActions, AgentAttentionBody, AgentAttentionHeader } from "../ai-sdk/AgentAttention.js";
|
|
6
|
+
import { Tooltip } from "../foundations/Tooltip.js";
|
|
7
|
+
import { Avatar } from "../foundations/Avatar.js";
|
|
8
|
+
import { AppIcon } from "../foundations/AppIcon.js";
|
|
9
|
+
import { EmptyState } from "../foundations/EmptyState.js";
|
|
10
|
+
import { LinkButton } from "../foundations/LinkButton.js";
|
|
11
|
+
import "../foundations/icons.js";
|
|
12
|
+
import { AppTopBar } from "../general-purpose/AppTopBar.js";
|
|
13
|
+
import { ResponsiveSidebarShell } from "../general-purpose/ResponsiveSidebarShell.js";
|
|
14
|
+
import * as React from "react";
|
|
15
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
16
|
+
//#region src/components/_internal/chrome-profile-colors.ts
|
|
17
|
+
const PALETTE = [
|
|
18
|
+
{
|
|
19
|
+
bg: "#ffab40",
|
|
20
|
+
fg: "#1f1f1f"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
bg: "#43a047",
|
|
24
|
+
fg: "#ffffff"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
bg: "#199da9",
|
|
28
|
+
fg: "#ffffff"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
bg: "#5d93e4",
|
|
32
|
+
fg: "#ffffff"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
bg: "#ffaebd",
|
|
36
|
+
fg: "#1f1f1f"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
bg: "#bd165c",
|
|
40
|
+
fg: "#ffffff"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
bg: "#b71c1c",
|
|
44
|
+
fg: "#ffffff"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
bg: "#2e7d32",
|
|
48
|
+
fg: "#ffffff"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
bg: "#006e78",
|
|
52
|
+
fg: "#ffffff"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
bg: "#1565c0",
|
|
56
|
+
fg: "#ffffff"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
bg: "#5b3689",
|
|
60
|
+
fg: "#ffffff"
|
|
61
|
+
}
|
|
62
|
+
];
|
|
63
|
+
/** FNV-1a, for a stable pick from the same seat across reloads. */
|
|
64
|
+
function hash(seed) {
|
|
65
|
+
let value = 2166136261;
|
|
66
|
+
for (let index = 0; index < seed.length; index++) {
|
|
67
|
+
value ^= seed.charCodeAt(index);
|
|
68
|
+
value = Math.imul(value, 16777619);
|
|
69
|
+
}
|
|
70
|
+
return value >>> 0;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Deterministic Chrome-style profile color for one identity. Pass the set of
|
|
74
|
+
* `bg` values already assigned to the rest of the roster so two profiles only
|
|
75
|
+
* share a color once the palette is exhausted, exactly as Chrome avoids
|
|
76
|
+
* colors in use by other profiles.
|
|
77
|
+
*/
|
|
78
|
+
function chromeProfileColor(seed, taken) {
|
|
79
|
+
const start = hash(seed) % PALETTE.length;
|
|
80
|
+
for (let offset = 0; offset < PALETTE.length; offset++) {
|
|
81
|
+
const candidate = PALETTE[(start + offset) % PALETTE.length];
|
|
82
|
+
if (!taken?.has(candidate.bg)) return candidate;
|
|
83
|
+
}
|
|
84
|
+
return PALETTE[start];
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region src/components/agents-sdk/ManagerOffice.tsx
|
|
88
|
+
const statusLabels = {
|
|
89
|
+
"needs-you": "Needs you",
|
|
90
|
+
working: "Working",
|
|
91
|
+
idle: "Idle",
|
|
92
|
+
issue: "Issue",
|
|
93
|
+
offline: "Offline",
|
|
94
|
+
connecting: "Connecting…",
|
|
95
|
+
unavailable: "Unavailable"
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Named positively, so a status added to the union later is disconnected until
|
|
99
|
+
* someone says otherwise. The negative form — "not offline, connecting, or
|
|
100
|
+
* unavailable" — silently admits every new status, and the first thing this
|
|
101
|
+
* component does with a connected employee is read `handoffs`, which a
|
|
102
|
+
* disconnected one does not carry.
|
|
103
|
+
*/
|
|
104
|
+
const CONNECTED_STATUSES = {
|
|
105
|
+
"needs-you": true,
|
|
106
|
+
working: true,
|
|
107
|
+
idle: true,
|
|
108
|
+
issue: true
|
|
109
|
+
};
|
|
110
|
+
function isConnected(employee) {
|
|
111
|
+
return employee.status in CONNECTED_STATUSES;
|
|
112
|
+
}
|
|
113
|
+
function employeeAttentionCount(employee) {
|
|
114
|
+
return isConnected(employee) ? employee.handoffs.length : 0;
|
|
115
|
+
}
|
|
116
|
+
/** The roster spells out what its handoff count measures. */
|
|
117
|
+
function employeeStatusText(employee) {
|
|
118
|
+
const count = employeeAttentionCount(employee);
|
|
119
|
+
const label = statusLabels[employee.status];
|
|
120
|
+
return count ? `${label} · ${count} handoff${count === 1 ? "" : "s"}` : label;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Each employee is a Chrome profile, so the bubble wears its profile color —
|
|
124
|
+
* the same palette Chrome assigns profiles from. Chrome's pick is per-machine
|
|
125
|
+
* state the host can't read, so the roster re-derives it: a stable hash per
|
|
126
|
+
* seat, skipping colors already worn by earlier roster entries the way Chrome
|
|
127
|
+
* skips colors in use by other profiles.
|
|
128
|
+
*/
|
|
129
|
+
function rosterProfileColors(employees) {
|
|
130
|
+
const taken = /* @__PURE__ */ new Set();
|
|
131
|
+
const colors = /* @__PURE__ */ new Map();
|
|
132
|
+
for (const employee of employees) {
|
|
133
|
+
const color = chromeProfileColor(employee.id, taken);
|
|
134
|
+
taken.add(color.bg);
|
|
135
|
+
colors.set(employee.id, color);
|
|
136
|
+
}
|
|
137
|
+
return colors;
|
|
138
|
+
}
|
|
139
|
+
function EmployeeAvatar({ color, employee, size = "sm" }) {
|
|
140
|
+
return /* @__PURE__ */ jsx(Avatar.Root, {
|
|
141
|
+
size,
|
|
142
|
+
shape: "rounded",
|
|
143
|
+
"aria-hidden": "true",
|
|
144
|
+
children: /* @__PURE__ */ jsx(Avatar.Fallback, {
|
|
145
|
+
style: {
|
|
146
|
+
color: color.fg,
|
|
147
|
+
backgroundColor: color.bg
|
|
148
|
+
},
|
|
149
|
+
children: employee.initials
|
|
150
|
+
})
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* One glyph per meaning, not one glyph per colour. Colour alone cannot carry
|
|
155
|
+
* these apart: `forced-colors` flattens the palette, and a red/amber pair is
|
|
156
|
+
* the most common colour-vision confusion there is. So an employee asking for
|
|
157
|
+
* a person (`needs-you`), one that has failed (`issue`), and one that cannot be
|
|
158
|
+
* reached at all (`unavailable`) each get a different shape.
|
|
159
|
+
*
|
|
160
|
+
* `working` and `connecting` deliberately share the spinner: both mean "in
|
|
161
|
+
* motion, wait", and mistaking one for the other costs the manager nothing.
|
|
162
|
+
*/
|
|
163
|
+
function statusIcon(status) {
|
|
164
|
+
if (status === "needs-you") return /* @__PURE__ */ jsx(InfoIcon, {});
|
|
165
|
+
if (status === "issue") return /* @__PURE__ */ jsx(WarningIcon, {});
|
|
166
|
+
if (status === "unavailable") return /* @__PURE__ */ jsx(XIcon, {});
|
|
167
|
+
if (status === "working" || status === "connecting") return /* @__PURE__ */ jsx(SpinnerIcon, {});
|
|
168
|
+
if (status === "offline") return /* @__PURE__ */ jsx(MonitorIcon, {});
|
|
169
|
+
return /* @__PURE__ */ jsx(PauseIcon, {});
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* The glyph makes the state scannable and the unframed word keeps it readable
|
|
173
|
+
* without hover. The employee header already provides the visual grouping.
|
|
174
|
+
*/
|
|
175
|
+
function EmployeeStatus({ employee }) {
|
|
176
|
+
const count = employeeAttentionCount(employee);
|
|
177
|
+
const label = count ? `${statusLabels[employee.status]} · ${count}` : statusLabels[employee.status];
|
|
178
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
179
|
+
className: "manager-office__status",
|
|
180
|
+
"data-status": employee.status,
|
|
181
|
+
"aria-label": label,
|
|
182
|
+
children: [statusIcon(employee.status), /* @__PURE__ */ jsx("span", { children: label })]
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
function ThreadStatusIcon({ status }) {
|
|
186
|
+
return /* @__PURE__ */ jsx("span", {
|
|
187
|
+
className: "manager-office__thread-status",
|
|
188
|
+
"data-status": status,
|
|
189
|
+
"aria-hidden": "true",
|
|
190
|
+
children: status === "running" ? /* @__PURE__ */ jsx(SpinnerIcon, {}) : status === "error" ? /* @__PURE__ */ jsx(WarningIcon, {}) : status === "interrupted" ? /* @__PURE__ */ jsx(PauseIcon, {}) : /* @__PURE__ */ jsx(DotIcon, {})
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
function threadStatusLabel(status) {
|
|
194
|
+
if (status === "attention") return "Update ready";
|
|
195
|
+
if (status === "running") return "Working";
|
|
196
|
+
if (status === "error") return "Issue";
|
|
197
|
+
if (status === "interrupted") return "Stopped";
|
|
198
|
+
return "Updated";
|
|
199
|
+
}
|
|
200
|
+
function relativeTime(timestamp, now) {
|
|
201
|
+
const elapsed = Math.max(0, now - timestamp);
|
|
202
|
+
const minute = 6e4;
|
|
203
|
+
const hour = 60 * minute;
|
|
204
|
+
const day = 24 * hour;
|
|
205
|
+
if (elapsed < minute) return "now";
|
|
206
|
+
if (elapsed < hour) return `${Math.floor(elapsed / minute)}m`;
|
|
207
|
+
if (elapsed < day) return `${Math.floor(elapsed / hour)}h`;
|
|
208
|
+
return `${Math.floor(elapsed / day)}d`;
|
|
209
|
+
}
|
|
210
|
+
function Timestamp({ now, timestamp }) {
|
|
211
|
+
const date = new Date(timestamp);
|
|
212
|
+
return /* @__PURE__ */ jsx("time", {
|
|
213
|
+
dateTime: date.toISOString(),
|
|
214
|
+
title: date.toLocaleString(),
|
|
215
|
+
children: relativeTime(timestamp, now)
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
function RoutineEvidence({ employee }) {
|
|
219
|
+
const { completed, finished } = employee.routines.reduce((total, routine) => ({
|
|
220
|
+
completed: total.completed + routine.completedRuns,
|
|
221
|
+
finished: total.finished + routine.finishedRuns
|
|
222
|
+
}), {
|
|
223
|
+
completed: 0,
|
|
224
|
+
finished: 0
|
|
225
|
+
});
|
|
226
|
+
const label = finished === 0 ? "No runs yet" : `${completed}/${finished} runs`;
|
|
227
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
228
|
+
className: "manager-office__evidence",
|
|
229
|
+
"data-complete": finished > 0 && completed === finished ? "" : void 0,
|
|
230
|
+
children: [finished === 0 ? /* @__PURE__ */ jsx(CalendarIcon, {}) : /* @__PURE__ */ jsx(CheckIcon, {}), /* @__PURE__ */ jsx("span", { children: label })]
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
const channelDirectionLabels = {
|
|
234
|
+
input: "In",
|
|
235
|
+
output: "Out",
|
|
236
|
+
both: "In · Out"
|
|
237
|
+
};
|
|
238
|
+
function channelDirectionIcon(direction) {
|
|
239
|
+
if (direction === "input") return /* @__PURE__ */ jsx(ArrowDownIcon, {});
|
|
240
|
+
if (direction === "output") return /* @__PURE__ */ jsx(ArrowUpIcon, {});
|
|
241
|
+
return /* @__PURE__ */ jsx(RefreshIcon, {});
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Deliberately the same three glyphs the employee statuses use: a channel that
|
|
245
|
+
* needs a sign-in is the same kind of event as an employee that needs one, and
|
|
246
|
+
* a manager should not have to learn a second vocabulary for it.
|
|
247
|
+
*/
|
|
248
|
+
function channelStatusIcon(status) {
|
|
249
|
+
if (status === "connected") return /* @__PURE__ */ jsx(CheckIcon, {});
|
|
250
|
+
if (status === "needs-auth") return /* @__PURE__ */ jsx(InfoIcon, {});
|
|
251
|
+
return /* @__PURE__ */ jsx(WarningIcon, {});
|
|
252
|
+
}
|
|
253
|
+
const channelStatusLabels = {
|
|
254
|
+
connected: "Connected",
|
|
255
|
+
"needs-auth": "Needs sign-in",
|
|
256
|
+
error: "Error"
|
|
257
|
+
};
|
|
258
|
+
function ChannelRow({ channel }) {
|
|
259
|
+
return /* @__PURE__ */ jsxs("li", {
|
|
260
|
+
className: "manager-office__channel",
|
|
261
|
+
"data-status": channel.status,
|
|
262
|
+
children: [
|
|
263
|
+
/* @__PURE__ */ jsx(AppIcon.Root, {
|
|
264
|
+
size: "sm",
|
|
265
|
+
"aria-hidden": "true",
|
|
266
|
+
children: channel.icon ? /* @__PURE__ */ jsx("span", {
|
|
267
|
+
className: "manager-office__channel-mark",
|
|
268
|
+
children: channel.icon
|
|
269
|
+
}) : /* @__PURE__ */ jsx(AppIcon.Fallback, { children: channel.name.slice(0, 1) })
|
|
270
|
+
}),
|
|
271
|
+
/* @__PURE__ */ jsxs("span", {
|
|
272
|
+
className: "manager-office__identity",
|
|
273
|
+
children: [/* @__PURE__ */ jsx("strong", {
|
|
274
|
+
className: "sigvelo-truncate",
|
|
275
|
+
children: channel.name
|
|
276
|
+
}), /* @__PURE__ */ jsx("small", {
|
|
277
|
+
className: "sigvelo-truncate",
|
|
278
|
+
children: channel.detail ?? channelStatusLabels[channel.status]
|
|
279
|
+
})]
|
|
280
|
+
}),
|
|
281
|
+
/* @__PURE__ */ jsx("span", {
|
|
282
|
+
className: "manager-office__channel-direction",
|
|
283
|
+
"aria-label": `Direction: ${channelDirectionLabels[channel.direction]}`,
|
|
284
|
+
role: "img",
|
|
285
|
+
title: channelDirectionLabels[channel.direction],
|
|
286
|
+
children: channelDirectionIcon(channel.direction)
|
|
287
|
+
}),
|
|
288
|
+
/* @__PURE__ */ jsxs("span", {
|
|
289
|
+
className: "manager-office__channel-status",
|
|
290
|
+
"data-status": channel.status,
|
|
291
|
+
title: channelStatusLabels[channel.status],
|
|
292
|
+
children: [channelStatusIcon(channel.status), /* @__PURE__ */ jsx("span", {
|
|
293
|
+
className: "sigvelo-visually-hidden",
|
|
294
|
+
children: channelStatusLabels[channel.status]
|
|
295
|
+
})]
|
|
296
|
+
})
|
|
297
|
+
]
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* A handoff is the one thing on this surface that is waiting on a person, so
|
|
302
|
+
* it gets the surface built for that — `AgentAttention` in its warning tone —
|
|
303
|
+
* rather than another ghost row indistinguishable from the work beneath it.
|
|
304
|
+
* The action is a link into the owning work, because that is where the single
|
|
305
|
+
* approval surface lives; nothing is approved or dismissed from the roster.
|
|
306
|
+
*/
|
|
307
|
+
function HandoffCard({ employee, handoff, renderLink, now, showEmployee }) {
|
|
308
|
+
return /* @__PURE__ */ jsxs(AgentAttention, {
|
|
309
|
+
tone: "attention",
|
|
310
|
+
className: cx("manager-office__handoff", !handoff.request && "manager-office__handoff--bare"),
|
|
311
|
+
children: [
|
|
312
|
+
/* @__PURE__ */ jsx(AgentAttentionHeader, {
|
|
313
|
+
icon: /* @__PURE__ */ jsx(InfoIcon, {}),
|
|
314
|
+
title: handoff.reason,
|
|
315
|
+
description: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
316
|
+
showEmployee ? `${employee.name} · ` : null,
|
|
317
|
+
handoff.workTitle,
|
|
318
|
+
" · ",
|
|
319
|
+
/* @__PURE__ */ jsx(Timestamp, {
|
|
320
|
+
timestamp: handoff.createdAt,
|
|
321
|
+
now
|
|
322
|
+
})
|
|
323
|
+
] })
|
|
324
|
+
}),
|
|
325
|
+
handoff.request ? /* @__PURE__ */ jsx(AgentAttentionBody, {
|
|
326
|
+
className: "manager-office__handoff-ask",
|
|
327
|
+
children: handoff.request
|
|
328
|
+
}) : null,
|
|
329
|
+
/* @__PURE__ */ jsx(AgentAttentionActions, { children: /* @__PURE__ */ jsxs(LinkButton, {
|
|
330
|
+
render: renderLink({
|
|
331
|
+
kind: "handoff",
|
|
332
|
+
employee,
|
|
333
|
+
handoff
|
|
334
|
+
}),
|
|
335
|
+
size: "sm",
|
|
336
|
+
"aria-label": `Open ${handoff.workTitle} to ${handoff.reason.toLowerCase()}`,
|
|
337
|
+
children: [/* @__PURE__ */ jsx(MonitorIcon, {}), "Open browser"]
|
|
338
|
+
}) })
|
|
339
|
+
]
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
function EmployeeSidebar({ closeSidebarOnCompact, employees, renderLink, officeActions, profileColors, view }) {
|
|
343
|
+
const rosterLabelId = React.useId();
|
|
344
|
+
const attentionCount = employees.reduce((total, employee) => total + employeeAttentionCount(employee), 0);
|
|
345
|
+
const selectedEmployeeId = view.kind === "employee" ? view.employeeId : null;
|
|
346
|
+
return /* @__PURE__ */ jsxs("nav", {
|
|
347
|
+
className: "manager-office__sidebar",
|
|
348
|
+
"aria-label": "Manager office",
|
|
349
|
+
children: [
|
|
350
|
+
/* @__PURE__ */ jsxs("div", {
|
|
351
|
+
className: "manager-office__sidebar-heading",
|
|
352
|
+
children: [/* @__PURE__ */ jsx("strong", { children: "Office" }), /* @__PURE__ */ jsx("span", {
|
|
353
|
+
className: "manager-office__sidebar-actions",
|
|
354
|
+
children: officeActions
|
|
355
|
+
})]
|
|
356
|
+
}),
|
|
357
|
+
/* @__PURE__ */ jsxs(LinkButton, {
|
|
358
|
+
render: renderLink({ kind: "attention" }),
|
|
359
|
+
onClick: closeSidebarOnCompact,
|
|
360
|
+
variant: "ghost",
|
|
361
|
+
color: "neutral",
|
|
362
|
+
size: "sm",
|
|
363
|
+
className: "manager-office__attention-nav",
|
|
364
|
+
"aria-current": view.kind === "attention" ? "page" : void 0,
|
|
365
|
+
children: [/* @__PURE__ */ jsx(WarningIcon, {}), /* @__PURE__ */ jsx("span", { children: attentionCount ? `Needs you (${attentionCount})` : "Needs you" })]
|
|
366
|
+
}),
|
|
367
|
+
/* @__PURE__ */ jsx("p", {
|
|
368
|
+
className: "manager-office__nav-label",
|
|
369
|
+
id: rosterLabelId,
|
|
370
|
+
children: "Employees"
|
|
371
|
+
}),
|
|
372
|
+
/* @__PURE__ */ jsx("ul", {
|
|
373
|
+
className: "manager-office__employee-nav sigvelo-stack-list",
|
|
374
|
+
"aria-labelledby": rosterLabelId,
|
|
375
|
+
children: employees.map((employee) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(LinkButton, {
|
|
376
|
+
render: renderLink({
|
|
377
|
+
kind: "employee",
|
|
378
|
+
employee
|
|
379
|
+
}),
|
|
380
|
+
onClick: closeSidebarOnCompact,
|
|
381
|
+
variant: "ghost",
|
|
382
|
+
color: "neutral",
|
|
383
|
+
size: "sm",
|
|
384
|
+
className: "manager-office__employee-link",
|
|
385
|
+
"aria-current": selectedEmployeeId === employee.id ? "page" : void 0,
|
|
386
|
+
"aria-label": `Open ${employee.name} · ${employeeStatusText(employee)}`,
|
|
387
|
+
children: [
|
|
388
|
+
/* @__PURE__ */ jsx(EmployeeAvatar, {
|
|
389
|
+
employee,
|
|
390
|
+
color: profileColors.get(employee.id)
|
|
391
|
+
}),
|
|
392
|
+
/* @__PURE__ */ jsxs("span", {
|
|
393
|
+
className: "manager-office__identity",
|
|
394
|
+
children: [/* @__PURE__ */ jsx("strong", {
|
|
395
|
+
className: "sigvelo-truncate",
|
|
396
|
+
children: employee.name
|
|
397
|
+
}), /* @__PURE__ */ jsx("small", {
|
|
398
|
+
className: "manager-office__nav-state sigvelo-truncate",
|
|
399
|
+
children: employeeStatusText(employee)
|
|
400
|
+
})]
|
|
401
|
+
}),
|
|
402
|
+
/* @__PURE__ */ jsx("span", {
|
|
403
|
+
className: "manager-office__nav-status",
|
|
404
|
+
"data-status": employee.status,
|
|
405
|
+
children: statusIcon(employee.status)
|
|
406
|
+
})
|
|
407
|
+
]
|
|
408
|
+
}) }, employee.id))
|
|
409
|
+
})
|
|
410
|
+
]
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
function AttentionView({ employees, renderLink, now }) {
|
|
414
|
+
const rows = employees.flatMap((employee) => isConnected(employee) ? employee.handoffs.map((handoff) => ({
|
|
415
|
+
employee,
|
|
416
|
+
handoff
|
|
417
|
+
})) : []);
|
|
418
|
+
if (!rows.length) return /* @__PURE__ */ jsx("section", {
|
|
419
|
+
className: "manager-office__attention",
|
|
420
|
+
"data-recipe": "page",
|
|
421
|
+
"aria-label": "Needs you",
|
|
422
|
+
children: /* @__PURE__ */ jsx(EmptyState, {
|
|
423
|
+
icon: /* @__PURE__ */ jsx(CheckIcon, {}),
|
|
424
|
+
title: "No active handoffs",
|
|
425
|
+
description: "Employee connection state remains visible in the roster."
|
|
426
|
+
})
|
|
427
|
+
});
|
|
428
|
+
return /* @__PURE__ */ jsx("section", {
|
|
429
|
+
className: "manager-office__attention",
|
|
430
|
+
"data-recipe": "page",
|
|
431
|
+
"aria-label": "Needs you",
|
|
432
|
+
children: /* @__PURE__ */ jsx("ul", {
|
|
433
|
+
className: "manager-office__attention-list sigvelo-stack-list",
|
|
434
|
+
children: rows.map(({ employee, handoff }) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(HandoffCard, {
|
|
435
|
+
employee,
|
|
436
|
+
handoff,
|
|
437
|
+
renderLink,
|
|
438
|
+
now,
|
|
439
|
+
showEmployee: true
|
|
440
|
+
}) }, `${employee.id}:${handoff.id}`))
|
|
441
|
+
})
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
function EmployeeDetail({ employee, renderLink, now, profileColor }) {
|
|
445
|
+
if (!isConnected(employee)) return /* @__PURE__ */ jsx("div", {
|
|
446
|
+
"data-recipe": "page",
|
|
447
|
+
children: /* @__PURE__ */ jsx(EmptyState, {
|
|
448
|
+
icon: employee.status === "connecting" ? /* @__PURE__ */ jsx(SpinnerIcon, {}) : /* @__PURE__ */ jsx(MonitorIcon, {}),
|
|
449
|
+
title: `${employee.name} is ${statusLabels[employee.status].toLowerCase()}`,
|
|
450
|
+
description: employee.statusDescription
|
|
451
|
+
})
|
|
452
|
+
});
|
|
453
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
454
|
+
className: "manager-office__employee-detail",
|
|
455
|
+
"data-recipe": "page",
|
|
456
|
+
children: [
|
|
457
|
+
/* @__PURE__ */ jsxs("header", {
|
|
458
|
+
className: "manager-office__employee-header",
|
|
459
|
+
children: [
|
|
460
|
+
/* @__PURE__ */ jsx(EmployeeAvatar, {
|
|
461
|
+
employee,
|
|
462
|
+
color: profileColor,
|
|
463
|
+
size: "lg"
|
|
464
|
+
}),
|
|
465
|
+
/* @__PURE__ */ jsxs("span", {
|
|
466
|
+
className: "manager-office__identity",
|
|
467
|
+
children: [/* @__PURE__ */ jsx("strong", {
|
|
468
|
+
className: "sigvelo-truncate",
|
|
469
|
+
children: employee.name
|
|
470
|
+
}), /* @__PURE__ */ jsxs("small", {
|
|
471
|
+
className: "manager-office__role sigvelo-truncate",
|
|
472
|
+
children: [
|
|
473
|
+
employee.email,
|
|
474
|
+
" · ",
|
|
475
|
+
employee.role
|
|
476
|
+
]
|
|
477
|
+
})]
|
|
478
|
+
}),
|
|
479
|
+
/* @__PURE__ */ jsx(RoutineEvidence, { employee }),
|
|
480
|
+
/* @__PURE__ */ jsx(EmployeeStatus, { employee })
|
|
481
|
+
]
|
|
482
|
+
}),
|
|
483
|
+
employee.handoffs.length ? /* @__PURE__ */ jsx("section", {
|
|
484
|
+
className: "manager-office__employee-handoffs",
|
|
485
|
+
"aria-label": "Needs you",
|
|
486
|
+
children: employee.handoffs.map((handoff) => /* @__PURE__ */ jsx(HandoffCard, {
|
|
487
|
+
employee,
|
|
488
|
+
handoff,
|
|
489
|
+
renderLink,
|
|
490
|
+
now,
|
|
491
|
+
showEmployee: false
|
|
492
|
+
}, handoff.id))
|
|
493
|
+
}) : null,
|
|
494
|
+
/* @__PURE__ */ jsxs("div", {
|
|
495
|
+
className: "manager-office__employee-columns",
|
|
496
|
+
children: [/* @__PURE__ */ jsxs("section", {
|
|
497
|
+
className: "manager-office__section",
|
|
498
|
+
children: [/* @__PURE__ */ jsx("header", {
|
|
499
|
+
className: "manager-office__section-header",
|
|
500
|
+
children: /* @__PURE__ */ jsxs("h2", {
|
|
501
|
+
className: "manager-office__section-title",
|
|
502
|
+
children: [/* @__PURE__ */ jsx(MessageSquareIcon, {}), "Work"]
|
|
503
|
+
})
|
|
504
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
505
|
+
className: "manager-office__section-content",
|
|
506
|
+
children: employee.work.length ? /* @__PURE__ */ jsx("ul", {
|
|
507
|
+
className: "manager-office__work-list sigvelo-stack-list",
|
|
508
|
+
children: employee.work.map((work) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(LinkButton, {
|
|
509
|
+
render: renderLink({
|
|
510
|
+
kind: "work",
|
|
511
|
+
employee,
|
|
512
|
+
work
|
|
513
|
+
}),
|
|
514
|
+
variant: "ghost",
|
|
515
|
+
color: "neutral",
|
|
516
|
+
size: "sm",
|
|
517
|
+
className: "manager-office__work-link",
|
|
518
|
+
children: [
|
|
519
|
+
/* @__PURE__ */ jsx(ThreadStatusIcon, { status: work.status }),
|
|
520
|
+
/* @__PURE__ */ jsxs("span", {
|
|
521
|
+
className: "manager-office__identity",
|
|
522
|
+
children: [/* @__PURE__ */ jsxs("strong", {
|
|
523
|
+
className: "sigvelo-truncate",
|
|
524
|
+
children: [work.title, work.status === "attention" ? /* @__PURE__ */ jsx("span", {
|
|
525
|
+
className: "manager-office__unread-dot",
|
|
526
|
+
"aria-hidden": "true"
|
|
527
|
+
}) : null]
|
|
528
|
+
}), /* @__PURE__ */ jsxs("small", {
|
|
529
|
+
className: "sigvelo-truncate",
|
|
530
|
+
children: [
|
|
531
|
+
threadStatusLabel(work.status),
|
|
532
|
+
" ·",
|
|
533
|
+
" ",
|
|
534
|
+
/* @__PURE__ */ jsx(Timestamp, {
|
|
535
|
+
timestamp: work.updatedAt,
|
|
536
|
+
now
|
|
537
|
+
})
|
|
538
|
+
]
|
|
539
|
+
})]
|
|
540
|
+
}),
|
|
541
|
+
/* @__PURE__ */ jsx(ChevronRightIcon, { className: "manager-office__row-chevron" })
|
|
542
|
+
]
|
|
543
|
+
}) }, work.id))
|
|
544
|
+
}) : /* @__PURE__ */ jsx(EmptyState, { description: "No work yet." })
|
|
545
|
+
})]
|
|
546
|
+
}), /* @__PURE__ */ jsxs("aside", {
|
|
547
|
+
className: "manager-office__employee-aside",
|
|
548
|
+
children: [/* @__PURE__ */ jsx("section", {
|
|
549
|
+
className: "manager-office__section",
|
|
550
|
+
"aria-label": "Routines",
|
|
551
|
+
children: /* @__PURE__ */ jsxs(Collapsible.Root, {
|
|
552
|
+
defaultOpen: true,
|
|
553
|
+
children: [/* @__PURE__ */ jsxs(Button, {
|
|
554
|
+
render: /* @__PURE__ */ jsx(Collapsible.Trigger, { unstyled: true }),
|
|
555
|
+
type: "button",
|
|
556
|
+
variant: "ghost",
|
|
557
|
+
color: "neutral",
|
|
558
|
+
size: "sm",
|
|
559
|
+
className: "manager-office__routine-trigger",
|
|
560
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
561
|
+
className: "manager-office__identity",
|
|
562
|
+
children: [/* @__PURE__ */ jsx(CalendarIcon, {}), /* @__PURE__ */ jsx("strong", { children: "Routines" })]
|
|
563
|
+
}), /* @__PURE__ */ jsx(ChevronDownIcon, { className: "sigvelo-disclosure-chevron" })]
|
|
564
|
+
}), /* @__PURE__ */ jsx(Collapsible.Panel, {
|
|
565
|
+
unstyled: true,
|
|
566
|
+
children: employee.routines.length ? /* @__PURE__ */ jsx("ul", {
|
|
567
|
+
className: "manager-office__routine-list sigvelo-stack-list",
|
|
568
|
+
children: employee.routines.map((routine) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(LinkButton, {
|
|
569
|
+
render: renderLink({
|
|
570
|
+
kind: "routine",
|
|
571
|
+
employee,
|
|
572
|
+
routine
|
|
573
|
+
}),
|
|
574
|
+
variant: "ghost",
|
|
575
|
+
color: "neutral",
|
|
576
|
+
size: "sm",
|
|
577
|
+
className: "manager-office__routine-link",
|
|
578
|
+
children: [
|
|
579
|
+
routine.enabled ? /* @__PURE__ */ jsx(CalendarIcon, {}) : /* @__PURE__ */ jsx(PauseIcon, {}),
|
|
580
|
+
/* @__PURE__ */ jsxs("span", {
|
|
581
|
+
className: "manager-office__identity",
|
|
582
|
+
children: [/* @__PURE__ */ jsx("strong", {
|
|
583
|
+
className: "sigvelo-truncate",
|
|
584
|
+
children: routine.name
|
|
585
|
+
}), /* @__PURE__ */ jsxs("small", {
|
|
586
|
+
className: "sigvelo-truncate",
|
|
587
|
+
children: [routine.enabled ? routine.schedule : `Paused · ${routine.schedule}`, routine.finishedRuns ? ` · ${routine.completedRuns}/${routine.finishedRuns}` : ""]
|
|
588
|
+
})]
|
|
589
|
+
}),
|
|
590
|
+
/* @__PURE__ */ jsx(ChevronRightIcon, { className: "manager-office__row-chevron" })
|
|
591
|
+
]
|
|
592
|
+
}) }, routine.id))
|
|
593
|
+
}) : /* @__PURE__ */ jsx(EmptyState, { description: "No routines yet." })
|
|
594
|
+
})]
|
|
595
|
+
})
|
|
596
|
+
}), /* @__PURE__ */ jsxs("section", {
|
|
597
|
+
className: "manager-office__section",
|
|
598
|
+
children: [/* @__PURE__ */ jsx("header", {
|
|
599
|
+
className: "manager-office__section-header",
|
|
600
|
+
children: /* @__PURE__ */ jsxs("h2", {
|
|
601
|
+
className: "manager-office__section-title",
|
|
602
|
+
children: [/* @__PURE__ */ jsx(LinkIcon, {}), "Inputs & outputs"]
|
|
603
|
+
})
|
|
604
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
605
|
+
className: "manager-office__section-content",
|
|
606
|
+
children: employee.channels.length ? /* @__PURE__ */ jsx("ul", {
|
|
607
|
+
className: "manager-office__channel-list sigvelo-stack-list",
|
|
608
|
+
children: employee.channels.map((channel) => /* @__PURE__ */ jsx(ChannelRow, { channel }, channel.id))
|
|
609
|
+
}) : /* @__PURE__ */ jsx(EmptyState, { description: "Nothing connected yet." })
|
|
610
|
+
})]
|
|
611
|
+
})]
|
|
612
|
+
})]
|
|
613
|
+
})
|
|
614
|
+
]
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
/**
|
|
618
|
+
* Multi-employee manager office: aggregate handoffs, employee roster, and one
|
|
619
|
+
* employee dossier. The consuming app owns authentication, Agent connections,
|
|
620
|
+
* routing, and the selected employee's full work surface.
|
|
621
|
+
*/
|
|
622
|
+
function ManagerOffice({ className, emptyOfficeAction, employees, renderLink, officeActions, renderEmployeeActions, style, view, ...props }) {
|
|
623
|
+
const titleId = React.useId();
|
|
624
|
+
const [now, setNow] = React.useState(Date.now);
|
|
625
|
+
React.useEffect(() => {
|
|
626
|
+
const interval = window.setInterval(() => setNow(Date.now()), 6e4);
|
|
627
|
+
return () => window.clearInterval(interval);
|
|
628
|
+
}, []);
|
|
629
|
+
const selectedEmployee = view.kind === "employee" ? employees.find((employee) => employee.id === view.employeeId) : void 0;
|
|
630
|
+
const profileColors = rosterProfileColors(employees);
|
|
631
|
+
const title = view.kind === "attention" ? "Needs you" : selectedEmployee?.name ?? "Employee";
|
|
632
|
+
return /* @__PURE__ */ jsx(Tooltip.Provider, { children: /* @__PURE__ */ jsx(ResponsiveSidebarShell, {
|
|
633
|
+
className: cx("manager-office", className),
|
|
634
|
+
style,
|
|
635
|
+
sidebarLabel: "employees",
|
|
636
|
+
showMainLabel: "Show manager office",
|
|
637
|
+
sidebar: ({ closeSidebarOnCompact }) => /* @__PURE__ */ jsx(EmployeeSidebar, {
|
|
638
|
+
closeSidebarOnCompact,
|
|
639
|
+
employees,
|
|
640
|
+
renderLink,
|
|
641
|
+
officeActions,
|
|
642
|
+
profileColors,
|
|
643
|
+
view
|
|
644
|
+
}),
|
|
645
|
+
bar: {
|
|
646
|
+
label: "Manager office controls",
|
|
647
|
+
titleRender: /* @__PURE__ */ jsx("h1", { id: titleId }),
|
|
648
|
+
title,
|
|
649
|
+
actions: selectedEmployee && isConnected(selectedEmployee) ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
650
|
+
/* @__PURE__ */ jsx(AppTopBar.Link, {
|
|
651
|
+
label: `Start new work with ${selectedEmployee.name}`,
|
|
652
|
+
tooltip: "New work",
|
|
653
|
+
render: renderLink({
|
|
654
|
+
kind: "new-work",
|
|
655
|
+
employee: selectedEmployee
|
|
656
|
+
}),
|
|
657
|
+
children: /* @__PURE__ */ jsx(PencilIcon, {})
|
|
658
|
+
}),
|
|
659
|
+
/* @__PURE__ */ jsx(AppTopBar.Link, {
|
|
660
|
+
label: `Open ${selectedEmployee.name} workspace`,
|
|
661
|
+
tooltip: "Workspace",
|
|
662
|
+
render: renderLink({
|
|
663
|
+
kind: "workspace",
|
|
664
|
+
employee: selectedEmployee
|
|
665
|
+
}),
|
|
666
|
+
children: /* @__PURE__ */ jsx(FolderIcon, {})
|
|
667
|
+
}),
|
|
668
|
+
renderEmployeeActions?.(selectedEmployee)
|
|
669
|
+
] }) : void 0
|
|
670
|
+
},
|
|
671
|
+
...props,
|
|
672
|
+
children: /* @__PURE__ */ jsx("main", {
|
|
673
|
+
className: "manager-office__main",
|
|
674
|
+
"aria-labelledby": titleId,
|
|
675
|
+
children: !employees.length ? /* @__PURE__ */ jsx(EmptyState, {
|
|
676
|
+
icon: /* @__PURE__ */ jsx(PlusIcon, {}),
|
|
677
|
+
title: "Add your first employee",
|
|
678
|
+
description: "Connect another profile to manage it here.",
|
|
679
|
+
children: emptyOfficeAction
|
|
680
|
+
}) : view.kind === "attention" ? /* @__PURE__ */ jsx(AttentionView, {
|
|
681
|
+
employees,
|
|
682
|
+
renderLink,
|
|
683
|
+
now
|
|
684
|
+
}) : selectedEmployee ? /* @__PURE__ */ jsx(EmployeeDetail, {
|
|
685
|
+
employee: selectedEmployee,
|
|
686
|
+
renderLink,
|
|
687
|
+
now,
|
|
688
|
+
profileColor: profileColors.get(selectedEmployee.id)
|
|
689
|
+
}) : /* @__PURE__ */ jsx(EmptyState, {
|
|
690
|
+
icon: /* @__PURE__ */ jsx(WarningIcon, {}),
|
|
691
|
+
title: "Employee unavailable",
|
|
692
|
+
description: "Choose another employee from the roster."
|
|
693
|
+
})
|
|
694
|
+
})
|
|
695
|
+
}) });
|
|
696
|
+
}
|
|
697
|
+
//#endregion
|
|
698
|
+
export { ManagerOffice };
|