Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
SeregPie committed May 6, 2024
1 parent 6984368 commit f738602
Show file tree
Hide file tree
Showing 32 changed files with 374 additions and 41 deletions.
2 changes: 1 addition & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
/src/core/basics/provider-compitibility
/src/core/basics/validator-customization
/src/core/composables/form-fallthrough
/src/core/composables/media-query
-/src/core/composables/media-query
47 changes: 47 additions & 0 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,53 @@
},
"projectType": "library",
"root": "."
},
"docs": {
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser-esbuild",
"configurations": {
"development": {
"extractLicenses": false,
"optimization": false,
"sourceMap": true
},
"production": {
"outputHashing": "all"
}
},
"defaultConfiguration": "production",
"options": {
"allowedCommonJsDependencies": ["@messageformat/core"],
"assets": ["./src/docs/favicon.ico", "./src/docs/assets"],
"index": "./src/docs/index.html",
"inlineStyleLanguage": "scss",
"main": "./src/docs/main.ts",
"outputPath": "./docs",
"polyfills": ["zone.js"],
"styles": ["./src/docs/styles.scss"],
"tsConfig": "./src/docs/tsconfig.json"
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"development": {
"buildTarget": "docs:build:development"
},
"production": {
"buildTarget": "docs:build:production"
}
},
"defaultConfiguration": "development",
"options": {
"open": true
}
}
},
"projectType": "application",
"root": ".",
"sourceRoot": "./src/docs"
}
},
"version": 1
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
},
"scripts": {
"build": "ng build core",
"build:docs": "ng build docs",
"start:docs": "ng serve docs",
"test": "ng test",
"format": "prettier --write ."
},
Expand Down
2 changes: 2 additions & 0 deletions src/core/basics/form-reactivity/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<!-- todo: better docs -->

# Form Reactivity

## Usage
Expand Down
4 changes: 4 additions & 0 deletions src/core/basics/form-reactivity/index.23907451.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import {FormControl, FormGroup, Validators} from '@angular/forms';

import {formi} from '.';

// todo: better descriptions

