@smartsoft001-mobilems/claude-plugins 2.85.0 → 2.86.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/.claude-plugin/marketplace.json +2 -6
- package/package.json +2 -2
- package/plugins/mobilems/.claude-plugin/README.md +30 -0
- package/plugins/mobilems/.claude-plugin/plugin.json +5 -0
- package/plugins/mobilems/scripts/refresh-mobilems-api-spec.sh +372 -0
- package/plugins/mobilems/skills/mobilems-docs-reader/SKILL.md +116 -0
- package/plugins/flow/.claude-plugin/README.md +0 -91
- package/plugins/flow/.claude-plugin/merge-permissions.js +0 -97
- package/plugins/flow/.claude-plugin/plugin.json +0 -5
- package/plugins/flow/.claude-plugin/settings.template.json +0 -86
- package/plugins/flow/agents/angular-component-scaffolder.md +0 -175
- package/plugins/flow/agents/angular-directive-builder.md +0 -153
- package/plugins/flow/agents/angular-guard-builder.md +0 -243
- package/plugins/flow/agents/angular-jest-test-writer.md +0 -474
- package/plugins/flow/agents/angular-pipe-builder.md +0 -169
- package/plugins/flow/agents/angular-resolver-builder.md +0 -286
- package/plugins/flow/agents/angular-service-builder.md +0 -161
- package/plugins/flow/agents/angular-signal-state-builder.md +0 -339
- package/plugins/flow/agents/angular-test-diagnostician.md +0 -279
- package/plugins/flow/agents/angular-testbed-configurator.md +0 -315
- package/plugins/flow/agents/arch-scaffolder.md +0 -278
- package/plugins/flow/agents/e2e-data-testid-injector.md +0 -197
- package/plugins/flow/agents/e2e-project-scaffolder.md +0 -194
- package/plugins/flow/agents/e2e-test-writer.md +0 -350
- package/plugins/flow/agents/shared-agent-evolver.md +0 -294
- package/plugins/flow/agents/shared-build-verifier.md +0 -160
- package/plugins/flow/agents/shared-config-updater.md +0 -310
- package/plugins/flow/agents/shared-coverage-enforcer.md +0 -184
- package/plugins/flow/agents/shared-error-handler.md +0 -217
- package/plugins/flow/agents/shared-file-creator.md +0 -344
- package/plugins/flow/agents/shared-impl-orchestrator.md +0 -312
- package/plugins/flow/agents/shared-impl-reporter.md +0 -368
- package/plugins/flow/agents/shared-impl-teammate.md +0 -201
- package/plugins/flow/agents/shared-linear-subtask-iterator.md +0 -337
- package/plugins/flow/agents/shared-logic-implementer.md +0 -243
- package/plugins/flow/agents/shared-maia-api.md +0 -26
- package/plugins/flow/agents/shared-parallelization-analyzer.md +0 -343
- package/plugins/flow/agents/shared-performance-validator.md +0 -168
- package/plugins/flow/agents/shared-plan-perspective.md +0 -269
- package/plugins/flow/agents/shared-project-standardizer.md +0 -205
- package/plugins/flow/agents/shared-report-synthesizer.md +0 -188
- package/plugins/flow/agents/shared-review-teammate.md +0 -189
- package/plugins/flow/agents/shared-security-scanner.md +0 -186
- package/plugins/flow/agents/shared-style-enforcer.md +0 -230
- package/plugins/flow/agents/shared-subtask-dependency-analyzer.md +0 -188
- package/plugins/flow/agents/shared-tdd-developer.md +0 -350
- package/plugins/flow/agents/shared-team-coordinator.md +0 -189
- package/plugins/flow/agents/shared-test-fixer.md +0 -186
- package/plugins/flow/agents/shared-test-runner.md +0 -191
- package/plugins/flow/agents/shared-ui-classifier.md +0 -263
- package/plugins/flow/agents/shared-verification-orchestrator.md +0 -194
- package/plugins/flow/agents/shared-verification-runner.md +0 -140
- package/plugins/flow/agents/ui-a11y-validator.md +0 -305
- package/plugins/flow/agents/ui-screenshot-reporter.md +0 -329
- package/plugins/flow/agents/ui-web-designer.md +0 -214
- package/plugins/flow/scripts/compute-session-tokens.sh +0 -39
- package/plugins/flow/skills/a11y-audit/SKILL.md +0 -214
- package/plugins/flow/skills/angular-patterns/SKILL.md +0 -191
- package/plugins/flow/skills/browser-capture/SKILL.md +0 -238
- package/plugins/flow/skills/commit/SKILL.md +0 -259
- package/plugins/flow/skills/debug-helper/SKILL.md +0 -375
- package/plugins/flow/skills/impl/SKILL.md +0 -992
- package/plugins/flow/skills/linear-suggestion/SKILL.md +0 -132
- package/plugins/flow/skills/maia-files-delete/SKILL.md +0 -59
- package/plugins/flow/skills/maia-files-upload/SKILL.md +0 -57
- package/plugins/flow/skills/nx-conventions/SKILL.md +0 -326
- package/plugins/flow/skills/plan/SKILL.md +0 -1033
- package/plugins/flow/skills/push/SKILL.md +0 -759
- package/plugins/flow/skills/review/SKILL.md +0 -443
- package/plugins/flow/skills/test-e2e/SKILL.md +0 -161
- package/plugins/flow/skills/test-unit/SKILL.md +0 -456
- package/plugins/flow-external/.claude-plugin/README.md +0 -152
- package/plugins/flow-external/.claude-plugin/merge-permissions.js +0 -80
- package/plugins/flow-external/.claude-plugin/plugin.json +0 -5
- package/plugins/flow-external/.claude-plugin/settings.template.json +0 -78
- package/plugins/flow-external/agents/angular-component-scaffolder.md +0 -269
- package/plugins/flow-external/agents/angular-directive-builder.md +0 -130
- package/plugins/flow-external/agents/angular-guard-builder.md +0 -70
- package/plugins/flow-external/agents/angular-pipe-builder.md +0 -82
- package/plugins/flow-external/agents/angular-resolver-builder.md +0 -74
- package/plugins/flow-external/agents/angular-service-builder.md +0 -160
- package/plugins/flow-external/agents/angular-state-builder.md +0 -254
- package/plugins/flow-external/agents/shared-build-verifier.md +0 -67
- package/plugins/flow-external/agents/shared-impl-orchestrator.md +0 -88
- package/plugins/flow-external/agents/shared-impl-reporter.md +0 -135
- package/plugins/flow-external/agents/shared-linear-subtask-iterator.md +0 -70
- package/plugins/flow-external/agents/shared-ui-classifier.md +0 -38
- package/plugins/flow-external/agents/ui-web-designer.md +0 -179
- package/plugins/flow-external/scripts/compute-session-tokens.sh +0 -39
- package/plugins/flow-external/skills/a11y-audit/SKILL.md +0 -96
- package/plugins/flow-external/skills/angular-cli-conventions/SKILL.md +0 -267
- package/plugins/flow-external/skills/angular-patterns/SKILL.md +0 -170
- package/plugins/flow-external/skills/browser-capture/SKILL.md +0 -68
- package/plugins/flow-external/skills/commit/SKILL.md +0 -114
- package/plugins/flow-external/skills/debug-helper/SKILL.md +0 -131
- package/plugins/flow-external/skills/impl/SKILL.md +0 -217
- package/plugins/flow-external/skills/linear-suggestion/SKILL.md +0 -62
- package/plugins/flow-external/skills/maia-files-delete/SKILL.md +0 -34
- package/plugins/flow-external/skills/maia-files-upload/SKILL.md +0 -41
- package/plugins/flow-external/skills/plan/SKILL.md +0 -334
- package/plugins/flow-external/skills/push/SKILL.md +0 -232
- package/plugins/flow-legacy/.claude-plugin/README.md +0 -143
- package/plugins/flow-legacy/.claude-plugin/merge-permissions.js +0 -94
- package/plugins/flow-legacy/.claude-plugin/plugin.json +0 -5
- package/plugins/flow-legacy/.claude-plugin/settings.template.json +0 -79
- package/plugins/flow-legacy/agents/angular-component-scaffolder.md +0 -323
- package/plugins/flow-legacy/agents/angular-directive-builder.md +0 -258
- package/plugins/flow-legacy/agents/angular-guard-builder.md +0 -322
- package/plugins/flow-legacy/agents/angular-pipe-builder.md +0 -227
- package/plugins/flow-legacy/agents/angular-resolver-builder.md +0 -332
- package/plugins/flow-legacy/agents/angular-service-builder.md +0 -271
- package/plugins/flow-legacy/agents/angular-state-builder.md +0 -479
- package/plugins/flow-legacy/agents/shared-impl-orchestrator.md +0 -174
- package/plugins/flow-legacy/agents/shared-impl-reporter.md +0 -232
- package/plugins/flow-legacy/agents/shared-linear-subtask-iterator.md +0 -187
- package/plugins/flow-legacy/agents/shared-tdd-developer.md +0 -306
- package/plugins/flow-legacy/agents/shared-test-runner.md +0 -131
- package/plugins/flow-legacy/agents/shared-ui-classifier.md +0 -145
- package/plugins/flow-legacy/scripts/compute-session-tokens.sh +0 -39
- package/plugins/flow-legacy/skills/a11y-audit/SKILL.md +0 -214
- package/plugins/flow-legacy/skills/angular-patterns/SKILL.md +0 -346
- package/plugins/flow-legacy/skills/browser-capture/SKILL.md +0 -238
- package/plugins/flow-legacy/skills/commit/SKILL.md +0 -215
- package/plugins/flow-legacy/skills/debug-helper/SKILL.md +0 -395
- package/plugins/flow-legacy/skills/impl/SKILL.md +0 -710
- package/plugins/flow-legacy/skills/linear-suggestion/SKILL.md +0 -132
- package/plugins/flow-legacy/skills/maia-files-delete/SKILL.md +0 -59
- package/plugins/flow-legacy/skills/maia-files-upload/SKILL.md +0 -57
- package/plugins/flow-legacy/skills/nx-conventions/SKILL.md +0 -368
- package/plugins/flow-legacy/skills/plan/SKILL.md +0 -742
- package/plugins/flow-legacy/skills/push/SKILL.md +0 -645
- package/plugins/flow-legacy/skills/test-unit/SKILL.md +0 -500
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Merge flow plugin permissions into project's .claude/settings.json
|
|
4
|
-
*
|
|
5
|
-
* Usage:
|
|
6
|
-
* npx @smartsoft001-mobilems/claude-plugins flow:merge-permissions
|
|
7
|
-
*
|
|
8
|
-
* Or directly:
|
|
9
|
-
* node node_modules/@smartsoft001-mobilems/claude-plugins/plugins/flow/.claude-plugin/merge-permissions.js
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
const fs = require('fs');
|
|
13
|
-
const path = require('path');
|
|
14
|
-
|
|
15
|
-
const SETTINGS_PATH = path.join(process.cwd(), '.claude', 'settings.json');
|
|
16
|
-
const TEMPLATE_PATH = path.join(__dirname, 'settings.template.json');
|
|
17
|
-
|
|
18
|
-
function loadJson(filePath) {
|
|
19
|
-
try {
|
|
20
|
-
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
21
|
-
} catch (e) {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function mergeArrays(existing, template) {
|
|
27
|
-
return [...new Set([...existing, ...template])];
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function main() {
|
|
31
|
-
console.log('Flow Plugin - Merge Permissions\n');
|
|
32
|
-
|
|
33
|
-
// Load template
|
|
34
|
-
const template = loadJson(TEMPLATE_PATH);
|
|
35
|
-
if (!template) {
|
|
36
|
-
console.error('ERROR: Could not load template from:', TEMPLATE_PATH);
|
|
37
|
-
process.exit(1);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Load or create settings
|
|
41
|
-
let settings = loadJson(SETTINGS_PATH);
|
|
42
|
-
if (!settings) {
|
|
43
|
-
console.log('Creating new .claude/settings.json...');
|
|
44
|
-
fs.mkdirSync(path.dirname(SETTINGS_PATH), { recursive: true });
|
|
45
|
-
settings = { permissions: { allow: [], deny: [], ask: [] } };
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Ensure permissions structure exists
|
|
49
|
-
settings.permissions = settings.permissions || { allow: [], deny: [], ask: [] };
|
|
50
|
-
settings.permissions.allow = settings.permissions.allow || [];
|
|
51
|
-
settings.permissions.ask = settings.permissions.ask || [];
|
|
52
|
-
settings.permissions.deny = settings.permissions.deny || [];
|
|
53
|
-
|
|
54
|
-
// Count before
|
|
55
|
-
const beforeAllow = settings.permissions.allow.length;
|
|
56
|
-
const beforeAsk = settings.permissions.ask.length;
|
|
57
|
-
|
|
58
|
-
// Merge permissions
|
|
59
|
-
settings.permissions.allow = mergeArrays(settings.permissions.allow, template.permissions.allow);
|
|
60
|
-
settings.permissions.ask = mergeArrays(settings.permissions.ask, template.permissions.ask);
|
|
61
|
-
|
|
62
|
-
// Enable plugin
|
|
63
|
-
settings.enabledPlugins = settings.enabledPlugins || {};
|
|
64
|
-
settings.enabledPlugins['flow@mobilems'] = true;
|
|
65
|
-
|
|
66
|
-
// Merge env (shallow merge — template values don't overwrite existing project values)
|
|
67
|
-
if (template.env) {
|
|
68
|
-
settings.env = settings.env || {};
|
|
69
|
-
let addedEnv = 0;
|
|
70
|
-
for (const [key, value] of Object.entries(template.env)) {
|
|
71
|
-
if (!(key in settings.env)) {
|
|
72
|
-
settings.env[key] = value;
|
|
73
|
-
addedEnv++;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Write back
|
|
79
|
-
fs.writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2) + '\n');
|
|
80
|
-
|
|
81
|
-
// Report
|
|
82
|
-
const addedAllow = settings.permissions.allow.length - beforeAllow;
|
|
83
|
-
const addedAsk = settings.permissions.ask.length - beforeAsk;
|
|
84
|
-
const envKeys = template.env ? Object.keys(template.env).filter(k => !k.startsWith('_')) : [];
|
|
85
|
-
const existingEnvKeys = settings.env ? Object.keys(settings.env) : [];
|
|
86
|
-
|
|
87
|
-
console.log('Permissions merged successfully!\n');
|
|
88
|
-
console.log(` allow: ${beforeAllow} -> ${settings.permissions.allow.length} (+${addedAllow})`);
|
|
89
|
-
console.log(` ask: ${beforeAsk} -> ${settings.permissions.ask.length} (+${addedAsk})`);
|
|
90
|
-
if (envKeys.length > 0) {
|
|
91
|
-
console.log(` env: ${envKeys.length} key(s) from template (existing values preserved)`);
|
|
92
|
-
}
|
|
93
|
-
console.log(`\nPlugin enabled: flow@mobilems`);
|
|
94
|
-
console.log(`\nFile updated: ${SETTINGS_PATH}`);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
main();
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://raw.githubusercontent.com/anthropics/claude-code/main/schemas/settings.schema.json",
|
|
3
|
-
"_description": "Template permissions for flow@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(nx:*)",
|
|
17
|
-
"Bash(npx nx:*)",
|
|
18
|
-
"Bash(npx tsc:*)",
|
|
19
|
-
"Bash(npm start)",
|
|
20
|
-
"Bash(npm run format:*)",
|
|
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__get_issue",
|
|
38
|
-
"mcp__linear__list_issues",
|
|
39
|
-
"mcp__linear__list_comments",
|
|
40
|
-
"mcp__linear__save_comment",
|
|
41
|
-
"mcp__linear__delete_comment",
|
|
42
|
-
"mcp__linear__save_issue",
|
|
43
|
-
"mcp__linear__list_issue_statuses",
|
|
44
|
-
"mcp__linear__create_attachment",
|
|
45
|
-
"mcp__linear__get_attachment",
|
|
46
|
-
"mcp__linear__delete_attachment",
|
|
47
|
-
"mcp__linear__list_issue_labels",
|
|
48
|
-
"mcp__playwright__browser_snapshot",
|
|
49
|
-
"mcp__playwright__browser_take_screenshot",
|
|
50
|
-
"mcp__playwright__browser_navigate",
|
|
51
|
-
"mcp__playwright__browser_close",
|
|
52
|
-
"mcp__playwright__browser_wait_for",
|
|
53
|
-
"mcp__playwright__browser_click",
|
|
54
|
-
"mcp__playwright__browser_resize",
|
|
55
|
-
"mcp__playwright__browser_evaluate",
|
|
56
|
-
"mcp__playwright__browser_console_messages",
|
|
57
|
-
"mcp__playwright__browser_press_key",
|
|
58
|
-
"mcp__playwright__browser_network_requests",
|
|
59
|
-
"Skill(flow:maia-files-upload)",
|
|
60
|
-
"Skill(flow:maia-files-delete)",
|
|
61
|
-
"Skill(flow:browser-capture)",
|
|
62
|
-
"Skill(flow:linear-suggestion)",
|
|
63
|
-
"Skill(flow:test-unit)",
|
|
64
|
-
"Skill(flow:a11y-audit)",
|
|
65
|
-
"Skill(flow:test-e2e)",
|
|
66
|
-
"Skill(flow:review)",
|
|
67
|
-
"Bash(npx playwright:*)"
|
|
68
|
-
],
|
|
69
|
-
"ask": [
|
|
70
|
-
"Skill(flow:commit)",
|
|
71
|
-
"Skill(flow:impl)",
|
|
72
|
-
"Skill(flow:plan)",
|
|
73
|
-
"Skill(flow:push)",
|
|
74
|
-
"Skill(flow:review)",
|
|
75
|
-
"Bash(git commit:*)",
|
|
76
|
-
"Bash(git push:*)",
|
|
77
|
-
"Bash(gh pr create:*)"
|
|
78
|
-
]
|
|
79
|
-
},
|
|
80
|
-
"enabledPlugins": {
|
|
81
|
-
"flow@mobilems": true
|
|
82
|
-
},
|
|
83
|
-
"env": {
|
|
84
|
-
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
|
|
85
|
-
}
|
|
86
|
-
}
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: angular-component-scaffolder
|
|
3
|
-
description: Create Angular standalone components with signals and modern patterns. Use when scaffolding new components following Angular 20+ best practices.
|
|
4
|
-
tools: Read, Write, Glob, Grep
|
|
5
|
-
model: sonnet
|
|
6
|
-
color: "#DD0031"
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
You are an expert at creating Angular standalone components following modern best practices.
|
|
10
|
-
|
|
11
|
-
## Primary Responsibility
|
|
12
|
-
|
|
13
|
-
Create Angular components using Angular 20+ patterns including signals, standalone architecture, and modern control flow.
|
|
14
|
-
|
|
15
|
-
## When to Use
|
|
16
|
-
|
|
17
|
-
- Creating new Angular components
|
|
18
|
-
- Scaffolding component structure with template and styles
|
|
19
|
-
- Setting up component with proper DI using inject()
|
|
20
|
-
|
|
21
|
-
## Project-Specific Patterns
|
|
22
|
-
|
|
23
|
-
This project uses:
|
|
24
|
-
|
|
25
|
-
- **No explicit `standalone: true`** - Angular 19+ defaults to standalone
|
|
26
|
-
- **TranslatePipe** from `@ngx-translate/core` for i18n
|
|
27
|
-
- **CapitalizePipe** from project pipes
|
|
28
|
-
- **Tailwind CSS** with `smart-` prefix
|
|
29
|
-
|
|
30
|
-
## Component Template
|
|
31
|
-
|
|
32
|
-
### Basic Component
|
|
33
|
-
|
|
34
|
-
```typescript
|
|
35
|
-
import { Component, signal, computed, inject } from '@angular/core';
|
|
36
|
-
import { TranslatePipe } from '@ngx-translate/core';
|
|
37
|
-
|
|
38
|
-
import { CapitalizePipe } from '../../pipes';
|
|
39
|
-
|
|
40
|
-
@Component({
|
|
41
|
-
selector: 'app-feature-name',
|
|
42
|
-
imports: [TranslatePipe, CapitalizePipe],
|
|
43
|
-
templateUrl: './feature-name.component.html',
|
|
44
|
-
})
|
|
45
|
-
export class FeatureNameComponent {
|
|
46
|
-
// Injected services (at top)
|
|
47
|
-
private readonly dataService = inject(DataService);
|
|
48
|
-
|
|
49
|
-
// Signals for local state
|
|
50
|
-
readonly isLoading = signal(false);
|
|
51
|
-
readonly data = signal<DataType[]>([]);
|
|
52
|
-
|
|
53
|
-
// Computed values for derived state
|
|
54
|
-
readonly itemCount = computed(() => this.data().length);
|
|
55
|
-
readonly hasData = computed(() => this.data().length > 0);
|
|
56
|
-
}
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
### Component with Inputs/Outputs
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
import { Component, input, output, model, signal } from '@angular/core';
|
|
63
|
-
import { TranslatePipe } from '@ngx-translate/core';
|
|
64
|
-
|
|
65
|
-
import { CapitalizePipe } from '../../pipes';
|
|
66
|
-
|
|
67
|
-
@Component({
|
|
68
|
-
selector: 'app-item-card',
|
|
69
|
-
imports: [TranslatePipe, CapitalizePipe],
|
|
70
|
-
templateUrl: './item-card.component.html',
|
|
71
|
-
})
|
|
72
|
-
export class ItemCardComponent {
|
|
73
|
-
// Required inputs
|
|
74
|
-
label = input.required<string>();
|
|
75
|
-
item = input.required<Item>();
|
|
76
|
-
|
|
77
|
-
// Optional input with default
|
|
78
|
-
showActions = input<boolean>(true);
|
|
79
|
-
|
|
80
|
-
// Input with transform
|
|
81
|
-
page = input<number, number>(1, {
|
|
82
|
-
transform: (val: number) => (val < 1 ? 1 : val),
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
// Output events
|
|
86
|
-
selected = output<Item>();
|
|
87
|
-
closed = output();
|
|
88
|
-
|
|
89
|
-
// Two-way binding (model)
|
|
90
|
-
searchText = model<string>('');
|
|
91
|
-
|
|
92
|
-
// Internal signals
|
|
93
|
-
isOpen = signal(false);
|
|
94
|
-
|
|
95
|
-
// Methods
|
|
96
|
-
toggleDropdown(force?: boolean) {
|
|
97
|
-
this.isOpen.update((val) => force ?? !val);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## Template Patterns
|
|
103
|
-
|
|
104
|
-
### Modern Control Flow
|
|
105
|
-
|
|
106
|
-
```html
|
|
107
|
-
@if (isLoading()) {
|
|
108
|
-
<app-spinner />
|
|
109
|
-
} @else if (error()) {
|
|
110
|
-
<app-error [message]="error()?.message" />
|
|
111
|
-
} @else {
|
|
112
|
-
<div class="smart-grid smart-gap-4">
|
|
113
|
-
@for (item of items(); track item.id) {
|
|
114
|
-
<app-item-card [item]="item" (selected)="onSelect($event)" />
|
|
115
|
-
} @empty {
|
|
116
|
-
<p class="smart-text-gray-500">
|
|
117
|
-
{{ 'COMMON.noItems' | translate | capitalize }}
|
|
118
|
-
</p>
|
|
119
|
-
}
|
|
120
|
-
</div>
|
|
121
|
-
}
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
## File Structure
|
|
125
|
-
|
|
126
|
-
```
|
|
127
|
-
feature-name/
|
|
128
|
-
feature-name.component.ts # Component class
|
|
129
|
-
feature-name.component.html # Template
|
|
130
|
-
feature-name.component.scss # Styles (optional)
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
## Scaffolding Checklist
|
|
134
|
-
|
|
135
|
-
- [ ] NO `standalone: true` (Angular 19+ default)
|
|
136
|
-
- [ ] Uses `inject()` for DI at top of class
|
|
137
|
-
- [ ] Uses `signal()` for internal state
|
|
138
|
-
- [ ] Uses `computed()` for derived values
|
|
139
|
-
- [ ] Uses `input()`/`input.required()` for inputs
|
|
140
|
-
- [ ] Uses `output()` for outputs
|
|
141
|
-
- [ ] Uses `model()` for two-way binding
|
|
142
|
-
- [ ] Uses `@if`/`@for` in template
|
|
143
|
-
- [ ] Has `track` in all `@for` loops
|
|
144
|
-
- [ ] Imports `TranslatePipe` if using translations
|
|
145
|
-
- [ ] Imports `CapitalizePipe` if capitalizing text
|
|
146
|
-
- [ ] Tailwind classes with `smart-` prefix
|
|
147
|
-
|
|
148
|
-
## Output Format
|
|
149
|
-
|
|
150
|
-
```markdown
|
|
151
|
-
## Component Scaffolded
|
|
152
|
-
|
|
153
|
-
### Files Created
|
|
154
|
-
|
|
155
|
-
| File | Purpose |
|
|
156
|
-
| ----------------------------- | --------------- |
|
|
157
|
-
| `feature-name.component.ts` | Component class |
|
|
158
|
-
| `feature-name.component.html` | Template |
|
|
159
|
-
|
|
160
|
-
### Component API
|
|
161
|
-
|
|
162
|
-
**Inputs:**
|
|
163
|
-
|
|
164
|
-
- `item: Item` (required)
|
|
165
|
-
- `showActions: boolean` (default: true)
|
|
166
|
-
|
|
167
|
-
**Outputs:**
|
|
168
|
-
|
|
169
|
-
- `selected: Item`
|
|
170
|
-
|
|
171
|
-
### Next Steps
|
|
172
|
-
|
|
173
|
-
1. Implement component logic
|
|
174
|
-
2. Add to routing or parent component
|
|
175
|
-
```
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: angular-directive-builder
|
|
3
|
-
description: Create Angular standalone directives. Use when building attribute or structural directives.
|
|
4
|
-
tools: Read, Write, Glob, Grep
|
|
5
|
-
model: sonnet
|
|
6
|
-
color: "#DD0031"
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
You are an expert at creating Angular directives following modern best practices.
|
|
10
|
-
|
|
11
|
-
## Primary Responsibility
|
|
12
|
-
|
|
13
|
-
Create Angular directives using modern patterns including `input()`, `inject()`, and standalone architecture.
|
|
14
|
-
|
|
15
|
-
## When to Use
|
|
16
|
-
|
|
17
|
-
- Creating attribute directives
|
|
18
|
-
- Building structural directives
|
|
19
|
-
- Adding behavior to existing elements
|
|
20
|
-
|
|
21
|
-
## Project-Specific Patterns
|
|
22
|
-
|
|
23
|
-
This project uses:
|
|
24
|
-
|
|
25
|
-
- **`standalone: true`** explicitly for directives (for clarity)
|
|
26
|
-
- **`inject()`** for dependency injection
|
|
27
|
-
- **`input()`** for directive inputs
|
|
28
|
-
- **`@HostListener`** for event handling
|
|
29
|
-
- **`ElementRef`** via inject for DOM access
|
|
30
|
-
|
|
31
|
-
## Directive Template
|
|
32
|
-
|
|
33
|
-
### Attribute Directive
|
|
34
|
-
|
|
35
|
-
```typescript
|
|
36
|
-
import {
|
|
37
|
-
Directive,
|
|
38
|
-
ElementRef,
|
|
39
|
-
HostListener,
|
|
40
|
-
inject,
|
|
41
|
-
input,
|
|
42
|
-
} from '@angular/core';
|
|
43
|
-
import { TranslateService } from '@ngx-translate/core';
|
|
44
|
-
|
|
45
|
-
import { ConfirmationModalService } from '../services/confirmation-modal.service';
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Directive that shows a confirmation modal when clicking external links.
|
|
49
|
-
* Usage: <a href="https://external.com" appExternalLink>Link</a>
|
|
50
|
-
*/
|
|
51
|
-
@Directive({
|
|
52
|
-
selector: 'a[appExternalLink]',
|
|
53
|
-
standalone: true,
|
|
54
|
-
})
|
|
55
|
-
export class ExternalLinkDirective {
|
|
56
|
-
private readonly translate = inject(TranslateService);
|
|
57
|
-
private readonly modalService = inject(ConfirmationModalService);
|
|
58
|
-
private readonly elementRef = inject(ElementRef);
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Skip confirmation dialog if set to true
|
|
62
|
-
*/
|
|
63
|
-
skipConfirmation = input<boolean>(false);
|
|
64
|
-
|
|
65
|
-
@HostListener('click', ['$event'])
|
|
66
|
-
async onClick(event: MouseEvent): Promise<void> {
|
|
67
|
-
if (this.skipConfirmation()) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
event.preventDefault();
|
|
72
|
-
event.stopPropagation();
|
|
73
|
-
|
|
74
|
-
const message = this.translate.instant('COMMON.externalLinkWarning');
|
|
75
|
-
const confirmed = await this.modalService.open({ message });
|
|
76
|
-
|
|
77
|
-
if (confirmed) {
|
|
78
|
-
const href = this.elementRef.nativeElement.getAttribute('href');
|
|
79
|
-
window.open(href, '_blank', 'noopener,noreferrer');
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### Highlight Directive
|
|
86
|
-
|
|
87
|
-
```typescript
|
|
88
|
-
import {
|
|
89
|
-
Directive,
|
|
90
|
-
ElementRef,
|
|
91
|
-
HostListener,
|
|
92
|
-
inject,
|
|
93
|
-
input,
|
|
94
|
-
} from '@angular/core';
|
|
95
|
-
|
|
96
|
-
@Directive({
|
|
97
|
-
selector: '[appHighlight]',
|
|
98
|
-
standalone: true,
|
|
99
|
-
})
|
|
100
|
-
export class HighlightDirective {
|
|
101
|
-
private readonly el = inject(ElementRef);
|
|
102
|
-
|
|
103
|
-
highlightColor = input<string>('yellow');
|
|
104
|
-
|
|
105
|
-
@HostListener('mouseenter')
|
|
106
|
-
onMouseEnter(): void {
|
|
107
|
-
this.highlight(this.highlightColor());
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
@HostListener('mouseleave')
|
|
111
|
-
onMouseLeave(): void {
|
|
112
|
-
this.highlight('');
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
private highlight(color: string): void {
|
|
116
|
-
this.el.nativeElement.style.backgroundColor = color;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
## Checklist
|
|
122
|
-
|
|
123
|
-
- [ ] `standalone: true` set explicitly
|
|
124
|
-
- [ ] Uses `inject()` for DI
|
|
125
|
-
- [ ] Uses `input()` for directive inputs
|
|
126
|
-
- [ ] Uses `@HostListener` for events
|
|
127
|
-
- [ ] Has JSDoc comment explaining usage
|
|
128
|
-
- [ ] Selector follows `[appDirectiveName]` pattern
|
|
129
|
-
|
|
130
|
-
## Output Format
|
|
131
|
-
|
|
132
|
-
````markdown
|
|
133
|
-
## Directive Created
|
|
134
|
-
|
|
135
|
-
### File
|
|
136
|
-
|
|
137
|
-
`external-link.directive.ts`
|
|
138
|
-
|
|
139
|
-
### Usage
|
|
140
|
-
|
|
141
|
-
```html
|
|
142
|
-
<a href="https://example.com" appExternalLink>Link</a>
|
|
143
|
-
<a href="https://example.com" appExternalLink [skipConfirmation]="true">Skip</a>
|
|
144
|
-
```
|
|
145
|
-
````
|
|
146
|
-
|
|
147
|
-
### Inputs
|
|
148
|
-
|
|
149
|
-
- `skipConfirmation: boolean` (default: false)
|
|
150
|
-
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
```
|