Skip to content

Commit

Permalink
Chore(): TS add detailed types for on/off/once callbacks (fabricjs#8431)
Browse files Browse the repository at this point in the history
  • Loading branch information
ShaMan123 authored and frankrousseau committed Jan 6, 2023
1 parent 837ac68 commit 6bf036a
Show file tree
Hide file tree
Showing 31 changed files with 431 additions and 168 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## [next]

- chore(TS): Observable types [#8431](https://github.com/fabricjs/fabric.js/pull/8431)
- chore(TS): migrate Group/ActiveSelection [#8455](https://github.com/fabricjs/fabric.js/pull/8455)
- fix(TS): migration error of itext key mixin (#8421) [#8457](https://github.com/fabricjs/fabric.js/pull/8457)
- chore(TS): migrate text classes/mixins [#8421](https://github.com/fabricjs/fabric.js/pull/8421)
Expand Down
234 changes: 234 additions & 0 deletions src/EventTypeDefs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
import type { Control } from './controls/control.class';
import type { Point } from './point.class';
import type { FabricObject } from './shapes/fabricObject.class';
import type { Group } from './shapes/group.class';
import type { TOriginX, TOriginY, TRadian } from './typedefs';
import type { saveObjectTransform } from './util/misc/objectTransforms';
import type { Canvas } from './__types__';
import type { IText } from './shapes/itext.class';

export type ModifierKey = 'altKey' | 'shiftKey' | 'ctrlKey';

export type TPointerEvent = MouseEvent | TouchEvent;

export type TransformAction<T extends Transform = Transform, R = void> = (
eventData: TPointerEvent,
transform: T,
x: number,
y: number
) => R;

export type TransformActionHandler<T extends Transform = Transform> =
TransformAction<T, boolean>;

export type ControlCallback<R = void> = (
eventData: TPointerEvent,
control: Control,
fabricObject: FabricObject
) => R;

export type ControlCursorCallback = ControlCallback<string>;

/**
* relative to target's containing coordinate plane
* both agree on every point
*/
export type Transform = {
target: FabricObject;
action: string;
actionHandler: TransformActionHandler;
corner: string;
scaleX: number;
scaleY: number;
skewX: number;
skewY: number;
offsetX: number;
offsetY: number;
originX: TOriginX;
originY: TOriginY;
ex: number;
ey: number;
lastX: number;
lastY: number;
theta: TRadian;
width: number;
height: number;
shiftKey: boolean;
altKey: boolean;
original: ReturnType<typeof saveObjectTransform>;
};

export type TEvent<E extends Event = TPointerEvent> = {
e: E;
};

export type BasicTransformEvent<E extends Event = TPointerEvent> = TEvent<E> & {
transform: Transform;
pointer: Point;
};

export type TModificationEvents =
| 'moving'
| 'scaling'
| 'rotating'
| 'skewing'
| 'resizing';

type ObjectModifiedEvents = Record<TModificationEvents, BasicTransformEvent> & {
modified: BasicTransformEvent | never;
};

type CanvasModifiedEvents = Record<
`object:${keyof ObjectModifiedEvents}`,
BasicTransformEvent & { target: FabricObject }
>;

export type TransformEvent<T extends Event = TPointerEvent> =
BasicTransformEvent<T> & {
target: FabricObject;
subTargets: FabricObject[];
button: number;
isClick: boolean;
pointer: Point;
absolutePointer: Point;
};

type SimpleEventHandler<T extends Event = TPointerEvent> = TEvent<T> & {
target: FabricObject;
subTargets: FabricObject[];
};

type InEvent = {
previousTarget?: FabricObject;
};

type OutEvent = {
nextTarget?: FabricObject;
};

type DragEventData = TEvent<DragEvent> & {
target: FabricObject;
subTargets?: FabricObject[];
dragSource?: FabricObject;
canDrop?: boolean;
dropTarget?: FabricObject;
};

type DropEventData = DragEventData & { pointer: Point };

type DnDEvents = {
dragstart: TEvent<DragEvent> & { target: FabricObject };
drag: DragEventData;
dragover: DragEventData;
dragenter: DragEventData & InEvent;
dragleave: DragEventData & OutEvent;
dragend: DragEventData;
'drop:before': DropEventData;
drop: DropEventData;
'drop:after': DropEventData;
};

type CanvasDnDEvents = DnDEvents & {
'drag:enter': DragEventData & InEvent;
'drag:leave': DragEventData & OutEvent;
};

type CanvasSelectionEvents = {
'selection:created': TEvent & {
selected: FabricObject[];
};
'selection:updated': TEvent & {
selected: FabricObject[];
deselected: FabricObject[];
};
'before:selection:cleared': Partial<TEvent> & {
deselected: FabricObject[];
};
'selection:cleared': Partial<TEvent> & {
deselected: FabricObject[];
};
};

type BeforeSuffix<T extends string> = `${T}:before`;
type WithBeforeSuffix<T extends string> = T | BeforeSuffix<T>;

type TPointerEvents<Prefix extends string, E = Record<string, never>> = Record<
`${Prefix}${
| WithBeforeSuffix<'down'>
| WithBeforeSuffix<'move'>
| WithBeforeSuffix<'up'>
| 'dblclick'}`,
TransformEvent & E
> &
Record<`${Prefix}wheel`, TransformEvent<WheelEvent> & E> &
Record<`${Prefix}over`, TransformEvent & InEvent & E> &
Record<`${Prefix}out`, TransformEvent & OutEvent & E>;

export type ObjectPointerEvents = TPointerEvents<'mouse'>;
export type CanvasPointerEvents = TPointerEvents<'mouse:'>;

export type ObjectEvents = ObjectPointerEvents &
DnDEvents &
ObjectModifiedEvents & {
// selection
selected: {
e: TEvent;
target: FabricObject;
};
deselected: {
e?: TEvent;
target: FabricObject;
};

// tree
added: { target: Group | Canvas };
removed: { target: Group | Canvas };

// erasing
'erasing:end': { path: FabricObject };
};

export type StaticCanvasEvents = {
// tree
'object:added': { target: FabricObject };
'object:removed': { target: FabricObject };
'canvas:cleared': never;

// rendering
'before:render': { ctx: CanvasRenderingContext2D };
'after:render': { ctx: CanvasRenderingContext2D };
};

export type CanvasEvents = StaticCanvasEvents &
CanvasPointerEvents &
CanvasDnDEvents &
CanvasModifiedEvents &
CanvasSelectionEvents & {
// brushes
'before:path:created': { path: FabricObject };
'path:created': { path: FabricObject };

// erasing
'erasing:start': never;
'erasing:end':
| never
| {
path: FabricObject;
targets: FabricObject[];
subTargets: FabricObject[];
drawables: {
backgroundImage?: FabricObject;
overlayImage?: FabricObject;
};
};

// IText
'text:selection:changed': { target: IText };
'text:changed': { target: IText };
'text:editing:entered': { target: IText };
'text:editing:exited': { target: IText };

// misc
'contextmenu:before': SimpleEventHandler<Event>;
contextmenu: SimpleEventHandler<Event>;
};
5 changes: 3 additions & 2 deletions src/__types__.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { CanvasEvents, ModifierKey } from './EventTypeDefs';
import type { Observable } from './mixins/observable.mixin';
import type { Point } from './point.class';
import { ModifierKey, TMat2D } from './typedefs';
import { TMat2D } from './typedefs';

/**
* @todo remove transient
Expand All @@ -18,4 +19,4 @@ export type StaticCanvas = Record<string, any> & {
br: Point;
};
getRetinaScaling(): number;
} & Observable;
} & Observable<CanvasEvents>;
3 changes: 2 additions & 1 deletion src/brushes/pencil_brush.class.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { fabric } from '../../HEADER';
import { ModifierKey, TEvent } from '../EventTypeDefs';
import { Point } from '../point.class';
import { Shadow } from '../shadow.class';
import { Path } from '../shapes/path.class';
import { TEvent, ModifierKey, PathData } from '../typedefs';
import { PathData } from '../typedefs';
import { getSmoothPathFromPoints, joinPath } from '../util/path';
import { Canvas } from '../__types__';
import { BaseBrush } from './base_brush.class';
Expand Down
17 changes: 11 additions & 6 deletions src/canvas.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { dragHandler, getActionFromCorner } from './controls/actions';
import { Point } from './point.class';
import { FabricObject } from './shapes/fabricObject.class';
import { Transform } from './typedefs';
import { Transform } from './EventTypeDefs';
import { saveObjectTransform } from './util/misc/objectTransforms';

(function (global) {
Expand Down Expand Up @@ -441,10 +441,12 @@ import { saveObjectTransform } from './util/misc/objectTransforms';
this._objectsToRender = undefined;
// removing active object should fire "selection:cleared" events
if (obj === this._activeObject) {
this.fire('before:selection:cleared', { target: obj });
this.fire('before:selection:cleared', { deselected: [obj] });
this._discardActiveObject();
this.fire('selection:cleared', { target: obj });
obj.fire('deselected');
this.fire('selection:cleared', { deselected: [obj] });
obj.fire('deselected', {
target: obj,
});
}
if (obj === this._hoveredTarget) {
this._hoveredTarget = null;
Expand Down Expand Up @@ -548,7 +550,7 @@ import { saveObjectTransform } from './util/misc/objectTransforms';
var ctx = this.contextTop;
this.clearContext(ctx);
this.renderTopLayer(ctx);
this.fire('after:render');
this.fire('after:render', { ctx });
return this;
},

Expand Down Expand Up @@ -1363,7 +1365,10 @@ import { saveObjectTransform } from './util/misc/objectTransforms';
var currentActives = this.getActiveObjects(),
activeObject = this.getActiveObject();
if (currentActives.length) {
this.fire('before:selection:cleared', { target: activeObject, e: e });
this.fire('before:selection:cleared', {
e,
deselected: [activeObject],
});
}
this._discardActiveObject(e);
this._fireSelectionEvents(currentActives, e);
Expand Down
2 changes: 1 addition & 1 deletion src/controls/changeWidth.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TransformActionHandler } from '../typedefs';
import { TransformActionHandler } from '../EventTypeDefs';
import { getLocalPoint, isTransformCentered } from './util';
import { wrapWithFireEvent } from './wrapWithFireEvent';
import { wrapWithFixedAnchor } from './wrapWithFixedAnchor';
Expand Down
9 changes: 4 additions & 5 deletions src/controls/control.class.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { fabric } from '../../HEADER';
import { halfPI } from '../constants';
import { Point } from '../point.class';
import type { FabricObject } from '../shapes/object.class';
import {
TDegree,
TMat2D,
TPointerEvent,
TransformAction,
TransformActionHandler,
} from '../typedefs';
} from '../EventTypeDefs';
import { Point } from '../point.class';
import type { FabricObject } from '../shapes/object.class';
import { TDegree, TMat2D } from '../typedefs';
import { cos } from '../util/misc/cos';
import { degreesToRadians } from '../util/misc/radiansDegreesConversion';
import { sin } from '../util/misc/sin';
Expand Down
2 changes: 1 addition & 1 deletion src/controls/drag.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TransformActionHandler } from '../typedefs';
import { TransformActionHandler } from '../EventTypeDefs';
import { fireEvent } from '../util/fireEvent';
import { commonEventInfo, isLocked } from './util';

Expand Down
7 changes: 4 additions & 3 deletions src/controls/rotate.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// @ts-nocheck

import { ControlCursorCallback, TransformActionHandler } from '../typedefs';
import {
ControlCursorCallback,
TransformActionHandler,
} from '../EventTypeDefs';
import { radiansToDegrees } from '../util/misc/radiansDegreesConversion';
import { isLocked, NOT_ALLOWED_CURSOR } from './util';
import { wrapWithFireEvent } from './wrapWithFireEvent';
Expand Down
6 changes: 3 additions & 3 deletions src/controls/scale.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { FabricObject } from '../shapes/fabricObject.class';
import {
ControlCursorCallback,
TAxis,
TPointerEvent,
Transform,
TransformActionHandler,
} from '../typedefs';
} from '../EventTypeDefs';
import type { FabricObject } from '../shapes/fabricObject.class';
import { TAxis } from '../typedefs';
import { Canvas } from '../__types__';
import {
findCornerQuadrant,
Expand Down
6 changes: 3 additions & 3 deletions src/controls/scaleSkew.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { FabricObject } from '../shapes/object.class';
import {
ControlCallback,
ControlCursorCallback,
TAxisKey,
TPointerEvent,
TransformActionHandler,
} from '../typedefs';
} from '../EventTypeDefs';
import type { FabricObject } from '../shapes/object.class';
import { TAxisKey } from '../typedefs';
import { Canvas } from '../__types__';
import { scaleCursorStyleHandler, scalingX, scalingY } from './scale';
import { skewCursorStyleHandler, skewHandlerX, skewHandlerY } from './skew';
Expand Down

0 comments on commit 6bf036a

Please sign in to comment.