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