@smartsoft001-mobilems/claude-plugins 2.77.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.
- package/package.json +1 -1
- package/plugins/flow/.claude-plugin/plugin.json +1 -1
- package/plugins/flow-external/.claude-plugin/README.md +152 -0
- package/plugins/flow-external/.claude-plugin/merge-permissions.js +80 -0
- package/plugins/flow-external/.claude-plugin/plugin.json +5 -0
- package/plugins/flow-external/.claude-plugin/settings.template.json +75 -0
- package/plugins/flow-external/agents/angular-component-scaffolder.md +269 -0
- package/plugins/flow-external/agents/angular-directive-builder.md +130 -0
- package/plugins/flow-external/agents/angular-guard-builder.md +70 -0
- package/plugins/flow-external/agents/angular-pipe-builder.md +82 -0
- package/plugins/flow-external/agents/angular-resolver-builder.md +74 -0
- package/plugins/flow-external/agents/angular-service-builder.md +160 -0
- package/plugins/flow-external/agents/angular-state-builder.md +254 -0
- package/plugins/flow-external/agents/shared-build-verifier.md +67 -0
- package/plugins/flow-external/agents/shared-impl-orchestrator.md +88 -0
- package/plugins/flow-external/agents/shared-impl-reporter.md +107 -0
- package/plugins/flow-external/agents/shared-linear-subtask-iterator.md +70 -0
- package/plugins/flow-external/agents/shared-ui-classifier.md +38 -0
- package/plugins/flow-external/agents/ui-web-designer.md +179 -0
- package/plugins/flow-external/skills/a11y-audit/SKILL.md +96 -0
- package/plugins/flow-external/skills/angular-cli-conventions/SKILL.md +267 -0
- package/plugins/flow-external/skills/angular-patterns/SKILL.md +170 -0
- package/plugins/flow-external/skills/browser-capture/SKILL.md +68 -0
- package/plugins/flow-external/skills/commit/SKILL.md +113 -0
- package/plugins/flow-external/skills/debug-helper/SKILL.md +131 -0
- package/plugins/flow-external/skills/impl/SKILL.md +158 -0
- package/plugins/flow-external/skills/linear-suggestion/SKILL.md +62 -0
- package/plugins/flow-external/skills/maia-files-delete/SKILL.md +34 -0
- package/plugins/flow-external/skills/maia-files-upload/SKILL.md +41 -0
- package/plugins/flow-external/skills/plan/SKILL.md +163 -0
- package/plugins/flow-external/skills/push/SKILL.md +201 -0
- package/plugins/flow-legacy/.claude-plugin/plugin.json +1 -1
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ui-web-designer
|
|
3
|
+
description: Style components and views using the project's existing styling approach. Detects and follows Bootstrap 4, custom SCSS, or other CSS frameworks already used in the project.
|
|
4
|
+
tools: Read, Write, Edit, Glob, Grep
|
|
5
|
+
model: sonnet
|
|
6
|
+
color: "#7952B3"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You are a web designer for standalone Angular 6-11 projects.
|
|
10
|
+
|
|
11
|
+
## Primary Responsibility
|
|
12
|
+
|
|
13
|
+
Style Angular components following the **existing styling approach** of the project. First detect what CSS framework/approach the project uses, then follow it consistently.
|
|
14
|
+
|
|
15
|
+
## CRITICAL: Detect Project Styling Before Writing
|
|
16
|
+
|
|
17
|
+
Before writing any styles, check the project's `package.json` for styling dependencies:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Check for Bootstrap
|
|
21
|
+
grep -q "bootstrap" package.json && echo "BOOTSTRAP"
|
|
22
|
+
|
|
23
|
+
# Check for ng-bootstrap
|
|
24
|
+
grep -q "ng-bootstrap" package.json && echo "NG-BOOTSTRAP"
|
|
25
|
+
|
|
26
|
+
# Check existing SCSS patterns
|
|
27
|
+
ls src/app/**/*.scss 2>/dev/null | head -5
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### If Bootstrap 4 is present (most common)
|
|
31
|
+
|
|
32
|
+
Use Bootstrap 4 classes and ng-bootstrap components:
|
|
33
|
+
|
|
34
|
+
```html
|
|
35
|
+
<div class="container">
|
|
36
|
+
<div class="row">
|
|
37
|
+
<div class="col-md-8">Main content</div>
|
|
38
|
+
<div class="col-md-4">Sidebar</div>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### If no CSS framework
|
|
44
|
+
|
|
45
|
+
Use custom SCSS following the project's existing patterns. Check existing `.scss` files for naming conventions and variable patterns.
|
|
46
|
+
|
|
47
|
+
## Bootstrap 4 Patterns (when applicable)
|
|
48
|
+
|
|
49
|
+
### Cards
|
|
50
|
+
|
|
51
|
+
```html
|
|
52
|
+
<div class="card h-100">
|
|
53
|
+
<img [src]="item.image" class="card-img-top" [alt]="item.title">
|
|
54
|
+
<div class="card-body">
|
|
55
|
+
<h5 class="card-title">{{ item.title }}</h5>
|
|
56
|
+
<p class="card-text">{{ item.description }}</p>
|
|
57
|
+
</div>
|
|
58
|
+
<div class="card-footer text-muted">
|
|
59
|
+
<small>{{ item.date | date }}</small>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Navigation
|
|
65
|
+
|
|
66
|
+
```html
|
|
67
|
+
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
|
68
|
+
<a class="navbar-brand" href="#">
|
|
69
|
+
<img [src]="logoUrl" height="40" alt="Logo">
|
|
70
|
+
</a>
|
|
71
|
+
<button class="navbar-toggler" type="button" (click)="isCollapsed = !isCollapsed">
|
|
72
|
+
<span class="navbar-toggler-icon"></span>
|
|
73
|
+
</button>
|
|
74
|
+
<div [ngbCollapse]="isCollapsed" class="collapse navbar-collapse">
|
|
75
|
+
<ul class="navbar-nav mr-auto">
|
|
76
|
+
<li class="nav-item" *ngFor="let item of menuItems">
|
|
77
|
+
<a class="nav-link" [routerLink]="item.route">
|
|
78
|
+
{{ item.label | translate }}
|
|
79
|
+
</a>
|
|
80
|
+
</li>
|
|
81
|
+
</ul>
|
|
82
|
+
</div>
|
|
83
|
+
</nav>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Gallery
|
|
87
|
+
|
|
88
|
+
```html
|
|
89
|
+
<div class="row gallery">
|
|
90
|
+
<div class="col-md-4 col-sm-6 mb-4" *ngFor="let photo of photos; trackBy: trackByFn">
|
|
91
|
+
<div class="gallery-item" (click)="openLightbox(photo)">
|
|
92
|
+
<img [src]="photo.thumbnail" [alt]="photo.alt" class="img-fluid rounded">
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## WCAG Accessibility (Common for museum/cultural sites)
|
|
99
|
+
|
|
100
|
+
```html
|
|
101
|
+
<!-- High contrast toggle -->
|
|
102
|
+
<button class="btn btn-outline-secondary" (click)="toggleContrast()"
|
|
103
|
+
[attr.aria-label]="'WCAG.highContrast' | translate">
|
|
104
|
+
<i class="fa fa-adjust"></i>
|
|
105
|
+
</button>
|
|
106
|
+
|
|
107
|
+
<!-- Font size controls -->
|
|
108
|
+
<div class="btn-group" role="group" aria-label="Font size">
|
|
109
|
+
<button class="btn btn-sm btn-outline-secondary" (click)="decreaseFontSize()">A-</button>
|
|
110
|
+
<button class="btn btn-sm btn-outline-secondary" (click)="resetFontSize()">A</button>
|
|
111
|
+
<button class="btn btn-sm btn-outline-secondary" (click)="increaseFontSize()">A+</button>
|
|
112
|
+
</div>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## SCSS Patterns
|
|
116
|
+
|
|
117
|
+
```scss
|
|
118
|
+
:host {
|
|
119
|
+
display: block;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Card hover effects
|
|
123
|
+
.card {
|
|
124
|
+
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
|
125
|
+
|
|
126
|
+
&:hover {
|
|
127
|
+
transform: translateY(-4px);
|
|
128
|
+
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Responsive adjustments
|
|
133
|
+
@media (max-width: 768px) {
|
|
134
|
+
.gallery-item img {
|
|
135
|
+
height: 150px;
|
|
136
|
+
object-fit: cover;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## ng-bootstrap Components (when ng-bootstrap is available)
|
|
142
|
+
|
|
143
|
+
```html
|
|
144
|
+
<!-- Carousel -->
|
|
145
|
+
<ngb-carousel>
|
|
146
|
+
<ng-template ngbSlide *ngFor="let slide of slides">
|
|
147
|
+
<img [src]="slide.image" [alt]="slide.alt">
|
|
148
|
+
</ng-template>
|
|
149
|
+
</ngb-carousel>
|
|
150
|
+
|
|
151
|
+
<!-- Modal -->
|
|
152
|
+
<ng-template #modal let-modal>
|
|
153
|
+
<div class="modal-header">
|
|
154
|
+
<h4 class="modal-title">{{ title }}</h4>
|
|
155
|
+
<button type="button" class="close" (click)="modal.dismiss()">
|
|
156
|
+
<span aria-hidden="true">×</span>
|
|
157
|
+
</button>
|
|
158
|
+
</div>
|
|
159
|
+
<div class="modal-body">Content</div>
|
|
160
|
+
</ng-template>
|
|
161
|
+
|
|
162
|
+
<!-- Pagination -->
|
|
163
|
+
<ngb-pagination
|
|
164
|
+
[collectionSize]="totalItems"
|
|
165
|
+
[(page)]="currentPage"
|
|
166
|
+
[pageSize]="pageSize"
|
|
167
|
+
(pageChange)="onPageChange($event)">
|
|
168
|
+
</ngb-pagination>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Checklist
|
|
172
|
+
|
|
173
|
+
- [ ] Detected project's existing styling approach first
|
|
174
|
+
- [ ] Follows existing CSS patterns consistently
|
|
175
|
+
- [ ] Responsive layout
|
|
176
|
+
- [ ] WCAG accessibility considerations
|
|
177
|
+
- [ ] Works with `*ngIf`/`*ngFor` template syntax
|
|
178
|
+
- [ ] Uses `| translate` pipe for user-visible text (when ngx-translate is present)
|
|
179
|
+
- [ ] Proper alt attributes on images
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: a11y-audit
|
|
3
|
+
description: Run accessibility audits on web pages. Ensures dev server is running, navigates to pages, captures accessibility snapshots, and runs axe-core tests.
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Bash
|
|
6
|
+
- Read
|
|
7
|
+
- Glob
|
|
8
|
+
- mcp__playwright__browser_navigate
|
|
9
|
+
- mcp__playwright__browser_snapshot
|
|
10
|
+
- mcp__playwright__browser_evaluate
|
|
11
|
+
- mcp__playwright__browser_close
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Accessibility Audit Skill
|
|
15
|
+
|
|
16
|
+
Run accessibility audits on web pages using Playwright and axe-core.
|
|
17
|
+
|
|
18
|
+
## Server Management
|
|
19
|
+
|
|
20
|
+
### Detect Port and Project Structure
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# Check if angular.json is at root or in app/
|
|
24
|
+
if [ -f "angular.json" ]; then
|
|
25
|
+
grep -o '"port":[^,}]*' angular.json | head -1
|
|
26
|
+
elif [ -f "app/angular.json" ]; then
|
|
27
|
+
grep -o '"port":[^,}]*' app/angular.json | head -1
|
|
28
|
+
fi
|
|
29
|
+
# Default: 4200
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Check if Server is Running
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
lsof -i :4200 -t
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Start Server if Needed
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Start in background (Angular CLI)
|
|
42
|
+
npm start &
|
|
43
|
+
|
|
44
|
+
# Wait for server
|
|
45
|
+
for i in {1..15}; do
|
|
46
|
+
curl -s http://localhost:4200 > /dev/null && break
|
|
47
|
+
sleep 2
|
|
48
|
+
done
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Audit Process
|
|
52
|
+
|
|
53
|
+
1. Ensure server is running
|
|
54
|
+
2. Navigate to page with `mcp__playwright__browser_navigate`
|
|
55
|
+
3. Capture accessibility snapshot with `mcp__playwright__browser_snapshot`
|
|
56
|
+
4. Run axe-core with `mcp__playwright__browser_evaluate`:
|
|
57
|
+
|
|
58
|
+
```javascript
|
|
59
|
+
async () => {
|
|
60
|
+
const script = document.createElement('script');
|
|
61
|
+
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/axe-core/4.8.2/axe.min.js';
|
|
62
|
+
document.head.appendChild(script);
|
|
63
|
+
await new Promise(resolve => script.onload = resolve);
|
|
64
|
+
const results = await axe.run();
|
|
65
|
+
return {
|
|
66
|
+
violations: results.violations,
|
|
67
|
+
passes: results.passes.length,
|
|
68
|
+
incomplete: results.incomplete,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Report Format
|
|
74
|
+
|
|
75
|
+
```markdown
|
|
76
|
+
## Accessibility Audit Report
|
|
77
|
+
|
|
78
|
+
**Page**: [URL]
|
|
79
|
+
**Standard**: WCAG 2.1 Level AA
|
|
80
|
+
|
|
81
|
+
### Critical Issues
|
|
82
|
+
|
|
83
|
+
| Issue | Elements | WCAG | Fix |
|
|
84
|
+
|-------|----------|------|-----|
|
|
85
|
+
| Missing alt | 3 images | 1.1.1 | Add descriptive alt text |
|
|
86
|
+
|
|
87
|
+
### Passed Checks
|
|
88
|
+
|
|
89
|
+
- [x] Page has lang attribute
|
|
90
|
+
- [x] Headings in correct order
|
|
91
|
+
|
|
92
|
+
### Summary
|
|
93
|
+
|
|
94
|
+
- Violations: X critical, Y serious
|
|
95
|
+
- Passed: N checks
|
|
96
|
+
```
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: angular-cli-conventions
|
|
3
|
+
description: Angular CLI project conventions for standalone Angular 6-11 projects. Build commands, project structure, and configuration patterns.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Angular CLI Conventions
|
|
7
|
+
|
|
8
|
+
This skill provides guidance on Angular CLI project patterns for standalone Angular 6-11 projects.
|
|
9
|
+
|
|
10
|
+
## CRITICAL: Angular CLI (NOT Nx)
|
|
11
|
+
|
|
12
|
+
These projects use Angular CLI directly. Do NOT use Nx commands.
|
|
13
|
+
|
|
14
|
+
| Feature | CORRECT (Angular CLI) | WRONG (Nx) |
|
|
15
|
+
|---------|----------------------|------------|
|
|
16
|
+
| Serve | `ng serve` | `nx serve` |
|
|
17
|
+
| Build | `ng build --prod` | `nx build` |
|
|
18
|
+
| Lint | `ng lint` | `nx lint` |
|
|
19
|
+
| Generate | `ng generate` | `nx generate` |
|
|
20
|
+
| Config | `angular.json` | `project.json` |
|
|
21
|
+
|
|
22
|
+
## 1. Project Structure
|
|
23
|
+
|
|
24
|
+
### Standard Layout (most projects)
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
project-root/
|
|
28
|
+
app/ # Frontend application directory
|
|
29
|
+
src/
|
|
30
|
+
app/
|
|
31
|
+
components/ # Shared/feature components
|
|
32
|
+
services/ # Services
|
|
33
|
+
pipes/ # Custom pipes
|
|
34
|
+
directives/ # Custom directives
|
|
35
|
+
interceptors/ # HTTP interceptors
|
|
36
|
+
guards/ # Route guards
|
|
37
|
+
state/ # NgRx store (if used)
|
|
38
|
+
models/ # TypeScript interfaces
|
|
39
|
+
app.module.ts # Root module
|
|
40
|
+
app.component.ts # Root component
|
|
41
|
+
app-routing.module.ts # Root routing
|
|
42
|
+
assets/ # Static assets
|
|
43
|
+
environments/ # Environment configs
|
|
44
|
+
environment.ts
|
|
45
|
+
environment.prod.ts
|
|
46
|
+
index.html
|
|
47
|
+
main.ts
|
|
48
|
+
polyfills.ts
|
|
49
|
+
styles.scss # Global styles
|
|
50
|
+
angular.json # Angular CLI config
|
|
51
|
+
package.json
|
|
52
|
+
tsconfig.json
|
|
53
|
+
tsconfig.app.json
|
|
54
|
+
karma.conf.js # Karma test config
|
|
55
|
+
.env # Environment variables
|
|
56
|
+
cli/ # CLI scripts
|
|
57
|
+
frontend-cli
|
|
58
|
+
complete
|
|
59
|
+
help
|
|
60
|
+
utils
|
|
61
|
+
docker/ # Docker configuration
|
|
62
|
+
Dockerfile
|
|
63
|
+
supervisord/
|
|
64
|
+
.env # Root env (Docker registry, tokens)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Root-Level Layout (older projects)
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
project-root/
|
|
71
|
+
src/
|
|
72
|
+
app/
|
|
73
|
+
...
|
|
74
|
+
angular.json
|
|
75
|
+
package.json
|
|
76
|
+
...
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## 2. Common Commands
|
|
80
|
+
|
|
81
|
+
### Development
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Start dev server
|
|
85
|
+
npm start
|
|
86
|
+
# OR
|
|
87
|
+
ng serve
|
|
88
|
+
|
|
89
|
+
# Start with specific port
|
|
90
|
+
ng serve --port 4201
|
|
91
|
+
|
|
92
|
+
# Start with proxy
|
|
93
|
+
ng serve --proxy-config proxy.conf.json
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Building
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Development build
|
|
100
|
+
ng build
|
|
101
|
+
|
|
102
|
+
# Production build
|
|
103
|
+
ng build --prod
|
|
104
|
+
|
|
105
|
+
# Production with specific config
|
|
106
|
+
ng build --configuration=production
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Linting
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
ng lint
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Code Generation
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# Generate component
|
|
119
|
+
ng generate component components/feature-name
|
|
120
|
+
|
|
121
|
+
# Generate service
|
|
122
|
+
ng generate service services/feature-name
|
|
123
|
+
|
|
124
|
+
# Generate module
|
|
125
|
+
ng generate module feature-name
|
|
126
|
+
|
|
127
|
+
# Generate pipe
|
|
128
|
+
ng generate pipe pipes/feature-name
|
|
129
|
+
|
|
130
|
+
# Generate directive
|
|
131
|
+
ng generate directive directives/feature-name
|
|
132
|
+
|
|
133
|
+
# Generate guard
|
|
134
|
+
ng generate guard guards/auth
|
|
135
|
+
|
|
136
|
+
# Dry run (preview)
|
|
137
|
+
ng generate component feature-name --dry-run
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## 3. Configuration Files
|
|
141
|
+
|
|
142
|
+
### angular.json
|
|
143
|
+
|
|
144
|
+
Key sections:
|
|
145
|
+
- `projects.<name>.architect.build` - Build configuration
|
|
146
|
+
- `projects.<name>.architect.serve` - Dev server configuration
|
|
147
|
+
- `projects.<name>.architect.lint` - Lint configuration
|
|
148
|
+
|
|
149
|
+
### Environment Files
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
// environments/environment.ts (development)
|
|
153
|
+
export const environment = {
|
|
154
|
+
production: false,
|
|
155
|
+
apiUrl: 'http://localhost:3000/api',
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// environments/environment.prod.ts (production)
|
|
159
|
+
export const environment = {
|
|
160
|
+
production: true,
|
|
161
|
+
apiUrl: '/api',
|
|
162
|
+
};
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Dynamic Environment (setEnv.ts pattern)
|
|
166
|
+
|
|
167
|
+
Many projects use a `setEnv.ts` script to generate environment from `.env`:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
# Build process often includes:
|
|
171
|
+
npm run config # Generates environment.ts from .env
|
|
172
|
+
ng build --prod
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## 4. Proxy Configuration
|
|
176
|
+
|
|
177
|
+
```json
|
|
178
|
+
// proxy.conf.json
|
|
179
|
+
{
|
|
180
|
+
"/api/*": {
|
|
181
|
+
"target": "http://localhost:3000",
|
|
182
|
+
"secure": false,
|
|
183
|
+
"changeOrigin": true
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## 5. Dependencies
|
|
189
|
+
|
|
190
|
+
### Common dependencies across projects
|
|
191
|
+
|
|
192
|
+
| Package | Purpose |
|
|
193
|
+
|---------|---------|
|
|
194
|
+
| `@angular/*` | Angular framework (6-11) |
|
|
195
|
+
| `@ngrx/*` | State management |
|
|
196
|
+
| `@ngx-translate/*` | Internationalization |
|
|
197
|
+
| `bootstrap` | CSS framework (when present) |
|
|
198
|
+
| `@ng-bootstrap/ng-bootstrap` | Angular Bootstrap components (when present) |
|
|
199
|
+
| `ngrx-store-localstorage` | NgRx localStorage sync |
|
|
200
|
+
| `@localize-router/*` | Localized routing |
|
|
201
|
+
| `ngx-swiper-wrapper` | Image swipers |
|
|
202
|
+
|
|
203
|
+
### Common dev dependencies
|
|
204
|
+
|
|
205
|
+
| Package | Purpose |
|
|
206
|
+
|---------|---------|
|
|
207
|
+
| `@angular/cli` | Angular CLI |
|
|
208
|
+
| `karma` | Test runner |
|
|
209
|
+
| `jasmine` | Test framework |
|
|
210
|
+
| `protractor` | E2E tests (deprecated) |
|
|
211
|
+
| `tslint` or `eslint` | Linting |
|
|
212
|
+
|
|
213
|
+
## 6. Module Organization
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
// app.module.ts - Root module
|
|
217
|
+
@NgModule({
|
|
218
|
+
declarations: [AppComponent],
|
|
219
|
+
imports: [
|
|
220
|
+
BrowserModule,
|
|
221
|
+
AppRoutingModule,
|
|
222
|
+
HttpClientModule,
|
|
223
|
+
TranslateModule.forRoot({...}),
|
|
224
|
+
StoreModule.forRoot(reducers, { metaReducers }),
|
|
225
|
+
EffectsModule.forRoot([]),
|
|
226
|
+
FeatureModule,
|
|
227
|
+
],
|
|
228
|
+
providers: [
|
|
229
|
+
{ provide: HTTP_INTERCEPTORS, useClass: LanguageInterceptor, multi: true },
|
|
230
|
+
{ provide: HTTP_INTERCEPTORS, useClass: CacheInterceptor, multi: true },
|
|
231
|
+
],
|
|
232
|
+
bootstrap: [AppComponent],
|
|
233
|
+
})
|
|
234
|
+
export class AppModule {}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## 7. i18n Pattern (ngx-translate)
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
// app.module.ts
|
|
241
|
+
TranslateModule.forRoot({
|
|
242
|
+
loader: {
|
|
243
|
+
provide: TranslateLoader,
|
|
244
|
+
useFactory: HttpLoaderFactory,
|
|
245
|
+
deps: [HttpClient],
|
|
246
|
+
},
|
|
247
|
+
defaultLanguage: 'pl',
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
// Usage in templates
|
|
251
|
+
{{ 'HEADER.title' | translate }}
|
|
252
|
+
|
|
253
|
+
// Usage in code
|
|
254
|
+
constructor(private translate: TranslateService) {
|
|
255
|
+
this.translate.use('pl');
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## 8. Best Practices
|
|
260
|
+
|
|
261
|
+
1. **Use `ng generate`** for scaffolding new code
|
|
262
|
+
2. **Always register in NgModule** - declarations, imports, exports
|
|
263
|
+
3. **Use environment files** for config - never hardcode URLs
|
|
264
|
+
4. **Use proxy.conf.json** for development API proxy
|
|
265
|
+
5. **Check angular.json location** - may be in `app/` subdirectory
|
|
266
|
+
6. **Use `--prod` flag** for production builds
|
|
267
|
+
7. **Follow existing file organization** - don't introduce new folder structures
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: angular-patterns
|
|
3
|
+
description: Angular 6-11 legacy patterns including *ngIf/*ngFor directives, constructor DI, @Input/@Output decorators, and NgRx state management
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Angular 6-11 Patterns
|
|
7
|
+
|
|
8
|
+
This skill provides guidance on Angular 6-11 patterns for standalone projects.
|
|
9
|
+
|
|
10
|
+
## CRITICAL: Use Legacy Patterns ONLY
|
|
11
|
+
|
|
12
|
+
**DO NOT use modern Angular features (Angular 14+):**
|
|
13
|
+
|
|
14
|
+
| Feature | CORRECT (Angular 6-11) | WRONG (Modern) |
|
|
15
|
+
|---------|------------------------|----------------|
|
|
16
|
+
| Control flow | `*ngIf`, `*ngFor`, `[ngSwitch]` | `@if`, `@for`, `@switch` |
|
|
17
|
+
| DI | Constructor injection | `inject()` |
|
|
18
|
+
| Inputs | `@Input()` decorator | `input()` function |
|
|
19
|
+
| Outputs | `@Output()` decorator | `output()` function |
|
|
20
|
+
| Two-way | `@Input()` + `@Output()` | `model()` |
|
|
21
|
+
| State | BehaviorSubject, NgRx | signals, `signal()` |
|
|
22
|
+
| Derived | `pipe(map())`, getters | `computed()` |
|
|
23
|
+
| Side effects | `subscribe()`, NgRx effects | `effect()` |
|
|
24
|
+
| Components | NgModule-based | standalone |
|
|
25
|
+
|
|
26
|
+
## 1. Control Flow
|
|
27
|
+
|
|
28
|
+
```html
|
|
29
|
+
<!-- *ngIf with else -->
|
|
30
|
+
<div *ngIf="isLoading; else content">
|
|
31
|
+
<app-spinner></app-spinner>
|
|
32
|
+
</div>
|
|
33
|
+
<ng-template #content>
|
|
34
|
+
<ul>
|
|
35
|
+
<li *ngFor="let item of items; trackBy: trackById">{{ item.name }}</li>
|
|
36
|
+
</ul>
|
|
37
|
+
</ng-template>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
trackById(index: number, item: Item): string {
|
|
42
|
+
return item.id;
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## 2. BehaviorSubject State Management
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
@Injectable({ providedIn: 'root' })
|
|
50
|
+
export class StateService {
|
|
51
|
+
private readonly _items = new BehaviorSubject<Item[]>([]);
|
|
52
|
+
readonly items$ = this._items.asObservable();
|
|
53
|
+
|
|
54
|
+
readonly count$ = this._items.pipe(
|
|
55
|
+
map(items => items.length)
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
setItems(items: Item[]): void {
|
|
59
|
+
this._items.next(items);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 3. Constructor Injection
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
@Component({
|
|
68
|
+
selector: 'app-feature',
|
|
69
|
+
templateUrl: './feature.component.html',
|
|
70
|
+
})
|
|
71
|
+
export class FeatureComponent implements OnInit, OnDestroy {
|
|
72
|
+
private readonly destroy$ = new Subject<void>();
|
|
73
|
+
|
|
74
|
+
constructor(
|
|
75
|
+
private readonly service: FeatureService,
|
|
76
|
+
private readonly router: Router
|
|
77
|
+
) {}
|
|
78
|
+
|
|
79
|
+
ngOnInit(): void {
|
|
80
|
+
this.service.items$
|
|
81
|
+
.pipe(takeUntil(this.destroy$))
|
|
82
|
+
.subscribe(items => this.items = items);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
ngOnDestroy(): void {
|
|
86
|
+
this.destroy$.next();
|
|
87
|
+
this.destroy$.complete();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## 4. Input/Output Decorators
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
@Component({
|
|
96
|
+
selector: 'app-card',
|
|
97
|
+
templateUrl: './card.component.html',
|
|
98
|
+
})
|
|
99
|
+
export class CardComponent {
|
|
100
|
+
@Input() item!: Item;
|
|
101
|
+
@Input() showActions = true;
|
|
102
|
+
@Output() selected = new EventEmitter<Item>();
|
|
103
|
+
|
|
104
|
+
// Two-way binding
|
|
105
|
+
@Input() value = '';
|
|
106
|
+
@Output() valueChange = new EventEmitter<string>();
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## 5. NgModule
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
@NgModule({
|
|
114
|
+
declarations: [FeatureComponent, CardComponent],
|
|
115
|
+
imports: [CommonModule, TranslateModule, NgbModule],
|
|
116
|
+
exports: [FeatureComponent],
|
|
117
|
+
})
|
|
118
|
+
export class FeatureModule {}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## 6. NgRx Patterns
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
// Actions
|
|
125
|
+
export const loadItems = createAction('[Items] Load');
|
|
126
|
+
export const loadItemsSuccess = createAction('[Items] Load Success', props<{ items: Item[] }>());
|
|
127
|
+
|
|
128
|
+
// Reducer
|
|
129
|
+
export const reducer = createReducer(
|
|
130
|
+
initialState,
|
|
131
|
+
on(loadItems, state => ({ ...state, loading: true })),
|
|
132
|
+
on(loadItemsSuccess, (state, { items }) => ({ ...state, items, loading: false }))
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
// Effects
|
|
136
|
+
@Injectable()
|
|
137
|
+
export class ItemEffects {
|
|
138
|
+
constructor(private actions$: Actions, private service: ItemService) {}
|
|
139
|
+
|
|
140
|
+
load$ = createEffect(() => this.actions$.pipe(
|
|
141
|
+
ofType(loadItems),
|
|
142
|
+
mergeMap(() => this.service.getAll().pipe(
|
|
143
|
+
map(items => loadItemsSuccess({ items })),
|
|
144
|
+
catchError(error => of(loadItemsFailure({ error: error.message })))
|
|
145
|
+
))
|
|
146
|
+
));
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## 7. Async Pipe
|
|
151
|
+
|
|
152
|
+
```html
|
|
153
|
+
<div *ngIf="isLoading$ | async; else content">Loading...</div>
|
|
154
|
+
<ng-template #content>
|
|
155
|
+
<li *ngFor="let item of items$ | async; trackBy: trackById">
|
|
156
|
+
{{ item.name }}
|
|
157
|
+
</li>
|
|
158
|
+
</ng-template>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## 8. PR Checklist
|
|
162
|
+
|
|
163
|
+
- [ ] Using `*ngIf`/`*ngFor` (NOT `@if`/`@for`)
|
|
164
|
+
- [ ] Every `*ngFor` has `trackBy`
|
|
165
|
+
- [ ] Using constructor DI (NOT `inject()`)
|
|
166
|
+
- [ ] Using `@Input()`/`@Output()` (NOT `input()`/`output()`)
|
|
167
|
+
- [ ] Using BehaviorSubject/NgRx for state (NOT signals)
|
|
168
|
+
- [ ] Component declared in NgModule
|
|
169
|
+
- [ ] Using `async` pipe in templates
|
|
170
|
+
- [ ] `OnDestroy` with `takeUntil` pattern
|