@yelon/util
Version:
130 lines (125 loc) • 4.26 kB
JavaScript
import { warn } from '@yelon/util/other';
function propDecoratorFactory(name, fallback, defaultValue) {
function propDecorator(target, propName, originalDescriptor) {
const privatePropName = `$$__${propName}`;
if (typeof ngDevMode === 'undefined' || ngDevMode) {
if (Object.prototype.hasOwnProperty.call(target, privatePropName)) {
warn(`The prop "${privatePropName}" is already exist, it will be overrided by ${name} decorator.`);
}
}
Object.defineProperty(target, privatePropName, {
configurable: true,
writable: true
});
return {
get() {
return originalDescriptor && originalDescriptor.get
? originalDescriptor.get.bind(this)()
: this[privatePropName];
},
set(value) {
if (originalDescriptor && originalDescriptor.set) {
originalDescriptor.set.bind(this)(fallback(value, defaultValue));
}
this[privatePropName] = fallback(value, defaultValue);
}
};
}
return propDecorator;
}
function toBoolean(value, defaultValue = false) {
return value == null ? defaultValue : `${value}` !== 'false';
}
/**
* @deprecated Recommended to use the built-in `transform` and `static ngAcceptInputType_` can be removed
* - Use `@Input({ transform: booleanAttribute })` instead of `@InputBoolean()`
* - Use `@Input({ transform: (v: unknown) => (v == null ? null : booleanAttribute(v)) })` instead of `@InputBoolean(null)`
*
* Input decorator that handle a prop to do get/set automatically with toBoolean
*
* ```ts
* {AT}Input() {AT}InputBoolean() visible: boolean = false;
* {AT}Input() {AT}InputBoolean(null) visible: boolean = false;
* ```
*/
function InputBoolean(defaultValue = false) {
return propDecoratorFactory('InputBoolean', toBoolean, defaultValue);
}
function toNumber(value, fallbackValue = 0) {
return !isNaN(parseFloat(value)) && !isNaN(Number(value)) ? Number(value) : fallbackValue;
}
/**
* @deprecated Recommended to use the built-in `transform` and `static ngAcceptInputType_` can be removed
* - Use `@Input({ transform: numberAttribute })` instead of `@InputNumber()`
* - Use `@Input({ transform: (v: unknown) => (v == null ? null : numberAttribute(v)) })` instead of `@InputNumber(null)`
*
* Input decorator that handle a prop to do get/set automatically with toNumber
*
* ```ts
* {AT}Input() {AT}InputNumber() visible: number = 1;
* {AT}Input() {AT}InputNumber(null) visible: number = 2;
* ```
*/
function InputNumber(defaultValue = 0) {
return propDecoratorFactory('InputNumber', toNumber, defaultValue);
}
function makeFn(type, options) {
return (_, __, descriptor) => {
const source = descriptor.value;
descriptor.value = function (...data) {
const that = this;
const ngZone = that[options?.ngZoneName || 'ngZone'];
if (!ngZone) {
if (typeof ngDevMode === 'undefined' || ngDevMode) {
warn(`ZoneOutside: Decorator should have 'ngZone' property with 'NgZone' class.`);
}
return source.call(this, ...data);
}
let res;
ngZone[type](() => {
res = source.call(this, ...data);
});
return res;
};
return descriptor;
};
}
/**
* The decoration method runs in `runOutsideAngular`
*
* 装饰方法运行在 `runOutsideAngular` 内
*
* ```ts
* class MockClass {
* readonly ngZone = inject(NgZone);
*
* {AT}ZoneOutside()
* runOutsideAngular(): void {}
* }
* ```
*/
function ZoneOutside(options) {
return makeFn('runOutsideAngular', options);
}
/**
* The decoration method runs in `run`
*
* 装饰方法运行在 `run` 内
*
* ```ts
* class MockClass {
* readonly ngZone = inject(NgZone);
*
* {AT}ZoneRun()
* run(): void {}
* }
* ```
*/
function ZoneRun(options) {
return makeFn('run', options);
}
/**
* Generated bundle index. Do not edit.
*/
export { InputBoolean, InputNumber, ZoneOutside, ZoneRun, toBoolean, toNumber };
//# sourceMappingURL=decorator.mjs.map