@acvl/mobile-components 0.0.0-stage → 0.0.1

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 (297) hide show
  1. package/README.md +146 -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/componentes/AccionesDelEncabezado.js +212 -0
  10. package/lib/module/componentes/AccionesDelEncabezado.js.map +1 -0
  11. package/lib/module/componentes/BotonDeAvatar.js +55 -0
  12. package/lib/module/componentes/BotonDeAvatar.js.map +1 -0
  13. package/lib/module/componentes/BotonGrande.js +105 -0
  14. package/lib/module/componentes/BotonGrande.js.map +1 -0
  15. package/lib/module/componentes/CabeceraEmpujada.js +101 -0
  16. package/lib/module/componentes/CabeceraEmpujada.js.map +1 -0
  17. package/lib/module/componentes/Chip.js +77 -0
  18. package/lib/module/componentes/Chip.js.map +1 -0
  19. package/lib/module/componentes/ContenidoDePantalla.js +56 -0
  20. package/lib/module/componentes/ContenidoDePantalla.js.map +1 -0
  21. package/lib/module/componentes/EstadoVacio.js +65 -0
  22. package/lib/module/componentes/EstadoVacio.js.map +1 -0
  23. package/lib/module/componentes/Foto.js +106 -0
  24. package/lib/module/componentes/Foto.js.map +1 -0
  25. package/lib/module/componentes/IconoDeRenglon.js +44 -0
  26. package/lib/module/componentes/IconoDeRenglon.js.map +1 -0
  27. package/lib/module/componentes/Logo.js +44 -0
  28. package/lib/module/componentes/Logo.js.map +1 -0
  29. package/lib/module/componentes/Nota.js +51 -0
  30. package/lib/module/componentes/Nota.js.map +1 -0
  31. package/lib/module/componentes/OpcionesExcluyentes.js +69 -0
  32. package/lib/module/componentes/OpcionesExcluyentes.js.map +1 -0
  33. package/lib/module/componentes/PantallaDeError.js +84 -0
  34. package/lib/module/componentes/PantallaDeError.js.map +1 -0
  35. package/lib/module/componentes/Pestanas.js +87 -0
  36. package/lib/module/componentes/Pestanas.js.map +1 -0
  37. package/lib/module/componentes/Rotulo.js +28 -0
  38. package/lib/module/componentes/Rotulo.js.map +1 -0
  39. package/lib/module/componentes/RotuloDeSeccion.js +87 -0
  40. package/lib/module/componentes/RotuloDeSeccion.js.map +1 -0
  41. package/lib/module/componentes/Tarjeta.js +47 -0
  42. package/lib/module/componentes/Tarjeta.js.map +1 -0
  43. package/lib/module/componentes/TarjetaDeDatos.js +79 -0
  44. package/lib/module/componentes/TarjetaDeDatos.js.map +1 -0
  45. package/lib/module/componentes/TiraDeFotos.js +184 -0
  46. package/lib/module/componentes/TiraDeFotos.js.map +1 -0
  47. package/lib/module/componentes/VisorDeFoto.js +171 -0
  48. package/lib/module/componentes/VisorDeFoto.js.map +1 -0
  49. package/lib/module/componentes/logos/bola-blanca.png +0 -0
  50. package/lib/module/componentes/logos/bola.png +0 -0
  51. package/lib/module/componentes/logos/logo-blanco.png +0 -0
  52. package/lib/module/componentes/logos/logo.png +0 -0
  53. package/lib/module/dialogos/HostDeDialogos.js +170 -0
  54. package/lib/module/dialogos/HostDeDialogos.js.map +1 -0
  55. package/lib/module/dialogos/dialogos.js +112 -0
  56. package/lib/module/dialogos/dialogos.js.map +1 -0
  57. package/lib/module/formularios/CampoDeSeleccion.js +47 -0
  58. package/lib/module/formularios/CampoDeSeleccion.js.map +1 -0
  59. package/lib/module/formularios/SelectorDeOpcion.js +406 -0
  60. package/lib/module/formularios/SelectorDeOpcion.js.map +1 -0
  61. package/lib/module/formularios/TextoDeAccesoControlado.js +73 -0
  62. package/lib/module/formularios/TextoDeAccesoControlado.js.map +1 -0
  63. package/lib/module/formularios/campos.js +493 -0
  64. package/lib/module/formularios/campos.js.map +1 -0
  65. package/lib/module/formularios/controlados.js +197 -0
  66. package/lib/module/formularios/controlados.js.map +1 -0
  67. package/lib/module/formularios/errores.js +91 -0
  68. package/lib/module/formularios/errores.js.map +1 -0
  69. package/lib/module/formularios/guardado.js +78 -0
  70. package/lib/module/formularios/guardado.js.map +1 -0
  71. package/lib/module/formularios/useBusqueda.js +22 -0
  72. package/lib/module/formularios/useBusqueda.js.map +1 -0
  73. package/lib/module/fotos/elegir.js +178 -0
  74. package/lib/module/fotos/elegir.js.map +1 -0
  75. package/lib/module/fotos/index.js +8 -0
  76. package/lib/module/fotos/index.js.map +1 -0
  77. package/lib/module/fotos/reducir.js +93 -0
  78. package/lib/module/fotos/reducir.js.map +1 -0
  79. package/lib/module/hoja/HojaInferior.js +108 -0
  80. package/lib/module/hoja/HojaInferior.js.map +1 -0
  81. package/lib/module/hoja/index.js +7 -0
  82. package/lib/module/hoja/index.js.map +1 -0
  83. package/lib/module/hoja/useMasDeLaFicha.js +48 -0
  84. package/lib/module/hoja/useMasDeLaFicha.js.map +1 -0
  85. package/lib/module/index.js +66 -0
  86. package/lib/module/index.js.map +1 -0
  87. package/lib/module/listas/HojaDeFiltros.js +260 -0
  88. package/lib/module/listas/HojaDeFiltros.js.map +1 -0
  89. package/lib/module/listas/ListaPaginada.js +103 -0
  90. package/lib/module/listas/ListaPaginada.js.map +1 -0
  91. package/lib/module/listas/TarjetaDeslizable.js +118 -0
  92. package/lib/module/listas/TarjetaDeslizable.js.map +1 -0
  93. package/lib/module/listas/paginado.js +11 -0
  94. package/lib/module/listas/paginado.js.map +1 -0
  95. package/lib/module/listas/piezas.js +603 -0
  96. package/lib/module/listas/piezas.js.map +1 -0
  97. package/lib/module/navegacion/BarraDePestanas.js +162 -0
  98. package/lib/module/navegacion/BarraDePestanas.js.map +1 -0
  99. package/lib/module/navegacion/BotonDeBarra.js +58 -0
  100. package/lib/module/navegacion/BotonDeBarra.js.map +1 -0
  101. package/lib/module/navegacion/encabezado.js +103 -0
  102. package/lib/module/navegacion/encabezado.js.map +1 -0
  103. package/lib/module/pantallas/PantallaDeAcceso.js +195 -0
  104. package/lib/module/pantallas/PantallaDeAcceso.js.map +1 -0
  105. package/lib/module/pantallas/PantallaDeEdicion.js +121 -0
  106. package/lib/module/pantallas/PantallaDeEdicion.js.map +1 -0
  107. package/lib/module/pantallas/PantallaDeFicha.js +94 -0
  108. package/lib/module/pantallas/PantallaDeFicha.js.map +1 -0
  109. package/lib/module/pantallas/PantallaDePerfil.js +137 -0
  110. package/lib/module/pantallas/PantallaDePerfil.js.map +1 -0
  111. package/lib/module/tema/ProveedorDeTema.js +122 -0
  112. package/lib/module/tema/ProveedorDeTema.js.map +1 -0
  113. package/lib/module/tema/estilos.js +54 -0
  114. package/lib/module/tema/estilos.js.map +1 -0
  115. package/lib/module/tema/fuentes.js +28 -0
  116. package/lib/module/tema/fuentes.js.map +1 -0
  117. package/lib/module/tema/index.js +8 -0
  118. package/lib/module/tema/index.js.map +1 -0
  119. package/lib/module/tema/paleta.js +107 -0
  120. package/lib/module/tema/paleta.js.map +1 -0
  121. package/lib/module/tema/tipografia.js +32 -0
  122. package/lib/module/tema/tipografia.js.map +1 -0
  123. package/lib/module/texto.js +48 -0
  124. package/lib/module/texto.js.map +1 -0
  125. package/lib/typescript/src/componentes/AccionesDelEncabezado.d.ts +34 -0
  126. package/lib/typescript/src/componentes/AccionesDelEncabezado.d.ts.map +1 -0
  127. package/lib/typescript/src/componentes/BotonDeAvatar.d.ts +17 -0
  128. package/lib/typescript/src/componentes/BotonDeAvatar.d.ts.map +1 -0
  129. package/lib/typescript/src/componentes/BotonGrande.d.ts +26 -0
  130. package/lib/typescript/src/componentes/BotonGrande.d.ts.map +1 -0
  131. package/lib/typescript/src/componentes/CabeceraEmpujada.d.ts +18 -0
  132. package/lib/typescript/src/componentes/CabeceraEmpujada.d.ts.map +1 -0
  133. package/lib/typescript/src/componentes/Chip.d.ts +14 -0
  134. package/lib/typescript/src/componentes/Chip.d.ts.map +1 -0
  135. package/lib/typescript/src/componentes/ContenidoDePantalla.d.ts +17 -0
  136. package/lib/typescript/src/componentes/ContenidoDePantalla.d.ts.map +1 -0
  137. package/lib/typescript/src/componentes/EstadoVacio.d.ts +17 -0
  138. package/lib/typescript/src/componentes/EstadoVacio.d.ts.map +1 -0
  139. package/lib/typescript/src/componentes/Foto.d.ts +41 -0
  140. package/lib/typescript/src/componentes/Foto.d.ts.map +1 -0
  141. package/lib/typescript/src/componentes/IconoDeRenglon.d.ts +25 -0
  142. package/lib/typescript/src/componentes/IconoDeRenglon.d.ts.map +1 -0
  143. package/lib/typescript/src/componentes/Logo.d.ts +13 -0
  144. package/lib/typescript/src/componentes/Logo.d.ts.map +1 -0
  145. package/lib/typescript/src/componentes/Nota.d.ts +7 -0
  146. package/lib/typescript/src/componentes/Nota.d.ts.map +1 -0
  147. package/lib/typescript/src/componentes/OpcionesExcluyentes.d.ts +14 -0
  148. package/lib/typescript/src/componentes/OpcionesExcluyentes.d.ts.map +1 -0
  149. package/lib/typescript/src/componentes/PantallaDeError.d.ts +23 -0
  150. package/lib/typescript/src/componentes/PantallaDeError.d.ts.map +1 -0
  151. package/lib/typescript/src/componentes/Pestanas.d.ts +28 -0
  152. package/lib/typescript/src/componentes/Pestanas.d.ts.map +1 -0
  153. package/lib/typescript/src/componentes/Rotulo.d.ts +6 -0
  154. package/lib/typescript/src/componentes/Rotulo.d.ts.map +1 -0
  155. package/lib/typescript/src/componentes/RotuloDeSeccion.d.ts +20 -0
  156. package/lib/typescript/src/componentes/RotuloDeSeccion.d.ts.map +1 -0
  157. package/lib/typescript/src/componentes/Tarjeta.d.ts +15 -0
  158. package/lib/typescript/src/componentes/Tarjeta.d.ts.map +1 -0
  159. package/lib/typescript/src/componentes/TarjetaDeDatos.d.ts +13 -0
  160. package/lib/typescript/src/componentes/TarjetaDeDatos.d.ts.map +1 -0
  161. package/lib/typescript/src/componentes/TiraDeFotos.d.ts +36 -0
  162. package/lib/typescript/src/componentes/TiraDeFotos.d.ts.map +1 -0
  163. package/lib/typescript/src/componentes/VisorDeFoto.d.ts +23 -0
  164. package/lib/typescript/src/componentes/VisorDeFoto.d.ts.map +1 -0
  165. package/lib/typescript/src/dialogos/HostDeDialogos.d.ts +14 -0
  166. package/lib/typescript/src/dialogos/HostDeDialogos.d.ts.map +1 -0
  167. package/lib/typescript/src/dialogos/dialogos.d.ts +65 -0
  168. package/lib/typescript/src/dialogos/dialogos.d.ts.map +1 -0
  169. package/lib/typescript/src/formularios/CampoDeSeleccion.d.ts +22 -0
  170. package/lib/typescript/src/formularios/CampoDeSeleccion.d.ts.map +1 -0
  171. package/lib/typescript/src/formularios/SelectorDeOpcion.d.ts +59 -0
  172. package/lib/typescript/src/formularios/SelectorDeOpcion.d.ts.map +1 -0
  173. package/lib/typescript/src/formularios/TextoDeAccesoControlado.d.ts +18 -0
  174. package/lib/typescript/src/formularios/TextoDeAccesoControlado.d.ts.map +1 -0
  175. package/lib/typescript/src/formularios/campos.d.ts +107 -0
  176. package/lib/typescript/src/formularios/campos.d.ts.map +1 -0
  177. package/lib/typescript/src/formularios/controlados.d.ts +29 -0
  178. package/lib/typescript/src/formularios/controlados.d.ts.map +1 -0
  179. package/lib/typescript/src/formularios/errores.d.ts +36 -0
  180. package/lib/typescript/src/formularios/errores.d.ts.map +1 -0
  181. package/lib/typescript/src/formularios/guardado.d.ts +36 -0
  182. package/lib/typescript/src/formularios/guardado.d.ts.map +1 -0
  183. package/lib/typescript/src/formularios/useBusqueda.d.ts +7 -0
  184. package/lib/typescript/src/formularios/useBusqueda.d.ts.map +1 -0
  185. package/lib/typescript/src/fotos/elegir.d.ts +58 -0
  186. package/lib/typescript/src/fotos/elegir.d.ts.map +1 -0
  187. package/lib/typescript/src/fotos/index.d.ts +3 -0
  188. package/lib/typescript/src/fotos/index.d.ts.map +1 -0
  189. package/lib/typescript/src/fotos/reducir.d.ts +32 -0
  190. package/lib/typescript/src/fotos/reducir.d.ts.map +1 -0
  191. package/lib/typescript/src/hoja/HojaInferior.d.ts +21 -0
  192. package/lib/typescript/src/hoja/HojaInferior.d.ts.map +1 -0
  193. package/lib/typescript/src/hoja/index.d.ts +3 -0
  194. package/lib/typescript/src/hoja/index.d.ts.map +1 -0
  195. package/lib/typescript/src/hoja/useMasDeLaFicha.d.ts +27 -0
  196. package/lib/typescript/src/hoja/useMasDeLaFicha.d.ts.map +1 -0
  197. package/lib/typescript/src/index.d.ts +45 -0
  198. package/lib/typescript/src/index.d.ts.map +1 -0
  199. package/lib/typescript/src/listas/HojaDeFiltros.d.ts +60 -0
  200. package/lib/typescript/src/listas/HojaDeFiltros.d.ts.map +1 -0
  201. package/lib/typescript/src/listas/ListaPaginada.d.ts +39 -0
  202. package/lib/typescript/src/listas/ListaPaginada.d.ts.map +1 -0
  203. package/lib/typescript/src/listas/TarjetaDeslizable.d.ts +33 -0
  204. package/lib/typescript/src/listas/TarjetaDeslizable.d.ts.map +1 -0
  205. package/lib/typescript/src/listas/paginado.d.ts +16 -0
  206. package/lib/typescript/src/listas/paginado.d.ts.map +1 -0
  207. package/lib/typescript/src/listas/piezas.d.ts +135 -0
  208. package/lib/typescript/src/listas/piezas.d.ts.map +1 -0
  209. package/lib/typescript/src/navegacion/BarraDePestanas.d.ts +57 -0
  210. package/lib/typescript/src/navegacion/BarraDePestanas.d.ts.map +1 -0
  211. package/lib/typescript/src/navegacion/BotonDeBarra.d.ts +15 -0
  212. package/lib/typescript/src/navegacion/BotonDeBarra.d.ts.map +1 -0
  213. package/lib/typescript/src/navegacion/encabezado.d.ts +44 -0
  214. package/lib/typescript/src/navegacion/encabezado.d.ts.map +1 -0
  215. package/lib/typescript/src/pantallas/PantallaDeAcceso.d.ts +32 -0
  216. package/lib/typescript/src/pantallas/PantallaDeAcceso.d.ts.map +1 -0
  217. package/lib/typescript/src/pantallas/PantallaDeEdicion.d.ts +38 -0
  218. package/lib/typescript/src/pantallas/PantallaDeEdicion.d.ts.map +1 -0
  219. package/lib/typescript/src/pantallas/PantallaDeFicha.d.ts +35 -0
  220. package/lib/typescript/src/pantallas/PantallaDeFicha.d.ts.map +1 -0
  221. package/lib/typescript/src/pantallas/PantallaDePerfil.d.ts +19 -0
  222. package/lib/typescript/src/pantallas/PantallaDePerfil.d.ts.map +1 -0
  223. package/lib/typescript/src/tema/ProveedorDeTema.d.ts +32 -0
  224. package/lib/typescript/src/tema/ProveedorDeTema.d.ts.map +1 -0
  225. package/lib/typescript/src/tema/estilos.d.ts +31 -0
  226. package/lib/typescript/src/tema/estilos.d.ts.map +1 -0
  227. package/lib/typescript/src/tema/fuentes.d.ts +20 -0
  228. package/lib/typescript/src/tema/fuentes.d.ts.map +1 -0
  229. package/lib/typescript/src/tema/index.d.ts +6 -0
  230. package/lib/typescript/src/tema/index.d.ts.map +1 -0
  231. package/lib/typescript/src/tema/paleta.d.ts +86 -0
  232. package/lib/typescript/src/tema/paleta.d.ts.map +1 -0
  233. package/lib/typescript/src/tema/tipografia.d.ts +29 -0
  234. package/lib/typescript/src/tema/tipografia.d.ts.map +1 -0
  235. package/lib/typescript/src/texto.d.ts +16 -0
  236. package/lib/typescript/src/texto.d.ts.map +1 -0
  237. package/package.json +135 -5
  238. package/src/componentes/AccionesDelEncabezado.tsx +247 -0
  239. package/src/componentes/BotonDeAvatar.tsx +59 -0
  240. package/src/componentes/BotonGrande.tsx +100 -0
  241. package/src/componentes/CabeceraEmpujada.tsx +69 -0
  242. package/src/componentes/Chip.tsx +60 -0
  243. package/src/componentes/ContenidoDePantalla.tsx +53 -0
  244. package/src/componentes/EstadoVacio.tsx +45 -0
  245. package/src/componentes/Foto.tsx +92 -0
  246. package/src/componentes/IconoDeRenglon.tsx +42 -0
  247. package/src/componentes/Logo.tsx +34 -0
  248. package/src/componentes/Nota.tsx +37 -0
  249. package/src/componentes/OpcionesExcluyentes.tsx +62 -0
  250. package/src/componentes/PantallaDeError.tsx +76 -0
  251. package/src/componentes/Pestanas.tsx +86 -0
  252. package/src/componentes/Rotulo.tsx +21 -0
  253. package/src/componentes/RotuloDeSeccion.tsx +71 -0
  254. package/src/componentes/Tarjeta.tsx +44 -0
  255. package/src/componentes/TarjetaDeDatos.tsx +62 -0
  256. package/src/componentes/TiraDeFotos.tsx +189 -0
  257. package/src/componentes/VisorDeFoto.tsx +181 -0
  258. package/src/componentes/logos/bola-blanca.png +0 -0
  259. package/src/componentes/logos/bola.png +0 -0
  260. package/src/componentes/logos/logo-blanco.png +0 -0
  261. package/src/componentes/logos/logo.png +0 -0
  262. package/src/dialogos/HostDeDialogos.tsx +172 -0
  263. package/src/dialogos/dialogos.ts +148 -0
  264. package/src/formularios/CampoDeSeleccion.tsx +46 -0
  265. package/src/formularios/SelectorDeOpcion.tsx +407 -0
  266. package/src/formularios/TextoDeAccesoControlado.tsx +72 -0
  267. package/src/formularios/campos.tsx +483 -0
  268. package/src/formularios/controlados.tsx +198 -0
  269. package/src/formularios/errores.ts +105 -0
  270. package/src/formularios/guardado.ts +76 -0
  271. package/src/formularios/useBusqueda.ts +19 -0
  272. package/src/fotos/elegir.ts +194 -0
  273. package/src/fotos/index.ts +15 -0
  274. package/src/fotos/reducir.ts +87 -0
  275. package/src/hoja/HojaInferior.tsx +102 -0
  276. package/src/hoja/index.ts +4 -0
  277. package/src/hoja/useMasDeLaFicha.tsx +63 -0
  278. package/src/index.ts +143 -0
  279. package/src/listas/HojaDeFiltros.tsx +261 -0
  280. package/src/listas/ListaPaginada.tsx +117 -0
  281. package/src/listas/TarjetaDeslizable.tsx +126 -0
  282. package/src/listas/paginado.ts +15 -0
  283. package/src/listas/piezas.tsx +594 -0
  284. package/src/navegacion/BarraDePestanas.tsx +198 -0
  285. package/src/navegacion/BotonDeBarra.tsx +61 -0
  286. package/src/navegacion/encabezado.tsx +88 -0
  287. package/src/pantallas/PantallaDeAcceso.tsx +184 -0
  288. package/src/pantallas/PantallaDeEdicion.tsx +116 -0
  289. package/src/pantallas/PantallaDeFicha.tsx +115 -0
  290. package/src/pantallas/PantallaDePerfil.tsx +126 -0
  291. package/src/tema/ProveedorDeTema.tsx +150 -0
  292. package/src/tema/estilos.ts +51 -0
  293. package/src/tema/fuentes.ts +20 -0
  294. package/src/tema/index.ts +10 -0
  295. package/src/tema/paleta.ts +147 -0
  296. package/src/tema/tipografia.ts +29 -0
  297. package/src/texto.tsx +44 -0
