Cleanup page state commands (#1800)
This PR cleans up some APIs around the editor's current page state: - `setEditingShapeId` -> `setEditingShape` - `setHoveredShapeId` -> `setHoveredShape` - `setCroppingShapeId` -> `setCroppingShape` - `setFocusedGroupId` -> `setFocusedGroup` - `setErasingShapeIds` -> `setErasingShapes` - `setHintingShapeIds` -> `setHintingShapes` It also adds some additional computed getters, e.g. `Editor.croppingShape`. It also adds some errors around `setCroppingShape`. ### Change Type - [x] `major` — Breaking change ### Test Plan - [x] Unit Tests
This commit is contained in:
parent
eabb0d52f8
commit
13ef8be58d
27 changed files with 252 additions and 125 deletions
|
@ -627,9 +627,11 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
duplicateShapes(shapes: TLShape[], offset?: VecLike): this;
|
||||
// (undocumented)
|
||||
duplicateShapes(ids: TLShapeId[], offset?: VecLike): this;
|
||||
get editingShape(): TLShape | undefined;
|
||||
get editingShapeId(): null | TLShapeId;
|
||||
readonly environment: EnvironmentManager;
|
||||
get erasingShapeIds(): TLShapeId[];
|
||||
get erasingShapes(): NonNullable<TLShape | undefined>[];
|
||||
// @internal (undocumented)
|
||||
externalAssetContentHandlers: {
|
||||
[K in TLExternalAssetContent_2['type']]: {
|
||||
|
@ -655,6 +657,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
flipShapes(shapes: TLShape[], operation: 'horizontal' | 'vertical'): this;
|
||||
// (undocumented)
|
||||
flipShapes(ids: TLShapeId[], operation: 'horizontal' | 'vertical'): this;
|
||||
get focusedGroup(): TLShape | undefined;
|
||||
get focusedGroupId(): TLPageId | TLShapeId;
|
||||
getAncestorPageId(shape?: TLShape): TLPageId | undefined;
|
||||
// (undocumented)
|
||||
|
@ -773,8 +776,9 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
// (undocumented)
|
||||
hasAncestor(shapeId: TLShapeId | undefined, ancestorId: TLShapeId): boolean;
|
||||
get hintingShapeIds(): TLShapeId[];
|
||||
get hintingShapes(): NonNullable<TLShape | undefined>[];
|
||||
readonly history: HistoryManager<this>;
|
||||
get hoveredShape(): TLUnknownShape | undefined;
|
||||
get hoveredShape(): TLShape | undefined;
|
||||
get hoveredShapeId(): null | TLShapeId;
|
||||
inputs: {
|
||||
originPagePoint: Vec2d;
|
||||
|
@ -843,7 +847,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
};
|
||||
pan(offset: VecLike, animation?: TLAnimationOptions): this;
|
||||
panZoomIntoView(ids: TLShapeId[], animation?: TLAnimationOptions): this;
|
||||
popFocusLayer(): this;
|
||||
popFocusedGroupId(): this;
|
||||
putContentOntoCurrentPage(content: TLContent, options?: {
|
||||
point?: VecLike;
|
||||
select?: boolean;
|
||||
|
@ -907,17 +911,29 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
// (undocumented)
|
||||
sendToBack(ids: TLShapeId[]): this;
|
||||
setCamera(point: VecLike, animation?: TLAnimationOptions): this;
|
||||
setCroppingShapeId(id: null | TLShapeId): this;
|
||||
setCroppingShape(shape: null | TLShape): this;
|
||||
// (undocumented)
|
||||
setCroppingShape(id: null | TLShapeId): this;
|
||||
setCurrentPage(page: TLPage, historyOptions?: TLCommandHistoryOptions): this;
|
||||
// (undocumented)
|
||||
setCurrentPage(pageId: TLPageId, historyOptions?: TLCommandHistoryOptions): this;
|
||||
setCurrentTool(id: string, info?: {}): this;
|
||||
setCursor: (cursor: Partial<TLCursor>) => this;
|
||||
setEditingShapeId(id: null | TLShapeId): this;
|
||||
setErasingShapeIds(ids: TLShapeId[]): this;
|
||||
setFocusedGroupId(next: null | TLShapeId): this;
|
||||
setHintingIds(ids: TLShapeId[]): this;
|
||||
setHoveredShapeId(id: null | TLShapeId): this;
|
||||
setEditingShape(shape: null | TLShape): this;
|
||||
// (undocumented)
|
||||
setEditingShape(id: null | TLShapeId): this;
|
||||
setErasingShapes(shapes: TLShape[]): this;
|
||||
// (undocumented)
|
||||
setErasingShapes(ids: TLShapeId[]): this;
|
||||
setFocusedGroup(shape: null | TLGroupShape): this;
|
||||
// (undocumented)
|
||||
setFocusedGroup(id: null | TLShapeId): this;
|
||||
setHintingShapes(shapes: TLShape[]): this;
|
||||
// (undocumented)
|
||||
setHintingShapes(ids: TLShapeId[]): this;
|
||||
setHoveredShape(shape: null | TLShape): this;
|
||||
// (undocumented)
|
||||
setHoveredShape(id: null | TLShapeId): this;
|
||||
setOpacity(opacity: number, historyOptions?: TLCommandHistoryOptions): this;
|
||||
setSelectedShapeIds(ids: TLShapeId[], historyOptions?: TLCommandHistoryOptions): this;
|
||||
setStyle<T>(style: StyleProp<T>, value: T, historyOptions?: TLCommandHistoryOptions): this;
|
||||
|
|
|
@ -1677,26 +1677,54 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
return boxFromRotatedVertices
|
||||
}
|
||||
|
||||
// Focus Layer Id
|
||||
// Focus Group
|
||||
|
||||
/**
|
||||
* The shape id of the current focus layer. Null when the focus layer id is the current page.
|
||||
* The current focused group id.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
get focusedGroupId(): TLShapeId | TLPageId {
|
||||
@computed get focusedGroupId(): TLShapeId | TLPageId {
|
||||
return this.currentPageState.focusedGroupId ?? this.currentPageId
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current focus layer id.
|
||||
*
|
||||
* @param next - The shape id (or page id) to set as the focus layer id.
|
||||
* The current focused group.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
setFocusedGroupId(next: TLShapeId | null): this {
|
||||
this._setFocusedGroupId(next)
|
||||
@computed get focusedGroup(): TLShape | undefined {
|
||||
const { focusedGroupId } = this
|
||||
return focusedGroupId ? this.getShape(focusedGroupId) : undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current focused group shape.
|
||||
*
|
||||
* @param shape - The group shape id (or group shape's id) to set as the focused group shape.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
setFocusedGroup(shape: TLGroupShape | null): this
|
||||
setFocusedGroup(id: TLShapeId | null): this
|
||||
setFocusedGroup(arg: TLShapeId | TLGroupShape | null): this {
|
||||
const id = typeof arg === 'string' ? arg : arg?.id ?? null
|
||||
|
||||
if (id !== null) {
|
||||
const shape = typeof arg === 'string' ? this.getShape(arg) : arg
|
||||
if (!shape) {
|
||||
throw Error(`Editor.setFocusedGroup: Shape with id ${id} does not exist`)
|
||||
}
|
||||
|
||||
if (!this.isShapeOfType<TLGroupShape>(shape, 'group')) {
|
||||
throw Error(
|
||||
`Editor.setFocusedGroup: Cannot set focused group to shape of type ${shape.type}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (id === this.focusedGroupId) return this
|
||||
this._setFocusedGroupId(id)
|
||||
return this
|
||||
}
|
||||
|
||||
|
@ -1704,11 +1732,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
private _setFocusedGroupId = this.history.createCommand(
|
||||
'setFocusedGroupId',
|
||||
(next: TLShapeId | null) => {
|
||||
// When we first click an empty canvas we don't want this to show up in the undo stack
|
||||
if (!next && !this.canUndo) {
|
||||
return
|
||||
}
|
||||
const prev = this.currentPageState.focusedGroupId
|
||||
if (prev === next) return
|
||||
return {
|
||||
data: {
|
||||
prev,
|
||||
|
@ -1732,25 +1757,24 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
)
|
||||
|
||||
/**
|
||||
* Exit the current focus layer, moving up to the next group if there is one.
|
||||
* Exit the current focused group, moving up to the next parent group if there is one.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
popFocusLayer(): this {
|
||||
const current = this.currentPageState.focusedGroupId
|
||||
const focusedShape = current && this.getShape(current)
|
||||
popFocusedGroupId(): this {
|
||||
const { focusedGroup } = this
|
||||
|
||||
if (focusedShape) {
|
||||
if (focusedGroup) {
|
||||
// If we have a focused layer, look for an ancestor of the focused shape that is a group
|
||||
const match = this.findShapeAncestor(focusedShape, (shape) =>
|
||||
const match = this.findShapeAncestor(focusedGroup, (shape) =>
|
||||
this.isShapeOfType<TLGroupShape>(shape, 'group')
|
||||
)
|
||||
// If we have an ancestor that can become a focused layer, set it as the focused layer
|
||||
this.setFocusedGroupId(match?.id ?? null)
|
||||
this.select(focusedShape.id)
|
||||
this.setFocusedGroup(match?.id ?? null)
|
||||
this.select(focusedGroup.id)
|
||||
} else {
|
||||
// If there's no focused shape, then clear the focus layer and clear selection
|
||||
this.setFocusedGroupId(null)
|
||||
// If there's no parent focused group, then clear the focus layer and clear selection
|
||||
this.setFocusedGroup(null)
|
||||
this.selectNone()
|
||||
}
|
||||
|
||||
|
@ -1762,18 +1786,37 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
*
|
||||
* @public
|
||||
*/
|
||||
get editingShapeId() {
|
||||
@computed get editingShapeId() {
|
||||
return this.currentPageState.editingShapeId
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current editing shape id.
|
||||
*
|
||||
* @param id - The shape id to set as editing.
|
||||
* The current editing shape.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
setEditingShapeId(id: TLShapeId | null): this {
|
||||
@computed get editingShape(): TLShape | undefined {
|
||||
const { editingShapeId } = this
|
||||
return editingShapeId ? this.getShape(editingShapeId) : undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current editing shape.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* editor.setEditingShape(myShape)
|
||||
* editor.setEditingShape(myShape.id)
|
||||
* ```
|
||||
*
|
||||
* @param shapes - The shape (or shape id) to set as editing.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
setEditingShape(shape: TLShape | null): this
|
||||
setEditingShape(id: TLShapeId | null): this
|
||||
setEditingShape(arg: TLShapeId | TLShape | null): this {
|
||||
const id = typeof arg === 'string' ? arg : arg?.id ?? null
|
||||
if (!id) {
|
||||
this._setInstancePageState({ editingShapeId: null })
|
||||
} else {
|
||||
|
@ -1788,7 +1831,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
return this
|
||||
}
|
||||
|
||||
// Hovered Id
|
||||
// Hovered
|
||||
|
||||
/**
|
||||
* The current hovered shape id.
|
||||
|
@ -1801,28 +1844,38 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the editor's current hovered shape id.
|
||||
*
|
||||
* @param id - The shape id to set as hovered.
|
||||
* The current hovered shape.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
setHoveredShapeId(id: TLShapeId | null): this {
|
||||
if (id === this.currentPageState.hoveredShapeId) return this
|
||||
@computed get hoveredShape(): TLShape | undefined {
|
||||
const { hoveredShapeId } = this
|
||||
return hoveredShapeId ? this.getShape(hoveredShapeId) : undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the editor's current hovered shape.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* editor.setHoveredShape(myShape)
|
||||
* editor.setHoveredShape(myShape.id)
|
||||
* ```
|
||||
*
|
||||
* @param shapes - The shape (or shape id) to set as hovered.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
setHoveredShape(shape: TLShape | null): this
|
||||
setHoveredShape(id: TLShapeId | null): this
|
||||
setHoveredShape(arg: TLShapeId | TLShape | null): this {
|
||||
const id = typeof arg === 'string' ? arg : arg?.id ?? null
|
||||
if (id === this.hoveredShapeId) return this
|
||||
this.updateCurrentPageState({ hoveredShapeId: id }, { ephemeral: true })
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* The editor's current hovered shape.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
@computed get hoveredShape() {
|
||||
return this.hoveredShapeId ? this.getShape(this.hoveredShapeId) : undefined
|
||||
}
|
||||
|
||||
// Hinting ids
|
||||
// Hinting
|
||||
|
||||
/**
|
||||
* The editor's current hinting shape ids.
|
||||
|
@ -1834,18 +1887,42 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the editor's current hinting shape ids.
|
||||
*
|
||||
* @param ids - The shape ids to set as hinting.
|
||||
* The editor's current hinting shapes.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
setHintingIds(ids: TLShapeId[]): this {
|
||||
@computed get hintingShapes() {
|
||||
const { hintingShapeIds } = this
|
||||
return compact(hintingShapeIds.map((id) => this.getShape(id)))
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the editor's current hinting shapes.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* editor.setHintingShapes([myShape])
|
||||
* editor.setHintingShapes([myShape.id])
|
||||
* ```
|
||||
*
|
||||
* @param shapes - The shapes (or shape ids) to set as hinting.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
setHintingShapes(shapes: TLShape[]): this
|
||||
setHintingShapes(ids: TLShapeId[]): this
|
||||
setHintingShapes(arg: TLShapeId[] | TLShape[]): this {
|
||||
const ids =
|
||||
typeof arg[0] === 'string'
|
||||
? (arg as TLShapeId[])
|
||||
: (arg as TLShape[]).map((shape) => shape.id)
|
||||
// always ephemeral
|
||||
this.updateCurrentPageState({ hintingShapeIds: dedupe(ids) }, { ephemeral: true })
|
||||
return this
|
||||
}
|
||||
|
||||
// Erasing
|
||||
|
||||
/**
|
||||
* The editor's current erasing ids.
|
||||
*
|
||||
|
@ -1856,13 +1933,35 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the editor's current erasing shape ids.
|
||||
*
|
||||
* @param ids - The shape ids to set as erasing.
|
||||
* The editor's current hinting shapes.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
setErasingShapeIds(ids: TLShapeId[]): this {
|
||||
@computed get erasingShapes() {
|
||||
const { erasingShapeIds } = this
|
||||
return compact(erasingShapeIds.map((id) => this.getShape(id)))
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the editor's current erasing shapes.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* editor.setErasingShapes([myShape])
|
||||
* editor.setErasingShapes([myShape.id])
|
||||
* ```
|
||||
*
|
||||
* @param shapes - The shapes (or shape ids) to set as hinting.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
setErasingShapes(shapes: TLShape[]): this
|
||||
setErasingShapes(ids: TLShapeId[]): this
|
||||
setErasingShapes(arg: TLShapeId[] | TLShape[]): this {
|
||||
const ids =
|
||||
typeof arg[0] === 'string'
|
||||
? (arg as TLShapeId[])
|
||||
: (arg as TLShape[]).map((shape) => shape.id)
|
||||
ids.sort() // sort the incoming ids
|
||||
const { erasingShapeIds } = this
|
||||
if (ids.length === erasingShapeIds.length) {
|
||||
|
@ -1883,6 +1982,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
return this
|
||||
}
|
||||
|
||||
// Cropping
|
||||
|
||||
/**
|
||||
* The current cropping shape's id.
|
||||
*
|
||||
|
@ -1893,13 +1994,23 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the current cropping shape id.
|
||||
* Set the current cropping shape.
|
||||
*
|
||||
* @param id - The shape id to set as cropping.
|
||||
* @example
|
||||
* ```ts
|
||||
* editor.setCroppingShape(myShape)
|
||||
* editor.setCroppingShape(myShape.id)
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* @param shape - The shape (or shape id) to set as cropping.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
setCroppingShapeId(id: TLShapeId | null): this {
|
||||
setCroppingShape(shape: TLShape | null): this
|
||||
setCroppingShape(id: TLShapeId | null): this
|
||||
setCroppingShape(arg: TLShapeId | TLShape | null): this {
|
||||
const id = typeof arg === 'string' ? arg : arg?.id ?? null
|
||||
if (id !== this.croppingShapeId) {
|
||||
if (!id) {
|
||||
this.updateCurrentPageState({ croppingShapeId: null })
|
||||
|
@ -5252,7 +5363,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|||
// Put the shape content onto the new page; parents and indices will
|
||||
// be taken care of by the putContent method; make sure to pop any focus
|
||||
// layers so that the content will be put onto the page.
|
||||
this.setFocusedGroupId(null)
|
||||
this.setFocusedGroup(null)
|
||||
this.selectNone()
|
||||
this.putContentOntoCurrentPage(content, {
|
||||
select: true,
|
||||
|
|
|
@ -101,13 +101,13 @@ export class GroupShapeUtil extends ShapeUtil<TLGroupShape> {
|
|||
const children = this.editor.getSortedChildIdsForParent(group.id)
|
||||
if (children.length === 0) {
|
||||
if (this.editor.currentPageState.focusedGroupId === group.id) {
|
||||
this.editor.popFocusLayer()
|
||||
this.editor.popFocusedGroupId()
|
||||
}
|
||||
this.editor.deleteShapes([group.id])
|
||||
return
|
||||
} else if (children.length === 1) {
|
||||
if (this.editor.currentPageState.focusedGroupId === group.id) {
|
||||
this.editor.popFocusLayer()
|
||||
this.editor.popFocusedGroupId()
|
||||
}
|
||||
this.editor.reparentShapes(children, group.parentId)
|
||||
this.editor.deleteShapes([group.id])
|
||||
|
|
|
@ -19,7 +19,7 @@ export class Pointing extends StateNode {
|
|||
if (!target) {
|
||||
this.createArrowShape()
|
||||
} else {
|
||||
this.editor.setHintingIds([target.id])
|
||||
this.editor.setHintingShapes([target.id])
|
||||
}
|
||||
|
||||
this.startPreciseTimeout()
|
||||
|
@ -27,7 +27,7 @@ export class Pointing extends StateNode {
|
|||
|
||||
override onExit = () => {
|
||||
this.shape = undefined
|
||||
this.editor.setHintingIds([])
|
||||
this.editor.setHintingShapes([])
|
||||
this.clearPreciseTimeout()
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ export class Pointing extends StateNode {
|
|||
// the arrow might not have been created yet!
|
||||
this.editor.bailToMark(this.markId)
|
||||
}
|
||||
this.editor.setHintingIds([])
|
||||
this.editor.setHintingShapes([])
|
||||
this.parent.transition('idle', {})
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ export class Pointing extends StateNode {
|
|||
if (change) {
|
||||
const startTerminal = change.props?.start
|
||||
if (startTerminal?.type === 'binding') {
|
||||
this.editor.setHintingIds([startTerminal.boundShapeId])
|
||||
this.editor.setHintingShapes([startTerminal.boundShapeId])
|
||||
}
|
||||
this.editor.updateShapes([change], { squashing: true })
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ export class Pointing extends StateNode {
|
|||
if (change) {
|
||||
const endTerminal = change.props?.end
|
||||
if (endTerminal?.type === 'binding') {
|
||||
this.editor.setHintingIds([endTerminal.boundShapeId])
|
||||
this.editor.setHintingShapes([endTerminal.boundShapeId])
|
||||
}
|
||||
this.editor.updateShapes([change], { squashing: true })
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ export const FrameLabelInput = forwardRef<
|
|||
// and sending us back into edit mode
|
||||
e.stopPropagation()
|
||||
e.currentTarget.blur()
|
||||
editor.setEditingShapeId(null)
|
||||
editor.setEditingShape(null)
|
||||
}
|
||||
},
|
||||
[editor]
|
||||
|
|
|
@ -17,7 +17,7 @@ export class Idle extends StateNode {
|
|||
if (shape && this.editor.isShapeOfType<TLGeoShape>(shape, 'geo')) {
|
||||
// todo: ensure that this only works with the most recently created shape, not just any geo shape that happens to be selected at the time
|
||||
this.editor.mark('editing shape')
|
||||
this.editor.setEditingShapeId(shape.id)
|
||||
this.editor.setEditingShape(shape.id)
|
||||
this.editor.setCurrentTool('select.editing_shape', {
|
||||
...info,
|
||||
target: 'shape',
|
||||
|
|
|
@ -65,7 +65,7 @@ export class Pointing extends StateNode {
|
|||
if (this.editor.instanceState.isToolLocked) {
|
||||
this.parent.transition('idle', {})
|
||||
} else {
|
||||
this.editor.setEditingShapeId(this.shape.id)
|
||||
this.editor.setEditingShape(this.shape.id)
|
||||
this.editor.setCurrentTool('select.editing_shape', {
|
||||
...this.info,
|
||||
target: 'shape',
|
||||
|
|
|
@ -211,8 +211,8 @@ export function useEditableText<T extends Extract<TLShape, { props: { text: stri
|
|||
(e: React.PointerEvent) => {
|
||||
if (isEditableFromHover) {
|
||||
transact(() => {
|
||||
editor.setEditingShapeId(id)
|
||||
editor.setHoveredShapeId(id)
|
||||
editor.setEditingShape(id)
|
||||
editor.setHoveredShape(id)
|
||||
editor.setSelectedShapeIds([id])
|
||||
})
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ export class Idle extends StateNode {
|
|||
if (this.editor.isShapeOfType<TLTextShape>(hitShape, 'text')) {
|
||||
requestAnimationFrame(() => {
|
||||
this.editor.setSelectedShapeIds([hitShape.id])
|
||||
this.editor.setEditingShapeId(hitShape.id)
|
||||
this.editor.setEditingShape(hitShape.id)
|
||||
this.editor.setCurrentTool('select.editing_shape', {
|
||||
...info,
|
||||
target: 'shape',
|
||||
|
@ -46,7 +46,7 @@ export class Idle extends StateNode {
|
|||
const shape = this.editor.selectedShapes[0]
|
||||
if (shape && this.editor.isShapeOfType<TLGeoShape>(shape, 'geo')) {
|
||||
this.editor.setCurrentTool('select')
|
||||
this.editor.setEditingShapeId(shape.id)
|
||||
this.editor.setEditingShape(shape.id)
|
||||
this.editor.root.current.value!.transition('editing_shape', {
|
||||
...info,
|
||||
target: 'shape',
|
||||
|
|
|
@ -8,7 +8,7 @@ export class Pointing extends StateNode {
|
|||
markId = ''
|
||||
|
||||
override onExit = () => {
|
||||
this.editor.setHintingIds([])
|
||||
this.editor.setHintingShapes([])
|
||||
}
|
||||
|
||||
override onPointerMove: TLEventHandlers['onPointerMove'] = (info) => {
|
||||
|
@ -88,7 +88,7 @@ export class Pointing extends StateNode {
|
|||
])
|
||||
.select(id)
|
||||
|
||||
this.editor.setEditingShapeId(id)
|
||||
this.editor.setEditingShape(id)
|
||||
this.editor.setCurrentTool('select')
|
||||
this.editor.root.current.value?.transition('editing_shape', {})
|
||||
}
|
||||
|
|
|
@ -129,17 +129,17 @@ export class Erasing extends StateNode {
|
|||
// Remove the hit shapes, except if they're in the list of excluded shapes
|
||||
// (these excluded shapes will be any frames or groups the pointer was inside of
|
||||
// when the user started erasing)
|
||||
this.editor.setErasingShapeIds([...erasing].filter((id) => !excludedShapeIds.has(id)))
|
||||
this.editor.setErasingShapes([...erasing].filter((id) => !excludedShapeIds.has(id)))
|
||||
}
|
||||
|
||||
complete() {
|
||||
this.editor.deleteShapes(this.editor.currentPageState.erasingShapeIds)
|
||||
this.editor.setErasingShapeIds([])
|
||||
this.editor.setErasingShapes([])
|
||||
this.parent.transition('idle', {})
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.editor.setErasingShapeIds([])
|
||||
this.editor.setErasingShapes([])
|
||||
this.editor.bailToMark(this.markId)
|
||||
this.parent.transition('idle', this.info)
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ export class Pointing extends StateNode {
|
|||
}
|
||||
}
|
||||
|
||||
this.editor.setErasingShapeIds([...erasing])
|
||||
this.editor.setErasingShapes([...erasing])
|
||||
}
|
||||
|
||||
override onPointerMove: TLEventHandlers['onPointerMove'] = (info) => {
|
||||
|
@ -79,12 +79,12 @@ export class Pointing extends StateNode {
|
|||
this.editor.deleteShapes(erasingShapeIds)
|
||||
}
|
||||
|
||||
this.editor.setErasingShapeIds([])
|
||||
this.editor.setErasingShapes([])
|
||||
this.parent.transition('idle', {})
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.editor.setErasingShapeIds([])
|
||||
this.editor.setErasingShapes([])
|
||||
this.parent.transition('idle', {})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,11 +72,11 @@ export class DragAndDropManager {
|
|||
.onDragShapesOver?.(nextDroppingShape, movingShapes)
|
||||
|
||||
if (res && res.shouldHint) {
|
||||
this.editor.setHintingIds([nextDroppingShape.id])
|
||||
this.editor.setHintingShapes([nextDroppingShape.id])
|
||||
}
|
||||
} else {
|
||||
// If we're dropping onto the page, then clear hinting ids
|
||||
this.editor.setHintingIds([])
|
||||
this.editor.setHintingShapes([])
|
||||
}
|
||||
|
||||
cb?.()
|
||||
|
@ -103,7 +103,7 @@ export class DragAndDropManager {
|
|||
}
|
||||
|
||||
this.droppingNodeTimer = null
|
||||
this.editor.setHintingIds([])
|
||||
this.editor.setHintingShapes([])
|
||||
}
|
||||
|
||||
dispose = () => {
|
||||
|
|
|
@ -43,7 +43,7 @@ export class SelectTool extends StateNode {
|
|||
|
||||
override onExit = () => {
|
||||
if (this.editor.currentPageState.editingShapeId) {
|
||||
this.editor.setEditingShapeId(null)
|
||||
this.editor.setEditingShape(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ export class Idle extends StateNode {
|
|||
|
||||
if (onlySelectedShape) {
|
||||
this.editor.mark('crop')
|
||||
this.editor.setCroppingShapeId(onlySelectedShape.id)
|
||||
this.editor.setCroppingShape(onlySelectedShape.id)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ export class Idle extends StateNode {
|
|||
}
|
||||
|
||||
override onCancel: TLEventHandlers['onCancel'] = () => {
|
||||
this.editor.setCroppingShapeId(null)
|
||||
this.editor.setCroppingShape(null)
|
||||
this.editor.setCurrentTool('select.idle', {})
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ export class Idle extends StateNode {
|
|||
return
|
||||
} else {
|
||||
if (this.editor.getShapeUtil(info.shape)?.canCrop(info.shape)) {
|
||||
this.editor.setCroppingShapeId(info.shape.id)
|
||||
this.editor.setCroppingShape(info.shape.id)
|
||||
this.editor.setSelectedShapeIds([info.shape.id])
|
||||
this.editor.setCurrentTool('select.crop.pointing_crop', info)
|
||||
} else {
|
||||
|
@ -152,7 +152,7 @@ export class Idle extends StateNode {
|
|||
override onKeyUp: TLEventHandlers['onKeyUp'] = (info) => {
|
||||
switch (info.code) {
|
||||
case 'Enter': {
|
||||
this.editor.setCroppingShapeId(null)
|
||||
this.editor.setCroppingShape(null)
|
||||
this.editor.setCurrentTool('select.idle', {})
|
||||
break
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ export class Idle extends StateNode {
|
|||
}
|
||||
|
||||
private cancel() {
|
||||
this.editor.setCroppingShapeId(null)
|
||||
this.editor.setCroppingShape(null)
|
||||
this.editor.setCurrentTool('select.idle', {})
|
||||
}
|
||||
|
||||
|
|
|
@ -208,7 +208,7 @@ export class Cropping extends StateNode {
|
|||
if (this.info.onInteractionEnd) {
|
||||
this.editor.setCurrentTool(this.info.onInteractionEnd, this.info)
|
||||
} else {
|
||||
this.editor.setCroppingShapeId(null)
|
||||
this.editor.setCroppingShape(null)
|
||||
this.parent.transition('idle', {})
|
||||
}
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ export class Cropping extends StateNode {
|
|||
if (this.info.onInteractionEnd) {
|
||||
this.editor.setCurrentTool(this.info.onInteractionEnd, this.info)
|
||||
} else {
|
||||
this.editor.setCroppingShapeId(null)
|
||||
this.editor.setCroppingShape(null)
|
||||
this.parent.transition('idle', {})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ export class DraggingHandle extends StateNode {
|
|||
this.isPrecise = false
|
||||
|
||||
if (initialTerminal?.type === 'binding') {
|
||||
this.editor.setHintingIds([initialTerminal.boundShapeId])
|
||||
this.editor.setHintingShapes([initialTerminal.boundShapeId])
|
||||
|
||||
this.isPrecise = !Vec2d.Equals(initialTerminal.normalizedAnchor, { x: 0.5, y: 0.5 })
|
||||
if (this.isPrecise) {
|
||||
|
@ -105,7 +105,7 @@ export class DraggingHandle extends StateNode {
|
|||
this.resetExactTimeout()
|
||||
}
|
||||
} else {
|
||||
this.editor.setHintingIds([])
|
||||
this.editor.setHintingShapes([])
|
||||
}
|
||||
// -->
|
||||
|
||||
|
@ -167,7 +167,7 @@ export class DraggingHandle extends StateNode {
|
|||
|
||||
override onExit = () => {
|
||||
this.parent.currentToolIdMask = undefined
|
||||
this.editor.setHintingIds([])
|
||||
this.editor.setHintingShapes([])
|
||||
this.editor.snaps.clear()
|
||||
this.editor.updateInstanceState(
|
||||
{ cursor: { type: 'default', rotation: 0 } },
|
||||
|
@ -284,7 +284,7 @@ export class DraggingHandle extends StateNode {
|
|||
|
||||
if (bindingAfter?.type === 'binding') {
|
||||
if (hintingShapeIds[0] !== bindingAfter.boundShapeId) {
|
||||
editor.setHintingIds([bindingAfter.boundShapeId])
|
||||
editor.setHintingShapes([bindingAfter.boundShapeId])
|
||||
this.pointingId = bindingAfter.boundShapeId
|
||||
this.isPrecise = pointerVelocity.len() < 0.5 || altKey
|
||||
this.isPreciseId = this.isPrecise ? bindingAfter.boundShapeId : null
|
||||
|
@ -292,7 +292,7 @@ export class DraggingHandle extends StateNode {
|
|||
}
|
||||
} else {
|
||||
if (hintingShapeIds.length > 0) {
|
||||
editor.setHintingIds([])
|
||||
editor.setHintingShapes([])
|
||||
this.pointingId = null
|
||||
this.isPrecise = false
|
||||
this.isPreciseId = null
|
||||
|
|
|
@ -19,7 +19,7 @@ export class EditingShape extends StateNode {
|
|||
if (!editingShapeId) return
|
||||
|
||||
// Clear the editing shape
|
||||
this.editor.setEditingShapeId(null)
|
||||
this.editor.setEditingShape(null)
|
||||
|
||||
const shape = this.editor.getShape(editingShapeId)!
|
||||
const util = this.editor.getShapeUtil(shape)
|
||||
|
|
|
@ -349,7 +349,7 @@ export class Idle extends StateNode {
|
|||
this.editor.focusedGroupId !== this.editor.currentPageId &&
|
||||
this.editor.selectedShapeIds.length > 0
|
||||
) {
|
||||
this.editor.popFocusLayer()
|
||||
this.editor.popFocusedGroupId()
|
||||
} else {
|
||||
this.editor.mark('clearing selection')
|
||||
this.editor.selectNone()
|
||||
|
@ -441,7 +441,7 @@ export class Idle extends StateNode {
|
|||
private startEditingShape(shape: TLShape, info: TLClickEventInfo | TLKeyboardEventInfo) {
|
||||
if (this.editor.isShapeOrAncestorLocked(shape) && shape.type !== 'embed') return
|
||||
this.editor.mark('editing shape')
|
||||
this.editor.setEditingShapeId(shape.id)
|
||||
this.editor.setEditingShape(shape.id)
|
||||
this.parent.transition('editing_shape', info)
|
||||
}
|
||||
|
||||
|
@ -470,7 +470,7 @@ export class Idle extends StateNode {
|
|||
const shape = this.editor.getShape(id)
|
||||
if (!shape) return
|
||||
|
||||
this.editor.setEditingShapeId(id)
|
||||
this.editor.setEditingShape(id)
|
||||
this.editor.select(id)
|
||||
this.parent.transition('editing_shape', info)
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ export class PointingCropHandle extends StateNode {
|
|||
if (!selectedShape) return
|
||||
|
||||
this.updateCursor(selectedShape)
|
||||
this.editor.setCroppingShapeId(selectedShape.id)
|
||||
this.editor.setCroppingShape(selectedShape.id)
|
||||
}
|
||||
|
||||
override onExit = () => {
|
||||
|
@ -55,7 +55,7 @@ export class PointingCropHandle extends StateNode {
|
|||
if (this.info.onInteractionEnd) {
|
||||
this.editor.setCurrentTool(this.info.onInteractionEnd, this.info)
|
||||
} else {
|
||||
this.editor.setCroppingShapeId(null)
|
||||
this.editor.setCroppingShape(null)
|
||||
this.parent.transition('idle', {})
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ export class PointingCropHandle extends StateNode {
|
|||
if (this.info.onInteractionEnd) {
|
||||
this.editor.setCurrentTool(this.info.onInteractionEnd, this.info)
|
||||
} else {
|
||||
this.editor.setCroppingShapeId(null)
|
||||
this.editor.setCroppingShape(null)
|
||||
this.parent.transition('idle', {})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ export class PointingHandle extends StateNode {
|
|||
const initialTerminal = (info.shape as TLArrowShape).props[info.handle.id as 'start' | 'end']
|
||||
|
||||
if (initialTerminal?.type === 'binding') {
|
||||
this.editor.setHintingIds([initialTerminal.boundShapeId])
|
||||
this.editor.setHintingShapes([initialTerminal.boundShapeId])
|
||||
}
|
||||
|
||||
this.editor.updateInstanceState(
|
||||
|
@ -21,7 +21,7 @@ export class PointingHandle extends StateNode {
|
|||
}
|
||||
|
||||
override onExit = () => {
|
||||
this.editor.setHintingIds([])
|
||||
this.editor.setHintingShapes([])
|
||||
this.editor.updateInstanceState(
|
||||
{ cursor: { type: 'default', rotation: 0 } },
|
||||
{ ephemeral: true }
|
||||
|
|
|
@ -94,7 +94,7 @@ export class PointingShape extends StateNode {
|
|||
this.editor.mark('clearing shape ids')
|
||||
this.editor.setSelectedShapeIds([])
|
||||
} else {
|
||||
this.editor.popFocusLayer()
|
||||
this.editor.popFocusedGroupId()
|
||||
}
|
||||
this.parent.transition('idle', info)
|
||||
return
|
||||
|
|
|
@ -108,7 +108,7 @@ export class Resizing extends StateNode {
|
|||
this.handleResizeEnd()
|
||||
|
||||
if (this.editAfterComplete && this.editor.onlySelectedShape) {
|
||||
this.editor.setEditingShapeId(this.editor.onlySelectedShape.id)
|
||||
this.editor.setEditingShape(this.editor.onlySelectedShape.id)
|
||||
this.editor.setCurrentTool('select')
|
||||
this.editor.root.current.value!.transition('editing_shape', {})
|
||||
return
|
||||
|
|
|
@ -152,7 +152,7 @@ export class Translating extends StateNode {
|
|||
if (this.editAfterComplete) {
|
||||
const onlySelected = this.editor.onlySelectedShape
|
||||
if (onlySelected) {
|
||||
this.editor.setEditingShapeId(onlySelected.id)
|
||||
this.editor.setEditingShape(onlySelected.id)
|
||||
this.editor.setCurrentTool('select')
|
||||
this.editor.root.current.value!.transition('editing_shape', {})
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ export function selectOnCanvasPointerUp(editor: Editor) {
|
|||
if (isShapeId(focusedGroupId)) {
|
||||
const groupShape = editor.getShape(focusedGroupId)!
|
||||
if (!editor.isPointInShape(groupShape, currentPagePoint, { margin: 0, hitInside: true })) {
|
||||
editor.setFocusedGroupId(null)
|
||||
editor.setFocusedGroup(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ export function updateHoveredId(editor: Editor) {
|
|||
margin: HIT_TEST_MARGIN / editor.zoomLevel,
|
||||
})
|
||||
|
||||
if (!hitShape) return editor.setHoveredShapeId(null)
|
||||
if (!hitShape) return editor.setHoveredShape(null)
|
||||
|
||||
let shapeToHover: TLShape | undefined = undefined
|
||||
|
||||
|
@ -26,5 +26,5 @@ export function updateHoveredId(editor: Editor) {
|
|||
}
|
||||
}
|
||||
|
||||
return editor.setHoveredShapeId(shapeToHover.id)
|
||||
return editor.setHoveredShape(shapeToHover.id)
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ const moveShapesToPage2 = () => {
|
|||
|
||||
describe('shapes that are moved to another page', () => {
|
||||
it("should be excluded from the previous page's focusedGroupId", () => {
|
||||
editor.setFocusedGroupId(ids.group1)
|
||||
editor.setFocusedGroup(ids.group1)
|
||||
expect(editor.focusedGroupId).toBe(ids.group1)
|
||||
moveShapesToPage2()
|
||||
expect(editor.focusedGroupId).toBe(editor.currentPageId)
|
||||
|
@ -53,13 +53,13 @@ describe('shapes that are moved to another page', () => {
|
|||
|
||||
describe("should be excluded from the previous page's hintingShapeIds", () => {
|
||||
test('[boxes]', () => {
|
||||
editor.setHintingIds([ids.box1, ids.box2, ids.box3])
|
||||
editor.setHintingShapes([ids.box1, ids.box2, ids.box3])
|
||||
expect(editor.hintingShapeIds).toEqual([ids.box1, ids.box2, ids.box3])
|
||||
moveShapesToPage2()
|
||||
expect(editor.hintingShapeIds).toEqual([])
|
||||
})
|
||||
test('[frame that does not move]', () => {
|
||||
editor.setHintingIds([ids.frame1])
|
||||
editor.setHintingShapes([ids.frame1])
|
||||
expect(editor.hintingShapeIds).toEqual([ids.frame1])
|
||||
moveShapesToPage2()
|
||||
expect(editor.hintingShapeIds).toEqual([ids.frame1])
|
||||
|
@ -68,25 +68,25 @@ describe('shapes that are moved to another page', () => {
|
|||
|
||||
describe("should be excluded from the previous page's editingShapeId", () => {
|
||||
test('[root shape]', () => {
|
||||
editor.setEditingShapeId(ids.box1)
|
||||
editor.setEditingShape(ids.box1)
|
||||
expect(editor.editingShapeId).toBe(ids.box1)
|
||||
moveShapesToPage2()
|
||||
expect(editor.editingShapeId).toBe(null)
|
||||
})
|
||||
test('[child of frame]', () => {
|
||||
editor.setEditingShapeId(ids.box2)
|
||||
editor.setEditingShape(ids.box2)
|
||||
expect(editor.editingShapeId).toBe(ids.box2)
|
||||
moveShapesToPage2()
|
||||
expect(editor.editingShapeId).toBe(null)
|
||||
})
|
||||
test('[child of group]', () => {
|
||||
editor.setEditingShapeId(ids.box3)
|
||||
editor.setEditingShape(ids.box3)
|
||||
expect(editor.editingShapeId).toBe(ids.box3)
|
||||
moveShapesToPage2()
|
||||
expect(editor.editingShapeId).toBe(null)
|
||||
})
|
||||
test('[frame that doesnt move]', () => {
|
||||
editor.setEditingShapeId(ids.frame1)
|
||||
editor.setEditingShape(ids.frame1)
|
||||
expect(editor.editingShapeId).toBe(ids.frame1)
|
||||
moveShapesToPage2()
|
||||
expect(editor.editingShapeId).toBe(ids.frame1)
|
||||
|
@ -95,13 +95,13 @@ describe('shapes that are moved to another page', () => {
|
|||
|
||||
describe("should be excluded from the previous page's erasingShapeIds", () => {
|
||||
test('[boxes]', () => {
|
||||
editor.setErasingShapeIds([ids.box1, ids.box2, ids.box3])
|
||||
editor.setErasingShapes([ids.box1, ids.box2, ids.box3])
|
||||
expect(editor.erasingShapeIds).toEqual([ids.box1, ids.box2, ids.box3])
|
||||
moveShapesToPage2()
|
||||
expect(editor.erasingShapeIds).toEqual([])
|
||||
})
|
||||
test('[frame that does not move]', () => {
|
||||
editor.setErasingShapeIds([ids.frame1])
|
||||
editor.setErasingShapes([ids.frame1])
|
||||
expect(editor.erasingShapeIds).toEqual([ids.frame1])
|
||||
moveShapesToPage2()
|
||||
expect(editor.erasingShapeIds).toEqual([ids.frame1])
|
||||
|
|
Loading…
Reference in a new issue