index.tsx 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. import React, { type FC, useCallback } from 'react'
  2. import { RiMoreFill } from '@remixicon/react'
  3. import { VersionHistoryContextMenuOptions } from '../../../types'
  4. import MenuItem from './menu-item'
  5. import useContextMenu from './use-context-menu'
  6. import {
  7. PortalToFollowElem,
  8. PortalToFollowElemContent,
  9. PortalToFollowElemTrigger,
  10. } from '@/app/components/base/portal-to-follow-elem'
  11. import Button from '@/app/components/base/button'
  12. import Divider from '@/app/components/base/divider'
  13. export type ContextMenuProps = {
  14. isShowDelete: boolean
  15. isNamedVersion: boolean
  16. open: boolean
  17. setOpen: React.Dispatch<React.SetStateAction<boolean>>
  18. handleClickMenuItem: (operation: VersionHistoryContextMenuOptions) => void
  19. }
  20. const ContextMenu: FC<ContextMenuProps> = (props: ContextMenuProps) => {
  21. const { isShowDelete, handleClickMenuItem, open, setOpen } = props
  22. const {
  23. deleteOperation,
  24. options,
  25. } = useContextMenu(props)
  26. const handleClickTrigger = useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
  27. e.stopPropagation()
  28. setOpen(v => !v)
  29. }, [setOpen])
  30. return (
  31. <PortalToFollowElem
  32. placement={'bottom-end'}
  33. offset={{
  34. mainAxis: 4,
  35. crossAxis: 0,
  36. }}
  37. open={open}
  38. onOpenChange={setOpen}
  39. >
  40. <PortalToFollowElemTrigger>
  41. <Button size='small' className='px-1' onClick={handleClickTrigger}>
  42. <RiMoreFill className='w-4 h-4' />
  43. </Button>
  44. </PortalToFollowElemTrigger>
  45. <PortalToFollowElemContent className='z-10'>
  46. <div className='flex flex-col w-[184px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg shadow-shadow-shadow-5 backdrop-blur-[5px]'>
  47. <div className='flex flex-col p-1'>
  48. {
  49. options.map((option) => {
  50. return (
  51. <MenuItem
  52. key={option.key}
  53. item={option}
  54. onClick={handleClickMenuItem.bind(null, option.key)}
  55. />
  56. )
  57. })
  58. }
  59. </div>
  60. {
  61. isShowDelete && (
  62. <>
  63. <Divider type='horizontal' className='h-[1px] bg-divider-subtle my-0' />
  64. <div className='p-1'>
  65. <MenuItem
  66. item={deleteOperation}
  67. isDestructive
  68. onClick={handleClickMenuItem.bind(null, VersionHistoryContextMenuOptions.delete)}
  69. />
  70. </div>
  71. </>
  72. )
  73. }
  74. </div>
  75. </PortalToFollowElemContent>
  76. </PortalToFollowElem>
  77. )
  78. }
  79. export default React.memo(ContextMenu)