No impure getters pt4 (#2206)

follow up to #2189 and #2203 

### Change Type

- [x] `patch` — Bug fix
This commit is contained in:
David Sheldrick 2023-11-13 16:02:50 +00:00 committed by GitHub
parent 7ffda2335c
commit daf729d45c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
45 changed files with 610 additions and 274 deletions

View file

@ -51,7 +51,7 @@ function MyComponent() {
// The "InFrontOfTheCanvas" component is rendered on top of the canvas, but behind the UI.
const MyComponentInFront = track(() => {
const editor = useEditor()
const { selectionRotatedPageBounds } = editor
const selectionRotatedPageBounds = editor.getSelectionRotatedPageBounds()
if (!selectionRotatedPageBounds) return null

View file

@ -642,7 +642,9 @@ export class Editor extends EventEmitter<TLEventMap> {
get documentSettings(): TLDocument;
duplicatePage(page: TLPage | TLPageId, createId?: TLPageId): this;
duplicateShapes(shapes: TLShape[] | TLShapeId[], offset?: VecLike): this;
// @deprecated (undocumented)
get editingShape(): TLShape | undefined;
// @deprecated (undocumented)
get editingShapeId(): null | TLShapeId;
readonly environment: EnvironmentManager;
get erasingShapeIds(): TLShapeId[];
@ -666,7 +668,9 @@ export class Editor extends EventEmitter<TLEventMap> {
findCommonAncestor(shapes: TLShape[] | TLShapeId[], predicate?: (shape: TLShape) => boolean): TLShapeId | undefined;
findShapeAncestor(shape: TLShape | TLShapeId, predicate: (parent: TLShape) => boolean): TLShape | undefined;
flipShapes(shapes: TLShape[] | TLShapeId[], operation: 'horizontal' | 'vertical'): this;
// @deprecated (undocumented)
get focusedGroup(): TLShape | undefined;
// @deprecated (undocumented)
get focusedGroupId(): TLPageId | TLShapeId;
getAncestorPageId(shape?: TLShape | TLShapeId): TLPageId | undefined;
getArrowInfo(shape: TLArrowShape | TLShapeId): TLArrowInfo | undefined;
@ -685,6 +689,10 @@ export class Editor extends EventEmitter<TLEventMap> {
getCurrentToolId(): string;
getDocumentSettings(): TLDocument;
getDroppingOverShape(point: VecLike, droppingShapes?: TLShape[]): TLUnknownShape | undefined;
getEditingShape(): TLShape | undefined;
getEditingShapeId(): null | TLShapeId;
getFocusedGroup(): TLShape | undefined;
getFocusedGroupId(): TLPageId | TLShapeId;
getHighestIndexForParent(parent: TLPage | TLParentId | TLShape): string;
getInitialMetaForShape(_shape: TLShape): JsonObject;
getInstanceState(): TLInstance;
@ -700,6 +708,9 @@ export class Editor extends EventEmitter<TLEventMap> {
getSelectedShapeAtPoint(point: VecLike): TLShape | undefined;
getSelectedShapeIds(): TLShapeId[];
getSelectedShapes(): TLShape[];
getSelectionPageBounds(): Box2d | null;
getSelectionRotatedPageBounds(): Box2d | undefined;
getSelectionRotation(): number;
getShape<T extends TLShape = TLShape>(shape: TLParentId | TLShape): T | undefined;
getShapeAncestors(shape: TLShape | TLShapeId, acc?: TLShape[]): TLShape[];
getShapeAndDescendantIds(ids: TLShapeId[]): Set<TLShapeId>;
@ -854,8 +865,11 @@ export class Editor extends EventEmitter<TLEventMap> {
get selectedShapeIds(): TLShapeId[];
// @deprecated (undocumented)
get selectedShapes(): TLShape[];
// @deprecated (undocumented)
get selectionPageBounds(): Box2d | null;
// @deprecated (undocumented)
get selectionRotatedPageBounds(): Box2d | undefined;
// @deprecated (undocumented)
get selectionRotation(): number;
selectNone(): this;
sendBackward(shapes: TLShape[] | TLShapeId[]): this;

View file

@ -9147,7 +9147,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!Editor#editingShape:member",
"docComment": "/**\n * The current editing shape.\n *\n * @public\n */\n",
"docComment": "/**\n * @deprecated\n *\n * Use `getEditingShape` instead.\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -9182,7 +9182,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!Editor#editingShapeId:member",
"docComment": "/**\n * The current editing shape's id.\n *\n * @public\n */\n",
"docComment": "/**\n * @deprecated\n *\n * Use `getEditingShapeId` instead.\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -9585,7 +9585,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!Editor#focusedGroup:member",
"docComment": "/**\n * The current focused group.\n *\n * @public\n */\n",
"docComment": "/**\n * @deprecated\n *\n * Use `getFocusedGroup` instead.\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -9620,7 +9620,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!Editor#focusedGroupId:member",
"docComment": "/**\n * The current focused group id.\n *\n * @public\n */\n",
"docComment": "/**\n * @deprecated\n *\n * Use `getFocusedGroupId` instead.\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -10337,6 +10337,155 @@
"isAbstract": false,
"name": "getDroppingOverShape"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getEditingShape:member(1)",
"docComment": "/**\n * The current editing shape.\n *\n * @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
"text": "getEditingShape(): "
},
{
"kind": "Reference",
"text": "TLShape",
"canonicalReference": "@tldraw/tlschema!TLShape:type"
},
{
"kind": "Content",
"text": " | undefined"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 3
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getEditingShape"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getEditingShapeId:member(1)",
"docComment": "/**\n * The current editing shape's id.\n *\n * @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
"text": "getEditingShapeId(): "
},
{
"kind": "Content",
"text": "null | "
},
{
"kind": "Reference",
"text": "TLShapeId",
"canonicalReference": "@tldraw/tlschema!TLShapeId:type"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 3
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getEditingShapeId"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getFocusedGroup:member(1)",
"docComment": "/**\n * The current focused group.\n *\n * @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
"text": "getFocusedGroup(): "
},
{
"kind": "Reference",
"text": "TLShape",
"canonicalReference": "@tldraw/tlschema!TLShape:type"
},
{
"kind": "Content",
"text": " | undefined"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 3
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getFocusedGroup"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getFocusedGroupId:member(1)",
"docComment": "/**\n * The current focused group id.\n *\n * @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
"text": "getFocusedGroupId(): "
},
{
"kind": "Reference",
"text": "TLPageId",
"canonicalReference": "@tldraw/tlschema!TLPageId:type"
},
{
"kind": "Content",
"text": " | "
},
{
"kind": "Reference",
"text": "TLShapeId",
"canonicalReference": "@tldraw/tlschema!TLShapeId:type"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 4
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getFocusedGroupId"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getHighestIndexForParent:member(1)",
@ -11117,6 +11266,109 @@
"isAbstract": false,
"name": "getSelectedShapes"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getSelectionPageBounds:member(1)",
"docComment": "/**\n * The current page bounds of all the selected shapes. If the selection is rotated, then these bounds are the axis-aligned box that the rotated bounds would fit inside of.\n *\n * @readonly @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
"text": "getSelectionPageBounds(): "
},
{
"kind": "Reference",
"text": "Box2d",
"canonicalReference": "@tldraw/editor!Box2d:class"
},
{
"kind": "Content",
"text": " | null"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 3
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getSelectionPageBounds"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getSelectionRotatedPageBounds:member(1)",
"docComment": "/**\n * The bounds of the selection bounding box in the current page space.\n *\n * @readonly @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
"text": "getSelectionRotatedPageBounds(): "
},
{
"kind": "Reference",
"text": "Box2d",
"canonicalReference": "@tldraw/editor!Box2d:class"
},
{
"kind": "Content",
"text": " | undefined"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 3
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getSelectionRotatedPageBounds"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getSelectionRotation:member(1)",
"docComment": "/**\n * The rotation of the selection bounding box in the current page space.\n *\n * @readonly @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
"text": "getSelectionRotation(): "
},
{
"kind": "Content",
"text": "number"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 2
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getSelectionRotation"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getShape:member(1)",
@ -15882,7 +16134,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!Editor#selectionPageBounds:member",
"docComment": "/**\n * The current page bounds of all the selected shapes. If the selection is rotated, then these bounds are the axis-aligned box that the rotated bounds would fit inside of.\n *\n * @readonly @public\n */\n",
"docComment": "/**\n * @deprecated\n *\n * Use `getSelectionPageBounds` instead.\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -15917,7 +16169,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!Editor#selectionRotatedPageBounds:member",
"docComment": "/**\n * The bounds of the selection bounding box in the current page space.\n *\n * @readonly @public\n */\n",
"docComment": "/**\n * @deprecated\n *\n * Use `getSelectionRotatedPageBounds` instead.\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -15952,7 +16204,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!Editor#selectionRotation:member",
"docComment": "/**\n * The rotation of the selection bounding box in the current page space.\n *\n * @readonly @public\n */\n",
"docComment": "/**\n * @deprecated\n *\n * Use `getSelectionRotation` instead.\n */\n",
"excerptTokens": [
{
"kind": "Content",

View file

@ -522,10 +522,14 @@ function UiLogger() {
export function SelectionForegroundWrapper() {
const editor = useEditor()
const selectionRotation = useValue('selection rotation', () => editor.selectionRotation, [editor])
const selectionBounds = useValue('selection bounds', () => editor.selectionRotatedPageBounds, [
const selectionRotation = useValue('selection rotation', () => editor.getSelectionRotation(), [
editor,
])
const selectionBounds = useValue(
'selection bounds',
() => editor.getSelectionRotatedPageBounds(),
[editor]
)
const { SelectionForeground } = useEditorComponents()
if (!selectionBounds || !SelectionForeground) return null
return <SelectionForeground bounds={selectionBounds} rotation={selectionRotation} />
@ -533,10 +537,14 @@ export function SelectionForegroundWrapper() {
export function SelectionBackgroundWrapper() {
const editor = useEditor()
const selectionRotation = useValue('selection rotation', () => editor.selectionRotation, [editor])
const selectionBounds = useValue('selection bounds', () => editor.selectionRotatedPageBounds, [
const selectionRotation = useValue('selection rotation', () => editor.getSelectionRotation(), [
editor,
])
const selectionBounds = useValue(
'selection bounds',
() => editor.getSelectionRotatedPageBounds(),
[editor]
)
const { SelectionBackground } = useEditorComponents()
if (!selectionBounds || !SelectionBackground) return null
return <SelectionBackground bounds={selectionBounds} rotation={selectionRotation} />

View file

@ -995,6 +995,7 @@ export class Editor extends EventEmitter<TLEventMap> {
}
} {
try {
const editingShapeId = this.getEditingShapeId()
return {
tags: {
origin: origin,
@ -1003,7 +1004,7 @@ export class Editor extends EventEmitter<TLEventMap> {
extras: {
activeStateNode: this.root.path.get(),
selectedShapes: this.getSelectedShapes(),
editingShape: this.editingShapeId ? this.getShape(this.editingShapeId) : undefined,
editingShape: editingShapeId ? this.getShape(editingShapeId) : undefined,
inputs: this.inputs,
},
}
@ -1681,20 +1682,27 @@ export class Editor extends EventEmitter<TLEventMap> {
*
* @public
*/
@computed get selectionPageBounds(): Box2d | null {
@computed getSelectionPageBounds(): Box2d | null {
const selectedShapeIds = this.getCurrentPageState().selectedShapeIds
if (selectedShapeIds.length === 0) return null
return Box2d.Common(compact(selectedShapeIds.map((id) => this.getShapePageBounds(id))))
}
/**
* @deprecated Use `getSelectionPageBounds` instead.
*/
get selectionPageBounds() {
return this.getSelectionPageBounds()
}
/**
* The rotation of the selection bounding box in the current page space.
*
* @readonly
* @public
*/
@computed get selectionRotation(): number {
@computed getSelectionRotation(): number {
const selectedShapeIds = this.getSelectedShapeIds()
if (selectedShapeIds.length === 0) {
return 0
@ -1711,22 +1719,29 @@ export class Editor extends EventEmitter<TLEventMap> {
return 0
}
/**
* @deprecated Use `getSelectionRotation` instead.
*/
get selectionRotation() {
return this.getSelectionRotation()
}
/**
* The bounds of the selection bounding box in the current page space.
*
* @readonly
* @public
*/
@computed get selectionRotatedPageBounds(): Box2d | undefined {
@computed getSelectionRotatedPageBounds(): Box2d | undefined {
const selectedShapeIds = this.getSelectedShapeIds()
if (selectedShapeIds.length === 0) {
return undefined
}
const { selectionRotation } = this
const selectionRotation = this.getSelectionRotation()
if (selectionRotation === 0) {
return this.selectionPageBounds!
return this.getSelectionPageBounds()!
}
if (selectedShapeIds.length === 1) {
@ -1751,6 +1766,13 @@ export class Editor extends EventEmitter<TLEventMap> {
return boxFromRotatedVertices
}
/**
* @deprecated Use `getSelectionRotatedPageBounds` instead.
*/
get selectionRotatedPageBounds() {
return this.getSelectionRotatedPageBounds()
}
// Focus Group
/**
@ -1758,20 +1780,34 @@ export class Editor extends EventEmitter<TLEventMap> {
*
* @public
*/
@computed get focusedGroupId(): TLShapeId | TLPageId {
@computed getFocusedGroupId(): TLShapeId | TLPageId {
return this.getCurrentPageState().focusedGroupId ?? this.currentPageId
}
/**
* @deprecated Use `getFocusedGroupId` instead.
*/
get focusedGroupId() {
return this.getFocusedGroupId()
}
/**
* The current focused group.
*
* @public
*/
@computed get focusedGroup(): TLShape | undefined {
const { focusedGroupId } = this
@computed getFocusedGroup(): TLShape | undefined {
const focusedGroupId = this.getFocusedGroupId()
return focusedGroupId ? this.getShape(focusedGroupId) : undefined
}
/**
* @deprecated Use `getFocusedGroup` instead.
*/
get focusedGroup() {
return this.getFocusedGroup()
}
/**
* Set the current focused group shape.
*
@ -1795,7 +1831,7 @@ export class Editor extends EventEmitter<TLEventMap> {
}
}
if (id === this.focusedGroupId) return this
if (id === this.getFocusedGroupId()) return this
this._setFocusedGroupId(id)
return this
}
@ -1834,7 +1870,7 @@ export class Editor extends EventEmitter<TLEventMap> {
* @public
*/
popFocusedGroupId(): this {
const { focusedGroup } = this
const focusedGroup = this.getFocusedGroup()
if (focusedGroup) {
// If we have a focused layer, look for an ancestor of the focused shape that is a group
@ -1858,20 +1894,34 @@ export class Editor extends EventEmitter<TLEventMap> {
*
* @public
*/
@computed get editingShapeId() {
@computed getEditingShapeId(): TLShapeId | null {
return this.getCurrentPageState().editingShapeId
}
/**
* @deprecated Use `getEditingShapeId` instead.
*/
get editingShapeId() {
return this.getEditingShapeId()
}
/**
* The current editing shape.
*
* @public
*/
@computed get editingShape(): TLShape | undefined {
const { editingShapeId } = this
@computed getEditingShape(): TLShape | undefined {
const editingShapeId = this.getEditingShapeId()
return editingShapeId ? this.getShape(editingShapeId) : undefined
}
/**
* @deprecated Use `getEditingShape` instead.
*/
get editingShape() {
return this.getEditingShape()
}
/**
* Set the current editing shape.
*
@ -1887,7 +1937,7 @@ export class Editor extends EventEmitter<TLEventMap> {
*/
setEditingShape(shape: TLShapeId | TLShape | null): this {
const id = typeof shape === 'string' ? shape : shape?.id ?? null
if (id !== this.editingShapeId) {
if (id !== this.getEditingShapeId()) {
if (id) {
const shape = this.getShape(id)
if (shape && this.getShapeUtil(shape).canEdit(shape)) {
@ -2226,7 +2276,7 @@ export class Editor extends EventEmitter<TLEventMap> {
* @public
*/
zoomToContent(): this {
const bounds = this.selectionPageBounds ?? this.currentPageBounds
const bounds = this.getSelectionPageBounds() ?? this.currentPageBounds
if (bounds) {
this.zoomToBounds(bounds, Math.min(1, this.zoomLevel), { duration: 220 })
@ -2383,7 +2433,7 @@ export class Editor extends EventEmitter<TLEventMap> {
zoomToSelection(animation?: TLAnimationOptions): this {
if (!this.getInstanceState().canMoveCamera) return this
const { selectionPageBounds } = this
const selectionPageBounds = this.getSelectionPageBounds()
if (!selectionPageBounds) return this
this.zoomToBounds(selectionPageBounds, Math.max(1, this.zoomLevel), animation)
@ -3112,7 +3162,7 @@ export class Editor extends EventEmitter<TLEventMap> {
let nextBackgroundIndex = MAX_SHAPES_PER_PAGE
// We only really need these if we're using editor state, but that's ok
const editingShapeId = this.editingShapeId
const editingShapeId = this.getEditingShapeId()
const selectedShapeIds = this.getSelectedShapeIds()
const erasingShapeIds = this.erasingShapeIds
const renderingBoundsExpanded = this.renderingBoundsExpanded
@ -5087,7 +5137,7 @@ export class Editor extends EventEmitter<TLEventMap> {
let match = freshShape
let node = freshShape as TLShape | undefined
const { focusedGroup } = this
const focusedGroup = this.getFocusedGroup()
while (node) {
if (
@ -5378,7 +5428,8 @@ export class Editor extends EventEmitter<TLEventMap> {
// If we've offset the duplicated shapes, check to see whether their new bounds is entirely
// contained in the current viewport. If not, then animate the camera to be centered on the
// new shapes.
const { viewportPageBounds, selectionPageBounds: selectionPageBounds } = this
const selectionPageBounds = this.getSelectionPageBounds()
const { viewportPageBounds } = this
if (selectionPageBounds && !viewportPageBounds.contains(selectionPageBounds)) {
this.centerOnPoint(selectionPageBounds.center, {
duration: ANIMATION_MEDIUM_MS,
@ -5454,7 +5505,7 @@ export class Editor extends EventEmitter<TLEventMap> {
// "from" page's camera, then center the "to" page's camera on the
// pasted shapes
this.setCamera({ ...this.camera, z: fromPageZ })
this.centerOnPoint(this.selectionRotatedPageBounds!.center)
this.centerOnPoint(this.getSelectionRotatedPageBounds()!.center)
})
return this
@ -6581,7 +6632,7 @@ export class Editor extends EventEmitter<TLEventMap> {
},
{
do: ({ partials }) => {
const { focusedGroupId } = this
const focusedGroupId = this.getFocusedGroupId()
// 1. Parents
@ -6601,7 +6652,7 @@ export class Editor extends EventEmitter<TLEventMap> {
!partial.parentId ||
!(this.store.has(partial.parentId) || partials.some((p) => p.id === partial.parentId))
) {
let parentId: TLParentId = this.focusedGroupId
let parentId: TLParentId = this.getFocusedGroupId()
for (let i = currentPageShapesSorted.length - 1; i >= 0; i--) {
const parent = currentPageShapesSorted[i]

View file

@ -126,7 +126,7 @@ export function useDocumentEvents() {
// escape de-selects them. Only when the user's selection is empty
// should we allow escape to do its normal thing.
if (editor.editingShape || editor.getSelectedShapeIds().length > 0) {
if (editor.getEditingShape() || editor.getSelectedShapeIds().length > 0) {
e.preventDefault()
}

View file

@ -97,12 +97,13 @@ export function useGestureEvents(ref: React.RefObject<HTMLDivElement>) {
// default on the evnet) if the user is wheeling over an a shape
// that is scrollable which they're currently editing.
if (editor.editingShapeId) {
const shape = editor.getShape(editor.editingShapeId)
const editingShapeId = editor.getEditingShapeId()
if (editingShapeId) {
const shape = editor.getShape(editingShapeId)
if (shape) {
const util = editor.getShapeUtil(shape)
if (util.canScroll(shape)) {
const bounds = editor.getShapePageBounds(editor.editingShapeId)
const bounds = editor.getShapePageBounds(editingShapeId)
if (bounds?.containsPoint(editor.inputs.currentPagePoint)) {
return
}

View file

@ -5,5 +5,5 @@ import { useEditor } from './useEditor'
/** @public */
export function useIsEditing(shapeId: TLShapeId) {
const editor = useEditor()
return useValue('isEditing', () => editor.editingShapeId === shapeId, [editor, shapeId])
return useValue('isEditing', () => editor.getEditingShapeId() === shapeId, [editor, shapeId])
}

View file

@ -8,9 +8,9 @@ import { Vec2d } from '../primitives/Vec2d'
/** @internal */
export function getRotationSnapshot({ editor }: { editor: Editor }): TLRotationSnapshot | null {
const selectedShapes = editor.getSelectedShapes()
const selectionRotation = editor.getSelectionRotation()
const selectionBounds = editor.getSelectionRotatedPageBounds()
const {
selectionRotation,
selectionRotatedPageBounds: selectionBounds,
inputs: { originPagePoint },
} = editor

View file

@ -40,6 +40,7 @@ import { SelectionEdge } from '@tldraw/editor';
import { SelectionHandle } from '@tldraw/editor';
import { SerializedSchema } from '@tldraw/editor';
import { ShapeUtil } from '@tldraw/editor';
import { SnapPoint } from '@tldraw/editor';
import { StateNode } from '@tldraw/editor';
import { StoreSnapshot } from '@tldraw/editor';
import { SvgExportContext } from '@tldraw/editor';

View file

@ -14,7 +14,7 @@ export const TldrawHoveredShapeIndicator: TLHoveredShapeIndicatorComponent = ({
// When the editor is editing a shape and hovering that shape,
// don't show its indicator; but DO show other hover indicators
if (editor.isIn('select.editing_shape')) {
return editor.hoveredShapeId !== editor.editingShapeId
return editor.hoveredShapeId !== editor.getEditingShapeId()
}
// Otherise, only show the hovered indicator when the editor

View file

@ -46,7 +46,7 @@ export const TldrawSelectionForeground: TLSelectionForegroundComponent = track(
? editor.getShapeUtil(onlyShape).expandSelectionOutlinePx(onlyShape)
: 0
useTransform(rSvg, bounds?.x, bounds?.y, 1, editor.selectionRotation, {
useTransform(rSvg, bounds?.x, bounds?.y, 1, editor.getSelectionRotation(), {
x: -expandOutlineBy,
y: -expandOutlineBy,
})

View file

@ -461,16 +461,16 @@ export async function createShapesForAssets(
editor.createShapes(partials).select(...partials.map((p) => p.id))
// Re-position shapes so that the center of the group is at the provided point
centerSelecitonAroundPoint(editor, position)
centerSelectionAroundPoint(editor, position)
})
return partials.map((p) => p.id)
}
function centerSelecitonAroundPoint(editor: Editor, position: VecLike) {
function centerSelectionAroundPoint(editor: Editor, position: VecLike) {
// Re-position shapes so that the center of the group is at the provided point
const { viewportPageBounds } = editor
let { selectionPageBounds } = editor
let selectionPageBounds = editor.getSelectionPageBounds()
if (selectionPageBounds) {
const offset = selectionPageBounds!.center.sub(position)
@ -490,7 +490,7 @@ function centerSelecitonAroundPoint(editor: Editor, position: VecLike) {
}
// Zoom out to fit the shapes, if necessary
selectionPageBounds = editor.selectionPageBounds
selectionPageBounds = editor.getSelectionPageBounds()
if (selectionPageBounds && !viewportPageBounds.contains(selectionPageBounds)) {
editor.zoomToSelection()
}
@ -515,7 +515,7 @@ export function createEmptyBookmarkShape(
editor.batch(() => {
editor.createShapes([partial]).select(partial.id)
centerSelecitonAroundPoint(editor, position)
centerSelectionAroundPoint(editor, position)
})
return editor.getShape(partial.id) as TLBookmarkShape

View file

@ -143,7 +143,7 @@ describe('When translating the arrow', () => {
it('retains all handles if either bound shape is also translating', () => {
editor.select(ids.arrow1, ids.box2)
expect(editor.selectionPageBounds).toMatchObject({
expect(editor.getSelectionPageBounds()).toMatchObject({
x: 200,
y: 200,
w: 200,

View file

@ -38,7 +38,7 @@ export const FrameHeading = function FrameHeading({
const event = getPointerInfo(e)
// If we're editing the frame label, we shouldn't hijack the pointer event
if (editor.editingShapeId === id) return
if (editor.getEditingShapeId() === id) return
editor.dispatch({
type: 'pointer',

View file

@ -23,7 +23,7 @@ export function useEditableText<T extends Extract<TLShape, { props: { text: stri
const rSkipSelectOnFocus = useRef(false)
const rSelectionRanges = useRef<Range[] | null>()
const isEditing = useValue('isEditing', () => editor.editingShapeId === id, [editor, id])
const isEditing = useValue('isEditing', () => editor.getEditingShapeId() === id, [editor, id])
// If the shape is editing but the input element not focused, focus the element
useEffect(() => {
@ -63,7 +63,7 @@ export function useEditableText<T extends Extract<TLShape, { props: { text: stri
requestAnimationFrame(() => {
const elm = rInput.current
const { editingShapeId } = editor
const editingShapeId = editor.getEditingShapeId()
// Did we move to a different shape?
if (elm && editingShapeId) {
// important! these ^v are two different things

View file

@ -143,7 +143,7 @@ export class TextShapeUtil extends ShapeUtil<TLTextShape> {
indicator(shape: TLTextShape) {
const bounds = this.editor.getShapeGeometry(shape).bounds
const editor = useEditor()
if (shape.props.autoSize && editor.editingShapeId === shape.id) return null
if (shape.props.autoSize && editor.getEditingShapeId() === shape.id) return null
return <rect width={toDomPrecision(bounds.width)} height={toDomPrecision(bounds.height)} />
}

View file

@ -224,14 +224,14 @@ export class Cropping extends StateNode {
}
private createSnapshot() {
const selectionRotation = this.editor.getSelectionRotation()
const {
selectionRotation,
inputs: { originPagePoint },
} = this.editor
const shape = this.editor.getOnlySelectedShape() as TLImageShape
const selectionBounds = this.editor.selectionRotatedPageBounds!
const selectionBounds = this.editor.getSelectionRotatedPageBounds()!
const dragHandlePoint = Vec2d.RotWith(
selectionBounds.getHandlePoint(this.info.handle!),

View file

@ -13,7 +13,7 @@ export class EditingShape extends StateNode {
static override id = 'editing_shape'
override onEnter = () => {
const { editingShape } = this.editor
const editingShape = this.editor.getEditingShape()
if (!editingShape) throw Error('Entered editing state without an editing shape')
updateHoveredId(this.editor)
this.editor.select(editingShape)
@ -62,7 +62,7 @@ export class EditingShape extends StateNode {
}
case 'shape': {
const { shape } = info
const { editingShape } = this.editor
const editingShape = this.editor.getEditingShape()
if (!editingShape) {
throw Error('Expected an editing shape!')

View file

@ -180,7 +180,7 @@ export class Idle extends StateNode {
hitInside: false,
})
const { focusedGroupId } = this.editor
const focusedGroupId = this.editor.getFocusedGroupId()
if (hitShape) {
if (this.editor.isShapeOfType<TLGroupShape>(hitShape, 'group')) {
@ -388,7 +388,7 @@ export class Idle extends StateNode {
override onCancel: TLEventHandlers['onCancel'] = () => {
if (
this.editor.focusedGroupId !== this.editor.currentPageId &&
this.editor.getFocusedGroupId() !== this.editor.currentPageId &&
this.editor.getSelectedShapeIds().length > 0
) {
this.editor.popFocusedGroupId()
@ -562,10 +562,10 @@ export const MINOR_NUDGE_FACTOR = 1
export const GRID_INCREMENT = 5
function isPointInRotatedSelectionBounds(editor: Editor, point: VecLike) {
const { selectionRotatedPageBounds: selectionBounds } = editor
const selectionBounds = editor.getSelectionRotatedPageBounds()
if (!selectionBounds) return false
const { selectionRotation } = editor
const selectionRotation = editor.getSelectionRotation()
if (!selectionRotation) return selectionBounds.containsPoint(point)
return pointInPolygon(

View file

@ -11,7 +11,7 @@ export class PointingRotateHandle extends StateNode {
private info = {} as PointingRotateHandleInfo
private updateCursor() {
const { selectionRotation } = this.editor
const selectionRotation = this.editor.getSelectionRotation()
this.editor.updateInstanceState({
cursor: {
type: CursorTypeMap[this.info.handle as RotateCorner],

View file

@ -19,9 +19,9 @@ export class PointingShape extends StateNode {
override onEnter = (info: TLPointerEventInfo & { target: 'shape' }) => {
const selectedShapeIds = this.editor.getSelectedShapeIds()
const selectionBounds = this.editor.getSelectionRotatedPageBounds()
const focusedGroupId = this.editor.getFocusedGroupId()
const {
focusedGroupId,
selectionRotatedPageBounds: selectionBounds,
inputs: { currentPagePoint, shiftKey, altKey },
} = this.editor
@ -61,9 +61,9 @@ export class PointingShape extends StateNode {
override onPointerUp: TLEventHandlers['onPointerUp'] = (info) => {
const selectedShapeIds = this.editor.getSelectedShapeIds()
const focusedGroupId = this.editor.getFocusedGroupId()
const {
zoomLevel,
focusedGroupId,
inputs: { currentPagePoint, shiftKey },
} = this.editor

View file

@ -368,12 +368,12 @@ export class Resizing extends StateNode {
_createSnapshot = () => {
const selectedShapeIds = this.editor.getSelectedShapeIds()
const selectionRotation = this.editor.getSelectionRotation()
const {
selectionRotation,
inputs: { originPagePoint },
} = this.editor
const selectionBounds = this.editor.selectionRotatedPageBounds!
const selectionBounds = this.editor.getSelectionRotatedPageBounds()!
const dragHandlePoint = Vec2d.RotWith(
selectionBounds.getHandlePoint(this.info.handle!),
@ -418,7 +418,7 @@ export class Resizing extends StateNode {
selectionRotation,
selectedShapeIds,
canShapesDeform,
initialSelectionPageBounds: this.editor.selectionPageBounds!,
initialSelectionPageBounds: this.editor.getSelectionPageBounds()!,
}
}

View file

@ -139,9 +139,9 @@ export class Rotating extends StateNode {
}
_getRotationFromPointerPosition({ snapToNearestDegree }: { snapToNearestDegree: boolean }) {
const selectionRotation = this.editor.getSelectionRotation()
const selectionBounds = this.editor.getSelectionRotatedPageBounds()
const {
selectionRotatedPageBounds: selectionBounds,
selectionRotation,
inputs: { shiftKey, currentPagePoint },
} = this.editor
const { initialCursorAngle, initialSelectionRotation } = this.snapshot

View file

@ -306,21 +306,26 @@ function getTranslatingSnapshot(editor: Editor) {
})
)
let initialSnapPoints: SnapPoint[] = []
if (editor.getSelectedShapeIds().length === 1) {
initialSnapPoints = editor.snaps.snapPointsCache.get(editor.getSelectedShapeIds()[0])!
} else {
const selectionPageBounds = editor.getSelectionPageBounds()
if (selectionPageBounds) {
initialSnapPoints = selectionPageBounds.snapPoints.map((p, i) => ({
id: 'selection:' + i,
x: p.x,
y: p.y,
}))
}
}
return {
averagePagePoint: Vec2d.Average(pagePoints),
movingShapes,
shapeSnapshots,
initialPageBounds: editor.selectionPageBounds!,
initialSnapPoints:
editor.getSelectedShapeIds().length === 1
? editor.snaps.snapPointsCache.get(editor.getSelectedShapeIds()[0])!
: editor.selectionPageBounds
? editor.selectionPageBounds.snapPoints.map((p, i) => ({
id: 'selection:' + i,
x: p.x,
y: p.y,
}))
: [],
initialPageBounds: editor.getSelectionPageBounds()!,
initialSnapPoints,
}
}

View file

@ -49,7 +49,7 @@ export function selectOnCanvasPointerUp(editor: Editor) {
// Otherwise, if the group isn't selected and isn't our current
// focus layer, then we need to select the group instead.
if (
outermostSelectableShape.id === editor.focusedGroupId ||
outermostSelectableShape.id === editor.getFocusedGroupId() ||
selectedShapeIds.includes(outermostSelectableShape.id)
) {
shapeToSelect = hitShape
@ -81,7 +81,7 @@ export function selectOnCanvasPointerUp(editor: Editor) {
// If the click was inside of the current focused group, then
// we keep that focused group; otherwise we clear the focused
// group (reset it to the page)
const { focusedGroupId } = editor
const focusedGroupId = editor.getFocusedGroupId()
if (isShapeId(focusedGroupId)) {
const groupShape = editor.getShape(focusedGroupId)!

View file

@ -19,7 +19,7 @@ export function updateHoveredId(editor: Editor) {
shapeToHover = hitShape
} else {
if (
outermostShape.id === editor.focusedGroupId ||
outermostShape.id === editor.getFocusedGroupId() ||
editor.getSelectedShapeIds().includes(outermostShape.id)
) {
shapeToHover = hitShape

View file

@ -835,7 +835,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('rotate-cw', { source })
editor.mark('rotate-cw')
const offset = editor.selectionRotation % (TAU / 2)
const offset = editor.getSelectionRotation() % (TAU / 2)
const dontUseOffset = approximately(offset, 0) || approximately(offset, TAU / 2)
editor.rotateShapesBy(
editor.getSelectedShapeIds(),
@ -854,7 +854,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('rotate-ccw', { source })
editor.mark('rotate-ccw')
const offset = editor.selectionRotation % (TAU / 2)
const offset = editor.getSelectionRotation() % (TAU / 2)
const offsetCloseToZero = approximately(offset, 0)
editor.rotateShapesBy(
editor.getSelectedShapeIds(),

View file

@ -195,7 +195,7 @@ const handlePasteFromEventClipboardData = async (
point?: VecLike
) => {
// Do not paste while in any editing state
if (editor.editingShapeId !== null) return
if (editor.getEditingShapeId() !== null) return
if (!clipboardData) {
throw Error('No clipboard data')
@ -598,7 +598,7 @@ export function useMenuClipboardEvents() {
// If we're editing a shape, or we are focusing an editable input, then
// we would want the user's paste interaction to go to that element or
// input instead; e.g. when pasting text into a text shape's content
if (editor.editingShapeId !== null || disallowClipboardEvents(editor)) return
if (editor.getEditingShapeId() !== null || disallowClipboardEvents(editor)) return
if (Array.isArray(data) && data[0] instanceof ClipboardItem) {
handlePasteFromClipboardApi(editor, data, point)
@ -634,7 +634,7 @@ export function useNativeClipboardEvents() {
const copy = () => {
if (
editor.getSelectedShapeIds().length === 0 ||
editor.editingShapeId !== null ||
editor.getEditingShapeId() !== null ||
disallowClipboardEvents(editor)
)
return
@ -645,7 +645,7 @@ export function useNativeClipboardEvents() {
function cut() {
if (
editor.getSelectedShapeIds().length === 0 ||
editor.editingShapeId !== null ||
editor.getEditingShapeId() !== null ||
disallowClipboardEvents(editor)
)
return
@ -673,7 +673,7 @@ export function useNativeClipboardEvents() {
// If we're editing a shape, or we are focusing an editable input, then
// we would want the user's paste interaction to go to that element or
// input instead; e.g. when pasting text into a text shape's content
if (editor.editingShapeId !== null || disallowClipboardEvents(editor)) return
if (editor.getEditingShapeId() !== null || disallowClipboardEvents(editor)) return
// First try to use the clipboard data on the event
if (event.clipboardData && !editor.inputs.shiftKey) {

View file

@ -37,7 +37,7 @@ export function useKeyboardShortcuts() {
// Add hotkeys for actions and tools.
// Except those that in SKIP_KBDS!
const areShortcutsDisabled = () =>
editor.getIsMenuOpen() || editor.editingShapeId !== null || editor.crashingError
editor.getIsMenuOpen() || editor.getEditingShapeId() !== null || editor.crashingError
for (const action of Object.values(actions)) {
if (!action.kbd) continue

View file

@ -53,9 +53,9 @@ const moveShapesToPage2 = () => {
describe('shapes that are moved to another page', () => {
it("should be excluded from the previous page's focusedGroupId", () => {
editor.setFocusedGroup(ids.group1)
expect(editor.focusedGroupId).toBe(ids.group1)
expect(editor.getFocusedGroupId()).toBe(ids.group1)
moveShapesToPage2()
expect(editor.focusedGroupId).toBe(editor.currentPageId)
expect(editor.getFocusedGroupId()).toBe(editor.currentPageId)
})
describe("should be excluded from the previous page's hintingShapeIds", () => {
@ -76,27 +76,27 @@ describe('shapes that are moved to another page', () => {
describe("should be excluded from the previous page's editingShapeId", () => {
test('[root shape]', () => {
editor.setEditingShape(ids.box1)
expect(editor.editingShapeId).toBe(ids.box1)
expect(editor.getEditingShapeId()).toBe(ids.box1)
moveShapesToPage2()
expect(editor.editingShapeId).toBe(null)
expect(editor.getEditingShapeId()).toBe(null)
})
test('[child of frame]', () => {
editor.setEditingShape(ids.box2)
expect(editor.editingShapeId).toBe(ids.box2)
expect(editor.getEditingShapeId()).toBe(ids.box2)
moveShapesToPage2()
expect(editor.editingShapeId).toBe(null)
expect(editor.getEditingShapeId()).toBe(null)
})
test('[child of group]', () => {
editor.setEditingShape(ids.box3)
expect(editor.editingShapeId).toBe(ids.box3)
expect(editor.getEditingShapeId()).toBe(ids.box3)
moveShapesToPage2()
expect(editor.editingShapeId).toBe(null)
expect(editor.getEditingShapeId()).toBe(null)
})
test('[frame that doesnt move]', () => {
editor.setEditingShape(ids.frame1)
expect(editor.editingShapeId).toBe(ids.frame1)
expect(editor.getEditingShapeId()).toBe(ids.frame1)
moveShapesToPage2()
expect(editor.editingShapeId).toBe(ids.frame1)
expect(editor.getEditingShapeId()).toBe(ids.frame1)
})
})

View file

@ -263,12 +263,12 @@ describe('When double clicking the selection edge', () => {
.doubleClick(100, 100, { target: 'selection', handle: 'left' })
.doubleClick(100, 100, { target: 'selection', handle: 'left' })
expect(editor.editingShapeId).toBe(null)
expect(editor.getEditingShapeId()).toBe(null)
editor.expectShapeToMatch({ id, props: { scale: 1, autoSize: true } })
editor.doubleClick(100, 100, { target: 'selection', handle: 'left' })
expect(editor.editingShapeId).toBe(id)
expect(editor.getEditingShapeId()).toBe(id)
})
it('Selects a geo shape when double clicking on its edge', () => {
@ -284,11 +284,11 @@ describe('When double clicking the selection edge', () => {
},
])
.select(id)
expect(editor.editingShapeId).toBe(null)
expect(editor.getEditingShapeId()).toBe(null)
editor.doubleClick(100, 100, { target: 'selection', handle: 'left' })
expect(editor.editingShapeId).toBe(id)
expect(editor.getEditingShapeId()).toBe(id)
})
})
@ -312,51 +312,51 @@ describe('When editing shapes', () => {
})
it('Pointing a shape of a different type selects it and leaves editing', () => {
expect(editor.editingShapeId).toBe(null)
expect(editor.getEditingShapeId()).toBe(null)
expect(editor.getSelectedShapeIds().length).toBe(0)
// start editing the geo shape
editor.doubleClick(50, 50, { target: 'shape', shape: editor.getShape(ids.geo1) })
expect(editor.editingShapeId).toBe(ids.geo1)
expect(editor.getEditingShapeId()).toBe(ids.geo1)
expect(editor.getOnlySelectedShape()?.id).toBe(ids.geo1)
// point the text shape
editor.pointerDown(50, 50, { target: 'shape', shape: editor.getShape(ids.text1) })
expect(editor.editingShapeId).toBe(null)
expect(editor.getEditingShapeId()).toBe(null)
expect(editor.getOnlySelectedShape()?.id).toBe(ids.text1)
})
// The behavior described here will only work end to end, not with the library,
// because useEditableText implements the behavior in React
it.skip('Pointing a shape of a different type selects it and leaves editing', () => {
expect(editor.editingShapeId).toBe(null)
expect(editor.getEditingShapeId()).toBe(null)
expect(editor.getSelectedShapeIds().length).toBe(0)
// start editing the geo shape
editor.doubleClick(50, 50, { target: 'shape', shape: editor.getShape(ids.geo1) })
expect(editor.editingShapeId).toBe(ids.geo1)
expect(editor.getEditingShapeId()).toBe(ids.geo1)
expect(editor.getOnlySelectedShape()?.id).toBe(ids.geo1)
// point the other geo shape
editor.pointerDown(50, 50, { target: 'shape', shape: editor.getShape(ids.geo2) })
// that other shape should now be editing and selected!
expect(editor.editingShapeId).toBe(ids.geo2)
expect(editor.getEditingShapeId()).toBe(ids.geo2)
expect(editor.getOnlySelectedShape()?.id).toBe(ids.geo2)
})
// This works but only end to end — the logic had to move to React
it.skip('Works with text, too', () => {
expect(editor.editingShapeId).toBe(null)
expect(editor.getEditingShapeId()).toBe(null)
expect(editor.getSelectedShapeIds().length).toBe(0)
// start editing the geo shape
editor.doubleClick(50, 50, { target: 'shape', shape: editor.getShape(ids.text1) })
editor.pointerDown(50, 50, { target: 'shape', shape: editor.getShape(ids.text2) })
// that other shape should now be editing and selected!
expect(editor.editingShapeId).toBe(ids.text2)
expect(editor.getEditingShapeId()).toBe(ids.text2)
expect(editor.getOnlySelectedShape()?.id).toBe(ids.text2)
})
it('Double clicking the canvas creates a new text shape', () => {
expect(editor.editingShapeId).toBe(null)
expect(editor.getEditingShapeId()).toBe(null)
expect(editor.getSelectedShapeIds().length).toBe(0)
expect(editor.currentPageShapes.length).toBe(5)
editor.doubleClick(750, 750)
@ -365,7 +365,7 @@ describe('When editing shapes', () => {
})
it('It deletes an empty text shape when your click away', () => {
expect(editor.editingShapeId).toBe(null)
expect(editor.getEditingShapeId()).toBe(null)
expect(editor.getSelectedShapeIds().length).toBe(0)
expect(editor.currentPageShapes.length).toBe(5)
@ -383,7 +383,7 @@ describe('When editing shapes', () => {
})
it('It deletes an empty text shape when your click another text shape', () => {
expect(editor.editingShapeId).toBe(null)
expect(editor.getEditingShapeId()).toBe(null)
expect(editor.getSelectedShapeIds().length).toBe(0)
expect(editor.currentPageShapes.length).toBe(5)
@ -422,17 +422,17 @@ describe('When in readonly mode', () => {
})
it('Begins editing embed when double clicked', () => {
expect(editor.editingShapeId).toBe(null)
expect(editor.getEditingShapeId()).toBe(null)
expect(editor.getSelectedShapeIds().length).toBe(0)
expect(editor.getInstanceState().isReadonly).toBe(true)
const shape = editor.getShape(ids.embed1)
editor.doubleClick(100, 100, { target: 'shape', shape })
expect(editor.editingShapeId).toBe(ids.embed1)
expect(editor.getEditingShapeId()).toBe(ids.embed1)
})
it('Begins editing embed when pressing Enter on a selected embed', () => {
expect(editor.editingShapeId).toBe(null)
expect(editor.getEditingShapeId()).toBe(null)
expect(editor.getSelectedShapeIds().length).toBe(0)
expect(editor.getInstanceState().isReadonly).toBe(true)
@ -440,6 +440,6 @@ describe('When in readonly mode', () => {
expect(editor.getSelectedShapeIds().length).toBe(1)
editor.keyUp('Enter')
expect(editor.editingShapeId).toBe(ids.embed1)
expect(editor.getEditingShapeId()).toBe(ids.embed1)
})
})

View file

@ -477,11 +477,10 @@ export class TestEditor extends Editor {
this.setCurrentTool('select')
const handlePoint = this.selectionRotatedPageBounds!.getHandlePoint(
ROTATE_CORNER_TO_SELECTION_CORNER[handle]
)
const handlePoint = this.getSelectionRotatedPageBounds()!
.getHandlePoint(ROTATE_CORNER_TO_SELECTION_CORNER[handle])
.clone()
.rotWith(this.selectionRotatedPageBounds!.point, this.selectionRotation)
.rotWith(this.getSelectionRotatedPageBounds()!.point, this.getSelectionRotation())
const targetHandlePoint = Vec2d.RotWith(handlePoint, this.selectionPageCenter!, angleRadians)
@ -498,7 +497,8 @@ export class TestEditor extends Editor {
* @public
*/
get selectionPageCenter() {
const { selectionRotatedPageBounds: selectionBounds, selectionRotation } = this
const selectionRotation = this.getSelectionRotation()
const selectionBounds = this.getSelectionRotatedPageBounds()
if (!selectionBounds) return null
return Vec2d.RotWith(selectionBounds.center, selectionBounds.point, selectionRotation)
}
@ -529,7 +529,7 @@ export class TestEditor extends Editor {
throw new Error('No selection')
}
this.setCurrentTool('select')
const bounds = this.selectionRotatedPageBounds!
const bounds = this.getSelectionRotatedPageBounds()!
const preRotationHandlePoint = bounds.getHandlePoint(handle)
const preRotationScaleOriginPoint = options?.altKey
@ -541,11 +541,15 @@ export class TestEditor extends Editor {
preRotationScaleOriginPoint
)
const handlePoint = Vec2d.RotWith(preRotationHandlePoint, bounds.point, this.selectionRotation)
const handlePoint = Vec2d.RotWith(
preRotationHandlePoint,
bounds.point,
this.getSelectionRotation()
)
const targetHandlePoint = Vec2d.RotWith(
preRotationTargetHandlePoint,
bounds.point,
this.selectionRotation
this.getSelectionRotation()
)
this.pointerDown(handlePoint.x, handlePoint.y, { target: 'selection', handle }, options)

View file

@ -64,7 +64,7 @@ it('Does not get an SVG when no ids are provided', async () => {
it('Gets the bounding box at the correct size', async () => {
const svg = await editor.getSvg(editor.getSelectedShapeIds())
const bbox = editor.selectionRotatedPageBounds!
const bbox = editor.getSelectionRotatedPageBounds()!
const expanded = bbox.expandBy(SVG_PADDING) // adds 32px padding
expect(svg!.getAttribute('width')).toMatch(expanded.width + '')
@ -73,7 +73,7 @@ it('Gets the bounding box at the correct size', async () => {
it('Gets the bounding box at the correct size', async () => {
const svg = (await editor.getSvg(editor.getSelectedShapeIds()))!
const bbox = editor.selectionRotatedPageBounds!
const bbox = editor.getSelectionRotatedPageBounds()!
const expanded = bbox.expandBy(SVG_PADDING) // adds 32px padding
expect(svg!.getAttribute('width')).toMatch(expanded.width + '')

View file

@ -240,7 +240,7 @@ describe('arrows', () => {
editor.setCurrentTool('arrow').pointerDown(250, 250).pointerMove(450, 450).pointerUp(450, 450)
editor.moveShapesToPage([ids.box1, ids.box2], ids.page2)
const { selectionPageBounds } = editor
const selectionPageBounds = editor.getSelectionPageBounds()
expect(editor.viewportPageCenter).toMatchObject(selectionPageBounds!.center)
})
})

View file

@ -73,14 +73,14 @@ describe('When a shape is selected...', () => {
editor.setSelectedShapes([ids.boxA])
editor.keyDown('ArrowUp')
expect(editor.selectionPageBounds).toMatchObject({ x: 10, y: 9 })
expect(editor.getSelectionPageBounds()).toMatchObject({ x: 10, y: 9 })
editor.keyUp('ArrowUp')
editor.undo()
expect(editor.selectionPageBounds).toMatchObject({ x: 10, y: 10 })
expect(editor.getSelectionPageBounds()).toMatchObject({ x: 10, y: 10 })
editor.redo()
expect(editor.selectionPageBounds).toMatchObject({ x: 10, y: 9 })
expect(editor.getSelectionPageBounds()).toMatchObject({ x: 10, y: 9 })
})
it('nudges and holds', () => {
@ -93,34 +93,34 @@ describe('When a shape is selected...', () => {
editor.keyRepeat('ArrowUp')
editor.keyUp('ArrowUp')
expect(editor.selectionPageBounds).toMatchObject({ x: 10, y: 5 })
expect(editor.getSelectionPageBounds()).toMatchObject({ x: 10, y: 5 })
// Undoing should go back to the keydown state, all those
// repeats should be ephemeral and squashed down
editor.undo()
expect(editor.selectionPageBounds).toMatchObject({ x: 10, y: 10 })
expect(editor.getSelectionPageBounds()).toMatchObject({ x: 10, y: 10 })
editor.redo()
expect(editor.selectionPageBounds).toMatchObject({ x: 10, y: 5 })
expect(editor.getSelectionPageBounds()).toMatchObject({ x: 10, y: 5 })
})
it('nudges a shape correctly', () => {
editor.setSelectedShapes([ids.boxA])
editor.keyDown('ArrowUp')
expect(editor.selectionPageBounds).toMatchObject({ x: 10, y: 9 })
expect(editor.getSelectionPageBounds()).toMatchObject({ x: 10, y: 9 })
editor.keyUp('ArrowUp')
editor.keyDown('ArrowRight')
expect(editor.selectionPageBounds).toMatchObject({ x: 11, y: 9 })
expect(editor.getSelectionPageBounds()).toMatchObject({ x: 11, y: 9 })
editor.keyUp('ArrowRight')
editor.keyDown('ArrowDown')
expect(editor.selectionPageBounds).toMatchObject({ x: 11, y: 10 })
expect(editor.getSelectionPageBounds()).toMatchObject({ x: 11, y: 10 })
editor.keyUp('ArrowDown')
editor.keyDown('ArrowLeft')
expect(editor.selectionPageBounds).toMatchObject({ x: 10, y: 10 })
expect(editor.getSelectionPageBounds()).toMatchObject({ x: 10, y: 10 })
editor.keyUp('ArrowLeft')
})
})
@ -141,13 +141,13 @@ describe('When a shape is rotated...', () => {
// Here's the selection page bounds and shape before we nudge it
editor.setSelectedShapes([ids.boxA])
expect(editor.selectionPageBounds).toCloselyMatchObject({ x: 10, y: 10, w: 100, h: 100 })
expect(editor.getSelectionPageBounds()).toCloselyMatchObject({ x: 10, y: 10, w: 100, h: 100 })
expect(editor.getShape(ids.boxA)).toCloselyMatchObject({ x: 10, y: -10 })
// Select box A and move it up. The page bounds should move up, but the
// shape should move left (since its parent is rotated 90 degrees)
editor.keyDown('ArrowUp')
expect(editor.selectionPageBounds).toMatchObject({ x: 10, y: 9, w: 100, h: 100 })
expect(editor.getSelectionPageBounds()).toMatchObject({ x: 10, y: 9, w: 100, h: 100 })
expect(editor.getShape(ids.boxA)).toMatchObject({ x: 9, y: -10 })
editor.keyUp('ArrowUp')
})

View file

@ -41,13 +41,13 @@ beforeEach(() => {
describe('editor.packShapes', () => {
it('packs shapes', () => {
editor.selectAll()
const centerBefore = editor.selectionRotatedPageBounds!.center.clone()
const centerBefore = editor.getSelectionRotatedPageBounds()!.center.clone()
editor.packShapes(editor.getSelectedShapeIds(), 16)
jest.advanceTimersByTime(1000)
expect(editor.currentPageShapes.map((s) => ({ ...s, parentId: 'wahtever' }))).toMatchSnapshot(
'packed shapes'
)
const centerAfter = editor.selectionRotatedPageBounds!.center.clone()
const centerAfter = editor.getSelectionRotatedPageBounds()!.center.clone()
expect(centerBefore).toMatchObject(centerAfter)
})

View file

@ -176,9 +176,9 @@ describe('When duplicating shapes that include arrows', () => {
it('Preserves the same selection bounds', () => {
editor.selectAll().deleteShapes(editor.getSelectedShapeIds()).createShapes(shapes).selectAll()
const boundsBefore = editor.selectionRotatedPageBounds!
const boundsBefore = editor.getSelectionRotatedPageBounds()!
editor.duplicateShapes(editor.getSelectedShapeIds())
expect(editor.selectionRotatedPageBounds).toCloselyMatchObject(boundsBefore)
expect(editor.getSelectionRotatedPageBounds()).toCloselyMatchObject(boundsBefore)
})
it('Preserves the same selection bounds when only duplicating the arrows', () => {
@ -192,9 +192,9 @@ describe('When duplicating shapes that include arrows', () => {
.map((s) => s.id)
)
const boundsBefore = editor.selectionRotatedPageBounds!
const boundsBefore = editor.getSelectionRotatedPageBounds()!
editor.duplicateShapes(editor.getSelectedShapeIds())
const boundsAfter = editor.selectionRotatedPageBounds!
const boundsAfter = editor.getSelectionRotatedPageBounds()!
// It's not exactly exact, but close enough is plenty close
expect(Math.abs(boundsAfter.x - boundsBefore.x)).toBeLessThan(1)

View file

@ -104,11 +104,11 @@ describe('When flipping horizontally', () => {
it('Flips rotated shapes', () => {
editor.updateShapes([{ id: ids.boxA, type: 'geo', rotation: PI }])
editor.select(ids.boxA, ids.boxB)
const a = editor.selectionPageBounds
const a = editor.getSelectionPageBounds()
editor.mark('flipped')
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
const b = editor.selectionPageBounds
const b = editor.getSelectionPageBounds()
expect(a!).toCloselyMatchObject(b!)
editor.expectShapeToMatch(
@ -129,11 +129,11 @@ describe('When flipping horizontally', () => {
editor.reparentShapes([ids.boxB], ids.boxA)
editor.updateShapes([{ id: ids.boxA, type: 'geo', rotation: PI }])
editor.select(ids.boxB, ids.boxC)
const a = editor.selectionPageBounds
const a = editor.getSelectionPageBounds()
editor.mark('flipped')
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
const b = editor.selectionPageBounds
const b = editor.getSelectionPageBounds()
expect(a).toCloselyMatchObject(b!)
})
})
@ -184,11 +184,11 @@ describe('When flipping vertically', () => {
it('Flips rotated shapes', () => {
editor.updateShapes([{ id: ids.boxA, type: 'geo', rotation: PI }])
editor.select(ids.boxA, ids.boxB)
const a = editor.selectionPageBounds
const a = editor.getSelectionPageBounds()
editor.mark('flipped')
editor.flipShapes(editor.getSelectedShapeIds(), 'vertical')
const b = editor.selectionPageBounds
const b = editor.getSelectionPageBounds()
expect(a).toCloselyMatchObject(b!)
editor.expectShapeToMatch(
{
@ -208,27 +208,27 @@ describe('When flipping vertically', () => {
editor.reparentShapes([ids.boxB], ids.boxA)
editor.updateShapes([{ id: ids.boxA, type: 'geo', rotation: PI }])
editor.select(ids.boxB, ids.boxC)
const a = editor.selectionPageBounds
const a = editor.getSelectionPageBounds()
editor.mark('flipped')
editor.flipShapes(editor.getSelectedShapeIds(), 'vertical')
const b = editor.selectionPageBounds
const b = editor.getSelectionPageBounds()
expect(a).toCloselyMatchObject(b!)
})
})
it('Preserves the selection bounds.', () => {
editor.selectAll()
const a = editor.selectionPageBounds
const a = editor.getSelectionPageBounds()
editor.mark('flipped')
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
const b = editor.selectionPageBounds
const b = editor.getSelectionPageBounds()
expect(a).toMatchObject(b!)
editor.mark('flipped')
editor.flipShapes(editor.getSelectedShapeIds(), 'vertical')
const c = editor.selectionPageBounds
const c = editor.getSelectionPageBounds()
expect(a).toMatchObject(c!)
})
@ -560,16 +560,16 @@ describe('When flipping shapes that include arrows', () => {
it('Flips horizontally', () => {
editor.selectAll().deleteShapes(editor.getSelectedShapeIds()).createShapes(shapes)
const boundsBefore = editor.selectionRotatedPageBounds!
const boundsBefore = editor.getSelectionRotatedPageBounds()!
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
expect(editor.selectionRotatedPageBounds).toCloselyMatchObject(boundsBefore)
expect(editor.getSelectionRotatedPageBounds()).toCloselyMatchObject(boundsBefore)
})
it('Flips vertically', () => {
editor.selectAll().deleteShapes(editor.getSelectedShapeIds()).createShapes(shapes)
const boundsBefore = editor.selectionRotatedPageBounds!
const boundsBefore = editor.getSelectionRotatedPageBounds()!
editor.flipShapes(editor.getSelectedShapeIds(), 'vertical')
expect(editor.selectionRotatedPageBounds).toCloselyMatchObject(boundsBefore)
expect(editor.getSelectionRotatedPageBounds()).toCloselyMatchObject(boundsBefore)
})
})

View file

@ -761,7 +761,7 @@ describe('When dragging a shape inside a group inside a frame', () => {
editor.pointerMove(100, 100).click().click()
expect(editor.getOnlySelectedShape()?.id).toBe(ids.box1)
expect(editor.focusedGroupId).toBe(ids.group1)
expect(editor.getFocusedGroupId()).toBe(ids.group1)
editor
.pointerMove(150, 150)

View file

@ -825,39 +825,39 @@ describe('focus layers', () => {
editor.selectNone()
})
it('should adjust to the parent layer of any selected shape', () => {
expect(editor.focusedGroupId).toBe(editor.currentPageId)
expect(editor.getFocusedGroupId()).toBe(editor.currentPageId)
editor.select(ids.boxA)
expect(editor.focusedGroupId).toBe(groupAId)
expect(editor.getFocusedGroupId()).toBe(groupAId)
editor.select(ids.boxB)
expect(editor.focusedGroupId).toBe(groupAId)
expect(editor.getFocusedGroupId()).toBe(groupAId)
editor.select(ids.boxC)
expect(editor.focusedGroupId).toBe(groupBId)
expect(editor.getFocusedGroupId()).toBe(groupBId)
editor.select(ids.boxD)
expect(editor.focusedGroupId).toBe(groupBId)
expect(editor.getFocusedGroupId()).toBe(groupBId)
editor.select(groupAId)
expect(editor.focusedGroupId).toBe(groupCId)
expect(editor.getFocusedGroupId()).toBe(groupCId)
})
it('should adjust to the common ancestor of selected shapes in multiple groups', () => {
expect(editor.focusedGroupId).toBe(editor.currentPageId)
expect(editor.getFocusedGroupId()).toBe(editor.currentPageId)
editor.select(ids.boxA)
expect(editor.focusedGroupId).toBe(groupAId)
expect(editor.getFocusedGroupId()).toBe(groupAId)
editor.setSelectedShapes([...editor.getSelectedShapeIds(), ids.boxC])
expect(editor.focusedGroupId).toBe(groupCId)
expect(editor.getFocusedGroupId()).toBe(groupCId)
editor.deselect(ids.boxA)
expect(editor.focusedGroupId).toBe(groupBId)
expect(editor.getFocusedGroupId()).toBe(groupBId)
editor.setSelectedShapes([...editor.getSelectedShapeIds(), ids.boxB])
expect(editor.focusedGroupId).toBe(groupCId)
expect(editor.getFocusedGroupId()).toBe(groupCId)
})
it('should not adjust the focus layer when clearing the selection', () => {
expect(editor.focusedGroupId).toBe(editor.currentPageId)
expect(editor.getFocusedGroupId()).toBe(editor.currentPageId)
editor.select(ids.boxA)
expect(editor.focusedGroupId).toBe(groupAId)
expect(editor.getFocusedGroupId()).toBe(groupAId)
editor.deselect(ids.boxA)
expect(editor.focusedGroupId).toBe(groupAId)
expect(editor.getFocusedGroupId()).toBe(groupAId)
editor.select(ids.boxB, ids.boxC)
expect(editor.focusedGroupId).toBe(groupCId)
expect(editor.getFocusedGroupId()).toBe(groupCId)
editor.selectNone()
expect(editor.focusedGroupId).toBe(groupCId)
expect(editor.getFocusedGroupId()).toBe(groupCId)
})
})
@ -922,14 +922,14 @@ describe('the select tool', () => {
it('should select the outermost non-selected group when you click on one of the shapes in that group', () => {
editor.pointerDown(0, 0, ids.boxA).pointerUp(0, 0)
expect(onlySelectedId()).toBe(groupCId)
expect(editor.focusedGroupId).toBe(editor.currentPageId)
expect(editor.getFocusedGroupId()).toBe(editor.currentPageId)
editor.pointerDown(0, 0, ids.boxA)
editor.pointerUp(0, 0, ids.boxA)
expect(onlySelectedId()).toBe(groupAId)
expect(editor.focusedGroupId).toBe(groupCId)
expect(editor.getFocusedGroupId()).toBe(groupCId)
editor.pointerDown(0, 0, ids.boxA).pointerUp(0, 0, ids.boxA)
expect(onlySelectedId()).toBe(ids.boxA)
expect(editor.focusedGroupId).toBe(groupAId)
expect(editor.getFocusedGroupId()).toBe(groupAId)
})
it('should select the outermost non-selected group when you right-click on one of the shapes in that group', () => {
@ -939,17 +939,17 @@ describe('the select tool', () => {
.pointerDown(0, 0, { target: 'shape', shape: boxA, button: 2 })
.pointerUp(0, 0, { button: 2 })
expect(onlySelectedId()).toBe(groupCId)
expect(editor.focusedGroupId).toBe(editor.currentPageId)
expect(editor.getFocusedGroupId()).toBe(editor.currentPageId)
editor
.pointerDown(0, 0, { target: 'shape', shape: boxA, button: 2 })
.pointerUp(0, 0, { button: 2 })
expect(onlySelectedId()).toBe(groupAId)
expect(editor.focusedGroupId).toBe(groupCId)
expect(editor.getFocusedGroupId()).toBe(groupCId)
editor
.pointerDown(0, 0, { target: 'shape', shape: boxA, button: 2 })
.pointerUp(0, 0, { button: 2 })
expect(onlySelectedId()).toBe(ids.boxA)
expect(editor.focusedGroupId).toBe(groupAId)
expect(editor.getFocusedGroupId()).toBe(groupAId)
})
it('should allow to shift-select other shapes outside of the current focus layer', () => {
@ -957,37 +957,37 @@ describe('the select tool', () => {
editor.pointerDown(0, 0, ids.boxA).pointerUp(0, 0)
editor.pointerDown(0, 0, ids.boxA).pointerUp(0, 0)
expect(onlySelectedId()).toBe(ids.boxA)
expect(editor.focusedGroupId).toBe(groupAId)
expect(editor.getFocusedGroupId()).toBe(groupAId)
editor
.pointerDown(60, 0, ids.boxC, { shiftKey: true })
.pointerUp(0, 0, ids.boxC, { shiftKey: true })
expect(editor.getSelectedShapeIds().includes(ids.boxA)).toBe(true)
expect(editor.getSelectedShapeIds().includes(groupBId)).toBe(true)
expect(editor.focusedGroupId).toBe(groupCId)
expect(editor.getFocusedGroupId()).toBe(groupCId)
editor.pointerDown(60, 0, ids.boxC, { shiftKey: true }).pointerUp()
expect(editor.getSelectedShapeIds().includes(ids.boxA)).toBe(true)
expect(editor.getSelectedShapeIds().includes(groupBId)).toBe(false)
expect(editor.getSelectedShapeIds().includes(ids.boxC)).toBe(true)
expect(editor.focusedGroupId).toBe(groupCId)
expect(editor.getFocusedGroupId()).toBe(groupCId)
})
it('if a shape inside a focused group is selected and you click outside the group it should clear the selection and focus the page', () => {
editor.select(ids.boxA)
expect(editor.focusedGroupId).toBe(groupAId)
expect(editor.getFocusedGroupId()).toBe(groupAId)
// click outside the focused group, but inside another group
editor.pointerDown(-235, 5, { target: 'canvas' }).pointerUp(-235, 5)
expect(editor.focusedGroupId).toBe(editor.currentPageId)
expect(editor.getFocusedGroupId()).toBe(editor.currentPageId)
expect(editor.getSelectedShapeIds()).toHaveLength(0)
editor.select(ids.boxA)
expect(editor.focusedGroupId).toBe(groupAId)
expect(editor.getFocusedGroupId()).toBe(groupAId)
// click the empty canvas
editor.pointerDown(-235, 50, { target: 'canvas' }).pointerUp(-235, 50)
expect(editor.focusedGroupId).toBe(editor.currentPageId)
expect(editor.getFocusedGroupId()).toBe(editor.currentPageId)
expect(editor.getSelectedShapeIds()).toHaveLength(0)
})
@ -1016,18 +1016,18 @@ describe('the select tool', () => {
it('should pop the focus layer when escape is pressed in idle state', () => {
editor.select(ids.boxA)
expect(editor.getSelectedShapeIds()).toMatchObject([ids.boxA]) // box1
expect(editor.focusedGroupId).toBe(groupAId)
expect(editor.getFocusedGroupId()).toBe(groupAId)
// deselct
editor.cancel()
expect(editor.getSelectedShapeIds()).toMatchObject([groupAId]) // groupA
expect(editor.focusedGroupId).toBe(groupCId)
expect(editor.getFocusedGroupId()).toBe(groupCId)
// pop focus layer
editor.cancel()
expect(editor.getSelectedShapeIds().length).toBe(1) // Group C
expect(editor.focusedGroupId).toBe(editor.currentPageId)
expect(editor.getFocusedGroupId()).toBe(editor.currentPageId)
editor.cancel()
expect(editor.getSelectedShapeIds().length).toBe(0)
expect(editor.focusedGroupId).toBe(editor.currentPageId)
expect(editor.getFocusedGroupId()).toBe(editor.currentPageId)
})
// ! Removed: pointing a group is impossible; you'd be pointing the selection instead.
@ -1172,7 +1172,7 @@ describe('creating new shapes', () => {
it('does create inside the group if the group is focused', () => {
editor.select(ids.boxA)
expect(editor.focusedGroupId === groupA.id).toBe(true)
expect(editor.getFocusedGroupId() === groupA.id).toBe(true)
editor.setCurrentTool('geo')
editor.pointerDown(20, 20).pointerMove(80, 80).pointerUp(80, 80)
@ -1185,12 +1185,12 @@ describe('creating new shapes', () => {
w: 60,
h: 60,
})
expect(editor.focusedGroupId === groupA.id).toBe(true)
expect(editor.getFocusedGroupId() === groupA.id).toBe(true)
})
it('will reisze the group appropriately if the new shape changes the group bounds', () => {
editor.select(ids.boxA)
expect(editor.focusedGroupId === groupA.id).toBe(true)
expect(editor.getFocusedGroupId() === groupA.id).toBe(true)
editor.setCurrentTool('geo')
editor.pointerDown(20, 20).pointerMove(-10, -10)
@ -1219,7 +1219,7 @@ describe('creating new shapes', () => {
it('works if the shape drawing begins outside of the current group bounds', () => {
editor.select(ids.boxA)
expect(editor.focusedGroupId === groupA.id).toBe(true)
expect(editor.getFocusedGroupId() === groupA.id).toBe(true)
editor.setCurrentTool('geo')
editor.pointerDown(-50, -50).pointerMove(-100, -100).pointerUp()
@ -1254,7 +1254,7 @@ describe('creating new shapes', () => {
it('does draw inside the group if the group is focused', () => {
editor.select(ids.boxA)
expect(editor.focusedGroupId === groupA.id).toBe(true)
expect(editor.getFocusedGroupId() === groupA.id).toBe(true)
editor.setCurrentTool('draw')
editor.pointerDown(20, 20).pointerMove(80, 80).pointerUp(80, 80)
@ -1265,7 +1265,7 @@ describe('creating new shapes', () => {
it('will resize the group appropriately if the new shape changes the group bounds', () => {
editor.select(ids.boxA)
expect(editor.focusedGroupId === groupA.id).toBe(true)
expect(editor.getFocusedGroupId() === groupA.id).toBe(true)
editor.setCurrentTool('draw')
editor.pointerDown(20, 20)
@ -1293,7 +1293,7 @@ describe('creating new shapes', () => {
it('works if the shape drawing begins outside of the current group bounds', () => {
editor.select(ids.boxA)
expect(editor.focusedGroupId === groupA.id).toBe(true)
expect(editor.getFocusedGroupId() === groupA.id).toBe(true)
editor.setCurrentTool('draw')
editor.pointerDown(-20, -20)
@ -1335,7 +1335,7 @@ describe('creating new shapes', () => {
it('does draw inside the group if the group is focused', () => {
editor.select(ids.boxA)
expect(editor.focusedGroupId === groupA.id).toBe(true)
expect(editor.getFocusedGroupId() === groupA.id).toBe(true)
editor.setCurrentTool('line')
editor.pointerDown(20, 20).pointerMove(80, 80).pointerUp(80, 80)
@ -1347,7 +1347,7 @@ describe('creating new shapes', () => {
it('will reisze the group appropriately if the new shape changes the group bounds', () => {
editor.select(ids.boxA)
expect(editor.focusedGroupId === groupA.id).toBe(true)
expect(editor.getFocusedGroupId() === groupA.id).toBe(true)
editor.setCurrentTool('line')
editor.pointerDown(20, 20).pointerMove(-10, -10)
@ -1363,7 +1363,7 @@ describe('creating new shapes', () => {
it('works if the shape drawing begins outside of the current group bounds', () => {
editor.select(ids.boxA)
expect(editor.focusedGroupId === groupA.id).toBe(true)
expect(editor.getFocusedGroupId() === groupA.id).toBe(true)
editor.setCurrentTool('line')
editor.pointerDown(-50, -50).pointerMove(-100, -100).pointerUp()
@ -1378,7 +1378,7 @@ describe('creating new shapes', () => {
describe('sticky notes', () => {
it('does not draw inside the group if the group is only selected and not focused', () => {
editor.select(groupA.id)
expect(editor.focusedGroupId === editor.currentPageId).toBe(true)
expect(editor.getFocusedGroupId() === editor.currentPageId).toBe(true)
editor.setCurrentTool('note')
editor.pointerDown(20, 20).pointerUp()
@ -1389,7 +1389,7 @@ describe('creating new shapes', () => {
it('does draw inside the group if the group is focused', () => {
editor.select(ids.boxA)
expect(editor.focusedGroupId === groupA.id).toBe(true)
expect(editor.getFocusedGroupId() === groupA.id).toBe(true)
editor.setCurrentTool('note')
editor.pointerDown(20, 20).pointerUp()
@ -1400,7 +1400,7 @@ describe('creating new shapes', () => {
it('will reisze the group appropriately if the new shape changes the group bounds', () => {
editor.select(ids.boxA)
expect(editor.focusedGroupId === groupA.id).toBe(true)
expect(editor.getFocusedGroupId() === groupA.id).toBe(true)
expect(editor.getShapePageBounds(groupA.id)).toCloselyMatchObject({
x: 0,
@ -1432,7 +1432,7 @@ describe('creating new shapes', () => {
it('works if the shape drawing begins outside of the current group bounds', () => {
editor.select(ids.boxA)
expect(editor.focusedGroupId === groupA.id).toBe(true)
expect(editor.getFocusedGroupId() === groupA.id).toBe(true)
editor.setCurrentTool('note')
expect(editor.getShapePageBounds(groupA.id)).toCloselyMatchObject({
@ -1510,7 +1510,7 @@ describe('erasing', () => {
it('works inside of groups', () => {
editor.select(ids.boxA)
expect(editor.focusedGroupId === groupAId).toBe(true)
expect(editor.getFocusedGroupId() === groupAId).toBe(true)
const groupA = editor.getShape(groupAId)!
editor.setCurrentTool('eraser')
@ -1527,7 +1527,7 @@ describe('erasing', () => {
it('works outside of the focus layer', () => {
editor.select(ids.boxA)
expect(editor.focusedGroupId === groupAId).toBe(true)
expect(editor.getFocusedGroupId() === groupAId).toBe(true)
editor.setCurrentTool('eraser')
@ -1710,7 +1710,7 @@ describe('moving handles within a group', () => {
})
it('resizes the group appropriately', () => {
editor.select(ids.boxA)
expect(editor.focusedGroupId).toBe(groupA.id)
expect(editor.getFocusedGroupId()).toBe(groupA.id)
editor.setCurrentTool('arrow')

View file

@ -243,9 +243,9 @@ describe('When resizing a rotated shape...', () => {
const initialPagePoint = editor.getShapePageTransform(ids.boxA)!.point()
const pt0 = Vec2d.From(initialPagePoint)
const pt1 = Vec2d.RotWith(initialPagePoint, editor.selectionPageBounds!.center, rotation)
const pt1 = Vec2d.RotWith(initialPagePoint, editor.getSelectionPageBounds()!.center, rotation)
const pt2 = Vec2d.Sub(initialPagePoint, offset).rotWith(
editor.selectionPageBounds!.center!,
editor.getSelectionPageBounds()!.center!,
rotation
)
@ -332,7 +332,7 @@ describe('When resizing mulitple shapes...', () => {
.select(ids.boxA)
.pointerDown(rotateStart.x, rotateStart.y, {
target: 'selection',
handle: rotateRotateCorner('top_left_rotate', -editor.selectionRotation),
handle: rotateRotateCorner('top_left_rotate', -editor.getSelectionRotation()),
})
.pointerMove(rotateEnd.x, rotateEnd.y)
.pointerUp()
@ -347,7 +347,7 @@ describe('When resizing mulitple shapes...', () => {
// Now drag to resize the selection bounds
const initialBounds = editor.selectionPageBounds!
const initialBounds = editor.getSelectionPageBounds()!
// oddly rotated shapes maintain aspect ratio when being resized (for now)
const aspectRatio = initialBounds.width / initialBounds.height
@ -367,15 +367,15 @@ describe('When resizing mulitple shapes...', () => {
editor
.pointerDown(resizeStart.x, resizeStart.y, {
target: 'selection',
handle: rotateSelectionHandle('top_left', -editor.selectionRotation),
handle: rotateSelectionHandle('top_left', -editor.getSelectionRotation()),
})
.pointerMove(resizeStart.x - 10, resizeStart.y - 10)
.pointerMove(resizeEnd.x, resizeEnd.y)
.pointerUp()
expect(editor.selectionPageBounds!.point).toCloselyMatchObject(resizeEnd)
expect(editor.getSelectionPageBounds()!.point).toCloselyMatchObject(resizeEnd)
expect(new Vec2d(initialBounds.maxX, initialBounds.maxY)).toCloselyMatchObject(
new Vec2d(editor.selectionPageBounds!.maxX, editor.selectionPageBounds!.maxY)
new Vec2d(editor.getSelectionPageBounds()!.maxX, editor.getSelectionPageBounds()!.maxY)
)
}
)
@ -423,7 +423,7 @@ describe('Reisizing a selection of multiple shapes', () => {
editor.pointerDown(30, 30, { target: 'selection', handle: 'bottom_right' })
editor.pointerMove(15, 15)
expect(roundedBox(editor.selectionPageBounds!)).toMatchObject({ w: 15, h: 15 })
expect(roundedBox(editor.getSelectionPageBounds()!)).toMatchObject({ w: 15, h: 15 })
expect(roundedPageBounds(ids.boxA)).toMatchObject({ x: 0, y: 0, w: 5, h: 5 })
expect(roundedPageBounds(ids.boxB)).toMatchObject({ x: 10, y: 10, w: 5, h: 5 })
@ -447,7 +447,7 @@ describe('Reisizing a selection of multiple shapes', () => {
// └──────────────────────────────────────────────────────────────────O
editor.pointerMove(60, 30)
expect(roundedBox(editor.selectionPageBounds!)).toMatchObject({ w: 60, h: 30 })
expect(roundedBox(editor.getSelectionPageBounds()!)).toMatchObject({ w: 60, h: 30 })
expect(roundedPageBounds(ids.boxA)).toMatchObject({ x: 0, y: 0, w: 20, h: 10 })
expect(roundedPageBounds(ids.boxB)).toMatchObject({ x: 40, y: 20, w: 20, h: 10 })
// stretch vertically
@ -482,7 +482,7 @@ describe('Reisizing a selection of multiple shapes', () => {
// 60 │ └──────────┘ │
// └─────────────────────────────────O
editor.pointerMove(30, 60)
expect(roundedBox(editor.selectionPageBounds!)).toMatchObject({ w: 30, h: 60 })
expect(roundedBox(editor.getSelectionPageBounds()!)).toMatchObject({ w: 30, h: 60 })
expect(roundedPageBounds(ids.boxA)).toMatchObject({ x: 0, y: 0, w: 10, h: 20 })
expect(roundedPageBounds(ids.boxB)).toMatchObject({ x: 20, y: 40, w: 10, h: 20 })
@ -499,7 +499,7 @@ describe('Reisizing a selection of multiple shapes', () => {
// │ └───┘ │
// └───────────────┘
editor.pointerMove(-15, -15)
expect(roundedBox(editor.selectionPageBounds!)).toMatchObject({ w: 15, h: 15 })
expect(roundedBox(editor.getSelectionPageBounds()!)).toMatchObject({ w: 15, h: 15 })
expect(roundedPageBounds(ids.boxA)).toMatchObject({ x: -5, y: -5, w: 5, h: 5 })
expect(roundedPageBounds(ids.boxB)).toMatchObject({ x: -15, y: -15, w: 5, h: 5 })
@ -523,7 +523,7 @@ describe('Reisizing a selection of multiple shapes', () => {
// └───────────────────────────────────O
editor.pointerMove(45, 45, { altKey: true })
expect(roundedBox(editor.selectionPageBounds!)).toMatchObject({
expect(roundedBox(editor.getSelectionPageBounds()!)).toMatchObject({
w: 60,
h: 60,
x: -15,
@ -548,7 +548,7 @@ describe('Reisizing a selection of multiple shapes', () => {
editor.pointerMove(15, 8, { altKey: false, shiftKey: true })
jest.advanceTimersByTime(200)
expect(roundedBox(editor.selectionPageBounds!)).toMatchObject({ w: 15, h: 15 })
expect(roundedBox(editor.getSelectionPageBounds()!)).toMatchObject({ w: 15, h: 15 })
expect(roundedPageBounds(ids.boxA)).toMatchObject({ x: 0, y: 0, w: 5, h: 5 })
expect(roundedPageBounds(ids.boxB)).toMatchObject({ x: 10, y: 10, w: 5, h: 5 })
@ -571,7 +571,7 @@ describe('Reisizing a selection of multiple shapes', () => {
// │ └──────────┘ │
// └───────────────────────────────────O
editor.pointerMove(45, 16, { altKey: true, shiftKey: true })
expect(roundedBox(editor.selectionPageBounds!)).toMatchObject({
expect(roundedBox(editor.getSelectionPageBounds()!)).toMatchObject({
w: 60,
h: 60,
x: -15,
@ -615,14 +615,14 @@ describe('Reisizing a selection of multiple shapes', () => {
editor.pointerDown(30, 30, {
target: 'selection',
handle: rotateSelectionHandle('bottom_right', -editor.selectionRotation),
handle: rotateSelectionHandle('bottom_right', -editor.getSelectionRotation()),
})
editor.pointerMove(15, 15)
expect(roundedPageBounds(ids.boxA)).toMatchObject({ x: 0, y: 0, w: 5, h: 5 })
expect(roundedPageBounds(ids.boxB)).toMatchObject({ x: 10, y: 10, w: 5, h: 5 })
expect(roundedBox(editor.selectionPageBounds!)).toMatchObject({ w: 15, h: 15 })
expect(roundedBox(editor.getSelectionPageBounds()!)).toMatchObject({ w: 15, h: 15 })
// strech horizontally
@ -644,7 +644,7 @@ describe('Reisizing a selection of multiple shapes', () => {
// └──────────────────────────────────────────────────────────────────O
editor.pointerMove(60, 30)
expect(roundedBox(editor.selectionPageBounds!)).toMatchObject({ w: 60, h: 30 })
expect(roundedBox(editor.getSelectionPageBounds()!)).toMatchObject({ w: 60, h: 30 })
expect(roundedPageBounds(ids.boxA)).toMatchObject({ x: 0, y: 0, w: 20, h: 10 })
expect(roundedPageBounds(ids.boxB)).toMatchObject({ x: 40, y: 20, w: 20, h: 10 })
// stretch vertically
@ -679,7 +679,7 @@ describe('Reisizing a selection of multiple shapes', () => {
// 60 │ └──────────┘ │
// └─────────────────────────────────O
editor.pointerMove(30, 60)
expect(roundedBox(editor.selectionPageBounds!)).toMatchObject({ w: 30, h: 60 })
expect(roundedBox(editor.getSelectionPageBounds()!)).toMatchObject({ w: 30, h: 60 })
expect(roundedPageBounds(ids.boxA)).toMatchObject({ x: 0, y: 0, w: 10, h: 20 })
expect(roundedPageBounds(ids.boxB)).toMatchObject({ x: 20, y: 40, w: 10, h: 20 })
@ -696,7 +696,7 @@ describe('Reisizing a selection of multiple shapes', () => {
// │ └───┘ │
// └───────────────┘
editor.pointerMove(-15, -15)
expect(roundedBox(editor.selectionPageBounds!)).toMatchObject({ w: 15, h: 15 })
expect(roundedBox(editor.getSelectionPageBounds()!)).toMatchObject({ w: 15, h: 15 })
expect(roundedPageBounds(ids.boxA)).toMatchObject({ x: -5, y: -5, w: 5, h: 5 })
expect(roundedPageBounds(ids.boxB)).toMatchObject({ x: -15, y: -15, w: 5, h: 5 })
@ -719,7 +719,7 @@ describe('Reisizing a selection of multiple shapes', () => {
// │ └──────────┘ │
// └───────────────────────────────────O
editor.pointerMove(45, 45, { altKey: true })
expect(roundedBox(editor.selectionPageBounds!)).toMatchObject({
expect(roundedBox(editor.getSelectionPageBounds()!)).toMatchObject({
w: 60,
h: 60,
x: -15,
@ -744,7 +744,7 @@ describe('Reisizing a selection of multiple shapes', () => {
editor.pointerMove(15, 8, { altKey: false, shiftKey: true })
jest.advanceTimersByTime(200)
expect(roundedBox(editor.selectionPageBounds!)).toMatchObject({ w: 15, h: 15 })
expect(roundedBox(editor.getSelectionPageBounds()!)).toMatchObject({ w: 15, h: 15 })
expect(roundedPageBounds(ids.boxA)).toMatchObject({ x: 0, y: 0, w: 5, h: 5 })
expect(roundedPageBounds(ids.boxB)).toMatchObject({ x: 10, y: 10, w: 5, h: 5 })
@ -767,7 +767,7 @@ describe('Reisizing a selection of multiple shapes', () => {
// │ └──────────┘ │
// └───────────────────────────────────O
editor.pointerMove(45, 16, { altKey: true, shiftKey: true })
expect(roundedBox(editor.selectionPageBounds!)).toMatchObject({
expect(roundedBox(editor.getSelectionPageBounds()!)).toMatchObject({
w: 60,
h: 60,
x: -15,
@ -803,7 +803,7 @@ describe('Reisizing a selection of multiple shapes', () => {
editor.select(ids.boxA, ids.boxB)
editor.pointerDown(30, 30, { target: 'selection', handle: 'bottom_right' })
editor.pointerMove(60, 30)
expect(roundedBox(editor.selectionPageBounds!)).toMatchObject({ w: 60, h: 30 })
expect(roundedBox(editor.getSelectionPageBounds()!)).toMatchObject({ w: 60, h: 30 })
// A should stretch
expect(roundedPageBounds(ids.boxA)).toMatchObject({ x: 0, y: 0, w: 20, h: 10 })
// B should not

View file

@ -119,7 +119,7 @@ describe('When rotating...', () => {
editor.select(ids.box1)
const shapeA = editor.getShape(ids.box1)!
const box = editor.selectionPageBounds!
const box = editor.getSelectionPageBounds()!
const center = box.center.clone().toFixed()
expect(Vec2d.ToFixed(editor.getPageCenter(shapeA)!)).toMatchObject(center)
@ -159,7 +159,7 @@ describe('When rotating...', () => {
editor.select(ids.box1, ids.box2)
const box = editor.selectionPageBounds!
const box = editor.getSelectionPageBounds()!
const center = box.center.clone()
editor.pointerDown(box.midX, box.minY, {
@ -219,7 +219,7 @@ describe('When rotating...', () => {
it('restores initial points / rotation when cancelled', () => {
editor.select(ids.box1, ids.box2)
const box = editor.selectionPageBounds!
const box = editor.getSelectionPageBounds()!
const center = box.center.clone()
const shapeA = editor.getShape(ids.box1)!
@ -246,7 +246,7 @@ describe('When rotating...', () => {
it('uses the same selection box center when rotating multiple times', () => {
editor.select(ids.box1, ids.box2)
const centerBefore = editor.selectionPageBounds!.center.clone()
const centerBefore = editor.getSelectionPageBounds()!.center.clone()
editor
.pointerDown(0, 0, {
@ -256,7 +256,7 @@ describe('When rotating...', () => {
.pointerMove(50, 100)
.pointerUp()
const centerBetween = editor.selectionPageBounds!.center.clone()
const centerBetween = editor.getSelectionPageBounds()!.center.clone()
expect(centerBefore.toFixed().toJson()).toMatchObject(centerBetween.toFixed().toJson())
@ -268,7 +268,7 @@ describe('When rotating...', () => {
.pointerMove(0, 0)
.pointerUp()
const centerAfter = editor.selectionPageBounds!.center.clone()
const centerAfter = editor.getSelectionPageBounds()!.center.clone()
expect(centerBefore.toFixed().toJson()).toMatchObject(centerAfter.toFixed().toJson())
})

View file

@ -985,7 +985,7 @@ describe('Selects inside of groups', () => {
expect(editor.hoveredShapeId).toBe(ids.group1)
editor.doubleClick()
expect(editor.getSelectedShapeIds()).toEqual([ids.box2])
expect(editor.focusedGroupId).toBe(ids.group1)
expect(editor.getFocusedGroupId()).toBe(ids.group1)
})
it('selects a solid shape in a group when double clicking its margin', () => {
@ -993,7 +993,7 @@ describe('Selects inside of groups', () => {
expect(editor.hoveredShapeId).toBe(ids.group1)
editor.doubleClick()
expect(editor.getSelectedShapeIds()).toEqual([ids.box2])
expect(editor.focusedGroupId).toBe(ids.group1)
expect(editor.getFocusedGroupId()).toBe(ids.group1)
})
// it('selects a hollow shape in a group when double clicking it', () => {
@ -1009,7 +1009,7 @@ describe('Selects inside of groups', () => {
expect(editor.hoveredShapeId).toBe(ids.group1)
editor.doubleClick()
expect(editor.getSelectedShapeIds()).toEqual([ids.box1])
expect(editor.focusedGroupId).toBe(ids.group1)
expect(editor.getFocusedGroupId()).toBe(ids.group1)
})
// it('double clicks a hollow shape when the focus layer is the shapes parent', () => {
@ -1026,7 +1026,7 @@ describe('Selects inside of groups', () => {
expect(editor.hoveredShapeId).toBe(ids.group1)
editor.doubleClick()
editor.doubleClick()
expect(editor.editingShapeId).toBe(ids.box2)
expect(editor.getEditingShapeId()).toBe(ids.box2)
editor.expectToBeIn('select.editing_shape')
})
@ -1308,58 +1308,58 @@ describe('When children / descendants of a group are selected', () => {
it('selects the child', () => {
editor.select(ids.box1)
expect(editor.getSelectedShapeIds()).toEqual([ids.box1])
expect(editor.focusedGroupId).toBe(ids.group1)
expect(editor.getFocusedGroupId()).toBe(ids.group1)
})
it('selects the children', () => {
editor.select(ids.box1, ids.box2)
expect(editor.getSelectedShapeIds()).toEqual([ids.box1, ids.box2])
expect(editor.focusedGroupId).toBe(ids.group1)
expect(editor.getFocusedGroupId()).toBe(ids.group1)
})
it('does not allow parents and children to be selected, picking the parent', () => {
editor.select(ids.group1, ids.box1)
expect(editor.getSelectedShapeIds()).toEqual([ids.group1])
expect(editor.focusedGroupId).toBe(ids.group3)
expect(editor.getFocusedGroupId()).toBe(ids.group3)
editor.select(ids.group1, ids.box1, ids.box2)
expect(editor.getSelectedShapeIds()).toEqual([ids.group1])
expect(editor.focusedGroupId).toBe(ids.group3)
expect(editor.getFocusedGroupId()).toBe(ids.group3)
})
it('does not allow ancestors and children to be selected, picking the ancestor', () => {
editor.select(ids.group3, ids.box1)
expect(editor.getSelectedShapeIds()).toEqual([ids.group3])
expect(editor.focusedGroupId).toBe(editor.currentPageId)
expect(editor.getFocusedGroupId()).toBe(editor.currentPageId)
editor.select(ids.group3, ids.box1, ids.box2)
expect(editor.getSelectedShapeIds()).toEqual([ids.group3])
expect(editor.focusedGroupId).toBe(editor.currentPageId)
expect(editor.getFocusedGroupId()).toBe(editor.currentPageId)
editor.select(ids.group3, ids.group2, ids.box1)
expect(editor.getSelectedShapeIds()).toEqual([ids.group3])
expect(editor.focusedGroupId).toBe(editor.currentPageId)
expect(editor.getFocusedGroupId()).toBe(editor.currentPageId)
})
it('picks the highest common focus layer id', () => {
editor.select(ids.box1, ids.box4) // child of group1, child of group 2
expect(editor.getSelectedShapeIds()).toEqual([ids.box1, ids.box4])
expect(editor.focusedGroupId).toBe(ids.group3)
expect(editor.getFocusedGroupId()).toBe(ids.group3)
})
it('picks the highest common focus layer id', () => {
editor.select(ids.box1, ids.box5) // child of group1 and child of the page
expect(editor.getSelectedShapeIds()).toEqual([ids.box1, ids.box5])
expect(editor.focusedGroupId).toBe(editor.currentPageId)
expect(editor.getFocusedGroupId()).toBe(editor.currentPageId)
})
it('sets the parent to the highest common ancestor', () => {
editor.selectNone()
expect(editor.focusedGroupId).toBe(editor.currentPageId)
expect(editor.getFocusedGroupId()).toBe(editor.currentPageId)
editor.select(ids.group3)
expect(editor.focusedGroupId).toBe(editor.currentPageId)
expect(editor.getFocusedGroupId()).toBe(editor.currentPageId)
editor.select(ids.group3, ids.box1)
expect(editor.focusedGroupId).toBe(editor.currentPageId)
expect(editor.getFocusedGroupId()).toBe(editor.currentPageId)
expect(editor.getSelectedShapeIds()).toEqual([ids.group3])
})
})
@ -1382,10 +1382,10 @@ describe('When pressing the enter key with groups selected', () => {
editor.select(ids.group1, ids.group2)
editor.keyDown('Enter')
expect(editor.getSelectedShapeIds()).toEqual([ids.group1, ids.group2])
expect(editor.focusedGroupId).toBe(editor.currentPageId)
expect(editor.getFocusedGroupId()).toBe(editor.currentPageId)
editor.keyUp('Enter')
expect(editor.getSelectedShapeIds()).toEqual([ids.box1, ids.box2, ids.box3, ids.box4])
expect(editor.focusedGroupId).toBe(editor.currentPageId)
expect(editor.getFocusedGroupId()).toBe(editor.currentPageId)
})
it('repeats children of the groups on enter up', () => {
@ -1394,10 +1394,10 @@ describe('When pressing the enter key with groups selected', () => {
expect(editor.getSelectedShapeIds()).toEqual([ids.group3])
editor.keyDown('Enter').keyUp('Enter')
expect(editor.getSelectedShapeIds()).toEqual([ids.group1, ids.group2])
expect(editor.focusedGroupId).toBe(ids.group3)
expect(editor.getFocusedGroupId()).toBe(ids.group3)
editor.keyDown('Enter').keyUp('Enter')
expect(editor.getSelectedShapeIds()).toEqual([ids.box1, ids.box2, ids.box3, ids.box4])
expect(editor.focusedGroupId).toBe(ids.group3)
expect(editor.getFocusedGroupId()).toBe(ids.group3)
})
it('does not select the children of the group if a non-group is also selected', () => {
@ -1429,14 +1429,14 @@ describe('When double clicking an editable shape', () => {
it('starts editing on double click', () => {
editor.pointerMove(50, 50).doubleClick()
expect(editor.getSelectedShapeIds()).toEqual([ids.box1])
expect(editor.editingShapeId).toBe(ids.box1)
expect(editor.getEditingShapeId()).toBe(ids.box1)
editor.expectToBeIn('select.editing_shape')
})
it('does not start editing on double click if shift is down', () => {
editor.pointerMove(50, 50).keyDown('Shift').doubleClick()
expect(editor.getSelectedShapeIds()).toEqual([ids.box1])
expect(editor.editingShapeId).toBe(null)
expect(editor.getEditingShapeId()).toBe(null)
editor.expectToBeIn('select.idle')
})
@ -1445,12 +1445,12 @@ describe('When double clicking an editable shape', () => {
editor.doubleClick()
expect(editor.getSelectedShapeIds()).toEqual([ids.box2])
expect(editor.editingShapeId).toBe(ids.box2)
expect(editor.getEditingShapeId()).toBe(ids.box2)
editor.expectToBeIn('select.editing_shape')
editor.doubleClick()
expect(editor.getSelectedShapeIds()).toEqual([ids.box2])
expect(editor.editingShapeId).toBe(ids.box2)
expect(editor.getEditingShapeId()).toBe(ids.box2)
editor.expectToBeIn('select.editing_shape')
})
@ -1460,13 +1460,13 @@ describe('When double clicking an editable shape', () => {
editor.selectNone()
editor.pointerMove(50, 50).click() // clicks on the shape label
expect(editor.getSelectedShapeIds()).toEqual([ids.group1])
expect(editor.editingShapeId).toBe(null)
expect(editor.getEditingShapeId()).toBe(null)
editor.pointerMove(50, 50).click() // clicks on the shape label
expect(editor.getSelectedShapeIds()).toEqual([ids.box1])
expect(editor.editingShapeId).toBe(null)
expect(editor.getEditingShapeId()).toBe(null)
editor.pointerMove(50, 50).click() // clicks on the shape label
expect(editor.getSelectedShapeIds()).toEqual([ids.box1])
expect(editor.editingShapeId).toBe(ids.box1)
expect(editor.getEditingShapeId()).toBe(ids.box1)
editor.expectToBeIn('select.editing_shape')
})
})

View file

@ -1819,6 +1819,6 @@ it('clones a single shape simply', () => {
expect(editor.currentPageShapes).toHaveLength(2)
const [, sticky2] = editor.currentPageShapes
expect(editor.getOnlySelectedShape()).toBe(sticky2)
expect(editor.editingShape).toBe(undefined)
expect(editor.getEditingShape()).toBe(undefined)
expect(editor.hoveredShape).toBe(sticky2)
})