describe('formi', () => {
it('should reflect actual state', fakeAsync(async () => {
let form = new FormGroup({
Expand All @@ -15,6 +17,7 @@ describe('formi', () => {
}),
});

// todo
for await (let _ of (async function* () {
yield;
for (let fn of [
Expand Down Expand Up @@ -48,6 +51,7 @@ describe('formi', () => {
it('should trigger changes properly', fakeAsync(async () => {
let form = new FormControl(null);

// todo: rename
let effectFn = jest.fn(() => {
formi(form).disabled;
});
Expand Down
4 changes: 4 additions & 0 deletions src/core/basics/form-reactivity/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,17 @@ export type ReadonlyReactiveFormProxy<
& Readonly<Pick<ControlT, ReadonlyReactiveFormProp>>
);

// todo: rework
// todo: rename
export const formi: {
<ControlT extends AbstractControl>(
control: ControlT,
): ReadonlyReactiveFormProxy<ControlT>;
} = (() => {
let create = (control) => {
// todo: use helper
let changes$ = signal({});
// todo: use helper
[
'_updatePristine',
'_updateTouched',
Expand Down
31 changes: 31 additions & 0 deletions src/core/basics/lggajrsh/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {DestroyRef, ElementRef, Signal, computed, inject, isSignal, signal} from '@angular/core';

export const onDestroy: {
(fn: {(): void}): void;
} = (fn) => {
let ref = inject(DestroyRef, {optional: true});
if (ref) {
ref.onDestroy(fn);
}
};

export type MaybeSignal<T> = T | Signal<T>;

export const resolveSignal: {
<T>(v: MaybeSignal<T>): Signal<T>;
} = (v) => (isSignal(v) ? v : signal(v).asReadonly());

export type MaybeElementSignal<T> = MaybeSignal<T | ElementRef<T>>;

export const resolveElementSignal: {
<T>(v: MaybeElementSignal<T>): Signal<T>;
} = (v) => {
let v$ = resolveSignal(v);
return computed(() => {
let v = v$();
if (v instanceof ElementRef) {
return v.nativeElement;
}
return v;
});
};
2 changes: 2 additions & 0 deletions src/core/basics/provider-compitibility/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<!-- todo: better docs -->

# Provider Compitibility

Simplifies the definition of providers and extends it with type safety.
Expand Down
34 changes: 17 additions & 17 deletions src/core/basics/provider-compitibility/index.45921704.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,18 @@ describe('provide', () => {
b = faker.number.int();
}

describe('regular', () => {
describe('single', () => {
let token = new InjectionToken<A>('');

describe('useValue', () => {
it('should create correct provider', fakeAsync(async () => {
it('should create a correct provider', fakeAsync(async () => {
expect(provide(token).useValue(A.asValue)).toEqual({
provide: token,
useValue: A.asValue,
});
}));

it('should ensure type safety', fakeAsync(async () => {
it('should enforce type safety', fakeAsync(async () => {
expect(async () => {
// @ts-expect-error
provide(token).useValue(B.asValue);
Expand All @@ -51,14 +51,14 @@ describe('provide', () => {
});

describe('useFactory', () => {
it('should create correct provider', fakeAsync(async () => {
it('should create a correct provider', fakeAsync(async () => {
expect(provide(token).useFactory(A.asFactory)).toEqual({
provide: token,
useFactory: A.asFactory,
});
}));

it('should ensure type safety', fakeAsync(async () => {
it('should enforce type safety', fakeAsync(async () => {
expect(async () => {
// @ts-expect-error
provide(token).useFactory(A.asValue);
Expand All @@ -73,14 +73,14 @@ describe('provide', () => {
});

describe('useClass', () => {
it('should create correct provider', fakeAsync(async () => {
it('should create a correct provider', fakeAsync(async () => {
expect(provide(token).useClass(A.asClass)).toEqual({
provide: token,
useClass: A.asClass,
});
}));

it('should ensure type safety', fakeAsync(async () => {
it('should enforce type safety', fakeAsync(async () => {
expect(async () => {
// @ts-expect-error
provide(token).useClass(A.asValue);
Expand All @@ -95,14 +95,14 @@ describe('provide', () => {
});

describe('useExisting', () => {
it('should create correct provider', fakeAsync(async () => {
it('should create a correct provider', fakeAsync(async () => {
expect(provide(token).useExisting(A.asExisting)).toEqual({
provide: token,
useExisting: A.asExisting,
});
}));

it('should ensure type safety', fakeAsync(async () => {
it('should enforce type safety', fakeAsync(async () => {
expect(async () => {
// @ts-expect-error
provide(token).useExisting(A.asValue);
Expand All @@ -121,15 +121,15 @@ describe('provide', () => {
let token = new InjectionToken<Array<A>>('');

describe('useValue', () => {
it('should create correct provider', fakeAsync(async () => {
it('should create a correct provider', fakeAsync(async () => {
expect(provide(token, {multi: true}).useValue(A.asValue)).toEqual({
provide: token,
multi: true,
useValue: A.asValue,
});
}));

it('should ensure type safety', fakeAsync(async () => {
it('should enforce type safety', fakeAsync(async () => {
expect(async () => {
// @ts-expect-error
provide(token, {multi: true}).useValue(B.asValue);
Expand All @@ -144,15 +144,15 @@ describe('provide', () => {
});

describe('useFactory', () => {
it('should create correct provider', fakeAsync(async () => {
it('should create a correct provider', fakeAsync(async () => {
expect(provide(token, {multi: true}).useFactory(A.asFactory)).toEqual({
provide: token,
multi: true,
useFactory: A.asFactory,
});
}));

it('should ensure type safety', fakeAsync(async () => {
it('should enforce type safety', fakeAsync(async () => {
expect(async () => {
// @ts-expect-error
provide(token, {multi: true}).useFactory(A.asValue);
Expand All @@ -167,15 +167,15 @@ describe('provide', () => {
});

describe('useClass', () => {
it('should create correct provider', fakeAsync(async () => {
it('should create a correct provider', fakeAsync(async () => {
expect(provide(token, {multi: true}).useClass(A.asClass)).toEqual({
provide: token,
multi: true,
useClass: A.asClass,
});
}));

it('should ensure type safety', fakeAsync(async () => {
it('should enforce type safety', fakeAsync(async () => {
expect(async () => {
// @ts-expect-error
provide(token, {multi: true}).useClass(A.asValue);
Expand All @@ -190,7 +190,7 @@ describe('provide', () => {
});

describe('useExisting', () => {
it('should create correct provider', fakeAsync(async () => {
it('should create a correct provider', fakeAsync(async () => {
expect(provide(token, {multi: true}).useExisting(A.asExisting)).toEqual(
{
provide: token,
Expand All @@ -200,7 +200,7 @@ describe('provide', () => {
);
}));

it('should ensure type safety', fakeAsync(async () => {
it('should enforce type safety', fakeAsync(async () => {
expect(async () => {
// @ts-expect-error
provide(token, {multi: true}).useExisting(A.asValue);
Expand Down
1 change: 1 addition & 0 deletions src/core/basics/provider-compitibility/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const provide: {
} = (token, {
multi = false,
} = {}) => {
// todo: rename
let provider = {provide: token, ...(multi ? {multi} : {})};
return oo(
...[
Expand Down
2 changes: 2 additions & 0 deletions src/core/basics/validator-customization/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<!-- todo: better docs -->

# Validator Customization

## Usage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {FormControl} from '@angular/forms';
import {composeAsyncValidators, noopAsyncValidator, stubAsyncValidator, withAsyncValidators} from '.';

describe('withAsyncValidators', () => {
it('should work', fakeAsync(async () => {
it('should work in a common scenario', fakeAsync(async () => {
let form = withAsyncValidators(
new FormControl<number>(1, {
nonNullable: true,
Expand All @@ -27,7 +27,7 @@ describe('withAsyncValidators', () => {
expect(form.errors).toBeNull();
}));

it('should contain validators', fakeAsync(async () => {
it('should contain all provided validators', fakeAsync(async () => {
let form = new FormControl(null);
let validators = [null, null].map((v) => async () => v);
withAsyncValidators(form, ...validators);
Expand Down Expand Up @@ -62,7 +62,7 @@ describe('withAsyncValidators', () => {
});

describe('composeAsyncValidators', () => {
it('should work', fakeAsync(async () => {
it('should work in a common scenario', fakeAsync(async () => {
let form = withAsyncValidators(
new FormControl<number>(1, {
nonNullable: true,
Expand Down Expand Up @@ -96,7 +96,7 @@ describe('composeAsyncValidators', () => {
expect(form.errors).toBeNull();
}));

it('should skip other validators after one fails', fakeAsync(async () => {
it('should skip remaining validators if one fails', fakeAsync(async () => {
let validators = [null, {error: true}, null].map((v) => jest.fn(async () => v));
new FormControl(null, {
asyncValidators: composeAsyncValidators(validators),
Expand All @@ -109,19 +109,19 @@ describe('composeAsyncValidators', () => {
expect(validators[2]).not.toHaveBeenCalled();
}));

it('should return same validator if only one provided', fakeAsync(async () => {
it('should return the same validator if only one provided', fakeAsync(async () => {
let validator = async () => null;

expect(composeAsyncValidators([validator])).toBe(validator);
}));

it('should return no-op validator if nothing provided', fakeAsync(async () => {
it('should return a no-op validator if no validators provided', fakeAsync(async () => {
expect(composeAsyncValidators([])).toBe(noopAsyncValidator);
}));
});

describe('noopAsyncValidator', () => {
it('should work', fakeAsync(async () => {
it('should return null', fakeAsync(async () => {
let form = withAsyncValidators(new FormControl(null), noopAsyncValidator);

tick();
Expand All @@ -131,7 +131,7 @@ describe('noopAsyncValidator', () => {
});

describe('stubAsyncValidator', () => {
it('should work', fakeAsync(async () => {
it('should return provided errors', fakeAsync(async () => {
let form = withAsyncValidators(new FormControl(null), stubAsyncValidator({error: true}));

tick();
Expand Down
Loading

0 comments on commit f738602

Please sign in to comment.