popup.tsx 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import type { FC } from 'react'
  2. import { useState } from 'react'
  3. import type {
  4. DefaultModel,
  5. Model,
  6. ModelItem,
  7. } from '../declarations'
  8. import { useLanguage } from '../hooks'
  9. import PopupItem from './popup-item'
  10. import { SearchLg } from '@/app/components/base/icons/src/vender/line/general'
  11. import { XCircle } from '@/app/components/base/icons/src/vender/solid/general'
  12. type PopupProps = {
  13. defaultModel?: DefaultModel
  14. modelList: Model[]
  15. onSelect: (provider: string, model: ModelItem) => void
  16. }
  17. const Popup: FC<PopupProps> = ({
  18. defaultModel,
  19. modelList,
  20. onSelect,
  21. }) => {
  22. const language = useLanguage()
  23. const [searchText, setSearchText] = useState('')
  24. const filteredModelList = modelList.filter(model => model.models.filter(modelItem => modelItem.label[language].includes(searchText)).length)
  25. return (
  26. <div className='w-[320px] max-h-[480px] rounded-lg border-[0.5px] border-gray-200 bg-white shadow-lg overflow-y-auto'>
  27. <div className='sticky top-0 pl-3 pt-3 pr-2 pb-1 bg-white z-10'>
  28. <div className={`
  29. flex items-center pl-[9px] pr-[10px] h-8 rounded-lg border
  30. ${searchText ? 'bg-white border-gray-300 shadow-xs' : 'bg-gray-100 border-transparent'}
  31. `}>
  32. <SearchLg
  33. className={`
  34. shrink-0 mr-[7px] w-[14px] h-[14px]
  35. ${searchText ? 'text-gray-500' : 'text-gray-400'}
  36. `}
  37. />
  38. <input
  39. className='block grow h-[18px] text-[13px] appearance-none outline-none bg-transparent'
  40. placeholder='Search model'
  41. value={searchText}
  42. onChange={e => setSearchText(e.target.value)}
  43. />
  44. {
  45. searchText && (
  46. <XCircle
  47. className='shrink-0 ml-1.5 w-[14px] h-[14px] text-gray-400 cursor-pointer'
  48. onClick={() => setSearchText('')}
  49. />
  50. )
  51. }
  52. </div>
  53. </div>
  54. <div className='p-1'>
  55. {
  56. filteredModelList.map(model => (
  57. <PopupItem
  58. key={model.provider}
  59. defaultModel={defaultModel}
  60. model={model}
  61. onSelect={onSelect}
  62. />
  63. ))
  64. }
  65. {
  66. !filteredModelList.length && (
  67. <div className='px-3 py-1.5 leading-[18px] text-center text-xs text-gray-500 break-all'>
  68. {`No model found for “${searchText}”`}
  69. </div>
  70. )
  71. }
  72. </div>
  73. </div>
  74. )
  75. }
  76. export default Popup