您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

tools-panel.tsx 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. import {
  2. CircleIcon,
  3. CursorArrowIcon,
  4. DividerHorizontalIcon,
  5. DotIcon,
  6. LineHeightIcon,
  7. LockClosedIcon,
  8. LockOpen1Icon,
  9. Pencil1Icon,
  10. Pencil2Icon,
  11. SewingPinIcon,
  12. SquareIcon,
  13. } from '@radix-ui/react-icons'
  14. import { IconButton } from 'components/shared'
  15. import React from 'react'
  16. import state, { useSelector } from 'state'
  17. import styled from 'styles'
  18. import { ShapeType } from 'types'
  19. import UndoRedo from './undo-redo'
  20. import Zoom from './zoom'
  21. const selectSelectTool = () => state.send('SELECTED_SELECT_TOOL')
  22. const selectDrawTool = () => state.send('SELECTED_DRAW_TOOL')
  23. const selectDotTool = () => state.send('SELECTED_DOT_TOOL')
  24. const selectCircleTool = () => state.send('SELECTED_CIRCLE_TOOL')
  25. const selectEllipseTool = () => state.send('SELECTED_ELLIPSE_TOOL')
  26. const selectRayTool = () => state.send('SELECTED_RAY_TOOL')
  27. const selectLineTool = () => state.send('SELECTED_LINE_TOOL')
  28. const selectPolylineTool = () => state.send('SELECTED_POLYLINE_TOOL')
  29. const selectRectangleTool = () => state.send('SELECTED_RECTANGLE_TOOL')
  30. const selectToolLock = () => state.send('TOGGLED_TOOL_LOCK')
  31. export default function ToolsPanel() {
  32. const activeTool = useSelector((state) =>
  33. state.whenIn({
  34. selecting: 'select',
  35. dot: ShapeType.Dot,
  36. circle: ShapeType.Circle,
  37. ellipse: ShapeType.Ellipse,
  38. ray: ShapeType.Ray,
  39. line: ShapeType.Line,
  40. polyline: ShapeType.Polyline,
  41. rectangle: ShapeType.Rectangle,
  42. draw: ShapeType.Draw,
  43. })
  44. )
  45. const isToolLocked = useSelector((s) => s.data.settings.isToolLocked)
  46. const isPenLocked = useSelector((s) => s.data.settings.isPenLocked)
  47. return (
  48. <OuterContainer>
  49. <Zoom />
  50. <Flex>
  51. <Container>
  52. <IconButton
  53. name="select"
  54. size={{ '@sm': 'small', '@md': 'large' }}
  55. onClick={selectSelectTool}
  56. isActive={activeTool === 'select'}
  57. >
  58. <CursorArrowIcon />
  59. </IconButton>
  60. </Container>
  61. <Container>
  62. <IconButton
  63. name={ShapeType.Draw}
  64. size={{ '@sm': 'small', '@md': 'large' }}
  65. onClick={selectDrawTool}
  66. isActive={activeTool === ShapeType.Draw}
  67. >
  68. <Pencil1Icon />
  69. </IconButton>
  70. <IconButton
  71. name={ShapeType.Rectangle}
  72. size={{ '@sm': 'small', '@md': 'large' }}
  73. onClick={selectRectangleTool}
  74. isActive={activeTool === ShapeType.Rectangle}
  75. >
  76. <SquareIcon />
  77. </IconButton>
  78. <IconButton
  79. name={ShapeType.Circle}
  80. size={{ '@sm': 'small', '@md': 'large' }}
  81. onClick={selectCircleTool}
  82. isActive={activeTool === ShapeType.Circle}
  83. >
  84. <CircleIcon />
  85. </IconButton>
  86. <IconButton
  87. name={ShapeType.Ellipse}
  88. size={{ '@sm': 'small', '@md': 'large' }}
  89. onClick={selectEllipseTool}
  90. isActive={activeTool === ShapeType.Ellipse}
  91. >
  92. <CircleIcon transform="rotate(-45) scale(1, .8)" />
  93. </IconButton>
  94. <IconButton
  95. name={ShapeType.Line}
  96. size={{ '@sm': 'small', '@md': 'large' }}
  97. onClick={selectLineTool}
  98. isActive={activeTool === ShapeType.Line}
  99. >
  100. <DividerHorizontalIcon transform="rotate(-45)" />
  101. </IconButton>
  102. <IconButton
  103. name={ShapeType.Ray}
  104. size={{ '@sm': 'small', '@md': 'large' }}
  105. onClick={selectRayTool}
  106. isActive={activeTool === ShapeType.Ray}
  107. >
  108. <SewingPinIcon transform="rotate(-135)" />
  109. </IconButton>
  110. <IconButton
  111. name={ShapeType.Dot}
  112. size={{ '@sm': 'small', '@md': 'large' }}
  113. onClick={selectDotTool}
  114. isActive={activeTool === ShapeType.Dot}
  115. >
  116. <DotIcon />
  117. </IconButton>
  118. </Container>
  119. <Container>
  120. <IconButton
  121. size={{ '@sm': 'small', '@md': 'large' }}
  122. onClick={selectToolLock}
  123. >
  124. {isToolLocked ? <LockClosedIcon /> : <LockOpen1Icon />}
  125. </IconButton>
  126. {isPenLocked && (
  127. <IconButton
  128. size={{ '@sm': 'small', '@md': 'large' }}
  129. onClick={selectToolLock}
  130. >
  131. <Pencil2Icon />
  132. </IconButton>
  133. )}
  134. </Container>
  135. </Flex>
  136. <UndoRedo />
  137. </OuterContainer>
  138. )
  139. }
  140. const OuterContainer = styled('div', {
  141. position: 'fixed',
  142. bottom: 40,
  143. left: 0,
  144. right: 0,
  145. padding: '0 8px 12px 8px',
  146. width: '100%',
  147. display: 'flex',
  148. alignItems: 'center',
  149. justifyContent: 'center',
  150. flexWrap: 'wrap',
  151. gap: 16,
  152. zIndex: 200,
  153. })
  154. const Flex = styled('div', {
  155. display: 'flex',
  156. '& > *:nth-child(n+2)': {
  157. marginLeft: 16,
  158. },
  159. })
  160. const Container = styled('div', {
  161. position: 'relative',
  162. backgroundColor: '$panel',
  163. borderRadius: '4px',
  164. overflow: 'hidden',
  165. border: '1px solid $border',
  166. pointerEvents: 'all',
  167. userSelect: 'none',
  168. height: '100%',
  169. display: 'flex',
  170. padding: 4,
  171. '& svg': {
  172. strokeWidth: 0,
  173. },
  174. })