@dropi/react-native-design-system 0.1.15 → 0.1.17
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.
package/README.md
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
#
|
|
2
|
-
-
|
|
3
|
-
|
|
4
1
|
El **Design System de Dropi** para aplicaciones **React Native**. Este paquete reúne la base visual y funcional de nuestros productos móviles, ofreciendo **tokens de diseño, componentes reutilizables y patrones consistentes** para mantener la coherencia en la experiencia de usuario. Su objetivo es simplificar el desarrollo, acelerar la implementación de interfaces y garantizar que cada proyecto Dropi mantenga una identidad visual sólida y escalable.
|
|
5
2
|
# Tokens
|
|
6
3
|
## Radius
|
|
@@ -326,4 +323,123 @@ import { TextButton } from "@dropi/react-native-design-system";
|
|
|
326
323
|
onPress={() => console.log("Eliminar presionado")}
|
|
327
324
|
/>
|
|
328
325
|
|
|
326
|
+
```
|
|
327
|
+
# Moléculas
|
|
328
|
+
## 🚨 Alert
|
|
329
|
+
|
|
330
|
+
El componente Alert muestra un mensaje contextual acompañado de un ícono y colores que representan su nivel de severidad. Está diseñado para comunicar información relevante al usuario: advertencias, errores, confirmaciones o simples avisos informativos.
|
|
331
|
+
|
|
332
|
+
Cada variante (info, warning, error, success) aplica automáticamente colores de fondo, borde e ícono usando el sistema de tokens (colors, sizes, radius, spacing). Además, permite incluir un botón de acción secundaria y un botón de cierre opcional.
|
|
333
|
+
|
|
334
|
+
## 📦 Importación:
|
|
335
|
+
```
|
|
336
|
+
import { Alert } from "@dropi/react-native-design-system";
|
|
337
|
+
|
|
338
|
+
```
|
|
339
|
+
## ⚙️ Props:
|
|
340
|
+
```
|
|
341
|
+
| Prop | Tipo | Descripción |
|
|
342
|
+
|---------------- |--------------------------------------------------- |---------------------------------------------------------------------|
|
|
343
|
+
| `message` | `string` | Texto principal que describe la alerta. |
|
|
344
|
+
| `variant` | `'info' \| 'warning' \| 'error' \| 'success'` | Define los colores, ícono y estilo visual general. |
|
|
345
|
+
| `buttonLabel` | `string` | Texto del botón opcional dentro de la alerta. |
|
|
346
|
+
| `onButtonPress` | `() => void` | Acción ejecutada al presionar el botón opcional. |
|
|
347
|
+
| `onClosePress` | `() => void` | Acción ejecutada al presionar el botón de cierre (`close-small`). |
|
|
348
|
+
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
## 🧩 Ejemplos de uso:
|
|
352
|
+
```Typescript
|
|
353
|
+
<Alert
|
|
354
|
+
message="Tu información ha sido guardada correctamente."
|
|
355
|
+
variant="success"
|
|
356
|
+
onClosePress={() => console.log("Cerrar alerta")}
|
|
357
|
+
/>
|
|
358
|
+
|
|
359
|
+
<Alert
|
|
360
|
+
message="No pudimos procesar tu solicitud."
|
|
361
|
+
variant="error"
|
|
362
|
+
buttonLabel="Reintentar"
|
|
363
|
+
onButtonPress={() => console.log("Reintentar")}
|
|
364
|
+
onClosePress={() => console.log("Cerrar")}
|
|
365
|
+
/>
|
|
366
|
+
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
## Empty State
|
|
370
|
+
|
|
371
|
+
El EmptyState es un componente visual diseñado para mostrar pantallas vacías en escenarios donde no hay datos disponibles, ocurrió un estado inicial o se requiere una primera acción del usuario. Puede incluir una imagen, un título opcional, un mensaje descriptivo y un botón configurable. Mantiene una composición centrada y un diseño minimalista, usando automáticamente tamaños distintos para tablet gracias a isTablet.
|
|
372
|
+
|
|
373
|
+
## 📦 Importación:
|
|
374
|
+
```
|
|
375
|
+
import { EmptyState } from "@dropi/react-native-design-system";
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## ⚙️ Props:
|
|
379
|
+
```
|
|
380
|
+
| Prop | Tipo | Descripción |
|
|
381
|
+
| ---------------- | ------------------------ | -------------------------------------------------------------------- |
|
|
382
|
+
| `imageSource` | `string \| number` | Imagen opcional (URL o require local) mostrada en la parte superior. |
|
|
383
|
+
| `title` | `string` | Título corto que introduce el estado vacío. |
|
|
384
|
+
| `message` | `string` (obligatorio) | Texto principal explicando el estado. |
|
|
385
|
+
| `buttonLabel` | `string` | Texto del botón opcional. |
|
|
386
|
+
| `onButtonPress` | `() => void` | Callback del botón. Si existe, el botón se muestra. |
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
## 🧩 Ejemplos de uso:
|
|
390
|
+
|
|
391
|
+
```
|
|
392
|
+
<EmptyState
|
|
393
|
+
imageSource={require("../../assets/empty-orders.png")}
|
|
394
|
+
title="Sin pedidos todavía"
|
|
395
|
+
message="Cuando tengas pedidos activos aparecerán aquí."
|
|
396
|
+
/>
|
|
397
|
+
|
|
398
|
+
<EmptyState
|
|
399
|
+
imageSource="https://example.com/empty.png"
|
|
400
|
+
message="Aún no has guardado favoritos."
|
|
401
|
+
buttonLabel="Explorar productos"
|
|
402
|
+
onButtonPress={() => console.log("Ir a explorar")}
|
|
403
|
+
/>
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
## Title Description
|
|
407
|
+
|
|
408
|
+
El TitleDescription es un componente de selección diseñado para mostrar opciones con un título principal, una descripción opcional, una imagen y un indicador visual circular que refleja si la opción está activa. Es ideal para flujos donde el usuario debe elegir entre varias alternativas.
|
|
409
|
+
Adapta automáticamente tamaños en tablets usando isTablet, mantiene una disposición horizontal limpia y un estilo consistente con el design system.
|
|
410
|
+
|
|
411
|
+
## 📦 Importación:
|
|
412
|
+
```
|
|
413
|
+
import { TitleDescription } from "@dropi/react-native-design-system";
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
## ⚙️ Props:
|
|
417
|
+
```
|
|
418
|
+
| Prop | Tipo | Descripción |
|
|
419
|
+
| -------------- | ------------------------ | ------------------------------------------------------------------------------ |
|
|
420
|
+
| `title` | `string` | Título principal de la opción. |
|
|
421
|
+
| `label` | `string` | Texto descriptivo o subtítulo opcional. |
|
|
422
|
+
| `imageSource` | `string | number` | Imagen opcional (URL o require local) que acompaña la opción. |
|
|
423
|
+
| `isActive` | `boolean` | Indica si la opción está seleccionada. Cambia estilos y muestra el inner dot. |
|
|
424
|
+
| `isDisabled` | `boolean` | Desactiva la interacción y reduce opacidad. |
|
|
425
|
+
| `...rest` | `TouchableOpacityProps` | Props adicionales del contenedor presionable. |
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
## 🧩 Ejemplos de uso:
|
|
429
|
+
```
|
|
430
|
+
<TitleDescription
|
|
431
|
+
title="Domicilio"
|
|
432
|
+
label="Entrega en tu dirección registrada"
|
|
433
|
+
imageSource={require("../../assets/location.png")}
|
|
434
|
+
isActive={selected === "home"}
|
|
435
|
+
onPress={() => setSelected("home")}
|
|
436
|
+
/>
|
|
437
|
+
|
|
438
|
+
<TitleDescription
|
|
439
|
+
title="Punto de recogida"
|
|
440
|
+
label="Elige una tienda cercana"
|
|
441
|
+
imageSource="https://example.com/pickup.png"
|
|
442
|
+
isActive={false}
|
|
443
|
+
isDisabled={true}
|
|
444
|
+
/>
|
|
329
445
|
```
|
|
@@ -8,6 +8,7 @@ var _reactNative = require("react-native");
|
|
|
8
8
|
var _expoImage = require("expo-image");
|
|
9
9
|
var _constants = require("../../constants");
|
|
10
10
|
var _atoms = require("../../atoms");
|
|
11
|
+
var _utils = require("../../utils");
|
|
11
12
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
12
13
|
const EmptyState = ({
|
|
13
14
|
imageSource,
|
|
@@ -17,40 +18,21 @@ const EmptyState = ({
|
|
|
17
18
|
onButtonPress
|
|
18
19
|
}) => {
|
|
19
20
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
20
|
-
style:
|
|
21
|
-
paddingVertical: _constants.spacing['size-4']
|
|
22
|
-
},
|
|
21
|
+
style: styles.container,
|
|
23
22
|
children: [imageSource && /*#__PURE__*/(0, _jsxRuntime.jsx)(_expoImage.Image, {
|
|
24
|
-
source: imageSource
|
|
25
|
-
|
|
26
|
-
,
|
|
27
|
-
style: {
|
|
28
|
-
width: 51,
|
|
29
|
-
height: 48,
|
|
30
|
-
alignSelf: 'center',
|
|
31
|
-
marginBottom: _constants.spacing['size-4']
|
|
32
|
-
},
|
|
23
|
+
source: imageSource,
|
|
24
|
+
style: styles.image,
|
|
33
25
|
contentFit: "contain"
|
|
34
26
|
}), title && /*#__PURE__*/(0, _jsxRuntime.jsx)(_atoms.Body, {
|
|
35
27
|
type: "l-medium",
|
|
36
|
-
style:
|
|
37
|
-
color: _constants.colors['Gray-700'].light,
|
|
38
|
-
textAlign: 'center',
|
|
39
|
-
marginBottom: _constants.spacing['size-2']
|
|
40
|
-
},
|
|
28
|
+
style: styles.title,
|
|
41
29
|
children: title
|
|
42
30
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_atoms.Body, {
|
|
43
31
|
type: "m-regular",
|
|
44
|
-
style:
|
|
45
|
-
color: _constants.colors['Gray-500'].light,
|
|
46
|
-
textAlign: 'center'
|
|
47
|
-
},
|
|
32
|
+
style: styles.message,
|
|
48
33
|
children: message
|
|
49
34
|
}), buttonLabel && onButtonPress && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
50
|
-
style:
|
|
51
|
-
marginTop: 24,
|
|
52
|
-
alignItems: 'center'
|
|
53
|
-
},
|
|
35
|
+
style: styles.buttonContainer,
|
|
54
36
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_atoms.DefaultButton, {
|
|
55
37
|
label: buttonLabel,
|
|
56
38
|
onPress: onButtonPress,
|
|
@@ -60,4 +42,28 @@ const EmptyState = ({
|
|
|
60
42
|
})]
|
|
61
43
|
});
|
|
62
44
|
};
|
|
63
|
-
exports.EmptyState = EmptyState;
|
|
45
|
+
exports.EmptyState = EmptyState;
|
|
46
|
+
const styles = _reactNative.StyleSheet.create({
|
|
47
|
+
container: {
|
|
48
|
+
paddingVertical: _constants.spacing['size-4']
|
|
49
|
+
},
|
|
50
|
+
image: {
|
|
51
|
+
width: !_utils.isTablet ? 51 : 72,
|
|
52
|
+
height: !_utils.isTablet ? 48 : 68,
|
|
53
|
+
alignSelf: 'center',
|
|
54
|
+
marginBottom: _constants.spacing['size-4']
|
|
55
|
+
},
|
|
56
|
+
title: {
|
|
57
|
+
color: _constants.colors['Gray-700'].light,
|
|
58
|
+
textAlign: 'center',
|
|
59
|
+
marginBottom: _constants.spacing['size-2']
|
|
60
|
+
},
|
|
61
|
+
message: {
|
|
62
|
+
color: _constants.colors['Gray-500'].light,
|
|
63
|
+
textAlign: 'center'
|
|
64
|
+
},
|
|
65
|
+
buttonContainer: {
|
|
66
|
+
marginTop: _constants.spacing['size-5'],
|
|
67
|
+
alignItems: 'center'
|
|
68
|
+
}
|
|
69
|
+
});
|
|
@@ -10,6 +10,16 @@ var _utils = require("../../../utils");
|
|
|
10
10
|
var _constants = require("../../../constants");
|
|
11
11
|
var _atoms = require("../../../atoms");
|
|
12
12
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
13
|
+
const OptionSelector = ({
|
|
14
|
+
isActive
|
|
15
|
+
}) => {
|
|
16
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
17
|
+
style: isActive ? styles.selectedOptionSelector : styles.optionSelector,
|
|
18
|
+
children: isActive && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
19
|
+
style: styles.innerSelector
|
|
20
|
+
})
|
|
21
|
+
});
|
|
22
|
+
};
|
|
13
23
|
const TitleDescription = ({
|
|
14
24
|
title,
|
|
15
25
|
label,
|
|
@@ -18,50 +28,29 @@ const TitleDescription = ({
|
|
|
18
28
|
isDisabled,
|
|
19
29
|
...rest
|
|
20
30
|
}) => {
|
|
21
|
-
return /*#__PURE__*/(0, _jsxRuntime.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
})]
|
|
31
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
|
|
32
|
+
style: [isActive ? styles.selectedOption : styles.option, {
|
|
33
|
+
opacity: isDisabled ? 0.5 : 1
|
|
34
|
+
}],
|
|
35
|
+
disabled: isActive || isDisabled,
|
|
36
|
+
...rest,
|
|
37
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(OptionSelector, {
|
|
38
|
+
isActive: isActive
|
|
39
|
+
}), imageSource && /*#__PURE__*/(0, _jsxRuntime.jsx)(_expoImage.Image, {
|
|
40
|
+
source: imageSource,
|
|
41
|
+
style: styles.image
|
|
42
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
43
|
+
style: styles.textContainer,
|
|
44
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_atoms.Body, {
|
|
45
|
+
type: "m-regular",
|
|
46
|
+
style: styles.titleText,
|
|
47
|
+
children: title
|
|
48
|
+
}), label && /*#__PURE__*/(0, _jsxRuntime.jsx)(_atoms.Body, {
|
|
49
|
+
type: "s-regular",
|
|
50
|
+
style: styles.optionText,
|
|
51
|
+
children: label
|
|
43
52
|
})]
|
|
44
|
-
})
|
|
45
|
-
style: styles.option,
|
|
46
|
-
...rest,
|
|
47
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
48
|
-
style: styles.optionSelector
|
|
49
|
-
}), imageSource && /*#__PURE__*/(0, _jsxRuntime.jsx)(_expoImage.Image, {
|
|
50
|
-
source: imageSource,
|
|
51
|
-
style: styles.image
|
|
52
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
53
|
-
style: styles.textContainer,
|
|
54
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_atoms.Body, {
|
|
55
|
-
type: "m-regular",
|
|
56
|
-
style: styles.optionText,
|
|
57
|
-
children: title
|
|
58
|
-
}), label && /*#__PURE__*/(0, _jsxRuntime.jsx)(_atoms.Body, {
|
|
59
|
-
type: "s-regular",
|
|
60
|
-
style: styles.optionText,
|
|
61
|
-
children: label
|
|
62
|
-
})]
|
|
63
|
-
})]
|
|
64
|
-
})
|
|
53
|
+
})]
|
|
65
54
|
});
|
|
66
55
|
};
|
|
67
56
|
exports.TitleDescription = TitleDescription;
|
|
@@ -110,18 +99,18 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
110
99
|
backgroundColor: _constants.colors["Primary-500"].light
|
|
111
100
|
},
|
|
112
101
|
image: {
|
|
113
|
-
width: 32,
|
|
114
|
-
height: 32,
|
|
102
|
+
width: !_utils.isTablet ? 32 : 32 * 1.5,
|
|
103
|
+
height: !_utils.isTablet ? 32 : 32 * 1.5,
|
|
115
104
|
marginRight: _constants.spacing['size-3'],
|
|
116
105
|
borderRadius: _constants.radius.circle
|
|
117
106
|
},
|
|
118
107
|
textContainer: {
|
|
119
108
|
flexDirection: 'column'
|
|
120
109
|
},
|
|
121
|
-
|
|
110
|
+
titleText: {
|
|
122
111
|
color: _constants.colors['Gray-700'].light
|
|
123
112
|
},
|
|
124
|
-
|
|
113
|
+
optionText: {
|
|
125
114
|
color: _constants.colors['Gray-600'].light
|
|
126
115
|
}
|
|
127
116
|
});
|