HighlighterShape.tsx 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. /* eslint-disable @typescript-eslint/no-explicit-any */
  2. import * as React from 'react'
  3. import { SvgPathUtils, TLDrawShape, TLDrawShapeProps } from '@tldraw/core'
  4. import { SVGContainer, TLComponentProps } from '@tldraw/react'
  5. import { observer } from 'mobx-react-lite'
  6. import { computed, makeObservable } from 'mobx'
  7. import { CustomStyleProps, withClampedStyles } from './style-props'
  8. export interface HighlighterShapeProps extends TLDrawShapeProps, CustomStyleProps {
  9. type: 'highlighter'
  10. }
  11. export class HighlighterShape extends TLDrawShape<HighlighterShapeProps> {
  12. constructor(props = {} as Partial<HighlighterShapeProps>) {
  13. super(props)
  14. makeObservable(this)
  15. }
  16. static id = 'highlighter'
  17. static defaultProps: HighlighterShapeProps = {
  18. id: 'highlighter',
  19. parentId: 'page',
  20. type: 'highlighter',
  21. point: [0, 0],
  22. points: [],
  23. isComplete: false,
  24. stroke: '#ffcc00',
  25. fill: '#ffffff',
  26. strokeWidth: 2,
  27. opacity: 1,
  28. }
  29. @computed get pointsPath() {
  30. const { points } = this.props
  31. return SvgPathUtils.getCurvedPathForPoints(points)
  32. }
  33. ReactComponent = observer(({ events, isErasing }: TLComponentProps) => {
  34. const {
  35. pointsPath,
  36. props: { stroke, strokeWidth, opacity },
  37. } = this
  38. return (
  39. <SVGContainer {...events} opacity={isErasing ? 0.2 : opacity}>
  40. <path
  41. d={pointsPath}
  42. strokeWidth={strokeWidth * 16}
  43. stroke={stroke}
  44. fill="none"
  45. pointerEvents="all"
  46. strokeLinejoin="round"
  47. strokeLinecap="round"
  48. opacity={0.5}
  49. />
  50. </SVGContainer>
  51. )
  52. })
  53. ReactIndicator = observer(() => {
  54. const { pointsPath } = this
  55. return <path d={pointsPath} fill="none" />
  56. })
  57. validateProps = (props: Partial<HighlighterShapeProps>) => {
  58. props = withClampedStyles(props)
  59. if (props.strokeWidth !== undefined) props.strokeWidth = Math.max(props.strokeWidth, 1)
  60. return props
  61. }
  62. }