@julianoczkowski/create-trimble-app 2.0.1 → 2.0.2
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/templates/angular/AGENTS.MD +377 -0
- package/templates/angular/README.md +394 -51
- package/templates/react/AGENTS.MD +291 -0
- package/templates/react/README.md +376 -602
- package/templates/react/amplify.yml +25 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@julianoczkowski/create-trimble-app",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "Interactive CLI to scaffold Modus 2.0 web component applications for React and Angular - templates bundled, works offline",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/cli.js",
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
# AGENTS.MD - Modus Angular Application
|
|
2
|
+
|
|
3
|
+
This file provides guidance to AI agents (GitHub Copilot, Claude, Cursor, etc.) when working with this codebase.
|
|
4
|
+
|
|
5
|
+
## Agent Profile
|
|
6
|
+
|
|
7
|
+
**Name**: `modus-angular-agent`
|
|
8
|
+
**Role**: Angular 20 + Modus Web Components Specialist
|
|
9
|
+
**Description**: Expert in building Angular applications with Trimble Modus Design System, Tailwind CSS v4, and strict design system compliance.
|
|
10
|
+
|
|
11
|
+
## Tech Stack
|
|
12
|
+
|
|
13
|
+
| Technology | Version | Package |
|
|
14
|
+
|------------|---------|---------|
|
|
15
|
+
| Angular | 20.3.0 | `@angular/core` |
|
|
16
|
+
| Modus Web Components | 1.0.6 | `@trimble-oss/moduswebcomponents` |
|
|
17
|
+
| Modus Angular Wrappers | 1.0.6-ng19 | `@trimble-oss/moduswebcomponents-angular` |
|
|
18
|
+
| Modus Icons | 1.18.0 | `@trimble-oss/modus-icons` |
|
|
19
|
+
| Tailwind CSS | 4.1.16 | `tailwindcss` |
|
|
20
|
+
| TypeScript | 5.9.2 | `typescript` |
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Commands (Run Frequently)
|
|
25
|
+
|
|
26
|
+
### Lint Commands (Run Before Committing)
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm run lint:all # Run ALL design system compliance checks
|
|
30
|
+
npm run type-check # TypeScript type validation
|
|
31
|
+
npm run lint:colors # Modus 9-color system compliance
|
|
32
|
+
npm run lint:styles # Inline styles validation
|
|
33
|
+
npm run lint:borders # Border pattern violations
|
|
34
|
+
npm run lint:opacity # Opacity utilities validation
|
|
35
|
+
npm run lint:icons # Modus Icons library validation
|
|
36
|
+
npm run lint:icon-names # Icon name validation (700+ icons)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Development Commands
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm start # Dev server on localhost:4200
|
|
43
|
+
npm run build # Production build
|
|
44
|
+
npm test # Run unit tests with Karma
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Pre-commit Hook
|
|
48
|
+
|
|
49
|
+
All lint commands run automatically on `git commit`. Fix all violations before committing.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## File Structure
|
|
54
|
+
|
|
55
|
+
| Directory | Purpose | Agent Action |
|
|
56
|
+
|-----------|---------|--------------|
|
|
57
|
+
| `src/app/pages/` | User application pages | WRITE - Build your app here |
|
|
58
|
+
| `src/app/components/` | Modus wrapper components | READ ONLY - Use as-is |
|
|
59
|
+
| `src/app/demos/` | Component demos | READ - Reference examples |
|
|
60
|
+
| `src/app/dev/` | Dev panel infrastructure | READ ONLY |
|
|
61
|
+
| `.cursor/rules/` | Detailed development rules | READ - Follow patterns |
|
|
62
|
+
| `scripts/` | Lint scripts | READ ONLY |
|
|
63
|
+
| `src/styles.css` | Design system definitions | READ - Color reference |
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Design System: 9 Colors Only
|
|
68
|
+
|
|
69
|
+
### Base Colors (5)
|
|
70
|
+
|
|
71
|
+
| Color | Class | Usage |
|
|
72
|
+
|-------|-------|-------|
|
|
73
|
+
| Background | `bg-background` | Page background |
|
|
74
|
+
| Card | `bg-card` | Card surfaces |
|
|
75
|
+
| Muted | `bg-muted` | Muted backgrounds |
|
|
76
|
+
| Secondary | `bg-secondary` | Secondary surfaces |
|
|
77
|
+
| Foreground | `text-foreground` | Primary text |
|
|
78
|
+
|
|
79
|
+
### Status Colors (4)
|
|
80
|
+
|
|
81
|
+
| Color | Class | Usage |
|
|
82
|
+
|-------|-------|-------|
|
|
83
|
+
| Primary | `bg-primary`, `text-primary` | Primary actions, info |
|
|
84
|
+
| Success | `bg-success`, `text-success` | Success states |
|
|
85
|
+
| Warning | `bg-warning`, `text-warning` | Warning states |
|
|
86
|
+
| Error | `bg-error`, `text-error` | Error states |
|
|
87
|
+
|
|
88
|
+
### Code Examples
|
|
89
|
+
|
|
90
|
+
```html
|
|
91
|
+
<!-- CORRECT: Design system colors -->
|
|
92
|
+
<div class="bg-background text-foreground p-4">
|
|
93
|
+
<div class="bg-card text-foreground border-default rounded-lg">
|
|
94
|
+
<div class="text-primary">Primary action</div>
|
|
95
|
+
<div class="text-muted-foreground">Muted text</div>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
<!-- WRONG: Generic Tailwind colors - LINT WILL FAIL -->
|
|
100
|
+
<div class="bg-blue-500 text-white">
|
|
101
|
+
<div class="bg-gray-100 text-gray-600">
|
|
102
|
+
<div style="background-color: #ffffff">
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Critical Patterns & Bug Fixes
|
|
108
|
+
|
|
109
|
+
### 1. Checkbox Value Inversion Bug
|
|
110
|
+
|
|
111
|
+
**Problem**: `modus-wc-checkbox` returns inverted values in `inputChange` event.
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
// CRITICAL: Always invert the value
|
|
115
|
+
handleChange(event: CustomEvent<InputEvent>): void {
|
|
116
|
+
const value = (event.target as HTMLModusWcCheckboxElement).value;
|
|
117
|
+
const actualChecked = !value; // INVERT: false means checked, true means unchecked
|
|
118
|
+
this.isChecked.set(actualChecked);
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 2. Modal Access Pattern
|
|
123
|
+
|
|
124
|
+
**Use `getElementById` with native HTMLDialogElement API:**
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
// CORRECT: Use getElementById with modalId
|
|
128
|
+
openModal(): void {
|
|
129
|
+
const dialog = document.getElementById('my-modal') as HTMLDialogElement | null;
|
|
130
|
+
if (dialog && typeof dialog.showModal === 'function') {
|
|
131
|
+
dialog.showModal();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
closeModal(): void {
|
|
136
|
+
const dialog = document.getElementById('my-modal') as HTMLDialogElement | null;
|
|
137
|
+
if (dialog && typeof dialog.close === 'function') {
|
|
138
|
+
dialog.close();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// WRONG: Don't use querySelector or web component methods
|
|
143
|
+
const modal = document.querySelector('modus-wc-modal'); // WRONG
|
|
144
|
+
modal.open(); // WRONG - method doesn't exist
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### 3. Signal Initialization
|
|
148
|
+
|
|
149
|
+
**Never use IIFE pattern with `signal()`:**
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
// WRONG: Causes TypeScript parsing errors
|
|
153
|
+
readonly minDate = signal<string>(() => {
|
|
154
|
+
return new Date().toISOString().split('T')[0];
|
|
155
|
+
}());
|
|
156
|
+
|
|
157
|
+
// CORRECT: Use helper method
|
|
158
|
+
private getTodayDate(): string {
|
|
159
|
+
return new Date().toISOString().split('T')[0];
|
|
160
|
+
}
|
|
161
|
+
readonly minDate = signal<string>(this.getTodayDate());
|
|
162
|
+
|
|
163
|
+
// CORRECT: Simple inline computation
|
|
164
|
+
readonly today = signal<string>(new Date().toISOString().split('T')[0]);
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### 4. Opacity Utilities
|
|
168
|
+
|
|
169
|
+
**Tailwind `/80` syntax doesn't work with CSS variables:**
|
|
170
|
+
|
|
171
|
+
```html
|
|
172
|
+
<!-- WRONG: Tailwind opacity syntax fails with design system colors -->
|
|
173
|
+
<div class="text-foreground/80">
|
|
174
|
+
<div class="bg-primary/20">
|
|
175
|
+
|
|
176
|
+
<!-- CORRECT: Custom opacity utilities -->
|
|
177
|
+
<div class="text-foreground-80">
|
|
178
|
+
<div class="bg-primary-20">
|
|
179
|
+
|
|
180
|
+
<!-- Available levels: 20, 40, 60, 80 -->
|
|
181
|
+
<div class="text-foreground-80 text-foreground-60 text-foreground-40 text-foreground-20">
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 5. Wrapper Component Usage
|
|
185
|
+
|
|
186
|
+
**Always use Angular wrappers, never web components directly:**
|
|
187
|
+
|
|
188
|
+
```html
|
|
189
|
+
<!-- CORRECT: Use wrapper selectors -->
|
|
190
|
+
<modus-button color="primary" (buttonClick)="handleClick($event)">
|
|
191
|
+
Click Me
|
|
192
|
+
</modus-button>
|
|
193
|
+
<modus-alert alertTitle="Success" variant="success" />
|
|
194
|
+
<modus-icon name="add" size="md" />
|
|
195
|
+
|
|
196
|
+
<!-- WRONG: Never use modus-wc-* in application templates -->
|
|
197
|
+
<modus-wc-button color="primary">Click</modus-wc-button>
|
|
198
|
+
<modus-wc-alert alert-title="Success"></modus-wc-alert>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### 6. Divider Component
|
|
202
|
+
|
|
203
|
+
**Vertical dividers require `items-stretch` and explicit height:**
|
|
204
|
+
|
|
205
|
+
```html
|
|
206
|
+
<!-- CORRECT: Vertical divider -->
|
|
207
|
+
<div class="flex items-stretch gap-4 min-h-[60px]">
|
|
208
|
+
<div>Left</div>
|
|
209
|
+
<modus-divider [orientation]="'vertical'" />
|
|
210
|
+
<div>Right</div>
|
|
211
|
+
</div>
|
|
212
|
+
|
|
213
|
+
<!-- WRONG: Won't render without items-stretch and height -->
|
|
214
|
+
<div class="flex items-center gap-4">
|
|
215
|
+
<modus-divider [orientation]="'vertical'" />
|
|
216
|
+
</div>
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Angular 20 Patterns
|
|
222
|
+
|
|
223
|
+
### Required Patterns
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
@Component({
|
|
227
|
+
selector: 'app-example',
|
|
228
|
+
changeDetection: ChangeDetectionStrategy.OnPush, // REQUIRED
|
|
229
|
+
template: `
|
|
230
|
+
@if (isVisible()) {
|
|
231
|
+
<modus-button [color]="color()" (buttonClick)="handleClick($event)">
|
|
232
|
+
{{ buttonText() }}
|
|
233
|
+
</modus-button>
|
|
234
|
+
}
|
|
235
|
+
@for (item of items(); track item.id) {
|
|
236
|
+
<div>{{ item.name }}</div>
|
|
237
|
+
}
|
|
238
|
+
`,
|
|
239
|
+
})
|
|
240
|
+
export class ExampleComponent {
|
|
241
|
+
// Signal-based inputs (not @Input decorator)
|
|
242
|
+
readonly color = input<ButtonColor>('primary');
|
|
243
|
+
readonly disabled = input<boolean>(false);
|
|
244
|
+
|
|
245
|
+
// Signal-based outputs (not @Output decorator)
|
|
246
|
+
readonly buttonClick = output<MouseEvent>();
|
|
247
|
+
|
|
248
|
+
// Writable signals for state
|
|
249
|
+
readonly isVisible = signal(true);
|
|
250
|
+
readonly items = signal<Item[]>([]);
|
|
251
|
+
|
|
252
|
+
// Computed for derived state
|
|
253
|
+
readonly isDisabled = computed(() => this.disabled() || this.loading());
|
|
254
|
+
|
|
255
|
+
// inject() for DI (not constructor injection)
|
|
256
|
+
private readonly myService = inject(MyService);
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Forbidden Patterns
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
// WRONG: @Input/@Output decorators
|
|
264
|
+
@Input() color: string;
|
|
265
|
+
@Output() buttonClick = new EventEmitter();
|
|
266
|
+
|
|
267
|
+
// WRONG: Constructor injection
|
|
268
|
+
constructor(private myService: MyService) {}
|
|
269
|
+
|
|
270
|
+
// WRONG: *ngIf/*ngFor directives
|
|
271
|
+
<div *ngIf="condition">
|
|
272
|
+
<div *ngFor="let item of items">
|
|
273
|
+
|
|
274
|
+
// WRONG: standalone: true (implicit in Angular 20)
|
|
275
|
+
@Component({ standalone: true, ... })
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## Boundaries
|
|
281
|
+
|
|
282
|
+
### Always Do
|
|
283
|
+
|
|
284
|
+
- Run `npm run lint:all` before committing
|
|
285
|
+
- Use wrapper components (`<modus-button>` not `<modus-wc-button>`)
|
|
286
|
+
- Use design system colors only (9 colors)
|
|
287
|
+
- Use Modus Icons only (`<i class="modus-icons">icon_name</i>`)
|
|
288
|
+
- Invert checkbox values from `inputChange` events
|
|
289
|
+
- Use `getElementById` for modal access
|
|
290
|
+
- Use custom opacity utilities (`-80` not `/80`)
|
|
291
|
+
- Use `ChangeDetectionStrategy.OnPush`
|
|
292
|
+
- Use `input()`, `output()`, `signal()`, `computed()`
|
|
293
|
+
- Use `@if`, `@for`, `@switch` control flow
|
|
294
|
+
- Use `inject()` for dependency injection
|
|
295
|
+
- Test in all 6 themes (classic/modern, light/dark, connect)
|
|
296
|
+
|
|
297
|
+
### Ask First
|
|
298
|
+
|
|
299
|
+
- Creating new wrapper components in `src/app/components/`
|
|
300
|
+
- Modifying existing wrapper components
|
|
301
|
+
- Changes to `src/styles.css` (design system definitions)
|
|
302
|
+
- Changes to lint scripts in `scripts/`
|
|
303
|
+
- Adding new dependencies
|
|
304
|
+
|
|
305
|
+
### Never Do
|
|
306
|
+
|
|
307
|
+
- Use generic Tailwind colors (`bg-blue-500`, `text-gray-600`)
|
|
308
|
+
- Use hardcoded hex colors (`#ffffff`, `#000000`)
|
|
309
|
+
- Use inline styles (except truly dynamic values)
|
|
310
|
+
- Use other icon libraries (Font Awesome, Material Icons, Heroicons)
|
|
311
|
+
- Use semantic HTML (`h1`, `p`, `section`, `header`) - use `div` only
|
|
312
|
+
- Use Tailwind opacity syntax (`/80`) with design system colors
|
|
313
|
+
- Use web components directly (`modus-wc-*`) in app templates
|
|
314
|
+
- Use `@Input()`, `@Output()` decorators
|
|
315
|
+
- Use `*ngIf`, `*ngFor` directives
|
|
316
|
+
- Use constructor injection
|
|
317
|
+
- Skip lint checks before committing
|
|
318
|
+
- Commit with lint violations
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
## Icons
|
|
323
|
+
|
|
324
|
+
### Usage
|
|
325
|
+
|
|
326
|
+
```html
|
|
327
|
+
<!-- Angular component -->
|
|
328
|
+
<modus-icon name="add" size="md" />
|
|
329
|
+
|
|
330
|
+
<!-- Direct class usage -->
|
|
331
|
+
<i class="modus-icons">add</i>
|
|
332
|
+
<i class="modus-icons text-lg text-primary">save_disk</i>
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Naming
|
|
336
|
+
|
|
337
|
+
- Icon names use **underscores**: `save_disk`, `arrow_left`, `check_circle`
|
|
338
|
+
- Run `npm run lint:icon-names` to validate icon names
|
|
339
|
+
- 700+ icons available - check `/dev/icons` route for browser
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
## Themes
|
|
344
|
+
|
|
345
|
+
6 themes supported:
|
|
346
|
+
- `modus-classic-light` / `modus-classic-dark`
|
|
347
|
+
- `modus-modern-light` / `modus-modern-dark`
|
|
348
|
+
- `modus-connect-light` / `modus-connect-dark`
|
|
349
|
+
|
|
350
|
+
Toggle Dev Panel with `Ctrl+Shift+D` in development mode to test themes.
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
## Reference
|
|
355
|
+
|
|
356
|
+
For comprehensive patterns, examples, and edge cases:
|
|
357
|
+
- **Master Rule**: `.cursor/rules/modus-angular-master.mdc`
|
|
358
|
+
- **Essentials**: `.cursor/rules/modus-angular-essentials.mdc`
|
|
359
|
+
- **Component Rules**: `.cursor/rules/modus-angular-[component].mdc`
|
|
360
|
+
- **Design System**: `.cursor/rules/modus-angular-design-system.mdc`
|
|
361
|
+
- **Scripts README**: `scripts/README.md`
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## Quick Checklist
|
|
366
|
+
|
|
367
|
+
Before completing any task:
|
|
368
|
+
|
|
369
|
+
- [ ] `npm run lint:all` passes with 0 violations
|
|
370
|
+
- [ ] Using wrapper components only (`<modus-button>` not `<modus-wc-button>`)
|
|
371
|
+
- [ ] Using design system colors only (no `bg-blue-500`)
|
|
372
|
+
- [ ] Using Modus Icons only (no Font Awesome)
|
|
373
|
+
- [ ] Using `div` elements only (no semantic HTML)
|
|
374
|
+
- [ ] Using custom opacity utilities (`-80` not `/80`)
|
|
375
|
+
- [ ] Using signal-based APIs (`input()`, `output()`, `signal()`)
|
|
376
|
+
- [ ] Using modern control flow (`@if`, `@for`)
|
|
377
|
+
- [ ] Tested in at least light and dark themes
|