xonecode 0.1.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 (187) hide show
  1. package/README.md +167 -0
  2. package/dist/agent/authEnDisco.js +56 -0
  3. package/dist/agent/authEnDisco.js.map +1 -0
  4. package/dist/agent/configEnDisco.js +109 -0
  5. package/dist/agent/configEnDisco.js.map +1 -0
  6. package/dist/agent/crearProyecto.js +34 -0
  7. package/dist/agent/crearProyecto.js.map +1 -0
  8. package/dist/agent/entorno.js +124 -0
  9. package/dist/agent/entorno.js.map +1 -0
  10. package/dist/agent/guionizado.js +53 -0
  11. package/dist/agent/guionizado.js.map +1 -0
  12. package/dist/agent/instantanea.js +129 -0
  13. package/dist/agent/instantanea.js.map +1 -0
  14. package/dist/agent/interrupts.js +83 -0
  15. package/dist/agent/interrupts.js.map +1 -0
  16. package/dist/agent/mensajes.js +24 -0
  17. package/dist/agent/mensajes.js.map +1 -0
  18. package/dist/agent/modelos.js +42 -0
  19. package/dist/agent/modelos.js.map +1 -0
  20. package/dist/agent/normalizar.js +20 -0
  21. package/dist/agent/normalizar.js.map +1 -0
  22. package/dist/agent/perfiles.js +103 -0
  23. package/dist/agent/perfiles.js.map +1 -0
  24. package/dist/agent/proyecto.js +107 -0
  25. package/dist/agent/proyecto.js.map +1 -0
  26. package/dist/agent/puente.js +142 -0
  27. package/dist/agent/puente.js.map +1 -0
  28. package/dist/agent/resumenDeTool.js +48 -0
  29. package/dist/agent/resumenDeTool.js.map +1 -0
  30. package/dist/agent/skills.js +65 -0
  31. package/dist/agent/skills.js.map +1 -0
  32. package/dist/agent/textoDeTool.js +113 -0
  33. package/dist/agent/textoDeTool.js.map +1 -0
  34. package/dist/agent/turnoReal.js +173 -0
  35. package/dist/agent/turnoReal.js.map +1 -0
  36. package/dist/agent/verificador.js +65 -0
  37. package/dist/agent/verificador.js.map +1 -0
  38. package/dist/agent/xoneAgent.js +106 -0
  39. package/dist/agent/xoneAgent.js.map +1 -0
  40. package/dist/bin.js +9 -0
  41. package/dist/bin.js.map +1 -0
  42. package/dist/cli/aprobar.js +82 -0
  43. package/dist/cli/aprobar.js.map +1 -0
  44. package/dist/cli/config.js +133 -0
  45. package/dist/cli/config.js.map +1 -0
  46. package/dist/cli/consola.js +346 -0
  47. package/dist/cli/consola.js.map +1 -0
  48. package/dist/cli/describe.js +53 -0
  49. package/dist/cli/describe.js.map +1 -0
  50. package/dist/cli/doctor.js +45 -0
  51. package/dist/cli/doctor.js.map +1 -0
  52. package/dist/cli/main.js +520 -0
  53. package/dist/cli/main.js.map +1 -0
  54. package/dist/cli/markdown.js +90 -0
  55. package/dist/cli/markdown.js.map +1 -0
  56. package/dist/cli/run.js +164 -0
  57. package/dist/cli/run.js.map +1 -0
  58. package/dist/cli/spinner.js +89 -0
  59. package/dist/cli/spinner.js.map +1 -0
  60. package/dist/cli/stdio.js +193 -0
  61. package/dist/cli/stdio.js.map +1 -0
  62. package/dist/cli/tema.js +40 -0
  63. package/dist/cli/tema.js.map +1 -0
  64. package/dist/cli/verify.js +62 -0
  65. package/dist/cli/verify.js.map +1 -0
  66. package/dist/core/bitacora.js +30 -0
  67. package/dist/core/bitacora.js.map +1 -0
  68. package/dist/core/config.js +236 -0
  69. package/dist/core/config.js.map +1 -0
  70. package/dist/core/contextos.js +56 -0
  71. package/dist/core/contextos.js.map +1 -0
  72. package/dist/core/deps.js +51 -0
  73. package/dist/core/deps.js.map +1 -0
  74. package/dist/core/diff.js +79 -0
  75. package/dist/core/diff.js.map +1 -0
  76. package/dist/core/esqueleto.js +366 -0
  77. package/dist/core/esqueleto.js.map +1 -0
  78. package/dist/core/events.js +2 -0
  79. package/dist/core/events.js.map +1 -0
  80. package/dist/core/modelos.js +85 -0
  81. package/dist/core/modelos.js.map +1 -0
  82. package/dist/core/notify.js +106 -0
  83. package/dist/core/notify.js.map +1 -0
  84. package/dist/core/ports.js +114 -0
  85. package/dist/core/ports.js.map +1 -0
  86. package/dist/core/turno.js +127 -0
  87. package/dist/core/turno.js.map +1 -0
  88. package/dist/vendor/hitl.js +103 -0
  89. package/dist/vendor/hitl.js.map +1 -0
  90. package/dist/vendor/skillLoaders/catalog.js +74 -0
  91. package/dist/vendor/skillLoaders/catalog.js.map +1 -0
  92. package/dist/vendor/tokenTracking.js +58 -0
  93. package/dist/vendor/tokenTracking.js.map +1 -0
  94. package/package.json +41 -0
  95. package/skills/xone-debugging/SKILL.md +52 -0
  96. package/skills/xone-debugging/references/faq.md +561 -0
  97. package/skills/xone-debugging/references/troubleshooting-y-glosario.md +429 -0
  98. package/skills/xone-development/SKILL.md +105 -0
  99. package/skills/xone-development/references/anti-patrones.md +94 -0
  100. package/skills/xone-development/references/css/atributos-por-categoria.md +509 -0
  101. package/skills/xone-development/references/css/buenas-practicas-y-parser.md +419 -0
  102. package/skills/xone-development/references/css/dinamicos-cascada-y-componentes.md +550 -0
  103. package/skills/xone-development/references/css/patrones-material-y-temas.md +1140 -0
  104. package/skills/xone-development/references/css/propiedades-y-herencia.md +885 -0
  105. package/skills/xone-development/references/css/selectores-unidades-colores.md +840 -0
  106. package/skills/xone-development/references/datos/appdata-referencia-ampliada.md +457 -0
  107. package/skills/xone-development/references/datos/appdata.md +611 -0
  108. package/skills/xone-development/references/datos/http-sqlmanager-y-crypto.md +720 -0
  109. package/skills/xone-development/references/datos/http.md +366 -0
  110. package/skills/xone-development/references/datos/oauth2-y-replica.md +156 -0
  111. package/skills/xone-development/references/device/biometria-imagedrawing-y-otros.md +544 -0
  112. package/skills/xone-development/references/device/objetos-de-dispositivo.md +583 -0
  113. package/skills/xone-development/references/device/systemsettings-referencia-ampliada.md +396 -0
  114. package/skills/xone-development/references/device/systemsettings-y-permisos.md +342 -0
  115. package/skills/xone-development/references/fundamentos/conceptos-clave.md +695 -0
  116. package/skills/xone-development/references/fundamentos/configuracion-app-xml-ini-mappings.md +668 -0
  117. package/skills/xone-development/references/fundamentos/errores-comunes.md +312 -0
  118. package/skills/xone-development/references/fundamentos/navegacion-convenciones-y-primer-proyecto.md +576 -0
  119. package/skills/xone-development/references/fundamentos/plataforma-y-anatomia-de-proyecto.md +387 -0
  120. package/skills/xone-development/references/indice-completo.md +77 -0
  121. package/skills/xone-development/references/javascript/coleccion-error-y-usuario.md +260 -0
  122. package/skills/xone-development/references/javascript/debugging-y-best-practices.md +245 -0
  123. package/skills/xone-development/references/javascript/metodos-de-los-controles.md +556 -0
  124. package/skills/xone-development/references/javascript/metodos-nativos-de-la-vista.md +114 -0
  125. package/skills/xone-development/references/javascript/motor-js-y-contexto-de-ejecucion.md +319 -0
  126. package/skills/xone-development/references/javascript/objeto-ai-llm-en-dispositivo.md +358 -0
  127. package/skills/xone-development/references/javascript/objetos-creables-a-m.md +527 -0
  128. package/skills/xone-development/references/javascript/objetos-creables-n-z.md +385 -0
  129. package/skills/xone-development/references/javascript/patrones-criticos-seguridad-y-rendimiento.md +595 -0
  130. package/skills/xone-development/references/javascript/patrones-de-navegacion-datos-y-codigo.md +751 -0
  131. package/skills/xone-development/references/javascript/patrones-de-ui-voz-integracion-y-seguridad.md +701 -0
  132. package/skills/xone-development/references/javascript/plantillas-y-funciones-utilitarias.md +647 -0
  133. package/skills/xone-development/references/javascript/self-y-dataobject.md +449 -0
  134. package/skills/xone-development/references/javascript/singletons-globales.md +361 -0
  135. package/skills/xone-development/references/javascript/ui-catalogo-de-metodos.md +464 -0
  136. package/skills/xone-development/references/javascript/ui-gps-camara-y-multimedia.md +506 -0
  137. package/skills/xone-development/references/javascript/ui-navegacion-mensajes-y-vista.md +422 -0
  138. package/skills/xone-development/references/resumen-js-datos-dispositivo.md +80 -0
  139. package/skills/xone-development/references/resumen-xml-y-css.md +74 -0
  140. package/skills/xone-development/references/tipos-de-prop.md +28 -0
  141. package/skills/xone-development/references/xml-ui/asfilter-visibilidad-eventos-y-macros.md +576 -0
  142. package/skills/xone-development/references/xml-ui/atributos-coll-group-frame.md +235 -0
  143. package/skills/xone-development/references/xml-ui/atributos-method-macro-script-event-app.md +244 -0
  144. package/skills/xone-development/references/xml-ui/atributos-prop.md +439 -0
  145. package/skills/xone-development/references/xml-ui/contents-y-macros.md +392 -0
  146. package/skills/xone-development/references/xml-ui/errores-comunes-xml.md +245 -0
  147. package/skills/xone-development/references/xml-ui/estructura-y-nodo-coll.md +326 -0
  148. package/skills/xone-development/references/xml-ui/eventos-ciclo-de-vida-e-interaccion.md +704 -0
  149. package/skills/xone-development/references/xml-ui/eventos-sistema-login-y-personalizados.md +944 -0
  150. package/skills/xone-development/references/xml-ui/layouts-herencia-y-buenas-practicas.md +618 -0
  151. package/skills/xone-development/references/xml-ui/mapas.md +685 -0
  152. package/skills/xone-development/references/xml-ui/mappings-y-colecciones-separadas.md +148 -0
  153. package/skills/xone-development/references/xml-ui/nodos-group-y-frame.md +666 -0
  154. package/skills/xone-development/references/xml-ui/patrones-de-pantalla.md +643 -0
  155. package/skills/xone-development/references/xml-ui/prop-atributos-y-condiciones.md +298 -0
  156. package/skills/xone-development/references/xml-ui/prop-tipos-basicos.md +493 -0
  157. package/skills/xone-development/references/xml-ui/prop-tipos-combos-y-controles.md +664 -0
  158. package/skills/xone-development/references/xml-ui/prop-tipos-listas-y-mapas.md +412 -0
  159. package/skills/xone-plan-builder/SKILL.md +183 -0
  160. package/skills/xone-plan-builder/agents/openai.yaml +5 -0
  161. package/skills/xone-plan-builder/references/TASKS-FORMAT.md +132 -0
  162. package/skills/xone-project-generator/SKILL.md +111 -0
  163. package/skills/xone-project-generator/references/canonical-sizes.md +292 -0
  164. package/skills/xone-project-generator/references/colecciones-base.md +16 -0
  165. package/skills/xone-project-generator/references/convenciones-de-nombres.md +16 -0
  166. package/skills/xone-project-generator/references/ejemplos-por-sector-y-prohibiciones.md +140 -0
  167. package/skills/xone-project-generator/references/fase-3-estilos-css.md +597 -0
  168. package/skills/xone-project-generator/references/fase-6-colecciones.md +762 -0
  169. package/skills/xone-project-generator/references/fase-7-asfilter-e-integraciones.md +142 -0
  170. package/skills/xone-project-generator/references/fase-7-entidades-y-estructura-de-pantalla.md +494 -0
  171. package/skills/xone-project-generator/references/fase-7-plantilla-consola.md +477 -0
  172. package/skills/xone-project-generator/references/fase-7-plantillas-de-pantalla.md +302 -0
  173. package/skills/xone-project-generator/references/fase-7-viewmodes-graficos-y-listas.md +681 -0
  174. package/skills/xone-project-generator/references/fase-7-viewmodes-mapa-y-calendario.md +479 -0
  175. package/skills/xone-project-generator/references/fases-0-2-analisis-y-modelo-de-datos.md +350 -0
  176. package/skills/xone-project-generator/references/fases-10-12-readmes-y-validacion.md +194 -0
  177. package/skills/xone-project-generator/references/fases-4-5-estructura-y-configuracion.md +587 -0
  178. package/skills/xone-project-generator/references/fases-8-9-eventos-y-javascript.md +861 -0
  179. package/skills/xone-project-generator/references/flujo-de-generacion.md +67 -0
  180. package/skills/xone-project-generator/references/plantillas-estandar.md +98 -0
  181. package/skills/xone-project-generator/references/tamanos-canonicos.md +49 -0
  182. package/skills/xone-review/SKILL.md +189 -0
  183. package/skills/xone-spec-builder/SKILL.md +235 -0
  184. package/skills/xone-spec-builder/agents/openai.yaml +5 -0
  185. package/skills/xone-spec-builder/references/ADR-FORMAT.md +55 -0
  186. package/skills/xone-spec-builder/references/CONTEXT-FORMAT.md +42 -0
  187. package/skills/xone-spec-builder/references/PLAN-FORMAT.md +120 -0
