|
@@ -4,18 +4,19 @@ import {
|
|
|
TLContextBarComponent,
|
|
TLContextBarComponent,
|
|
|
useApp,
|
|
useApp,
|
|
|
getContextBarTranslation,
|
|
getContextBarTranslation,
|
|
|
|
|
+ useRendererContext,
|
|
|
} from '@tldraw/react'
|
|
} from '@tldraw/react'
|
|
|
import { observer } from 'mobx-react-lite'
|
|
import { observer } from 'mobx-react-lite'
|
|
|
import type { TextShape, PolygonShape, Shape } from '~lib/shapes'
|
|
import type { TextShape, PolygonShape, Shape } from '~lib/shapes'
|
|
|
import { NumberInput } from '~components/inputs/NumberInput'
|
|
import { NumberInput } from '~components/inputs/NumberInput'
|
|
|
import { ColorInput } from '~components/inputs/ColorInput'
|
|
import { ColorInput } from '~components/inputs/ColorInput'
|
|
|
|
|
|
|
|
-const _ContextBar: TLContextBarComponent<Shape> = ({
|
|
|
|
|
- shapes,
|
|
|
|
|
- offset,
|
|
|
|
|
- scaledBounds,
|
|
|
|
|
- // rotation,
|
|
|
|
|
-}) => {
|
|
|
|
|
|
|
+const _ContextBar: TLContextBarComponent<Shape> = ({ shapes, offsets }) => {
|
|
|
|
|
+ const {
|
|
|
|
|
+ viewport: {
|
|
|
|
|
+ camera: { zoom },
|
|
|
|
|
+ },
|
|
|
|
|
+ } = useRendererContext()
|
|
|
const app = useApp()
|
|
const app = useApp()
|
|
|
const rSize = React.useRef<[number, number] | null>(null)
|
|
const rSize = React.useRef<[number, number] | null>(null)
|
|
|
const rContextBar = React.useRef<HTMLDivElement>(null)
|
|
const rContextBar = React.useRef<HTMLDivElement>(null)
|
|
@@ -63,9 +64,18 @@ const _ContextBar: TLContextBarComponent<Shape> = ({
|
|
|
const elm = rContextBar.current
|
|
const elm = rContextBar.current
|
|
|
if (!elm) return
|
|
if (!elm) return
|
|
|
const size = rSize.current ?? [0, 0]
|
|
const size = rSize.current ?? [0, 0]
|
|
|
- const [x, y] = getContextBarTranslation(size, { ...offset, bottom: offset.bottom - 32 })
|
|
|
|
|
|
|
+ const vpOffsets = {
|
|
|
|
|
+ left: offsets.left / zoom,
|
|
|
|
|
+ right: offsets.right / zoom,
|
|
|
|
|
+ top: offsets.top / zoom,
|
|
|
|
|
+ bottom: offsets.bottom / zoom,
|
|
|
|
|
+ width: offsets.width / zoom,
|
|
|
|
|
+ height: offsets.height / zoom,
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const [x, y] = getContextBarTranslation(size, { ...vpOffsets, bottom: vpOffsets.bottom - 32 })
|
|
|
elm.style.setProperty('transform', `translateX(${x}px) translateY(${y}px)`)
|
|
elm.style.setProperty('transform', `translateX(${x}px) translateY(${y}px)`)
|
|
|
- }, [offset])
|
|
|
|
|
|
|
+ }, [offsets, zoom])
|
|
|
|
|
|
|
|
if (!app) return null
|
|
if (!app) return null
|
|
|
|
|
|
|
@@ -79,65 +89,67 @@ const _ContextBar: TLContextBarComponent<Shape> = ({
|
|
|
return (
|
|
return (
|
|
|
<HTMLContainer centered>
|
|
<HTMLContainer centered>
|
|
|
<div ref={rContextBar} className="contextbar">
|
|
<div ref={rContextBar} className="contextbar">
|
|
|
- {ShapeContent ? (
|
|
|
|
|
- <ShapeContent />
|
|
|
|
|
- ) : (
|
|
|
|
|
- <>
|
|
|
|
|
- <ColorInput label="Stroke" value={shapes[0].props.stroke} onChange={updateStroke} />
|
|
|
|
|
- <ColorInput label="Fill" value={shapes[0].props.fill} onChange={updateFill} />
|
|
|
|
|
- <NumberInput
|
|
|
|
|
- label="Width"
|
|
|
|
|
- value={Math.max(...shapes.map(shape => shape.props.strokeWidth))}
|
|
|
|
|
- onChange={updateStrokeWidth}
|
|
|
|
|
- style={{ width: 48 }}
|
|
|
|
|
- />
|
|
|
|
|
- {sidesShapes.length > 0 && (
|
|
|
|
|
|
|
+ <div style={{ transform: `scale(var(--tl-scale))` }}>
|
|
|
|
|
+ {ShapeContent ? (
|
|
|
|
|
+ <ShapeContent />
|
|
|
|
|
+ ) : (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <ColorInput label="Stroke" value={shapes[0].props.stroke} onChange={updateStroke} />
|
|
|
|
|
+ <ColorInput label="Fill" value={shapes[0].props.fill} onChange={updateFill} />
|
|
|
<NumberInput
|
|
<NumberInput
|
|
|
- label="Sides"
|
|
|
|
|
- value={Math.max(...sidesShapes.map(shape => shape.props.sides))}
|
|
|
|
|
- onChange={updateSides}
|
|
|
|
|
- style={{ width: 40 }}
|
|
|
|
|
|
|
+ label="Width"
|
|
|
|
|
+ value={Math.max(...shapes.map(shape => shape.props.strokeWidth))}
|
|
|
|
|
+ onChange={updateStrokeWidth}
|
|
|
|
|
+ style={{ width: 48 }}
|
|
|
/>
|
|
/>
|
|
|
- )}
|
|
|
|
|
- {sidesShapes.length > 0 && (
|
|
|
|
|
- <NumberInput
|
|
|
|
|
- label="Ratio"
|
|
|
|
|
- value={Math.max(...sidesShapes.map(shape => shape.props.ratio))}
|
|
|
|
|
- onChange={updateRatio}
|
|
|
|
|
- step={0.1}
|
|
|
|
|
- min={0}
|
|
|
|
|
- max={2}
|
|
|
|
|
- style={{ width: 40 }}
|
|
|
|
|
- />
|
|
|
|
|
- )}
|
|
|
|
|
- <NumberInput
|
|
|
|
|
- label="Opacity"
|
|
|
|
|
- value={Math.max(...shapes.map(shape => shape.props.opacity))}
|
|
|
|
|
- onChange={updateOpacity}
|
|
|
|
|
- step={0.1}
|
|
|
|
|
- style={{ width: 48 }}
|
|
|
|
|
- />
|
|
|
|
|
- {textShapes.length > 0 ? (
|
|
|
|
|
- <>
|
|
|
|
|
|
|
+ {sidesShapes.length > 0 && (
|
|
|
<NumberInput
|
|
<NumberInput
|
|
|
- label="Size"
|
|
|
|
|
- value={Math.max(...textShapes.map(shape => shape.props.fontSize))}
|
|
|
|
|
- onChange={updateFontSize}
|
|
|
|
|
- style={{ width: 48 }}
|
|
|
|
|
|
|
+ label="Sides"
|
|
|
|
|
+ value={Math.max(...sidesShapes.map(shape => shape.props.sides))}
|
|
|
|
|
+ onChange={updateSides}
|
|
|
|
|
+ style={{ width: 40 }}
|
|
|
/>
|
|
/>
|
|
|
|
|
+ )}
|
|
|
|
|
+ {sidesShapes.length > 0 && (
|
|
|
<NumberInput
|
|
<NumberInput
|
|
|
- label=" Weight"
|
|
|
|
|
- value={Math.max(...textShapes.map(shape => shape.props.fontWeight))}
|
|
|
|
|
- onChange={updateFontWeight}
|
|
|
|
|
- style={{ width: 48 }}
|
|
|
|
|
|
|
+ label="Ratio"
|
|
|
|
|
+ value={Math.max(...sidesShapes.map(shape => shape.props.ratio))}
|
|
|
|
|
+ onChange={updateRatio}
|
|
|
|
|
+ step={0.1}
|
|
|
|
|
+ min={0}
|
|
|
|
|
+ max={2}
|
|
|
|
|
+ style={{ width: 40 }}
|
|
|
/>
|
|
/>
|
|
|
- </>
|
|
|
|
|
- ) : null}
|
|
|
|
|
- </>
|
|
|
|
|
- )}
|
|
|
|
|
- <a className="shape-link" onClick={() => app.pubEvent('whiteboard-link', shapes)}>
|
|
|
|
|
- Link
|
|
|
|
|
- </a>
|
|
|
|
|
|
|
+ )}
|
|
|
|
|
+ <NumberInput
|
|
|
|
|
+ label="Opacity"
|
|
|
|
|
+ value={Math.max(...shapes.map(shape => shape.props.opacity))}
|
|
|
|
|
+ onChange={updateOpacity}
|
|
|
|
|
+ step={0.1}
|
|
|
|
|
+ style={{ width: 48 }}
|
|
|
|
|
+ />
|
|
|
|
|
+ {textShapes.length > 0 ? (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <NumberInput
|
|
|
|
|
+ label="Size"
|
|
|
|
|
+ value={Math.max(...textShapes.map(shape => shape.props.fontSize))}
|
|
|
|
|
+ onChange={updateFontSize}
|
|
|
|
|
+ style={{ width: 48 }}
|
|
|
|
|
+ />
|
|
|
|
|
+ <NumberInput
|
|
|
|
|
+ label=" Weight"
|
|
|
|
|
+ value={Math.max(...textShapes.map(shape => shape.props.fontWeight))}
|
|
|
|
|
+ onChange={updateFontWeight}
|
|
|
|
|
+ style={{ width: 48 }}
|
|
|
|
|
+ />
|
|
|
|
|
+ </>
|
|
|
|
|
+ ) : null}
|
|
|
|
|
+ </>
|
|
|
|
|
+ )}
|
|
|
|
|
+ <a className="shape-link" onClick={() => app.pubEvent('whiteboard-link', shapes)}>
|
|
|
|
|
+ Link
|
|
|
|
|
+ </a>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
</HTMLContainer>
|
|
</HTMLContainer>
|
|
|
)
|
|
)
|