index.tsx 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import { Fragment } from 'react'
  2. import type { FC } from 'react'
  3. import { Popover, Transition } from '@headlessui/react'
  4. import { useTranslation } from 'react-i18next'
  5. import { Check, DotsHorizontal, Trash03 } from '@/app/components/base/icons/src/vender/line/general'
  6. const itemClassName = `
  7. flex items-center px-3 h-9 text-sm text-gray-700 rounded-lg cursor-pointer
  8. `
  9. type SelectorProps = {
  10. value?: string
  11. onOperate: (v: Record<string, string>) => void
  12. hiddenOptions?: boolean
  13. className?: (v: boolean) => string
  14. deleteText?: string
  15. }
  16. const Selector: FC<SelectorProps> = ({
  17. value,
  18. onOperate,
  19. hiddenOptions,
  20. className,
  21. deleteText,
  22. }) => {
  23. const { t } = useTranslation()
  24. const options = [
  25. {
  26. key: 'custom',
  27. text: 'API',
  28. },
  29. {
  30. key: 'system',
  31. text: t('common.modelProvider.quota'),
  32. },
  33. ]
  34. return (
  35. <Popover className='relative'>
  36. <Popover.Button>
  37. {
  38. ({ open }) => (
  39. <div className={`
  40. flex justify-center items-center w-6 h-6 rounded-md hover:bg-gray-50 cursor-pointer
  41. ${open && 'bg-gray-50'}
  42. ${className && className(open)}
  43. `}>
  44. <DotsHorizontal className='w-3 h-3 text-gray-700' />
  45. </div>
  46. )
  47. }
  48. </Popover.Button>
  49. <Transition
  50. as={Fragment}
  51. leave='transition ease-in duration-100'
  52. leaveFrom='opacity-100'
  53. leaveTo='opacity-0'
  54. >
  55. <Popover.Panel className='absolute top-7 right-0 w-[192px] bg-white border-[0.5px] border-gray-200 rounded-lg shadow-lg z-10'>
  56. {
  57. !hiddenOptions && (
  58. <>
  59. <div className='p-1'>
  60. <div className='px-3 pt-2 pb-1 text-sm font-medium text-gray-700'>{t('common.modelProvider.card.priorityUse')}</div>
  61. {
  62. options.map(option => (
  63. <Popover.Button as={Fragment} key={option.key}>
  64. <div
  65. className={`${itemClassName} hover:bg-gray-50`}
  66. onClick={() => onOperate({ type: 'priority', value: option.key })}>
  67. <div className='grow'>{option.text}</div>
  68. {value === option.key && <Check className='w-4 h-4 text-primary-600' />}
  69. </div>
  70. </Popover.Button>
  71. ))
  72. }
  73. </div>
  74. <div className='h-[1px] bg-gray-100' />
  75. </>
  76. )
  77. }
  78. <div className='p-1'>
  79. <Popover.Button as={Fragment}>
  80. <div
  81. className={`group ${itemClassName} hover:bg-[#FEF3F2] hover:text-[#D92D20]`}
  82. onClick={() => onOperate({ type: 'delete' })}>
  83. <Trash03 className='mr-2 w-4 h-4 text-gray-500 group-hover:text-[#D92D20]' />
  84. {deleteText || t('common.modelProvider.card.removeKey')}
  85. </div>
  86. </Popover.Button>
  87. </div>
  88. </Popover.Panel>
  89. </Transition>
  90. </Popover>
  91. )
  92. }
  93. export default Selector