kopia lustrzana https://github.com/Tldraw/Tldraw
Add result type.
rodzic
029116fefd
commit
44f0a3d6d0
|
@ -56,17 +56,18 @@ export default function AfterCreateUpdateShapeExample() {
|
|||
|
||||
// create some shapes to demonstrate the side-effects we added
|
||||
function createDemoShapes(editor: Editor) {
|
||||
editor
|
||||
.createShapes(
|
||||
'there can only be one red shape'.split(' ').map((word, i) => ({
|
||||
id: createShapeId(),
|
||||
type: 'text',
|
||||
y: i * 30,
|
||||
props: {
|
||||
color: i === 5 ? 'red' : 'black',
|
||||
text: word,
|
||||
},
|
||||
}))
|
||||
)
|
||||
.zoomToContent({ duration: 0 })
|
||||
const result = editor.createShapes(
|
||||
'there can only be one red shape'.split(' ').map((word, i) => ({
|
||||
id: createShapeId(),
|
||||
type: 'text',
|
||||
y: i * 30,
|
||||
props: {
|
||||
color: i === 5 ? 'red' : 'black',
|
||||
text: word,
|
||||
},
|
||||
}))
|
||||
)
|
||||
if (result.ok) {
|
||||
editor.zoomToContent({ duration: 0 })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,25 +24,26 @@ export default function BeforeDeleteShapeExample() {
|
|||
|
||||
// create some shapes to demonstrate the side-effect we added
|
||||
function createDemoShapes(editor: Editor) {
|
||||
editor
|
||||
.createShapes([
|
||||
{
|
||||
id: createShapeId(),
|
||||
type: 'text',
|
||||
props: {
|
||||
text: "Red shapes can't be deleted",
|
||||
color: 'red',
|
||||
},
|
||||
const result = editor.createShapes([
|
||||
{
|
||||
id: createShapeId(),
|
||||
type: 'text',
|
||||
props: {
|
||||
text: "Red shapes can't be deleted",
|
||||
color: 'red',
|
||||
},
|
||||
{
|
||||
id: createShapeId(),
|
||||
type: 'text',
|
||||
y: 30,
|
||||
props: {
|
||||
text: 'but other shapes can',
|
||||
color: 'black',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: createShapeId(),
|
||||
type: 'text',
|
||||
y: 30,
|
||||
props: {
|
||||
text: 'but other shapes can',
|
||||
color: 'black',
|
||||
},
|
||||
])
|
||||
.zoomToContent({ duration: 0 })
|
||||
},
|
||||
])
|
||||
if (result.ok) {
|
||||
editor.zoomToContent({ duration: 0 })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -634,7 +634,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
};
|
||||
createPage(page: Partial<TLPage>): this;
|
||||
createShape<T extends TLUnknownShape>(shape: OptionalKeys<TLShapePartial<T>, 'id'>): this;
|
||||
createShapes<T extends TLUnknownShape>(shapes: OptionalKeys<TLShapePartial<T>, 'id'>[]): this;
|
||||
createShapes<T extends TLUnknownShape>(shapes: OptionalKeys<TLShapePartial<T>, 'id'>[]): EditorResult<void>;
|
||||
deleteAssets(assets: TLAsset[] | TLAssetId[]): this;
|
||||
deleteOpenMenu(id: string): this;
|
||||
deletePage(page: TLPage | TLPageId): this;
|
||||
|
|
|
@ -129,7 +129,7 @@ import {
|
|||
} from './types/event-types'
|
||||
import { TLExternalAssetContent, TLExternalContent } from './types/external-content'
|
||||
import { TLHistoryBatchOptions } from './types/history-types'
|
||||
import { OptionalKeys, RequiredKeys, TLSvgOptions } from './types/misc-types'
|
||||
import { EditorResult, OptionalKeys, RequiredKeys, TLSvgOptions } from './types/misc-types'
|
||||
import { TLResizeHandle } from './types/selection-types'
|
||||
|
||||
/** @public */
|
||||
|
@ -6242,12 +6242,14 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
*
|
||||
* @public
|
||||
*/
|
||||
createShapes<T extends TLUnknownShape>(shapes: OptionalKeys<TLShapePartial<T>, 'id'>[]): this {
|
||||
createShapes<T extends TLUnknownShape>(
|
||||
shapes: OptionalKeys<TLShapePartial<T>, 'id'>[]
|
||||
): EditorResult<void> {
|
||||
if (!Array.isArray(shapes)) {
|
||||
throw Error('Editor.createShapes: must provide an array of shapes or shape partials')
|
||||
return EditorResult.error('not-an-array-of-shapes')
|
||||
}
|
||||
if (this.getInstanceState().isReadonly) return this
|
||||
if (shapes.length <= 0) return this
|
||||
if (this.getInstanceState().isReadonly) return EditorResult.error('readonly-room')
|
||||
if (shapes.length <= 0) return EditorResult.error('no-shapes-provied')
|
||||
|
||||
const currentPageShapeIds = this.getCurrentPageShapeIds()
|
||||
|
||||
|
@ -6256,12 +6258,12 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
if (maxShapesReached) {
|
||||
// can't create more shapes than fit on the page
|
||||
alertMaxShapes(this)
|
||||
return this
|
||||
return EditorResult.error('max-shapes-reached')
|
||||
}
|
||||
|
||||
const focusedGroupId = this.getFocusedGroupId()
|
||||
|
||||
return this.batch(() => {
|
||||
this.batch(() => {
|
||||
// 1. Parents
|
||||
|
||||
// Make sure that each partial will become the child of either the
|
||||
|
@ -6419,6 +6421,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
|
||||
this.store.put(shapeRecordsToCreate)
|
||||
})
|
||||
return EditorResult.ok()
|
||||
}
|
||||
|
||||
private animatingShapes = new Map<TLShapeId, string>()
|
||||
|
|
|
@ -28,20 +28,24 @@ export class Pointing extends StateNode {
|
|||
|
||||
this.editor.mark(this.markId)
|
||||
|
||||
this.editor
|
||||
.createShapes<TLBaseBoxShape>([
|
||||
{
|
||||
id,
|
||||
type: shapeType,
|
||||
x: originPagePoint.x,
|
||||
y: originPagePoint.y,
|
||||
props: {
|
||||
w: 1,
|
||||
h: 1,
|
||||
},
|
||||
const result = this.editor.createShapes<TLBaseBoxShape>([
|
||||
{
|
||||
id,
|
||||
type: shapeType,
|
||||
x: originPagePoint.x,
|
||||
y: originPagePoint.y,
|
||||
props: {
|
||||
w: 1,
|
||||
h: 1,
|
||||
},
|
||||
])
|
||||
.select(id)
|
||||
},
|
||||
])
|
||||
if (!result.ok) {
|
||||
this.cancel()
|
||||
return
|
||||
}
|
||||
|
||||
this.editor.select(id)
|
||||
this.editor.setCurrentTool('select.resizing', {
|
||||
...info,
|
||||
target: 'selection',
|
||||
|
@ -85,7 +89,7 @@ export class Pointing extends StateNode {
|
|||
|
||||
this.editor.mark(this.markId)
|
||||
|
||||
this.editor.createShapes<TLBaseBoxShape>([
|
||||
const result = this.editor.createShapes<TLBaseBoxShape>([
|
||||
{
|
||||
id,
|
||||
type: shapeType,
|
||||
|
@ -93,6 +97,10 @@ export class Pointing extends StateNode {
|
|||
y: originPagePoint.y,
|
||||
},
|
||||
])
|
||||
if (!result.ok) {
|
||||
this.cancel()
|
||||
return
|
||||
}
|
||||
|
||||
const shape = this.editor.getShape<TLBaseBoxShape>(id)!
|
||||
const { w, h } = this.editor.getShapeUtil(shape).getDefaultProps() as TLBaseBoxShape['props']
|
||||
|
|
|
@ -14,3 +14,43 @@ export type TLSvgOptions = {
|
|||
darkMode?: boolean
|
||||
preserveAspectRatio: React.SVGAttributes<SVGSVGElement>['preserveAspectRatio']
|
||||
}
|
||||
|
||||
export type TLEditorErrorType = keyof typeof TLEditorErrorTypeMap
|
||||
|
||||
export type TLEditorError = { message: string; type: TLEditorErrorType }
|
||||
|
||||
const TLEditorErrorTypeMap = {
|
||||
'not-an-array-of-shapes': {
|
||||
message: 'createShapes requires an array of shapes',
|
||||
type: 'not-an-array-of-shapes' as const,
|
||||
},
|
||||
'no-shapes-provied': {
|
||||
message: 'No shapes provided',
|
||||
type: 'no-shapes-provied' as const,
|
||||
},
|
||||
'readonly-room': {
|
||||
message: 'Room is readonly',
|
||||
type: 'readonly-room' as const,
|
||||
},
|
||||
'max-shapes-reached': {
|
||||
message: 'Max shapes reached',
|
||||
type: 'max-shapes-reached' as const,
|
||||
},
|
||||
}
|
||||
|
||||
export type ErrorResult = { ok: false; error: TLEditorError }
|
||||
export type OkResult = { ok: true }
|
||||
export type OkResultWithValue<T> = { ok: true; value: T }
|
||||
|
||||
export type EditorResult<T> = ErrorResult | OkResult | OkResultWithValue<T>
|
||||
export const EditorResult = {
|
||||
ok(): OkResult {
|
||||
return { ok: true }
|
||||
},
|
||||
okWithValue<T>(value: T): OkResultWithValue<T> {
|
||||
return { ok: true, value }
|
||||
},
|
||||
error(errorType: TLEditorErrorType): ErrorResult {
|
||||
return { ok: false, error: TLEditorErrorTypeMap[errorType] }
|
||||
},
|
||||
}
|
||||
|
|
|
@ -203,7 +203,10 @@ export function registerDefaultExternalContentHandlers(
|
|||
},
|
||||
}
|
||||
|
||||
editor.createShapes([shapePartial]).select(id)
|
||||
const result = editor.createShapes([shapePartial])
|
||||
if (result.ok) {
|
||||
editor.select(id)
|
||||
}
|
||||
})
|
||||
|
||||
// files
|
||||
|
@ -483,7 +486,10 @@ export async function createShapesForAssets(
|
|||
}
|
||||
|
||||
// Create the shapes
|
||||
editor.createShapes(partials).select(...partials.map((p) => p.id))
|
||||
const result = editor.createShapes(partials)
|
||||
if (!result.ok) return
|
||||
|
||||
editor.select(...partials.map((p) => p.id))
|
||||
|
||||
// Re-position shapes so that the center of the group is at the provided point
|
||||
centerSelectionAroundPoint(editor, position)
|
||||
|
@ -539,7 +545,9 @@ export function createEmptyBookmarkShape(
|
|||
}
|
||||
|
||||
editor.batch(() => {
|
||||
editor.createShapes([partial]).select(partial.id)
|
||||
const result = editor.createShapes([partial])
|
||||
if (!result.ok) return
|
||||
editor.select(partial.id)
|
||||
centerSelectionAroundPoint(editor, position)
|
||||
})
|
||||
|
||||
|
|
|
@ -294,8 +294,8 @@ describe('Other cases when arrow are moved', () => {
|
|||
{ id: ids.box3, type: 'geo', x: 0, y: 300, props: { w: 100, h: 100 } },
|
||||
{ id: ids.box4, type: 'geo', x: 0, y: 600, props: { w: 100, h: 100 } },
|
||||
])
|
||||
.selectAll()
|
||||
.groupShapes(editor.getSelectedShapeIds())
|
||||
|
||||
editor.selectAll().groupShapes(editor.getSelectedShapeIds())
|
||||
|
||||
editor.setCurrentTool('arrow').pointerDown(1000, 1000).pointerMove(50, 350).pointerUp(50, 350)
|
||||
let arrow = editor.getCurrentPageShapes()[editor.getCurrentPageShapes().length - 1]
|
||||
|
|
|
@ -26,29 +26,31 @@ export class Pointing extends StateNode {
|
|||
|
||||
this.editor.mark(this.markId)
|
||||
|
||||
this.editor
|
||||
.createShapes<TLGeoShape>([
|
||||
{
|
||||
id,
|
||||
type: 'geo',
|
||||
x: originPagePoint.x,
|
||||
y: originPagePoint.y,
|
||||
props: {
|
||||
w: 1,
|
||||
h: 1,
|
||||
geo: this.editor.getStyleForNextShape(GeoShapeGeoStyle),
|
||||
},
|
||||
const result = this.editor.createShapes<TLGeoShape>([
|
||||
{
|
||||
id,
|
||||
type: 'geo',
|
||||
x: originPagePoint.x,
|
||||
y: originPagePoint.y,
|
||||
props: {
|
||||
w: 1,
|
||||
h: 1,
|
||||
geo: this.editor.getStyleForNextShape(GeoShapeGeoStyle),
|
||||
},
|
||||
])
|
||||
.select(id)
|
||||
.setCurrentTool('select.resizing', {
|
||||
...info,
|
||||
target: 'selection',
|
||||
handle: 'bottom_right',
|
||||
isCreating: true,
|
||||
creationCursorOffset: { x: 1, y: 1 },
|
||||
onInteractionEnd: 'geo',
|
||||
})
|
||||
},
|
||||
])
|
||||
if (!result.ok) {
|
||||
this.cancel()
|
||||
return
|
||||
}
|
||||
this.editor.select(id).setCurrentTool('select.resizing', {
|
||||
...info,
|
||||
target: 'selection',
|
||||
handle: 'bottom_right',
|
||||
isCreating: true,
|
||||
creationCursorOffset: { x: 1, y: 1 },
|
||||
onInteractionEnd: 'geo',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -78,21 +78,24 @@ export class Pointing extends StateNode {
|
|||
this.editor.mark('creating text shape')
|
||||
const id = createShapeId()
|
||||
const { x, y } = this.editor.inputs.currentPagePoint
|
||||
this.editor
|
||||
.createShapes([
|
||||
{
|
||||
id,
|
||||
type: 'text',
|
||||
x,
|
||||
y,
|
||||
props: {
|
||||
text: '',
|
||||
autoSize: true,
|
||||
},
|
||||
const result = this.editor.createShapes([
|
||||
{
|
||||
id,
|
||||
type: 'text',
|
||||
x,
|
||||
y,
|
||||
props: {
|
||||
text: '',
|
||||
autoSize: true,
|
||||
},
|
||||
])
|
||||
.select(id)
|
||||
},
|
||||
])
|
||||
if (!result.ok) {
|
||||
this.cancel()
|
||||
return
|
||||
}
|
||||
|
||||
this.editor.select(id)
|
||||
this.editor.setEditingShape(id)
|
||||
this.editor.setCurrentTool('select')
|
||||
this.editor.root.getCurrent()?.transition('editing_shape')
|
||||
|
|
|
@ -295,6 +295,7 @@ function createNShapes(editor: Editor, n: number) {
|
|||
}
|
||||
|
||||
editor.batch(() => {
|
||||
editor.createShapes(shapesToCreate).setSelectedShapes(shapesToCreate.map((s) => s.id))
|
||||
editor.createShapes(shapesToCreate)
|
||||
editor.setSelectedShapes(shapesToCreate.map((s) => s.id))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -292,6 +292,7 @@ describe('When double clicking a shape', () => {
|
|||
.deleteShapes(editor.getSelectedShapeIds())
|
||||
.selectNone()
|
||||
.createShapes([{ id: createShapeId(), type: 'geo' }])
|
||||
editor
|
||||
.doubleClick(50, 50, { target: 'shape', shape: editor.getCurrentPageShapes()[0] })
|
||||
.expectToBeIn('select.editing_shape')
|
||||
})
|
||||
|
@ -305,9 +306,7 @@ describe('When pressing enter on a selected shape', () => {
|
|||
.deleteShapes(editor.getSelectedShapeIds())
|
||||
.selectNone()
|
||||
.createShapes([{ id, type: 'geo' }])
|
||||
.select(id)
|
||||
.keyUp('Enter')
|
||||
.expectToBeIn('select.editing_shape')
|
||||
editor.select(id).keyUp('Enter').expectToBeIn('select.editing_shape')
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -336,8 +335,7 @@ describe('When double clicking the selection edge', () => {
|
|||
.deleteShapes(editor.getSelectedShapeIds())
|
||||
.selectNone()
|
||||
.createShapes([{ id, type: 'text', x: 100, y: 100, props: { scale: 2, text: 'hello' } }])
|
||||
.select(id)
|
||||
.doubleClick(100, 100, { target: 'selection', handle: 'left' })
|
||||
editor.select(id).doubleClick(100, 100, { target: 'selection', handle: 'left' })
|
||||
|
||||
editor.expectShapeToMatch({ id, props: { scale: 1 } })
|
||||
})
|
||||
|
@ -355,8 +353,7 @@ describe('When double clicking the selection edge', () => {
|
|||
props: { scale: 2, autoSize: false, w: 200, text: 'hello' },
|
||||
},
|
||||
])
|
||||
.select(id)
|
||||
.doubleClick(100, 100, { target: 'selection', handle: 'left' })
|
||||
editor.select(id).doubleClick(100, 100, { target: 'selection', handle: 'left' })
|
||||
|
||||
editor.expectShapeToMatch({ id, props: { scale: 2, autoSize: true } })
|
||||
|
||||
|
@ -378,6 +375,7 @@ describe('When double clicking the selection edge', () => {
|
|||
props: { scale: 2, autoSize: false, w: 200, text: 'hello' },
|
||||
},
|
||||
])
|
||||
editor
|
||||
.select(id)
|
||||
.doubleClick(100, 100, { target: 'selection', handle: 'left' })
|
||||
.doubleClick(100, 100, { target: 'selection', handle: 'left' })
|
||||
|
@ -402,7 +400,7 @@ describe('When double clicking the selection edge', () => {
|
|||
type: 'geo',
|
||||
},
|
||||
])
|
||||
.select(id)
|
||||
editor.select(id)
|
||||
expect(editor.getEditingShapeId()).toBe(null)
|
||||
|
||||
editor.doubleClick(100, 100, { target: 'selection', handle: 'left' })
|
||||
|
|
|
@ -9,13 +9,15 @@ beforeEach(() => {
|
|||
|
||||
it('Sets shape meta by default to an empty object', () => {
|
||||
const id = createShapeId()
|
||||
editor.createShapes([{ id, type: 'geo' }]).select(id)
|
||||
editor.createShapes([{ id, type: 'geo' }])
|
||||
editor.select(id)
|
||||
expect(editor.getOnlySelectedShape()!.meta).toStrictEqual({})
|
||||
})
|
||||
|
||||
it('Sets shape meta', () => {
|
||||
editor.getInitialMetaForShape = (shape) => ({ firstThreeCharactersOfId: shape.id.slice(0, 3) })
|
||||
const id = createShapeId()
|
||||
editor.createShapes([{ id, type: 'geo' }]).select(id)
|
||||
editor.createShapes([{ id, type: 'geo' }])
|
||||
editor.select(id)
|
||||
expect(editor.getOnlySelectedShape()!.meta).toStrictEqual({ firstThreeCharactersOfId: 'sha' })
|
||||
})
|
||||
|
|
|
@ -182,7 +182,8 @@ describe('When duplicating shapes that include arrows', () => {
|
|||
})
|
||||
|
||||
it('Preserves the same selection bounds', () => {
|
||||
editor.selectAll().deleteShapes(editor.getSelectedShapeIds()).createShapes(shapes).selectAll()
|
||||
editor.selectAll().deleteShapes(editor.getSelectedShapeIds()).createShapes(shapes)
|
||||
editor.selectAll()
|
||||
|
||||
const boundsBefore = editor.getSelectionRotatedPageBounds()!
|
||||
editor.duplicateShapes(editor.getSelectedShapeIds())
|
||||
|
@ -190,16 +191,13 @@ describe('When duplicating shapes that include arrows', () => {
|
|||
})
|
||||
|
||||
it('Preserves the same selection bounds when only duplicating the arrows', () => {
|
||||
editor
|
||||
.selectAll()
|
||||
.deleteShapes(editor.getSelectedShapeIds())
|
||||
.createShapes(shapes)
|
||||
.select(
|
||||
...editor
|
||||
.getCurrentPageShapes()
|
||||
.filter((s) => editor.isShapeOfType<TLArrowShape>(s, 'arrow'))
|
||||
.map((s) => s.id)
|
||||
)
|
||||
editor.selectAll().deleteShapes(editor.getSelectedShapeIds()).createShapes(shapes)
|
||||
editor.select(
|
||||
...editor
|
||||
.getCurrentPageShapes()
|
||||
.filter((s) => editor.isShapeOfType<TLArrowShape>(s, 'arrow'))
|
||||
.map((s) => s.id)
|
||||
)
|
||||
|
||||
const boundsBefore = editor.getSelectionRotatedPageBounds()!
|
||||
editor.duplicateShapes(editor.getSelectedShapeIds())
|
||||
|
|
|
@ -177,6 +177,7 @@ describe('frame shapes', () => {
|
|||
editor
|
||||
// Create a frame
|
||||
.createShapes([{ id: frameId, type: 'frame', x: 100, y: 100, props: { w: 100, h: 100 } }])
|
||||
editor
|
||||
.select(frameId)
|
||||
// Rotate it by PI/2
|
||||
.rotateSelection(Math.PI / 2)
|
||||
|
|
|
@ -395,7 +395,7 @@ describe('When pasting into frames...', () => {
|
|||
y: 500,
|
||||
},
|
||||
])
|
||||
.setScreenBounds({ x: 0, y: 0, w: 1000, h: 1000 })
|
||||
editor.setScreenBounds({ x: 0, y: 0, w: 1000, h: 1000 })
|
||||
|
||||
// put frame2 inside frame1
|
||||
editor.reparentShapes([ids.frame2], ids.frame1)
|
||||
|
@ -455,20 +455,19 @@ describe('When pasting into frames...', () => {
|
|||
editor.deleteShapes(editor.getSelectedShapeIds())
|
||||
|
||||
// create a big frame away from the origin, the size of the viewport
|
||||
editor
|
||||
.createShapes([
|
||||
{
|
||||
id: ids.frame1,
|
||||
type: 'frame',
|
||||
x: editor.getViewportScreenBounds().w,
|
||||
y: editor.getViewportScreenBounds().h,
|
||||
props: {
|
||||
w: editor.getViewportScreenBounds().w,
|
||||
h: editor.getViewportScreenBounds().h,
|
||||
},
|
||||
editor.createShapes([
|
||||
{
|
||||
id: ids.frame1,
|
||||
type: 'frame',
|
||||
x: editor.getViewportScreenBounds().w,
|
||||
y: editor.getViewportScreenBounds().h,
|
||||
props: {
|
||||
w: editor.getViewportScreenBounds().w,
|
||||
h: editor.getViewportScreenBounds().h,
|
||||
},
|
||||
])
|
||||
.selectAll()
|
||||
},
|
||||
])
|
||||
editor.selectAll()
|
||||
// rotate the frame for hard mode
|
||||
editor.rotateSelection(45)
|
||||
// center on the center of the frame
|
||||
|
|
|
@ -912,7 +912,7 @@ describe('When resizing a shape with children', () => {
|
|||
},
|
||||
},
|
||||
])
|
||||
.select(ids.boxB, ids.lineA)
|
||||
editor.select(ids.boxB, ids.lineA)
|
||||
|
||||
editor
|
||||
.pointerDown(10, 10, {
|
||||
|
|
|
@ -1132,13 +1132,12 @@ describe('Selects inside of groups', () => {
|
|||
|
||||
describe('when selecting behind selection', () => {
|
||||
beforeEach(() => {
|
||||
editor
|
||||
.createShapes([
|
||||
{ id: ids.box1, type: 'geo', x: 100, y: 0, props: { fill: 'solid' } },
|
||||
{ id: ids.box2, type: 'geo', x: 0, y: 0 },
|
||||
{ id: ids.box3, type: 'geo', x: 200, y: 0 },
|
||||
])
|
||||
.select(ids.box2, ids.box3)
|
||||
editor.createShapes([
|
||||
{ id: ids.box1, type: 'geo', x: 100, y: 0, props: { fill: 'solid' } },
|
||||
{ id: ids.box2, type: 'geo', x: 0, y: 0 },
|
||||
{ id: ids.box3, type: 'geo', x: 200, y: 0 },
|
||||
])
|
||||
editor.select(ids.box2, ids.box3)
|
||||
})
|
||||
|
||||
it('does not select on pointer down, only on pointer up', () => {
|
||||
|
@ -1165,13 +1164,12 @@ describe('when selecting behind selection', () => {
|
|||
|
||||
describe('when shift+selecting', () => {
|
||||
beforeEach(() => {
|
||||
editor
|
||||
.createShapes([
|
||||
{ id: ids.box1, type: 'geo', x: 0, y: 0 },
|
||||
{ id: ids.box2, type: 'geo', x: 200, y: 0 },
|
||||
{ id: ids.box3, type: 'geo', x: 400, y: 0, props: { fill: 'solid' } },
|
||||
])
|
||||
.select(ids.box1)
|
||||
editor.createShapes([
|
||||
{ id: ids.box1, type: 'geo', x: 0, y: 0 },
|
||||
{ id: ids.box2, type: 'geo', x: 200, y: 0 },
|
||||
{ id: ids.box3, type: 'geo', x: 400, y: 0, props: { fill: 'solid' } },
|
||||
])
|
||||
editor.select(ids.box1)
|
||||
})
|
||||
|
||||
it('adds solid shape to selection on pointer down', () => {
|
||||
|
@ -1281,15 +1279,13 @@ describe('when shift+selecting', () => {
|
|||
|
||||
describe('when shift+selecting a group', () => {
|
||||
beforeEach(() => {
|
||||
editor
|
||||
.createShapes([
|
||||
{ id: ids.box1, type: 'geo', x: 0, y: 0 },
|
||||
{ id: ids.box2, type: 'geo', x: 200, y: 0 },
|
||||
{ id: ids.box3, type: 'geo', x: 400, y: 0, props: { fill: 'solid' } },
|
||||
{ id: ids.box4, type: 'geo', x: 600, y: 0 },
|
||||
])
|
||||
.groupShapes([ids.box2, ids.box3], ids.group1)
|
||||
.select(ids.box1)
|
||||
editor.createShapes([
|
||||
{ id: ids.box1, type: 'geo', x: 0, y: 0 },
|
||||
{ id: ids.box2, type: 'geo', x: 200, y: 0 },
|
||||
{ id: ids.box3, type: 'geo', x: 400, y: 0, props: { fill: 'solid' } },
|
||||
{ id: ids.box4, type: 'geo', x: 600, y: 0 },
|
||||
])
|
||||
editor.groupShapes([ids.box2, ids.box3], ids.group1).select(ids.box1)
|
||||
})
|
||||
|
||||
it('does not add group to selection when pointing empty space in the group', () => {
|
||||
|
@ -1362,14 +1358,14 @@ describe('when shift+selecting a group', () => {
|
|||
|
||||
describe('When children / descendants of a group are selected', () => {
|
||||
beforeEach(() => {
|
||||
editor.createShapes([
|
||||
{ id: ids.box1, type: 'geo', x: 0, y: 0 },
|
||||
{ id: ids.box2, type: 'geo', x: 200, y: 0 },
|
||||
{ id: ids.box3, type: 'geo', x: 400, y: 0, props: { fill: 'solid' } },
|
||||
{ id: ids.box4, type: 'geo', x: 600, y: 0 },
|
||||
{ id: ids.box5, type: 'geo', x: 800, y: 0 },
|
||||
])
|
||||
editor
|
||||
.createShapes([
|
||||
{ id: ids.box1, type: 'geo', x: 0, y: 0 },
|
||||
{ id: ids.box2, type: 'geo', x: 200, y: 0 },
|
||||
{ id: ids.box3, type: 'geo', x: 400, y: 0, props: { fill: 'solid' } },
|
||||
{ id: ids.box4, type: 'geo', x: 600, y: 0 },
|
||||
{ id: ids.box5, type: 'geo', x: 800, y: 0 },
|
||||
])
|
||||
.groupShapes([ids.box1, ids.box2], ids.group1)
|
||||
.groupShapes([ids.box3, ids.box4], ids.group2)
|
||||
.groupShapes([ids.group1, ids.group2], ids.group3)
|
||||
|
@ -1437,14 +1433,14 @@ describe('When children / descendants of a group are selected', () => {
|
|||
|
||||
describe('When pressing the enter key with groups selected', () => {
|
||||
beforeEach(() => {
|
||||
editor.createShapes([
|
||||
{ id: ids.box1, type: 'geo', x: 0, y: 0 },
|
||||
{ id: ids.box2, type: 'geo', x: 200, y: 0 },
|
||||
{ id: ids.box3, type: 'geo', x: 400, y: 0, props: { fill: 'solid' } },
|
||||
{ id: ids.box4, type: 'geo', x: 600, y: 0 },
|
||||
{ id: ids.box5, type: 'geo', x: 800, y: 0 },
|
||||
])
|
||||
editor
|
||||
.createShapes([
|
||||
{ id: ids.box1, type: 'geo', x: 0, y: 0 },
|
||||
{ id: ids.box2, type: 'geo', x: 200, y: 0 },
|
||||
{ id: ids.box3, type: 'geo', x: 400, y: 0, props: { fill: 'solid' } },
|
||||
{ id: ids.box4, type: 'geo', x: 600, y: 0 },
|
||||
{ id: ids.box5, type: 'geo', x: 800, y: 0 },
|
||||
])
|
||||
.groupShapes([ids.box1, ids.box2], ids.group1)
|
||||
.groupShapes([ids.box3, ids.box4], ids.group2)
|
||||
})
|
||||
|
@ -1545,14 +1541,13 @@ describe('When double clicking an editable shape', () => {
|
|||
describe('shift brushes to add to the selection', () => {
|
||||
beforeEach(() => {
|
||||
editor.user.updateUserPreferences({ isWrapMode: false })
|
||||
editor
|
||||
.createShapes([
|
||||
{ id: ids.box1, type: 'geo', x: 0, y: 0 },
|
||||
{ id: ids.box2, type: 'geo', x: 200, y: 0 },
|
||||
{ id: ids.box3, type: 'geo', x: 400, y: 0 },
|
||||
{ id: ids.box4, type: 'geo', x: 600, y: 200 },
|
||||
])
|
||||
.groupShapes([ids.box3, ids.box4], ids.group1)
|
||||
editor.createShapes([
|
||||
{ id: ids.box1, type: 'geo', x: 0, y: 0 },
|
||||
{ id: ids.box2, type: 'geo', x: 200, y: 0 },
|
||||
{ id: ids.box3, type: 'geo', x: 400, y: 0 },
|
||||
{ id: ids.box4, type: 'geo', x: 600, y: 200 },
|
||||
])
|
||||
editor.groupShapes([ids.box3, ids.box4], ids.group1)
|
||||
})
|
||||
|
||||
it('does not select when brushing into margin', () => {
|
||||
|
|
Ładowanie…
Reference in New Issue