Browse Source

wip: clone handlers

Konstantinos Kaloutas 2 years ago
parent
commit
dbe70278f5

+ 4 - 0
tldraw/packages/react/src/components/Canvas/Canvas.tsx

@@ -33,6 +33,7 @@ import { Indicator } from '../Indicator'
 import { QuickLinksContainer } from '../QuickLinksContainer'
 import { BacklinksCountContainer } from '../BacklinksCountContainer'
 import { SelectionDetailContainer } from '../SelectionDetailContainer'
+import { CloneButtonsContainer } from '../CloneButtonsContainer'
 import { Shape } from '../Shape'
 import { SVGContainer } from '../SVGContainer'
 import { DirectionIndicator } from '../ui'
@@ -184,6 +185,9 @@ export const Canvas = observer(function Renderer<S extends TLReactShape>({
           {hoveredShape && hoveredShape !== singleSelectedShape && components.QuickLinks && (
             <QuickLinksContainer hidden={false} bounds={hoveredShape.bounds} shape={hoveredShape} />
           )}
+          {singleSelectedShape && components.QuickLinks && (
+            <CloneButtonsContainer hidden={false} bounds={singleSelectedShape.bounds} shape={singleSelectedShape} />
+          )}
           {brush && components.Brush && <components.Brush bounds={brush} />}
           {selectedShapes && selectionBounds && (
             <>

+ 63 - 0
tldraw/packages/react/src/components/CloneButtonsContainer/CloneButtonsContainer.tsx

@@ -0,0 +1,63 @@
+import type { TLBounds } from '@tldraw/core'
+import { observer } from 'mobx-react-lite'
+import { useApp, useRendererContext } from '../../hooks'
+import { useShapeEvents } from '../../hooks/useShapeEvents'
+import type { TLReactShape } from '../../lib'
+import { Container } from '../Container'
+import { HTMLContainer } from '../HTMLContainer'
+
+export interface TLCloneButtonsContainerProps<S extends TLReactShape> {
+  hidden: boolean
+  bounds: TLBounds
+  shape: S
+}
+
+// backlinks
+export const CloneButtonsContainer = observer(function CloneButtonsContainer<S extends TLReactShape>({
+  bounds,
+  shape,
+}: TLCloneButtonsContainerProps<S>) {
+  const {
+    viewport: {
+      camera: { zoom },
+    },
+    components: { CloneButton },
+  } = useRendererContext()
+
+  const app = useApp<S>()
+
+  const events = useShapeEvents(shape)
+
+  if (!CloneButton) throw Error('Expected a QuickLinks component.')
+
+  const stop: React.EventHandler<any> = e => e.stopPropagation()
+
+  const rounded = bounds.height * zoom < 50 || !app.selectedShapesArray.includes(shape)
+
+  return (
+    <Container bounds={bounds} className="tl-quick-links-container" data-html2canvas-ignore="true">
+      <HTMLContainer>
+        <span
+          style={{
+            position: 'absolute',
+            top: '100%',
+            pointerEvents: 'all',
+            transformOrigin: 'left top',
+            paddingTop: '8px',
+            // anti-scale the container so that it always show in 100% for the user
+            transform: 'scale(var(--tl-scale))',
+            // Make it a little bit easier to click
+            minWidth: '320px',
+          }}
+          {...events}
+          onPointerDown={stop}
+        >
+          <CloneButton
+            direction={"left"}
+            shape={shape}
+          />
+        </span>
+      </HTMLContainer>
+    </Container>
+  )
+})

+ 1 - 0
tldraw/packages/react/src/components/CloneButtonsContainer/index.ts

@@ -0,0 +1 @@
+export * from './CloneButtonsContainer'

+ 3 - 0
tldraw/packages/react/src/components/Renderer/RendererContext.tsx

@@ -14,6 +14,7 @@ import {
   Grid as _Grid,
   Brush as _Brush,
   Handle as _Handle,
+  CloneButton as _CloneButton,
   DirectionIndicator as _DirectionIndicator,
 } from '../../components'
 
@@ -56,6 +57,7 @@ export const RendererContext = observer(function App<S extends TLReactShape>({
       DirectionIndicator,
       Grid,
       Handle,
+      CloneButton,
       SelectionBackground,
       SelectionDetail,
       SelectionForeground,
@@ -72,6 +74,7 @@ export const RendererContext = observer(function App<S extends TLReactShape>({
         ...rest,
         Brush: Brush === null ? undefined : _Brush,
         ContextBar,
+        CloneButton,
         DirectionIndicator: DirectionIndicator === null ? undefined : _DirectionIndicator,
         Grid: Grid === null ? undefined : _Grid,
         Handle: Handle === null ? undefined : _Handle,

+ 14 - 0
tldraw/packages/react/src/components/ui/CloneButton/CloneButton.tsx

@@ -0,0 +1,14 @@
+import { observer } from 'mobx-react-lite'
+import type { TLReactShape } from '../../../lib'
+import type { TLCloneButtonComponentProps } from '../../../types'
+
+export const CloneButton = observer(function Handle<S extends TLReactShape>({
+  shape,
+  direction,
+}: TLCloneButtonComponentProps<S>) {
+
+  return (
+    <g className="tl-clone-button" aria-label="handle"  transform={`translate()`}>
+    </g>
+  )
+})

+ 1 - 0
tldraw/packages/react/src/components/ui/CloneButton/index.ts

@@ -0,0 +1 @@
+export * from './CloneButton'

+ 1 - 0
tldraw/packages/react/src/components/ui/index.ts

@@ -6,3 +6,4 @@ export * from './Brush'
 export * from './Cursor'
 export * from './Handle'
 export * from './DirectionIndicator'
+export * from './CloneButton'

+ 10 - 0
tldraw/packages/react/src/types/component-props.ts

@@ -98,6 +98,15 @@ export interface TLGridProps {
 
 export type TLGridComponent = (props: TLGridProps) => JSX.Element | null
 
+export interface TLCloneButtonComponentProps<
+  S extends TLReactShape = TLReactShape
+> {
+  shape: S
+  direction: string
+}
+
+export type TLCloneButtonComponent = (props: TLCloneButtonComponentProps) => JSX.Element | null
+
 export type TLReactComponents<S extends TLReactShape = TLReactShape> = {
   SelectionBackground?: TLBoundsComponent<S> | null
   SelectionForeground?: TLBoundsComponent<S> | null
@@ -109,4 +118,5 @@ export type TLReactComponents<S extends TLReactShape = TLReactShape> = {
   ContextBar?: TLContextBarComponent<S> | null
   Brush?: TLBrushComponent | null
   Grid?: TLGridComponent | null
+  CloneButton?: TLCloneButtonComponent | null
 }