@ng-solid/mcp 22.0.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 (47) hide show
  1. package/GUIDE.md +292 -0
  2. package/README.md +159 -0
  3. package/data/design-system.json +24204 -0
  4. package/data/icons.json +1 -0
  5. package/data/skills/ns-solid-components/SKILL.md +140 -0
  6. package/data/skills/ns-solid-forms/SKILL.md +183 -0
  7. package/data/skills/ns-solid-icons/SKILL.md +95 -0
  8. package/data/skills/ns-solid-install/SKILL.md +120 -0
  9. package/data/skills/ns-solid-style-contract/SKILL.md +84 -0
  10. package/data/skills/ns-solid-theming/SKILL.md +123 -0
  11. package/index.d.ts +3 -0
  12. package/index.js +38 -0
  13. package/lib/data.d.ts +26 -0
  14. package/lib/data.js +51 -0
  15. package/lib/install-skills.d.ts +1 -0
  16. package/lib/install-skills.js +159 -0
  17. package/lib/preset-validator.d.ts +44 -0
  18. package/lib/preset-validator.js +172 -0
  19. package/lib/prompts.d.ts +2 -0
  20. package/lib/prompts.js +173 -0
  21. package/lib/resources.d.ts +2 -0
  22. package/lib/resources.js +328 -0
  23. package/lib/server.d.ts +3 -0
  24. package/lib/server.js +31 -0
  25. package/lib/style-contract.d.ts +37 -0
  26. package/lib/style-contract.js +167 -0
  27. package/lib/template-parser.d.ts +29 -0
  28. package/lib/template-parser.js +230 -0
  29. package/lib/tools.components.d.ts +44 -0
  30. package/lib/tools.components.js +836 -0
  31. package/lib/tools.d.ts +9 -0
  32. package/lib/tools.guides.d.ts +15 -0
  33. package/lib/tools.guides.js +103 -0
  34. package/lib/tools.icons.d.ts +7 -0
  35. package/lib/tools.icons.js +106 -0
  36. package/lib/tools.js +18 -0
  37. package/lib/tools.tokens.d.ts +7 -0
  38. package/lib/tools.tokens.js +278 -0
  39. package/lib/types.d.ts +349 -0
  40. package/lib/types.js +11 -0
  41. package/package.json +52 -0
  42. package/skills/ns-solid-components/SKILL.md +77 -0
  43. package/skills/ns-solid-forms/SKILL.md +166 -0
  44. package/skills/ns-solid-icons/SKILL.md +95 -0
  45. package/skills/ns-solid-install/SKILL.md +119 -0
  46. package/skills/ns-solid-style-contract/SKILL.md +84 -0
  47. package/skills/ns-solid-theming/SKILL.md +123 -0
