@widergy/mobile-ui 2.17.0 → 2.18.0

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 (33) hide show
  1. package/CHANGELOG.md +24 -2
  2. package/lib/components/UTBottomSheet/index.js +35 -32
  3. package/lib/components/UTBottomSheet/styles.js +4 -3
  4. package/lib/components/UTDatePicker/README.md +73 -0
  5. package/lib/components/UTDatePicker/components/Calendar/constants.js +3 -0
  6. package/lib/components/UTDatePicker/components/Calendar/index.js +197 -0
  7. package/lib/components/UTDatePicker/components/Day/index.js +44 -0
  8. package/lib/components/UTDatePicker/components/Day/styles.js +8 -0
  9. package/lib/components/UTDatePicker/components/PickerColumn/index.js +57 -0
  10. package/lib/components/UTDatePicker/constants.js +48 -0
  11. package/lib/components/UTDatePicker/index.js +135 -0
  12. package/lib/components/UTDatePicker/layout.js +108 -0
  13. package/lib/components/UTDatePicker/proptypes.js +20 -0
  14. package/lib/components/UTDatePicker/styles.js +63 -0
  15. package/lib/components/UTDatePicker/theme.js +18 -0
  16. package/lib/components/UTDatePicker/utils.js +52 -0
  17. package/lib/components/UTLoading/README.md +109 -31
  18. package/lib/components/UTLoading/index.js +9 -9
  19. package/lib/components/UTLoading/{components → versions/V0/components}/AnimatedCircles/index.js +1 -1
  20. package/lib/components/UTLoading/{components → versions/V0/components}/AnimatedCircles/styles.js +16 -13
  21. package/lib/components/UTLoading/{components → versions/V0/components}/Spinner/index.js +4 -4
  22. package/lib/components/UTLoading/{components → versions/V0/components}/Spinner/styles.js +0 -3
  23. package/lib/components/UTLoading/versions/V0/index.js +18 -0
  24. package/lib/components/UTLoading/versions/V1/components/LoaderWithLogo/index.js +84 -0
  25. package/lib/components/UTLoading/versions/V1/components/LoaderWithLogo/theme.js +45 -0
  26. package/lib/components/UTLoading/versions/V1/components/Spinner/constants.js +5 -0
  27. package/lib/components/UTLoading/versions/V1/components/Spinner/index.js +143 -0
  28. package/lib/components/UTLoading/versions/V1/components/Spinner/theme.js +23 -0
  29. package/lib/components/UTLoading/versions/V1/index.js +33 -0
  30. package/lib/constants/testIds.js +19 -0
  31. package/lib/index.js +1 -0
  32. package/package.json +5 -4
  33. /package/lib/components/UTLoading/{components → versions/V0/components}/AnimatedCircles/constants.js +0 -0