@@ -0,0 +1,115 @@
1
+ import React from "react";
2
+ import { ActivityIndicator, RefreshControl, ScrollView, View } from "react-native";
3
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
4
+ import type { AccionDelEncabezado } from "../componentes/AccionesDelEncabezado";
5
+ import BotonGrande from "../componentes/BotonGrande";
6
+ import CabeceraEmpujada from "../componentes/CabeceraEmpujada";
7
+ import EstadoVacio from "../componentes/EstadoVacio";
8
+ import { crearEstilos, usePaleta } from "../tema";
9
+
10
+ /** Lo que la ficha lee de un `use…Query` de RTK Query. */
11
+ interface ConsultaDeFicha {
12
+ isLoading: boolean;
13
+ isError: boolean;
14
+ isFetching: boolean;
15
+ refetch: () => unknown;
16
+ error?: unknown;
17
+ }
18
+
19
+ const esNoEncontrado = (error: unknown) =>
20
+ typeof error === "object" && error !== null && "status" in error && error.status === 404;
21
+
22
+ /**
23
+ * Una ficha de solo lectura (un viaje, un tracto, un cliente): la cabecera con atrás, y lo suyo en
24
+ * un scroll que se refresca jalando hacia abajo. Mientras carga, o si falla, lo dice en vez de
25
+ * pintar vacía.
26
+ *
27
+ * `children` sólo se pinta con datos: quien la usa no tiene que preguntar si ya llegaron.
28
+ */
29
+ export default function PantallaDeFicha({
30
+ eyebrow,
31
+ titulo,
32
+ consulta,
33
+ hayDatos,
34
+ acciones,
35
+ estado,
36
+ encima,
37
+ children,
38
+ }: {
39
+ eyebrow: string;
40
+ titulo: string;
41
+ /** El estado de la ficha bajo su título (un `Chip`); sólo con datos. */
42
+ estado?: React.ReactNode;
43
+ /** Las acciones de la ficha, en su encabezado; sólo se ofrecen con datos. */
44
+ acciones?: AccionDelEncabezado[];
45
+ /**
46
+ * Lo que va encima de la ficha y no dentro de su scroll: sus hojas inferiores
47
+ * (`HojaInferior`) y diálogos. Sólo con datos.
48
+ */
49
+ encima?: React.ReactNode;
50
+ consulta: ConsultaDeFicha;
51
+ hayDatos: boolean;
52
+ children: React.ReactNode;
53
+ }) {
54
+ const c = usePaleta();
55
+ const styles = useStyles();
56
+ const insets = useSafeAreaInsets();
57
+
58
+ let cuerpo: React.ReactNode;
59
+ if (consulta.isLoading) {
60
+ cuerpo = <ActivityIndicator color={c.primary} size="large" style={styles.cargando} />;
61
+ } else if (!hayDatos) {
62
+ cuerpo = esNoEncontrado(consulta.error) ? (
63
+ <EstadoVacio
64
+ icono="file-hidden"
65
+ titulo="No existe"
66
+ texto="Puede que lo hayan borrado, o que no tengas permiso de verlo."
67
+ />
68
+ ) : (
69
+ <EstadoVacio
70
+ icono="cloud-off-outline"
71
+ titulo="No se pudo cargar"
72
+ texto="Revisa tu señal e intenta de nuevo."
73
+ >
74
+ <BotonGrande icono="refresh" onPress={() => consulta.refetch()}>
75
+ Reintentar
76
+ </BotonGrande>
77
+ </EstadoVacio>
78
+ );
79
+ } else {
80
+ cuerpo = (
81
+ <ScrollView
82
+ contentContainerStyle={[styles.contenido, { paddingBottom: insets.bottom + 24 }]}
83
+ refreshControl={
84
+ <RefreshControl
85
+ refreshing={consulta.isFetching && !consulta.isLoading}
86
+ onRefresh={() => consulta.refetch()}
87
+ colors={[c.primary]}
88
+ progressBackgroundColor={c.superficie}
89
+ />
90
+ }
91
+ >
92
+ {children}
93
+ </ScrollView>
94
+ );
95
+ }
96
+
97
+ return (
98
+ <View style={styles.root}>
99
+ <CabeceraEmpujada
100
+ eyebrow={eyebrow}
101
+ titulo={titulo}
102
+ acciones={hayDatos ? acciones : undefined}
103
+ estado={hayDatos ? estado : undefined}
104
+ />
105
+ {cuerpo}
106
+ {hayDatos ? encima : null}
107
+ </View>
108
+ );
109
+ }
110
+
111
+ const useStyles = crearEstilos((c) => ({
112
+ root: { flex: 1, backgroundColor: c.fondo },
113
+ cargando: { marginTop: 40 },
114
+ contenido: { padding: 16, gap: 20 },
115
+ }));
@@ -0,0 +1,126 @@
1
+ import React from "react";
2
+ import { ScrollView, View } from "react-native";
3
+ import { Avatar, Button, Card } from "react-native-paper";
4
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
5
+ import CabeceraEmpujada from "../componentes/CabeceraEmpujada";
6
+ import ContenidoDePantalla from "../componentes/ContenidoDePantalla";
7
+ import Pestanas, { type Pestana } from "../componentes/Pestanas";
8
+ import {
9
+ crearEstilos,
10
+ renglon,
11
+ tipografia,
12
+ usePreferenciaDeTema,
13
+ type PreferenciaDeTema,
14
+ } from "../tema";
15
+ import { Text } from "../texto";
16
+
17
+ /**
18
+ * La apariencia: **igual que el teléfono** por omisión, o fija. Tres opciones y no un interruptor de
19
+ * «modo oscuro», como el del portal: con un interruptor, quien lo toca una vez ya no vuelve a seguir
20
+ * al teléfono.
21
+ */
22
+ const APARIENCIAS: Pestana<PreferenciaDeTema>[] = [
23
+ { key: "sistema", label: "Teléfono", icono: "cellphone" },
24
+ { key: "claro", label: "Claro", icono: "white-balance-sunny" },
25
+ { key: "oscuro", label: "Oscuro", icono: "weather-night" },
26
+ ];
27
+
28
+ /**
29
+ * El perfil de una app, igual en todas: quién entró, cómo se ve la app y cerrar sesión. Va
30
+ * empujado encima de las pestañas (lo abre el avatar del header). Necesita `ProveedorDeTema`.
31
+ *
32
+ * Lo propio de cada app va por props: quién es, qué pasa al cerrar sesión (avisar si hay envíos
33
+ * pendientes, confirmar) y, en `children`, lo que vaya al final (la versión instalada).
34
+ */
35
+ export default function PantallaDePerfil({
36
+ rotulo,
37
+ nombre,
38
+ subtitulo,
39
+ onCerrarSesion,
40
+ saliendo = false,
41
+ children,
42
+ }: {
43
+ /** Qué tipo de sesión es («Operador», «Guardia de caseta»): el rótulo de la cabecera. */
44
+ rotulo: string;
45
+ nombre?: string | null;
46
+ /** El usuario, el número de empleado. */
47
+ subtitulo?: string | null;
48
+ onCerrarSesion: () => void;
49
+ saliendo?: boolean;
50
+ children?: React.ReactNode;
51
+ }) {
52
+ const styles = useStyles();
53
+ const [tema, setTema] = usePreferenciaDeTema();
54
+ const insets = useSafeAreaInsets();
55
+
56
+ return (
57
+ <View style={styles.root}>
58
+ <CabeceraEmpujada eyebrow={rotulo} titulo="Perfil" />
59
+
60
+ <ContenidoDePantalla paddingBottom={insets.bottom + 20}>
61
+ <ScrollView
62
+ contentContainerStyle={styles.contenido}
63
+ keyboardShouldPersistTaps="handled"
64
+ >
65
+ <Card mode={"outlined"} style={styles.card}>
66
+ {/* Paper recorta título y subtítulo a un renglón por omisión: un nombre
67
+ largo con la letra al 180% se perdía. */}
68
+ <Card.Title
69
+ title={nombre || "N/A"}
70
+ titleVariant={"titleLarge"}
71
+ titleStyle={{ fontWeight: "bold" }}
72
+ titleNumberOfLines={0}
73
+ subtitleNumberOfLines={0}
74
+ subtitleStyle={renglon(tipografia.secundario)}
75
+ subtitle={subtitulo || "N/A"}
76
+ subtitleVariant={"bodySmall"}
77
+ left={(props) => (
78
+ <Avatar.Text
79
+ {...props}
80
+ label={(nombre || "?").charAt(0).toUpperCase()}
81
+ color="#ffffff"
82
+ />
83
+ )}
84
+ />
85
+ </Card>
86
+
87
+ <View style={styles.apariencia}>
88
+ <Text style={styles.rotulo}>Apariencia</Text>
89
+ <Pestanas pestanas={APARIENCIAS} activa={tema} onSelect={setTema} />
90
+ </View>
91
+
92
+ {/* El tope de ancho vive en este View y no en el Button: el Surface de
93
+ Paper reparte el estilo en dos capas anidadas en iOS y `maxWidth` cae
94
+ en la de adentro, que queda pegada a la izquierda. */}
95
+ <View style={styles.acciones}>
96
+ <Button
97
+ onPress={onCerrarSesion}
98
+ mode={"contained"}
99
+ icon={"logout"}
100
+ loading={saliendo}
101
+ disabled={saliendo}
102
+ >
103
+ Cerrar sesión
104
+ </Button>
105
+ </View>
106
+ {children}
107
+ </ScrollView>
108
+ </ContenidoDePantalla>
109
+ </View>
110
+ );
111
+ }
112
+
113
+ const useStyles = crearEstilos((c) => ({
114
+ root: { flex: 1, backgroundColor: c.fondo },
115
+ contenido: { gap: 20, alignItems: "center" },
116
+ card: { width: "100%", backgroundColor: c.superficie, borderColor: c.secondaryLighter },
117
+ acciones: { width: "100%", maxWidth: 300, gap: 20 },
118
+ apariencia: { width: "100%", gap: 8 },
119
+ rotulo: {
120
+ ...renglon(tipografia.etiqueta),
121
+ fontWeight: "800",
122
+ color: c.secondary,
123
+ textTransform: "uppercase",
124
+ letterSpacing: 0.8,
125
+ },
126
+ }));
@@ -0,0 +1,150 @@
1
+ import { StatusBar } from "expo-status-bar";
2
+ import React from "react";
3
+ import { Appearance } from "react-native";
4
+ import { configureFonts, MD3DarkTheme, MD3LightTheme, PaperProvider } from "react-native-paper";
5
+ import { useEsOscuro, useFondoDeLaRaiz } from "./estilos";
6
+ import { fontFamily } from "./fuentes";
7
+ import { PALETA_CLARA, PALETA_OSCURA, type Paleta } from "./paleta";
8
+
9
+ /**
10
+ * Cómo quiere ver la app quien la usa: **igual que el teléfono** (por omisión), o siempre clara, o
11
+ * siempre oscura. Es del teléfono y no de la cuenta: sobrevive al cerrar sesión.
12
+ */
13
+ export type PreferenciaDeTema = "sistema" | "claro" | "oscuro";
14
+
15
+ const PREFERENCIAS: readonly PreferenciaDeTema[] = ["sistema", "claro", "oscuro"];
16
+
17
+ /**
18
+ * Dónde guarda cada app la preferencia (SecureStore, AsyncStorage…). `leer` puede devolver
19
+ * cualquier cosa: lo que no sea una preferencia válida cuenta como `"sistema"`.
20
+ */
21
+ export interface AlmacenDelTema {
22
+ leer: () => Promise<string | null | undefined>;
23
+ guardar: (preferencia: PreferenciaDeTema) => Promise<unknown>;
24
+ }
25
+
26
+ /**
27
+ * Pone la preferencia **en toda la app nativa** (`Appearance.setColorScheme`), no sólo en lo que
28
+ * pinta React: así `useColorScheme` ya contesta la elegida, y lo nativo —un mapa de Google, el
29
+ * selector de fecha, la barra de estado— la sigue sin que nadie se la pase. «Igual que el teléfono»
30
+ * es quitar la imposición.
31
+ */
32
+ const aplicar = (preferencia: PreferenciaDeTema) =>
33
+ Appearance.setColorScheme(
34
+ preferencia === "claro" ? "light" : preferencia === "oscuro" ? "dark" : "unspecified",
35
+ );
36
+
37
+ // La escala tipográfica de Paper trae `System` en iOS y `sans-serif` en Android; en Android se
38
+ // cambia la familia por Inter y se conservan tamaños y pesos de cada variante. Los `Text` de
39
+ // React Native no leen el tema: esos van por `texto.tsx`.
40
+ const fonts = fontFamily ? configureFonts({ config: { fontFamily } }) : MD3LightTheme.fonts;
41
+
42
+ /**
43
+ * El tema de Paper de cada modo, con los colores de la paleta: los componentes de Paper (Card,
44
+ * Button, Avatar, Menu) no leen la paleta, leen esto.
45
+ */
46
+ const temaDePaper = (base: typeof MD3LightTheme, c: Paleta) => ({
47
+ ...base,
48
+ fonts,
49
+ colors: {
50
+ ...base.colors,
51
+ primary: c.primary,
52
+ onPrimary: c.sobrePrimario,
53
+ primaryLight: c.primaryLight,
54
+ primaryLighter: c.primaryLighter,
55
+ primaryDark: c.primaryDark,
56
+
57
+ secondary: c.secondary,
58
+ secondaryLight: c.secondaryLight,
59
+ secondaryLighter: c.secondaryLighter,
60
+ secondaryDark: c.secondaryDark,
61
+
62
+ background: c.fondo,
63
+ surface: c.superficie,
64
+ onSurface: c.texto,
65
+ outline: c.secondaryLighter,
66
+ surfacePrimary: c.superficie,
67
+ },
68
+ });
69
+
70
+ const TEMA_CLARO = temaDePaper(MD3LightTheme, PALETA_CLARA);
71
+ const TEMA_OSCURO = temaDePaper(MD3DarkTheme, PALETA_OSCURA);
72
+
73
+ type ContextoDelTema = [PreferenciaDeTema, (preferencia: PreferenciaDeTema) => void];
74
+
75
+ const Contexto = React.createContext<ContextoDelTema | null>(null);
76
+
77
+ /**
78
+ * El tema de la app: lee la preferencia guardada, se la impone a lo nativo, y da el tema de Paper,
79
+ * la barra de estado y el fondo de la raíz de ahora. Va en el layout raíz, por encima de todo lo
80
+ * que pinta.
81
+ *
82
+ * **No pinta nada hasta leer la preferencia**: así no se asoma el claro un momento en quien eligió
83
+ * el oscuro. Leerla es una consulta local, no se nota.
84
+ */
85
+ export function ProveedorDeTema({
86
+ almacen,
87
+ children,
88
+ }: {
89
+ /** Sin almacén, la preferencia dura lo que dure la app abierta. */
90
+ almacen?: AlmacenDelTema;
91
+ children: React.ReactNode;
92
+ }) {
93
+ const [preferencia, setPreferencia] = React.useState<PreferenciaDeTema | null>(
94
+ almacen ? null : "sistema",
95
+ );
96
+ const oscuro = useEsOscuro();
97
+ useFondoDeLaRaiz((oscuro ? PALETA_OSCURA : PALETA_CLARA).fondo);
98
+
99
+ React.useEffect(() => {
100
+ if (!almacen) return;
101
+ let vigente = true;
102
+ almacen
103
+ .leer()
104
+ .catch(() => null)
105
+ .then((guardada) => {
106
+ if (!vigente) return;
107
+ const valida = PREFERENCIAS.find((p) => p === guardada) ?? "sistema";
108
+ aplicar(valida);
109
+ setPreferencia(valida);
110
+ });
111
+ return () => {
112
+ vigente = false;
113
+ };
114
+ // Se lee una sola vez, al arrancar: un almacén nuevo en cada render no la vuelve a leer.
115
+ // eslint-disable-next-line react-hooks/exhaustive-deps
116
+ }, []);
117
+
118
+ const valor = React.useMemo<ContextoDelTema | null>(
119
+ () =>
120
+ preferencia === null
121
+ ? null
122
+ : [
123
+ preferencia,
124
+ (nueva) => {
125
+ aplicar(nueva);
126
+ setPreferencia(nueva);
127
+ almacen?.guardar(nueva).catch(() => {});
128
+ },
129
+ ],
130
+ [preferencia, almacen],
131
+ );
132
+
133
+ if (!valor) return null;
134
+
135
+ return (
136
+ <Contexto.Provider value={valor}>
137
+ <PaperProvider theme={oscuro ? TEMA_OSCURO : TEMA_CLARO}>
138
+ <StatusBar style={oscuro ? "light" : "dark"} />
139
+ {children}
140
+ </PaperProvider>
141
+ </Contexto.Provider>
142
+ );
143
+ }
144
+
145
+ /** La preferencia del tema y cómo cambiarla (el perfil). Sólo dentro de `ProveedorDeTema`. */
146
+ export function usePreferenciaDeTema(): ContextoDelTema {
147
+ const valor = React.useContext(Contexto);
148
+ if (!valor) throw new Error("usePreferenciaDeTema va dentro de <ProveedorDeTema>.");
149
+ return valor;
150
+ }
@@ -0,0 +1,51 @@
1
+ import * as SystemUI from "expo-system-ui";
2
+ import { useEffect } from "react";
3
+ import { StyleSheet, useColorScheme } from "react-native";
4
+ import { PALETA_CLARA, PALETA_OSCURA, type Paleta } from "./paleta";
5
+
6
+ /**
7
+ * Si la app se ve oscura. Lee `useColorScheme` y no un contexto: `ProveedorDeTema` le impone la
8
+ * preferencia a toda la app nativa (`Appearance.setColorScheme`), así que contesta la elegida, o la
9
+ * del teléfono con «igual que el teléfono». Y así sirve también fuera de los proveedores, en la
10
+ * pantalla de error del layout raíz.
11
+ */
12
+ export const useEsOscuro = (): boolean => useColorScheme() === "dark";
13
+
14
+ /** Los colores de ahora (`paleta.ts`). */
15
+ export const usePaleta = (): Paleta => (useEsOscuro() ? PALETA_OSCURA : PALETA_CLARA);
16
+
17
+ /**
18
+ * Hojas de estilo que dependen del tema. Se declaran igual que un `StyleSheet.create`, pero con la
19
+ * paleta como argumento, y dan un hook:
20
+ *
21
+ * ```ts
22
+ * const useStyles = crearEstilos((c) => ({ caja: { backgroundColor: c.superficie } }));
23
+ * // en el componente:
24
+ * const styles = useStyles();
25
+ * ```
26
+ *
27
+ * Cada hoja se crea una vez por paleta y se guarda: cambiar de tema no la vuelve a crear en cada
28
+ * render.
29
+ */
30
+ export function crearEstilos<T extends StyleSheet.NamedStyles<T>>(fabrica: (c: Paleta) => T) {
31
+ const hojas = new Map<Paleta, T>();
32
+ return function useEstilos(): T {
33
+ const c = usePaleta();
34
+ let hoja = hojas.get(c);
35
+ if (!hoja) {
36
+ hoja = StyleSheet.create(fabrica(c));
37
+ hojas.set(c, hoja);
38
+ }
39
+ return hoja;
40
+ };
41
+ }
42
+
43
+ /**
44
+ * El fondo de la raíz nativa (lo que se ve detrás de una transición) sigue al tema: sin esto, al
45
+ * empujar una pantalla en oscuro se asomaba un destello blanco.
46
+ */
47
+ export function useFondoDeLaRaiz(fondo: string) {
48
+ useEffect(() => {
49
+ SystemUI.setBackgroundColorAsync(fondo).catch(() => {});
50
+ }, [fondo]);
51
+ }
@@ -0,0 +1,20 @@
1
+ import { Platform } from "react-native";
2
+
3
+ /**
4
+ * La tipografía de iOS es San Francisco —lo que React Native llama `System`— y no se puede
5
+ * llevar a Android: la licencia de Apple la limita a sus plataformas. Android se quedaba con
6
+ * `sans-serif` (Roboto), de ahí que las dos versiones no se parecieran.
7
+ *
8
+ * Inter es el sustituto libre (OFL) más cercano a San Francisco: misma altura de x, mismo
9
+ * aire de fuente de interfaz. Así que Android va con Inter e iOS se queda como está.
10
+ *
11
+ * Los seis cortes —de 400 a 900, que son los pesos que usan las pantallas— vienen en
12
+ * `assets/fonts/` de este paquete y **cada app los registra** como una sola familia en su
13
+ * `app.json` (plugin de expo-font, sección `android.fonts`; ver el README). Al declarar cada peso
14
+ * con su archivo, `fontWeight: "600"` toma el SemiBold de verdad en vez de una negrita sintética.
15
+ * Tocar esa lista obliga a reconstruir el binario, no basta con recargar.
16
+ */
17
+ export const fontFamily = Platform.select({ android: "Inter", default: undefined });
18
+
19
+ /** Familia lista para mezclar en un `style`; `null` donde vale la del sistema. */
20
+ export const fuenteBase = fontFamily ? { fontFamily } : null;
@@ -0,0 +1,10 @@
1
+ export { crearEstilos, useEsOscuro, useFondoDeLaRaiz, usePaleta } from "./estilos";
2
+ export { fontFamily, fuenteBase } from "./fuentes";
3
+ export { PALETA_CLARA, PALETA_OSCURA, type Paleta } from "./paleta";
4
+ export {
5
+ ProveedorDeTema,
6
+ usePreferenciaDeTema,
7
+ type AlmacenDelTema,
8
+ type PreferenciaDeTema,
9
+ } from "./ProveedorDeTema";
10
+ export { renglon, tipografia } from "./tipografia";
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Los colores de las apps, **uno por cosa y no por tono**: el fondo, la superficie de una tarjeta,
3
+ * el texto, el aviso ámbar. Cada pantalla los toma de aquí (`usePaleta`, `crearEstilos`) y no
4
+ * escribe hexadecimales: así el modo oscuro es cambiar de paleta, no revisar cada pantalla.
5
+ *
6
+ * Los nombres `primary…`/`secondary…` son los del `colors` que traían las apps antes de la paleta,
7
+ * con el mismo sentido. Lo oscuro sigue al portal (`@acvl/frontend-components`, `v1/theme`): fondo
8
+ * `#121212`, papel `#1e1e1e` y el rojo más claro `#ff4a57`, que sobre negro se lee mejor que el de
9
+ * la marca.
10
+ *
11
+ * Lo que se pinta dentro de un mapa (los colores de estado de una flota, un pin) no sale de aquí:
12
+ * tiene que leerse igual sobre claro, oscuro y satélite, y lo escoge cada app.
13
+ */
14
+ export interface Paleta {
15
+ esOscuro: boolean;
16
+
17
+ /** El fondo de la pantalla, detrás de las tarjetas. */
18
+ fondo: string;
19
+ /** Una tarjeta, un campo, una hoja, el header y la barra de pestañas. */
20
+ superficie: string;
21
+ /** Lo que va encima de una superficie y se tiene que distinguir de ella (un campo apagado). */
22
+ superficieTenue: string;
23
+ /** El texto normal. */
24
+ texto: string;
25
+ /** El texto que va sobre el rojo (un botón lleno, el chip «En curso»). */
26
+ sobrePrimario: string;
27
+ /** El velo detrás de un diálogo. */
28
+ velo: string;
29
+ /** La sombra: en oscuro casi no se ve, así que el borde hace su trabajo. */
30
+ sombra: string;
31
+
32
+ // Los de `colors`, con el mismo sentido.
33
+ primary: string;
34
+ primaryLight: string;
35
+ primaryLighter: string;
36
+ primaryDark: string;
37
+ /** El fondo de lo elegido. */
38
+ primaryWash: string;
39
+ /** El texto secundario. */
40
+ secondary: string;
41
+ /** El texto tenue: un placeholder, un icono apagado. */
42
+ secondaryLight: string;
43
+ /** Los bordes y separadores. */
44
+ secondaryLighter: string;
45
+ /** El gris fuerte: un título gris, el texto de un estado vacío. */
46
+ secondaryDark: string;
47
+ secondaryText: string;
48
+ /** El rótulo arriba del título del header. */
49
+ eyebrow: string;
50
+
51
+ /**
52
+ * Lo que pide atención sin ser error: pausas, pendientes, avisos. `acento` es el ámbar medio de
53
+ * un borde o una barra; `sobreFuerte`, la letra encima de un relleno `fuerte`.
54
+ */
55
+ aviso: {
56
+ fondo: string;
57
+ tinta: string;
58
+ fuerte: string;
59
+ acento: string;
60
+ sobreFuerte: string;
61
+ borde: string;
62
+ };
63
+ /** Lo cumplido. */
64
+ exito: { fondo: string; tinta: string };
65
+ /** Lo informativo. */
66
+ info: { fondo: string; tinta: string };
67
+ /** Lo que salió mal. */
68
+ error: { fondo: string; tinta: string };
69
+ /**
70
+ * Un escalón más de un avance que ya usa los otros: en wms, una orden de envío facturada
71
+ * (todavía no pagada, que es el verde) o un recibo entregado a medias. Es el morado que el
72
+ * portal le da a la orden de envío.
73
+ */
74
+ morado: { fondo: string; tinta: string };
75
+ }
76
+
77
+ export const PALETA_CLARA: Paleta = {
78
+ esOscuro: false,
79
+ fondo: "#f7f7f7",
80
+ superficie: "#ffffff",
81
+ superficieTenue: "#f1f1f1",
82
+ texto: "#1a1a1a",
83
+ sobrePrimario: "#ffffff",
84
+ velo: "rgba(0,0,0,0.45)",
85
+ sombra: "#000000",
86
+
87
+ primary: "#ea1b2b",
88
+ primaryLight: "rgb(242, 118, 127)",
89
+ primaryLighter: "rgb(250, 209, 212)",
90
+ primaryDark: "rgb(163, 18, 30)",
91
+ primaryWash: "rgba(234,27,43,0.08)",
92
+ secondary: "#606060",
93
+ secondaryLight: "rgb(159, 159, 159)",
94
+ secondaryLighter: "rgb(231, 231, 231)",
95
+ secondaryDark: "rgb(67, 67, 67)",
96
+ secondaryText: "#3a3d42",
97
+ eyebrow: "#4B5563",
98
+
99
+ aviso: {
100
+ fondo: "#fff8e1",
101
+ tinta: "#8a5300",
102
+ fuerte: "#b26a00",
103
+ acento: "#f5b955",
104
+ sobreFuerte: "#ffffff",
105
+ borde: "#ffe0a3",
106
+ },
107
+ exito: { fondo: "#e8f5e9", tinta: "#2e7d32" },
108
+ info: { fondo: "#e3f2fd", tinta: "#1565c0" },
109
+ error: { fondo: "#fdecea", tinta: "#c62828" },
110
+ morado: { fondo: "#f1e9fd", tinta: "#5b21b6" },
111
+ };
112
+
113
+ export const PALETA_OSCURA: Paleta = {
114
+ esOscuro: true,
115
+ fondo: "#121212",
116
+ superficie: "#1e1e1e",
117
+ superficieTenue: "#2a2a2a",
118
+ texto: "#f2f2f2",
119
+ sobrePrimario: "#ffffff",
120
+ velo: "rgba(0,0,0,0.65)",
121
+ sombra: "#000000",
122
+
123
+ primary: "#ff4a57",
124
+ primaryLight: "rgb(255, 128, 137)",
125
+ primaryLighter: "rgb(90, 24, 30)",
126
+ primaryDark: "#ea1b2b",
127
+ primaryWash: "rgba(255,74,87,0.16)",
128
+ secondary: "#b3b3b3",
129
+ secondaryLight: "#8c8c8c",
130
+ secondaryLighter: "#3a3a3a",
131
+ secondaryDark: "#d6d6d6",
132
+ secondaryText: "#c9ccd1",
133
+ eyebrow: "#a8b0bd",
134
+
135
+ aviso: {
136
+ fondo: "#3a2e12",
137
+ tinta: "#ffcc80",
138
+ fuerte: "#ffb74d",
139
+ acento: "#c9932f",
140
+ sobreFuerte: "#1e1e1e",
141
+ borde: "#6b5320",
142
+ },
143
+ exito: { fondo: "#1b3320", tinta: "#81c784" },
144
+ info: { fondo: "#132a40", tinta: "#90caf9" },
145
+ error: { fondo: "#3d1a1a", tinta: "#ff8a80" },
146
+ morado: { fondo: "#2a1d45", tinta: "#c4b5fd" },
147
+ };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Los tamaños de letra de las apps. Son grandes a propósito: quien las usa lee de pie, con prisa, a
3
+ * veces con sol y sin lentes, y la letra chica es donde batalla. **Nada baja de `etiqueta`.** Una
4
+ * pantalla nueva toma de aquí en lugar de inventar su número.
5
+ */
6
+ export const tipografia = {
7
+ /** La acción que toca completar: lo único que tiene que leerse de un vistazo. */
8
+ destacado: 32,
9
+ /** El folio y lo que identifica la pantalla. */
10
+ titulo: 24,
11
+ /** El nombre de un paso, el cliente: lo que se lee primero dentro de una tarjeta. */
12
+ subtitulo: 21,
13
+ /** El texto normal: valores, instrucciones, el lugar. */
14
+ cuerpo: 19,
15
+ /** Lo que acompaña: direcciones, el siguiente paso, horas. */
16
+ secundario: 17,
17
+ /** Rótulos en mayúsculas, chips y pestañas. El mínimo. */
18
+ etiqueta: 15,
19
+ };
20
+
21
+ /**
22
+ * Tamaño y alto de renglón explícito para un texto que lleva un icono al lado. `IconoDeRenglon`
23
+ * usa el mismo alto para centrarse contra el primer renglón; los dos crecen con la escala de
24
+ * letra del sistema.
25
+ */
26
+ export const renglon = (fontSize: number) => ({
27
+ fontSize,
28
+ lineHeight: Math.round(fontSize * 1.3),
29
+ });