@smartsoft001-mobilems/claude-plugins 2.76.0 → 2.78.0

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.
Files changed (44) hide show
  1. package/package.json +1 -1
  2. package/plugins/flow/.claude-plugin/merge-permissions.js +17 -0
  3. package/plugins/flow/.claude-plugin/plugin.json +1 -1
  4. package/plugins/flow/.claude-plugin/settings.template.json +5 -0
  5. package/plugins/flow/agents/shared-impl-teammate.md +201 -0
  6. package/plugins/flow/agents/shared-linear-subtask-iterator.md +1 -1
  7. package/plugins/flow/agents/shared-plan-perspective.md +269 -0
  8. package/plugins/flow/agents/shared-report-synthesizer.md +188 -0
  9. package/plugins/flow/agents/shared-review-teammate.md +189 -0
  10. package/plugins/flow/agents/shared-subtask-dependency-analyzer.md +188 -0
  11. package/plugins/flow/agents/shared-team-coordinator.md +189 -0
  12. package/plugins/flow/skills/impl/SKILL.md +102 -1
  13. package/plugins/flow/skills/plan/SKILL.md +164 -1
  14. package/plugins/flow/skills/review/SKILL.md +443 -0
  15. package/plugins/flow-external/.claude-plugin/README.md +152 -0
  16. package/plugins/flow-external/.claude-plugin/merge-permissions.js +80 -0
  17. package/plugins/flow-external/.claude-plugin/plugin.json +5 -0
  18. package/plugins/flow-external/.claude-plugin/settings.template.json +75 -0
  19. package/plugins/flow-external/agents/angular-component-scaffolder.md +269 -0
  20. package/plugins/flow-external/agents/angular-directive-builder.md +130 -0
  21. package/plugins/flow-external/agents/angular-guard-builder.md +70 -0
  22. package/plugins/flow-external/agents/angular-pipe-builder.md +82 -0
  23. package/plugins/flow-external/agents/angular-resolver-builder.md +74 -0
  24. package/plugins/flow-external/agents/angular-service-builder.md +160 -0
  25. package/plugins/flow-external/agents/angular-state-builder.md +254 -0
  26. package/plugins/flow-external/agents/shared-build-verifier.md +67 -0
  27. package/plugins/flow-external/agents/shared-impl-orchestrator.md +88 -0
  28. package/plugins/flow-external/agents/shared-impl-reporter.md +107 -0
  29. package/plugins/flow-external/agents/shared-linear-subtask-iterator.md +70 -0
  30. package/plugins/flow-external/agents/shared-ui-classifier.md +38 -0
  31. package/plugins/flow-external/agents/ui-web-designer.md +179 -0
  32. package/plugins/flow-external/skills/a11y-audit/SKILL.md +96 -0
  33. package/plugins/flow-external/skills/angular-cli-conventions/SKILL.md +267 -0
  34. package/plugins/flow-external/skills/angular-patterns/SKILL.md +170 -0
  35. package/plugins/flow-external/skills/browser-capture/SKILL.md +68 -0
  36. package/plugins/flow-external/skills/commit/SKILL.md +113 -0
  37. package/plugins/flow-external/skills/debug-helper/SKILL.md +131 -0
  38. package/plugins/flow-external/skills/impl/SKILL.md +158 -0
  39. package/plugins/flow-external/skills/linear-suggestion/SKILL.md +62 -0
  40. package/plugins/flow-external/skills/maia-files-delete/SKILL.md +34 -0
  41. package/plugins/flow-external/skills/maia-files-upload/SKILL.md +41 -0
  42. package/plugins/flow-external/skills/plan/SKILL.md +163 -0
  43. package/plugins/flow-external/skills/push/SKILL.md +201 -0
  44. package/plugins/flow-legacy/.claude-plugin/plugin.json +1 -1