@@ -0,0 +1,135 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { Keyboard } from 'react-native';
3
+ import dayjs from 'dayjs';
4
+ import customParseFormat from 'dayjs/plugin/customParseFormat';
5
+
6
+ import { COMPONENT_KEYS } from '../UTBaseInputField/constants';
7
+
8
+ import { DEFAULT_PLACEHOLDER, OUTPUT_LABEL_MASK, VARIANTS } from './constants';
9
+ import UTDatePickerLayout from './layout';
10
+ import { propTypes } from './proptypes';
11
+ import { dateMatchesFormat, getFinalDate } from './utils';
12
+
13
+ dayjs.extend(customParseFormat);
14
+
15
+ const UTDatePicker = ({
16
+ modalProps,
17
+ clearable = true,
18
+ CustomIcon,
19
+ disabled,
20
+ error = '',
21
+ helpText,
22
+ onChange = () => {},
23
+ placeholder,
24
+ range,
25
+ readOnly = false,
26
+ required,
27
+ style,
28
+ title,
29
+ value = '',
30
+ variant = VARIANTS.select
31
+ }) => {
32
+ const { maxDate, minDate } = range || {};
33
+
34
+ const [pickedDate, setPickedDate] = useState(null);
35
+ const [isOpen, setIsOpen] = useState(false);
36
+
37
+ useEffect(() => {
38
+ if (!value && pickedDate?.isValid()) setPickedDate(null);
39
+ else if (dateMatchesFormat(value, OUTPUT_LABEL_MASK)) setPickedDate(dayjs(value, OUTPUT_LABEL_MASK));
40
+ else setPickedDate(null);
41
+ }, [value]);
42
+
43
+ const openCalendar = () => {
44
+ if (disabled || readOnly) return;
45
+ Keyboard.dismiss();
46
+ setIsOpen(true);
47
+ };
48
+
49
+ const handleClose = () => {
50
+ setIsOpen(false);
51
+ };
52
+
53
+ const handleDaySelect = date => {
54
+ const finalDate = getFinalDate({ date, maxDate, minDate });
55
+ setPickedDate(finalDate);
56
+ if (finalDate.isValid()) onChange(finalDate.format(OUTPUT_LABEL_MASK));
57
+ else onChange('');
58
+ setIsOpen(false);
59
+ };
60
+
61
+ const handleClear = () => {
62
+ setPickedDate(null);
63
+ onChange('');
64
+ };
65
+
66
+ const displayValue = pickedDate?.isValid() ? pickedDate.format(OUTPUT_LABEL_MASK) : '';
67
+
68
+ const hasError = !!error;
69
+ const hasValue = !!pickedDate?.isValid();
70
+ const displayPlaceholder = placeholder || DEFAULT_PLACEHOLDER;
71
+ const errorMessage = error;
72
+ const isTransparent = variant === VARIANTS.picker;
73
+
74
+ const showClearButton = clearable && hasValue && !disabled && !readOnly;
75
+ const showCalendarIcon = !readOnly && !disabled;
76
+
77
+ const calendarAction = {
78
+ colorTheme: hasError ? 'error' : isOpen ? 'primary' : 'gray',
79
+ Icon: CustomIcon || 'IconCalendarEvent',
80
+ onPress: openCalendar,
81
+ size: 'small',
82
+ variant: 'text'
83
+ };
84
+
85
+ const clearAction = {
86
+ colorTheme: 'secondary',
87
+ Icon: 'IconX',
88
+ onPress: handleClear,
89
+ size: 'small',
90
+ variant: 'text'
91
+ };
92
+
93
+ const rightAdornments = showCalendarIcon
94
+ ? [
95
+ {
96
+ name: COMPONENT_KEYS.ACTION,
97
+ props: { action: showClearButton ? clearAction : calendarAction }
98
+ }
99
+ ]
100
+ : [];
101
+
102
+ const inputStyle = isTransparent
103
+ ? { container: { backgroundColor: 'transparent', borderColor: 'transparent' } }
104
+ : { container: { alignItems: 'stretch', paddingHorizontal: 12 } };
105
+
106
+ return (
107
+ <UTDatePickerLayout
108
+ disabled={disabled}
109
+ displayPlaceholder={displayPlaceholder}
110
+ displayValue={displayValue}
111
+ errorMessage={errorMessage}
112
+ handleClose={handleClose}
113
+ handleDaySelect={handleDaySelect}
114
+ hasError={hasError}
115
+ helpText={helpText}
116
+ inputStyle={inputStyle}
117
+ isOpen={isOpen}
118
+ maxDate={maxDate}
119
+ minDate={minDate}
120
+ modalProps={modalProps}
121
+ onPress={openCalendar}
122
+ pickedDate={pickedDate}
123
+ readOnly={readOnly}
124
+ required={required}
125
+ rightAdornments={rightAdornments}
126
+ style={style}
127
+ title={title}
128
+ variant={variant}
129
+ />
130
+ );
131
+ };
132
+
133
+ UTDatePicker.propTypes = propTypes;
134
+
135
+ export default UTDatePicker;
@@ -0,0 +1,108 @@
1
+ import React from 'react';
2
+ import { Pressable, View } from 'react-native';
3
+ import { array, bool, func, object, string } from 'prop-types';
4
+
5
+ import UTBaseInputField from '../UTBaseInputField';
6
+ import UTBottomSheet from '../UTBottomSheet';
7
+ import UTFieldLabel from '../UTFieldLabel';
8
+ import UTLabel from '../UTLabel';
9
+ import UTValidation from '../UTValidation';
10
+ import { TEST_IDS } from '../../constants/testIds';
11
+
12
+ import Calendar from './components/Calendar';
13
+ import { VARIANTS } from './constants';
14
+ import styles from './styles';
15
+
16
+ const { UTDatePicker: datePickerTestIds } = TEST_IDS;
17
+
18
+ const UTDatePickerLayout = ({
19
+ disabled,
20
+ displayPlaceholder,
21
+ displayValue,
22
+ errorMessage,
23
+ handleClose,
24
+ handleDaySelect,
25
+ hasError,
26
+ helpText,
27
+ inputStyle,
28
+ isOpen,
29
+ maxDate,
30
+ minDate,
31
+ modalProps,
32
+ onPress,
33
+ pickedDate,
34
+ readOnly,
35
+ required,
36
+ rightAdornments,
37
+ style,
38
+ title,
39
+ variant
40
+ }) => (
41
+ <View style={[styles.root, style?.root]} testID={datePickerTestIds.root}>
42
+ {!!title && <UTFieldLabel required={required}>{title}</UTFieldLabel>}
43
+
44
+ <Pressable onPress={onPress} style={styles.pressable}>
45
+ <UTBaseInputField
46
+ alwaysShowPlaceholder
47
+ dataTestId={datePickerTestIds.input}
48
+ disabled={disabled}
49
+ editable={false}
50
+ error={hasError}
51
+ placeholder={displayPlaceholder}
52
+ readOnly={readOnly}
53
+ rightAdornments={rightAdornments}
54
+ style={inputStyle}
55
+ value={displayValue}
56
+ />
57
+ </Pressable>
58
+
59
+ {!!helpText && (
60
+ <UTLabel colorTheme="gray" variant="small">
61
+ {helpText}
62
+ </UTLabel>
63
+ )}
64
+
65
+ {variant === VARIANTS.select && !!errorMessage && (
66
+ <UTValidation
67
+ dataTestId={datePickerTestIds.errorMessage}
68
+ validationData={[{ items: [{ status: 'error', text: errorMessage }] }]}
69
+ />
70
+ )}
71
+
72
+ <UTBottomSheet
73
+ adjustableHeight
74
+ onClose={handleClose}
75
+ visible={isOpen}
76
+ withBodyPadding={false}
77
+ {...modalProps}
78
+ >
79
+ <Calendar maxDate={maxDate} minDate={minDate} onDaySelect={handleDaySelect} pickedDate={pickedDate} />
80
+ </UTBottomSheet>
81
+ </View>
82
+ );
83
+
84
+ UTDatePickerLayout.propTypes = {
85
+ disabled: bool,
86
+ displayPlaceholder: string,
87
+ displayValue: string,
88
+ errorMessage: string,
89
+ handleClose: func,
90
+ handleDaySelect: func,
91
+ hasError: bool,
92
+ helpText: string,
93
+ inputStyle: object,
94
+ isOpen: bool,
95
+ maxDate: string,
96
+ minDate: string,
97
+ modalProps: object,
98
+ onPress: func,
99
+ pickedDate: object,
100
+ readOnly: bool,
101
+ required: bool,
102
+ rightAdornments: array,
103
+ style: object,
104
+ title: string,
105
+ variant: string
106
+ };
107
+
108
+ export default UTDatePickerLayout;
@@ -0,0 +1,20 @@
1
+ import { bool, elementType, func, object, oneOf, shape, string } from 'prop-types';
2
+
3
+ export const propTypes = {
4
+ clearable: bool,
5
+ CustomIcon: elementType,
6
+ disabled: bool,
7
+ error: string,
8
+ helpText: string,
9
+ modalProps: object,
10
+ onChange: func,
11
+ placeholder: string,
12
+ range: shape({ maxDate: string, minDate: string }),
13
+ readOnly: bool,
14
+ required: bool,
15
+ size: oneOf(['sm', 'md']),
16
+ style: shape({ root: object }),
17
+ title: string,
18
+ value: string,
19
+ variant: oneOf(['select', 'picker'])
20
+ };
@@ -0,0 +1,63 @@
1
+ import { StyleSheet } from 'react-native';
2
+
3
+ const styles = StyleSheet.create({
4
+ calendarRoot: {
5
+ paddingHorizontal: 24,
6
+ paddingTop: 16
7
+ },
8
+ dayCell: {
9
+ flex: 1,
10
+ paddingVertical: 2,
11
+ textAlign: 'center'
12
+ },
13
+ month: {
14
+ gap: 2,
15
+ minHeight: 260
16
+ },
17
+ nav: {
18
+ alignItems: 'center',
19
+ flexDirection: 'row',
20
+ justifyContent: 'space-between',
21
+ marginBottom: 24
22
+ },
23
+ navLabel: {
24
+ flex: 1,
25
+ textAlign: 'center'
26
+ },
27
+ navSpacer: {
28
+ width: 36
29
+ },
30
+ pickerColumn: {
31
+ flex: 1,
32
+ overflow: 'hidden'
33
+ },
34
+ pickerContainer: {
35
+ flexDirection: 'row',
36
+ gap: 8,
37
+ height: 260
38
+ },
39
+ pickerScroll: {
40
+ height: 260
41
+ },
42
+ pickerScrollContent: {
43
+ paddingBottom: 220
44
+ },
45
+ pressable: {
46
+ width: '100%'
47
+ },
48
+ root: {
49
+ gap: 8
50
+ },
51
+ week: {
52
+ flexDirection: 'row'
53
+ },
54
+ yearItem: {
55
+ alignItems: 'center',
56
+ borderRadius: 8,
57
+ height: 40,
58
+ justifyContent: 'center',
59
+ width: '100%'
60
+ }
61
+ });
62
+
63
+ export default styles;
@@ -0,0 +1,18 @@
1
+ export const getDayCellButtonStyle = (selected, theme) => ({
2
+ root: {
3
+ alignItems: 'center',
4
+ flex: 1,
5
+ height: 36,
6
+ justifyContent: 'center',
7
+ paddingHorizontal: 0,
8
+ paddingVertical: 0,
9
+ ...(selected && {
10
+ backgroundColor: theme.Palette.accent['04'],
11
+ borderRadius: 18
12
+ })
13
+ }
14
+ });
15
+
16
+ export const getYearItemStyle = (selected, theme) => ({
17
+ backgroundColor: selected ? theme.Palette.accent['04'] : undefined
18
+ });
@@ -0,0 +1,52 @@
1
+ import dayjs from 'dayjs';
2
+ import customParseFormat from 'dayjs/plugin/customParseFormat';
3
+
4
+ import { DAY_UNIT, MONTH_UNIT, OUTPUT_LABEL_MASK, YEAR_RANGE_AFTER, YEAR_RANGE_BEFORE } from './constants';
5
+
6
+ dayjs.extend(customParseFormat);
7
+
8
+ export const isSelected = (date, selectedDate) => selectedDate && date.isSame(selectedDate, DAY_UNIT);
9
+
10
+ export const dateMatchesFormat = (date, targetFormat) => dayjs(date, targetFormat, true).isValid();
11
+
12
+ export const getFinalDate = ({ date, maxDate, minDate }) => {
13
+ const formattedDate = dayjs(date);
14
+ if (maxDate && formattedDate?.isAfter(dayjs(maxDate, OUTPUT_LABEL_MASK)))
15
+ return dayjs(maxDate, OUTPUT_LABEL_MASK);
16
+ if (minDate && formattedDate?.isBefore(dayjs(minDate, OUTPUT_LABEL_MASK)))
17
+ return dayjs(minDate, OUTPUT_LABEL_MASK);
18
+ return formattedDate;
19
+ };
20
+
21
+ export const getWeeks = month => {
22
+ const firstDay = month.startOf(MONTH_UNIT);
23
+ const lastDay = month.endOf(MONTH_UNIT);
24
+ const startDate = firstDay.subtract(firstDay.day(), DAY_UNIT);
25
+
26
+ const weeks = [];
27
+ let current = startDate;
28
+
29
+ do {
30
+ const weekStart = current;
31
+ weeks.push(Array.from({ length: 7 }, (_, i) => weekStart.add(i, DAY_UNIT)));
32
+ current = current.add(7, DAY_UNIT);
33
+ } while (current.isBefore(lastDay) || current.isSame(lastDay, DAY_UNIT));
34
+
35
+ return weeks;
36
+ };
37
+
38
+ export const getYearRange = (minDateStr, maxDateStr) => {
39
+ const currentYear = dayjs().year();
40
+ const minYear = minDateStr ? dayjs(minDateStr, OUTPUT_LABEL_MASK).year() : currentYear - YEAR_RANGE_BEFORE;
41
+ const maxYear = maxDateStr ? dayjs(maxDateStr, OUTPUT_LABEL_MASK).year() : currentYear + YEAR_RANGE_AFTER;
42
+ const years = [];
43
+ for (let y = maxYear; y >= minYear; y--) years.push(y);
44
+ return years;
45
+ };
46
+
47
+ export const autoFormatDate = val => {
48
+ const digits = val.replace(/\D/g, '').slice(0, 8);
49
+ if (digits.length <= 2) return digits;
50
+ if (digits.length <= 4) return `${digits.slice(0, 2)}/${digits.slice(2)}`;
51
+ return `${digits.slice(0, 2)}/${digits.slice(2, 4)}/${digits.slice(4)}`;
52
+ };
@@ -1,39 +1,117 @@
1
1
  # UTLoading
