Skip to content

Commit

Permalink
chore(TS): types for toObject and additionaProperties (#8677)
Browse files Browse the repository at this point in the history
  • Loading branch information
ShaMan123 authored Mar 4, 2023
1 parent 0a37035 commit a0f8275
Show file tree
Hide file tree
Showing 20 changed files with 740 additions and 663 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): type Object props [#8677](https://github.com/fabricjs/fabric.js/issues/8677)
- chore(TS): remove default values from filter prototypes [#8742](https://github.com/fabricjs/fabric.js/issues/8742)
- chore(TS): remove default values from Objects prototypes, ( filters in a followup ) [#8719](https://github.com/fabricjs/fabric.js/issues/8719)
- fix(Intersection): bug causing selection edge case [#8735](https://github.com/fabricjs/fabric.js/pull/8735)
Expand Down
2 changes: 1 addition & 1 deletion src/Shadow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ export class Shadow {
}

const defaults = Shadow.ownDefaults;
const out: Record<string, unknown> = {};
const out: Partial<typeof data> = {};
for (const key in data) {
if (
data[key as keyof typeof data] !== defaults[key as keyof typeof data]
Expand Down
2 changes: 1 addition & 1 deletion src/controls/controlRendering.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { twoMathPi } from '../constants';
import type { FabricObject } from '../shapes/Object/Object';
import type { FabricObject } from '../shapes/Object/FabricObject';
import { degreesToRadians } from '../util/misc/radiansDegreesConversion';
import type { Control } from './Control';

Expand Down
72 changes: 45 additions & 27 deletions src/shapes/Circle.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ObjectEvents } from '../EventTypeDefs';
import { SHARED_ATTRIBUTES } from '../parser/attributes';
import { parseAttributes } from '../parser/parseAttributes';
import { cos } from '../util/misc/cos';
Expand All @@ -6,15 +7,13 @@ import { sin } from '../util/misc/sin';
import { classRegistry } from '../ClassRegistry';
import { FabricObject, cacheProperties } from './Object/FabricObject';
import { TClassProperties } from '../typedefs';
import { FabricObjectProps } from './Object/ObjectProps';
import {
FabricObjectProps,
SerializedObjectProps,
TProps,
} from './Object/types';

export const circleDefaultValues: Partial<TClassProperties<Circle>> = {
radius: 0,
startAngle: 0,
endAngle: 360,
};

export interface CircleProps extends FabricObjectProps {
interface UniqCircleProps {
/**
* Radius of this circle
* @type Number
Expand All @@ -39,17 +38,33 @@ export interface CircleProps extends FabricObjectProps {
endAngle: number;
}

export class Circle extends FabricObject implements CircleProps {
export interface SerializedCircleProps
extends SerializedObjectProps,
UniqCircleProps {}

export interface CircleProps extends FabricObjectProps, UniqCircleProps {}

const CIRCLE_PROPS = ['radius', 'startAngle', 'endAngle'] as const;

export const circleDefaultValues: UniqCircleProps = {
radius: 0,
startAngle: 0,
endAngle: 360,
};

export class Circle<
Props extends TProps<CircleProps> = Partial<CircleProps>,
SProps extends SerializedCircleProps = SerializedCircleProps,
EventSpec extends ObjectEvents = ObjectEvents
>
extends FabricObject<Props, SProps, EventSpec>
implements UniqCircleProps
{
declare radius: number;
declare startAngle: number;
declare endAngle: number;

static cacheProperties = [
...cacheProperties,
'radius',
'startAngle',
'endAngle',
];
static cacheProperties = [...cacheProperties, ...CIRCLE_PROPS];

static ownDefaults: Record<string, any> = circleDefaultValues;

Expand All @@ -60,10 +75,6 @@ export class Circle extends FabricObject implements CircleProps {
};
}

constructor(options?: CircleProps) {
super(options);
}

/**
* @private
* @param {String} key
Expand Down Expand Up @@ -125,13 +136,11 @@ export class Circle extends FabricObject implements CircleProps {
* @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
* @return {Object} object representation of an instance
*/
toObject(propertiesToInclude: string[] = []): object {
return super.toObject([
'radius',
'startAngle',
'endAngle',
...propertiesToInclude,
]);
toObject<
T extends Omit<Props & TClassProperties<this>, keyof SProps>,
K extends keyof T = never
>(propertiesToInclude: K[] = []): { [R in K]: T[K] } & SProps {
return super.toObject([...CIRCLE_PROPS, ...propertiesToInclude]);
}

/* _TO_SVG_START_ */
Expand Down Expand Up @@ -200,7 +209,7 @@ export class Circle extends FabricObject implements CircleProps {
top = 0,
radius,
...otherParsedAttributes
} = parseAttributes(element, this.ATTRIBUTE_NAMES);
} = parseAttributes(element, this.ATTRIBUTE_NAMES) as Partial<CircleProps>;

if (!radius || radius < 0) {
throw new Error(
Expand All @@ -220,6 +229,15 @@ export class Circle extends FabricObject implements CircleProps {
}

/* _FROM_SVG_END_ */

/**
* @todo how do we declare this??
*/
static fromObject<T extends TProps<SerializedCircleProps>>(
object: T
): Promise<Circle> {
return super.fromObject(object) as unknown as Promise<Circle>;
}
}

// @ts-expect-error
Expand Down
18 changes: 12 additions & 6 deletions src/shapes/Object/FabricObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,23 @@ import { ObjectEvents } from '../../EventTypeDefs';
import { FabricObjectSVGExportMixin } from './FabricObjectSVGExportMixin';
import { InteractiveFabricObject } from './InteractiveObject';
import { applyMixins } from '../../util/applyMixins';
import { FabricObjectProps } from './ObjectProps';
import { FabricObjectProps } from './types/FabricObjectProps';
import { TFabricObjectProps, SerializedObjectProps } from './types';

// TODO somehow we have to make a tree-shakeable import

// eslint-disable-next-line @typescript-eslint/no-empty-interface, @typescript-eslint/no-unused-vars
export interface FabricObject<EventSpec extends ObjectEvents = ObjectEvents>
extends FabricObjectSVGExportMixin {}
export interface FabricObject<
Props extends TFabricObjectProps = Partial<FabricObjectProps>,
SProps extends SerializedObjectProps = SerializedObjectProps,
EventSpec extends ObjectEvents = ObjectEvents
> extends FabricObjectSVGExportMixin {}

export class FabricObject<EventSpec extends ObjectEvents = ObjectEvents>
extends InteractiveFabricObject<EventSpec>
implements FabricObjectProps {}
export class FabricObject<
Props extends TFabricObjectProps = Partial<FabricObjectProps>,
SProps extends SerializedObjectProps = SerializedObjectProps,
EventSpec extends ObjectEvents = ObjectEvents
> extends InteractiveFabricObject<Props, SProps, EventSpec> {}

applyMixins(FabricObject, [FabricObjectSVGExportMixin]);

Expand Down
75 changes: 51 additions & 24 deletions src/shapes/Object/InteractiveObject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import { sizeAfterTransform } from '../../util/misc/objectTransforms';
import { ObjectEvents, TPointerEvent } from '../../EventTypeDefs';
import type { Canvas } from '../../canvas/Canvas';
import type { ControlRenderingStyleOverride } from '../../controls/controlRendering';
import { FabricObjectProps } from './ObjectProps';
import { FabricObjectProps } from './types/FabricObjectProps';
import { TFabricObjectProps, SerializedObjectProps } from './types';

type TOCoord = Point & {
corner: TCornerPoint;
Expand All @@ -23,13 +24,13 @@ type TOCoord = Point & {
type TControlSet = Record<string, Control>;

type TBorderRenderingStyleOverride = Partial<
Pick<FabricObject, 'borderColor' | 'borderDashArray'>
Pick<InteractiveFabricObject, 'borderColor' | 'borderDashArray'>
>;

type TStyleOverride = ControlRenderingStyleOverride &
TBorderRenderingStyleOverride &
Partial<
Pick<FabricObject, 'hasBorders' | 'hasControls'> & {
Pick<InteractiveFabricObject, 'hasBorders' | 'hasControls'> & {
forActiveSelection: boolean;
}
>;
Expand All @@ -42,11 +43,53 @@ export interface DragMethods {
export type FabricObjectWithDragSupport = InteractiveFabricObject & DragMethods;

export class InteractiveFabricObject<
Props extends TFabricObjectProps = Partial<FabricObjectProps>,
SProps extends SerializedObjectProps = SerializedObjectProps,
EventSpec extends ObjectEvents = ObjectEvents
>
extends FabricObject<EventSpec>
extends FabricObject<Props, SProps, EventSpec>
implements FabricObjectProps
{
declare noScaleCache: boolean;
declare centeredScaling: false;

declare snapAngle?: TDegree;
declare snapThreshold?: TDegree;
declare centeredRotation: true;

declare lockMovementX: boolean;
declare lockMovementY: boolean;
declare lockRotation: boolean;
declare lockScalingX: boolean;
declare lockScalingY: boolean;
declare lockSkewingX: boolean;
declare lockSkewingY: boolean;
declare lockScalingFlip: boolean;

declare cornerSize: number;
declare touchCornerSize: number;
declare transparentCorners: boolean;
declare cornerColor: string;
declare cornerStrokeColor: string;
declare cornerStyle: 'rect' | 'circle';
declare cornerDashArray: number[] | null;
declare hasControls: boolean;

declare borderColor: string;
declare borderDashArray: number[] | null;
declare borderOpacityWhenMoving: number;
declare borderScaleFactor: number;
declare hasBorders: boolean;
declare selectionBackgroundColor: string;

declare selectable: boolean;
declare evented: boolean;
declare perPixelTargetFind: boolean;
declare activeOn: 'down' | 'up';

declare hoverCursor: CSSStyleDeclaration['cursor'] | null;
declare moveCursor: CSSStyleDeclaration['cursor'] | null;

/**
* Describe object's corner position in canvas element coordinates.
* properties are depending on control keys and padding the main controls.
Expand Down Expand Up @@ -75,10 +118,6 @@ export class InteractiveFabricObject<
*/
declare _controlsVisibility: Record<string, boolean>;

declare noScaleCache: boolean;
declare snapAngle?: TDegree;
declare snapThreshold?: TDegree;

/**
* holds the controls for the object.
* controls are added by default_controls.js
Expand All @@ -103,14 +142,6 @@ export class InteractiveFabricObject<

declare canvas?: Canvas;

/**
* Constructor
* @param {Object} [options] Options object
*/
constructor(options?: FabricObjectProps) {
super(options);
}

/**
* Update width and height of the canvas for cache
* returns true or false if canvas needed resize.
Expand All @@ -122,10 +153,7 @@ export class InteractiveFabricObject<
if (this.noScaleCache && targetCanvas && targetCanvas._currentTransform) {
const target = targetCanvas._currentTransform.target,
action = targetCanvas._currentTransform.action;
if (
this === (target as InteractiveFabricObject) &&
action.startsWith('scale')
) {
if (this === (target as unknown as this) && action.startsWith('scale')) {
return false;
}
}
Expand All @@ -136,7 +164,7 @@ export class InteractiveFabricObject<
* Determines which corner is under the mouse cursor, represented by `pointer`.
* This function is return a corner only if the object is the active one.
* This is done to avoid selecting corner of non active object and activating transformations
* rather than drag action. The default behaviour of fabricJS is that if you want to trasform
* rather than drag action. The default behavior of fabricJS is that if you want to transform
* an object, first you select it to show the control set
* @private
* @param {Object} pointer The pointer indicating the mouse position
Expand All @@ -147,7 +175,7 @@ export class InteractiveFabricObject<
if (
!this.hasControls ||
!this.canvas ||
(this.canvas._activeObject as InteractiveFabricObject) !== this
(this.canvas._activeObject as unknown as this) !== this
) {
return 0;
}
Expand Down Expand Up @@ -312,8 +340,7 @@ export class InteractiveFabricObject<
if (
!this.selectionBackgroundColor ||
(this.canvas && !this.canvas.interactive) ||
(this.canvas &&
(this.canvas._activeObject as InteractiveFabricObject) !== this)
(this.canvas && (this.canvas._activeObject as unknown as this) !== this)
) {
return;
}
Expand Down
Loading

0 comments on commit a0f8275

Please sign in to comment.