diff --git a/package-lock.json b/package-lock.json
index 66d939b873d..3a04e96b9f8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4623,6 +4623,12 @@
"is-typedarray": "^1.0.0"
}
},
+ "typescript": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz",
+ "integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==",
+ "dev": true
+ },
"uglify-js": {
"version": "3.3.28",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.28.tgz",
diff --git a/package.json b/package.json
index 4cab830c341..60f416a9c99 100644
--- a/package.json
+++ b/package.json
@@ -58,7 +58,8 @@
"lint_tests": "eslint test/unit --config .eslintrc_tests && eslint test/visual --config .eslintrc_tests",
"all": "npm run build && npm run test -- --all && npm run lint && npm run lint_tests && npm run export",
"testem": "testem .",
- "testem:ci": "testem ci"
+ "testem:ci": "testem ci",
+ "tsc": "tsc"
},
"optionalDependencies": {
"canvas": "^2.8.0",
@@ -82,6 +83,7 @@
"pixelmatch": "^4.0.2",
"qunit": "^2.17.2",
"testem": "^3.2.0",
+ "typescript": "^4.5.4",
"uglify-js": "^3.3.28"
},
"engines": {
diff --git a/src/shapes/Rect.ts b/src/shapes/Rect.ts
new file mode 100644
index 00000000000..3c8846de0e5
--- /dev/null
+++ b/src/shapes/Rect.ts
@@ -0,0 +1,149 @@
+import { Object } from './object.class';
+
+export class Rect extends Object {
+ readonly type = 'rect';
+ rx: number = 0;
+ ry: number = 0;
+
+
+ /**
+ * List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged})
+ * as well as for history (undo/redo) purposes
+ * @type Array
+ */
+ stateProperties = Object.stateProperties.concat('rx', 'ry');
+
+ cacheProperties = Object.cacheProperties.concat('rx', 'ry');
+
+ constructor(options) {
+ super(options);
+ this._initRxRy();
+ }
+
+ /**
+ * Initializes rx/ry attributes
+ * @private
+ */
+ private _initRxRy() {
+ if (this.rx && !this.ry) {
+ this.ry = this.rx;
+ }
+ else if (this.ry && !this.rx) {
+ this.rx = this.ry;
+ }
+ }
+
+ /**
+ * @private
+ * @param {CanvasRenderingContext2D} ctx Context to render on
+ */
+ protected _render(ctx: CanvasRenderingContext2D) {
+
+ // 1x1 case (used in spray brush) optimization was removed because
+ // with caching and higher zoom level this makes more damage than help
+
+ var rx = this.rx ? Math.min(this.rx, this.width / 2) : 0,
+ ry = this.ry ? Math.min(this.ry, this.height / 2) : 0,
+ w = this.width,
+ h = this.height,
+ x = -this.width / 2,
+ y = -this.height / 2,
+ isRounded = rx !== 0 || ry !== 0,
+ /* "magic number" for bezier approximations of arcs (http://itc.ktu.lt/itc354/Riskus354.pdf) */
+ k = 1 - 0.5522847498;
+ ctx.beginPath();
+
+ ctx.moveTo(x + rx, y);
+
+ ctx.lineTo(x + w - rx, y);
+ isRounded && ctx.bezierCurveTo(x + w - k * rx, y, x + w, y + k * ry, x + w, y + ry);
+
+ ctx.lineTo(x + w, y + h - ry);
+ isRounded && ctx.bezierCurveTo(x + w, y + h - k * ry, x + w - k * rx, y + h, x + w - rx, y + h);
+
+ ctx.lineTo(x + rx, y + h);
+ isRounded && ctx.bezierCurveTo(x + k * rx, y + h, x, y + h - k * ry, x, y + h - ry);
+
+ ctx.lineTo(x, y + ry);
+ isRounded && ctx.bezierCurveTo(x, y + k * ry, x + k * rx, y, x + rx, y);
+
+ ctx.closePath();
+
+ this._renderPaintInOrder(ctx);
+ }
+
+ /**
+ * Returns object representation of an instance
+ * @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
+ * @return {Object} object representation of an instance
+ */
+ toObject(propertiesToInclude: (keyof Rect)[]) {
+ return super.toObject(['rx', 'ry'].concat(propertiesToInclude));
+ }
+
+ /* _TO_SVG_START_ */
+ /**
+ * Returns svg representation of an instance
+ * @return {Array} an array of strings with the specific svg representation
+ * of the instance
+ */
+ protected _toSVG() {
+ var x = -this.width / 2, y = -this.height / 2;
+ return [
+ '\n'
+ ];
+ }
+ /* _TO_SVG_END_ */
+
+ static ATTRIBUTE_NAMES = fabric.SHARED_ATTRIBUTES.concat('x y rx ry width height'.split(' '));
+
+ /**
+ * Returns {@link fabric.Rect} instance from an SVG element
+ * @static
+ * @memberOf fabric.Rect
+ * @param {SVGElement} element Element to parse
+ * @param {Function} callback callback function invoked after parsing
+ * @param {Object} [options] Options object
+ */
+ static fromElement void, T extends unknown | CB>(element: SVGElement, callback: T, options?) {
+ if (!element) {
+ return callback(null);
+ }
+ options = options || {};
+
+ var parsedAttributes = fabric.parseAttributes(element, fabric.Rect.ATTRIBUTE_NAMES);
+ parsedAttributes.left = parsedAttributes.left || 0;
+ parsedAttributes.top = parsedAttributes.top || 0;
+ parsedAttributes.height = parsedAttributes.height || 0;
+ parsedAttributes.width = parsedAttributes.width || 0;
+ var rect = new fabric.Rect(fabric.util.object.extend((options ? fabric.util.object.clone(options) : {}), parsedAttributes));
+ rect.visible = rect.visible && rect.width > 0 && rect.height > 0;
+ callback(rect);
+ }
+
+ /**
+ * Returns {@link fabric.Rect} instance from an object representation
+ * @static
+ * @memberOf fabric.Rect
+ * @param {Object} object Object to create an instance from
+ * @param {Function} [callback] Callback to invoke when an fabric.Rect instance is created
+ */
+ static fromObject void, T extends unknown | CB>(object, callback?: T):
+ T extends (instance: Rect) => void ? void : Promise {
+ if (!callback) {
+ //@ts-ignore
+ return new Promise((resolve, reject) => {
+ try {
+ return Object._fromObject('Rect', object, resolve);
+ } catch (error) {
+ reject(error);
+ }
+ });
+ }
+ return Object._fromObject('Rect', object, callback);
+ }
+}
\ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 00000000000..627c363949d
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,102 @@
+{
+ "compilerOptions": {
+ /* Visit https://aka.ms/tsconfig.json to read more about this file */
+
+ /* Projects */
+ // "incremental": true, /* Enable incremental compilation */
+ // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
+ // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
+ // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
+ // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
+ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
+
+ /* Language and Environment */
+ "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
+ // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
+ // "jsx": "preserve", /* Specify what JSX code is generated. */
+ // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
+ // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
+ // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
+ // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
+ // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
+ // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
+ // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
+ // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
+
+ /* Modules */
+ "module": "ESNext", /* Specify what module code is generated. */
+ // "rootDir": "./", /* Specify the root folder within your source files. */
+ // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
+ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
+ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
+ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
+ // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
+ // "types": [], /* Specify type package names to be included without being referenced in a source file. */
+ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
+ // "resolveJsonModule": true, /* Enable importing .json files */
+ // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */
+
+ /* JavaScript Support */
+ // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
+ // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
+ // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
+
+ /* Emit */
+ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
+ // "declarationMap": true, /* Create sourcemaps for d.ts files. */
+ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
+ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */
+ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
+ // "outDir": "./", /* Specify an output folder for all emitted files. */
+ // "removeComments": true, /* Disable emitting comments. */
+ // "noEmit": true, /* Disable emitting files from a compilation. */
+ // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
+ // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
+ // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
+ // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
+ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
+ // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
+ // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
+ // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
+ // "newLine": "crlf", /* Set the newline character for emitting files. */
+ // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
+ // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
+ // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
+ // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
+ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */
+ // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
+
+ /* Interop Constraints */
+ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
+ // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
+ "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */
+ // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
+ "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
+
+ /* Type Checking */
+ "strict": true, /* Enable all strict type-checking options. */
+ // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
+ // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
+ // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
+ // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
+ // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
+ // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
+ // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
+ // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
+ // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
+ // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
+ // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
+ // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
+ // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
+ // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
+ // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
+ // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
+ // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
+ // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
+
+ /* Completeness */
+ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
+ "skipLibCheck": true /* Skip type checking all .d.ts files. */
+ },
+ "include": ["src"],
+}