1import { mergeClasses } from '@expo/styleguide';
2import { Command } from 'cmdk';
3import { PropsWithChildren, useState } from 'react';
4
5import { openLink } from '../utils';
6
7import { Tag } from '~/ui/components/Tag';
8
9type Props = PropsWithChildren<{
10  url: string;
11  onSelect?: () => void;
12  isExternalLink?: boolean;
13  isNested?: boolean;
14  // Props forwarded to Command.Item
15  className?: string;
16  value?: string;
17}>;
18
19/**
20 * Wrapper for Command.Item that adds copy link on right/ middle click + visual copy indicator.
21 */
22export const CommandItemBase = ({
23  children,
24  url,
25  isExternalLink,
26  isNested,
27  onSelect,
28  className,
29  value,
30}: Props) => {
31  const [copyDone, setCopyDone] = useState(false);
32
33  const copyUrl = () => {
34    navigator.clipboard?.writeText(url);
35    setCopyDone(true);
36    setTimeout(() => setCopyDone(false), 1500);
37  };
38
39  return (
40    <Command.Item
41      className={mergeClasses('relative', className)}
42      value={value}
43      data-nested={isNested ? true : undefined}
44      onMouseUp={event => {
45        // note(Keith): middle click (typical *nix copy shortcut)
46        // right click (works with Mac trackpads)
47        // onAuxClick is not supported in Safari
48        if (event.button === 1 || event.button === 2) {
49          copyUrl();
50        }
51      }}
52      onSelect={() => {
53        openLink(url, isExternalLink);
54        onSelect && onSelect();
55      }}
56      onContextMenu={event => {
57        event.preventDefault();
58      }}>
59      {children}
60      {copyDone && (
61        <Tag
62          name="Copied!"
63          className="absolute right-2.5 top-[calc(50%-13px)] !m-0 !border-secondary !bg-default"
64        />
65      )}
66    </Command.Item>
67  );
68};
69