Files
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

79 lines
2.1 KiB
TypeScript

import { useCallback, useState } from "react";
import type { ReactNode } from "react";
import {
Button,
InspectIcon,
Tooltip,
TooltipContent,
TooltipTrigger,
cn
} from "@tutti-os/ui-system";
import { useActiveBrowserNodeWebview } from "@tutti-os/browser-node/react";
import { useEngineSelector } from "../../shared/engine/useEngineSelector.ts";
import { BrowserElementContextSelectionController } from "./browserElementContextSelectionController.ts";
export interface BrowserElementContextCopy {
cancel: string;
failed: string;
select: string;
}
export function BrowserElementContextAction({
copy,
onAppendMention,
onError,
workspaceId
}: {
copy: BrowserElementContextCopy;
onAppendMention: (mention: string) => void;
onError: (message: string) => void;
workspaceId: string;
}): ReactNode {
const activeWebview = useActiveBrowserNodeWebview();
const [controller] = useState(
() =>
new BrowserElementContextSelectionController({
failedCopy: copy.failed,
onAppendMention,
onError,
workspaceId
})
);
controller.configure({
failedCopy: copy.failed,
onAppendMention,
onError,
workspaceId
});
const state = useEngineSelector(controller, (snapshot) => snapshot.state);
const bindAction = useCallback(
(node: HTMLButtonElement | null) =>
controller.bindAction(node, activeWebview),
[activeWebview, controller]
);
const label = state === "selecting" ? copy.cancel : copy.select;
return (
<Tooltip>
<TooltipTrigger asChild>
<Button
aria-label={label}
aria-pressed={state === "selecting"}
className={cn(
"nodrag shrink-0 rounded-md",
state === "selecting" &&
"bg-[var(--transparency-block)] text-[var(--text-primary)]"
)}
size="icon-sm"
ref={bindAction}
type="button"
variant="chrome"
onClick={() => controller.toggle(activeWebview)}
>
<InspectIcon className="size-[15px]" />
</Button>
</TooltipTrigger>
<TooltipContent side="bottom">{label}</TooltipContent>
</Tooltip>
);
}