mobile-design 0.1.1 → 0.1.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 (3) hide show
  1. package/COMPONENTS.md +3049 -1626
  2. package/README.md +53 -242
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -4,9 +4,9 @@
4
4
 
5
5
  Componentes Material Design 3 para React Native y React Native Web. El paquete integra el tema, las fuentes y los componentes sobre React Native Paper.
6
6
 
7
- [Instalación](#instalación-desde-npm) · [Primer componente](#primer-componente) · [Proveedor](#configurar-el-proveedor) · [Temas y colores](#temas-y-colores) · [Iconos](#tipografía-e-iconos) · [Componentes](#referencia-de-componentes)
7
+ [Instalación](#instalación-desde-npm) · [Dependencias](#para-qué-sirve-cada-dependencia) · [Primer componente](#primer-componente) · [Proveedor](#configurar-el-proveedor) · [Temas y colores](#temas-y-colores) · [Tipografía e iconos](#tipografía-e-iconos) · [Índice de componentes](#índice-de-componentes)
8
8
 
9
- La referencia detallada de propiedades, configuraciones y ejemplos se incluye como `COMPONENTS.md` en el paquete. [Referencia completa de componentes en la versión 0.1.1](https://cdn.jsdelivr.net/npm/mobile-design@0.1.1/COMPONENTS.md)
9
+ La referencia detallada de propiedades y ejemplos viaja con el paquete. Puedes abrir `node_modules/mobile-design/COMPONENTS.md` para consultar la versión instalada. [Referencia en este código fuente](COMPONENTS.md) · [Referencia de la versión publicada](https://cdn.jsdelivr.net/npm/mobile-design@latest/COMPONENTS.md)
10
10
 
11
11
  ## Instalación desde npm
12
12
 
@@ -31,6 +31,34 @@ npx expo start --web
31
31
 
32
32
  `mobile-design` instala `@mobile-design/tokens` como dependencia e incluye Roboto y los símbolos MD3 que necesitan los componentes. Con estas versiones se verificaron TypeScript, la exportación de Metro en Android, iOS y web, y el renderizado de fuentes y símbolos en Chromium con dependencias públicas.
33
33
 
34
+ ### Para qué sirve cada dependencia
35
+
36
+ Los *peers* forman parte de la configuración de la app. Los comandos anteriores fijan las versiones probadas. En una app Expo, el SDK ya determina las versiones de `react` y `react-native`.
37
+
38
+ | Paquete | Dónde se necesita | Qué aporta |
39
+ | --- | --- | --- |
40
+ | `mobile-design` | Android, iOS y web | Componentes, proveedor MD3, Roboto y los símbolos incluidos. |
41
+ | `@mobile-design/tokens` | Se instala con `mobile-design` | Paletas clara y oscura, tamaños, tipografía y movimiento. Se puede instalar solo si tu app consume únicamente los valores. |
42
+ | `expo` | App Expo o proyecto React Native con módulos Expo configurados | Integra los módulos Expo como fuentes e imágenes. Metro procesa el TypeScript que distribuye el paquete. |
43
+ | `react` | Peer común | Estado, hooks y composición de componentes. |
44
+ | `react-native` | Peer común | Vistas, estilos, accesibilidad y eventos. En web, Metro resuelve los hosts mediante React Native Web. |
45
+ | `react-native-paper` | Peer común | Tema base, iconos por nombre, dirección de lectura, portal y primitivas como `Avatar` y `TouchableRipple`. |
46
+ | `expo-font` | Peer común | Registra Roboto y la fuente de símbolos. También carga las familias que aporta tu app. |
47
+ | `expo-image` | Peer común | Renderiza las imágenes de `Carousel` y `FullScreenCarousel`. |
48
+ | `react-native-gesture-handler` | Peer común | Gestos de arrastre y desplazamiento en hojas, sliders, listas y otros controles. Monta `GestureHandlerRootView` en la raíz. |
49
+ | `react-native-reanimated` | Peer común | Valores compartidos, transiciones de estado y animaciones de los componentes. |
50
+ | `react-native-worklets` | Peer común | Ejecuta callbacks de gestos y animación en UI y comunica resultados al estado de React. |
51
+ | `react-native-safe-area-context` | Peer común | Proporciona los bordes seguros para barras y superficies superpuestas. Monta `SafeAreaProvider` en la raíz. |
52
+ | `react-native-svg` | Peer común | Dibuja indicadores de progreso y las rutas SVG de símbolos disponibles antes de cargar la fuente. |
53
+ | `@gorhom/bottom-sheet` | Peer común | Motor de `BottomSheet` y sus listas, scroll y campos de texto coordinados con el teclado. |
54
+ | `react-dom` | Peer de web | Monta el árbol de React en el DOM. |
55
+ | `react-native-web` | Peer de web | Traduce las primitivas React Native a elementos y eventos del navegador. |
56
+ | `@expo/metro-runtime` | App Expo con Metro en web | Runtime para los bundles web de Expo. Se instala en la app. |
57
+ | `@mobile-design/icons` | Opcional en las tres plataformas | Catálogo completo de Material Symbols Rounded. Instala la versión que corresponda a `mobile-design`. |
58
+ | `@expo/vector-icons` | Opcional en las tres plataformas | Proveedor alternativo si tu app elige, por ejemplo, Ionicons. |
59
+
60
+ ### Elegir la entrada del paquete
61
+
34
62
  | Entrada | Cuándo usarla |
35
63
  | --- | --- |
36
64
  | `mobile-design/react-native` | Android e iOS. |
@@ -89,18 +117,18 @@ export default function App() {
89
117
 
90
118
  Monta un `MobileDesignProvider` en la raíz para compartir el tema, la dirección de lectura y los portales. `GestureHandlerRootView` da soporte a los gestos y `SafeAreaProvider` permite a las barras y hojas respetar los bordes de la pantalla. Mantén ambos por fuera del proveedor.
91
119
 
92
- | Propiedad | Valores y comportamiento |
93
- | --- | --- |
94
- | `children` | Pantallas y componentes que consumen el tema y el host de `Portal`. |
95
- | `colorScheme` | `'light'` o `'dark'`. Si se omite, el proveedor sigue el esquema del sistema y usa claro cuando el sistema no declara modo oscuro. |
96
- | `theme` | Tema parcial de Paper. Fusiona por rol objetos como `colors`, `fonts`, `shapes`, `elevation` y `motion`. `theme.dark` explícito prevalece sobre `colorScheme`. |
97
- | `fontFamily` | Nombre de una familia registrada. Por defecto usa `'Roboto'`. Aplica la familia a la escala tipográfica y puedes ajustar un estilo concreto con `theme.fonts`. |
98
- | `languageHeight` | `'small'`, `'medium'`, `'large'` o `'extraLarge'`. El valor inicial es `'small'`. Cambia el interlineado de los estilos MD3 base y enfatizados. |
99
- | `motion` | `'expressive'` o `'standard'`. El valor inicial es `'expressive'`. Selecciona el perfil de los resortes espaciales. |
100
- | `reduceMotion` | `'auto'`, `'on'` u `'off'`. El valor inicial es `'auto'` y sigue la preferencia del sistema. |
101
- | `direction` | `'ltr'` o `'rtl'`. Si se omite, Paper usa la dirección del entorno. |
102
- | `settings.icon` | Renderizador para iconos pedidos por nombre. Por defecto usa los Material Symbols del paquete base. |
103
- | `settings.rippleEffectEnabled` | Habilita el ripple en los controles que consultan este ajuste. Paper lo habilita de forma predeterminada. |
120
+ | Propiedad | Valores y comportamiento | Ejemplo |
121
+ | --- | --- | --- |
122
+ | `children` | Pantallas y componentes que consumen el tema y el host de `Portal`. | `<MobileDesignProvider><Button>Guardar</Button></MobileDesignProvider>` |
123
+ | `colorScheme` | `'light'` o `'dark'`. Si se omite, el proveedor sigue el esquema del sistema y usa claro cuando el sistema no declara modo oscuro. | `colorScheme="dark"` para una vista previa fija. |
124
+ | `theme` | Tema parcial de Paper. Fusiona por rol objetos como `colors`, `fonts`, `shapes`, `elevation` y `motion`. `theme.dark` explícito prevalece sobre `colorScheme`. | `theme={{ fonts: { titleLarge: { fontWeight: '700' } } }}` para enfatizar los títulos grandes. |
125
+ | `fontFamily` | Nombre de una familia registrada. Por defecto usa `'Roboto'`. Aplica la familia a la escala tipográfica y puedes ajustar un estilo concreto con `theme.fonts`. | `fontFamily="Inter"` después de registrar Inter. |
126
+ | `languageHeight` | `'small'`, `'medium'`, `'large'` o `'extraLarge'`. El valor inicial es `'small'`. Cambia el interlineado de los estilos MD3 base y enfatizados. | `languageHeight="large"` para texto que requiera más altura de línea. |
127
+ | `motion` | `'expressive'` o `'standard'`. El valor inicial es `'expressive'`. Selecciona el perfil de los resortes espaciales. | `motion="standard"` para usar el perfil espacial estándar. |
128
+ | `reduceMotion` | `'auto'`, `'on'` u `'off'`. El valor inicial es `'auto'` y sigue la preferencia del sistema. | `reduceMotion="on"` para habilitar la reducción en una vista previa. |
129
+ | `direction` | `'ltr'` o `'rtl'`. Si se omite, Paper usa la dirección del entorno. | `direction="rtl"` para una interfaz en árabe. |
130
+ | `settings.icon` | Renderizador para iconos pedidos por nombre. Por defecto usa los Material Symbols del paquete base. | `settings={{ icon: renderMaterialIcon }}` con el renderizador de la colección opcional. |
131
+ | `settings.rippleEffectEnabled` | Habilita el ripple en los controles que consultan este ajuste. Paper lo habilita de forma predeterminada. | `settings={{ rippleEffectEnabled: false }}` para desactivar el efecto en esos controles. |
104
132
 
105
133
  El proveedor carga las fuentes predeterminadas que necesita el tema o el renderizador elegido. Antes de la primera carga completa puede mostrar el árbol vacío. Registra las caras y pesos de una fuente personalizada en tu app con `expo-font` antes de pasar su `fontFamily`.
106
134
 
@@ -292,12 +320,16 @@ Los ejemplos se montan bajo el proveedor de la instalación. Importan desde `mob
292
320
 
293
321
  El archivo `node_modules/mobile-design/COMPONENTS.md` amplía la tabla de cada familia, las piezas relacionadas y los ejemplos completos.
294
322
 
295
- - [Acciones y botones](#acciones-y-botones). Button, IconButton, ButtonGroup, SegmentedButtons, SplitButton, FAB, FAB.Extended, FAB.Menu.
296
- - [Campos y selección](#campos-y-selección). TextField, Select, Autocomplete, Checkbox, RadioButton, Switch, Slider y RangeSlider, DatePicker y DockedDatePicker, TimePicker.
297
- - [Navegación y búsqueda](#navegación-y-búsqueda). TopAppBar, NavigationBar, NavigationRail, NavigationDrawer, Tabs y TabsPager, Searchbar y SearchView, Toolbar.
298
- - [Contenido y tipografía](#contenido-y-tipografía). Text, Badge y BadgedBox, Card, Carousel, Chip, Divider, List.
299
- - [Superficies y ayuda](#superficies-y-ayuda). Menu, Dialog y FullScreenDialog, BottomSheet, SideSheet, Snackbar, Tooltip y RichTooltip.
300
- - [Carga y progreso](#carga-y-progreso). LoadingIndicator y PullToRefresh, ProgressIndicator.
323
+ ## Índice de componentes
324
+
325
+ | Familia | Fichas |
326
+ | --- | --- |
327
+ | [Acciones y botones](#acciones-y-botones) | [`Button`](#button), [`IconButton`](#iconbutton), [`ButtonGroup`](#buttongroup), [`SegmentedButtons`](#segmentedbuttons), [`SplitButton`](#splitbutton), [`FAB`](#fab), [`FAB.Extended`](#fabextended), [`FAB.Menu`](#fabmenu) |
328
+ | [Campos y selección](#campos-y-selección) | [`TextField`](#textfield), [`Select`](#select), [`Autocomplete`](#autocomplete), [`Checkbox`](#checkbox), [`RadioButton`](#radiobutton), [`Switch`](#switch), [`Slider`](#slider-y-rangeslider), [`RangeSlider`](#slider-y-rangeslider), [`DatePicker`](#datepicker-y-dockeddatepicker), [`DockedDatePicker`](#datepicker-y-dockeddatepicker), [`TimePicker`](#timepicker) |
329
+ | [Navegación y búsqueda](#navegación-y-búsqueda) | [`TopAppBar`](#topappbar), [`NavigationBar`](#navigationbar), [`NavigationRail`](#navigationrail), [`NavigationDrawer`](#navigationdrawer), [`Tabs`](#tabs-y-tabspager), [`TabsPager`](#tabs-y-tabspager), [`Searchbar`](#searchbar-y-searchview), [`SearchView`](#searchbar-y-searchview), [`Toolbar`](#toolbar) |
330
+ | [Contenido y tipografía](#contenido-y-tipografía) | [`Text`](#text), [`Badge`](#badge-y-badgedbox), [`BadgedBox`](#badge-y-badgedbox), [`Card`](#card), [`Carousel`](#carousel), [`Chip`](#chip), [`Divider`](#divider), [`List`](#list) |
331
+ | [Superficies y ayuda](#superficies-y-ayuda) | [`Menu`](#menu), [`Dialog`](#dialog-y-fullscreendialog), [`FullScreenDialog`](#dialog-y-fullscreendialog), [`BottomSheet`](#bottomsheet), [`SideSheet`](#sidesheet), [`Snackbar`](#snackbar), [`Tooltip`](#tooltip-y-richtooltip), [`RichTooltip`](#tooltip-y-richtooltip) |
332
+ | [Carga y progreso](#carga-y-progreso) | [`LoadingIndicator`](#loadingindicator-y-pulltorefresh), [`PullToRefresh`](#loadingindicator-y-pulltorefresh), [`ProgressIndicator`](#progressindicator) |
301
333
 
302
334
  ### Acciones y botones
303
335
 
@@ -361,7 +393,7 @@ El componente usa `mode` y `sizeClass`. `mode="contained"` aplica Filled, `conta
361
393
 
362
394
  Reúne acciones relacionadas o alternativas de selección. Standard redistribuye el espacio al pulsar. Connected mantiene el grupo unido.
363
395
 
364
- Cada ítem puede tener icono y `selectedIcon`. `maxVisibleItems` limita cuántos se muestran y el resto aparece en el menú. Con selección múltiple el valor es un arreglo de claves.
396
+ Cada ítem puede tener `icon`. Con `showSelectedIcon`, el ítem seleccionado muestra una marca de verificación. `maxVisibleItems` limita cuántos se muestran y el resto aparece en el menú. Con selección múltiple el valor es un arreglo de claves.
365
397
 
366
398
  | Propiedad | Tipo | Inicial | Uso |
367
399
  | --- | --- | --- | --- |
@@ -461,58 +493,6 @@ Controla expanded y ciérralo desde onDismiss. Trigger define el FAB y su nombre
461
493
  | `expanded` · requerida | `boolean` | — | Estado controlado de expansión. |
462
494
  | `onDismiss` · requerida | `() => void` | — | Solicita cerrar la superficie. |
463
495
 
464
- **Ejemplo**
465
-
466
- ```tsx
467
- import { useState } from 'react';
468
- import { View } from 'react-native';
469
- import { FAB, Text } from 'mobile-design/react-native';
470
-
471
- export default function Example() {
472
- const [feedback, setFeedback] = useState('');
473
- const [expanded, setExpanded] = useState(false);
474
-
475
- return (
476
- <View style={{ gap: 16 }}>
477
- <View
478
- style={{
479
- minHeight: 280,
480
- justifyContent: 'flex-end',
481
- alignItems: 'flex-end',
482
- }}
483
- >
484
- <FAB.Menu
485
- presentation="expressive"
486
- expanded={expanded}
487
- onDismiss={() => setExpanded(false)}
488
- trigger={{
489
- icon: 'plus',
490
- size: 'medium',
491
- accessibilityLabel: 'Crear',
492
- onPress: () => setExpanded(true),
493
- }}
494
- items={[
495
- {
496
- key: 'note',
497
- label: 'Nota',
498
- icon: 'pencil-outline',
499
- onPress: () => setFeedback('Nueva nota'),
500
- },
501
- {
502
- key: 'folder',
503
- label: 'Carpeta',
504
- icon: 'folder-outline',
505
- onPress: () => setFeedback('Nueva carpeta'),
506
- },
507
- ]}
508
- />
509
- </View>
510
- <Text accessibilityLiveRegion="polite">{feedback}</Text>
511
- </View>
512
- );
513
- }
514
- ```
515
-
516
496
  ### Campos y selección
517
497
 
518
498
  #### TextField
@@ -844,61 +824,6 @@ Para deslizar entre paneles comparte `value`, `position` y la solicitud de selec
844
824
  | `onValueChange` · requerida | `(key: string) => void` | — | Entrega el siguiente valor para actualizar el estado del consumidor. |
845
825
  | `variant` | `"primary" \| "secondary"` | `'primary'` | Tratamiento visual o modalidad del componente. |
846
826
 
847
- **Ejemplo**
848
-
849
- ```tsx
850
- import { useState } from 'react';
851
- import { View } from 'react-native';
852
- import { useSharedValue } from 'react-native-reanimated';
853
- import { Tabs, TabsPager, Text } from 'mobile-design/react-native';
854
-
855
- export default function Example() {
856
- const [value, setValue] = useState('files');
857
- const [request, setRequest] = useState(0);
858
- const position = useSharedValue(0);
859
- const items = [
860
- {
861
- key: 'files',
862
- label: 'Archivos',
863
- icon: 'folder',
864
- nativeID: 'library-files-tab',
865
- panelID: 'library-files-panel',
866
- },
867
- {
868
- key: 'recent',
869
- label: 'Recientes',
870
- icon: 'schedule',
871
- nativeID: 'library-recent-tab',
872
- panelID: 'library-recent-panel',
873
- },
874
- ];
875
-
876
- return (
877
- <View style={{ flex: 1 }}>
878
- <Tabs
879
- items={items}
880
- value={value}
881
- onValueChange={setValue}
882
- position={position}
883
- onTabPress={() => setRequest((value) => value + 1)}
884
- />
885
- <TabsPager
886
- items={items}
887
- value={value}
888
- onValueChange={setValue}
889
- position={position}
890
- selectionRequest={request}
891
- renderPage={(item) => (
892
- <View style={{ padding: 24 }}>
893
- <Text>{item.label}</Text>
894
- </View>
895
- )}
896
- />
897
- </View>
898
- );
899
- }
900
- ```
901
-
902
827
  #### Searchbar y SearchView
903
828
 
904
829
  Conecta una barra de búsqueda con una vista que presenta consulta, sugerencias y resultados.
@@ -1065,37 +990,6 @@ Usa `List.Accordion` con `title`, `expanded` y `onPress`. Configura las acciones
1065
990
  | `variant` | `"expressive" \| "baseline"` | `'expressive'` | Tratamiento visual o modalidad del componente. |
1066
991
  | `selectionMode` | `"single" \| "multiple"` | — | Define si la selección es inexistente, única o múltiple. |
1067
992
 
1068
- **Ejemplo**
1069
-
1070
- ```tsx
1071
- import { useState } from 'react';
1072
- import { View } from 'react-native';
1073
- import { List, IconButton, Text } from 'mobile-design/react-native';
1074
-
1075
- export default function Example() {
1076
- const [feedback, setFeedback] = useState('');
1077
-
1078
- return (
1079
- <View style={{ gap: 16 }}>
1080
- <List.Item
1081
- title="Informe trimestral"
1082
- description="Documento compartido"
1083
- lines={2}
1084
- onPress={() => setFeedback('Detalle del documento')}
1085
- trailing={
1086
- <IconButton
1087
- icon="bookmark-outline"
1088
- accessibilityLabel="Guardar Informe trimestral"
1089
- onPress={() => setFeedback('Guardado Informe trimestral')}
1090
- />
1091
- }
1092
- />
1093
- <Text accessibilityLiveRegion="polite">{feedback}</Text>
1094
- </View>
1095
- );
1096
- }
1097
- ```
1098
-
1099
993
  ### Superficies y ayuda
1100
994
 
1101
995
  #### Menu
@@ -1113,48 +1007,6 @@ Controla visible y onDismiss y proporciona un anchor que abra el menú.
1113
1007
  | `onDismiss` | `(() => void)` | — | Solicita cerrar la superficie. |
1114
1008
  | `onClosed` | `(() => void)` | — | Avisa cuando concluye la salida de la superficie. |
1115
1009
 
1116
- **Ejemplo**
1117
-
1118
- ```tsx
1119
- import { useState } from 'react';
1120
- import { View } from 'react-native';
1121
- import { Menu, Button, Text } from 'mobile-design/react-native';
1122
-
1123
- export default function Example() {
1124
- const [feedback, setFeedback] = useState('');
1125
- const [visible, setVisible] = useState(false);
1126
-
1127
- return (
1128
- <View style={{ gap: 16 }}>
1129
- <Menu
1130
- visible={visible}
1131
- onDismiss={() => setVisible(false)}
1132
- anchor={
1133
- <Button
1134
- variant="tonal"
1135
- onPress={() => setVisible(true)}
1136
- >
1137
- Opciones
1138
- </Button>
1139
- }
1140
- >
1141
- <Menu.Item
1142
- title="Guardar"
1143
- leadingIcon="bookmark-outline"
1144
- onPress={() => setFeedback('Guardado')}
1145
- />
1146
- <Menu.Item
1147
- title="Enviar"
1148
- leadingIcon="send-outline"
1149
- onPress={() => setFeedback('Enviar')}
1150
- />
1151
- </Menu>
1152
- <Text accessibilityLiveRegion="polite">{feedback}</Text>
1153
- </View>
1154
- );
1155
- }
1156
- ```
1157
-
1158
1010
  #### Dialog y FullScreenDialog
1159
1011
 
1160
1012
  Presenta información o una tarea que necesita atención antes de volver al contenido anterior.
@@ -1183,47 +1035,6 @@ Monta `GestureHandlerRootView` como se muestra en el ejemplo de instalación. Us
1183
1035
  | `variant` | `"standard" \| "modal"` | `'modal'` | `standard` comparte el layout y `modal` presenta una hoja superpuesta. |
1184
1036
  | `snapPoints` | `(string \| number)[]` | — | Posiciones de reposo de la hoja. Admite puntos en dp o porcentajes según el tipo. |
1185
1037
 
1186
- **Ejemplo**
1187
-
1188
- ```tsx
1189
- import { useState } from 'react';
1190
- import {
1191
- BottomSheet,
1192
- BottomSheetScrollView,
1193
- Text,
1194
- Button,
1195
- } from 'mobile-design/react-native';
1196
-
1197
- export default function Example() {
1198
- const [open, setOpen] = useState(false);
1199
-
1200
- return (
1201
- <>
1202
- <Button onPress={() => setOpen(true)}>Ver detalles</Button>
1203
- <BottomSheet
1204
- open={open}
1205
- onOpenChange={setOpen}
1206
- variant="modal"
1207
- scrollable
1208
- snapPoints={['50%', '85%']}
1209
- accessibilityLabel="Detalles de la colección"
1210
- >
1211
- <BottomSheetScrollView contentContainerStyle={{ padding: 24 }}>
1212
- <Text variant="headlineSmall">Tu colección</Text>
1213
- <Text>Información adicional de la colección guardada.</Text>
1214
- <Button
1215
- variant="text"
1216
- onPress={() => setOpen(false)}
1217
- >
1218
- Cerrar
1219
- </Button>
1220
- </BottomSheetScrollView>
1221
- </BottomSheet>
1222
- </>
1223
- );
1224
- }
1225
- ```
1226
-
1227
1038
  #### SideSheet
1228
1039
 
1229
1040
  Muestra una tarea complementaria desde un borde lateral, como parte del layout o en una superficie modal.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mobile-design",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Material Design 3 components for React Native and React Native Web, built on React Native Paper",
5
5
  "keywords": [
6
6
  "material-design",
@@ -38,7 +38,7 @@
38
38
  ],
39
39
  "sideEffects": false,
40
40
  "dependencies": {
41
- "@mobile-design/tokens": "0.1.1"
41
+ "@mobile-design/tokens": "0.1.2"
42
42
  },
43
43
  "peerDependencies": {
44
44
  "react": ">=19.2.0",