diff --git a/CHANGELOG.md b/CHANGELOG.md index 32aad034919..2cb02249e35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/src/Shadow.ts b/src/Shadow.ts index 04d7a908c01..9b19a02d2f5 100644 --- a/src/Shadow.ts +++ b/src/Shadow.ts @@ -195,7 +195,7 @@ export class Shadow { } const defaults = Shadow.ownDefaults; - const out: Record = {}; + const out: Partial = {}; for (const key in data) { if ( data[key as keyof typeof data] !== defaults[key as keyof typeof data] diff --git a/src/controls/controlRendering.ts b/src/controls/controlRendering.ts index 9da23bc38d9..e78a9dc641d 100644 --- a/src/controls/controlRendering.ts +++ b/src/controls/controlRendering.ts @@ -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'; diff --git a/src/shapes/Circle.ts b/src/shapes/Circle.ts index fe750966746..8a8b27b8bd3 100644 --- a/src/shapes/Circle.ts +++ b/src/shapes/Circle.ts @@ -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'; @@ -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> = { - radius: 0, - startAngle: 0, - endAngle: 360, -}; - -export interface CircleProps extends FabricObjectProps { +interface UniqCircleProps { /** * Radius of this circle * @type Number @@ -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 = Partial, + SProps extends SerializedCircleProps = SerializedCircleProps, + EventSpec extends ObjectEvents = ObjectEvents + > + extends FabricObject + 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 = circleDefaultValues; @@ -60,10 +75,6 @@ export class Circle extends FabricObject implements CircleProps { }; } - constructor(options?: CircleProps) { - super(options); - } - /** * @private * @param {String} key @@ -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, keyof SProps>, + K extends keyof T = never + >(propertiesToInclude: K[] = []): { [R in K]: T[K] } & SProps { + return super.toObject([...CIRCLE_PROPS, ...propertiesToInclude]); } /* _TO_SVG_START_ */ @@ -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; if (!radius || radius < 0) { throw new Error( @@ -220,6 +229,15 @@ export class Circle extends FabricObject implements CircleProps { } /* _FROM_SVG_END_ */ + + /** + * @todo how do we declare this?? + */ + static fromObject>( + object: T + ): Promise { + return super.fromObject(object) as unknown as Promise; + } } // @ts-expect-error diff --git a/src/shapes/Object/FabricObject.ts b/src/shapes/Object/FabricObject.ts index 69943253957..560d23fb3c5 100644 --- a/src/shapes/Object/FabricObject.ts +++ b/src/shapes/Object/FabricObject.ts @@ -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 - extends FabricObjectSVGExportMixin {} +export interface FabricObject< + Props extends TFabricObjectProps = Partial, + SProps extends SerializedObjectProps = SerializedObjectProps, + EventSpec extends ObjectEvents = ObjectEvents +> extends FabricObjectSVGExportMixin {} -export class FabricObject - extends InteractiveFabricObject - implements FabricObjectProps {} +export class FabricObject< + Props extends TFabricObjectProps = Partial, + SProps extends SerializedObjectProps = SerializedObjectProps, + EventSpec extends ObjectEvents = ObjectEvents +> extends InteractiveFabricObject {} applyMixins(FabricObject, [FabricObjectSVGExportMixin]); diff --git a/src/shapes/Object/InteractiveObject.ts b/src/shapes/Object/InteractiveObject.ts index 894d1676aba..13d77adf688 100644 --- a/src/shapes/Object/InteractiveObject.ts +++ b/src/shapes/Object/InteractiveObject.ts @@ -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; @@ -23,13 +24,13 @@ type TOCoord = Point & { type TControlSet = Record; type TBorderRenderingStyleOverride = Partial< - Pick + Pick >; type TStyleOverride = ControlRenderingStyleOverride & TBorderRenderingStyleOverride & Partial< - Pick & { + Pick & { forActiveSelection: boolean; } >; @@ -42,11 +43,53 @@ export interface DragMethods { export type FabricObjectWithDragSupport = InteractiveFabricObject & DragMethods; export class InteractiveFabricObject< + Props extends TFabricObjectProps = Partial, + SProps extends SerializedObjectProps = SerializedObjectProps, EventSpec extends ObjectEvents = ObjectEvents > - extends FabricObject + extends FabricObject 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. @@ -75,10 +118,6 @@ export class InteractiveFabricObject< */ declare _controlsVisibility: Record; - declare noScaleCache: boolean; - declare snapAngle?: TDegree; - declare snapThreshold?: TDegree; - /** * holds the controls for the object. * controls are added by default_controls.js @@ -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. @@ -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; } } @@ -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 @@ -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; } @@ -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; } diff --git a/src/shapes/Object/Object.ts b/src/shapes/Object/Object.ts index 8e90c412b66..549fe6d0ec9 100644 --- a/src/shapes/Object/Object.ts +++ b/src/shapes/Object/Object.ts @@ -10,6 +10,7 @@ import type { TFiller, TSize, TCacheCanvasDimensions, + TClassProperties, } from '../../typedefs'; import { classRegistry } from '../../ClassRegistry'; import { runningAnimations } from '../../util/animation/AnimationRegistry'; @@ -38,7 +39,9 @@ import { import type { Gradient } from '../../gradient/Gradient'; import type { Pattern } from '../../Pattern'; import type { Canvas } from '../../canvas/Canvas'; -import { ObjectProps } from './ObjectProps'; +import { SerializedObjectProps } from './types/SerializedObjectProps'; +import { ObjectProps } from './types/ObjectProps'; +import { TProps } from './types'; export type TCachedFabricObject = FabricObject & Required< @@ -83,62 +86,41 @@ export type TCachedFabricObject = FabricObject & * @fires dragleave * @fires drop */ -export class FabricObject +export class FabricObject< + Props extends TProps = Partial, + SProps extends SerializedObjectProps = SerializedObjectProps, + EventSpec extends ObjectEvents = ObjectEvents + > extends AnimatableObject implements ObjectProps { declare readonly type: string; + declare minScaleLimit: number; + declare opacity: number; - declare cornerSize: number; - declare touchCornerSize: number; - declare transparentCorners: boolean; - declare hoverCursor: CSSStyleDeclaration['cursor'] | null; - declare moveCursor: CSSStyleDeclaration['cursor'] | null; - declare borderColor: string; - declare borderDashArray: number[] | null; - declare cornerColor: string; - declare cornerStrokeColor: string; - declare cornerStyle: 'rect' | 'circle'; - declare cornerDashArray: number[] | null; - declare centeredScaling: false; - declare centeredRotation: true; - declare stroke: string | TFiller | null; + + declare paintFirst: 'fill' | 'stroke'; declare fill: string | TFiller | null; declare fillRule: CanvasFillRule; - declare globalCompositeOperation: GlobalCompositeOperation; - declare backgroundColor: string; - declare selectionBackgroundColor: string; + declare stroke: string | TFiller | null; declare strokeDashArray: number[] | null; declare strokeDashOffset: number; declare strokeLineCap: CanvasLineCap; declare strokeLineJoin: CanvasLineJoin; declare strokeMiterLimit: number; + + declare globalCompositeOperation: GlobalCompositeOperation; + declare backgroundColor: string; + declare shadow: Shadow | null; - declare borderOpacityWhenMoving: number; - declare borderScaleFactor: number; - declare minScaleLimit: number; - declare selectable: boolean; - declare evented: boolean; + declare visible: boolean; - declare hasControls: boolean; - declare hasBorders: boolean; - declare perPixelTargetFind: boolean; + declare includeDefaultValues: boolean; declare excludeFromExport: boolean; - 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 objectCaching: boolean; - declare paintFirst: 'fill' | 'stroke'; - declare activeOn: 'down' | 'up'; declare clipPath?: FabricObject; declare inverted: boolean; @@ -280,7 +262,7 @@ export class FabricObject * Constructor * @param {Object} [options] Options object */ - constructor(options?: Partial) { + constructor(options?: Props) { super(); Object.assign( this, @@ -490,7 +472,10 @@ export class FabricObject * @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[]): Record { + toObject< + T extends Omit, keyof SProps>, + K extends keyof T = never + >(propertiesToInclude?: K[]): { [R in K]: T[K] } & SProps { const NUM_FRACTION_DIGITS = config.NUM_FRACTION_DIGITS, clipPathData = this.clipPath && !this.clipPath.excludeFromExport @@ -501,7 +486,7 @@ export class FabricObject } : null, object = { - ...pick(this, propertiesToInclude as (keyof this)[]), + ...pick(this, propertiesToInclude), type: this.type, version: VERSION, originX: this.originX, @@ -564,7 +549,7 @@ export class FabricObject * @private * @param {Object} object */ - _removeDefaultValues(object: Record) { + _removeDefaultValues(object: T): Partial { // getDefaults() ( get from static ownDefaults ) should win over prototype since anyway they get assigned to instance // ownDefault vs prototype is swappable only if you change all the fabric objects consistently. const defaults = (this.constructor as typeof FabricObject).getDefaults(); @@ -1522,13 +1507,13 @@ export class FabricObject * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal * @returns {Promise} */ - static _fromObject( + static _fromObject( object: Record, { extraParam, ...options }: { extraParam?: string; signal?: AbortSignal } = {} - ): Promise { + ): Promise { return enlivenObjectEnlivables(cloneDeep(object), options).then( (enlivedMap) => { const allOptions = { ...options, ...enlivedMap }; @@ -1542,7 +1527,7 @@ export class FabricObject return new this(allOptions); } } - ); + ) as Promise; } /** @@ -1552,8 +1537,8 @@ export class FabricObject * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal * @returns {Promise} */ - static fromObject( - object: ReturnType, + static fromObject>( + object: T, options?: { signal?: AbortSignal } ): Promise { return this._fromObject(object, options); diff --git a/src/shapes/Object/ObjectGeometry.ts b/src/shapes/Object/ObjectGeometry.ts index aeeaa402dbf..21329f79bfd 100644 --- a/src/shapes/Object/ObjectGeometry.ts +++ b/src/shapes/Object/ObjectGeometry.ts @@ -25,6 +25,7 @@ import type { Canvas } from '../../canvas/Canvas'; import type { StaticCanvas } from '../../canvas/StaticCanvas'; import { ObjectOrigin } from './ObjectOrigin'; import { ObjectEvents } from '../../EventTypeDefs'; +import { ControlProps } from './types/ControlProps'; type TLineDescriptor = { o: Point; @@ -45,9 +46,12 @@ type TMatrixCache = { type TACoords = TCornerPoint; -export class ObjectGeometry< - EventSpec extends ObjectEvents = ObjectEvents -> extends ObjectOrigin { +export class ObjectGeometry + extends ObjectOrigin + implements Pick +{ + declare padding: number; + /** * Describe object's corner position in canvas object absolute coordinates * properties are tl,tr,bl,br and describe the four main corner. diff --git a/src/shapes/Object/ObjectOrigin.ts b/src/shapes/Object/ObjectOrigin.ts index 00f9ba9daaf..a79405d8c22 100644 --- a/src/shapes/Object/ObjectOrigin.ts +++ b/src/shapes/Object/ObjectOrigin.ts @@ -6,11 +6,12 @@ import { sizeAfterTransform } from '../../util/misc/objectTransforms'; import { degreesToRadians } from '../../util/misc/radiansDegreesConversion'; import { CommonMethods } from '../../CommonMethods'; import { resolveOrigin } from '../../util/misc/resolveOrigin'; -import { ObjectBaseProps } from './ObjectProps'; +import { BaseProps } from './types/BaseProps'; +import { FillStrokeProps } from './types/FillStrokeProps'; export class ObjectOrigin extends CommonMethods - implements ObjectBaseProps + implements BaseProps, Pick { declare top: number; declare left: number; @@ -27,7 +28,6 @@ export class ObjectOrigin declare angle: TDegree; declare strokeWidth: number; declare strokeUniform: boolean; - declare padding: number; /** * Object containing this object. diff --git a/src/shapes/Object/ObjectProps.ts b/src/shapes/Object/ObjectProps.ts deleted file mode 100644 index 5622470067d..00000000000 --- a/src/shapes/Object/ObjectProps.ts +++ /dev/null @@ -1,550 +0,0 @@ -import { Shadow } from '../../Shadow'; -import { TDegree, TFiller, TOriginX, TOriginY } from '../../typedefs'; -import { FabricObject } from './Object'; - -export interface ObjectBaseProps { - /** - * Top position of an object. Note that by default it's relative to object top. You can change this by setting originY={top/center/bottom} - * @type Number - * @default 0 - */ - top: number; - - /** - * Left position of an object. Note that by default it's relative to object left. You can change this by setting originX={left/center/right} - * @type Number - * @default 0 - */ - left: number; - - /** - * Object width - * @type Number - * @default - */ - width: number; - - /** - * Object height - * @type Number - * @default - */ - height: number; - - /** - * When true, an object is rendered as flipped horizontally - * @type Boolean - * @default false - */ - flipX: boolean; - - /** - * When true, an object is rendered as flipped vertically - * @type Boolean - * @default false - */ - flipY: boolean; - - /** - * Object scale factor (horizontal) - * @type Number - * @default 1 - */ - scaleX: number; - - /** - * Object scale factor (vertical) - * @type Number - * @default 1 - */ - scaleY: number; - - /** - * Angle of skew on x axes of an object (in degrees) - * @type Number - * @default 0 - */ - skewX: number; - - /** - * Angle of skew on y axes of an object (in degrees) - * @type Number - * @default 0 - */ - skewY: number; - - /** - * Horizontal origin of transformation of an object (one of "left", "right", "center") - * See http://jsfiddle.net/1ow02gea/244/ on how originX/originY affect objects in groups - * @type String - * @default 'left' - */ - originX: TOriginX; - - /** - * Vertical origin of transformation of an object (one of "top", "bottom", "center") - * See http://jsfiddle.net/1ow02gea/244/ on how originX/originY affect objects in groups - * @type String - * @default 'top' - */ - originY: TOriginY; - - /** - * Angle of rotation of an object (in degrees) - * @type Number - * @default 0 - */ - angle: TDegree; - - /** - * Width of a stroke used to render this object - * @type Number - * @default 1 - */ - strokeWidth: number; - - /** - * When `false`, the stoke width will scale with the object. - * When `true`, the stroke will always match the exact pixel size entered for stroke width. - * this Property does not work on Text classes or drawing call that uses strokeText,fillText methods - * default to false - * @since 2.6.0 - * @type Boolean - * @default false - * @type Boolean - * @default false - */ - strokeUniform: boolean; - - /** - * Padding between object and its controlling borders (in pixels) - * @type Number - * @default 0 - */ - padding: number; -} - -export interface ObjectProps extends ObjectBaseProps { - /** - * Opacity of an object - * @type Number - * @default 1 - */ - opacity: number; - - /** - * Size of object's controlling corners (in pixels) - * @type Number - * @default 13 - */ - cornerSize: number; - - /** - * Size of object's controlling corners when touch interaction is detected - * @type Number - * @default 24 - */ - touchCornerSize: number; - - /** - * When true, object's controlling corners are rendered as transparent inside (i.e. stroke instead of fill) - * @type Boolean - * @default true - */ - transparentCorners: boolean; - - /** - * Default cursor value used when hovering over this object on canvas - * @type CSSStyleDeclaration['cursor'] | null - * @default null - */ - hoverCursor: CSSStyleDeclaration['cursor'] | null; - - /** - * Default cursor value used when moving this object on canvas - * @type CSSStyleDeclaration['cursor'] | null - * @default null - */ - moveCursor: CSSStyleDeclaration['cursor'] | null; - - /** - * Color of controlling borders of an object (when it's active) - * @type String - * @default rgb(178,204,255) - */ - borderColor: string; - - /** - * Array specifying dash pattern of an object's borders (hasBorder must be true) - * @since 1.6.2 - * @type Array | null - * default null; - */ - borderDashArray: number[] | null; - - /** - * Color of controlling corners of an object (when it's active) - * @type String - * @default rgb(178,204,255) - */ - cornerColor: string; - - /** - * Color of controlling corners of an object (when it's active and transparentCorners false) - * @since 1.6.2 - * @type String - * @default null - */ - cornerStrokeColor: string; - - /** - * Specify style of control, 'rect' or 'circle' - * This is deprecated. In the future there will be a standard control render - * And you can swap it with one of the alternative proposed with the control api - * @since 1.6.2 - * @type 'rect' | 'circle' - * @default rect - * @deprecated - */ - cornerStyle: 'rect' | 'circle'; - - /** - * Array specifying dash pattern of an object's control (hasBorder must be true) - * @since 1.6.2 - * @type Array | null - */ - cornerDashArray: number[] | null; - - /** - * When true, this object will use center point as the origin of transformation - * when being scaled via the controls. - * Backwards incompatibility note: This property replaces "centerTransform" (Boolean). - * @since 1.3.4 - * @type Boolean - * @default - */ - centeredScaling: false; - - /** - * When true, this object will use center point as the origin of transformation - * when being rotated via the controls. - * Backwards incompatibility note: This property replaces "centerTransform" (Boolean). - * @since 1.3.4 - * @type Boolean - * @default - */ - centeredRotation: true; - - /** - * When defined, an object is rendered via stroke and this property specifies its color - * takes css colors https://www.w3.org/TR/css-color-3/ - * @type String - * @default null - */ - stroke: string | TFiller | null; - - /** - * Color of object's fill - * takes css colors https://www.w3.org/TR/css-color-3/ - * @type String - * @default rgb(0,0,0) - */ - fill: string | TFiller | null; - - /** - * Fill rule used to fill an object - * accepted values are nonzero, evenodd - * Backwards incompatibility note: This property was used for setting globalCompositeOperation until v1.4.12 (use `globalCompositeOperation` instead) - * @type String - * @default nonzero - */ - fillRule: CanvasFillRule; - - /** - * Composite rule used for canvas globalCompositeOperation - * @type String - * @default - */ - globalCompositeOperation: GlobalCompositeOperation; - - /** - * Background color of an object. - * takes css colors https://www.w3.org/TR/css-color-3/ - * @type String - * @default - */ - backgroundColor: string; - - /** - * Selection Background color of an object. colored layer behind the object when it is active. - * does not mix good with globalCompositeOperation methods. - * @type String - * @deprecated - * @default - */ - selectionBackgroundColor: string; - - /** - * Array specifying dash pattern of an object's stroke (stroke must be defined) - * @type Array - * @default null; - */ - strokeDashArray: number[] | null; - - /** - * Line offset of an object's stroke - * @type Number - * @default 0 - */ - strokeDashOffset: number; - - /** - * Line endings style of an object's stroke (one of "butt", "round", "square") - * @type String - * @default butt - */ - strokeLineCap: CanvasLineCap; - - /** - * Corner style of an object's stroke (one of "bevel", "round", "miter") - * @type String - * @default - */ - strokeLineJoin: CanvasLineJoin; - - /** - * Maximum miter length (used for strokeLineJoin = "miter") of an object's stroke - * @type Number - * @default 4 - */ - strokeMiterLimit: number; - - /** - * Shadow object representing shadow of this shape - * @type Shadow - * @default null - */ - shadow: Shadow | null; - - /** - * Opacity of object's controlling borders when object is active and moving - * @type Number - * @default 0.4 - */ - borderOpacityWhenMoving: number; - - /** - * Scale factor of object's controlling borders - * bigger number will make a thicker border - * border is 1, so this is basically a border thickness - * since there is no way to change the border itself. - * @type Number - * @default 1 - */ - borderScaleFactor: number; - - /** - * Minimum allowed scale value of an object - * @type Number - * @default 0 - */ - minScaleLimit: number; - - /** - * When set to `false`, an object can not be selected for modification (using either point-click-based or group-based selection). - * But events still fire on it. - * @type Boolean - * @default - */ - selectable: boolean; - - /** - * When set to `false`, an object can not be a target of events. All events propagate through it. Introduced in v1.3.4 - * @type Boolean - * @default - */ - evented: boolean; - - /** - * When set to `false`, an object is not rendered on canvas - * @type Boolean - * @default - */ - visible: boolean; - - /** - * When set to `false`, object's controls are not displayed and can not be used to manipulate object - * @type Boolean - * @default - */ - hasControls: boolean; - - /** - * When set to `false`, object's controlling borders are not rendered - * @type Boolean - * @default - */ - hasBorders: boolean; - - /** - * When set to `true`, objects are "found" on canvas on per-pixel basis rather than according to bounding box - * @type Boolean - * @default - */ - perPixelTargetFind: boolean; - - /** - * When `false`, default object's values are not included in its serialization - * @type Boolean - * @default - */ - includeDefaultValues: boolean; - - /** - * When `true`, object is not exported in OBJECT/JSON - * @since 1.6.3 - * @type Boolean - * @default - */ - excludeFromExport: boolean; - - /** - * When `true`, object horizontal movement is locked - * @type Boolean - * @default - */ - lockMovementX: boolean; - - /** - * When `true`, object vertical movement is locked - * @type Boolean - * @default - */ - lockMovementY: boolean; - - /** - * When `true`, object rotation is locked - * @type Boolean - * @default - */ - lockRotation: boolean; - - /** - * When `true`, object horizontal scaling is locked - * @type Boolean - * @default - */ - lockScalingX: boolean; - - /** - * When `true`, object vertical scaling is locked - * @type Boolean - * @default - */ - lockScalingY: boolean; - - /** - * When `true`, object horizontal skewing is locked - * @type Boolean - * @default - */ - lockSkewingX: boolean; - - /** - * When `true`, object vertical skewing is locked - * @type Boolean - * @default - */ - lockSkewingY: boolean; - - /** - * When `true`, object cannot be flipped by scaling into negative values - * @type Boolean - * @default - */ - lockScalingFlip: boolean; - - /** - * When `true`, object is cached on an additional canvas. - * When `false`, object is not cached unless necessary ( clipPath ) - * default to true - * @since 1.7.0 - * @type Boolean - * @default true - */ - objectCaching: boolean; - - /** - * Determines if the fill or the stroke is drawn first (one of "fill" or "stroke") - * @type String - * @default - */ - paintFirst: 'fill' | 'stroke'; - - /** - * When 'down', object is set to active on mousedown/touchstart - * When 'up', object is set to active on mouseup/touchend - * Experimental. Let's see if this breaks anything before supporting officially - * @private - * since 4.4.0 - * @type String - * @default 'down' - */ - activeOn: 'down' | 'up'; - - /** - * a fabricObject that, without stroke define a clipping area with their shape. filled in black - * the clipPath object gets used when the object has rendered, and the context is placed in the center - * of the object cacheCanvas. - * If you want 0,0 of a clipPath to align with an object center, use clipPath.originX/Y to 'center' - * @type FabricObject - */ - clipPath?: FabricObject; - - /** - * Meaningful ONLY when the object is used as clipPath. - * if true, the clipPath will make the object clip to the outside of the clipPath - * since 2.4.0 - * @type boolean - * @default false - */ - inverted: boolean; - - /** - * Meaningful ONLY when the object is used as clipPath. - * if true, the clipPath will have its top and left relative to canvas, and will - * not be influenced by the object transform. This will make the clipPath relative - * to the canvas, but clipping just a particular object. - * WARNING this is beta, this feature may change or be renamed. - * since 2.4.0 - * @type boolean - * @default false - */ - absolutePositioned: boolean; -} - -export interface FabricObjectProps extends ObjectProps { - /** - * When `true`, cache does not get updated during scaling. The picture will get blocky if scaled - * too much and will be redrawn with correct details at the end of scaling. - * this setting is performance and application dependant. - * default to true - * since 1.7.0 - * @type Boolean - * @default true - */ - noScaleCache: boolean; - - /** - * The angle that an object will lock to while rotating. - * @type [TDegree] - */ - snapAngle?: TDegree; - - /** - * The angle difference from the current snapped angle in which snapping should occur. - * When undefined, the snapThreshold will default to the snapAngle. - * @type [TDegree] - */ - snapThreshold?: TDegree; -} diff --git a/src/shapes/Object/types/BaseProps.ts b/src/shapes/Object/types/BaseProps.ts new file mode 100644 index 00000000000..016a192f0c6 --- /dev/null +++ b/src/shapes/Object/types/BaseProps.ts @@ -0,0 +1,96 @@ +import { TDegree, TOriginX, TOriginY } from '../../../typedefs'; + +export interface BaseProps { + /** + * Top position of an object. Note that by default it's relative to object top. You can change this by setting originY={top/center/bottom} + * @type Number + * @default 0 + */ + top: number; + + /** + * Left position of an object. Note that by default it's relative to object left. You can change this by setting originX={left/center/right} + * @type Number + * @default 0 + */ + left: number; + + /** + * Object width + * @type Number + * @default + */ + width: number; + + /** + * Object height + * @type Number + * @default + */ + height: number; + + /** + * When true, an object is rendered as flipped horizontally + * @type Boolean + * @default false + */ + flipX: boolean; + + /** + * When true, an object is rendered as flipped vertically + * @type Boolean + * @default false + */ + flipY: boolean; + + /** + * Object scale factor (horizontal) + * @type Number + * @default 1 + */ + scaleX: number; + + /** + * Object scale factor (vertical) + * @type Number + * @default 1 + */ + scaleY: number; + + /** + * Angle of skew on x axes of an object (in degrees) + * @type Number + * @default 0 + */ + skewX: number; + + /** + * Angle of skew on y axes of an object (in degrees) + * @type Number + * @default 0 + */ + skewY: number; + + /** + * Horizontal origin of transformation of an object (one of "left", "right", "center") + * See http://jsfiddle.net/1ow02gea/244/ on how originX/originY affect objects in groups + * @type String + * @default 'left' + */ + originX: TOriginX; + + /** + * Vertical origin of transformation of an object (one of "top", "bottom", "center") + * See http://jsfiddle.net/1ow02gea/244/ on how originX/originY affect objects in groups + * @type String + * @default 'top' + */ + originY: TOriginY; + + /** + * Angle of rotation of an object (in degrees) + * @type Number + * @default 0 + */ + angle: TDegree; +} diff --git a/src/shapes/Object/types/BorderProps.ts b/src/shapes/Object/types/BorderProps.ts new file mode 100644 index 00000000000..02034448ee3 --- /dev/null +++ b/src/shapes/Object/types/BorderProps.ts @@ -0,0 +1,40 @@ +export interface BorderProps { + /** + * Color of controlling borders of an object (when it's active) + * @type String + * @default rgb(178,204,255) + */ + borderColor: string; + + /** + * Array specifying dash pattern of an object's borders (hasBorder must be true) + * @since 1.6.2 + * @type Array | null + * default null; + */ + borderDashArray: number[] | null; + + /** + * When set to `false`, object's controlling borders are not rendered + * @type Boolean + * @default + */ + hasBorders: boolean; + + /** + * Opacity of object's controlling borders when object is active and moving + * @type Number + * @default 0.4 + */ + borderOpacityWhenMoving: number; + + /** + * Scale factor of object's controlling borders + * bigger number will make a thicker border + * border is 1, so this is basically a border thickness + * since there is no way to change the border itself. + * @type Number + * @default 1 + */ + borderScaleFactor: number; +} diff --git a/src/shapes/Object/types/ControlProps.ts b/src/shapes/Object/types/ControlProps.ts new file mode 100644 index 00000000000..9088447a089 --- /dev/null +++ b/src/shapes/Object/types/ControlProps.ts @@ -0,0 +1,69 @@ +export interface ControlProps { + /** + * Size of object's controlling corners (in pixels) + * @type Number + * @default 13 + */ + cornerSize: number; + + /** + * Size of object's controlling corners when touch interaction is detected + * @type Number + * @default 24 + */ + touchCornerSize: number; + + /** + * When true, object's controlling corners are rendered as transparent inside (i.e. stroke instead of fill) + * @type Boolean + * @default true + */ + transparentCorners: boolean; + + /** + * Color of controlling corners of an object (when it's active) + * @type String + * @default rgb(178,204,255) + */ + cornerColor: string; + + /** + * Color of controlling corners of an object (when it's active and transparentCorners false) + * @since 1.6.2 + * @type String + * @default null + */ + cornerStrokeColor: string; + + /** + * Specify style of control, 'rect' or 'circle' + * This is deprecated. In the future there will be a standard control render + * And you can swap it with one of the alternative proposed with the control api + * @since 1.6.2 + * @type 'rect' | 'circle' + * @default rect + * @deprecated + */ + cornerStyle: 'rect' | 'circle'; + + /** + * Array specifying dash pattern of an object's control (hasBorder must be true) + * @since 1.6.2 + * @type Array | null + */ + cornerDashArray: number[] | null; + + /** + * Padding between object and its controlling borders (in pixels) + * @type Number + * @default 0 + */ + padding: number; + + /** + * When set to `false`, object's controls are not displayed and can not be used to manipulate object + * @type Boolean + * @default + */ + hasControls: boolean; +} diff --git a/src/shapes/Object/types/FabricObjectProps.ts b/src/shapes/Object/types/FabricObjectProps.ts new file mode 100644 index 00000000000..3edf91f5af3 --- /dev/null +++ b/src/shapes/Object/types/FabricObjectProps.ts @@ -0,0 +1,111 @@ +import { TDegree } from '../../../typedefs'; +import { BorderProps } from './BorderProps'; +import { ControlProps } from './ControlProps'; +import { LockInteractionProps } from './LockInteractionProps'; +import { ObjectProps } from './ObjectProps'; + +export interface FabricObjectProps + extends ObjectProps, + ControlProps, + BorderProps, + LockInteractionProps { + /** + * When `true`, cache does not get updated during scaling. The picture will get blocky if scaled + * too much and will be redrawn with correct details at the end of scaling. + * this setting is performance and application dependant. + * default to true + * since 1.7.0 + * @type Boolean + * @default true + */ + noScaleCache?: boolean; + + /** + * When true, this object will use center point as the origin of transformation + * when being scaled via the controls. + * Backwards incompatibility note: This property replaces "centerTransform" (Boolean). + * @since 1.3.4 + * @type Boolean + * @default + */ + centeredScaling: false; + + /** + * When true, this object will use center point as the origin of transformation + * when being rotated via the controls. + * Backwards incompatibility note: This property replaces "centerTransform" (Boolean). + * @since 1.3.4 + * @type Boolean + * @default + */ + centeredRotation: true; + + /** + * The angle that an object will lock to while rotating. + * @type [TDegree] + */ + snapAngle?: TDegree; + + /** + * The angle difference from the current snapped angle in which snapping should occur. + * When undefined, the snapThreshold will default to the snapAngle. + * @type [TDegree] + */ + snapThreshold?: TDegree; + + /** + * Default cursor value used when hovering over this object on canvas + * @type CSSStyleDeclaration['cursor'] | null + * @default null + */ + hoverCursor: CSSStyleDeclaration['cursor'] | null; + + /** + * Default cursor value used when moving this object on canvas + * @type CSSStyleDeclaration['cursor'] | null + * @default null + */ + moveCursor: CSSStyleDeclaration['cursor'] | null; + + /** + * Selection Background color of an object. colored layer behind the object when it is active. + * does not mix good with globalCompositeOperation methods. + * @type String + * @deprecated + * @default + */ + selectionBackgroundColor: string; + + /** + * When set to `true`, objects are "found" on canvas on per-pixel basis rather than according to bounding box + * @type Boolean + * @default + */ + perPixelTargetFind: boolean; + + /** + * When set to `false`, an object can not be selected for modification (using either point-click-based or group-based selection). + * But events still fire on it. + * @type Boolean + * @default + */ + selectable: boolean; + + /** + * When set to `false`, an object can not be a target of events. All events propagate through it. Introduced in v1.3.4 + * @type Boolean + * @default + */ + evented: boolean; + + /** + * When 'down', object is set to active on mousedown/touchstart + * When 'up', object is set to active on mouseup/touchend + * Experimental. Let's see if this breaks anything before supporting officially + * @private + * since 4.4.0 + * @type String + * @default 'down' + */ + activeOn: 'down' | 'up'; +} diff --git a/src/shapes/Object/types/FillStrokeProps.ts b/src/shapes/Object/types/FillStrokeProps.ts new file mode 100644 index 00000000000..4f6b0c1b157 --- /dev/null +++ b/src/shapes/Object/types/FillStrokeProps.ts @@ -0,0 +1,90 @@ +import { TFiller } from '../../../typedefs'; + +export interface FillStrokeProps { + /** + * Determines if the fill or the stroke is drawn first (one of "fill" or "stroke") + * @type String + * @default + */ + paintFirst: 'fill' | 'stroke'; + + /** + * Color of object's fill + * takes css colors https://www.w3.org/TR/css-color-3/ + * @type String + * @default rgb(0,0,0) + */ + fill: ReturnType | string | null; + + /** + * Fill rule used to fill an object + * accepted values are nonzero, evenodd + * Backwards incompatibility note: This property was used for setting globalCompositeOperation until v1.4.12 (use `globalCompositeOperation` instead) + * @type String + * @default nonzero + */ + fillRule: CanvasFillRule; + + /** + * When defined, an object is rendered via stroke and this property specifies its color + * takes css colors https://www.w3.org/TR/css-color-3/ + * @type String + * @default null + */ + stroke: ReturnType | string | null; + + /** + * Width of a stroke used to render this object + * @type Number + * @default 1 + */ + strokeWidth: number; + + /** + * Array specifying dash pattern of an object's stroke (stroke must be defined) + * @type Array + * @default null; + */ + strokeDashArray: number[] | null; + + /** + * Line offset of an object's stroke + * @type Number + * @default 0 + */ + strokeDashOffset: number; + + /** + * Line endings style of an object's stroke (one of "butt", "round", "square") + * @type String + * @default butt + */ + strokeLineCap: CanvasLineCap; + + /** + * Corner style of an object's stroke (one of "bevel", "round", "miter") + * @type String + * @default + */ + strokeLineJoin: CanvasLineJoin; + + /** + * Maximum miter length (used for strokeLineJoin = "miter") of an object's stroke + * @type Number + * @default 4 + */ + strokeMiterLimit: number; + + /** + * When `false`, the stoke width will scale with the object. + * When `true`, the stroke will always match the exact pixel size entered for stroke width. + * this Property does not work on Text classes or drawing call that uses strokeText,fillText methods + * default to false + * @since 2.6.0 + * @type Boolean + * @default false + * @type Boolean + * @default false + */ + strokeUniform: boolean; +} diff --git a/src/shapes/Object/types/LockInteractionProps.ts b/src/shapes/Object/types/LockInteractionProps.ts new file mode 100644 index 00000000000..5337dbc85f9 --- /dev/null +++ b/src/shapes/Object/types/LockInteractionProps.ts @@ -0,0 +1,57 @@ +export interface LockInteractionProps { + /** + * When `true`, object horizontal movement is locked + * @type Boolean + * @default + */ + lockMovementX: boolean; + + /** + * When `true`, object vertical movement is locked + * @type Boolean + * @default + */ + lockMovementY: boolean; + + /** + * When `true`, object rotation is locked + * @type Boolean + * @default + */ + lockRotation: boolean; + + /** + * When `true`, object horizontal scaling is locked + * @type Boolean + * @default + */ + lockScalingX: boolean; + + /** + * When `true`, object vertical scaling is locked + * @type Boolean + * @default + */ + lockScalingY: boolean; + + /** + * When `true`, object horizontal skewing is locked + * @type Boolean + * @default + */ + lockSkewingX: boolean; + + /** + * When `true`, object vertical skewing is locked + * @type Boolean + * @default + */ + lockSkewingY: boolean; + + /** + * When `true`, object cannot be flipped by scaling into negative values + * @type Boolean + * @default + */ + lockScalingFlip: boolean; +} diff --git a/src/shapes/Object/types/ObjectProps.ts b/src/shapes/Object/types/ObjectProps.ts new file mode 100644 index 00000000000..4011602d3b3 --- /dev/null +++ b/src/shapes/Object/types/ObjectProps.ts @@ -0,0 +1,43 @@ +import type { Shadow } from '../../../Shadow'; +import { TFiller } from '../../../typedefs'; +import type { FabricObject } from '../Object'; +import { ClipPathProps, SerializedObjectProps } from './SerializedObjectProps'; + +export interface ObjectProps extends SerializedObjectProps, ClipPathProps { + clipPath?: FabricObject; + fill: TFiller | string | null; + stroke: TFiller | string | null; + shadow: Shadow | null; + + /** + * Minimum allowed scale value of an object + * @type Number + * @default 0 + */ + minScaleLimit: number; + + /** + * When `true`, object is cached on an additional canvas. + * When `false`, object is not cached unless necessary ( clipPath ) + * default to true + * @since 1.7.0 + * @type Boolean + * @default true + */ + objectCaching: boolean; + + /** + * When `false`, default object's values are not included in its serialization + * @type Boolean + * @default + */ + includeDefaultValues: boolean; + + /** + * When `true`, object is not exported in OBJECT/JSON + * @since 1.6.3 + * @type Boolean + * @default + */ + excludeFromExport: boolean; +} diff --git a/src/shapes/Object/types/SerializedObjectProps.ts b/src/shapes/Object/types/SerializedObjectProps.ts new file mode 100644 index 00000000000..8da5507fdf3 --- /dev/null +++ b/src/shapes/Object/types/SerializedObjectProps.ts @@ -0,0 +1,73 @@ +import { Shadow } from '../../../Shadow'; +import { BaseProps } from './BaseProps'; +import { FillStrokeProps } from './FillStrokeProps'; + +export interface SerializedObjectProps extends BaseProps, FillStrokeProps { + /** + * Opacity of an object + * @type Number + * @default 1 + */ + opacity: number; + + /** + * Composite rule used for canvas globalCompositeOperation + * @type String + * @default + */ + globalCompositeOperation: GlobalCompositeOperation; + + /** + * Background color of an object. + * takes css colors https://www.w3.org/TR/css-color-3/ + * @type String + * @default + */ + backgroundColor: string; + + /** + * Shadow object representing shadow of this shape + * @type Shadow + * @default null + */ + shadow: ReturnType | null; + + /** + * When set to `false`, an object is not rendered on canvas + * @type Boolean + * @default + */ + visible: boolean; + + /** + * a fabricObject that, without stroke define a clipping area with their shape. filled in black + * the clipPath object gets used when the object has rendered, and the context is placed in the center + * of the object cacheCanvas. + * If you want 0,0 of a clipPath to align with an object center, use clipPath.originX/Y to 'center' + * @type FabricObject + */ + clipPath?: Partial & ClipPathProps; +} + +export interface ClipPathProps { + /** + * Meaningful ONLY when the object is used as clipPath. + * if true, the clipPath will make the object clip to the outside of the clipPath + * since 2.4.0 + * @type boolean + * @default false + */ + inverted: boolean; + + /** + * Meaningful ONLY when the object is used as clipPath. + * if true, the clipPath will have its top and left relative to canvas, and will + * not be influenced by the object transform. This will make the clipPath relative + * to the canvas, but clipping just a particular object. + * WARNING this is beta, this feature may change or be renamed. + * since 2.4.0 + * @type boolean + * @default false + */ + absolutePositioned: boolean; +} diff --git a/src/shapes/Object/types/index.ts b/src/shapes/Object/types/index.ts new file mode 100644 index 00000000000..7565e9ba11c --- /dev/null +++ b/src/shapes/Object/types/index.ts @@ -0,0 +1,8 @@ +import { FabricObjectProps } from './FabricObjectProps'; + +export { SerializedObjectProps } from './SerializedObjectProps'; +export { FabricObjectProps }; + +export type TProps = Partial & Record; + +export type TFabricObjectProps = TProps; diff --git a/src/typedefs.ts b/src/typedefs.ts index c59f48fd119..68cd37072c0 100644 --- a/src/typedefs.ts +++ b/src/typedefs.ts @@ -3,7 +3,6 @@ import { BaseFabricObject } from './EventTypeDefs'; import type { Gradient } from './gradient/Gradient'; import type { Pattern } from './Pattern'; import type { Point } from './Point'; -import type { FabricObject } from './shapes/Object/FabricObject'; interface NominalTag { nominalTag?: T;