@smartsoft001/pro-claude-plugins 0.3.0 → 0.3.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartsoft001/pro-claude-plugins",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -383,8 +383,8 @@ The agent will:
383
383
 
384
384
  1. **Check for existing `orchestration.md` attachment** on the task via `mcp__linear__get_issue` (the response includes an `attachments` array).
385
385
  - If one exists, delete it via `mcp__linear__delete_attachment({ id: oldAttachmentId })`. Linear hosts the file natively, so nothing else needs cleanup.
386
- 2. **Write locally**: use `Write` to save the orchestration markdown to `/tmp/claude-plans/<taskId>-orchestration.md`.
387
- 3. **Base64-encode**: `b64=$(base64 -i /tmp/claude-plans/<taskId>-orchestration.md)`.
386
+ 2. **Write locally**: ensure `.ai/tasks/` is gitignored (idempotent — `.ai/tasks` must NOT be synced to git): `grep -qxF '.ai/tasks/' .gitignore 2>/dev/null || echo '.ai/tasks/' >> .gitignore`. Then `mkdir -p .ai/tasks/<taskId>` and use `Write` to save the orchestration markdown to `.ai/tasks/<taskId>/orchestration.md` (sibling of `plan.md`).
387
+ 3. **Base64-encode**: `b64=$(base64 -i .ai/tasks/<taskId>/orchestration.md)`.
388
388
  4. **Create Linear attachment** via `mcp__linear__create_attachment`:
389
389
  - `issue`: the task/subtask ID
390
390
  - `filename`: `orchestration.md`
@@ -392,7 +392,7 @@ The agent will:
392
392
  - `title`: `orchestration.md` (exact — used for detection/replacement on the next `/impl` run)
393
393
  - `subtitle`: `Plan orkiestracji wygenerowany przez Claude Code`
394
394
  - `base64Content`: the base64 string from step 3
395
- 5. **Clean up** the local `/tmp/claude-plans/<taskId>-orchestration.md` file after a successful attachment.
395
+ 5. **Keep the local file**: do NOT delete `.ai/tasks/<taskId>/orchestration.md` it persists as a gitignored local artifact.
396
396
  6. **Follow the plan** — execute agents in the defined order.
397
397
  7. **Use TDD strictly** — `shared-tdd-developer` is MANDATORY for ALL code implementation.
398
398
 
@@ -915,6 +915,7 @@ When verification fails, delegate to appropriate fix agent:
915
915
  19. **Capture before screenshots in background**: Launch `screenshot-reporter` agent with `run_in_background: true` BEFORE implementing UI changes to capture "before" state while implementation proceeds
916
916
  20. **Capture after screenshots + post to Linear**: After implementation, launch `screenshot-reporter` agent to capture "after" screenshots, generate comparison report, post to Linear, and cleanup
917
917
  21. **Document translations changes**: If `apps/web/public/translations.json` was modified, include a table with added/changed translation keys and their PL/EN values in the Implementation Report
918
+ 21a. **⚠️ MANDATORY: Translation completeness before completion**: No hardcoded UI strings — every static label, heading, button, aria-label, meta/SEO text goes through a translation key. Before marking a subtask complete, verify that EVERY key referenced in the changed templates/TS exists in `apps/web/public/translations.json` in BOTH `pl` and `en` (a raw `GROUP.key` rendered in the UI is a defect), and that the touched groups are complete against the design/mockup — every visible text on the mockup has its key. When a reference project is available, diff the touched groups against it and fill the gaps
918
919
  22. **Capture screenshots in both modes**: Agent captures screenshots in BOTH normal mode and dark mode (high contrast) for complete visual documentation
919
920
  23. **Ask before collecting feedback for agent evolution**: When user provides corrections or suggestions during implementation, **explicitly ask** if they want to create a Linear issue for the improvement. Only user-confirmed feedback (answered "Yes") should be processed at evolution checkpoints (Step 3g-evolve, Step 4a) via `shared-agent-evolver` agent.
920
921
  24. **Never modify agent files directly during implementation**: The `shared-agent-evolver` agent files all proposals as Linear issues for manual review — it does NOT modify agent, command, or skill files directly.
@@ -679,7 +679,18 @@ When using `--deep` flag and the Planning Team has completed its analysis, appen
679
679
 
