diff --git a/packages/editor/api-report.md b/packages/editor/api-report.md index 6eb92c0cb..28253e231 100644 --- a/packages/editor/api-report.md +++ b/packages/editor/api-report.md @@ -1844,7 +1844,6 @@ export abstract class ShapeUtil { hitTestLineSegment(shape: T, A: VecLike, B: VecLike): boolean; hitTestPoint(shape: T, point: VecLike): boolean; abstract indicator(shape: T): any; - is(shape: TLBaseShape): shape is T; isAspectRatioLocked: TLShapeUtilFlag; isClosed: TLShapeUtilFlag; onBeforeCreate?: TLOnBeforeCreateHandler; @@ -1885,7 +1884,6 @@ export abstract class ShapeUtil { transform(shape: T): Matrix2d; // (undocumented) readonly type: T['type']; - // (undocumented) static type: string; } diff --git a/packages/editor/editor.css b/packages/editor/editor.css index 2cb69e3ce..511fda559 100644 --- a/packages/editor/editor.css +++ b/packages/editor/editor.css @@ -29,31 +29,39 @@ https://alex.dytry.ch/toys/palette/?palette=%7B%22families%22:%5B%22black%22,%22 /* Misc */ --tl-zoom: 1; + /* Cursor SVGs */ + --tl-cursor-none: none; + --tl-cursor-default: url("data:image/svg+xml,") + 12 8, + pointer; + --tl-cursor-pointer: url("data:image/svg+xml,") + 14 10, + pointer; + --tl-cursor-cross: url("data:image/svg+xml,") + 16 16, + pointer; + --tl-cursor-move: url("data:image/svg+xml,") + 16 16, + pointer; + --tl-cursor-grab: url("data:image/svg+xml,") + 16 16, + pointer; + --tl-cursor-grabbing: url("data:image/svg+xml,") + 16 16, + pointer; + --tl-cursor-text: url("data:image/svg+xml,") + 4 10, + pointer; + --tl-cursor-zoom-in: url("data:image/svg+xml,") + 16 16, + pointer; + --tl-cursor-zoom-out: url("data:image/svg+xml,") + 16 16, + pointer; + /* These cursor values get programmatically overridden */ /* They're just here to help your editor autocomplete */ - --tl-cursor: var(--tl-cursor-default); - --tl-cursor-none: none; - --tl-cursor-default: default; - --tl-cursor-pointer: pointer; - --tl-cursor-cross: crosshair; - --tl-cursor-move: move; - --tl-cursor-grab: grab; - --tl-cursor-grabbing: grabbing; - --tl-cursor-text: text; - --tl-cursor-resize-edge: ew-resize; - --tl-cursor-resize-corner: nesw-resize; - --tl-cursor-ew-resize: ew-resize; - --tl-cursor-ns-resize: ns-resize; - --tl-cursor-nesw-resize: nesw-resize; - --tl-cursor-nwse-resize: nwse-resize; - --tl-cursor-rotate: pointer; - --tl-cursor-nwse-rotate: pointer; - --tl-cursor-nesw-rotate: pointer; - --tl-cursor-senw-rotate: pointer; - --tl-cursor-swne-rotate: pointer; - --tl-cursor-zoom-in: zoom-in; - --tl-cursor-zoom-out: zoom-out; - + --tl-cursor: var(--tl-default-svg); --tl-scale: calc(1 / var(--tl-zoom)); --tl-font-draw: 'tldraw_draw', sans-serif; --tl-font-sans: 'tldraw_sans', sans-serif; diff --git a/packages/editor/src/lib/app/shapeutils/ShapeUtil.ts b/packages/editor/src/lib/app/shapeutils/ShapeUtil.ts index e8b71f6fd..2cb9754e5 100644 --- a/packages/editor/src/lib/app/shapeutils/ShapeUtil.ts +++ b/packages/editor/src/lib/app/shapeutils/ShapeUtil.ts @@ -1,14 +1,7 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { Box2d, linesIntersect, Matrix2d, VecLike } from '@tldraw/primitives' import { ComputedCache } from '@tldraw/store' -import { - TLBaseShape, - TLHandle, - TLShape, - TLShapePartial, - TLUnknownShape, - Vec2dModel, -} from '@tldraw/tlschema' +import { TLHandle, TLShape, TLShapePartial, TLUnknownShape, Vec2dModel } from '@tldraw/tlschema' import { computed, EMPTY_ARRAY } from 'signia' import { WeakMapCache } from '../../utils/WeakMapCache' import type { Editor } from '../Editor' @@ -34,18 +27,12 @@ export type TLShapeUtilFlag = (shape: T) => boolean export abstract class ShapeUtil { constructor(public editor: Editor, public readonly type: T['type']) {} - static type: string - /** - * Check if a shape is of this type. + * The type of the shape util, which should match the shape's type. * - * @param shape - The shape to check. - * @returns Whether the shape is of this type. * @public */ - is(shape: TLBaseShape): shape is T { - return shape.type === this.type - } + static type: string /** * Whether the shape can be scrolled while editing. @@ -55,7 +42,7 @@ export abstract class ShapeUtil { canScroll: TLShapeUtilFlag = () => false /** - * Whether the shape can be bound to by an arrow. + * Whether the shape should unmount when not visible in the editor. Consider keeping this to false if the shape's `component` has local state. * * @public */ diff --git a/packages/editor/src/lib/hooks/useCursor.ts b/packages/editor/src/lib/hooks/useCursor.ts index bed40a21f..1f46da393 100644 --- a/packages/editor/src/lib/hooks/useCursor.ts +++ b/packages/editor/src/lib/hooks/useCursor.ts @@ -8,14 +8,12 @@ const DEFAULT_SVG = `` const CROSS_SVG = `` const MOVE_SVG = `` - const CORNER_SVG = `` const EDGE_SVG = `` -const ROTATE_CORNER_SVG = `` +const ROTATE_CORNER_SVG = `` const TEXT_SVG = `` const GRABBING_SVG = `` const GRAB_SVG = `` - const ZOOM_IN_SVG = `` const ZOOM_OUT_SVG = `` @@ -52,13 +50,10 @@ const CURSORS: Record st grab: (r, f, c) => getCursorCss(GRAB_SVG, r, 0, f, c), grabbing: (r, f, c) => getCursorCss(GRABBING_SVG, r, 0, f, c), text: (r, f, c) => getCursorCss(TEXT_SVG, r, 0, f, c, 4, 10), - 'resize-edge': (r, f, c) => getCursorCss(EDGE_SVG, r, 0, f, c), - 'resize-corner': (r, f, c) => getCursorCss(CORNER_SVG, r, 0, f, c), 'ew-resize': (r, f, c) => getCursorCss(EDGE_SVG, r, 0, f, c), 'ns-resize': (r, f, c) => getCursorCss(EDGE_SVG, r, 90, f, c), 'nesw-resize': (r, f, c) => getCursorCss(CORNER_SVG, r, 0, f, c), 'nwse-resize': (r, f, c) => getCursorCss(CORNER_SVG, r, 90, f, c), - rotate: (r, f, c) => getCursorCss(ROTATE_CORNER_SVG, r, 45, f, c), 'nwse-rotate': (r, f, c) => getCursorCss(ROTATE_CORNER_SVG, r, 0, f, c), 'nesw-rotate': (r, f, c) => getCursorCss(ROTATE_CORNER_SVG, r, 90, f, c), 'senw-rotate': (r, f, c) => getCursorCss(ROTATE_CORNER_SVG, r, 180, f, c), @@ -71,6 +66,8 @@ export function getCursor(cursor: TLCursorType, rotation = 0, color = 'black') { return CURSORS[cursor](radiansToDegrees(rotation), false, color) } +const STATIC_CURSORS = ['default', 'pointer', 'cross', 'move', 'grab', 'grabbing', 'text'] + export function useCursor() { const editor = useEditor() const container = useContainer() @@ -79,18 +76,14 @@ export function useCursor() { 'useCursor', () => { const { type, rotation, color } = editor.cursor + + if (STATIC_CURSORS.includes(type)) { + container.style.setProperty('--tl-cursor', `var(--tl-cursor-${type})`) + return + } + container.style.setProperty('--tl-cursor', getCursor(type, rotation, color)) }, [editor, container] ) - - useQuickReactor( - 'useStaticCursor', - () => { - for (const key in CURSORS) { - container.style.setProperty(`--tl-cursor-${key}`, getCursor(key)) - } - }, - [editor, container] - ) } diff --git a/packages/ui/src/lib/components/DebugPanel.tsx b/packages/ui/src/lib/components/DebugPanel.tsx index d0c761e7a..24b571f30 100644 --- a/packages/ui/src/lib/components/DebugPanel.tsx +++ b/packages/ui/src/lib/components/DebugPanel.tsx @@ -268,13 +268,10 @@ const CURSOR_NAMES = [ 'grab', 'grabbing', 'text', - 'resize-edge', - 'resize-corner', 'ew-resize', 'ns-resize', 'nesw-resize', 'nwse-resize', - 'rotate', 'nwse-rotate', 'nesw-rotate', 'senw-rotate',