You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tools-panel.tsx 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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': 'medium' }}
  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.Text}
  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. </Container>
  113. <Container>
  114. <Tooltip label="Lock Tool">
  115. <IconButton
  116. bp={{ '@initial': 'mobile', '@sm': 'small' }}
  117. size={{ '@initial': 'small', '@sm': 'small', '@md': 'medium' }}
  118. onClick={selectToolLock}
  119. >
  120. {isToolLocked ? <LockClosedIcon /> : <LockOpen1Icon />}
  121. </IconButton>
  122. </Tooltip>
  123. {isPenLocked && (
  124. <Tooltip label="Unlock Pen">
  125. <IconButton
  126. bp={{ '@initial': 'mobile', '@sm': 'small' }}
  127. size={{ '@initial': 'small', '@sm': 'small', '@md': 'medium' }}
  128. onClick={selectToolLock}
  129. >
  130. <Pencil2Icon />
  131. </IconButton>
  132. </Tooltip>
  133. )}
  134. </Container>
  135. </Flex>
  136. <UndoRedo />
  137. </OuterContainer>
  138. )
  139. }
  140. const OuterContainer = styled('div', {
  141. position: 'fixed',
  142. bottom: 44,
  143. left: 0,
  144. right: 0,
  145. padding: '0 8px 12px 8px',
  146. width: '100%',
  147. display: 'flex',
  148. alignItems: 'flex-end',
  149. justifyContent: 'center',
  150. flexWrap: 'wrap',
  151. gap: 16,
  152. zIndex: 200,
  153. })
  154. const Flex = styled('div', {
  155. display: 'flex',
  156. width: '100%',
  157. padding: '0 4px',
  158. justifyContent: 'space-between',
  159. alignItems: 'flex-end',
  160. variants: {
  161. size: {
  162. small: {
  163. width: 'auto',
  164. padding: '0',
  165. justifyContent: 'center',
  166. '& > *:nth-child(n+2)': {
  167. marginLeft: 16,
  168. },
  169. },
  170. },
  171. },
  172. })
  173. const Container = styled('div', {
  174. position: 'relative',
  175. backgroundColor: '$panel',
  176. borderRadius: '4px',
  177. overflow: 'hidden',
  178. border: '1px solid $panel',
  179. pointerEvents: 'all',
  180. userSelect: 'none',
  181. height: '100%',
  182. display: 'flex',
  183. padding: 4,
  184. boxShadow: '0px 2px 4px rgba(0,0,0,.12)',
  185. '& svg': {
  186. strokeWidth: 0,
  187. },
  188. })