680
680
  **MANDATORY.** Before any Linear write (deletion of old `plan.md`, creation of new `plan.md`, label apply), the user MUST approve the generated plan content. This is the gate FRA-126 added.
681
681
 
682
- **`--auto` mode**: Skip this entire step. The plan is auto-approved. Record the auto-approval in the final Linear audit comment (e.g. `Plan zaakceptowany automatycznie (--auto)`). Proceed to Step 9.
682
+ **Persist the plan locally first (both modes).** For each task/subtask that needs planning:
683
+
684
+ - Ensure `.ai/tasks/` is gitignored (idempotent — `.ai/tasks` must NOT be synced to git):
685
+ ```bash
686
+ grep -qxF '.ai/tasks/' .gitignore 2>/dev/null || echo '.ai/tasks/' >> .gitignore
687
+ ```
688
+ - `mkdir -p .ai/tasks/<taskId>`
689
+ - Use the `Write` tool to save the Step 8 plan markdown to `.ai/tasks/<taskId>/plan.md`.
690
+
691
+ This file is the source for the Linear attachment in Step 9a and is NOT deleted — it persists as a gitignored local artifact. On regeneration (below) the `Write` overwrites it with the new plan.
692
+
693
+ **`--auto` mode**: Skip the approval prompt below — the plan is auto-approved and already persisted above. Record the auto-approval in the final Linear audit comment (e.g. `Plan zaakceptowany automatycznie (--auto)`). Proceed to Step 9.
683
694
 
684
695
  **Default mode** (interactive):
685
696
 
@@ -749,20 +760,14 @@ Use `AskUserQuestion` tool with options:
749
760
 
750
761
  For each task that needs planning, upload the plan content directly to Linear via `mcp__linear__create_attachment` — Linear hosts the file itself, no intermediate storage.
751
762
 
752
- #### 9a.1 — Prepare plan content
753
-
754
- The plan content is exactly the markdown produced in Step 8 (the same block that would previously have been posted as a comment). Write it to the temp file:
755
-
756
- ```bash
757
- mkdir -p /tmp/claude-plans
758
- ```
763
+ #### 9a.1 — Locate plan content
759
764
 
760
- Use the `Write` tool to save the plan markdown to `/tmp/claude-plans/<taskId>-plan.md`.
765
+ The plan content was already written to `.ai/tasks/<taskId>/plan.md` in Step 8a (before acceptance). No temp file is needed — that persistent, gitignored file is the source for the attachment below.
761
766
 
762
767
  #### 9a.2 — Base64-encode the content
763
768
 
764
769
  ```bash
765
- b64=$(base64 -i /tmp/claude-plans/<taskId>-plan.md)
770
+ b64=$(base64 -i .ai/tasks/<taskId>/plan.md)
766
771
  ```
767
772
 
768
773
  On macOS `base64 -i <file>` outputs without line-wrapping (which is what the Linear MCP expects). If you ever switch to GNU coreutils, pipe through `tr -d '\n'` to strip wraps.
@@ -780,9 +785,9 @@ Call `mcp__linear__create_attachment` with:
780
785
 
781
786
  Linear stores the file on its own infrastructure and surfaces it in the issue's Attachments pane.
782
787
 
783
- #### 9a.4 — Clean up local file
788
+ #### 9a.4 — Keep the local file
784
789
 
785
- Delete `/tmp/claude-plans/<taskId>-plan.md` after the attachment is created successfully. `/push` leaves Linear attachments in place — they stay on the issue as permanent artifacts.
790
+ Do NOT delete `.ai/tasks/<taskId>/plan.md` it is intentionally kept as a gitignored local artifact. `/push` leaves Linear attachments in place — they stay on the issue as permanent artifacts.
786
791
 
787
792
  #### Scope rule
788
793
 
@@ -1030,4 +1035,4 @@ _Plan generated by Claude Code_
1030
1035
  - **Default mode**: Before saving the plans as attachments, show them to the user for review and approval.
1031
1036
  - **`--auto` mode**: Skip the review step; proceed directly to saving the attachments.
1032
1037
 
