Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

useKeyboardEvents.ts 8.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
  2. import { useEffect } from 'react'
  3. import state from 'state'
  4. import inputs from 'state/inputs'
  5. import { ColorStyle, MoveType, SizeStyle } from 'types'
  6. import { metaKey } from 'utils'
  7. export default function useKeyboardEvents() {
  8. useEffect(() => {
  9. function handleKeyDown(e: KeyboardEvent) {
  10. const info = inputs.keydown(e)
  11. const meta = metaKey(e)
  12. if (
  13. meta &&
  14. ![
  15. 'a',
  16. 'i',
  17. 'r',
  18. 'j',
  19. 'ArrowLeft',
  20. 'ArrowRight',
  21. 'ArrowUp',
  22. 'ArrowDown',
  23. 'z',
  24. ].includes(e.key)
  25. ) {
  26. e.preventDefault()
  27. }
  28. switch (e.key) {
  29. case '1': {
  30. if (meta) {
  31. state.send('CHANGED_STYLE', { color: ColorStyle.Black })
  32. break
  33. }
  34. if (e.altKey) {
  35. state.send('CHANGED_STYLE', { size: SizeStyle.Small })
  36. break
  37. }
  38. state.send('SELECTED_SELECT_TOOL', info)
  39. break
  40. }
  41. case '2': {
  42. if (meta) {
  43. state.send('CHANGED_STYLE', { color: ColorStyle.White })
  44. break
  45. }
  46. if (e.altKey) {
  47. state.send('CHANGED_STYLE', { size: SizeStyle.Medium })
  48. break
  49. }
  50. state.send('SELECTED_DRAW_TOOL', info)
  51. break
  52. }
  53. case '3': {
  54. if (meta) {
  55. state.send('CHANGED_STYLE', { color: ColorStyle.Green })
  56. break
  57. }
  58. if (e.altKey) {
  59. state.send('CHANGED_STYLE', { size: SizeStyle.Large })
  60. break
  61. }
  62. state.send('SELECTED_RECTANGLE_TOOL', info)
  63. break
  64. }
  65. case '4': {
  66. if (meta) {
  67. state.send('CHANGED_STYLE', { color: ColorStyle.Blue })
  68. }
  69. state.send('SELECTED_ELLIPSE_TOOL', info)
  70. break
  71. }
  72. case '5': {
  73. if (meta) {
  74. state.send('CHANGED_STYLE', { color: ColorStyle.Indigo })
  75. break
  76. }
  77. state.send('SELECTED_ARROW_TOOL', info)
  78. break
  79. }
  80. case '6': {
  81. if (meta) {
  82. state.send('CHANGED_STYLE', { color: ColorStyle.Violet })
  83. break
  84. }
  85. state.send('SELECTED_TEXT_TOOL', info)
  86. break
  87. }
  88. case '7': {
  89. if (meta) {
  90. state.send('CHANGED_STYLE', { color: ColorStyle.Red })
  91. break
  92. }
  93. state.send('TOGGLED_TOOL_LOCK', info)
  94. break
  95. }
  96. case '8': {
  97. if (meta) {
  98. state.send('CHANGED_STYLE', { color: ColorStyle.Orange })
  99. break
  100. }
  101. break
  102. }
  103. case '9': {
  104. if (meta) {
  105. state.send('CHANGED_STYLE', { color: ColorStyle.Yellow })
  106. break
  107. }
  108. break
  109. }
  110. case 'ArrowUp': {
  111. state.send('NUDGED', { delta: [0, -1], ...info })
  112. break
  113. }
  114. case 'ArrowRight': {
  115. state.send('NUDGED', { delta: [1, 0], ...info })
  116. break
  117. }
  118. case 'ArrowDown': {
  119. state.send('NUDGED', { delta: [0, 1], ...info })
  120. break
  121. }
  122. case 'ArrowLeft': {
  123. state.send('NUDGED', { delta: [-1, 0], ...info })
  124. break
  125. }
  126. case '=': {
  127. if (e.metaKey) {
  128. state.send('ZOOMED_IN')
  129. }
  130. break
  131. }
  132. case '-': {
  133. if (e.metaKey) {
  134. state.send('ZOOMED_OUT')
  135. }
  136. break
  137. }
  138. case '!': {
  139. // Shift + 1
  140. if (e.shiftKey) {
  141. state.send('ZOOMED_TO_FIT')
  142. }
  143. break
  144. }
  145. case '@': {
  146. // Shift + 2
  147. if (e.shiftKey) {
  148. state.send('ZOOMED_TO_SELECTION')
  149. }
  150. break
  151. }
  152. case ')': {
  153. // Shift + 0
  154. if (e.shiftKey) {
  155. state.send('ZOOMED_TO_ACTUAL')
  156. }
  157. break
  158. }
  159. case 'Escape': {
  160. state.send('CANCELLED')
  161. break
  162. }
  163. case 'z': {
  164. if (meta) {
  165. if (e.shiftKey) {
  166. state.send('REDO', info)
  167. } else {
  168. state.send('UNDO', info)
  169. }
  170. }
  171. break
  172. }
  173. case '‘': {
  174. if (meta) {
  175. state.send('MOVED', {
  176. ...info,
  177. type: MoveType.ToFront,
  178. })
  179. }
  180. break
  181. }
  182. case '“': {
  183. if (meta) {
  184. state.send('MOVED', {
  185. ...info,
  186. type: MoveType.ToBack,
  187. })
  188. }
  189. break
  190. }
  191. case ']': {
  192. if (meta) {
  193. state.send('MOVED', {
  194. ...info,
  195. type: MoveType.Forward,
  196. })
  197. }
  198. break
  199. }
  200. case '[': {
  201. if (meta) {
  202. state.send('MOVED', {
  203. ...info,
  204. type: MoveType.Backward,
  205. })
  206. }
  207. break
  208. }
  209. case 'Shift': {
  210. state.send('PRESSED_SHIFT_KEY', info)
  211. break
  212. }
  213. case 'Alt': {
  214. state.send('PRESSED_ALT_KEY', info)
  215. break
  216. }
  217. case 'Backspace': {
  218. if (meta) {
  219. if (e.shiftKey) {
  220. if (window.confirm('Reset document and state?')) {
  221. state.send('RESET_DOCUMENT_STATE', info)
  222. }
  223. } else {
  224. state.send('FORCE_CLEARED_PAGE', info)
  225. }
  226. } else {
  227. state.send('DELETED', info)
  228. }
  229. break
  230. }
  231. case 'g': {
  232. if (meta) {
  233. if (e.shiftKey) {
  234. state.send('UNGROUPED', info)
  235. } else {
  236. state.send('GROUPED', info)
  237. }
  238. }
  239. break
  240. }
  241. case 's': {
  242. if (meta) {
  243. if (e.shiftKey) {
  244. state.send('SAVED_AS_TO_FILESYSTEM', info)
  245. } else {
  246. state.send('SAVED', info)
  247. }
  248. }
  249. break
  250. }
  251. case 'o': {
  252. if (meta) {
  253. break
  254. } else {
  255. state.send('SELECTED_DOT_TOOL', info)
  256. }
  257. break
  258. }
  259. case 'v': {
  260. if (meta) {
  261. state.send('PASTED', info)
  262. } else {
  263. state.send('SELECTED_SELECT_TOOL', info)
  264. }
  265. break
  266. }
  267. case 'a': {
  268. if (meta) {
  269. state.send('SELECTED_ALL', info)
  270. } else {
  271. state.send('SELECTED_ARROW_TOOL', info)
  272. }
  273. break
  274. }
  275. case 'd': {
  276. if (meta) {
  277. state.send('DUPLICATED', info)
  278. } else {
  279. state.send('SELECTED_DRAW_TOOL', info)
  280. }
  281. break
  282. }
  283. case 't': {
  284. state.send('SELECTED_TEXT_TOOL', info)
  285. break
  286. }
  287. case 'c': {
  288. if (meta) {
  289. if (e.shiftKey) {
  290. state.send('COPIED_TO_SVG', info)
  291. } else {
  292. state.send('COPIED', info)
  293. }
  294. } else {
  295. state.send('SELECTED_ELLIPSE_TOOL', info)
  296. }
  297. break
  298. }
  299. case 'i': {
  300. if (meta) {
  301. break
  302. } else {
  303. state.send('SELECTED_CIRCLE_TOOL', info)
  304. }
  305. break
  306. }
  307. case 'l': {
  308. if (meta) {
  309. if (e.shiftKey) {
  310. state.send('TOGGLED_LOGGER')
  311. } else {
  312. state.send('LOADED_FROM_FILE_STSTEM', info)
  313. }
  314. } else {
  315. state.send('SELECTED_LINE_TOOL', info)
  316. }
  317. break
  318. }
  319. case 'y': {
  320. if (meta) {
  321. break
  322. } else {
  323. state.send('SELECTED_RAY_TOOL', info)
  324. }
  325. break
  326. }
  327. case 'p': {
  328. if (meta) {
  329. break
  330. } else {
  331. state.send('SELECTED_POLYLINE_TOOL', info)
  332. }
  333. break
  334. }
  335. case 'r': {
  336. if (meta) {
  337. break
  338. } else {
  339. state.send('SELECTED_RECTANGLE_TOOL', info)
  340. }
  341. break
  342. }
  343. case '|': {
  344. state.send('COPIED_STATE_TO_CLIPBOARD')
  345. break
  346. }
  347. default: {
  348. null
  349. }
  350. }
  351. }
  352. function handleKeyUp(e: KeyboardEvent) {
  353. const info = inputs.keyup(e)
  354. if (e.key === 'Shift') {
  355. state.send('RELEASED_SHIFT_KEY', info)
  356. }
  357. if (e.key === 'Alt') {
  358. state.send('RELEASED_ALT_KEY', info)
  359. }
  360. }
  361. window.addEventListener('keydown', handleKeyDown)
  362. window.addEventListener('keyup', handleKeyUp)
  363. return () => {
  364. window.removeEventListener('keydown', handleKeyDown)
  365. window.removeEventListener('keyup', handleKeyUp)
  366. }
  367. }, [])
  368. }