2
2
 
3
- Wraps a component within a screen and displays a loading indicator until it's done loading. For example, if you have a screen with a component that requires data from an external source to render properly, you can wrap it with this component, and by providing the proper `loading` prop, it'll show a spinner until the process finishes.
3
+ Envuelve un componente y muestra un indicador de carga mientras la prop `loading` es `true`. Soporta dos versiones: V0 (comportamiento original) y V1 (nuevo diseño con spinner SVG y loader con logo).
4
4
 
5
- ## Props
5
+ ## Props comunes
6
6
 
7
- | NAME | TYPE | REQUIRED | USED BY | DESCRIPTION |
8
- | ----------------- | ------------------- | -------- | :-----------------------: | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
9
- | children | PropTypes.element | Yes | AnimatedCircles - Spinner | The component that you want to wrap until it's done loading |
10
- | loading | PropTypes.bool | Yes | AnimatedCircles - Spinner | The boolean`loading` that you want the spinner to depend on |
11
- | color | PropTypes.string | No | AnimatedCircles - Spinner | Color of spinner. Uses the theme's primary color by default |
12
- | size | PropTypes.number | No | Spinner | The size of the spinner, defaults to`70` |
13
- | thickness | PropTypes.number | No | Spinner | The thickness of the spinner, defaults to`3` |
14
- | style | ViewPropTypes.style | No | Spinner | custom style applied to the spinner's container |
15
- | message | PropTypes.string | No | Spinner | A message to display below the spinner |
16
- | messageStyle | ViewPropTypes.style | No | Spinner | Custom style applied to the message |
17
- | Logo | PropTypes.number | No | AnimatedCircles | Utility logo (png) shown above the animated circles. |
18
- | useUtilityLoading | PropTypes.bool | No | AnimatedCircles - Spinner | Flag that determines whether to show the classic loader (spinner) or the new one (animated circles with utility logo).<br /> (_Default: classic loader_). |
7
+ | Nombre | Tipo | Requerido | Descripción |
8
+ | ----------------- | ------------------- | --------- | --------------------------------------------------------------------------- |
9
+ | loading | bool | | Controla si se muestra el indicador de carga |
10
+ | version | string | No | Versión del componente: `'V0'` (default) o `'V1'` |
11
+ | useUtilityLoading | bool | No | En V0: muestra AnimatedCircles en lugar del Spinner. En V1: muestra LoaderWithLogo en lugar de NewSpinner |
19
12
 
