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.

canvas.tsx 2.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import { ErrorBoundary } from 'react-error-boundary'
  2. import Bounds from './bounds/bounding-box'
  3. import BoundsBg from './bounds/bounds-bg'
  4. import Brush from './brush'
  5. import ContextMenu from './context-menu/context-menu'
  6. import Coop from './coop/coop'
  7. import Defs from './defs'
  8. import Handles from './bounds/handles'
  9. import Page from './page'
  10. import React, { useRef } from 'react'
  11. import state, { useSelector } from 'state'
  12. import styled from 'styles'
  13. import useCamera from 'hooks/useCamera'
  14. import useCanvasEvents from 'hooks/useCanvasEvents'
  15. import useZoomEvents from 'hooks/useZoomEvents'
  16. function resetError() {
  17. null
  18. }
  19. export default function Canvas(): JSX.Element {
  20. const rCanvas = useRef<SVGSVGElement>(null)
  21. const rGroup = useRef<SVGGElement>(null)
  22. useCamera(rGroup)
  23. useZoomEvents()
  24. const events = useCanvasEvents(rCanvas)
  25. const isReady = useSelector((s) => s.isIn('ready'))
  26. return (
  27. <ContextMenu>
  28. <MainSVG ref={rCanvas} {...events}>
  29. <ErrorBoundary FallbackComponent={ErrorFallback} onReset={resetError}>
  30. <Defs />
  31. {isReady && (
  32. <g ref={rGroup} id="shapes">
  33. <BoundsBg />
  34. <Page />
  35. <Coop />
  36. <Bounds />
  37. <Handles />
  38. <Brush />
  39. </g>
  40. )}
  41. </ErrorBoundary>
  42. </MainSVG>
  43. </ContextMenu>
  44. )
  45. }
  46. const MainSVG = styled('svg', {
  47. position: 'fixed',
  48. overflow: 'hidden',
  49. top: 0,
  50. left: 0,
  51. width: '100%',
  52. height: '100%',
  53. touchAction: 'none',
  54. zIndex: 100,
  55. backgroundColor: '$canvas',
  56. pointerEvents: 'all',
  57. // cursor: 'none',
  58. '& *': {
  59. userSelect: 'none',
  60. },
  61. })
  62. function ErrorFallback({ error, resetErrorBoundary }) {
  63. React.useEffect(() => {
  64. console.error(error)
  65. const copy = 'Sorry, something went wrong. Clear canvas and continue?'
  66. if (window.confirm(copy)) {
  67. state.send('CLEARED_PAGE')
  68. resetErrorBoundary()
  69. }
  70. }, [])
  71. return (
  72. <g>
  73. <text>Oops</text>
  74. </g>
  75. )
  76. }