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
67 lines
2.5 KiB
TypeScript
67 lines
2.5 KiB
TypeScript
import { forwardRef, type ButtonHTMLAttributes, type ReactNode } from "react";
|
|
import { cn } from "../../app/renderer/lib/utils";
|
|
|
|
export type CanvasNodeGhostIconButtonProps = Omit<
|
|
ButtonHTMLAttributes<HTMLButtonElement>,
|
|
"type"
|
|
> & {
|
|
children: ReactNode;
|
|
/**
|
|
* When true (default), pointer/click stopPropagation — keeps React Flow from stealing node chrome
|
|
* interactions. Set false for Radix `DropdownMenuTrigger asChild` and other portaled triggers.
|
|
*/
|
|
stopsEventPropagation?: boolean;
|
|
};
|
|
|
|
/**
|
|
* Ghost icon control for canvas node chrome.
|
|
*/
|
|
export const CanvasNodeGhostIconButton = forwardRef<
|
|
HTMLButtonElement,
|
|
CanvasNodeGhostIconButtonProps
|
|
>(function CanvasNodeGhostIconButton(
|
|
{
|
|
className,
|
|
children,
|
|
onPointerDown,
|
|
onMouseDown,
|
|
onClick,
|
|
stopsEventPropagation = true,
|
|
...rest
|
|
},
|
|
ref
|
|
) {
|
|
"use memo";
|
|
return (
|
|
<button
|
|
ref={ref}
|
|
{...rest}
|
|
type="button"
|
|
className={cn(
|
|
"nodrag inline-flex h-7 min-h-7 w-7 min-w-7 shrink-0 items-center justify-center rounded-[4px] border border-transparent bg-transparent p-0 text-[var(--text-secondary)] transition-[background-color,color,border-color,opacity] duration-200 ease-in-out [-webkit-app-region:no-drag] hover:border-transparent hover:bg-[var(--transparency-block)] hover:text-[var(--text-primary)] active:bg-[var(--transparency-block-active)] active:text-[var(--text-primary)] disabled:cursor-not-allowed disabled:opacity-45 focus-visible:outline-2 focus-visible:outline-[color:color-mix(in_srgb,var(--tsh-shell-accent)_80%,white)] focus-visible:outline-offset-2 [&_svg]:block [&_svg]:h-3.5 [&_svg]:w-3.5 [&_svg]:shrink-0 [&_svg:not([data-nexight-chrome-glyph=fill]):not([data-tutti-chrome-glyph=fill])]:fill-none [&_svg:not([data-nexight-chrome-glyph=fill]):not([data-tutti-chrome-glyph=fill])]:stroke-current data-[menu-open=true]:border-transparent data-[menu-open=true]:bg-[var(--transparency-block)] data-[menu-open=true]:text-[var(--text-primary)] data-[menu-open=true]:hover:bg-[var(--transparency-block-active)]",
|
|
className
|
|
)}
|
|
onPointerDown={(event) => {
|
|
if (stopsEventPropagation) {
|
|
event.stopPropagation();
|
|
}
|
|
onPointerDown?.(event);
|
|
}}
|
|
onMouseDown={(event) => {
|
|
if (stopsEventPropagation) {
|
|
event.stopPropagation();
|
|
}
|
|
onMouseDown?.(event);
|
|
}}
|
|
onClick={(event) => {
|
|
if (stopsEventPropagation) {
|
|
event.stopPropagation();
|
|
}
|
|
onClick?.(event);
|
|
}}
|
|
>
|
|
{children}
|
|
</button>
|
|
);
|
|
});
|