# Herramientas interactivas Estado: primera versión funcional. Este documento conserva el contexto necesario para extender `DsSortableList` y `DsLogicTree` sin cambiar accidentalmente sus contratos públicos. ## Principios compartidos - Los modelos son serializables y no contienen referencias DOM ni estado interno de Vue. - Cada elemento o nodo necesita un `id` estable y único. - Las actualizaciones reemplazan arreglos y nodos en lugar de mutar los objetos recibidos. - La interacción con puntero siempre debe tener una alternativa de teclado. - La lógica de negocio, persistencia y traducción a consultas pertenece a la aplicación consumidora o a adaptadores independientes. - Cualquier ampliación debe actualizar tipos, API pública, pruebas, playground y documentación. ## `DsSortableList` ### Contrato actual Recibe `v-model`. Cada elemento contiene: ```ts interface DsSortableItem { id: string; label: string; description?: string; disabled?: boolean; } ``` El usuario puede arrastrar un elemento o utilizar los botones subir/bajar. Cada cambio reemplaza el arreglo y emite: ```ts interface DsSortableChange { item: DsSortableItem; from: number; to: number; } ``` El slot predeterminado puede personalizar la representación, pero `id` y `label` continúan formando parte del contrato porque se utilizan para identidad y nombres accesibles. ### Decisiones - Se usa drag-and-drop nativo del navegador para mantener pequeña la primera versión y evitar una dependencia runtime. - Los botones subir/bajar son la alternativa accesible y también permiten operar la lista en pantallas táctiles. - La nueva posición se anuncia mediante una región `status`. - Un elemento `disabled` no puede iniciar un movimiento. ### Limitaciones conocidas - Solo reordena elementos dentro de una misma lista. - No tiene gesto táctil de arrastre; en móvil se usan los botones. - No ofrece clonación, selección múltiple, grupos ni zonas de descarte. - El destino corresponde al elemento sobre el que se suelta; todavía no existe un indicador entre filas. - No administra persistencia ni historial para deshacer/rehacer. ### Próximas extensiones 1. Mejorar el indicador de inserción antes/después de una fila. 2. Evaluar Pointer Events para arrastre táctil sin eliminar la alternativa por botones. 3. Diseñar drag-and-drop entre listas. Antes de implementarlo hay que definir `sourceListId`, `targetListId`, copia frente a movimiento y el evento público resultante. 4. Añadir soporte opcional para deshacer/rehacer como composable independiente. 5. Incorporar pruebas visuales y de interacción en navegadores reales. ## `DsLogicTree` ### Contrato actual Recibe `v-model`. El árbol utiliza una unión discriminada: ```ts type DsLogicNode = DsLogicCondition | DsLogicGroup; interface DsLogicGroup { id: string; type: "group"; operator: "and" | "or"; children: DsLogicNode[]; } interface DsLogicCondition { id: string; type: "condition"; field: string; comparison: string; value: string; } ``` `fields` y `comparisons` usan opciones `{ label, value, disabled? }`. La prop `labels` permite adaptar todos los textos del editor y `readonly` conserva la estructura sin permitir cambios. Cada edición actualiza el `v-model` y emite `change` con el árbol completo. El render recursivo vive en `DsLogicTreeNode.vue`, que es una implementación interna y no forma parte de la API pública. ### Decisiones - `AND` y `OR` se almacenan como `and` y `or`; los textos visibles son configurables. - Las condiciones usan cadenas para que la primera versión sea neutral respecto al dominio. - Los nodos nuevos reciben UUID y los nodos proporcionados por el consumidor deben conservar IDs estables. - El árbol solamente describe reglas. No evalúa condiciones ni genera SQL, JSON Logic u otra sintaxis. - Los controles nativos mantienen nombres accesibles y el anidamiento se representa con listas y grupos. ### Limitaciones conocidas - Todos los valores se editan como texto, sin tipos `number`, `boolean`, fecha o selección múltiple. - No existe validación de campos vacíos, operadores incompatibles o grupos sin condiciones. - Los nodos no pueden reordenarse ni moverse entre grupos. - No hay operadores unarios como `is-empty` ni condiciones que omitan `value`. - No se muestran resúmenes en lenguaje natural. - No se incluye un evaluador ni adaptadores para backends. ### Próximas extensiones 1. Añadir validación sin cambiar el modelo serializable; los errores deben asociarse al control correspondiente. 2. Diseñar definiciones de campo tipadas con un `valueType` y opciones de valor. Hay que conservar compatibilidad con el esquema actual o introducir el cambio en una versión mayor. 3. Permitir comparadores que no requieran valor y editores personalizados mediante slots. 4. Reordenar condiciones y mover nodos entre grupos reutilizando un contrato de drag-and-drop estable. 5. Crear adaptadores separados para evaluar el árbol o convertirlo a formatos como JSON Logic. Estos adaptadores no deben acoplar el componente visual a un backend. 6. Añadir colapsado de grupos, resumen legible y deshacer/rehacer cuando el árbol crezca. ## Checklist para futuras sesiones Antes de modificar estas herramientas: 1. Revisa este documento, `src/types.ts` y las pruebas de `tests/data-tools.test.ts`. 2. Decide si el cambio es compatible con los modelos actuales y documenta cualquier migración. 3. Conserva una alternativa completa al arrastre para teclado y tecnologías asistivas. 4. Añade el caso nuevo al playground en `?section=tools`. 5. Actualiza `docs/components.md` si cambia la API pública. 6. Ejecuta `npm run check` y `npm run test:coverage`. ## Fuera de alcance actual - Ejecución de reglas contra datos reales. - Generación directa de SQL o llamadas a APIs. - Colaboración en tiempo real. - Persistencia automática. - Un editor visual de flujos con nodos y conexiones libres. Estas capacidades requieren contratos y análisis de seguridad propios; no deben incorporarse como comportamiento implícito de los componentes visuales.