@anglr/datetime 9.0.2 → 9.0.3-beta.20260518114213
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/angular-developer/SKILL.md +130 -0
- package/.claude/skills/angular-developer/references/angular-animations.md +160 -0
- package/.claude/skills/angular-developer/references/angular-aria.md +410 -0
- package/.claude/skills/angular-developer/references/cli.md +86 -0
- package/.claude/skills/angular-developer/references/component-harnesses.md +59 -0
- package/.claude/skills/angular-developer/references/component-styling.md +91 -0
- package/.claude/skills/angular-developer/references/components.md +117 -0
- package/.claude/skills/angular-developer/references/creating-services.md +97 -0
- package/.claude/skills/angular-developer/references/data-resolvers.md +69 -0
- package/.claude/skills/angular-developer/references/define-routes.md +67 -0
- package/.claude/skills/angular-developer/references/defining-providers.md +72 -0
- package/.claude/skills/angular-developer/references/di-fundamentals.md +120 -0
- package/.claude/skills/angular-developer/references/e2e-testing.md +66 -0
- package/.claude/skills/angular-developer/references/effects.md +83 -0
- package/.claude/skills/angular-developer/references/hierarchical-injectors.md +43 -0
- package/.claude/skills/angular-developer/references/host-elements.md +80 -0
- package/.claude/skills/angular-developer/references/injection-context.md +63 -0
- package/.claude/skills/angular-developer/references/inputs.md +101 -0
- package/.claude/skills/angular-developer/references/linked-signal.md +59 -0
- package/.claude/skills/angular-developer/references/loading-strategies.md +61 -0
- package/.claude/skills/angular-developer/references/mcp.md +106 -0
- package/.claude/skills/angular-developer/references/migrations.md +30 -0
- package/.claude/skills/angular-developer/references/navigate-to-routes.md +69 -0
- package/.claude/skills/angular-developer/references/outputs.md +86 -0
- package/.claude/skills/angular-developer/references/reactive-forms.md +122 -0
- package/.claude/skills/angular-developer/references/rendering-strategies.md +44 -0
- package/.claude/skills/angular-developer/references/resource.md +77 -0
- package/.claude/skills/angular-developer/references/route-animations.md +56 -0
- package/.claude/skills/angular-developer/references/route-guards.md +52 -0
- package/.claude/skills/angular-developer/references/router-lifecycle.md +45 -0
- package/.claude/skills/angular-developer/references/router-testing.md +87 -0
- package/.claude/skills/angular-developer/references/show-routes-with-outlets.md +68 -0
- package/.claude/skills/angular-developer/references/signal-forms.md +897 -0
- package/.claude/skills/angular-developer/references/signals-overview.md +94 -0
- package/.claude/skills/angular-developer/references/tailwind-css.md +69 -0
- package/.claude/skills/angular-developer/references/template-driven-forms.md +114 -0
- package/.claude/skills/angular-developer/references/testing-fundamentals.md +66 -0
- package/.github/instructions/typescript/code-conventions.md +8 -0
- package/.github/instructions/typescript/comments.md +41 -0
- package/.github/instructions/typescript/formatting.md +43 -0
- package/.github/instructions/typescript/naming-conventions.md +7 -0
- package/.github/instructions/typescript.instructions.md +26 -0
- package/changelog.md +6 -0
- package/es2022/src/services/dateValueProvider/dateValueProvider.service.js +1 -1
- package/es2022/src/services/dateValueProvider/dateValueProvider.service.js.map +1 -1
- package/package.json +1 -1
- package/readme.md +1453 -4
- package/version.bak +1 -1
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Angular Signals Overview
|
|
2
|
+
|
|
3
|
+
Signals are the foundation of reactivity in modern Angular applications. A **signal** is a wrapper around a value that notifies interested consumers when that value changes.
|
|
4
|
+
|
|
5
|
+
## Writable Signals (`signal`)
|
|
6
|
+
|
|
7
|
+
Use `signal()` to create state that can be directly updated.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import {signal} from '@angular/core';
|
|
11
|
+
|
|
12
|
+
// Create a writable signal
|
|
13
|
+
const count = signal(0);
|
|
14
|
+
|
|
15
|
+
// Read the value (always requires calling the getter function)
|
|
16
|
+
console.log(count());
|
|
17
|
+
|
|
18
|
+
// Update the value directly
|
|
19
|
+
count.set(3);
|
|
20
|
+
|
|
21
|
+
// Update based on the previous value
|
|
22
|
+
count.update((value) => value + 1);
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Exposing as Readonly
|
|
26
|
+
|
|
27
|
+
When exposing state from a service, it is a best practice to expose a readonly version to prevent external mutation.
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
private readonly _count = signal(0);
|
|
31
|
+
// Consumers can read this, but cannot call .set() or .update()
|
|
32
|
+
readonly count = this._count.asReadonly();
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Computed Signals (`computed`)
|
|
36
|
+
|
|
37
|
+
Use `computed()` to create read-only signals that derive their value from other signals.
|
|
38
|
+
|
|
39
|
+
- **Lazily Evaluated**: The derivation function doesn't run until the computed signal is read.
|
|
40
|
+
- **Memoized**: The result is cached. It only recalculates when one of the signals it depends on changes.
|
|
41
|
+
- **Dynamic Dependencies**: Only the signals _actually read_ during the derivation are tracked.
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import {signal, computed} from '@angular/core';
|
|
45
|
+
|
|
46
|
+
const count = signal(0);
|
|
47
|
+
const doubleCount = computed(() => count() * 2);
|
|
48
|
+
|
|
49
|
+
// doubleCount automatically updates when count changes.
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Reactive Contexts
|
|
53
|
+
|
|
54
|
+
A **reactive context** is a runtime state where Angular monitors signal reads to establish a dependency.
|
|
55
|
+
|
|
56
|
+
Angular automatically enters a reactive context when evaluating:
|
|
57
|
+
|
|
58
|
+
- `computed` signals
|
|
59
|
+
- `effect` callbacks
|
|
60
|
+
- `linkedSignal` computations
|
|
61
|
+
- Component templates
|
|
62
|
+
|
|
63
|
+
### Untracked Reads (`untracked`)
|
|
64
|
+
|
|
65
|
+
If you need to read a signal inside a reactive context _without_ creating a dependency (so that the context doesn't re-run when the signal changes), use `untracked()`.
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import {effect, untracked} from '@angular/core';
|
|
69
|
+
|
|
70
|
+
effect(() => {
|
|
71
|
+
// This effect only runs when currentUser changes.
|
|
72
|
+
// It does NOT run when counter changes, even though counter is read here.
|
|
73
|
+
console.log(`User: ${currentUser()}, Count: ${untracked(counter)}`);
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Async Operations in Reactive Contexts
|
|
78
|
+
|
|
79
|
+
The reactive context is only active for **synchronous** code. Signal reads after an `await` will not be tracked. **Always read signals before asynchronous boundaries.**
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
// ❌ INCORRECT: theme() is not tracked because it is read after await
|
|
83
|
+
effect(async () => {
|
|
84
|
+
const data = await fetchUserData();
|
|
85
|
+
console.log(theme());
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// ✅ CORRECT: Read the signal before the await
|
|
89
|
+
effect(async () => {
|
|
90
|
+
const currentTheme = theme();
|
|
91
|
+
const data = await fetchUserData();
|
|
92
|
+
console.log(currentTheme);
|
|
93
|
+
});
|
|
94
|
+
```
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Using Tailwind CSS with Angular
|
|
2
|
+
|
|
3
|
+
Tailwind CSS is a utility-first CSS framework that integrates seamlessly with Angular.
|
|
4
|
+
|
|
5
|
+
**CRITICAL AGENT GUIDANCE: ALWAYS focus on Tailwind CSS v4 practices. DO NOT revert to old Tailwind v3 patterns (like creating `tailwind.config.js` with `@tailwind` directives) as this will break the application build. Modern Angular projects use Tailwind v4.**
|
|
6
|
+
|
|
7
|
+
## Automated Setup (Recommended)
|
|
8
|
+
|
|
9
|
+
The easiest way to add Tailwind CSS to an Angular project is via the Angular CLI:
|
|
10
|
+
|
|
11
|
+
```shell
|
|
12
|
+
ng add tailwindcss
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
This will automatically:
|
|
16
|
+
|
|
17
|
+
1. Install `tailwindcss` and peer dependencies.
|
|
18
|
+
2. Configure the project to use Tailwind CSS.
|
|
19
|
+
3. Add the proper import to your global styles.
|
|
20
|
+
|
|
21
|
+
## Manual Setup (Tailwind v4)
|
|
22
|
+
|
|
23
|
+
If setting up manually, use the following Tailwind v4 pattern:
|
|
24
|
+
|
|
25
|
+
### 1. Install Dependencies
|
|
26
|
+
|
|
27
|
+
Install Tailwind CSS and PostCSS:
|
|
28
|
+
|
|
29
|
+
```shell
|
|
30
|
+
npm install tailwindcss @tailwindcss/postcss postcss
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 2. Configure PostCSS
|
|
34
|
+
|
|
35
|
+
Create a `.postcssrc.json` file in the project root:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"plugins": {
|
|
40
|
+
"@tailwindcss/postcss": {}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
_(Do NOT create a `tailwind.config.js` file! Configuration in v4 is handled through CSS variables)._
|
|
46
|
+
|
|
47
|
+
### 3. Import Tailwind CSS
|
|
48
|
+
|
|
49
|
+
In your global styles file (e.g., `src/styles.css`), add the standard v4 import:
|
|
50
|
+
|
|
51
|
+
```css
|
|
52
|
+
@import 'tailwindcss';
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
_(If using SCSS, use `@use 'tailwindcss';` instead)._
|
|
56
|
+
|
|
57
|
+
### 4. Use Utility Classes
|
|
58
|
+
|
|
59
|
+
You can now use Tailwind classes directly in your component templates:
|
|
60
|
+
|
|
61
|
+
```html
|
|
62
|
+
<h1 class="text-3xl font-bold underline">Hello world!</h1>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Summary for AI Agents
|
|
66
|
+
|
|
67
|
+
- **Do not use `@tailwind base; @tailwind components; @tailwind utilities;`**. Use `@import 'tailwindcss';`.
|
|
68
|
+
- **Do not create `tailwind.config.js`**. Configuration is managed directly in CSS via theme variables or using PostCSS configurations.
|
|
69
|
+
- Stick strictly to v4 syntax and workflows.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Template-Driven Forms
|
|
2
|
+
|
|
3
|
+
Template-driven forms use two-way data binding (`[(ngModel)]`) to update the data model in the component as changes are made in the template and vice versa. They are ideal for simple forms and use directives in the HTML template to manage form state and validation.
|
|
4
|
+
|
|
5
|
+
## Core Directives
|
|
6
|
+
|
|
7
|
+
Template-driven forms rely on the `FormsModule` which provides these key directives:
|
|
8
|
+
|
|
9
|
+
- `NgModel`: Reconciles value changes in the form element with the data model (`[(ngModel)]`).
|
|
10
|
+
- `NgForm`: Automatically creates a top-level `FormGroup` bound to the `<form>` tag.
|
|
11
|
+
- `NgModelGroup`: Creates a nested `FormGroup` bound to a DOM element.
|
|
12
|
+
|
|
13
|
+
## Setup
|
|
14
|
+
|
|
15
|
+
First, import `FormsModule` into your component or module.
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import {Component} from '@angular/core';
|
|
19
|
+
import {FormsModule} from '@angular/forms';
|
|
20
|
+
|
|
21
|
+
@Component({
|
|
22
|
+
selector: 'app-user-form',
|
|
23
|
+
imports: [FormsModule],
|
|
24
|
+
templateUrl: './user-form.component.html',
|
|
25
|
+
})
|
|
26
|
+
export class UserForm {
|
|
27
|
+
user = {name: '', role: 'Guest'};
|
|
28
|
+
|
|
29
|
+
onSubmit() {
|
|
30
|
+
console.log('Form submitted!', this.user);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Building the Form Template
|
|
36
|
+
|
|
37
|
+
### Two-Way Binding with `[(ngModel)]`
|
|
38
|
+
|
|
39
|
+
Use `[(ngModel)]` on input elements. **Every element using `[(ngModel)]` MUST have a `name` attribute.** Angular uses the `name` attribute to register the control with the parent `NgForm`.
|
|
40
|
+
|
|
41
|
+
```html
|
|
42
|
+
<form #userForm="ngForm" (ngSubmit)="onSubmit()">
|
|
43
|
+
<!-- Basic Input -->
|
|
44
|
+
<div>
|
|
45
|
+
<label for="name">Name:</label>
|
|
46
|
+
<input type="text" id="name" required [(ngModel)]="user.name" name="name" #nameCtrl="ngModel" />
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<!-- Select Box -->
|
|
50
|
+
<div>
|
|
51
|
+
<label for="role">Role:</label>
|
|
52
|
+
<select id="role" [(ngModel)]="user.role" name="role">
|
|
53
|
+
<option value="Admin">Admin</option>
|
|
54
|
+
<option value="Guest">Guest</option>
|
|
55
|
+
</select>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<!-- Submit Button (disabled if form is invalid) -->
|
|
59
|
+
<button type="submit" [disabled]="!userForm.form.valid">Submit</button>
|
|
60
|
+
</form>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Form and Control State
|
|
64
|
+
|
|
65
|
+
Angular automatically applies CSS classes to controls and forms based on their state:
|
|
66
|
+
|
|
67
|
+
| State | Class if True | Class if False |
|
|
68
|
+
| :------------- | :-------------------------------- | :------------- |
|
|
69
|
+
| Visited | `ng-touched` | `ng-untouched` |
|
|
70
|
+
| Value Changed | `ng-dirty` | `ng-pristine` |
|
|
71
|
+
| Value is Valid | `ng-valid` | `ng-invalid` |
|
|
72
|
+
| Form Submitted | `ng-submitted` (on `<form>` only) | - |
|
|
73
|
+
|
|
74
|
+
You can use these classes to provide visual feedback in your CSS:
|
|
75
|
+
|
|
76
|
+
```css
|
|
77
|
+
.ng-valid[required],
|
|
78
|
+
.ng-valid.required {
|
|
79
|
+
border-left: 5px solid #42a948; /* green */
|
|
80
|
+
}
|
|
81
|
+
.ng-invalid:not(form) {
|
|
82
|
+
border-left: 5px solid #a94442; /* red */
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Validation and Error Messages
|
|
87
|
+
|
|
88
|
+
To display error messages conditionally, export the `ngModel` directive to a template reference variable (e.g., `#nameCtrl="ngModel"`).
|
|
89
|
+
|
|
90
|
+
```html
|
|
91
|
+
<input type="text" id="name" required [(ngModel)]="user.name" name="name" #nameCtrl="ngModel" />
|
|
92
|
+
|
|
93
|
+
<!-- Show error only if the control is invalid AND (touched OR dirty) -->
|
|
94
|
+
@if (nameCtrl.invalid && (nameCtrl.dirty || nameCtrl.touched)) {
|
|
95
|
+
<div class="alert alert-danger">
|
|
96
|
+
@if (nameCtrl.errors?.['required']) {
|
|
97
|
+
<div>Name is required.</div>
|
|
98
|
+
}
|
|
99
|
+
</div>
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Submitting the Form
|
|
104
|
+
|
|
105
|
+
1. Use the `(ngSubmit)` event on the `<form>` element.
|
|
106
|
+
2. Bind the submit button's disabled state to the overall form validity using the `NgForm` template reference variable (e.g., `[disabled]="!userForm.form.valid"`).
|
|
107
|
+
|
|
108
|
+
## Resetting the Form
|
|
109
|
+
|
|
110
|
+
To programmatically reset the form to its pristine state (clearing values and validation flags), use the `reset()` method on the `NgForm` instance.
|
|
111
|
+
|
|
112
|
+
```html
|
|
113
|
+
<button type="button" (click)="userForm.reset()">Reset</button>
|
|
114
|
+
```
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Testing Fundamentals
|
|
2
|
+
|
|
3
|
+
This guide covers the fundamental principles and practices for writing unit tests in this repository, which uses Vitest as the test runner.
|
|
4
|
+
|
|
5
|
+
## Core Philosophy: Zoneless & Async-First
|
|
6
|
+
|
|
7
|
+
This project follows a modern, zoneless testing approach. State changes schedule updates asynchronously, and tests must account for this.
|
|
8
|
+
|
|
9
|
+
**Do NOT** use `fixture.detectChanges()` to manually trigger updates.
|
|
10
|
+
**ALWAYS** use the "Act, Wait, Assert" pattern:
|
|
11
|
+
|
|
12
|
+
1. **Act:** Update state or perform an action (e.g., set a component input, click a button).
|
|
13
|
+
2. **Wait:** Use `await fixture.whenStable()` to allow the framework to process the scheduled update and render the changes.
|
|
14
|
+
3. **Assert:** Verify the outcome.
|
|
15
|
+
|
|
16
|
+
### Basic Test Structure Example
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
|
20
|
+
import {MyComponent} from './my.component';
|
|
21
|
+
|
|
22
|
+
describe('MyComponent', () => {
|
|
23
|
+
let component: MyComponent;
|
|
24
|
+
let fixture: ComponentFixture<MyComponent>;
|
|
25
|
+
let h1: HTMLElement;
|
|
26
|
+
|
|
27
|
+
beforeEach(async () => {
|
|
28
|
+
// 1. Configure the test module
|
|
29
|
+
await TestBed.configureTestingModule({
|
|
30
|
+
imports: [MyComponent],
|
|
31
|
+
}).compileComponents();
|
|
32
|
+
|
|
33
|
+
// 2. Create the component fixture
|
|
34
|
+
fixture = TestBed.createComponent(MyComponent);
|
|
35
|
+
component = fixture.componentInstance;
|
|
36
|
+
h1 = fixture.nativeElement.querySelector('h1');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should display the default title', async () => {
|
|
40
|
+
// ACT: (Implicit) Component is created with default state.
|
|
41
|
+
// WAIT for initial data binding.
|
|
42
|
+
await fixture.whenStable();
|
|
43
|
+
// ASSERT the initial state.
|
|
44
|
+
expect(h1.textContent).toContain('Default Title');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should display a different title after a change', async () => {
|
|
48
|
+
// ACT: Change the component's title property.
|
|
49
|
+
component.title.set('New Test Title');
|
|
50
|
+
|
|
51
|
+
// WAIT for the asynchronous update to complete.
|
|
52
|
+
await fixture.whenStable();
|
|
53
|
+
|
|
54
|
+
// ASSERT the DOM has been updated.
|
|
55
|
+
expect(h1.textContent).toContain('New Test Title');
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## TestBed and ComponentFixture
|
|
61
|
+
|
|
62
|
+
- **`TestBed`**: The primary utility for creating a test-specific Angular module. Use `TestBed.configureTestingModule({...})` in your `beforeEach` to declare components, provide services, and set up imports needed for your test.
|
|
63
|
+
- **`ComponentFixture`**: A handle on the created component instance and its environment.
|
|
64
|
+
- `fixture.componentInstance`: Access the component's class instance.
|
|
65
|
+
- `fixture.nativeElement`: Access the component's root DOM element.
|
|
66
|
+
- `fixture.debugElement`: An Angular-specific wrapper around the `nativeElement` that provides safer, platform-agnostic ways to query the DOM (e.g., `debugElement.query(By.css('p'))`).
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Code conventions
|
|
2
|
+
|
|
3
|
+
- Use Angular Developer skills and best practices whenever possible, but also:
|
|
4
|
+
- Always use explicit type annotations for class members even if type can be inferred even if it is not recommended by any skill
|
|
5
|
+
- Use `const` whenever possible, and only use `let` when variable needs to be reassigned
|
|
6
|
+
- For local constants, let typescript infer type if it is possible to infer it from initializer, otherwise use explicit type annotation
|
|
7
|
+
- Use `readonly` modifier for class members that are not reassigned after initialization
|
|
8
|
+
- Always use access modifiers for class members (private, protected, public)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Comments
|
|
2
|
+
|
|
3
|
+
- Use JSDoc comments everywhere (classes, interfaces, types, functions, constants, properties, methods, parameters, etc.)
|
|
4
|
+
- Use JSDoc for all members, also for private, protected
|
|
5
|
+
- Use title `//######################### <name-of-title> #########################` for group of members in class or interface, where `<name-of-title>` is descriptive name of the group:
|
|
6
|
+
- supported names of titles are: `private fields`, `protected fields`, `protected properties`, `protected properties - template bindings`, `protected properties - children`, `public properties`, `public properties - inputs`, `public properties - outputs`, `public properties - models`, `constructor`, `public methods - implementation of <interface-name>`, `public methods`, `protected methods - template bindings`, `protected methods - overrides`, `protected methods`, `private methods`
|
|
7
|
+
- use empty line before and after title (except if its first line of the block)
|
|
8
|
+
- order members in class or interface according to the following rules (unless dependencies between members require different order):
|
|
9
|
+
- private fields
|
|
10
|
+
- protected fields
|
|
11
|
+
- protected properties
|
|
12
|
+
- protected properties - template bindings
|
|
13
|
+
- protected properties - children
|
|
14
|
+
- public properties
|
|
15
|
+
- public properties - inputs
|
|
16
|
+
- public properties - outputs
|
|
17
|
+
- public properties - models
|
|
18
|
+
- constructor
|
|
19
|
+
- public methods - implementation of <interface-name>
|
|
20
|
+
- public methods
|
|
21
|
+
- protected methods - template bindings
|
|
22
|
+
- protected methods - overrides
|
|
23
|
+
- protected methods
|
|
24
|
+
- private methods
|
|
25
|
+
- when to use each group
|
|
26
|
+
- private fields - use this for all private properties
|
|
27
|
+
- protected fields - use this for all protected properties that are used only in component
|
|
28
|
+
- protected properties - use this only for getter and setter properties
|
|
29
|
+
- protected properties - template bindings - use this for properties that are used in template
|
|
30
|
+
- protected properties - children - use this for Angular *view child/children* and *content child/children* properties
|
|
31
|
+
- public properties - use this for rest of public properties
|
|
32
|
+
- public properties - inputs - use this for Angular *inputs* properties
|
|
33
|
+
- public properties - outputs - use this for Angular *outputs* properties
|
|
34
|
+
- public properties - models - use this for Angular *model* properties
|
|
35
|
+
- constructor - use this only for constructor
|
|
36
|
+
- public methods - implementation of <interface-name> - use this for each method that was implemented by <interface-name>
|
|
37
|
+
- public methods - use this for rest of public methods
|
|
38
|
+
- protected methods - template bindings - use this for protected methdos that are used in template
|
|
39
|
+
- protected methods - overrides - use this for all protected methods that are overriden
|
|
40
|
+
- protected methods - use this for all protected methods that are used only in component
|
|
41
|
+
- private methods - use this for all private methods
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Formatting
|
|
2
|
+
|
|
3
|
+
- Order typescript imports, use following rules:
|
|
4
|
+
- put `@angular/core` on first place
|
|
5
|
+
- then put other `@angular/core/*` imports
|
|
6
|
+
- then put other `@angular/*` imports
|
|
7
|
+
- then put `@anglr/*` imports
|
|
8
|
+
- then put `@jscrpt/common` and `@jscrpt/common/*` imports
|
|
9
|
+
- then put other *scoped* imports (e.g. `@fortawesome/*`, `@ngx-translate/*`, etc.)
|
|
10
|
+
- then other absolute imports
|
|
11
|
+
- then relative imports
|
|
12
|
+
- use empty line to separate absolute and relative imports
|
|
13
|
+
- Use 4 spaces for indentation
|
|
14
|
+
- For new lines use LF (line feed) character, not CRLF (carriage return + line feed)
|
|
15
|
+
- Put empty line at the end of file
|
|
16
|
+
- Always put opening braces on the new line, except case when object or array literal used together with `return` statement, in that case put opening brace on same line as `return`
|
|
17
|
+
- Always use single quotes for strings
|
|
18
|
+
- Always use semicolons at the end of statements
|
|
19
|
+
- Always use block braces for control flow statements (if, for, while, switch), even if they are optional
|
|
20
|
+
- Do not use braces around single parameter lambda functions, unless the parameter type is unknown
|
|
21
|
+
- Do not use space after control flow statements (if, for, while, switch)
|
|
22
|
+
- Do not put space after opening braces and before closing braces in oneline object literals, arrays, and function parameters, deconstructions, and imports (e.g. `import {Component} from '@angular/core';`, not `import { Component } from '@angular/core';`)
|
|
23
|
+
- never wrap `import` statements, always keep them on one line, does not matter what is length of that line
|
|
24
|
+
- Use empty line after before and after control flow statements (if, for, while, switch) (unless its first or last line of the block)
|
|
25
|
+
- Always put comma after last item in array literal, after last property in object literal or after last argument in function definition when defined across multiple lines
|
|
26
|
+
- Formatting arguments of function definition and declaration:
|
|
27
|
+
- Constructor arguments, put second and following arguments on new line, and align them with the first argument
|
|
28
|
+
- For other functions, if the function has more than 2 arguments and line length exceeds 120 characters, put second and following arguments on new line, and align them with the first argument
|
|
29
|
+
- For method and function (also decorator use) calls:
|
|
30
|
+
- If there is only one parameter and it is not an object literal, keep it on the same line
|
|
31
|
+
- If there is only one parameter and it is lambda function, put body of lambda function on new line and use same indentation as previous line
|
|
32
|
+
- If there is only one paremeter and it is an object or array literal, put it on new line and use same indentation as previous line
|
|
33
|
+
- If there are more than one parameters and lenght does not exceed 120 characters, keep them on the same line
|
|
34
|
+
- If there are more than one parameters and lenght exceeds 120 characters, put second and following parameters on new line, and align them with the first parameter
|
|
35
|
+
- Json literals:
|
|
36
|
+
- Put each property on new line and align them with the first property
|
|
37
|
+
- Opening and closing braces should be on their own line and aligned with the first property
|
|
38
|
+
- Angular Component and Directive decorators:
|
|
39
|
+
- Follow rules for Json literals, but also:
|
|
40
|
+
- order properties in the following order: selector, templateUrl, template, styleUrl, styleUrls, styles, host, imports, providers, hostDirectives, changeDetection
|
|
41
|
+
- order array properties values in the following order: from shortest to longest (e.g. in `imports` property, put items with shorter names first)
|
|
42
|
+
- never use one line array or object literal for `imports`, `providers`, `host`
|
|
43
|
+
- always use `changeDetection: ChangeDetectionStrategy.OnPush`
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Naming Conventions
|
|
2
|
+
|
|
3
|
+
- Use PascalCase for component names, directives, pipes, services, interfaces, and type aliases
|
|
4
|
+
- Use camelCase for variables, functions, and methods
|
|
5
|
+
- Prefix private class members with underscore (_)
|
|
6
|
+
- Do NOT prefix protected class members with underscore (_)
|
|
7
|
+
- Use ALL_CAPS for constants
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: This file describes the TypeScript code style, formatting, and conventions for the project.
|
|
3
|
+
applyTo: "**/*.ts, **/*.js"
|
|
4
|
+
---
|
|
5
|
+
# Project general coding standards
|
|
6
|
+
|
|
7
|
+
## Formatting
|
|
8
|
+
|
|
9
|
+
For formatting instructions see [formatting instructions](./typescript/formatting.md).
|
|
10
|
+
|
|
11
|
+
## Code conventions
|
|
12
|
+
|
|
13
|
+
For code conventions instructions see [code conventions instructions](./typescript/code-conventions.md).
|
|
14
|
+
|
|
15
|
+
## Comments
|
|
16
|
+
|
|
17
|
+
For comments instructions see [comments instructions](./typescript/comments.md).
|
|
18
|
+
|
|
19
|
+
## Naming Conventions
|
|
20
|
+
|
|
21
|
+
For naming conventions instructions see [naming conventions instructions](./typescript/naming-conventions.md).
|
|
22
|
+
|
|
23
|
+
## Error Handling
|
|
24
|
+
|
|
25
|
+
- Use try/catch blocks for async operations
|
|
26
|
+
- Always log errors with contextual information
|
package/changelog.md
CHANGED
|
@@ -52,7 +52,7 @@ export class DateValueProvider {
|
|
|
52
52
|
}
|
|
53
53
|
return {
|
|
54
54
|
from: start,
|
|
55
|
-
to: end
|
|
55
|
+
to: end,
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
58
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.0", ngImport: i0, type: DateValueProvider, deps: [{ token: DATE_API }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dateValueProvider.service.js","sourceRoot":"","sources":["../../../../src/services/dateValueProvider/dateValueProvider.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAE,UAAU,EAAC,MAAM,eAAe,CAAC;AAGjD,OAAO,EAAC,QAAQ,EAAC,MAAM,mBAAmB,CAAC;;AAG3C;;GAEG;AAEH,MAAM,OAAO,iBAAiB;IAE1B,iEAAiE;IACjE,YAAwC,QAAwB;QAAxB,aAAQ,GAAR,QAAQ,CAAgB;IAEhE,CAAC;IAED,oEAAoE;IAEpE;;;;OAIG;IACI,QAAQ,CAAC,KAAY,EAAE,MAAc;QAExC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAClD,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACnD,IAAI,KAAK,GAAU,KAAK,CAAC;QACzB,IAAI,GAAG,GAAU,KAAK,CAAC;QAEvB,QAAQ;QACR,IAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAC/B,CAAC;YACG,KAAK,GAAG,GAAG,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC;YAClC,GAAG,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC;QAClC,CAAC;QACD,MAAM;aACD,IAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EACpE,CAAC;YACG,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC;YAChC,GAAG,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC;QAChC,CAAC;QACD,KAAK;aACA,IAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EACpC,CAAC;YACG,KAAK,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC;YAC/B,GAAG,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC;QAC/B,CAAC;QACD,MAAM;aACD,IAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EACpC,CAAC;YACG,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC;YAChC,GAAG,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC;QAChC,CAAC;QACD,OAAO;aACF,IAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EACpC,CAAC;YACG,KAAK,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC;YACjC,GAAG,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC;QACjC,CAAC;QACD,MAAM;aACD,IAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EACpE,CAAC;YACG,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC;YAChC,GAAG,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC;QAChC,CAAC;QAED,OAAO;YACH,IAAI,EAAE,KAAK;YACX,EAAE,EAAE,GAAG;SACV,CAAC;IACN,CAAC;8GA9DQ,iBAAiB,kBAGN,QAAQ;kHAHnB,iBAAiB,cADL,MAAM;;2FAClB,iBAAiB;kBAD7B,UAAU;mBAAC,EAAC,UAAU,EAAE,MAAM,EAAC;;0BAIf,MAAM;2BAAC,QAAQ","sourcesContent":["import {Inject, Injectable} from '@angular/core';\n\nimport {DateTimeValue} from '../../interfaces/dateTime/datetime.interface';\nimport {DATE_API} from '../../misc/tokens';\nimport {DateApi} from '../dateApi/dateApi.interface';\n\n/**\n * Class used for obtaining DateTimeValue for various formats\n */\n@Injectable({providedIn: 'root'})\nexport class DateValueProvider<TDate = unknown>\n{\n //######################### constructor #########################\n constructor(@Inject(DATE_API) protected _dateApi: DateApi<TDate>)\n {\n }\n\n //######################### public methods #########################\n\n /**\n * Gets DateTimeValue from single value based on format\n * @param value - Current value to be converted to ranged value\n * @param format - Format that is requested to be displayed, it tells what range should be created\n */\n public getValue(value: TDate, format: string): DateTimeValue<TDate>\n {\n const val = this._dateApi.getValue(value, format);\n const fullFormat = this._dateApi.getFormat(format);\n let start: TDate = value;\n let end: TDate = value;\n\n //minute\n if(fullFormat.indexOf('m') >= 0)\n {\n start = val.startOfMinute().value;\n end = val.endOfMinute().value;\n }\n //hour\n else if(fullFormat.indexOf('H') >= 0 || fullFormat.indexOf('h') >= 0)\n {\n start = val.startOfHour().value;\n end = val.endOfHour().value;\n }\n //day\n else if(fullFormat.indexOf('d') >= 0)\n {\n start = val.startOfDay().value;\n end = val.endOfDay().value;\n }\n //week\n else if(fullFormat.indexOf('w') >= 0)\n {\n start = val.startOfWeek().value;\n end = val.endOfWeek().value;\n }\n //month\n else if(fullFormat.indexOf('M') >= 0)\n {\n start = val.startOfMonth().value;\n end = val.endOfMonth().value;\n }\n //year\n else if(fullFormat.indexOf('Y') >= 0 || fullFormat.indexOf('y') >= 0)\n {\n start = val.startOfYear().value;\n end = val.endOfYear().value;\n }\n\n return {\n from: start,\n to: end
|
|
1
|
+
{"version":3,"file":"dateValueProvider.service.js","sourceRoot":"","sources":["../../../../src/services/dateValueProvider/dateValueProvider.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAE,UAAU,EAAC,MAAM,eAAe,CAAC;AAGjD,OAAO,EAAC,QAAQ,EAAC,MAAM,mBAAmB,CAAC;;AAG3C;;GAEG;AAEH,MAAM,OAAO,iBAAiB;IAE1B,iEAAiE;IACjE,YAAwC,QAAwB;QAAxB,aAAQ,GAAR,QAAQ,CAAgB;IAEhE,CAAC;IAED,oEAAoE;IAEpE;;;;OAIG;IACI,QAAQ,CAAC,KAAY,EAAE,MAAc;QAExC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAClD,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACnD,IAAI,KAAK,GAAU,KAAK,CAAC;QACzB,IAAI,GAAG,GAAU,KAAK,CAAC;QAEvB,QAAQ;QACR,IAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAC/B,CAAC;YACG,KAAK,GAAG,GAAG,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC;YAClC,GAAG,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC;QAClC,CAAC;QACD,MAAM;aACD,IAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EACpE,CAAC;YACG,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC;YAChC,GAAG,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC;QAChC,CAAC;QACD,KAAK;aACA,IAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EACpC,CAAC;YACG,KAAK,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC;YAC/B,GAAG,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC;QAC/B,CAAC;QACD,MAAM;aACD,IAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EACpC,CAAC;YACG,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC;YAChC,GAAG,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC;QAChC,CAAC;QACD,OAAO;aACF,IAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EACpC,CAAC;YACG,KAAK,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC;YACjC,GAAG,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC;QACjC,CAAC;QACD,MAAM;aACD,IAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EACpE,CAAC;YACG,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC;YAChC,GAAG,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC;QAChC,CAAC;QAED,OAAO;YACH,IAAI,EAAE,KAAK;YACX,EAAE,EAAE,GAAG;SACV,CAAC;IACN,CAAC;8GA9DQ,iBAAiB,kBAGN,QAAQ;kHAHnB,iBAAiB,cADL,MAAM;;2FAClB,iBAAiB;kBAD7B,UAAU;mBAAC,EAAC,UAAU,EAAE,MAAM,EAAC;;0BAIf,MAAM;2BAAC,QAAQ","sourcesContent":["import {Inject, Injectable} from '@angular/core';\n\nimport {DateTimeValue} from '../../interfaces/dateTime/datetime.interface';\nimport {DATE_API} from '../../misc/tokens';\nimport {DateApi} from '../dateApi/dateApi.interface';\n\n/**\n * Class used for obtaining DateTimeValue for various formats\n */\n@Injectable({providedIn: 'root'})\nexport class DateValueProvider<TDate = unknown>\n{\n //######################### constructor #########################\n constructor(@Inject(DATE_API) protected _dateApi: DateApi<TDate>)\n {\n }\n\n //######################### public methods #########################\n\n /**\n * Gets DateTimeValue from single value based on format\n * @param value - Current value to be converted to ranged value\n * @param format - Format that is requested to be displayed, it tells what range should be created\n */\n public getValue(value: TDate, format: string): DateTimeValue<TDate>\n {\n const val = this._dateApi.getValue(value, format);\n const fullFormat = this._dateApi.getFormat(format);\n let start: TDate = value;\n let end: TDate = value;\n\n //minute\n if(fullFormat.indexOf('m') >= 0)\n {\n start = val.startOfMinute().value;\n end = val.endOfMinute().value;\n }\n //hour\n else if(fullFormat.indexOf('H') >= 0 || fullFormat.indexOf('h') >= 0)\n {\n start = val.startOfHour().value;\n end = val.endOfHour().value;\n }\n //day\n else if(fullFormat.indexOf('d') >= 0)\n {\n start = val.startOfDay().value;\n end = val.endOfDay().value;\n }\n //week\n else if(fullFormat.indexOf('w') >= 0)\n {\n start = val.startOfWeek().value;\n end = val.endOfWeek().value;\n }\n //month\n else if(fullFormat.indexOf('M') >= 0)\n {\n start = val.startOfMonth().value;\n end = val.endOfMonth().value;\n }\n //year\n else if(fullFormat.indexOf('Y') >= 0 || fullFormat.indexOf('y') >= 0)\n {\n start = val.startOfYear().value;\n end = val.endOfYear().value;\n }\n\n return {\n from: start,\n to: end,\n };\n }\n}\n"]}
|