1033
- The plan content is written to `/tmp/claude-plans/<taskId>-plan.md`, base64-encoded, and uploaded as a native Linear attachment via `mcp__linear__create_attachment`. After that, the `AI Plan` label is applied to the invoked issue.
1038
+ The plan content is written to `.ai/tasks/<taskId>/plan.md` (before acceptance, gitignored), base64-encoded, and uploaded as a native Linear attachment via `mcp__linear__create_attachment`. After that, the `AI Plan` label is applied to the invoked issue.
@@ -133,8 +133,8 @@ Use `shared-impl-orchestrator` agent to generate a `🎭 Agent Orchestration Pla
133
133
  Then save it as an `orchestration.md` attachment on the task (not as a comment):
134
134
 
135
135
  1. **Replace existing orchestration**: use `mcp__linear__get_issue` to list attachments; if one titled `orchestration.md` exists, delete it via `mcp__linear__delete_attachment({ id: oldAttachmentId })`. Linear hosts the file natively, so nothing else needs cleanup.
136
- 2. **Write locally**: `Write` the orchestration markdown to `/tmp/claude-plans/<taskId>-orchestration.md`.
137
- 3. **Base64-encode**: `b64=$(base64 -i /tmp/claude-plans/<taskId>-orchestration.md)`.
136
+ 2. **Write locally**: ensure `.ai/tasks/` is gitignored (idempotent — `.ai/tasks` must NOT be synced to git): `grep -qxF '.ai/tasks/' .gitignore 2>/dev/null || echo '.ai/tasks/' >> .gitignore`. Then `mkdir -p .ai/tasks/<taskId>` and `Write` the orchestration markdown to `.ai/tasks/<taskId>/orchestration.md` (sibling of `plan.md`).
137
+ 3. **Base64-encode**: `b64=$(base64 -i .ai/tasks/<taskId>/orchestration.md)`.
138
138
  4. **Create Linear attachment** via `mcp__linear__create_attachment`:
139
139
  - `issue`: the task ID
140
140
  - `filename`: `orchestration.md`
@@ -142,7 +142,7 @@ Then save it as an `orchestration.md` attachment on the task (not as a comment):
142
142
  - `title`: `orchestration.md` (exact)
143
143
  - `subtitle`: `Plan orkiestracji wygenerowany przez Claude Code (external)`
144
144
  - `base64Content`: the base64 string from step 3
145
- 5. **Clean up** local `/tmp/claude-plans/<taskId>-orchestration.md` file after the attachment is created.
145
+ 5. **Keep the local file**: do NOT delete `.ai/tasks/<taskId>/orchestration.md` it persists as a gitignored local artifact.
146
146
 
147
147
  ### Step 4: Implement Each Step
148
148
 
@@ -177,7 +177,18 @@ Structure the plan as follows:
177
177
 
178
178
  **MANDATORY.** Before any Linear write (subtask creation, attachment delete, attachment create, label apply), the user MUST approve the generated plan content. This is the gate FRA-126 added.
179
179
 
180
- **`--auto` mode**: Skip this entire step. The plan is auto-approved. Record the auto-approval in the final Linear audit comment (e.g. `Plan zaakceptowany automatycznie (--auto)`). Proceed to Step 5.
180
+ **Persist the plan locally first (both modes this is the "przed akceptacją" save).**
181
+
182
+ - Ensure `.ai/tasks/` is gitignored (idempotent — `.ai/tasks` must NOT be synced to git):
183
+ ```bash
184
+ grep -qxF '.ai/tasks/' .gitignore 2>/dev/null || echo '.ai/tasks/' >> .gitignore
185
+ ```
186
+ - `mkdir -p .ai/tasks/<taskId>`
187
+ - Use the `Write` tool to save the Step 4 plan markdown to `.ai/tasks/<taskId>/plan.md`.
188
+
189
+ This file is the source for the Linear attachment in Step 6 and is NOT deleted — it persists as a gitignored local artifact. On regeneration (below) the `Write` overwrites it with the new plan.
190
+
191
+ **`--auto` mode**: Skip the approval prompt below — the plan is auto-approved and already persisted above. Record the auto-approval in the final Linear audit comment (e.g. `Plan zaakceptowany automatycznie (--auto)`). Proceed to Step 5.
181
192
 
182
193
  **Default mode** (interactive):
183
194
 
@@ -233,20 +244,14 @@ If a `plan.md` attachment is being replaced:
233
244
 
234
245
  - **`--auto` mode**: skip the prompt; delete the old Linear attachment via `mcp__linear__delete_attachment({ id: oldAttachmentId })` automatically and proceed.
235
246
 
236
- #### 6.2 — Write `plan.md` locally
237
-
238
- The plan content is exactly the markdown produced in Step 4. Write it to the temp file:
239
-
240
- ```bash
241
- mkdir -p /tmp/claude-plans
242
- ```
247
+ #### 6.2 — Locate plan content
243
248
 
244
- Use `Write` to save the plan content to `/tmp/claude-plans/<taskId>-plan.md`.
249
+ The plan content was already written to `.ai/tasks/<taskId>/plan.md` in Step 4a (before acceptance). No temp file is needed — that persistent, gitignored file is the source for the attachment below.
245
250
 
246
251
  #### 6.3 — Base64-encode
247
252
 
248
253
  ```bash
