Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

page-panel.tsx 2.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
  2. import styled from 'styles'
  3. import {
  4. breakpoints,
  5. DropdownMenuButton,
  6. DropdownMenuDivider,
  7. RowButton,
  8. MenuContent,
  9. FloatingContainer,
  10. IconButton,
  11. IconWrapper,
  12. } from 'components/shared'
  13. import { MixerVerticalIcon, PlusIcon, CheckIcon } from '@radix-ui/react-icons'
  14. import state, { useSelector } from 'state'
  15. import { useEffect, useRef, useState } from 'react'
  16. export default function PagePanel(): JSX.Element {
  17. const rIsOpen = useRef(false)
  18. const [isOpen, setIsOpen] = useState(false)
  19. useEffect(() => {
  20. if (rIsOpen.current !== isOpen) {
  21. rIsOpen.current = isOpen
  22. }
  23. }, [isOpen])
  24. const documentPages = useSelector((s) => s.data.document.pages)
  25. const currentPageId = useSelector((s) => s.data.currentPageId)
  26. if (!documentPages[currentPageId]) return null
  27. const sorted = Object.values(documentPages).sort(
  28. (a, b) => a.childIndex - b.childIndex
  29. )
  30. return (
  31. <DropdownMenu.Root
  32. dir="ltr"
  33. open={isOpen}
  34. onOpenChange={(isOpen) => {
  35. if (rIsOpen.current !== isOpen) {
  36. setIsOpen(isOpen)
  37. }
  38. }}
  39. >
  40. <FloatingContainer>
  41. <RowButton as={DropdownMenu.Trigger} bp={breakpoints}>
  42. <span>{documentPages[currentPageId].name}</span>
  43. </RowButton>
  44. </FloatingContainer>
  45. <MenuContent as={DropdownMenu.Content} sideOffset={8}>
  46. <DropdownMenu.RadioGroup
  47. value={currentPageId}
  48. onValueChange={(id) => {
  49. setIsOpen(false)
  50. state.send('CHANGED_PAGE', { id })
  51. }}
  52. >
  53. {sorted.map(({ id, name }) => (
  54. <ButtonWithOptions key={id}>
  55. <DropdownMenu.RadioItem
  56. as={RowButton}
  57. bp={breakpoints}
  58. value={id}
  59. variant="pageButton"
  60. >
  61. <span>{name}</span>
  62. <DropdownMenu.ItemIndicator>
  63. <IconWrapper>
  64. <CheckIcon />
  65. </IconWrapper>
  66. </DropdownMenu.ItemIndicator>
  67. </DropdownMenu.RadioItem>
  68. <IconButton bp={breakpoints} size="small" data-shy="true">
  69. <MixerVerticalIcon />
  70. </IconButton>
  71. </ButtonWithOptions>
  72. ))}
  73. </DropdownMenu.RadioGroup>
  74. <DropdownMenuDivider />
  75. <DropdownMenuButton onSelect={() => state.send('CREATED_PAGE')}>
  76. <span>Create Page</span>
  77. <IconWrapper size="small">
  78. <PlusIcon />
  79. </IconWrapper>
  80. </DropdownMenuButton>
  81. </MenuContent>
  82. </DropdownMenu.Root>
  83. )
  84. }
  85. const ButtonWithOptions = styled('div', {
  86. display: 'grid',
  87. gridTemplateColumns: '1fr auto',
  88. gridAutoFlow: 'column',
  89. '& > *[data-shy="true"]': {
  90. opacity: 0,
  91. },
  92. '&:hover > *[data-shy="true"]': {
  93. opacity: 1,
  94. },
  95. })