@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,497 @@
1
+ import DateTimePicker from "@react-native-community/datetimepicker";
2
+ import dayjs from "dayjs";
3
+ import React from "react";
4
+ import { Pressable, Switch, View, type KeyboardTypeOptions } from "react-native";
5
+ import IconoDeRenglon from "../componentes/IconoDeRenglon";
6
+ import OpcionesExcluyentes from "../componentes/OpcionesExcluyentes";
7
+ import { crearEstilos, renglon, tipografia, usePaleta } from "../tema";
8
+ import { Text, TextInput } from "../texto";
9
+
10
+ /**
11
+ * Los campos de un formulario (un viaje, un tracto, un operador). Cada uno trae su rótulo arriba y
12
+ * su error abajo, para que la pantalla sólo los apile. Son controlados: atados a react-hook-form,
13
+ * van por `controlados.tsx`.
14
+ */
15
+
16
+ /** El error de un campo, en rojo y debajo de él. */
17
+ export function ErrorDelCampo({ error }: { error?: string }) {
18
+ const styles = useStyles();
19
+ return error ? <Text style={styles.error}>{error}</Text> : null;
20
+ }
21
+
22
+ /**
23
+ * El marco de un campo: el rótulo arriba, lo que se captura en medio, y debajo la ayuda y el error.
24
+ * Lo usan todos los campos de aquí, y una app lo usa para lo que no es un campo de la casa —una
25
+ * tira de fotos, el renglón de un escáner— sin que se vea distinto de los demás.
26
+ *
27
+ * Sin `etiqueta` no pinta rótulo: el interruptor lleva el suyo adentro.
28
+ */
29
+ export function Campo({
30
+ etiqueta,
31
+ ayuda,
32
+ error,
33
+ children,
34
+ }: {
35
+ etiqueta?: string;
36
+ ayuda?: string;
37
+ error?: string;
38
+ children: React.ReactNode;
39
+ }) {
40
+ const styles = useStyles();
41
+ return (
42
+ <View style={styles.campo}>
43
+ {etiqueta ? <Text style={styles.etiqueta}>{etiqueta}</Text> : null}
44
+ {children}
45
+ {ayuda ? <Text style={styles.ayuda}>{ayuda}</Text> : null}
46
+ <ErrorDelCampo error={error} />
47
+ </View>
48
+ );
49
+ }
50
+
51
+ /**
52
+ * Un texto libre: una referencia (tope de 100), unas instrucciones (varios renglones), un VIN (en
53
+ * mayúsculas) o un año (`teclado="number-pad"`).
54
+ */
55
+ export function CampoDeTexto({
56
+ etiqueta,
57
+ valor,
58
+ onCambiar,
59
+ error,
60
+ multilinea,
61
+ maximo,
62
+ placeholder,
63
+ ayuda,
64
+ disabled,
65
+ teclado,
66
+ mayusculas,
67
+ }: {
68
+ etiqueta: string;
69
+ valor: string;
70
+ onCambiar: (valor: string) => void;
71
+ error?: string;
72
+ multilinea?: boolean;
73
+ maximo?: number;
74
+ placeholder?: string;
75
+ ayuda?: string;
76
+ disabled?: boolean;
77
+ teclado?: KeyboardTypeOptions;
78
+ /** Cómo pone mayúsculas el teclado; un VIN o una placa, `characters`. */
79
+ mayusculas?: "none" | "sentences" | "words" | "characters";
80
+ }) {
81
+ const styles = useStyles();
82
+ return (
83
+ <Campo etiqueta={etiqueta} ayuda={ayuda} error={error}>
84
+ <TextInput
85
+ value={valor}
86
+ onChangeText={onCambiar}
87
+ keyboardType={teclado}
88
+ autoCapitalize={mayusculas}
89
+ autoCorrect={mayusculas === "characters" ? false : undefined}
90
+ multiline={multilinea}
91
+ maxLength={maximo}
92
+ placeholder={placeholder}
93
+ editable={!disabled}
94
+ style={[
95
+ styles.entrada,
96
+ multilinea && styles.multilinea,
97
+ !!error && styles.entradaError,
98
+ disabled && styles.inactivo,
99
+ ]}
100
+ />
101
+ </Campo>
102
+ );
103
+ }
104
+
105
+ /**
106
+ * Una fecha con su hora: dos botones, el día y la hora, cada uno con el selector del sistema. **La
107
+ * hora es el dato** (contra ella se mide si un viaje va tarde o un equipo está comprometido), así
108
+ * que nunca se manda sólo el día.
109
+ *
110
+ * Vacío, un solo botón «Elegir»: abre el día y, al elegirlo, la hora. Si es `opcional`, «Quitar»
111
+ * lo deja vacío otra vez.
112
+ */
113
+ export function CampoDeFechaHora({
114
+ etiqueta,
115
+ valor,
116
+ onCambiar,
117
+ error,
118
+ opcional,
119
+ ayuda,
120
+ desde,
121
+ hasta,
122
+ }: {
123
+ etiqueta: string;
124
+ valor: Date | null;
125
+ onCambiar: (valor: Date | null) => void;
126
+ error?: string;
127
+ opcional?: boolean;
128
+ ayuda?: string;
129
+ /** El primer y el último momento que el selector deja elegir, como en `CampoDeFecha`. */
130
+ desde?: Date;
131
+ hasta?: Date;
132
+ }) {
133
+ const c = usePaleta();
134
+ const styles = useStyles();
135
+ const [eligiendo, setEligiendo] = React.useState<"date" | "time" | null>(null);
136
+ // Vacío, el selector arranca en la próxima hora en punto: la hora de ahora no le sirve a nadie.
137
+ const base = valor ?? dayjs().add(1, "hour").startOf("hour").toDate();
138
+
139
+ return (
140
+ <Campo etiqueta={etiqueta} ayuda={ayuda} error={error}>
141
+ {valor ? (
142
+ <View style={styles.fechaHora}>
143
+ <Pressable
144
+ onPress={() => setEligiendo("date")}
145
+ accessibilityRole="button"
146
+ style={[styles.entrada, styles.mitad, !!error && styles.entradaError]}
147
+ >
148
+ <Text style={styles.textoFecha}>{dayjs(valor).format("D MMM YYYY")}</Text>
149
+ </Pressable>
150
+ <Pressable
151
+ onPress={() => setEligiendo("time")}
152
+ accessibilityRole="button"
153
+ style={[styles.entrada, styles.mitad, !!error && styles.entradaError]}
154
+ >
155
+ <Text style={styles.textoFecha}>{dayjs(valor).format("HH:mm")}</Text>
156
+ </Pressable>
157
+ </View>
158
+ ) : (
159
+ <Pressable
160
+ onPress={() => setEligiendo("date")}
161
+ accessibilityRole="button"
162
+ style={[styles.entrada, !!error && styles.entradaError]}
163
+ >
164
+ <View style={styles.renglon}>
165
+ <IconoDeRenglon
166
+ name="calendar-clock"
167
+ fontSize={tipografia.subtitulo}
168
+ color={c.secondaryLight}
169
+ />
170
+ <Text style={[styles.textoFecha, styles.sinValor]}>Elegir…</Text>
171
+ </View>
172
+ </Pressable>
173
+ )}
174
+ {opcional && valor ? (
175
+ <Pressable
176
+ onPress={() => onCambiar(null)}
177
+ accessibilityRole="button"
178
+ style={styles.quitar}
179
+ >
180
+ <IconoDeRenglon
181
+ name="close-circle-outline"
182
+ fontSize={tipografia.cuerpo}
183
+ color={c.secondary}
184
+ />
185
+ <Text style={styles.quitarTexto}>Quitar</Text>
186
+ </Pressable>
187
+ ) : null}
188
+ {eligiendo ? (
189
+ <DateTimePicker
190
+ value={base}
191
+ mode={eligiendo}
192
+ is24Hour
193
+ minimumDate={desde}
194
+ maximumDate={hasta}
195
+ onChange={(evento, elegida) => {
196
+ const paso = eligiendo;
197
+ setEligiendo(null);
198
+ if (evento.type !== "set" || !elegida) return;
199
+ const nueva =
200
+ paso === "date"
201
+ ? dayjs(base)
202
+ .year(elegida.getFullYear())
203
+ .month(elegida.getMonth())
204
+ .date(elegida.getDate())
205
+ : dayjs(base)
206
+ .hour(elegida.getHours())
207
+ .minute(elegida.getMinutes())
208
+ .second(0)
209
+ .millisecond(0);
210
+ onCambiar(nueva.toDate());
211
+ // Vacío, tras el día va la hora: sin ella el campo no está completo.
212
+ if (paso === "date" && !valor) setEligiendo("time");
213
+ }}
214
+ />
215
+ ) : null}
216
+ </Campo>
217
+ );
218
+ }
219
+
220
+ /** Un interruptor con su texto y, si hace falta, por qué está como está. */
221
+ export function CampoInterruptor({
222
+ texto,
223
+ valor,
224
+ onCambiar,
225
+ ayuda,
226
+ error,
227
+ disabled,
228
+ }: {
229
+ texto: string;
230
+ valor: boolean;
231
+ onCambiar: (valor: boolean) => void;
232
+ ayuda?: string;
233
+ error?: string;
234
+ disabled?: boolean;
235
+ }) {
236
+ const c = usePaleta();
237
+ const styles = useStyles();
238
+ return (
239
+ <Campo ayuda={ayuda} error={error}>
240
+ <Pressable
241
+ onPress={() => onCambiar(!valor)}
242
+ disabled={disabled}
243
+ accessibilityRole="switch"
244
+ accessibilityState={{ checked: valor, disabled: !!disabled }}
245
+ style={[styles.interruptor, disabled && styles.inactivo]}
246
+ >
247
+ <Text style={styles.interruptorTexto}>{texto}</Text>
248
+ <Switch
249
+ value={valor}
250
+ onValueChange={onCambiar}
251
+ disabled={disabled}
252
+ trackColor={{ true: c.primaryLight }}
253
+ thumbColor={valor ? c.primary : undefined}
254
+ />
255
+ </Pressable>
256
+ </Campo>
257
+ );
258
+ }
259
+
260
+ /**
261
+ * Una fecha sin hora (un nacimiento, el fin de una renta): un botón con el selector del sistema.
262
+ * El valor es el de la API, `YYYY-MM-DD`, para no pasar por una zona horaria que lo corra un día.
263
+ */
264
+ export function CampoDeFecha({
265
+ etiqueta,
266
+ valor,
267
+ onCambiar,
268
+ error,
269
+ opcional,
270
+ ayuda,
271
+ desde,
272
+ hasta,
273
+ }: {
274
+ etiqueta: string;
275
+ valor: string | null;
276
+ onCambiar: (valor: string | null) => void;
277
+ error?: string;
278
+ opcional?: boolean;
279
+ ayuda?: string;
280
+ /** Los días que el selector deja elegir: una recepción no puede ser de mañana (`hasta`). */
281
+ desde?: Date;
282
+ hasta?: Date;
283
+ }) {
284
+ const c = usePaleta();
285
+ const styles = useStyles();
286
+ const [eligiendo, setEligiendo] = React.useState(false);
287
+ const fecha = valor ? dayjs(valor) : null;
288
+
289
+ return (
290
+ <Campo etiqueta={etiqueta} ayuda={ayuda} error={error}>
291
+ <Pressable
292
+ onPress={() => setEligiendo(true)}
293
+ accessibilityRole="button"
294
+ style={[styles.entrada, !!error && styles.entradaError]}
295
+ >
296
+ <View style={styles.renglon}>
297
+ <IconoDeRenglon
298
+ name="calendar"
299
+ fontSize={tipografia.subtitulo}
300
+ color={fecha ? c.secondary : c.secondaryLight}
301
+ />
302
+ <Text style={[styles.textoFecha, !fecha && styles.sinValor]}>
303
+ {fecha ? fecha.format("D MMM YYYY") : "Elegir…"}
304
+ </Text>
305
+ </View>
306
+ </Pressable>
307
+ {opcional && valor ? (
308
+ <Pressable
309
+ onPress={() => onCambiar(null)}
310
+ accessibilityRole="button"
311
+ style={styles.quitar}
312
+ >
313
+ <IconoDeRenglon
314
+ name="close-circle-outline"
315
+ fontSize={tipografia.cuerpo}
316
+ color={c.secondary}
317
+ />
318
+ <Text style={styles.quitarTexto}>Quitar</Text>
319
+ </Pressable>
320
+ ) : null}
321
+ {eligiendo ? (
322
+ <DateTimePicker
323
+ value={fecha?.toDate() ?? new Date()}
324
+ mode="date"
325
+ minimumDate={desde}
326
+ maximumDate={hasta}
327
+ onChange={(evento, elegida) => {
328
+ setEligiendo(false);
329
+ if (evento.type === "set" && elegida) {
330
+ onCambiar(dayjs(elegida).format("YYYY-MM-DD"));
331
+ }
332
+ }}
333
+ />
334
+ ) : null}
335
+ </Campo>
336
+ );
337
+ }
338
+
339
+ /**
340
+ * Una de pocas opciones fijas (la cabina, la propiedad, la longitud): todas a la vista, una por
341
+ * renglón, en vez de un menú que con la letra al 180% deja ver dos.
342
+ */
343
+ export function CampoDeOpciones<V extends string>({
344
+ etiqueta,
345
+ opciones,
346
+ valor,
347
+ onElegir,
348
+ error,
349
+ ayuda,
350
+ }: {
351
+ etiqueta: string;
352
+ opciones: readonly { value: V; label: string }[];
353
+ valor: V | null;
354
+ onElegir: (valor: V) => void;
355
+ error?: string;
356
+ ayuda?: string;
357
+ }) {
358
+ return (
359
+ <Campo etiqueta={etiqueta} ayuda={ayuda} error={error}>
360
+ <OpcionesExcluyentes
361
+ opciones={opciones.map((o) => ({ valor: o.value, texto: o.label }))}
362
+ valor={valor}
363
+ onElegir={onElegir}
364
+ />
365
+ </Campo>
366
+ );
367
+ }
368
+
369
+ /** Los países de un teléfono: lo que la operación marca, de un lado y del otro. */
370
+ const LADAS = [
371
+ { pais: "MX", lada: "+52", texto: "MX +52" },
372
+ { pais: "US", lada: "+1", texto: "US +1" },
373
+ ] as const;
374
+
375
+ /** Un teléfono guardado (`+526641234567`) partido en su lada y sus dígitos. */
376
+ const partirTelefono = (telefono: string | null) => {
377
+ const limpio = (telefono ?? "").replace(/[^\d+]/g, "");
378
+ const lada = LADAS.find((l) => limpio.startsWith(l.lada)) ?? LADAS[0];
379
+ return {
380
+ lada: lada.lada,
381
+ digitos: limpio.startsWith(lada.lada) ? limpio.slice(lada.lada.length) : limpio,
382
+ };
383
+ };
384
+
385
+ /**
386
+ * Un teléfono, como el `ControlledPhoneNumber` del portal: la lada (México o Estados Unidos) y los
387
+ * diez dígitos. El valor es el del servidor (`PhoneNumberField`), en E.164: `+526641234567`; vacío
388
+ * es `null`.
389
+ */
390
+ export function CampoDeTelefono({
391
+ etiqueta,
392
+ valor,
393
+ onCambiar,
394
+ error,
395
+ ayuda,
396
+ }: {
397
+ etiqueta: string;
398
+ valor: string | null;
399
+ onCambiar: (valor: string | null) => void;
400
+ error?: string;
401
+ ayuda?: string;
402
+ }) {
403
+ const c = usePaleta();
404
+ const styles = useStyles();
405
+ const { lada, digitos } = partirTelefono(valor);
406
+ const armar = (nuevaLada: string, nuevosDigitos: string) => {
407
+ const solo = nuevosDigitos.replace(/\D/g, "");
408
+ onCambiar(solo ? `${nuevaLada}${solo}` : null);
409
+ };
410
+ return (
411
+ <Campo etiqueta={etiqueta} ayuda={ayuda} error={error}>
412
+ <View style={styles.telefono}>
413
+ {LADAS.map((l) => (
414
+ <Pressable
415
+ key={l.pais}
416
+ onPress={() => armar(l.lada, digitos)}
417
+ accessibilityRole="radio"
418
+ accessibilityState={{ selected: lada === l.lada }}
419
+ style={[styles.lada, lada === l.lada && styles.ladaElegida]}
420
+ >
421
+ <Text style={[styles.ladaTexto, lada === l.lada && { color: c.primary }]}>
422
+ {l.texto}
423
+ </Text>
424
+ </Pressable>
425
+ ))}
426
+ </View>
427
+ <TextInput
428
+ value={digitos}
429
+ onChangeText={(texto) => armar(lada, texto)}
430
+ keyboardType="phone-pad"
431
+ maxLength={10}
432
+ placeholder="10 dígitos"
433
+ style={[styles.entrada, !!error && styles.entradaError]}
434
+ />
435
+ </Campo>
436
+ );
437
+ }
438
+
439
+ const useStyles = crearEstilos((c) => ({
440
+ campo: { gap: 6 },
441
+ etiqueta: {
442
+ ...renglon(tipografia.etiqueta),
443
+ fontWeight: "800",
444
+ color: c.secondary,
445
+ textTransform: "uppercase",
446
+ letterSpacing: 0.8,
447
+ },
448
+ entrada: {
449
+ borderWidth: 1.5,
450
+ borderColor: c.secondaryLight,
451
+ borderRadius: 12,
452
+ paddingHorizontal: 14,
453
+ paddingVertical: 12,
454
+ backgroundColor: c.superficie,
455
+ fontSize: tipografia.subtitulo,
456
+ color: c.texto,
457
+ },
458
+ multilinea: { minHeight: 100, textAlignVertical: "top", fontSize: tipografia.cuerpo },
459
+ entradaError: { borderColor: c.primary },
460
+ inactivo: { opacity: 0.5 },
461
+ fechaHora: { flexDirection: "row", gap: 12 },
462
+ mitad: { flex: 1, justifyContent: "center" },
463
+ renglon: { flexDirection: "row", alignItems: "flex-start", gap: 8 },
464
+ textoFecha: { ...renglon(tipografia.cuerpo), fontWeight: "700", color: c.texto },
465
+ sinValor: { color: c.secondaryLight, fontWeight: "600" },
466
+ quitar: { flexDirection: "row", alignItems: "flex-start", gap: 6, alignSelf: "flex-start" },
467
+ quitarTexto: { ...renglon(tipografia.cuerpo), fontWeight: "700", color: c.secondary },
468
+ ayuda: { ...renglon(tipografia.secundario), color: c.secondary },
469
+ error: { ...renglon(tipografia.secundario), color: c.primary },
470
+ telefono: { flexDirection: "row", gap: 10 },
471
+ lada: {
472
+ flex: 1,
473
+ alignItems: "center",
474
+ borderWidth: 2,
475
+ borderColor: c.secondaryLighter,
476
+ borderRadius: 12,
477
+ paddingVertical: 10,
478
+ backgroundColor: c.superficie,
479
+ },
480
+ ladaElegida: { borderColor: c.primary, backgroundColor: c.primaryWash },
481
+ ladaTexto: { ...renglon(tipografia.cuerpo), fontWeight: "800", color: c.secondary },
482
+ interruptor: {
483
+ flexDirection: "row",
484
+ alignItems: "center",
485
+ gap: 10,
486
+ backgroundColor: c.superficie,
487
+ borderRadius: 14,
488
+ paddingHorizontal: 14,
489
+ paddingVertical: 10,
490
+ },
491
+ interruptorTexto: {
492
+ flex: 1,
493
+ ...renglon(tipografia.cuerpo),
494
+ fontWeight: "700",
495
+ color: c.texto,
496
+ },
497
+ }));
@@ -0,0 +1,200 @@
1
+ import React from "react";
2
+ import { Controller, type Control, type FieldValues, type Path } from "react-hook-form";
3
+ import CampoDeSeleccion, { CampoDeVarias } from "./CampoDeSeleccion";
4
+ import {
5
+ CampoDeFecha,
6
+ CampoDeFechaHora,
7
+ CampoDeOpciones,
8
+ CampoDeTelefono,
9
+ CampoDeTexto,
10
+ CampoInterruptor,
11
+ } from "./campos";
12
+ import type { Opcion } from "./SelectorDeOpcion";
13
+
14
+ /**
15
+ * Los campos de `campos.tsx` ya atados a un formulario de react-hook-form: reciben `control` y
16
+ * `name` y se cuelgan su valor y su error. Así un formulario largo (un tracto, una caja, un
17
+ * operador) es una lista de campos y no una de `Controller`.
18
+ *
19
+ * Un campo propio de una app (un catálogo de su API, una dirección) se ata igual, con `CampoAtado`
20
+ * y `SinValor`.
21
+ */
22
+
23
+ /** Lo que un campo controlado recibe para atarse al formulario. */
24
+ export interface CampoAtado<T extends FieldValues> {
25
+ control: Control<T>;
26
+ name: Path<T>;
27
+ }
28
+
29
+ /** Las props de un campo sin lo que pone el `Controller`. */
30
+ export type SinValor<P> = Omit<P, "valor" | "onCambiar" | "onElegir" | "error">;
31
+
32
+ export function TextoControlado<T extends FieldValues>({
33
+ control,
34
+ name,
35
+ ...props
36
+ }: CampoAtado<T> & SinValor<React.ComponentProps<typeof CampoDeTexto>>) {
37
+ return (
38
+ <Controller
39
+ name={name}
40
+ control={control}
41
+ render={({ field: { value, onChange }, fieldState }) => (
42
+ <CampoDeTexto
43
+ {...props}
44
+ // Un número del formulario (un conteo, un monto) también se escribe aquí: el
45
+ // TextInput sólo sabe de texto.
46
+ valor={value == null ? "" : String(value)}
47
+ onCambiar={onChange}
48
+ error={fieldState.error?.message}
49
+ />
50
+ )}
51
+ />
52
+ );
53
+ }
54
+
55
+ export function InterruptorControlado<T extends FieldValues>({
56
+ control,
57
+ name,
58
+ ...props
59
+ }: CampoAtado<T> & SinValor<React.ComponentProps<typeof CampoInterruptor>>) {
60
+ return (
61
+ <Controller
62
+ name={name}
63
+ control={control}
64
+ render={({ field: { value, onChange }, fieldState }) => (
65
+ <CampoInterruptor
66
+ {...props}
67
+ valor={Boolean(value)}
68
+ onCambiar={onChange}
69
+ error={fieldState.error?.message}
70
+ />
71
+ )}
72
+ />
73
+ );
74
+ }
75
+
76
+ export function FechaControlada<T extends FieldValues>({
77
+ control,
78
+ name,
79
+ ...props
80
+ }: CampoAtado<T> & SinValor<React.ComponentProps<typeof CampoDeFecha>>) {
81
+ return (
82
+ <Controller
83
+ name={name}
84
+ control={control}
85
+ render={({ field: { value, onChange }, fieldState }) => (
86
+ <CampoDeFecha
87
+ {...props}
88
+ valor={value ?? null}
89
+ onCambiar={onChange}
90
+ error={fieldState.error?.message}
91
+ />
92
+ )}
93
+ />
94
+ );
95
+ }
96
+
97
+ export function FechaHoraControlada<T extends FieldValues>({
98
+ control,
99
+ name,
100
+ ...props
101
+ }: CampoAtado<T> & SinValor<React.ComponentProps<typeof CampoDeFechaHora>>) {
102
+ return (
103
+ <Controller
104
+ name={name}
105
+ control={control}
106
+ render={({ field: { value, onChange }, fieldState }) => (
107
+ <CampoDeFechaHora
108
+ {...props}
109
+ valor={value ?? null}
110
+ onCambiar={onChange}
111
+ error={fieldState.error?.message}
112
+ />
113
+ )}
114
+ />
115
+ );
116
+ }
117
+
118
+ export function OpcionesControladas<T extends FieldValues, V extends string>({
119
+ control,
120
+ name,
121
+ ...props
122
+ }: CampoAtado<T> & SinValor<React.ComponentProps<typeof CampoDeOpciones<V>>>) {
123
+ return (
124
+ <Controller
125
+ name={name}
126
+ control={control}
127
+ render={({ field: { value, onChange }, fieldState }) => (
128
+ <CampoDeOpciones<V>
129
+ {...props}
130
+ valor={value ?? null}
131
+ onElegir={onChange}
132
+ error={fieldState.error?.message}
133
+ />
134
+ )}
135
+ />
136
+ );
137
+ }
138
+
139
+ export function SeleccionControlada<T extends FieldValues, O extends Opcion>({
140
+ control,
141
+ name,
142
+ ...props
143
+ }: CampoAtado<T> & SinValor<React.ComponentProps<typeof CampoDeSeleccion<O>>>) {
144
+ return (
145
+ <Controller
146
+ name={name}
147
+ control={control}
148
+ render={({ field: { value, onChange }, fieldState }) => (
149
+ <CampoDeSeleccion<O>
150
+ {...props}
151
+ valor={(value as O | null) ?? null}
152
+ onElegir={onChange}
153
+ error={fieldState.error?.message}
154
+ />
155
+ )}
156
+ />
157
+ );
158
+ }
159
+
160
+ export function TelefonoControlado<T extends FieldValues>({
161
+ control,
162
+ name,
163
+ ...props
164
+ }: CampoAtado<T> & SinValor<React.ComponentProps<typeof CampoDeTelefono>>) {
165
+ return (
166
+ <Controller
167
+ name={name}
168
+ control={control}
169
+ render={({ field: { value, onChange }, fieldState }) => (
170
+ <CampoDeTelefono
171
+ {...props}
172
+ valor={value ?? null}
173
+ onCambiar={onChange}
174
+ error={fieldState.error?.message}
175
+ />
176
+ )}
177
+ />
178
+ );
179
+ }
180
+
181
+ export function VariasControladas<T extends FieldValues, O extends Opcion>({
182
+ control,
183
+ name,
184
+ ...props
185
+ }: CampoAtado<T> & SinValor<React.ComponentProps<typeof CampoDeVarias<O>>>) {
186
+ return (
187
+ <Controller
188
+ name={name}
189
+ control={control}
190
+ render={({ field: { value, onChange }, fieldState }) => (
191
+ <CampoDeVarias<O>
192
+ {...props}
193
+ valor={(value as O[] | null) ?? []}
194
+ onElegir={onChange}
195
+ error={fieldState.error?.message}
196
+ />
197
+ )}
198
+ />
199
+ );
200
+ }