2025-05-13 11:07:31 +08:00
|
|
|
import type { ReactNode } from 'react'
|
|
|
|
import React from 'react'
|
|
|
|
import cn from '@/utils/classnames'
|
|
|
|
import Badge from '@/app/components/base/badge'
|
|
|
|
import { useTranslation } from 'react-i18next'
|
|
|
|
import { EffectColor } from './chunk-structure/types'
|
2025-05-13 15:35:21 +08:00
|
|
|
import { ArrowShape } from '../../base/icons/src/vender/knowledge'
|
2025-05-13 11:07:31 +08:00
|
|
|
|
|
|
|
const HEADER_EFFECT_MAP: Record<EffectColor, string> = {
|
|
|
|
[EffectColor.indigo]: 'bg-util-colors-indigo-indigo-600 opacity-50',
|
|
|
|
[EffectColor.blueLight]: 'bg-util-colors-blue-light-blue-light-600 opacity-80',
|
|
|
|
[EffectColor.orange]: 'bg-util-colors-orange-orange-500 opacity-50',
|
|
|
|
[EffectColor.purple]: 'bg-util-colors-purple-purple-600 opacity-80',
|
|
|
|
}
|
|
|
|
type OptionCardProps<T> = {
|
|
|
|
id: T
|
|
|
|
className?: string
|
2025-05-13 15:35:21 +08:00
|
|
|
isActive?: boolean
|
2025-05-13 11:07:31 +08:00
|
|
|
icon?: ReactNode
|
2025-05-13 15:35:21 +08:00
|
|
|
iconActiveColor?: string
|
2025-05-13 11:07:31 +08:00
|
|
|
title: string
|
|
|
|
description?: string
|
|
|
|
isRecommended?: boolean
|
|
|
|
effectColor?: EffectColor
|
|
|
|
showEffectColor?: boolean
|
2025-05-13 15:35:21 +08:00
|
|
|
disabled?: boolean
|
2025-05-13 11:07:31 +08:00
|
|
|
onClick?: (id: T) => void
|
2025-05-13 15:35:21 +08:00
|
|
|
children?: ReactNode
|
|
|
|
showChildren?: boolean
|
|
|
|
ref?: React.Ref<HTMLDivElement>
|
2025-05-13 11:07:31 +08:00
|
|
|
}
|
|
|
|
const OptionCard = <T,>({
|
|
|
|
id,
|
|
|
|
className,
|
2025-05-13 15:35:21 +08:00
|
|
|
isActive,
|
2025-05-13 11:07:31 +08:00
|
|
|
icon,
|
2025-05-13 15:35:21 +08:00
|
|
|
iconActiveColor,
|
2025-05-13 11:07:31 +08:00
|
|
|
title,
|
|
|
|
description,
|
|
|
|
isRecommended,
|
|
|
|
effectColor,
|
|
|
|
showEffectColor,
|
2025-05-13 15:35:21 +08:00
|
|
|
disabled,
|
2025-05-13 11:07:31 +08:00
|
|
|
onClick,
|
2025-05-13 15:35:21 +08:00
|
|
|
children,
|
|
|
|
showChildren,
|
|
|
|
ref,
|
2025-05-13 11:07:31 +08:00
|
|
|
}: OptionCardProps<T>) => {
|
|
|
|
const { t } = useTranslation()
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div
|
2025-05-13 15:35:21 +08:00
|
|
|
ref={ref}
|
2025-05-13 11:07:31 +08:00
|
|
|
className={cn(
|
|
|
|
'cursor-pointer overflow-hidden rounded-xl border border-components-option-card-option-border bg-components-option-card-option-bg',
|
2025-05-13 15:35:21 +08:00
|
|
|
isActive && 'border border-components-option-card-option-selected-border ring-[1px] ring-components-option-card-option-selected-border',
|
|
|
|
disabled && 'cursor-not-allowed opacity-50',
|
2025-05-13 11:07:31 +08:00
|
|
|
)}
|
2025-05-13 15:35:21 +08:00
|
|
|
onClick={() => {
|
2025-05-16 17:54:41 +08:00
|
|
|
if (isActive || disabled) return
|
2025-05-13 15:35:21 +08:00
|
|
|
onClick?.(id)
|
|
|
|
}}
|
2025-05-13 11:07:31 +08:00
|
|
|
>
|
|
|
|
<div className={cn(
|
|
|
|
'relative flex rounded-t-xl p-2',
|
|
|
|
className,
|
|
|
|
)}>
|
|
|
|
{
|
|
|
|
effectColor && showEffectColor && (
|
|
|
|
<div className={cn(
|
|
|
|
'absolute left-[-2px] top-[-2px] h-14 w-14 rounded-full blur-[80px]',
|
|
|
|
`${HEADER_EFFECT_MAP[effectColor]}`,
|
2025-05-16 17:54:41 +08:00
|
|
|
)} />
|
2025-05-13 11:07:31 +08:00
|
|
|
)
|
|
|
|
}
|
|
|
|
{
|
|
|
|
icon && (
|
2025-05-13 15:35:21 +08:00
|
|
|
<div className={cn(
|
|
|
|
'flex size-6 shrink-0 items-center justify-center text-text-tertiary',
|
|
|
|
isActive && iconActiveColor,
|
|
|
|
)}>
|
2025-05-13 11:07:31 +08:00
|
|
|
{icon}
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
<div className='flex grow flex-col gap-y-0.5 py-px'>
|
|
|
|
<div className='flex items-center gap-x-1'>
|
2025-05-13 15:35:21 +08:00
|
|
|
<span className='system-sm-medium text-text-secondary'>
|
2025-05-13 11:07:31 +08:00
|
|
|
{title}
|
|
|
|
</span>
|
|
|
|
{
|
|
|
|
isRecommended && (
|
|
|
|
<Badge className='h-[18px] border-text-accent-secondary text-text-accent-secondary'>
|
|
|
|
{t('datasetCreation.stepTwo.recommend')}
|
|
|
|
</Badge>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
</div>
|
|
|
|
{
|
|
|
|
description && (
|
|
|
|
<div className='system-xs-regular text-text-tertiary'>
|
|
|
|
{description}
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
</div>
|
|
|
|
</div>
|
2025-05-13 15:35:21 +08:00
|
|
|
{
|
|
|
|
children && showChildren && (
|
|
|
|
<div className='relative rounded-b-xl bg-components-panel-bg p-4'>
|
|
|
|
<ArrowShape className='absolute left-[14px] top-[-11px] size-4 text-components-panel-bg' />
|
|
|
|
{children}
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
2025-05-13 11:07:31 +08:00
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2025-05-13 15:35:21 +08:00
|
|
|
export default React.memo(OptionCard) as typeof OptionCard
|