Tldraw/packages/editor/src/lib/components/default-components/DefaultShapeIndicator.tsx

82 wiersze
2.4 KiB
TypeScript
Czysty Zwykły widok Historia

import { useQuickReactor, useStateTracking, useValue } from '@tldraw/state'
2023-04-25 11:01:25 +00:00
import { TLShape, TLShapeId } from '@tldraw/tlschema'
import classNames from 'classnames'
import { memo, useLayoutEffect, useRef } from 'react'
import type { Editor } from '../../editor/Editor'
import { ShapeUtil } from '../../editor/shapes/ShapeUtil'
import { useEditor } from '../../hooks/useEditor'
import { useEditorComponents } from '../../hooks/useEditorComponents'
import { OptionalErrorBoundary } from '../ErrorBoundary'
2023-04-25 11:01:25 +00:00
// need an extra layer of indirection here to allow hooks to be used inside the indicator render
const EvenInnererIndicator = ({ shape, util }: { shape: TLShape; util: ShapeUtil<any> }) => {
return useStateTracking('Indicator: ' + shape.type, () => util.indicator(shape))
2023-04-25 11:01:25 +00:00
}
const InnerIndicator = ({ editor, id }: { editor: Editor; id: TLShapeId }) => {
const shape = useValue('shape for indicator', () => editor.store.get(id), [editor, id])
2023-04-25 11:01:25 +00:00
const { ShapeIndicatorErrorFallback } = useEditorComponents()
if (!shape || shape.isLocked) return null
2023-04-25 11:01:25 +00:00
return (
<OptionalErrorBoundary
fallback={ShapeIndicatorErrorFallback}
2023-04-25 11:01:25 +00:00
onError={(error) =>
editor.annotateError(error, { origin: 'react.shapeIndicator', willCrashApp: false })
2023-04-25 11:01:25 +00:00
}
>
<EvenInnererIndicator key={shape.id} shape={shape} util={editor.getShapeUtil(shape)} />
2023-04-25 11:01:25 +00:00
</OptionalErrorBoundary>
)
}
Remove helpers / extraneous API methods. (#1745) This PR removes several extraneous computed values from the editor. It adds some silly instance state onto the instance state record and unifies a few methods which were inconsistent. This is fit and finish work 🧽 ## Computed Values In general, where once we had a getter and setter for `isBlahMode`, which really masked either an `_isBlahMode` atom on the editor or `instanceState.isBlahMode`, these are merged into `instanceState`; they can be accessed / updated via `editor.instanceState` / `editor.updateInstanceState`. ## tldraw select tool specific things This PR also removes some tldraw specific state checks and creates new component overrides to allow us to include them in tldraw/tldraw. ### Change Type - [x] `major` — Breaking change ### Test Plan - [x] Unit Tests - [x] End to end tests ### Release Notes - [tldraw] rename `useReadonly` to `useReadOnly` - [editor] remove `Editor.isDarkMode` - [editor] remove `Editor.isChangingStyle` - [editor] remove `Editor.isCoarsePointer` - [editor] remove `Editor.isDarkMode` - [editor] remove `Editor.isFocused` - [editor] remove `Editor.isGridMode` - [editor] remove `Editor.isPenMode` - [editor] remove `Editor.isReadOnly` - [editor] remove `Editor.isSnapMode` - [editor] remove `Editor.isToolLocked` - [editor] remove `Editor.locale` - [editor] rename `Editor.pageState` to `Editor.currentPageState` - [editor] add `Editor.pageStates` - [editor] add `Editor.setErasingIds` - [editor] add `Editor.setEditingId` - [editor] add several new component overrides
2023-07-18 21:50:23 +00:00
/** @public */
export type TLShapeIndicatorProps = {
shapeId: TLShapeId
color?: string | undefined
opacity?: number
className?: string
hidden?: boolean
}
/** @public */
export const DefaultShapeIndicator = memo(function DefaultShapeIndicator({
shapeId,
className,
color,
hidden,
opacity,
}: TLShapeIndicatorProps) {
const editor = useEditor()
2023-04-25 11:01:25 +00:00
const rIndicator = useRef<SVGSVGElement>(null)
useQuickReactor(
'indicator transform',
2023-04-25 11:01:25 +00:00
() => {
const elm = rIndicator.current
if (!elm) return
const pageTransform = editor.getShapePageTransform(shapeId)
if (!pageTransform) return
elm.style.setProperty('transform', pageTransform.toCssString())
2023-04-25 11:01:25 +00:00
},
[editor, shapeId]
2023-04-25 11:01:25 +00:00
)
useLayoutEffect(() => {
const elm = rIndicator.current
if (!elm) return
elm.style.setProperty('display', hidden ? 'none' : 'block')
}, [hidden])
2023-04-25 11:01:25 +00:00
return (
<svg ref={rIndicator} className={classNames('tl-overlays__item', className)}>
<g className="tl-shape-indicator" stroke={color ?? 'var(--color-selected)'} opacity={opacity}>
<InnerIndicator editor={editor} id={shapeId} />
</g>
</svg>
2023-04-25 11:01:25 +00:00
)
})