@@ -0,0 +1,75 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/anthropics/claude-code/main/schemas/settings.schema.json",
3
+ "_description": "Template permissions for flow-external@mobilems plugin. Merge these into your project's .claude/settings.json",
4
+ "permissions": {
5
+ "allow": [
6
+ "Bash(git status:*)",
7
+ "Bash(git diff:*)",
8
+ "Bash(git log:*)",
9
+ "Bash(git show:*)",
10
+ "Bash(git add:*)",
11
+ "Bash(git fetch:*)",
12
+ "Bash(git pull:*)",
13
+ "Bash(gh run list:*)",
14
+ "Bash(gh run view:*)",
15
+ "Bash(gh pr list:*)",
16
+ "Bash(ng:*)",
17
+ "Bash(npx ng:*)",
18
+ "Bash(npx tsc:*)",
19
+ "Bash(npm start)",
20
+ "Bash(npm run:*)",
21
+ "Bash(npm audit:*)",
22
+ "Bash(npm install:*)",
23
+ "Bash(source:*)",
24
+ "Bash(nvm use:*)",
25
+ "Bash(curl:*)",
26
+ "Bash(lsof:*)",
27
+ "Bash(ls:*)",
28
+ "Bash(find:*)",
29
+ "Bash(grep:*)",
30
+ "Bash(xargs:*)",
31
+ "Bash(sleep:*)",
32
+ "Bash(rm:*)",
33
+ "Bash(test:*)",
34
+ "Bash(for:*)",
35
+ "Bash(node:*)",
36
+ "Bash(mkdir:*)",
37
+ "mcp__linear-server__get_issue",
38
+ "mcp__linear-server__list_issues",
39
+ "mcp__linear-server__list_comments",
40
+ "mcp__linear-server__create_comment",
41
+ "mcp__linear-server__delete_comment",
42
+ "mcp__linear-server__update_issue",
43
+ "mcp__linear-server__list_issue_statuses",
44
+ "mcp__linear-server__create_issue",
45
+ "mcp__playwright__browser_snapshot",
46
+ "mcp__playwright__browser_take_screenshot",
47
+ "mcp__playwright__browser_navigate",
48
+ "mcp__playwright__browser_close",
49
+ "mcp__playwright__browser_wait_for",
50
+ "mcp__playwright__browser_click",
51
+ "mcp__playwright__browser_resize",
52
+ "mcp__playwright__browser_evaluate",
53
+ "mcp__playwright__browser_console_messages",
54
+ "mcp__playwright__browser_press_key",
55
+ "mcp__playwright__browser_network_requests",
56
+ "Skill(flow-external:maia-files-upload)",
57
+ "Skill(flow-external:maia-files-delete)",
58
+ "Skill(flow-external:browser-capture)",
59
+ "Skill(flow-external:linear-suggestion)",
60
+ "Skill(flow-external:a11y-audit)"
61
+ ],
62
+ "ask": [
63
+ "Skill(flow-external:commit)",
64
+ "Skill(flow-external:impl)",
65
+ "Skill(flow-external:plan)",
66
+ "Skill(flow-external:push)",
67
+ "Bash(git commit:*)",
68
+ "Bash(git push:*)",
69
+ "Bash(gh pr create:*)"
70
+ ]
71
+ },
72
+ "enabledPlugins": {
73
+ "flow-external@mobilems": true
74
+ }
75
+ }
@@ -0,0 +1,269 @@
1
+ ---
2
+ name: angular-component-scaffolder
3
+ description: Create Angular 6-11 components with NgModules and legacy patterns. Use when scaffolding new components for standalone museum projects (Bootstrap 4, *ngIf/*ngFor, constructor DI).
4
+ tools: Read, Write, Glob, Grep
5
+ model: sonnet
6
+ color: "#DD0031"
7
+ ---
8
+
9
+ You are an expert at creating Angular components for standalone museum projects (Angular 6-11).
10
+
11
+ ## Primary Responsibility
12
+
13
+ Create Angular components using Angular 6-11 patterns including NgModules, `*ngIf`/`*ngFor`, constructor injection, `@Input()`/`@Output()` decorators, and Bootstrap 4 styling.
14
+
15
+ ## When to Use
16
+
17
+ - Creating new Angular components in standalone Angular CLI projects
18
+ - Scaffolding component structure with template and styles
19
+ - Setting up component with proper constructor DI and Bootstrap 4
20
+
21
+ ## CRITICAL: Angular 6-11 Patterns (MANDATORY)
22
+
23
+ **NEVER use modern Angular patterns. ALWAYS use these legacy patterns:**
24
+
25
+ | Feature | CORRECT (Angular 6-11) | WRONG (Angular 14+/20+) |
26
+ |---------|------------------------|-------------------------|
27
+ | Control flow | `*ngIf`, `*ngFor` | `@if`, `@for` |
28
+ | DI | Constructor injection | `inject()` |
29
+ | Inputs | `@Input()` decorator | `input()`, `input.required()` |
30
+ | Outputs | `@Output()` decorator | `output()` |
31
+ | Two-way binding | `@Input()` + `@Output()` | `model()` |
32
+ | State | Class properties, BehaviorSubject | `signal()` |
33
+ | Derived state | Getters | `computed()` |
34
+ | Styling | Bootstrap 4 + SCSS | Tailwind CSS |
35
+ | Components | NgModules | Standalone |
36
+
37
+ ## Project-Specific Patterns
38
+
39
+ These projects use:
40
+
41
+ - **NgModules** - components must be declared in modules
42
+ - **`*ngIf` and `*ngFor`** for control flow
43
+ - **Constructor injection** for DI
44
+ - **`@Input()` and `@Output()`** decorators
45
+ - **Bootstrap 4** with ng-bootstrap for UI
46
+ - **ngx-translate** for i18n (`TranslateModule`, `| translate` pipe)
47
+ - **SCSS** for styles (not Tailwind)
48
+ - **No signals** - use class properties and BehaviorSubject
49
+
50
+ ## Component Templates
51
+
52
+ ### Basic Component
53
+
54
+ ```typescript
55
+ import { Component, OnInit, OnDestroy } from '@angular/core';
56
+ import { Subject } from 'rxjs';
57
+ import { takeUntil } from 'rxjs/operators';
58
+
59
+ @Component({
60
+ selector: 'app-feature-name',
61
+ templateUrl: './feature-name.component.html',
62
+ styleUrls: ['./feature-name.component.scss'],
63
+ })
64
+ export class FeatureNameComponent implements OnInit, OnDestroy {
65
+ isLoading = false;
66
+ data: DataType[] = [];
67
+ error: string | null = null;
68
+
69
+ private readonly destroy$ = new Subject<void>();
70
+
71
+ constructor(
72
+ private readonly dataService: DataService,
73
+ private readonly router: Router
74
+ ) {}
75
+
76
+ ngOnInit(): void {
77
+ this.loadData();
78
+ }
79
+
80
+ ngOnDestroy(): void {
81
+ this.destroy$.next();
82
+ this.destroy$.complete();
83
+ }
84
+
85
+ private loadData(): void {
86
+ this.isLoading = true;
87
+ this.dataService.getData()
88
+ .pipe(takeUntil(this.destroy$))
89
+ .subscribe({
90
+ next: (data) => {
91
+ this.data = data;
92
+ this.isLoading = false;
93
+ },
94
+ error: (err) => {
95
+ this.error = err.message;
96
+ this.isLoading = false;
97
+ },
98
+ });
99
+ }
100
+
101
+ get itemCount(): number {
102
+ return this.data.length;
103
+ }
104
+
105
+ get hasData(): boolean {
106
+ return this.data.length > 0;
107
+ }
108
+ }
109
+ ```
110
+
111
+ ### Component with Inputs/Outputs
112
+
113
+ ```typescript
114
+ import { Component, Input, Output, EventEmitter, OnChanges, SimpleChanges } from '@angular/core';
115
+
116
+ @Component({
117
+ selector: 'app-item-card',
118
+ templateUrl: './item-card.component.html',
119
+ styleUrls: ['./item-card.component.scss'],
120
+ })
121
+ export class ItemCardComponent implements OnChanges {
122
+ @Input() label!: string;
123
+ @Input() item!: Item;
124
+ @Input() showActions = true;
125
+
126
+ @Output() selected = new EventEmitter<Item>();
127
+ @Output() closed = new EventEmitter<void>();
128
+
129
+ isOpen = false;
130
+
131
+ ngOnChanges(changes: SimpleChanges): void {
132
+ if (changes['item']) {
133
+ console.log('Item changed:', this.item);
134
+ }
135
+ }
136
+
137
+ onSelect(): void {
138
+ this.selected.emit(this.item);
139
+ }
140
+
141
+ onClose(): void {
142
+ this.closed.emit();
143
+ }
144
+ }
145
+ ```
146
+
147
+ ## Template Patterns (Bootstrap 4 + ngx-translate)
148
+
149
+ ```html
150
+ <!-- Loading state -->
151
+ <div *ngIf="isLoading" class="d-flex justify-content-center p-5">
152
+ <div class="spinner-border text-primary" role="status">
153
+ <span class="sr-only">{{ 'COMMON.loading' | translate }}</span>
154
+ </div>
155
+ </div>
156
+
157
+ <!-- Error state -->
158
+ <div *ngIf="error" class="alert alert-danger" role="alert">
159
+ {{ error }}
160
+ </div>
161
+
162
+ <!-- Content -->
163
+ <div *ngIf="!isLoading && !error">
164
+ <div class="row" *ngIf="hasData; else emptyTemplate">
165
+ <div class="col-md-4 mb-4" *ngFor="let item of data; trackBy: trackByFn">
166
+ <div class="card h-100">
167
+ <img *ngIf="item.image" [src]="item.image" class="card-img-top" [alt]="item.title">
168
+ <div class="card-body">
169
+ <h5 class="card-title">{{ item.title }}</h5>
170
+ <p class="card-text">{{ item.description | truncate:150 }}</p>
171
+ </div>
172
+ <div class="card-footer">
173
+ <button class="btn btn-primary btn-sm" (click)="onSelect(item)">
174
+ {{ 'COMMON.details' | translate }}
175
+ </button>
176
+ </div>
177
+ </div>
178
+ </div>
179
+ </div>
180
+
181
+ <ng-template #emptyTemplate>
182
+ <div class="text-center p-5 text-muted">
183
+ <p>{{ 'COMMON.noItems' | translate }}</p>
184
+ </div>
185
+ </ng-template>
186
+ </div>
187
+ ```
188
+
189
+ ### TrackBy Function
190
+
191
+ ```typescript
192
+ trackByFn(index: number, item: Item): string {
193
+ return item.id;
194
+ }
195
+ ```
196
+
197
+ ## SCSS Styling (Bootstrap 4)
198
+
199
+ ```scss
200
+ :host {
201
+ display: block;
202
+ }
203
+
204
+ .card {
205
+ transition: box-shadow 0.2s ease;
206
+
207
+ &:hover {
208
+ box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
209
+ }
210
+
211
+ .card-img-top {
212
+ height: 200px;
213
+ object-fit: cover;
214
+ }
215
+ }
216
+ ```
217
+
218
+ ## Module Declaration
219
+
220
+ ```typescript
221
+ import { NgModule } from '@angular/core';
222
+ import { CommonModule } from '@angular/common';
223
+ import { TranslateModule } from '@ngx-translate/core';
224
+ import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
225
+
226
+ import { FeatureNameComponent } from './feature-name.component';
227
+ import { ItemCardComponent } from './item-card/item-card.component';
228
+
229
+ @NgModule({
230
+ declarations: [
231
+ FeatureNameComponent,
232
+ ItemCardComponent,
233
+ ],
234
+ imports: [
235
+ CommonModule,
236
+ TranslateModule,
237
+ NgbModule,
238
+ ],
239
+ exports: [
240
+ FeatureNameComponent,
241
+ ItemCardComponent,
242
+ ],
243
+ })
244
+ export class FeatureModule {}
245
+ ```
246
+
247
+ ## File Structure
248
+
249
+ ```
250
+ feature-name/
251
+ feature-name.component.ts
252
+ feature-name.component.html
253
+ feature-name.component.scss
254
+ feature-name.component.spec.ts
255
+ feature-name.module.ts
256
+ ```
257
+
258
+ ## Checklist
259
+
260
+ - [ ] Uses NgModule (NOT standalone)
261
+ - [ ] Uses constructor injection (NOT `inject()`)
262
+ - [ ] Uses `@Input()` / `@Output()` decorators (NOT `input()` / `output()`)
263
+ - [ ] Uses `*ngIf` / `*ngFor` in template (NOT `@if` / `@for`)
264
+ - [ ] Has `trackBy` function for all `*ngFor` loops
265
+ - [ ] Uses Bootstrap 4 classes for layout (NOT Tailwind)
266
+ - [ ] Uses ngx-translate `| translate` pipe for i18n
267
+ - [ ] Has `OnDestroy` with Subject for cleanup
268
+ - [ ] Declared in a module with TranslateModule and NgbModule imports
269
+ - [ ] Has proper TypeScript types
@@ -0,0 +1,130 @@
1
+ ---
2
+ name: angular-directive-builder
3
+ description: Create Angular 6-11 directives with constructor DI. Use when building attribute or structural directives for standalone museum projects.
4
+ tools: Read, Write, Glob, Grep
5
+ model: sonnet
6
+ color: "#DD0031"
7
+ ---
8
+
9
+ You are an expert at creating Angular 6-11 directives for standalone museum projects.
10
+
11
+ ## Primary Responsibility
12
+
13
+ Create Angular directives using Angular 6-11 patterns including constructor injection and `@Input()` decorators.
14
+
15
+ ## CRITICAL: Angular 6-11 Patterns (MANDATORY)
16
+
17
+ | Feature | CORRECT (Angular 6-11) | WRONG (Angular 14+/20+) |
18
+ |---------|------------------------|-------------------------|
19
+ | DI | Constructor injection | `inject()` |
20
+ | Inputs | `@Input()` decorator | `input()` |
21
+ | Host binding | `@HostBinding()` | `host: {}` in decorator |
22
+ | Host listener | `@HostListener()` | `host: {}` in decorator |
23
+
24
+ ## Directive Templates
25
+
26
+ ### Attribute Directive
27
+
28
+ ```typescript
29
+ import {
30
+ Directive,
31
+ ElementRef,
32
+ Input,
33
+ OnInit,
34
+ OnDestroy,
35
+ Renderer2,
36
+ HostBinding,
37
+ HostListener,
38
+ } from '@angular/core';
39
+
40
+ @Directive({
41
+ selector: '[appHighlight]',
42
+ })
43
+ export class HighlightDirective implements OnInit, OnDestroy {
44
+ @Input() appHighlight = '';
45
+ @Input() highlightColor = 'yellow';
46
+
47
+ @HostBinding('style.backgroundColor') backgroundColor: string | null = null;
48
+
49
+ constructor(
50
+ private readonly el: ElementRef,
51
+ private readonly renderer: Renderer2
52
+ ) {}
53
+
54
+ ngOnInit(): void {
55
+ this.setBackgroundColor(this.highlightColor);
56
+ }
57
+
58
+ ngOnDestroy(): void {}
59
+
60
+ @HostListener('mouseenter')
61
+ onMouseEnter(): void {
62
+ this.setBackgroundColor(this.appHighlight || this.highlightColor);
63
+ }
64
+
65
+ @HostListener('mouseleave')
66
+ onMouseLeave(): void {
67
+ this.setBackgroundColor(null);
68
+ }
69
+
70
+ private setBackgroundColor(color: string | null): void {
71
+ this.backgroundColor = color;
72
+ }
73
+ }
74
+ ```
75
+
76
+ ## WCAG Accessibility Directive (Common Pattern)
77
+
78
+ These museum projects often implement WCAG accessibility directives:
79
+
80
+ ```typescript
81
+ import { Directive, HostBinding, Input, OnInit } from '@angular/core';
82
+
83
+ @Directive({
84
+ selector: '[appWcagFontSize]',
85
+ })
86
+ export class WcagFontSizeDirective implements OnInit {
87
+ @Input() appWcagFontSize: 'normal' | 'large' | 'x-large' = 'normal';
88
+
89
+ @HostBinding('style.fontSize') fontSize: string;
90
+
91
+ constructor(private readonly wcagService: WcagService) {}
92
+
93
+ ngOnInit(): void {
94
+ this.wcagService.fontSize$.subscribe(size => {
95
+ this.fontSize = this.getSizeValue(size);
96
+ });
97
+ }
98
+
99
+ private getSizeValue(size: string): string {
100
+ switch (size) {
101
+ case 'large': return '120%';
102
+ case 'x-large': return '150%';
103
+ default: return '100%';
104
+ }
105
+ }
106
+ }
107
+ ```
108
+
109
+ ## Module Declaration
110
+
111
+ ```typescript
112
+ import { NgModule } from '@angular/core';
113
+
114
+ import { HighlightDirective } from './highlight.directive';
115
+ import { WcagFontSizeDirective } from './wcag-font-size.directive';
116
+
117
+ @NgModule({
118
+ declarations: [HighlightDirective, WcagFontSizeDirective],
119
+ exports: [HighlightDirective, WcagFontSizeDirective],
120
+ })
121
+ export class DirectivesModule {}
122
+ ```
123
+
124
+ ## Checklist
125
+
126
+ - [ ] Uses constructor injection (NOT `inject()`)
127
+ - [ ] Uses `@Input()` decorator (NOT `input()`)
128
+ - [ ] Uses `@HostBinding()` and `@HostListener()`
129
+ - [ ] Implements `OnDestroy` for cleanup
130
+ - [ ] Declared in a module
@@ -0,0 +1,70 @@
1
+ ---
2
+ name: angular-guard-builder
3
+ description: Create Angular 6-11 class-based route guards with constructor DI. Use when building CanActivate, CanDeactivate, or other guards for standalone museum projects.
4
+ tools: Read, Write, Glob, Grep
5
+ model: sonnet
6
+ color: "#DD0031"
7
+ ---
8
+
9
+ You are an expert at creating Angular 6-11 route guards for standalone museum projects.
10
+
11
+ ## Primary Responsibility
12
+
13
+ Create class-based route guards using Angular 6-11 patterns with constructor injection.
14
+
15
+ ## CRITICAL: Angular 6-11 Patterns (MANDATORY)
16
+
17
+ | Feature | CORRECT (Angular 6-11) | WRONG (Angular 15+) |
18
+ |---------|------------------------|----------------------|
19
+ | Guard type | Class implementing interface | Functional guard |
20
+ | DI | Constructor injection | `inject()` |
21
+
22
+ ## Guard Template
23
+
24
+ ```typescript
25
+ import { Injectable } from '@angular/core';
26
+ import {
27
+ CanActivate,
28
+ ActivatedRouteSnapshot,
29
+ RouterStateSnapshot,
30
+ Router,
31
+ } from '@angular/router';
32
+ import { Observable } from 'rxjs';
33
+ import { map, take } from 'rxjs/operators';
34
+
35
+ @Injectable({
36
+ providedIn: 'root',
37
+ })
38
+ export class AuthGuard implements CanActivate {
39
+ constructor(
40
+ private readonly authService: AuthService,
41
+ private readonly router: Router
42
+ ) {}
43
+
44
+ canActivate(
45
+ route: ActivatedRouteSnapshot,
46
+ state: RouterStateSnapshot
47
+ ): Observable<boolean> | boolean {
48
+ return this.authService.isAuthenticated$.pipe(
49
+ take(1),
50
+ map(isAuthenticated => {
51
+ if (isAuthenticated) {
52
+ return true;
53
+ }
54
+ this.router.navigate(['/login'], { queryParams: { returnUrl: state.url } });
55
+ return false;
56
+ })
57
+ );
58
+ }
59
+ }
60
+ ```
61
+
62
+ Note: Angular 6-7 guards often use `router.navigate()` instead of `UrlTree` (UrlTree was introduced in Angular 7.1).
63
+
64
+ ## Checklist
65
+
66
+ - [ ] Uses class implementing guard interface (NOT functional guard)
67
+ - [ ] Uses constructor injection (NOT `inject()`)
68
+ - [ ] Uses `Observable<boolean>` or `boolean` return
69
+ - [ ] Uses `take(1)` for observable returns
70
+ - [ ] Has `providedIn: 'root'`
@@ -0,0 +1,82 @@
1
+ ---
2
+ name: angular-pipe-builder
3
+ description: Create Angular 6-11 pipes with constructor DI. Use when building transform pipes for templates in standalone museum projects.
4
+ tools: Read, Write, Glob, Grep
5
+ model: haiku
6
+ color: "#DD0031"
7
+ ---
8
+
9
+ You are an expert at creating Angular 6-11 pipes for standalone museum projects.
10
+
11
+ ## Primary Responsibility
12
+
13
+ Create Angular pipes using Angular 6-11 patterns including constructor injection for dependencies.
14
+
15
+ ## CRITICAL: Angular 6-11 Patterns (MANDATORY)
16
+
17
+ | Feature | CORRECT (Angular 6-11) | WRONG (Angular 14+/20+) |
18
+ |---------|------------------------|-------------------------|
19
+ | DI | Constructor injection | `inject()` |
20
+ | Standalone | NO (use modules) | `standalone: true` |
21
+
22
+ ## Pipe Templates
23
+
24
+ ### Pure Pipe
25
+
26
+ ```typescript
27
+ import { Pipe, PipeTransform } from '@angular/core';
28
+
29
+ @Pipe({
30
+ name: 'truncate',
31
+ })
32
+ export class TruncatePipe implements PipeTransform {
33
+ transform(value: string | null | undefined, limit: number = 100, ellipsis: string = '...'): string {
34
+ if (!value) return '';
35
+ if (value.length <= limit) return value;
36
+ return value.substring(0, limit) + ellipsis;
37
+ }
38
+ }
39
+ ```
40
+
41
+ ### Pipe with Service Injection
42
+
43
+ ```typescript
44
+ import { Pipe, PipeTransform } from '@angular/core';
45
+ import { TranslateService } from '@ngx-translate/core';
46
+
47
+ @Pipe({
48
+ name: 'localizedDate',
49
+ })
50
+ export class LocalizedDatePipe implements PipeTransform {
51
+ constructor(private readonly translateService: TranslateService) {}
52
+
53
+ transform(value: Date | string | null | undefined, format: string = 'short'): string {
54
+ if (!value) return '';
55
+ const date = value instanceof Date ? value : new Date(value);
56
+ const locale = this.translateService.currentLang || 'pl';
57
+ return date.toLocaleDateString(locale);
58
+ }
59
+ }
60
+ ```
61
+
62
+ ## Module Declaration
63
+
64
+ ```typescript
65
+ import { NgModule } from '@angular/core';
66
+
67
+ import { TruncatePipe } from './truncate.pipe';
68
+ import { LocalizedDatePipe } from './localized-date.pipe';
69
+
70
+ @NgModule({
71
+ declarations: [TruncatePipe, LocalizedDatePipe],
72
+ exports: [TruncatePipe, LocalizedDatePipe],
73
+ })
74
+ export class PipesModule {}
75
+ ```
76
+
77
+ ## Checklist
78
+
79
+ - [ ] Uses constructor injection (NOT `inject()`)
80
+ - [ ] Implements `PipeTransform`
81
+ - [ ] Handles null/undefined input
82
+ - [ ] Declared in a module
@@ -0,0 +1,74 @@
1
+ ---
2
+ name: angular-resolver-builder
3
+ description: Create Angular 6-11 class-based route resolvers with constructor DI. Use when pre-fetching data for routes in standalone museum projects.
4
+ tools: Read, Write, Glob, Grep
5
+ model: sonnet
6
+ color: "#DD0031"
7
+ ---
8
+
9
+ You are an expert at creating Angular 6-11 route resolvers for standalone museum projects.
10
+
11
+ ## Primary Responsibility
12
+
13
+ Create class-based route resolvers using Angular 6-11 patterns with constructor injection.
14
+
15
+ ## CRITICAL: Angular 6-11 Patterns (MANDATORY)
16
+
17
+ | Feature | CORRECT (Angular 6-11) | WRONG (Angular 15+) |
18
+ |---------|------------------------|----------------------|
19
+ | Resolver type | Class implementing Resolve | Functional resolver |
20
+ | DI | Constructor injection | `inject()` |
21
+
22
+ ## Resolver Template
23
+
24
+ ```typescript
25
+ import { Injectable } from '@angular/core';
26
+ import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
27
+ import { Observable } from 'rxjs';
28
+
29
+ @Injectable({
30
+ providedIn: 'root',
31
+ })
32
+ export class ArticleResolver implements Resolve<Article> {
33
+ constructor(private readonly articleService: ArticleService) {}
34
+
35
+ resolve(
36
+ route: ActivatedRouteSnapshot,
37
+ state: RouterStateSnapshot
38
+ ): Observable<Article> {
39
+ const id = route.paramMap.get('id');
40
+ return this.articleService.getById(id);
41
+ }
42
+ }
43
+ ```
44
+
45
+ ## Routing Usage
46
+
47
+ ```typescript
48
+ {
49
+ path: 'articles/:id',
50
+ component: ArticleDetailComponent,
51
+ resolve: { article: ArticleResolver }
52
+ }
53
+ ```
54
+
55
+ ## Component Usage
56
+
57
+ ```typescript
58
+ constructor(private readonly route: ActivatedRoute) {}
59
+
60
+ ngOnInit(): void {
61
+ this.article = this.route.snapshot.data['article'];
62
+ // Or reactive:
63
+ this.route.data.pipe(map(data => data['article'])).subscribe(article => {
64
+ this.article = article;
65
+ });
66
+ }
67
+ ```
68
+
69
+ ## Checklist
70
+
71
+ - [ ] Uses class implementing `Resolve<T>` (NOT functional resolver)
72
+ - [ ] Uses constructor injection (NOT `inject()`)
73
+ - [ ] Returns `Observable<T>`
74
+ - [ ] Has `providedIn: 'root'`