249
- b64=$(base64 -i /tmp/claude-plans/<taskId>-plan.md)
254
+ b64=$(base64 -i .ai/tasks/<taskId>/plan.md)
250
255
  ```
251
256
 
252
257
  #### 6.4 — Create Linear attachment
@@ -260,9 +265,9 @@ Call `mcp__linear__create_attachment` with:
260
265
  - `subtitle`: `Plan wygenerowany przez Claude Code (external)`
261
266
  - `base64Content`: the base64 string from 6.3
262
267
 
263
- #### 6.5 — Clean up local file
268
+ #### 6.5 — Keep the local file
264
269
 
265
- Delete `/tmp/claude-plans/<taskId>-plan.md` after the attachment is created. `/push` leaves the Linear attachment in place.
270
+ Do NOT delete `.ai/tasks/<taskId>/plan.md` it is intentionally kept as a gitignored local artifact. `/push` leaves the Linear attachment in place.
266
271
 
267
272
  ### Step 7: Add "AI Plan" Label
268
273
 
@@ -352,8 +352,8 @@ The agent will:
352
352
 
353
353
  1. **Check for existing `orchestration.md` attachment** on the task via `mcp__linear__get_issue` (response includes `attachments`).
354
354
  - If one exists, delete it via `mcp__linear__delete_attachment({ id: oldAttachmentId })`. Linear hosts the file natively, so nothing else needs cleanup.
355
- 2. **Write locally**: `Write` the orchestration markdown to `/tmp/claude-plans/<taskId>-orchestration.md`.
356
- 3. **Base64-encode**: `b64=$(base64 -i /tmp/claude-plans/<taskId>-orchestration.md)`.
355
+ 2. **Write locally**: ensure `.ai/tasks/` is gitignored (idempotent — `.ai/tasks` must NOT be synced to git): `grep -qxF '.ai/tasks/' .gitignore 2>/dev/null || echo '.ai/tasks/' >> .gitignore`. Then `mkdir -p .ai/tasks/<taskId>` and `Write` the orchestration markdown to `.ai/tasks/<taskId>/orchestration.md` (sibling of `plan.md`).
356
+ 3. **Base64-encode**: `b64=$(base64 -i .ai/tasks/<taskId>/orchestration.md)`.
357
357
  4. **Create Linear attachment** via `mcp__linear__create_attachment`:
358
358
  - `issue`: the task/subtask ID
359
359
  - `filename`: `orchestration.md`
@@ -361,7 +361,7 @@ The agent will:
361
361
  - `title`: `orchestration.md` (exact — used for detection/replacement on the next `/impl` run)
362
362
  - `subtitle`: `Plan orkiestracji wygenerowany przez Claude Code (legacy)`
363
363
  - `base64Content`: the base64 string from step 3
364
- 5. **Clean up** local `/tmp/claude-plans/<taskId>-orchestration.md`.
364
+ 5. **Keep the local file**: do NOT delete `.ai/tasks/<taskId>/orchestration.md` — it persists as a gitignored local artifact.
365
365
  6. **Follow the plan** — execute agents in the defined order.
366
366
  7. **Use TDD strictly** — `shared-tdd-developer` is MANDATORY for ALL code implementation.
367
367
 
@@ -550,7 +550,18 @@ _Plan generated by Claude Code (flow-legacy)_
550
550
 
551
551
  **MANDATORY.** Before any Linear write (deletion of old `plan.md`, creation of new `plan.md`, label apply), the user MUST approve the generated plan content. This is the gate FRA-126 added.
552
552
 
553
- **`--auto` mode**: Skip this entire step. The plan is auto-approved. Record the auto-approval in the final Linear audit comment (e.g. `Plan zaakceptowany automatycznie (--auto)`). Proceed to Step 9.
553
+ **Persist the plan locally first (both modes this is the "przed akceptacją" save).** For each task/subtask that needs planning:
554
+
555
+ - Ensure `.ai/tasks/` is gitignored (idempotent — `.ai/tasks` must NOT be synced to git):
556
+ ```bash
557
+ grep -qxF '.ai/tasks/' .gitignore 2>/dev/null || echo '.ai/tasks/' >> .gitignore
558
+ ```
559
+ - `mkdir -p .ai/tasks/<taskId>`
560
+ - Use the `Write` tool to save the Step 8 plan markdown to `.ai/tasks/<taskId>/plan.md`.
561
+
562
+ This file is the source for the Linear attachment in Step 9a and is NOT deleted — it persists as a gitignored local artifact. On regeneration (below) the `Write` overwrites it with the new plan.
563
+
564
+ **`--auto` mode**: Skip the approval prompt below — the plan is auto-approved and already persisted above. Record the auto-approval in the final Linear audit comment (e.g. `Plan zaakceptowany automatycznie (--auto)`). Proceed to Step 9.
554
565
 
555
566
  **Default mode** (interactive):
556
567
 
@@ -618,20 +629,14 @@ Use `AskUserQuestion` with options:
618
629
 
619
630
  For each task that needs planning, upload the plan content directly to Linear (no external storage).
620
631
 
621
- #### 9a.1 — Write `plan.md` locally
622
-
623
- The plan content is exactly the markdown produced in Step 8. Write it to the temp file:
624
-
625
- ```bash
626
- mkdir -p /tmp/claude-plans
627
- ```
632
+ #### 9a.1 — Locate plan content
628
633
 
629
- Use `Write` to save the plan content to `/tmp/claude-plans/<taskId>-plan.md`.
634
+ The plan content was already written to `.ai/tasks/<taskId>/plan.md` in Step 8a (before acceptance). No temp file is needed — that persistent, gitignored file is the source for the attachment below.
630
635
 
631
636
  #### 9a.2 — Base64-encode
632
637
 
633
638
  ```bash