@@ -0,0 +1,95 @@
1
+ ---
2
+ name: ns-solid-icons
3
+ description: Render Lucide icons with @ng-solid/icons' <ns-icon> component — registering symbols with provideIcons/provideIconsPatch and resolving camelCase symbol names.
4
+ ---
5
+
6
+ # Iconos con @ng-solid/icons
7
+
8
+ ## El componente `<ns-icon>`
9
+
10
+ ```html
11
+ <ns-icon name="alarm-clock" [size]="20" />
12
+ ```
13
+
14
+ `NsIconsComponent` (selector `ns-icon`) acepta:
15
+
16
+ - `name: string` — el nombre **kebab-case** del icono Lucide (`alarm-clock`,
17
+ no `alarmClock`).
18
+ - `size: number` (default `24`) — acepta el atributo plano (`numberAttribute`),
19
+ así que `<ns-icon name="x" size="16">` también funciona.
20
+ - `color: string` (default `'currentColor'`).
21
+ - `strokeWidth: number` (default `2`).
22
+ - `viewBox: string` (default `'0 0 24 24'`).
23
+
24
+ Internamente resuelve el SVG contra un `Map` poblado por
25
+ `provideIcons`/`provideIconsPatch`; si el nombre no fue registrado, emite un
26
+ `console.warn` y no renderiza el path.
27
+
28
+ ## Registrar iconos — dos providers, dos momentos distintos
29
+
30
+ **`provideIcons(icons)`** — en el bootstrap de la app (`appConfig.providers`
31
+ o `bootstrapApplication`). Usar para los iconos que se necesitan siempre:
32
+
33
+ ```ts
34
+ import { provideIcons, alarmClock, x } from '@ng-solid/icons';
35
+
36
+ export const appConfig: ApplicationConfig = {
37
+ providers: [
38
+ // ...
39
+ provideIcons([alarmClock, x])
40
+ ]
41
+ };
42
+ ```
43
+
44
+ **`provideIconsPatch(icons)`** — a nivel de `Route.providers`, para iconos
45
+ que sólo hace falta cargar cuando se navega a esa ruta (lazy):
46
+
47
+ ```ts
48
+ const routes: Routes = [
49
+ {
50
+ path: 'products',
51
+ providers: [provideIconsPatch([alarmClock])],
52
+ loadComponent: () =>
53
+ import('./products.component').then((m) => m.ProductsComponent)
54
+ }
55
+ ];
56
+ ```
57
+
58
+ `provideIconsPatch` registra además `NsIconsPatchService`, que
59
+ `NsIconsComponent` detecta e invoca (`doPatch()`) antes de intentar resolver
60
+ el icono, para que el registro parcial se aplique aunque el componente ya
61
+ esté instanciado.
62
+
63
+ ## Los símbolos se importan en camelCase
64
+
65
+ El catálogo generado (`packages/icons/src/lib/generated/index.ts`) exporta
66
+ un símbolo por icono con el nombre kebab-case convertido a camelCase:
67
+
68
+ | Icono (`name` en `<ns-icon>`) | Símbolo importado de `@ng-solid/icons` |
69
+ | --------------------------------- | -------------------------------------- |
70
+ | `alarm-clock` | `alarmClock` |
71
+ | `a-arrow-down` | `aArrowDown` |
72
+ | `align-horizontal-justify-center` | `alignHorizontalJustifyCenter` |
73
+ | `circle-check` | `circleCheck` |
74
+
75
+ Cada símbolo es un objeto `{ name, icon }` (ver `NsIconDefinition`) — nunca
76
+ pases un string al provider, pasa el símbolo importado.
77
+
78
+ ## Catálogo
79
+
80
+ <!-- ns:icon-count -->
81
+
82
+ - Fuente: Lucide (`LUCIDE_SOURCE_URL` en `packages/icons/src/lib/generated/metadata.ts`).
83
+ - Licencia: **ISC** (`LUCIDE_SOURCE_LICENSE`).
84
+ - Usa la tool `search_icons` del MCP para encontrar el `name`/símbolo correcto
85
+ por palabra clave en vez de adivinar el nombre exacto de Lucide.
86
+
87
+ ## Errores comunes
88
+
89
+ - Registrar el símbolo pero usar un `name` distinto en el template (deben
90
+ coincidir exactamente, kebab-case).
91
+ - Olvidar `provideIcons`/`provideIconsPatch` por completo — el icono no
92
+ truena, simplemente no renderiza y deja un warning en consola.
93
+ - Confundir `provideIcons` (bootstrap, global) con `provideIconsPatch`
94
+ (`Route.providers`, por ruta) — usar el segundo en el bootstrap no falla,
95
+ pero pierde el propósito de carga diferida.
@@ -0,0 +1,119 @@
1
+ ---
2
+ name: ns-solid-install
3
+ description: Install and bootstrap @ng-solid/design-system (Arvisfy) plus @ng-solid/icons in an Angular 21 standalone application, including the Tailwind bridge and theme provider.
4
+ ---
5
+
6
+ # Instalación de @ng-solid/design-system
7
+
8
+ ## Paquetes y peer dependencies
9
+
10
+ ```bash
11
+ pnpm add @ng-solid/design-system @ng-solid/icons
12
+ ```
13
+
14
+ `@ng-solid/design-system` declara estos peer dependencies (ver
15
+ `packages/design-system/package.json`):
16
+
17
+ - `@angular/core`, `@angular/common`, `@angular/forms`,
18
+ `@angular/platform-browser`, `@angular/router` en `^21.0.0`.
19
+ - `@ng-solid/icons` en `^22.0.5`.
20
+ - `tailwindcss` en `^4.0.0`, marcado **opcional** (`peerDependenciesMeta`) —
21
+ sólo hace falta si la app consume el puente de utilidades semánticas.
22
+
23
+ Versiones publicadas actualmente:
24
+
25
+ <!-- ns:versions -->
26
+
27
+ Si tu app usa Tailwind, añade también el plugin de PostCSS:
28
+
29
+ ```bash
30
+ pnpm add -D tailwindcss @tailwindcss/postcss
31
+ ```
32
+
33
+ ## Entrypoint único — nada de subpaths
34
+
35
+ `@ng-solid/design-system` tiene **un solo entry point público**
36
+ (`ng-package.json` → `entryFile: src/index.ts`, sin `secondaryEntrypoints`).
37
+ Todo se importa desde la raíz del paquete:
38
+
39
+ ```ts
40
+ import { NsButtonComponent, NsInputComponent } from '@ng-solid/design-system';
41
+ ```
42
+
43
+ Nunca inventes rutas como `@ng-solid/design-system/button` — no existen. La
44
+ única excepción es el asset CSS publicado explícitamente como
45
+ `@ng-solid/design-system/themes/tailwind.css` (ver más abajo), que no es un
46
+ entry point de JS/TS.
47
+
48
+ ## Puente de Tailwind
49
+
50
+ Si la app importa el puente semántico, hazlo una sola vez en el stylesheet
51
+ global, después de las capas de Tailwind:
52
+
53
+ ```css
54
+ @import '@ng-solid/design-system/themes/tailwind.css';
55
+ ```
56
+
57
+ Ese fichero define el bridge `@theme inline` que mapea los tokens de
58
+ Tailwind a `--ns-semantic-*`, además de registrar localmente la fuente
59
+ variable Inter (sin peticiones de red en runtime).
60
+
61
+ ## Registrar el tema en `appConfig`
62
+
63
+ ```ts
64
+ import { Arvisfy, provideNsTheme } from '@ng-solid/design-system';
65
+ import { ApplicationConfig } from '@angular/core';
66
+
67
+ export const appConfig: ApplicationConfig = {
68
+ providers: [provideNsTheme({ preset: Arvisfy, colorScheme: 'system' })]
69
+ };
70
+ ```
71
+
72
+ `colorScheme: 'system'` sigue `prefers-color-scheme`. Ver la skill
73
+ `ns-solid-theming` para `defineNsPreset`, `NsThemeService.setScheme` y las
74
+ reglas de validación del preset.
75
+
76
+ ## Standalone: `imports` es obligatorio
77
+
78
+ Todos los componentes son **standalone**. Angular no los resuelve
79
+ automáticamente: hay que declararlos explícitamente en el `imports` del
80
+ componente (o del `NgModule`) que los usa. Omitir esto es el error más común
81
+ al generar código con un agente:
82
+
83
+ ```ts
84
+ import { Component } from '@angular/core';
85
+ import { NsButtonComponent } from '@ng-solid/design-system';
86
+
87
+ @Component({
88
+ selector: 'app-toolbar',
89
+ standalone: true,
90
+ imports: [NsButtonComponent], // obligatorio — <ns-button> no funciona sin esto
91
+ template: `<ns-button variant="primary">Guardar</ns-button>`
92
+ })
93
+ export class ToolbarComponent {}
94
+ ```
95
+
96
+ Esto vale también para directivas de composición (`NsFieldDirective`,
97
+ `NsTooltipDirective`, `NsDropdownItemDirective`, etc.) y para componentes
98
+ usados vía `contentChildren`/proyección (`ns-card-header`, `ns-tab`,
99
+ `ns-accordion-item`…): todos deben aparecer en `imports`.
100
+
101
+ ## Iconos
102
+
103
+ `@ng-solid/icons` se instala aparte y se registra con `provideIcons(...)` en
104
+ el bootstrap. Ver la skill `ns-solid-icons` para el detalle completo
105
+ (símbolos camelCase, `provideIconsPatch` para rutas con lazy loading).
106
+
107
+ ## Extender el preset
108
+
109
+ No copies `Arvisfy`; extiéndelo con `defineNsPreset` (ver `ns-solid-theming`
110
+ para las reglas de validación completas):
111
+
112
+ ```ts
113
+ import { Arvisfy, defineNsPreset } from '@ng-solid/design-system';
114
+
115
+ export const ProductTheme = defineNsPreset(Arvisfy, {
116
+ name: 'product',
117
+ primitive: { color: { brand: { 500: '#0052ff' } } }
118
+ });
119
+ ```
@@ -0,0 +1,84 @@
1
+ ---
2
+ name: ns-solid-style-contract
3
+ description: Follow ng-solid's enforced style architecture — ns-* BEM class naming, zero Tailwind utilities in markup, and the @reference-only SCSS contract checked by pnpm quality:styles.
4
+ ---
5
+
6
+ # Contrato de estilos de ng-solid
7
+
8
+ Este contrato lo enforcea en CI
9
+ `tools/scripts/check-design-system-styles.mjs` (`pnpm quality:styles`) sobre
10
+ `packages/design-system/src/lib` y `apps/demo/src`. Un PR que lo viole falla
11
+ el build, tanto en la librería como en aplicaciones que sigan la misma
12
+ convención.
13
+
14
+ ## 1. Clases de template: sólo `ns-*` BEM
15
+
16
+ Toda clase en `class="…"`, `[class.x]` o claves de objeto `[ngClass]` debe
17
+ matchear:
18
+
19
+ ```
20
+ ns-block__element--modifier
21
+ ```
22
+
23
+ Regex real usada por el gate:
24
+
25
+ ```
26
+ /^ns-[a-z0-9]+(?:-[a-z0-9]+)*(?:(?:__[a-z0-9]+(?:-[a-z0-9]+)*)?(?:--[a-z0-9]+(?:-[a-z0-9]+)*)?)?$/
27
+ ```
28
+
29
+ Válido: `ns-button`, `ns-button__icon`, `ns-button--danger`,
30
+ `ns-card__header--sticky`. Inválido: `btn-primary`, `NsButton`,
31
+ `ns_button`, `flex`.
32
+
33
+ ## 2. Cero utilidades Tailwind en markup
34
+
35
+ Ninguna clase de template puede empezar con un prefijo de utilidad Tailwind
36
+ (`flex`, `grid`, `gap-`, `p-`/`m-` + variantes, `text-`, `bg-`, `border`,
37
+ `rounded`, `shadow`, `absolute`/`relative`/`fixed`/`sticky`, `inset`/`top-`/
38
+ `bottom-`/`start-`/`end-`, `z-`, `w-`/`h-`, `min-`/`max-`, `overflow`,
39
+ `opacity`, `font-`, `items-`/`justify-`/`content-`). Tailwind se compone
40
+ **sólo** desde SCSS con `@apply`, nunca directamente en el HTML.
41
+
42
+ ## 3. Nada de `styles:` inline
43
+
44
+ Un componente no puede declarar estilos inline en el decorador
45
+ (`styles: [...]`). Usa `styleUrl` (o `styleUrls`) apuntando a un `.scss`
46
+ hermano.
47
+
48
+ ## 4. SCSS de componente: `@reference`, sin `@use`/`@import`, sin valores crudos
49
+
50
+ Cada `.scss` de componente (fuera de `lib/theme/`) debe:
51
+
52
+ - Incluir literalmente `@reference` (al bridge de Tailwind:
53
+ `@reference '../theme/tailwind.css';` o la ruta relativa que corresponda).
54
+ - **No** usar `@use` ni `@import` — extender Tailwind sólo vía `@reference`.
55
+ - **No** contener valores crudos: hex (`#fff`), `rgb()`/`rgba()`, literales
56
+ `px`/`rem`/`em`/`ms`/`s`, o `var(--x, fallback)` con valor por defecto.
57
+ Toda decisión visual se lee de un token `--ns-component-*` ya resuelto por
58
+ el preset (ver la skill `ns-solid-theming`) — sin fallback embebido, porque
59
+ el preset garantiza que la variable siempre está definida.
60
+
61
+ Ejemplo correcto:
62
+
63
+ ```scss
64
+ @reference '../theme/tailwind.css';
65
+
66
+ .ns-button {
67
+ @apply inline-flex items-center;
68
+ background: var(--ns-component-button-background);
69
+ color: var(--ns-component-button-foreground);
70
+ }
71
+ ```
72
+
73
+ ## 5. Prohibido reintroducir Bootstrap / `@popperjs`
74
+
75
+ El gate falla si `package.json` o `pnpm-lock.yaml` vuelven a traer
76
+ `bootstrap` o `@popperjs/*` — el design-system fue migrado fuera de esas
77
+ dependencias deliberadamente.
78
+
79
+ ## Validar un snippet antes de proponerlo
80
+
81
+ Usa la tool del MCP `validate_style_contract` (o `validate_component_usage`
82
+ para un uso completo de componente) contra cualquier markup/SCSS que generes
83
+ antes de entregarlo — es la misma lógica que corre `pnpm quality:styles`,
84
+ expuesta como función pura.
@@ -0,0 +1,123 @@
1
+ ---
2
+ name: ns-solid-theming
3
+ description: Work with the Arvisfy three-tier token architecture in @ng-solid/design-system — extending the preset, validating tokens and switching color scheme at runtime.
4
+ ---
5
+
6
+ # Theming con Arvisfy
7
+
8
+ ## Los tres niveles de tokens
9
+
10
+ `packages/design-system/src/lib/theme/presets/arvisfy.preset.ts` define el
11
+ preset en tres tiers, cada uno sólo puede referenciar al tier anterior:
12
+
13
+ 1. **`primitive`** — únicos valores crudos permitidos (hex, `rem`, pesos de
14
+ fuente, escalas numéricas). Ejemplo real: `primitive.color.klein.500 =
15
+ '#3665F3'`.
16
+ 2. **`semantic`** — referencia primitivos con la sintaxis `{primitive.…}`, y
17
+ se divide en `common` (independiente de esquema) y
18
+ `colorScheme.light` / `colorScheme.dark` (un valor distinto por esquema).
19
+ 3. **`components`** — referencia semánticos con `{semantic.…}`. Es el único
20
+ tier que las hojas de estilo de componente pueden consumir, y sólo a
21
+ través de la variable CSS resultante.
22
+
23
+ Conteo actual del preset Arvisfy:
24
+
25
+ <!-- ns:token-count -->
26
+
27
+ ## Regla de oro del SCSS de componente
28
+
29
+ El SCSS de un componente **sólo** puede leer variables `--ns-component-*`.
30
+ Nunca `--ns-primitive-*` ni `--ns-semantic-*` directamente, y nunca un valor
31
+ crudo (hex, `rgb()`, `px`/`rem`/`ms` literal) — eso lo enforcea
32
+ `pnpm quality:styles` (ver la skill `ns-solid-style-contract`).
33
+
34
+ La conversión de un path de token a variable CSS es determinista
35
+ (`tokenPathToCssVariable` en `theme.utils.ts`): camelCase se separa en
36
+ kebab-case y los puntos se vuelven guiones, con el tier como prefijo:
37
+
38
+ ```
39
+ tier: 'component', path: 'button.background'
40
+ -> --ns-component-button-background
41
+ ```
42
+
43
+ ## Extender el preset — nunca copiarlo
44
+
45
+ ```ts
46
+ import { Arvisfy, defineNsPreset } from '@ng-solid/design-system';
47
+
48
+ export const ProductTheme = defineNsPreset(Arvisfy, {
49
+ name: 'product',
50
+ primitive: {
51
+ color: { brand: { 500: '#0052ff' } }
52
+ },
53
+ semantic: {
54
+ colorScheme: {
55
+ light: { color: { primary: '{primitive.color.brand.500}' } },
56
+ dark: { color: { primary: '{primitive.color.brand.500}' } }
57
+ }
58
+ },
59
+ components: {
60
+ button: { borderColor: '{semantic.color.primary}' }
61
+ }
62
+ });
63
+ ```
64
+
65
+ `defineNsPreset(base, overrides)` hace un merge profundo (`overrides` gana
66
+ por clave) y llama a `validateNsPreset` sobre el resultado antes de
67
+ devolverlo. `NsThemeService` también valida el preset activo en su
68
+ constructor y en cada `setPreset`.
69
+
70
+ ## Reglas que aplica `validateNsPreset`
71
+
72
+ Extraídas de `packages/design-system/src/lib/theme/utils/theme.utils.ts`:
73
+
74
+ - **Nombre del preset**: debe matchear `/^[a-z][a-z0-9-]*$/i` (falla si no).
75
+ - **Claves de token**: cada segmento del path debe matchear
76
+ `/^(?:[a-z][a-zA-Z0-9]*|[0-9]+)$/` — sin guiones ni mayúsculas iniciales.
77
+ - **Valores primitivos seguros**: ningún string primitivo puede contener
78
+ `;`, `{` o `}`, ni estar vacío.
79
+ - **Referencias `semantic.*`**: todo valor de `semantic.common` /
80
+ `semantic.colorScheme.{light,dark}` debe tener la forma exacta
81
+ `{primitive.<path>}` y ese `<path>` debe existir en `primitive`.
82
+ - **Referencias `components.*`**: todo valor debe tener la forma
83
+ `{semantic.<path>}`, y ese `<path>` debe existir en `semantic.common`, o
84
+ en **ambos** `colorScheme.light` y `colorScheme.dark` a la vez — un token
85
+ de componente que sólo resuelve en un esquema es un preset inválido.
86
+
87
+ Cualquier violación lanza una excepción síncrona (`throw new Error(...)`),
88
+ no un warning: un preset inválido rompe el arranque de la app.
89
+
90
+ ## Cambiar de esquema en runtime
91
+
92
+ ```ts
93
+ import { inject } from '@angular/core';
94
+ import { NsThemeService } from '@ng-solid/design-system';
95
+
96
+ const theme = inject(NsThemeService);
97
+ theme.setScheme('dark'); // 'light' | 'dark' | 'system'
98
+ ```
99
+
100
+ - `'system'` delega en `prefers-color-scheme` y reacciona a cambios en vivo
101
+ vía `matchMedia('(prefers-color-scheme: dark)')`.
102
+ - Una elección explícita (`'light'` / `'dark'`) se persiste en
103
+ `localStorage` bajo la clave `ns-color-scheme` (configurable con
104
+ `provideNsTheme({ storageKey: '...' })`, o desactivable con
105
+ `storageKey: false`).
106
+ - `NsThemeService` expone `preset`, `colorScheme`, `resolvedColorScheme`
107
+ (siempre `'light' | 'dark'`, nunca `'system'`) y `scheme` como signals de
108
+ sólo lectura.
109
+ - Al aplicar el tema, el servicio escribe todas las custom properties en
110
+ `documentElement.style` y además `dataset.nsPreset` / `dataset.nsColorScheme`
111
+ y `style.colorScheme`, para que el navegador ajuste scrollbars/controles
112
+ nativos.
113
+
114
+ ## Configurar el provider
115
+
116
+ ```ts
117
+ provideNsTheme({
118
+ preset: Arvisfy,
119
+ colorScheme: 'system', // default
120
+ storageKey: 'ns-color-scheme', // default; false para desactivar persistencia
121
+ toast: { placement: 'top-end' } // default de NsToastService
122
+ });
123
+ ```