(props: { latestVersion: string; channel: UpdateChannel })
| 114 | // ── NpmUpdateCard (npm-installed CLI: copyable command) ─────────────────── |
| 115 | |
| 116 | function NpmUpdateCard(props: { latestVersion: string; channel: UpdateChannel }) { |
| 117 | const command = `npm i -g executor@${props.channel}`; |
| 118 | const [copied, setCopied] = useState(false); |
| 119 | |
| 120 | const handleCopy = useCallback(() => { |
| 121 | void copyToClipboard(command).then((ok) => { |
| 122 | if (!ok) { |
| 123 | toast.error("Failed to copy to clipboard"); |
| 124 | return; |
| 125 | } |
| 126 | setCopied(true); |
| 127 | setTimeout(() => setCopied(false), 1500); |
| 128 | }); |
| 129 | }, [command]); |
| 130 | |
| 131 | return ( |
| 132 | <UpdateCardShell version={props.latestVersion}> |
| 133 | <Button |
| 134 | type="button" |
| 135 | variant="outline" |
| 136 | onClick={handleCopy} |
| 137 | className="mt-2.5 flex w-full items-center justify-between gap-2 rounded-lg border-border/60 bg-background/50 px-2.5 py-1.5 text-left hover:bg-background/80" |
| 138 | > |
| 139 | <code className="truncate font-mono text-xs text-sidebar-foreground">{command}</code> |
| 140 | <span className="shrink-0 text-muted-foreground transition-colors group-hover:text-foreground"> |
| 141 | {copied ? ( |
| 142 | <svg viewBox="0 0 16 16" fill="none" className="size-3 text-primary"> |
| 143 | <path |
| 144 | d="M3 8.5l3.5 3.5L13 4" |
| 145 | stroke="currentColor" |
| 146 | strokeWidth="1.4" |
| 147 | strokeLinecap="round" |
| 148 | strokeLinejoin="round" |
| 149 | /> |
| 150 | </svg> |
| 151 | ) : ( |
| 152 | <svg viewBox="0 0 16 16" fill="none" className="size-3"> |
| 153 | <rect |
| 154 | x="5" |
| 155 | y="5" |
| 156 | width="8" |
| 157 | height="8" |
| 158 | rx="1.5" |
| 159 | stroke="currentColor" |
| 160 | strokeWidth="1.2" |
| 161 | /> |
| 162 | <path |
| 163 | d="M3 11V3.5A.5.5 0 013.5 3H11" |
| 164 | stroke="currentColor" |
| 165 | strokeWidth="1.2" |
| 166 | strokeLinecap="round" |
| 167 | /> |
| 168 | </svg> |
| 169 | )} |
| 170 | </span> |
| 171 | </Button> |
| 172 | </UpdateCardShell> |
| 173 | ); |
nothing calls this directly
no test coverage detected