20
- ## Example
13
+ ## V0 — Comportamiento original (default)
14
+
15
+ Cuando `useUtilityLoading` es `false` (default): spinner Material Design.
16
+ Cuando `useUtilityLoading` es `true`: logo del cliente + tres círculos animados.
17
+
18
+ ### Props adicionales de V0
19
+
20
+ | Nombre | Tipo | Usado por | Descripción |
21
+ | ------------- | ------------------- | --------------------------- | ------------------------------------------------ |
22
+ | children | node | AnimatedCircles - Spinner | Componente a mostrar cuando `loading` es `false` |
23
+ | color | string | AnimatedCircles - Spinner | Color del spinner |
24
+ | Logo | number | AnimatedCircles | Asset del logo de la utility (`require()`) |
25
+ | message | string | Spinner | Texto debajo del spinner |
26
+ | messageStyle | style | Spinner | Estilo del texto |
27
+ | preventUnmount| bool | Spinner | Mantiene el children montado durante la carga |
28
+ | size | number | Spinner | Tamaño del spinner (default: 70) |
29
+ | style | style | Spinner | Estilo del contenedor |
30
+ | thickness | number | Spinner | Grosor del spinner (default: 3) |
31
+
32
+ ## V1 — Nuevo diseño
33
+
34
+ Cuando `useUtilityLoading` es `false` (default): **NewSpinner** — spinner SVG animado con Track + Arc redondeado.
35
+ Cuando `useUtilityLoading` es `true`: **LoaderWithLogo** — logo SVG del cliente con animación de pulso y track con gradiente.
36
+
37
+ ### Props adicionales de V1 — NewSpinner
38
+
39
+ | Nombre | Tipo | Descripción |
40
+ | ---------- | ------ | --------------------------------------------------- |
41
+ | dataTestId | string | Test ID del contenedor (default: `UTLoading.spinner`) |
42
+ | label | string | Texto opcional debajo del spinner (ej: "Cargando...") |
43
+ | size | number | Tamaño del spinner en px (default: 72) |
44
+ | thickness | number | Grosor del Track y Arc (default: 5) |
45
+
46
+ ### Props adicionales de V1 — LoaderWithLogo
47
+
48
+ | Nombre | Tipo | Descripción |
49
+ | ---------- | ----------- | -------------------------------------------------------------- |
50
+ | dataTestId | string | Test ID del contenedor (default: `UTLoading.loader`) |
51
+ | fullScreen | bool | Si `true`, ocupa toda la pantalla con position absolute y z-index alto |
52
+ | Logo | elementType | Componente SVG del logo de la utility (importado vía react-native-svg-transformer) |
53
+ | logoSize | number | Tamaño del logo en px (default: 56) |
54
+ | size | number | Tamaño del track circular en px (default: 120) |
55
+ | thickness | number | Grosor del track (default: 5) |
56
+
57
+ ### Colores (override vía ThemeProvider)
58
+
59
+ Los colores del V1 se configuran vía `theme.UTLoading`:
60
+
61
+ | Token | Default | Descripción |
62
+ | ------------------ | ---------- | ------------------------------------ |
63
+ | `arcColor` | `#0136E7` | Color del arco del NewSpinner |
64
+ | `trackColor` | `#E9EFFF` | Color del track del NewSpinner |
65
+ | `gradientStart` | `#285AFF` | Color inicial del gradiente del Loader |
66
+ | `gradientEnd` | `#7AA0FF` | Color final del gradiente del Loader |
67
+ | `trackBackground` | `#E9EFFF` | Color del track de fondo del Loader |
68
+
69
+ ## Activación desde la app (UtilityGO Office Mobile)
70
+
71
+ ```js
72
+ // src/config/base/config.json
73
+ "dashboard": {
74
+ "parameters": {
75
+ "newDashboardExperience": {
76
+ "parameters": {
77
+ "loading": { "enabled": false }
78
+ }
79
+ }
80
+ }
81
+ }
82
+ ```
83
+
84
+ ```js
85
+ // En cada pantalla
86
+ const { enabled: useNewLoading } =
87
+ appConfig.dashboard?.parameters?.newDashboardExperience?.parameters?.loading || {};
88
+
89
+ <UTLoading
90
+ version={useNewLoading ? 'V1' : 'V0'}
91
+ loading={isLoading}
92
+ Logo={UtilityLogo}
93
+ useUtilityLoading={useUtilityLoading}
94
+ />
95
+ ```
96
+
97
+ ## Ejemplo
21
98
 
