parent
ae5c60ab36
commit
2ca2f81f2a
86 changed files with 930 additions and 743 deletions
|
@ -88,7 +88,7 @@ const InsideOfEditorContext = () => {
|
||||||
let i = 0
|
let i = 0
|
||||||
|
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
const selection = [...editor.selectedShapeIds]
|
const selection = [...editor.getSelectedShapeIds()]
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.setStyleForSelectedShapes(DefaultColorStyle, i % 2 ? 'blue' : 'light-blue')
|
editor.setStyleForSelectedShapes(DefaultColorStyle, i % 2 ? 'blue' : 'light-blue')
|
||||||
editor.setStyleForNextShapes(DefaultColorStyle, i % 2 ? 'blue' : 'light-blue')
|
editor.setStyleForNextShapes(DefaultColorStyle, i % 2 ? 'blue' : 'light-blue')
|
||||||
|
|
|
@ -22,7 +22,7 @@ const CustomUi = track(() => {
|
||||||
switch (e.key) {
|
switch (e.key) {
|
||||||
case 'Delete':
|
case 'Delete':
|
||||||
case 'Backspace': {
|
case 'Backspace': {
|
||||||
editor.deleteShapes(editor.selectedShapeIds)
|
editor.deleteShapes(editor.getSelectedShapeIds())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'v': {
|
case 'v': {
|
||||||
|
|
|
@ -52,9 +52,9 @@ class IdleState extends StateNode {
|
||||||
}
|
}
|
||||||
case 'shape': {
|
case 'shape': {
|
||||||
if (editor.inputs.shiftKey) {
|
if (editor.inputs.shiftKey) {
|
||||||
editor.select(...editor.selectedShapeIds, info.shape.id)
|
editor.select(...editor.getSelectedShapeIds(), info.shape.id)
|
||||||
} else {
|
} else {
|
||||||
if (!editor.selectedShapeIds.includes(info.shape.id)) {
|
if (!editor.getSelectedShapeIds().includes(info.shape.id)) {
|
||||||
editor.select(info.shape.id)
|
editor.select(info.shape.id)
|
||||||
}
|
}
|
||||||
this.parent.transition('pointing', info)
|
this.parent.transition('pointing', info)
|
||||||
|
|
|
@ -18,7 +18,7 @@ export default function OnlyEditorExample() {
|
||||||
onMount={(editor: Editor) => {
|
onMount={(editor: Editor) => {
|
||||||
editor
|
editor
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.deleteShapes(editor.selectedShapeIds)
|
.deleteShapes(editor.getSelectedShapeIds())
|
||||||
.createShapes([
|
.createShapes([
|
||||||
{
|
{
|
||||||
id: createShapeId(),
|
id: createShapeId(),
|
||||||
|
|
|
@ -618,6 +618,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
get currentPageShapeIds(): Set<TLShapeId>;
|
get currentPageShapeIds(): Set<TLShapeId>;
|
||||||
get currentPageShapes(): TLShape[];
|
get currentPageShapes(): TLShape[];
|
||||||
get currentPageShapesSorted(): TLShape[];
|
get currentPageShapesSorted(): TLShape[];
|
||||||
|
// @deprecated (undocumented)
|
||||||
get currentPageState(): TLInstancePageState;
|
get currentPageState(): TLInstancePageState;
|
||||||
// @deprecated (undocumented)
|
// @deprecated (undocumented)
|
||||||
get currentTool(): StateNode | undefined;
|
get currentTool(): StateNode | undefined;
|
||||||
|
@ -679,6 +680,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
getCanUndo(): boolean;
|
getCanUndo(): boolean;
|
||||||
getContainer: () => HTMLElement;
|
getContainer: () => HTMLElement;
|
||||||
getContentFromCurrentPage(shapes: TLShape[] | TLShapeId[]): TLContent | undefined;
|
getContentFromCurrentPage(shapes: TLShape[] | TLShapeId[]): TLContent | undefined;
|
||||||
|
getCurrentPageState(): TLInstancePageState;
|
||||||
getCurrentTool(): StateNode | undefined;
|
getCurrentTool(): StateNode | undefined;
|
||||||
getCurrentToolId(): string;
|
getCurrentToolId(): string;
|
||||||
getDocumentSettings(): TLDocument;
|
getDocumentSettings(): TLDocument;
|
||||||
|
@ -686,13 +688,16 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
getHighestIndexForParent(parent: TLPage | TLParentId | TLShape): string;
|
getHighestIndexForParent(parent: TLPage | TLParentId | TLShape): string;
|
||||||
getInitialMetaForShape(_shape: TLShape): JsonObject;
|
getInitialMetaForShape(_shape: TLShape): JsonObject;
|
||||||
getInstanceState(): TLInstance;
|
getInstanceState(): TLInstance;
|
||||||
|
getIsMenuOpen(): boolean;
|
||||||
getOpenMenus(): string[];
|
getOpenMenus(): string[];
|
||||||
getOutermostSelectableShape(shape: TLShape | TLShapeId, filter?: (shape: TLShape) => boolean): TLShape;
|
getOutermostSelectableShape(shape: TLShape | TLShapeId, filter?: (shape: TLShape) => boolean): TLShape;
|
||||||
getPage(page: TLPage | TLPageId): TLPage | undefined;
|
getPage(page: TLPage | TLPageId): TLPage | undefined;
|
||||||
getPageShapeIds(page: TLPage | TLPageId): Set<TLShapeId>;
|
getPageShapeIds(page: TLPage | TLPageId): Set<TLShapeId>;
|
||||||
|
getPageStates(): TLInstancePageState[];
|
||||||
getPointInParentSpace(shape: TLShape | TLShapeId, point: VecLike): Vec2d;
|
getPointInParentSpace(shape: TLShape | TLShapeId, point: VecLike): Vec2d;
|
||||||
getPointInShapeSpace(shape: TLShape | TLShapeId, point: VecLike): Vec2d;
|
getPointInShapeSpace(shape: TLShape | TLShapeId, point: VecLike): Vec2d;
|
||||||
getSelectedShapeAtPoint(point: VecLike): TLShape | undefined;
|
getSelectedShapeAtPoint(point: VecLike): TLShape | undefined;
|
||||||
|
getSelectedShapeIds(): TLShapeId[];
|
||||||
getShape<T extends TLShape = TLShape>(shape: TLParentId | TLShape): T | undefined;
|
getShape<T extends TLShape = TLShape>(shape: TLParentId | TLShape): T | undefined;
|
||||||
getShapeAncestors(shape: TLShape | TLShapeId, acc?: TLShape[]): TLShape[];
|
getShapeAncestors(shape: TLShape | TLShapeId, acc?: TLShape[]): TLShape[];
|
||||||
getShapeAndDescendantIds(ids: TLShapeId[]): Set<TLShapeId>;
|
getShapeAndDescendantIds(ids: TLShapeId[]): Set<TLShapeId>;
|
||||||
|
@ -770,6 +775,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
isAncestorSelected(shape: TLShape | TLShapeId): boolean;
|
isAncestorSelected(shape: TLShape | TLShapeId): boolean;
|
||||||
isIn(path: string): boolean;
|
isIn(path: string): boolean;
|
||||||
isInAny(...paths: string[]): boolean;
|
isInAny(...paths: string[]): boolean;
|
||||||
|
// @deprecated (undocumented)
|
||||||
get isMenuOpen(): boolean;
|
get isMenuOpen(): boolean;
|
||||||
isPointInShape(shape: TLShape | TLShapeId, point: VecLike, opts?: {
|
isPointInShape(shape: TLShape | TLShapeId, point: VecLike, opts?: {
|
||||||
margin?: number | undefined;
|
margin?: number | undefined;
|
||||||
|
@ -790,6 +796,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
get openMenus(): string[];
|
get openMenus(): string[];
|
||||||
packShapes(shapes: TLShape[] | TLShapeId[], gap: number): this;
|
packShapes(shapes: TLShape[] | TLShapeId[], gap: number): this;
|
||||||
get pages(): TLPage[];
|
get pages(): TLPage[];
|
||||||
|
// @deprecated (undocumented)
|
||||||
get pageStates(): TLInstancePageState[];
|
get pageStates(): TLInstancePageState[];
|
||||||
pageToScreen(point: VecLike): {
|
pageToScreen(point: VecLike): {
|
||||||
x: number;
|
x: number;
|
||||||
|
@ -840,6 +847,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
readonly scribbles: ScribbleManager;
|
readonly scribbles: ScribbleManager;
|
||||||
select(...shapes: TLShape[] | TLShapeId[]): this;
|
select(...shapes: TLShape[] | TLShapeId[]): this;
|
||||||
selectAll(): this;
|
selectAll(): this;
|
||||||
|
// @deprecated (undocumented)
|
||||||
get selectedShapeIds(): TLShapeId[];
|
get selectedShapeIds(): TLShapeId[];
|
||||||
get selectedShapes(): TLShape[];
|
get selectedShapes(): TLShape[];
|
||||||
get selectionPageBounds(): Box2d | null;
|
get selectionPageBounds(): Box2d | null;
|
||||||
|
|
|
@ -6749,7 +6749,7 @@
|
||||||
{
|
{
|
||||||
"kind": "Method",
|
"kind": "Method",
|
||||||
"canonicalReference": "@tldraw/editor!Editor#alignShapes:member(1)",
|
"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": [
|
"excerptTokens": [
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
|
@ -7229,7 +7229,7 @@
|
||||||
{
|
{
|
||||||
"kind": "Method",
|
"kind": "Method",
|
||||||
"canonicalReference": "@tldraw/editor!Editor#batch:member(1)",
|
"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": [
|
"excerptTokens": [
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
|
@ -8249,7 +8249,7 @@
|
||||||
{
|
{
|
||||||
"kind": "Property",
|
"kind": "Property",
|
||||||
"canonicalReference": "@tldraw/editor!Editor#currentPageState:member",
|
"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": [
|
"excerptTokens": [
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
|
@ -8884,7 +8884,7 @@
|
||||||
{
|
{
|
||||||
"kind": "Method",
|
"kind": "Method",
|
||||||
"canonicalReference": "@tldraw/editor!Editor#distributeShapes:member(1)",
|
"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": [
|
"excerptTokens": [
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
|
@ -9507,7 +9507,7 @@
|
||||||
{
|
{
|
||||||
"kind": "Method",
|
"kind": "Method",
|
||||||
"canonicalReference": "@tldraw/editor!Editor#flipShapes:member(1)",
|
"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": [
|
"excerptTokens": [
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
|
@ -10131,6 +10131,38 @@
|
||||||
"isAbstract": false,
|
"isAbstract": false,
|
||||||
"name": "getContentFromCurrentPage"
|
"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",
|
"kind": "Method",
|
||||||
"canonicalReference": "@tldraw/editor!Editor#getCurrentTool:member(1)",
|
"canonicalReference": "@tldraw/editor!Editor#getCurrentTool:member(1)",
|
||||||
|
@ -10454,6 +10486,37 @@
|
||||||
"isAbstract": false,
|
"isAbstract": false,
|
||||||
"name": "getInstanceState"
|
"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",
|
"kind": "Method",
|
||||||
"canonicalReference": "@tldraw/editor!Editor#getOpenMenus:member(1)",
|
"canonicalReference": "@tldraw/editor!Editor#getOpenMenus:member(1)",
|
||||||
|
@ -10704,6 +10767,42 @@
|
||||||
"isAbstract": false,
|
"isAbstract": false,
|
||||||
"name": "getPageShapeIds"
|
"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",
|
"kind": "Method",
|
||||||
"canonicalReference": "@tldraw/editor!Editor#getPointInParentSpace:member(1)",
|
"canonicalReference": "@tldraw/editor!Editor#getPointInParentSpace:member(1)",
|
||||||
|
@ -10910,6 +11009,42 @@
|
||||||
"isAbstract": false,
|
"isAbstract": false,
|
||||||
"name": "getSelectedShapeAtPoint"
|
"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",
|
"kind": "Method",
|
||||||
"canonicalReference": "@tldraw/editor!Editor#getShape:member(1)",
|
"canonicalReference": "@tldraw/editor!Editor#getShape:member(1)",
|
||||||
|
@ -13253,7 +13388,7 @@
|
||||||
{
|
{
|
||||||
"kind": "Property",
|
"kind": "Property",
|
||||||
"canonicalReference": "@tldraw/editor!Editor#isMenuOpen:member",
|
"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": [
|
"excerptTokens": [
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
|
@ -14055,7 +14190,7 @@
|
||||||
{
|
{
|
||||||
"kind": "Method",
|
"kind": "Method",
|
||||||
"canonicalReference": "@tldraw/editor!Editor#packShapes:member(1)",
|
"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": [
|
"excerptTokens": [
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
|
@ -14168,7 +14303,7 @@
|
||||||
{
|
{
|
||||||
"kind": "Property",
|
"kind": "Property",
|
||||||
"canonicalReference": "@tldraw/editor!Editor#pageStates:member",
|
"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": [
|
"excerptTokens": [
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
|
@ -15354,7 +15489,7 @@
|
||||||
{
|
{
|
||||||
"kind": "Method",
|
"kind": "Method",
|
||||||
"canonicalReference": "@tldraw/editor!Editor#rotateShapesBy:member(1)",
|
"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": [
|
"excerptTokens": [
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
|
@ -15605,7 +15740,7 @@
|
||||||
{
|
{
|
||||||
"kind": "Property",
|
"kind": "Property",
|
||||||
"canonicalReference": "@tldraw/editor!Editor#selectedShapeIds:member",
|
"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": [
|
"excerptTokens": [
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
|
@ -17199,7 +17334,7 @@
|
||||||
{
|
{
|
||||||
"kind": "Method",
|
"kind": "Method",
|
||||||
"canonicalReference": "@tldraw/editor!Editor#stackShapes:member(1)",
|
"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": [
|
"excerptTokens": [
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
|
@ -17434,7 +17569,7 @@
|
||||||
{
|
{
|
||||||
"kind": "Method",
|
"kind": "Method",
|
||||||
"canonicalReference": "@tldraw/editor!Editor#stretchShapes:member(1)",
|
"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": [
|
"excerptTokens": [
|
||||||
{
|
{
|
||||||
"kind": "Content",
|
"kind": "Content",
|
||||||
|
|
|
@ -335,7 +335,7 @@ function SelectedIdIndicators() {
|
||||||
const editor = useEditor()
|
const editor = useEditor()
|
||||||
const selectedShapeIds = useValue(
|
const selectedShapeIds = useValue(
|
||||||
'selectedShapeIds',
|
'selectedShapeIds',
|
||||||
() => editor.currentPageState.selectedShapeIds,
|
() => editor.getCurrentPageState().selectedShapeIds,
|
||||||
[editor]
|
[editor]
|
||||||
)
|
)
|
||||||
const shouldDisplay = useValue(
|
const shouldDisplay = useValue(
|
||||||
|
@ -381,7 +381,7 @@ const HoveredShapeIndicator = function HoveredShapeIndicator() {
|
||||||
() => editor.getInstanceState().isHoveringCanvas,
|
() => editor.getInstanceState().isHoveringCanvas,
|
||||||
[editor]
|
[editor]
|
||||||
)
|
)
|
||||||
const hoveredShapeId = useValue('hovered id', () => editor.currentPageState.hoveredShapeId, [
|
const hoveredShapeId = useValue('hovered id', () => editor.getCurrentPageState().hoveredShapeId, [
|
||||||
editor,
|
editor,
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
|
@ -464,7 +464,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
}
|
}
|
||||||
const deletedIds = new Set([record.id])
|
const deletedIds = new Set([record.id])
|
||||||
const updates = compact(
|
const updates = compact(
|
||||||
this.pageStates.map((pageState) => {
|
this.getPageStates().map((pageState) => {
|
||||||
return cleanupInstancePageState(pageState, deletedIds)
|
return cleanupInstancePageState(pageState, deletedIds)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
@ -514,7 +514,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
allMovingIds.add(id)
|
allMovingIds.add(id)
|
||||||
})
|
})
|
||||||
|
|
||||||
for (const instancePageState of this.pageStates) {
|
for (const instancePageState of this.getPageStates()) {
|
||||||
if (instancePageState.pageId === next.parentId) continue
|
if (instancePageState.pageId === next.parentId) continue
|
||||||
const nextPageState = cleanupInstancePageState(instancePageState, allMovingIds)
|
const nextPageState = cleanupInstancePageState(instancePageState, allMovingIds)
|
||||||
|
|
||||||
|
@ -892,7 +892,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
* ```ts
|
* ```ts
|
||||||
* editor.batch(() => {
|
* editor.batch(() => {
|
||||||
* editor.selectAll()
|
* editor.selectAll()
|
||||||
* editor.deleteShapes(editor.selectedShapeIds)
|
* editor.deleteShapes(editor.getSelectedShapeIds())
|
||||||
* editor.createShapes(myShapes)
|
* editor.createShapes(myShapes)
|
||||||
* editor.selectNone()
|
* editor.selectNone()
|
||||||
* })
|
* })
|
||||||
|
@ -1345,10 +1345,17 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
*
|
*
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@computed get isMenuOpen(): boolean {
|
@computed getIsMenuOpen(): boolean {
|
||||||
return this.getOpenMenus().length > 0
|
return this.getOpenMenus().length > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use `getIsMenuOpen` instead.
|
||||||
|
*/
|
||||||
|
get isMenuOpen() {
|
||||||
|
return this.getIsMenuOpen()
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------- Cursor --------------------- */
|
/* --------------------- Cursor --------------------- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1374,11 +1381,19 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
*
|
*
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@computed get pageStates(): TLInstancePageState[] {
|
@computed getPageStates(): TLInstancePageState[] {
|
||||||
return this._pageStates.get()
|
return this._getPageStatesQuery().get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use `getPageStates` instead.
|
||||||
|
*/
|
||||||
|
get pageStates() {
|
||||||
|
return this.getPageStates()
|
||||||
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
@computed private get _pageStates() {
|
@computed private _getPageStatesQuery() {
|
||||||
return this.store.query.records('instance_page_state')
|
return this.store.query.records('instance_page_state')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1387,11 +1402,19 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
*
|
*
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@computed get currentPageState(): TLInstancePageState {
|
@computed getCurrentPageState(): TLInstancePageState {
|
||||||
return this.store.get(this._currentPageStateId)!
|
return this.store.get(this._getCurrentPageStateId())!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use `getCurrentPageState` instead.
|
||||||
|
*/
|
||||||
|
get currentPageState() {
|
||||||
|
return this.getCurrentPageState()
|
||||||
|
}
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
@computed private get _currentPageStateId() {
|
@computed private _getCurrentPageStateId() {
|
||||||
return InstancePageStateRecordType.createId(this.currentPageId)
|
return InstancePageStateRecordType.createId(this.currentPageId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1426,7 +1449,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
partial: Partial<Omit<TLInstancePageState, 'selectedShapeIds'>>,
|
partial: Partial<Omit<TLInstancePageState, 'selectedShapeIds'>>,
|
||||||
historyOptions?: TLCommandHistoryOptions
|
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 }
|
return { data: { prev, partial }, ...historyOptions }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1444,8 +1467,15 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
*
|
*
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@computed get selectedShapeIds() {
|
@computed getSelectedShapeIds() {
|
||||||
return this.currentPageState.selectedShapeIds
|
return this.getCurrentPageState().selectedShapeIds
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use `getSelectedShapeIds` instead.
|
||||||
|
*/
|
||||||
|
get selectedShapeIds() {
|
||||||
|
return this.getSelectedShapeIds()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1460,7 +1490,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
* @readonly
|
* @readonly
|
||||||
*/
|
*/
|
||||||
@computed get selectedShapes(): TLShape[] {
|
@computed get selectedShapes(): TLShape[] {
|
||||||
const { selectedShapeIds } = this.currentPageState
|
const { selectedShapeIds } = this.getCurrentPageState()
|
||||||
return compact(selectedShapeIds.map((id) => this.store.get(id)))
|
return compact(selectedShapeIds.map((id) => this.store.get(id)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1491,7 +1521,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
private _setSelectedShapes = this.history.createCommand(
|
private _setSelectedShapes = this.history.createCommand(
|
||||||
'setSelectedShapes',
|
'setSelectedShapes',
|
||||||
(ids: TLShapeId[], historyOptions?: TLCommandHistoryOptions) => {
|
(ids: TLShapeId[], historyOptions?: TLCommandHistoryOptions) => {
|
||||||
const { selectedShapeIds: prevSelectedShapeIds } = this.currentPageState
|
const { selectedShapeIds: prevSelectedShapeIds } = this.getCurrentPageState()
|
||||||
const prevSet = new Set(prevSelectedShapeIds)
|
const prevSet = new Set(prevSelectedShapeIds)
|
||||||
|
|
||||||
if (ids.length === prevSet.size && ids.every((id) => prevSet.has(id))) return null
|
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 }) => {
|
do: ({ selectedShapeIds }) => {
|
||||||
this.store.put([{ ...this.currentPageState, selectedShapeIds }])
|
this.store.put([{ ...this.getCurrentPageState(), selectedShapeIds }])
|
||||||
},
|
},
|
||||||
undo: ({ prevSelectedShapeIds }) => {
|
undo: ({ prevSelectedShapeIds }) => {
|
||||||
this.store.put([
|
this.store.put([
|
||||||
{
|
{
|
||||||
...this.currentPageState,
|
...this.getCurrentPageState(),
|
||||||
selectedShapeIds: prevSelectedShapeIds,
|
selectedShapeIds: prevSelectedShapeIds,
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
@ -1534,7 +1564,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
const id = typeof shape === 'string' ? shape : shape?.id ?? null
|
const id = typeof shape === 'string' ? shape : shape?.id ?? null
|
||||||
const _shape = this.getShape(id)
|
const _shape = this.getShape(id)
|
||||||
if (!_shape) return false
|
if (!_shape) return false
|
||||||
const { selectedShapeIds } = this
|
const selectedShapeIds = this.getSelectedShapeIds()
|
||||||
return !!this.findShapeAncestor(_shape, (parent) => selectedShapeIds.includes(parent.id))
|
return !!this.findShapeAncestor(_shape, (parent) => selectedShapeIds.includes(parent.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1575,7 +1605,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
typeof shapes[0] === 'string'
|
typeof shapes[0] === 'string'
|
||||||
? (shapes as TLShapeId[])
|
? (shapes as TLShapeId[])
|
||||||
: (shapes as TLShape[]).map((shape) => shape.id)
|
: (shapes as TLShape[]).map((shape) => shape.id)
|
||||||
const { selectedShapeIds } = this
|
const selectedShapeIds = this.getSelectedShapeIds()
|
||||||
if (selectedShapeIds.length > 0 && ids.length > 0) {
|
if (selectedShapeIds.length > 0 && ids.length > 0) {
|
||||||
this.setSelectedShapes(selectedShapeIds.filter((id) => !ids.includes(id)))
|
this.setSelectedShapes(selectedShapeIds.filter((id) => !ids.includes(id)))
|
||||||
}
|
}
|
||||||
|
@ -1612,7 +1642,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
selectNone(): this {
|
selectNone(): this {
|
||||||
if (this.selectedShapeIds.length > 0) {
|
if (this.getSelectedShapeIds().length > 0) {
|
||||||
this.setSelectedShapes([])
|
this.setSelectedShapes([])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1648,10 +1678,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@computed get selectionPageBounds(): Box2d | null {
|
@computed get selectionPageBounds(): Box2d | null {
|
||||||
const {
|
const selectedShapeIds = this.getCurrentPageState().selectedShapeIds
|
||||||
currentPageState: { selectedShapeIds },
|
|
||||||
} = this
|
|
||||||
|
|
||||||
if (selectedShapeIds.length === 0) return null
|
if (selectedShapeIds.length === 0) return null
|
||||||
|
|
||||||
return Box2d.Common(compact(selectedShapeIds.map((id) => this.getShapePageBounds(id))))
|
return Box2d.Common(compact(selectedShapeIds.map((id) => this.getShapePageBounds(id))))
|
||||||
|
@ -1664,12 +1691,12 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@computed get selectionRotation(): number {
|
@computed get selectionRotation(): number {
|
||||||
const { selectedShapeIds } = this
|
const selectedShapeIds = this.getSelectedShapeIds()
|
||||||
if (selectedShapeIds.length === 0) {
|
if (selectedShapeIds.length === 0) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
if (selectedShapeIds.length === 1) {
|
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())
|
const allRotations = selectedShapeIds.map((id) => this.getShapePageTransform(id)!.rotation())
|
||||||
|
@ -1687,7 +1714,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@computed get selectionRotatedPageBounds(): Box2d | undefined {
|
@computed get selectionRotatedPageBounds(): Box2d | undefined {
|
||||||
const { selectedShapeIds } = this
|
const selectedShapeIds = this.getSelectedShapeIds()
|
||||||
|
|
||||||
if (selectedShapeIds.length === 0) {
|
if (selectedShapeIds.length === 0) {
|
||||||
return undefined
|
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
|
// need to 'un-rotate' all the outlines of the existing nodes so we can fit them inside a box
|
||||||
const boxFromRotatedVertices = Box2d.FromPoints(
|
const boxFromRotatedVertices = Box2d.FromPoints(
|
||||||
this.selectedShapeIds
|
this.getSelectedShapeIds()
|
||||||
.flatMap((id) => {
|
.flatMap((id) => {
|
||||||
const pageTransform = this.getShapePageTransform(id)
|
const pageTransform = this.getShapePageTransform(id)
|
||||||
if (!pageTransform) return []
|
if (!pageTransform) return []
|
||||||
|
@ -1728,7 +1755,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@computed get focusedGroupId(): TLShapeId | TLPageId {
|
@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(
|
private _setFocusedGroupId = this.history.createCommand(
|
||||||
'setFocusedGroupId',
|
'setFocusedGroupId',
|
||||||
(next: TLShapeId | null) => {
|
(next: TLShapeId | null) => {
|
||||||
const prev = this.currentPageState.focusedGroupId
|
const prev = this.getCurrentPageState().focusedGroupId
|
||||||
if (prev === next) return
|
if (prev === next) return
|
||||||
return {
|
return {
|
||||||
data: {
|
data: {
|
||||||
|
@ -1786,10 +1813,10 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
do: ({ next }) => {
|
do: ({ next }) => {
|
||||||
this.store.update(this.currentPageState.id, (s) => ({ ...s, focusedGroupId: next }))
|
this.store.update(this.getCurrentPageState().id, (s) => ({ ...s, focusedGroupId: next }))
|
||||||
},
|
},
|
||||||
undo: ({ prev }) => {
|
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 }) {
|
squash({ prev }, { next }) {
|
||||||
return { prev, next }
|
return { prev, next }
|
||||||
|
@ -1828,7 +1855,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@computed get editingShapeId() {
|
@computed get editingShapeId() {
|
||||||
return this.currentPageState.editingShapeId
|
return this.getCurrentPageState().editingShapeId
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1880,7 +1907,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@computed get hoveredShapeId() {
|
@computed get hoveredShapeId() {
|
||||||
return this.currentPageState.hoveredShapeId
|
return this.getCurrentPageState().hoveredShapeId
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1921,7 +1948,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@computed get hintingShapeIds() {
|
@computed get hintingShapeIds() {
|
||||||
return this.currentPageState.hintingShapeIds
|
return this.getCurrentPageState().hintingShapeIds
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1965,7 +1992,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@computed get erasingShapeIds() {
|
@computed get erasingShapeIds() {
|
||||||
return this.currentPageState.erasingShapeIds
|
return this.getCurrentPageState().erasingShapeIds
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2024,7 +2051,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
get croppingShapeId() {
|
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
|
// We only really need these if we're using editor state, but that's ok
|
||||||
const editingShapeId = this.editingShapeId
|
const editingShapeId = this.editingShapeId
|
||||||
const selectedShapeIds = this.selectedShapeIds
|
const selectedShapeIds = this.getSelectedShapeIds()
|
||||||
const erasingShapeIds = this.erasingShapeIds
|
const erasingShapeIds = this.erasingShapeIds
|
||||||
const renderingBoundsExpanded = this.renderingBoundsExpanded
|
const renderingBoundsExpanded = this.renderingBoundsExpanded
|
||||||
|
|
||||||
|
@ -3366,7 +3393,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
// in multiplayer contexts this page might have been deleted
|
// in multiplayer contexts this page might have been deleted
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!this.pageStates.find((p) => p.pageId === toId)) {
|
if (!this.getPageStates().find((p) => p.pageId === toId)) {
|
||||||
const camera = CameraRecordType.create({
|
const camera = CameraRecordType.create({
|
||||||
id: CameraRecordType.createId(toId),
|
id: CameraRecordType.createId(toId),
|
||||||
})
|
})
|
||||||
|
@ -3541,7 +3568,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
if (pages.length === 1) return null
|
if (pages.length === 1) return null
|
||||||
|
|
||||||
const deletedPage = this.getPage(id)
|
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
|
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.
|
* @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 {
|
getSelectedShapeAtPoint(point: VecLike): TLShape | undefined {
|
||||||
const { selectedShapeIds } = this
|
const selectedShapeIds = this.getSelectedShapeIds()
|
||||||
return this.currentPageShapesSorted
|
return this.currentPageShapesSorted
|
||||||
.filter((shape) => shape.type !== 'group' && selectedShapeIds.includes(shape.id))
|
.filter((shape) => shape.type !== 'group' && selectedShapeIds.includes(shape.id))
|
||||||
.reverse() // findlast
|
.reverse() // findlast
|
||||||
|
@ -5083,8 +5110,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* ```ts
|
* ```ts
|
||||||
* editor.rotateShapesBy(editor.selectedShapeIds, Math.PI)
|
* editor.rotateShapesBy(editor.getSelectedShapeIds(), Math.PI)
|
||||||
* editor.rotateShapesBy(editor.selectedShapeIds, Math.PI / 2)
|
* editor.rotateShapesBy(editor.getSelectedShapeIds(), Math.PI / 2)
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @param shapes - The shapes (or shape ids) of the shapes to move.
|
* @param shapes - The shapes (or shape ids) of the shapes to move.
|
||||||
|
@ -5576,7 +5603,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
* @example
|
* @example
|
||||||
* ```ts
|
* ```ts
|
||||||
* editor.flipShapes([box1, box2], 'horizontal', 32)
|
* 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.
|
* @param shapes - The ids of the shapes to flip.
|
||||||
|
@ -5641,7 +5668,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
* @example
|
* @example
|
||||||
* ```ts
|
* ```ts
|
||||||
* editor.stackShapes([box1, box2], 'horizontal', 32)
|
* 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.
|
* @param shapes - The shapes (or shape ids) to stack.
|
||||||
|
@ -5791,7 +5818,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
* @example
|
* @example
|
||||||
* ```ts
|
* ```ts
|
||||||
* editor.packShapes([box1, box2], 32)
|
* 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
|
* @example
|
||||||
* ```ts
|
* ```ts
|
||||||
* editor.alignShapes([box1, box2], 'left')
|
* editor.alignShapes([box1, box2], 'left')
|
||||||
* editor.alignShapes(editor.selectedShapeIds, 'left')
|
* editor.alignShapes(editor.getSelectedShapeIds(), 'left')
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @param shapes - The shapes (or shape ids) to align.
|
* @param shapes - The shapes (or shape ids) to align.
|
||||||
|
@ -6045,7 +6072,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
* @example
|
* @example
|
||||||
* ```ts
|
* ```ts
|
||||||
* editor.distributeShapes([box1, box2], 'horizontal')
|
* editor.distributeShapes([box1, box2], 'horizontal')
|
||||||
* editor.distributeShapes(editor.selectedShapeIds, 'horizontal')
|
* editor.distributeShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @param shapes - The shapes (or shape ids) to distribute.
|
* @param shapes - The shapes (or shape ids) to distribute.
|
||||||
|
@ -6136,7 +6163,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
* @example
|
* @example
|
||||||
* ```ts
|
* ```ts
|
||||||
* editor.stretchShapes([box1, box2], 'horizontal')
|
* editor.stretchShapes([box1, box2], 'horizontal')
|
||||||
* editor.stretchShapes(editor.selectedShapeIds, 'horizontal')
|
* editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* @param shapes - The shapes (or shape ids) to stretch.
|
* @param shapes - The shapes (or shape ids) to stretch.
|
||||||
|
@ -7181,7 +7208,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
(ids: TLShapeId[]) => {
|
(ids: TLShapeId[]) => {
|
||||||
if (this.getInstanceState().isReadonly) return null
|
if (this.getInstanceState().isReadonly) return null
|
||||||
if (ids.length === 0) return null
|
if (ids.length === 0) return null
|
||||||
const prevSelectedShapeIds = [...this.currentPageState.selectedShapeIds]
|
const prevSelectedShapeIds = [...this.getCurrentPageState().selectedShapeIds]
|
||||||
|
|
||||||
const allIds = new Set(ids)
|
const allIds = new Set(ids)
|
||||||
|
|
||||||
|
@ -7213,14 +7240,14 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
{
|
{
|
||||||
do: ({ deletedIds, postSelectedShapeIds }) => {
|
do: ({ deletedIds, postSelectedShapeIds }) => {
|
||||||
this.store.remove(deletedIds)
|
this.store.remove(deletedIds)
|
||||||
this.store.update(this.currentPageState.id, (state) => ({
|
this.store.update(this.getCurrentPageState().id, (state) => ({
|
||||||
...state,
|
...state,
|
||||||
selectedShapeIds: postSelectedShapeIds,
|
selectedShapeIds: postSelectedShapeIds,
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
undo: ({ snapshots, prevSelectedShapeIds }) => {
|
undo: ({ snapshots, prevSelectedShapeIds }) => {
|
||||||
this.store.put(snapshots)
|
this.store.put(snapshots)
|
||||||
this.store.update(this.currentPageState.id, (state) => ({
|
this.store.update(this.getCurrentPageState().id, (state) => ({
|
||||||
...state,
|
...state,
|
||||||
selectedShapeIds: prevSelectedShapeIds,
|
selectedShapeIds: prevSelectedShapeIds,
|
||||||
}))
|
}))
|
||||||
|
@ -7302,7 +7329,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
get sharedStyles(): ReadonlySharedStyleMap {
|
get sharedStyles(): ReadonlySharedStyleMap {
|
||||||
// If we're in selecting and if we have a selection, return the shared styles from the
|
// If we're in selecting and if we have a selection, return the shared styles from the
|
||||||
// current selection
|
// current selection
|
||||||
if (this.isIn('select') && this.selectedShapeIds.length > 0) {
|
if (this.isIn('select') && this.getSelectedShapeIds().length > 0) {
|
||||||
return this._selectionSharedStyles.get()
|
return this._selectionSharedStyles.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7327,7 +7354,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@computed get sharedOpacity(): SharedStyle<number> {
|
@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 shapesToCheck: TLShape[] = []
|
||||||
const addShape = (shapeId: TLShapeId) => {
|
const addShape = (shapeId: TLShapeId) => {
|
||||||
const shape = this.getShape(shapeId)
|
const shape = this.getShape(shapeId)
|
||||||
|
@ -7343,7 +7370,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
shapesToCheck.push(shape)
|
shapesToCheck.push(shape)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const shapeId of this.selectedShapeIds) {
|
for (const shapeId of this.getSelectedShapeIds()) {
|
||||||
addShape(shapeId)
|
addShape(shapeId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8649,7 +8676,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
if (!inputs.isEditing) {
|
if (!inputs.isEditing) {
|
||||||
this._pinchStart = this.camera.z
|
this._pinchStart = this.camera.z
|
||||||
if (!this._selectedShapeIdsAtPointerDown.length) {
|
if (!this._selectedShapeIdsAtPointerDown.length) {
|
||||||
this._selectedShapeIdsAtPointerDown = this.selectedShapeIds
|
this._selectedShapeIdsAtPointerDown = this.getSelectedShapeIds()
|
||||||
}
|
}
|
||||||
|
|
||||||
this._didPinch = true
|
this._didPinch = true
|
||||||
|
@ -8709,7 +8736,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
|
|
||||||
this._updateInputsFromEvent(info)
|
this._updateInputsFromEvent(info)
|
||||||
|
|
||||||
if (this.isMenuOpen) {
|
if (this.getIsMenuOpen()) {
|
||||||
// noop
|
// noop
|
||||||
} else {
|
} else {
|
||||||
if (inputs.ctrlKey) {
|
if (inputs.ctrlKey) {
|
||||||
|
@ -8759,7 +8786,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
|
|
||||||
switch (info.name) {
|
switch (info.name) {
|
||||||
case 'pointer_down': {
|
case 'pointer_down': {
|
||||||
this._selectedShapeIdsAtPointerDown = this.selectedShapeIds
|
this._selectedShapeIdsAtPointerDown = this.getSelectedShapeIds()
|
||||||
|
|
||||||
// Firefox bug fix...
|
// Firefox bug fix...
|
||||||
// If it's a left-mouse-click, we store the pointer id for later user
|
// 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.isPointing = false
|
||||||
inputs.isDragging = false
|
inputs.isDragging = false
|
||||||
|
|
||||||
if (this.isMenuOpen) {
|
if (this.getIsMenuOpen()) {
|
||||||
// Suppressing pointerup here as <ContextMenu/> doesn't seem to do what we what here.
|
// Suppressing pointerup here as <ContextMenu/> doesn't seem to do what we what here.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -248,7 +248,8 @@ export class SnapManager {
|
||||||
// TODO: make this an incremental derivation
|
// TODO: make this an incremental derivation
|
||||||
@computed get snappableShapes(): GapNode[] {
|
@computed get snappableShapes(): GapNode[] {
|
||||||
const { editor } = this
|
const { editor } = this
|
||||||
const { selectedShapeIds, renderingBounds: renderingBounds } = editor
|
const { renderingBounds: renderingBounds } = editor
|
||||||
|
const selectedShapeIds = editor.getSelectedShapeIds()
|
||||||
|
|
||||||
const snappableShapes: GapNode[] = []
|
const snappableShapes: GapNode[] = []
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ export class GroupShapeUtil extends ShapeUtil<TLGroupShape> {
|
||||||
component(shape: TLGroupShape) {
|
component(shape: TLGroupShape) {
|
||||||
const isErasing = this.editor.erasingShapeIds.includes(shape.id)
|
const isErasing = this.editor.erasingShapeIds.includes(shape.id)
|
||||||
|
|
||||||
const { hintingShapeIds } = this.editor.currentPageState
|
const { hintingShapeIds } = this.editor.getCurrentPageState()
|
||||||
const isHintingOtherGroup =
|
const isHintingOtherGroup =
|
||||||
hintingShapeIds.length > 0 &&
|
hintingShapeIds.length > 0 &&
|
||||||
hintingShapeIds.some(
|
hintingShapeIds.some(
|
||||||
|
@ -60,7 +60,7 @@ export class GroupShapeUtil extends ShapeUtil<TLGroupShape> {
|
||||||
this.editor.isShapeOfType<TLGroupShape>(this.editor.getShape(id)!, 'group')
|
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 (
|
if (
|
||||||
!isErasing && // always show the outline while we're erasing the group
|
!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) => {
|
override onChildrenChange: TLOnChildrenChangeHandler<TLGroupShape> = (group) => {
|
||||||
const children = this.editor.getSortedChildIdsForParent(group.id)
|
const children = this.editor.getSortedChildIdsForParent(group.id)
|
||||||
if (children.length === 0) {
|
if (children.length === 0) {
|
||||||
if (this.editor.currentPageState.focusedGroupId === group.id) {
|
if (this.editor.getCurrentPageState().focusedGroupId === group.id) {
|
||||||
this.editor.popFocusedGroupId()
|
this.editor.popFocusedGroupId()
|
||||||
}
|
}
|
||||||
this.editor.deleteShapes([group.id])
|
this.editor.deleteShapes([group.id])
|
||||||
return
|
return
|
||||||
} else if (children.length === 1) {
|
} else if (children.length === 1) {
|
||||||
if (this.editor.currentPageState.focusedGroupId === group.id) {
|
if (this.editor.getCurrentPageState().focusedGroupId === group.id) {
|
||||||
this.editor.popFocusedGroupId()
|
this.editor.popFocusedGroupId()
|
||||||
}
|
}
|
||||||
this.editor.reparentShapes(children, group.parentId)
|
this.editor.reparentShapes(children, group.parentId)
|
||||||
|
|
|
@ -13,8 +13,7 @@ export class Pointing extends StateNode {
|
||||||
wasFocusedOnEnter = false
|
wasFocusedOnEnter = false
|
||||||
|
|
||||||
override onEnter = () => {
|
override onEnter = () => {
|
||||||
const { isMenuOpen } = this.editor
|
this.wasFocusedOnEnter = !this.editor.getIsMenuOpen()
|
||||||
this.wasFocusedOnEnter = !isMenuOpen
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override onPointerMove: TLEventHandlers['onPointerMove'] = (info) => {
|
override onPointerMove: TLEventHandlers['onPointerMove'] = (info) => {
|
||||||
|
|
|
@ -83,7 +83,7 @@ export function useDocumentEvents() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'Tab': {
|
case 'Tab': {
|
||||||
if (isFocusingInput() || editor.isMenuOpen) {
|
if (isFocusingInput() || editor.getIsMenuOpen()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
@ -126,7 +126,7 @@ export function useDocumentEvents() {
|
||||||
// escape de-selects them. Only when the user's selection is empty
|
// escape de-selects them. Only when the user's selection is empty
|
||||||
// should we allow escape to do its normal thing.
|
// 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()
|
e.preventDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ export function useDocumentEvents() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
if (isFocusingInput() || editor.isMenuOpen) {
|
if (isFocusingInput() || editor.getIsMenuOpen()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,7 @@ export function useDocumentEvents() {
|
||||||
if ((e as any).isKilled) return
|
if ((e as any).isKilled) return
|
||||||
;(e as any).isKilled = true
|
;(e as any).isKilled = true
|
||||||
|
|
||||||
if (isFocusingInput() || editor.isMenuOpen) {
|
if (isFocusingInput() || editor.getIsMenuOpen()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ export const TldrawSelectionForeground: TLSelectionForegroundComponent = track(
|
||||||
const bottomLeftEvents = useSelectionEvents('bottom_left')
|
const bottomLeftEvents = useSelectionEvents('bottom_left')
|
||||||
|
|
||||||
const isDefaultCursor =
|
const isDefaultCursor =
|
||||||
!editor.isMenuOpen && editor.getInstanceState().cursor.type === 'default'
|
!editor.getIsMenuOpen() && editor.getInstanceState().cursor.type === 'default'
|
||||||
const isCoarsePointer = editor.getInstanceState().isCoarsePointer
|
const isCoarsePointer = editor.getInstanceState().isCoarsePointer
|
||||||
|
|
||||||
const shapes = editor.selectedShapes
|
const shapes = editor.selectedShapes
|
||||||
|
|
|
@ -23,7 +23,7 @@ beforeEach(() => {
|
||||||
editor = new TestEditor()
|
editor = new TestEditor()
|
||||||
editor
|
editor
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.deleteShapes(editor.selectedShapeIds)
|
.deleteShapes(editor.getSelectedShapeIds())
|
||||||
.createShapes([
|
.createShapes([
|
||||||
{ id: ids.box1, type: 'geo', x: 100, y: 100, props: { w: 100, h: 100 } },
|
{ 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 } },
|
{ 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', () => {
|
describe('reparenting issue', () => {
|
||||||
it('Correctly sets index when reparenting', () => {
|
it('Correctly sets index when reparenting', () => {
|
||||||
editor.selectAll().deleteShapes(editor.selectedShapeIds)
|
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
// Create an arrow!
|
// Create an arrow!
|
||||||
editor.setCurrentTool('arrow')
|
editor.setCurrentTool('arrow')
|
||||||
|
@ -440,7 +440,7 @@ describe('reparenting issue', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Correctly sets index when reparenting with multiple arrows', () => {
|
it('Correctly sets index when reparenting with multiple arrows', () => {
|
||||||
editor.selectAll().deleteShapes(editor.selectedShapeIds)
|
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
// create two rectangles:
|
// create two rectangles:
|
||||||
editor.createShapes([
|
editor.createShapes([
|
||||||
|
@ -494,7 +494,7 @@ describe('reparenting issue', () => {
|
||||||
expect(arrow2BoundIndex).toBe('a1G')
|
expect(arrow2BoundIndex).toBe('a1G')
|
||||||
|
|
||||||
// nudge everything around and make sure we all stay in the right order
|
// 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(arrow1Id)!.index).toBe('a1V')
|
||||||
expect(editor.getShape(arrow2Id)!.index).toBe('a1G')
|
expect(editor.getShape(arrow2Id)!.index).toBe('a1G')
|
||||||
})
|
})
|
||||||
|
@ -502,7 +502,7 @@ describe('reparenting issue', () => {
|
||||||
|
|
||||||
describe('line bug', () => {
|
describe('line bug', () => {
|
||||||
it('works as expected when binding to a straight line', () => {
|
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)
|
expect(editor.currentPageShapes.length).toBe(0)
|
||||||
|
|
||||||
|
@ -528,7 +528,7 @@ describe('line bug', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('works as expected when binding to a straight horizontal line', () => {
|
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)
|
expect(editor.currentPageShapes.length).toBe(0)
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ beforeEach(() => {
|
||||||
editor = new TestEditor()
|
editor = new TestEditor()
|
||||||
editor
|
editor
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.deleteShapes(editor.selectedShapeIds)
|
.deleteShapes(editor.getSelectedShapeIds())
|
||||||
.createShapes([
|
.createShapes([
|
||||||
{ id: ids.box1, type: 'geo', x: 100, y: 100, props: { w: 100, h: 100 } },
|
{ 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 } },
|
{ 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)
|
editor.select(ids.arrow1, ids.box2)
|
||||||
|
|
||||||
// When box one is not selected, unbinds box1 and keeps binding to 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({
|
expect(editor.getShape(ids.arrow1)).toMatchObject({
|
||||||
props: {
|
props: {
|
||||||
|
@ -190,7 +190,7 @@ describe('Other cases when arrow are moved', () => {
|
||||||
|
|
||||||
// unbinds when only the arrow is selected (not its bound shapes)
|
// unbinds when only the arrow is selected (not its bound shapes)
|
||||||
editor.select(ids.arrow1)
|
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({
|
expect(editor.getShape(ids.arrow1)).toMatchObject({
|
||||||
props: { start: { type: 'point' }, end: { type: 'point' } },
|
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
|
// When box one is not selected, unbinds box1 and keeps binding to box2
|
||||||
editor.select(ids.arrow1, ids.box2, ids.box3)
|
editor.select(ids.arrow1, ids.box2, ids.box3)
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'right')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'right')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
expect(editor.getShape(ids.arrow1)).toMatchObject({
|
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)
|
// unbinds when only the arrow is selected (not its bound shapes)
|
||||||
editor.select(ids.arrow1, ids.box3)
|
editor.select(ids.arrow1, ids.box3)
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'top')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'top')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
expect(editor.getShape(ids.arrow1)).toMatchObject({
|
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
|
// When box one is not selected, unbinds box1 and keeps binding to box2
|
||||||
editor.select(ids.arrow1, ids.box2, ids.box3)
|
editor.select(ids.arrow1, ids.box2, ids.box3)
|
||||||
editor.distributeShapes(editor.selectedShapeIds, 'horizontal')
|
editor.distributeShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
expect(editor.getShape(ids.arrow1)).toMatchObject({
|
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
|
// 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.select(ids.arrow1, ids.box3, ids.box4)
|
||||||
editor.distributeShapes(editor.selectedShapeIds, 'vertical')
|
editor.distributeShapes(editor.getSelectedShapeIds(), 'vertical')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
// The arrow didn't actually move
|
// 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
|
// The arrow will move this time, so it should unbind
|
||||||
editor.updateShapes([{ id: ids.box4, type: 'geo', y: -600 }])
|
editor.updateShapes([{ id: ids.box4, type: 'geo', y: -600 }])
|
||||||
editor.distributeShapes(editor.selectedShapeIds, 'vertical')
|
editor.distributeShapes(editor.getSelectedShapeIds(), 'vertical')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
expect(editor.getShape(ids.arrow1)).toMatchObject({
|
expect(editor.getShape(ids.arrow1)).toMatchObject({
|
||||||
|
@ -293,13 +293,13 @@ describe('Other cases when arrow are moved', () => {
|
||||||
// create shapes in a group:
|
// create shapes in a group:
|
||||||
editor
|
editor
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.deleteShapes(editor.selectedShapeIds)
|
.deleteShapes(editor.getSelectedShapeIds())
|
||||||
.createShapes([
|
.createShapes([
|
||||||
{ id: ids.box3, type: 'geo', x: 0, y: 300, props: { w: 100, h: 100 } },
|
{ 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 } },
|
{ id: ids.box4, type: 'geo', x: 0, y: 600, props: { w: 100, h: 100 } },
|
||||||
])
|
])
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.groupShapes(editor.selectedShapeIds)
|
.groupShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
editor.setCurrentTool('arrow').pointerDown(1000, 1000).pointerMove(50, 350).pointerUp(50, 350)
|
editor.setCurrentTool('arrow').pointerDown(1000, 1000).pointerMove(50, 350).pointerUp(50, 350)
|
||||||
let arrow = editor.currentPageShapes[editor.currentPageShapes.length - 1]
|
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)
|
expect(arrow.props.end.boundShapeId).toBe(ids.box3)
|
||||||
|
|
||||||
// translate:
|
// 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 should still be bound to box3
|
||||||
arrow = editor.getShape(arrow.id)!
|
arrow = editor.getShape(arrow.id)!
|
||||||
|
@ -360,7 +360,7 @@ describe('resizing', () => {
|
||||||
it('resizes', () => {
|
it('resizes', () => {
|
||||||
editor
|
editor
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.deleteShapes(editor.selectedShapeIds)
|
.deleteShapes(editor.getSelectedShapeIds())
|
||||||
.setCurrentTool('arrow')
|
.setCurrentTool('arrow')
|
||||||
.pointerDown(0, 0)
|
.pointerDown(0, 0)
|
||||||
.pointerMove(200, 200)
|
.pointerMove(200, 200)
|
||||||
|
@ -415,7 +415,7 @@ describe('resizing', () => {
|
||||||
it('flips bend when flipping x or y', () => {
|
it('flips bend when flipping x or y', () => {
|
||||||
editor
|
editor
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.deleteShapes(editor.selectedShapeIds)
|
.deleteShapes(editor.getSelectedShapeIds())
|
||||||
.setCurrentTool('arrow')
|
.setCurrentTool('arrow')
|
||||||
.pointerDown(0, 0)
|
.pointerDown(0, 0)
|
||||||
.pointerMove(200, 200)
|
.pointerMove(200, 200)
|
||||||
|
@ -484,7 +484,7 @@ describe("an arrow's parents", () => {
|
||||||
let boxCid: TLShapeId
|
let boxCid: TLShapeId
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
editor.selectAll().deleteShapes(editor.selectedShapeIds)
|
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
editor.setCurrentTool('frame')
|
editor.setCurrentTool('frame')
|
||||||
editor.pointerDown(0, 0).pointerMove(100, 100).pointerUp()
|
editor.pointerDown(0, 0).pointerMove(100, 100).pointerUp()
|
||||||
|
|
|
@ -339,7 +339,7 @@ export class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
|
||||||
// If at least one bound shape is in the selection, do nothing;
|
// If at least one bound shape is in the selection, do nothing;
|
||||||
// If no bound shapes are in the selection, unbind any bound shapes
|
// If no bound shapes are in the selection, unbind any bound shapes
|
||||||
|
|
||||||
const { selectedShapeIds } = this.editor
|
const selectedShapeIds = this.editor.getSelectedShapeIds()
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(startBindingId &&
|
(startBindingId &&
|
||||||
|
|
|
@ -53,7 +53,7 @@ export class Drawing extends StateNode {
|
||||||
override onEnter = (info: TLPointerEventInfo) => {
|
override onEnter = (info: TLPointerEventInfo) => {
|
||||||
this.markId = null
|
this.markId = null
|
||||||
this.info = info
|
this.info = info
|
||||||
this.canDraw = !this.editor.isMenuOpen
|
this.canDraw = !this.editor.getIsMenuOpen()
|
||||||
this.lastRecordedPoint = this.editor.inputs.currentPagePoint.clone()
|
this.lastRecordedPoint = this.editor.inputs.currentPagePoint.clone()
|
||||||
if (this.canDraw) {
|
if (this.canDraw) {
|
||||||
this.startShape()
|
this.startShape()
|
||||||
|
|
|
@ -84,7 +84,7 @@ export class EmbedShapeUtil extends BaseBoxShapeUtil<TLEmbedShape> {
|
||||||
const isHoveringWhileEditingSameShape = useValue(
|
const isHoveringWhileEditingSameShape = useValue(
|
||||||
'is hovering',
|
'is hovering',
|
||||||
() => {
|
() => {
|
||||||
const { editingShapeId, hoveredShapeId } = this.editor.currentPageState
|
const { editingShapeId, hoveredShapeId } = this.editor.getCurrentPageState()
|
||||||
|
|
||||||
if (editingShapeId && hoveredShapeId !== editingShapeId) {
|
if (editingShapeId && hoveredShapeId !== editingShapeId) {
|
||||||
const editingShape = this.editor.getShape(editingShapeId)
|
const editingShape = this.editor.getShape(editingShapeId)
|
||||||
|
|
|
@ -21,7 +21,7 @@ describe(FrameShapeTool, () => {
|
||||||
|
|
||||||
expect(editor.currentPageShapes.length).toBe(1)
|
expect(editor.currentPageShapes.length).toBe(1)
|
||||||
expect(editor.currentPageShapes[0]?.type).toBe('frame')
|
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()
|
editor.undo()
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ describe(FrameShapeTool, () => {
|
||||||
|
|
||||||
expect(editor.currentPageShapes.length).toBe(1)
|
expect(editor.currentPageShapes.length).toBe(1)
|
||||||
expect(editor.currentPageShapes[0]?.type).toBe('frame')
|
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()
|
editor.undo()
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ describe(GeoShapeTool, () => {
|
||||||
|
|
||||||
expect(editor.currentPageShapes.length).toBe(1)
|
expect(editor.currentPageShapes.length).toBe(1)
|
||||||
expect(editor.currentPageShapes[0]?.type).toBe('geo')
|
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()
|
editor.undo()
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ describe(GeoShapeTool, () => {
|
||||||
|
|
||||||
expect(editor.currentPageShapes.length).toBe(1)
|
expect(editor.currentPageShapes.length).toBe(1)
|
||||||
expect(editor.currentPageShapes[0]?.type).toBe('geo')
|
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()
|
editor.undo()
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ beforeEach(() => {
|
||||||
editor = new TestEditor()
|
editor = new TestEditor()
|
||||||
editor
|
editor
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.deleteShapes(editor.selectedShapeIds)
|
.deleteShapes(editor.getSelectedShapeIds())
|
||||||
.createShapes([
|
.createShapes([
|
||||||
{
|
{
|
||||||
id: id,
|
id: id,
|
||||||
|
@ -149,7 +149,7 @@ describe('Misc', () => {
|
||||||
|
|
||||||
it('nudges', () => {
|
it('nudges', () => {
|
||||||
editor.select(id)
|
editor.select(id)
|
||||||
editor.nudgeShapes(editor.selectedShapeIds, { x: 1, y: 0 })
|
editor.nudgeShapes(editor.getSelectedShapeIds(), { x: 1, y: 0 })
|
||||||
|
|
||||||
editor.expectShapeToMatch({
|
editor.expectShapeToMatch({
|
||||||
id: id,
|
id: id,
|
||||||
|
@ -157,7 +157,7 @@ describe('Misc', () => {
|
||||||
y: 150,
|
y: 150,
|
||||||
})
|
})
|
||||||
|
|
||||||
editor.nudgeShapes(editor.selectedShapeIds, { x: 0, y: 10 })
|
editor.nudgeShapes(editor.getSelectedShapeIds(), { x: 0, y: 10 })
|
||||||
|
|
||||||
editor.expectShapeToMatch({
|
editor.expectShapeToMatch({
|
||||||
id: id,
|
id: id,
|
||||||
|
@ -176,12 +176,12 @@ describe('Misc', () => {
|
||||||
editor.select(boxID, id)
|
editor.select(boxID, id)
|
||||||
|
|
||||||
expect(editor.getShapePageBounds(box)!.maxX).not.toEqual(editor.getShapePageBounds(line)!.maxX)
|
expect(editor.getShapePageBounds(box)!.maxX).not.toEqual(editor.getShapePageBounds(line)!.maxX)
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'right')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'right')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
expect(editor.getShapePageBounds(box)!.maxX).toEqual(editor.getShapePageBounds(line)!.maxX)
|
expect(editor.getShapePageBounds(box)!.maxX).toEqual(editor.getShapePageBounds(line)!.maxX)
|
||||||
|
|
||||||
expect(editor.getShapePageBounds(box)!.maxY).not.toEqual(editor.getShapePageBounds(line)!.maxY)
|
expect(editor.getShapePageBounds(box)!.maxY).not.toEqual(editor.getShapePageBounds(line)!.maxY)
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'bottom')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'bottom')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
expect(editor.getShapePageBounds(box)!.maxY).toEqual(editor.getShapePageBounds(line)!.maxY)
|
expect(editor.getShapePageBounds(box)!.maxY).toEqual(editor.getShapePageBounds(line)!.maxY)
|
||||||
})
|
})
|
||||||
|
@ -213,7 +213,7 @@ describe('Misc', () => {
|
||||||
const duplicate = ids.filter((i) => i !== id)[0]
|
const duplicate = ids.filter((i) => i !== id)[0]
|
||||||
editor.select(duplicate)
|
editor.select(duplicate)
|
||||||
|
|
||||||
editor.deleteShapes(editor.selectedShapeIds)
|
editor.deleteShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
ids = Array.from(editor.currentPageShapeIds.values())
|
ids = Array.from(editor.currentPageShapeIds.values())
|
||||||
expect(ids.length).toEqual(1)
|
expect(ids.length).toEqual(1)
|
||||||
|
|
|
@ -21,7 +21,7 @@ describe(NoteShapeTool, () => {
|
||||||
|
|
||||||
expect(editor.currentPageShapes.length).toBe(1)
|
expect(editor.currentPageShapes.length).toBe(1)
|
||||||
expect(editor.currentPageShapes[0]?.type).toBe('note')
|
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
|
editor.cancel() // leave edit mode
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ describe(NoteShapeTool, () => {
|
||||||
|
|
||||||
expect(editor.currentPageShapes.length).toBe(1)
|
expect(editor.currentPageShapes.length).toBe(1)
|
||||||
expect(editor.currentPageShapes[0]?.type).toBe('note')
|
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()
|
editor.undo()
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ export class Pointing extends StateNode {
|
||||||
shape = {} as TLNoteShape
|
shape = {} as TLNoteShape
|
||||||
|
|
||||||
override onEnter = () => {
|
override onEnter = () => {
|
||||||
this.wasFocusedOnEnter = !this.editor.isMenuOpen
|
this.wasFocusedOnEnter = !this.editor.getIsMenuOpen()
|
||||||
if (this.wasFocusedOnEnter) {
|
if (this.wasFocusedOnEnter) {
|
||||||
this.shape = this.createShape()
|
this.shape = this.createShape()
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ export class Erasing extends StateNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
complete() {
|
complete() {
|
||||||
this.editor.deleteShapes(this.editor.currentPageState.erasingShapeIds)
|
this.editor.deleteShapes(this.editor.getCurrentPageState().erasingShapeIds)
|
||||||
this.editor.setErasingShapes([])
|
this.editor.setErasingShapes([])
|
||||||
this.parent.transition('idle', {})
|
this.parent.transition('idle', {})
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ export class SelectTool extends StateNode {
|
||||||
]
|
]
|
||||||
|
|
||||||
override onExit = () => {
|
override onExit = () => {
|
||||||
if (this.editor.currentPageState.editingShapeId) {
|
if (this.editor.getCurrentPageState().editingShapeId) {
|
||||||
this.editor.setEditingShape(null)
|
this.editor.setEditingShape(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ export class Brushing extends StateNode {
|
||||||
)
|
)
|
||||||
|
|
||||||
this.info = info
|
this.info = info
|
||||||
this.initialSelectedShapeIds = this.editor.selectedShapeIds.slice()
|
this.initialSelectedShapeIds = this.editor.getSelectedShapeIds().slice()
|
||||||
this.initialStartShape = this.editor.getShapesAtPoint(currentPagePoint)[0]
|
this.initialStartShape = this.editor.getShapesAtPoint(currentPagePoint)[0]
|
||||||
this.onPointerMove()
|
this.onPointerMove()
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ export class Idle extends StateNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
override onPointerDown: TLEventHandlers['onPointerDown'] = (info) => {
|
override onPointerDown: TLEventHandlers['onPointerDown'] = (info) => {
|
||||||
if (this.editor.isMenuOpen) return
|
if (this.editor.getIsMenuOpen()) return
|
||||||
|
|
||||||
if (info.ctrlKey) {
|
if (info.ctrlKey) {
|
||||||
this.cancel()
|
this.cancel()
|
||||||
|
|
|
@ -20,7 +20,7 @@ export class EditingShape extends StateNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
override onExit = () => {
|
override onExit = () => {
|
||||||
const { editingShapeId } = this.editor.currentPageState
|
const { editingShapeId } = this.editor.getCurrentPageState()
|
||||||
if (!editingShapeId) return
|
if (!editingShapeId) return
|
||||||
|
|
||||||
// Clear the editing shape
|
// Clear the editing shape
|
||||||
|
|
|
@ -35,7 +35,7 @@ export class Idle extends StateNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
override onPointerDown: TLEventHandlers['onPointerDown'] = (info) => {
|
override onPointerDown: TLEventHandlers['onPointerDown'] = (info) => {
|
||||||
if (this.editor.isMenuOpen) return
|
if (this.editor.getIsMenuOpen()) return
|
||||||
|
|
||||||
const shouldEnterCropMode = info.ctrlKey && getShouldEnterCropMode(this.editor)
|
const shouldEnterCropMode = info.ctrlKey && getShouldEnterCropMode(this.editor)
|
||||||
|
|
||||||
|
@ -66,9 +66,9 @@ export class Idle extends StateNode {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const selectedShapeIds = this.editor.getSelectedShapeIds()
|
||||||
const {
|
const {
|
||||||
onlySelectedShape,
|
onlySelectedShape,
|
||||||
selectedShapeIds,
|
|
||||||
inputs: { currentPagePoint },
|
inputs: { currentPagePoint },
|
||||||
} = this.editor
|
} = this.editor
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ export class Idle extends StateNode {
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
const { hoveredShape } = this.editor
|
const { hoveredShape } = this.editor
|
||||||
if (hoveredShape && !this.editor.selectedShapeIds.includes(hoveredShape.id)) {
|
if (hoveredShape && !this.editor.getSelectedShapeIds().includes(hoveredShape.id)) {
|
||||||
this.onPointerDown({
|
this.onPointerDown({
|
||||||
...info,
|
...info,
|
||||||
shape: hoveredShape,
|
shape: hoveredShape,
|
||||||
|
@ -345,9 +345,9 @@ export class Idle extends StateNode {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const selectedShapeIds = this.editor.getSelectedShapeIds()
|
||||||
const {
|
const {
|
||||||
onlySelectedShape,
|
onlySelectedShape,
|
||||||
selectedShapeIds,
|
|
||||||
inputs: { currentPagePoint },
|
inputs: { currentPagePoint },
|
||||||
} = this.editor
|
} = this.editor
|
||||||
|
|
||||||
|
@ -369,7 +369,7 @@ export class Idle extends StateNode {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'shape': {
|
case 'shape': {
|
||||||
const { selectedShapeIds } = this.editor.currentPageState
|
const { selectedShapeIds } = this.editor.getCurrentPageState()
|
||||||
const { shape } = info
|
const { shape } = info
|
||||||
|
|
||||||
const targetShape = this.editor.getOutermostSelectableShape(
|
const targetShape = this.editor.getOutermostSelectableShape(
|
||||||
|
@ -389,7 +389,7 @@ export class Idle extends StateNode {
|
||||||
override onCancel: TLEventHandlers['onCancel'] = () => {
|
override onCancel: TLEventHandlers['onCancel'] = () => {
|
||||||
if (
|
if (
|
||||||
this.editor.focusedGroupId !== this.editor.currentPageId &&
|
this.editor.focusedGroupId !== this.editor.currentPageId &&
|
||||||
this.editor.selectedShapeIds.length > 0
|
this.editor.getSelectedShapeIds().length > 0
|
||||||
) {
|
) {
|
||||||
this.editor.popFocusedGroupId()
|
this.editor.popFocusedGroupId()
|
||||||
} else {
|
} else {
|
||||||
|
@ -544,7 +544,7 @@ export class Idle extends StateNode {
|
||||||
? MAJOR_NUDGE_FACTOR
|
? MAJOR_NUDGE_FACTOR
|
||||||
: MINOR_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) {
|
private canInteractWithShapeInReadOnly(shape: TLShape) {
|
||||||
|
|
|
@ -8,7 +8,7 @@ export class PointingCanvas extends StateNode {
|
||||||
const { inputs } = this.editor
|
const { inputs } = this.editor
|
||||||
|
|
||||||
if (!inputs.shiftKey) {
|
if (!inputs.shiftKey) {
|
||||||
if (this.editor.selectedShapeIds.length > 0) {
|
if (this.editor.getSelectedShapeIds().length > 0) {
|
||||||
this.editor.mark('selecting none')
|
this.editor.mark('selecting none')
|
||||||
this.editor.selectNone()
|
this.editor.selectNone()
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,8 @@ export class PointingShape extends StateNode {
|
||||||
didSelectOnEnter = false
|
didSelectOnEnter = false
|
||||||
|
|
||||||
override onEnter = (info: TLPointerEventInfo & { target: 'shape' }) => {
|
override onEnter = (info: TLPointerEventInfo & { target: 'shape' }) => {
|
||||||
|
const selectedShapeIds = this.editor.getSelectedShapeIds()
|
||||||
const {
|
const {
|
||||||
selectedShapeIds,
|
|
||||||
focusedGroupId,
|
focusedGroupId,
|
||||||
selectionRotatedPageBounds: selectionBounds,
|
selectionRotatedPageBounds: selectionBounds,
|
||||||
inputs: { currentPagePoint, shiftKey, altKey },
|
inputs: { currentPagePoint, shiftKey, altKey },
|
||||||
|
@ -60,10 +60,10 @@ export class PointingShape extends StateNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
override onPointerUp: TLEventHandlers['onPointerUp'] = (info) => {
|
override onPointerUp: TLEventHandlers['onPointerUp'] = (info) => {
|
||||||
|
const selectedShapeIds = this.editor.getSelectedShapeIds()
|
||||||
const {
|
const {
|
||||||
zoomLevel,
|
zoomLevel,
|
||||||
focusedGroupId,
|
focusedGroupId,
|
||||||
selectedShapeIds,
|
|
||||||
inputs: { currentPagePoint, shiftKey },
|
inputs: { currentPagePoint, shiftKey },
|
||||||
} = this.editor
|
} = this.editor
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ export class PointingShape extends StateNode {
|
||||||
|
|
||||||
this.editor.mark('shift deselecting on pointer up')
|
this.editor.mark('shift deselecting on pointer up')
|
||||||
this.editor.setSelectedShapes([
|
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,
|
outermostSelectableShape.id,
|
||||||
])
|
])
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -364,8 +364,8 @@ export class Resizing extends StateNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
_createSnapshot = () => {
|
_createSnapshot = () => {
|
||||||
|
const selectedShapeIds = this.editor.getSelectedShapeIds()
|
||||||
const {
|
const {
|
||||||
selectedShapeIds,
|
|
||||||
selectionRotation,
|
selectionRotation,
|
||||||
inputs: { originPagePoint },
|
inputs: { originPagePoint },
|
||||||
} = this.editor
|
} = this.editor
|
||||||
|
|
|
@ -26,7 +26,7 @@ export class ScribbleBrushing extends StateNode {
|
||||||
|
|
||||||
override onEnter = () => {
|
override onEnter = () => {
|
||||||
this.initialSelectedShapeIds = new Set<TLShapeId>(
|
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.newlySelectedShapeIds = new Set<TLShapeId>()
|
||||||
this.size = 0
|
this.size = 0
|
||||||
|
|
|
@ -132,7 +132,7 @@ export class Translating extends StateNode {
|
||||||
this.markId = 'translating'
|
this.markId = 'translating'
|
||||||
this.editor.mark(this.markId)
|
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.snapshot = getTranslatingSnapshot(this.editor)
|
||||||
this.handleStart()
|
this.handleStart()
|
||||||
|
@ -285,7 +285,7 @@ function getTranslatingSnapshot(editor: Editor) {
|
||||||
const pagePoints: Vec2d[] = []
|
const pagePoints: Vec2d[] = []
|
||||||
|
|
||||||
const shapeSnapshots = compact(
|
const shapeSnapshots = compact(
|
||||||
editor.selectedShapeIds.map((id): null | MovingShapeSnapshot => {
|
editor.getSelectedShapeIds().map((id): null | MovingShapeSnapshot => {
|
||||||
const shape = editor.getShape(id)
|
const shape = editor.getShape(id)
|
||||||
if (!shape) return null
|
if (!shape) return null
|
||||||
movingShapes.push(shape)
|
movingShapes.push(shape)
|
||||||
|
@ -312,8 +312,8 @@ function getTranslatingSnapshot(editor: Editor) {
|
||||||
shapeSnapshots,
|
shapeSnapshots,
|
||||||
initialPageBounds: editor.selectionPageBounds!,
|
initialPageBounds: editor.selectionPageBounds!,
|
||||||
initialSnapPoints:
|
initialSnapPoints:
|
||||||
editor.selectedShapeIds.length === 1
|
editor.getSelectedShapeIds().length === 1
|
||||||
? editor.snaps.snapPointsCache.get(editor.selectedShapeIds[0])!
|
? editor.snaps.snapPointsCache.get(editor.getSelectedShapeIds()[0])!
|
||||||
: editor.selectionPageBounds
|
: editor.selectionPageBounds
|
||||||
? editor.selectionPageBounds.snapPoints.map((p, i) => ({
|
? editor.selectionPageBounds.snapPoints.map((p, i) => ({
|
||||||
id: 'selection:' + i,
|
id: 'selection:' + i,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Editor, HIT_TEST_MARGIN, TLShape, isShapeId } from '@tldraw/editor'
|
import { Editor, HIT_TEST_MARGIN, TLShape, isShapeId } from '@tldraw/editor'
|
||||||
|
|
||||||
export function selectOnCanvasPointerUp(editor: Editor) {
|
export function selectOnCanvasPointerUp(editor: Editor) {
|
||||||
const { selectedShapeIds } = editor
|
const selectedShapeIds = editor.getSelectedShapeIds()
|
||||||
const { shiftKey, altKey, currentPagePoint } = editor.inputs
|
const { shiftKey, altKey, currentPagePoint } = editor.inputs
|
||||||
|
|
||||||
const hitShape = editor.getShapeAtPoint(currentPagePoint, {
|
const hitShape = editor.getShapeAtPoint(currentPagePoint, {
|
||||||
|
|
|
@ -20,7 +20,7 @@ export function updateHoveredId(editor: Editor) {
|
||||||
} else {
|
} else {
|
||||||
if (
|
if (
|
||||||
outermostShape.id === editor.focusedGroupId ||
|
outermostShape.id === editor.focusedGroupId ||
|
||||||
editor.selectedShapeIds.includes(outermostShape.id)
|
editor.getSelectedShapeIds().includes(outermostShape.id)
|
||||||
) {
|
) {
|
||||||
shapeToHover = hitShape
|
shapeToHover = hitShape
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -15,7 +15,7 @@ export const DuplicateButton = track(function DuplicateButton() {
|
||||||
icon={action.icon}
|
icon={action.icon}
|
||||||
type="icon"
|
type="icon"
|
||||||
onClick={() => action.onSelect('quick-actions')}
|
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!)}`}
|
title={`${msg(action.label!)} ${kbdStr(action.kbd!)}`}
|
||||||
smallIcon
|
smallIcon
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -36,7 +36,7 @@ export const MoveToPageMenu = track(function MoveToPageMenu() {
|
||||||
disabled={currentPageId === page.id}
|
disabled={currentPageId === page.id}
|
||||||
onSelect={() => {
|
onSelect={() => {
|
||||||
editor.mark('move_shapes_to_page')
|
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)
|
const toPage = editor.getPage(page.id)
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ export const MoveToPageMenu = track(function MoveToPageMenu() {
|
||||||
key="new-page"
|
key="new-page"
|
||||||
onSelect={() => {
|
onSelect={() => {
|
||||||
const newPageId = PageRecordType.createId()
|
const newPageId = PageRecordType.createId()
|
||||||
const ids = editor.selectedShapeIds
|
const ids = editor.getSelectedShapeIds()
|
||||||
editor.batch(() => {
|
editor.batch(() => {
|
||||||
editor.mark('move_shapes_to_page')
|
editor.mark('move_shapes_to_page')
|
||||||
editor.createPage({ name: 'Page', id: newPageId })
|
editor.createPage({ name: 'Page', id: newPageId })
|
||||||
|
|
|
@ -178,7 +178,10 @@ export class MinimapManager {
|
||||||
const { editor, canvasScreenBounds, canvasPageBounds, contentPageBounds, contentScreenBounds } =
|
const { editor, canvasScreenBounds, canvasPageBounds, contentPageBounds, contentScreenBounds } =
|
||||||
this
|
this
|
||||||
const { width: cw, height: ch } = canvasScreenBounds
|
const { width: cw, height: ch } = canvasScreenBounds
|
||||||
const { viewportPageBounds, selectedShapeIds } = editor
|
|
||||||
|
const selectedShapeIds = this.editor.getSelectedShapeIds()
|
||||||
|
|
||||||
|
const { viewportPageBounds } = editor
|
||||||
|
|
||||||
if (!cvs || !pageBounds) {
|
if (!cvs || !pageBounds) {
|
||||||
return
|
return
|
||||||
|
|
|
@ -13,7 +13,7 @@ export const ZoomMenu = track(function ZoomMenu() {
|
||||||
|
|
||||||
const zoom = editor.zoomLevel
|
const zoom = editor.zoomLevel
|
||||||
const hasShapes = editor.currentPageShapeIds.size > 0
|
const hasShapes = editor.currentPageShapeIds.size > 0
|
||||||
const hasSelected = editor.selectedShapeIds.length > 0
|
const hasSelected = editor.getSelectedShapeIds().length > 0
|
||||||
const isZoomedTo100 = editor.zoomLevel === 1
|
const isZoomedTo100 = editor.zoomLevel === 1
|
||||||
|
|
||||||
const handleDoubleClick = React.useCallback(() => {
|
const handleDoubleClick = React.useCallback(() => {
|
||||||
|
|
|
@ -20,7 +20,7 @@ export const TrashButton = track(function TrashButton() {
|
||||||
icon={action.icon}
|
icon={action.icon}
|
||||||
type="icon"
|
type="icon"
|
||||||
onClick={() => action.onSelect('quick-actions')}
|
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!)}`}
|
title={`${msg(action.label!)} ${kbdStr(action.kbd!)}`}
|
||||||
smallIcon
|
smallIcon
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -137,7 +137,7 @@ export function menuItem(
|
||||||
}
|
}
|
||||||
|
|
||||||
function shapesWithUnboundArrows(editor: Editor) {
|
function shapesWithUnboundArrows(editor: Editor) {
|
||||||
const { selectedShapeIds } = editor
|
const selectedShapeIds = editor.getSelectedShapeIds()
|
||||||
const selectedShapes = selectedShapeIds.map((id) => {
|
const selectedShapes = selectedShapeIds.map((id) => {
|
||||||
return editor.getShape(id)
|
return editor.getShape(id)
|
||||||
})
|
})
|
||||||
|
@ -174,7 +174,7 @@ export const useAllowUngroup = () => {
|
||||||
const editor = useEditor()
|
const editor = useEditor()
|
||||||
return useValue(
|
return useValue(
|
||||||
'allowUngroup',
|
'allowUngroup',
|
||||||
() => editor.selectedShapeIds.some((id) => editor.getShape(id)?.type === 'group'),
|
() => editor.getSelectedShapeIds().some((id) => editor.getShape(id)?.type === 'group'),
|
||||||
[editor]
|
[editor]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasSelectedShapes() {
|
function hasSelectedShapes() {
|
||||||
return editor.selectedShapeIds.length > 0
|
return editor.getSelectedShapeIds().length > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
const actions = makeActions([
|
const actions = makeActions([
|
||||||
|
@ -163,7 +163,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
|
||||||
readonlyOk: true,
|
readonlyOk: true,
|
||||||
onSelect(source) {
|
onSelect(source) {
|
||||||
trackEvent('export-as', { format: 'svg', 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,
|
readonlyOk: true,
|
||||||
onSelect(source) {
|
onSelect(source) {
|
||||||
trackEvent('export-as', { format: 'png', 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,
|
readonlyOk: true,
|
||||||
onSelect(source) {
|
onSelect(source) {
|
||||||
trackEvent('export-as', { format: 'json', 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,
|
readonlyOk: true,
|
||||||
onSelect(source) {
|
onSelect(source) {
|
||||||
trackEvent('copy-as', { format: 'svg', 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,
|
readonlyOk: true,
|
||||||
onSelect(source) {
|
onSelect(source) {
|
||||||
trackEvent('copy-as', { format: 'png', 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,
|
readonlyOk: true,
|
||||||
onSelect(source) {
|
onSelect(source) {
|
||||||
trackEvent('copy-as', { format: 'json', 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,
|
readonlyOk: true,
|
||||||
onSelect(source) {
|
onSelect(source) {
|
||||||
trackEvent('open-embed-link', { source })
|
trackEvent('open-embed-link', { source })
|
||||||
const ids = editor.selectedShapeIds
|
const ids = editor.getSelectedShapeIds()
|
||||||
const warnMsg = 'No embed shapes selected'
|
const warnMsg = 'No embed shapes selected'
|
||||||
if (ids.length !== 1) {
|
if (ids.length !== 1) {
|
||||||
console.error(warnMsg)
|
console.error(warnMsg)
|
||||||
|
@ -344,7 +344,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
|
||||||
trackEvent('convert-to-embed', { source })
|
trackEvent('convert-to-embed', { source })
|
||||||
|
|
||||||
editor.batch(() => {
|
editor.batch(() => {
|
||||||
const ids = editor.selectedShapeIds
|
const ids = editor.getSelectedShapeIds()
|
||||||
const shapes = compact(ids.map((id) => editor.getShape(id)))
|
const shapes = compact(ids.map((id) => editor.getShape(id)))
|
||||||
|
|
||||||
const createList: TLShapePartial[] = []
|
const createList: TLShapePartial[] = []
|
||||||
|
@ -400,7 +400,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
|
||||||
if (mustGoBackToSelectToolFirst()) return
|
if (mustGoBackToSelectToolFirst()) return
|
||||||
|
|
||||||
trackEvent('duplicate-shapes', { source })
|
trackEvent('duplicate-shapes', { source })
|
||||||
const ids = editor.selectedShapeIds
|
const ids = editor.getSelectedShapeIds()
|
||||||
const commonBounds = Box2d.Common(compact(ids.map((id) => editor.getShapePageBounds(id))))
|
const commonBounds = Box2d.Common(compact(ids.map((id) => editor.getShapePageBounds(id))))
|
||||||
const offset = editor.getInstanceState().canMoveCamera
|
const offset = editor.getInstanceState().canMoveCamera
|
||||||
? {
|
? {
|
||||||
|
@ -427,7 +427,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
|
||||||
|
|
||||||
trackEvent('ungroup-shapes', { source })
|
trackEvent('ungroup-shapes', { source })
|
||||||
editor.mark('ungroup')
|
editor.mark('ungroup')
|
||||||
editor.ungroupShapes(editor.selectedShapeIds)
|
editor.ungroupShapes(editor.getSelectedShapeIds())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -444,10 +444,10 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
|
||||||
const { onlySelectedShape } = editor
|
const { onlySelectedShape } = editor
|
||||||
if (onlySelectedShape && editor.isShapeOfType<TLGroupShape>(onlySelectedShape, 'group')) {
|
if (onlySelectedShape && editor.isShapeOfType<TLGroupShape>(onlySelectedShape, 'group')) {
|
||||||
editor.mark('ungroup')
|
editor.mark('ungroup')
|
||||||
editor.ungroupShapes(editor.selectedShapeIds)
|
editor.ungroupShapes(editor.getSelectedShapeIds())
|
||||||
} else {
|
} else {
|
||||||
editor.mark('group')
|
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 })
|
trackEvent('align-shapes', { operation: 'left', source })
|
||||||
editor.mark('align left')
|
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 })
|
trackEvent('align-shapes', { operation: 'center-horizontal', source })
|
||||||
editor.mark('align center horizontal')
|
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 })
|
trackEvent('align-shapes', { operation: 'right', source })
|
||||||
editor.mark('align right')
|
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 })
|
trackEvent('align-shapes', { operation: 'center-vertical', source })
|
||||||
editor.mark('align center vertical')
|
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 })
|
trackEvent('align-shapes', { operation: 'top', source })
|
||||||
editor.mark('align top')
|
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 })
|
trackEvent('align-shapes', { operation: 'bottom', source })
|
||||||
editor.mark('align bottom')
|
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 })
|
trackEvent('distribute-shapes', { operation: 'horizontal', source })
|
||||||
editor.mark('distribute horizontal')
|
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 })
|
trackEvent('distribute-shapes', { operation: 'vertical', source })
|
||||||
editor.mark('distribute vertical')
|
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 })
|
trackEvent('stretch-shapes', { operation: 'horizontal', source })
|
||||||
editor.mark('stretch horizontal')
|
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 })
|
trackEvent('stretch-shapes', { operation: 'vertical', source })
|
||||||
editor.mark('stretch vertical')
|
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 })
|
trackEvent('flip-shapes', { operation: 'horizontal', source })
|
||||||
editor.mark('flip horizontal')
|
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 })
|
trackEvent('flip-shapes', { operation: 'vertical', source })
|
||||||
editor.mark('flip vertical')
|
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 })
|
trackEvent('pack-shapes', { source })
|
||||||
editor.mark('pack')
|
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 })
|
trackEvent('stack-shapes', { operation: 'vertical', source })
|
||||||
editor.mark('stack-vertical')
|
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 })
|
trackEvent('stack-shapes', { operation: 'horizontal', source })
|
||||||
editor.mark('stack-horizontal')
|
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 })
|
trackEvent('reorder-shapes', { operation: 'toFront', source })
|
||||||
editor.mark('bring to front')
|
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 })
|
trackEvent('reorder-shapes', { operation: 'forward', source })
|
||||||
editor.mark('bring forward')
|
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 })
|
trackEvent('reorder-shapes', { operation: 'backward', source })
|
||||||
editor.mark('send backward')
|
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 })
|
trackEvent('reorder-shapes', { operation: 'toBack', source })
|
||||||
editor.mark('send to back')
|
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 })
|
trackEvent('delete-shapes', { source })
|
||||||
editor.mark('delete')
|
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')
|
editor.mark('rotate-cw')
|
||||||
const offset = editor.selectionRotation % (TAU / 2)
|
const offset = editor.selectionRotation % (TAU / 2)
|
||||||
const dontUseOffset = approximately(offset, 0) || approximately(offset, 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')
|
editor.mark('rotate-ccw')
|
||||||
const offset = editor.selectionRotation % (TAU / 2)
|
const offset = editor.selectionRotation % (TAU / 2)
|
||||||
const offsetCloseToZero = approximately(offset, 0)
|
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) {
|
onSelect(source) {
|
||||||
editor.mark('locking')
|
editor.mark('locking')
|
||||||
trackEvent('toggle-lock', { source })
|
trackEvent('toggle-lock', { source })
|
||||||
editor.toggleLock(editor.selectedShapeIds)
|
editor.toggleLock(editor.getSelectedShapeIds())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
|
@ -40,7 +40,9 @@ export const ActionsMenuSchemaProvider = ({
|
||||||
const editor = useEditor()
|
const editor = useEditor()
|
||||||
const actions = useActions()
|
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 oneSelected = selectedCount > 0
|
||||||
const twoSelected = selectedCount > 1
|
const twoSelected = selectedCount > 1
|
||||||
|
|
|
@ -74,7 +74,7 @@ const INPUTS = ['input', 'select', 'textarea']
|
||||||
function disallowClipboardEvents(editor: Editor) {
|
function disallowClipboardEvents(editor: Editor) {
|
||||||
const { activeElement } = document
|
const { activeElement } = document
|
||||||
return (
|
return (
|
||||||
editor.isMenuOpen ||
|
editor.getIsMenuOpen() ||
|
||||||
(activeElement &&
|
(activeElement &&
|
||||||
(activeElement.getAttribute('contenteditable') ||
|
(activeElement.getAttribute('contenteditable') ||
|
||||||
INPUTS.indexOf(activeElement.tagName.toLowerCase()) > -1))
|
INPUTS.indexOf(activeElement.tagName.toLowerCase()) > -1))
|
||||||
|
@ -497,7 +497,7 @@ async function handleClipboardThings(editor: Editor, things: ClipboardThing[], p
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
const handleNativeOrMenuCopy = (editor: Editor) => {
|
const handleNativeOrMenuCopy = (editor: Editor) => {
|
||||||
const content = editor.getContentFromCurrentPage(editor.selectedShapeIds)
|
const content = editor.getContentFromCurrentPage(editor.getSelectedShapeIds())
|
||||||
if (!content) {
|
if (!content) {
|
||||||
if (navigator && navigator.clipboard) {
|
if (navigator && navigator.clipboard) {
|
||||||
navigator.clipboard.writeText('')
|
navigator.clipboard.writeText('')
|
||||||
|
@ -570,7 +570,7 @@ export function useMenuClipboardEvents() {
|
||||||
|
|
||||||
const copy = useCallback(
|
const copy = useCallback(
|
||||||
function onCopy(source: TLUiEventSource) {
|
function onCopy(source: TLUiEventSource) {
|
||||||
if (editor.selectedShapeIds.length === 0) return
|
if (editor.getSelectedShapeIds().length === 0) return
|
||||||
|
|
||||||
handleNativeOrMenuCopy(editor)
|
handleNativeOrMenuCopy(editor)
|
||||||
trackEvent('copy', { source })
|
trackEvent('copy', { source })
|
||||||
|
@ -580,10 +580,10 @@ export function useMenuClipboardEvents() {
|
||||||
|
|
||||||
const cut = useCallback(
|
const cut = useCallback(
|
||||||
function onCut(source: TLUiEventSource) {
|
function onCut(source: TLUiEventSource) {
|
||||||
if (editor.selectedShapeIds.length === 0) return
|
if (editor.getSelectedShapeIds().length === 0) return
|
||||||
|
|
||||||
handleNativeOrMenuCopy(editor)
|
handleNativeOrMenuCopy(editor)
|
||||||
editor.deleteShapes(editor.selectedShapeIds)
|
editor.deleteShapes(editor.getSelectedShapeIds())
|
||||||
trackEvent('cut', { source })
|
trackEvent('cut', { source })
|
||||||
},
|
},
|
||||||
[editor, trackEvent]
|
[editor, trackEvent]
|
||||||
|
@ -633,7 +633,7 @@ export function useNativeClipboardEvents() {
|
||||||
if (!appIsFocused) return
|
if (!appIsFocused) return
|
||||||
const copy = () => {
|
const copy = () => {
|
||||||
if (
|
if (
|
||||||
editor.selectedShapeIds.length === 0 ||
|
editor.getSelectedShapeIds().length === 0 ||
|
||||||
editor.editingShapeId !== null ||
|
editor.editingShapeId !== null ||
|
||||||
disallowClipboardEvents(editor)
|
disallowClipboardEvents(editor)
|
||||||
)
|
)
|
||||||
|
@ -644,13 +644,13 @@ export function useNativeClipboardEvents() {
|
||||||
|
|
||||||
function cut() {
|
function cut() {
|
||||||
if (
|
if (
|
||||||
editor.selectedShapeIds.length === 0 ||
|
editor.getSelectedShapeIds().length === 0 ||
|
||||||
editor.editingShapeId !== null ||
|
editor.editingShapeId !== null ||
|
||||||
disallowClipboardEvents(editor)
|
disallowClipboardEvents(editor)
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
handleNativeOrMenuCopy(editor)
|
handleNativeOrMenuCopy(editor)
|
||||||
editor.deleteShapes(editor.selectedShapeIds)
|
editor.deleteShapes(editor.getSelectedShapeIds())
|
||||||
trackEvent('cut', { source: 'kbd' })
|
trackEvent('cut', { source: 'kbd' })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ export const TLUiContextMenuSchemaProvider = track(function TLUiContextMenuSchem
|
||||||
|
|
||||||
const onlyFlippableShapeSelected = useOnlyFlippableShape()
|
const onlyFlippableShapeSelected = useOnlyFlippableShape()
|
||||||
|
|
||||||
const selectedCount = editor.selectedShapeIds.length
|
const selectedCount = editor.getSelectedShapeIds().length
|
||||||
|
|
||||||
const oneSelected = selectedCount > 0
|
const oneSelected = selectedCount > 0
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ export function useCopyAs() {
|
||||||
//
|
//
|
||||||
// this is fine for navigator.clipboard.write, but for fallbacks it's a
|
// this is fine for navigator.clipboard.write, but for fallbacks it's a
|
||||||
// little awkward.
|
// little awkward.
|
||||||
function copyAs(ids: TLShapeId[] = editor.selectedShapeIds, format: TLCopyType = 'svg') {
|
function copyAs(ids: TLShapeId[] = editor.getSelectedShapeIds(), format: TLCopyType = 'svg') {
|
||||||
if (ids.length === 0) {
|
if (ids.length === 0) {
|
||||||
ids = [...editor.currentPageShapeIds]
|
ids = [...editor.currentPageShapeIds]
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ export function useExportAs() {
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
async function exportAs(
|
async function exportAs(
|
||||||
ids: TLShapeId[] = editor.selectedShapeIds,
|
ids: TLShapeId[] = editor.getSelectedShapeIds(),
|
||||||
format: TLExportType = 'png'
|
format: TLExportType = 'png'
|
||||||
) {
|
) {
|
||||||
if (ids.length === 0) {
|
if (ids.length === 0) {
|
||||||
|
|
|
@ -37,7 +37,7 @@ export const HelpMenuSchemaProvider = track(function HelpMenuSchemaProvider({
|
||||||
const editor = useEditor()
|
const editor = useEditor()
|
||||||
const actions = useActions()
|
const actions = useActions()
|
||||||
|
|
||||||
const selectedCount = editor.selectedShapeIds.length
|
const selectedCount = editor.getSelectedShapeIds().length
|
||||||
|
|
||||||
const oneSelected = selectedCount > 0
|
const oneSelected = selectedCount > 0
|
||||||
const twoSelected = selectedCount > 1
|
const twoSelected = selectedCount > 1
|
||||||
|
|
|
@ -37,7 +37,7 @@ export function useKeyboardShortcuts() {
|
||||||
// Add hotkeys for actions and tools.
|
// Add hotkeys for actions and tools.
|
||||||
// Except those that in SKIP_KBDS!
|
// Except those that in SKIP_KBDS!
|
||||||
const areShortcutsDisabled = () =>
|
const areShortcutsDisabled = () =>
|
||||||
editor.isMenuOpen || editor.editingShapeId !== null || editor.crashingError
|
editor.getIsMenuOpen() || editor.editingShapeId !== null || editor.crashingError
|
||||||
|
|
||||||
for (const action of Object.values(actions)) {
|
for (const action of Object.values(actions)) {
|
||||||
if (!action.kbd) continue
|
if (!action.kbd) continue
|
||||||
|
|
|
@ -64,7 +64,9 @@ export function TLUiMenuSchemaProvider({ overrides, children }: TLUiMenuSchemaPr
|
||||||
|
|
||||||
const emptyPage = useValue('emptyPage', () => editor.currentPageShapeIds.size === 0, [editor])
|
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 noneSelected = selectedCount === 0
|
||||||
const oneSelected = selectedCount > 0
|
const oneSelected = selectedCount > 0
|
||||||
const twoSelected = selectedCount > 1
|
const twoSelected = selectedCount > 1
|
||||||
|
|
|
@ -171,7 +171,8 @@ export function usePrint() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { pages, currentPageId, selectedShapeIds } = editor
|
const selectedShapeIds = editor.getSelectedShapeIds()
|
||||||
|
const { pages, currentPageId } = editor
|
||||||
|
|
||||||
const preserveAspectRatio = 'xMidYMid meet'
|
const preserveAspectRatio = 'xMidYMid meet'
|
||||||
|
|
||||||
|
@ -182,7 +183,7 @@ export function usePrint() {
|
||||||
preserveAspectRatio,
|
preserveAspectRatio,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (editor.selectedShapeIds.length > 0) {
|
if (editor.getSelectedShapeIds().length > 0) {
|
||||||
// Print the selected ids from the current page
|
// Print the selected ids from the current page
|
||||||
const svg = await editor.getSvg(selectedShapeIds, svgOpts)
|
const svg = await editor.getSvg(selectedShapeIds, svgOpts)
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,10 @@ export function useRelevantStyles(): {
|
||||||
'getRelevantStyles',
|
'getRelevantStyles',
|
||||||
() => {
|
() => {
|
||||||
const styles = new SharedStyleMap(editor.sharedStyles)
|
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) {
|
for (const style of selectToolStyles) {
|
||||||
styles.applyValue(style, editor.getStyleForNextShape(style))
|
styles.applyValue(style, editor.getStyleForNextShape(style))
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ export function buildFromV1Document(editor: Editor, document: LegacyTldrawDocume
|
||||||
|
|
||||||
// Delete all of the shapes on the current page
|
// Delete all of the shapes on the current page
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.deleteShapes(editor.selectedShapeIds)
|
editor.deleteShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
// Create assets
|
// Create assets
|
||||||
const v1AssetIdsToV2AssetIds = new Map<string, TLAssetId>()
|
const v1AssetIdsToV2AssetIds = new Map<string, TLAssetId>()
|
||||||
|
|
|
@ -118,15 +118,15 @@ describe('shapes that are moved to another page', () => {
|
||||||
describe("should be excluded from the previous page's selectedShapeIds", () => {
|
describe("should be excluded from the previous page's selectedShapeIds", () => {
|
||||||
test('[boxes]', () => {
|
test('[boxes]', () => {
|
||||||
editor.setSelectedShapes([ids.box1, ids.box2, ids.box3])
|
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()
|
moveShapesToPage2()
|
||||||
expect(editor.selectedShapeIds).toEqual([])
|
expect(editor.getSelectedShapeIds()).toEqual([])
|
||||||
})
|
})
|
||||||
test('[frame that does not move]', () => {
|
test('[frame that does not move]', () => {
|
||||||
editor.setSelectedShapes([ids.frame1])
|
editor.setSelectedShapes([ids.frame1])
|
||||||
expect(editor.selectedShapeIds).toEqual([ids.frame1])
|
expect(editor.getSelectedShapeIds()).toEqual([ids.frame1])
|
||||||
moveShapesToPage2()
|
moveShapesToPage2()
|
||||||
expect(editor.selectedShapeIds).toEqual([ids.frame1])
|
expect(editor.getSelectedShapeIds()).toEqual([ids.frame1])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -15,7 +15,7 @@ beforeEach(() => {
|
||||||
editor = new TestEditor()
|
editor = new TestEditor()
|
||||||
editor
|
editor
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.deleteShapes(editor.selectedShapeIds)
|
.deleteShapes(editor.getSelectedShapeIds())
|
||||||
.createShapes([{ id: ids.box1, type: 'geo', x: 100, y: 100, props: { w: 100, h: 100 } }])
|
.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:
|
// shift-alt-drag the original, we shouldn't duplicate the copy too:
|
||||||
editor.pointerDown(150, 150, { target: 'shape', shape })
|
editor.pointerDown(150, 150, { target: 'shape', shape })
|
||||||
expect(editor.selectedShapeIds).toStrictEqual([ids.box1])
|
expect(editor.getSelectedShapeIds()).toStrictEqual([ids.box1])
|
||||||
editor.pointerMove(250, 150)
|
editor.pointerMove(250, 150)
|
||||||
editor.pointerUp()
|
editor.pointerUp()
|
||||||
expect(editor.currentPageShapes.length).toStrictEqual(3)
|
expect(editor.currentPageShapes.length).toStrictEqual(3)
|
||||||
|
@ -170,7 +170,7 @@ describe('When double clicking a shape', () => {
|
||||||
it('begins editing a geo shapes label', () => {
|
it('begins editing a geo shapes label', () => {
|
||||||
editor
|
editor
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.deleteShapes(editor.selectedShapeIds)
|
.deleteShapes(editor.getSelectedShapeIds())
|
||||||
.selectNone()
|
.selectNone()
|
||||||
.createShapes([{ id: createShapeId(), type: 'geo' }])
|
.createShapes([{ id: createShapeId(), type: 'geo' }])
|
||||||
.doubleClick(50, 50, { target: 'shape', shape: editor.currentPageShapes[0] })
|
.doubleClick(50, 50, { target: 'shape', shape: editor.currentPageShapes[0] })
|
||||||
|
@ -183,7 +183,7 @@ describe('When pressing enter on a selected shape', () => {
|
||||||
const id = createShapeId()
|
const id = createShapeId()
|
||||||
editor
|
editor
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.deleteShapes(editor.selectedShapeIds)
|
.deleteShapes(editor.getSelectedShapeIds())
|
||||||
.selectNone()
|
.selectNone()
|
||||||
.createShapes([{ id, type: 'geo' }])
|
.createShapes([{ id, type: 'geo' }])
|
||||||
.select(id)
|
.select(id)
|
||||||
|
@ -214,7 +214,7 @@ describe('When double clicking the selection edge', () => {
|
||||||
const id = createShapeId()
|
const id = createShapeId()
|
||||||
editor
|
editor
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.deleteShapes(editor.selectedShapeIds)
|
.deleteShapes(editor.getSelectedShapeIds())
|
||||||
.selectNone()
|
.selectNone()
|
||||||
.createShapes([{ id, type: 'text', x: 100, y: 100, props: { scale: 2, text: 'hello' } }])
|
.createShapes([{ id, type: 'text', x: 100, y: 100, props: { scale: 2, text: 'hello' } }])
|
||||||
.select(id)
|
.select(id)
|
||||||
|
@ -227,7 +227,7 @@ describe('When double clicking the selection edge', () => {
|
||||||
const id = createShapeId()
|
const id = createShapeId()
|
||||||
editor
|
editor
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.deleteShapes(editor.selectedShapeIds)
|
.deleteShapes(editor.getSelectedShapeIds())
|
||||||
.selectNone()
|
.selectNone()
|
||||||
.createShapes([
|
.createShapes([
|
||||||
{
|
{
|
||||||
|
@ -250,7 +250,7 @@ describe('When double clicking the selection edge', () => {
|
||||||
const id = createShapeId()
|
const id = createShapeId()
|
||||||
editor
|
editor
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.deleteShapes(editor.selectedShapeIds)
|
.deleteShapes(editor.getSelectedShapeIds())
|
||||||
.selectNone()
|
.selectNone()
|
||||||
.createShapes([
|
.createShapes([
|
||||||
{
|
{
|
||||||
|
@ -275,7 +275,7 @@ describe('When double clicking the selection edge', () => {
|
||||||
const id = createShapeId()
|
const id = createShapeId()
|
||||||
editor
|
editor
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.deleteShapes(editor.selectedShapeIds)
|
.deleteShapes(editor.getSelectedShapeIds())
|
||||||
.selectNone()
|
.selectNone()
|
||||||
.createShapes([
|
.createShapes([
|
||||||
{
|
{
|
||||||
|
@ -313,7 +313,7 @@ describe('When editing shapes', () => {
|
||||||
|
|
||||||
it('Pointing a shape of a different type selects it and leaves editing', () => {
|
it('Pointing a shape of a different type selects it and leaves editing', () => {
|
||||||
expect(editor.editingShapeId).toBe(null)
|
expect(editor.editingShapeId).toBe(null)
|
||||||
expect(editor.selectedShapeIds.length).toBe(0)
|
expect(editor.getSelectedShapeIds().length).toBe(0)
|
||||||
|
|
||||||
// start editing the geo shape
|
// start editing the geo shape
|
||||||
editor.doubleClick(50, 50, { target: 'shape', shape: editor.getShape(ids.geo1) })
|
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
|
// because useEditableText implements the behavior in React
|
||||||
it.skip('Pointing a shape of a different type selects it and leaves editing', () => {
|
it.skip('Pointing a shape of a different type selects it and leaves editing', () => {
|
||||||
expect(editor.editingShapeId).toBe(null)
|
expect(editor.editingShapeId).toBe(null)
|
||||||
expect(editor.selectedShapeIds.length).toBe(0)
|
expect(editor.getSelectedShapeIds().length).toBe(0)
|
||||||
|
|
||||||
// start editing the geo shape
|
// start editing the geo shape
|
||||||
editor.doubleClick(50, 50, { target: 'shape', shape: editor.getShape(ids.geo1) })
|
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
|
// This works but only end to end — the logic had to move to React
|
||||||
it.skip('Works with text, too', () => {
|
it.skip('Works with text, too', () => {
|
||||||
expect(editor.editingShapeId).toBe(null)
|
expect(editor.editingShapeId).toBe(null)
|
||||||
expect(editor.selectedShapeIds.length).toBe(0)
|
expect(editor.getSelectedShapeIds().length).toBe(0)
|
||||||
|
|
||||||
// start editing the geo shape
|
// start editing the geo shape
|
||||||
editor.doubleClick(50, 50, { target: 'shape', shape: editor.getShape(ids.text1) })
|
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', () => {
|
it('Double clicking the canvas creates a new text shape', () => {
|
||||||
expect(editor.editingShapeId).toBe(null)
|
expect(editor.editingShapeId).toBe(null)
|
||||||
expect(editor.selectedShapeIds.length).toBe(0)
|
expect(editor.getSelectedShapeIds().length).toBe(0)
|
||||||
expect(editor.currentPageShapes.length).toBe(5)
|
expect(editor.currentPageShapes.length).toBe(5)
|
||||||
editor.doubleClick(750, 750)
|
editor.doubleClick(750, 750)
|
||||||
expect(editor.currentPageShapes.length).toBe(6)
|
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', () => {
|
it('It deletes an empty text shape when your click away', () => {
|
||||||
expect(editor.editingShapeId).toBe(null)
|
expect(editor.editingShapeId).toBe(null)
|
||||||
expect(editor.selectedShapeIds.length).toBe(0)
|
expect(editor.getSelectedShapeIds().length).toBe(0)
|
||||||
expect(editor.currentPageShapes.length).toBe(5)
|
expect(editor.currentPageShapes.length).toBe(5)
|
||||||
|
|
||||||
// Create a new shape by double clicking
|
// Create a new shape by double clicking
|
||||||
editor.doubleClick(750, 750)
|
editor.doubleClick(750, 750)
|
||||||
expect(editor.selectedShapeIds.length).toBe(1)
|
expect(editor.getSelectedShapeIds().length).toBe(1)
|
||||||
expect(editor.currentPageShapes.length).toBe(6)
|
expect(editor.currentPageShapes.length).toBe(6)
|
||||||
const shapeId = editor.selectedShapeIds[0]
|
const shapeId = editor.getSelectedShapeIds()[0]
|
||||||
|
|
||||||
// Click away
|
// Click away
|
||||||
editor.click(1000, 1000)
|
editor.click(1000, 1000)
|
||||||
expect(editor.selectedShapeIds.length).toBe(0)
|
expect(editor.getSelectedShapeIds().length).toBe(0)
|
||||||
expect(editor.currentPageShapes.length).toBe(5)
|
expect(editor.currentPageShapes.length).toBe(5)
|
||||||
expect(editor.getShape(shapeId)).toBe(undefined)
|
expect(editor.getShape(shapeId)).toBe(undefined)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('It deletes an empty text shape when your click another text shape', () => {
|
it('It deletes an empty text shape when your click another text shape', () => {
|
||||||
expect(editor.editingShapeId).toBe(null)
|
expect(editor.editingShapeId).toBe(null)
|
||||||
expect(editor.selectedShapeIds.length).toBe(0)
|
expect(editor.getSelectedShapeIds().length).toBe(0)
|
||||||
expect(editor.currentPageShapes.length).toBe(5)
|
expect(editor.currentPageShapes.length).toBe(5)
|
||||||
|
|
||||||
// Create a new shape by double clicking
|
// Create a new shape by double clicking
|
||||||
editor.doubleClick(750, 750)
|
editor.doubleClick(750, 750)
|
||||||
expect(editor.selectedShapeIds.length).toBe(1)
|
expect(editor.getSelectedShapeIds().length).toBe(1)
|
||||||
expect(editor.currentPageShapes.length).toBe(6)
|
expect(editor.currentPageShapes.length).toBe(6)
|
||||||
const shapeId = editor.selectedShapeIds[0]
|
const shapeId = editor.getSelectedShapeIds()[0]
|
||||||
|
|
||||||
// Click another text shape
|
// Click another text shape
|
||||||
editor.pointerMove(50, 50)
|
editor.pointerMove(50, 50)
|
||||||
editor.click()
|
editor.click()
|
||||||
expect(editor.selectedShapeIds.length).toBe(1)
|
expect(editor.getSelectedShapeIds().length).toBe(1)
|
||||||
expect(editor.currentPageShapes.length).toBe(5)
|
expect(editor.currentPageShapes.length).toBe(5)
|
||||||
expect(editor.getShape(shapeId)).toBe(undefined)
|
expect(editor.getShape(shapeId)).toBe(undefined)
|
||||||
})
|
})
|
||||||
|
@ -423,7 +423,7 @@ describe('When in readonly mode', () => {
|
||||||
|
|
||||||
it('Begins editing embed when double clicked', () => {
|
it('Begins editing embed when double clicked', () => {
|
||||||
expect(editor.editingShapeId).toBe(null)
|
expect(editor.editingShapeId).toBe(null)
|
||||||
expect(editor.selectedShapeIds.length).toBe(0)
|
expect(editor.getSelectedShapeIds().length).toBe(0)
|
||||||
expect(editor.getInstanceState().isReadonly).toBe(true)
|
expect(editor.getInstanceState().isReadonly).toBe(true)
|
||||||
|
|
||||||
const shape = editor.getShape(ids.embed1)
|
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', () => {
|
it('Begins editing embed when pressing Enter on a selected embed', () => {
|
||||||
expect(editor.editingShapeId).toBe(null)
|
expect(editor.editingShapeId).toBe(null)
|
||||||
expect(editor.selectedShapeIds.length).toBe(0)
|
expect(editor.getSelectedShapeIds().length).toBe(0)
|
||||||
expect(editor.getInstanceState().isReadonly).toBe(true)
|
expect(editor.getInstanceState().isReadonly).toBe(true)
|
||||||
|
|
||||||
editor.setSelectedShapes([ids.embed1])
|
editor.setSelectedShapes([ids.embed1])
|
||||||
expect(editor.selectedShapeIds.length).toBe(1)
|
expect(editor.getSelectedShapeIds().length).toBe(1)
|
||||||
|
|
||||||
editor.keyUp('Enter')
|
editor.keyUp('Enter')
|
||||||
expect(editor.editingShapeId).toBe(ids.embed1)
|
expect(editor.editingShapeId).toBe(ids.embed1)
|
||||||
|
|
|
@ -131,7 +131,7 @@ export class TestEditor extends Editor {
|
||||||
|
|
||||||
clipboard = null as TLContent | null
|
clipboard = null as TLContent | null
|
||||||
|
|
||||||
copy = (ids = this.selectedShapeIds) => {
|
copy = (ids = this.getSelectedShapeIds()) => {
|
||||||
if (ids.length > 0) {
|
if (ids.length > 0) {
|
||||||
const content = this.getContentFromCurrentPage(ids)
|
const content = this.getContentFromCurrentPage(ids)
|
||||||
if (content) {
|
if (content) {
|
||||||
|
@ -141,7 +141,7 @@ export class TestEditor extends Editor {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
cut = (ids = this.selectedShapeIds) => {
|
cut = (ids = this.getSelectedShapeIds()) => {
|
||||||
if (ids.length > 0) {
|
if (ids.length > 0) {
|
||||||
const content = this.getContentFromCurrentPage(ids)
|
const content = this.getContentFromCurrentPage(ids)
|
||||||
if (content) {
|
if (content) {
|
||||||
|
@ -471,7 +471,7 @@ export class TestEditor extends Editor {
|
||||||
shiftKey = false,
|
shiftKey = false,
|
||||||
}: { handle?: RotateCorner; shiftKey?: boolean } = {}
|
}: { handle?: RotateCorner; shiftKey?: boolean } = {}
|
||||||
) {
|
) {
|
||||||
if (this.selectedShapeIds.length === 0) {
|
if (this.getSelectedShapeIds().length === 0) {
|
||||||
throw new Error('No selection')
|
throw new Error('No selection')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,14 +504,14 @@ export class TestEditor extends Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
translateSelection(dx: number, dy: number, options?: Partial<TLPointerEventInfo>) {
|
translateSelection(dx: number, dy: number, options?: Partial<TLPointerEventInfo>) {
|
||||||
if (this.selectedShapeIds.length === 0) {
|
if (this.getSelectedShapeIds().length === 0) {
|
||||||
throw new Error('No selection')
|
throw new Error('No selection')
|
||||||
}
|
}
|
||||||
this.setCurrentTool('select')
|
this.setCurrentTool('select')
|
||||||
|
|
||||||
const center = this.selectionPageCenter!
|
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
|
const numSteps = 10
|
||||||
for (let i = 1; i < numSteps; i++) {
|
for (let i = 1; i < numSteps; i++) {
|
||||||
this.pointerMove(center.x + (i * dx) / numSteps, center.y + (i * dy) / numSteps, options)
|
this.pointerMove(center.x + (i * dx) / numSteps, center.y + (i * dy) / numSteps, options)
|
||||||
|
@ -525,7 +525,7 @@ export class TestEditor extends Editor {
|
||||||
handle: SelectionHandle,
|
handle: SelectionHandle,
|
||||||
options?: Partial<TLPointerEventInfo>
|
options?: Partial<TLPointerEventInfo>
|
||||||
) {
|
) {
|
||||||
if (this.selectedShapeIds.length === 0) {
|
if (this.getSelectedShapeIds().length === 0) {
|
||||||
throw new Error('No selection')
|
throw new Error('No selection')
|
||||||
}
|
}
|
||||||
this.setCurrentTool('select')
|
this.setCurrentTool('select')
|
||||||
|
|
|
@ -255,7 +255,7 @@ describe('<TldrawEditor />', () => {
|
||||||
// Select the shape
|
// Select the shape
|
||||||
await act(async () => editor.select(id))
|
await act(async () => editor.select(id))
|
||||||
|
|
||||||
expect(editor.selectedShapeIds.length).toBe(1)
|
expect(editor.getSelectedShapeIds().length).toBe(1)
|
||||||
|
|
||||||
// Is the shape's component rendering?
|
// Is the shape's component rendering?
|
||||||
expect(document.querySelectorAll('.tl-shape-indicator')).toHaveLength(1)
|
expect(document.querySelectorAll('.tl-shape-indicator')).toHaveLength(1)
|
||||||
|
|
|
@ -13,7 +13,7 @@ beforeEach(() => {
|
||||||
editor = new TestEditor()
|
editor = new TestEditor()
|
||||||
editor
|
editor
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.deleteShapes(editor.selectedShapeIds)
|
.deleteShapes(editor.getSelectedShapeIds())
|
||||||
.createShapes([{ id: ids.box1, type: 'geo', x: 100, y: 100, props: { w: 100, h: 100 } }])
|
.createShapes([{ id: ids.box1, type: 'geo', x: 100, y: 100, props: { w: 100, h: 100 } }])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -234,7 +234,7 @@ describe('arrowBindingsIndex', () => {
|
||||||
expect(editor.getArrowsBoundTo(ids.box1)).toHaveLength(3)
|
expect(editor.getArrowsBoundTo(ids.box1)).toHaveLength(3)
|
||||||
|
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.duplicateShapes(editor.selectedShapeIds)
|
editor.duplicateShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
const [box1Clone, box2Clone] = editor.selectedShapes
|
const [box1Clone, box2Clone] = editor.selectedShapes
|
||||||
.filter((shape) => editor.isShapeOfType<TLGeoShape>(shape, 'geo'))
|
.filter((shape) => editor.isShapeOfType<TLGeoShape>(shape, 'geo'))
|
||||||
|
|
|
@ -24,7 +24,7 @@ describe('when less than two shapes are selected', () => {
|
||||||
|
|
||||||
const fn = jest.fn()
|
const fn = jest.fn()
|
||||||
editor.on('update', fn)
|
editor.on('update', fn)
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'top')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'top')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
expect(fn).not.toHaveBeenCalled()
|
expect(fn).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
@ -33,7 +33,7 @@ describe('when less than two shapes are selected', () => {
|
||||||
describe('when multiple shapes are selected', () => {
|
describe('when multiple shapes are selected', () => {
|
||||||
it('does, undoes and redoes command', () => {
|
it('does, undoes and redoes command', () => {
|
||||||
editor.mark('align')
|
editor.mark('align')
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'top')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'top')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
editor.expectShapeToMatch({ id: ids.boxB, y: 0 })
|
editor.expectShapeToMatch({ id: ids.boxB, y: 0 })
|
||||||
|
@ -44,7 +44,7 @@ describe('when multiple shapes are selected', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('aligns top', () => {
|
it('aligns top', () => {
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'top')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'top')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
editor.expectShapeToMatch(
|
editor.expectShapeToMatch(
|
||||||
|
@ -55,7 +55,7 @@ describe('when multiple shapes are selected', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('aligns right', () => {
|
it('aligns right', () => {
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'right')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'right')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
editor.expectShapeToMatch(
|
editor.expectShapeToMatch(
|
||||||
|
@ -66,7 +66,7 @@ describe('when multiple shapes are selected', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('aligns bottom', () => {
|
it('aligns bottom', () => {
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'bottom')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'bottom')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
editor.expectShapeToMatch(
|
editor.expectShapeToMatch(
|
||||||
|
@ -77,7 +77,7 @@ describe('when multiple shapes are selected', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('aligns left', () => {
|
it('aligns left', () => {
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'left')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'left')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
editor.expectShapeToMatch(
|
editor.expectShapeToMatch(
|
||||||
|
@ -88,7 +88,7 @@ describe('when multiple shapes are selected', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('aligns center horizontal', () => {
|
it('aligns center horizontal', () => {
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'center-horizontal')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'center-horizontal')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
editor.expectShapeToMatch(
|
editor.expectShapeToMatch(
|
||||||
|
@ -99,7 +99,7 @@ describe('when multiple shapes are selected', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('aligns center vertical', () => {
|
it('aligns center vertical', () => {
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'center-vertical')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'center-vertical')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
editor.expectShapeToMatch(
|
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)
|
jest.advanceTimersByTime(1000)
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'center-horizontal')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'center-horizontal')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
const commonBounds = Box2d.Common([
|
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)
|
jest.advanceTimersByTime(1000)
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'left')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'left')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
const commonBounds = Box2d.Common([
|
const commonBounds = Box2d.Common([
|
||||||
|
@ -207,9 +207,9 @@ describe('when multiple shapes are selected', () => {
|
||||||
])
|
])
|
||||||
|
|
||||||
editor.setSelectedShapes([ids.boxA, ids.boxB, ids.boxC])
|
editor.setSelectedShapes([ids.boxA, ids.boxB, ids.boxC])
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'bottom')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'bottom')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'right')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'right')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
const commonBounds = Box2d.Common([
|
const commonBounds = Box2d.Common([
|
||||||
|
@ -231,7 +231,7 @@ describe('When shapes are parented to other shapes...', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
editor = new TestEditor()
|
editor = new TestEditor()
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.deleteShapes(editor.selectedShapeIds)
|
editor.deleteShapes(editor.getSelectedShapeIds())
|
||||||
ids = editor.createShapesFromJsx([
|
ids = editor.createShapesFromJsx([
|
||||||
<TL.geo ref="boxA" x={0} y={0} w={100} h={100}>
|
<TL.geo ref="boxA" x={0} y={0} w={100} h={100}>
|
||||||
<TL.geo ref="boxB" x={100} y={100} w={50} h={50} />
|
<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.getShapePageBounds(ids.boxB)!,
|
||||||
])
|
])
|
||||||
|
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'top')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'top')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'left')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'left')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
const commonBoundsAfter = Box2d.Common([
|
const commonBoundsAfter = Box2d.Common([
|
||||||
|
@ -272,9 +272,9 @@ describe('When shapes are parented to other shapes...', () => {
|
||||||
editor.getShapePageBounds(ids.boxB)!,
|
editor.getShapePageBounds(ids.boxB)!,
|
||||||
])
|
])
|
||||||
|
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'bottom')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'bottom')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'right')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'right')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
const commonBoundsAfter = Box2d.Common([
|
const commonBoundsAfter = Box2d.Common([
|
||||||
|
@ -291,7 +291,7 @@ describe('When shapes are parented to a rotated shape...', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
editor = new TestEditor()
|
editor = new TestEditor()
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.deleteShapes(editor.selectedShapeIds)
|
editor.deleteShapes(editor.getSelectedShapeIds())
|
||||||
editor.createShapes([
|
editor.createShapes([
|
||||||
{
|
{
|
||||||
id: ids.boxA,
|
id: ids.boxA,
|
||||||
|
@ -338,9 +338,9 @@ describe('When shapes are parented to a rotated shape...', () => {
|
||||||
editor.getShapePageBounds(ids.boxB)!,
|
editor.getShapePageBounds(ids.boxB)!,
|
||||||
])
|
])
|
||||||
|
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'top')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'top')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'left')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'left')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
const commonBoundsAfter = Box2d.Common([
|
const commonBoundsAfter = Box2d.Common([
|
||||||
|
@ -366,9 +366,9 @@ describe('When shapes are parented to a rotated shape...', () => {
|
||||||
editor.getShapePageBounds(ids.boxB)!,
|
editor.getShapePageBounds(ids.boxB)!,
|
||||||
])
|
])
|
||||||
|
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'bottom')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'bottom')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
editor.alignShapes(editor.selectedShapeIds, 'right')
|
editor.alignShapes(editor.getSelectedShapeIds(), 'right')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
const commonBoundsAfter = Box2d.Common([
|
const commonBoundsAfter = Box2d.Common([
|
||||||
|
|
|
@ -14,11 +14,11 @@ const ids = {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
editor = new TestEditor()
|
editor = new TestEditor()
|
||||||
|
|
||||||
editor.selectAll().deleteShapes(editor.selectedShapeIds)
|
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
editor.selectAll().deleteShapes(editor.selectedShapeIds)
|
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
|
||||||
})
|
})
|
||||||
|
|
||||||
const doMockClipboard = () => {
|
const doMockClipboard = () => {
|
||||||
|
@ -446,7 +446,7 @@ describe('When copying and pasting', () => {
|
||||||
editor
|
editor
|
||||||
// Create group
|
// Create group
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.groupShapes(editor.selectedShapeIds)
|
.groupShapes(editor.getSelectedShapeIds())
|
||||||
// Move the group
|
// Move the group
|
||||||
.updateShapes([
|
.updateShapes([
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,7 +17,7 @@ beforeEach(() => {
|
||||||
editor = new TestEditor()
|
editor = new TestEditor()
|
||||||
editor
|
editor
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.deleteShapes(editor.selectedShapeIds)
|
.deleteShapes(editor.getSelectedShapeIds())
|
||||||
.createShapes([
|
.createShapes([
|
||||||
{ id: ids.box1, type: 'geo', x: 100, y: 100, props: { w: 100, h: 100 } },
|
{ 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 } },
|
{ 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', () => {
|
it('Deletes a shape', () => {
|
||||||
editor.select(ids.box3, ids.box4)
|
editor.select(ids.box3, ids.box4)
|
||||||
editor.mark('before deleting')
|
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.box3)).toBeUndefined()
|
||||||
expect(editor.getShape(ids.box4)).toBeUndefined()
|
expect(editor.getShape(ids.box4)).toBeUndefined()
|
||||||
expect(editor.selectedShapeIds).toMatchObject([])
|
expect(editor.getSelectedShapeIds()).toMatchObject([])
|
||||||
editor.undo()
|
editor.undo()
|
||||||
expect(editor.getShape(ids.box3)).not.toBeUndefined()
|
expect(editor.getShape(ids.box3)).not.toBeUndefined()
|
||||||
expect(editor.getShape(ids.box4)).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()
|
editor.redo()
|
||||||
expect(editor.getShape(ids.box3)).toBeUndefined()
|
expect(editor.getShape(ids.box3)).toBeUndefined()
|
||||||
expect(editor.getShape(ids.box4)).toBeUndefined()
|
expect(editor.getShape(ids.box4)).toBeUndefined()
|
||||||
expect(editor.selectedShapeIds).toMatchObject([])
|
expect(editor.getSelectedShapeIds()).toMatchObject([])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Does nothing on an empty ids array', () => {
|
it('Does nothing on an empty ids array', () => {
|
||||||
editor.selectNone()
|
editor.selectNone()
|
||||||
const before = editor.store.serialize()
|
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)
|
expect(editor.store.serialize()).toStrictEqual(before)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ describe('Editor.deleteShapes', () => {
|
||||||
editor.reparentShapes([ids.box4], ids.box3)
|
editor.reparentShapes([ids.box4], ids.box3)
|
||||||
editor.select(ids.box3)
|
editor.select(ids.box3)
|
||||||
editor.mark('before deleting')
|
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.box3)).toBeUndefined()
|
||||||
expect(editor.getShape(ids.box4)).toBeUndefined()
|
expect(editor.getShape(ids.box4)).toBeUndefined()
|
||||||
editor.undo()
|
editor.undo()
|
||||||
|
@ -96,7 +96,7 @@ describe('When deleting arrows', () => {
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
expect(editor._arrowBindingsIndex.get()[ids.box2]).not.toBeUndefined()
|
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
|
// @ts-expect-error
|
||||||
expect(editor._arrowBindingsIndex.get()[ids.box1]).toBeUndefined()
|
expect(editor._arrowBindingsIndex.get()[ids.box1]).toBeUndefined()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
|
|
|
@ -19,7 +19,7 @@ beforeEach(() => {
|
||||||
describe('distributeShapes command', () => {
|
describe('distributeShapes command', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.deleteShapes(editor.selectedShapeIds)
|
editor.deleteShapes(editor.getSelectedShapeIds())
|
||||||
editor.createShapes([
|
editor.createShapes([
|
||||||
{
|
{
|
||||||
id: ids.boxA,
|
id: ids.boxA,
|
||||||
|
@ -47,7 +47,7 @@ describe('distributeShapes command', () => {
|
||||||
editor.setSelectedShapes([ids.boxA, ids.boxB])
|
editor.setSelectedShapes([ids.boxA, ids.boxB])
|
||||||
const fn = jest.fn()
|
const fn = jest.fn()
|
||||||
editor.on('change-history', fn)
|
editor.on('change-history', fn)
|
||||||
editor.distributeShapes(editor.selectedShapeIds, 'horizontal')
|
editor.distributeShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
expect(fn).not.toHaveBeenCalled()
|
expect(fn).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
@ -56,7 +56,7 @@ describe('distributeShapes command', () => {
|
||||||
describe('When distributing...', () => {
|
describe('When distributing...', () => {
|
||||||
it('distributeShapes horizontally', () => {
|
it('distributeShapes horizontally', () => {
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.distributeShapes(editor.selectedShapeIds, 'horizontal')
|
editor.distributeShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
editor.expectShapeToMatch(
|
editor.expectShapeToMatch(
|
||||||
{ id: ids.boxA, x: 0 },
|
{ id: ids.boxA, x: 0 },
|
||||||
|
@ -68,7 +68,7 @@ describe('distributeShapes command', () => {
|
||||||
it('distributeShapes horizontally when shapes are clustered', () => {
|
it('distributeShapes horizontally when shapes are clustered', () => {
|
||||||
editor.updateShapes([{ id: ids.boxC, type: 'geo', x: 25 }])
|
editor.updateShapes([{ id: ids.boxC, type: 'geo', x: 25 }])
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.distributeShapes(editor.selectedShapeIds, 'horizontal')
|
editor.distributeShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
editor.expectShapeToMatch(
|
editor.expectShapeToMatch(
|
||||||
{ id: ids.boxA, x: 0 },
|
{ id: ids.boxA, x: 0 },
|
||||||
|
@ -79,7 +79,7 @@ describe('distributeShapes command', () => {
|
||||||
|
|
||||||
it('distributeShapes vertically', () => {
|
it('distributeShapes vertically', () => {
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.distributeShapes(editor.selectedShapeIds, 'vertical')
|
editor.distributeShapes(editor.getSelectedShapeIds(), 'vertical')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
editor.expectShapeToMatch(
|
editor.expectShapeToMatch(
|
||||||
{ id: ids.boxA, y: 0 },
|
{ id: ids.boxA, y: 0 },
|
||||||
|
@ -91,7 +91,7 @@ describe('distributeShapes command', () => {
|
||||||
it('distributeShapes vertically when shapes are clustered', () => {
|
it('distributeShapes vertically when shapes are clustered', () => {
|
||||||
editor.updateShapes([{ id: ids.boxC, type: 'geo', y: 25 }])
|
editor.updateShapes([{ id: ids.boxC, type: 'geo', y: 25 }])
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.distributeShapes(editor.selectedShapeIds, 'vertical')
|
editor.distributeShapes(editor.getSelectedShapeIds(), 'vertical')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
editor.expectShapeToMatch(
|
editor.expectShapeToMatch(
|
||||||
{ id: ids.boxA, y: 0 },
|
{ id: ids.boxA, y: 0 },
|
||||||
|
@ -103,7 +103,7 @@ describe('distributeShapes command', () => {
|
||||||
|
|
||||||
it('distributeShapes shapes that are the child of another shape.', () => {
|
it('distributeShapes shapes that are the child of another shape.', () => {
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.deleteShapes(editor.selectedShapeIds)
|
editor.deleteShapes(editor.getSelectedShapeIds())
|
||||||
editor.createShapes([
|
editor.createShapes([
|
||||||
{
|
{
|
||||||
id: ids.boxA,
|
id: ids.boxA,
|
||||||
|
@ -133,7 +133,7 @@ describe('distributeShapes command', () => {
|
||||||
])
|
])
|
||||||
editor.setSelectedShapes([ids.boxB, ids.boxC, ids.boxD])
|
editor.setSelectedShapes([ids.boxB, ids.boxC, ids.boxD])
|
||||||
|
|
||||||
editor.distributeShapes(editor.selectedShapeIds, 'horizontal')
|
editor.distributeShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
editor.expectShapeToMatch(
|
editor.expectShapeToMatch(
|
||||||
|
@ -145,7 +145,7 @@ describe('distributeShapes command', () => {
|
||||||
|
|
||||||
it('distributeShapes shapes that are the child of another shape when clustered.', () => {
|
it('distributeShapes shapes that are the child of another shape when clustered.', () => {
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.deleteShapes(editor.selectedShapeIds)
|
editor.deleteShapes(editor.getSelectedShapeIds())
|
||||||
editor.createShapes([
|
editor.createShapes([
|
||||||
{
|
{
|
||||||
id: ids.boxA,
|
id: ids.boxA,
|
||||||
|
@ -175,7 +175,7 @@ describe('distributeShapes command', () => {
|
||||||
])
|
])
|
||||||
editor.setSelectedShapes([ids.boxB, ids.boxC, ids.boxD])
|
editor.setSelectedShapes([ids.boxB, ids.boxC, ids.boxD])
|
||||||
|
|
||||||
editor.distributeShapes(editor.selectedShapeIds, 'horizontal')
|
editor.distributeShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
editor.expectShapeToMatch(
|
editor.expectShapeToMatch(
|
||||||
|
@ -188,7 +188,7 @@ describe('distributeShapes command', () => {
|
||||||
it('distributeShapes shapes that are the child of another shape when a parent is rotated.', () => {
|
it('distributeShapes shapes that are the child of another shape when a parent is rotated.', () => {
|
||||||
editor = new TestEditor()
|
editor = new TestEditor()
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.deleteShapes(editor.selectedShapeIds)
|
editor.deleteShapes(editor.getSelectedShapeIds())
|
||||||
editor.createShapes([
|
editor.createShapes([
|
||||||
{
|
{
|
||||||
id: ids.boxA,
|
id: ids.boxA,
|
||||||
|
@ -220,7 +220,7 @@ describe('distributeShapes command', () => {
|
||||||
|
|
||||||
editor.setSelectedShapes([ids.boxB, ids.boxC, ids.boxD])
|
editor.setSelectedShapes([ids.boxB, ids.boxC, ids.boxD])
|
||||||
|
|
||||||
editor.distributeShapes(editor.selectedShapeIds, 'horizontal')
|
editor.distributeShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
editor.expectShapeToMatch(
|
editor.expectShapeToMatch(
|
||||||
|
|
|
@ -51,7 +51,7 @@ beforeEach(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('gets an SVG', async () => {
|
it('gets an SVG', async () => {
|
||||||
const svg = await editor.getSvg(editor.selectedShapeIds)
|
const svg = await editor.getSvg(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
expect(svg).toBeTruthy()
|
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 () => {
|
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 bbox = editor.selectionRotatedPageBounds!
|
||||||
const expanded = bbox.expandBy(SVG_PADDING) // adds 32px padding
|
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 () => {
|
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 bbox = editor.selectionRotatedPageBounds!
|
||||||
const expanded = bbox.expandBy(SVG_PADDING) // adds 32px padding
|
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 () => {
|
it('Matches a snapshot', async () => {
|
||||||
const svg = (await editor.getSvg(editor.selectedShapeIds))!
|
const svg = (await editor.getSvg(editor.getSelectedShapeIds()))!
|
||||||
|
|
||||||
const elm = document.createElement('wrapper')
|
const elm = document.createElement('wrapper')
|
||||||
elm.appendChild(svg)
|
elm.appendChild(svg)
|
||||||
|
@ -90,21 +90,21 @@ it('Matches a snapshot', async () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Accepts a scale option', 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')
|
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')
|
expect(svg2.getAttribute('width')).toBe('1128')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Accepts a background option', async () => {
|
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')
|
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')
|
expect(svg2.style.backgroundColor).toBe('transparent')
|
||||||
})
|
})
|
||||||
|
|
|
@ -17,7 +17,7 @@ const ids = {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
editor = new TestEditor()
|
editor = new TestEditor()
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.deleteShapes(editor.selectedShapeIds)
|
editor.deleteShapes(editor.getSelectedShapeIds())
|
||||||
editor.createShapes([
|
editor.createShapes([
|
||||||
{
|
{
|
||||||
id: ids.lockedShapeA,
|
id: ids.lockedShapeA,
|
||||||
|
@ -83,10 +83,10 @@ beforeEach(() => {
|
||||||
describe('Locking', () => {
|
describe('Locking', () => {
|
||||||
it('Can lock shapes', () => {
|
it('Can lock shapes', () => {
|
||||||
editor.setSelectedShapes([ids.unlockedShapeA])
|
editor.setSelectedShapes([ids.unlockedShapeA])
|
||||||
editor.toggleLock(editor.selectedShapeIds)
|
editor.toggleLock(editor.getSelectedShapeIds())
|
||||||
expect(editor.getShape(ids.unlockedShapeA)!.isLocked).toBe(true)
|
expect(editor.getShape(ids.unlockedShapeA)!.isLocked).toBe(true)
|
||||||
// Locking deselects the shape
|
// 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', () => {
|
it('Cannot be selected with select all', () => {
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
expect(editor.selectedShapeIds).toEqual([ids.unlockedShapeA, ids.unlockedShapeB])
|
expect(editor.getSelectedShapeIds()).toEqual([ids.unlockedShapeA, ids.unlockedShapeB])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Cannot be selected by clicking', () => {
|
it('Cannot be selected by clicking', () => {
|
||||||
|
@ -128,7 +128,7 @@ describe('Locked shapes', () => {
|
||||||
.expectToBeIn('select.pointing_canvas')
|
.expectToBeIn('select.pointing_canvas')
|
||||||
.pointerUp()
|
.pointerUp()
|
||||||
.expectToBeIn('select.idle')
|
.expectToBeIn('select.idle')
|
||||||
expect(editor.selectedShapeIds).not.toContain(shape.id)
|
expect(editor.getSelectedShapeIds()).not.toContain(shape.id)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Cannot be edited', () => {
|
it('Cannot be edited', () => {
|
||||||
|
@ -138,7 +138,7 @@ describe('Locked shapes', () => {
|
||||||
// We create a new shape and we edit that one
|
// We create a new shape and we edit that one
|
||||||
editor.doubleClick(10, 10, { target: 'shape', shape }).expectToBeIn('select.editing_shape')
|
editor.doubleClick(10, 10, { target: 'shape', shape }).expectToBeIn('select.editing_shape')
|
||||||
expect(editor.currentPageShapes.length).toBe(shapeCount + 1)
|
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', () => {
|
it('Cannot be grouped', () => {
|
||||||
|
@ -169,7 +169,7 @@ describe('Unlocking', () => {
|
||||||
(id) => editor.getShape(id)!.isLocked
|
(id) => editor.getShape(id)!.isLocked
|
||||||
)
|
)
|
||||||
expect(lockedStatus).toStrictEqual([true, true])
|
expect(lockedStatus).toStrictEqual([true, true])
|
||||||
editor.toggleLock(editor.selectedShapeIds)
|
editor.toggleLock(editor.getSelectedShapeIds())
|
||||||
lockedStatus = [ids.lockedShapeA, ids.lockedShapeB].map((id) => editor.getShape(id)!.isLocked)
|
lockedStatus = [ids.lockedShapeA, ids.lockedShapeB].map((id) => editor.getShape(id)!.isLocked)
|
||||||
expect(lockedStatus).toStrictEqual([false, false])
|
expect(lockedStatus).toStrictEqual([false, false])
|
||||||
})
|
})
|
||||||
|
|
|
@ -155,7 +155,7 @@ describe('arrows', () => {
|
||||||
let secondBox: TLShape
|
let secondBox: TLShape
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
editor.selectAll().deleteShapes(editor.selectedShapeIds)
|
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
|
||||||
// draw a first box
|
// draw a first box
|
||||||
editor.createShapes([
|
editor.createShapes([
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,22 +39,22 @@ function nudgeAndGet(ids: TLShapeId[], key: string, shiftKey: boolean) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'ArrowLeft': {
|
case 'ArrowLeft': {
|
||||||
editor.mark('nudge')
|
editor.mark('nudge')
|
||||||
editor.nudgeShapes(editor.selectedShapeIds, { x: -step, y: 0 })
|
editor.nudgeShapes(editor.getSelectedShapeIds(), { x: -step, y: 0 })
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'ArrowRight': {
|
case 'ArrowRight': {
|
||||||
editor.mark('nudge')
|
editor.mark('nudge')
|
||||||
editor.nudgeShapes(editor.selectedShapeIds, { x: step, y: 0 })
|
editor.nudgeShapes(editor.getSelectedShapeIds(), { x: step, y: 0 })
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'ArrowUp': {
|
case 'ArrowUp': {
|
||||||
editor.mark('nudge')
|
editor.mark('nudge')
|
||||||
editor.nudgeShapes(editor.selectedShapeIds, { x: 0, y: -step })
|
editor.nudgeShapes(editor.getSelectedShapeIds(), { x: 0, y: -step })
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'ArrowDown': {
|
case 'ArrowDown': {
|
||||||
editor.mark('nudge')
|
editor.mark('nudge')
|
||||||
editor.nudgeShapes(editor.selectedShapeIds, { x: 0, y: step })
|
editor.nudgeShapes(editor.getSelectedShapeIds(), { x: 0, y: step })
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ jest.useFakeTimers()
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
editor = new TestEditor()
|
editor = new TestEditor()
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.deleteShapes(editor.selectedShapeIds)
|
editor.deleteShapes(editor.getSelectedShapeIds())
|
||||||
editor.createShapes([
|
editor.createShapes([
|
||||||
{
|
{
|
||||||
id: ids.boxA,
|
id: ids.boxA,
|
||||||
|
@ -42,7 +42,7 @@ describe('editor.packShapes', () => {
|
||||||
it('packs shapes', () => {
|
it('packs shapes', () => {
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
const centerBefore = editor.selectionRotatedPageBounds!.center.clone()
|
const centerBefore = editor.selectionRotatedPageBounds!.center.clone()
|
||||||
editor.packShapes(editor.selectedShapeIds, 16)
|
editor.packShapes(editor.getSelectedShapeIds(), 16)
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
expect(editor.currentPageShapes.map((s) => ({ ...s, parentId: 'wahtever' }))).toMatchSnapshot(
|
expect(editor.currentPageShapes.map((s) => ({ ...s, parentId: 'wahtever' }))).toMatchSnapshot(
|
||||||
'packed shapes'
|
'packed shapes'
|
||||||
|
@ -53,7 +53,7 @@ describe('editor.packShapes', () => {
|
||||||
|
|
||||||
it('packs rotated shapes', () => {
|
it('packs rotated shapes', () => {
|
||||||
editor.updateShapes([{ id: ids.boxA, type: 'geo', rotation: Math.PI }])
|
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)
|
jest.advanceTimersByTime(1000)
|
||||||
expect(editor.currentPageShapes.map((s) => ({ ...s, parentId: 'wahtever' }))).toMatchSnapshot(
|
expect(editor.currentPageShapes.map((s) => ({ ...s, parentId: 'wahtever' }))).toMatchSnapshot(
|
||||||
'packed shapes'
|
'packed shapes'
|
||||||
|
|
|
@ -60,7 +60,7 @@ describe('editor.rotateShapes', () => {
|
||||||
const { selectionPageCenter } = editor
|
const { selectionPageCenter } = editor
|
||||||
|
|
||||||
// Rotate the shape...
|
// Rotate the shape...
|
||||||
editor.rotateShapesBy(editor.selectedShapeIds, Math.PI)
|
editor.rotateShapesBy(editor.getSelectedShapeIds(), Math.PI)
|
||||||
|
|
||||||
// Once for each shape
|
// Once for each shape
|
||||||
expect(fnStart).toHaveBeenCalledTimes(2)
|
expect(fnStart).toHaveBeenCalledTimes(2)
|
||||||
|
|
|
@ -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", () => {
|
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' })
|
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])
|
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', () => {
|
it('squashes', () => {
|
||||||
|
|
|
@ -15,43 +15,43 @@ beforeEach(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Sets selected shapes', () => {
|
it('Sets selected shapes', () => {
|
||||||
expect(editor.selectedShapeIds).toMatchObject([])
|
expect(editor.getSelectedShapeIds()).toMatchObject([])
|
||||||
editor.setSelectedShapes([ids.box1, ids.box2])
|
editor.setSelectedShapes([ids.box1, ids.box2])
|
||||||
expect(editor.selectedShapeIds).toMatchObject([ids.box1, ids.box2])
|
expect(editor.getSelectedShapeIds()).toMatchObject([ids.box1, ids.box2])
|
||||||
editor.undo()
|
editor.undo()
|
||||||
expect(editor.selectedShapeIds).toMatchObject([])
|
expect(editor.getSelectedShapeIds()).toMatchObject([])
|
||||||
editor.redo()
|
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', () => {
|
it('Prevents parent and child from both being selected', () => {
|
||||||
editor.setSelectedShapes([ids.box2, ids.ellipse1]) // ellipse1 is child of box2
|
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', () => {
|
it('Deleting the parent also deletes descendants', () => {
|
||||||
editor.setSelectedShapes([ids.box2])
|
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.box2)).not.toBeUndefined()
|
||||||
expect(editor.getShape(ids.ellipse1)).not.toBeUndefined()
|
expect(editor.getShape(ids.ellipse1)).not.toBeUndefined()
|
||||||
|
|
||||||
editor.mark('')
|
editor.mark('')
|
||||||
editor.deleteShapes([ids.box2])
|
editor.deleteShapes([ids.box2])
|
||||||
|
|
||||||
expect(editor.selectedShapeIds).toMatchObject([])
|
expect(editor.getSelectedShapeIds()).toMatchObject([])
|
||||||
expect(editor.getShape(ids.box2)).toBeUndefined()
|
expect(editor.getShape(ids.box2)).toBeUndefined()
|
||||||
expect(editor.getShape(ids.ellipse1)).toBeUndefined()
|
expect(editor.getShape(ids.ellipse1)).toBeUndefined()
|
||||||
|
|
||||||
editor.undo()
|
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.box2)).not.toBe(undefined)
|
||||||
expect(editor.getShape(ids.ellipse1)).not.toBe(undefined)
|
expect(editor.getShape(ids.ellipse1)).not.toBe(undefined)
|
||||||
|
|
||||||
editor.redo()
|
editor.redo()
|
||||||
|
|
||||||
expect(editor.selectedShapeIds).toMatchObject([])
|
expect(editor.getSelectedShapeIds()).toMatchObject([])
|
||||||
expect(editor.getShape(ids.box2)).toBeUndefined()
|
expect(editor.getShape(ids.box2)).toBeUndefined()
|
||||||
expect(editor.getShape(ids.ellipse1)).toBeUndefined()
|
expect(editor.getShape(ids.ellipse1)).toBeUndefined()
|
||||||
})
|
})
|
||||||
|
|
|
@ -19,7 +19,7 @@ beforeEach(() => {
|
||||||
describe('distributeShapes command', () => {
|
describe('distributeShapes command', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.deleteShapes(editor.selectedShapeIds)
|
editor.deleteShapes(editor.getSelectedShapeIds())
|
||||||
editor.createShapes([
|
editor.createShapes([
|
||||||
{
|
{
|
||||||
id: ids.boxA,
|
id: ids.boxA,
|
||||||
|
@ -53,7 +53,7 @@ describe('distributeShapes command', () => {
|
||||||
editor.setSelectedShapes([ids.boxA, ids.boxB])
|
editor.setSelectedShapes([ids.boxA, ids.boxB])
|
||||||
const fn = jest.fn()
|
const fn = jest.fn()
|
||||||
editor.on('change-history', fn)
|
editor.on('change-history', fn)
|
||||||
editor.stackShapes(editor.selectedShapeIds, 'horizontal', 0)
|
editor.stackShapes(editor.getSelectedShapeIds(), 'horizontal', 0)
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
expect(fn).not.toHaveBeenCalled()
|
expect(fn).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
@ -62,7 +62,7 @@ describe('distributeShapes command', () => {
|
||||||
describe('when stacking horizontally', () => {
|
describe('when stacking horizontally', () => {
|
||||||
it('stacks the shapes based on a given value', () => {
|
it('stacks the shapes based on a given value', () => {
|
||||||
editor.setSelectedShapes([ids.boxA, ids.boxB, ids.boxC, ids.boxD])
|
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)
|
jest.advanceTimersByTime(1000)
|
||||||
// 200 distance gap between c and d
|
// 200 distance gap between c and d
|
||||||
editor.expectShapeToMatch({
|
editor.expectShapeToMatch({
|
||||||
|
@ -89,7 +89,7 @@ describe('distributeShapes command', () => {
|
||||||
|
|
||||||
it('stacks the shapes based on the most common gap', () => {
|
it('stacks the shapes based on the most common gap', () => {
|
||||||
editor.setSelectedShapes([ids.boxA, ids.boxB, ids.boxC, ids.boxD])
|
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)
|
jest.advanceTimersByTime(1000)
|
||||||
// 200 distance gap between c and d
|
// 200 distance gap between c and d
|
||||||
editor.expectShapeToMatch({
|
editor.expectShapeToMatch({
|
||||||
|
@ -117,7 +117,7 @@ describe('distributeShapes command', () => {
|
||||||
it('stacks the shapes based on the average', () => {
|
it('stacks the shapes based on the average', () => {
|
||||||
editor.updateShapes([{ id: ids.boxD, type: 'geo', x: 540, y: 700 }])
|
editor.updateShapes([{ id: ids.boxD, type: 'geo', x: 540, y: 700 }])
|
||||||
editor.setSelectedShapes([ids.boxA, ids.boxB, ids.boxC, ids.boxD])
|
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)
|
jest.advanceTimersByTime(1000)
|
||||||
editor.expectShapeToMatch({
|
editor.expectShapeToMatch({
|
||||||
id: ids.boxA,
|
id: ids.boxA,
|
||||||
|
@ -145,7 +145,7 @@ describe('distributeShapes command', () => {
|
||||||
describe('when stacking vertically', () => {
|
describe('when stacking vertically', () => {
|
||||||
it('stacks the shapes based on a given value', () => {
|
it('stacks the shapes based on a given value', () => {
|
||||||
editor.setSelectedShapes([ids.boxA, ids.boxB, ids.boxC, ids.boxD])
|
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)
|
jest.advanceTimersByTime(1000)
|
||||||
// 200 distance gap between c and d
|
// 200 distance gap between c and d
|
||||||
editor.expectShapeToMatch({
|
editor.expectShapeToMatch({
|
||||||
|
@ -172,7 +172,7 @@ describe('distributeShapes command', () => {
|
||||||
|
|
||||||
it('stacks the shapes based on the most common gap', () => {
|
it('stacks the shapes based on the most common gap', () => {
|
||||||
editor.setSelectedShapes([ids.boxA, ids.boxB, ids.boxC, ids.boxD])
|
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)
|
jest.advanceTimersByTime(1000)
|
||||||
// 200 distance gap between c and d
|
// 200 distance gap between c and d
|
||||||
editor.expectShapeToMatch({
|
editor.expectShapeToMatch({
|
||||||
|
@ -200,7 +200,7 @@ describe('distributeShapes command', () => {
|
||||||
it('stacks the shapes based on the average', () => {
|
it('stacks the shapes based on the average', () => {
|
||||||
editor.updateShapes([{ id: ids.boxD, type: 'geo', x: 700, y: 540 }])
|
editor.updateShapes([{ id: ids.boxD, type: 'geo', x: 700, y: 540 }])
|
||||||
editor.setSelectedShapes([ids.boxA, ids.boxB, ids.boxC, ids.boxD])
|
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)
|
jest.advanceTimersByTime(1000)
|
||||||
editor.expectShapeToMatch({
|
editor.expectShapeToMatch({
|
||||||
id: ids.boxA,
|
id: ids.boxA,
|
||||||
|
|
|
@ -14,7 +14,7 @@ function createVideoShape() {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
editor = new TestEditor()
|
editor = new TestEditor()
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.deleteShapes(editor.selectedShapeIds)
|
editor.deleteShapes(editor.getSelectedShapeIds())
|
||||||
ids = editor.createShapesFromJsx([
|
ids = editor.createShapesFromJsx([
|
||||||
<TL.geo ref="boxA" x={0} y={0} w={100} h={100} />,
|
<TL.geo ref="boxA" x={0} y={0} w={100} h={100} />,
|
||||||
<TL.geo ref="boxB" x={100} y={100} w={50} h={50} />,
|
<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])
|
editor.setSelectedShapes([ids.boxB])
|
||||||
const fn = jest.fn()
|
const fn = jest.fn()
|
||||||
editor.on('change-history', fn)
|
editor.on('change-history', fn)
|
||||||
editor.stretchShapes(editor.selectedShapeIds, 'horizontal')
|
editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
expect(fn).not.toHaveBeenCalled()
|
expect(fn).not.toHaveBeenCalled()
|
||||||
|
@ -38,7 +38,7 @@ describe('when less than two shapes are selected', () => {
|
||||||
describe('when multiple shapes are selected', () => {
|
describe('when multiple shapes are selected', () => {
|
||||||
it('stretches horizontally', () => {
|
it('stretches horizontally', () => {
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.stretchShapes(editor.selectedShapeIds, 'horizontal')
|
editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
editor.expectShapeToMatch(
|
editor.expectShapeToMatch(
|
||||||
{ id: ids.boxA, x: 0, y: 0, props: { w: 500 } },
|
{ id: ids.boxA, x: 0, y: 0, props: { w: 500 } },
|
||||||
|
@ -51,7 +51,7 @@ describe('when multiple shapes are selected', () => {
|
||||||
const videoA = createVideoShape()
|
const videoA = createVideoShape()
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
expect(editor.selectedShapes.length).toBe(4)
|
expect(editor.selectedShapes.length).toBe(4)
|
||||||
editor.stretchShapes(editor.selectedShapeIds, 'horizontal')
|
editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
const newHeight = (500 * 9) / 16
|
const newHeight = (500 * 9) / 16
|
||||||
editor.expectShapeToMatch(
|
editor.expectShapeToMatch(
|
||||||
|
@ -64,7 +64,7 @@ describe('when multiple shapes are selected', () => {
|
||||||
|
|
||||||
it('stretches vertically', () => {
|
it('stretches vertically', () => {
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.stretchShapes(editor.selectedShapeIds, 'vertical')
|
editor.stretchShapes(editor.getSelectedShapeIds(), 'vertical')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
editor.expectShapeToMatch(
|
editor.expectShapeToMatch(
|
||||||
{ id: ids.boxA, x: 0, y: 0, props: { h: 500 } },
|
{ id: ids.boxA, x: 0, y: 0, props: { h: 500 } },
|
||||||
|
@ -77,7 +77,7 @@ describe('when multiple shapes are selected', () => {
|
||||||
const videoA = createVideoShape()
|
const videoA = createVideoShape()
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
expect(editor.selectedShapes.length).toBe(4)
|
expect(editor.selectedShapes.length).toBe(4)
|
||||||
editor.stretchShapes(editor.selectedShapeIds, 'vertical')
|
editor.stretchShapes(editor.getSelectedShapeIds(), 'vertical')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
const newWidth = (500 * 16) / 9
|
const newWidth = (500 * 16) / 9
|
||||||
editor.expectShapeToMatch(
|
editor.expectShapeToMatch(
|
||||||
|
@ -90,7 +90,7 @@ describe('when multiple shapes are selected', () => {
|
||||||
|
|
||||||
it('does, undoes and redoes command', () => {
|
it('does, undoes and redoes command', () => {
|
||||||
editor.mark('stretch')
|
editor.mark('stretch')
|
||||||
editor.stretchShapes(editor.selectedShapeIds, 'horizontal')
|
editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
editor.expectShapeToMatch({ id: ids.boxB, x: 0, props: { w: 500 } })
|
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', () => {
|
it('stretches horizontally', () => {
|
||||||
editor.reparentShapes([ids.boxB], ids.boxA)
|
editor.reparentShapes([ids.boxB], ids.boxA)
|
||||||
editor.select(ids.boxB, ids.boxC)
|
editor.select(ids.boxB, ids.boxC)
|
||||||
editor.stretchShapes(editor.selectedShapeIds, 'horizontal')
|
editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
editor.expectShapeToMatch(
|
editor.expectShapeToMatch(
|
||||||
{ id: ids.boxB, x: 100, y: 100, props: { w: 400 } },
|
{ 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', () => {
|
it('stretches vertically', () => {
|
||||||
editor.reparentShapes([ids.boxB], ids.boxA)
|
editor.reparentShapes([ids.boxB], ids.boxA)
|
||||||
editor.select(ids.boxB, ids.boxC)
|
editor.select(ids.boxB, ids.boxC)
|
||||||
editor.stretchShapes(editor.selectedShapeIds, 'vertical')
|
editor.stretchShapes(editor.getSelectedShapeIds(), 'vertical')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
editor.expectShapeToMatch(
|
editor.expectShapeToMatch(
|
||||||
{ id: ids.boxB, x: 100, y: 100, props: { h: 400 } },
|
{ 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(() => {
|
beforeEach(() => {
|
||||||
editor = new TestEditor()
|
editor = new TestEditor()
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.deleteShapes(editor.selectedShapeIds)
|
editor.deleteShapes(editor.getSelectedShapeIds())
|
||||||
ids = editor.createShapesFromJsx([
|
ids = editor.createShapesFromJsx([
|
||||||
<TL.geo ref="boxA" x={0} y={0} w={100} h={100} rotation={PI}>
|
<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} />
|
<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', () => {
|
it('does not stretches rotated shapes', () => {
|
||||||
editor.select(ids.boxB, ids.boxC)
|
editor.select(ids.boxB, ids.boxC)
|
||||||
editor.stretchShapes(editor.selectedShapeIds, 'horizontal')
|
editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
editor.expectShapeToMatch(
|
editor.expectShapeToMatch(
|
||||||
{
|
{
|
||||||
|
@ -167,7 +167,7 @@ describe('When shapes are the child of a rotated shape.', () => {
|
||||||
|
|
||||||
it('does not stretches rotated shapes', () => {
|
it('does not stretches rotated shapes', () => {
|
||||||
editor.select(ids.boxB, ids.boxC)
|
editor.select(ids.boxB, ids.boxC)
|
||||||
editor.stretchShapes(editor.selectedShapeIds, 'vertical')
|
editor.stretchShapes(editor.getSelectedShapeIds(), 'vertical')
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
editor.expectShapeToMatch(
|
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', () => {
|
describe('When shapes have 0-width or 0-height', () => {
|
||||||
it('Does not error with 0-width', () => {
|
it('Does not error with 0-width', () => {
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.deleteShapes(editor.selectedShapeIds)
|
editor.deleteShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
editor
|
editor
|
||||||
.setCurrentTool('arrow')
|
.setCurrentTool('arrow')
|
||||||
|
@ -213,13 +213,13 @@ describe('When shapes have 0-width or 0-height', () => {
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
|
|
||||||
// make sure we don't get any errors:
|
// make sure we don't get any errors:
|
||||||
editor.stretchShapes(editor.selectedShapeIds, 'horizontal')
|
editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
editor.stretchShapes(editor.selectedShapeIds, 'vertical')
|
editor.stretchShapes(editor.getSelectedShapeIds(), 'vertical')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Does not error with 0-height', () => {
|
it('Does not error with 0-height', () => {
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.deleteShapes(editor.selectedShapeIds)
|
editor.deleteShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
editor
|
editor
|
||||||
// draw a perfectly horiztonal arrow:
|
// draw a perfectly horiztonal arrow:
|
||||||
|
@ -239,7 +239,7 @@ describe('When shapes have 0-width or 0-height', () => {
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
|
|
||||||
// make sure we don't get any errors:
|
// make sure we don't get any errors:
|
||||||
editor.stretchShapes(editor.selectedShapeIds, 'horizontal')
|
editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
editor.stretchShapes(editor.selectedShapeIds, 'vertical')
|
editor.stretchShapes(editor.getSelectedShapeIds(), 'vertical')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -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', () => {
|
it('Throws out all shapes if any update is invalid', () => {
|
||||||
editor.selectAll().deleteShapes(editor.selectedShapeIds)
|
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
editor.createShapes([
|
editor.createShapes([
|
||||||
{ id: ids.box1, type: 'geo', x: 0, y: 0 },
|
{ id: ids.box1, type: 'geo', x: 0, y: 0 },
|
||||||
|
|
|
@ -91,27 +91,27 @@ describe('When in the select.idle state', () => {
|
||||||
editor.select(ids.boxA)
|
editor.select(ids.boxA)
|
||||||
|
|
||||||
editor.expectPathToBe('root.select.idle')
|
editor.expectPathToBe('root.select.idle')
|
||||||
expect(editor.selectedShapeIds).toMatchObject([ids.boxA])
|
expect(editor.getSelectedShapeIds()).toMatchObject([ids.boxA])
|
||||||
expect(editor.croppingShapeId).toBe(null)
|
expect(editor.croppingShapeId).toBe(null)
|
||||||
|
|
||||||
editor.doubleClick(550, 550, ids.imageB)
|
editor.doubleClick(550, 550, ids.imageB)
|
||||||
editor.expectPathToBe('root.select.crop.idle')
|
editor.expectPathToBe('root.select.crop.idle')
|
||||||
|
|
||||||
expect(editor.selectedShapeIds).toMatchObject([ids.imageB])
|
expect(editor.getSelectedShapeIds()).toMatchObject([ids.imageB])
|
||||||
expect(editor.croppingShapeId).toBe(ids.imageB)
|
expect(editor.croppingShapeId).toBe(ids.imageB)
|
||||||
|
|
||||||
editor.undo()
|
editor.undo()
|
||||||
|
|
||||||
// first selection should have been a mark
|
// first selection should have been a mark
|
||||||
editor.expectPathToBe('root.select.idle')
|
editor.expectPathToBe('root.select.idle')
|
||||||
expect(editor.selectedShapeIds).toMatchObject([ids.imageB])
|
expect(editor.getSelectedShapeIds()).toMatchObject([ids.imageB])
|
||||||
expect(editor.croppingShapeId).toBe(null)
|
expect(editor.croppingShapeId).toBe(null)
|
||||||
|
|
||||||
editor.undo()
|
editor.undo()
|
||||||
|
|
||||||
// back to start
|
// back to start
|
||||||
editor.expectPathToBe('root.select.idle')
|
editor.expectPathToBe('root.select.idle')
|
||||||
expect(editor.selectedShapeIds).toMatchObject([ids.boxA])
|
expect(editor.getSelectedShapeIds()).toMatchObject([ids.boxA])
|
||||||
expect(editor.croppingShapeId).toBe(null)
|
expect(editor.croppingShapeId).toBe(null)
|
||||||
|
|
||||||
editor
|
editor
|
||||||
|
@ -119,7 +119,7 @@ describe('When in the select.idle state', () => {
|
||||||
.redo() // crop again
|
.redo() // crop again
|
||||||
|
|
||||||
editor.expectPathToBe('root.select.crop.idle')
|
editor.expectPathToBe('root.select.crop.idle')
|
||||||
expect(editor.selectedShapeIds).toMatchObject([ids.imageB])
|
expect(editor.getSelectedShapeIds()).toMatchObject([ids.imageB])
|
||||||
expect(editor.croppingShapeId).toBe(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')
|
.expectPathToBe('root.select.crop.pointing_crop')
|
||||||
|
|
||||||
expect(editor.croppingShapeId).toBe(ids.imageB)
|
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', () => {
|
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')
|
.expectPathToBe('root.select.crop.pointing_crop')
|
||||||
|
|
||||||
expect(editor.croppingShapeId).toBe(ids.imageA)
|
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', () => {
|
it('rotating will return to select.crop.idle', () => {
|
||||||
|
|
|
@ -14,12 +14,12 @@ const ids = {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
editor = new TestEditor()
|
editor = new TestEditor()
|
||||||
|
|
||||||
editor.selectAll().deleteShapes(editor.selectedShapeIds)
|
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
|
||||||
})
|
})
|
||||||
it('creates new bindings for arrows when pasting', async () => {
|
it('creates new bindings for arrows when pasting', async () => {
|
||||||
editor
|
editor
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.deleteShapes(editor.selectedShapeIds)
|
.deleteShapes(editor.getSelectedShapeIds())
|
||||||
.createShapes([
|
.createShapes([
|
||||||
{ id: ids.box1, type: 'geo', x: 100, y: 100, props: { w: 100, h: 100 } },
|
{ 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 } },
|
{ 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
|
const shapesBefore = editor.currentPageShapes
|
||||||
|
|
||||||
editor.selectAll().duplicateShapes(editor.selectedShapeIds)
|
editor.selectAll().duplicateShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
const shapesAfter = editor.currentPageShapes
|
const shapesAfter = editor.currentPageShapes
|
||||||
|
|
||||||
|
@ -174,17 +174,17 @@ describe('When duplicating shapes that include arrows', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Preserves the same selection bounds', () => {
|
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!
|
const boundsBefore = editor.selectionRotatedPageBounds!
|
||||||
editor.duplicateShapes(editor.selectedShapeIds)
|
editor.duplicateShapes(editor.getSelectedShapeIds())
|
||||||
expect(editor.selectionRotatedPageBounds).toCloselyMatchObject(boundsBefore)
|
expect(editor.selectionRotatedPageBounds).toCloselyMatchObject(boundsBefore)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Preserves the same selection bounds when only duplicating the arrows', () => {
|
it('Preserves the same selection bounds when only duplicating the arrows', () => {
|
||||||
editor
|
editor
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.deleteShapes(editor.selectedShapeIds)
|
.deleteShapes(editor.getSelectedShapeIds())
|
||||||
.createShapes(shapes)
|
.createShapes(shapes)
|
||||||
.select(
|
.select(
|
||||||
...editor.currentPageShapes
|
...editor.currentPageShapes
|
||||||
|
@ -193,7 +193,7 @@ describe('When duplicating shapes that include arrows', () => {
|
||||||
)
|
)
|
||||||
|
|
||||||
const boundsBefore = editor.selectionRotatedPageBounds!
|
const boundsBefore = editor.selectionRotatedPageBounds!
|
||||||
editor.duplicateShapes(editor.selectedShapeIds)
|
editor.duplicateShapes(editor.getSelectedShapeIds())
|
||||||
const boundsAfter = editor.selectionRotatedPageBounds!
|
const boundsAfter = editor.selectionRotatedPageBounds!
|
||||||
|
|
||||||
// It's not exactly exact, but close enough is plenty close
|
// It's not exactly exact, but close enough is plenty close
|
||||||
|
|
|
@ -23,7 +23,7 @@ const ids = {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
editor = new TestEditor()
|
editor = new TestEditor()
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
editor.deleteShapes(editor.selectedShapeIds)
|
editor.deleteShapes(editor.getSelectedShapeIds())
|
||||||
editor.createShapes([
|
editor.createShapes([
|
||||||
{
|
{
|
||||||
id: ids.boxA,
|
id: ids.boxA,
|
||||||
|
@ -62,7 +62,7 @@ describe('When flipping horizontally', () => {
|
||||||
it('Flips the selected shapes', () => {
|
it('Flips the selected shapes', () => {
|
||||||
editor.select(ids.boxA, ids.boxB, ids.boxC)
|
editor.select(ids.boxA, ids.boxB, ids.boxC)
|
||||||
editor.mark('flipped')
|
editor.mark('flipped')
|
||||||
editor.flipShapes(editor.selectedShapeIds, 'horizontal')
|
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
|
|
||||||
editor.expectShapeToMatch(
|
editor.expectShapeToMatch(
|
||||||
{
|
{
|
||||||
|
@ -106,7 +106,7 @@ describe('When flipping horizontally', () => {
|
||||||
editor.select(ids.boxA, ids.boxB)
|
editor.select(ids.boxA, ids.boxB)
|
||||||
const a = editor.selectionPageBounds
|
const a = editor.selectionPageBounds
|
||||||
editor.mark('flipped')
|
editor.mark('flipped')
|
||||||
editor.flipShapes(editor.selectedShapeIds, 'horizontal')
|
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
|
|
||||||
const b = editor.selectionPageBounds
|
const b = editor.selectionPageBounds
|
||||||
expect(a!).toCloselyMatchObject(b!)
|
expect(a!).toCloselyMatchObject(b!)
|
||||||
|
@ -131,7 +131,7 @@ describe('When flipping horizontally', () => {
|
||||||
editor.select(ids.boxB, ids.boxC)
|
editor.select(ids.boxB, ids.boxC)
|
||||||
const a = editor.selectionPageBounds
|
const a = editor.selectionPageBounds
|
||||||
editor.mark('flipped')
|
editor.mark('flipped')
|
||||||
editor.flipShapes(editor.selectedShapeIds, 'horizontal')
|
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
|
|
||||||
const b = editor.selectionPageBounds
|
const b = editor.selectionPageBounds
|
||||||
expect(a).toCloselyMatchObject(b!)
|
expect(a).toCloselyMatchObject(b!)
|
||||||
|
@ -142,7 +142,7 @@ describe('When flipping vertically', () => {
|
||||||
it('Flips the selected shapes', () => {
|
it('Flips the selected shapes', () => {
|
||||||
editor.select(ids.boxA, ids.boxB, ids.boxC)
|
editor.select(ids.boxA, ids.boxB, ids.boxC)
|
||||||
editor.mark('flipped')
|
editor.mark('flipped')
|
||||||
editor.flipShapes(editor.selectedShapeIds, 'vertical')
|
editor.flipShapes(editor.getSelectedShapeIds(), 'vertical')
|
||||||
|
|
||||||
editor.expectShapeToMatch(
|
editor.expectShapeToMatch(
|
||||||
{
|
{
|
||||||
|
@ -186,7 +186,7 @@ describe('When flipping vertically', () => {
|
||||||
editor.select(ids.boxA, ids.boxB)
|
editor.select(ids.boxA, ids.boxB)
|
||||||
const a = editor.selectionPageBounds
|
const a = editor.selectionPageBounds
|
||||||
editor.mark('flipped')
|
editor.mark('flipped')
|
||||||
editor.flipShapes(editor.selectedShapeIds, 'vertical')
|
editor.flipShapes(editor.getSelectedShapeIds(), 'vertical')
|
||||||
|
|
||||||
const b = editor.selectionPageBounds
|
const b = editor.selectionPageBounds
|
||||||
expect(a).toCloselyMatchObject(b!)
|
expect(a).toCloselyMatchObject(b!)
|
||||||
|
@ -210,7 +210,7 @@ describe('When flipping vertically', () => {
|
||||||
editor.select(ids.boxB, ids.boxC)
|
editor.select(ids.boxB, ids.boxC)
|
||||||
const a = editor.selectionPageBounds
|
const a = editor.selectionPageBounds
|
||||||
editor.mark('flipped')
|
editor.mark('flipped')
|
||||||
editor.flipShapes(editor.selectedShapeIds, 'vertical')
|
editor.flipShapes(editor.getSelectedShapeIds(), 'vertical')
|
||||||
|
|
||||||
const b = editor.selectionPageBounds
|
const b = editor.selectionPageBounds
|
||||||
expect(a).toCloselyMatchObject(b!)
|
expect(a).toCloselyMatchObject(b!)
|
||||||
|
@ -221,12 +221,12 @@ it('Preserves the selection bounds.', () => {
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
const a = editor.selectionPageBounds
|
const a = editor.selectionPageBounds
|
||||||
editor.mark('flipped')
|
editor.mark('flipped')
|
||||||
editor.flipShapes(editor.selectedShapeIds, 'horizontal')
|
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
|
|
||||||
const b = editor.selectionPageBounds
|
const b = editor.selectionPageBounds
|
||||||
expect(a).toMatchObject(b!)
|
expect(a).toMatchObject(b!)
|
||||||
editor.mark('flipped')
|
editor.mark('flipped')
|
||||||
editor.flipShapes(editor.selectedShapeIds, 'vertical')
|
editor.flipShapes(editor.getSelectedShapeIds(), 'vertical')
|
||||||
|
|
||||||
const c = editor.selectionPageBounds
|
const c = editor.selectionPageBounds
|
||||||
expect(a).toMatchObject(c!)
|
expect(a).toMatchObject(c!)
|
||||||
|
@ -287,7 +287,7 @@ describe('When one shape is selected', () => {
|
||||||
it('Does nothing if the shape is not a group', () => {
|
it('Does nothing if the shape is not a group', () => {
|
||||||
const before = editor.getShape(ids.boxA)!
|
const before = editor.getShape(ids.boxA)!
|
||||||
editor.select(ids.boxA)
|
editor.select(ids.boxA)
|
||||||
editor.flipShapes(editor.selectedShapeIds, 'horizontal')
|
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
|
|
||||||
expect(editor.getShape(ids.boxA)).toMatchObject(before)
|
expect(editor.getShape(ids.boxA)).toMatchObject(before)
|
||||||
})
|
})
|
||||||
|
@ -296,10 +296,10 @@ describe('When one shape is selected', () => {
|
||||||
const fn = jest.fn()
|
const fn = jest.fn()
|
||||||
|
|
||||||
editor.selectAll()
|
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]
|
const groupBefore = editor.selectedShapes[0]
|
||||||
editor.on('change', fn)
|
editor.on('change', fn)
|
||||||
editor.flipShapes(editor.selectedShapeIds, 'horizontal')
|
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
|
|
||||||
// The change event should have been called
|
// The change event should have been called
|
||||||
jest.runOnlyPendingTimers()
|
jest.runOnlyPendingTimers()
|
||||||
|
@ -352,7 +352,7 @@ describe('flipping rotated shapes', () => {
|
||||||
arrowD: createShapeId('arrowD'),
|
arrowD: createShapeId('arrowD'),
|
||||||
}
|
}
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
editor.selectAll().deleteShapes(editor.selectedShapeIds)
|
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
|
||||||
const props: Partial<TLArrowShapeProps> = {
|
const props: Partial<TLArrowShapeProps> = {
|
||||||
start: {
|
start: {
|
||||||
type: 'point',
|
type: 'point',
|
||||||
|
@ -416,7 +416,7 @@ describe('flipping rotated shapes', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
test('flipping horizontally', () => {
|
test('flipping horizontally', () => {
|
||||||
editor.flipShapes(editor.selectedShapeIds, 'horizontal')
|
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
// now arrow A should be pointing from top to left
|
// now arrow A should be pointing from top to left
|
||||||
let { start, end } = getStartAndEndPoints(ids.arrowA)
|
let { start, end } = getStartAndEndPoints(ids.arrowA)
|
||||||
expect(start).toCloselyMatchObject(topPoint)
|
expect(start).toCloselyMatchObject(topPoint)
|
||||||
|
@ -439,7 +439,7 @@ describe('flipping rotated shapes', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
test('flipping vertically', () => {
|
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
|
// arrows that have height 0 get nudged by a pixel when flipped vertically
|
||||||
// so we need to use a fairly loose tolerance
|
// so we need to use a fairly loose tolerance
|
||||||
// now arrow A should be pointing from bottom to right
|
// now arrow A should be pointing from bottom to right
|
||||||
|
@ -558,18 +558,18 @@ describe('When flipping shapes that include arrows', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Flips horizontally', () => {
|
it('Flips horizontally', () => {
|
||||||
editor.selectAll().deleteShapes(editor.selectedShapeIds).createShapes(shapes)
|
editor.selectAll().deleteShapes(editor.getSelectedShapeIds()).createShapes(shapes)
|
||||||
|
|
||||||
const boundsBefore = editor.selectionRotatedPageBounds!
|
const boundsBefore = editor.selectionRotatedPageBounds!
|
||||||
editor.flipShapes(editor.selectedShapeIds, 'horizontal')
|
editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
|
||||||
expect(editor.selectionRotatedPageBounds).toCloselyMatchObject(boundsBefore)
|
expect(editor.selectionRotatedPageBounds).toCloselyMatchObject(boundsBefore)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Flips vertically', () => {
|
it('Flips vertically', () => {
|
||||||
editor.selectAll().deleteShapes(editor.selectedShapeIds).createShapes(shapes)
|
editor.selectAll().deleteShapes(editor.getSelectedShapeIds()).createShapes(shapes)
|
||||||
|
|
||||||
const boundsBefore = editor.selectionRotatedPageBounds!
|
const boundsBefore = editor.selectionRotatedPageBounds!
|
||||||
editor.flipShapes(editor.selectedShapeIds, 'vertical')
|
editor.flipShapes(editor.getSelectedShapeIds(), 'vertical')
|
||||||
expect(editor.selectionRotatedPageBounds).toCloselyMatchObject(boundsBefore)
|
expect(editor.selectionRotatedPageBounds).toCloselyMatchObject(boundsBefore)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -515,15 +515,15 @@ describe('frame shapes', () => {
|
||||||
|
|
||||||
const frameId = editor.onlySelectedShape!.id
|
const frameId = editor.onlySelectedShape!.id
|
||||||
|
|
||||||
expect(editor.selectedShapeIds[0]).toBe(frameId)
|
expect(editor.getSelectedShapeIds()[0]).toBe(frameId)
|
||||||
expect(editor.currentPageState.editingShapeId).toBe(null)
|
expect(editor.getCurrentPageState().editingShapeId).toBe(null)
|
||||||
|
|
||||||
editor.setCurrentTool('select')
|
editor.setCurrentTool('select')
|
||||||
|
|
||||||
editor.keyDown('Enter')
|
editor.keyDown('Enter')
|
||||||
editor.keyUp('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', () => {
|
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.pointerDown(50, 50).pointerMove(150, 150)
|
||||||
editor.expectPathToBe('root.select.brushing')
|
editor.expectPathToBe('root.select.brushing')
|
||||||
|
|
||||||
expect(editor.selectedShapeIds).toHaveLength(0)
|
expect(editor.getSelectedShapeIds()).toHaveLength(0)
|
||||||
|
|
||||||
editor.pointerMove(250, 250)
|
editor.pointerMove(250, 250)
|
||||||
|
|
||||||
expect(editor.selectedShapeIds).toHaveLength(1)
|
expect(editor.getSelectedShapeIds()).toHaveLength(1)
|
||||||
expect(editor.onlySelectedShape!.id).toBe(frameId)
|
expect(editor.onlySelectedShape!.id).toBe(frameId)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -555,7 +555,7 @@ describe('frame shapes', () => {
|
||||||
editor.pointerDown(150, 150).pointerMove(250, 250)
|
editor.pointerDown(150, 150).pointerMove(250, 250)
|
||||||
editor.expectPathToBe('root.select.brushing')
|
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', () => {
|
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)
|
editor.pointerDown(500, 500).pointerMove(300, 300).pointerUp(300, 300)
|
||||||
|
|
||||||
// Check if the inner box was selected
|
// 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
|
// Select from outside the frame via box brushing
|
||||||
// but also include the frame in the selection
|
// but also include the frame in the selection
|
||||||
editor.pointerDown(400, 0).pointerMove(195, 175).pointerUp(195, 175)
|
editor.pointerDown(400, 0).pointerMove(195, 175).pointerUp(195, 175)
|
||||||
|
|
||||||
// Check if the inner box was selected
|
// Check if the inner box was selected
|
||||||
expect(editor.selectedShapeIds).toHaveLength(1)
|
expect(editor.getSelectedShapeIds()).toHaveLength(1)
|
||||||
expect(editor.onlySelectedShape!.id).toBe(innerBoxId)
|
expect(editor.onlySelectedShape!.id).toBe(innerBoxId)
|
||||||
|
|
||||||
// Deselect everything
|
// Deselect everything
|
||||||
|
@ -594,7 +594,7 @@ describe('frame shapes', () => {
|
||||||
|
|
||||||
// Check if the inner box was selected
|
// Check if the inner box was selected
|
||||||
editor.pointerUp(300, 300)
|
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', () => {
|
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.setCurrentTool('select')
|
||||||
editor.select(boxBId, boxCId)
|
editor.select(boxBId, boxCId)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
const groupId = editor.onlySelectedShape!.id
|
const groupId = editor.onlySelectedShape!.id
|
||||||
|
|
||||||
editor.setCurrentTool('arrow')
|
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', () => {
|
it('When dragging a shape out of a frame', () => {
|
||||||
editor.select(ids.box1, ids.box2)
|
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)
|
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', () => {
|
it('reparents the shape to the page if it leaves the frame', () => {
|
||||||
editor.select(ids.box1, ids.box2)
|
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)
|
expect(editor.getShape(ids.box1)!.parentId).toBe(ids.group1)
|
||||||
|
|
||||||
|
|
|
@ -85,8 +85,8 @@ afterEach(() => {
|
||||||
const getAllShapes = () => editor.currentPageShapes
|
const getAllShapes = () => editor.currentPageShapes
|
||||||
|
|
||||||
const onlySelectedId = () => {
|
const onlySelectedId = () => {
|
||||||
expect(editor.selectedShapeIds).toHaveLength(1)
|
expect(editor.getSelectedShapeIds()).toHaveLength(1)
|
||||||
return editor.selectedShapeIds[0]
|
return editor.getSelectedShapeIds()[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
const onlySelectedShape = () => {
|
const onlySelectedShape = () => {
|
||||||
|
@ -114,12 +114,12 @@ describe('creating groups', () => {
|
||||||
|
|
||||||
editor.select(ids.boxA, ids.boxB)
|
editor.select(ids.boxA, ids.boxB)
|
||||||
expect(getAllShapes()).toHaveLength(3)
|
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(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.boxA)).toBeTruthy()
|
||||||
expect(editor.getShape(ids.boxB)).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)])
|
editor.createShapes([box(ids.boxA, 0, 0), box(ids.boxB, 20, 0), box(ids.boxC, 40, 0)])
|
||||||
expect(getAllShapes()).toHaveLength(3)
|
expect(getAllShapes()).toHaveLength(3)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
expect(getAllShapes()).toHaveLength(3)
|
expect(getAllShapes()).toHaveLength(3)
|
||||||
editor.select(ids.boxA)
|
editor.select(ids.boxA)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
expect(getAllShapes()).toHaveLength(3)
|
expect(getAllShapes()).toHaveLength(3)
|
||||||
expect(onlySelectedId()).toBe(ids.boxA)
|
expect(onlySelectedId()).toBe(ids.boxA)
|
||||||
})
|
})
|
||||||
|
@ -181,7 +181,7 @@ describe('creating groups', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
editor.select(ids.boxA, ids.boxB, ids.boxC)
|
editor.select(ids.boxA, ids.boxB, ids.boxC)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
try {
|
try {
|
||||||
expect({
|
expect({
|
||||||
|
@ -213,17 +213,17 @@ describe('creating groups', () => {
|
||||||
])
|
])
|
||||||
|
|
||||||
editor.select(ids.boxA, ids.boxB)
|
editor.select(ids.boxA, ids.boxB)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
const groupAId = onlySelectedId()
|
const groupAId = onlySelectedId()
|
||||||
|
|
||||||
editor.select(ids.boxC, ids.boxD)
|
editor.select(ids.boxC, ids.boxD)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
const groupBId = onlySelectedId()
|
const groupBId = onlySelectedId()
|
||||||
|
|
||||||
editor.select(groupAId, groupBId)
|
editor.select(groupAId, groupBId)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
const uberGroup = onlySelectedShape()
|
const uberGroup = onlySelectedShape()
|
||||||
expect(uberGroup.type).toBe(GroupShapeUtil.type)
|
expect(uberGroup.type).toBe(GroupShapeUtil.type)
|
||||||
|
@ -258,14 +258,14 @@ describe('creating groups', () => {
|
||||||
])
|
])
|
||||||
|
|
||||||
editor.select(ids.boxA, ids.boxB, ids.boxC)
|
editor.select(ids.boxA, ids.boxB, ids.boxC)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
const groupA = onlySelectedShape()
|
const groupA = onlySelectedShape()
|
||||||
editor.select(ids.boxD, ids.boxE, ids.boxF)
|
editor.select(ids.boxD, ids.boxE, ids.boxF)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
const groupB = onlySelectedShape()
|
const groupB = onlySelectedShape()
|
||||||
|
|
||||||
editor.select(ids.boxB, ids.boxE)
|
editor.select(ids.boxB, ids.boxE)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
const groupC = onlySelectedShape()
|
const groupC = onlySelectedShape()
|
||||||
|
|
||||||
expect(children(groupA).size).toBe(2)
|
expect(children(groupA).size).toBe(2)
|
||||||
|
@ -294,9 +294,9 @@ describe('creating groups', () => {
|
||||||
editor.updateInstanceState({ isReadonly: true })
|
editor.updateInstanceState({ isReadonly: true })
|
||||||
editor.setCurrentTool('hand')
|
editor.setCurrentTool('hand')
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
expect(editor.selectedShapeIds.length).toBe(3)
|
expect(editor.getSelectedShapeIds().length).toBe(3)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
expect(editor.selectedShapeIds.length).toBe(3)
|
expect(editor.getSelectedShapeIds().length).toBe(3)
|
||||||
})
|
})
|
||||||
it('keeps order correct simple', () => {
|
it('keeps order correct simple', () => {
|
||||||
// 0 10 20 30 40 50 60 70
|
// 0 10 20 30 40 50 60 70
|
||||||
|
@ -311,7 +311,7 @@ describe('creating groups', () => {
|
||||||
])
|
])
|
||||||
|
|
||||||
editor.select(ids.boxC, ids.boxB)
|
editor.select(ids.boxC, ids.boxB)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
const groupAId = onlySelectedId()
|
const groupAId = onlySelectedId()
|
||||||
const sortedGroupChildrenIds = editor
|
const sortedGroupChildrenIds = editor
|
||||||
|
@ -344,7 +344,7 @@ describe('creating groups', () => {
|
||||||
])
|
])
|
||||||
|
|
||||||
editor.select(ids.boxC, ids.boxA)
|
editor.select(ids.boxC, ids.boxA)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
const groupAId = onlySelectedId()
|
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.createShapes([box(ids.boxA, 0, 0), box(ids.boxB, 20, 0), box(ids.boxC, 40, 0)])
|
||||||
|
|
||||||
editor.select(ids.boxA, ids.boxB)
|
editor.select(ids.boxA, ids.boxB)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
const groupA = onlySelectedShape()
|
const groupA = onlySelectedShape()
|
||||||
|
|
||||||
editor.ungroupShapes(editor.selectedShapeIds)
|
editor.ungroupShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
expect(isRemoved(groupA)).toBe(true)
|
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({
|
expect(editor.getShapePageBounds(ids.boxA)!).toCloselyMatchObject({
|
||||||
x: 0,
|
x: 0,
|
||||||
|
@ -401,14 +401,16 @@ describe('ungrouping shapes', () => {
|
||||||
it('selects the groups children and other non-group shapes on ungroup', () => {
|
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.createShapes([box(ids.boxA, 0, 0), box(ids.boxB, 20, 0), box(ids.boxC, 40, 0)])
|
||||||
editor.select(ids.boxA, ids.boxB)
|
editor.select(ids.boxA, ids.boxB)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
const groupA = onlySelectedShape()
|
const groupA = onlySelectedShape()
|
||||||
|
|
||||||
editor.select(groupA.id, ids.boxC)
|
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', () => {
|
it('preserves the page positions and rotations of the ungrouped shapes', () => {
|
||||||
for (let i = 0; i < 100; i++) {
|
for (let i = 0; i < 100; i++) {
|
||||||
|
@ -442,9 +444,9 @@ describe('ungrouping shapes', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
editor.select(ids.boxA, ids.boxB, ids.boxC)
|
editor.select(ids.boxA, ids.boxB, ids.boxC)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
editor.ungroupShapes(editor.selectedShapeIds)
|
editor.ungroupShapes(editor.getSelectedShapeIds())
|
||||||
expect(editor.selectedShapeIds.length).toBe(3)
|
expect(editor.getSelectedShapeIds().length).toBe(3)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
expect({
|
expect({
|
||||||
|
@ -476,20 +478,20 @@ describe('ungrouping shapes', () => {
|
||||||
])
|
])
|
||||||
|
|
||||||
editor.select(ids.boxA, ids.boxB)
|
editor.select(ids.boxA, ids.boxB)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
const groupAId = onlySelectedId()
|
const groupAId = onlySelectedId()
|
||||||
|
|
||||||
editor.select(ids.boxC, ids.boxD)
|
editor.select(ids.boxC, ids.boxD)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
const groupBId = onlySelectedId()
|
const groupBId = onlySelectedId()
|
||||||
|
|
||||||
editor.select(groupAId, groupBId)
|
editor.select(groupAId, groupBId)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
expect(editor.selectedShapeIds.length).toBe(1)
|
expect(editor.getSelectedShapeIds().length).toBe(1)
|
||||||
editor.ungroupShapes(editor.selectedShapeIds)
|
editor.ungroupShapes(editor.getSelectedShapeIds())
|
||||||
expect(editor.selectedShapeIds.length).toBe(2)
|
expect(editor.getSelectedShapeIds().length).toBe(2)
|
||||||
expect(editor.getShape(groupAId)).not.toBe(undefined)
|
expect(editor.getShape(groupAId)).not.toBe(undefined)
|
||||||
expect(editor.getShape(groupBId)).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.createShapes([box(ids.boxA, 0, 0), box(ids.boxB, 20, 0), box(ids.boxC, 40, 0)])
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
expect(editor.selectedShapeIds.length).toBe(3)
|
expect(editor.getSelectedShapeIds().length).toBe(3)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
expect(editor.selectedShapeIds.length).toBe(1)
|
expect(editor.getSelectedShapeIds().length).toBe(1)
|
||||||
editor.updateInstanceState({ isReadonly: true })
|
editor.updateInstanceState({ isReadonly: true })
|
||||||
editor.setCurrentTool('hand')
|
editor.setCurrentTool('hand')
|
||||||
|
|
||||||
editor.ungroupShapes(editor.selectedShapeIds)
|
editor.ungroupShapes(editor.getSelectedShapeIds())
|
||||||
expect(editor.selectedShapeIds.length).toBe(1)
|
expect(editor.getSelectedShapeIds().length).toBe(1)
|
||||||
expect(onlySelectedShape().type).toBe(GroupShapeUtil.type)
|
expect(onlySelectedShape().type).toBe(GroupShapeUtil.type)
|
||||||
})
|
})
|
||||||
it('keeps order correct simple', () => {
|
it('keeps order correct simple', () => {
|
||||||
|
@ -523,8 +525,8 @@ describe('ungrouping shapes', () => {
|
||||||
])
|
])
|
||||||
|
|
||||||
editor.select(ids.boxC, ids.boxB)
|
editor.select(ids.boxC, ids.boxB)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
editor.ungroupShapes(editor.selectedShapeIds)
|
editor.ungroupShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
const sortedShapesOnCurrentPage = editor.currentPageShapes
|
const sortedShapesOnCurrentPage = editor.currentPageShapes
|
||||||
.sort(sortByIndex)
|
.sort(sortByIndex)
|
||||||
|
@ -548,8 +550,8 @@ describe('ungrouping shapes', () => {
|
||||||
])
|
])
|
||||||
|
|
||||||
editor.select(ids.boxC, ids.boxA)
|
editor.select(ids.boxC, ids.boxA)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
editor.ungroupShapes(editor.selectedShapeIds)
|
editor.ungroupShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
const sortedShapesOnCurrentPage = editor.currentPageShapes
|
const sortedShapesOnCurrentPage = editor.currentPageShapes
|
||||||
.sort(sortByIndex)
|
.sort(sortByIndex)
|
||||||
|
@ -580,7 +582,7 @@ describe('the bounds of a group', () => {
|
||||||
])
|
])
|
||||||
|
|
||||||
editor.select(ids.boxA, ids.boxB)
|
editor.select(ids.boxA, ids.boxB)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
const group = onlySelectedShape()
|
const group = onlySelectedShape()
|
||||||
|
|
||||||
expect(editor.getShapePageBounds(group.id)!.minX).toBe(0)
|
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.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.select(ids.boxA, ids.boxB, ids.boxC)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
const group = onlySelectedShape()
|
const group = onlySelectedShape()
|
||||||
|
|
||||||
expect(editor.getShapePageBounds(group.id)!).toCloselyMatchObject({
|
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.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.select(ids.boxA, ids.boxB, ids.boxC)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
const group = onlySelectedShape()
|
const group = onlySelectedShape()
|
||||||
|
|
||||||
expect(editor.getShapePageBounds(group.id)!).toCloselyMatchObject({
|
expect(editor.getShapePageBounds(group.id)!).toCloselyMatchObject({
|
||||||
|
@ -688,7 +690,7 @@ describe('the bounds of a rotated group', () => {
|
||||||
])
|
])
|
||||||
|
|
||||||
editor.select(ids.boxA, ids.boxB)
|
editor.select(ids.boxA, ids.boxB)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
const group = onlySelectedShape()
|
const group = onlySelectedShape()
|
||||||
|
|
||||||
editor.rotateSelection(Math.PI / 2)
|
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.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.select(ids.boxA, ids.boxB, ids.boxC)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
const group = onlySelectedShape()
|
const group = onlySelectedShape()
|
||||||
editor.updateShapes([{ id: group.id, type: 'group', rotation: Math.PI / 2, x: 10, y: 0 }])
|
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 })
|
expect(editor.getShapeGeometry(ids.boxA)!.bounds).toMatchObject({ x: 0, y: 0, w: 10, h: 10 })
|
||||||
|
|
||||||
editor.select(ids.boxA, ids.boxB, ids.boxC)
|
editor.select(ids.boxA, ids.boxB, ids.boxC)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
const group = onlySelectedShape()
|
const group = onlySelectedShape()
|
||||||
editor.updateShapes([{ id: group.id, type: 'group', rotation: Math.PI / 2, x: 10, y: 0 }])
|
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),
|
box(ids.boxD, 60, 0),
|
||||||
])
|
])
|
||||||
editor.select(ids.boxA, ids.boxB)
|
editor.select(ids.boxA, ids.boxB)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
groupAId = onlySelectedId()
|
groupAId = onlySelectedId()
|
||||||
editor.select(ids.boxC, ids.boxD)
|
editor.select(ids.boxC, ids.boxD)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
groupBId = onlySelectedId()
|
groupBId = onlySelectedId()
|
||||||
editor.select(groupAId, groupBId)
|
editor.select(groupAId, groupBId)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
groupCId = onlySelectedId()
|
groupCId = onlySelectedId()
|
||||||
editor.selectNone()
|
editor.selectNone()
|
||||||
})
|
})
|
||||||
|
@ -839,11 +841,11 @@ describe('focus layers', () => {
|
||||||
expect(editor.focusedGroupId).toBe(editor.currentPageId)
|
expect(editor.focusedGroupId).toBe(editor.currentPageId)
|
||||||
editor.select(ids.boxA)
|
editor.select(ids.boxA)
|
||||||
expect(editor.focusedGroupId).toBe(groupAId)
|
expect(editor.focusedGroupId).toBe(groupAId)
|
||||||
editor.setSelectedShapes([...editor.selectedShapeIds, ids.boxC])
|
editor.setSelectedShapes([...editor.getSelectedShapeIds(), ids.boxC])
|
||||||
expect(editor.focusedGroupId).toBe(groupCId)
|
expect(editor.focusedGroupId).toBe(groupCId)
|
||||||
editor.deselect(ids.boxA)
|
editor.deselect(ids.boxA)
|
||||||
expect(editor.focusedGroupId).toBe(groupBId)
|
expect(editor.focusedGroupId).toBe(groupBId)
|
||||||
editor.setSelectedShapes([...editor.selectedShapeIds, ids.boxB])
|
editor.setSelectedShapes([...editor.getSelectedShapeIds(), ids.boxB])
|
||||||
expect(editor.focusedGroupId).toBe(groupCId)
|
expect(editor.focusedGroupId).toBe(groupCId)
|
||||||
})
|
})
|
||||||
it('should not adjust the focus layer when clearing the selection', () => {
|
it('should not adjust the focus layer when clearing the selection', () => {
|
||||||
|
@ -960,14 +962,14 @@ describe('the select tool', () => {
|
||||||
editor
|
editor
|
||||||
.pointerDown(60, 0, ids.boxC, { shiftKey: true })
|
.pointerDown(60, 0, ids.boxC, { shiftKey: true })
|
||||||
.pointerUp(0, 0, ids.boxC, { shiftKey: true })
|
.pointerUp(0, 0, ids.boxC, { shiftKey: true })
|
||||||
expect(editor.selectedShapeIds.includes(ids.boxA)).toBe(true)
|
expect(editor.getSelectedShapeIds().includes(ids.boxA)).toBe(true)
|
||||||
expect(editor.selectedShapeIds.includes(groupBId)).toBe(true)
|
expect(editor.getSelectedShapeIds().includes(groupBId)).toBe(true)
|
||||||
expect(editor.focusedGroupId).toBe(groupCId)
|
expect(editor.focusedGroupId).toBe(groupCId)
|
||||||
|
|
||||||
editor.pointerDown(60, 0, ids.boxC, { shiftKey: true }).pointerUp()
|
editor.pointerDown(60, 0, ids.boxC, { shiftKey: true }).pointerUp()
|
||||||
expect(editor.selectedShapeIds.includes(ids.boxA)).toBe(true)
|
expect(editor.getSelectedShapeIds().includes(ids.boxA)).toBe(true)
|
||||||
expect(editor.selectedShapeIds.includes(groupBId)).toBe(false)
|
expect(editor.getSelectedShapeIds().includes(groupBId)).toBe(false)
|
||||||
expect(editor.selectedShapeIds.includes(ids.boxC)).toBe(true)
|
expect(editor.getSelectedShapeIds().includes(ids.boxC)).toBe(true)
|
||||||
expect(editor.focusedGroupId).toBe(groupCId)
|
expect(editor.focusedGroupId).toBe(groupCId)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -978,7 +980,7 @@ describe('the select tool', () => {
|
||||||
// click outside the focused group, but inside another group
|
// click outside the focused group, but inside another group
|
||||||
editor.pointerDown(-235, 5, { target: 'canvas' }).pointerUp(-235, 5)
|
editor.pointerDown(-235, 5, { target: 'canvas' }).pointerUp(-235, 5)
|
||||||
expect(editor.focusedGroupId).toBe(editor.currentPageId)
|
expect(editor.focusedGroupId).toBe(editor.currentPageId)
|
||||||
expect(editor.selectedShapeIds).toHaveLength(0)
|
expect(editor.getSelectedShapeIds()).toHaveLength(0)
|
||||||
|
|
||||||
editor.select(ids.boxA)
|
editor.select(ids.boxA)
|
||||||
expect(editor.focusedGroupId).toBe(groupAId)
|
expect(editor.focusedGroupId).toBe(groupAId)
|
||||||
|
@ -986,7 +988,7 @@ describe('the select tool', () => {
|
||||||
// click the empty canvas
|
// click the empty canvas
|
||||||
editor.pointerDown(-235, 50, { target: 'canvas' }).pointerUp(-235, 50)
|
editor.pointerDown(-235, 50, { target: 'canvas' }).pointerUp(-235, 50)
|
||||||
expect(editor.focusedGroupId).toBe(editor.currentPageId)
|
expect(editor.focusedGroupId).toBe(editor.currentPageId)
|
||||||
expect(editor.selectedShapeIds).toHaveLength(0)
|
expect(editor.getSelectedShapeIds()).toHaveLength(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
// ! Removed with hollow shape clicking feature
|
// ! 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', () => {
|
it('should pop the focus layer when escape is pressed in idle state', () => {
|
||||||
editor.select(ids.boxA)
|
editor.select(ids.boxA)
|
||||||
expect(editor.selectedShapeIds).toMatchObject([ids.boxA]) // box1
|
expect(editor.getSelectedShapeIds()).toMatchObject([ids.boxA]) // box1
|
||||||
expect(editor.focusedGroupId).toBe(groupAId)
|
expect(editor.focusedGroupId).toBe(groupAId)
|
||||||
// deselct
|
// deselct
|
||||||
editor.cancel()
|
editor.cancel()
|
||||||
expect(editor.selectedShapeIds).toMatchObject([groupAId]) // groupA
|
expect(editor.getSelectedShapeIds()).toMatchObject([groupAId]) // groupA
|
||||||
expect(editor.focusedGroupId).toBe(groupCId)
|
expect(editor.focusedGroupId).toBe(groupCId)
|
||||||
// pop focus layer
|
// pop focus layer
|
||||||
editor.cancel()
|
editor.cancel()
|
||||||
expect(editor.selectedShapeIds.length).toBe(1) // Group C
|
expect(editor.getSelectedShapeIds().length).toBe(1) // Group C
|
||||||
expect(editor.focusedGroupId).toBe(editor.currentPageId)
|
expect(editor.focusedGroupId).toBe(editor.currentPageId)
|
||||||
editor.cancel()
|
editor.cancel()
|
||||||
expect(editor.selectedShapeIds.length).toBe(0)
|
expect(editor.getSelectedShapeIds().length).toBe(0)
|
||||||
expect(editor.focusedGroupId).toBe(editor.currentPageId)
|
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)
|
editor.pointerDown(-305, -5, { target: 'canvas' }).pointerMove(35, 9, ids.boxB)
|
||||||
|
|
||||||
expect(editor.root.path.get()).toBe(`root.select.brushing`)
|
expect(editor.root.path.get()).toBe(`root.select.brushing`)
|
||||||
expect(editor.selectedShapeIds.includes(ids.boxA)).toBe(true)
|
expect(editor.getSelectedShapeIds().includes(ids.boxA)).toBe(true)
|
||||||
expect(editor.selectedShapeIds.includes(ids.boxB)).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
|
// 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
|
// 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
|
// │ mouse selection
|
||||||
editor.pointerDown(12.5, -15, undefined).pointerMove(17.5, 15, ids.boxB)
|
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)
|
editor.pointerMove(35, 15)
|
||||||
expect(onlySelectedId()).toBe(groupCId)
|
expect(onlySelectedId()).toBe(groupCId)
|
||||||
})
|
})
|
||||||
|
@ -1104,13 +1106,13 @@ describe("when a group's children are deleted", () => {
|
||||||
box(ids.boxD, 60, 0),
|
box(ids.boxD, 60, 0),
|
||||||
])
|
])
|
||||||
editor.select(ids.boxA, ids.boxB)
|
editor.select(ids.boxA, ids.boxB)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
groupAId = onlySelectedId()
|
groupAId = onlySelectedId()
|
||||||
editor.select(ids.boxC, ids.boxD)
|
editor.select(ids.boxC, ids.boxD)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
groupBId = onlySelectedId()
|
groupBId = onlySelectedId()
|
||||||
editor.select(groupAId, groupBId)
|
editor.select(groupAId, groupBId)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
groupCId = onlySelectedId()
|
groupCId = onlySelectedId()
|
||||||
editor.selectNone()
|
editor.selectNone()
|
||||||
})
|
})
|
||||||
|
@ -1148,7 +1150,7 @@ describe('creating new shapes', () => {
|
||||||
// └──────────────────────────────┘
|
// └──────────────────────────────┘
|
||||||
editor.createShapes([box(ids.boxA, 0, 0), box(ids.boxB, 90, 90)])
|
editor.createShapes([box(ids.boxA, 0, 0), box(ids.boxB, 90, 90)])
|
||||||
editor.select(ids.boxA, ids.boxB)
|
editor.select(ids.boxA, ids.boxB)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
groupA = onlySelectedShape() as TLGroupShape
|
groupA = onlySelectedShape() as TLGroupShape
|
||||||
editor.selectNone()
|
editor.selectNone()
|
||||||
})
|
})
|
||||||
|
@ -1478,13 +1480,13 @@ describe('erasing', () => {
|
||||||
box(ids.boxE, 0, 20),
|
box(ids.boxE, 0, 20),
|
||||||
])
|
])
|
||||||
editor.select(ids.boxA, ids.boxB)
|
editor.select(ids.boxA, ids.boxB)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
groupAId = onlySelectedId()
|
groupAId = onlySelectedId()
|
||||||
editor.select(ids.boxC, ids.boxD)
|
editor.select(ids.boxC, ids.boxD)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
groupBId = onlySelectedId()
|
groupBId = onlySelectedId()
|
||||||
editor.select(groupAId, groupBId)
|
editor.select(groupAId, groupBId)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
groupCId = onlySelectedId()
|
groupCId = onlySelectedId()
|
||||||
editor.selectNone()
|
editor.selectNone()
|
||||||
})
|
})
|
||||||
|
@ -1494,8 +1496,8 @@ describe('erasing', () => {
|
||||||
|
|
||||||
// erase D
|
// erase D
|
||||||
editor.pointerDown(65, 5, ids.boxD)
|
editor.pointerDown(65, 5, ids.boxD)
|
||||||
expect(editor.currentPageState.erasingShapeIds.length).toBe(1)
|
expect(editor.getCurrentPageState().erasingShapeIds.length).toBe(1)
|
||||||
expect(editor.currentPageState.erasingShapeIds[0]).toBe(groupCId)
|
expect(editor.getCurrentPageState().erasingShapeIds[0]).toBe(groupCId)
|
||||||
editor.pointerUp()
|
editor.pointerUp()
|
||||||
expect(editor.getShape(groupCId)).toBeFalsy()
|
expect(editor.getShape(groupCId)).toBeFalsy()
|
||||||
})
|
})
|
||||||
|
@ -1515,8 +1517,8 @@ describe('erasing', () => {
|
||||||
|
|
||||||
// erase B
|
// erase B
|
||||||
editor.pointerDown(25, 5, ids.boxB)
|
editor.pointerDown(25, 5, ids.boxB)
|
||||||
expect(editor.currentPageState.erasingShapeIds.length).toBe(1)
|
expect(editor.getCurrentPageState().erasingShapeIds.length).toBe(1)
|
||||||
expect(editor.currentPageState.erasingShapeIds[0]).toBe(ids.boxB)
|
expect(editor.getCurrentPageState().erasingShapeIds[0]).toBe(ids.boxB)
|
||||||
editor.pointerUp()
|
editor.pointerUp()
|
||||||
|
|
||||||
// group A disappears
|
// group A disappears
|
||||||
|
@ -1531,8 +1533,8 @@ describe('erasing', () => {
|
||||||
|
|
||||||
// erase E
|
// erase E
|
||||||
editor.pointerDown(5, 25, ids.boxE)
|
editor.pointerDown(5, 25, ids.boxE)
|
||||||
expect(editor.currentPageState.erasingShapeIds.length).toBe(1)
|
expect(editor.getCurrentPageState().erasingShapeIds.length).toBe(1)
|
||||||
expect(editor.currentPageState.erasingShapeIds[0]).toBe(ids.boxE)
|
expect(editor.getCurrentPageState().erasingShapeIds[0]).toBe(ids.boxE)
|
||||||
|
|
||||||
// move to group B
|
// move to group B
|
||||||
editor.pointerMove(65, 5)
|
editor.pointerMove(65, 5)
|
||||||
|
@ -1545,7 +1547,7 @@ describe('binding bug', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
editor.createShapes([box(ids.boxA, 0, 0, 10, 10), box(ids.boxB, 50, 0, 10, 10)])
|
editor.createShapes([box(ids.boxA, 0, 0, 10, 10), box(ids.boxB, 50, 0, 10, 10)])
|
||||||
editor.select(ids.boxA, ids.boxB)
|
editor.select(ids.boxA, ids.boxB)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
editor.selectNone()
|
editor.selectNone()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1585,13 +1587,13 @@ describe('bindings', () => {
|
||||||
box(ids.boxE, 0, 20),
|
box(ids.boxE, 0, 20),
|
||||||
])
|
])
|
||||||
editor.select(ids.boxA, ids.boxB)
|
editor.select(ids.boxA, ids.boxB)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
groupAId = onlySelectedId()
|
groupAId = onlySelectedId()
|
||||||
editor.select(ids.boxC, ids.boxD)
|
editor.select(ids.boxC, ids.boxD)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
groupBId = onlySelectedId()
|
groupBId = onlySelectedId()
|
||||||
editor.select(groupAId, groupBId)
|
editor.select(groupAId, groupBId)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
editor.selectNone()
|
editor.selectNone()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1670,7 +1672,7 @@ describe('grouping arrows', () => {
|
||||||
expect(arrowBBefore.index).toBe('a2')
|
expect(arrowBBefore.index).toBe('a2')
|
||||||
|
|
||||||
editor.select(arrowAId, arrowBId)
|
editor.select(arrowAId, arrowBId)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
const arrowAAfter = editor.getShape(arrowAId)!
|
const arrowAAfter = editor.getShape(arrowAId)!
|
||||||
const arrowBAfter = editor.getShape(arrowBId)!
|
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.createShapes([box(ids.boxA, 0, 0), box(ids.boxB, 90, 90)])
|
||||||
editor.select(ids.boxA, ids.boxB)
|
editor.select(ids.boxA, ids.boxB)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
groupA = onlySelectedShape() as TLGroupShape
|
groupA = onlySelectedShape() as TLGroupShape
|
||||||
editor.selectNone()
|
editor.selectNone()
|
||||||
})
|
})
|
||||||
|
@ -1903,13 +1905,13 @@ describe('snapping', () => {
|
||||||
box(ids.boxE, 0, 20),
|
box(ids.boxE, 0, 20),
|
||||||
])
|
])
|
||||||
editor.select(ids.boxA, ids.boxB)
|
editor.select(ids.boxA, ids.boxB)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
groupAId = onlySelectedId()
|
groupAId = onlySelectedId()
|
||||||
editor.select(ids.boxC, ids.boxD)
|
editor.select(ids.boxC, ids.boxD)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
groupBId = onlySelectedId()
|
groupBId = onlySelectedId()
|
||||||
editor.select(groupAId, groupBId)
|
editor.select(groupAId, groupBId)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
groupCId = onlySelectedId()
|
groupCId = onlySelectedId()
|
||||||
editor.selectNone()
|
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', () => {
|
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.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.select(ids.boxA, ids.boxB, ids.boxC)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
editor.keyDown('Enter')
|
editor.keyDown('Enter')
|
||||||
editor.keyUp('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', () => {
|
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.boxA, 0, 0), box(ids.boxB, 20, 0)])
|
||||||
editor.createShapes([box(ids.boxC, 40, 0), box(ids.boxD, 70, 0)])
|
editor.createShapes([box(ids.boxC, 40, 0), box(ids.boxD, 70, 0)])
|
||||||
editor.select(ids.boxA, ids.boxB)
|
editor.select(ids.boxA, ids.boxB)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
editor.select(ids.boxC, ids.boxD)
|
editor.select(ids.boxC, ids.boxD)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
editor.selectAll() // both groups
|
editor.selectAll() // both groups
|
||||||
editor.keyDown('Enter')
|
editor.keyDown('Enter')
|
||||||
editor.keyUp('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.select(ids.boxA, ids.boxB)
|
||||||
editor.setOpacityForSelectedShapes(0.5)
|
editor.setOpacityForSelectedShapes(0.5)
|
||||||
editor.setOpacityForNextShapes(0.5)
|
editor.setOpacityForNextShapes(0.5)
|
||||||
editor.groupShapes(editor.selectedShapeIds)
|
editor.groupShapes(editor.getSelectedShapeIds())
|
||||||
const group = editor.getShape(onlySelectedId())!
|
const group = editor.getShape(onlySelectedId())!
|
||||||
assert(editor.isShapeOfType<TLGroupShape>(group, 'group'))
|
assert(editor.isShapeOfType<TLGroupShape>(group, 'group'))
|
||||||
expect(group.opacity).toBe(1)
|
expect(group.opacity).toBe(1)
|
||||||
|
@ -1988,7 +1990,7 @@ describe('Grouping / ungrouping locked shapes', () => {
|
||||||
expect(editor.getShape(ids.boxB)).toBeTruthy()
|
expect(editor.getShape(ids.boxB)).toBeTruthy()
|
||||||
|
|
||||||
// Both be selected
|
// 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
|
// And be in the correct position
|
||||||
expect(editor.getShape(ids.boxA)!.x).toBe(100)
|
expect(editor.getShape(ids.boxA)!.x).toBe(100)
|
||||||
|
|
|
@ -363,7 +363,7 @@ it('pastes shapes with children', () => {
|
||||||
describe('When pasting into frames...', () => {
|
describe('When pasting into frames...', () => {
|
||||||
it('Does not paste into a clipped frame', () => {
|
it('Does not paste into a clipped frame', () => {
|
||||||
// clear the page
|
// clear the page
|
||||||
editor.selectAll().deleteShapes(editor.selectedShapeIds)
|
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
editor
|
editor
|
||||||
// move the two frames far from all other shapes
|
// 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
|
// Make sure that frame 1 is brought to front
|
||||||
.select(ids.frame1)
|
.select(ids.frame1)
|
||||||
.bringToFront(editor.selectedShapeIds)
|
.bringToFront(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
editor.setCamera({ x: -2000, y: -2000, z: 1 })
|
editor.setCamera({ x: -2000, y: -2000, z: 1 })
|
||||||
editor.updateRenderingBounds()
|
editor.updateRenderingBounds()
|
||||||
|
@ -436,7 +436,7 @@ describe('When pasting into frames...', () => {
|
||||||
|
|
||||||
it('keeps things in the right place', () => {
|
it('keeps things in the right place', () => {
|
||||||
// clear the page
|
// clear the page
|
||||||
editor.selectAll().deleteShapes(editor.selectedShapeIds)
|
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
|
||||||
// create a small box and copy it
|
// create a small box and copy it
|
||||||
editor.createShapes([
|
editor.createShapes([
|
||||||
{
|
{
|
||||||
|
@ -452,7 +452,7 @@ describe('When pasting into frames...', () => {
|
||||||
])
|
])
|
||||||
editor.selectAll().copy()
|
editor.selectAll().copy()
|
||||||
// now delete it
|
// now delete it
|
||||||
editor.deleteShapes(editor.selectedShapeIds)
|
editor.deleteShapes(editor.getSelectedShapeIds())
|
||||||
|
|
||||||
// create a big frame away from the origin, the size of the viewport
|
// create a big frame away from the origin, the size of the viewport
|
||||||
editor
|
editor
|
||||||
|
|
|
@ -3570,13 +3570,13 @@ describe('nodes that have do not resize', () => {
|
||||||
|
|
||||||
editor.select(ids.boxA, noteBId, noteCId)
|
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(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(noteBId)).toMatchObject({ x: 0, y: 0, w: 200, h: 200 })
|
||||||
expect(editor.getShapePageBounds(noteCId)).toMatchObject({ x: 300, y: 300, 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({
|
expect(editor.getShapePageBounds(ids.boxA)).toMatchObject({
|
||||||
x: 300,
|
x: 300,
|
||||||
|
|
|
@ -22,7 +22,7 @@ describe(SelectTool, () => {
|
||||||
editor.expectPathToBe('root.select.idle')
|
editor.expectPathToBe('root.select.idle')
|
||||||
editor.doubleClick(50, 50, shapeId)
|
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.
|
// note: this behavior has moved to the React hook useEditableText.
|
||||||
// clicking on the input will preserve selection, however you can
|
// clicking on the input will preserve selection, however you can
|
||||||
|
@ -36,7 +36,7 @@ describe(SelectTool, () => {
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
editor.pointerDown(150, 150).pointerUp()
|
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')
|
expect(editor.root.path.get()).toEqual('root.select.idle')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -48,18 +48,18 @@ describe(SelectTool, () => {
|
||||||
editor.setCurrentTool('select')
|
editor.setCurrentTool('select')
|
||||||
editor.doubleClick(50, 50, shapeId)
|
editor.doubleClick(50, 50, shapeId)
|
||||||
|
|
||||||
expect(editor.currentPageState.editingShapeId).toBe(shapeId)
|
expect(editor.getCurrentPageState().editingShapeId).toBe(shapeId)
|
||||||
|
|
||||||
// clicking outside the shape should end editing
|
// clicking outside the shape should end editing
|
||||||
jest.advanceTimersByTime(1000)
|
jest.advanceTimersByTime(1000)
|
||||||
|
|
||||||
editor.pointerDown(150, 150).pointerUp()
|
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')
|
expect(editor.root.path.get()).toEqual('root.select.idle')
|
||||||
|
|
||||||
editor.undo()
|
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)
|
editor.select(ids.A, ids.C)
|
||||||
// don't select it yet! It's behind the current selection
|
// don't select it yet! It's behind the current selection
|
||||||
editor.pointerDown(75, 75)
|
editor.pointerDown(75, 75)
|
||||||
expect(editor.selectedShapeIds).toMatchObject([ids.A, ids.C])
|
expect(editor.getSelectedShapeIds()).toMatchObject([ids.A, ids.C])
|
||||||
editor.pointerUp(75, 75)
|
editor.pointerUp(75, 75)
|
||||||
expect(editor.selectedShapeIds).toMatchObject([ids.B])
|
expect(editor.getSelectedShapeIds()).toMatchObject([ids.B])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Selects on shift+pointer up', () => {
|
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
|
// don't select B yet! It's behind the current selection
|
||||||
editor.pointerDown(75, 75, { target: 'canvas' }, { shiftKey: true })
|
editor.pointerDown(75, 75, { target: 'canvas' }, { shiftKey: true })
|
||||||
editor.expectToBeIn('select.pointing_selection')
|
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.pointerUp(75, 75, { target: 'canvas' }, { shiftKey: true })
|
||||||
editor.expectToBeIn('select.idle')
|
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
|
// and deselect
|
||||||
editor.pointerDown(75, 75, { target: 'canvas' }, { shiftKey: true })
|
editor.pointerDown(75, 75, { target: 'canvas' }, { shiftKey: true })
|
||||||
editor.expectToBeIn('select.pointing_shape')
|
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.pointerUp(75, 75, { target: 'canvas' }, { shiftKey: true })
|
||||||
editor.expectToBeIn('select.idle')
|
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', () => {
|
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(150, 150)
|
||||||
editor.pointerMove(151, 151)
|
editor.pointerMove(151, 151)
|
||||||
editor.pointerMove(100, 100)
|
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)
|
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', () => {
|
it('Brushes a straight arrow', () => {
|
||||||
const ids = editor
|
const ids = editor
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.deleteShapes(editor.selectedShapeIds)
|
.deleteShapes(editor.getSelectedShapeIds())
|
||||||
.setCamera({ x: 0, y: 0, z: 1 })
|
.setCamera({ x: 0, y: 0, z: 1 })
|
||||||
.createShapesFromJsx([
|
.createShapesFromJsx([
|
||||||
<TL.arrow
|
<TL.arrow
|
||||||
|
@ -145,13 +145,13 @@ describe('When brushing arrows', () => {
|
||||||
editor.pointerDown(0, 45)
|
editor.pointerDown(0, 45)
|
||||||
editor.pointerMove(100, 55)
|
editor.pointerMove(100, 55)
|
||||||
editor.expectPathToBe('root.select.brushing')
|
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', () => {
|
it('Brushes within the curve of a curved arrow without selecting the arrow', () => {
|
||||||
editor
|
editor
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.deleteShapes(editor.selectedShapeIds)
|
.deleteShapes(editor.getSelectedShapeIds())
|
||||||
.setCamera({ x: 0, y: 0, z: 1 })
|
.setCamera({ x: 0, y: 0, z: 1 })
|
||||||
.createShapesFromJsx([
|
.createShapesFromJsx([
|
||||||
<TL.arrow
|
<TL.arrow
|
||||||
|
@ -167,6 +167,6 @@ describe('When brushing arrows', () => {
|
||||||
editor.pointerDown(55, 45)
|
editor.pointerDown(55, 45)
|
||||||
editor.pointerMove(45, 55)
|
editor.pointerMove(45, 55)
|
||||||
editor.expectPathToBe('root.select.brushing')
|
editor.expectPathToBe('root.select.brushing')
|
||||||
expect(editor.selectedShapeIds).toStrictEqual([])
|
expect(editor.getSelectedShapeIds()).toStrictEqual([])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -66,7 +66,7 @@ describe('When interacting with a shape...', () => {
|
||||||
util.onRotateEnd = fnEnd
|
util.onRotateEnd = fnEnd
|
||||||
|
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
expect(editor.selectedShapeIds).toMatchObject([ids.frame1, ids.box1])
|
expect(editor.getSelectedShapeIds()).toMatchObject([ids.frame1, ids.box1])
|
||||||
|
|
||||||
editor
|
editor
|
||||||
.pointerDown(300, 300, {
|
.pointerDown(300, 300, {
|
||||||
|
@ -115,7 +115,7 @@ describe('When interacting with a shape...', () => {
|
||||||
util.onResizeEnd = fnEnd
|
util.onResizeEnd = fnEnd
|
||||||
|
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
expect(editor.selectedShapeIds).toMatchObject([ids.frame1, ids.box1])
|
expect(editor.getSelectedShapeIds()).toMatchObject([ids.frame1, ids.box1])
|
||||||
|
|
||||||
editor.pointerDown(300, 300, {
|
editor.pointerDown(300, 300, {
|
||||||
target: 'selection',
|
target: 'selection',
|
||||||
|
@ -152,7 +152,7 @@ describe('When interacting with a shape...', () => {
|
||||||
util.onTranslateEnd = fnEnd
|
util.onTranslateEnd = fnEnd
|
||||||
|
|
||||||
editor.selectAll()
|
editor.selectAll()
|
||||||
expect(editor.selectedShapeIds).toMatchObject([ids.frame1, ids.box1])
|
expect(editor.getSelectedShapeIds()).toMatchObject([ids.frame1, ids.box1])
|
||||||
|
|
||||||
// Translate the shapes...
|
// Translate the shapes...
|
||||||
editor.pointerDown(50, 50, ids.box1).pointerMove(50, 40).pointerUp(50, 40)
|
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,
|
// If a shape has an onClick handler, and if the handler returns nothing,
|
||||||
// then normal selection rules should apply.
|
// 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', () => {
|
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
|
// If a shape has an onClick handler, and it returns something, then
|
||||||
// it should not be selected.
|
// it should not be selected.
|
||||||
expect(editor.selectedShapeIds.length).toBe(0)
|
expect(editor.getSelectedShapeIds().length).toBe(0)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -209,8 +209,8 @@ describe('When cloning...', () => {
|
||||||
// Start cloning!
|
// Start cloning!
|
||||||
editor.keyDown('Alt')
|
editor.keyDown('Alt')
|
||||||
expect(editor.currentPageShapeIds.size).toBe(5) // Two new shapes!
|
expect(editor.currentPageShapeIds.size).toBe(5) // Two new shapes!
|
||||||
const newShapeA = editor.getShape(editor.selectedShapeIds[0])!
|
const newShapeA = editor.getShape(editor.getSelectedShapeIds()[0])!
|
||||||
const newShapeB = editor.getShape(editor.selectedShapeIds[1])!
|
const newShapeB = editor.getShape(editor.getSelectedShapeIds()[1])!
|
||||||
expect(newShapeA).toBeDefined()
|
expect(newShapeA).toBeDefined()
|
||||||
expect(newShapeB).toBeDefined()
|
expect(newShapeB).toBeDefined()
|
||||||
|
|
||||||
|
@ -246,7 +246,7 @@ describe('When cloning...', () => {
|
||||||
editor.keyDown('Alt', { altKey: true })
|
editor.keyDown('Alt', { altKey: true })
|
||||||
expect(editor.currentPageShapeIds.size).toBe(5) // Creates a clone of B and C (its descendant)
|
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])!
|
const newShapeB = editor.getShape(editor.getSortedChildIdsForParent(newShapeA.id)[0])!
|
||||||
|
|
||||||
expect(newShapeA).toBeDefined()
|
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 })
|
editor.pointerDown(50, 50, ids.box1).pointerMove(84, 110, { ctrlKey: true })
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue