[chore] remove mobx (#961)

* remove mobx as dependency

* fix bugs
add-postinstall
Steve Ruiz 2022-09-08 09:38:28 +01:00 zatwierdzone przez GitHub
rodzic c3ff5a51bf
commit d0cd924ca7
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
58 zmienionych plików z 521 dodań i 523 usunięć

Wyświetl plik

@ -24,8 +24,6 @@
"concurrently": "^7.0.0",
"esbuild": "^0.14.54",
"esbuild-serve": "^1.0.1",
"mobx": "^6.3.13",
"mobx-react-lite": "^3.2.3",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},

Wyświetl plik

@ -1,5 +1,4 @@
import { Renderer, TLPointerEventHandler, TLShapeUtilsMap } from '@tldraw/core'
import { observer } from 'mobx-react-lite'
import { Renderer, TLPointerEventHandler } from '@tldraw/core'
import * as React from 'react'
import { RectUtil, Shape } from './shapes'
import { Page, PageState } from './stores'
@ -23,11 +22,11 @@ const page = new Page({
const pageState = new PageState()
const shapeUtils: TLShapeUtilsMap<Shape> = {
const shapeUtils = {
rect: new RectUtil(),
}
export default observer(function App() {
export default function App() {
const onHoverShape: TLPointerEventHandler = (e) => {
pageState.setHoveredId(e.target)
}
@ -113,4 +112,4 @@ export default observer(function App() {
/>
</div>
)
})
}

Wyświetl plik

@ -1,6 +1,5 @@
import { TLBounds, TLPage, TLPageState, Utils } from '@tldraw/core'
import Vec from '@tldraw/vec'
import { action, makeAutoObservable } from 'mobx'
import type { Shape } from './shapes'
export class Page implements TLPage<Shape> {
@ -15,10 +14,9 @@ export class Page implements TLPage<Shape> {
this.name = name
this.shapes = shapes
this.bindings = bindings
makeAutoObservable(this)
}
@action dragShape(id: string, point: number[]) {
dragShape(id: string, point: number[]) {
const shape = this.shapes[id]
shape.point = Vec.sub(point, Vec.div(shape.size, 2))
}
@ -46,24 +44,23 @@ export class PageState implements TLPageState {
this.id = id
this.camera = camera
this.selectedIds = selectedIds
makeAutoObservable(this)
}
@action setHoveredId = (id: string | undefined) => {
setHoveredId = (id: string | undefined) => {
this.hoveredId = id
}
@action setSelectedIds = (id: string) => {
setSelectedIds = (id: string) => {
if (!this.selectedIds.includes(id)) {
this.selectedIds = [id]
}
}
@action clearSelectedIds = () => {
clearSelectedIds = () => {
this.selectedIds = []
}
@action pan = (point: number[]) => {
pan = (point: number[]) => {
this.camera.point = Vec.add(this.camera.point, point)
}
}

Wyświetl plik

@ -57,7 +57,6 @@
"init-package-json": "^2.0.5",
"jest": "^27.4.7",
"lint-staged": "^12.3.3",
"mobx": "^6.3.8",
"prettier": "^2.7.1",
"resize-observer-polyfill": "^1.5.1",
"source-map-loader": "^3.0.1",

Wyświetl plik

@ -35,7 +35,6 @@
"@tldraw/intersect": "^1.7.1",
"@tldraw/vec": "^1.7.1",
"@use-gesture/react": "^10.2.14",
"mobx-react-lite": "^3.2.3",
"perfect-freehand": "^1.1.0",
"resize-observer-polyfill": "^1.5.1"
},
@ -46,13 +45,12 @@
"devDependencies": {
"@swc-node/jest": "^1.4.3",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0",
"@testing-library/react": "^13.4.0",
"@tldraw/intersect": "*",
"@tldraw/lfg": "latest",
"@tldraw/vec": "*",
"@types/react": "^18.0.17",
"@types/react-dom": "^18.0.6",
"@tldraw/lfg": "latest",
"mobx": "^6.3.8",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},

Wyświetl plik

@ -206,20 +206,22 @@ describe('When creating a realistic API around TLShapeUtil', () => {
return <div ref={ref2}>{props.message}</div>
})
render(<H message="Hello" />)
expect(() => render(<H message="Hello" />)).not.toThrowError()
render(
<Box.Component
ref={ref}
shape={box}
bounds={Box.getBounds(box)}
isEditing={false}
isBinding={false}
isHovered={false}
isSelected={false}
meta={meta}
events={{} as any}
/>
)
expect(() =>
render(
<Box.Component
ref={ref}
shape={box}
bounds={Box.getBounds(box)}
isEditing={false}
isBinding={false}
isHovered={false}
isSelected={false}
meta={meta}
events={{} as any}
/>
)
).not.toThrowError()
})
})

Wyświetl plik

@ -6,7 +6,13 @@ jest.spyOn(console, 'error').mockImplementation(() => void null)
describe('binding', () => {
test('mounts component without crashing', () => {
render(<Binding point={[0, 0]} type={'anchor'} />)
expect(() =>
render(
<div>
<Binding point={[0, 0]} type={'anchor'} />
</div>
)
).not.toThrowError()
})
test('validate attributes rendered properly for anchor binding type', () => {
render(<Binding point={[10, 20]} type={'anchor'} />)
@ -17,7 +23,11 @@ describe('binding', () => {
expect(use).toHaveAttribute('y', '20')
})
test('validate attributes rendered properly for center binding type', () => {
render(<Binding point={[10, 20]} type={'center'} />)
render(
<div>
<Binding point={[10, 20]} type={'center'} />
</div>
)
const circle = screen.getByLabelText('binding circle')
expect(circle).toHaveAttribute('cx', '10')
@ -25,7 +35,11 @@ describe('binding', () => {
expect(circle).toHaveAttribute('r', '8')
})
test('validate no children should be rendered for pin binding type', () => {
const { container } = render(<Binding point={[10, 20]} type={'pin'} />)
const { container } = render(
<div>
<Binding point={[10, 20]} type={'pin'} />
</div>
)
const group = container.querySelector('g')
expect(group?.hasChildNodes()).toBe(false)
})

Wyświetl plik

@ -1,4 +1,3 @@
import { observer } from 'mobx-react-lite'
import * as React from 'react'
import { Container } from '~components/Container'
import { SVGContainer } from '~components/SVGContainer'
@ -10,7 +9,7 @@ import { EdgeHandle } from './EdgeHandle'
import { LinkHandle } from './LinkHandle'
import { RotateHandle } from './RotateHandle'
interface BoundsProps {
export interface BoundsProps {
zoom: number
bounds: TLBounds
rotation: number
@ -24,7 +23,7 @@ interface BoundsProps {
children?: React.ReactElement
}
export const Bounds = observer<BoundsProps>(function Bounds({
const _Bounds = function Bounds({
zoom,
bounds,
viewportWidth,
@ -137,4 +136,6 @@ export const Bounds = observer<BoundsProps>(function Bounds({
</SVGContainer>
</Container>
)
})
}
export const Bounds = React.memo(_Bounds)

Wyświetl plik

@ -1,17 +1,16 @@
import { observer } from 'mobx-react-lite'
import * as React from 'react'
import { Container } from '~components/Container'
import { SVGContainer } from '~components/SVGContainer'
import { useBoundsEvents } from '~hooks'
import type { TLBounds } from '~types'
interface BoundsBgProps {
export interface BoundsBgProps {
bounds: TLBounds
rotation: number
isHidden: boolean
}
export const BoundsBg = observer<BoundsBgProps>(function BoundsBg({ bounds, rotation, isHidden }) {
function _BoundsBg({ bounds, rotation, isHidden }: BoundsBgProps) {
const events = useBoundsEvents()
return (
@ -28,4 +27,6 @@ export const BoundsBg = observer<BoundsBgProps>(function BoundsBg({ bounds, rota
</SVGContainer>
</Container>
)
})
}
export const BoundsBg = React.memo(_BoundsBg)

Wyświetl plik

@ -1,4 +1,3 @@
import { observer } from 'mobx-react-lite'
import * as React from 'react'
import type { TLBounds } from '~types'
@ -8,11 +7,7 @@ export interface CenterHandleProps {
isHidden: boolean
}
export const CenterHandle = observer<CenterHandleProps>(function CenterHandle({
bounds,
isLocked,
isHidden,
}) {
function _CenterHandle({ bounds, isLocked, isHidden }: CenterHandleProps) {
return (
<rect
className={['tl-bounds-center', isLocked ? 'tl-dashed' : ''].join(' ')}
@ -25,4 +20,6 @@ export const CenterHandle = observer<CenterHandleProps>(function CenterHandle({
aria-label="center handle"
/>
)
})
}
export const CenterHandle = React.memo(_CenterHandle)

Wyświetl plik

@ -1,4 +1,3 @@
import { observer } from 'mobx-react-lite'
import * as React from 'react'
import { useTLContext } from '~hooks'
import type { TLBounds } from '~types'
@ -21,12 +20,7 @@ export interface CloneButtonProps {
side: 'top' | 'right' | 'bottom' | 'left' | 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight'
}
export const CloneButton = observer<CloneButtonProps>(function CloneButton({
bounds,
side,
targetSize,
size,
}: CloneButtonProps) {
function _CloneButton({ bounds, side, targetSize, size }: CloneButtonProps) {
const s = targetSize * 2
const x = {
left: -s,
@ -78,4 +72,6 @@ export const CloneButton = observer<CloneButtonProps>(function CloneButton({
</g>
</g>
)
})
}
export const CloneButton = React.memo(_CloneButton)

Wyświetl plik

@ -8,7 +8,7 @@ export interface CloneButtonsProps {
size: number
}
export function CloneButtons({ targetSize, size, bounds }: CloneButtonsProps) {
function _CloneButtons({ targetSize, size, bounds }: CloneButtonsProps) {
return (
<>
<CloneButton targetSize={targetSize} size={size} bounds={bounds} side="top" />
@ -22,3 +22,5 @@ export function CloneButtons({ targetSize, size, bounds }: CloneButtonsProps) {
</>
)
}
export const CloneButtons = React.memo(_CloneButtons)

Wyświetl plik

@ -1,4 +1,3 @@
import { observer } from 'mobx-react-lite'
import * as React from 'react'
import { useBoundsHandleEvents } from '~hooks'
import { TLBounds, TLBoundsCorner } from '~types'
@ -10,7 +9,7 @@ const cornerBgClassnames = {
[TLBoundsCorner.BottomLeft]: 'tl-cursor-nesw',
}
interface CornerHandleProps {
export interface CornerHandleProps {
size: number
targetSize: number
bounds: TLBounds
@ -18,13 +17,7 @@ interface CornerHandleProps {
isHidden?: boolean
}
export const CornerHandle = observer(function CornerHandle({
size,
targetSize,
isHidden,
corner,
bounds,
}: CornerHandleProps) {
function _CornerHandle({ size, targetSize, isHidden, corner, bounds }: CornerHandleProps) {
const events = useBoundsHandleEvents(corner)
const isTop = corner === TLBoundsCorner.TopLeft || corner === TLBoundsCorner.TopRight
@ -53,4 +46,6 @@ export const CornerHandle = observer(function CornerHandle({
/>
</g>
)
})
}
export const CornerHandle = React.memo(_CornerHandle)

Wyświetl plik

@ -1,4 +1,3 @@
import { observer } from 'mobx-react-lite'
import * as React from 'react'
import { useBoundsHandleEvents } from '~hooks'
import { TLBounds, TLBoundsEdge } from '~types'
@ -10,7 +9,7 @@ const edgeClassnames = {
[TLBoundsEdge.Left]: 'tl-cursor-ew',
}
interface EdgeHandleProps {
export interface EdgeHandleProps {
targetSize: number
size: number
bounds: TLBounds
@ -18,12 +17,7 @@ interface EdgeHandleProps {
isHidden: boolean
}
export const EdgeHandle = observer<EdgeHandleProps>(function EdgeHandle({
size,
isHidden,
bounds,
edge,
}: EdgeHandleProps) {
function _EdgeHandle({ size, isHidden, bounds, edge }: EdgeHandleProps) {
const events = useBoundsHandleEvents(edge)
const isHorizontal = edge === TLBoundsEdge.Top || edge === TLBoundsEdge.Bottom
@ -44,4 +38,6 @@ export const EdgeHandle = observer<EdgeHandleProps>(function EdgeHandle({
{...events}
/>
)
})
}
export const EdgeHandle = React.memo(_EdgeHandle)

Wyświetl plik

@ -2,14 +2,14 @@ import * as React from 'react'
import { useBoundsHandleEvents } from '~hooks'
import type { TLBounds } from '~types'
interface LinkHandleProps {
export interface LinkHandleProps {
size: number
targetSize: number
isHidden: boolean
bounds: TLBounds
}
export function LinkHandle({ size, bounds, isHidden }: LinkHandleProps) {
function _LinkHandle({ size, bounds, isHidden }: LinkHandleProps) {
const leftEvents = useBoundsHandleEvents('left')
const centerEvents = useBoundsHandleEvents('center')
const rightEvents = useBoundsHandleEvents('right')
@ -51,3 +51,5 @@ export function LinkHandle({ size, bounds, isHidden }: LinkHandleProps) {
</g>
)
}
export const LinkHandle = React.memo(_LinkHandle)

Wyświetl plik

@ -1,21 +1,15 @@
import { observer } from 'mobx-react-lite'
import * as React from 'react'
import { useBoundsHandleEvents } from '~hooks'
import type { TLBounds } from '~types'
interface RotateHandleProps {
export interface RotateHandleProps {
bounds: TLBounds
size: number
targetSize: number
isHidden: boolean
}
export const RotateHandle = observer<RotateHandleProps>(function RotateHandle({
bounds,
targetSize,
size,
isHidden,
}) {
function _RotateHandle({ bounds, targetSize, size, isHidden }: RotateHandleProps) {
const events = useBoundsHandleEvents('rotate')
return (
@ -39,4 +33,6 @@ export const RotateHandle = observer<RotateHandleProps>(function RotateHandle({
/>
</g>
)
})
}
export const RotateHandle = React.memo(_RotateHandle)

Wyświetl plik

@ -5,20 +5,22 @@ import { Bounds } from '../Bounds'
describe('bounds', () => {
test('mounts component without crashing', () => {
renderWithContext(
<Bounds
zoom={1}
bounds={{ minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }}
rotation={0}
viewportWidth={1000}
isLocked={false}
isHidden={false}
hideBindingHandles={false}
hideCloneHandles={false}
hideRotateHandle={false}
hideResizeHandles={false}
/>
)
expect(() =>
renderWithContext(
<Bounds
zoom={1}
bounds={{ minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }}
rotation={0}
viewportWidth={1000}
isLocked={false}
isHidden={false}
hideBindingHandles={false}
hideCloneHandles={false}
hideRotateHandle={false}
hideResizeHandles={false}
/>
)
).not.toThrowError()
})
test('validate all attributes of bounds commponent', () => {
renderWithContext(

Wyświetl plik

@ -6,13 +6,17 @@ jest.spyOn(console, 'error').mockImplementation(() => void null)
describe('BoundsBg', () => {
test('mounts component without crashing', () => {
render(
<BoundsBg
bounds={{ minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }}
rotation={45}
isHidden={false}
/>
)
expect(() =>
render(
<div>
<BoundsBg
bounds={{ minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }}
rotation={45}
isHidden={false}
/>
</div>
)
).not.toThrowError()
})
test('validate attributes for a bounds bg', () => {
render(

Wyświetl plik

@ -6,21 +6,27 @@ jest.spyOn(console, 'error').mockImplementation(() => void null)
describe('CenterHandle', () => {
test('mounts component without crashing', () => {
render(
<CenterHandle
bounds={{ minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }}
isLocked={false}
isHidden={false}
/>
)
expect(() =>
render(
<div>
<CenterHandle
bounds={{ minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }}
isLocked={false}
isHidden={false}
/>
</div>
)
).not.toThrowError()
})
test('validate attributes for a center handle', () => {
render(
<CenterHandle
bounds={{ minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }}
isLocked={false}
isHidden={false}
/>
<div>
<CenterHandle
bounds={{ minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }}
isLocked={false}
isHidden={false}
/>
</div>
)
const centerHandle = screen.getByLabelText('center handle')
expect(centerHandle).toHaveAttribute('height', '102')
@ -31,11 +37,13 @@ describe('CenterHandle', () => {
})
test('validate attributes for a hidden center handle', () => {
render(
<CenterHandle
bounds={{ minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }}
isLocked={false}
isHidden={true}
/>
<div>
<CenterHandle
bounds={{ minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }}
isLocked={false}
isHidden={true}
/>
</div>
)
const centerHandle = screen.getByLabelText('center handle')
expect(centerHandle).toHaveAttribute('height', '102')

Wyświetl plik

@ -7,14 +7,16 @@ jest.spyOn(console, 'error').mockImplementation(() => void null)
describe('CloneButton', () => {
test('mounts component without crashing', () => {
renderWithContext(
<CloneButton
size={10}
targetSize={20}
bounds={{ minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }}
side="top"
/>
)
expect(() =>
renderWithContext(
<CloneButton
size={10}
targetSize={20}
bounds={{ minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }}
side="top"
/>
)
).not.toThrowError()
})
test('validate attributes for clone button', () => {
renderWithContext(

Wyświetl plik

@ -8,14 +8,16 @@ jest.spyOn(console, 'error').mockImplementation(() => void null)
describe('CenterHandle', () => {
test('mounts component without crashing', () => {
renderWithContext(
<CornerHandle
size={10}
targetSize={20}
bounds={{ minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }}
corner={TLBoundsCorner.TopLeft}
/>
)
expect(() =>
renderWithContext(
<CornerHandle
size={10}
targetSize={20}
bounds={{ minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }}
corner={TLBoundsCorner.TopLeft}
/>
)
).not.toThrowError()
})
test('top left corner > validate attributes', () => {
renderWithContext(

Wyświetl plik

@ -8,15 +8,17 @@ jest.spyOn(console, 'error').mockImplementation(() => void null)
describe('EdgeHandle', () => {
test('mounts component without crashing', () => {
renderWithContext(
<EdgeHandle
targetSize={20}
size={10}
bounds={{ minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }}
edge={TLBoundsEdge.Top}
isHidden={false}
/>
)
expect(() =>
renderWithContext(
<EdgeHandle
targetSize={20}
size={10}
bounds={{ minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }}
edge={TLBoundsEdge.Top}
isHidden={false}
/>
)
).not.toThrowError()
})
test('top edge > validate attributes', () => {
renderWithContext(

Wyświetl plik

@ -7,14 +7,16 @@ jest.spyOn(console, 'error').mockImplementation(() => void null)
describe('LinkHandle', () => {
test('mounts component without crashing', () => {
renderWithContext(
<LinkHandle
targetSize={20}
size={10}
bounds={{ minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }}
isHidden={false}
/>
)
expect(() =>
renderWithContext(
<LinkHandle
targetSize={20}
size={10}
bounds={{ minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }}
isHidden={false}
/>
)
).not.toThrowError()
})
test('validate attributes for link handle component', () => {
renderWithContext(

Wyświetl plik

@ -7,14 +7,16 @@ jest.spyOn(console, 'error').mockImplementation(() => void null)
describe('RotateHandle', () => {
test('mounts component without crashing', () => {
renderWithContext(
<RotateHandle
targetSize={20}
size={10}
bounds={{ minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }}
isHidden={false}
/>
)
expect(() =>
renderWithContext(
<RotateHandle
targetSize={20}
size={10}
bounds={{ minX: 0, minY: 0, maxX: 100, maxY: 100, width: 100, height: 100 }}
isHidden={false}
/>
)
).not.toThrowError()
})
test('validates all attributes of rotate handle', () => {
renderWithContext(

Wyświetl plik

@ -5,20 +5,22 @@ import { Brush } from './Brush'
describe('brush', () => {
test('mounts component without crashing', () => {
renderWithSvg(
<Brush
zoom={1}
dashed={false}
brush={{
minX: 0,
maxX: 100,
minY: 0,
maxY: 100,
width: 100,
height: 100,
}}
/>
)
expect(() =>
renderWithSvg(
<Brush
zoom={1}
dashed={false}
brush={{
minX: 0,
maxX: 100,
minY: 0,
maxY: 100,
width: 100,
height: 100,
}}
/>
)
).not.toThrowError()
})
})

Wyświetl plik

@ -1,15 +1,16 @@
import { observer } from 'mobx-react-lite'
import * as React from 'react'
import { SVGContainer } from '~components'
import { Container } from '~components/Container'
import type { TLBounds } from '~types'
import Utils from '~utils'
export const Brush = observer<{
export interface BrushProps {
brush: TLBounds
zoom: number
dashed: boolean | null | undefined
}>(function Brush({ brush, zoom, dashed }) {
}
function _Brush({ brush, zoom, dashed }: BrushProps) {
return (
<Container bounds={brush} rotation={0}>
<SVGContainer>
@ -45,7 +46,9 @@ export const Brush = observer<{
</SVGContainer>
</Container>
)
})
}
export const Brush = React.memo(_Brush)
interface PerfectDashLineProps {
x1: number

Wyświetl plik

@ -4,24 +4,26 @@ import { Canvas } from './Canvas'
describe('page', () => {
test('mounts component without crashing', () => {
renderWithContext(
<Canvas
page={mockDocument.page}
pageState={mockDocument.pageState}
hideBounds={false}
hideGrid={false}
hideIndicators={false}
hideHandles={false}
hideBindingHandles={false}
hideResizeHandles={false}
hideCloneHandles={false}
hideRotateHandle={false}
showDashedBrush={false}
onBoundsChange={() => {
// noop
}}
assets={{}}
/>
)
expect(() =>
renderWithContext(
<Canvas
page={mockDocument.page}
pageState={mockDocument.pageState}
hideBounds={false}
hideGrid={false}
hideIndicators={false}
hideHandles={false}
hideBindingHandles={false}
hideResizeHandles={false}
hideCloneHandles={false}
hideRotateHandle={false}
showDashedBrush={false}
onBoundsChange={() => {
// noop
}}
assets={{}}
/>
)
).not.toThrowError()
})
})

Wyświetl plik

@ -1,4 +1,3 @@
import { observer } from 'mobx-react-lite'
import * as React from 'react'
import { Brush } from '~components/Brush'
import { EraseLine } from '~components/EraseLine'
@ -30,7 +29,7 @@ import type {
TLUsers,
} from '~types'
interface CanvasProps<T extends TLShape, M extends Record<string, unknown>> {
export interface CanvasProps<T extends TLShape, M extends Record<string, unknown>> {
page: TLPage<T, TLBinding>
pageState: TLPageState
assets: TLAssets
@ -55,10 +54,7 @@ interface CanvasProps<T extends TLShape, M extends Record<string, unknown>> {
onBoundsChange: (bounds: TLBounds) => void
}
export const Canvas = observer(function _Canvas<
T extends TLShape,
M extends Record<string, unknown>
>({
function _Canvas<T extends TLShape, M extends Record<string, unknown>>({
id,
page,
pageState,
@ -141,4 +137,6 @@ export const Canvas = observer(function _Canvas<
</div>
</div>
)
})
}
export const Canvas = React.memo(_Canvas)

Wyświetl plik

@ -1,10 +1,9 @@
import { observer } from 'mobx-react-lite'
import type { HTMLProps } from 'react'
import * as React from 'react'
import type { HTMLProps } from 'react'
import { usePosition } from '~hooks'
import type { TLBounds } from '~types'
interface ContainerProps extends HTMLProps<HTMLDivElement> {
export interface ContainerProps extends HTMLProps<HTMLDivElement> {
id?: string
bounds: TLBounds
rotation?: number
@ -13,7 +12,7 @@ interface ContainerProps extends HTMLProps<HTMLDivElement> {
children: React.ReactNode
}
export const Container = observer<ContainerProps>(function Container({
function _Container({
id,
bounds,
rotation = 0,
@ -21,7 +20,7 @@ export const Container = observer<ContainerProps>(function Container({
isSelected = false,
children,
...props
}) {
}: ContainerProps) {
const rPositioned = usePosition(bounds, rotation)
return (
@ -38,4 +37,6 @@ export const Container = observer<ContainerProps>(function Container({
{children}
</div>
)
})
}
export const Container = React.memo(_Container)

Wyświetl plik

@ -1,16 +1,15 @@
import { observer } from 'mobx-react-lite'
import getStroke from 'perfect-freehand'
import * as React from 'react'
import Utils from '~utils'
export interface UiEraseLintProps {
export interface UiEraseLineProps {
points: number[][]
zoom: number
}
export type UiEraseLineComponent = (props: UiEraseLintProps) => any | null
export type UiEraseLineComponent = (props: UiEraseLineProps) => any | null
export const EraseLine = observer(function EraserLine({ points, zoom }: UiEraseLintProps) {
function _EraseLine({ points, zoom }: UiEraseLineProps) {
if (points.length === 0) return null
const d = Utils.getSvgPathFromStroke(
@ -18,4 +17,6 @@ export const EraseLine = observer(function EraserLine({ points, zoom }: UiEraseL
)
return <path d={d} className="tl-erase-line" />
})
}
export const EraseLine = React.memo(_EraseLine)

Wyświetl plik

@ -1,20 +1,18 @@
import { Observer } from 'mobx-react-lite'
import * as React from 'react'
interface HTMLContainerProps extends React.HTMLProps<HTMLDivElement> {
children: React.ReactNode
}
export const HTMLContainer = React.forwardRef<HTMLDivElement, HTMLContainerProps>(
function HTMLContainer({ children, className = '', ...rest }, ref) {
export const HTMLContainer = React.memo(
React.forwardRef<HTMLDivElement, HTMLContainerProps>(function HTMLContainer(
{ children, className = '', ...rest },
ref
) {
return (
<Observer>
{() => (
<div ref={ref} className={`tl-positioned-div ${className}`} draggable={false} {...rest}>
<div className="tl-inner-div">{children}</div>
</div>
)}
</Observer>
<div ref={ref} className={`tl-positioned-div ${className}`} draggable={false} {...rest}>
<div className="tl-inner-div">{children}</div>
</div>
)
}
})
)

Wyświetl plik

@ -5,7 +5,7 @@ import { Handle } from './Handle'
describe('handle', () => {
test('mounts component without crashing', () => {
renderWithContext(<Handle id="123" point={[100, 200]} />)
expect(() => renderWithContext(<Handle id="123" point={[100, 200]} />)).not.toThrowError()
})
test('validate attributes for handle component', () => {
renderWithContext(<Handle id="123" point={[100, 200]} />)

Wyświetl plik

@ -1,4 +1,3 @@
import { observer } from 'mobx-react-lite'
import * as React from 'react'
import { Container } from '~components/Container'
import { SVGContainer } from '~components/SVGContainer'
@ -10,7 +9,7 @@ interface HandleProps {
point: number[]
}
export const Handle = observer(function Handle({ id, point }: HandleProps) {
function _Handle({ id, point }: HandleProps) {
const events = useHandleEvents(id)
return (
@ -35,4 +34,6 @@ export const Handle = observer(function Handle({ id, point }: HandleProps) {
</SVGContainer>
</Container>
)
})
}
export const Handle = React.memo(_Handle)

Wyświetl plik

@ -6,7 +6,7 @@ import { Handles } from './Handles'
describe('handles', () => {
test('mounts component without crashing', () => {
renderWithContext(<Handles shape={boxShape} zoom={1} />)
expect(() => renderWithContext(<Handles shape={boxShape} zoom={1} />)).not.toThrowError()
})
test('validate attributes for handles component', () => {
const boxShapeWithHandles = {

Wyświetl plik

@ -1,5 +1,4 @@
import { Vec } from '@tldraw/vec'
import { observer } from 'mobx-react-lite'
import * as React from 'react'
import type { TLHandle, TLShape } from '~types'
import { Handle } from './Handle'
@ -9,7 +8,7 @@ interface HandlesProps {
zoom: number
}
export const Handles = observer(function Handles({ shape, zoom }: HandlesProps) {
function _Handles({ shape, zoom }: HandlesProps) {
if (shape.handles === undefined) {
return null
}
@ -40,4 +39,6 @@ export const Handles = observer(function Handles({ shape, zoom }: HandlesProps)
))}
</>
)
})
}
export const Handles = React.memo(_Handles)

Wyświetl plik

@ -1,12 +1,11 @@
import { observer } from 'mobx-react-lite'
import * as React from 'react'
type MyProps = {
export type OverlayProps = {
camera: { point: number[]; zoom: number }
children: React.ReactNode
}
export const Overlay = observer<MyProps>(function Overlay({ camera: { zoom, point }, children }) {
function _Overlay({ camera: { zoom, point }, children }: OverlayProps) {
const l = 2.5 / zoom
return (
<svg className="tl-overlay">
@ -21,4 +20,6 @@ export const Overlay = observer<MyProps>(function Overlay({ camera: { zoom, poin
<g transform={`scale(${zoom}) translate(${point})`}>{children}</g>
</svg>
)
})
}
export const Overlay = React.memo(_Overlay)

Wyświetl plik

@ -4,19 +4,21 @@ import { Page } from './Page'
describe('page', () => {
test('mounts component without crashing', () => {
renderWithContext(
<Page
page={mockDocument.page}
pageState={mockDocument.pageState}
assets={{}}
hideBounds={false}
hideIndicators={false}
hideHandles={false}
hideBindingHandles={false}
hideCloneHandles={false}
hideRotateHandle={false}
hideResizeHandles={false}
/>
)
expect(() =>
renderWithContext(
<Page
page={mockDocument.page}
pageState={mockDocument.pageState}
assets={{}}
hideBounds={false}
hideIndicators={false}
hideHandles={false}
hideBindingHandles={false}
hideCloneHandles={false}
hideRotateHandle={false}
hideResizeHandles={false}
/>
)
).not.toThrowError()
})
})

Wyświetl plik

@ -1,4 +1,3 @@
import { observer } from 'mobx-react-lite'
import * as React from 'react'
import type { TLShapeUtil } from '~TLShapeUtil'
import { Bounds } from '~components/Bounds'
@ -9,7 +8,7 @@ import { ShapeIndicator } from '~components/ShapeIndicator'
import { useSelection, useShapeTree, useTLContext } from '~hooks'
import type { TLAssets, TLBinding, TLPage, TLPageState, TLShape } from '~types'
interface PageProps<T extends TLShape, M extends Record<string, unknown>> {
export interface PageProps<T extends TLShape, M extends Record<string, unknown>> {
page: TLPage<T, TLBinding>
pageState: TLPageState
assets: TLAssets
@ -26,7 +25,7 @@ interface PageProps<T extends TLShape, M extends Record<string, unknown>> {
/**
* The Page component renders the current page.
*/
export const Page = observer(function _Page<T extends TLShape, M extends Record<string, unknown>>({
function _Page<T extends TLShape, M extends Record<string, unknown>>({
page,
pageState,
assets,
@ -112,4 +111,6 @@ export const Page = observer(function _Page<T extends TLShape, M extends Record<
{!hideHandles && shapeWithHandles && <Handles shape={shapeWithHandles} zoom={zoom} />}
</>
)
})
}
export const Page = React.memo(_Page)

Wyświetl plik

@ -1,6 +1,5 @@
import { act, render } from '@testing-library/react'
import Vec from '@tldraw/vec'
import { action, makeAutoObservable } from 'mobx'
import * as React from 'react'
import type { BoxShape } from '~TLShapeUtil/TLShapeUtil.spec'
import { mockDocument, mockUtils } from '~test'
@ -10,118 +9,120 @@ import { Renderer } from './Renderer'
describe('renderer', () => {
test('mounts component without crashing', () => {
render(
<Renderer
shapeUtils={mockUtils}
page={mockDocument.page}
pageState={mockDocument.pageState}
/>
)
expect(() =>
render(
<Renderer
shapeUtils={mockUtils as any}
page={mockDocument.page}
pageState={mockDocument.pageState}
/>
)
).not.toThrowError()
})
})
describe('When passing observables', () => {
it('updates when the observables change', () => {
class PageState implements TLPageState {
id
selectedIds
camera
brush?: TLBounds
pointedId?: string
hoveredId?: string
editingId?: string
bindingId?: string
// describe('When passing observables', () => {
// it('updates when the observables change', () => {
// class PageState implements TLPageState {
// id
// selectedIds
// camera
// brush?: TLBounds
// pointedId?: string
// hoveredId?: string
// editingId?: string
// bindingId?: string
constructor(opts = {} as TLPageState) {
const {
id = Utils.uniqueId(),
selectedIds = [],
camera = {
point: [0, 0],
zoom: 1,
},
} = opts
this.id = id
this.camera = camera
this.selectedIds = selectedIds
makeAutoObservable(this)
}
// constructor(opts = {} as TLPageState) {
// const {
// id = Utils.uniqueId(),
// selectedIds = [],
// camera = {
// point: [0, 0],
// zoom: 1,
// },
// } = opts
// this.id = id
// this.camera = camera
// this.selectedIds = selectedIds
// makeAutoObservable(this)
// }
@action pan = (point: number[]) => {
this.camera.point = Vec.add(this.camera.point, point)
}
}
// @action pan = (point: number[]) => {
// this.camera.point = Vec.add(this.camera.point, point)
// }
// }
class Page implements TLPage<BoxShape> {
id = 'page1'
shapes = {
box1: {
id: 'box1',
type: 'box' as const,
parentId: 'page1',
name: 'Box',
childIndex: 1,
rotation: 0,
point: [0, 0],
size: [100, 100],
},
} as Record<string, BoxShape>
bindings = {}
// class Page implements TLPage<BoxShape> {
// id = 'page1'
// shapes = {
// box1: {
// id: 'box1',
// type: 'box' as const,
// parentId: 'page1',
// name: 'Box',
// childIndex: 1,
// rotation: 0,
// point: [0, 0],
// size: [100, 100],
// },
// } as Record<string, BoxShape>
// bindings = {}
constructor() {
makeAutoObservable(this)
}
// constructor() {
// makeAutoObservable(this)
// }
@action moveShape = (id: string, point: number[]) => {
const shape = this.shapes[id]
shape.point = point
}
}
// @action moveShape = (id: string, point: number[]) => {
// const shape = this.shapes[id]
// shape.point = point
// }
// }
const page = new Page()
const pageState = new PageState()
// const page = new Page()
// const pageState = new PageState()
const wrapper = render(<Renderer shapeUtils={mockUtils} page={page} pageState={pageState} />)
// const wrapper = render(<Renderer shapeUtils={mockUtils} page={page} pageState={pageState} />)
expect(wrapper.getByTestId('layer')).toHaveProperty(
'style.transform',
`scale(1) translateX(0px) translateY(0px)`
)
// expect(wrapper.getByTestId('layer')).toHaveProperty(
// 'style.transform',
// `scale(1) translateX(0px) translateY(0px)`
// )
act(() => {
// PageState
pageState.pan([10, 10])
})
// act(() => {
// // PageState
// pageState.pan([10, 10])
// })
expect(wrapper.getByTestId('layer')).toHaveProperty(
'style.transform',
`scale(1) translateX(10px) translateY(10px)`
)
// expect(wrapper.getByTestId('layer')).toHaveProperty(
// 'style.transform',
// `scale(1) translateX(10px) translateY(10px)`
// )
// Page
// // Page
expect(wrapper.getByTestId('container')).toHaveProperty(
'style.transform',
`
translate(
calc(0px - var(--tl-padding)),
calc(0px - var(--tl-padding))
)
rotate(0rad)`
)
// expect(wrapper.getByTestId('container')).toHaveProperty(
// 'style.transform',
// `
// translate(
// calc(0px - var(--tl-padding)),
// calc(0px - var(--tl-padding))
// )
// rotate(0rad)`
// )
act(() => {
page.moveShape('box1', [10, 10])
})
// act(() => {
// page.moveShape('box1', [10, 10])
// })
expect(wrapper.getByTestId('container')).toHaveProperty(
'style.transform',
`
translate(
calc(10px - var(--tl-padding)),
calc(10px - var(--tl-padding))
)
rotate(0rad)`
)
})
})
// expect(wrapper.getByTestId('container')).toHaveProperty(
// 'style.transform',
// `
// translate(
// calc(10px - var(--tl-padding)),
// calc(10px - var(--tl-padding))
// )
// rotate(0rad)`
// )
// })
// })

Wyświetl plik

@ -1,4 +1,3 @@
import { observer } from 'mobx-react-lite'
import * as React from 'react'
import { Canvas } from '~/components/Canvas'
import type { TLShapeUtilsMap } from '~TLShapeUtil'
@ -18,11 +17,15 @@ import type {
TLUsers,
} from '~types'
export interface RendererProps<T extends TLShape, M = any> extends Partial<TLCallbacks<T>> {
const EMPTY_OBJECT = {} as TLAssets
export type RendererProps<T extends TLShape, M = any> = Partial<TLCallbacks<T>> & {
/**
* An object containing instances of your shape classes.
*/
shapeUtils: TLShapeUtilsMap<T>
shapeUtils: {
[K in T['type']]: any
}
/**
* The current page, containing shapes and bindings.
*/
@ -130,10 +133,7 @@ export interface RendererProps<T extends TLShape, M = any> extends Partial<TLCal
* @param props
* @returns
*/
export const Renderer = observer(function _Renderer<
T extends TLShape,
M extends Record<string, unknown>
>({
function _Renderer<T extends TLShape, M extends Record<string, unknown>>({
id = 'tl',
shapeUtils,
page,
@ -220,6 +220,6 @@ export const Renderer = observer(function _Renderer<
/>
</TLContext.Provider>
)
})
}
const EMPTY_OBJECT = {} as TLAssets
export const Renderer = React.memo(_Renderer)

Wyświetl plik

@ -1,23 +1,21 @@
import { Observer } from 'mobx-react-lite'
import * as React from 'react'
interface SvgContainerProps extends React.SVGProps<SVGSVGElement> {
export interface SvgContainerProps extends React.SVGProps<SVGSVGElement> {
children: React.ReactNode
className?: string
}
export const SVGContainer = React.forwardRef<SVGSVGElement, SvgContainerProps>(
function SVGContainer({ id, className = '', children, ...rest }, ref) {
export const SVGContainer = React.memo(
React.forwardRef<SVGSVGElement, SvgContainerProps>(function SVGContainer(
{ id, className = '', children, ...rest },
ref
) {
return (
<Observer>
{() => (
<svg ref={ref} className={`tl-positioned-svg ${className}`} {...rest}>
<g id={id} className="tl-centered-g">
{children}
</g>
</svg>
)}
</Observer>
<svg ref={ref} className={`tl-positioned-svg ${className}`} {...rest}>
<g id={id} className="tl-centered-g">
{children}
</g>
</svg>
)
}
})
)

Wyświetl plik

@ -1,4 +1,3 @@
import { observer } from 'mobx-react-lite'
import * as React from 'react'
import type { TLShapeUtil } from '~TLShapeUtil'
import type { TLComponentProps, TLShape } from '~types'
@ -9,12 +8,12 @@ interface RenderedShapeProps<T extends TLShape, E extends Element, M>
utils: TLShapeUtil<T, E, M>
}
const _RenderedShape = observer(function RenderedShape<T extends TLShape, E extends Element, M>(
function _RenderedShape<T extends TLShape, E extends Element, M>(
props: RenderedShapeProps<T, E, M>
) {
const ref = props.utils.getRef(props.shape)
return <props.utils.Component ref={ref} {...props} />
})
}
export const RenderedShape = React.memo(_RenderedShape, (prev, next) => {
// If these have changed, then definitely render

Wyświetl plik

@ -7,17 +7,19 @@ import { Shape } from './Shape'
describe('shape', () => {
test('mounts component without crashing', () => {
renderWithContext(
<Shape
shape={boxShape}
utils={new BoxUtil() as unknown as TLShapeUtil<TLShape>}
isEditing={false}
isBinding={false}
isHovered={false}
isSelected={false}
isGhost={false}
isChildOfSelected={false}
/>
)
expect(() =>
renderWithContext(
<Shape
shape={boxShape}
utils={new BoxUtil() as unknown as TLShapeUtil<TLShape>}
isEditing={false}
isBinding={false}
isHovered={false}
isSelected={false}
isGhost={false}
isChildOfSelected={false}
/>
)
).not.toThrowError()
})
})

Wyświetl plik

@ -1,4 +1,3 @@
import { observer } from 'mobx-react-lite'
import * as React from 'react'
import type { TLShapeUtil } from '~TLShapeUtil'
import { Container } from '~components/Container'
@ -7,11 +6,11 @@ import { useTLContext } from '~hooks'
import type { IShapeTreeNode, TLShape } from '~types'
import { RenderedShape } from './RenderedShape'
interface ShapeProps<T extends TLShape, E extends Element, M> extends IShapeTreeNode<T, M> {
export interface ShapeProps<T extends TLShape, E extends Element, M> extends IShapeTreeNode<T, M> {
utils: TLShapeUtil<T, E, M>
}
export const Shape = observer(function Shape<T extends TLShape, E extends Element, M>({
function _Shape<T extends TLShape, E extends Element, M>({
shape,
utils,
meta,
@ -42,4 +41,6 @@ export const Shape = observer(function Shape<T extends TLShape, E extends Elemen
/>
</Container>
)
})
}
export const Shape = React.memo(_Shape)

Wyświetl plik

@ -1,14 +1,13 @@
import { observer } from 'mobx-react-lite'
import * as React from 'react'
import type { TLShapeUtilsMap } from '~TLShapeUtil'
import type { IShapeTreeNode, TLShape } from '~types'
import { Shape } from './Shape'
interface ShapeNodeProps<T extends TLShape> extends IShapeTreeNode<T> {
utils: TLShapeUtilsMap<TLShape>
export interface ShapeNodeProps<T extends TLShape> extends IShapeTreeNode<T> {
utils: TLShapeUtilsMap<T>
}
export const ShapeNode = observer(function ShapeNode<T extends TLShape>({
function _ShapeNode<T extends TLShape>({
shape,
utils,
meta,
@ -17,11 +16,13 @@ export const ShapeNode = observer(function ShapeNode<T extends TLShape>({
}: ShapeNodeProps<T>) {
return (
<>
<Shape shape={shape} utils={utils[shape.type as T['type']]} meta={meta} {...rest} />
<Shape shape={shape} utils={(utils as any)[shape.type]} meta={meta} {...rest} />
{children &&
children.map((childNode) => (
<ShapeNode key={childNode.shape.id} utils={utils} {...childNode} />
<ShapeNode key={childNode.shape.id} utils={utils as any} {...childNode} />
))}
</>
)
})
}
export const ShapeNode = React.memo(_ShapeNode)

Wyświetl plik

@ -5,14 +5,16 @@ import { ShapeIndicator } from './ShapeIndicator'
describe('shape indicator', () => {
test('mounts component without crashing', () => {
renderWithSvg(
<ShapeIndicator
shape={boxShape}
isSelected={true}
isHovered={false}
isEditing={false}
meta={undefined}
/>
)
expect(() =>
renderWithSvg(
<ShapeIndicator
shape={boxShape}
isSelected={true}
isHovered={false}
isEditing={false}
meta={undefined}
/>
)
).not.toThrowError()
})
})

Wyświetl plik

@ -1,9 +1,8 @@
import { observer } from 'mobx-react-lite'
import * as React from 'react'
import { usePosition, useTLContext } from '~hooks'
import type { TLShape, TLUser } from '~types'
interface IndicatorProps<T extends TLShape, M = unknown> {
export interface IndicatorProps<T extends TLShape, M = unknown> {
shape: T
meta: M extends unknown ? M : undefined
isSelected?: boolean
@ -12,7 +11,7 @@ interface IndicatorProps<T extends TLShape, M = unknown> {
user?: TLUser<T>
}
export const ShapeIndicator = observer(function ShapeIndicator<T extends TLShape, M>({
function _ShapeIndicator<T extends TLShape, M>({
isHovered = false,
isSelected = false,
isEditing = false,
@ -51,4 +50,6 @@ export const ShapeIndicator = observer(function ShapeIndicator<T extends TLShape
</svg>
</div>
)
})
}
export const ShapeIndicator = React.memo(_ShapeIndicator)

Wyświetl plik

@ -1,9 +1,8 @@
import { observer } from 'mobx-react-lite'
import * as React from 'react'
import type { TLSnapLine } from '~types'
import Utils from '~utils'
export const SnapLines = observer<{ snapLines: TLSnapLine[] }>(function SnapLines({ snapLines }) {
function _SnapLines({ snapLines }: { snapLines: TLSnapLine[] }) {
return (
<>
{snapLines.map((snapLine, i) => (
@ -11,9 +10,9 @@ export const SnapLines = observer<{ snapLines: TLSnapLine[] }>(function SnapLine
))}
</>
)
})
}
export const SnapLine = observer<{ snapLine: TLSnapLine }>(function SnapLine({ snapLine }) {
function _SnapLine({ snapLine }: { snapLine: TLSnapLine }) {
const bounds = Utils.getBoundsFromPoints(snapLine)
return (
@ -30,4 +29,7 @@ export const SnapLine = observer<{ snapLine: TLSnapLine }>(function SnapLine({ s
))}
</>
)
})
}
export const SnapLine = React.memo(_SnapLine)
export const SnapLines = React.memo(_SnapLines)

Wyświetl plik

@ -1,4 +1,3 @@
import { autorun } from 'mobx'
import * as React from 'react'
import type { TLPageState } from '~types'
@ -12,36 +11,34 @@ export function useCameraCss(
const rPoint = React.useRef<number[]>()
React.useLayoutEffect(() => {
return autorun(() => {
const { zoom, point } = pageState.camera
const { zoom, point } = pageState.camera
const didZoom = zoom !== rZoom.current
const didPan = point !== rPoint.current
const didZoom = zoom !== rZoom.current
const didPan = point !== rPoint.current
rZoom.current = zoom
rPoint.current = point
rZoom.current = zoom
rPoint.current = point
if (didZoom || didPan) {
const layer = layerRef.current
if (containerRef && 'current' in containerRef) {
const container = containerRef.current
if (didZoom || didPan) {
const layer = layerRef.current
if (containerRef && 'current' in containerRef) {
const container = containerRef.current
// If we zoomed, set the CSS variable for the zoom
if (didZoom) {
if (container) {
container.style.setProperty('--tl-zoom', zoom.toString())
}
}
// Either way, position the layer
if (layer) {
layer.style.setProperty(
'transform',
`scale(${zoom}) translateX(${point[0]}px) translateY(${point[1]}px)`
)
// If we zoomed, set the CSS variable for the zoom
if (didZoom) {
if (container) {
container.style.setProperty('--tl-zoom', zoom.toString())
}
}
// Either way, position the layer
if (layer) {
layer.style.setProperty(
'transform',
`scale(${zoom}) translateX(${point[0]}px) translateY(${point[1]}px)`
)
}
}
})
}, [pageState])
}
}, [pageState.camera.zoom, pageState.camera.point])
}

Wyświetl plik

@ -1,4 +1,3 @@
import { autorun } from 'mobx'
import * as React from 'react'
import type { TLBounds } from '~types'
@ -7,24 +6,19 @@ export function usePosition(bounds: TLBounds, rotation = 0) {
// Update the transform
React.useLayoutEffect(() => {
return autorun(() => {
const elm = rBounds.current!
const transform = `
const elm = rBounds.current!
const transform = `
translate(
calc(${bounds.minX}px - var(--tl-padding)),
calc(${bounds.minY}px - var(--tl-padding))
)
rotate(${rotation + (bounds.rotation || 0)}rad)`
elm.style.setProperty('transform', transform)
elm.style.setProperty(
'width',
`calc(${Math.floor(bounds.width)}px + (var(--tl-padding) * 2))`
)
elm.style.setProperty(
'height',
`calc(${Math.floor(bounds.height)}px + (var(--tl-padding) * 2))`
)
})
elm.style.setProperty('transform', transform)
elm.style.setProperty('width', `calc(${Math.floor(bounds.width)}px + (var(--tl-padding) * 2))`)
elm.style.setProperty(
'height',
`calc(${Math.floor(bounds.height)}px + (var(--tl-padding) * 2))`
)
}, [bounds, rotation])
return rBounds

Wyświetl plik

@ -3,5 +3,9 @@ import * as React from 'react'
import { ContextWrapper } from './ContextWrapper'
export const renderWithContext = (children: React.ReactNode) => {
return render(<ContextWrapper>{children}</ContextWrapper>)
return render(
<div>
<ContextWrapper>{children}</ContextWrapper>
</div>
)
}

Wyświetl plik

@ -146,7 +146,7 @@ export type TLPinchEventHandler = (
| PointerEventInit
) => void
export type TLShapeChangeHandler<T, K = any> = (
export type TLShapeChangeHandler<T extends TLShape, K = any> = (
shape: { id: string } & Partial<T>,
info?: K
) => void

Wyświetl plik

@ -71,7 +71,6 @@
"@types/react-dom": "^18.0.6",
"@typescript-eslint/eslint-plugin": "^5.10.2",
"@typescript-eslint/parser": "^5.10.2",
"mobx": "^6.3.8",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"typescript": "^4.7.3"

Wyświetl plik

@ -598,41 +598,6 @@ const OneOff = React.memo(function OneOff({
return null
})
const Wrapper = styled('div', {
variants: {
isForcingPanning: {
true: {},
false: {},
},
isPointerDown: {
true: {},
false: {},
},
},
compoundVariants: [
{
isForcingPanning: true,
isPointerDown: false,
css: {
cursor: 'grab',
},
},
{
isForcingPanning: false,
css: {
cursor: 'default',
},
},
{
isPointerDown: true,
isForcingPanning: true,
css: {
cursor: 'grabbing',
},
},
],
})
const StyledLayout = styled('div', {
position: 'absolute',
height: '100%',

Wyświetl plik

@ -42,7 +42,7 @@ interface ContextMenuProps {
children: React.ReactNode
}
export const ContextMenu = ({ onBlur, children }: ContextMenuProps) => {
export const _ContextMenu = ({ onBlur, children }: ContextMenuProps) => {
const container = useContainer()
return (
@ -524,3 +524,5 @@ export const CMSubTriggerButton = ({ id, ...rest }: RowButtonProps) => {
</RadixContextMenu.SubTrigger>
)
}
export const ContextMenu = React.memo(_ContextMenu)

Wyświetl plik

@ -19,7 +19,7 @@ interface TopPanelProps {
showMultiplayerMenu: boolean
}
export function TopPanel({
export function _TopPanel({
readOnly,
showPages,
showMenu,
@ -91,3 +91,5 @@ const ReadOnlyLabel = styled('div', {
paddingRight: '$1',
userSelect: 'none',
})
export const TopPanel = React.memo(_TopPanel)

Wyświetl plik

@ -8,6 +8,7 @@ import {
TLPageState,
TLPinchEventHandler,
TLPointerEventHandler,
TLShape,
TLShapeCloneHandler,
TLWheelEventHandler,
Utils,
@ -3993,7 +3994,7 @@ export class TldrawApp extends StateManager<TDSnapshot> {
this.currentTool.onReleaseHandle?.(info, e)
}
onShapeChange = (shape: { id: string } & Partial<TDShape>) => {
onShapeChange = (shape: { id: string } & Partial<TLShape>) => {
const pageShapes = this.document.pages[this.currentPageId].shapes
const shapeToUpdate = { ...(pageShapes[shape.id] as any), ...shape }
const patch = Commands.updateShapes(this, [shapeToUpdate], this.currentPageId).after

Wyświetl plik

@ -2663,6 +2663,15 @@
"@testing-library/dom" "^8.5.0"
"@types/react-dom" "^18.0.0"
"@testing-library/react@^13.4.0":
version "13.4.0"
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-13.4.0.tgz#6a31e3bf5951615593ad984e96b9e5e2d9380966"
integrity sha512-sXOGON+WNTh3MLE9rve97ftaZukN3oNf2KjDy7YTx6hcTO2uuLHuCGynMDhFwGw/jYf4OJ2Qk0i4i79qMNNkyw==
dependencies:
"@babel/runtime" "^7.12.5"
"@testing-library/dom" "^8.5.0"
"@types/react-dom" "^18.0.0"
"@tldraw/lfg@latest":
version "1.1.3"
resolved "https://registry.yarnpkg.com/@tldraw/lfg/-/lfg-1.1.3.tgz#23b36664dc5057902f7f2ad0b68f5cfd5b9cc133"
@ -7292,16 +7301,6 @@ mkdirp@^0.5.5:
dependencies:
minimist "^1.2.5"
mobx-react-lite@^3.2.3:
version "3.2.3"
resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-3.2.3.tgz#83d2b32ebf4383cd0dc0d397acbf53a8e9c66765"
integrity sha512-7exWp1FV0M9dP08H9PIeHlJqDw4IdkQVRMfLYaZFMmlbzSS6ZU6p/kx392KN+rVf81hH3IQYewvRGQ70oiwmbw==
mobx@^6.3.13, mobx@^6.3.8:
version "6.3.13"
resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.3.13.tgz#93e56a57ee72369f850cf3d6398fd36ee8ef062e"
integrity sha512-zDDKDhYUk9QCHQUdLG+wb4Jv/nXutSLt/P8kkwHyjdbrJO4OZS6QTEsrOnrKM39puqXSrJZHdB6+yRys2NBFFA==
mocha@^9.1.1:
version "9.2.2"
resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.2.2.tgz#d70db46bdb93ca57402c809333e5a84977a88fb9"