lkd-web-kit 0.10.6 → 0.10.8

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 (27) hide show
  1. package/package.json +2 -2
  2. package/scripts/install-agent-skills.mjs +2 -2
  3. package/src/distributed-skills/lkd-create-modal-component/SKILL.md +168 -0
  4. package/src/distributed-skills/lkd-create-modal-component/agents/openai.yaml +4 -0
  5. package/src/distributed-skills/lkd-create-nextjs-page/SKILL.md +84 -0
  6. package/src/distributed-skills/lkd-create-nextjs-page/agents/openai.yaml +3 -0
  7. package/src/distributed-skills/lkd-create-svg-icon/SKILL.md +41 -0
  8. package/src/distributed-skills/lkd-create-svg-icon/agents/openai.yaml +3 -0
  9. package/src/distributed-skills/lkd-create-table-component/SKILL.md +189 -0
  10. package/src/distributed-skills/lkd-create-table-component/agents/openai.yaml +3 -0
  11. package/src/distributed-skills/lkd-layout-mantine-tailwind/SKILL.md +99 -0
  12. package/src/distributed-skills/lkd-layout-mantine-tailwind/agents/openai.yaml +4 -0
  13. package/src/distributed-skills/lkd-rhf-lkd-forms/SKILL.md +186 -0
  14. package/.agents/skills/create-nextjs-page/SKILL.md +0 -104
  15. package/.agents/skills/create-nextjs-page/agents/openai.yaml +0 -3
  16. package/.agents/skills/mantine-combobox/SKILL.md +0 -73
  17. package/.agents/skills/mantine-combobox/references/api.md +0 -199
  18. package/.agents/skills/mantine-combobox/references/patterns.md +0 -279
  19. package/.agents/skills/mantine-custom-components/SKILL.md +0 -112
  20. package/.agents/skills/mantine-custom-components/references/api.md +0 -407
  21. package/.agents/skills/mantine-custom-components/references/patterns.md +0 -431
  22. package/.agents/skills/publish-lkd-web-kit/SKILL.md +0 -165
  23. package/.agents/skills/publish-lkd-web-kit/agents/openai.yaml +0 -4
  24. package/.agents/skills/publish-lkd-web-kit/references/npm-trusted-publishing.md +0 -82
  25. package/.agents/skills/update-lkd-dependencies/SKILL.md +0 -88
  26. package/.agents/skills/update-lkd-dependencies/agents/openai.yaml +0 -4
  27. package/.agents/skills/update-lkd-dependencies/scripts/collect-npm-metadata.mjs +0 -73
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lkd-web-kit",
3
- "version": "0.10.6",
3
+ "version": "0.10.8",
4
4
  "description": "A template for creating React component libraries with Vite.",
5
5
  "author": "LKD",
6
6
  "license": "MIT",
@@ -26,7 +26,7 @@
26
26
  "engines": {
27
27
  "node": ">=22.12.0"
28
28
  },