22
99
  ```js
23
- import { Loading } from "@widergy/mobile-ui";
24
-
25
- return (
26
- <UTLabel>This component does not depend on the loader</UTLabel>
27
- <UTLoading
28
- loading={this.props.loading}
29
- color="blue"
30
- size={200}
31
- thickness={20}
32
- style={{backgroundColor: 'green'}}
33
- message="This one does!"
34
- messageStyle={{fontWeight: 'italic'}}
35
- />
36
- {your wrapped component goes here}
37
- </UTLoading>
38
- )
100
+ import { UTLoading } from '@widergy/mobile-ui';
101
+ import DemoLogo from 'config/utility/usersConfig/default/logo.svg';
102
+
103
+ // V1 Spinner nuevo
104
+ <UTLoading version="V1" loading={isLoading} label="Cargando..." />
105
+
106
+ // V1 — Loader con logo fullScreen
107
+ <UTLoading
108
+ version="V1"
109
+ useUtilityLoading
110
+ fullScreen
111
+ loading={isLoading}
112
+ Logo={DemoLogo}
113
+ />
114
+
115
+ // V0 — Spinner clásico (sin cambios)
116
+ <UTLoading version="V0" loading={isLoading} message="Cargando..." />
39
117
  ```
@@ -1,18 +1,18 @@
1
1
  import React from 'react';
