320 lines
6.3 KiB
TypeScript
320 lines
6.3 KiB
TypeScript
import { X } from 'lucide-react'
|
|
import { PropsWithChildren } from 'react'
|
|
|
|
import {
|
|
Mentionable,
|
|
MentionableBlock,
|
|
MentionableCurrentFile,
|
|
MentionableFile,
|
|
MentionableFolder,
|
|
MentionableImage,
|
|
MentionableUrl,
|
|
MentionableVault,
|
|
} from '../../../types/mentionable'
|
|
|
|
import { getMentionableIcon } from './utils/get-metionable-icon'
|
|
|
|
function BadgeBase({
|
|
children,
|
|
onDelete,
|
|
onClick,
|
|
isFocused,
|
|
}: PropsWithChildren<{
|
|
onDelete: () => void
|
|
onClick: () => void
|
|
isFocused: boolean
|
|
}>) {
|
|
return (
|
|
<div
|
|
className={`infio-chat-user-input-file-badge ${isFocused ? 'infio-chat-user-input-file-badge-focused' : ''}`}
|
|
onClick={onClick}
|
|
>
|
|
{children}
|
|
<div
|
|
className="infio-chat-user-input-file-badge-delete"
|
|
onClick={(evt) => {
|
|
evt.stopPropagation()
|
|
onDelete()
|
|
}}
|
|
>
|
|
<X size={16} />
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function FileBadge({
|
|
mentionable,
|
|
onDelete,
|
|
onClick,
|
|
isFocused,
|
|
}: {
|
|
mentionable: MentionableFile
|
|
onDelete: () => void
|
|
onClick: () => void
|
|
isFocused: boolean
|
|
}) {
|
|
const Icon = getMentionableIcon(mentionable)
|
|
return (
|
|
<BadgeBase onDelete={onDelete} onClick={onClick} isFocused={isFocused}>
|
|
<div className="infio-chat-user-input-file-badge-name">
|
|
{Icon && (
|
|
<Icon
|
|
size={10}
|
|
className="infio-chat-user-input-file-badge-name-icon"
|
|
/>
|
|
)}
|
|
<span>{mentionable.file.name}</span>
|
|
</div>
|
|
</BadgeBase>
|
|
)
|
|
}
|
|
|
|
function FolderBadge({
|
|
mentionable,
|
|
onDelete,
|
|
onClick,
|
|
isFocused,
|
|
}: {
|
|
mentionable: MentionableFolder
|
|
onDelete: () => void
|
|
onClick: () => void
|
|
isFocused: boolean
|
|
}) {
|
|
const Icon = getMentionableIcon(mentionable)
|
|
return (
|
|
<BadgeBase onDelete={onDelete} onClick={onClick} isFocused={isFocused}>
|
|
<div className="infio-chat-user-input-file-badge-name">
|
|
{Icon && (
|
|
<Icon
|
|
size={10}
|
|
className="infio-chat-user-input-file-badge-name-icon"
|
|
/>
|
|
)}
|
|
<span>{mentionable.folder.name}</span>
|
|
</div>
|
|
</BadgeBase>
|
|
)
|
|
}
|
|
|
|
function VaultBadge({
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
mentionable,
|
|
onDelete,
|
|
onClick,
|
|
isFocused,
|
|
}: {
|
|
mentionable: MentionableVault
|
|
onDelete: () => void
|
|
onClick: () => void
|
|
isFocused: boolean
|
|
}) {
|
|
const Icon = getMentionableIcon(mentionable)
|
|
return (
|
|
<BadgeBase onDelete={onDelete} onClick={onClick} isFocused={isFocused}>
|
|
{/* TODO: Update style */}
|
|
<div className="infio-chat-user-input-file-badge-name">
|
|
{Icon && (
|
|
<Icon
|
|
size={10}
|
|
className="infio-chat-user-input-file-badge-name-icon"
|
|
/>
|
|
)}
|
|
<span>Vault</span>
|
|
</div>
|
|
</BadgeBase>
|
|
)
|
|
}
|
|
|
|
function CurrentFileBadge({
|
|
mentionable,
|
|
onDelete,
|
|
onClick,
|
|
isFocused,
|
|
}: {
|
|
mentionable: MentionableCurrentFile
|
|
onDelete: () => void
|
|
onClick: () => void
|
|
isFocused: boolean
|
|
}) {
|
|
const Icon = getMentionableIcon(mentionable)
|
|
return mentionable.file ? (
|
|
<BadgeBase onDelete={onDelete} onClick={onClick} isFocused={isFocused}>
|
|
<div className="infio-chat-user-input-file-badge-name">
|
|
{Icon && (
|
|
<Icon
|
|
size={10}
|
|
className="infio-chat-user-input-file-badge-name-icon"
|
|
/>
|
|
)}
|
|
<span>{mentionable.file.name}</span>
|
|
</div>
|
|
<div className="infio-chat-user-input-file-badge-name-block-suffix">
|
|
{' (Current file)'}
|
|
</div>
|
|
</BadgeBase>
|
|
) : null
|
|
}
|
|
|
|
function BlockBadge({
|
|
mentionable,
|
|
onDelete,
|
|
onClick,
|
|
isFocused,
|
|
}: {
|
|
mentionable: MentionableBlock
|
|
onDelete: () => void
|
|
onClick: () => void
|
|
isFocused: boolean
|
|
}) {
|
|
const Icon = getMentionableIcon(mentionable)
|
|
return (
|
|
<BadgeBase onDelete={onDelete} onClick={onClick} isFocused={isFocused}>
|
|
<div className="infio-chat-user-input-file-badge-name-block-name">
|
|
{Icon && (
|
|
<Icon
|
|
size={10}
|
|
className="infio-chat-user-input-file-badge-name-block-name-icon"
|
|
/>
|
|
)}
|
|
<span>{mentionable.file.name}</span>
|
|
</div>
|
|
<div className="infio-chat-user-input-file-badge-name-block-suffix">
|
|
{` (${mentionable.startLine}:${mentionable.endLine})`}
|
|
</div>
|
|
</BadgeBase>
|
|
)
|
|
}
|
|
|
|
function UrlBadge({
|
|
mentionable,
|
|
onDelete,
|
|
onClick,
|
|
isFocused,
|
|
}: {
|
|
mentionable: MentionableUrl
|
|
onDelete: () => void
|
|
onClick: () => void
|
|
isFocused: boolean
|
|
}) {
|
|
const Icon = getMentionableIcon(mentionable)
|
|
return (
|
|
<BadgeBase onDelete={onDelete} onClick={onClick} isFocused={isFocused}>
|
|
<div className="infio-chat-user-input-file-badge-name">
|
|
{Icon && (
|
|
<Icon
|
|
size={10}
|
|
className="infio-chat-user-input-file-badge-name-icon"
|
|
/>
|
|
)}
|
|
<span>{mentionable.url}</span>
|
|
</div>
|
|
</BadgeBase>
|
|
)
|
|
}
|
|
|
|
function ImageBadge({
|
|
mentionable,
|
|
onDelete,
|
|
onClick,
|
|
isFocused,
|
|
}: {
|
|
mentionable: MentionableImage
|
|
onDelete: () => void
|
|
onClick: () => void
|
|
isFocused: boolean
|
|
}) {
|
|
const Icon = getMentionableIcon(mentionable)
|
|
return (
|
|
<BadgeBase onDelete={onDelete} onClick={onClick} isFocused={isFocused}>
|
|
<div className="infio-chat-user-input-file-badge-name">
|
|
{Icon && (
|
|
<Icon
|
|
size={10}
|
|
className="infio-chat-user-input-file-badge-name-icon"
|
|
/>
|
|
)}
|
|
<span>{mentionable.name}</span>
|
|
</div>
|
|
</BadgeBase>
|
|
)
|
|
}
|
|
|
|
export default function MentionableBadge({
|
|
mentionable,
|
|
onDelete,
|
|
onClick,
|
|
isFocused = false,
|
|
}: {
|
|
mentionable: Mentionable
|
|
onDelete: () => void
|
|
onClick: () => void
|
|
isFocused?: boolean
|
|
}) {
|
|
switch (mentionable.type) {
|
|
case 'file':
|
|
return (
|
|
<FileBadge
|
|
mentionable={mentionable}
|
|
onDelete={onDelete}
|
|
onClick={onClick}
|
|
isFocused={isFocused}
|
|
/>
|
|
)
|
|
case 'folder':
|
|
return (
|
|
<FolderBadge
|
|
mentionable={mentionable}
|
|
onDelete={onDelete}
|
|
onClick={onClick}
|
|
isFocused={isFocused}
|
|
/>
|
|
)
|
|
case 'vault':
|
|
return (
|
|
<VaultBadge
|
|
mentionable={mentionable}
|
|
onDelete={onDelete}
|
|
onClick={onClick}
|
|
isFocused={isFocused}
|
|
/>
|
|
)
|
|
case 'current-file':
|
|
return (
|
|
<CurrentFileBadge
|
|
mentionable={mentionable}
|
|
onDelete={onDelete}
|
|
onClick={onClick}
|
|
isFocused={isFocused}
|
|
/>
|
|
)
|
|
case 'block':
|
|
return (
|
|
<BlockBadge
|
|
mentionable={mentionable}
|
|
onDelete={onDelete}
|
|
onClick={onClick}
|
|
isFocused={isFocused}
|
|
/>
|
|
)
|
|
case 'url':
|
|
return (
|
|
<UrlBadge
|
|
mentionable={mentionable}
|
|
onDelete={onDelete}
|
|
onClick={onClick}
|
|
isFocused={isFocused}
|
|
/>
|
|
)
|
|
case 'image':
|
|
return (
|
|
<ImageBadge
|
|
mentionable={mentionable}
|
|
onDelete={onDelete}
|
|
onClick={onClick}
|
|
isFocused={isFocused}
|
|
/>
|
|
)
|
|
}
|
|
}
|