選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

tools-panel.tsx 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. import {
  2. ArrowTopRightIcon,
  3. CircleIcon,
  4. CursorArrowIcon,
  5. DividerHorizontalIcon,
  6. DotIcon,
  7. LockClosedIcon,
  8. LockOpen1Icon,
  9. Pencil1Icon,
  10. Pencil2Icon,
  11. SewingPinIcon,
  12. SquareIcon,
  13. TextIcon,
  14. } from '@radix-ui/react-icons'
  15. import { IconButton } from 'components/shared'
  16. import React from 'react'
  17. import state, { useSelector } from 'state'
  18. import styled from 'styles'
  19. import { ShapeType } from 'types'
  20. import UndoRedo from './undo-redo'
  21. import Zoom from './zoom'
  22. import Tooltip from '../tooltip'
  23. const selectArrowTool = () => state.send('SELECTED_ARROW_TOOL')
  24. const selectCircleTool = () => state.send('SELECTED_CIRCLE_TOOL')
  25. const selectDotTool = () => state.send('SELECTED_DOT_TOOL')
  26. const selectDrawTool = () => state.send('SELECTED_DRAW_TOOL')
  27. const selectEllipseTool = () => state.send('SELECTED_ELLIPSE_TOOL')
  28. const selectLineTool = () => state.send('SELECTED_LINE_TOOL')
  29. const selectPolylineTool = () => state.send('SELECTED_POLYLINE_TOOL')
  30. const selectTextTool = () => state.send('SELECTED_TEXT_TOOL')
  31. const selectRayTool = () => state.send('SELECTED_RAY_TOOL')
  32. const selectRectangleTool = () => state.send('SELECTED_RECTANGLE_TOOL')
  33. const selectSelectTool = () => state.send('SELECTED_SELECT_TOOL')
  34. const selectToolLock = () => state.send('TOGGLED_TOOL_LOCK')
  35. export default function ToolsPanel() {
  36. const activeTool = useSelector((s) => s.data.activeTool)
  37. const isToolLocked = useSelector((s) => s.data.settings.isToolLocked)
  38. const isPenLocked = useSelector((s) => s.data.settings.isPenLocked)
  39. return (
  40. <OuterContainer>
  41. <Zoom />
  42. <Flex size={{ '@sm': 'small' }}>
  43. <Container>
  44. <Tooltip label="Select">
  45. <IconButton
  46. name="select"
  47. bp={{ '@initial': 'mobile', '@sm': 'small' }}
  48. size={{ '@initial': 'small', '@sm': 'small', '@md': 'large' }}
  49. onClick={selectSelectTool}
  50. isActive={activeTool === 'select'}
  51. >
  52. <CursorArrowIcon />
  53. </IconButton>
  54. </Tooltip>
  55. </Container>
  56. <Container>
  57. <Tooltip label="Draw">
  58. <IconButton
  59. name={ShapeType.Draw}
  60. bp={{ '@initial': 'mobile', '@sm': 'small' }}
  61. size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
  62. onClick={selectDrawTool}
  63. isActive={activeTool === ShapeType.Draw}
  64. >
  65. <Pencil1Icon />
  66. </IconButton>
  67. </Tooltip>
  68. <Tooltip label="Rectangle">
  69. <IconButton
  70. name={ShapeType.Rectangle}
  71. bp={{ '@initial': 'mobile', '@sm': 'small' }}
  72. size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
  73. onClick={selectRectangleTool}
  74. isActive={activeTool === ShapeType.Rectangle}
  75. >
  76. <SquareIcon />
  77. </IconButton>
  78. </Tooltip>
  79. <Tooltip label="Ellipse">
  80. <IconButton
  81. name={ShapeType.Circle}
  82. bp={{ '@initial': 'mobile', '@sm': 'small' }}
  83. size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
  84. onClick={selectEllipseTool}
  85. isActive={activeTool === ShapeType.Ellipse}
  86. >
  87. <CircleIcon />
  88. </IconButton>
  89. </Tooltip>
  90. <Tooltip label="Arrow">
  91. <IconButton
  92. name={ShapeType.Arrow}
  93. bp={{ '@initial': 'mobile', '@sm': 'small' }}
  94. size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
  95. onClick={selectArrowTool}
  96. isActive={activeTool === ShapeType.Arrow}
  97. >
  98. <ArrowTopRightIcon />
  99. </IconButton>
  100. </Tooltip>
  101. <Tooltip label="Text">
  102. <IconButton
  103. name={ShapeType.Arrow}
  104. bp={{ '@initial': 'mobile', '@sm': 'small' }}
  105. size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
  106. onClick={selectTextTool}
  107. isActive={activeTool === ShapeType.Text}
  108. >
  109. <TextIcon />
  110. </IconButton>
  111. </Tooltip>
  112. {/* <IconButton
  113. name={ShapeType.Circle}
  114. size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
  115. onClick={selectCircleTool}
  116. isActive={activeTool === ShapeType.Circle}
  117. >
  118. <CircleIcon />
  119. </IconButton> */}
  120. {/* <IconButton
  121. name={ShapeType.Line}
  122. size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
  123. onClick={selectLineTool}
  124. isActive={activeTool === ShapeType.Line}
  125. >
  126. <DividerHorizontalIcon transform="rotate(-45)" />
  127. </IconButton>
  128. <IconButton
  129. name={ShapeType.Ray}
  130. size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
  131. onClick={selectRayTool}
  132. isActive={activeTool === ShapeType.Ray}
  133. >
  134. <SewingPinIcon transform="rotate(-135)" />
  135. </IconButton>
  136. <IconButton
  137. name={ShapeType.Dot}
  138. size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
  139. onClick={selectDotTool}
  140. isActive={activeTool === ShapeType.Dot}
  141. >
  142. <DotIcon />
  143. </IconButton> */}
  144. </Container>
  145. <Container>
  146. <Tooltip label="Lock Tool">
  147. <IconButton
  148. bp={{ '@initial': 'mobile', '@sm': 'small' }}
  149. size={{ '@initial': 'small', '@sm': 'small', '@md': 'large' }}
  150. onClick={selectToolLock}
  151. >
  152. {isToolLocked ? <LockClosedIcon /> : <LockOpen1Icon />}
  153. </IconButton>
  154. </Tooltip>
  155. {isPenLocked && (
  156. <Tooltip label="Unlock Pen">
  157. <IconButton
  158. bp={{ '@initial': 'mobile', '@sm': 'small' }}
  159. size={{ '@initial': 'small', '@sm': 'small', '@md': 'large' }}
  160. onClick={selectToolLock}
  161. >
  162. <Pencil2Icon />
  163. </IconButton>
  164. </Tooltip>
  165. )}
  166. </Container>
  167. </Flex>
  168. <UndoRedo />
  169. </OuterContainer>
  170. )
  171. }
  172. const OuterContainer = styled('div', {
  173. position: 'fixed',
  174. bottom: 40,
  175. left: 0,
  176. right: 0,
  177. padding: '0 8px 12px 8px',
  178. width: '100%',
  179. display: 'flex',
  180. alignItems: 'flex-end',
  181. justifyContent: 'center',
  182. flexWrap: 'wrap',
  183. gap: 16,
  184. zIndex: 200,
  185. })
  186. const Flex = styled('div', {
  187. display: 'flex',
  188. width: '100%',
  189. padding: '0 4px',
  190. justifyContent: 'space-between',
  191. alignItems: 'flex-end',
  192. variants: {
  193. size: {
  194. small: {
  195. width: 'auto',
  196. padding: '0',
  197. justifyContent: 'center',
  198. '& > *:nth-child(n+2)': {
  199. marginLeft: 16,
  200. },
  201. },
  202. },
  203. },
  204. })
  205. const Container = styled('div', {
  206. position: 'relative',
  207. backgroundColor: '$panel',
  208. borderRadius: '4px',
  209. overflow: 'hidden',
  210. border: '1px solid $panel',
  211. pointerEvents: 'all',
  212. userSelect: 'none',
  213. height: '100%',
  214. display: 'flex',
  215. padding: 4,
  216. boxShadow: '0px 2px 4px rgba(0,0,0,.12)',
  217. '& svg': {
  218. strokeWidth: 0,
  219. },
  220. })