diff --git a/.github/skills/cps-examples-generator/SKILL.md b/.github/skills/cps-examples-generator/SKILL.md new file mode 100644 index 00000000..ed7b663e --- /dev/null +++ b/.github/skills/cps-examples-generator/SKILL.md @@ -0,0 +1,204 @@ +--- +name: cps-examples-generator +description: > + Generates `.examples.ts` files for cps-shared-ui composition pages. Use this skill + whenever someone asks to add code examples, create an examples file, generate + examples.ts, wire up CodeExampleComponent for a new component page, or populate + HTML/TS code strings for composition previews. Triggers on phrases like "generate + examples for X component", "add code examples to Y page", "create examples.ts for Z", + or "wire up the code preview for W". Always use this skill — not general knowledge — + when working on cps-shared-ui example generation tasks. +--- + +# CPS Examples Generator + +Generates `-page.examples.ts` files for the `cps-shared-ui` composition app. +These files hold the HTML and TypeScript code strings shown in the `CodeExampleComponent` +(Preview / HTML / TS tab switcher) introduced in PR #554. + +## Context + +The composition app lives at `projects/composition/src/app/pages/-page/`. +Each component page has three files: + +- `-page.component.ts` — Angular component, imports `CodeExampleComponent`, exposes `examples` +- `-page.component.html` — Template, wraps each preview in `` +- `-page.examples.ts` — **Your output**: typed object with `html` and `ts` strings per example + +The `CodeExampleComponent` accepts: + +```html + + + +``` + +## Your Job + +Given: + +- The page's **HTML template** (to discover the live preview blocks) +- The page's **TypeScript component** (to discover reactive state, signals, options arrays, etc.) + +Produce a complete `-page.examples.ts` that: + +1. Exports a **single const object** (e.g. `export const buttonExamples = { ... }`) +2. Has one key per `` block (camelCase, matching the `label`) +3. Each key maps to `{ html: string, ts: string }` +4. The `html` string is a **faithful, minimal reproduction** of that preview block — stripped of the outer `` wrapper but keeping inner content verbatim (attributes, bindings, classes, event bindings — everything) +5. The `ts` string shows only what is **relevant to that example**: signal/property declarations, option arrays, event handlers, imports — nothing unrelated to the example + +## Step-by-Step Process + +### 1. Read the inputs + +Ask the user to paste (or point to) the following files for the component being wired up: + +- `-page.component.html` +- `-page.component.ts` + +If both are available in context already, proceed without asking. + +### 2. Identify examples + +Scan the HTML template for every `` block. For each block: + +- Note the `label` input value → this becomes the camelCase key +- Extract the inner content (the live preview markup) → this becomes the `html` string + +### 3. Extract relevant TS per example + +For each example, identify which TypeScript pieces are used by that example's HTML: + +- Signal/property declarations (`myProp = signal(...)`, `options = [...]`) +- Methods/event handlers called in the template (`onSelect(...)`, `onChange(...)`) +- Any reactive computation relevant to the example + +Do **not** include: + +- Imports (readers can figure those out from the component; they clutter the snippet) +- Lifecycle hooks unless they directly set up something used in this specific example +- Component-level boilerplate (`@Component`, `host`, `constructor`) — only include constructor logic if it directly initialises something used in this example +- Properties/signals used only in _other_ examples + +### 4. Format the output + +```typescript +// -page.examples.ts + +export const Examples = { + exampleOneLabel: { + html: ` + +`, + ts: ` +someValue = 'hello'; +handler(event: SomeType) { + // ... +}`, + }, + + exampleTwoLabel: { + html: `...`, + ts: `...`, + }, +}; + +export type Examples = typeof Examples; +``` + +## Strict Rules (never break these) + +| Rule | Why | +| ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | +| **Copy HTML verbatim** — do not paraphrase, simplify, or reformat attributes | Users copy these snippets; any change breaks their code | +| **Preserve Angular syntax exactly** — `[input]`, `(event)`, `*ngIf`, `@if`, signal calls `()`, etc. | Angular is strict about template syntax | +| **No hallucinated properties** — only include TS properties you actually see used in that specific example's HTML | Hallucinated props compile-error or mislead users | +| **No invented imports** — never add import statements to the `ts` string | They vary by project setup and add noise | +| **One object export per file** — don't split into multiple exports or use `default export` | The component imports it as `import { xExamples } from './x-page.examples'` | +| **Preserve indentation style** — if the project uses 2-space indent, keep it | Consistency with the codebase | +| **`ts` string may be empty** — if an example needs no TypeScript at all, use `ts: ''` | `CodeExampleComponent` handles empty TS gracefully | + +## Example Output (Button) + +```typescript +// button-page.examples.ts + +export const buttonExamples = { + primaryButton: { + html: ` +`, + ts: ` +onButtonClick() { + console.log('Button clicked'); +}` + }, + + disabledButton: { + html: ` +`, + ts: `` + }, + + buttonWithIcon: { + html: ` +`, + ts: `` + } +}; + +export type ButtonExamples = typeof buttonExamples; +``` + +## After generating examples.ts + +Remind the user of the two integration steps still needed: + +**1. In `-page.component.ts`**, import `CodeExampleComponent` and the examples: + +```typescript +import { CodeExampleComponent } from '../../components/code-example/code-example.component'; +import { componentExamples } from './-page.examples'; + +// inside @Component: +imports: [..., CodeExampleComponent], + +// inside class: +readonly examples = componentExamples; +``` + +**2. In `-page.component.html`**, wrap each preview: + +```html + + + +``` + +Point them to an already-wired component (Autocomplete, Button, Button Toggle from PR #554) +as a reference if they want to see a complete end-to-end example. + +## Handling Ambiguity + +- **Signal vs property unclear?** Default to property syntax in the `ts` string; it's safe for both +- **Example has complex reactive setup shared across examples?** Extract the shared state once into both `ts` strings — duplication is fine; accuracy matters more +- **Template uses `@if` / `@for` control flow?** Include in `html` verbatim; do NOT convert to `*ngIf`/`*ngFor` +- **Example uses a service injected in constructor?** Show the injection in the `ts` string as a comment: `// inject(MyService) used here` + +## File placement in the repo + +``` +projects/composition/src/app/pages/-page/ +├── -page.component.ts +├── -page.component.html +├── -page.component.scss +└── -page.examples.ts ← generated file goes here +```