29
- "files": ["dist", ".agents/skills", "scripts/install-agent-skills.mjs"],
29
+ "files": ["dist", "src/distributed-skills", "scripts/install-agent-skills.mjs"],
30
30
  "scripts": {
31
31
  "test": "vitest run --passWithNoTests",
32
32
  "test:watch": "vitest",
@@ -4,11 +4,11 @@ import { dirname, join } from 'node:path'
4
4
  import { fileURLToPath } from 'node:url'
5
5
 
6
6
  const scriptDir = dirname(fileURLToPath(import.meta.url))
7
- const source = join(scriptDir, '..', '.agents', 'skills')
7
+ const source = join(scriptDir, '..', 'src', 'distributed-skills')
8
8
  const target = join(process.cwd(), '.agents', 'skills')
9
9
 
10
10
  if (!existsSync(source)) {
11
- throw new Error(`No se encontraron skills en ${source}`)
11
+ throw new Error(`No se encontraron skills distribuibles en ${source}`)
12
12
  }
13
13
 
14
14
  mkdirSync(target, { recursive: true })
@@ -0,0 +1,168 @@
1
+ ---
2
+ name: lkd-create-modal-component
3
+ description: Crear modales en proyectos internos con el modal manager global de lkd-web-kit. Usar cuando Codex deba agregar, modificar o registrar modales bajo src/components/modals, envolverlos con withModalManager, elegir entre un modal interno del proyecto o Modal de Mantine, organizar el modal en carpeta propia, tipar props para showModal, actualizar dynamicModals, MyModalManagerProvider, module augmentation o loadModals.
4
+ ---
5
+
6
+ # Crear Modal Component
7
+
8
+ Usar este flujo para modales abiertos con `useModalManager().showModal(...)`.
9
+
10
+ ## Lectura Obligatoria
11
+
12
+ 1. Leer `docs/lkd-web-kit.md` y `docs/local-components.md`.
13
+ 2. Leer `src/components/modals/index.ts`.
14
+ 3. Leer `src/contexts/MyModalManagerContext/index.tsx`.
15
+ 4. Leer `src/types/lkd-web-kit.d.ts`.
16
+ 5. Buscar si existe un modal interno en `src/components/ui` o componentes compartidos antes de importar `Modal` de Mantine.
17
+ 6. Leer un modal existente del mismo dominio en `src/components/modals/{dominio}`.
18
+ 7. Si se toca `next/dynamic` o lazy loading, leer `node_modules/next/dist/docs/01-app/02-guides/lazy-loading.md`.
19
+
20
+ ## Arquitectura Actual
21
+
22
+ - `lkd-web-kit` exporta `ModalManagerProvider`, `useModalManager`, `withModalManager`, `ModalRegistryItem`, `ModalKey` y tipos relacionados.
23
+ - El proyecto no usa `src/contexts/ModalManagerContext`; no recrearlo.
24
+ - `src/contexts/MyModalManagerContext/index.tsx` adapta el provider del kit y le pasa `dynamicModals`.
25
+ - `src/types/lkd-web-kit.d.ts` hace module augmentation para que `showModal` infiera keys y props desde `dynamicModals`.
26
+ - `src/app/PageProviders.tsx` envuelve la app con `MyModalManagerProvider` y propaga `loadModals`.
27
+
28
+ ## Estructura
29
+
30
+ - Crear modales en `src/components/modals/{dominio}/{NombreModal}/index.tsx` cuando tengan formulario, schema, hooks internos, assets o subcomponentes.
31
+ - Usar archivo plano `src/components/modals/{dominio}/{NombreModal}.tsx` solo para modales triviales de una pieza, siguiendo el patron existente.
32
+ - Colocar piezas privadas junto al modal: `schema.ts`, `helpers.ts`, subcomponentes o assets dentro de la misma carpeta.
33
+ - No mover logica compartida a `src/components/ui` salvo que ya exista mas de un consumidor real.
34
+
35
+ ## Implementacion
36
+
37
+ 1. Definir props exportadas si el modal recibe datos desde `showModal`:
38
+
39
+ ```tsx
40
+ export interface MyModalProps {
41
+ itemId: string;
42
+ onSuccess?: () => void;
43
+ }
44
+ ```
45
+
46
+ 2. Envolver el componente con `withModalManager<Props>`.
47
+ 3. Recibir `modalProps` desde el wrapper y pasarlo al modal raiz.
48
+ 4. Antes de usar `Modal` de `@mantine/core`, corroborar si el proyecto tiene un modal interno que ya envuelve Mantine y usarlo si cubre el caso.
49
+ 5. Usar clases Tailwind para spacing, radius, shadow, margin y padding; evitar props Mantine equivalentes si `className` resuelve el caso.
50
+ 6. Usar wrappers locales del proyecto o `lkd-web-kit` antes que primitivas Mantine directas.
51
+ 7. No usar `any`.
52
+
53
+ Modal base con modal interno:
54
+
55
+ ```tsx
56
+ import { withModalManager } from "lkd-web-kit";
57
+ import ButtonAE from "src/components/ui/ButtonAE";
58
+ import InternalModal from "src/components/ui/InternalModal";
59
+
60
+ export interface MyModalProps {
61
+ onConfirm?: () => void;
62
+ }
63
+
64
+ const MyModal = withModalManager<MyModalProps>(
65
+ ({ onConfirm, modalProps }) => {
66
+ return (
67
+ <InternalModal {...modalProps} size="lg">
68
+ <InternalModal.Header>Titulo</InternalModal.Header>
69
+ <InternalModal.Body className="grid gap-4">Contenido</InternalModal.Body>
70
+ <InternalModal.Footer>
71
+ <ButtonAE
72
+ onClick={() => {
73
+ onConfirm?.();
74
+ modalProps.onClose?.();
75
+ }}
76
+ >
77
+ Guardar
78
+ </ButtonAE>
79
+ </InternalModal.Footer>
80
+ </InternalModal>
81
+ );
82
+ },
83
+ );
84
+
85
+ export default MyModal;
86
+ ```
87
+
88
+ Fallback con Mantine, solo si no hay modal interno aplicable:
89
+
90
+ ```tsx
91
+ import { Modal } from "@mantine/core";
92
+ import { withModalManager } from "lkd-web-kit";
93
+
94
+ const MyModal = withModalManager(({ modalProps }) => (
95
+ <Modal {...modalProps} title="Titulo">
96
+ Contenido
97
+ </Modal>
98
+ ));
99
+
100
+ export default MyModal;
101
+ ```
102
+
103
+ ## Registro
104
+
105
+ 1. Exportar las props publicas desde el modal.
106
+ 2. Importar el tipo de props en `src/components/modals/index.ts`:
107
+
108
+ ```ts
109
+ import type { MyModalProps } from "./domain/MyModal";
110
+ ```
111
+
112
+ 3. Registrar con `dynamicModal<Props>("domain/MyModal")`:
113
+
114
+ ```ts
115
+ "domain.myModal": dynamicModal<MyModalProps>("domain/MyModal"),
116
+ ```
117
+
118
+ 4. Usar una key estable con formato `{dominio}.{accion}`.
119
+ 5. No tocar `src/types/lkd-web-kit.d.ts` si `dynamicModals` sigue siendo la fuente unica. La augmentacion ya apunta a `typeof dynamicModals`.
120
+ 6. Si se cambia la forma del registro, mantener `ModalRegistryItem<T>` y que cada item tenga `component`, `load` y `path`.
121
+
122
+ ## Contexto y Precarga
123
+
124
+ - Para rutas que ya usan `PageProviders`, pasar `loadModals` ahi:
125
+
126
+ ```tsx
127
+ <PageProviders loadModals={["domain.myModal"]}>{children}</PageProviders>
128
+ ```
129
+
130
+ - `loadModals` acepta una key exacta o un prefijo, por ejemplo `"development"` para precargar todos los modales cuyo key empieza con ese prefijo.
131
+ - Para layouts que no usan `PageProviders`, envolver el arbol con `MyModalManagerProvider`:
132
+
133
+ ```tsx
134
+ import { MyModalManagerProvider } from "src/contexts/MyModalManagerContext";
135
+
136
+ <MyModalManagerProvider loadModals={["domain.myModal"]}>
137
+ {children}
138
+ </MyModalManagerProvider>
139
+ ```
140
+
141
+ - Evitar providers anidados salvo que haya una razon real: un provider interno aisla estado y puede cerrar o reemplazar modales inesperadamente.
142
+ - Invocar siempre con `useModalManager` desde `lkd-web-kit`, nunca importando el modal directo desde una vista:
143
+
144
+ ```tsx
145
+ import { useModalManager } from "lkd-web-kit";
146
+
147
+ const { showModal, closeModal } = useModalManager();
148
+ showModal("domain.myModal", { itemId: "123" });
149
+ closeModal("domain.myModal");
150
+ ```
151
+
152
+ ## Formularios Dentro de Modales
153
+
154
+ - Usar la skill `rhf-lkd-forms` si el modal contiene formulario.
155
+ - Pasar `onSuccess={modalProps.onClose}` o cerrar en el submit exitoso.
156
+ - En errores de API, mostrar la alerta esperada y luego hacer `throw error`.
157
+ - No poner mensajes textuales en reglas base de Zod.
158
+
159
+ ## Checklist
160
+
161
+ - El modal exporta default envuelto con `withModalManager`.
162
+ - Las props publicas estan exportadas y registradas en `dynamicModals`.
163
+ - `showModal("key", props)` queda tipado sin `any`.
164
+ - `useModalManager` se importa desde `lkd-web-kit`.
165
+ - La ruta esta bajo `PageProviders` o `MyModalManagerProvider`.
166
+ - `loadModals` se agrega solo cuando conviene precargar.
167
+ - Se reutiliza el modal interno del proyecto salvo necesidad concreta de Mantine directo.
168
+ - Se ejecuta una verificacion focalizada si el cambio no es trivial.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Create Modal Component"
3
+ short_description: "Create project modals with manager registration."
4
+ default_prompt: "Use $lkd-create-modal-component to create a modal following this project's modal manager pattern."
@@ -0,0 +1,84 @@
1
+ ---
2
+ name: lkd-create-nextjs-page
3
+ description: Crear o refactorizar paginas de Next.js App Router manteniendo el directorio app enfocado en routing y delegando la UI a componentes Page en src/components/pages. Usar al crear page.tsx, migrar vistas fuera de app, organizar subcomponentes privados, aplicar providers de pagina o normalizar nombres y rutas de componentes Page en proyectos que consumen lkd-web-kit.
4
+ ---
5
+
6
+ # Create Next.js Page
7
+
8
+ Usar este skill para crear o refactorizar paginas de Next.js App Router en proyectos que usan `lkd-web-kit`.
9
+
10
+ ## Lectura obligatoria
11
+
12
+ 1. Leer la documentacion relevante de Next.js antes de tocar rutas. Si existe `node_modules/next/dist/docs/`, usarla como fuente local.
13
+ 2. Leer la documentacion local del proyecto sobre `lkd-web-kit`, componentes compartidos y patrones de UI si existe.
14
+ 3. Revisar una pagina y un layout cercanos antes de editar para respetar aliases, providers, carga de datos, traducciones y convenciones locales.
15
+
16
+ ## Regla principal
17
+
18
+ - Mantener `app` como capa de routing de Next.js.
19
+ - En `app`, dejar `page.tsx`, `layout.tsx` y archivos especiales de Next.js cuando correspondan: `not-found.tsx`, `loading.tsx`, `error.tsx`, `route.ts`, `template.tsx`, `default.tsx` y archivos de metadata.
20
+ - No colocar vistas, subcomponentes, hooks privados, helpers de UI, schemas ni columnas de tabla dentro de `app`.
21
+ - Colocar la UI real de cada ruta en `src/components/pages`.
22
+ - No crear carpetas de features genericas en la raiz de `pages`, como `components`, `widgets` o `recommendations`. Colocar las piezas privadas dentro de la Page dueña o moverlas a componentes compartidos cuando exista reutilizacion real.
23
+
24
+ ## Estructura
25
+
26
+ Derivar el area desde el route group principal cuando exista. Si termina en `-layout`, quitar ese sufijo; si no hay route group, usar el primer segmento estatico de la ruta. Ignorar locale, route groups y segmentos dinamicos.
27
+
28
+ ```txt
29
+ src/app/(dashboard-layout)/reports/page.tsx
30
+ src/components/pages/dashboard/reports/ReportsPage.tsx
31
+
32
+ src/app/products/[productId]/page.tsx
33
+ src/components/pages/products/ProductPage.tsx
34
+ ```
35
+
36
+ Para una Page con piezas privadas:
37
+
38
+ ```txt
39
+ src/components/pages/dashboard/reports/ReportsPage/index.tsx
40
+ src/components/pages/dashboard/reports/ReportsPage/ReportFilters.tsx
41
+ src/components/pages/dashboard/reports/ReportsPage/helpers.ts
42
+ ```
43
+
44
+ - Usar archivo plano `{PageName}Page.tsx` si el componente es de una pieza.
45
+ - Usar carpeta `{PageName}Page/index.tsx` si tiene subcomponentes, helpers, schemas o piezas privadas.
46
+ - Usar PascalCase y el sufijo `Page` para todo componente que represente una pagina.
47
+ - Para rutas dinamicas, nombrar la Page por el ultimo concepto estable, no por el nombre del parametro. En rutas anidadas, reflejar los segmentos estaticos que den contexto.
48
+ - Si hay colision o ambiguedad real, anteponer el segmento padre.
49
+ - No usar `index.tsx` como Page principal directamente bajo el area o la ruta.
50
+ - Mover a componentes compartidos solo cuando haya mas de un consumidor real o exista un patron local establecido.
51
+
52
+ ## Providers
53
+
54
+ Si el proyecto ya define `PageProviders`, envolver cada `page.tsx` con ese componente y pasar solo props soportadas y necesarias.
55
+
56
+ ```tsx
57
+ import PageProviders from "@/app/PageProviders";
58
+ import ReportsPage from "@/components/pages/dashboard/reports/ReportsPage";
59
+
60
+ export default async function Page() {
61
+ return (
62
+ <PageProviders>
63
+ <ReportsPage />
64
+ </PageProviders>
65
+ );
66
+ }
67
+ ```
68
+
69
+ - Adaptar los aliases, import y props al proyecto consumidor. No crear `PageProviders` solo para cumplir este skill.
70
+ - No usar `PageProviders` en un `layout.tsx` compartido por varias pages. Si el layout necesita un provider, importar y aplicar solamente el provider especifico del proyecto.
71
+ - Excepcion: un layout dedicado exclusivamente a una page puede usar `PageProviders` cuando evita duplicar providers o carga de datos de esa unica ruta.
72
+ - Mantener `PageProviders` en `page.tsx` cuando la pagina necesita props propias, como datos de servidor, traducciones, catalogos o precarga de modales.
73
+ - Mantener en `page.tsx` solo responsabilidades de entrypoint: params, metadata, fetch server-side, redirects, `notFound` y providers.
74
+ - No duplicar providers dentro del componente Page salvo que el proyecto lo documente.
75
+
76
+ ## Checklist
77
+
78
+ - `app` queda sin UI ni logica privada de ruta.
79
+ - `page.tsx` importa un componente desde `src/components/pages`.
80
+ - El componente de pagina termina en `Page` y sus piezas privadas estan dentro de su carpeta `*Page` cuando corresponde.
81
+ - Se usa el provider existente del proyecto en el limite correcto: page por defecto, layout solo si es exclusivo de una unica page.
82
+ - No quedan imports a la ubicacion anterior de vistas.
83
+ - No se usa `any`.
84
+ - Ejecutar una verificacion focalizada para el cambio realizado.
@@ -0,0 +1,3 @@
1
+ display_name: Create Next.js Page
2
+ short_description: Create clean Next.js App Router pages.
3
+ default_prompt: "Use $lkd-create-nextjs-page to create or refactor a Next.js App Router page using the clean PageProviders pattern."
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: lkd-create-svg-icon
3
+ description: Create SVG icon files in projects that expose SVGs from src/icons. Use when Codex must add a new icon under src/icons from user-provided SVG markup, normalize SVG colors to currentColor for Tailwind text-* styling, and export the icon alias from src/icons/index.ts.
4
+ ---
5
+
6
+ # Create SVG Icon
7
+
8
+ Use this skill when the user provides SVG markup and the desired icon name, usually in the form `Icon{Name}`.
9
+
10
+ ## Required Workflow
11
+
12
+ 1. Read `src/icons/index.ts` before editing.
13
+ 2. Determine the component export name from the user input.
14
+ - Expected format: `Icon{Name}`.
15
+ - Keep the export alias with the `Icon` prefix.
16
+ 3. Verify the icon does not already exist.
17
+ - Check for the exact alias in `src/icons/index.ts`.
18
+ - Check for the target SVG filename in `src/icons/`.
19
+ - If either exists, cancel the operation and notify the user.
20
+ 4. Build the SVG filename.
21
+ - Remove the leading `Icon` prefix.
22
+ - Convert the remaining name to kebab-case.
23
+ - Save it as `src/icons/{name}.svg`.
24
+ - Example: `IconBuildingTower` -> `src/icons/building-tower.svg`.
25
+ 5. Normalize the provided SVG.
26
+ - Replace every explicit visual color value with `currentColor`.
27
+ - Include colors expressed as hex, rgb(), rgba(), hsl(), hsla(), named colors, or inline style values.
28
+ - Apply this to attributes such as `fill`, `stroke`, `color`, `stop-color`, and CSS declarations inside `style`.
29
+ - Preserve `fill="none"`, `stroke="none"`, `currentColor`, `transparent`, masks, clipping, sizing, viewBox, paths, and structural SVG attributes.
30
+ - Do not convert opacity values to `currentColor`.
31
+ 6. Create the SVG file in `src/icons/`.
32
+ 7. Add the alias in `src/icons/index.ts` following the existing export style in that file.
33
+ 8. Report the created SVG path and the added export alias.
34
+
35
+ ## Guardrails
36
+
37
+ - Do not use `any`.
38
+ - Do not create React wrapper components for the icon unless the existing icon system requires it.
39
+ - Do not overwrite an existing icon file or alias.
40
+ - Do not invent SVG path data; use the SVG supplied by the user.
41
+ - Keep edits scoped to `src/icons/{name}.svg` and `src/icons/index.ts` unless the user asks for something else.
@@ -0,0 +1,3 @@
1
+ display_name: Create SVG Icon
2
+ short_description: Create project SVG icons with currentColor and index exports.
3
+ default_prompt: "Use $lkd-create-svg-icon to create an SVG icon for this project from the SVG markup and icon name I provide."
@@ -0,0 +1,189 @@
1
+ ---
2
+ name: lkd-create-table-component
3
+ description: Crear, extraer o refactorizar tablas/listados tabulares en proyectos internos usando el patron estricto de componente encapsulado con MyTable, TableWrapper y createColumnHelper. Usar cuando Codex deba mostrar datos en tabla, mover columnas/hook de servicio a un componente de tabla, agregar paginacion, header/footer de tabla, acciones por fila, tablas verticales o adaptar una vista para no usar MyTablePagination.
4
+ ---
5
+
6
+ # Create Table Component
7
+
8
+ Usar este skill para crear o refactorizar tablas del proyecto.
9
+
10
+ ## Workflow obligatorio
11
+
12
+ 1. Leer primero `docs/local-components.md` y `docs/lkd-web-kit.md`.
13
+ 2. Si toca Next.js, leer la documentacion relevante en `node_modules/next/dist/docs/`.
14
+ 3. Revisar un ejemplo cercano antes de editar; preferir `Table{EntityPlural}.tsx`.
15
+ 4. Crear o mantener la tabla en un componente encapsulado junto a la vista/feature que la consume.
16
+ 5. Usar `createColumnHelper<RowData>()`; no declarar `any`.
17
+ 6. Importar `MyTable` y `TableWrapper*` desde `lkd-web-kit`.
18
+ 7. Usar `MyTable` para renderizar la tabla.
19
+ 8. Usar `TableWrapper` como raiz visual de la tabla.
20
+ 9. No usar `MyTablePagination` para nuevas tablas.
21
+
22
+ ## Checklist antes de escribir columnas
23
+
24
+ - Definir si la tabla es horizontal o `variant="vertical"`.
25
+ - Definir que representa cada header: solo deben ser columnas/campos reales de la tabla.
26
+ - Distinguir contenido superior/inferior de estructura tabular: titulos, subtitulos, emails, filtros, secciones y acciones van en `TableWrapperHeader`/`TableWrapperFooter`, no en columnas falsas.
27
+ - Definir si la data representa registros completos o pares label/value. Para `variant="vertical"`, preferir registros completos con campos reales.
28
+
29
+ ## Decisiones que hay que preguntar
30
+
31
+ Si el usuario no lo especifica y no se puede inferir del codigo cercano, preguntar:
32
+
33
+ - Si la tabla lleva contenido arriba de la tabla.
34
+ - Si la tabla lleva contenido abajo de la tabla.
35
+ - Si la tabla lleva paginacion.
36
+ - Si la tabla debe ser horizontal o `variant="vertical"`.
37
+
38
+ No asumir que `TableWrapperHeader` implica titulo. Usarlo para cualquier contenido superior: titulo, filtros, acciones, botones, tabs, resumen, subtitulo, email o encabezado de seccion.
39
+
40
+ No asumir que `TableWrapperFooter` implica paginacion. Usarlo para cualquier contenido inferior: paginacion, totales, leyendas, acciones o resumen.
41
+
42
+ Si hay titulo, usar `TableWrapperTitle` dentro de `TableWrapperHeader`.
43
+
44
+ Si hay paginacion, usar `TableWrapperPagination` dentro de `TableWrapperFooter`.
45
+
46
+ ## Paginacion
47
+
48
+ - Usar `TableWrapperPagination`, nunca `MyTablePagination` en tablas nuevas.
49
+ - Usar `variant="short"` para paginacion compacta con texto tipo `1-10 de 15 filas`; queda alineada a la derecha por defecto.
50
+ - Para `variant="short"`, pasar siempre `pageSize`. Si los datos vienen async, usar un fallback estable como `pageSize={currentPage?.pageSize ?? 10}`.
51
+ - No armar el texto de rango en la vista si alcanza con metadata: pasar `totalRows`, `pageSize` y `currentRows`.
52
+ - Usar `text` solo como override manual del texto calculado.
53
+ - Mantener `variant="long"` o sin `variant` para la paginacion completa.
54
+
55
+ ## Tablas verticales
56
+
57
+ Para `MyTable variant="vertical"`, modelar los campos como columnas reales y la data como una fila/registro completo. Los nombres de campos van en `column.header`; los valores van en `column.cell`.
58
+
59
+ No simular una tabla vertical con una columna `entry`, `{ field, value }` o un `grid` dentro de una celda.
60
+
61
+ Ejemplo:
62
+
63
+ ```tsx
64
+ type UserInformationRow = {
65
+ name: string | undefined;
66
+ lastName: string | undefined;
67
+ email: string | undefined;
68
+ };
69
+
70
+ const columnHelper = createColumnHelper<UserInformationRow>();
71
+
72
+ const columns = [
73
+ columnHelper.accessor("name", {
74
+ header: "Nombre",
75
+ cell: (cell) => cell.getValue() ?? "-",
76
+ }),
77
+ columnHelper.accessor("lastName", {
78
+ header: "Apellido",
79
+ cell: (cell) => cell.getValue() ?? "-",
80
+ }),
81
+ columnHelper.accessor("email", {
82
+ header: "Email",
83
+ cell: (cell) => cell.getValue() ?? "-",
84
+ }),
85
+ ];
86
+
87
+ <TableWrapper>
88
+ <TableWrapperHeader>
89
+ <TableWrapperTitle>Informacion del usuario</TableWrapperTitle>
90
+ <span>{user.email}</span>
91
+ <div>Datos personales</div>
92
+ </TableWrapperHeader>
93
+ <MyTable columns={columns} data={[user]} variant="vertical" />
94
+ </TableWrapper>;
95
+ ```
96
+
97
+ ## Encapsulacion
98
+
99
+ - Mover `columns` al componente `Table{EntityPlural}`.
100
+ - Si la tabla consulta datos, mover el hook/servicio al componente de tabla.
101
+ - Si la tabla pagina, mover `pageIndex` y `setPageIndex` al componente de tabla.
102
+ - El padre solo debe pasar entradas externas reales: filtros ya aplicados, ids, callbacks o flags.
103
+ - Al cambiar filtros externos, resetear la pagina dentro del componente de tabla con `useEffect` si aplica.
104
+
105
+ ## Patron base
106
+
107
+ ```tsx
108
+ "use client";
109
+
110
+ import { createColumnHelper } from "@tanstack/react-table";
111
+ import {
112
+ MyTable,
113
+ TableWrapper,
114
+ TableWrapperFooter,
115
+ TableWrapperHeader,
116
+ TableWrapperPagination,
117
+ TableWrapperTitle,
118
+ } from "lkd-web-kit";
119
+ import { useMemo, useState } from "react";
120
+
121
+ type ItemTableData = {
122
+ id: string;
123
+ name: string;
124
+ };
125
+
126
+ type TableItemsProps = {
127
+ selectedFilters: Record<string, unknown>;
128
+ };
129
+
130
+ const columnHelper = createColumnHelper<ItemTableData>();
131
+
132
+ const TableItems = ({ selectedFilters }: TableItemsProps) => {
133
+ const [pageIndex, setPageIndex] = useState(0);
134
+
135
+ const columns = useMemo(
136
+ () => [
137
+ columnHelper.accessor("name", {
138
+ header: "Nombre",
139
+ cell: (cell) => cell.getValue(),
140
+ }),
141
+ ],
142
+ [],
143
+ );
144
+
145
+ return (
146
+ <TableWrapper>
147
+ <TableWrapperHeader>
148
+ <TableWrapperTitle>Items</TableWrapperTitle>
149
+ </TableWrapperHeader>
150
+ <MyTable columns={columns} data={[]} />
151
+ <TableWrapperFooter>
152
+ <TableWrapperPagination
153
+ total={1}
154
+ value={pageIndex + 1}
155
+ onChange={(page) => setPageIndex(page - 1)}
156
+ />
157
+ </TableWrapperFooter>
158
+ </TableWrapper>
159
+ );
160
+ };
161
+
162
+ export default TableItems;
163
+ ```
164
+
165
+ Ejemplo short:
166
+
167
+ ```tsx
168
+ <TableWrapperPagination
169
+ variant="short"
170
+ total={pageData?.total.pages ?? 1}
171
+ value={(pageData?.currentPage.pageIndex ?? 0) + 1}
172
+ totalRows={pageData?.total.elements}
173
+ pageSize={pageData?.currentPage.pageSize ?? 10}
174
+ currentRows={pageData?.currentPage.elements}
175
+ onChange={(page) => setPageIndex(page - 1)}
176
+ />;
177
+ ```
178
+
179
+ ## Antipatrones
180
+
181
+ - No dejar columnas o hooks de servicio de la tabla en la vista padre.
182
+ - No crear wrappers nuevos si `TableWrapper` y `MyTable` alcanzan.
183
+ - No usar `Paper` directamente para la tabla cuando el patron pide `TableWrapper`.
184
+ - No usar `MyTablePagination` en codigo nuevo.
185
+ - No usar `paginationVariant` ni `paginationText` en `TableWrapperPagination`; usar `variant` y `text`.
186
+ - No calcular `1-10 de 15 filas` en la vista si `TableWrapperPagination` puede calcularlo.
187
+ - No agregar abstracciones compartidas antes de tener reutilizacion real.
188
+ - No crear `MyTableVertical` si `MyTable variant="vertical"` resuelve el caso.
189
+ - No poner titulos de seccion como "Datos personales" o "Informacion del usuario" como headers de columna.
@@ -0,0 +1,3 @@
1
+ display_name: Create Table Component
2
+ short_description: Create encapsulated project tables with MyTable and TableWrapper.
3
+ default_prompt: "Use $lkd-create-table-component to create or refactor a table component using this project's MyTable and TableWrapper pattern."
@@ -0,0 +1,99 @@
1
+ ---
2
+ name: lkd-layout-mantine-tailwind
3
+ description: Create or refactor React/Next.js UI layout in this project using Mantine Layout components to express visual structure and Tailwind classes for styling, spacing, responsive behavior, columns, and display properties. Use when Codex needs to create or adjust JSX with Container, Center, Flex, Group, Stack, SimpleGrid, Grid, or Paper, especially in Page or UI components that mix Mantine and Tailwind.
4
+ ---
5
+
6
+ # Layout Mantine Tailwind
7
+
8
+ Usar este skill para maquetar componentes visuales en `aestrenar-web` con Mantine y Tailwind sin mezclar responsabilidades.
9
+
10
+ ## Lectura Obligatoria
11
+
12
+ 1. Leer `docs/lkd-web-kit.md` y `docs/local-components.md` antes de crear componentes nuevos o reemplazar UI existente.
13
+ 2. Si se toca una pagina o componente de Next.js, leer la documentacion local relevante en `node_modules/next/dist/docs/`.
14
+ 3. Revisar uno o dos componentes cercanos antes de editar para seguir imports, wrappers locales y tono visual.
15
+
16
+ ## Regla Principal
17
+
18
+ - Usar componentes Layout de Mantine para que el JSX deje claro el tipo de display o contenedor.
19
+ - Usar Tailwind para estilos, medidas, espaciado, columnas, alineacion y responsive.
20
+ - No usar props visuales de Mantine cuando una clase Tailwind resuelve lo mismo.
21
+
22
+ ## Componentes Layout
23
+
24
+ - `Container`: contenedor de ancho de pagina o seccion.
25
+ - `Paper`: superficie visual cuando ya existe una tarjeta/panel real.
26
+ - `Stack`: layout vertical.
27
+ - `Group`: layout horizontal, grupos de acciones, pills, header row o wrapping.
28
+ - `SimpleGrid`: grillas simples responsive. Definir columnas con Tailwind: `grid-cols-1 sm:grid-cols-2 xl:grid-cols-4`.
29
+ - `Grid`: usar solo si hace falta una capacidad propia de `Grid` que `SimpleGrid` no cubre.
30
+ - `Center`: centrar contenido en ambos ejes cuando ese sea el objetivo del layout.
31
+ - `Flex`: usar solo cuando se requiera cambiar entre `flex-row` y `flex-col` segun responsive, con clases Tailwind.
32
+
33
+ ## Tailwind
34
+
35
+ Usar clases Tailwind para:
36
+
37
+ - `m*`, `p*`, `gap-*`, `space-*`.
38
+ - `rounded-*`, `shadow-*`, `border`, colores y fondos.
39
+ - `text-*`, `font-*`, `leading-*`, `tracking-*`.
40
+ - `h-*`, `w-*`, `min-*`, `max-*`.
41
+ - `items-*`, `justify-*`, `flex-wrap`, `grid-cols-*`, `col-span-*`.
42
+ - Breakpoints responsive: `sm:`, `md:`, `lg:`, `xl:`.
43
+
44
+ No usar props Mantine equivalentes como `m`, `p`, `px`, `py`, `radius`, `shadow`, `w`, `h`, `gap`, `justify`, `align` o `cols` si Tailwind lo expresa claramente.
45
+
46
+ ## Texto y Semantica
47
+
48
+ - No usar `Text` ni `Title` de Mantine.
49
+ - Usar elementos HTML semanticos (`h1`, `h2`, `p`, `section`, `article`, `footer`, `header`) cuando correspondan.
50
+ - Usar la prop `component` solo para cambiar semantica real: `component="main"`, `component="section"`, `component="article"`, `component="footer"`.
51
+ - Omitir `component` si el resultado seria `div`, porque es el default.
52
+
53
+ ## Patrones
54
+
55
+ Grilla simple:
56
+
57
+ ```tsx
58
+ <SimpleGrid className="grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-4">
59
+ {items.map((item) => (
60
+ <Card key={item.id} data={item} />
61
+ ))}
62
+ </SimpleGrid>
63
+ ```
64
+
65
+ Layout vertical:
66
+
67
+ ```tsx
68
+ <Stack component="section" className="w-full gap-5">
69
+ <Header />
70
+ <Content />
71
+ </Stack>
72
+ ```
73
+
74
+ Grupo horizontal:
75
+
76
+ ```tsx
77
+ <Group className="items-start justify-between gap-3">
78
+ <h2 className="font-bold text-xl">Titulo</h2>
79
+ <ButtonAE>Accion</ButtonAE>
80
+ </Group>
81
+ ```
82
+
83
+ Responsive row/column:
84
+
85
+ ```tsx
86
+ <Flex className="flex-col gap-2 md:flex-row md:items-center md:justify-between">
87
+ <Summary />
88
+ <Actions />
89
+ </Flex>
90
+ ```
91
+
92
+ ## Checklist
93
+
94
+ - El JSX muestra el layout con Mantine, no con `div` anonimos cuando hay `Stack`, `Group`, `SimpleGrid`, `Flex`, `Center`, `Container` o `Paper` aplicable.
95
+ - Las columnas de grilla estan en Tailwind, no en `cols`.
96
+ - No hay `component="div"`.
97
+ - No hay `Text` ni `Title` de Mantine.
98
+ - No se agregaron abstracciones compartidas si el componente es privado de una pagina.
99
+ - Se ejecuto una verificacion focalizada, como `npx biome lint <archivo>`.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Layout Mantine Tailwind"
3
+ short_description: "Layout UI with Mantine and Tailwind."
4
+ default_prompt: "Use $lkd-layout-mantine-tailwind para maquetar componentes React con Mantine Layout y Tailwind."