634
- b64=$(base64 -i /tmp/claude-plans/<taskId>-plan.md)
639
+ b64=$(base64 -i .ai/tasks/<taskId>/plan.md)
635
640
  ```
636
641
 
637
642
  On macOS `base64 -i <file>` outputs without line-wrapping. On Linux, pipe through `tr -d '\n'` if needed.
@@ -649,9 +654,9 @@ Call `mcp__linear__create_attachment` with:
649
654
 
650
655
  Linear hosts the file on its own infrastructure.
651
656
 
652
- #### 9a.4 — Clean up local file
657
+ #### 9a.4 — Keep the local file
653
658
 
654
- Delete `/tmp/claude-plans/<taskId>-plan.md` after the attachment is created. `/push` does NOT delete Linear attachments — they stay on the issue.
659
+ Do NOT delete `.ai/tasks/<taskId>/plan.md` it is intentionally kept as a gitignored local artifact. `/push` does NOT delete Linear attachments — they stay on the issue.
655
660
 
656
661
  #### Scope rule
657
662
 
@@ -739,4 +744,4 @@ After saving:
739
744
  - **Default mode**: Before saving the plans as attachments, show them to the user for review and approval.
740
745
  - **`--auto` mode**: Skip the review step; proceed directly to saving the attachments.
741
746
 
742
- The plan content is written to `/tmp/claude-plans/<taskId>-plan.md`, base64-encoded, and uploaded as a native Linear attachment via `mcp__linear__create_attachment`. After that, the `AI Plan` label is applied to the invoked issue.
747
+ The plan content is written to `.ai/tasks/<taskId>/plan.md` (before acceptance, gitignored), base64-encoded, and uploaded as a native Linear attachment via `mcp__linear__create_attachment`. After that, the `AI Plan` label is applied to the invoked issue.
@@ -0,0 +1,236 @@
1
+ ---
2
+ name: angular-components-crud
3
+ description: Pro CRUD shell for @smartsoft001/pro-crud-shell-angular — ProCrudModule.forFeature wiring, 6 smartpro-* components with inputs/selectors, DYNAMIC_COMPONENTS_STORE override mechanism, cssClass/variant styling surface, known routed-wrapper projection limitation, and [class]-not-[class.smart:X] Tailwind rule.
4
+ user-invocable: false
5
+ ---
6
+
7
+ # Pro CRUD Shell (`@smartsoft001/pro-crud-shell-angular`)
8
+
9
+ This package is the pro UI tier of the CRUD engine. It inherits all logic from
10
+ `@smartsoft001/crud-shell-angular` (config-driven routing, NgRx facades,
11
+ filter/sort/export/multiselect) and replaces the rendering layer with
12
+ `smartpro-*` components styled with the `smart:` Tailwind prefix.
13
+
14
+ ## When to Use This Skill
15
+
16
+ - Developer wants to wire a CRUD feature with pro Tailwind UI → show `ProCrudModule.forFeature` setup
17
+ - Developer asks which pro CRUD components exist → show the component table below
18
+ - Developer asks how the engine selects the pro page over the free one → explain `DYNAMIC_COMPONENTS_STORE`
19
+ - Developer asks how to style the CRUD pages → show `cssClass` / `variant` on `CrudFullConfig`
20
+ - Developer gets a blank page despite the override being registered → point to the known routed-wrapper limitation
21
+ - Developer tries to use `[class.smart:X]` → apply the Tailwind rule
22
+
23
+ ## Module Setup
24
+
25
+ ### `ProCrudModule.forFeature`
26
+
27
+ ```typescript
28
+ import { NgModule } from '@angular/core';
29
+ import { ProCrudModule } from '@smartsoft001/pro-crud-shell-angular';
30
+
31
+ @NgModule({
32
+ imports: [
33
+ ProCrudModule.forFeature({
34
+ routing: true, // true -> ProCrudModule (routed pages); false -> ProCrudCoreModule (no routes)
35
+ config: userConfig, // CrudFullConfig<T>
36
+ // socket: true, // opt-in realtime provider (inert stub today)
37
+ }),
38
+ ],
39
+ })
40
+ export class UserModule {}
41
+ ```
42
+
43
+ `forFeature` delegates to the engine's `CrudModule.forFeature` for all engine
44
+ providers, then additionally provides `ProCrudListPageComponent` and
45
+ `ProCrudItemPageComponent` into `DYNAMIC_COMPONENTS_STORE`.
46
+
47
+ ### `ProCrudCoreModule`
48
+
49
+ When `routing: false`, `forFeature` returns `ProCrudCoreModule`, which wraps
50
+ the engine's `CrudCoreModule` (logic without routed pages). Use this when you
51
+ manage routing yourself or compose the pro components manually.
52
+
53
+ ## CrudFullConfig — Relevant Fields
54
+
55
+ Declare `CrudFullConfig<T>` from `@smartsoft001/crud-shell-angular`. The fields
56
+ below are the ones the pro layer reads directly; the full reference is in the
57
+ engine's README.
58
+
59
+ ```typescript
60
+ import { CrudFullConfig } from '@smartsoft001/crud-shell-angular';
61
+ import { ListMode, PaginationMode } from '@smartsoft001/angular';
62
+
63
+ export const userConfig: CrudFullConfig<User> = {
64
+ apiUrl: 'https://api.example.com',
65
+ entity: 'user',
66
+ type: User,
67
+
68
+ title: 'Users',
69
+ details: true,
70
+ edit: true,
71
+ add: true,
72
+ remove: true,
73
+ search: true,
74
+ export: true,
75
+ pagination: { limit: 25 },
76
+ sort: { default: 'lastName', defaultDesc: false },
77
+ list: {
78
+ mode: ListMode.desktop,
79
+ paginationMode: PaginationMode.singlePage,
80
+ groups: [], // optional — activates the group accordion
81
+ },
82
+ inputComponents: {}, // per-field input overrides keyed by field name
83
+
84
+ // Pro styling surface (tier 2)
85
+ cssClass: 'smart:bg-gray-50', // forwarded as [class] to page host
86
+ variant: 'with-actions', // picks the smartpro-page-* variant
87
+ };
88
+ ```
89
+
90
+ ## DYNAMIC_COMPONENTS_STORE Override Mechanism
91
+
92
+ The engine resolves `'crud-list-page'` and `'crud-item-page'` dynamic slots
93
+ against `DYNAMIC_COMPONENTS_STORE`. Each pro page component carries a static
94
+ `smartType` field that matches those keys:
95
+
96
+ ```typescript
97
+ // Pro list page
98
+ ProCrudListPageComponent.smartType = 'crud-list-page';
99
+
100
+ // Pro item page
101
+ ProCrudItemPageComponent.smartType = 'crud-item-page';
102
+ ```
103
+
104
+ `ProCrudModule.forFeature` registers both into the token:
105
+
106
+ ```typescript
107
+ {
108
+ provide: DYNAMIC_COMPONENTS_STORE,
109
+ useValue: [ProCrudListPageComponent, ProCrudItemPageComponent],
110
+ }
111
+ ```
112
+
113
+ The engine's dynamic-component resolver checks `DYNAMIC_COMPONENTS_STORE` first
114
+ and selects the pro variant over the free standard variant for those two slots.
115
+
116
+ ## Component Reference
117
+
118
+ All six components are `ChangeDetectionStrategy.OnPush` and extend an engine
119
+ base class that provides all facade wiring.
120
+
121
+ | Selector | Class | Extends | Purpose |
122
+ | --------------------------- | ----------------------------- | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
123
+ | `smartpro-crud-list-page` | `ProCrudListPageComponent` | `CrudListPageBaseComponent` | List page: `smart-crud-filters-config` + `smartpro-list`; shows group accordion when `config.list.groups` is set; hides flat list during search |
124
+ | `smartpro-crud-item-page` | `ProCrudItemPageComponent` | `CrudItemPageBaseComponent` | Item page: `smartpro-details` in details mode; `smart-form` with `config.inputComponents` in add/update mode |
125
+ | `smartpro-crud-filters` | `ProCrudFiltersComponent` | `FiltersBaseComponent` | Filters panel: Tailwind header with close button; individual filter controls via engine `smart-crud-filter` |
126
+ | `smartpro-crud-group` | `ProCrudGroupComponent` | `GroupBaseComponent` | Group accordion: accessible `button`/region with `aria-expanded`, rotating chevron; recursive child group support; embeds `smartpro-list` for leaf groups |
127
+ | `smartpro-crud-multiselect` | `ProCrudMultiselectComponent` | `MultiselectBaseComponent` | Multiselect panel: count header with close; optional `config.list.components.multi` outlet; multi-update `smart-form` + `smartpro-button` submit |
128
+ | `smartpro-crud-export` | `ProCrudExportComponent` | `ExportBaseComponent` | Export popover: CSV and XLSX triggers via `smartpro-button`; `config.cssClass` forwarded to wrapper |
129
+
130
+ ### Key inputs (inherited from engine base classes)
131
+
132
+ | Component | Signal/Input | Source | Description |
133
+ | --------------------------- | ---------------------------------------------------- | --------------------------- | -------------------------------------------------------------------- |
134
+ | `smartpro-crud-list-page` | `listOptions()` | `CrudListPageBaseComponent` | `IListOptionsPro<T>` fed to `smartpro-list` |
135
+ | `smartpro-crud-list-page` | `config` | `inject(CrudFullConfig)` | Full config (groups, cssClass, variant) |
136
+ | `smartpro-crud-item-page` | `mode()` | `CrudItemPageBaseComponent` | `'details' \| 'add' \| 'update'` |
137
+ | `smartpro-crud-item-page` | `detailsOptions()` | `CrudItemPageBaseComponent` | Options fed to `smartpro-details` |
138
+ | `smartpro-crud-item-page` | `selected()` | `CrudItemPageBaseComponent` | Current entity fed to `smart-form` |
139
+ | `smartpro-crud-filters` | `list()` | `FiltersBaseComponent` | Array of filter items; each rendered by `smart-crud-filter` |
140
+ | `smartpro-crud-filters` | `hideMenu()` | `FiltersBaseComponent` | Hides the header row when `true` |
141
+ | `smartpro-crud-group` | `groups()` | `GroupBaseComponent` | Array of group nodes with `key`, `text`, `show`, optional `children` |
142
+ | `smartpro-crud-group` | `listOptions()` | `GroupBaseComponent` | `IListOptionsPro<T>` for leaf group `smartpro-list` |
143
+ | `smartpro-crud-multiselect` | `list()` | `MultiselectBaseComponent` | Array of selected entities |
144
+ | `smartpro-crud-export` | `buttonExportCsvOptions` / `buttonExportXlsxOptions` | `ExportBaseComponent` | `IButtonOptions` for each trigger |
145
+
146
+ ## Styling Rules
147
+
148
+ ### Tier-2 surface: `cssClass` and `variant`
149
+
150
+ ```typescript
151
+ // In CrudFullConfig
152
+ cssClass: 'smart:bg-gray-50 smart:rounded-xl',
153
+ variant: 'with-actions', // any SmartPageVariant from @smartsoft001/pro-angular
154
+ ```
155
+
156
+ - `cssClass` is bound as `[class]` on the page host element of the list and item pages, and on the export wrapper.
157
+ - `variant` is threaded into `pageOptions().variant`, which `SmartProComponentsModule` resolves to the matching `smartpro-page-*` component via `PAGE_VARIANT_COMPONENTS_TOKEN`.
158
+
159
+ ### Tailwind `smart:` prefix — no `[class.smart:X]` shorthand
160
+
161
+ Angular's `[class.X]` shorthand treats the full string `smart:X` as the class
162
+ name, which breaks the Tailwind `smart:` prefix during JIT purging.
163
+
164
+ ```html
165
+ <!-- WRONG -->
166
+ <div [class.smart:font-semibold]="isActive"></div>
167
+
168
+ <!-- CORRECT -->
169
+ <div [class]="isActive ? 'smart:font-semibold' : ''"></div>
170
+ ```
171
+
172
+ All pro CRUD components follow this rule. Enforce it in any customization.
173
+
174
+ ## Known Limitation — Routed Wrappers Do Not Project the Pro Page
175
+
176
+ The engine's free routed wrappers (`smart-crud-list-page` /
177
+ `smart-crud-item-page`) use `CreateDynamicComponent` to mount the override
178
+ found in `DYNAMIC_COMPONENTS_STORE`. The wrapper templates currently do not
179
+ include `DynamicContentDirective` in their `imports` array, so the pro component
180
+ is instantiated but not inserted into the DOM — the page renders blank.
181
+
182
+ **This is an engine-side fix pending in `@smartsoft001/crud-shell-angular`.**
183
+
184
+ Until the fix lands, mount the pro pages directly instead of relying on the
185
+ routed wrappers:
186
+
187
+ ```html
188
+ <smartpro-crud-list-page></smartpro-crud-list-page>
189
+ <smartpro-crud-item-page></smartpro-crud-item-page>
190
+ ```
191
+
192
+ Or compose the components manually inside your own page shell.
193
+
194
+ ## Usage Example
195
+
196
+ ```typescript
197
+ // user.module.ts
198
+ import { NgModule } from '@angular/core';
199
+ import { ProCrudModule } from '@smartsoft001/pro-crud-shell-angular';
200
+ import { userConfig } from './user.config';
201
+
202
+ @NgModule({
203
+ imports: [ProCrudModule.forFeature({ routing: true, config: userConfig })],
204
+ })
205
+ export class UserModule {}
206
+ ```
207
+
208
+ ```html
209
+ <!-- user-list.page.html — direct mount (recommended until engine fix) -->
210
+ <smartpro-crud-list-page></smartpro-crud-list-page>
211
+ ```
212
+
213
+ ```html
214
+ <!-- user-item.page.html -->
215
+ <smartpro-crud-item-page></smartpro-crud-item-page>
216
+ ```
217
+
218
+ Compositional use — embed only the filters panel in a custom page shell:
219
+
220
+ ```html
221
+ <aside class="smart:w-72">
222
+ <smartpro-crud-filters></smartpro-crud-filters>
223
+ </aside>
224
+ <main>
225
+ <!-- your own content -->
226
+ </main>
227
+ ```
228
+
229
+ ## File Locations
230
+
231
+ - Package: `packages/crud/shell/pro-angular/`
232
+ - Module: `packages/crud/shell/pro-angular/src/lib/pro-crud.module.ts`
233
+ - Pages: `packages/crud/shell/pro-angular/src/lib/pages/{list,item}/`
234
+ - Components: `packages/crud/shell/pro-angular/src/lib/components/{filters,group,multiselect,export}/`
235
+ - Barrel: `packages/crud/shell/pro-angular/src/index.ts`
236
+ - README: `packages/crud/shell/pro-angular/README.md`