@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.
Files changed (132) hide show
  1. package/.claude-plugin/marketplace.json +2 -6
  2. package/package.json +2 -2
  3. package/plugins/mobilems/.claude-plugin/README.md +30 -0
  4. package/plugins/mobilems/.claude-plugin/plugin.json +5 -0
  5. package/plugins/mobilems/scripts/refresh-mobilems-api-spec.sh +372 -0
  6. package/plugins/mobilems/skills/mobilems-docs-reader/SKILL.md +116 -0
  7. package/plugins/flow/.claude-plugin/README.md +0 -91
  8. package/plugins/flow/.claude-plugin/merge-permissions.js +0 -97
  9. package/plugins/flow/.claude-plugin/plugin.json +0 -5
  10. package/plugins/flow/.claude-plugin/settings.template.json +0 -86
  11. package/plugins/flow/agents/angular-component-scaffolder.md +0 -175
  12. package/plugins/flow/agents/angular-directive-builder.md +0 -153
  13. package/plugins/flow/agents/angular-guard-builder.md +0 -243
  14. package/plugins/flow/agents/angular-jest-test-writer.md +0 -474
  15. package/plugins/flow/agents/angular-pipe-builder.md +0 -169
  16. package/plugins/flow/agents/angular-resolver-builder.md +0 -286
  17. package/plugins/flow/agents/angular-service-builder.md +0 -161
  18. package/plugins/flow/agents/angular-signal-state-builder.md +0 -339
  19. package/plugins/flow/agents/angular-test-diagnostician.md +0 -279
  20. package/plugins/flow/agents/angular-testbed-configurator.md +0 -315
  21. package/plugins/flow/agents/arch-scaffolder.md +0 -278
  22. package/plugins/flow/agents/e2e-data-testid-injector.md +0 -197
  23. package/plugins/flow/agents/e2e-project-scaffolder.md +0 -194
  24. package/plugins/flow/agents/e2e-test-writer.md +0 -350
  25. package/plugins/flow/agents/shared-agent-evolver.md +0 -294
  26. package/plugins/flow/agents/shared-build-verifier.md +0 -160
  27. package/plugins/flow/agents/shared-config-updater.md +0 -310
  28. package/plugins/flow/agents/shared-coverage-enforcer.md +0 -184
  29. package/plugins/flow/agents/shared-error-handler.md +0 -217
  30. package/plugins/flow/agents/shared-file-creator.md +0 -344
  31. package/plugins/flow/agents/shared-impl-orchestrator.md +0 -312
  32. package/plugins/flow/agents/shared-impl-reporter.md +0 -368
  33. package/plugins/flow/agents/shared-impl-teammate.md +0 -201
  34. package/plugins/flow/agents/shared-linear-subtask-iterator.md +0 -337
  35. package/plugins/flow/agents/shared-logic-implementer.md +0 -243
  36. package/plugins/flow/agents/shared-maia-api.md +0 -26
  37. package/plugins/flow/agents/shared-parallelization-analyzer.md +0 -343
  38. package/plugins/flow/agents/shared-performance-validator.md +0 -168
  39. package/plugins/flow/agents/shared-plan-perspective.md +0 -269
  40. package/plugins/flow/agents/shared-project-standardizer.md +0 -205
  41. package/plugins/flow/agents/shared-report-synthesizer.md +0 -188
  42. package/plugins/flow/agents/shared-review-teammate.md +0 -189
  43. package/plugins/flow/agents/shared-security-scanner.md +0 -186
  44. package/plugins/flow/agents/shared-style-enforcer.md +0 -230
  45. package/plugins/flow/agents/shared-subtask-dependency-analyzer.md +0 -188
  46. package/plugins/flow/agents/shared-tdd-developer.md +0 -350
  47. package/plugins/flow/agents/shared-team-coordinator.md +0 -189
  48. package/plugins/flow/agents/shared-test-fixer.md +0 -186
  49. package/plugins/flow/agents/shared-test-runner.md +0 -191
  50. package/plugins/flow/agents/shared-ui-classifier.md +0 -263
  51. package/plugins/flow/agents/shared-verification-orchestrator.md +0 -194
  52. package/plugins/flow/agents/shared-verification-runner.md +0 -140
  53. package/plugins/flow/agents/ui-a11y-validator.md +0 -305
  54. package/plugins/flow/agents/ui-screenshot-reporter.md +0 -329
  55. package/plugins/flow/agents/ui-web-designer.md +0 -214
  56. package/plugins/flow/scripts/compute-session-tokens.sh +0 -39
  57. package/plugins/flow/skills/a11y-audit/SKILL.md +0 -214
  58. package/plugins/flow/skills/angular-patterns/SKILL.md +0 -191
  59. package/plugins/flow/skills/browser-capture/SKILL.md +0 -238
  60. package/plugins/flow/skills/commit/SKILL.md +0 -259
  61. package/plugins/flow/skills/debug-helper/SKILL.md +0 -375
  62. package/plugins/flow/skills/impl/SKILL.md +0 -992
  63. package/plugins/flow/skills/linear-suggestion/SKILL.md +0 -132
  64. package/plugins/flow/skills/maia-files-delete/SKILL.md +0 -59
  65. package/plugins/flow/skills/maia-files-upload/SKILL.md +0 -57
  66. package/plugins/flow/skills/nx-conventions/SKILL.md +0 -326
  67. package/plugins/flow/skills/plan/SKILL.md +0 -1033
  68. package/plugins/flow/skills/push/SKILL.md +0 -759
  69. package/plugins/flow/skills/review/SKILL.md +0 -443
  70. package/plugins/flow/skills/test-e2e/SKILL.md +0 -161
  71. package/plugins/flow/skills/test-unit/SKILL.md +0 -456
  72. package/plugins/flow-external/.claude-plugin/README.md +0 -152
  73. package/plugins/flow-external/.claude-plugin/merge-permissions.js +0 -80
  74. package/plugins/flow-external/.claude-plugin/plugin.json +0 -5
  75. package/plugins/flow-external/.claude-plugin/settings.template.json +0 -78
  76. package/plugins/flow-external/agents/angular-component-scaffolder.md +0 -269
  77. package/plugins/flow-external/agents/angular-directive-builder.md +0 -130
  78. package/plugins/flow-external/agents/angular-guard-builder.md +0 -70
  79. package/plugins/flow-external/agents/angular-pipe-builder.md +0 -82
  80. package/plugins/flow-external/agents/angular-resolver-builder.md +0 -74
  81. package/plugins/flow-external/agents/angular-service-builder.md +0 -160
  82. package/plugins/flow-external/agents/angular-state-builder.md +0 -254
  83. package/plugins/flow-external/agents/shared-build-verifier.md +0 -67
  84. package/plugins/flow-external/agents/shared-impl-orchestrator.md +0 -88
  85. package/plugins/flow-external/agents/shared-impl-reporter.md +0 -135
  86. package/plugins/flow-external/agents/shared-linear-subtask-iterator.md +0 -70
  87. package/plugins/flow-external/agents/shared-ui-classifier.md +0 -38
  88. package/plugins/flow-external/agents/ui-web-designer.md +0 -179
  89. package/plugins/flow-external/scripts/compute-session-tokens.sh +0 -39
  90. package/plugins/flow-external/skills/a11y-audit/SKILL.md +0 -96
  91. package/plugins/flow-external/skills/angular-cli-conventions/SKILL.md +0 -267
  92. package/plugins/flow-external/skills/angular-patterns/SKILL.md +0 -170
  93. package/plugins/flow-external/skills/browser-capture/SKILL.md +0 -68
  94. package/plugins/flow-external/skills/commit/SKILL.md +0 -114
  95. package/plugins/flow-external/skills/debug-helper/SKILL.md +0 -131
  96. package/plugins/flow-external/skills/impl/SKILL.md +0 -217
  97. package/plugins/flow-external/skills/linear-suggestion/SKILL.md +0 -62
  98. package/plugins/flow-external/skills/maia-files-delete/SKILL.md +0 -34
  99. package/plugins/flow-external/skills/maia-files-upload/SKILL.md +0 -41
  100. package/plugins/flow-external/skills/plan/SKILL.md +0 -334
  101. package/plugins/flow-external/skills/push/SKILL.md +0 -232
  102. package/plugins/flow-legacy/.claude-plugin/README.md +0 -143
  103. package/plugins/flow-legacy/.claude-plugin/merge-permissions.js +0 -94
  104. package/plugins/flow-legacy/.claude-plugin/plugin.json +0 -5
  105. package/plugins/flow-legacy/.claude-plugin/settings.template.json +0 -79
  106. package/plugins/flow-legacy/agents/angular-component-scaffolder.md +0 -323
  107. package/plugins/flow-legacy/agents/angular-directive-builder.md +0 -258
  108. package/plugins/flow-legacy/agents/angular-guard-builder.md +0 -322
  109. package/plugins/flow-legacy/agents/angular-pipe-builder.md +0 -227
  110. package/plugins/flow-legacy/agents/angular-resolver-builder.md +0 -332
  111. package/plugins/flow-legacy/agents/angular-service-builder.md +0 -271
  112. package/plugins/flow-legacy/agents/angular-state-builder.md +0 -479
  113. package/plugins/flow-legacy/agents/shared-impl-orchestrator.md +0 -174
  114. package/plugins/flow-legacy/agents/shared-impl-reporter.md +0 -232
  115. package/plugins/flow-legacy/agents/shared-linear-subtask-iterator.md +0 -187
  116. package/plugins/flow-legacy/agents/shared-tdd-developer.md +0 -306
  117. package/plugins/flow-legacy/agents/shared-test-runner.md +0 -131
  118. package/plugins/flow-legacy/agents/shared-ui-classifier.md +0 -145
  119. package/plugins/flow-legacy/scripts/compute-session-tokens.sh +0 -39
  120. package/plugins/flow-legacy/skills/a11y-audit/SKILL.md +0 -214
  121. package/plugins/flow-legacy/skills/angular-patterns/SKILL.md +0 -346
  122. package/plugins/flow-legacy/skills/browser-capture/SKILL.md +0 -238
  123. package/plugins/flow-legacy/skills/commit/SKILL.md +0 -215
  124. package/plugins/flow-legacy/skills/debug-helper/SKILL.md +0 -395
  125. package/plugins/flow-legacy/skills/impl/SKILL.md +0 -710
  126. package/plugins/flow-legacy/skills/linear-suggestion/SKILL.md +0 -132
  127. package/plugins/flow-legacy/skills/maia-files-delete/SKILL.md +0 -59
  128. package/plugins/flow-legacy/skills/maia-files-upload/SKILL.md +0 -57
  129. package/plugins/flow-legacy/skills/nx-conventions/SKILL.md +0 -368
  130. package/plugins/flow-legacy/skills/plan/SKILL.md +0 -742
  131. package/plugins/flow-legacy/skills/push/SKILL.md +0 -645
  132. 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,5 +0,0 @@
1
- {
2
- "name": "flow",
3
- "description": "Development flow skills for Linear-driven development workflow",
4
- "version": "2.85.0"
5
- }
@@ -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
- ```