2
- import { bool } from 'prop-types';
2
+ import { string } from 'prop-types';
3
3
 
4
- import AnimatedCircles from './components/AnimatedCircles';
5
- import Spinner from './components/Spinner';
4
+ import V0 from './versions/V0';
5
+ import V1 from './versions/V1';
6
6
 
7
- const UTLoading = props => {
8
- const { useUtilityLoading } = props || {};
9
- return useUtilityLoading ? <AnimatedCircles {...props} /> : <Spinner {...props} />;
10
- };
7
+ const VERSIONS = { V0, V1 };
11
8
 
12
- UTLoading.displayName = 'UTLoading';
9
+ const UTLoading = ({ version = 'V0', ...props }) => {
10
+ const Component = VERSIONS[version] || V0;
11
+ return <Component {...props} />;
12
+ };
13
13
 
14
14
  UTLoading.propTypes = {
15
- useUtilityLoading: bool
15
+ version: string
16
16
  };
17
17
 
18
18
  export default UTLoading;
@@ -3,7 +3,7 @@ import React, { useEffect, useRef } from 'react';
3
3
  import { Animated, Image, View } from 'react-native';
4
4
  import { string, bool, node, number } from 'prop-types';
5
5
 
6
- import { useTheme } from '../../../../theming';
6
+ import { useTheme } from '../../../../../../theming';
7
7
 
