diff --git a/apps/examples/public/man.png b/apps/examples/public/man.png new file mode 100644 index 000000000..85554ce6e Binary files /dev/null and b/apps/examples/public/man.png differ diff --git a/apps/examples/public/shadow-man.png b/apps/examples/public/shadow-man.png new file mode 100644 index 000000000..9d892a68a Binary files /dev/null and b/apps/examples/public/shadow-man.png differ diff --git a/apps/examples/src/examples/popup-shape/PopupShapeExample.tsx b/apps/examples/src/examples/popup-shape/PopupShapeExample.tsx new file mode 100644 index 000000000..b05fd8615 --- /dev/null +++ b/apps/examples/src/examples/popup-shape/PopupShapeExample.tsx @@ -0,0 +1,25 @@ +import { Tldraw } from 'tldraw' +import 'tldraw/tldraw.css' +import { PopupShapeUtil } from './PopupShapeUtil' + +const customShapeUtils = [PopupShapeUtil] + +export default function PopupShapeExample() { + return ( +
+ { + for (let i = 0; i < 9; i++) { + editor.createShape({ + type: 'my-popup-shape', + x: (i % 3) * 220, + y: Math.floor(i / 3) * 220, + }) + } + editor.zoomToContent({ duration: 0 }) + }} + /> +
+ ) +} diff --git a/apps/examples/src/examples/popup-shape/PopupShapeUtil.tsx b/apps/examples/src/examples/popup-shape/PopupShapeUtil.tsx new file mode 100644 index 000000000..184552e79 --- /dev/null +++ b/apps/examples/src/examples/popup-shape/PopupShapeUtil.tsx @@ -0,0 +1,138 @@ +/* eslint-disable react-hooks/rules-of-hooks */ +import { useEffect, useRef, useState } from 'react' +import { + BaseBoxShapeUtil, + HTMLContainer, + ShapeProps, + T, + TLBaseShape, + stopEventPropagation, +} from 'tldraw' + +type IMyPopupShape = TLBaseShape< + 'my-popup-shape', + { + w: number + h: number + animal: number + } +> + +export class PopupShapeUtil extends BaseBoxShapeUtil { + static override type = 'my-popup-shape' as const + static override props: ShapeProps = { + w: T.number, + h: T.number, + animal: T.number, + } + + getDefaultProps(): IMyPopupShape['props'] { + return { + w: 200, + h: 200, + animal: 0, + } + } + + component(shape: IMyPopupShape) { + const [popped, setPopped] = useState(false) + + const ref = useRef(null) + const ref2 = useRef(null) + + useEffect(() => { + const elm = ref.current + if (!elm) return + const elm2 = ref2.current + if (!elm2) return + if (popped) { + // man + // elm2.style.transform = `rotateX(0deg) translateY(0px) translateZ(0px)` + // note + elm.style.transform = `rotateX(0deg) translateY(0px) translateZ(0px)` + } else { + // man + // elm.style.transform = `rotateX(-50deg) translateY(5px) translateZ(0px)` + // elm2.style.transform = `scaleY(.8)` + // note + elm.style.transform = `rotateX(20deg)` + } + }, [popped]) + + const vpb = this.editor.getViewportPageBounds() + const spb = this.editor.getShapePageBounds(shape)! + const px = vpb.midX - spb.midX + spb.w / 2 + const py = vpb.midY - spb.midY + spb.h / 2 + + return ( + { + setPopped((p) => !p) + stopEventPropagation(e) + }} + > +
+
+ {/* {shape.id.slice(-1).toUpperCase()} */} +
+ + ) + } + + indicator(shape: IMyPopupShape) { + return + } +} diff --git a/apps/examples/src/examples/popup-shape/README.md b/apps/examples/src/examples/popup-shape/README.md new file mode 100644 index 000000000..138491462 --- /dev/null +++ b/apps/examples/src/examples/popup-shape/README.md @@ -0,0 +1,11 @@ +--- +title: Popup shape +component: ./PopupShapeExample.tsx +category: shapes/tools +--- + +... + +--- + +...