123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- import useShapeEvents from 'hooks/useShapeEvents'
- import { Shape as _Shape, ShapeType, TextShape } from 'types'
- import { getShapeUtils } from 'state/shape-utils'
- import { shallowEqual } from 'utils'
- import { memo, useRef } from 'react'
- import styled from 'styles'
-
- interface ShapeProps {
- shape: _Shape
- isEditing: boolean
- isHovered: boolean
- isSelected: boolean
- isDarkMode: boolean
- isCurrentParent: boolean
- }
-
- const Shape = memo(
- ({
- shape,
- isEditing,
- isHovered,
- isSelected,
- isDarkMode,
- isCurrentParent,
- }: ShapeProps) => {
- const rGroup = useRef<SVGGElement>(null)
- const events = useShapeEvents(shape.id, isCurrentParent, rGroup)
- const utils = getShapeUtils(shape)
-
- const center = utils.getCenter(shape)
- const rotation = shape.rotation * (180 / Math.PI)
- const transform = `rotate(${rotation}, ${center}) translate(${shape.point})`
-
- return (
- <ShapeGroup
- ref={rGroup}
- id={shape.id}
- transform={transform}
- isCurrentParent={isCurrentParent}
- filter={isHovered ? 'url(#expand)' : 'none'}
- {...events}
- >
- {isEditing && shape.type === ShapeType.Text ? (
- <EditingTextShape shape={shape} isDarkMode={isDarkMode} />
- ) : (
- <RenderedShape
- shape={shape}
- isEditing={isEditing}
- isHovered={isHovered}
- isSelected={isSelected}
- isDarkMode={isDarkMode}
- isCurrentParent={isCurrentParent}
- />
- )}
- </ShapeGroup>
- )
- },
- shallowEqual
- )
-
- export default Shape
-
- interface RenderedShapeProps {
- shape: _Shape
- isEditing: boolean
- isHovered: boolean
- isSelected: boolean
- isDarkMode: boolean
- isCurrentParent: boolean
- }
-
- const RenderedShape = memo(
- function RenderedShape({
- shape,
- isEditing,
- isHovered,
- isSelected,
- isDarkMode,
- isCurrentParent,
- }: RenderedShapeProps) {
- return getShapeUtils(shape).render(shape, {
- isEditing,
- isHovered,
- isSelected,
- isDarkMode,
- isCurrentParent,
- })
- },
- (prev, next) => {
- if (
- prev.isEditing !== next.isEditing ||
- prev.isHovered !== next.isHovered ||
- prev.isSelected !== next.isSelected ||
- prev.isDarkMode !== next.isDarkMode ||
- prev.isCurrentParent !== next.isCurrentParent
- ) {
- return false
- }
-
- if (next.shape !== prev.shape) {
- return !getShapeUtils(next.shape).shouldRender(next.shape, prev.shape)
- }
-
- return true
- }
- )
-
- function EditingTextShape({
- shape,
- isDarkMode,
- }: {
- shape: TextShape
- isDarkMode: boolean
- }) {
- const ref = useRef<HTMLTextAreaElement>(null)
-
- return getShapeUtils(shape).render(shape, {
- ref,
- isEditing: true,
- isHovered: false,
- isSelected: false,
- isDarkMode,
- isCurrentParent: false,
- })
- }
-
- const ShapeGroup = styled('g', {
- outline: 'none',
-
- '& > *[data-shy=true]': {
- opacity: 0,
- },
-
- '&:hover': {
- '& > *[data-shy=true]': {
- opacity: 1,
- },
- },
-
- variants: {
- isCurrentParent: {
- true: {
- '& > *[data-shy=true]': {
- opacity: 1,
- },
- },
- },
- },
- })
|