8
8
  import {
9
9
  OPACITY_DURATION,
@@ -1,27 +1,30 @@
1
1
  import { StyleSheet } from 'react-native';
2
2
 
3
- import { verticalScale } from '../../../../utils/scaleUtils';
3
+ import { verticalScale } from '../../../../../../utils/scaleUtils';
4
+
5
+ const WHITE = '#ffffff';
6
+ const BLACK = '#000000';
4
7
 
5
8
  export default StyleSheet.create({
9
+ circle: {
10
+ backgroundColor: BLACK,
11
+ borderRadius: 10,
12
+ height: 16,
13
+ margin: 4,
14
+ width: 16
15
+ },
16
+ circlesContainer: {
17
+ flexDirection: 'row',
18
+ marginTop: 50
19
+ },
6
20
  container: {
7
21
  alignItems: 'center',
8
- backgroundColor: '#ffffff',
22
+ backgroundColor: WHITE,
9
23
  flex: 1,
10
24
  flexDirection: 'column',
11
25
  justifyContent: 'center',
12
26
  width: '100%'
13
27
  },
14
- circlesContainer: {
15
- marginTop: 50,
16
- flexDirection: 'row'
17
- },
18
- circle: {
19
- backgroundColor: '#000000',
20
- borderRadius: 10,
21
- height: 16,
22
- margin: 4,
23
- width: 16
24
- },
25
28
  imageStyle: {
26
29
  height: verticalScale(40)
27
30
  }
@@ -1,9 +1,9 @@
1
- import React, { Fragment } from 'react';
1
+ import React from 'react';
2
2
  import { number, string, bool } from 'prop-types';
3
3
  import { View } from 'react-native';
4
4
  import { ViewPropTypes } from 'deprecated-react-native-prop-types';
5
5
 
6
- import Loading from '../../../Loading';
6
+ import Loading from '../../../../../Loading';
7
7
 
8
8
  import styles from './styles';
9
9
 
@@ -19,7 +19,7 @@ const Spinner = ({
19
19
  thickness
20
20
  }) => {
21
21
  return (
22
- <Fragment>
22
+ <>
23
23
  {!!loading && (
24
24
  <Loading
25
25
  style={[styles.spinner, style]}
@@ -36,7 +36,7 @@ const Spinner = ({
36
36
  ) : (
37
37
  !loading && children
38
38
  )}
39
- </Fragment>
39
+ </>
40
40
  );
41
41
  };
42
42
 
@@ -4,8 +4,5 @@ export default StyleSheet.create({
4
4
  spinner: {
5
5
  alignSelf: 'center',
6
6
  justifyContent: 'center'
7
- },
8
- displayNone: {
9
- display: 'none'
10
7
  }
11
8
  });