Skip to content

Commit

Permalink
Merge branch 'psychedelicious-psyche/typing-2'
Browse files Browse the repository at this point in the history
  • Loading branch information
lavrton committed Dec 6, 2024
2 parents be24e9b + 5ca5fd0 commit cbbc992
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 65 deletions.
19 changes: 10 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "konva",
"version": "9.3.16",
"description": "HTML5 2d canvas library.",
"author": "Anton Lavrenov",
"files": [
"README.md",
Expand Down Expand Up @@ -59,13 +60,13 @@
}
],
"devDependencies": {
"@parcel/transformer-image": "2.10.1",
"@size-limit/preset-big-lib": "^11.0.1",
"@types/mocha": "^10.0.6",
"@parcel/transformer-image": "2.13.2",
"@size-limit/preset-big-lib": "^11.1.6",
"@types/mocha": "^10.0.10",
"canvas": "^2.11.2",
"chai": "4.3.10",
"chai": "5.1.2",
"filehound": "^1.17.6",
"gulp": "^4.0.2",
"gulp": "^5.0.0",
"gulp-concat": "^2.6.1",
"gulp-connect": "^5.7.0",
"gulp-exec": "^5.0.0",
Expand All @@ -78,14 +79,14 @@
"gulp-util": "^3.0.8",
"mocha": "10.2.0",
"mocha-headless-chrome": "^4.0.0",
"parcel": "2.10.1",
"parcel": "2.13.2",
"process": "^0.11.10",
"rollup": "^4.9.1",
"rollup": "^4.28.1",
"rollup-plugin-typescript2": "^0.36.0",
"size-limit": "^11.0.1",
"size-limit": "^11.1.6",
"ts-mocha": "^10.0.0",
"ts-node": "^10.9.2",
"typescript": "^5.3.3"
"typescript": "^5.7.2"
},
"keywords": [
"canvas",
Expand Down
125 changes: 103 additions & 22 deletions src/Factory.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,76 @@
import { Node } from './Node';
import { GetSet } from './types';
import { Util } from './Util';
import { getComponentValidator } from './Validators';

const GET = 'get',
SET = 'set';
const GET = 'get';
const SET = 'set';

/**
* Enforces that a type is a string.
*/
type EnforceString<T> = T extends string ? T : never;

/**
* Represents a class.
*/
type Constructor = abstract new (...args: any) => any;

/**
* An attribute of an instance of the provided class. Attributes names be strings.
*/
type Attr<T extends Constructor> = EnforceString<keyof InstanceType<T>>;

/**
* A function that is called after a setter is called.
*/
type AfterFunc<T extends Constructor> = (this: InstanceType<T>) => void;

/**
* Extracts the type of a GetSet.
*/
type ExtractGetSet<T> = T extends GetSet<infer U, any> ? U : never;

/**
* Extracts the type of a GetSet class attribute.
*/
type Value<T extends Constructor, U extends Attr<T>> = ExtractGetSet<
InstanceType<T>[U]
>;

/**
* A function that validates a value.
*/
type ValidatorFunc<T> = (val: ExtractGetSet<T>, attr: string) => T;

/**
* Extracts the "components" (keys) of a GetSet value. The value must be an object.
*/
type ExtractComponents<T extends Constructor, U extends Attr<T>> = Value<
T,
U
> extends Record<string, any>
? EnforceString<keyof Value<T, U>>[]
: never;

export const Factory = {
addGetterSetter(constructor, attr, def?, validator?, after?) {
addGetterSetter<T extends Constructor, U extends Attr<T>>(
constructor: T,
attr: U,
def?: Value<T, U>,
validator?: ValidatorFunc<Value<T, U>>,
after?: AfterFunc<T>
): void {
Factory.addGetter(constructor, attr, def);
Factory.addSetter(constructor, attr, validator, after);
Factory.addOverloadedGetterSetter(constructor, attr);
},
addGetter(constructor, attr, def?) {
const method = GET + Util._capitalize(attr);
addGetter<T extends Constructor, U extends Attr<T>>(
constructor: T,
attr: U,
def?: Value<T, U>
) {
var method = GET + Util._capitalize(attr);

constructor.prototype[method] =
constructor.prototype[method] ||
Expand All @@ -22,15 +80,26 @@ export const Factory = {
};
},

addSetter(constructor, attr, validator?, after?) {
const method = SET + Util._capitalize(attr);
addSetter<T extends Constructor, U extends Attr<T>>(
constructor: T,
attr: U,
validator?: ValidatorFunc<Value<T, U>>,
after?: AfterFunc<T>
) {
var method = SET + Util._capitalize(attr);

if (!constructor.prototype[method]) {
Factory.overWriteSetter(constructor, attr, validator, after);
}
},
overWriteSetter(constructor, attr, validator?, after?) {
const method = SET + Util._capitalize(attr);

overWriteSetter<T extends Constructor, U extends Attr<T>>(
constructor: T,
attr: U,
validator?: ValidatorFunc<Value<T, U>>,
after?: AfterFunc<T>
) {
var method = SET + Util._capitalize(attr);
constructor.prototype[method] = function (val) {
if (validator && val !== undefined && val !== null) {
val = validator.call(this, val, attr);
Expand All @@ -45,12 +114,13 @@ export const Factory = {
return this;
};
},
addComponentsGetterSetter(
constructor,
attr: string,
components: Array<string>,
validator?: Function,
after?: Function

addComponentsGetterSetter<T extends Constructor, U extends Attr<T>>(
constructor: T,
attr: U,
components: ExtractComponents<T, U>,
validator?: ValidatorFunc<Value<T, U>>,
after?: AfterFunc<T>
) {
const len = components.length,
capitalize = Util._capitalize,
Expand All @@ -59,7 +129,7 @@ export const Factory = {

// getter
constructor.prototype[getter] = function () {
const ret = {};
const ret: Record<string, any> = {};

for (let n = 0; n < len; n++) {
const component = components[n];
Expand All @@ -76,7 +146,7 @@ export const Factory = {
const oldVal = this.attrs[attr];

if (validator) {
val = validator.call(this, val);
val = validator.call(this, val, attr);
}

if (basicValidator) {
Expand Down Expand Up @@ -106,8 +176,11 @@ export const Factory = {

Factory.addOverloadedGetterSetter(constructor, attr);
},
addOverloadedGetterSetter(constructor, attr) {
const capitalizedAttr = Util._capitalize(attr),
addOverloadedGetterSetter<T extends Constructor, U extends Attr<T>>(
constructor: T,
attr: U
) {
var capitalizedAttr = Util._capitalize(attr),
setter = SET + capitalizedAttr,
getter = GET + capitalizedAttr;

Expand All @@ -121,7 +194,12 @@ export const Factory = {
return this[getter]();
};
},
addDeprecatedGetterSetter(constructor, attr, def, validator) {
addDeprecatedGetterSetter<T extends Constructor, U extends Attr<T>>(
constructor: T,
attr: U,
def: Value<T, U>,
validator: ValidatorFunc<Value<T, U>>
) {
Util.error('Adding deprecated ' + attr);

const method = GET + Util._capitalize(attr);
Expand All @@ -139,7 +217,10 @@ export const Factory = {
});
Factory.addOverloadedGetterSetter(constructor, attr);
},
backCompat(constructor, methods) {
backCompat<T extends Constructor>(
constructor: T,
methods: Record<string, string>
) {
Util.each(methods, function (oldMethodName, newMethodName) {
const method = constructor.prototype[newMethodName];
const oldGetter = GET + Util._capitalize(oldMethodName);
Expand All @@ -161,7 +242,7 @@ export const Factory = {
constructor.prototype[oldSetter] = deprecated;
});
},
afterSetFilter(this: Node) {
afterSetFilter(this: Node): void {
this._filterUpToDate = false;
},
};
6 changes: 3 additions & 3 deletions src/Node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2660,7 +2660,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
rotation: GetSet<number, this>;
zIndex: GetSet<number, this>;

scale: GetSet<Vector2d | undefined, this>;
scale: GetSet<Vector2d, this>;
scaleX: GetSet<number, this>;
scaleY: GetSet<number, this>;
skew: GetSet<Vector2d, this>;
Expand Down Expand Up @@ -3102,7 +3102,7 @@ addGetterSetter(Node, 'offsetY', 0, getNumberValidator());
* node.offsetY(3);
*/

addGetterSetter(Node, 'dragDistance', null, getNumberValidator());
addGetterSetter(Node, 'dragDistance', undefined, getNumberValidator());

/**
* get/set drag distance
Expand Down Expand Up @@ -3193,7 +3193,7 @@ addGetterSetter(Node, 'listening', true, getBooleanValidator());

addGetterSetter(Node, 'preventDefault', true, getBooleanValidator());

addGetterSetter(Node, 'filters', null, function (this: Node, val) {
addGetterSetter(Node, 'filters', undefined, function (this: Node, val) {
this._filterUpToDate = false;
return val;
});
Expand Down
5 changes: 5 additions & 0 deletions src/Shape.ts
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,11 @@ export class Shape<
strokeLinearGradientStartPoint: GetSet<Vector2d, this>;
strokeLinearGradientEndPoint: GetSet<Vector2d, this>;
strokeLinearGradientColorStops: GetSet<Array<number | string>, this>;
strokeLinearGradientStartPointX: GetSet<number, this>;
strokeLinearGradientStartPointY: GetSet<number, this>;
strokeLinearGradientEndPointX: GetSet<number, this>;
strokeLinearGradientEndPointY: GetSet<number, this>;
fillRule: GetSet<CanvasFillRule, this>;
}

Shape.prototype._fillFunc = _fillFunc;
Expand Down
Loading

0 comments on commit cbbc992

Please sign in to comment.