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,422 @@
1
+ # XOne JavaScript — ui: navegación, mensajes y vista
2
+
3
+ > Fuente: `xone/v2/xone-help-docs/topics/03b-js-ui.md` §3.1–§3.4. Referencia de la skill; el índice está en [../../SKILL.md](../../SKILL.md).
4
+
5
+ Contenido: §3.1 navegación (openEditView, openMenu) · §3.2 mensajes y diálogos (msgBox, showToast, showSnackbar) · §3.3 refrescar y acceder a controles, showcase · §3.4 date/time pickers
6
+
7
+ ---
8
+
9
+ ### 3.1 Navegación
10
+
11
+ `ui.openEditView()` es el mecanismo principal de navegación en XOne. Sirve tanto para "abrir una pantalla" como para "editar un objeto existente":
12
+
13
+ ```javascript
14
+ // === Abrir una pantalla (la forma habitual) ===
15
+ // Firma: ui.openEditView(target, [exit])
16
+ // target : dataObject | string — un dataObject ya preparado, o el nombre de la coll destino
17
+ // exit : boolean — si true, cierra la vista origen al abrir la nueva (default false)
18
+
19
+ // Forma corta: pasar el nombre de la coll. XOne crea internamente un dataObject
20
+ // vacío de esa coll (createObject + addItem) y abre su vista de edición.
21
+ ui.openEditView("Productos");
22
+
23
+ // Pasar un objeto NUEVO con datos pre-rellenados
24
+ let coll = appData.getCollection("Productos");
25
+ let obj = new Productos({ MAP_CATEGORIA_ID: idCategoria });
26
+ coll.addItem(obj);
27
+ ui.openEditView(obj);
28
+
29
+ // Abrir un objeto EXISTENTE recuperado de la BD
30
+ let producto = appData.getCollection("Productos").findObject("ID = " + nId);
31
+ if (producto) {
32
+ ui.openEditView(producto);
33
+ }
34
+
35
+ // Cerrar la vista origen al abrir la nueva (flujos lineales sin botón atrás)
36
+ ui.openEditView(obj, true);
37
+
38
+ // === Obtener la ventana actual ===
39
+ let window = ui.getView(self); // Ventana del objeto actual
40
+ let window = ui.getView(); // Ventana actual sin parametro
41
+
42
+ // === Cerrar ventana actual ===
43
+ let window = ui.getView(self);
44
+ if (window) {
45
+ window.exit();
46
+ }
47
+
48
+ // === Cerrar la aplicación ===
49
+ appData.exit();
50
+
51
+ // === Mostrar/ocultar grupos (tabs) ===
52
+ ui.showGroup(2); // Mostrar grupo por indice
53
+
54
+ // Con animacion
55
+ ui.showGroup(2, "##ALPHA_IN##", 200, "##ALPHA_OUT##", 200);
56
+
57
+ // Ejemplo real: navegacion entre paginas con animacion
58
+ function mostrarGrupo(nGroup, sAnimIn, sAnimOut) {
59
+ sAnimIn = sAnimIn || "##ALPHA_IN##";
60
+ sAnimOut = sAnimOut || "##ALPHA_OUT##";
61
+ ui.showGroup(nGroup, sAnimIn, 200, sAnimOut, 200);
62
+ }
63
+ ```
64
+
65
+ **Animaciones predefinidas disponibles:**
66
+
67
+ | Constante | Descripción |
68
+ |-----------|-------------|
69
+ | `##ALPHA_IN##` / `##ALPHA_OUT##` | Entrada/salida con fundido |
70
+ | `##ZOOM_IN##` / `##ZOOM_OUT##` | Entrada/salida con zoom |
71
+ | `##LEFT_IN##` / `##LEFT_OUT##` | Deslizar desde/hacia la izquierda |
72
+ | `##RIGHT_IN##` / `##RIGHT_OUT##` | Deslizar desde/hacia la derecha |
73
+ | `##TOP_IN##` / `##TOP_OUT##` | Deslizar desde/hacia arriba |
74
+ | `##BOTTOM_IN##` / `##BOTTOM_OUT##` | Deslizar desde/hacia abajo |
75
+
76
+ #### Caso especial — abrir la LISTA de una coll directamente
77
+
78
+ `ui.openEditView()` siempre abre el EditView de un dataObject. Si lo que se necesita es lanzar directamente la **lista** de una coll como pantalla independiente (`MainListCollectionActivity` o `MainCalendarViewActivity` si tiene `viewmode="calendar"`), hay que recurrir al método legacy `ui.openMenu(collName, mask, mode)` con `mode=0`:
79
+
80
+ ```javascript
81
+ // Lista con todas las opciones del menú (mode=0, mask=0xFFFFFF)
82
+ ui.openMenu("Productos", 0xFFFFFF, 0);
83
+
84
+ // Lista en modo sólo lectura (mask = MENU_MASK_VIEW)
85
+ ui.openMenu("Productos", 0x000200, 0);
86
+ ```
87
+
88
+ Constantes `mask` (combinables con OR — JavaScript NO expone los nombres, usar el valor numérico): `ADD=0x01`, `EDIT=0x02`, `DELETE=0x04`, `EXIT=0x08`, `FILTRAR=0x10`, `SAVE=0x40`, `SORT=0x80`, `REFRESH=0x100`, `VIEW=0x200`, `FULLMASK=0xFFFFFF`.
89
+
90
+ > Para el resto de necesidades de navegación (abrir una pantalla nueva, abrir un objeto existente, abrir un detalle desde un `<selecteditem>`) usar siempre `ui.openEditView()`. Habitualmente las "listas" en XOne se muestran como `<contents>` embebido en una pantalla padre, no como activity independiente — por eso `mode=0` se necesita poco.
91
+
92
+ ### 3.2 Mensajes y Dialogos
93
+
94
+ ```javascript
95
+ // === Message Box clasico ===
96
+ // Tipo 0 = Solo botón OK
97
+ // Tipo 4 = Botones Si/No (retorna 6=Si, 7=No)
98
+ let nResult = ui.msgBox("Desea continuar?", "Confirmar", 4);
99
+ if (nResult == 6) {
100
+ // Usuario pulso Si
101
+ }
102
+
103
+ // === Toast simple ===
104
+ ui.showToast("Mensaje rápido");
105
+
106
+ // === Toast personalizado ===
107
+ ui.showToast({
108
+ color : "#4CAF50", // Color de fondo
109
+ duration : "short", // "short" o "long"
110
+ text : "Guardado correctamente",
111
+ textColor: "#FFFFFF", // Color del texto
112
+ textFont : "Roboto-Regular.ttf", // Fuente (debe estar en fonts/)
113
+ textSize : 14, // Tamano de fuente
114
+ rounded : true // Esquinas redondeadas
115
+ });
116
+
117
+ // === Snackbar simple (solo texto) ===
118
+ ui.showSnackbar("Registro eliminado"); // duración "long", texto blanco por defecto
119
+
120
+ // === Snackbar con acción ===
121
+ ui.showSnackbar({
122
+ text : "Registro eliminado", // OBLIGATORIO (vacío => excepción)
123
+ color : "#323232",
124
+ duration : "long", // "short" | "long" | "indefinite" (otro valor => excepción)
125
+ width : "80%", // "100%" => ancho completo
126
+ textColor : "#FFFFFF",
127
+ actionText : "Deshacer", // solo se muestra si TAMBIÉN hay actionMethod
128
+ actionTextColor: "#FFEB3B",
129
+ maxLines : 1, // solo aplica si > 1
130
+ align : "center|bottom",
131
+ height : "10%", // Altura del snackbar (opcional)
132
+ actionMethod : function() { // se ejecuta en un hilo aparte, no en el de UI
133
+ deshacerEliminacion();
134
+ }
135
+ });
136
+
137
+ // Ocultar snackbar manualmente (oculta el último mostrado; false si no hay ninguno visible)
138
+ ui.hideSnackbar();
139
+
140
+ // NOTA: showSnackbar solo funciona dentro de una pantalla de edición.
141
+ // En otros contextos lanza una excepción.
142
+
143
+ // === msgBox con DataObject (dialogo completamente personalizado) ===
144
+
145
+ // Variante SINCRONA: bloquea hasta que el usuario pulsa
146
+ // La coll debe tener botones con button-option="N"
147
+ // ui.msgBox() devuelve el valor del button-option del botón pulsado
148
+ let msgBoxObj = new MessageBoxNormal();
149
+ let nResult = ui.msgBox(msgBoxObj);
150
+ // nResult == 1 -> pulsó Cancel (button-option="1")
151
+ // nResult == 2 -> pulsó OK (button-option="2")
152
+
153
+ // Variante ASINCRONA con callbacks (no bloquea)
154
+ // La coll debe tener: hardware-accelerated="false", bgcolor="#00000000"
155
+ // y campos type="O" para los callbacks
156
+ function showMsgBoxAsync(callbackOk, callbackCancel) {
157
+ let obj = new MessageBoxAsync({ MAP_CALLBACK_OK: callbackOk, MAP_CALLBACK_CANCEL: callbackCancel });
158
+ ui.openEditView(obj);
159
+ }
160
+
161
+ // Uso:
162
+ showMsgBoxAsync(
163
+ function() { ui.showToast("OK pulsado"); ui.getView(self).exit(); },
164
+ function() { ui.showToast("Cancel pulsado"); ui.getView(self).exit(); }
165
+ );
166
+
167
+ // === Wait Dialog (indicador de carga) ===
168
+ ui.showWaitDialog("Cargando datos...");
169
+ ui.setWaitDialogText("Procesando registros...");
170
+ ui.hideWaitDialog();
171
+
172
+ // === Notificaciones ===
173
+ // Notificación simple
174
+ ui.showNotification(1, "Titulo", "Texto de la notificación");
175
+
176
+ // Notificación con ticker
177
+ ui.showNotification(2, "Titulo", "Texto", "Texto en barra de estado");
178
+
179
+ // Notificación con callback al pulsar
180
+ ui.showNotification(3, "Titulo", "Texto", "Ticker", self, "miNodoCallback");
181
+
182
+ // Notificación avanzada con botones
183
+ ui.showNotification({
184
+ id : 5000,
185
+ title : "Nueva tarea asignada",
186
+ text : "Tiene una nueva tarea pendiente",
187
+ textHtml : "<b>Tarea urgente</b>: Revision de inventario",
188
+ icon : "app_icon1", // app_icon1 a app_icon10
189
+ largeIcon : "app_icon4",
190
+ backgroundColor: "#1976D2",
191
+ sound : "notification.wav",
192
+ cancelable : true,
193
+ dataObject : self,
194
+ nodeName : "callbackNotificacion",
195
+ parameters : '{ "tareaId": "123" }',
196
+ buttons : [{
197
+ id : 5001,
198
+ title : "Responder",
199
+ directReply : true,
200
+ directReplyLabel: "Escriba su respuesta...",
201
+ dataObject : self,
202
+ nodeName : "respuestaCallback"
203
+ }]
204
+ });
205
+
206
+ // LED de notificación (solo Android)
207
+ ui.setNotificationLed("#00FF00", 1000, 1000); // color, onMs, offMs
208
+ ```
209
+
210
+ #### msgBox con DataObject (Dialogos Personalizados)
211
+
212
+ `ui.msgBox(dataObject)` permite abrir una coleccion XOne como dialogo completamente personalizado.
213
+
214
+ **Variante sincrona** — Los botones usan `button-option`. `ui.msgBox()` bloquea hasta que el usuario pulsa y devuelve el valor del `button-option` pulsado:
215
+
216
+ ```javascript
217
+ let msgBoxObj = new MessageBoxNormal();
218
+ let nResult = ui.msgBox(msgBoxObj);
219
+ // nResult == 1 -> pulsó Cancel (button-option="1")
220
+ // nResult == 2 -> pulsó OK (button-option="2")
221
+ ```
222
+
223
+ La coll `MessageBoxNormal` requiere: `notab="true"`, `show-toolbar="false"`, `check-owner="false"`, `dependent="false"`, y botones con `button-option="N"`.
224
+
225
+ **Variante asíncrona con callbacks** — Los botones invocan `self.MAP_CALLBACK_OK()`. Usa campos `type="O"` para las funciones callback:
226
+
227
+ ```javascript
228
+ function showMessageBoxDataObject(callbackOk, callbackCancel) {
229
+ let newMsgBox = new MessageBoxAsync({ MAP_CALLBACK_OK: callbackOk, MAP_CALLBACK_CANCEL: callbackCancel });
230
+ ui.openEditView(newMsgBox);
231
+ }
232
+
233
+ // Uso
234
+ showMessageBoxDataObject(
235
+ function() { ui.showToast("OK pulsado"); ui.getView(self).exit(); },
236
+ function() { ui.showToast("Cancel pulsado"); ui.getView(self).exit(); }
237
+ );
238
+ ```
239
+
240
+ La coll `MessageBoxAsync` requiere además: `hardware-accelerated="false"` y `bgcolor="#00000000"` para fondo transparente sin fondo negro.
241
+
242
+ ### 3.3 Vista - Refrescar y Acceder a Controles
243
+
244
+ ```javascript
245
+ // === Obtener la ventana actual ===
246
+ let window = ui.getView(self);
247
+ let window = ui.getView(); // Sin parametro = ventana activa actual
248
+
249
+ // === Acceder a un control por nombre ===
250
+ let control = window["MAP_BOTON"];
251
+
252
+ // === getControl(name, [dataObject]) - función NATIVA global (recomendado) ===
253
+ // Disponible directamente, NO hace falta declarar el helper. Devuelve el control
254
+ // resuelto en la ventana destino:
255
+ // - getControl(name) → última ventana visible.
256
+ // - getControl(name, dataObject) → ventana asociada a ese DataObject.
257
+ //
258
+ // Semántica ESTRICTA: lanza error si el nombre está vacío, el control no
259
+ // existe, no hay ventana destino, o el dataObject no es válido.
260
+ //
261
+ // Si un proyecto ya tiene "function getControl(...)" propia, esa sombrea a la
262
+ // nativa en su scope local (compatibilidad hacia atrás preservada).
263
+ let control = getControl("MAP_BOTON");
264
+ let controlEnOtraVentana = getControl("MAP_TITULO", objPadre);
265
+
266
+ // === Refrescar campos de la interfaz ===
267
+ ui.refresh(); // Refrescar TODO (costoso, evitar)
268
+ ui.refresh("MAP_NOMBRE"); // Refrescar un campo específico
269
+ ui.refresh("MAP_NOMBRE,MAP_ESTADO"); // Refrescar multiples campos
270
+
271
+ // Solo actualizar el valor (sin reconstruir la vista del control)
272
+ ui.refreshValue("MAP_CAMPO");
273
+ // Multiples campos (cada uno como argumento)
274
+ let ventana = ui.getView(self);
275
+ ventana.refreshValue("MAP_CAMPO1", "MAP_CAMPO2", "MAP_CAMPO3");
276
+
277
+ // Refrescar una fila específica de un content
278
+ ui.refreshContentRow("MAP_CONTENT", 0);
279
+
280
+ // Refrescar la fila seleccionada de un content
281
+ ui.refreshContentSelectedRow("MAP_CONTENT");
282
+
283
+ // Refrescar usando la ventana directamente
284
+ window.refresh("MAP_CAMPO");
285
+ window.refreshAll("frmMiFrame"); // Refresca el frame y todos sus hijos
286
+
287
+ // === Grupos (tabs) y Drawers ===
288
+ // Mostrar un grupo por indice
289
+ ui.showGroup(2);
290
+ ui.showGroup(2, "##ALPHA_IN##", 300, "##ALPHA_OUT##", 300); // Con animacion
291
+
292
+ // Comprobar si un grupo esta abierto (util para drawers)
293
+ if (window.isGroupOpen(999)) {
294
+ window.hideGroup(999); // Cerrar el drawer
295
+ }
296
+
297
+ // Patron: botón atrás cierra drawer antes de salir
298
+ function doOnBack() {
299
+ let window = ui.getView();
300
+ if (!window) return;
301
+ if (window.isGroupOpen(999)) {
302
+ window.hideGroup(999);
303
+ return;
304
+ }
305
+ window.exit();
306
+ }
307
+
308
+ // === Nombre de la coleccion activa ===
309
+ function getCurrentCollectionName() {
310
+ let window = ui.getView();
311
+ if (!window) return "";
312
+ let dataObject = window.getDataObject();
313
+ if (!dataObject) return "";
314
+ let coll = dataObject.getOwnerCollection();
315
+ if (!coll) return "";
316
+ return coll.getName();
317
+ }
318
+
319
+ // === Traer app al primer plano (desde handler de notificación) ===
320
+ ui.returnToForeground();
321
+
322
+ // === Scroll de Frames ===
323
+ let frame = window["frmScroll"];
324
+ frame.scrollToTop(true); // true = animado
325
+ frame.scrollToBottom(true);
326
+
327
+ // === Bottom Sheet ===
328
+ // sFrame: nombre del frame con behavior="bottom-sheet"
329
+ // sState: "expanded" / "collapsed" / "hidden"
330
+ // bLockDrag: true = impedir que el usuario lo arrastre
331
+ window.setBottomSheetState("mi_panel", "expanded", false);
332
+ window.setBottomSheetState("mi_panel", "collapsed", true); // Bloqueado
333
+ let sEstado = window.getBottomSheetState("mi_panel");
334
+
335
+ // === Progress Bar JS ===
336
+ let control = window["MAP_PROGRESS_BAR"];
337
+ control.setIndeterminate(true); // Activar animacion continua
338
+ control.setIndeterminate(false); // Desactivar, mostrar valor actual
339
+ control.toggleIndeterminate(); // Alternar estado
340
+ let bIndet = control.isIndeterminate();
341
+
342
+ // === Efectos visuales en frame: setBlur / setSaturation ===
343
+ // NO son API de XOne: los expone la vista nativa de Android/iOS que hay por debajo.
344
+ // Se llaman sobre el frame o el control, nunca sobre ui, y no hay ui.setBlur.
345
+ // Documentados en metodos-nativos-de-la-vista.md, con el envoltorio y el patron de slider.
346
+
347
+ // === Color de la barra de estado ===
348
+ window.setStatusBarColor("#1565C0"); // Color RRGGBB
349
+ window.setStatusBarColor(null); // Restaurar color por defecto
350
+
351
+ // === Showcase (tutorial interactivo) ===
352
+ window.startShowcase({
353
+ continueOnCancel: true, // Si cancela un paso, ir al siguiente
354
+ tapTargets: [{
355
+ target : "MAP_CAMPO1",
356
+ title : "Paso 1",
357
+ description : "Descripción del primer paso",
358
+ cancelable : true,
359
+ transparentTarget : true,
360
+ targetRadius : 90,
361
+ outerCircleOpacity : 96,
362
+ outerCircleColor : "#1565C0",
363
+ targetCircleColor : "#FF0000",
364
+ dimColor : "#CC000000",
365
+ titleTextSize : 20,
366
+ descriptionTextSize : 15,
367
+ textColor : "#FFFFFF",
368
+ titleTextColor : "#FFFF00",
369
+ descriptionTextColor: "#FFFFFF",
370
+ textFont : "MiFuente.ttf",
371
+ drawShadow : true
372
+ }, {
373
+ target : "MAP_CAMPO2",
374
+ title : "Paso 2",
375
+ description: "Segundo paso del tutorial",
376
+ cancelable : true
377
+ }]
378
+ });
379
+ ```
380
+
381
+ ### 3.4 Date/Time Pickers
382
+
383
+ ```javascript
384
+ // Date Picker con callback
385
+ ui.showDatePicker({
386
+ initialYear : 2024,
387
+ initialMonth: 6,
388
+ initialDay : 15,
389
+ title : "Seleccione fecha",
390
+ theme : "holo_light", // Tema visual del picker
391
+ onDateSet : function(nYear, nMonth, nDay) {
392
+ self.MAP_FECHA = nDay + "/" + nMonth + "/" + nYear;
393
+ ui.refresh("MAP_FECHA");
394
+ }
395
+ });
396
+
397
+ // Date Picker que escribe directamente en un campo (sin callback)
398
+ ui.showDatePicker({
399
+ targetProperty: "MAP_FECHA" // El picker escribe aquí al confirmar
400
+ });
401
+
402
+ // Time Picker con callback
403
+ ui.showTimePicker({
404
+ initialHour : 17,
405
+ initialMinute: 30,
406
+ is24HoursMode: true,
407
+ title : "Seleccione hora",
408
+ theme : "holo_light",
409
+ onTimeSet : function(nHours, nMinutes) {
410
+ let h = ("0" + nHours).slice(-2);
411
+ let m = ("0" + nMinutes).slice(-2);
412
+ self.MAP_HORA = h + ":" + m;
413
+ ui.refresh("MAP_HORA");
414
+ }
415
+ });
416
+
417
+ // Time Picker que escribe directamente en un campo
418
+ ui.showTimePicker({
419
+ targetProperty: "MAP_HORA"
420
+ });
421
+ ```
422
+
@@ -0,0 +1,80 @@
1
+ # Resumen por capa: JavaScript, datos y dispositivo
2
+
3
+ > Referencia de `xone-development`. Sale del `SKILL.md` para que las reglas
4
+ > duras quepan en una lectura por omisión (100 líneas).
5
+
6
+ ## JavaScript
7
+
8
+ JavaScript ejecutado en bloques `<script>` de los `.xne` y en `functions.js`. No es JavaScript de navegador ni de Node: no hay módulos (`require`/`import`) y el código compartido es global. Los LLMs inventan sistemáticamente `self.lock()`, `ui.startChronometer()` y variantes de `setCircularReveal` que no existen.
9
+
10
+ **Objetos globales.** `self` (DataObject actual, alias `dataobject`) · `selfDataColl` (su colección, alias `datacollection`) · `ui` · `appData` (alias `appdata`) · `err` (alias `error`) · `user`.
11
+
12
+ Singletons de acceso directo, **sin `new`**: `$http`, `crypto`, `clipboard`, `deviceInfo`, `systemSettings`, `packageManager`, `biometricsManager`, `fingerprintManager`, `bleManager`, `sensorManager`, `paymentManager`, `pushMessage`, `appBroadcastManager`, `replica`, `live`, `smsService`, `serial`, `bluetoothSerial`, `bleSerial`, `ml`, `ai`.
13
+
14
+ Objetos que se crean con `new` (o `createObject`): `FileManager`, `GpsTools`, `SqlManager`, `IniParser`, `EncodingUtils`, `AndroidIntent`, `DeviceManager`, `WifiManager`, `BluetoothSerialPort`, `OAuth2`, `Worker`, `Animation`, `Socket`, `WebSocket`, `DebugTools`, `IrManager`, `SoundManager`, `VibrationManager`, `WearableConnection`, `AccountManager`, `XOneNFC`, `ImageDrawing`, `BarcodeGenerator`, `XOnePrinter`, `XOnePDF`, `XOneOCR`, `XOneSigner` y los demás de la lista canónica.
15
+
16
+ **Acceso a datos.** `self.CAMPO`, `self["CAMPO"]` y `self.getValue("CAMPO")` son válidos. **`self("CAMPO")` no existe**: la notación de `self` como función no es parte del motor.
17
+
18
+ **Controles.** `getControl(name, [dataObject])` es una **función nativa global** del motor (Rhino y V8), no un método de `ui`. Con un solo argumento usa la última ventana visible; con `dataObject`, la ventana asociada a ese objeto. Lanza error si el nombre está vacío, si el control no existe en la ventana destino, si no hay ventana o si el `dataObject` no es válido. Si el proyecto define su propia `function getControl(...)`, esa sombrea a la nativa en su ámbito local.
19
+
20
+ Los métodos específicos (`getValue`/`setValue`/`setMin`/`setMax`/`setStepSize` de un stepper, `getOtpValue`/`clearOtp`/`focusOtp` de un OTP, `startChronometer`/`stopChronometer`) son métodos **del control**, no de `ui`.
21
+
22
+ **Patrones críticos.** Modifica colecciones dentro de `unlock()` y devuelve el estado con `lock()` en `finally`. `lock()` activa el modo solo lectura: con la bandera activa, `clear()` y `loadAll()` son no-op. Las colecciones nacen desbloqueadas, pero el convenio es dejarlas bloqueadas tras operar para que código posterior no las mute por accidente.
23
+
24
+ - `lock()`/`unlock()` son métodos de la **colección**, nunca de `self`. Para bloquear la de un contents: `self.getContents("X").unlock()`.
25
+ - Navega con `startBrowse()` y `endBrowse()` en `finally`. Para contents: `getContents(nombre)` → `unlock` → `createObject`/`addItem` → `lock` → `saveAll`. Cierra siempre cursores y conexiones SQL. Un `WaitDialog` abierto va dentro de `try/finally`.
26
+ - En callbacks asíncronos (`$http`, WebSocket, GPS) guarda el contexto **antes** de la llamada: `var miSelf = self;`.
27
+ - Para crear objetos, el patrón preferido es `new NombreColeccion({ PROP: valor })` (el parámetro es opcional). `coll.createObject()` queda para contents anidados —vincula al padre— o cuando el nombre de la colección es dinámico.
28
+
29
+ **APIs web y sus equivalentes.**
30
+
31
+ | API web | Equivalente XOne |
32
+ |---|---|
33
+ | `document.getElementById("X")` | `ui.getView(self)["X"]` o `getControl("X")` |
34
+ | `window.location` / `window.history` | `ui.openEditView("Coll")`, `ui.getView(self).exit()` |
35
+ | `localStorage` | `appData.getGlobalMacro("##X##")` / `setGlobalMacro` |
36
+ | `sessionStorage` | `coll.setVariable`/`getVariable` o variables de empresa |
37
+ | `new XMLHttpRequest()` | `$http.get(url, request, success, error)` |
38
+ | `alert` / `confirm` / `prompt` | `ui.msgBox(msg, título, 0)` o `ui.showToast(msg)` |
39
+ | `navigator.geolocation.getCurrentPosition` | `ui.startGps({nodeName: "callbackgps"})` |
40
+ | `require()` / `import` | `<include file="..."/>` o `<script src="..."/>` en `<app>`; dinámico solo con `appData.loadIncludeFile(...)` |
41
+
42
+ ## Datos e integración
43
+
44
+ **Modelo local.** La BD es `gestion.db`, normalmente bajo `bd/`, y las tablas suelen llevar prefijo `gen_` en minúsculas. Usa siempre `##PREF##`, nunca el prefijo literal. Cada registro replicable tiene `ROWID` como GUID hexadecimal de 32 caracteres sin guiones, declarado `type="T" fieldsize="32"`. Las colecciones con `objname`/`updateobj` generan tabla; si falta, regenera con `python3 -m xone_db_generator mi_proyecto --overwrite`.
45
+
46
+ Macros habituales: `##PREF##`, `##ENTID##`, `##USERID##`, `##NOW##`, `##NOW_DATE##`, `##NOW_TIME##`, `##FLD_CAMPO##`. Guarda y restaura filtros con `try/finally` y limpia la colección antes de recargar.
47
+
48
+ **Seguridad.**
49
+
50
+ - Parametriza SQL: `sqlManager.doRawQuery("… WHERE ID=?", id)`. Nunca concatenes entrada de usuario. Si un filtro exige texto, escapa `'` como `''`; valida los numéricos antes de concatenar.
51
+ - Cierra cursor y conexión en `finally`.
52
+ - HTTPS siempre, con `allowUnsafeCertificates: false` en producción. Pinning con `enablePinning`/`allowedRootCas`; mTLS con `privateKey`/`certificateChain`.
53
+ - No hardcodees ni registres credenciales. Cifra los tokens antes de guardarlos en macros globales y límpialos al cerrar sesión.
54
+ - Valida obligatorios, longitud, rangos y formato antes de `save()`: un obligatorio vacío produce `-8100`.
55
+
56
+ **Integración y réplica.** `$http` devuelve respuestas string y futures cancelables: parsea con `try/catch`, preserva `self` antes del callback y cancela la búsqueda anterior antes de lanzar otra. OAuth2 se usa con `new OAuth2()`. `replica.processReplicatorQueue` sincroniza por `ROWID`; la configuración programada vive en el evento `maintenance` de `Empresas`. El error `-11888` con `##EXIT##` cierra la pantalla y con `##EXITAPP##` cierra la aplicación.
57
+
58
+ Para almacenamiento clave-valor, el equivalente de `localStorage` es `appData.setGlobalMacro`/`getGlobalMacro`; para datos de sesión, variables de colección (`setVariable`/`getVariable`).
59
+
60
+ Los **eventos** implicados en la sincronización y el provisionamiento (`maintenance`, `sys-message` con sus códigos detallados, eventos de réplica) están documentados en [eventos de sistema, login y personalizados](references/xml-ui/eventos-sistema-login-y-personalizados.md), porque se declaran en el XML.
61
+
62
+ Para probar integraciones sin backend, usa `mock/http.json` con `xone-simulator` (skill `xone-review`).
63
+
64
+ ## Dispositivo
65
+
66
+ `xone-simulator` reproduce muchas capacidades con `mock/device.json` (skill `xone-review`).
67
+
68
+ - Pide y comprueba permisos antes de GPS, cámara, micrófono o biometría. Los permisos se solicitan con `systemSettings.requestPermissions`, que devuelve un future. En el simulador se conceden automáticamente.
69
+ - Declara los permisos que use la app en el nodo `<permissions>`: `location-foreground`, `location-background`, `camera`, `notifications`, `contacts`…
70
+ - GPS: `ui.startGps()` antes de leer la colección de GPS; recórrela con `startBrowse`/`endBrowse`, comprueba `STATUS == 1` y que `LONGITUD` no esté vacío. `ui.checkGpsStatus()` devuelve `0` sin hardware, `1` solo GPS, `2` solo redes, `3` ninguno y `4` GPS y redes.
71
+ - La colección de GPS (`GPSColl`/`GpsCollection`) **la declara el proyecto** con el connector GPS: no es built-in de XOne.
72
+ - En callbacks de cámara, GPS y escáner conserva `self` antes de la operación y refresca solo los campos modificados.
73
+ - Cierra Bluetooth y WebSocket al terminar. Prefiere `ui.executeActionAfterDelay()` (segundos) a una espera bloqueante.
74
+ - `biometricsManager` es el singleton actual; `fingerprintManager` es legacy.
75
+ - La firma se hace con `<prop type="DR">` (`stroke-color`, `stroke-width`, `apply-format-to-file`, `ui.saveDrawing`, `ui.clearDrawing`). `type="IMG" readonly="false"` es la forma **obsoleta**.
76
+ - En archivos, comprueba `fileExists(...) === 0`; `saveFile(..., false)` sobrescribe.
77
+
78
+ Del registro de GPS se leen `LATITUD`, `LONGITUD`, `ALTITUD`, `VELOCIDAD`, `RUMBO`, `FGPS`, `HGPS`, `STATUS`, `SATELITES`, `FUENTE`, `PRECISION` y el campo `FAKE`. Para cálculos hay `GpsTools` (`distanceBetweenCoordinates`, `getPositionFromAddress`, encode/decode, `simplifyPolyline`, `addExifLocationToFile`, `routeTo`).
79
+
80
+ Los métodos de los controles de cámara, vídeo, dibujo y escáner están en [métodos de los controles](references/javascript/metodos-de-los-controles.md). Los atributos XML de esos props, en [atributos-prop.md](references/xml-ui/atributos-prop.md).
@@ -0,0 +1,74 @@
1
+ # Resumen por capa: XML y CSS
2
+
3
+ > Referencia de `xone-development`. Sale del `SKILL.md` para que las reglas
4
+ > duras quepan en una lectura por omisión (100 líneas).
5
+
6
+ ## Estructura XML
7
+
8
+ Capa declarativa de XOne: ficheros `.xne`, jerarquía `coll > group > frame > prop`, `contents`, macros, eventos y permisos. Antes de proponer código, inspecciona los `.xne` y el CSS del proyecto para respetar sus convenciones.
9
+
10
+ - Jerarquía: `coll > group > frame > prop`. Un `<prop>` vive dentro de un `<group>` o de un `<frame>`.
11
+ - Una coll de datos lleva `sql`, `objname` y `updateobj`, y usa `##PREF##` como prefijo de tabla: `sql="SELECT ID, NOMBRE FROM ##PREF##Clientes"`.
12
+ - Una pantalla sin datos (menú, login) usa `special="true"` y **no** lleva `sql`. Son excluyentes.
13
+ - `<prop>` tiene dos atributos obligatorios: `name` y `type`.
14
+ - `notab="true"` cuando solo hay un grupo visible.
15
+ - El splash es un **fichero estático en la raíz** (`splash.png`/`.jpg`/`.gif`/`.webp`/`.apng`/`.mp4`/`.3gp`) que carga el framework. No es una `<coll>`, no es `EntradaApp` (pantalla post-login), y no es `load-imgbk` del `<app>` (fondo del EditView).
16
+
17
+ **Combo y selector.** Un combo **no tiene tipo propio**: son dos props vinculados, uno oculto con el ID y otro visible con la descripción. Para valores fijos sin tabla, `mapcol-values` en el prop oculto. `mapcol` debe apuntar a una coll existente, y `mapfld`/`linkedfield` a campos reales de esa coll: `xone-simulator` lo valida.
18
+
19
+ **Contents y listas.**
20
+
21
+ - El `name` del contents lleva prefijo `@`; sin él no vincula.
22
+ - `src` es obligatorio y apunta a una coll existente. `filter` y `sort` son opcionales.
23
+ - Filtros dinámicos por el objeto padre con `##FLD_CAMPO##`, p. ej. `filter="IDPADRE=##FLD_IDPADRE##"`.
24
+ - Un mapa es `type="Z" viewmode="mapview"` vinculado a un `<contents>`, no un tipo inventado.
25
+
26
+ **Layout.** Los elementos son `newline="true"` por defecto y se apilan. Para ponerlos en la misma fila, `newline="false"` va en el **segundo y siguientes**; el primero de la fila nunca lo lleva. Si el primer elemento de un `<frame>` lleva `newline="false"`, el frame entero puede no montarse y sus controles desaparecen de la pantalla. Dimensiones en `p` o `%`, nunca `px`/`em`/`rem`.
27
+
28
+ **Macros.** `##PREF##` prefijo de tablas · `##FLD_CAMPO##` valor del campo del objeto padre en un contents · macros del sistema como `##NOW_TIME##`, `##USERID##`, `##DEVICE_OS##`, `##DEVICE_TYPE##`, `##CURRENT_ORIENTATION##`, `##FRAME_VERSION_CODE##`.
29
+
30
+ Una macro de colección debe declararse en el XML antes de usarla: `<macro name="##NOMBRE##" value="..." default="true" />` como hijo directo de `<coll>`, al mismo nivel que los `<group>`. Sin esa declaración, `setMacro` no inyecta nada en el SQL. La API es `setMacro`/`getMacro`; `coll.macro(...)` no existe.
31
+
32
+ ## CSS
33
+
34
+ Sistema de estilos propietario, con sintaxis parecida a CSS web pero atributos propios. Antes de editar, lee el `default.css` del proyecto y respeta sus convenciones de nombres de clase.
35
+
36
+ **Archivos.** `default.css` en la raíz del proyecto es obligatorio y es el único que se declara en `app.xml`: `<style url="default.css" encoding="UTF-8" />`. Las variantes se cargan automáticamente por convención de nombre.
37
+
38
+ Si el atributo `compatibility-mode` del nodo `<app>` vale `true`, **el CSS se ignora por completo** — compruébalo antes de diagnosticar cualquier estilo que «no se aplica».
39
+
40
+ > **El TEMA OSCURO está sin definir, y hasta que se defina no se genera.** El corpus escribe el
41
+ > nombre del fichero de variante de dos formas incompatibles —con guion bajo
42
+ > (`default_night.css`) y con punto (`default.night.css`)—, y en los proyectos reales de
43
+ > referencia no existe ninguno de los dos: lo que hay son variantes con guion normal
44
+ > (`default-ios.css`, `default-colors.css`). Como el framework carga estas variantes **por
45
+ > convención de nombre**, un nombre equivocado no da error: el fichero no se carga y la app
46
+ > se ve en claro sin que nada lo diga. **Decisión del proyecto (2026-08-29): no proponer ni
47
+ > generar el fichero de tema oscuro hasta fijar su nombre.** Los ejemplos de tema que quedan
48
+ > en las referencias de CSS ilustran la CASCADA, no el nombre — no los copies como ruta.
49
+
50
+ **Cascada.** De menor a mayor prioridad: `default.css` → plataforma → orientación → tema → condiciones combinadas → **atributos inline en XML** (máxima prioridad). Lo más específico gana atributo por atributo, no bloque por bloque.
51
+
52
+ **Selectores.** Solo estos: `coll`, `prop`, `prop:TYPE` (`prop:T`, `prop:N`, `prop:B`, `prop:NC`, `prop:Z`, `prop:IMG`, `prop:D`…), `group`, `frame` y `.clase`. Las clases se asignan con `class="..."` en el XML.
53
+
54
+ **Unidades.**
55
+
56
+ - `p` para dimensiones absolutas, `%` relativo al contenedor.
57
+ - Sin unidad: `fontsize`, `border-corner-radius`, `border-width`, `labelwidth`, `lines`, `visible`, `gallery-columns`, `img-width`, `img-height`.
58
+ - Prohibidas: `px`, `em`, `rem`, `vw`, `vh`, `vmin`, `vmax`.
59
+
60
+ **Colores.** `#RRGGBB` o ARGB `#AARRGGBB`. **El alpha va primero**, al contrario que el `#RRGGBBAA` de CSS web.
61
+
62
+ **Herencia.** Dos mecanismos equivalentes: el atributo `extends: .claseBase;` y la at-rule `@extend selector;`. Diferencia relevante: `@extend` detecta ciclos en tiempo de parseo (auto-referencia, 2 vías y N vías) y admite referencias adelantadas; `extends:` no detecta ciclos automáticamente. En un proyecto que ya usa `extends:`, mantén `extends:` por consistencia.
63
+
64
+ **Funciones del parser.**
65
+
66
+ **Sí soportadas:** comentarios `/* */` y `//`; `@import "ruta";` (solo al inicio del archivo); variables CSS en `:root` o locales de bloque, con `var(--nombre)` y `var(--nombre, fallback)`; `calc()` con `+ - * /`, paréntesis y `-` unario sobre números puros; `!important`; `!default`; selectores múltiples `a, b, c { }`.
67
+
68
+ **No soportadas:** `min()`, `max()`, `clamp()`, `@media`, pseudo-clases (`:hover`, `:focus`, `:active`, `:nth-child`), pseudo-elementos (`::before`, `::after`), selectores de atributo (`[data-attr]`), combinadores (`>`, `+`, `~`, descendiente), `transition`, `transform`, Flexbox, CSS Grid, `box-shadow`, `text-shadow` y gradientes.
69
+
70
+ Para sombras usa `elevation` y `shadow-color`. No hay abreviados `margin` ni `padding`: usa `tmargin`, `bmargin`, `lmargin`, `rmargin` y sus equivalentes `*padding`.
71
+
72
+ **Estilos dinámicos.** No existe selector condicional puro. Dos vías: tokens `##FLD_CAMPO##` en el valor (funcionan en CSS y en atributos inline XML) y cambio de clase desde JavaScript en tiempo de ejecución.
73
+
74
+ Si un estilo no se aplica, empieza por `compatibility-mode`; el resto de síntomas está en la skill `xone-debugging`.
@@ -0,0 +1,28 @@
1
+ # Tipos de `prop` válidos
2
+
3
+ > Referencia de `xone-development`. Sale del `SKILL.md` para que las reglas
4
+ > duras quepan en una lectura por omisión (100 líneas).
5
+
6
+ ## Tipos de prop válidos
7
+
8
+ | Tipo | Descripción |
9
+ |---|---|
10
+ | `T` | Texto editable |
11
+ | `TN` / `TN2`…`TN6` | Texto numérico; el sufijo son los decimales visibles |
12
+ | `L` | Etiqueta de solo lectura. Sin `title`, muestra el valor del campo |
13
+ | `TL` | Alias legacy de `L` |
14
+ | `THTML` | Texto con formato HTML |
15
+ | `N` / `N2`…`N6` | Número; el sufijo son los decimales visibles |
16
+ | `D` / `DT` / `TT` | Fecha / fecha y hora / solo hora |
17
+ | `B` | Botón |
18
+ | `NC` | Checkbox, toggle, radio o switch |
19
+ | `X` | Password enmascarado |
20
+ | `IMG` / `PH` | Imagen referenciada / foto capturable |
21
+ | `VD` | Vídeo o escáner QR/barcode |
22
+ | `DR` | Dibujo o firma digital |
23
+ | `Z` | Contenedor de lista embebida |
24
+ | `WEB` | WebView |
25
+ | `AT` | Adjunto |
26
+ | `O` | Sub-objeto JavaScript, no persiste |
27
+
28
+ Los combos **no tienen tipo propio**: se hacen con `type="T"` (o `type="N"`) más `mapcol` y `mapfld`. No existen `type="C"`, `"M"`, `"A"`, `"F"`, `"S"`, `"P"`, `"E"`, `"R"`, `"H"`, `"W"`, `"CAM"`, `"ARRAY"`, `"STRING"`, `"N1"` ni `"BT"`.