No impure getters pt2 (#2202)

follow up to #2189
This commit is contained in:
David Sheldrick 2023-11-13 12:42:07 +00:00 committed by GitHub
parent ae5c60ab36
commit 2ca2f81f2a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
86 changed files with 930 additions and 743 deletions

View file

@ -88,7 +88,7 @@ const InsideOfEditorContext = () => {
let i = 0
const interval = setInterval(() => {
const selection = [...editor.selectedShapeIds]
const selection = [...editor.getSelectedShapeIds()]
editor.selectAll()
editor.setStyleForSelectedShapes(DefaultColorStyle, i % 2 ? 'blue' : 'light-blue')
editor.setStyleForNextShapes(DefaultColorStyle, i % 2 ? 'blue' : 'light-blue')

View file

@ -22,7 +22,7 @@ const CustomUi = track(() => {
switch (e.key) {
case 'Delete':
case 'Backspace': {
editor.deleteShapes(editor.selectedShapeIds)
editor.deleteShapes(editor.getSelectedShapeIds())
break
}
case 'v': {

View file

@ -52,9 +52,9 @@ class IdleState extends StateNode {
}
case 'shape': {
if (editor.inputs.shiftKey) {
editor.select(...editor.selectedShapeIds, info.shape.id)
editor.select(...editor.getSelectedShapeIds(), info.shape.id)
} else {
if (!editor.selectedShapeIds.includes(info.shape.id)) {
if (!editor.getSelectedShapeIds().includes(info.shape.id)) {
editor.select(info.shape.id)
}
this.parent.transition('pointing', info)

View file

@ -18,7 +18,7 @@ export default function OnlyEditorExample() {
onMount={(editor: Editor) => {
editor
.selectAll()
.deleteShapes(editor.selectedShapeIds)
.deleteShapes(editor.getSelectedShapeIds())
.createShapes([
{
id: createShapeId(),

View file

@ -618,6 +618,7 @@ export class Editor extends EventEmitter<TLEventMap> {
get currentPageShapeIds(): Set<TLShapeId>;
get currentPageShapes(): TLShape[];
get currentPageShapesSorted(): TLShape[];
// @deprecated (undocumented)
get currentPageState(): TLInstancePageState;
// @deprecated (undocumented)
get currentTool(): StateNode | undefined;
@ -679,6 +680,7 @@ export class Editor extends EventEmitter<TLEventMap> {
getCanUndo(): boolean;
getContainer: () => HTMLElement;
getContentFromCurrentPage(shapes: TLShape[] | TLShapeId[]): TLContent | undefined;
getCurrentPageState(): TLInstancePageState;
getCurrentTool(): StateNode | undefined;
getCurrentToolId(): string;
getDocumentSettings(): TLDocument;
@ -686,13 +688,16 @@ export class Editor extends EventEmitter<TLEventMap> {
getHighestIndexForParent(parent: TLPage | TLParentId | TLShape): string;
getInitialMetaForShape(_shape: TLShape): JsonObject;
getInstanceState(): TLInstance;
getIsMenuOpen(): boolean;
getOpenMenus(): string[];
getOutermostSelectableShape(shape: TLShape | TLShapeId, filter?: (shape: TLShape) => boolean): TLShape;
getPage(page: TLPage | TLPageId): TLPage | undefined;
getPageShapeIds(page: TLPage | TLPageId): Set<TLShapeId>;
getPageStates(): TLInstancePageState[];
getPointInParentSpace(shape: TLShape | TLShapeId, point: VecLike): Vec2d;
getPointInShapeSpace(shape: TLShape | TLShapeId, point: VecLike): Vec2d;
getSelectedShapeAtPoint(point: VecLike): TLShape | undefined;
getSelectedShapeIds(): TLShapeId[];
getShape<T extends TLShape = TLShape>(shape: TLParentId | TLShape): T | undefined;
getShapeAncestors(shape: TLShape | TLShapeId, acc?: TLShape[]): TLShape[];
getShapeAndDescendantIds(ids: TLShapeId[]): Set<TLShapeId>;
@ -770,6 +775,7 @@ export class Editor extends EventEmitter<TLEventMap> {
isAncestorSelected(shape: TLShape | TLShapeId): boolean;
isIn(path: string): boolean;
isInAny(...paths: string[]): boolean;
// @deprecated (undocumented)
get isMenuOpen(): boolean;
isPointInShape(shape: TLShape | TLShapeId, point: VecLike, opts?: {
margin?: number | undefined;
@ -790,6 +796,7 @@ export class Editor extends EventEmitter<TLEventMap> {
get openMenus(): string[];
packShapes(shapes: TLShape[] | TLShapeId[], gap: number): this;
get pages(): TLPage[];
// @deprecated (undocumented)
get pageStates(): TLInstancePageState[];
pageToScreen(point: VecLike): {
x: number;
@ -840,6 +847,7 @@ export class Editor extends EventEmitter<TLEventMap> {
readonly scribbles: ScribbleManager;
select(...shapes: TLShape[] | TLShapeId[]): this;
selectAll(): this;
// @deprecated (undocumented)
get selectedShapeIds(): TLShapeId[];
get selectedShapes(): TLShape[];
get selectionPageBounds(): Box2d | null;

View file

@ -6749,7 +6749,7 @@
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#alignShapes:member(1)",
"docComment": "/**\n * Align shape positions.\n *\n * @param shapes - The shapes (or shape ids) to align.\n *\n * @param operation - The align operation to apply.\n *\n * @example\n * ```ts\n * editor.alignShapes([box1, box2], 'left')\n * editor.alignShapes(editor.selectedShapeIds, 'left')\n * ```\n *\n * @public\n */\n",
"docComment": "/**\n * Align shape positions.\n *\n * @param shapes - The shapes (or shape ids) to align.\n *\n * @param operation - The align operation to apply.\n *\n * @example\n * ```ts\n * editor.alignShapes([box1, box2], 'left')\n * editor.alignShapes(editor.getSelectedShapeIds(), 'left')\n * ```\n *\n * @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -7229,7 +7229,7 @@
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#batch:member(1)",
"docComment": "/**\n * Run a function in a batch, which will be undone/redone as a single action.\n *\n * @example\n * ```ts\n * editor.batch(() => {\n * \teditor.selectAll()\n * \teditor.deleteShapes(editor.selectedShapeIds)\n * \teditor.createShapes(myShapes)\n * \teditor.selectNone()\n * })\n *\n * editor.undo() // will undo all of the above\n * ```\n *\n * @public\n */\n",
"docComment": "/**\n * Run a function in a batch, which will be undone/redone as a single action.\n *\n * @example\n * ```ts\n * editor.batch(() => {\n * \teditor.selectAll()\n * \teditor.deleteShapes(editor.getSelectedShapeIds())\n * \teditor.createShapes(myShapes)\n * \teditor.selectNone()\n * })\n *\n * editor.undo() // will undo all of the above\n * ```\n *\n * @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -8249,7 +8249,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!Editor#currentPageState:member",
"docComment": "/**\n * The current page state.\n *\n * @public\n */\n",
"docComment": "/**\n * @deprecated\n *\n * Use `getCurrentPageState` instead.\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -8884,7 +8884,7 @@
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#distributeShapes:member(1)",
"docComment": "/**\n * Distribute shape positions.\n *\n * @param shapes - The shapes (or shape ids) to distribute.\n *\n * @param operation - Whether to distribute shapes horizontally or vertically.\n *\n * @example\n * ```ts\n * editor.distributeShapes([box1, box2], 'horizontal')\n * editor.distributeShapes(editor.selectedShapeIds, 'horizontal')\n * ```\n *\n * @public\n */\n",
"docComment": "/**\n * Distribute shape positions.\n *\n * @param shapes - The shapes (or shape ids) to distribute.\n *\n * @param operation - Whether to distribute shapes horizontally or vertically.\n *\n * @example\n * ```ts\n * editor.distributeShapes([box1, box2], 'horizontal')\n * editor.distributeShapes(editor.getSelectedShapeIds(), 'horizontal')\n * ```\n *\n * @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -9507,7 +9507,7 @@
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#flipShapes:member(1)",
"docComment": "/**\n * Flip shape positions.\n *\n * @param shapes - The ids of the shapes to flip.\n *\n * @param operation - Whether to flip horizontally or vertically.\n *\n * @example\n * ```ts\n * editor.flipShapes([box1, box2], 'horizontal', 32)\n * editor.flipShapes(editor.selectedShapeIds, 'horizontal', 32)\n * ```\n *\n * @public\n */\n",
"docComment": "/**\n * Flip shape positions.\n *\n * @param shapes - The ids of the shapes to flip.\n *\n * @param operation - Whether to flip horizontally or vertically.\n *\n * @example\n * ```ts\n * editor.flipShapes([box1, box2], 'horizontal', 32)\n * editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal', 32)\n * ```\n *\n * @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -10131,6 +10131,38 @@
"isAbstract": false,
"name": "getContentFromCurrentPage"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getCurrentPageState:member(1)",
"docComment": "/**\n * The current page state.\n *\n * @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
"text": "getCurrentPageState(): "
},
{
"kind": "Reference",
"text": "TLInstancePageState",
"canonicalReference": "@tldraw/tlschema!TLInstancePageState:interface"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 2
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getCurrentPageState"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getCurrentTool:member(1)",
@ -10454,6 +10486,37 @@
"isAbstract": false,
"name": "getInstanceState"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getIsMenuOpen:member(1)",
"docComment": "/**\n * Get whether any menus are open.\n *\n * @example\n * ```ts\n * editor.isMenuOpen()\n * ```\n *\n * @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
"text": "getIsMenuOpen(): "
},
{
"kind": "Content",
"text": "boolean"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 2
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getIsMenuOpen"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getOpenMenus:member(1)",
@ -10704,6 +10767,42 @@
"isAbstract": false,
"name": "getPageShapeIds"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getPageStates:member(1)",
"docComment": "/**\n * Page states.\n *\n * @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
"text": "getPageStates(): "
},
{
"kind": "Reference",
"text": "TLInstancePageState",
"canonicalReference": "@tldraw/tlschema!TLInstancePageState:interface"
},
{
"kind": "Content",
"text": "[]"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 3
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getPageStates"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getPointInParentSpace:member(1)",
@ -10910,6 +11009,42 @@
"isAbstract": false,
"name": "getSelectedShapeAtPoint"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getSelectedShapeIds:member(1)",
"docComment": "/**\n * The current selected ids.\n *\n * @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
"text": "getSelectedShapeIds(): "
},
{
"kind": "Reference",
"text": "TLShapeId",
"canonicalReference": "@tldraw/tlschema!TLShapeId:type"
},
{
"kind": "Content",
"text": "[]"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 3
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getSelectedShapeIds"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getShape:member(1)",
@ -13253,7 +13388,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!Editor#isMenuOpen:member",
"docComment": "/**\n * Get whether any menus are open.\n *\n * @example\n * ```ts\n * editor.isMenuOpen()\n * ```\n *\n * @public\n */\n",
"docComment": "/**\n * @deprecated\n *\n * Use `getIsMenuOpen` instead.\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -14055,7 +14190,7 @@
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#packShapes:member(1)",
"docComment": "/**\n * Pack shapes into a grid centered on their current position. Based on potpack (https://github.com/mapbox/potpack).\n *\n * @param shapes - The shapes (or shape ids) to pack.\n *\n * @param gap - The padding to apply to the packed shapes. Defaults to 16.\n *\n * @example\n * ```ts\n * editor.packShapes([box1, box2], 32)\n * editor.packShapes(editor.selectedShapeIds, 32)\n * ```\n *\n */\n",
"docComment": "/**\n * Pack shapes into a grid centered on their current position. Based on potpack (https://github.com/mapbox/potpack).\n *\n * @param shapes - The shapes (or shape ids) to pack.\n *\n * @param gap - The padding to apply to the packed shapes. Defaults to 16.\n *\n * @example\n * ```ts\n * editor.packShapes([box1, box2], 32)\n * editor.packShapes(editor.getSelectedShapeIds(), 32)\n * ```\n *\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -14168,7 +14303,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!Editor#pageStates:member",
"docComment": "/**\n * Page states.\n *\n * @public\n */\n",
"docComment": "/**\n * @deprecated\n *\n * Use `getPageStates` instead.\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -15354,7 +15489,7 @@
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#rotateShapesBy:member(1)",
"docComment": "/**\n * Rotate shapes by a delta in radians. Note: Currently, this assumes that the shapes are your currently selected shapes.\n *\n * @param shapes - The shapes (or shape ids) of the shapes to move.\n *\n * @param delta - The delta in radians to apply to the selection rotation.\n *\n * @example\n * ```ts\n * editor.rotateShapesBy(editor.selectedShapeIds, Math.PI)\n * editor.rotateShapesBy(editor.selectedShapeIds, Math.PI / 2)\n * ```\n *\n */\n",
"docComment": "/**\n * Rotate shapes by a delta in radians. Note: Currently, this assumes that the shapes are your currently selected shapes.\n *\n * @param shapes - The shapes (or shape ids) of the shapes to move.\n *\n * @param delta - The delta in radians to apply to the selection rotation.\n *\n * @example\n * ```ts\n * editor.rotateShapesBy(editor.getSelectedShapeIds(), Math.PI)\n * editor.rotateShapesBy(editor.getSelectedShapeIds(), Math.PI / 2)\n * ```\n *\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -15605,7 +15740,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!Editor#selectedShapeIds:member",
"docComment": "/**\n * The current selected ids.\n *\n * @public\n */\n",
"docComment": "/**\n * @deprecated\n *\n * Use `getSelectedShapeIds` instead.\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -17199,7 +17334,7 @@
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#stackShapes:member(1)",
"docComment": "/**\n * Stack shape.\n *\n * @param shapes - The shapes (or shape ids) to stack.\n *\n * @param operation - Whether to stack horizontally or vertically.\n *\n * @param gap - The gap to leave between shapes.\n *\n * @example\n * ```ts\n * editor.stackShapes([box1, box2], 'horizontal', 32)\n * editor.stackShapes(editor.selectedShapeIds, 'horizontal', 32)\n * ```\n *\n * @public\n */\n",
"docComment": "/**\n * Stack shape.\n *\n * @param shapes - The shapes (or shape ids) to stack.\n *\n * @param operation - Whether to stack horizontally or vertically.\n *\n * @param gap - The gap to leave between shapes.\n *\n * @example\n * ```ts\n * editor.stackShapes([box1, box2], 'horizontal', 32)\n * editor.stackShapes(editor.getSelectedShapeIds(), 'horizontal', 32)\n * ```\n *\n * @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -17434,7 +17569,7 @@
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#stretchShapes:member(1)",
"docComment": "/**\n * Stretch shape sizes and positions to fill their common bounding box.\n *\n * @param shapes - The shapes (or shape ids) to stretch.\n *\n * @param operation - Whether to stretch shapes horizontally or vertically.\n *\n * @example\n * ```ts\n * editor.stretchShapes([box1, box2], 'horizontal')\n * editor.stretchShapes(editor.selectedShapeIds, 'horizontal')\n * ```\n *\n * @public\n */\n",
"docComment": "/**\n * Stretch shape sizes and positions to fill their common bounding box.\n *\n * @param shapes - The shapes (or shape ids) to stretch.\n *\n * @param operation - Whether to stretch shapes horizontally or vertically.\n *\n * @example\n * ```ts\n * editor.stretchShapes([box1, box2], 'horizontal')\n * editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')\n * ```\n *\n * @public\n */\n",
"excerptTokens": [
{
"kind": "Content",

View file

@ -335,7 +335,7 @@ function SelectedIdIndicators() {
const editor = useEditor()
const selectedShapeIds = useValue(
'selectedShapeIds',
() => editor.currentPageState.selectedShapeIds,
() => editor.getCurrentPageState().selectedShapeIds,
[editor]
)
const shouldDisplay = useValue(
@ -381,7 +381,7 @@ const HoveredShapeIndicator = function HoveredShapeIndicator() {
() => editor.getInstanceState().isHoveringCanvas,
[editor]
)
const hoveredShapeId = useValue('hovered id', () => editor.currentPageState.hoveredShapeId, [
const hoveredShapeId = useValue('hovered id', () => editor.getCurrentPageState().hoveredShapeId, [
editor,
])

View file

@ -464,7 +464,7 @@ export class Editor extends EventEmitter<TLEventMap> {
}
const deletedIds = new Set([record.id])
const updates = compact(
this.pageStates.map((pageState) => {
this.getPageStates().map((pageState) => {
return cleanupInstancePageState(pageState, deletedIds)
})
)
@ -514,7 +514,7 @@ export class Editor extends EventEmitter<TLEventMap> {
allMovingIds.add(id)
})
for (const instancePageState of this.pageStates) {
for (const instancePageState of this.getPageStates()) {
if (instancePageState.pageId === next.parentId) continue
const nextPageState = cleanupInstancePageState(instancePageState, allMovingIds)
@ -892,7 +892,7 @@ export class Editor extends EventEmitter<TLEventMap> {
* ```ts
* editor.batch(() => {
* editor.selectAll()
* editor.deleteShapes(editor.selectedShapeIds)
* editor.deleteShapes(editor.getSelectedShapeIds())
* editor.createShapes(myShapes)
* editor.selectNone()
* })
@ -1345,10 +1345,17 @@ export class Editor extends EventEmitter<TLEventMap> {
*
* @public
*/
@computed get isMenuOpen(): boolean {
@computed getIsMenuOpen(): boolean {
return this.getOpenMenus().length > 0
}
/**
* @deprecated Use `getIsMenuOpen` instead.
*/
get isMenuOpen() {
return this.getIsMenuOpen()
}
/* --------------------- Cursor --------------------- */
/**
@ -1374,11 +1381,19 @@ export class Editor extends EventEmitter<TLEventMap> {
*
* @public
*/
@computed get pageStates(): TLInstancePageState[] {
return this._pageStates.get()
@computed getPageStates(): TLInstancePageState[] {
return this._getPageStatesQuery().get()
}
/**
* @deprecated Use `getPageStates` instead.
*/
get pageStates() {
return this.getPageStates()
}
/** @internal */
@computed private get _pageStates() {
@computed private _getPageStatesQuery() {
return this.store.query.records('instance_page_state')
}
@ -1387,11 +1402,19 @@ export class Editor extends EventEmitter<TLEventMap> {
*
* @public
*/
@computed get currentPageState(): TLInstancePageState {
return this.store.get(this._currentPageStateId)!
@computed getCurrentPageState(): TLInstancePageState {
return this.store.get(this._getCurrentPageStateId())!
}
/**
* @deprecated Use `getCurrentPageState` instead.
*/
get currentPageState() {
return this.getCurrentPageState()
}
/** @internal */
@computed private get _currentPageStateId() {
@computed private _getCurrentPageStateId() {
return InstancePageStateRecordType.createId(this.currentPageId)
}
@ -1426,7 +1449,7 @@ export class Editor extends EventEmitter<TLEventMap> {
partial: Partial<Omit<TLInstancePageState, 'selectedShapeIds'>>,
historyOptions?: TLCommandHistoryOptions
) => {
const prev = this.store.get(partial.id ?? this.currentPageState.id)!
const prev = this.store.get(partial.id ?? this.getCurrentPageState().id)!
return { data: { prev, partial }, ...historyOptions }
},
{
@ -1444,8 +1467,15 @@ export class Editor extends EventEmitter<TLEventMap> {
*
* @public
*/
@computed get selectedShapeIds() {
return this.currentPageState.selectedShapeIds
@computed getSelectedShapeIds() {
return this.getCurrentPageState().selectedShapeIds
}
/**
* @deprecated Use `getSelectedShapeIds` instead.
*/
get selectedShapeIds() {
return this.getSelectedShapeIds()
}
/**
@ -1460,7 +1490,7 @@ export class Editor extends EventEmitter<TLEventMap> {
* @readonly
*/
@computed get selectedShapes(): TLShape[] {
const { selectedShapeIds } = this.currentPageState
const { selectedShapeIds } = this.getCurrentPageState()
return compact(selectedShapeIds.map((id) => this.store.get(id)))
}
@ -1491,7 +1521,7 @@ export class Editor extends EventEmitter<TLEventMap> {
private _setSelectedShapes = this.history.createCommand(
'setSelectedShapes',
(ids: TLShapeId[], historyOptions?: TLCommandHistoryOptions) => {
const { selectedShapeIds: prevSelectedShapeIds } = this.currentPageState
const { selectedShapeIds: prevSelectedShapeIds } = this.getCurrentPageState()
const prevSet = new Set(prevSelectedShapeIds)
if (ids.length === prevSet.size && ids.every((id) => prevSet.has(id))) return null
@ -1504,12 +1534,12 @@ export class Editor extends EventEmitter<TLEventMap> {
},
{
do: ({ selectedShapeIds }) => {
this.store.put([{ ...this.currentPageState, selectedShapeIds }])
this.store.put([{ ...this.getCurrentPageState(), selectedShapeIds }])
},
undo: ({ prevSelectedShapeIds }) => {
this.store.put([
{
...this.currentPageState,
...this.getCurrentPageState(),
selectedShapeIds: prevSelectedShapeIds,
},
])
@ -1534,7 +1564,7 @@ export class Editor extends EventEmitter<TLEventMap> {
const id = typeof shape === 'string' ? shape : shape?.id ?? null
const _shape = this.getShape(id)
if (!_shape) return false
const { selectedShapeIds } = this
const selectedShapeIds = this.getSelectedShapeIds()
return !!this.findShapeAncestor(_shape, (parent) => selectedShapeIds.includes(parent.id))
}
@ -1575,7 +1605,7 @@ export class Editor extends EventEmitter<TLEventMap> {
typeof shapes[0] === 'string'
? (shapes as TLShapeId[])
: (shapes as TLShape[]).map((shape) => shape.id)
const { selectedShapeIds } = this
const selectedShapeIds = this.getSelectedShapeIds()
if (selectedShapeIds.length > 0 && ids.length > 0) {
this.setSelectedShapes(selectedShapeIds.filter((id) => !ids.includes(id)))
}
@ -1612,7 +1642,7 @@ export class Editor extends EventEmitter<TLEventMap> {
* @public
*/
selectNone(): this {
if (this.selectedShapeIds.length > 0) {
if (this.getSelectedShapeIds().length > 0) {
this.setSelectedShapes([])
}
@ -1648,10 +1678,7 @@ export class Editor extends EventEmitter<TLEventMap> {
* @public
*/
@computed get selectionPageBounds(): Box2d | null {
const {
currentPageState: { selectedShapeIds },
} = this
const selectedShapeIds = this.getCurrentPageState().selectedShapeIds
if (selectedShapeIds.length === 0) return null
return Box2d.Common(compact(selectedShapeIds.map((id) => this.getShapePageBounds(id))))
@ -1664,12 +1691,12 @@ export class Editor extends EventEmitter<TLEventMap> {
* @public
*/
@computed get selectionRotation(): number {
const { selectedShapeIds } = this
const selectedShapeIds = this.getSelectedShapeIds()
if (selectedShapeIds.length === 0) {
return 0
}
if (selectedShapeIds.length === 1) {
return this.getShapePageTransform(this.selectedShapeIds[0])!.rotation()
return this.getShapePageTransform(this.getSelectedShapeIds()[0])!.rotation()
}
const allRotations = selectedShapeIds.map((id) => this.getShapePageTransform(id)!.rotation())
@ -1687,7 +1714,7 @@ export class Editor extends EventEmitter<TLEventMap> {
* @public
*/
@computed get selectionRotatedPageBounds(): Box2d | undefined {
const { selectedShapeIds } = this
const selectedShapeIds = this.getSelectedShapeIds()
if (selectedShapeIds.length === 0) {
return undefined
@ -1707,7 +1734,7 @@ export class Editor extends EventEmitter<TLEventMap> {
// need to 'un-rotate' all the outlines of the existing nodes so we can fit them inside a box
const boxFromRotatedVertices = Box2d.FromPoints(
this.selectedShapeIds
this.getSelectedShapeIds()
.flatMap((id) => {
const pageTransform = this.getShapePageTransform(id)
if (!pageTransform) return []
@ -1728,7 +1755,7 @@ export class Editor extends EventEmitter<TLEventMap> {
* @public
*/
@computed get focusedGroupId(): TLShapeId | TLPageId {
return this.currentPageState.focusedGroupId ?? this.currentPageId
return this.getCurrentPageState().focusedGroupId ?? this.currentPageId
}
/**
@ -1773,7 +1800,7 @@ export class Editor extends EventEmitter<TLEventMap> {
private _setFocusedGroupId = this.history.createCommand(
'setFocusedGroupId',
(next: TLShapeId | null) => {
const prev = this.currentPageState.focusedGroupId
const prev = this.getCurrentPageState().focusedGroupId
if (prev === next) return
return {
data: {
@ -1786,10 +1813,10 @@ export class Editor extends EventEmitter<TLEventMap> {
},
{
do: ({ next }) => {
this.store.update(this.currentPageState.id, (s) => ({ ...s, focusedGroupId: next }))
this.store.update(this.getCurrentPageState().id, (s) => ({ ...s, focusedGroupId: next }))
},
undo: ({ prev }) => {
this.store.update(this.currentPageState.id, (s) => ({ ...s, focusedGroupId: prev }))
this.store.update(this.getCurrentPageState().id, (s) => ({ ...s, focusedGroupId: prev }))
},
squash({ prev }, { next }) {
return { prev, next }
@ -1828,7 +1855,7 @@ export class Editor extends EventEmitter<TLEventMap> {
* @public
*/
@computed get editingShapeId() {
return this.currentPageState.editingShapeId
return this.getCurrentPageState().editingShapeId
}
/**
@ -1880,7 +1907,7 @@ export class Editor extends EventEmitter<TLEventMap> {
* @public
*/
@computed get hoveredShapeId() {
return this.currentPageState.hoveredShapeId
return this.getCurrentPageState().hoveredShapeId
}
/**
@ -1921,7 +1948,7 @@ export class Editor extends EventEmitter<TLEventMap> {
* @public
*/
@computed get hintingShapeIds() {
return this.currentPageState.hintingShapeIds
return this.getCurrentPageState().hintingShapeIds
}
/**
@ -1965,7 +1992,7 @@ export class Editor extends EventEmitter<TLEventMap> {
* @public
*/
@computed get erasingShapeIds() {
return this.currentPageState.erasingShapeIds
return this.getCurrentPageState().erasingShapeIds
}
/**
@ -2024,7 +2051,7 @@ export class Editor extends EventEmitter<TLEventMap> {
* @public
*/
get croppingShapeId() {
return this.currentPageState.croppingShapeId
return this.getCurrentPageState().croppingShapeId
}
/**
@ -3082,7 +3109,7 @@ export class Editor extends EventEmitter<TLEventMap> {
// We only really need these if we're using editor state, but that's ok
const editingShapeId = this.editingShapeId
const selectedShapeIds = this.selectedShapeIds
const selectedShapeIds = this.getSelectedShapeIds()
const erasingShapeIds = this.erasingShapeIds
const renderingBoundsExpanded = this.renderingBoundsExpanded
@ -3366,7 +3393,7 @@ export class Editor extends EventEmitter<TLEventMap> {
// in multiplayer contexts this page might have been deleted
return
}
if (!this.pageStates.find((p) => p.pageId === toId)) {
if (!this.getPageStates().find((p) => p.pageId === toId)) {
const camera = CameraRecordType.create({
id: CameraRecordType.createId(toId),
})
@ -3541,7 +3568,7 @@ export class Editor extends EventEmitter<TLEventMap> {
if (pages.length === 1) return null
const deletedPage = this.getPage(id)
const deletedPageStates = this.pageStates.filter((s) => s.pageId === id)
const deletedPageStates = this.getPageStates().filter((s) => s.pageId === id)
if (!deletedPage) return null
@ -4268,7 +4295,7 @@ export class Editor extends EventEmitter<TLEventMap> {
* @returns The top-most selected shape at the given point, or undefined if there is no shape at the point.
*/
getSelectedShapeAtPoint(point: VecLike): TLShape | undefined {
const { selectedShapeIds } = this
const selectedShapeIds = this.getSelectedShapeIds()
return this.currentPageShapesSorted
.filter((shape) => shape.type !== 'group' && selectedShapeIds.includes(shape.id))
.reverse() // findlast
@ -5083,8 +5110,8 @@ export class Editor extends EventEmitter<TLEventMap> {
*
* @example
* ```ts
* editor.rotateShapesBy(editor.selectedShapeIds, Math.PI)
* editor.rotateShapesBy(editor.selectedShapeIds, Math.PI / 2)
* editor.rotateShapesBy(editor.getSelectedShapeIds(), Math.PI)
* editor.rotateShapesBy(editor.getSelectedShapeIds(), Math.PI / 2)
* ```
*
* @param shapes - The shapes (or shape ids) of the shapes to move.
@ -5576,7 +5603,7 @@ export class Editor extends EventEmitter<TLEventMap> {
* @example
* ```ts
* editor.flipShapes([box1, box2], 'horizontal', 32)
* editor.flipShapes(editor.selectedShapeIds, 'horizontal', 32)
* editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal', 32)
* ```
*
* @param shapes - The ids of the shapes to flip.
@ -5641,7 +5668,7 @@ export class Editor extends EventEmitter<TLEventMap> {
* @example
* ```ts
* editor.stackShapes([box1, box2], 'horizontal', 32)
* editor.stackShapes(editor.selectedShapeIds, 'horizontal', 32)
* editor.stackShapes(editor.getSelectedShapeIds(), 'horizontal', 32)
* ```
*
* @param shapes - The shapes (or shape ids) to stack.
@ -5791,7 +5818,7 @@ export class Editor extends EventEmitter<TLEventMap> {
* @example
* ```ts
* editor.packShapes([box1, box2], 32)
* editor.packShapes(editor.selectedShapeIds, 32)
* editor.packShapes(editor.getSelectedShapeIds(), 32)
* ```
*
*
@ -5950,7 +5977,7 @@ export class Editor extends EventEmitter<TLEventMap> {
* @example
* ```ts
* editor.alignShapes([box1, box2], 'left')
* editor.alignShapes(editor.selectedShapeIds, 'left')
* editor.alignShapes(editor.getSelectedShapeIds(), 'left')
* ```
*
* @param shapes - The shapes (or shape ids) to align.
@ -6045,7 +6072,7 @@ export class Editor extends EventEmitter<TLEventMap> {
* @example
* ```ts
* editor.distributeShapes([box1, box2], 'horizontal')
* editor.distributeShapes(editor.selectedShapeIds, 'horizontal')
* editor.distributeShapes(editor.getSelectedShapeIds(), 'horizontal')
* ```
*
* @param shapes - The shapes (or shape ids) to distribute.
@ -6136,7 +6163,7 @@ export class Editor extends EventEmitter<TLEventMap> {
* @example
* ```ts
* editor.stretchShapes([box1, box2], 'horizontal')
* editor.stretchShapes(editor.selectedShapeIds, 'horizontal')
* editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
* ```
*
* @param shapes - The shapes (or shape ids) to stretch.
@ -7181,7 +7208,7 @@ export class Editor extends EventEmitter<TLEventMap> {
(ids: TLShapeId[]) => {
if (this.getInstanceState().isReadonly) return null
if (ids.length === 0) return null
const prevSelectedShapeIds = [...this.currentPageState.selectedShapeIds]
const prevSelectedShapeIds = [...this.getCurrentPageState().selectedShapeIds]
const allIds = new Set(ids)
@ -7213,14 +7240,14 @@ export class Editor extends EventEmitter<TLEventMap> {
{
do: ({ deletedIds, postSelectedShapeIds }) => {
this.store.remove(deletedIds)
this.store.update(this.currentPageState.id, (state) => ({
this.store.update(this.getCurrentPageState().id, (state) => ({
...state,
selectedShapeIds: postSelectedShapeIds,
}))
},
undo: ({ snapshots, prevSelectedShapeIds }) => {
this.store.put(snapshots)
this.store.update(this.currentPageState.id, (state) => ({
this.store.update(this.getCurrentPageState().id, (state) => ({
...state,
selectedShapeIds: prevSelectedShapeIds,
}))
@ -7302,7 +7329,7 @@ export class Editor extends EventEmitter<TLEventMap> {
get sharedStyles(): ReadonlySharedStyleMap {
// If we're in selecting and if we have a selection, return the shared styles from the
// current selection
if (this.isIn('select') && this.selectedShapeIds.length > 0) {
if (this.isIn('select') && this.getSelectedShapeIds().length > 0) {
return this._selectionSharedStyles.get()
}
@ -7327,7 +7354,7 @@ export class Editor extends EventEmitter<TLEventMap> {
* @public
*/
@computed get sharedOpacity(): SharedStyle<number> {
if (this.isIn('select') && this.selectedShapeIds.length > 0) {
if (this.isIn('select') && this.getSelectedShapeIds().length > 0) {
const shapesToCheck: TLShape[] = []
const addShape = (shapeId: TLShapeId) => {
const shape = this.getShape(shapeId)
@ -7343,7 +7370,7 @@ export class Editor extends EventEmitter<TLEventMap> {
shapesToCheck.push(shape)
}
}
for (const shapeId of this.selectedShapeIds) {
for (const shapeId of this.getSelectedShapeIds()) {
addShape(shapeId)
}
@ -8649,7 +8676,7 @@ export class Editor extends EventEmitter<TLEventMap> {
if (!inputs.isEditing) {
this._pinchStart = this.camera.z
if (!this._selectedShapeIdsAtPointerDown.length) {
this._selectedShapeIdsAtPointerDown = this.selectedShapeIds
this._selectedShapeIdsAtPointerDown = this.getSelectedShapeIds()
}
this._didPinch = true
@ -8709,7 +8736,7 @@ export class Editor extends EventEmitter<TLEventMap> {
this._updateInputsFromEvent(info)
if (this.isMenuOpen) {
if (this.getIsMenuOpen()) {
// noop
} else {
if (inputs.ctrlKey) {
@ -8759,7 +8786,7 @@ export class Editor extends EventEmitter<TLEventMap> {
switch (info.name) {
case 'pointer_down': {
this._selectedShapeIdsAtPointerDown = this.selectedShapeIds
this._selectedShapeIdsAtPointerDown = this.getSelectedShapeIds()
// Firefox bug fix...
// If it's a left-mouse-click, we store the pointer id for later user
@ -8843,7 +8870,7 @@ export class Editor extends EventEmitter<TLEventMap> {
inputs.isPointing = false
inputs.isDragging = false
if (this.isMenuOpen) {
if (this.getIsMenuOpen()) {
// Suppressing pointerup here as <ContextMenu/> doesn't seem to do what we what here.
return
}

View file

@ -248,7 +248,8 @@ export class SnapManager {
// TODO: make this an incremental derivation
@computed get snappableShapes(): GapNode[] {
const { editor } = this
const { selectedShapeIds, renderingBounds: renderingBounds } = editor
const { renderingBounds: renderingBounds } = editor
const selectedShapeIds = editor.getSelectedShapeIds()
const snappableShapes: GapNode[] = []

View file

@ -51,7 +51,7 @@ export class GroupShapeUtil extends ShapeUtil<TLGroupShape> {
component(shape: TLGroupShape) {
const isErasing = this.editor.erasingShapeIds.includes(shape.id)
const { hintingShapeIds } = this.editor.currentPageState
const { hintingShapeIds } = this.editor.getCurrentPageState()
const isHintingOtherGroup =
hintingShapeIds.length > 0 &&
hintingShapeIds.some(
@ -60,7 +60,7 @@ export class GroupShapeUtil extends ShapeUtil<TLGroupShape> {
this.editor.isShapeOfType<TLGroupShape>(this.editor.getShape(id)!, 'group')
)
const isFocused = this.editor.currentPageState.focusedGroupId !== shape.id
const isFocused = this.editor.getCurrentPageState().focusedGroupId !== shape.id
if (
!isErasing && // always show the outline while we're erasing the group
@ -89,13 +89,13 @@ export class GroupShapeUtil extends ShapeUtil<TLGroupShape> {
override onChildrenChange: TLOnChildrenChangeHandler<TLGroupShape> = (group) => {
const children = this.editor.getSortedChildIdsForParent(group.id)
if (children.length === 0) {
if (this.editor.currentPageState.focusedGroupId === group.id) {
if (this.editor.getCurrentPageState().focusedGroupId === group.id) {
this.editor.popFocusedGroupId()
}
this.editor.deleteShapes([group.id])
return
} else if (children.length === 1) {
if (this.editor.currentPageState.focusedGroupId === group.id) {
if (this.editor.getCurrentPageState().focusedGroupId === group.id) {
this.editor.popFocusedGroupId()
}
this.editor.reparentShapes(children, group.parentId)

View file

@ -13,8 +13,7 @@ export class Pointing extends StateNode {
wasFocusedOnEnter = false
override onEnter = () => {
const { isMenuOpen } = this.editor
this.wasFocusedOnEnter = !isMenuOpen
this.wasFocusedOnEnter = !this.editor.getIsMenuOpen()
}
override onPointerMove: TLEventHandlers['onPointerMove'] = (info) => {

View file

@ -83,7 +83,7 @@ export function useDocumentEvents() {
break
}
case 'Tab': {
if (isFocusingInput() || editor.isMenuOpen) {
if (isFocusingInput() || editor.getIsMenuOpen()) {
return
}
break
@ -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.selectedShapeIds.length > 0) {
if (editor.editingShape || editor.getSelectedShapeIds().length > 0) {
e.preventDefault()
}
@ -147,7 +147,7 @@ export function useDocumentEvents() {
return
}
default: {
if (isFocusingInput() || editor.isMenuOpen) {
if (isFocusingInput() || editor.getIsMenuOpen()) {
return
}
}
@ -170,7 +170,7 @@ export function useDocumentEvents() {
if ((e as any).isKilled) return
;(e as any).isKilled = true
if (isFocusingInput() || editor.isMenuOpen) {
if (isFocusingInput() || editor.getIsMenuOpen()) {
return
}

View file

@ -34,7 +34,7 @@ export const TldrawSelectionForeground: TLSelectionForegroundComponent = track(
const bottomLeftEvents = useSelectionEvents('bottom_left')
const isDefaultCursor =
!editor.isMenuOpen && editor.getInstanceState().cursor.type === 'default'
!editor.getIsMenuOpen() && editor.getInstanceState().cursor.type === 'default'
const isCoarsePointer = editor.getInstanceState().isCoarsePointer
const shapes = editor.selectedShapes

View file

@ -23,7 +23,7 @@ beforeEach(() => {
editor = new TestEditor()
editor
.selectAll()
.deleteShapes(editor.selectedShapeIds)
.deleteShapes(editor.getSelectedShapeIds())
.createShapes([
{ id: ids.box1, type: 'geo', x: 100, y: 100, props: { w: 100, h: 100 } },
{ id: ids.box2, type: 'geo', x: 300, y: 300, props: { w: 100, h: 100 } },
@ -382,7 +382,7 @@ describe('When pointing an end shape', () => {
describe('reparenting issue', () => {
it('Correctly sets index when reparenting', () => {
editor.selectAll().deleteShapes(editor.selectedShapeIds)
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
// Create an arrow!
editor.setCurrentTool('arrow')
@ -440,7 +440,7 @@ describe('reparenting issue', () => {
})
it('Correctly sets index when reparenting with multiple arrows', () => {
editor.selectAll().deleteShapes(editor.selectedShapeIds)
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
// create two rectangles:
editor.createShapes([
@ -494,7 +494,7 @@ describe('reparenting issue', () => {
expect(arrow2BoundIndex).toBe('a1G')
// nudge everything around and make sure we all stay in the right order
editor.selectAll().nudgeShapes(editor.selectedShapeIds, { x: -1, y: 0 })
editor.selectAll().nudgeShapes(editor.getSelectedShapeIds(), { x: -1, y: 0 })
expect(editor.getShape(arrow1Id)!.index).toBe('a1V')
expect(editor.getShape(arrow2Id)!.index).toBe('a1G')
})
@ -502,7 +502,7 @@ describe('reparenting issue', () => {
describe('line bug', () => {
it('works as expected when binding to a straight line', () => {
editor.selectAll().deleteShapes(editor.selectedShapeIds)
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
expect(editor.currentPageShapes.length).toBe(0)
@ -528,7 +528,7 @@ describe('line bug', () => {
})
it('works as expected when binding to a straight horizontal line', () => {
editor.selectAll().deleteShapes(editor.selectedShapeIds)
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
expect(editor.currentPageShapes.length).toBe(0)

View file

@ -32,7 +32,7 @@ beforeEach(() => {
editor = new TestEditor()
editor
.selectAll()
.deleteShapes(editor.selectedShapeIds)
.deleteShapes(editor.getSelectedShapeIds())
.createShapes([
{ id: ids.box1, type: 'geo', x: 100, y: 100, props: { w: 100, h: 100 } },
{ id: ids.box2, type: 'geo', x: 300, y: 300, props: { w: 100, h: 100 } },
@ -179,7 +179,7 @@ describe('Other cases when arrow are moved', () => {
editor.select(ids.arrow1, ids.box2)
// When box one is not selected, unbinds box1 and keeps binding to box2
editor.nudgeShapes(editor.selectedShapeIds, { x: 0, y: -1 })
editor.nudgeShapes(editor.getSelectedShapeIds(), { x: 0, y: -1 })
expect(editor.getShape(ids.arrow1)).toMatchObject({
props: {
@ -190,7 +190,7 @@ describe('Other cases when arrow are moved', () => {
// unbinds when only the arrow is selected (not its bound shapes)
editor.select(ids.arrow1)
editor.nudgeShapes(editor.selectedShapeIds, { x: 0, y: -1 })
editor.nudgeShapes(editor.getSelectedShapeIds(), { x: 0, y: -1 })
expect(editor.getShape(ids.arrow1)).toMatchObject({
props: { start: { type: 'point' }, end: { type: 'point' } },
@ -202,7 +202,7 @@ describe('Other cases when arrow are moved', () => {
// When box one is not selected, unbinds box1 and keeps binding to box2
editor.select(ids.arrow1, ids.box2, ids.box3)
editor.alignShapes(editor.selectedShapeIds, 'right')
editor.alignShapes(editor.getSelectedShapeIds(), 'right')
jest.advanceTimersByTime(1000)
expect(editor.getShape(ids.arrow1)).toMatchObject({
@ -214,7 +214,7 @@ describe('Other cases when arrow are moved', () => {
// unbinds when only the arrow is selected (not its bound shapes)
editor.select(ids.arrow1, ids.box3)
editor.alignShapes(editor.selectedShapeIds, 'top')
editor.alignShapes(editor.getSelectedShapeIds(), 'top')
jest.advanceTimersByTime(1000)
expect(editor.getShape(ids.arrow1)).toMatchObject({
@ -237,7 +237,7 @@ describe('Other cases when arrow are moved', () => {
// When box one is not selected, unbinds box1 and keeps binding to box2
editor.select(ids.arrow1, ids.box2, ids.box3)
editor.distributeShapes(editor.selectedShapeIds, 'horizontal')
editor.distributeShapes(editor.getSelectedShapeIds(), 'horizontal')
jest.advanceTimersByTime(1000)
expect(editor.getShape(ids.arrow1)).toMatchObject({
@ -255,7 +255,7 @@ describe('Other cases when arrow are moved', () => {
// unbinds when only the arrow is selected (not its bound shapes) if the arrow itself has moved
editor.select(ids.arrow1, ids.box3, ids.box4)
editor.distributeShapes(editor.selectedShapeIds, 'vertical')
editor.distributeShapes(editor.getSelectedShapeIds(), 'vertical')
jest.advanceTimersByTime(1000)
// The arrow didn't actually move
@ -274,7 +274,7 @@ describe('Other cases when arrow are moved', () => {
// The arrow will move this time, so it should unbind
editor.updateShapes([{ id: ids.box4, type: 'geo', y: -600 }])
editor.distributeShapes(editor.selectedShapeIds, 'vertical')
editor.distributeShapes(editor.getSelectedShapeIds(), 'vertical')
jest.advanceTimersByTime(1000)
expect(editor.getShape(ids.arrow1)).toMatchObject({
@ -293,13 +293,13 @@ describe('Other cases when arrow are moved', () => {
// create shapes in a group:
editor
.selectAll()
.deleteShapes(editor.selectedShapeIds)
.deleteShapes(editor.getSelectedShapeIds())
.createShapes([
{ id: ids.box3, type: 'geo', x: 0, y: 300, props: { w: 100, h: 100 } },
{ id: ids.box4, type: 'geo', x: 0, y: 600, props: { w: 100, h: 100 } },
])
.selectAll()
.groupShapes(editor.selectedShapeIds)
.groupShapes(editor.getSelectedShapeIds())
editor.setCurrentTool('arrow').pointerDown(1000, 1000).pointerMove(50, 350).pointerUp(50, 350)
let arrow = editor.currentPageShapes[editor.currentPageShapes.length - 1]
@ -308,7 +308,7 @@ describe('Other cases when arrow are moved', () => {
expect(arrow.props.end.boundShapeId).toBe(ids.box3)
// translate:
editor.selectAll().nudgeShapes(editor.selectedShapeIds, { x: 0, y: 1 })
editor.selectAll().nudgeShapes(editor.getSelectedShapeIds(), { x: 0, y: 1 })
// arrow should still be bound to box3
arrow = editor.getShape(arrow.id)!
@ -360,7 +360,7 @@ describe('resizing', () => {
it('resizes', () => {
editor
.selectAll()
.deleteShapes(editor.selectedShapeIds)
.deleteShapes(editor.getSelectedShapeIds())
.setCurrentTool('arrow')
.pointerDown(0, 0)
.pointerMove(200, 200)
@ -415,7 +415,7 @@ describe('resizing', () => {
it('flips bend when flipping x or y', () => {
editor
.selectAll()
.deleteShapes(editor.selectedShapeIds)
.deleteShapes(editor.getSelectedShapeIds())
.setCurrentTool('arrow')
.pointerDown(0, 0)
.pointerMove(200, 200)
@ -484,7 +484,7 @@ describe("an arrow's parents", () => {
let boxCid: TLShapeId
beforeEach(() => {
editor.selectAll().deleteShapes(editor.selectedShapeIds)
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
editor.setCurrentTool('frame')
editor.pointerDown(0, 0).pointerMove(100, 100).pointerUp()

View file

@ -339,7 +339,7 @@ export class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
// If at least one bound shape is in the selection, do nothing;
// If no bound shapes are in the selection, unbind any bound shapes
const { selectedShapeIds } = this.editor
const selectedShapeIds = this.editor.getSelectedShapeIds()
if (
(startBindingId &&

View file

@ -53,7 +53,7 @@ export class Drawing extends StateNode {
override onEnter = (info: TLPointerEventInfo) => {
this.markId = null
this.info = info
this.canDraw = !this.editor.isMenuOpen
this.canDraw = !this.editor.getIsMenuOpen()
this.lastRecordedPoint = this.editor.inputs.currentPagePoint.clone()
if (this.canDraw) {
this.startShape()

View file

@ -84,7 +84,7 @@ export class EmbedShapeUtil extends BaseBoxShapeUtil<TLEmbedShape> {
const isHoveringWhileEditingSameShape = useValue(
'is hovering',
() => {
const { editingShapeId, hoveredShapeId } = this.editor.currentPageState
const { editingShapeId, hoveredShapeId } = this.editor.getCurrentPageState()
if (editingShapeId && hoveredShapeId !== editingShapeId) {
const editingShape = this.editor.getShape(editingShapeId)

View file

@ -21,7 +21,7 @@ describe(FrameShapeTool, () => {
expect(editor.currentPageShapes.length).toBe(1)
expect(editor.currentPageShapes[0]?.type).toBe('frame')
expect(editor.selectedShapeIds[0]).toBe(editor.currentPageShapes[0]?.id)
expect(editor.getSelectedShapeIds()[0]).toBe(editor.currentPageShapes[0]?.id)
editor.undo()
@ -41,7 +41,7 @@ describe(FrameShapeTool, () => {
expect(editor.currentPageShapes.length).toBe(1)
expect(editor.currentPageShapes[0]?.type).toBe('frame')
expect(editor.selectedShapeIds[0]).toBe(editor.currentPageShapes[0]?.id)
expect(editor.getSelectedShapeIds()[0]).toBe(editor.currentPageShapes[0]?.id)
editor.undo()

View file

@ -21,7 +21,7 @@ describe(GeoShapeTool, () => {
expect(editor.currentPageShapes.length).toBe(1)
expect(editor.currentPageShapes[0]?.type).toBe('geo')
expect(editor.selectedShapeIds[0]).toBe(editor.currentPageShapes[0]?.id)
expect(editor.getSelectedShapeIds()[0]).toBe(editor.currentPageShapes[0]?.id)
editor.undo()
@ -41,7 +41,7 @@ describe(GeoShapeTool, () => {
expect(editor.currentPageShapes.length).toBe(1)
expect(editor.currentPageShapes[0]?.type).toBe('geo')
expect(editor.selectedShapeIds[0]).toBe(editor.currentPageShapes[0]?.id)
expect(editor.getSelectedShapeIds()[0]).toBe(editor.currentPageShapes[0]?.id)
editor.undo()

View file

@ -15,7 +15,7 @@ beforeEach(() => {
editor = new TestEditor()
editor
.selectAll()
.deleteShapes(editor.selectedShapeIds)
.deleteShapes(editor.getSelectedShapeIds())
.createShapes([
{
id: id,
@ -149,7 +149,7 @@ describe('Misc', () => {
it('nudges', () => {
editor.select(id)
editor.nudgeShapes(editor.selectedShapeIds, { x: 1, y: 0 })
editor.nudgeShapes(editor.getSelectedShapeIds(), { x: 1, y: 0 })
editor.expectShapeToMatch({
id: id,
@ -157,7 +157,7 @@ describe('Misc', () => {
y: 150,
})
editor.nudgeShapes(editor.selectedShapeIds, { x: 0, y: 10 })
editor.nudgeShapes(editor.getSelectedShapeIds(), { x: 0, y: 10 })
editor.expectShapeToMatch({
id: id,
@ -176,12 +176,12 @@ describe('Misc', () => {
editor.select(boxID, id)
expect(editor.getShapePageBounds(box)!.maxX).not.toEqual(editor.getShapePageBounds(line)!.maxX)
editor.alignShapes(editor.selectedShapeIds, 'right')
editor.alignShapes(editor.getSelectedShapeIds(), 'right')
jest.advanceTimersByTime(1000)
expect(editor.getShapePageBounds(box)!.maxX).toEqual(editor.getShapePageBounds(line)!.maxX)
expect(editor.getShapePageBounds(box)!.maxY).not.toEqual(editor.getShapePageBounds(line)!.maxY)
editor.alignShapes(editor.selectedShapeIds, 'bottom')
editor.alignShapes(editor.getSelectedShapeIds(), 'bottom')
jest.advanceTimersByTime(1000)
expect(editor.getShapePageBounds(box)!.maxY).toEqual(editor.getShapePageBounds(line)!.maxY)
})
@ -213,7 +213,7 @@ describe('Misc', () => {
const duplicate = ids.filter((i) => i !== id)[0]
editor.select(duplicate)
editor.deleteShapes(editor.selectedShapeIds)
editor.deleteShapes(editor.getSelectedShapeIds())
ids = Array.from(editor.currentPageShapeIds.values())
expect(ids.length).toEqual(1)

View file

@ -21,7 +21,7 @@ describe(NoteShapeTool, () => {
expect(editor.currentPageShapes.length).toBe(1)
expect(editor.currentPageShapes[0]?.type).toBe('note')
expect(editor.selectedShapeIds[0]).toBe(editor.currentPageShapes[0]?.id)
expect(editor.getSelectedShapeIds()[0]).toBe(editor.currentPageShapes[0]?.id)
editor.cancel() // leave edit mode
@ -44,7 +44,7 @@ describe(NoteShapeTool, () => {
expect(editor.currentPageShapes.length).toBe(1)
expect(editor.currentPageShapes[0]?.type).toBe('note')
expect(editor.selectedShapeIds[0]).toBe(editor.currentPageShapes[0]?.id)
expect(editor.getSelectedShapeIds()[0]).toBe(editor.currentPageShapes[0]?.id)
editor.undo()

View file

@ -21,7 +21,7 @@ export class Pointing extends StateNode {
shape = {} as TLNoteShape
override onEnter = () => {
this.wasFocusedOnEnter = !this.editor.isMenuOpen
this.wasFocusedOnEnter = !this.editor.getIsMenuOpen()
if (this.wasFocusedOnEnter) {
this.shape = this.createShape()
}

View file

@ -117,7 +117,7 @@ export class Erasing extends StateNode {
}
complete() {
this.editor.deleteShapes(this.editor.currentPageState.erasingShapeIds)
this.editor.deleteShapes(this.editor.getCurrentPageState().erasingShapeIds)
this.editor.setErasingShapes([])
this.parent.transition('idle', {})
}

View file

@ -42,7 +42,7 @@ export class SelectTool extends StateNode {
]
override onExit = () => {
if (this.editor.currentPageState.editingShapeId) {
if (this.editor.getCurrentPageState().editingShapeId) {
this.editor.setEditingShape(null)
}
}

View file

@ -49,7 +49,7 @@ export class Brushing extends StateNode {
)
this.info = info
this.initialSelectedShapeIds = this.editor.selectedShapeIds.slice()
this.initialSelectedShapeIds = this.editor.getSelectedShapeIds().slice()
this.initialStartShape = this.editor.getShapesAtPoint(currentPagePoint)[0]
this.onPointerMove()
}

View file

@ -39,7 +39,7 @@ export class Idle extends StateNode {
}
override onPointerDown: TLEventHandlers['onPointerDown'] = (info) => {
if (this.editor.isMenuOpen) return
if (this.editor.getIsMenuOpen()) return
if (info.ctrlKey) {
this.cancel()

View file

@ -20,7 +20,7 @@ export class EditingShape extends StateNode {
}
override onExit = () => {
const { editingShapeId } = this.editor.currentPageState
const { editingShapeId } = this.editor.getCurrentPageState()
if (!editingShapeId) return
// Clear the editing shape

View file

@ -35,7 +35,7 @@ export class Idle extends StateNode {
}
override onPointerDown: TLEventHandlers['onPointerDown'] = (info) => {
if (this.editor.isMenuOpen) return
if (this.editor.getIsMenuOpen()) return
const shouldEnterCropMode = info.ctrlKey && getShouldEnterCropMode(this.editor)
@ -66,9 +66,9 @@ export class Idle extends StateNode {
return
}
const selectedShapeIds = this.editor.getSelectedShapeIds()
const {
onlySelectedShape,
selectedShapeIds,
inputs: { currentPagePoint },
} = this.editor
@ -140,7 +140,7 @@ export class Idle extends StateNode {
}
default: {
const { hoveredShape } = this.editor
if (hoveredShape && !this.editor.selectedShapeIds.includes(hoveredShape.id)) {
if (hoveredShape && !this.editor.getSelectedShapeIds().includes(hoveredShape.id)) {
this.onPointerDown({
...info,
shape: hoveredShape,
@ -345,9 +345,9 @@ export class Idle extends StateNode {
return
}
const selectedShapeIds = this.editor.getSelectedShapeIds()
const {
onlySelectedShape,
selectedShapeIds,
inputs: { currentPagePoint },
} = this.editor
@ -369,7 +369,7 @@ export class Idle extends StateNode {
break
}
case 'shape': {
const { selectedShapeIds } = this.editor.currentPageState
const { selectedShapeIds } = this.editor.getCurrentPageState()
const { shape } = info
const targetShape = this.editor.getOutermostSelectableShape(
@ -389,7 +389,7 @@ export class Idle extends StateNode {
override onCancel: TLEventHandlers['onCancel'] = () => {
if (
this.editor.focusedGroupId !== this.editor.currentPageId &&
this.editor.selectedShapeIds.length > 0
this.editor.getSelectedShapeIds().length > 0
) {
this.editor.popFocusedGroupId()
} else {
@ -544,7 +544,7 @@ export class Idle extends StateNode {
? MAJOR_NUDGE_FACTOR
: MINOR_NUDGE_FACTOR
this.editor.nudgeShapes(this.editor.selectedShapeIds, delta.mul(step))
this.editor.nudgeShapes(this.editor.getSelectedShapeIds(), delta.mul(step))
}
private canInteractWithShapeInReadOnly(shape: TLShape) {

View file

@ -8,7 +8,7 @@ export class PointingCanvas extends StateNode {
const { inputs } = this.editor
if (!inputs.shiftKey) {
if (this.editor.selectedShapeIds.length > 0) {
if (this.editor.getSelectedShapeIds().length > 0) {
this.editor.mark('selecting none')
this.editor.selectNone()
}

View file

@ -18,8 +18,8 @@ export class PointingShape extends StateNode {
didSelectOnEnter = false
override onEnter = (info: TLPointerEventInfo & { target: 'shape' }) => {
const selectedShapeIds = this.editor.getSelectedShapeIds()
const {
selectedShapeIds,
focusedGroupId,
selectionRotatedPageBounds: selectionBounds,
inputs: { currentPagePoint, shiftKey, altKey },
@ -60,10 +60,10 @@ export class PointingShape extends StateNode {
}
override onPointerUp: TLEventHandlers['onPointerUp'] = (info) => {
const selectedShapeIds = this.editor.getSelectedShapeIds()
const {
zoomLevel,
focusedGroupId,
selectedShapeIds,
inputs: { currentPagePoint, shiftKey },
} = this.editor
@ -180,7 +180,7 @@ export class PointingShape extends StateNode {
this.editor.mark('shift deselecting on pointer up')
this.editor.setSelectedShapes([
...this.editor.selectedShapeIds.filter((id) => !ancestors.find((a) => a.id === id)),
...this.editor.getSelectedShapeIds().filter((id) => !ancestors.find((a) => a.id === id)),
outermostSelectableShape.id,
])
} else {

View file

@ -364,8 +364,8 @@ export class Resizing extends StateNode {
}
_createSnapshot = () => {
const selectedShapeIds = this.editor.getSelectedShapeIds()
const {
selectedShapeIds,
selectionRotation,
inputs: { originPagePoint },
} = this.editor

View file

@ -26,7 +26,7 @@ export class ScribbleBrushing extends StateNode {
override onEnter = () => {
this.initialSelectedShapeIds = new Set<TLShapeId>(
this.editor.inputs.shiftKey ? this.editor.selectedShapeIds : []
this.editor.inputs.shiftKey ? this.editor.getSelectedShapeIds() : []
)
this.newlySelectedShapeIds = new Set<TLShapeId>()
this.size = 0

View file

@ -132,7 +132,7 @@ export class Translating extends StateNode {
this.markId = 'translating'
this.editor.mark(this.markId)
this.editor.duplicateShapes(Array.from(this.editor.selectedShapeIds))
this.editor.duplicateShapes(Array.from(this.editor.getSelectedShapeIds()))
this.snapshot = getTranslatingSnapshot(this.editor)
this.handleStart()
@ -285,7 +285,7 @@ function getTranslatingSnapshot(editor: Editor) {
const pagePoints: Vec2d[] = []
const shapeSnapshots = compact(
editor.selectedShapeIds.map((id): null | MovingShapeSnapshot => {
editor.getSelectedShapeIds().map((id): null | MovingShapeSnapshot => {
const shape = editor.getShape(id)
if (!shape) return null
movingShapes.push(shape)
@ -312,8 +312,8 @@ function getTranslatingSnapshot(editor: Editor) {
shapeSnapshots,
initialPageBounds: editor.selectionPageBounds!,
initialSnapPoints:
editor.selectedShapeIds.length === 1
? editor.snaps.snapPointsCache.get(editor.selectedShapeIds[0])!
editor.getSelectedShapeIds().length === 1
? editor.snaps.snapPointsCache.get(editor.getSelectedShapeIds()[0])!
: editor.selectionPageBounds
? editor.selectionPageBounds.snapPoints.map((p, i) => ({
id: 'selection:' + i,

View file

@ -1,7 +1,7 @@
import { Editor, HIT_TEST_MARGIN, TLShape, isShapeId } from '@tldraw/editor'
export function selectOnCanvasPointerUp(editor: Editor) {
const { selectedShapeIds } = editor
const selectedShapeIds = editor.getSelectedShapeIds()
const { shiftKey, altKey, currentPagePoint } = editor.inputs
const hitShape = editor.getShapeAtPoint(currentPagePoint, {

View file

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

View file

@ -15,7 +15,7 @@ export const DuplicateButton = track(function DuplicateButton() {
icon={action.icon}
type="icon"
onClick={() => action.onSelect('quick-actions')}
disabled={!(editor.isIn('select') && editor.selectedShapeIds.length > 0)}
disabled={!(editor.isIn('select') && editor.getSelectedShapeIds().length > 0)}
title={`${msg(action.label!)} ${kbdStr(action.kbd!)}`}
smallIcon
/>

View file

@ -36,7 +36,7 @@ export const MoveToPageMenu = track(function MoveToPageMenu() {
disabled={currentPageId === page.id}
onSelect={() => {
editor.mark('move_shapes_to_page')
editor.moveShapesToPage(editor.selectedShapeIds, page.id as TLPageId)
editor.moveShapesToPage(editor.getSelectedShapeIds(), page.id as TLPageId)
const toPage = editor.getPage(page.id)
@ -79,7 +79,7 @@ export const MoveToPageMenu = track(function MoveToPageMenu() {
key="new-page"
onSelect={() => {
const newPageId = PageRecordType.createId()
const ids = editor.selectedShapeIds
const ids = editor.getSelectedShapeIds()
editor.batch(() => {
editor.mark('move_shapes_to_page')
editor.createPage({ name: 'Page', id: newPageId })

View file

@ -178,7 +178,10 @@ export class MinimapManager {
const { editor, canvasScreenBounds, canvasPageBounds, contentPageBounds, contentScreenBounds } =
this
const { width: cw, height: ch } = canvasScreenBounds
const { viewportPageBounds, selectedShapeIds } = editor
const selectedShapeIds = this.editor.getSelectedShapeIds()
const { viewportPageBounds } = editor
if (!cvs || !pageBounds) {
return

View file

@ -13,7 +13,7 @@ export const ZoomMenu = track(function ZoomMenu() {
const zoom = editor.zoomLevel
const hasShapes = editor.currentPageShapeIds.size > 0
const hasSelected = editor.selectedShapeIds.length > 0
const hasSelected = editor.getSelectedShapeIds().length > 0
const isZoomedTo100 = editor.zoomLevel === 1
const handleDoubleClick = React.useCallback(() => {

View file

@ -20,7 +20,7 @@ export const TrashButton = track(function TrashButton() {
icon={action.icon}
type="icon"
onClick={() => action.onSelect('quick-actions')}
disabled={!(editor.isIn('select') && editor.selectedShapeIds.length > 0)}
disabled={!(editor.isIn('select') && editor.getSelectedShapeIds().length > 0)}
title={`${msg(action.label!)} ${kbdStr(action.kbd!)}`}
smallIcon
/>

View file

@ -137,7 +137,7 @@ export function menuItem(
}
function shapesWithUnboundArrows(editor: Editor) {
const { selectedShapeIds } = editor
const selectedShapeIds = editor.getSelectedShapeIds()
const selectedShapes = selectedShapeIds.map((id) => {
return editor.getShape(id)
})
@ -174,7 +174,7 @@ export const useAllowUngroup = () => {
const editor = useEditor()
return useValue(
'allowUngroup',
() => editor.selectedShapeIds.some((id) => editor.getShape(id)?.type === 'group'),
() => editor.getSelectedShapeIds().some((id) => editor.getShape(id)?.type === 'group'),
[editor]
)
}

View file

@ -95,7 +95,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
}
function hasSelectedShapes() {
return editor.selectedShapeIds.length > 0
return editor.getSelectedShapeIds().length > 0
}
const actions = makeActions([
@ -163,7 +163,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
readonlyOk: true,
onSelect(source) {
trackEvent('export-as', { format: 'svg', source })
exportAs(editor.selectedShapeIds, 'svg')
exportAs(editor.getSelectedShapeIds(), 'svg')
},
},
{
@ -174,7 +174,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
readonlyOk: true,
onSelect(source) {
trackEvent('export-as', { format: 'png', source })
exportAs(editor.selectedShapeIds, 'png')
exportAs(editor.getSelectedShapeIds(), 'png')
},
},
{
@ -185,7 +185,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
readonlyOk: true,
onSelect(source) {
trackEvent('export-as', { format: 'json', source })
exportAs(editor.selectedShapeIds, 'json')
exportAs(editor.getSelectedShapeIds(), 'json')
},
},
{
@ -197,7 +197,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
readonlyOk: true,
onSelect(source) {
trackEvent('copy-as', { format: 'svg', source })
copyAs(editor.selectedShapeIds, 'svg')
copyAs(editor.getSelectedShapeIds(), 'svg')
},
},
{
@ -208,7 +208,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
readonlyOk: true,
onSelect(source) {
trackEvent('copy-as', { format: 'png', source })
copyAs(editor.selectedShapeIds, 'png')
copyAs(editor.getSelectedShapeIds(), 'png')
},
},
{
@ -219,7 +219,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
readonlyOk: true,
onSelect(source) {
trackEvent('copy-as', { format: 'json', source })
copyAs(editor.selectedShapeIds, 'json')
copyAs(editor.getSelectedShapeIds(), 'json')
},
},
{
@ -258,7 +258,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
readonlyOk: true,
onSelect(source) {
trackEvent('open-embed-link', { source })
const ids = editor.selectedShapeIds
const ids = editor.getSelectedShapeIds()
const warnMsg = 'No embed shapes selected'
if (ids.length !== 1) {
console.error(warnMsg)
@ -344,7 +344,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('convert-to-embed', { source })
editor.batch(() => {
const ids = editor.selectedShapeIds
const ids = editor.getSelectedShapeIds()
const shapes = compact(ids.map((id) => editor.getShape(id)))
const createList: TLShapePartial[] = []
@ -400,7 +400,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
if (mustGoBackToSelectToolFirst()) return
trackEvent('duplicate-shapes', { source })
const ids = editor.selectedShapeIds
const ids = editor.getSelectedShapeIds()
const commonBounds = Box2d.Common(compact(ids.map((id) => editor.getShapePageBounds(id))))
const offset = editor.getInstanceState().canMoveCamera
? {
@ -427,7 +427,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('ungroup-shapes', { source })
editor.mark('ungroup')
editor.ungroupShapes(editor.selectedShapeIds)
editor.ungroupShapes(editor.getSelectedShapeIds())
},
},
{
@ -444,10 +444,10 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
const { onlySelectedShape } = editor
if (onlySelectedShape && editor.isShapeOfType<TLGroupShape>(onlySelectedShape, 'group')) {
editor.mark('ungroup')
editor.ungroupShapes(editor.selectedShapeIds)
editor.ungroupShapes(editor.getSelectedShapeIds())
} else {
editor.mark('group')
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
}
},
},
@ -463,7 +463,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('align-shapes', { operation: 'left', source })
editor.mark('align left')
editor.alignShapes(editor.selectedShapeIds, 'left')
editor.alignShapes(editor.getSelectedShapeIds(), 'left')
},
},
{
@ -479,7 +479,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('align-shapes', { operation: 'center-horizontal', source })
editor.mark('align center horizontal')
editor.alignShapes(editor.selectedShapeIds, 'center-horizontal')
editor.alignShapes(editor.getSelectedShapeIds(), 'center-horizontal')
},
},
{
@ -494,7 +494,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('align-shapes', { operation: 'right', source })
editor.mark('align right')
editor.alignShapes(editor.selectedShapeIds, 'right')
editor.alignShapes(editor.getSelectedShapeIds(), 'right')
},
},
{
@ -510,7 +510,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('align-shapes', { operation: 'center-vertical', source })
editor.mark('align center vertical')
editor.alignShapes(editor.selectedShapeIds, 'center-vertical')
editor.alignShapes(editor.getSelectedShapeIds(), 'center-vertical')
},
},
{
@ -525,7 +525,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('align-shapes', { operation: 'top', source })
editor.mark('align top')
editor.alignShapes(editor.selectedShapeIds, 'top')
editor.alignShapes(editor.getSelectedShapeIds(), 'top')
},
},
{
@ -540,7 +540,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('align-shapes', { operation: 'bottom', source })
editor.mark('align bottom')
editor.alignShapes(editor.selectedShapeIds, 'bottom')
editor.alignShapes(editor.getSelectedShapeIds(), 'bottom')
},
},
{
@ -556,7 +556,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('distribute-shapes', { operation: 'horizontal', source })
editor.mark('distribute horizontal')
editor.distributeShapes(editor.selectedShapeIds, 'horizontal')
editor.distributeShapes(editor.getSelectedShapeIds(), 'horizontal')
},
},
{
@ -572,7 +572,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('distribute-shapes', { operation: 'vertical', source })
editor.mark('distribute vertical')
editor.distributeShapes(editor.selectedShapeIds, 'vertical')
editor.distributeShapes(editor.getSelectedShapeIds(), 'vertical')
},
},
{
@ -587,7 +587,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('stretch-shapes', { operation: 'horizontal', source })
editor.mark('stretch horizontal')
editor.stretchShapes(editor.selectedShapeIds, 'horizontal')
editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
},
},
{
@ -602,7 +602,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('stretch-shapes', { operation: 'vertical', source })
editor.mark('stretch vertical')
editor.stretchShapes(editor.selectedShapeIds, 'vertical')
editor.stretchShapes(editor.getSelectedShapeIds(), 'vertical')
},
},
{
@ -617,7 +617,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('flip-shapes', { operation: 'horizontal', source })
editor.mark('flip horizontal')
editor.flipShapes(editor.selectedShapeIds, 'horizontal')
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
},
},
{
@ -632,7 +632,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('flip-shapes', { operation: 'vertical', source })
editor.mark('flip vertical')
editor.flipShapes(editor.selectedShapeIds, 'vertical')
editor.flipShapes(editor.getSelectedShapeIds(), 'vertical')
},
},
{
@ -646,7 +646,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('pack-shapes', { source })
editor.mark('pack')
editor.packShapes(editor.selectedShapeIds, 16)
editor.packShapes(editor.getSelectedShapeIds(), 16)
},
},
{
@ -661,7 +661,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('stack-shapes', { operation: 'vertical', source })
editor.mark('stack-vertical')
editor.stackShapes(editor.selectedShapeIds, 'vertical', 16)
editor.stackShapes(editor.getSelectedShapeIds(), 'vertical', 16)
},
},
{
@ -676,7 +676,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('stack-shapes', { operation: 'horizontal', source })
editor.mark('stack-horizontal')
editor.stackShapes(editor.selectedShapeIds, 'horizontal', 16)
editor.stackShapes(editor.getSelectedShapeIds(), 'horizontal', 16)
},
},
{
@ -691,7 +691,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('reorder-shapes', { operation: 'toFront', source })
editor.mark('bring to front')
editor.bringToFront(editor.selectedShapeIds)
editor.bringToFront(editor.getSelectedShapeIds())
},
},
{
@ -706,7 +706,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('reorder-shapes', { operation: 'forward', source })
editor.mark('bring forward')
editor.bringForward(editor.selectedShapeIds)
editor.bringForward(editor.getSelectedShapeIds())
},
},
{
@ -721,7 +721,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('reorder-shapes', { operation: 'backward', source })
editor.mark('send backward')
editor.sendBackward(editor.selectedShapeIds)
editor.sendBackward(editor.getSelectedShapeIds())
},
},
{
@ -736,7 +736,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('reorder-shapes', { operation: 'toBack', source })
editor.mark('send to back')
editor.sendToBack(editor.selectedShapeIds)
editor.sendToBack(editor.getSelectedShapeIds())
},
},
{
@ -820,7 +820,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
trackEvent('delete-shapes', { source })
editor.mark('delete')
editor.deleteShapes(editor.selectedShapeIds)
editor.deleteShapes(editor.getSelectedShapeIds())
},
},
{
@ -836,7 +836,10 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
editor.mark('rotate-cw')
const offset = editor.selectionRotation % (TAU / 2)
const dontUseOffset = approximately(offset, 0) || approximately(offset, TAU / 2)
editor.rotateShapesBy(editor.selectedShapeIds, TAU / 2 - (dontUseOffset ? 0 : offset))
editor.rotateShapesBy(
editor.getSelectedShapeIds(),
TAU / 2 - (dontUseOffset ? 0 : offset)
)
},
},
{
@ -852,7 +855,10 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
editor.mark('rotate-ccw')
const offset = editor.selectionRotation % (TAU / 2)
const offsetCloseToZero = approximately(offset, 0)
editor.rotateShapesBy(editor.selectedShapeIds, offsetCloseToZero ? -(TAU / 2) : -offset)
editor.rotateShapesBy(
editor.getSelectedShapeIds(),
offsetCloseToZero ? -(TAU / 2) : -offset
)
},
},
{
@ -1084,7 +1090,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
onSelect(source) {
editor.mark('locking')
trackEvent('toggle-lock', { source })
editor.toggleLock(editor.selectedShapeIds)
editor.toggleLock(editor.getSelectedShapeIds())
},
},
])

View file

@ -40,7 +40,9 @@ export const ActionsMenuSchemaProvider = ({
const editor = useEditor()
const actions = useActions()
const selectedCount = useValue('selected count', () => editor.selectedShapeIds.length, [editor])
const selectedCount = useValue('selected count', () => editor.getSelectedShapeIds().length, [
editor,
])
const oneSelected = selectedCount > 0
const twoSelected = selectedCount > 1

View file

@ -74,7 +74,7 @@ const INPUTS = ['input', 'select', 'textarea']
function disallowClipboardEvents(editor: Editor) {
const { activeElement } = document
return (
editor.isMenuOpen ||
editor.getIsMenuOpen() ||
(activeElement &&
(activeElement.getAttribute('contenteditable') ||
INPUTS.indexOf(activeElement.tagName.toLowerCase()) > -1))
@ -497,7 +497,7 @@ async function handleClipboardThings(editor: Editor, things: ClipboardThing[], p
* @public
*/
const handleNativeOrMenuCopy = (editor: Editor) => {
const content = editor.getContentFromCurrentPage(editor.selectedShapeIds)
const content = editor.getContentFromCurrentPage(editor.getSelectedShapeIds())
if (!content) {
if (navigator && navigator.clipboard) {
navigator.clipboard.writeText('')
@ -570,7 +570,7 @@ export function useMenuClipboardEvents() {
const copy = useCallback(
function onCopy(source: TLUiEventSource) {
if (editor.selectedShapeIds.length === 0) return
if (editor.getSelectedShapeIds().length === 0) return
handleNativeOrMenuCopy(editor)
trackEvent('copy', { source })
@ -580,10 +580,10 @@ export function useMenuClipboardEvents() {
const cut = useCallback(
function onCut(source: TLUiEventSource) {
if (editor.selectedShapeIds.length === 0) return
if (editor.getSelectedShapeIds().length === 0) return
handleNativeOrMenuCopy(editor)
editor.deleteShapes(editor.selectedShapeIds)
editor.deleteShapes(editor.getSelectedShapeIds())
trackEvent('cut', { source })
},
[editor, trackEvent]
@ -633,7 +633,7 @@ export function useNativeClipboardEvents() {
if (!appIsFocused) return
const copy = () => {
if (
editor.selectedShapeIds.length === 0 ||
editor.getSelectedShapeIds().length === 0 ||
editor.editingShapeId !== null ||
disallowClipboardEvents(editor)
)
@ -644,13 +644,13 @@ export function useNativeClipboardEvents() {
function cut() {
if (
editor.selectedShapeIds.length === 0 ||
editor.getSelectedShapeIds().length === 0 ||
editor.editingShapeId !== null ||
disallowClipboardEvents(editor)
)
return
handleNativeOrMenuCopy(editor)
editor.deleteShapes(editor.selectedShapeIds)
editor.deleteShapes(editor.getSelectedShapeIds())
trackEvent('cut', { source: 'kbd' })
}

View file

@ -55,7 +55,7 @@ export const TLUiContextMenuSchemaProvider = track(function TLUiContextMenuSchem
const onlyFlippableShapeSelected = useOnlyFlippableShape()
const selectedCount = editor.selectedShapeIds.length
const selectedCount = editor.getSelectedShapeIds().length
const oneSelected = selectedCount > 0

View file

@ -18,7 +18,7 @@ export function useCopyAs() {
//
// this is fine for navigator.clipboard.write, but for fallbacks it's a
// little awkward.
function copyAs(ids: TLShapeId[] = editor.selectedShapeIds, format: TLCopyType = 'svg') {
function copyAs(ids: TLShapeId[] = editor.getSelectedShapeIds(), format: TLCopyType = 'svg') {
if (ids.length === 0) {
ids = [...editor.currentPageShapeIds]
}

View file

@ -17,7 +17,7 @@ export function useExportAs() {
return useCallback(
async function exportAs(
ids: TLShapeId[] = editor.selectedShapeIds,
ids: TLShapeId[] = editor.getSelectedShapeIds(),
format: TLExportType = 'png'
) {
if (ids.length === 0) {

View file

@ -37,7 +37,7 @@ export const HelpMenuSchemaProvider = track(function HelpMenuSchemaProvider({
const editor = useEditor()
const actions = useActions()
const selectedCount = editor.selectedShapeIds.length
const selectedCount = editor.getSelectedShapeIds().length
const oneSelected = selectedCount > 0
const twoSelected = selectedCount > 1

View file

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

View file

@ -64,7 +64,9 @@ export function TLUiMenuSchemaProvider({ overrides, children }: TLUiMenuSchemaPr
const emptyPage = useValue('emptyPage', () => editor.currentPageShapeIds.size === 0, [editor])
const selectedCount = useValue('selectedCount', () => editor.selectedShapeIds.length, [editor])
const selectedCount = useValue('selectedCount', () => editor.getSelectedShapeIds().length, [
editor,
])
const noneSelected = selectedCount === 0
const oneSelected = selectedCount > 0
const twoSelected = selectedCount > 1

View file

@ -171,7 +171,8 @@ export function usePrint() {
}
}
const { pages, currentPageId, selectedShapeIds } = editor
const selectedShapeIds = editor.getSelectedShapeIds()
const { pages, currentPageId } = editor
const preserveAspectRatio = 'xMidYMid meet'
@ -182,7 +183,7 @@ export function usePrint() {
preserveAspectRatio,
}
if (editor.selectedShapeIds.length > 0) {
if (editor.getSelectedShapeIds().length > 0) {
// Print the selected ids from the current page
const svg = await editor.getSvg(selectedShapeIds, svgOpts)

View file

@ -21,9 +21,10 @@ export function useRelevantStyles(): {
'getRelevantStyles',
() => {
const styles = new SharedStyleMap(editor.sharedStyles)
const hasShape = editor.selectedShapeIds.length > 0 || !!editor.root.current.get()?.shapeType
const hasShape =
editor.getSelectedShapeIds().length > 0 || !!editor.root.current.get()?.shapeType
if (styles.size === 0 && editor.isIn('select') && editor.selectedShapeIds.length === 0) {
if (styles.size === 0 && editor.isIn('select') && editor.getSelectedShapeIds().length === 0) {
for (const style of selectToolStyles) {
styles.applyValue(style, editor.getStyleForNextShape(style))
}

View file

@ -48,7 +48,7 @@ export function buildFromV1Document(editor: Editor, document: LegacyTldrawDocume
// Delete all of the shapes on the current page
editor.selectAll()
editor.deleteShapes(editor.selectedShapeIds)
editor.deleteShapes(editor.getSelectedShapeIds())
// Create assets
const v1AssetIdsToV2AssetIds = new Map<string, TLAssetId>()

View file

@ -118,15 +118,15 @@ describe('shapes that are moved to another page', () => {
describe("should be excluded from the previous page's selectedShapeIds", () => {
test('[boxes]', () => {
editor.setSelectedShapes([ids.box1, ids.box2, ids.box3])
expect(editor.selectedShapeIds).toEqual([ids.box1, ids.box2, ids.box3])
expect(editor.getSelectedShapeIds()).toEqual([ids.box1, ids.box2, ids.box3])
moveShapesToPage2()
expect(editor.selectedShapeIds).toEqual([])
expect(editor.getSelectedShapeIds()).toEqual([])
})
test('[frame that does not move]', () => {
editor.setSelectedShapes([ids.frame1])
expect(editor.selectedShapeIds).toEqual([ids.frame1])
expect(editor.getSelectedShapeIds()).toEqual([ids.frame1])
moveShapesToPage2()
expect(editor.selectedShapeIds).toEqual([ids.frame1])
expect(editor.getSelectedShapeIds()).toEqual([ids.frame1])
})
})
})

View file

@ -15,7 +15,7 @@ beforeEach(() => {
editor = new TestEditor()
editor
.selectAll()
.deleteShapes(editor.selectedShapeIds)
.deleteShapes(editor.getSelectedShapeIds())
.createShapes([{ id: ids.box1, type: 'geo', x: 100, y: 100, props: { w: 100, h: 100 } }])
})
@ -100,7 +100,7 @@ describe('TLSelectTool.Translating', () => {
// shift-alt-drag the original, we shouldn't duplicate the copy too:
editor.pointerDown(150, 150, { target: 'shape', shape })
expect(editor.selectedShapeIds).toStrictEqual([ids.box1])
expect(editor.getSelectedShapeIds()).toStrictEqual([ids.box1])
editor.pointerMove(250, 150)
editor.pointerUp()
expect(editor.currentPageShapes.length).toStrictEqual(3)
@ -170,7 +170,7 @@ describe('When double clicking a shape', () => {
it('begins editing a geo shapes label', () => {
editor
.selectAll()
.deleteShapes(editor.selectedShapeIds)
.deleteShapes(editor.getSelectedShapeIds())
.selectNone()
.createShapes([{ id: createShapeId(), type: 'geo' }])
.doubleClick(50, 50, { target: 'shape', shape: editor.currentPageShapes[0] })
@ -183,7 +183,7 @@ describe('When pressing enter on a selected shape', () => {
const id = createShapeId()
editor
.selectAll()
.deleteShapes(editor.selectedShapeIds)
.deleteShapes(editor.getSelectedShapeIds())
.selectNone()
.createShapes([{ id, type: 'geo' }])
.select(id)
@ -214,7 +214,7 @@ describe('When double clicking the selection edge', () => {
const id = createShapeId()
editor
.selectAll()
.deleteShapes(editor.selectedShapeIds)
.deleteShapes(editor.getSelectedShapeIds())
.selectNone()
.createShapes([{ id, type: 'text', x: 100, y: 100, props: { scale: 2, text: 'hello' } }])
.select(id)
@ -227,7 +227,7 @@ describe('When double clicking the selection edge', () => {
const id = createShapeId()
editor
.selectAll()
.deleteShapes(editor.selectedShapeIds)
.deleteShapes(editor.getSelectedShapeIds())
.selectNone()
.createShapes([
{
@ -250,7 +250,7 @@ describe('When double clicking the selection edge', () => {
const id = createShapeId()
editor
.selectAll()
.deleteShapes(editor.selectedShapeIds)
.deleteShapes(editor.getSelectedShapeIds())
.selectNone()
.createShapes([
{
@ -275,7 +275,7 @@ describe('When double clicking the selection edge', () => {
const id = createShapeId()
editor
.selectAll()
.deleteShapes(editor.selectedShapeIds)
.deleteShapes(editor.getSelectedShapeIds())
.selectNone()
.createShapes([
{
@ -313,7 +313,7 @@ describe('When editing shapes', () => {
it('Pointing a shape of a different type selects it and leaves editing', () => {
expect(editor.editingShapeId).toBe(null)
expect(editor.selectedShapeIds.length).toBe(0)
expect(editor.getSelectedShapeIds().length).toBe(0)
// start editing the geo shape
editor.doubleClick(50, 50, { target: 'shape', shape: editor.getShape(ids.geo1) })
@ -329,7 +329,7 @@ describe('When editing shapes', () => {
// 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.selectedShapeIds.length).toBe(0)
expect(editor.getSelectedShapeIds().length).toBe(0)
// start editing the geo shape
editor.doubleClick(50, 50, { target: 'shape', shape: editor.getShape(ids.geo1) })
@ -345,7 +345,7 @@ describe('When editing shapes', () => {
// 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.selectedShapeIds.length).toBe(0)
expect(editor.getSelectedShapeIds().length).toBe(0)
// start editing the geo shape
editor.doubleClick(50, 50, { target: 'shape', shape: editor.getShape(ids.text1) })
@ -357,7 +357,7 @@ describe('When editing shapes', () => {
it('Double clicking the canvas creates a new text shape', () => {
expect(editor.editingShapeId).toBe(null)
expect(editor.selectedShapeIds.length).toBe(0)
expect(editor.getSelectedShapeIds().length).toBe(0)
expect(editor.currentPageShapes.length).toBe(5)
editor.doubleClick(750, 750)
expect(editor.currentPageShapes.length).toBe(6)
@ -366,37 +366,37 @@ describe('When editing shapes', () => {
it('It deletes an empty text shape when your click away', () => {
expect(editor.editingShapeId).toBe(null)
expect(editor.selectedShapeIds.length).toBe(0)
expect(editor.getSelectedShapeIds().length).toBe(0)
expect(editor.currentPageShapes.length).toBe(5)
// Create a new shape by double clicking
editor.doubleClick(750, 750)
expect(editor.selectedShapeIds.length).toBe(1)
expect(editor.getSelectedShapeIds().length).toBe(1)
expect(editor.currentPageShapes.length).toBe(6)
const shapeId = editor.selectedShapeIds[0]
const shapeId = editor.getSelectedShapeIds()[0]
// Click away
editor.click(1000, 1000)
expect(editor.selectedShapeIds.length).toBe(0)
expect(editor.getSelectedShapeIds().length).toBe(0)
expect(editor.currentPageShapes.length).toBe(5)
expect(editor.getShape(shapeId)).toBe(undefined)
})
it('It deletes an empty text shape when your click another text shape', () => {
expect(editor.editingShapeId).toBe(null)
expect(editor.selectedShapeIds.length).toBe(0)
expect(editor.getSelectedShapeIds().length).toBe(0)
expect(editor.currentPageShapes.length).toBe(5)
// Create a new shape by double clicking
editor.doubleClick(750, 750)
expect(editor.selectedShapeIds.length).toBe(1)
expect(editor.getSelectedShapeIds().length).toBe(1)
expect(editor.currentPageShapes.length).toBe(6)
const shapeId = editor.selectedShapeIds[0]
const shapeId = editor.getSelectedShapeIds()[0]
// Click another text shape
editor.pointerMove(50, 50)
editor.click()
expect(editor.selectedShapeIds.length).toBe(1)
expect(editor.getSelectedShapeIds().length).toBe(1)
expect(editor.currentPageShapes.length).toBe(5)
expect(editor.getShape(shapeId)).toBe(undefined)
})
@ -423,7 +423,7 @@ describe('When in readonly mode', () => {
it('Begins editing embed when double clicked', () => {
expect(editor.editingShapeId).toBe(null)
expect(editor.selectedShapeIds.length).toBe(0)
expect(editor.getSelectedShapeIds().length).toBe(0)
expect(editor.getInstanceState().isReadonly).toBe(true)
const shape = editor.getShape(ids.embed1)
@ -433,11 +433,11 @@ describe('When in readonly mode', () => {
it('Begins editing embed when pressing Enter on a selected embed', () => {
expect(editor.editingShapeId).toBe(null)
expect(editor.selectedShapeIds.length).toBe(0)
expect(editor.getSelectedShapeIds().length).toBe(0)
expect(editor.getInstanceState().isReadonly).toBe(true)
editor.setSelectedShapes([ids.embed1])
expect(editor.selectedShapeIds.length).toBe(1)
expect(editor.getSelectedShapeIds().length).toBe(1)
editor.keyUp('Enter')
expect(editor.editingShapeId).toBe(ids.embed1)

View file

@ -131,7 +131,7 @@ export class TestEditor extends Editor {
clipboard = null as TLContent | null
copy = (ids = this.selectedShapeIds) => {
copy = (ids = this.getSelectedShapeIds()) => {
if (ids.length > 0) {
const content = this.getContentFromCurrentPage(ids)
if (content) {
@ -141,7 +141,7 @@ export class TestEditor extends Editor {
return this
}
cut = (ids = this.selectedShapeIds) => {
cut = (ids = this.getSelectedShapeIds()) => {
if (ids.length > 0) {
const content = this.getContentFromCurrentPage(ids)
if (content) {
@ -471,7 +471,7 @@ export class TestEditor extends Editor {
shiftKey = false,
}: { handle?: RotateCorner; shiftKey?: boolean } = {}
) {
if (this.selectedShapeIds.length === 0) {
if (this.getSelectedShapeIds().length === 0) {
throw new Error('No selection')
}
@ -504,14 +504,14 @@ export class TestEditor extends Editor {
}
translateSelection(dx: number, dy: number, options?: Partial<TLPointerEventInfo>) {
if (this.selectedShapeIds.length === 0) {
if (this.getSelectedShapeIds().length === 0) {
throw new Error('No selection')
}
this.setCurrentTool('select')
const center = this.selectionPageCenter!
this.pointerDown(center.x, center.y, this.selectedShapeIds[0])
this.pointerDown(center.x, center.y, this.getSelectedShapeIds()[0])
const numSteps = 10
for (let i = 1; i < numSteps; i++) {
this.pointerMove(center.x + (i * dx) / numSteps, center.y + (i * dy) / numSteps, options)
@ -525,7 +525,7 @@ export class TestEditor extends Editor {
handle: SelectionHandle,
options?: Partial<TLPointerEventInfo>
) {
if (this.selectedShapeIds.length === 0) {
if (this.getSelectedShapeIds().length === 0) {
throw new Error('No selection')
}
this.setCurrentTool('select')

View file

@ -255,7 +255,7 @@ describe('<TldrawEditor />', () => {
// Select the shape
await act(async () => editor.select(id))
expect(editor.selectedShapeIds.length).toBe(1)
expect(editor.getSelectedShapeIds().length).toBe(1)
// Is the shape's component rendering?
expect(document.querySelectorAll('.tl-shape-indicator')).toHaveLength(1)

View file

@ -13,7 +13,7 @@ beforeEach(() => {
editor = new TestEditor()
editor
.selectAll()
.deleteShapes(editor.selectedShapeIds)
.deleteShapes(editor.getSelectedShapeIds())
.createShapes([{ id: ids.box1, type: 'geo', x: 100, y: 100, props: { w: 100, h: 100 } }])
})

View file

@ -234,7 +234,7 @@ describe('arrowBindingsIndex', () => {
expect(editor.getArrowsBoundTo(ids.box1)).toHaveLength(3)
editor.selectAll()
editor.duplicateShapes(editor.selectedShapeIds)
editor.duplicateShapes(editor.getSelectedShapeIds())
const [box1Clone, box2Clone] = editor.selectedShapes
.filter((shape) => editor.isShapeOfType<TLGeoShape>(shape, 'geo'))

View file

@ -24,7 +24,7 @@ describe('when less than two shapes are selected', () => {
const fn = jest.fn()
editor.on('update', fn)
editor.alignShapes(editor.selectedShapeIds, 'top')
editor.alignShapes(editor.getSelectedShapeIds(), 'top')
jest.advanceTimersByTime(1000)
expect(fn).not.toHaveBeenCalled()
})
@ -33,7 +33,7 @@ describe('when less than two shapes are selected', () => {
describe('when multiple shapes are selected', () => {
it('does, undoes and redoes command', () => {
editor.mark('align')
editor.alignShapes(editor.selectedShapeIds, 'top')
editor.alignShapes(editor.getSelectedShapeIds(), 'top')
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch({ id: ids.boxB, y: 0 })
@ -44,7 +44,7 @@ describe('when multiple shapes are selected', () => {
})
it('aligns top', () => {
editor.alignShapes(editor.selectedShapeIds, 'top')
editor.alignShapes(editor.getSelectedShapeIds(), 'top')
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch(
@ -55,7 +55,7 @@ describe('when multiple shapes are selected', () => {
})
it('aligns right', () => {
editor.alignShapes(editor.selectedShapeIds, 'right')
editor.alignShapes(editor.getSelectedShapeIds(), 'right')
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch(
@ -66,7 +66,7 @@ describe('when multiple shapes are selected', () => {
})
it('aligns bottom', () => {
editor.alignShapes(editor.selectedShapeIds, 'bottom')
editor.alignShapes(editor.getSelectedShapeIds(), 'bottom')
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch(
@ -77,7 +77,7 @@ describe('when multiple shapes are selected', () => {
})
it('aligns left', () => {
editor.alignShapes(editor.selectedShapeIds, 'left')
editor.alignShapes(editor.getSelectedShapeIds(), 'left')
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch(
@ -88,7 +88,7 @@ describe('when multiple shapes are selected', () => {
})
it('aligns center horizontal', () => {
editor.alignShapes(editor.selectedShapeIds, 'center-horizontal')
editor.alignShapes(editor.getSelectedShapeIds(), 'center-horizontal')
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch(
@ -99,7 +99,7 @@ describe('when multiple shapes are selected', () => {
})
it('aligns center vertical', () => {
editor.alignShapes(editor.selectedShapeIds, 'center-vertical')
editor.alignShapes(editor.getSelectedShapeIds(), 'center-vertical')
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch(
@ -128,9 +128,9 @@ describe('when multiple shapes are selected', () => {
},
])
editor.alignShapes(editor.selectedShapeIds, 'center-vertical')
editor.alignShapes(editor.getSelectedShapeIds(), 'center-vertical')
jest.advanceTimersByTime(1000)
editor.alignShapes(editor.selectedShapeIds, 'center-horizontal')
editor.alignShapes(editor.getSelectedShapeIds(), 'center-horizontal')
jest.advanceTimersByTime(1000)
const commonBounds = Box2d.Common([
@ -167,9 +167,9 @@ describe('when multiple shapes are selected', () => {
},
])
editor.alignShapes(editor.selectedShapeIds, 'top')
editor.alignShapes(editor.getSelectedShapeIds(), 'top')
jest.advanceTimersByTime(1000)
editor.alignShapes(editor.selectedShapeIds, 'left')
editor.alignShapes(editor.getSelectedShapeIds(), 'left')
jest.advanceTimersByTime(1000)
const commonBounds = Box2d.Common([
@ -207,9 +207,9 @@ describe('when multiple shapes are selected', () => {
])
editor.setSelectedShapes([ids.boxA, ids.boxB, ids.boxC])
editor.alignShapes(editor.selectedShapeIds, 'bottom')
editor.alignShapes(editor.getSelectedShapeIds(), 'bottom')
jest.advanceTimersByTime(1000)
editor.alignShapes(editor.selectedShapeIds, 'right')
editor.alignShapes(editor.getSelectedShapeIds(), 'right')
jest.advanceTimersByTime(1000)
const commonBounds = Box2d.Common([
@ -231,7 +231,7 @@ describe('When shapes are parented to other shapes...', () => {
beforeEach(() => {
editor = new TestEditor()
editor.selectAll()
editor.deleteShapes(editor.selectedShapeIds)
editor.deleteShapes(editor.getSelectedShapeIds())
ids = editor.createShapesFromJsx([
<TL.geo ref="boxA" x={0} y={0} w={100} h={100}>
<TL.geo ref="boxB" x={100} y={100} w={50} h={50} />
@ -250,9 +250,9 @@ describe('When shapes are parented to other shapes...', () => {
editor.getShapePageBounds(ids.boxB)!,
])
editor.alignShapes(editor.selectedShapeIds, 'top')
editor.alignShapes(editor.getSelectedShapeIds(), 'top')
jest.advanceTimersByTime(1000)
editor.alignShapes(editor.selectedShapeIds, 'left')
editor.alignShapes(editor.getSelectedShapeIds(), 'left')
jest.advanceTimersByTime(1000)
const commonBoundsAfter = Box2d.Common([
@ -272,9 +272,9 @@ describe('When shapes are parented to other shapes...', () => {
editor.getShapePageBounds(ids.boxB)!,
])
editor.alignShapes(editor.selectedShapeIds, 'bottom')
editor.alignShapes(editor.getSelectedShapeIds(), 'bottom')
jest.advanceTimersByTime(1000)
editor.alignShapes(editor.selectedShapeIds, 'right')
editor.alignShapes(editor.getSelectedShapeIds(), 'right')
jest.advanceTimersByTime(1000)
const commonBoundsAfter = Box2d.Common([
@ -291,7 +291,7 @@ describe('When shapes are parented to a rotated shape...', () => {
beforeEach(() => {
editor = new TestEditor()
editor.selectAll()
editor.deleteShapes(editor.selectedShapeIds)
editor.deleteShapes(editor.getSelectedShapeIds())
editor.createShapes([
{
id: ids.boxA,
@ -338,9 +338,9 @@ describe('When shapes are parented to a rotated shape...', () => {
editor.getShapePageBounds(ids.boxB)!,
])
editor.alignShapes(editor.selectedShapeIds, 'top')
editor.alignShapes(editor.getSelectedShapeIds(), 'top')
jest.advanceTimersByTime(1000)
editor.alignShapes(editor.selectedShapeIds, 'left')
editor.alignShapes(editor.getSelectedShapeIds(), 'left')
jest.advanceTimersByTime(1000)
const commonBoundsAfter = Box2d.Common([
@ -366,9 +366,9 @@ describe('When shapes are parented to a rotated shape...', () => {
editor.getShapePageBounds(ids.boxB)!,
])
editor.alignShapes(editor.selectedShapeIds, 'bottom')
editor.alignShapes(editor.getSelectedShapeIds(), 'bottom')
jest.advanceTimersByTime(1000)
editor.alignShapes(editor.selectedShapeIds, 'right')
editor.alignShapes(editor.getSelectedShapeIds(), 'right')
jest.advanceTimersByTime(1000)
const commonBoundsAfter = Box2d.Common([

View file

@ -14,11 +14,11 @@ const ids = {
beforeEach(() => {
editor = new TestEditor()
editor.selectAll().deleteShapes(editor.selectedShapeIds)
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
})
afterEach(() => {
editor.selectAll().deleteShapes(editor.selectedShapeIds)
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
})
const doMockClipboard = () => {
@ -446,7 +446,7 @@ describe('When copying and pasting', () => {
editor
// Create group
.selectAll()
.groupShapes(editor.selectedShapeIds)
.groupShapes(editor.getSelectedShapeIds())
// Move the group
.updateShapes([
{

View file

@ -17,7 +17,7 @@ beforeEach(() => {
editor = new TestEditor()
editor
.selectAll()
.deleteShapes(editor.selectedShapeIds)
.deleteShapes(editor.getSelectedShapeIds())
.createShapes([
{ id: ids.box1, type: 'geo', x: 100, y: 100, props: { w: 100, h: 100 } },
{ id: ids.box2, type: 'geo', x: 300, y: 300, props: { w: 100, h: 100 } },
@ -50,24 +50,24 @@ describe('Editor.deleteShapes', () => {
it('Deletes a shape', () => {
editor.select(ids.box3, ids.box4)
editor.mark('before deleting')
editor.deleteShapes(editor.selectedShapeIds) // delete the selected shapes
editor.deleteShapes(editor.getSelectedShapeIds()) // delete the selected shapes
expect(editor.getShape(ids.box3)).toBeUndefined()
expect(editor.getShape(ids.box4)).toBeUndefined()
expect(editor.selectedShapeIds).toMatchObject([])
expect(editor.getSelectedShapeIds()).toMatchObject([])
editor.undo()
expect(editor.getShape(ids.box3)).not.toBeUndefined()
expect(editor.getShape(ids.box4)).not.toBeUndefined()
expect(editor.selectedShapeIds).toMatchObject([ids.box3, ids.box4])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.box3, ids.box4])
editor.redo()
expect(editor.getShape(ids.box3)).toBeUndefined()
expect(editor.getShape(ids.box4)).toBeUndefined()
expect(editor.selectedShapeIds).toMatchObject([])
expect(editor.getSelectedShapeIds()).toMatchObject([])
})
it('Does nothing on an empty ids array', () => {
editor.selectNone()
const before = editor.store.serialize()
editor.deleteShapes(editor.selectedShapeIds) // should be a noop, nothing to delete
editor.deleteShapes(editor.getSelectedShapeIds()) // should be a noop, nothing to delete
expect(editor.store.serialize()).toStrictEqual(before)
})
@ -75,7 +75,7 @@ describe('Editor.deleteShapes', () => {
editor.reparentShapes([ids.box4], ids.box3)
editor.select(ids.box3)
editor.mark('before deleting')
editor.deleteShapes(editor.selectedShapeIds) // should be a noop, nothing to delete
editor.deleteShapes(editor.getSelectedShapeIds()) // should be a noop, nothing to delete
expect(editor.getShape(ids.box3)).toBeUndefined()
expect(editor.getShape(ids.box4)).toBeUndefined()
editor.undo()
@ -96,7 +96,7 @@ describe('When deleting arrows', () => {
// @ts-expect-error
expect(editor._arrowBindingsIndex.get()[ids.box2]).not.toBeUndefined()
editor.deleteShapes(editor.selectedShapeIds) // delete the selected shapes
editor.deleteShapes(editor.getSelectedShapeIds()) // delete the selected shapes
// @ts-expect-error
expect(editor._arrowBindingsIndex.get()[ids.box1]).toBeUndefined()
// @ts-expect-error

View file

@ -19,7 +19,7 @@ beforeEach(() => {
describe('distributeShapes command', () => {
beforeEach(() => {
editor.selectAll()
editor.deleteShapes(editor.selectedShapeIds)
editor.deleteShapes(editor.getSelectedShapeIds())
editor.createShapes([
{
id: ids.boxA,
@ -47,7 +47,7 @@ describe('distributeShapes command', () => {
editor.setSelectedShapes([ids.boxA, ids.boxB])
const fn = jest.fn()
editor.on('change-history', fn)
editor.distributeShapes(editor.selectedShapeIds, 'horizontal')
editor.distributeShapes(editor.getSelectedShapeIds(), 'horizontal')
jest.advanceTimersByTime(1000)
expect(fn).not.toHaveBeenCalled()
})
@ -56,7 +56,7 @@ describe('distributeShapes command', () => {
describe('When distributing...', () => {
it('distributeShapes horizontally', () => {
editor.selectAll()
editor.distributeShapes(editor.selectedShapeIds, 'horizontal')
editor.distributeShapes(editor.getSelectedShapeIds(), 'horizontal')
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch(
{ id: ids.boxA, x: 0 },
@ -68,7 +68,7 @@ describe('distributeShapes command', () => {
it('distributeShapes horizontally when shapes are clustered', () => {
editor.updateShapes([{ id: ids.boxC, type: 'geo', x: 25 }])
editor.selectAll()
editor.distributeShapes(editor.selectedShapeIds, 'horizontal')
editor.distributeShapes(editor.getSelectedShapeIds(), 'horizontal')
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch(
{ id: ids.boxA, x: 0 },
@ -79,7 +79,7 @@ describe('distributeShapes command', () => {
it('distributeShapes vertically', () => {
editor.selectAll()
editor.distributeShapes(editor.selectedShapeIds, 'vertical')
editor.distributeShapes(editor.getSelectedShapeIds(), 'vertical')
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch(
{ id: ids.boxA, y: 0 },
@ -91,7 +91,7 @@ describe('distributeShapes command', () => {
it('distributeShapes vertically when shapes are clustered', () => {
editor.updateShapes([{ id: ids.boxC, type: 'geo', y: 25 }])
editor.selectAll()
editor.distributeShapes(editor.selectedShapeIds, 'vertical')
editor.distributeShapes(editor.getSelectedShapeIds(), 'vertical')
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch(
{ id: ids.boxA, y: 0 },
@ -103,7 +103,7 @@ describe('distributeShapes command', () => {
it('distributeShapes shapes that are the child of another shape.', () => {
editor.selectAll()
editor.deleteShapes(editor.selectedShapeIds)
editor.deleteShapes(editor.getSelectedShapeIds())
editor.createShapes([
{
id: ids.boxA,
@ -133,7 +133,7 @@ describe('distributeShapes command', () => {
])
editor.setSelectedShapes([ids.boxB, ids.boxC, ids.boxD])
editor.distributeShapes(editor.selectedShapeIds, 'horizontal')
editor.distributeShapes(editor.getSelectedShapeIds(), 'horizontal')
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch(
@ -145,7 +145,7 @@ describe('distributeShapes command', () => {
it('distributeShapes shapes that are the child of another shape when clustered.', () => {
editor.selectAll()
editor.deleteShapes(editor.selectedShapeIds)
editor.deleteShapes(editor.getSelectedShapeIds())
editor.createShapes([
{
id: ids.boxA,
@ -175,7 +175,7 @@ describe('distributeShapes command', () => {
])
editor.setSelectedShapes([ids.boxB, ids.boxC, ids.boxD])
editor.distributeShapes(editor.selectedShapeIds, 'horizontal')
editor.distributeShapes(editor.getSelectedShapeIds(), 'horizontal')
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch(
@ -188,7 +188,7 @@ describe('distributeShapes command', () => {
it('distributeShapes shapes that are the child of another shape when a parent is rotated.', () => {
editor = new TestEditor()
editor.selectAll()
editor.deleteShapes(editor.selectedShapeIds)
editor.deleteShapes(editor.getSelectedShapeIds())
editor.createShapes([
{
id: ids.boxA,
@ -220,7 +220,7 @@ describe('distributeShapes command', () => {
editor.setSelectedShapes([ids.boxB, ids.boxC, ids.boxD])
editor.distributeShapes(editor.selectedShapeIds, 'horizontal')
editor.distributeShapes(editor.getSelectedShapeIds(), 'horizontal')
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch(

View file

@ -51,7 +51,7 @@ beforeEach(() => {
})
it('gets an SVG', async () => {
const svg = await editor.getSvg(editor.selectedShapeIds)
const svg = await editor.getSvg(editor.getSelectedShapeIds())
expect(svg).toBeTruthy()
})
@ -63,7 +63,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.selectedShapeIds)
const svg = await editor.getSvg(editor.getSelectedShapeIds())
const bbox = editor.selectionRotatedPageBounds!
const expanded = bbox.expandBy(SVG_PADDING) // adds 32px padding
@ -72,7 +72,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.selectedShapeIds))!
const svg = (await editor.getSvg(editor.getSelectedShapeIds()))!
const bbox = editor.selectionRotatedPageBounds!
const expanded = bbox.expandBy(SVG_PADDING) // adds 32px padding
@ -81,7 +81,7 @@ it('Gets the bounding box at the correct size', async () => {
})
it('Matches a snapshot', async () => {
const svg = (await editor.getSvg(editor.selectedShapeIds))!
const svg = (await editor.getSvg(editor.getSelectedShapeIds()))!
const elm = document.createElement('wrapper')
elm.appendChild(svg)
@ -90,21 +90,21 @@ it('Matches a snapshot', async () => {
})
it('Accepts a scale option', async () => {
const svg1 = (await editor.getSvg(editor.selectedShapeIds, { scale: 1 }))!
const svg1 = (await editor.getSvg(editor.getSelectedShapeIds(), { scale: 1 }))!
expect(svg1.getAttribute('width')).toBe('564')
const svg2 = (await editor.getSvg(editor.selectedShapeIds, { scale: 2 }))!
const svg2 = (await editor.getSvg(editor.getSelectedShapeIds(), { scale: 2 }))!
expect(svg2.getAttribute('width')).toBe('1128')
})
it('Accepts a background option', async () => {
const svg1 = (await editor.getSvg(editor.selectedShapeIds, { background: true }))!
const svg1 = (await editor.getSvg(editor.getSelectedShapeIds(), { background: true }))!
expect(svg1.style.backgroundColor).not.toBe('transparent')
const svg2 = (await editor.getSvg(editor.selectedShapeIds, { background: false }))!
const svg2 = (await editor.getSvg(editor.getSelectedShapeIds(), { background: false }))!
expect(svg2.style.backgroundColor).toBe('transparent')
})

View file

@ -17,7 +17,7 @@ const ids = {
beforeEach(() => {
editor = new TestEditor()
editor.selectAll()
editor.deleteShapes(editor.selectedShapeIds)
editor.deleteShapes(editor.getSelectedShapeIds())
editor.createShapes([
{
id: ids.lockedShapeA,
@ -83,10 +83,10 @@ beforeEach(() => {
describe('Locking', () => {
it('Can lock shapes', () => {
editor.setSelectedShapes([ids.unlockedShapeA])
editor.toggleLock(editor.selectedShapeIds)
editor.toggleLock(editor.getSelectedShapeIds())
expect(editor.getShape(ids.unlockedShapeA)!.isLocked).toBe(true)
// Locking deselects the shape
expect(editor.selectedShapeIds).toEqual([])
expect(editor.getSelectedShapeIds()).toEqual([])
})
})
@ -117,7 +117,7 @@ describe('Locked shapes', () => {
it('Cannot be selected with select all', () => {
editor.selectAll()
expect(editor.selectedShapeIds).toEqual([ids.unlockedShapeA, ids.unlockedShapeB])
expect(editor.getSelectedShapeIds()).toEqual([ids.unlockedShapeA, ids.unlockedShapeB])
})
it('Cannot be selected by clicking', () => {
@ -128,7 +128,7 @@ describe('Locked shapes', () => {
.expectToBeIn('select.pointing_canvas')
.pointerUp()
.expectToBeIn('select.idle')
expect(editor.selectedShapeIds).not.toContain(shape.id)
expect(editor.getSelectedShapeIds()).not.toContain(shape.id)
})
it('Cannot be edited', () => {
@ -138,7 +138,7 @@ describe('Locked shapes', () => {
// We create a new shape and we edit that one
editor.doubleClick(10, 10, { target: 'shape', shape }).expectToBeIn('select.editing_shape')
expect(editor.currentPageShapes.length).toBe(shapeCount + 1)
expect(editor.selectedShapeIds).not.toContain(shape.id)
expect(editor.getSelectedShapeIds()).not.toContain(shape.id)
})
it('Cannot be grouped', () => {
@ -169,7 +169,7 @@ describe('Unlocking', () => {
(id) => editor.getShape(id)!.isLocked
)
expect(lockedStatus).toStrictEqual([true, true])
editor.toggleLock(editor.selectedShapeIds)
editor.toggleLock(editor.getSelectedShapeIds())
lockedStatus = [ids.lockedShapeA, ids.lockedShapeB].map((id) => editor.getShape(id)!.isLocked)
expect(lockedStatus).toStrictEqual([false, false])
})

View file

@ -155,7 +155,7 @@ describe('arrows', () => {
let secondBox: TLShape
beforeEach(() => {
editor.selectAll().deleteShapes(editor.selectedShapeIds)
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
// draw a first box
editor.createShapes([
{

View file

@ -39,22 +39,22 @@ function nudgeAndGet(ids: TLShapeId[], key: string, shiftKey: boolean) {
switch (key) {
case 'ArrowLeft': {
editor.mark('nudge')
editor.nudgeShapes(editor.selectedShapeIds, { x: -step, y: 0 })
editor.nudgeShapes(editor.getSelectedShapeIds(), { x: -step, y: 0 })
break
}
case 'ArrowRight': {
editor.mark('nudge')
editor.nudgeShapes(editor.selectedShapeIds, { x: step, y: 0 })
editor.nudgeShapes(editor.getSelectedShapeIds(), { x: step, y: 0 })
break
}
case 'ArrowUp': {
editor.mark('nudge')
editor.nudgeShapes(editor.selectedShapeIds, { x: 0, y: -step })
editor.nudgeShapes(editor.getSelectedShapeIds(), { x: 0, y: -step })
break
}
case 'ArrowDown': {
editor.mark('nudge')
editor.nudgeShapes(editor.selectedShapeIds, { x: 0, y: step })
editor.nudgeShapes(editor.getSelectedShapeIds(), { x: 0, y: step })
break
}
}

View file

@ -15,7 +15,7 @@ jest.useFakeTimers()
beforeEach(() => {
editor = new TestEditor()
editor.selectAll()
editor.deleteShapes(editor.selectedShapeIds)
editor.deleteShapes(editor.getSelectedShapeIds())
editor.createShapes([
{
id: ids.boxA,
@ -42,7 +42,7 @@ describe('editor.packShapes', () => {
it('packs shapes', () => {
editor.selectAll()
const centerBefore = editor.selectionRotatedPageBounds!.center.clone()
editor.packShapes(editor.selectedShapeIds, 16)
editor.packShapes(editor.getSelectedShapeIds(), 16)
jest.advanceTimersByTime(1000)
expect(editor.currentPageShapes.map((s) => ({ ...s, parentId: 'wahtever' }))).toMatchSnapshot(
'packed shapes'
@ -53,7 +53,7 @@ describe('editor.packShapes', () => {
it('packs rotated shapes', () => {
editor.updateShapes([{ id: ids.boxA, type: 'geo', rotation: Math.PI }])
editor.selectAll().packShapes(editor.selectedShapeIds, 16)
editor.selectAll().packShapes(editor.getSelectedShapeIds(), 16)
jest.advanceTimersByTime(1000)
expect(editor.currentPageShapes.map((s) => ({ ...s, parentId: 'wahtever' }))).toMatchSnapshot(
'packed shapes'

View file

@ -60,7 +60,7 @@ describe('editor.rotateShapes', () => {
const { selectionPageCenter } = editor
// Rotate the shape...
editor.rotateShapesBy(editor.selectedShapeIds, Math.PI)
editor.rotateShapesBy(editor.getSelectedShapeIds(), Math.PI)
// Once for each shape
expect(fnStart).toHaveBeenCalledTimes(2)

View file

@ -40,9 +40,9 @@ describe('setCurrentPage', () => {
it("adding a page to the store by any means adds tab state for the page if it doesn't already exist", () => {
const page = PageRecordType.create({ name: 'test', index: 'a4' })
expect(editor.pageStates.find((p) => p.pageId === page.id)).toBeUndefined()
expect(editor.getPageStates().find((p) => p.pageId === page.id)).toBeUndefined()
editor.store.put([page])
expect(editor.pageStates.find((p) => p.pageId === page.id)).not.toBeUndefined()
expect(editor.getPageStates().find((p) => p.pageId === page.id)).not.toBeUndefined()
})
it('squashes', () => {

View file

@ -15,43 +15,43 @@ beforeEach(() => {
})
it('Sets selected shapes', () => {
expect(editor.selectedShapeIds).toMatchObject([])
expect(editor.getSelectedShapeIds()).toMatchObject([])
editor.setSelectedShapes([ids.box1, ids.box2])
expect(editor.selectedShapeIds).toMatchObject([ids.box1, ids.box2])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.box1, ids.box2])
editor.undo()
expect(editor.selectedShapeIds).toMatchObject([])
expect(editor.getSelectedShapeIds()).toMatchObject([])
editor.redo()
expect(editor.selectedShapeIds).toMatchObject([ids.box1, ids.box2])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.box1, ids.box2])
})
it('Prevents parent and child from both being selected', () => {
editor.setSelectedShapes([ids.box2, ids.ellipse1]) // ellipse1 is child of box2
expect(editor.selectedShapeIds).toMatchObject([ids.box2])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.box2])
})
it('Deleting the parent also deletes descendants', () => {
editor.setSelectedShapes([ids.box2])
expect(editor.selectedShapeIds).toMatchObject([ids.box2])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.box2])
expect(editor.getShape(ids.box2)).not.toBeUndefined()
expect(editor.getShape(ids.ellipse1)).not.toBeUndefined()
editor.mark('')
editor.deleteShapes([ids.box2])
expect(editor.selectedShapeIds).toMatchObject([])
expect(editor.getSelectedShapeIds()).toMatchObject([])
expect(editor.getShape(ids.box2)).toBeUndefined()
expect(editor.getShape(ids.ellipse1)).toBeUndefined()
editor.undo()
expect(editor.selectedShapeIds).toMatchObject([ids.box2])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.box2])
expect(editor.getShape(ids.box2)).not.toBe(undefined)
expect(editor.getShape(ids.ellipse1)).not.toBe(undefined)
editor.redo()
expect(editor.selectedShapeIds).toMatchObject([])
expect(editor.getSelectedShapeIds()).toMatchObject([])
expect(editor.getShape(ids.box2)).toBeUndefined()
expect(editor.getShape(ids.ellipse1)).toBeUndefined()
})

View file

@ -19,7 +19,7 @@ beforeEach(() => {
describe('distributeShapes command', () => {
beforeEach(() => {
editor.selectAll()
editor.deleteShapes(editor.selectedShapeIds)
editor.deleteShapes(editor.getSelectedShapeIds())
editor.createShapes([
{
id: ids.boxA,
@ -53,7 +53,7 @@ describe('distributeShapes command', () => {
editor.setSelectedShapes([ids.boxA, ids.boxB])
const fn = jest.fn()
editor.on('change-history', fn)
editor.stackShapes(editor.selectedShapeIds, 'horizontal', 0)
editor.stackShapes(editor.getSelectedShapeIds(), 'horizontal', 0)
jest.advanceTimersByTime(1000)
expect(fn).not.toHaveBeenCalled()
})
@ -62,7 +62,7 @@ describe('distributeShapes command', () => {
describe('when stacking horizontally', () => {
it('stacks the shapes based on a given value', () => {
editor.setSelectedShapes([ids.boxA, ids.boxB, ids.boxC, ids.boxD])
editor.stackShapes(editor.selectedShapeIds, 'horizontal', 10)
editor.stackShapes(editor.getSelectedShapeIds(), 'horizontal', 10)
jest.advanceTimersByTime(1000)
// 200 distance gap between c and d
editor.expectShapeToMatch({
@ -89,7 +89,7 @@ describe('distributeShapes command', () => {
it('stacks the shapes based on the most common gap', () => {
editor.setSelectedShapes([ids.boxA, ids.boxB, ids.boxC, ids.boxD])
editor.stackShapes(editor.selectedShapeIds, 'horizontal', 0)
editor.stackShapes(editor.getSelectedShapeIds(), 'horizontal', 0)
jest.advanceTimersByTime(1000)
// 200 distance gap between c and d
editor.expectShapeToMatch({
@ -117,7 +117,7 @@ describe('distributeShapes command', () => {
it('stacks the shapes based on the average', () => {
editor.updateShapes([{ id: ids.boxD, type: 'geo', x: 540, y: 700 }])
editor.setSelectedShapes([ids.boxA, ids.boxB, ids.boxC, ids.boxD])
editor.stackShapes(editor.selectedShapeIds, 'horizontal', 0)
editor.stackShapes(editor.getSelectedShapeIds(), 'horizontal', 0)
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch({
id: ids.boxA,
@ -145,7 +145,7 @@ describe('distributeShapes command', () => {
describe('when stacking vertically', () => {
it('stacks the shapes based on a given value', () => {
editor.setSelectedShapes([ids.boxA, ids.boxB, ids.boxC, ids.boxD])
editor.stackShapes(editor.selectedShapeIds, 'vertical', 10)
editor.stackShapes(editor.getSelectedShapeIds(), 'vertical', 10)
jest.advanceTimersByTime(1000)
// 200 distance gap between c and d
editor.expectShapeToMatch({
@ -172,7 +172,7 @@ describe('distributeShapes command', () => {
it('stacks the shapes based on the most common gap', () => {
editor.setSelectedShapes([ids.boxA, ids.boxB, ids.boxC, ids.boxD])
editor.stackShapes(editor.selectedShapeIds, 'vertical', 0)
editor.stackShapes(editor.getSelectedShapeIds(), 'vertical', 0)
jest.advanceTimersByTime(1000)
// 200 distance gap between c and d
editor.expectShapeToMatch({
@ -200,7 +200,7 @@ describe('distributeShapes command', () => {
it('stacks the shapes based on the average', () => {
editor.updateShapes([{ id: ids.boxD, type: 'geo', x: 700, y: 540 }])
editor.setSelectedShapes([ids.boxA, ids.boxB, ids.boxC, ids.boxD])
editor.stackShapes(editor.selectedShapeIds, 'vertical', 0)
editor.stackShapes(editor.getSelectedShapeIds(), 'vertical', 0)
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch({
id: ids.boxA,

View file

@ -14,7 +14,7 @@ function createVideoShape() {
beforeEach(() => {
editor = new TestEditor()
editor.selectAll()
editor.deleteShapes(editor.selectedShapeIds)
editor.deleteShapes(editor.getSelectedShapeIds())
ids = editor.createShapesFromJsx([
<TL.geo ref="boxA" x={0} y={0} w={100} h={100} />,
<TL.geo ref="boxB" x={100} y={100} w={50} h={50} />,
@ -28,7 +28,7 @@ describe('when less than two shapes are selected', () => {
editor.setSelectedShapes([ids.boxB])
const fn = jest.fn()
editor.on('change-history', fn)
editor.stretchShapes(editor.selectedShapeIds, 'horizontal')
editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
jest.advanceTimersByTime(1000)
expect(fn).not.toHaveBeenCalled()
@ -38,7 +38,7 @@ describe('when less than two shapes are selected', () => {
describe('when multiple shapes are selected', () => {
it('stretches horizontally', () => {
editor.selectAll()
editor.stretchShapes(editor.selectedShapeIds, 'horizontal')
editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch(
{ id: ids.boxA, x: 0, y: 0, props: { w: 500 } },
@ -51,7 +51,7 @@ describe('when multiple shapes are selected', () => {
const videoA = createVideoShape()
editor.selectAll()
expect(editor.selectedShapes.length).toBe(4)
editor.stretchShapes(editor.selectedShapeIds, 'horizontal')
editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
jest.advanceTimersByTime(1000)
const newHeight = (500 * 9) / 16
editor.expectShapeToMatch(
@ -64,7 +64,7 @@ describe('when multiple shapes are selected', () => {
it('stretches vertically', () => {
editor.selectAll()
editor.stretchShapes(editor.selectedShapeIds, 'vertical')
editor.stretchShapes(editor.getSelectedShapeIds(), 'vertical')
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch(
{ id: ids.boxA, x: 0, y: 0, props: { h: 500 } },
@ -77,7 +77,7 @@ describe('when multiple shapes are selected', () => {
const videoA = createVideoShape()
editor.selectAll()
expect(editor.selectedShapes.length).toBe(4)
editor.stretchShapes(editor.selectedShapeIds, 'vertical')
editor.stretchShapes(editor.getSelectedShapeIds(), 'vertical')
jest.advanceTimersByTime(1000)
const newWidth = (500 * 16) / 9
editor.expectShapeToMatch(
@ -90,7 +90,7 @@ describe('when multiple shapes are selected', () => {
it('does, undoes and redoes command', () => {
editor.mark('stretch')
editor.stretchShapes(editor.selectedShapeIds, 'horizontal')
editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch({ id: ids.boxB, x: 0, props: { w: 500 } })
@ -105,7 +105,7 @@ describe('When shapes are the child of another shape.', () => {
it('stretches horizontally', () => {
editor.reparentShapes([ids.boxB], ids.boxA)
editor.select(ids.boxB, ids.boxC)
editor.stretchShapes(editor.selectedShapeIds, 'horizontal')
editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch(
{ id: ids.boxB, x: 100, y: 100, props: { w: 400 } },
@ -116,7 +116,7 @@ describe('When shapes are the child of another shape.', () => {
it('stretches vertically', () => {
editor.reparentShapes([ids.boxB], ids.boxA)
editor.select(ids.boxB, ids.boxC)
editor.stretchShapes(editor.selectedShapeIds, 'vertical')
editor.stretchShapes(editor.getSelectedShapeIds(), 'vertical')
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch(
{ id: ids.boxB, x: 100, y: 100, props: { h: 400 } },
@ -129,7 +129,7 @@ describe('When shapes are the child of a rotated shape.', () => {
beforeEach(() => {
editor = new TestEditor()
editor.selectAll()
editor.deleteShapes(editor.selectedShapeIds)
editor.deleteShapes(editor.getSelectedShapeIds())
ids = editor.createShapesFromJsx([
<TL.geo ref="boxA" x={0} y={0} w={100} h={100} rotation={PI}>
<TL.geo ref="boxB" x={100} y={100} w={50} h={50} />
@ -141,7 +141,7 @@ describe('When shapes are the child of a rotated shape.', () => {
it('does not stretches rotated shapes', () => {
editor.select(ids.boxB, ids.boxC)
editor.stretchShapes(editor.selectedShapeIds, 'horizontal')
editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch(
{
@ -167,7 +167,7 @@ describe('When shapes are the child of a rotated shape.', () => {
it('does not stretches rotated shapes', () => {
editor.select(ids.boxB, ids.boxC)
editor.stretchShapes(editor.selectedShapeIds, 'vertical')
editor.stretchShapes(editor.getSelectedShapeIds(), 'vertical')
jest.advanceTimersByTime(1000)
editor.expectShapeToMatch(
{
@ -195,7 +195,7 @@ describe('When shapes are the child of a rotated shape.', () => {
describe('When shapes have 0-width or 0-height', () => {
it('Does not error with 0-width', () => {
editor.selectAll()
editor.deleteShapes(editor.selectedShapeIds)
editor.deleteShapes(editor.getSelectedShapeIds())
editor
.setCurrentTool('arrow')
@ -213,13 +213,13 @@ describe('When shapes have 0-width or 0-height', () => {
editor.selectAll()
// make sure we don't get any errors:
editor.stretchShapes(editor.selectedShapeIds, 'horizontal')
editor.stretchShapes(editor.selectedShapeIds, 'vertical')
editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
editor.stretchShapes(editor.getSelectedShapeIds(), 'vertical')
})
it('Does not error with 0-height', () => {
editor.selectAll()
editor.deleteShapes(editor.selectedShapeIds)
editor.deleteShapes(editor.getSelectedShapeIds())
editor
// draw a perfectly horiztonal arrow:
@ -239,7 +239,7 @@ describe('When shapes have 0-width or 0-height', () => {
editor.selectAll()
// make sure we don't get any errors:
editor.stretchShapes(editor.selectedShapeIds, 'horizontal')
editor.stretchShapes(editor.selectedShapeIds, 'vertical')
editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
editor.stretchShapes(editor.getSelectedShapeIds(), 'vertical')
})
})

View file

@ -156,7 +156,7 @@ describe('When a shape has a different shape as a parent...', () => {
})
it('Throws out all shapes if any update is invalid', () => {
editor.selectAll().deleteShapes(editor.selectedShapeIds)
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
editor.createShapes([
{ id: ids.box1, type: 'geo', x: 0, y: 0 },

View file

@ -91,27 +91,27 @@ describe('When in the select.idle state', () => {
editor.select(ids.boxA)
editor.expectPathToBe('root.select.idle')
expect(editor.selectedShapeIds).toMatchObject([ids.boxA])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.boxA])
expect(editor.croppingShapeId).toBe(null)
editor.doubleClick(550, 550, ids.imageB)
editor.expectPathToBe('root.select.crop.idle')
expect(editor.selectedShapeIds).toMatchObject([ids.imageB])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.imageB])
expect(editor.croppingShapeId).toBe(ids.imageB)
editor.undo()
// first selection should have been a mark
editor.expectPathToBe('root.select.idle')
expect(editor.selectedShapeIds).toMatchObject([ids.imageB])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.imageB])
expect(editor.croppingShapeId).toBe(null)
editor.undo()
// back to start
editor.expectPathToBe('root.select.idle')
expect(editor.selectedShapeIds).toMatchObject([ids.boxA])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.boxA])
expect(editor.croppingShapeId).toBe(null)
editor
@ -119,7 +119,7 @@ describe('When in the select.idle state', () => {
.redo() // crop again
editor.expectPathToBe('root.select.crop.idle')
expect(editor.selectedShapeIds).toMatchObject([ids.imageB])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.imageB])
expect(editor.croppingShapeId).toBe(ids.imageB)
})
@ -296,7 +296,7 @@ describe('When in the crop.idle state', () => {
.expectPathToBe('root.select.crop.pointing_crop')
expect(editor.croppingShapeId).toBe(ids.imageB)
expect(editor.selectedShapeIds).toMatchObject([ids.imageB])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.imageB])
})
it('clicking another image shape should set that shape as the new cropping shape and transition to pointing_crop', () => {
@ -308,7 +308,7 @@ describe('When in the crop.idle state', () => {
.expectPathToBe('root.select.crop.pointing_crop')
expect(editor.croppingShapeId).toBe(ids.imageA)
expect(editor.selectedShapeIds).toMatchObject([ids.imageA])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.imageA])
})
it('rotating will return to select.crop.idle', () => {

View file

@ -14,12 +14,12 @@ const ids = {
beforeEach(() => {
editor = new TestEditor()
editor.selectAll().deleteShapes(editor.selectedShapeIds)
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
})
it('creates new bindings for arrows when pasting', async () => {
editor
.selectAll()
.deleteShapes(editor.selectedShapeIds)
.deleteShapes(editor.getSelectedShapeIds())
.createShapes([
{ id: ids.box1, type: 'geo', x: 100, y: 100, props: { w: 100, h: 100 } },
{ id: ids.box2, type: 'geo', x: 300, y: 300, props: { w: 100, h: 100 } },
@ -47,7 +47,7 @@ it('creates new bindings for arrows when pasting', async () => {
const shapesBefore = editor.currentPageShapes
editor.selectAll().duplicateShapes(editor.selectedShapeIds)
editor.selectAll().duplicateShapes(editor.getSelectedShapeIds())
const shapesAfter = editor.currentPageShapes
@ -174,17 +174,17 @@ describe('When duplicating shapes that include arrows', () => {
})
it('Preserves the same selection bounds', () => {
editor.selectAll().deleteShapes(editor.selectedShapeIds).createShapes(shapes).selectAll()
editor.selectAll().deleteShapes(editor.getSelectedShapeIds()).createShapes(shapes).selectAll()
const boundsBefore = editor.selectionRotatedPageBounds!
editor.duplicateShapes(editor.selectedShapeIds)
editor.duplicateShapes(editor.getSelectedShapeIds())
expect(editor.selectionRotatedPageBounds).toCloselyMatchObject(boundsBefore)
})
it('Preserves the same selection bounds when only duplicating the arrows', () => {
editor
.selectAll()
.deleteShapes(editor.selectedShapeIds)
.deleteShapes(editor.getSelectedShapeIds())
.createShapes(shapes)
.select(
...editor.currentPageShapes
@ -193,7 +193,7 @@ describe('When duplicating shapes that include arrows', () => {
)
const boundsBefore = editor.selectionRotatedPageBounds!
editor.duplicateShapes(editor.selectedShapeIds)
editor.duplicateShapes(editor.getSelectedShapeIds())
const boundsAfter = editor.selectionRotatedPageBounds!
// It's not exactly exact, but close enough is plenty close

View file

@ -23,7 +23,7 @@ const ids = {
beforeEach(() => {
editor = new TestEditor()
editor.selectAll()
editor.deleteShapes(editor.selectedShapeIds)
editor.deleteShapes(editor.getSelectedShapeIds())
editor.createShapes([
{
id: ids.boxA,
@ -62,7 +62,7 @@ describe('When flipping horizontally', () => {
it('Flips the selected shapes', () => {
editor.select(ids.boxA, ids.boxB, ids.boxC)
editor.mark('flipped')
editor.flipShapes(editor.selectedShapeIds, 'horizontal')
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
editor.expectShapeToMatch(
{
@ -106,7 +106,7 @@ describe('When flipping horizontally', () => {
editor.select(ids.boxA, ids.boxB)
const a = editor.selectionPageBounds
editor.mark('flipped')
editor.flipShapes(editor.selectedShapeIds, 'horizontal')
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
const b = editor.selectionPageBounds
expect(a!).toCloselyMatchObject(b!)
@ -131,7 +131,7 @@ describe('When flipping horizontally', () => {
editor.select(ids.boxB, ids.boxC)
const a = editor.selectionPageBounds
editor.mark('flipped')
editor.flipShapes(editor.selectedShapeIds, 'horizontal')
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
const b = editor.selectionPageBounds
expect(a).toCloselyMatchObject(b!)
@ -142,7 +142,7 @@ describe('When flipping vertically', () => {
it('Flips the selected shapes', () => {
editor.select(ids.boxA, ids.boxB, ids.boxC)
editor.mark('flipped')
editor.flipShapes(editor.selectedShapeIds, 'vertical')
editor.flipShapes(editor.getSelectedShapeIds(), 'vertical')
editor.expectShapeToMatch(
{
@ -186,7 +186,7 @@ describe('When flipping vertically', () => {
editor.select(ids.boxA, ids.boxB)
const a = editor.selectionPageBounds
editor.mark('flipped')
editor.flipShapes(editor.selectedShapeIds, 'vertical')
editor.flipShapes(editor.getSelectedShapeIds(), 'vertical')
const b = editor.selectionPageBounds
expect(a).toCloselyMatchObject(b!)
@ -210,7 +210,7 @@ describe('When flipping vertically', () => {
editor.select(ids.boxB, ids.boxC)
const a = editor.selectionPageBounds
editor.mark('flipped')
editor.flipShapes(editor.selectedShapeIds, 'vertical')
editor.flipShapes(editor.getSelectedShapeIds(), 'vertical')
const b = editor.selectionPageBounds
expect(a).toCloselyMatchObject(b!)
@ -221,12 +221,12 @@ it('Preserves the selection bounds.', () => {
editor.selectAll()
const a = editor.selectionPageBounds
editor.mark('flipped')
editor.flipShapes(editor.selectedShapeIds, 'horizontal')
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
const b = editor.selectionPageBounds
expect(a).toMatchObject(b!)
editor.mark('flipped')
editor.flipShapes(editor.selectedShapeIds, 'vertical')
editor.flipShapes(editor.getSelectedShapeIds(), 'vertical')
const c = editor.selectionPageBounds
expect(a).toMatchObject(c!)
@ -287,7 +287,7 @@ describe('When one shape is selected', () => {
it('Does nothing if the shape is not a group', () => {
const before = editor.getShape(ids.boxA)!
editor.select(ids.boxA)
editor.flipShapes(editor.selectedShapeIds, 'horizontal')
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
expect(editor.getShape(ids.boxA)).toMatchObject(before)
})
@ -296,10 +296,10 @@ describe('When one shape is selected', () => {
const fn = jest.fn()
editor.selectAll()
editor.groupShapes(editor.selectedShapeIds) // this will also select the new group
editor.groupShapes(editor.getSelectedShapeIds()) // this will also select the new group
const groupBefore = editor.selectedShapes[0]
editor.on('change', fn)
editor.flipShapes(editor.selectedShapeIds, 'horizontal')
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
// The change event should have been called
jest.runOnlyPendingTimers()
@ -352,7 +352,7 @@ describe('flipping rotated shapes', () => {
arrowD: createShapeId('arrowD'),
}
beforeEach(() => {
editor.selectAll().deleteShapes(editor.selectedShapeIds)
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
const props: Partial<TLArrowShapeProps> = {
start: {
type: 'point',
@ -416,7 +416,7 @@ describe('flipping rotated shapes', () => {
}
test('flipping horizontally', () => {
editor.flipShapes(editor.selectedShapeIds, 'horizontal')
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
// now arrow A should be pointing from top to left
let { start, end } = getStartAndEndPoints(ids.arrowA)
expect(start).toCloselyMatchObject(topPoint)
@ -439,7 +439,7 @@ describe('flipping rotated shapes', () => {
})
test('flipping vertically', () => {
editor.flipShapes(editor.selectedShapeIds, 'vertical')
editor.flipShapes(editor.getSelectedShapeIds(), 'vertical')
// arrows that have height 0 get nudged by a pixel when flipped vertically
// so we need to use a fairly loose tolerance
// now arrow A should be pointing from bottom to right
@ -558,18 +558,18 @@ describe('When flipping shapes that include arrows', () => {
})
it('Flips horizontally', () => {
editor.selectAll().deleteShapes(editor.selectedShapeIds).createShapes(shapes)
editor.selectAll().deleteShapes(editor.getSelectedShapeIds()).createShapes(shapes)
const boundsBefore = editor.selectionRotatedPageBounds!
editor.flipShapes(editor.selectedShapeIds, 'horizontal')
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
expect(editor.selectionRotatedPageBounds).toCloselyMatchObject(boundsBefore)
})
it('Flips vertically', () => {
editor.selectAll().deleteShapes(editor.selectedShapeIds).createShapes(shapes)
editor.selectAll().deleteShapes(editor.getSelectedShapeIds()).createShapes(shapes)
const boundsBefore = editor.selectionRotatedPageBounds!
editor.flipShapes(editor.selectedShapeIds, 'vertical')
editor.flipShapes(editor.getSelectedShapeIds(), 'vertical')
expect(editor.selectionRotatedPageBounds).toCloselyMatchObject(boundsBefore)
})
})

View file

@ -515,15 +515,15 @@ describe('frame shapes', () => {
const frameId = editor.onlySelectedShape!.id
expect(editor.selectedShapeIds[0]).toBe(frameId)
expect(editor.currentPageState.editingShapeId).toBe(null)
expect(editor.getSelectedShapeIds()[0]).toBe(frameId)
expect(editor.getCurrentPageState().editingShapeId).toBe(null)
editor.setCurrentTool('select')
editor.keyDown('Enter')
editor.keyUp('Enter')
expect(editor.currentPageState.editingShapeId).toBe(frameId)
expect(editor.getCurrentPageState().editingShapeId).toBe(frameId)
})
it('can be selected with box brushing only if the whole frame is selected', () => {
@ -536,11 +536,11 @@ describe('frame shapes', () => {
editor.pointerDown(50, 50).pointerMove(150, 150)
editor.expectPathToBe('root.select.brushing')
expect(editor.selectedShapeIds).toHaveLength(0)
expect(editor.getSelectedShapeIds()).toHaveLength(0)
editor.pointerMove(250, 250)
expect(editor.selectedShapeIds).toHaveLength(1)
expect(editor.getSelectedShapeIds()).toHaveLength(1)
expect(editor.onlySelectedShape!.id).toBe(frameId)
})
@ -555,7 +555,7 @@ describe('frame shapes', () => {
editor.pointerDown(150, 150).pointerMove(250, 250)
editor.expectPathToBe('root.select.brushing')
expect(editor.selectedShapeIds).toHaveLength(0)
expect(editor.getSelectedShapeIds()).toHaveLength(0)
})
it('children of a frame will not be selected from outside of the frame', () => {
@ -573,14 +573,14 @@ describe('frame shapes', () => {
editor.pointerDown(500, 500).pointerMove(300, 300).pointerUp(300, 300)
// Check if the inner box was selected
expect(editor.selectedShapeIds).toHaveLength(0)
expect(editor.getSelectedShapeIds()).toHaveLength(0)
// Select from outside the frame via box brushing
// but also include the frame in the selection
editor.pointerDown(400, 0).pointerMove(195, 175).pointerUp(195, 175)
// Check if the inner box was selected
expect(editor.selectedShapeIds).toHaveLength(1)
expect(editor.getSelectedShapeIds()).toHaveLength(1)
expect(editor.onlySelectedShape!.id).toBe(innerBoxId)
// Deselect everything
@ -594,7 +594,7 @@ describe('frame shapes', () => {
// Check if the inner box was selected
editor.pointerUp(300, 300)
expect(editor.selectedShapeIds).toHaveLength(0)
expect(editor.getSelectedShapeIds()).toHaveLength(0)
})
it('arrows will not bind to parts of shapes outside the frame', () => {
@ -686,7 +686,7 @@ test('arrows bound to a shape within a group within a frame are reparented if th
editor.setCurrentTool('select')
editor.select(boxBId, boxCId)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
const groupId = editor.onlySelectedShape!.id
editor.setCurrentTool('arrow')
@ -732,9 +732,9 @@ describe('When dragging a shape inside a group inside a frame', () => {
it('When dragging a shape out of a frame', () => {
editor.select(ids.box1, ids.box2)
expect(editor.selectedShapeIds).toHaveLength(2)
expect(editor.getSelectedShapeIds()).toHaveLength(2)
editor.groupShapes(editor.selectedShapeIds, ids.group1)
editor.groupShapes(editor.getSelectedShapeIds(), ids.group1)
expect(editor.getShape(ids.box1)!.parentId).toBe(ids.group1)
@ -752,9 +752,9 @@ describe('When dragging a shape inside a group inside a frame', () => {
it('reparents the shape to the page if it leaves the frame', () => {
editor.select(ids.box1, ids.box2)
expect(editor.selectedShapeIds).toHaveLength(2)
expect(editor.getSelectedShapeIds()).toHaveLength(2)
editor.groupShapes(editor.selectedShapeIds, ids.group1)
editor.groupShapes(editor.getSelectedShapeIds(), ids.group1)
expect(editor.getShape(ids.box1)!.parentId).toBe(ids.group1)

View file

@ -85,8 +85,8 @@ afterEach(() => {
const getAllShapes = () => editor.currentPageShapes
const onlySelectedId = () => {
expect(editor.selectedShapeIds).toHaveLength(1)
return editor.selectedShapeIds[0]
expect(editor.getSelectedShapeIds()).toHaveLength(1)
return editor.getSelectedShapeIds()[0]
}
const onlySelectedShape = () => {
@ -114,12 +114,12 @@ describe('creating groups', () => {
editor.select(ids.boxA, ids.boxB)
expect(getAllShapes()).toHaveLength(3)
expect(editor.selectedShapeIds.length).toBe(2)
expect(editor.getSelectedShapeIds().length).toBe(2)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
expect(getAllShapes()).toHaveLength(4)
expect(editor.selectedShapeIds.length).toBe(1)
expect(editor.getSelectedShapeIds().length).toBe(1)
expect(editor.getShape(ids.boxA)).toBeTruthy()
expect(editor.getShape(ids.boxB)).toBeTruthy()
@ -142,10 +142,10 @@ describe('creating groups', () => {
// └───┘ └───┘ └───┘
editor.createShapes([box(ids.boxA, 0, 0), box(ids.boxB, 20, 0), box(ids.boxC, 40, 0)])
expect(getAllShapes()).toHaveLength(3)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
expect(getAllShapes()).toHaveLength(3)
editor.select(ids.boxA)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
expect(getAllShapes()).toHaveLength(3)
expect(onlySelectedId()).toBe(ids.boxA)
})
@ -181,7 +181,7 @@ describe('creating groups', () => {
}
editor.select(ids.boxA, ids.boxB, ids.boxC)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
try {
expect({
@ -213,17 +213,17 @@ describe('creating groups', () => {
])
editor.select(ids.boxA, ids.boxB)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
const groupAId = onlySelectedId()
editor.select(ids.boxC, ids.boxD)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
const groupBId = onlySelectedId()
editor.select(groupAId, groupBId)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
const uberGroup = onlySelectedShape()
expect(uberGroup.type).toBe(GroupShapeUtil.type)
@ -258,14 +258,14 @@ describe('creating groups', () => {
])
editor.select(ids.boxA, ids.boxB, ids.boxC)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
const groupA = onlySelectedShape()
editor.select(ids.boxD, ids.boxE, ids.boxF)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
const groupB = onlySelectedShape()
editor.select(ids.boxB, ids.boxE)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
const groupC = onlySelectedShape()
expect(children(groupA).size).toBe(2)
@ -294,9 +294,9 @@ describe('creating groups', () => {
editor.updateInstanceState({ isReadonly: true })
editor.setCurrentTool('hand')
editor.selectAll()
expect(editor.selectedShapeIds.length).toBe(3)
editor.groupShapes(editor.selectedShapeIds)
expect(editor.selectedShapeIds.length).toBe(3)
expect(editor.getSelectedShapeIds().length).toBe(3)
editor.groupShapes(editor.getSelectedShapeIds())
expect(editor.getSelectedShapeIds().length).toBe(3)
})
it('keeps order correct simple', () => {
// 0 10 20 30 40 50 60 70
@ -311,7 +311,7 @@ describe('creating groups', () => {
])
editor.select(ids.boxC, ids.boxB)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
const groupAId = onlySelectedId()
const sortedGroupChildrenIds = editor
@ -344,7 +344,7 @@ describe('creating groups', () => {
])
editor.select(ids.boxC, ids.boxA)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
const groupAId = onlySelectedId()
@ -375,14 +375,14 @@ describe('ungrouping shapes', () => {
editor.createShapes([box(ids.boxA, 0, 0), box(ids.boxB, 20, 0), box(ids.boxC, 40, 0)])
editor.select(ids.boxA, ids.boxB)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
const groupA = onlySelectedShape()
editor.ungroupShapes(editor.selectedShapeIds)
editor.ungroupShapes(editor.getSelectedShapeIds())
expect(isRemoved(groupA)).toBe(true)
expect(new Set(editor.selectedShapeIds)).toEqual(new Set([ids.boxA, ids.boxB]))
expect(new Set(editor.getSelectedShapeIds())).toEqual(new Set([ids.boxA, ids.boxB]))
expect(editor.getShapePageBounds(ids.boxA)!).toCloselyMatchObject({
x: 0,
@ -401,14 +401,16 @@ describe('ungrouping shapes', () => {
it('selects the groups children and other non-group shapes on ungroup', () => {
editor.createShapes([box(ids.boxA, 0, 0), box(ids.boxB, 20, 0), box(ids.boxC, 40, 0)])
editor.select(ids.boxA, ids.boxB)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
const groupA = onlySelectedShape()
editor.select(groupA.id, ids.boxC)
editor.ungroupShapes(editor.selectedShapeIds)
editor.ungroupShapes(editor.getSelectedShapeIds())
expect(new Set(editor.selectedShapeIds)).toMatchObject(new Set([ids.boxA, ids.boxB, ids.boxC]))
expect(new Set(editor.getSelectedShapeIds())).toMatchObject(
new Set([ids.boxA, ids.boxB, ids.boxC])
)
})
it('preserves the page positions and rotations of the ungrouped shapes', () => {
for (let i = 0; i < 100; i++) {
@ -442,9 +444,9 @@ describe('ungrouping shapes', () => {
}
editor.select(ids.boxA, ids.boxB, ids.boxC)
editor.groupShapes(editor.selectedShapeIds)
editor.ungroupShapes(editor.selectedShapeIds)
expect(editor.selectedShapeIds.length).toBe(3)
editor.groupShapes(editor.getSelectedShapeIds())
editor.ungroupShapes(editor.getSelectedShapeIds())
expect(editor.getSelectedShapeIds().length).toBe(3)
try {
expect({
@ -476,20 +478,20 @@ describe('ungrouping shapes', () => {
])
editor.select(ids.boxA, ids.boxB)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
const groupAId = onlySelectedId()
editor.select(ids.boxC, ids.boxD)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
const groupBId = onlySelectedId()
editor.select(groupAId, groupBId)
editor.groupShapes(editor.selectedShapeIds)
expect(editor.selectedShapeIds.length).toBe(1)
editor.ungroupShapes(editor.selectedShapeIds)
expect(editor.selectedShapeIds.length).toBe(2)
editor.groupShapes(editor.getSelectedShapeIds())
expect(editor.getSelectedShapeIds().length).toBe(1)
editor.ungroupShapes(editor.getSelectedShapeIds())
expect(editor.getSelectedShapeIds().length).toBe(2)
expect(editor.getShape(groupAId)).not.toBe(undefined)
expect(editor.getShape(groupBId)).not.toBe(undefined)
})
@ -500,14 +502,14 @@ describe('ungrouping shapes', () => {
// └───┘ └───┘ └───┘
editor.createShapes([box(ids.boxA, 0, 0), box(ids.boxB, 20, 0), box(ids.boxC, 40, 0)])
editor.selectAll()
expect(editor.selectedShapeIds.length).toBe(3)
editor.groupShapes(editor.selectedShapeIds)
expect(editor.selectedShapeIds.length).toBe(1)
expect(editor.getSelectedShapeIds().length).toBe(3)
editor.groupShapes(editor.getSelectedShapeIds())
expect(editor.getSelectedShapeIds().length).toBe(1)
editor.updateInstanceState({ isReadonly: true })
editor.setCurrentTool('hand')
editor.ungroupShapes(editor.selectedShapeIds)
expect(editor.selectedShapeIds.length).toBe(1)
editor.ungroupShapes(editor.getSelectedShapeIds())
expect(editor.getSelectedShapeIds().length).toBe(1)
expect(onlySelectedShape().type).toBe(GroupShapeUtil.type)
})
it('keeps order correct simple', () => {
@ -523,8 +525,8 @@ describe('ungrouping shapes', () => {
])
editor.select(ids.boxC, ids.boxB)
editor.groupShapes(editor.selectedShapeIds)
editor.ungroupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
editor.ungroupShapes(editor.getSelectedShapeIds())
const sortedShapesOnCurrentPage = editor.currentPageShapes
.sort(sortByIndex)
@ -548,8 +550,8 @@ describe('ungrouping shapes', () => {
])
editor.select(ids.boxC, ids.boxA)
editor.groupShapes(editor.selectedShapeIds)
editor.ungroupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
editor.ungroupShapes(editor.getSelectedShapeIds())
const sortedShapesOnCurrentPage = editor.currentPageShapes
.sort(sortByIndex)
@ -580,7 +582,7 @@ describe('the bounds of a group', () => {
])
editor.select(ids.boxA, ids.boxB)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
const group = onlySelectedShape()
expect(editor.getShapePageBounds(group.id)!.minX).toBe(0)
@ -605,7 +607,7 @@ describe('the bounds of a group', () => {
editor.createShapes([box(ids.boxA, 0, 0), box(ids.boxB, 20, 0), box(ids.boxC, 40, 0)])
editor.select(ids.boxA, ids.boxB, ids.boxC)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
const group = onlySelectedShape()
expect(editor.getShapePageBounds(group.id)!).toCloselyMatchObject({
@ -641,7 +643,7 @@ describe('the bounds of a group', () => {
editor.createShapes([box(ids.boxA, 0, 0), box(ids.boxB, 20, 0), box(ids.boxC, 40, 0)])
editor.select(ids.boxA, ids.boxB, ids.boxC)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
const group = onlySelectedShape()
expect(editor.getShapePageBounds(group.id)!).toCloselyMatchObject({
@ -688,7 +690,7 @@ describe('the bounds of a rotated group', () => {
])
editor.select(ids.boxA, ids.boxB)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
const group = onlySelectedShape()
editor.rotateSelection(Math.PI / 2)
@ -721,7 +723,7 @@ describe('the bounds of a rotated group', () => {
editor.createShapes([box(ids.boxA, 0, 0), box(ids.boxB, 20, 0), box(ids.boxC, 40, 0)])
editor.select(ids.boxA, ids.boxB, ids.boxC)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
const group = onlySelectedShape()
editor.updateShapes([{ id: group.id, type: 'group', rotation: Math.PI / 2, x: 10, y: 0 }])
@ -761,7 +763,7 @@ describe('the bounds of a rotated group', () => {
expect(editor.getShapeGeometry(ids.boxA)!.bounds).toMatchObject({ x: 0, y: 0, w: 10, h: 10 })
editor.select(ids.boxA, ids.boxB, ids.boxC)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
const group = onlySelectedShape()
editor.updateShapes([{ id: group.id, type: 'group', rotation: Math.PI / 2, x: 10, y: 0 }])
@ -812,13 +814,13 @@ describe('focus layers', () => {
box(ids.boxD, 60, 0),
])
editor.select(ids.boxA, ids.boxB)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
groupAId = onlySelectedId()
editor.select(ids.boxC, ids.boxD)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
groupBId = onlySelectedId()
editor.select(groupAId, groupBId)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
groupCId = onlySelectedId()
editor.selectNone()
})
@ -839,11 +841,11 @@ describe('focus layers', () => {
expect(editor.focusedGroupId).toBe(editor.currentPageId)
editor.select(ids.boxA)
expect(editor.focusedGroupId).toBe(groupAId)
editor.setSelectedShapes([...editor.selectedShapeIds, ids.boxC])
editor.setSelectedShapes([...editor.getSelectedShapeIds(), ids.boxC])
expect(editor.focusedGroupId).toBe(groupCId)
editor.deselect(ids.boxA)
expect(editor.focusedGroupId).toBe(groupBId)
editor.setSelectedShapes([...editor.selectedShapeIds, ids.boxB])
editor.setSelectedShapes([...editor.getSelectedShapeIds(), ids.boxB])
expect(editor.focusedGroupId).toBe(groupCId)
})
it('should not adjust the focus layer when clearing the selection', () => {
@ -960,14 +962,14 @@ describe('the select tool', () => {
editor
.pointerDown(60, 0, ids.boxC, { shiftKey: true })
.pointerUp(0, 0, ids.boxC, { shiftKey: true })
expect(editor.selectedShapeIds.includes(ids.boxA)).toBe(true)
expect(editor.selectedShapeIds.includes(groupBId)).toBe(true)
expect(editor.getSelectedShapeIds().includes(ids.boxA)).toBe(true)
expect(editor.getSelectedShapeIds().includes(groupBId)).toBe(true)
expect(editor.focusedGroupId).toBe(groupCId)
editor.pointerDown(60, 0, ids.boxC, { shiftKey: true }).pointerUp()
expect(editor.selectedShapeIds.includes(ids.boxA)).toBe(true)
expect(editor.selectedShapeIds.includes(groupBId)).toBe(false)
expect(editor.selectedShapeIds.includes(ids.boxC)).toBe(true)
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)
})
@ -978,7 +980,7 @@ describe('the select tool', () => {
// 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.selectedShapeIds).toHaveLength(0)
expect(editor.getSelectedShapeIds()).toHaveLength(0)
editor.select(ids.boxA)
expect(editor.focusedGroupId).toBe(groupAId)
@ -986,7 +988,7 @@ describe('the select tool', () => {
// click the empty canvas
editor.pointerDown(-235, 50, { target: 'canvas' }).pointerUp(-235, 50)
expect(editor.focusedGroupId).toBe(editor.currentPageId)
expect(editor.selectedShapeIds).toHaveLength(0)
expect(editor.getSelectedShapeIds()).toHaveLength(0)
})
// ! Removed with hollow shape clicking feature
@ -1013,18 +1015,18 @@ describe('the select tool', () => {
it('should pop the focus layer when escape is pressed in idle state', () => {
editor.select(ids.boxA)
expect(editor.selectedShapeIds).toMatchObject([ids.boxA]) // box1
expect(editor.getSelectedShapeIds()).toMatchObject([ids.boxA]) // box1
expect(editor.focusedGroupId).toBe(groupAId)
// deselct
editor.cancel()
expect(editor.selectedShapeIds).toMatchObject([groupAId]) // groupA
expect(editor.getSelectedShapeIds()).toMatchObject([groupAId]) // groupA
expect(editor.focusedGroupId).toBe(groupCId)
// pop focus layer
editor.cancel()
expect(editor.selectedShapeIds.length).toBe(1) // Group C
expect(editor.getSelectedShapeIds().length).toBe(1) // Group C
expect(editor.focusedGroupId).toBe(editor.currentPageId)
editor.cancel()
expect(editor.selectedShapeIds.length).toBe(0)
expect(editor.getSelectedShapeIds().length).toBe(0)
expect(editor.focusedGroupId).toBe(editor.currentPageId)
})
@ -1047,8 +1049,8 @@ describe('the select tool', () => {
editor.pointerDown(-305, -5, { target: 'canvas' }).pointerMove(35, 9, ids.boxB)
expect(editor.root.path.get()).toBe(`root.select.brushing`)
expect(editor.selectedShapeIds.includes(ids.boxA)).toBe(true)
expect(editor.selectedShapeIds.includes(ids.boxB)).toBe(true)
expect(editor.getSelectedShapeIds().includes(ids.boxA)).toBe(true)
expect(editor.getSelectedShapeIds().includes(ids.boxB)).toBe(true)
// this one didn't make sense as written—the forced event on canvas won't work now
// that we're doing hit testing manually—we'll catch that it was inside a shape
@ -1076,7 +1078,7 @@ describe('the select tool', () => {
// ▲
// │ mouse selection
editor.pointerDown(12.5, -15, undefined).pointerMove(17.5, 15, ids.boxB)
expect(editor.selectedShapeIds.length).toBe(0)
expect(editor.getSelectedShapeIds().length).toBe(0)
editor.pointerMove(35, 15)
expect(onlySelectedId()).toBe(groupCId)
})
@ -1104,13 +1106,13 @@ describe("when a group's children are deleted", () => {
box(ids.boxD, 60, 0),
])
editor.select(ids.boxA, ids.boxB)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
groupAId = onlySelectedId()
editor.select(ids.boxC, ids.boxD)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
groupBId = onlySelectedId()
editor.select(groupAId, groupBId)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
groupCId = onlySelectedId()
editor.selectNone()
})
@ -1148,7 +1150,7 @@ describe('creating new shapes', () => {
// └──────────────────────────────┘
editor.createShapes([box(ids.boxA, 0, 0), box(ids.boxB, 90, 90)])
editor.select(ids.boxA, ids.boxB)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
groupA = onlySelectedShape() as TLGroupShape
editor.selectNone()
})
@ -1478,13 +1480,13 @@ describe('erasing', () => {
box(ids.boxE, 0, 20),
])
editor.select(ids.boxA, ids.boxB)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
groupAId = onlySelectedId()
editor.select(ids.boxC, ids.boxD)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
groupBId = onlySelectedId()
editor.select(groupAId, groupBId)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
groupCId = onlySelectedId()
editor.selectNone()
})
@ -1494,8 +1496,8 @@ describe('erasing', () => {
// erase D
editor.pointerDown(65, 5, ids.boxD)
expect(editor.currentPageState.erasingShapeIds.length).toBe(1)
expect(editor.currentPageState.erasingShapeIds[0]).toBe(groupCId)
expect(editor.getCurrentPageState().erasingShapeIds.length).toBe(1)
expect(editor.getCurrentPageState().erasingShapeIds[0]).toBe(groupCId)
editor.pointerUp()
expect(editor.getShape(groupCId)).toBeFalsy()
})
@ -1515,8 +1517,8 @@ describe('erasing', () => {
// erase B
editor.pointerDown(25, 5, ids.boxB)
expect(editor.currentPageState.erasingShapeIds.length).toBe(1)
expect(editor.currentPageState.erasingShapeIds[0]).toBe(ids.boxB)
expect(editor.getCurrentPageState().erasingShapeIds.length).toBe(1)
expect(editor.getCurrentPageState().erasingShapeIds[0]).toBe(ids.boxB)
editor.pointerUp()
// group A disappears
@ -1531,8 +1533,8 @@ describe('erasing', () => {
// erase E
editor.pointerDown(5, 25, ids.boxE)
expect(editor.currentPageState.erasingShapeIds.length).toBe(1)
expect(editor.currentPageState.erasingShapeIds[0]).toBe(ids.boxE)
expect(editor.getCurrentPageState().erasingShapeIds.length).toBe(1)
expect(editor.getCurrentPageState().erasingShapeIds[0]).toBe(ids.boxE)
// move to group B
editor.pointerMove(65, 5)
@ -1545,7 +1547,7 @@ describe('binding bug', () => {
beforeEach(() => {
editor.createShapes([box(ids.boxA, 0, 0, 10, 10), box(ids.boxB, 50, 0, 10, 10)])
editor.select(ids.boxA, ids.boxB)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
editor.selectNone()
})
@ -1585,13 +1587,13 @@ describe('bindings', () => {
box(ids.boxE, 0, 20),
])
editor.select(ids.boxA, ids.boxB)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
groupAId = onlySelectedId()
editor.select(ids.boxC, ids.boxD)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
groupBId = onlySelectedId()
editor.select(groupAId, groupBId)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
editor.selectNone()
})
@ -1670,7 +1672,7 @@ describe('grouping arrows', () => {
expect(arrowBBefore.index).toBe('a2')
editor.select(arrowAId, arrowBId)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
const arrowAAfter = editor.getShape(arrowAId)!
const arrowBAfter = editor.getShape(arrowBId)!
@ -1702,7 +1704,7 @@ describe('moving handles within a group', () => {
// └──────────────────────────────┘
editor.createShapes([box(ids.boxA, 0, 0), box(ids.boxB, 90, 90)])
editor.select(ids.boxA, ids.boxB)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
groupA = onlySelectedShape() as TLGroupShape
editor.selectNone()
})
@ -1903,13 +1905,13 @@ describe('snapping', () => {
box(ids.boxE, 0, 20),
])
editor.select(ids.boxA, ids.boxB)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
groupAId = onlySelectedId()
editor.select(ids.boxC, ids.boxD)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
groupBId = onlySelectedId()
editor.select(groupAId, groupBId)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
groupCId = onlySelectedId()
editor.selectNone()
})
@ -1933,22 +1935,22 @@ describe('When pressing enter with selected group', () => {
it('Should select the children of the group when enter is pressed', () => {
editor.createShapes([box(ids.boxA, 0, 0), box(ids.boxB, 20, 0), box(ids.boxC, 40, 0)])
editor.select(ids.boxA, ids.boxB, ids.boxC)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
editor.keyDown('Enter')
editor.keyUp('Enter')
expect(editor.selectedShapeIds).toMatchObject([ids.boxA, ids.boxB, ids.boxC])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.boxA, ids.boxB, ids.boxC])
})
it('Should select the children of multiple groups when enter is pressed', () => {
editor.createShapes([box(ids.boxA, 0, 0), box(ids.boxB, 20, 0)])
editor.createShapes([box(ids.boxC, 40, 0), box(ids.boxD, 70, 0)])
editor.select(ids.boxA, ids.boxB)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
editor.select(ids.boxC, ids.boxD)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
editor.selectAll() // both groups
editor.keyDown('Enter')
editor.keyUp('Enter')
expect(editor.selectedShapeIds).toMatchObject([ids.boxA, ids.boxB, ids.boxC, ids.boxD])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.boxA, ids.boxB, ids.boxC, ids.boxD])
})
})
@ -1958,7 +1960,7 @@ describe('Group opacity', () => {
editor.select(ids.boxA, ids.boxB)
editor.setOpacityForSelectedShapes(0.5)
editor.setOpacityForNextShapes(0.5)
editor.groupShapes(editor.selectedShapeIds)
editor.groupShapes(editor.getSelectedShapeIds())
const group = editor.getShape(onlySelectedId())!
assert(editor.isShapeOfType<TLGroupShape>(group, 'group'))
expect(group.opacity).toBe(1)
@ -1988,7 +1990,7 @@ describe('Grouping / ungrouping locked shapes', () => {
expect(editor.getShape(ids.boxB)).toBeTruthy()
// Both be selected
expect(editor.selectedShapeIds).toMatchObject([ids.boxA, ids.boxB])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.boxA, ids.boxB])
// And be in the correct position
expect(editor.getShape(ids.boxA)!.x).toBe(100)

View file

@ -363,7 +363,7 @@ it('pastes shapes with children', () => {
describe('When pasting into frames...', () => {
it('Does not paste into a clipped frame', () => {
// clear the page
editor.selectAll().deleteShapes(editor.selectedShapeIds)
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
editor
// move the two frames far from all other shapes
@ -416,7 +416,7 @@ describe('When pasting into frames...', () => {
])
// Make sure that frame 1 is brought to front
.select(ids.frame1)
.bringToFront(editor.selectedShapeIds)
.bringToFront(editor.getSelectedShapeIds())
editor.setCamera({ x: -2000, y: -2000, z: 1 })
editor.updateRenderingBounds()
@ -436,7 +436,7 @@ describe('When pasting into frames...', () => {
it('keeps things in the right place', () => {
// clear the page
editor.selectAll().deleteShapes(editor.selectedShapeIds)
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
// create a small box and copy it
editor.createShapes([
{
@ -452,7 +452,7 @@ describe('When pasting into frames...', () => {
])
editor.selectAll().copy()
// now delete it
editor.deleteShapes(editor.selectedShapeIds)
editor.deleteShapes(editor.getSelectedShapeIds())
// create a big frame away from the origin, the size of the viewport
editor

View file

@ -3570,13 +3570,13 @@ describe('nodes that have do not resize', () => {
editor.select(ids.boxA, noteBId, noteCId)
editor.flipShapes(editor.selectedShapeIds, 'horizontal')
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
expect(editor.getShapePageBounds(ids.boxA)).toMatchObject({ x: 300, y: 0, w: 200, h: 200 })
expect(editor.getShapePageBounds(noteBId)).toMatchObject({ x: 0, y: 0, w: 200, h: 200 })
expect(editor.getShapePageBounds(noteCId)).toMatchObject({ x: 300, y: 300, w: 200, h: 200 })
editor.flipShapes(editor.selectedShapeIds, 'vertical')
editor.flipShapes(editor.getSelectedShapeIds(), 'vertical')
expect(editor.getShapePageBounds(ids.boxA)).toMatchObject({
x: 300,

View file

@ -22,7 +22,7 @@ describe(SelectTool, () => {
editor.expectPathToBe('root.select.idle')
editor.doubleClick(50, 50, shapeId)
expect(editor.currentPageState.editingShapeId).toBe(shapeId)
expect(editor.getCurrentPageState().editingShapeId).toBe(shapeId)
// note: this behavior has moved to the React hook useEditableText.
// clicking on the input will preserve selection, however you can
@ -36,7 +36,7 @@ describe(SelectTool, () => {
jest.advanceTimersByTime(1000)
editor.pointerDown(150, 150).pointerUp()
expect(editor.currentPageState.editingShapeId).toBe(null)
expect(editor.getCurrentPageState().editingShapeId).toBe(null)
expect(editor.root.path.get()).toEqual('root.select.idle')
})
})
@ -48,18 +48,18 @@ describe(SelectTool, () => {
editor.setCurrentTool('select')
editor.doubleClick(50, 50, shapeId)
expect(editor.currentPageState.editingShapeId).toBe(shapeId)
expect(editor.getCurrentPageState().editingShapeId).toBe(shapeId)
// clicking outside the shape should end editing
jest.advanceTimersByTime(1000)
editor.pointerDown(150, 150).pointerUp()
expect(editor.currentPageState.editingShapeId).toBe(null)
expect(editor.getCurrentPageState().editingShapeId).toBe(null)
expect(editor.root.path.get()).toEqual('root.select.idle')
editor.undo()
expect(editor.currentPageState.editingShapeId).toBe(null)
expect(editor.getCurrentPageState().editingShapeId).toBe(null)
})
})
@ -74,9 +74,9 @@ describe('When pointing a shape behind the current selection', () => {
editor.select(ids.A, ids.C)
// don't select it yet! It's behind the current selection
editor.pointerDown(75, 75)
expect(editor.selectedShapeIds).toMatchObject([ids.A, ids.C])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.A, ids.C])
editor.pointerUp(75, 75)
expect(editor.selectedShapeIds).toMatchObject([ids.B])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.B])
})
it('Selects on shift+pointer up', () => {
@ -91,20 +91,20 @@ describe('When pointing a shape behind the current selection', () => {
// don't select B yet! It's behind the current selection
editor.pointerDown(75, 75, { target: 'canvas' }, { shiftKey: true })
editor.expectToBeIn('select.pointing_selection')
expect(editor.selectedShapeIds).toMatchObject([ids.A, ids.C])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.A, ids.C])
editor.pointerUp(75, 75, { target: 'canvas' }, { shiftKey: true })
editor.expectToBeIn('select.idle')
expect(editor.selectedShapeIds).toMatchObject([ids.A, ids.C, ids.B])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.A, ids.C, ids.B])
// and deselect
editor.pointerDown(75, 75, { target: 'canvas' }, { shiftKey: true })
editor.expectToBeIn('select.pointing_shape')
expect(editor.selectedShapeIds).toMatchObject([ids.A, ids.C, ids.B])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.A, ids.C, ids.B])
editor.pointerUp(75, 75, { target: 'canvas' }, { shiftKey: true })
editor.expectToBeIn('select.idle')
expect(editor.selectedShapeIds).toMatchObject([ids.A, ids.C])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.A, ids.C])
})
it('Moves on pointer move, does not select on pointer up', () => {
@ -119,9 +119,9 @@ describe('When pointing a shape behind the current selection', () => {
editor.pointerMove(150, 150)
editor.pointerMove(151, 151)
editor.pointerMove(100, 100)
expect(editor.selectedShapeIds).toMatchObject([ids.A, ids.C])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.A, ids.C])
editor.pointerUp(100, 100, ids.B)
expect(editor.selectedShapeIds).toMatchObject([ids.A, ids.C]) // no change! we've moved
expect(editor.getSelectedShapeIds()).toMatchObject([ids.A, ids.C]) // no change! we've moved
})
})
@ -129,7 +129,7 @@ describe('When brushing arrows', () => {
it('Brushes a straight arrow', () => {
const ids = editor
.selectAll()
.deleteShapes(editor.selectedShapeIds)
.deleteShapes(editor.getSelectedShapeIds())
.setCamera({ x: 0, y: 0, z: 1 })
.createShapesFromJsx([
<TL.arrow
@ -145,13 +145,13 @@ describe('When brushing arrows', () => {
editor.pointerDown(0, 45)
editor.pointerMove(100, 55)
editor.expectPathToBe('root.select.brushing')
expect(editor.selectedShapeIds).toStrictEqual([ids.arrow1])
expect(editor.getSelectedShapeIds()).toStrictEqual([ids.arrow1])
})
it('Brushes within the curve of a curved arrow without selecting the arrow', () => {
editor
.selectAll()
.deleteShapes(editor.selectedShapeIds)
.deleteShapes(editor.getSelectedShapeIds())
.setCamera({ x: 0, y: 0, z: 1 })
.createShapesFromJsx([
<TL.arrow
@ -167,6 +167,6 @@ describe('When brushing arrows', () => {
editor.pointerDown(55, 45)
editor.pointerMove(45, 55)
editor.expectPathToBe('root.select.brushing')
expect(editor.selectedShapeIds).toStrictEqual([])
expect(editor.getSelectedShapeIds()).toStrictEqual([])
})
})

File diff suppressed because it is too large Load diff

View file

@ -66,7 +66,7 @@ describe('When interacting with a shape...', () => {
util.onRotateEnd = fnEnd
editor.selectAll()
expect(editor.selectedShapeIds).toMatchObject([ids.frame1, ids.box1])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.frame1, ids.box1])
editor
.pointerDown(300, 300, {
@ -115,7 +115,7 @@ describe('When interacting with a shape...', () => {
util.onResizeEnd = fnEnd
editor.selectAll()
expect(editor.selectedShapeIds).toMatchObject([ids.frame1, ids.box1])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.frame1, ids.box1])
editor.pointerDown(300, 300, {
target: 'selection',
@ -152,7 +152,7 @@ describe('When interacting with a shape...', () => {
util.onTranslateEnd = fnEnd
editor.selectAll()
expect(editor.selectedShapeIds).toMatchObject([ids.frame1, ids.box1])
expect(editor.getSelectedShapeIds()).toMatchObject([ids.frame1, ids.box1])
// Translate the shapes...
editor.pointerDown(50, 50, ids.box1).pointerMove(50, 40).pointerUp(50, 40)
@ -178,7 +178,7 @@ describe('When interacting with a shape...', () => {
// If a shape has an onClick handler, and if the handler returns nothing,
// then normal selection rules should apply.
expect(editor.selectedShapeIds.length).toBe(1)
expect(editor.getSelectedShapeIds().length).toBe(1)
})
it('Uses the shape utils onClick handler', () => {
@ -199,6 +199,6 @@ describe('When interacting with a shape...', () => {
// If a shape has an onClick handler, and it returns something, then
// it should not be selected.
expect(editor.selectedShapeIds.length).toBe(0)
expect(editor.getSelectedShapeIds().length).toBe(0)
})
})

View file

@ -209,8 +209,8 @@ describe('When cloning...', () => {
// Start cloning!
editor.keyDown('Alt')
expect(editor.currentPageShapeIds.size).toBe(5) // Two new shapes!
const newShapeA = editor.getShape(editor.selectedShapeIds[0])!
const newShapeB = editor.getShape(editor.selectedShapeIds[1])!
const newShapeA = editor.getShape(editor.getSelectedShapeIds()[0])!
const newShapeB = editor.getShape(editor.getSelectedShapeIds()[1])!
expect(newShapeA).toBeDefined()
expect(newShapeB).toBeDefined()
@ -246,7 +246,7 @@ describe('When cloning...', () => {
editor.keyDown('Alt', { altKey: true })
expect(editor.currentPageShapeIds.size).toBe(5) // Creates a clone of B and C (its descendant)
const newShapeA = editor.getShape(editor.selectedShapeIds[0])!
const newShapeA = editor.getShape(editor.getSelectedShapeIds()[0])!
const newShapeB = editor.getShape(editor.getSortedChildIdsForParent(newShapeA.id)[0])!
expect(newShapeA).toBeDefined()
@ -1571,7 +1571,7 @@ describe('translating a shape with a bound shape', () => {
// | └───┘ |
// └───────────────────┘
expect(editor.getShape(editor.selectedShapeIds[0])?.type).toBe('arrow')
expect(editor.getShape(editor.getSelectedShapeIds()[0])?.type).toBe('arrow')
editor.pointerDown(50, 50, ids.box1).pointerMove(84, 110, { ctrlKey: true })