@@ -0,0 +1,142 @@
1
+ # Generación XOne — Fase 7: asfilter e integraciones
2
+
3
+ > Fuente: `xone/v2/xone-project-generator/references/xone-project-generation-workflow.md` L4652–4784. Referencia de la skill; el índice está en [../SKILL.md](../SKILL.md).
4
+
5
+ Contenido: §7.14 filtros de búsqueda con asfilter · §7.15 objetos complementarios como opciones de integración
6
+
7
+ ---
8
+
9
+ ### 7.14 Filtros de Busqueda con `<asfilter>`
10
+
11
+ Para pantallas de lista que requieran busqueda nativa, se puede usar el nodo `<asfilter>` dentro de la coleccion. Este nodo genera automáticamente una barra de filtros en la parte superior de la lista.
12
+
13
+ ```xml
14
+ <coll name="Productos"
15
+ sql="SELECT * FROM ##PREF##Productos"
16
+ objname="Productos" loadall="true">
17
+
18
+ <asfilter fontsize="8" left="12" sort="false">
19
+ <field name="NOMBRE" fldname="NOMBRE"
20
+ oper="##FLD## LIKE '##VAL##%'" width="15"
21
+ tooltip="Buscar por nombre">NOMBRE</field>
22
+ <field name="CODIGO" fldname="CODIGO"
23
+ oper="##FLD## LIKE '##VAL##%'" width="10"
24
+ tooltip="Buscar por código" newline="false">CODIGO</field>
25
+ </asfilter>
26
+
27
+ <group name="Lista" id="1">
28
+ <!-- contenido de la lista -->
29
+ </group>
30
+ </coll>
31
+ ```
32
+
33
+ | Atributo `<asfilter>` | Descripción |
34
+ |-----------------------|-------------|
35
+ | `fontsize` | Tamaño de fuente de los campos del filtro |
36
+ | `left` | Margen izquierdo del filtro |
37
+ | `sort` | Habilita ordenamiento (`true`/`false`) |
38
+
39
+ | Atributo `<field>` | Descripción |
40
+ |--------------------|-------------|
41
+ | `name` | Nombre del campo de filtro |
42
+ | `fldname` | Nombre del campo real en la tabla |
43
+ | `oper` | Operador SQL. `##FLD##` = campo, `##VAL##` = valor introducido |
44
+ | `width` | Ancho del campo de filtro |
45
+ | `tooltip` | Texto de ayuda |
46
+ | `newline` | `false` = mismo renglon que el anterior |
47
+
48
+ ### 7.15 Objetos Complementarios como Opciones de Integración
49
+
50
+ Al analizar los requisitos del proyecto (Fase 1), el agente debe identificar si se necesitan integraciones con hardware o servicios externos. XOne proporciona objetos complementarios que se deben incorporar al proyecto según la funcionalidad requerida.
51
+
52
+ #### Tabla de Integraciones Disponibles
53
+
54
+ | Objeto | Tipo de App | Impacto en Generación |
55
+ |--------|-------------|----------------------|
56
+ | **FileManager** | Apps con descarga/subida de archivos, exportacion de datos, gestion documental | Incluir funciones en `functions.js` para `download()`, `uploadFile()`, `readFile()`, `saveFile()`. Creación: `new FileManager()` |
57
+ | **XOnePDF** | Apps con reportes, tickets, albaranes, facturas en PDF | Incluir funciones de generación PDF en `functions.js`. Creación: `new XOnePDF()`. Patron: `create()` > `open()` > contenido > `close()` > `launchPDF()` |
58
+ | **XOnePrinter** | Apps de campo con impresion de etiquetas/tickets via Bluetooth (Zebra) | Incluir funciones de impresion en `functions.js`. Agregar permisos Bluetooth en `app.xml`. Creación: `new XOnePrinter()` |
59
+ | **BarcodeGenerator** | Apps con generación de códigos QR/barras para etiquetas, identificación | Incluir funciones de generación en `functions.js`. Tipos: `qrcode`, `code128`, `ean13`, `pdf417`, etc. Creación: `new BarcodeGenerator()` |
60
+ | **Escaner QR/barras** | Apps con lectura de códigos QR/barras desde camara | Agregar permiso `camera` en `app.xml`. Declarar `<prop type="VD" code-type="qr" oncodescanned="...">` en el XML; en JS usar `control.setOnCodeScanned(callback)` sobre el control obtenido con `getControl("MAP_CAMERA")`. El callback recibe `evento.data` y `evento.type` |
61
+ | **XOneNFC** | Apps con lectura de tarjetas NFC, DNI electrónico, tags MIFARE | Agregar permisos NFC en `app.xml`. Creación: `new XOneNFC()`. Métodos: `readNdefMessageAsync()`, `enableDnieReader()`. Para el DNIe, `enableDnieReader()` admite `enablePassiveAuthentication` (defecto `true`: comprueba la firma del país emisor y aborta por `onDnieReadError` si no cuadra), `trustedCountries` (emisoras admitidas, p. ej. `"ES"`) y `minimumSessionKeySize` (`112`/`128`/`192`/`256`) |
62
+ | **XOneOCR** | Apps con reconocimiento de texto en imágenes, lectura de matriculas | Creación: `new XOneOCR()`. Métodos: `scanLicensePlate()` (matrículas), `startScan({regex, onResult})` (validación por patrones). `scanText()` aún NO está implementado (lanza UnsupportedOperationException). Agregar permisos de camara |
63
+ | **BluetoothSerialPort** | Apps de campo con dispositivos Bluetooth (balanzas, sensores, terminales) | Singleton `bluetoothSerial`. Agregar permisos Bluetooth en `app.xml`. Métodos: `connect()`, `write()`, `read()` |
64
+ | **WifiManager** | Apps con configuración de redes WiFi, conexión a dispositivos | Creación: `new WifiManager()`. Agregar permisos WiFi en `app.xml`. Métodos: `scanAvailableNetworks()`, `connect()` |
65
+ | **GpsTools** | Apps con tracking GPS, calculo de distancias, geocodificacion | Creación: `new GpsTools()`. Métodos: `distanceTo()`, `getAddressFromPosition()`, `containsLocation()`, `getLastKnownLocation()` |
66
+ | **OAuth2** | Apps con autenticación externa (Google, Microsoft, SSO corporativo) | Creación: `new OAuth2()`. Configurar `authority`, `clientID`, `clientSecret`, `scope`, `redirectUri` en `functions.js` |
67
+ | **WebSocket** | Apps con comunicación en tiempo real (chat, notificaciones push, IoT) | Creación: `new WebSocket(request)`. Configurar callbacks: `onOpen`, `onMessage`, `onError`, `onClose`. Métodos: `send()`, `close()` |
68
+ | **fingerprintManager** | Apps con autenticación biometrica (huella dactilar, Face ID) | Singleton `fingerprintManager`. Configurar callbacks `onSuccess`/`onFailure`. Métodos: `listen()`, `stopListening()` |
69
+ | **Animation** | Apps con transiciones y animaciones personalizadas en controles | Creación: `new Animation()`. Configurar `setTarget()`, `setDuration()`, efectos (`setAlpha()`, `setRotation()`, `setX()`) |
70
+ | **Animación Lottie** | Apps con loaders, checks animados o ilustraciones en movimiento | Sin objeto JS: `<prop type="IMG">` apuntando a un `.json`, `.lottie` o `.tgs`; arranca sola en bucle infinito. `repeat-mode="reverse"` para ida y vuelta; desde JS, `playAnimation` / `stopAnimation` / `setAnimationFrame`. Las fuentes que use la animación van en `fonts/`. Detalle en [fase-6-colecciones.md](fase-6-colecciones.md) §6.8b |
71
+ | **ImageDrawing** | Apps con edición de imágenes, marca de agua, timestamps en fotos | Creación: `new ImageDrawing()`. Métodos: `create()`, `setBackground()`, `addTextSetXY()`, `save()` |
72
+
73
+ #### Regla de Decisión para Integraciones
74
+
75
+ ```
76
+ Al analizar los requisitos del usuario:
77
+ 1. Identificar funcionalidades que requieran hardware (GPS, camara, Bluetooth, NFC)
78
+ 2. Identificar funcionalidades que requieran servicios (PDF, impresion, OAuth)
79
+ 3. Para cada integracion identificada:
80
+ a. Agregar las funciones necesarias en functions.js
81
+ b. Agregar permisos requeridos en app.xml si aplica
82
+ c. Incluir pantallas/botones que invoquen la funcionalidad
83
+ d. Documentar la integracion en el README.md del proyecto
84
+ ```
85
+
86
+ #### Ejemplo: Impacto de Integraciones en functions.js
87
+
88
+ ```javascript
89
+ // === Si el proyecto necesita escaneo de codigos QR ===
90
+ // Requiere haber declarado en el XML:
91
+ // <prop name="MAP_CAMERA" type="VD" code-type="qr" viewmode="camerapreview"
92
+ // width="100%" height="300p"/>
93
+ function iniciarEscaneoQR() {
94
+ let control = getControl("MAP_CAMERA");
95
+ if (!control) {
96
+ ui.showToast("Camara no disponible");
97
+ return;
98
+ }
99
+ control.setOnCodeScanned(function(evento) {
100
+ self.CODIGO_BARRAS = evento.data;
101
+ ui.refresh("CODIGO_BARRAS");
102
+ ui.showToast("Código leido: " + evento.data);
103
+ return true; // true = parar escaneo; false = seguir leyendo
104
+ });
105
+ }
106
+
107
+ // === Si el proyecto necesita generacion de PDF ===
108
+ function generarReportePDF(sNombreArchivo) {
109
+ var pdf = new XOnePDF();
110
+ pdf.create(sNombreArchivo);
111
+ pdf.open();
112
+ pdf.setFont("helvetica");
113
+ pdf.setFontSize(14);
114
+ pdf.setFontStyle("bold");
115
+ pdf.addTextLine("Reporte generado: " + formatearFechaHora(new Date()));
116
+ pdf.newLine();
117
+ // ... contenido del reporte ...
118
+ pdf.close();
119
+ pdf.launchPDF();
120
+ }
121
+
122
+ // === Si el proyecto necesita autenticación biométrica ===
123
+ function activarBiometria() {
124
+ var params = {
125
+ onSuccess: function(result) {
126
+ ui.showToast("Autenticación exitosa");
127
+ abrirPantalla("MenuPrincipal");
128
+ },
129
+ onFailure: function(nError, sErrorMessage) {
130
+ ui.showToast("Error: " + sErrorMessage);
131
+ }
132
+ };
133
+ fingerprintManager.setCallback(params);
134
+ fingerprintManager.listen();
135
+ }
136
+ ```
137
+
138
+ ---
139
+
140
+
141
+ ## 9. Fase 8: Eventos y Reglas de Negocio
142
+
@@ -0,0 +1,494 @@
1
+ # Generación XOne — Fase 7: pantallas de entidad y estructura
2
+
3
+ > Fuente: `xone/v2/xone-project-generator/references/xone-project-generation-workflow.md` L3033–3521. Referencia de la skill; el índice está en [../SKILL.md](../SKILL.md).
4
+
5
+ Contenido: §7.8 lista de entidad · §7.9 detalle/formulario · §7.10 pantalla con mapa · §7.11 configuración · §7.12 estructura de pantalla estándar · §7.12b nodo group y pestañas · §7.12c nodo frame
6
+
7
+ ---
8
+
9
+ ### 7.8 Plantilla: Lista de Entidad
10
+
11
+ ```xml
12
+ <?xml version="1.0" encoding="utf-8"?>
13
+ <!--
14
+ Pantalla de lista de [Entidad]
15
+ -->
16
+ <coll name="Lista[Entidad]"
17
+ sql="SELECT * FROM ##PREF##[Entidad]"
18
+ loadall="true" objname="[Entidad]"
19
+ notab="true" show-toolbar="false">
20
+
21
+ <group name="grpLista" id="1" class="groupNoTab">
22
+ <!-- Header -->
23
+ <frame name="frmHeader" width="100%" height="80p"
24
+ bgcolor="#2196F3" align="center">
25
+ <prop name="btnAtras" type="B" visible="7"
26
+ width="48p" height="48p" lmargin="10p"
27
+ img="./icons/ic_arrow_back_white.png"
28
+ bgcolor="#00000000"
29
+ onclick="var w = ui.getView(self); if (w) w.exit();" />
30
+ <prop name="lblTitulo" type="L" visible="7"
31
+ width="70%" height="48p" lmargin="10p"
32
+ newline="false" forecolor="#FFFFFF"
33
+ fontsize="16" title="Lista de [Entidad]" />
34
+ </frame>
35
+
36
+ <!-- Campos visibles en modo lista (visible="2" o "7") -->
37
+ <prop name="NOMBRE" type="T" visible="7" title="Nombre" />
38
+ <prop name="DESCRIPCION" type="T" visible="2" title="Descripción" />
39
+ </group>
40
+
41
+ <!-- Al seleccionar un item de la lista -->
42
+ <selecteditem show-wait-dialog="false" refresh="false">
43
+ <action name="runscript">
44
+ <script language="javascript">
45
+ ui.openEditView(self);
46
+ </script>
47
+ </action>
48
+ </selecteditem>
49
+
50
+ <onback show-wait-dialog="false" refresh="false">
51
+ <action name="runscript">
52
+ <script language="javascript">
53
+ let window = ui.getView(self);
54
+ if (window) window.exit();
55
+ </script>
56
+ </action>
57
+ </onback>
58
+ </coll>
59
+ ```
60
+
61
+ ### 7.9 Plantilla: Detalle/Formulario de Entidad
62
+
63
+ ```xml
64
+ <?xml version="1.0" encoding="utf-8"?>
65
+ <!--
66
+ Pantalla de detalle/edicion de [Entidad]
67
+ -->
68
+ <coll name="Detalle[Entidad]" title="Detalle"
69
+ notab="true" show-toolbar="false">
70
+
71
+ <group name="grpDetalle" id="1" class="groupNoTab">
72
+ <!-- Header -->
73
+ <frame name="frmHeader" width="100%" height="80p"
74
+ bgcolor="#2196F3" align="center">
75
+ <prop name="btnAtras" type="B" visible="7"
76
+ width="48p" height="48p" lmargin="10p"
77
+ img="./icons/ic_arrow_back_white.png"
78
+ bgcolor="#00000000"
79
+ onclick="var w = ui.getView(self); if (w) w.exit();" />
80
+ <prop name="lblTitulo" type="L" visible="7"
81
+ width="70%" height="48p" lmargin="10p"
82
+ newline="false" forecolor="#FFFFFF"
83
+ fontsize="16" title="Detalle" />
84
+ <prop name="btnGuardar" type="B" visible="7"
85
+ width="48p" height="48p" rmargin="10p"
86
+ newline="false" img="./icons/ic_save_white.png"
87
+ bgcolor="#00000000"
88
+ method="executenode(guardar)" />
89
+ </frame>
90
+
91
+ <!-- Formulario -->
92
+ <frame name="frmFormulario" width="100%" height="100%"
93
+ scroll="true" bgcolor="#FFFFFF">
94
+ <prop name="NOMBRE" type="T" visible="1"
95
+ width="90%" height="50p" align="center"
96
+ tmargin="15p" labelwidth="0"
97
+ floating-tooltip="true" tooltip="Nombre"
98
+ class="textoEditable" />
99
+ <prop name="DESCRIPCION" type="T" visible="1"
100
+ width="90%" height="80p" align="center"
101
+ tmargin="15p" labelwidth="0" lines="3"
102
+ floating-tooltip="true" tooltip="Descripción"
103
+ class="textoEditable" />
104
+ <!-- Agregar mas campos según el modelo de datos -->
105
+ </frame>
106
+ </group>
107
+
108
+ <!-- Evento guardar -->
109
+ <guardar>
110
+ <action name="runscript">
111
+ <script language="javascript">
112
+ if (isEmpty(self.NOMBRE)) {
113
+ ui.showToast("El nombre es obligatorio");
114
+ return;
115
+ }
116
+ self.save();
117
+ ui.showToast("Guardado correctamente");
118
+ let window = ui.getView(self);
119
+ if (window) window.exit();
120
+ </script>
121
+ </action>
122
+ </guardar>
123
+
124
+ <onback show-wait-dialog="false" refresh="false">
125
+ <action name="runscript">
126
+ <script language="javascript">
127
+ let window = ui.getView(self);
128
+ if (window) window.exit();
129
+ </script>
130
+ </action>
131
+ </onback>
132
+ </coll>
133
+ ```
134
+
135
+ ### 7.10 Plantilla: Pantalla con Mapa
136
+
137
+ ```xml
138
+ <?xml version="1.0" encoding="utf-8"?>
139
+ <!--
140
+ Pantalla con mapa
141
+ -->
142
+ <coll name="Mapa[Entidad]" title="Mapa"
143
+ notab="true" show-toolbar="false">
144
+
145
+ <group name="grpMapa" id="1" class="groupNoTab">
146
+ <frame name="frmHeader" width="100%" height="80p"
147
+ bgcolor="#2196F3" align="center">
148
+ <prop name="btnAtras" type="B" visible="7"
149
+ width="48p" height="48p" lmargin="10p"
150
+ img="./icons/ic_arrow_back_white.png"
151
+ bgcolor="#00000000"
152
+ onclick="var w = ui.getView(self); if (w) w.exit();" />
153
+ <prop name="lblTitulo" type="L" visible="7"
154
+ width="70%" height="48p" lmargin="10p"
155
+ newline="false" forecolor="#FFFFFF"
156
+ fontsize="16" title="Mapa" />
157
+ </frame>
158
+
159
+ <!-- Mapa -->
160
+ <prop name="MAP_MAPA" type="Z" visible="7"
161
+ viewmode="mapview"
162
+ contents="@Ubicaciones"
163
+ width="100%" height="85%"
164
+ show-user-location="true"
165
+ zoom-to-pois="true"
166
+ onmapclicked="onMapClicked(e);"
167
+ onmapready="onMapReady(e);" />
168
+ </group>
169
+
170
+ <contents name="@Ubicaciones" src="UbicacionesColl" />
171
+
172
+ <onback show-wait-dialog="false" refresh="false">
173
+ <action name="runscript">
174
+ <script language="javascript">
175
+ let window = ui.getView(self);
176
+ if (window) window.exit();
177
+ </script>
178
+ </action>
179
+ </onback>
180
+ </coll>
181
+ ```
182
+
183
+ ### 7.11 Plantilla: Pantalla de Configuración
184
+
185
+ ```xml
186
+ <?xml version="1.0" encoding="utf-8"?>
187
+ <!--
188
+ Pantalla de configuración/ajustes
189
+ -->
190
+ <coll name="Configuración" title="Configuración"
191
+ special="true" notab="true" show-toolbar="false">
192
+
193
+ <group name="grpConfig" id="1" class="groupNoTab">
194
+ <frame name="frmHeader" width="100%" height="80p"
195
+ bgcolor="#2196F3" align="center">
196
+ <prop name="btnAtras" type="B" visible="7"
197
+ width="48p" height="48p" lmargin="10p"
198
+ img="./icons/ic_arrow_back_white.png"
199
+ bgcolor="#00000000"
200
+ onclick="var w = ui.getView(self); if (w) w.exit();" />
201
+ <prop name="lblTitulo" type="L" visible="7"
202
+ width="70%" height="48p" lmargin="10p"
203
+ newline="false" forecolor="#FFFFFF"
204
+ fontsize="16" title="Configuración" />
205
+ </frame>
206
+
207
+ <frame name="frmOpciones" width="100%" height="100%"
208
+ scroll="true" bgcolor="#FFFFFF">
209
+
210
+ <!-- Info del usuario -->
211
+ <prop name="lblUsuario" type="L" visible="7"
212
+ width="90%" height="40p" align="center"
213
+ tmargin="20p" fontsize="14"
214
+ title="Usuario conectado" />
215
+
216
+ <!-- Opciones -->
217
+ <prop name="MAP_NOTIFICACIONES" type="NC" visible="7"
218
+ width="90%" height="50p" align="center"
219
+ tmargin="15p" title="Notificaciones"
220
+ check-type="toggle" />
221
+
222
+ <!-- Botón cerrar sesion -->
223
+ <prop name="btnCerrarSesion" type="B" visible="7"
224
+ width="80%" height="50p" align="center"
225
+ tmargin="40p" class="btnPeligro"
226
+ title="Cerrar Sesion"
227
+ onclick="if (confirmar('Desea cerrar sesion?', 'Cerrar Sesion')) { appData.logout(); };" />
228
+
229
+ <!-- Versión -->
230
+ <prop name="lblVersion" type="L" visible="7"
231
+ width="100%" height="30p" align="center"
232
+ tmargin="30p" class="textoSubtitulo"
233
+ title="Versión 1.0.0" />
234
+ </frame>
235
+ </group>
236
+
237
+ <onback show-wait-dialog="false" refresh="false">
238
+ <action name="runscript">
239
+ <script language="javascript">
240
+ let window = ui.getView(self);
241
+ if (window) window.exit();
242
+ </script>
243
+ </action>
244
+ </onback>
245
+ </coll>
246
+ ```
247
+
248
+ ### 7.12 Estructura de Pantalla Estándar
249
+
250
+ Toda pantalla debe seguir esta estructura básica:
251
+
252
+ ```xml
253
+ <coll name="NombrePantalla" title="Título" class="xnCollBase">
254
+ <!-- Eventos de ciclo de vida -->
255
+ <create><!-- Se ejecuta una sola vez al crear un objeto nuevo --></create>
256
+ <before-edit><!-- Se ejecuta al abrir el objeto para editar, antes de pintar la UI --></before-edit>
257
+ <after-edit><!-- Se ejecuta al abrir el objeto para editar, una vez pintada la UI --></after-edit>
258
+
259
+ <!-- Contenido visual -->
260
+ <group name="grpPrincipal" id="1" class="groupNoTab">
261
+ <frame name="frmHeader" class="frameHeader">...</frame>
262
+ <frame name="frmBody" class="frameBody">...</frame>
263
+ <frame name="frmFooter" class="frameFooter">...</frame>
264
+ </group>
265
+
266
+ <!-- Contents embebidos (si aplica) -->
267
+ <contents name="@MiContenido" src="MiColeccion" />
268
+
269
+ <!-- Eventos custom (invocados con ExecuteNode) -->
270
+ <miEvento>
271
+ <action name="runscript">
272
+ <script language="javascript">
273
+ // Lógica del evento
274
+ </script>
275
+ </action>
276
+ </miEvento>
277
+
278
+ <!-- Manejo del botón atrás -->
279
+ <onback>
280
+ <action name="runscript">
281
+ <script language="javascript">
282
+ let window = ui.getView(self);
283
+ if (window) window.exit();
284
+ </script>
285
+ </action>
286
+ </onback>
287
+ </coll>
288
+ ```
289
+
290
+ ### 7.12b Nodo GROUP — Pestanas y Grupos de Pantalla
291
+
292
+ El nodo `<group>` define las pestanas o áreas de contenido dentro de una coleccion. Cada group tiene un `id` único que lo identifica.
293
+
294
+ #### Atributos del nodo `<group>`
295
+
296
+ | Atributo | Descripción | Ejemplo |
297
+ |----------|-------------|---------|
298
+ | `name` | Caption que se muestra en la pestana | `"General"` |
299
+ | `id` | Identificador numérico único del grupo | `"1"` |
300
+ | `bgcolor` | Color de fondo del grupo | `"#FFFFFF"` |
301
+ | `imgbk` | Imagen de fondo del grupo | `"fondo.png"` |
302
+ | `disableedit` | Deshabilita edición de todos los campos SI se cumple la condición | `"ESTADO=2"` |
303
+ | `disablevisible` | Oculta el grupo entero SI se cumple la condición | `"TIPO=0"` |
304
+ | `align` | Alineacion del contenido dentro del group. Mismos valores y comportamiento que en `<frame>`: `center`, `left\|top`, `center\|center`, etc. | `"center\|top"` |
305
+ | `tab-width` | Ancho de la pestana. Por defecto `"33%"` | `"50%"` |
306
+ | `animation-in` | Animación al entrar al grupo | `"##ALPHA_IN##"` |
307
+ | `animation-out` | Animación al salir del grupo | `"##ALPHA_OUT##"` |
308
+ | `onfocus` | Evento que se ejecuta cuando el usuario selecciona el grupo | `"ExecuteNode(onfocusgrupo(1))"` |
309
+ | `below-drawer` | Si es `true`, el grupo queda por debajo del drawer. Usar en headers y footers fijos para que el drawer se superponga correctamente | `"true"` |
310
+ | `floating` | Si es `true`, el grupo se superpone sobre el contenido. Posicionar con `top` y `left` | `"true"` |
311
+
312
+ #### Grupo Fijo (Header/Footer)
313
+
314
+ Para crear cabeceras o pies fijos que no se desplazan con el scroll:
315
+
316
+ ```xml
317
+ <!-- Header fijo en la parte superior -->
318
+ <group name="HEADER" id="10" fixed="true" orientation="top" width="100%" height="120p">
319
+ <frame name="frmHeader" class="frmsuperior">
320
+ <prop name="SALIR" type="B" class="btvolversuper" />
321
+ <prop name="TITULO" type="L" class="tlsuper" title="MI PANTALLA" />
322
+ <prop name="BTMENU" type="B" class="btmenuicon" method="ExecuteNode(onback)" />
323
+ </frame>
324
+ </group>
325
+
326
+ <!-- Footer fijo en la parte inferior -->
327
+ <group name="FOOTER" id="0" fixed="true" orientation="bottom" width="100%" height="80p">
328
+ <frame name="frmFooter">
329
+ <prop name="BTN_CANCELAR" type="B" title="Cancelar" method="ExecuteNode(onback)"
330
+ width="45%" height="80%" />
331
+ <prop name="BTN_ACEPTAR" type="B" title="Aceptar" method="ExecuteNode(guardar)"
332
+ width="45%" height="80%" newline="false" lmargin="6%" />
333
+ </frame>
334
+ </group>
335
+
336
+ <!-- Contenido principal — ocupa el espacio restante tras los grupos fijos -->
337
+ <group name="General" id="1">
338
+ <!-- ... -->
339
+ </group>
340
+ ```
341
+
342
+ > **IMPORTANTE:** Una vez definidos los grupos fijos, el espacio restante se considera el 100% para los grupos de contenido. No hay que restar el alto de los grupos fijos.
343
+
344
+ #### Grupo Drawer (panel lateral deslizante)
345
+
346
+ ```xml
347
+ <group name="Drawer" id="999" drawer-orientation="left" width="70%" height="100%">
348
+ <prop name="MAP_BT_MENU1" type="B" title="Clientes" visible="1"
349
+ onclick="javascript:ui.openEditView('ListaClientes'); ocultarGrupo(999);"
350
+ class="xnTituloDrawerC" />
351
+ <prop name="MAP_BT_MENU2" type="B" title="Pedidos" visible="1"
352
+ onclick="javascript:ui.openEditView('ListaPedidos'); ocultarGrupo(999);"
353
+ class="xnTituloDrawerC" />
354
+ <prop name="MAP_BT_SALIR" type="B" title="Salir" visible="1"
355
+ method="ExecuteNode(onback)" class="xnTituloDrawerC" />
356
+ </group>
357
+ ```
358
+
359
+ **Métodos JavaScript para el Drawer:**
360
+
361
+ | Método | Descripción |
362
+ |--------|-------------|
363
+ | `ui.showGroup(id)` | Muestra el grupo |
364
+ | `ui.showGroup(id, animIn, durIn, animOut, durOut)` | Muestra el grupo con animación personalizada |
365
+ | `ui.hideGroup(id)` | Oculta el grupo |
366
+ | `ui.toggleGroup(id)` | Alterna entre mostrar y ocultar |
367
+ | `ui.lockGroup(id, close)` | Bloquea el grupo: `close=true` lo bloquea cerrado, `close=false` lo bloquea abierto |
368
+ | `ui.unlockGroup(id)` | Desbloquea el grupo para que vuelva a ser interactivo |
369
+
370
+ ```javascript
371
+ // Abrir drawer con animacion
372
+ ui.showGroup(999, "##RIGHT_IN##", 300, "##LEFT_OUT##", 200);
373
+ // Cerrar
374
+ ui.hideGroup(999);
375
+ // Bloquear cerrado durante carga inicial
376
+ ui.lockGroup(999, true);
377
+ ```
378
+
379
+ #### Macros de animación para grupos y frames
380
+
381
+ | Macro entrada | Macro salida | Efecto |
382
+ |---------------|--------------|--------|
383
+ | `##ALPHA_IN##` | `##ALPHA_OUT##` | Fundido de entrada/salida |
384
+ | `##RIGHT_IN##` | `##RIGHT_OUT##` | Desde/hacia la derecha |
385
+ | `##LEFT_IN##` | `##LEFT_OUT##` | Desde/hacia la izquierda |
386
+ | `##PUSH_IN##` | `##PUSH_OUT##` | Empuje desde abajo |
387
+ | `##PUSH_DOWN_IN##` | `##PUSH_DOWN_OUT##` | Empuje hacia abajo |
388
+ | `##ROTATE3D_IN##` | `##ROTATE3D_OUT##` | Rotación 3D |
389
+ | `##ZOOM_IN##` | `##ZOOM_OUT##` | Zoom de entrada/salida |
390
+
391
+ #### Atributos de COLL relacionados con grupos
392
+
393
+ | Atributo en coll | Descripción |
394
+ |------------------|-------------|
395
+ | `notab="true"` | Oculta las pestanas de los grupos |
396
+ | `group-swipe="true"` | Permite deslizar entre grupos con el dedo |
397
+ | `group-theme="material"` | Estilo Material Design para las pestanas |
398
+ | `tab-mode="fixed"` | Pestanas de ancho fijo distribuidas en pantalla |
399
+ | `tab-mode="scrollable"` | Pestanas con scroll si no caben en pantalla |
400
+
401
+ ---
402
+
403
+ ### 7.12c Nodo FRAME — Contenedores Visuales
404
+
405
+ El nodo `<frame>` es el equivalente al `<div>` de HTML. Permite organizar los props en áreas visuales dentro de un group. Los frames pueden anidarse sin limite.
406
+
407
+ > **REGLA CRITICA:** Un `<frame>` **solo se pinta si contiene al menos un `<prop>` visible**. Un frame vacio, o con todos sus props con `visible="0"`, no ocupa espacio ni se renderiza en pantalla. **No usar frames como espaciadores vacios** — no funcionan para crear espacio. Si se necesita separación visual, usar `tmargin`/`bmargin` en el prop anterior, o un `<prop type="L" title=" " height="20p" visible="1" />` como separador.
408
+
409
+ ```xml
410
+ <frame name="frmContenido" width="100%" height="100%" scroll="true" bgcolor="#FFFFFF">
411
+ <frame name="frmCabecera" width="100%" height="80p" bgcolor="#2196F3">
412
+ <prop name="TITULO" type="L" title="Mi título" forecolor="#FFFFFF" labelwidth="0" />
413
+ </frame>
414
+ <frame name="frmCuerpo" width="90%" height="100%" lmargin="5%">
415
+ <prop name="NOMBRE" type="T" visible="1" title="Nombre:" />
416
+ </frame>
417
+ </frame>
418
+ ```
419
+
420
+ #### Atributos del nodo `<frame>`
421
+
422
+ | Atributo | Descripción | Ejemplo |
423
+ |----------|-------------|---------|
424
+ | `name` | Identificador del frame | `"frmHeader"` |
425
+ | `width` | Ancho: `%`, `p` (puntos) o valor numérico DIP | `"100%"`, `"300p"` |
426
+ | `height` | Alto: `%`, `p` o DIP. `-2` = ajuste automático al contenido | `"120p"`, `-2` |
427
+ | `bgcolor` | Color de fondo | `"#2196F3"`, `"#00000000"` (transparente) |
428
+ | `imgbk` | Imagen de fondo | `"fondo.png"` |
429
+ | `framebox` | `false` oculta el borde del frame | `"false"` |
430
+ | `border-width` | Ancho del borde | `"1"` |
431
+ | `align` | Alineacion del contenido dentro del frame. Valores: `left`, `right`, `center`, `top`, `bottom`. Combinar horizontal y vertical con `\|`: `center\|center`, `left\|top`, `left\|center`, `center\|top`, `right\|center`. Mismo comportamiento en `<group>` y `<prop>` | `"center\|top"` |
432
+ | `newline` | Por defecto `true`. Con `false` el frame se coloca a la derecha del anterior en la misma línea. Los anchos deben sumar 100% o menos | `"false"` |
433
+ | `scroll` | `true` permite scroll si el contenido supera el alto | `"true"` |
434
+ | `lmargin`/`tmargin`/`rmargin`/`bmargin` | Margenes exteriores | `"5%"`, `"10p"` |
435
+ | `lpadding`/`tpadding`/`rpadding`/`bpadding` | Margenes interiores | `"15p"` |
436
+ | `disablevisible` | Oculta el frame SI se cumple la condición | `"ESTADO=0"` |
437
+ | `animation-in` | Animación de entrada | `"##ALPHA_IN##"` |
438
+ | `animation-out` | Animación de salida | `"##ALPHA_OUT##"` |
439
+ | `animation-in-delay` | Duración de la animación de entrada (ms) | `"300"` |
440
+ | `animation-out-delay` | Duración de la animación de salida (ms) | `"300"` |
441
+ | `elevation` | Elevacion / sombra Material Design. Valores de 1 a 24 | `"5"` |
442
+ | `border-corner-radius` | Radio de esquinas redondeadas | `"10"` |
443
+ | `ignore-touch-on-transparent-area` | En frames flotantes, los toques sobre áreas transparentes pasan al elemento que hay detras | `"true"` |
444
+
445
+ #### Frame Flotante
446
+
447
+ Un frame flotante se superpone sobre el resto de la pantalla sin afectar al layout de los demas elementos. Útil para FABs, menus contextuales, alertas:
448
+
449
+ ```xml
450
+ <!-- Botón flotante en la esquina inferior derecha (FAB) -->
451
+ <frame name="frmFAB" floating="true" top="900p" left="610p" width="90p" height="90p">
452
+ <prop name="BTN_ADD" type="B" visible="1" labelwidth="0"
453
+ method="ExecuteNode(nuevo)" width="75p" img="add.png" imgsel="add_click.png" />
454
+ </frame>
455
+ ```
456
+
457
+ | Atributo frame flotante | Descripción |
458
+ |------------------------|-------------|
459
+ | `floating="true"` | Activa el modo flotante |
460
+ | `top` | Coordenada Y en pixeles desde el borde superior |
461
+ | `left` | Coordenada X en pixeles desde el borde izquierdo |
462
+
463
+ > **NOTA:** En frames flotantes usar `p` (pixeles) para `top`, `left`, `width` y `height` para mejor funcionamiento. Evitar `%`.
464
+
465
+ #### Bottom Sheet (panel deslizante inferior)
466
+
467
+ ```xml
468
+ <frame name="bottom_panel" floating="true" left="0" behavior="bottom-sheet"
469
+ initial-state="collapsed" width="100%" height="50%">
470
+ <prop name="TITULO" type="L" title="Panel inferior" labelwidth="0" width="100%" />
471
+ <!-- contenido del panel -->
472
+ </frame>
473
+ ```
474
+
475
+ | Estado `initial-state` | Descripción |
476
+ |------------------------|-------------|
477
+ | `expanded` | Aparece expandido al 100% de su tamaño |
478
+ | `collapsed` | Aparece minimizado mostrando solo una franja |
479
+ | `hidden` | Aparece oculto completamente |
480
+
481
+ **JavaScript:** `window.setBottomSheetState(sProp, "expanded")` para cambiar el estado.
482
+
483
+ #### Macros de animación disponibles
484
+
485
+ | Macro | Efecto |
486
+ |-------|--------|
487
+ | `##ALPHA_IN##` / `##ALPHA_OUT##` | Fade in / fade out |
488
+ | `##ZOOM_IN##` / `##ZOOM_OUT##` | Zoom in / zoom out |
489
+ | `##PUSH_IN##` / `##PUSH_OUT##` | Deslizar desde abajo / hacia abajo |
490
+ | `##PUSH_DOWN_IN##` / `##PUSH_DOWN_OUT##` | Deslizar desde arriba / hacia arriba |
491
+ | `##RIGHT_IN##` / `##LEFT_OUT##` | Entrar desde la derecha / salir hacia la izquierda |
492
+ | `##LEFT_IN##` / `##RIGHT_OUT##` | Entrar desde la izquierda / salir hacia la derecha |
493
+ | `##ROTATE3D_IN##` / `##ROTATE3D_OUT##` | Rotación 3D de entrada / salida |
494
+