@acvl/mobile-components 0.0.0-stage → 0.0.2

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 (322) hide show
  1. package/README.md +147 -2
  2. package/assets/fonts/Inter_400Regular.ttf +0 -0
  3. package/assets/fonts/Inter_500Medium.ttf +0 -0
  4. package/assets/fonts/Inter_600SemiBold.ttf +0 -0
  5. package/assets/fonts/Inter_700Bold.ttf +0 -0
  6. package/assets/fonts/Inter_800ExtraBold.ttf +0 -0
  7. package/assets/fonts/Inter_900Black.ttf +0 -0
  8. package/assets/fonts/OFL.txt +93 -0
  9. package/lib/module/camara/CampoDeFotos.js +124 -0
  10. package/lib/module/camara/CampoDeFotos.js.map +1 -0
  11. package/lib/module/camara/elegir.js +104 -0
  12. package/lib/module/camara/elegir.js.map +1 -0
  13. package/lib/module/camara/index.js +10 -0
  14. package/lib/module/camara/index.js.map +1 -0
  15. package/lib/module/camara/reducir.js +93 -0
  16. package/lib/module/camara/reducir.js.map +1 -0
  17. package/lib/module/componentes/AccionesDelEncabezado.js +212 -0
  18. package/lib/module/componentes/AccionesDelEncabezado.js.map +1 -0
  19. package/lib/module/componentes/BotonDeAvatar.js +55 -0
  20. package/lib/module/componentes/BotonDeAvatar.js.map +1 -0
  21. package/lib/module/componentes/BotonGrande.js +105 -0
  22. package/lib/module/componentes/BotonGrande.js.map +1 -0
  23. package/lib/module/componentes/CabeceraEmpujada.js +101 -0
  24. package/lib/module/componentes/CabeceraEmpujada.js.map +1 -0
  25. package/lib/module/componentes/Chip.js +77 -0
  26. package/lib/module/componentes/Chip.js.map +1 -0
  27. package/lib/module/componentes/ContenidoDePantalla.js +56 -0
  28. package/lib/module/componentes/ContenidoDePantalla.js.map +1 -0
  29. package/lib/module/componentes/EstadoVacio.js +65 -0
  30. package/lib/module/componentes/EstadoVacio.js.map +1 -0
  31. package/lib/module/componentes/Foto.js +106 -0
  32. package/lib/module/componentes/Foto.js.map +1 -0
  33. package/lib/module/componentes/IconoDeRenglon.js +44 -0
  34. package/lib/module/componentes/IconoDeRenglon.js.map +1 -0
  35. package/lib/module/componentes/Logo.js +44 -0
  36. package/lib/module/componentes/Logo.js.map +1 -0
  37. package/lib/module/componentes/Nota.js +51 -0
  38. package/lib/module/componentes/Nota.js.map +1 -0
  39. package/lib/module/componentes/OpcionesExcluyentes.js +69 -0
  40. package/lib/module/componentes/OpcionesExcluyentes.js.map +1 -0
  41. package/lib/module/componentes/PantallaDeError.js +84 -0
  42. package/lib/module/componentes/PantallaDeError.js.map +1 -0
  43. package/lib/module/componentes/Pestanas.js +87 -0
  44. package/lib/module/componentes/Pestanas.js.map +1 -0
  45. package/lib/module/componentes/Rotulo.js +28 -0
  46. package/lib/module/componentes/Rotulo.js.map +1 -0
  47. package/lib/module/componentes/RotuloDeSeccion.js +87 -0
  48. package/lib/module/componentes/RotuloDeSeccion.js.map +1 -0
  49. package/lib/module/componentes/Tarjeta.js +63 -0
  50. package/lib/module/componentes/Tarjeta.js.map +1 -0
  51. package/lib/module/componentes/TarjetaDeDatos.js +79 -0
  52. package/lib/module/componentes/TarjetaDeDatos.js.map +1 -0
  53. package/lib/module/componentes/TiraDeFotos.js +184 -0
  54. package/lib/module/componentes/TiraDeFotos.js.map +1 -0
  55. package/lib/module/componentes/VisorDeFoto.js +171 -0
  56. package/lib/module/componentes/VisorDeFoto.js.map +1 -0
  57. package/lib/module/componentes/logos/bola-blanca.png +0 -0
  58. package/lib/module/componentes/logos/bola.png +0 -0
  59. package/lib/module/componentes/logos/logo-blanco.png +0 -0
  60. package/lib/module/componentes/logos/logo.png +0 -0
  61. package/lib/module/dialogos/HostDeDialogos.js +170 -0
  62. package/lib/module/dialogos/HostDeDialogos.js.map +1 -0
  63. package/lib/module/dialogos/dialogos.js +112 -0
  64. package/lib/module/dialogos/dialogos.js.map +1 -0
  65. package/lib/module/formularios/CampoDeSeleccion.js +72 -0
  66. package/lib/module/formularios/CampoDeSeleccion.js.map +1 -0
  67. package/lib/module/formularios/SelectorDeOpcion.js +406 -0
  68. package/lib/module/formularios/SelectorDeOpcion.js.map +1 -0
  69. package/lib/module/formularios/TextoDeAccesoControlado.js +73 -0
  70. package/lib/module/formularios/TextoDeAccesoControlado.js.map +1 -0
  71. package/lib/module/formularios/campos.js +501 -0
  72. package/lib/module/formularios/campos.js.map +1 -0
  73. package/lib/module/formularios/controlados.js +199 -0
  74. package/lib/module/formularios/controlados.js.map +1 -0
  75. package/lib/module/formularios/errores.js +91 -0
  76. package/lib/module/formularios/errores.js.map +1 -0
  77. package/lib/module/formularios/guardado.js +78 -0
  78. package/lib/module/formularios/guardado.js.map +1 -0
  79. package/lib/module/formularios/useBusqueda.js +22 -0
  80. package/lib/module/formularios/useBusqueda.js.map +1 -0
  81. package/lib/module/fotos/elegir.js +105 -0
  82. package/lib/module/fotos/elegir.js.map +1 -0
  83. package/lib/module/fotos/index.js +9 -0
  84. package/lib/module/fotos/index.js.map +1 -0
  85. package/lib/module/hoja/HojaDeLista.js +211 -0
  86. package/lib/module/hoja/HojaDeLista.js.map +1 -0
  87. package/lib/module/hoja/HojaInferior.js +112 -0
  88. package/lib/module/hoja/HojaInferior.js.map +1 -0
  89. package/lib/module/hoja/index.js +8 -0
  90. package/lib/module/hoja/index.js.map +1 -0
  91. package/lib/module/hoja/useMasDeLaFicha.js +48 -0
  92. package/lib/module/hoja/useMasDeLaFicha.js.map +1 -0
  93. package/lib/module/index.js +67 -0
  94. package/lib/module/index.js.map +1 -0
  95. package/lib/module/listas/HojaDeFiltros.js +270 -0
  96. package/lib/module/listas/HojaDeFiltros.js.map +1 -0
  97. package/lib/module/listas/ListaPaginada.js +103 -0
  98. package/lib/module/listas/ListaPaginada.js.map +1 -0
  99. package/lib/module/listas/TarjetaDeslizable.js +118 -0
  100. package/lib/module/listas/TarjetaDeslizable.js.map +1 -0
  101. package/lib/module/listas/paginado.js +11 -0
  102. package/lib/module/listas/paginado.js.map +1 -0
  103. package/lib/module/listas/piezas.js +666 -0
  104. package/lib/module/listas/piezas.js.map +1 -0
  105. package/lib/module/navegacion/BarraDePestanas.js +162 -0
  106. package/lib/module/navegacion/BarraDePestanas.js.map +1 -0
  107. package/lib/module/navegacion/BotonDeBarra.js +58 -0
  108. package/lib/module/navegacion/BotonDeBarra.js.map +1 -0
  109. package/lib/module/navegacion/encabezado.js +103 -0
  110. package/lib/module/navegacion/encabezado.js.map +1 -0
  111. package/lib/module/pantallas/PantallaDeAcceso.js +195 -0
  112. package/lib/module/pantallas/PantallaDeAcceso.js.map +1 -0
  113. package/lib/module/pantallas/PantallaDeEdicion.js +121 -0
  114. package/lib/module/pantallas/PantallaDeEdicion.js.map +1 -0
  115. package/lib/module/pantallas/PantallaDeFicha.js +94 -0
  116. package/lib/module/pantallas/PantallaDeFicha.js.map +1 -0
  117. package/lib/module/pantallas/PantallaDeHistorial.js +328 -0
  118. package/lib/module/pantallas/PantallaDeHistorial.js.map +1 -0
  119. package/lib/module/pantallas/PantallaDePerfil.js +137 -0
  120. package/lib/module/pantallas/PantallaDePerfil.js.map +1 -0
  121. package/lib/module/tema/ProveedorDeTema.js +122 -0
  122. package/lib/module/tema/ProveedorDeTema.js.map +1 -0
  123. package/lib/module/tema/estilos.js +54 -0
  124. package/lib/module/tema/estilos.js.map +1 -0
  125. package/lib/module/tema/fuentes.js +28 -0
  126. package/lib/module/tema/fuentes.js.map +1 -0
  127. package/lib/module/tema/index.js +8 -0
  128. package/lib/module/tema/index.js.map +1 -0
  129. package/lib/module/tema/paleta.js +107 -0
  130. package/lib/module/tema/paleta.js.map +1 -0
  131. package/lib/module/tema/tipografia.js +32 -0
  132. package/lib/module/tema/tipografia.js.map +1 -0
  133. package/lib/module/texto.js +48 -0
  134. package/lib/module/texto.js.map +1 -0
  135. package/lib/typescript/src/camara/CampoDeFotos.d.ts +30 -0
  136. package/lib/typescript/src/camara/CampoDeFotos.d.ts.map +1 -0
  137. package/lib/typescript/src/camara/elegir.d.ts +47 -0
  138. package/lib/typescript/src/camara/elegir.d.ts.map +1 -0
  139. package/lib/typescript/src/camara/index.d.ts +4 -0
  140. package/lib/typescript/src/camara/index.d.ts.map +1 -0
  141. package/lib/typescript/src/camara/reducir.d.ts +32 -0
  142. package/lib/typescript/src/camara/reducir.d.ts.map +1 -0
  143. package/lib/typescript/src/componentes/AccionesDelEncabezado.d.ts +34 -0
  144. package/lib/typescript/src/componentes/AccionesDelEncabezado.d.ts.map +1 -0
  145. package/lib/typescript/src/componentes/BotonDeAvatar.d.ts +17 -0
  146. package/lib/typescript/src/componentes/BotonDeAvatar.d.ts.map +1 -0
  147. package/lib/typescript/src/componentes/BotonGrande.d.ts +26 -0
  148. package/lib/typescript/src/componentes/BotonGrande.d.ts.map +1 -0
  149. package/lib/typescript/src/componentes/CabeceraEmpujada.d.ts +18 -0
  150. package/lib/typescript/src/componentes/CabeceraEmpujada.d.ts.map +1 -0
  151. package/lib/typescript/src/componentes/Chip.d.ts +14 -0
  152. package/lib/typescript/src/componentes/Chip.d.ts.map +1 -0
  153. package/lib/typescript/src/componentes/ContenidoDePantalla.d.ts +17 -0
  154. package/lib/typescript/src/componentes/ContenidoDePantalla.d.ts.map +1 -0
  155. package/lib/typescript/src/componentes/EstadoVacio.d.ts +17 -0
  156. package/lib/typescript/src/componentes/EstadoVacio.d.ts.map +1 -0
  157. package/lib/typescript/src/componentes/Foto.d.ts +41 -0
  158. package/lib/typescript/src/componentes/Foto.d.ts.map +1 -0
  159. package/lib/typescript/src/componentes/IconoDeRenglon.d.ts +25 -0
  160. package/lib/typescript/src/componentes/IconoDeRenglon.d.ts.map +1 -0
  161. package/lib/typescript/src/componentes/Logo.d.ts +13 -0
  162. package/lib/typescript/src/componentes/Logo.d.ts.map +1 -0
  163. package/lib/typescript/src/componentes/Nota.d.ts +7 -0
  164. package/lib/typescript/src/componentes/Nota.d.ts.map +1 -0
  165. package/lib/typescript/src/componentes/OpcionesExcluyentes.d.ts +14 -0
  166. package/lib/typescript/src/componentes/OpcionesExcluyentes.d.ts.map +1 -0
  167. package/lib/typescript/src/componentes/PantallaDeError.d.ts +23 -0
  168. package/lib/typescript/src/componentes/PantallaDeError.d.ts.map +1 -0
  169. package/lib/typescript/src/componentes/Pestanas.d.ts +28 -0
  170. package/lib/typescript/src/componentes/Pestanas.d.ts.map +1 -0
  171. package/lib/typescript/src/componentes/Rotulo.d.ts +6 -0
  172. package/lib/typescript/src/componentes/Rotulo.d.ts.map +1 -0
  173. package/lib/typescript/src/componentes/RotuloDeSeccion.d.ts +20 -0
  174. package/lib/typescript/src/componentes/RotuloDeSeccion.d.ts.map +1 -0
  175. package/lib/typescript/src/componentes/Tarjeta.d.ts +25 -0
  176. package/lib/typescript/src/componentes/Tarjeta.d.ts.map +1 -0
  177. package/lib/typescript/src/componentes/TarjetaDeDatos.d.ts +13 -0
  178. package/lib/typescript/src/componentes/TarjetaDeDatos.d.ts.map +1 -0
  179. package/lib/typescript/src/componentes/TiraDeFotos.d.ts +36 -0
  180. package/lib/typescript/src/componentes/TiraDeFotos.d.ts.map +1 -0
  181. package/lib/typescript/src/componentes/VisorDeFoto.d.ts +23 -0
  182. package/lib/typescript/src/componentes/VisorDeFoto.d.ts.map +1 -0
  183. package/lib/typescript/src/dialogos/HostDeDialogos.d.ts +14 -0
  184. package/lib/typescript/src/dialogos/HostDeDialogos.d.ts.map +1 -0
  185. package/lib/typescript/src/dialogos/dialogos.d.ts +65 -0
  186. package/lib/typescript/src/dialogos/dialogos.d.ts.map +1 -0
  187. package/lib/typescript/src/formularios/CampoDeSeleccion.d.ts +24 -0
  188. package/lib/typescript/src/formularios/CampoDeSeleccion.d.ts.map +1 -0
  189. package/lib/typescript/src/formularios/SelectorDeOpcion.d.ts +59 -0
  190. package/lib/typescript/src/formularios/SelectorDeOpcion.d.ts.map +1 -0
  191. package/lib/typescript/src/formularios/TextoDeAccesoControlado.d.ts +18 -0
  192. package/lib/typescript/src/formularios/TextoDeAccesoControlado.d.ts.map +1 -0
  193. package/lib/typescript/src/formularios/campos.d.ts +113 -0
  194. package/lib/typescript/src/formularios/campos.d.ts.map +1 -0
  195. package/lib/typescript/src/formularios/controlados.d.ts +29 -0
  196. package/lib/typescript/src/formularios/controlados.d.ts.map +1 -0
  197. package/lib/typescript/src/formularios/errores.d.ts +36 -0
  198. package/lib/typescript/src/formularios/errores.d.ts.map +1 -0
  199. package/lib/typescript/src/formularios/guardado.d.ts +36 -0
  200. package/lib/typescript/src/formularios/guardado.d.ts.map +1 -0
  201. package/lib/typescript/src/formularios/useBusqueda.d.ts +7 -0
  202. package/lib/typescript/src/formularios/useBusqueda.d.ts.map +1 -0
  203. package/lib/typescript/src/fotos/elegir.d.ts +28 -0
  204. package/lib/typescript/src/fotos/elegir.d.ts.map +1 -0
  205. package/lib/typescript/src/fotos/index.d.ts +3 -0
  206. package/lib/typescript/src/fotos/index.d.ts.map +1 -0
  207. package/lib/typescript/src/hoja/HojaDeLista.d.ts +50 -0
  208. package/lib/typescript/src/hoja/HojaDeLista.d.ts.map +1 -0
  209. package/lib/typescript/src/hoja/HojaInferior.d.ts +21 -0
  210. package/lib/typescript/src/hoja/HojaInferior.d.ts.map +1 -0
  211. package/lib/typescript/src/hoja/index.d.ts +4 -0
  212. package/lib/typescript/src/hoja/index.d.ts.map +1 -0
  213. package/lib/typescript/src/hoja/useMasDeLaFicha.d.ts +27 -0
  214. package/lib/typescript/src/hoja/useMasDeLaFicha.d.ts.map +1 -0
  215. package/lib/typescript/src/index.d.ts +46 -0
  216. package/lib/typescript/src/index.d.ts.map +1 -0
  217. package/lib/typescript/src/listas/HojaDeFiltros.d.ts +76 -0
  218. package/lib/typescript/src/listas/HojaDeFiltros.d.ts.map +1 -0
  219. package/lib/typescript/src/listas/ListaPaginada.d.ts +39 -0
  220. package/lib/typescript/src/listas/ListaPaginada.d.ts.map +1 -0
  221. package/lib/typescript/src/listas/TarjetaDeslizable.d.ts +33 -0
  222. package/lib/typescript/src/listas/TarjetaDeslizable.d.ts.map +1 -0
  223. package/lib/typescript/src/listas/paginado.d.ts +16 -0
  224. package/lib/typescript/src/listas/paginado.d.ts.map +1 -0
  225. package/lib/typescript/src/listas/piezas.d.ts +157 -0
  226. package/lib/typescript/src/listas/piezas.d.ts.map +1 -0
  227. package/lib/typescript/src/navegacion/BarraDePestanas.d.ts +57 -0
  228. package/lib/typescript/src/navegacion/BarraDePestanas.d.ts.map +1 -0
  229. package/lib/typescript/src/navegacion/BotonDeBarra.d.ts +15 -0
  230. package/lib/typescript/src/navegacion/BotonDeBarra.d.ts.map +1 -0
  231. package/lib/typescript/src/navegacion/encabezado.d.ts +44 -0
  232. package/lib/typescript/src/navegacion/encabezado.d.ts.map +1 -0
  233. package/lib/typescript/src/pantallas/PantallaDeAcceso.d.ts +32 -0
  234. package/lib/typescript/src/pantallas/PantallaDeAcceso.d.ts.map +1 -0
  235. package/lib/typescript/src/pantallas/PantallaDeEdicion.d.ts +38 -0
  236. package/lib/typescript/src/pantallas/PantallaDeEdicion.d.ts.map +1 -0
  237. package/lib/typescript/src/pantallas/PantallaDeFicha.d.ts +35 -0
  238. package/lib/typescript/src/pantallas/PantallaDeFicha.d.ts.map +1 -0
  239. package/lib/typescript/src/pantallas/PantallaDeHistorial.d.ts +65 -0
  240. package/lib/typescript/src/pantallas/PantallaDeHistorial.d.ts.map +1 -0
  241. package/lib/typescript/src/pantallas/PantallaDePerfil.d.ts +19 -0
  242. package/lib/typescript/src/pantallas/PantallaDePerfil.d.ts.map +1 -0
  243. package/lib/typescript/src/tema/ProveedorDeTema.d.ts +32 -0
  244. package/lib/typescript/src/tema/ProveedorDeTema.d.ts.map +1 -0
  245. package/lib/typescript/src/tema/estilos.d.ts +31 -0
  246. package/lib/typescript/src/tema/estilos.d.ts.map +1 -0
  247. package/lib/typescript/src/tema/fuentes.d.ts +20 -0
  248. package/lib/typescript/src/tema/fuentes.d.ts.map +1 -0
  249. package/lib/typescript/src/tema/index.d.ts +6 -0
  250. package/lib/typescript/src/tema/index.d.ts.map +1 -0
  251. package/lib/typescript/src/tema/paleta.d.ts +86 -0
  252. package/lib/typescript/src/tema/paleta.d.ts.map +1 -0
  253. package/lib/typescript/src/tema/tipografia.d.ts +29 -0
  254. package/lib/typescript/src/tema/tipografia.d.ts.map +1 -0
  255. package/lib/typescript/src/texto.d.ts +16 -0
  256. package/lib/typescript/src/texto.d.ts.map +1 -0
  257. package/package.json +140 -5
  258. package/src/camara/CampoDeFotos.tsx +132 -0
  259. package/src/camara/elegir.ts +113 -0
  260. package/src/camara/index.ts +15 -0
  261. package/src/camara/reducir.ts +87 -0
  262. package/src/componentes/AccionesDelEncabezado.tsx +247 -0
  263. package/src/componentes/BotonDeAvatar.tsx +59 -0
  264. package/src/componentes/BotonGrande.tsx +100 -0
  265. package/src/componentes/CabeceraEmpujada.tsx +69 -0
  266. package/src/componentes/Chip.tsx +60 -0
  267. package/src/componentes/ContenidoDePantalla.tsx +53 -0
  268. package/src/componentes/EstadoVacio.tsx +45 -0
  269. package/src/componentes/Foto.tsx +92 -0
  270. package/src/componentes/IconoDeRenglon.tsx +42 -0
  271. package/src/componentes/Logo.tsx +34 -0
  272. package/src/componentes/Nota.tsx +37 -0
  273. package/src/componentes/OpcionesExcluyentes.tsx +62 -0
  274. package/src/componentes/PantallaDeError.tsx +76 -0
  275. package/src/componentes/Pestanas.tsx +86 -0
  276. package/src/componentes/Rotulo.tsx +21 -0
  277. package/src/componentes/RotuloDeSeccion.tsx +71 -0
  278. package/src/componentes/Tarjeta.tsx +58 -0
  279. package/src/componentes/TarjetaDeDatos.tsx +62 -0
  280. package/src/componentes/TiraDeFotos.tsx +189 -0
  281. package/src/componentes/VisorDeFoto.tsx +181 -0
  282. package/src/componentes/logos/bola-blanca.png +0 -0
  283. package/src/componentes/logos/bola.png +0 -0
  284. package/src/componentes/logos/logo-blanco.png +0 -0
  285. package/src/componentes/logos/logo.png +0 -0
  286. package/src/dialogos/HostDeDialogos.tsx +172 -0
  287. package/src/dialogos/dialogos.ts +148 -0
  288. package/src/formularios/CampoDeSeleccion.tsx +60 -0
  289. package/src/formularios/SelectorDeOpcion.tsx +407 -0
  290. package/src/formularios/TextoDeAccesoControlado.tsx +72 -0
  291. package/src/formularios/campos.tsx +497 -0
  292. package/src/formularios/controlados.tsx +200 -0
  293. package/src/formularios/errores.ts +105 -0
  294. package/src/formularios/guardado.ts +76 -0
  295. package/src/formularios/useBusqueda.ts +19 -0
  296. package/src/fotos/elegir.ts +116 -0
  297. package/src/fotos/index.ts +6 -0
  298. package/src/hoja/HojaDeLista.tsx +214 -0
  299. package/src/hoja/HojaInferior.tsx +103 -0
  300. package/src/hoja/index.ts +5 -0
  301. package/src/hoja/useMasDeLaFicha.tsx +63 -0
  302. package/src/index.ts +151 -0
  303. package/src/listas/HojaDeFiltros.tsx +286 -0
  304. package/src/listas/ListaPaginada.tsx +117 -0
  305. package/src/listas/TarjetaDeslizable.tsx +126 -0
  306. package/src/listas/paginado.ts +15 -0
  307. package/src/listas/piezas.tsx +670 -0
  308. package/src/navegacion/BarraDePestanas.tsx +198 -0
  309. package/src/navegacion/BotonDeBarra.tsx +61 -0
  310. package/src/navegacion/encabezado.tsx +88 -0
  311. package/src/pantallas/PantallaDeAcceso.tsx +184 -0
  312. package/src/pantallas/PantallaDeEdicion.tsx +116 -0
  313. package/src/pantallas/PantallaDeFicha.tsx +115 -0
  314. package/src/pantallas/PantallaDeHistorial.tsx +293 -0
  315. package/src/pantallas/PantallaDePerfil.tsx +126 -0
  316. package/src/tema/ProveedorDeTema.tsx +150 -0
  317. package/src/tema/estilos.ts +51 -0
  318. package/src/tema/fuentes.ts +20 -0
  319. package/src/tema/index.ts +10 -0
  320. package/src/tema/paleta.ts +147 -0
  321. package/src/tema/tipografia.ts +29 -0
  322. package/src/texto.tsx +44 -0
