Tidy up (#1600)
This PR is intended to do some housecleaning ahead of our developer release. It: - co-locates code in the `Editor` class, i.e. moving shape-related methods next to other shape-related methods - renames `cullingBounds` and other culling-related names to `renderingBounds` - renames `Editor.getParentPageId` to `Editor.getAncestorPageId` - renames `Editor.shapeIds` to `Editor.currentPageShapeIds` ### Change Type - [x] `major` — api changes
This commit is contained in:
parent
b88a2370b3
commit
271d0088e9
22 changed files with 2165 additions and 2108 deletions
|
@ -404,14 +404,9 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
createPage(title: string, id?: TLPageId, belowPageIndex?: string): this;
|
createPage(title: string, id?: TLPageId, belowPageIndex?: string): this;
|
||||||
createShapes<T extends TLUnknownShape>(partials: TLShapePartial<T>[], select?: boolean): this;
|
createShapes<T extends TLUnknownShape>(partials: TLShapePartial<T>[], select?: boolean): this;
|
||||||
get croppingId(): null | TLShapeId;
|
get croppingId(): null | TLShapeId;
|
||||||
get cullingBounds(): Box2d;
|
|
||||||
// @internal (undocumented)
|
|
||||||
readonly _cullingBounds: Atom<Box2d, unknown>;
|
|
||||||
get cullingBoundsExpanded(): Box2d;
|
|
||||||
// @internal (undocumented)
|
|
||||||
readonly _cullingBoundsExpanded: Atom<Box2d, unknown>;
|
|
||||||
get currentPage(): TLPage;
|
get currentPage(): TLPage;
|
||||||
get currentPageId(): TLPageId;
|
get currentPageId(): TLPageId;
|
||||||
|
get currentPageShapeIds(): Set<TLShapeId>;
|
||||||
get currentToolId(): string;
|
get currentToolId(): string;
|
||||||
get cursor(): TLCursor;
|
get cursor(): TLCursor;
|
||||||
deleteAssets(ids: TLAssetId[]): this;
|
deleteAssets(ids: TLAssetId[]): this;
|
||||||
|
@ -440,6 +435,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
focus(): this;
|
focus(): this;
|
||||||
get focusLayerId(): TLPageId | TLShapeId;
|
get focusLayerId(): TLPageId | TLShapeId;
|
||||||
get focusLayerShape(): TLShape | undefined;
|
get focusLayerShape(): TLShape | undefined;
|
||||||
|
getAncestorPageId(shape?: TLShape): TLPageId | undefined;
|
||||||
getAncestors(shape: TLShape, acc?: TLShape[]): TLShape[];
|
getAncestors(shape: TLShape, acc?: TLShape[]): TLShape[];
|
||||||
getAncestorsById(id: TLShapeId, acc?: TLShape[]): TLShape[];
|
getAncestorsById(id: TLShapeId, acc?: TLShape[]): TLShape[];
|
||||||
getArrowsBoundTo(shapeId: TLShapeId): {
|
getArrowsBoundTo(shapeId: TLShapeId): {
|
||||||
|
@ -477,7 +473,6 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
getPageTransform(shape: TLShape): Matrix2d | undefined;
|
getPageTransform(shape: TLShape): Matrix2d | undefined;
|
||||||
getPageTransformById(id: TLShapeId): Matrix2d | undefined;
|
getPageTransformById(id: TLShapeId): Matrix2d | undefined;
|
||||||
getParentIdForNewShapeAtPoint(point: VecLike, shapeType: TLShape['type']): TLPageId | TLShapeId;
|
getParentIdForNewShapeAtPoint(point: VecLike, shapeType: TLShape['type']): TLPageId | TLShapeId;
|
||||||
getParentPageId(shape?: TLShape): TLPageId | undefined;
|
|
||||||
getParentShape(shape?: TLShape): TLShape | undefined;
|
getParentShape(shape?: TLShape): TLShape | undefined;
|
||||||
getParentsMappedToChildren(ids: TLShapeId[]): Map<TLParentId, Set<TLShape>>;
|
getParentsMappedToChildren(ids: TLShapeId[]): Map<TLParentId, Set<TLShape>>;
|
||||||
getParentTransform(shape: TLShape): Matrix2d;
|
getParentTransform(shape: TLShape): Matrix2d;
|
||||||
|
@ -588,6 +583,12 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
putExternalContent(info: TLExternalContent): Promise<void>;
|
putExternalContent(info: TLExternalContent): Promise<void>;
|
||||||
redo(): this;
|
redo(): this;
|
||||||
renamePage(id: TLPageId, name: string, squashing?: boolean): this;
|
renamePage(id: TLPageId, name: string, squashing?: boolean): this;
|
||||||
|
get renderingBounds(): Box2d;
|
||||||
|
// @internal (undocumented)
|
||||||
|
readonly _renderingBounds: Atom<Box2d, unknown>;
|
||||||
|
get renderingBoundsExpanded(): Box2d;
|
||||||
|
// @internal (undocumented)
|
||||||
|
readonly _renderingBoundsExpanded: Atom<Box2d, unknown>;
|
||||||
get renderingShapes(): {
|
get renderingShapes(): {
|
||||||
id: TLShapeId;
|
id: TLShapeId;
|
||||||
index: number;
|
index: number;
|
||||||
|
@ -658,7 +659,6 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
setStyle<T>(style: StyleProp<T>, value: T, ephemeral?: boolean, squashing?: boolean): this;
|
setStyle<T>(style: StyleProp<T>, value: T, ephemeral?: boolean, squashing?: boolean): this;
|
||||||
setToolLocked(isToolLocked: boolean): this;
|
setToolLocked(isToolLocked: boolean): this;
|
||||||
setZoomBrush(zoomBrush?: Box2dModel | null): this;
|
setZoomBrush(zoomBrush?: Box2dModel | null): this;
|
||||||
get shapeIds(): Set<TLShapeId>;
|
|
||||||
get shapesArray(): TLShape[];
|
get shapesArray(): TLShape[];
|
||||||
shapeUtils: {
|
shapeUtils: {
|
||||||
readonly [K in string]?: ShapeUtil<TLUnknownShape>;
|
readonly [K in string]?: ShapeUtil<TLUnknownShape>;
|
||||||
|
@ -684,11 +684,11 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
undo(): HistoryManager<this>;
|
undo(): HistoryManager<this>;
|
||||||
ungroupShapes(ids?: TLShapeId[]): this;
|
ungroupShapes(ids?: TLShapeId[]): this;
|
||||||
updateAssets(assets: TLAssetPartial[]): this;
|
updateAssets(assets: TLAssetPartial[]): this;
|
||||||
// @internal
|
|
||||||
updateCullingBounds(): this;
|
|
||||||
updateDocumentSettings(settings: Partial<TLDocument>): void;
|
updateDocumentSettings(settings: Partial<TLDocument>): void;
|
||||||
updateInstanceState(partial: Partial<Omit<TLInstance, 'currentPageId'>>, ephemeral?: boolean, squashing?: boolean): this;
|
updateInstanceState(partial: Partial<Omit<TLInstance, 'currentPageId'>>, ephemeral?: boolean, squashing?: boolean): this;
|
||||||
updatePage(partial: RequiredKeys<TLPage, 'id'>, squashing?: boolean): this;
|
updatePage(partial: RequiredKeys<TLPage, 'id'>, squashing?: boolean): this;
|
||||||
|
// @internal
|
||||||
|
updateRenderingBounds(): this;
|
||||||
updateShapes<T extends TLUnknownShape>(partials: (null | TLShapePartial<T> | undefined)[], squashing?: boolean): this;
|
updateShapes<T extends TLUnknownShape>(partials: (null | TLShapePartial<T> | undefined)[], squashing?: boolean): this;
|
||||||
updateViewportScreenBounds(center?: boolean): this;
|
updateViewportScreenBounds(center?: boolean): this;
|
||||||
readonly user: UserPreferencesManager;
|
readonly user: UserPreferencesManager;
|
||||||
|
|
|
@ -107,3 +107,6 @@ export const COLLABORATOR_CHECK_INTERVAL = 1200
|
||||||
export const INTERNAL_POINTER_IDS = {
|
export const INTERNAL_POINTER_IDS = {
|
||||||
CAMERA_MOVE: -10,
|
CAMERA_MOVE: -10,
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
export const CAMERA_MOVING_TIMEOUT = 64
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -19,30 +19,30 @@ const ids = {
|
||||||
|
|
||||||
describe('shapeIdsInCurrentPage', () => {
|
describe('shapeIdsInCurrentPage', () => {
|
||||||
it('keeps the shape ids in the current page', () => {
|
it('keeps the shape ids in the current page', () => {
|
||||||
expect(new Set(editor.shapeIds)).toEqual(new Set([]))
|
expect(new Set(editor.currentPageShapeIds)).toEqual(new Set([]))
|
||||||
editor.createShapes([{ type: 'geo', id: ids.box1 }])
|
editor.createShapes([{ type: 'geo', id: ids.box1 }])
|
||||||
|
|
||||||
expect(new Set(editor.shapeIds)).toEqual(new Set([ids.box1]))
|
expect(new Set(editor.currentPageShapeIds)).toEqual(new Set([ids.box1]))
|
||||||
|
|
||||||
editor.createShapes([{ type: 'geo', id: ids.box2 }])
|
editor.createShapes([{ type: 'geo', id: ids.box2 }])
|
||||||
|
|
||||||
expect(new Set(editor.shapeIds)).toEqual(new Set([ids.box1, ids.box2]))
|
expect(new Set(editor.currentPageShapeIds)).toEqual(new Set([ids.box1, ids.box2]))
|
||||||
|
|
||||||
editor.createShapes([{ type: 'geo', id: ids.box3 }])
|
editor.createShapes([{ type: 'geo', id: ids.box3 }])
|
||||||
|
|
||||||
expect(new Set(editor.shapeIds)).toEqual(new Set([ids.box1, ids.box2, ids.box3]))
|
expect(new Set(editor.currentPageShapeIds)).toEqual(new Set([ids.box1, ids.box2, ids.box3]))
|
||||||
|
|
||||||
editor.deleteShapes([ids.box2])
|
editor.deleteShapes([ids.box2])
|
||||||
|
|
||||||
expect(new Set(editor.shapeIds)).toEqual(new Set([ids.box1, ids.box3]))
|
expect(new Set(editor.currentPageShapeIds)).toEqual(new Set([ids.box1, ids.box3]))
|
||||||
|
|
||||||
editor.deleteShapes([ids.box1])
|
editor.deleteShapes([ids.box1])
|
||||||
|
|
||||||
expect(new Set(editor.shapeIds)).toEqual(new Set([ids.box3]))
|
expect(new Set(editor.currentPageShapeIds)).toEqual(new Set([ids.box3]))
|
||||||
|
|
||||||
editor.deleteShapes([ids.box3])
|
editor.deleteShapes([ids.box3])
|
||||||
|
|
||||||
expect(new Set(editor.shapeIds)).toEqual(new Set([]))
|
expect(new Set(editor.currentPageShapeIds)).toEqual(new Set([]))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('changes when the current page changes', () => {
|
it('changes when the current page changes', () => {
|
||||||
|
@ -60,10 +60,10 @@ describe('shapeIdsInCurrentPage', () => {
|
||||||
{ type: 'geo', id: ids.box6 },
|
{ type: 'geo', id: ids.box6 },
|
||||||
])
|
])
|
||||||
|
|
||||||
expect(new Set(editor.shapeIds)).toEqual(new Set([ids.box4, ids.box5, ids.box6]))
|
expect(new Set(editor.currentPageShapeIds)).toEqual(new Set([ids.box4, ids.box5, ids.box6]))
|
||||||
|
|
||||||
editor.setCurrentPageId(editor.pages[0].id)
|
editor.setCurrentPageId(editor.pages[0].id)
|
||||||
|
|
||||||
expect(new Set(editor.shapeIds)).toEqual(new Set([ids.box1, ids.box2, ids.box3]))
|
expect(new Set(editor.currentPageShapeIds)).toEqual(new Set([ids.box1, ids.box2, ids.box3]))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -33,7 +33,7 @@ const isShapeInPage = (store: TLStore, pageId: TLPageId, shape: TLShape): boolea
|
||||||
* @param store - The tldraw store.
|
* @param store - The tldraw store.
|
||||||
* @param getCurrentPageId - A function that returns the current page id.
|
* @param getCurrentPageId - A function that returns the current page id.
|
||||||
*/
|
*/
|
||||||
export const shapeIdsInCurrentPage = (store: TLStore, getCurrentPageId: () => TLPageId) => {
|
export const deriveShapeIdsInCurrentPage = (store: TLStore, getCurrentPageId: () => TLPageId) => {
|
||||||
const shapesIndex = store.query.ids('shape')
|
const shapesIndex = store.query.ids('shape')
|
||||||
let lastPageId: null | TLPageId = null
|
let lastPageId: null | TLPageId = null
|
||||||
function fromScratch() {
|
function fromScratch() {
|
||||||
|
|
|
@ -15,7 +15,7 @@ export class CameraManager {
|
||||||
if (this.timeoutRemaining <= 0) {
|
if (this.timeoutRemaining <= 0) {
|
||||||
this.state.set('idle')
|
this.state.set('idle')
|
||||||
this.editor.off('tick', this.decay)
|
this.editor.off('tick', this.decay)
|
||||||
this.editor.updateCullingBounds()
|
this.editor.updateRenderingBounds()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -248,7 +248,7 @@ 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 { selectedIds, cullingBounds } = editor
|
const { selectedIds, renderingBounds: renderingBounds } = editor
|
||||||
|
|
||||||
const snappableShapes: GapNode[] = []
|
const snappableShapes: GapNode[] = []
|
||||||
|
|
||||||
|
@ -264,7 +264,7 @@ export class SnapManager {
|
||||||
if (!util.canSnap(childShape)) continue
|
if (!util.canSnap(childShape)) continue
|
||||||
// Only consider shapes if they're inside of the viewport page bounds
|
// Only consider shapes if they're inside of the viewport page bounds
|
||||||
const pageBounds = editor.getPageBoundsById(childId)
|
const pageBounds = editor.getPageBoundsById(childId)
|
||||||
if (!(pageBounds && cullingBounds.includes(pageBounds))) continue
|
if (!(pageBounds && renderingBounds.includes(pageBounds))) continue
|
||||||
// Snap to children of groups but not group itself
|
// Snap to children of groups but not group itself
|
||||||
if (editor.isShapeOfType(childShape, GroupShapeUtil)) {
|
if (editor.isShapeOfType(childShape, GroupShapeUtil)) {
|
||||||
collectSnappableShapesFromParent(childId)
|
collectSnappableShapesFromParent(childId)
|
||||||
|
|
|
@ -196,7 +196,7 @@ describe('Misc', () => {
|
||||||
editor.pointerMove(50, 50) // Move shape by 25, 25
|
editor.pointerMove(50, 50) // Move shape by 25, 25
|
||||||
editor.pointerUp().keyUp('Alt')
|
editor.pointerUp().keyUp('Alt')
|
||||||
|
|
||||||
expect(Array.from(editor.shapeIds.values()).length).toEqual(2)
|
expect(Array.from(editor.currentPageShapeIds.values()).length).toEqual(2)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('deletes', () => {
|
it('deletes', () => {
|
||||||
|
@ -208,7 +208,7 @@ describe('Misc', () => {
|
||||||
editor.pointerMove(50, 50) // Move shape by 25, 25
|
editor.pointerMove(50, 50) // Move shape by 25, 25
|
||||||
editor.pointerUp().keyUp('Alt')
|
editor.pointerUp().keyUp('Alt')
|
||||||
|
|
||||||
let ids = Array.from(editor.shapeIds.values())
|
let ids = Array.from(editor.currentPageShapeIds.values())
|
||||||
expect(ids.length).toEqual(2)
|
expect(ids.length).toEqual(2)
|
||||||
|
|
||||||
const duplicate = ids.filter((i) => i !== id)[0]
|
const duplicate = ids.filter((i) => i !== id)[0]
|
||||||
|
@ -216,7 +216,7 @@ describe('Misc', () => {
|
||||||
|
|
||||||
editor.deleteShapes()
|
editor.deleteShapes()
|
||||||
|
|
||||||
ids = Array.from(editor.shapeIds.values())
|
ids = Array.from(editor.currentPageShapeIds.values())
|
||||||
expect(ids.length).toEqual(1)
|
expect(ids.length).toEqual(1)
|
||||||
expect(ids[0]).toEqual(id)
|
expect(ids[0]).toEqual(id)
|
||||||
})
|
})
|
||||||
|
|
|
@ -46,7 +46,7 @@ describe('TLSelectTool.Translating', () => {
|
||||||
|
|
||||||
expect(editor.shapesArray.length).toBe(1)
|
expect(editor.shapesArray.length).toBe(1)
|
||||||
editor.expectShapeToMatch({ id: ids.box1, x: 150, y: 150 })
|
editor.expectShapeToMatch({ id: ids.box1, x: 150, y: 150 })
|
||||||
const t1 = [...editor.shapeIds.values()]
|
const t1 = [...editor.currentPageShapeIds.values()]
|
||||||
|
|
||||||
editor.keyDown('Alt')
|
editor.keyDown('Alt')
|
||||||
expect(editor.shapesArray.length).toBe(2)
|
expect(editor.shapesArray.length).toBe(2)
|
||||||
|
@ -66,7 +66,7 @@ describe('TLSelectTool.Translating', () => {
|
||||||
|
|
||||||
editor.expectShapeToMatch({ id: ids.box1, x: 150, y: 150 })
|
editor.expectShapeToMatch({ id: ids.box1, x: 150, y: 150 })
|
||||||
|
|
||||||
expect([...editor.shapeIds.values()]).toMatchObject(t1)
|
expect([...editor.currentPageShapeIds.values()]).toMatchObject(t1)
|
||||||
|
|
||||||
// todo: Should cloning again duplicate new shapes, or restore the last clone?
|
// todo: Should cloning again duplicate new shapes, or restore the last clone?
|
||||||
// editor.keyDown('Alt')
|
// editor.keyDown('Alt')
|
||||||
|
|
|
@ -13,7 +13,7 @@ export function useZoomCss() {
|
||||||
const setScaleDebounced = debounce(setScale, 100)
|
const setScaleDebounced = debounce(setScale, 100)
|
||||||
|
|
||||||
const scheduler = new EffectScheduler('useZoomCss', () => {
|
const scheduler = new EffectScheduler('useZoomCss', () => {
|
||||||
const numShapes = editor.shapeIds.size
|
const numShapes = editor.currentPageShapeIds.size
|
||||||
if (numShapes < 300) {
|
if (numShapes < 300) {
|
||||||
setScale(editor.zoomLevel)
|
setScale(editor.zoomLevel)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -125,7 +125,7 @@ export class TestEditor extends Editor {
|
||||||
this.bounds.bottom = bounds.y + bounds.h
|
this.bounds.bottom = bounds.y + bounds.h
|
||||||
|
|
||||||
this.updateViewportScreenBounds(center)
|
this.updateViewportScreenBounds(center)
|
||||||
this.updateCullingBounds()
|
this.updateRenderingBounds()
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,13 +117,13 @@ it('Creates shapes at the correct index', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Throws out all shapes if any shape is invalid', () => {
|
it('Throws out all shapes if any shape is invalid', () => {
|
||||||
const n = editor.shapeIds.size
|
const n = editor.currentPageShapeIds.size
|
||||||
|
|
||||||
expect(() => {
|
expect(() => {
|
||||||
editor.createShapes([{ id: ids.box1, type: 'geo' }])
|
editor.createShapes([{ id: ids.box1, type: 'geo' }])
|
||||||
}).not.toThrow()
|
}).not.toThrow()
|
||||||
|
|
||||||
expect(editor.shapeIds.size).toBe(n + 1)
|
expect(editor.currentPageShapeIds.size).toBe(n + 1)
|
||||||
|
|
||||||
console.error = jest.fn()
|
console.error = jest.fn()
|
||||||
|
|
||||||
|
@ -136,5 +136,5 @@ it('Throws out all shapes if any shape is invalid', () => {
|
||||||
])
|
])
|
||||||
}).toThrow()
|
}).toThrow()
|
||||||
|
|
||||||
expect(editor.shapeIds.size).toBe(n + 1)
|
expect(editor.currentPageShapeIds.size).toBe(n + 1)
|
||||||
})
|
})
|
||||||
|
|
|
@ -38,13 +38,13 @@ describe('Editor.moveShapesToPage', () => {
|
||||||
// box1 didn't get moved, still on page 1
|
// box1 didn't get moved, still on page 1
|
||||||
expect(editor.getShapeById(ids.box1)!.parentId).toBe(ids.page1)
|
expect(editor.getShapeById(ids.box1)!.parentId).toBe(ids.page1)
|
||||||
|
|
||||||
expect([...editor.shapeIds].sort()).toMatchObject([ids.box2, ids.ellipse1])
|
expect([...editor.currentPageShapeIds].sort()).toMatchObject([ids.box2, ids.ellipse1])
|
||||||
|
|
||||||
expect(editor.currentPageId).toBe(ids.page2)
|
expect(editor.currentPageId).toBe(ids.page2)
|
||||||
|
|
||||||
editor.setCurrentPageId(ids.page1)
|
editor.setCurrentPageId(ids.page1)
|
||||||
|
|
||||||
expect([...editor.shapeIds]).toEqual([ids.box1])
|
expect([...editor.currentPageShapeIds]).toEqual([ids.box1])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Moves children to page', () => {
|
it('Moves children to page', () => {
|
||||||
|
@ -80,23 +80,23 @@ describe('Editor.moveShapesToPage', () => {
|
||||||
|
|
||||||
it('Restores on undo / redo', () => {
|
it('Restores on undo / redo', () => {
|
||||||
expect(editor.currentPageId).toBe(ids.page1)
|
expect(editor.currentPageId).toBe(ids.page1)
|
||||||
expect([...editor.shapeIds].sort()).toMatchObject([ids.box1, ids.box2, ids.ellipse1])
|
expect([...editor.currentPageShapeIds].sort()).toMatchObject([ids.box1, ids.box2, ids.ellipse1])
|
||||||
|
|
||||||
editor.mark('move shapes to page')
|
editor.mark('move shapes to page')
|
||||||
editor.moveShapesToPage([ids.box2], ids.page2)
|
editor.moveShapesToPage([ids.box2], ids.page2)
|
||||||
|
|
||||||
expect(editor.currentPageId).toBe(ids.page2)
|
expect(editor.currentPageId).toBe(ids.page2)
|
||||||
expect([...editor.shapeIds].sort()).toMatchObject([ids.box2])
|
expect([...editor.currentPageShapeIds].sort()).toMatchObject([ids.box2])
|
||||||
|
|
||||||
editor.undo()
|
editor.undo()
|
||||||
|
|
||||||
expect(editor.currentPageId).toBe(ids.page1)
|
expect(editor.currentPageId).toBe(ids.page1)
|
||||||
expect([...editor.shapeIds].sort()).toMatchObject([ids.box1, ids.box2, ids.ellipse1])
|
expect([...editor.currentPageShapeIds].sort()).toMatchObject([ids.box1, ids.box2, ids.ellipse1])
|
||||||
|
|
||||||
editor.redo()
|
editor.redo()
|
||||||
|
|
||||||
expect(editor.currentPageId).toBe(ids.page2)
|
expect(editor.currentPageId).toBe(ids.page2)
|
||||||
expect([...editor.shapeIds].sort()).toMatchObject([ids.box2])
|
expect([...editor.currentPageShapeIds].sort()).toMatchObject([ids.box2])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Sets the correct indices', () => {
|
it('Sets the correct indices', () => {
|
||||||
|
|
|
@ -417,7 +417,7 @@ describe('When pasting into frames...', () => {
|
||||||
.bringToFront()
|
.bringToFront()
|
||||||
|
|
||||||
editor.setCamera(-2000, -2000, 1)
|
editor.setCamera(-2000, -2000, 1)
|
||||||
editor.updateCullingBounds()
|
editor.updateRenderingBounds()
|
||||||
|
|
||||||
// Copy box 1 (should be out of viewport)
|
// Copy box 1 (should be out of viewport)
|
||||||
editor.select(ids.box1).copy()
|
editor.select(ids.box1).copy()
|
||||||
|
|
|
@ -48,13 +48,15 @@ function createShapes() {
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
it('updates the culling viewport', () => {
|
it('updates the rendering viewport when the camera stops moving', () => {
|
||||||
const ids = createShapes()
|
const ids = createShapes()
|
||||||
editor.updateCullingBounds = jest.fn(editor.updateCullingBounds)
|
|
||||||
|
editor.updateRenderingBounds = jest.fn(editor.updateRenderingBounds)
|
||||||
editor.pan(-201, -201)
|
editor.pan(-201, -201)
|
||||||
jest.advanceTimersByTime(500)
|
jest.advanceTimersByTime(500)
|
||||||
expect(editor.updateCullingBounds).toHaveBeenCalledTimes(1)
|
|
||||||
expect(editor.cullingBounds).toMatchObject({ x: 201, y: 201, w: 1800, h: 900 })
|
expect(editor.updateRenderingBounds).toHaveBeenCalledTimes(1)
|
||||||
|
expect(editor.renderingBounds).toMatchObject({ x: 201, y: 201, w: 1800, h: 900 })
|
||||||
expect(editor.getPageBoundsById(ids.A)).toMatchObject({ x: 100, y: 100, w: 100, h: 100 })
|
expect(editor.getPageBoundsById(ids.A)).toMatchObject({ x: 100, y: 100, w: 100, h: 100 })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -63,7 +65,7 @@ it('lists shapes in viewport', () => {
|
||||||
expect(
|
expect(
|
||||||
editor.renderingShapes.map(({ id, isCulled, isInViewport }) => [id, isCulled, isInViewport])
|
editor.renderingShapes.map(({ id, isCulled, isInViewport }) => [id, isCulled, isInViewport])
|
||||||
).toStrictEqual([
|
).toStrictEqual([
|
||||||
[ids.A, false, true], // A is within the expanded culling bounds, so should not be culled; and it's in the regular viewport too, so it's on screen.
|
[ids.A, false, true], // A is within the expanded rendering bounds, so should not be culled; and it's in the regular viewport too, so it's on screen.
|
||||||
[ids.B, false, true],
|
[ids.B, false, true],
|
||||||
[ids.C, false, true],
|
[ids.C, false, true],
|
||||||
[ids.D, true, false], // D is clipped and so should always be culled / outside of viewport
|
[ids.D, true, false], // D is clipped and so should always be culled / outside of viewport
|
||||||
|
|
|
@ -211,15 +211,15 @@ describe('When cloning...', () => {
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
it('clones a single shape and restores when stopping cloning', () => {
|
it('clones a single shape and restores when stopping cloning', () => {
|
||||||
expect(editor.shapeIds.size).toBe(3)
|
expect(editor.currentPageShapeIds.size).toBe(3)
|
||||||
expect(editor.shapeIds.size).toBe(3)
|
expect(editor.currentPageShapeIds.size).toBe(3)
|
||||||
editor.select(ids.box1).pointerDown(50, 50, ids.box1).pointerMove(50, 40) // [0, -10]
|
editor.select(ids.box1).pointerDown(50, 50, ids.box1).pointerMove(50, 40) // [0, -10]
|
||||||
expect(editor.shapeIds.size).toBe(3)
|
expect(editor.currentPageShapeIds.size).toBe(3)
|
||||||
editor.expectShapeToMatch({ id: ids.box1, x: 10, y: 0 }) // Translated A...
|
editor.expectShapeToMatch({ id: ids.box1, x: 10, y: 0 }) // Translated A...
|
||||||
|
|
||||||
// Start cloning!
|
// Start cloning!
|
||||||
editor.keyDown('Alt')
|
editor.keyDown('Alt')
|
||||||
expect(editor.shapeIds.size).toBe(4)
|
expect(editor.currentPageShapeIds.size).toBe(4)
|
||||||
const newShape = editor.selectedShapes[0]
|
const newShape = editor.selectedShapes[0]
|
||||||
expect(newShape.id).not.toBe(ids.box1)
|
expect(newShape.id).not.toBe(ids.box1)
|
||||||
|
|
||||||
|
@ -240,13 +240,13 @@ describe('When cloning...', () => {
|
||||||
|
|
||||||
it('clones multiple single shape and restores when stopping cloning', () => {
|
it('clones multiple single shape and restores when stopping cloning', () => {
|
||||||
editor.select(ids.box1, ids.box2).pointerDown(50, 50, ids.box1).pointerMove(50, 40) // [0, -10]
|
editor.select(ids.box1, ids.box2).pointerDown(50, 50, ids.box1).pointerMove(50, 40) // [0, -10]
|
||||||
expect(editor.shapeIds.size).toBe(3)
|
expect(editor.currentPageShapeIds.size).toBe(3)
|
||||||
editor.expectShapeToMatch({ id: ids.box1, x: 10, y: 0 }) // Translated A...
|
editor.expectShapeToMatch({ id: ids.box1, x: 10, y: 0 }) // Translated A...
|
||||||
editor.expectShapeToMatch({ id: ids.box2, x: 200, y: 190 }) // Translated B...
|
editor.expectShapeToMatch({ id: ids.box2, x: 200, y: 190 }) // Translated B...
|
||||||
|
|
||||||
// Start cloning!
|
// Start cloning!
|
||||||
editor.keyDown('Alt')
|
editor.keyDown('Alt')
|
||||||
expect(editor.shapeIds.size).toBe(5) // Two new shapes!
|
expect(editor.currentPageShapeIds.size).toBe(5) // Two new shapes!
|
||||||
const newShapeA = editor.getShapeById(editor.selectedIds[0])!
|
const newShapeA = editor.getShapeById(editor.selectedIds[0])!
|
||||||
const newShapeB = editor.getShapeById(editor.selectedIds[1])!
|
const newShapeB = editor.getShapeById(editor.selectedIds[1])!
|
||||||
expect(newShapeA).toBeDefined()
|
expect(newShapeA).toBeDefined()
|
||||||
|
@ -280,9 +280,9 @@ describe('When cloning...', () => {
|
||||||
expect(editor.getShapeById(ids.line1)!.parentId).toBe(ids.box2)
|
expect(editor.getShapeById(ids.line1)!.parentId).toBe(ids.box2)
|
||||||
editor.select(ids.box2).pointerDown(250, 250, ids.box2).pointerMove(250, 240) // [0, -10]
|
editor.select(ids.box2).pointerDown(250, 250, ids.box2).pointerMove(250, 240) // [0, -10]
|
||||||
|
|
||||||
expect(editor.shapeIds.size).toBe(3)
|
expect(editor.currentPageShapeIds.size).toBe(3)
|
||||||
editor.keyDown('Alt', { altKey: true })
|
editor.keyDown('Alt', { altKey: true })
|
||||||
expect(editor.shapeIds.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.getShapeById(editor.selectedIds[0])!
|
const newShapeA = editor.getShapeById(editor.selectedIds[0])!
|
||||||
const newShapeB = editor.getShapeById(editor.getSortedChildIds(newShapeA.id)[0])!
|
const newShapeB = editor.getShapeById(editor.getSortedChildIds(newShapeA.id)[0])!
|
||||||
|
|
|
@ -55,7 +55,7 @@ export const Minimap = track(function Minimap({
|
||||||
|
|
||||||
const onDoubleClick = React.useCallback(
|
const onDoubleClick = React.useCallback(
|
||||||
(e: React.MouseEvent<HTMLCanvasElement>) => {
|
(e: React.MouseEvent<HTMLCanvasElement>) => {
|
||||||
if (!editor.shapeIds.size) return
|
if (!editor.currentPageShapeIds.size) return
|
||||||
|
|
||||||
const { x, y } = minimap.minimapScreenPointToPagePoint(e.clientX, e.clientY, false, false)
|
const { x, y } = minimap.minimapScreenPointToPagePoint(e.clientX, e.clientY, false, false)
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ export const Minimap = track(function Minimap({
|
||||||
const onPointerDown = React.useCallback(
|
const onPointerDown = React.useCallback(
|
||||||
(e: React.PointerEvent<HTMLCanvasElement>) => {
|
(e: React.PointerEvent<HTMLCanvasElement>) => {
|
||||||
e.currentTarget.setPointerCapture(e.pointerId)
|
e.currentTarget.setPointerCapture(e.pointerId)
|
||||||
if (!editor.shapeIds.size) return
|
if (!editor.currentPageShapeIds.size) return
|
||||||
|
|
||||||
rPointing.current = true
|
rPointing.current = true
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ export const Minimap = track(function Minimap({
|
||||||
|
|
||||||
const allShapeBounds = [] as (Box2d & { id: TLShapeId })[]
|
const allShapeBounds = [] as (Box2d & { id: TLShapeId })[]
|
||||||
|
|
||||||
editor.shapeIds.forEach((id) => {
|
editor.currentPageShapeIds.forEach((id) => {
|
||||||
let pageBounds = editor.getPageBoundsById(id)! as Box2d & { id: TLShapeId }
|
let pageBounds = editor.getPageBoundsById(id)! as Box2d & { id: TLShapeId }
|
||||||
|
|
||||||
const pageMask = editor.getPageMaskById(id)
|
const pageMask = editor.getPageMaskById(id)
|
||||||
|
|
|
@ -13,7 +13,7 @@ export const ZoomMenu = track(function ZoomMenu() {
|
||||||
const breakpoint = useBreakpoint()
|
const breakpoint = useBreakpoint()
|
||||||
|
|
||||||
const zoom = editor.zoomLevel
|
const zoom = editor.zoomLevel
|
||||||
const hasShapes = editor.shapeIds.size > 0
|
const hasShapes = editor.currentPageShapeIds.size > 0
|
||||||
const hasSelected = editor.selectedIds.length > 0
|
const hasSelected = editor.selectedIds.length > 0
|
||||||
const isZoomedTo100 = editor.zoomLevel === 1
|
const isZoomedTo100 = editor.zoomLevel === 1
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ export const TLUiContextMenuSchemaProvider = track(function TLUiContextMenuSchem
|
||||||
const threeStackableItems = useThreeStackableItems()
|
const threeStackableItems = useThreeStackableItems()
|
||||||
const atLeastOneShapeOnPage = useValue(
|
const atLeastOneShapeOnPage = useValue(
|
||||||
'atLeastOneShapeOnPage',
|
'atLeastOneShapeOnPage',
|
||||||
() => editor.shapeIds.size > 0,
|
() => editor.currentPageShapeIds.size > 0,
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
const isTransparentBg = useValue(
|
const isTransparentBg = useValue(
|
||||||
|
|
|
@ -26,7 +26,7 @@ export function useCopyAs() {
|
||||||
// little awkward.
|
// little awkward.
|
||||||
function copyAs(ids: TLShapeId[] = editor.selectedIds, format: TLCopyType = 'svg') {
|
function copyAs(ids: TLShapeId[] = editor.selectedIds, format: TLCopyType = 'svg') {
|
||||||
if (ids.length === 0) {
|
if (ids.length === 0) {
|
||||||
ids = [...editor.shapeIds]
|
ids = [...editor.currentPageShapeIds]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ids.length === 0) {
|
if (ids.length === 0) {
|
||||||
|
|
|
@ -20,7 +20,7 @@ export function useExportAs() {
|
||||||
return useCallback(
|
return useCallback(
|
||||||
async function exportAs(ids: TLShapeId[] = editor.selectedIds, format: TLExportType = 'png') {
|
async function exportAs(ids: TLShapeId[] = editor.selectedIds, format: TLExportType = 'png') {
|
||||||
if (ids.length === 0) {
|
if (ids.length === 0) {
|
||||||
ids = [...editor.shapeIds]
|
ids = [...editor.currentPageShapeIds]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ids.length === 0) {
|
if (ids.length === 0) {
|
||||||
|
|
|
@ -62,7 +62,7 @@ export function TLUiMenuSchemaProvider({ overrides, children }: TLUiMenuSchemaPr
|
||||||
[editor]
|
[editor]
|
||||||
)
|
)
|
||||||
|
|
||||||
const emptyPage = useValue('emptyPage', () => editor.shapeIds.size === 0, [editor])
|
const emptyPage = useValue('emptyPage', () => editor.currentPageShapeIds.size === 0, [editor])
|
||||||
|
|
||||||
const selectedCount = useValue('selectedCount', () => editor.selectedIds.length, [editor])
|
const selectedCount = useValue('selectedCount', () => editor.selectedIds.length, [editor])
|
||||||
const noneSelected = selectedCount === 0
|
const noneSelected = selectedCount === 0
|
||||||
|
|
Loading…
Reference in a new issue