PolygonShape.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. /* eslint-disable @typescript-eslint/no-explicit-any */
  2. import { TLPolygonShape, TLPolygonShapeProps } from '@tldraw/core'
  3. import { SVGContainer, TLComponentProps } from '@tldraw/react'
  4. import { observer } from 'mobx-react-lite'
  5. import { CustomStyleProps, withClampedStyles } from './style-props'
  6. import { getComputedColor } from '../color'
  7. interface PolygonShapeProps extends TLPolygonShapeProps, CustomStyleProps {
  8. type: 'polygon'
  9. }
  10. export class PolygonShape extends TLPolygonShape<PolygonShapeProps> {
  11. static id = 'polygon'
  12. static defaultProps: PolygonShapeProps = {
  13. id: 'polygon',
  14. parentId: 'page',
  15. type: 'polygon',
  16. point: [0, 0],
  17. size: [100, 100],
  18. sides: 3,
  19. ratio: 1,
  20. isFlippedY: false,
  21. stroke: '',
  22. fill: '',
  23. noFill: false,
  24. strokeType: 'line',
  25. strokeWidth: 2,
  26. opacity: 1,
  27. }
  28. ReactComponent = observer(({ events, isErasing, isSelected }: TLComponentProps) => {
  29. const {
  30. offset: [x, y],
  31. props: { stroke, fill, noFill, strokeWidth, opacity, strokeType },
  32. } = this
  33. const path = this.getVertices(strokeWidth / 2).join()
  34. return (
  35. <SVGContainer {...events} opacity={isErasing ? 0.2 : opacity}>
  36. <g transform={`translate(${x}, ${y})`}>
  37. <polygon
  38. className={isSelected || !noFill ? 'tl-hitarea-fill' : 'tl-hitarea-stroke'}
  39. points={path}
  40. />
  41. <polygon
  42. points={path}
  43. stroke={getComputedColor(stroke, 'stroke')}
  44. fill={noFill ? 'none' : getComputedColor(fill, 'background')}
  45. strokeWidth={strokeWidth}
  46. rx={2}
  47. ry={2}
  48. strokeLinejoin="round"
  49. strokeDasharray={strokeType === 'dashed' ? '8 2' : undefined}
  50. />
  51. </g>
  52. </SVGContainer>
  53. )
  54. })
  55. ReactIndicator = observer(() => {
  56. const {
  57. offset: [x, y],
  58. props: { strokeWidth },
  59. } = this
  60. return (
  61. <polygon
  62. transform={`translate(${x}, ${y})`}
  63. points={this.getVertices(strokeWidth / 2).join()}
  64. />
  65. )
  66. })
  67. validateProps = (props: Partial<PolygonShapeProps>) => {
  68. if (props.sides !== undefined) props.sides = Math.max(props.sides, 3)
  69. return withClampedStyles(this, props)
  70. }
  71. /**
  72. * Get a svg group element that can be used to render the shape with only the props data. In the
  73. * base, draw any shape as a box. Can be overridden by subclasses.
  74. */
  75. getShapeSVGJsx(opts: any) {
  76. // Do not need to consider the original point here
  77. const {
  78. offset: [x, y],
  79. props: { stroke, fill, noFill, strokeWidth, opacity, strokeType },
  80. } = this
  81. const path = this.getVertices(strokeWidth / 2).join()
  82. return (
  83. <g transform={`translate(${x}, ${y})`} opacity={opacity}>
  84. <polygon className={!noFill ? 'tl-hitarea-fill' : 'tl-hitarea-stroke'} points={path} />
  85. <polygon
  86. points={path}
  87. stroke={getComputedColor(stroke, 'stroke')}
  88. fill={noFill ? 'none' : getComputedColor(fill, 'background')}
  89. strokeWidth={strokeWidth}
  90. rx={2}
  91. ry={2}
  92. strokeLinejoin="round"
  93. strokeDasharray={strokeType === 'dashed' ? '8 2' : undefined}
  94. />
  95. </g>
  96. )
  97. }
  98. }