@@ -0,0 +1,407 @@
1
+ import MaterialIcons from "@expo/vector-icons/MaterialIcons";
2
+ import React from "react";
3
+ import {
4
+ ActivityIndicator,
5
+ FlatList,
6
+ Modal,
7
+ Pressable,
8
+ TouchableOpacity,
9
+ View,
10
+ } from "react-native";
11
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
12
+ import BotonGrande from "../componentes/BotonGrande";
13
+ import EstadoVacio from "../componentes/EstadoVacio";
14
+ import IconoDeRenglon from "../componentes/IconoDeRenglon";
15
+ import { crearEstilos, renglon, tipografia, usePaleta } from "../tema";
16
+ import { Text, TextInput } from "../texto";
17
+
18
+ /** Una opción de una lista: lo que se guarda (`value`) y lo que se lee (`label`). */
19
+ export interface Opcion {
20
+ value: number | string;
21
+ label: string;
22
+ }
23
+
24
+ /** Lo que tienen en común el selector de una y el de varias: de dónde salen las opciones. */
25
+ interface FuenteDeOpciones<T extends Opcion> {
26
+ etiqueta: string;
27
+ opciones: T[];
28
+ /**
29
+ * Si las opciones las trae el servidor, mientras llegan. Una lista fija (las modalidades, los
30
+ * estados) no lo pasa.
31
+ */
32
+ cargando?: boolean;
33
+ /**
34
+ * El texto de la búsqueda, para que quien llama pida al servidor. **Sin `onBuscar` la lista es
35
+ * fija** y se filtra aquí, por lo que se lee: así una lista de cinco opciones no necesita una
36
+ * consulta ni un estado en la pantalla.
37
+ */
38
+ texto?: string;
39
+ onBuscar?: (texto: string) => void;
40
+ /** Lo que va debajo del nombre de cada opción (un viaje: sus unidades). */
41
+ detalle?: (opcion: T) => string | null;
42
+ /** Para agrupar las opciones con un rótulo (los viajes esperados primero). */
43
+ grupo?: (opcion: T) => string;
44
+ vacio?: string;
45
+ disabled?: boolean;
46
+ }
47
+
48
+ export interface PropsDeSelectorDeOpcion<T extends Opcion> extends FuenteDeOpciones<T> {
49
+ valor: T | null;
50
+ onElegir: (opcion: T | null) => void;
51
+ /** Si se puede dejar vacío: agrega «Ninguno» arriba de la lista. */
52
+ opcional?: boolean;
53
+ /** Cómo se dice el vacío de `opcional`: «Todos» en un filtro. */
54
+ textoDeNinguno?: string;
55
+ }
56
+
57
+ export interface PropsDeSelectorDeVarias<T extends Opcion> extends FuenteDeOpciones<T> {
58
+ valor: T[];
59
+ onElegir: (opciones: T[]) => void;
60
+ }
61
+
62
+ /** Para comparar lo escrito con una opción sin que estorben los acentos ni las mayúsculas. */
63
+ const normalizar = (texto: string) =>
64
+ texto.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase().trim();
65
+
66
+ /**
67
+ * La búsqueda de un selector: la de quien llama si trae `onBuscar`, o una propia que filtra la
68
+ * lista fija aquí mismo.
69
+ */
70
+ function useBuscador<T extends Opcion>({ opciones, texto, onBuscar }: FuenteDeOpciones<T>) {
71
+ const [propio, setPropio] = React.useState("");
72
+ const fija = !onBuscar;
73
+ const actual = fija ? propio : (texto ?? "");
74
+ const visibles = React.useMemo(() => {
75
+ if (!fija || !propio.trim()) return opciones;
76
+ const buscado = normalizar(propio);
77
+ return opciones.filter((opcion) => normalizar(opcion.label).includes(buscado));
78
+ }, [fija, propio, opciones]);
79
+ return {
80
+ texto: actual,
81
+ buscar: fija ? setPropio : onBuscar,
82
+ visibles,
83
+ };
84
+ }
85
+
86
+ /**
87
+ * La lista a pantalla completa de los dos selectores: la cabecera con la flecha, el buscador, y
88
+ * las opciones como tarjetas. Lo que pasa al tocar una —elegirla y cerrar, o marcarla— y lo que
89
+ * va al pie es de cada selector.
90
+ */
91
+ function HojaDeOpciones<T extends Opcion>({
92
+ etiqueta,
93
+ abierto,
94
+ onCerrar,
95
+ texto,
96
+ onBuscar,
97
+ cargando,
98
+ opciones,
99
+ marcada,
100
+ onTocar,
101
+ detalle,
102
+ grupo,
103
+ vacio = "Nada que coincida.",
104
+ encabezado,
105
+ pie,
106
+ }: {
107
+ etiqueta: string;
108
+ abierto: boolean;
109
+ onCerrar: () => void;
110
+ texto: string;
111
+ onBuscar: (texto: string) => void;
112
+ cargando?: boolean;
113
+ opciones: T[];
114
+ marcada: (opcion: T) => boolean;
115
+ onTocar: (opcion: T) => void;
116
+ detalle?: (opcion: T) => string | null;
117
+ grupo?: (opcion: T) => string;
118
+ vacio?: string;
119
+ encabezado?: React.ReactElement | null;
120
+ pie?: React.ReactNode;
121
+ }) {
122
+ const c = usePaleta();
123
+ const styles = useStyles();
124
+ const insets = useSafeAreaInsets();
125
+
126
+ return (
127
+ <Modal visible={abierto} animationType="slide" onRequestClose={onCerrar}>
128
+ <View style={[styles.hoja, { paddingTop: insets.top + 10 }]}>
129
+ <View style={styles.cabecera}>
130
+ <TouchableOpacity onPress={onCerrar}>
131
+ <MaterialIcons name="arrow-back" size={45} color={c.primary} />
132
+ </TouchableOpacity>
133
+ <Text style={styles.titulo}>{etiqueta}</Text>
134
+ </View>
135
+ <TextInput
136
+ value={texto}
137
+ onChangeText={onBuscar}
138
+ placeholder="Buscar"
139
+ placeholderTextColor={c.secondaryLight}
140
+ autoCorrect={false}
141
+ autoCapitalize="characters"
142
+ style={styles.buscador}
143
+ />
144
+ {cargando ? <ActivityIndicator color={c.primary} /> : null}
145
+ <FlatList
146
+ data={opciones}
147
+ keyExtractor={(opcion) => String(opcion.value)}
148
+ keyboardShouldPersistTaps="handled"
149
+ contentContainerStyle={{
150
+ gap: 10,
151
+ paddingBottom: pie ? 24 : insets.bottom + 24,
152
+ }}
153
+ ListHeaderComponent={encabezado}
154
+ ListEmptyComponent={
155
+ cargando ? null : <EstadoVacio icono="magnify" titulo={vacio} />
156
+ }
157
+ renderItem={({ item, index }) => {
158
+ const rotulo = grupo?.(item);
159
+ const nuevoGrupo =
160
+ rotulo !== undefined &&
161
+ (index === 0 || grupo?.(opciones[index - 1]) !== rotulo);
162
+ const elegida = marcada(item);
163
+ return (
164
+ <>
165
+ {nuevoGrupo ? <Text style={styles.grupo}>{rotulo}</Text> : null}
166
+ <Pressable
167
+ onPress={() => onTocar(item)}
168
+ accessibilityState={{ selected: elegida }}
169
+ style={[styles.opcion, elegida && styles.opcionElegida]}
170
+ >
171
+ <Text style={styles.opcionNombre}>{item.label}</Text>
172
+ {detalle?.(item) ? (
173
+ <Text style={styles.detalle}>{detalle(item)}</Text>
174
+ ) : null}
175
+ </Pressable>
176
+ </>
177
+ );
178
+ }}
179
+ />
180
+ {pie ? (
181
+ <View style={[styles.pie, { paddingBottom: insets.bottom + 16 }]}>{pie}</View>
182
+ ) : null}
183
+ </View>
184
+ </Modal>
185
+ );
186
+ }
187
+
188
+ /** El renglón cerrado de un selector: el rótulo, lo elegido y la flecha. */
189
+ function RenglonDelSelector({
190
+ etiqueta,
191
+ texto,
192
+ detalle,
193
+ disabled,
194
+ onPress,
195
+ }: {
196
+ etiqueta: string;
197
+ texto: string | null;
198
+ detalle?: string | null;
199
+ disabled?: boolean;
200
+ onPress: () => void;
201
+ }) {
202
+ const c = usePaleta();
203
+ const styles = useStyles();
204
+ return (
205
+ <Pressable
206
+ onPress={onPress}
207
+ disabled={disabled}
208
+ accessibilityRole="button"
209
+ style={[styles.campo, disabled && styles.campoInactivo]}
210
+ >
211
+ <Text style={styles.etiqueta}>{etiqueta}</Text>
212
+ <View style={styles.renglon}>
213
+ <Text style={[styles.valor, !texto && styles.sinValor]}>{texto ?? "Elegir…"}</Text>
214
+ <IconoDeRenglon
215
+ name="chevron-down"
216
+ fontSize={tipografia.subtitulo}
217
+ color={c.secondary}
218
+ />
219
+ </View>
220
+ {detalle ? <Text style={styles.detalle}>{detalle}</Text> : null}
221
+ </Pressable>
222
+ );
223
+ }
224
+
225
+ /**
226
+ * Un campo que se elige de una lista: el renglón con lo elegido y, al tocarlo, la lista a pantalla
227
+ * completa con su buscador. **A pantalla completa y no un menú**: con la letra al 180% un menú
228
+ * desplegable deja ver dos opciones, y quien la usa elige de pie.
229
+ */
230
+ export default function SelectorDeOpcion<T extends Opcion>(props: PropsDeSelectorDeOpcion<T>) {
231
+ const {
232
+ etiqueta,
233
+ valor,
234
+ onElegir,
235
+ cargando,
236
+ detalle,
237
+ grupo,
238
+ opcional,
239
+ textoDeNinguno = "Ninguno",
240
+ vacio,
241
+ disabled,
242
+ } = props;
243
+ const styles = useStyles();
244
+ const [abierto, setAbierto] = React.useState(false);
245
+ const { texto, buscar, visibles } = useBuscador(props);
246
+
247
+ const elegir = (opcion: T | null) => {
248
+ onElegir(opcion);
249
+ setAbierto(false);
250
+ buscar("");
251
+ };
252
+
253
+ return (
254
+ <>
255
+ <RenglonDelSelector
256
+ etiqueta={etiqueta}
257
+ texto={valor ? valor.label : null}
258
+ detalle={valor ? detalle?.(valor) : null}
259
+ disabled={disabled}
260
+ onPress={() => setAbierto(true)}
261
+ />
262
+ <HojaDeOpciones
263
+ etiqueta={etiqueta}
264
+ abierto={abierto}
265
+ onCerrar={() => setAbierto(false)}
266
+ texto={texto}
267
+ onBuscar={buscar}
268
+ cargando={cargando}
269
+ opciones={visibles}
270
+ marcada={(opcion) => valor?.value === opcion.value}
271
+ onTocar={elegir}
272
+ detalle={detalle}
273
+ grupo={grupo}
274
+ vacio={vacio}
275
+ encabezado={
276
+ opcional ? (
277
+ <Pressable onPress={() => elegir(null)} style={styles.opcion}>
278
+ <Text style={styles.opcionNombre}>{textoDeNinguno}</Text>
279
+ </Pressable>
280
+ ) : null
281
+ }
282
+ />
283
+ </>
284
+ );
285
+ }
286
+
287
+ /**
288
+ * Lo mismo que `SelectorDeOpcion`, pero se marcan varias: tocar una la pone o la quita, y la
289
+ * elección se confirma con el botón del pie. Se confirma y no se guarda a cada toque para que
290
+ * salir con la flecha deje lo que había —igual que en el selector de una, donde salir no cambia
291
+ * nada—.
292
+ *
293
+ * Cerrado dice lo elegido separado por comas, que con la letra grande parte en los renglones que
294
+ * haga falta en vez de recortarse.
295
+ */
296
+ export function SelectorDeVarias<T extends Opcion>(props: PropsDeSelectorDeVarias<T>) {
297
+ const { etiqueta, valor, onElegir, cargando, detalle, grupo, vacio, disabled } = props;
298
+ const [abierto, setAbierto] = React.useState(false);
299
+ const [marcadas, setMarcadas] = React.useState<T[]>(valor);
300
+ const { texto, buscar, visibles } = useBuscador(props);
301
+
302
+ const abrir = () => {
303
+ setMarcadas(valor);
304
+ setAbierto(true);
305
+ };
306
+ const cerrar = () => {
307
+ setAbierto(false);
308
+ buscar("");
309
+ };
310
+ const tocar = (opcion: T) =>
311
+ setMarcadas((previas) =>
312
+ previas.some((p) => p.value === opcion.value)
313
+ ? previas.filter((p) => p.value !== opcion.value)
314
+ : [...previas, opcion],
315
+ );
316
+
317
+ return (
318
+ <>
319
+ <RenglonDelSelector
320
+ etiqueta={etiqueta}
321
+ texto={valor.length ? valor.map((o) => o.label).join(", ") : null}
322
+ disabled={disabled}
323
+ onPress={abrir}
324
+ />
325
+ <HojaDeOpciones
326
+ etiqueta={etiqueta}
327
+ abierto={abierto}
328
+ onCerrar={cerrar}
329
+ texto={texto}
330
+ onBuscar={buscar}
331
+ cargando={cargando}
332
+ opciones={visibles}
333
+ marcada={(opcion) => marcadas.some((m) => m.value === opcion.value)}
334
+ onTocar={tocar}
335
+ detalle={detalle}
336
+ grupo={grupo}
337
+ vacio={vacio}
338
+ pie={
339
+ <BotonGrande
340
+ icono="check"
341
+ onPress={() => {
342
+ onElegir(marcadas);
343
+ cerrar();
344
+ }}
345
+ >
346
+ {marcadas.length ? `Listo (${marcadas.length})` : "Listo"}
347
+ </BotonGrande>
348
+ }
349
+ />
350
+ </>
351
+ );
352
+ }
353
+
354
+ const useStyles = crearEstilos((c) => ({
355
+ campo: {
356
+ backgroundColor: c.superficie,
357
+ borderRadius: 14,
358
+ borderWidth: 2,
359
+ borderColor: c.secondaryLighter,
360
+ padding: 14,
361
+ gap: 4,
362
+ },
363
+ campoInactivo: { opacity: 0.5 },
364
+ etiqueta: {
365
+ ...renglon(tipografia.etiqueta),
366
+ fontWeight: "800",
367
+ color: c.secondary,
368
+ textTransform: "uppercase",
369
+ letterSpacing: 0.8,
370
+ },
371
+ renglon: { flexDirection: "row", alignItems: "flex-start", gap: 8 },
372
+ valor: { flex: 1, ...renglon(tipografia.subtitulo), fontWeight: "800", color: c.texto },
373
+ sinValor: { color: c.secondaryLight, fontWeight: "600" },
374
+ detalle: { ...renglon(tipografia.secundario), color: c.secondary },
375
+ hoja: { flex: 1, backgroundColor: c.fondo, paddingHorizontal: 18, gap: 12 },
376
+ cabecera: { flexDirection: "row", alignItems: "center", gap: 8 },
377
+ titulo: { flex: 1, fontSize: tipografia.titulo, fontWeight: "900", color: c.primary },
378
+ buscador: {
379
+ borderWidth: 1.5,
380
+ borderColor: c.secondaryLight,
381
+ borderRadius: 12,
382
+ paddingHorizontal: 14,
383
+ paddingVertical: 12,
384
+ backgroundColor: c.superficie,
385
+ fontSize: tipografia.subtitulo,
386
+ color: c.texto,
387
+ },
388
+ grupo: {
389
+ ...renglon(tipografia.etiqueta),
390
+ fontWeight: "800",
391
+ color: c.secondary,
392
+ textTransform: "uppercase",
393
+ letterSpacing: 0.8,
394
+ marginTop: 8,
395
+ },
396
+ opcion: {
397
+ backgroundColor: c.superficie,
398
+ borderRadius: 14,
399
+ borderWidth: 2,
400
+ borderColor: c.secondaryLighter,
401
+ padding: 14,
402
+ gap: 4,
403
+ },
404
+ opcionElegida: { borderColor: c.primary, backgroundColor: c.primaryWash },
405
+ opcionNombre: { ...renglon(tipografia.subtitulo), fontWeight: "800", color: c.texto },
406
+ pie: { paddingTop: 12 },
407
+ }));
@@ -0,0 +1,72 @@
1
+ import { useState } from "react";
2
+ import { Controller, type FieldValues } from "react-hook-form";
3
+ import { View } from "react-native";
4
+ import { HelperText, TextInput, type TextInputProps } from "react-native-paper";
5
+ import { crearEstilos } from "../tema";
6
+ import type { CampoAtado } from "./controlados";
7
+
8
+ /**
9
+ * Un campo del login (el usuario, la contraseña), atado a react-hook-form: el `TextInput` de Paper
10
+ * con contorno y la etiqueta que sube al escribir. Con `contrasena`, oculta lo escrito y lleva el
11
+ * ojo para verlo.
12
+ *
13
+ * Es de Paper y no `TextoControlado`, que lleva su rótulo arriba, porque así es la pantalla de
14
+ * entrada de las apps.
15
+ */
16
+ export default function TextoDeAccesoControlado<T extends FieldValues>({
17
+ control,
18
+ name,
19
+ etiqueta,
20
+ contrasena = false,
21
+ entrada,
22
+ }: CampoAtado<T> & {
23
+ etiqueta: string;
24
+ contrasena?: boolean;
25
+ /** Lo demás del `TextInput` de Paper (`autoCapitalize`, `keyboardType`…). */
26
+ entrada?: Partial<TextInputProps>;
27
+ }) {
28
+ const styles = useStyles();
29
+ const [verla, setVerla] = useState(false);
30
+
31
+ return (
32
+ <Controller
33
+ name={name}
34
+ control={control}
35
+ render={({ field: { onChange, value }, fieldState: { error } }) => (
36
+ <View>
37
+ <TextInput
38
+ label={etiqueta}
39
+ value={value}
40
+ onChangeText={onChange}
41
+ mode={"outlined"}
42
+ error={!!error}
43
+ secureTextEntry={contrasena && !verla}
44
+ right={
45
+ contrasena ? (
46
+ <TextInput.Icon
47
+ icon={verla ? "eye-off" : "eye"}
48
+ onPress={() => setVerla(!verla)}
49
+ />
50
+ ) : undefined
51
+ }
52
+ outlineStyle={styles.contorno}
53
+ style={styles.caja}
54
+ contentStyle={styles.contenido}
55
+ {...entrada}
56
+ />
57
+ {error ? (
58
+ <HelperText type={"error"} visible>
59
+ {error.message}
60
+ </HelperText>
61
+ ) : null}
62
+ </View>
63
+ )}
64
+ />
65
+ );
66
+ }
67
+
68
+ const useStyles = crearEstilos((c) => ({
69
+ contorno: { backgroundColor: c.superficie, borderRadius: 12 },
70
+ caja: { height: 64 },
71
+ contenido: { fontSize: 18 },
72
+ }));