@m4l/components 9.3.16-JT19092025.beta.1 → 9.3.17-JT25092025.beta.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.
- package/components/Stepper/Stepper.styles.js +11 -13
- package/components/Stepper/helpers/getInitialFieldValues/index.d.ts +12 -0
- package/components/Stepper/helpers/getInitialFieldValues/index.js +14 -0
- package/components/Stepper/helpers/index.d.ts +2 -0
- package/components/Stepper/helpers/parseWatchedValues/index.d.ts +17 -0
- package/components/Stepper/helpers/parseWatchedValues/index.js +12 -0
- package/components/Stepper/hooks/useDynamicValidation/index.d.ts +3 -1
- package/components/Stepper/hooks/useDynamicValidation/index.js +30 -18
- package/components/Stepper/hooks/useStepperActions/index.js +1 -3
- package/components/Stepper/store/StepperStore/index.js +20 -1
- package/components/Stepper/subcomponents/StepArea/index.js +38 -26
- package/components/Stepper/subcomponents/StepArea/subcomponents/Inidicator/index.js +18 -10
- package/components/Stepper/subcomponents/StepperContent/subcomponents/Step/index.js +30 -11
- package/components/Stepper/subcomponents/StepperFooter/subcomponents/StepperFooterRightActions/index.js +5 -3
- package/components/areas/icons.js +1 -1
- package/components/hook-form/RHFAutocomplete/RHFAutocomplete.js +3 -35
- package/components/hook-form/RHFAutocomplete/types.d.ts +1 -6
- package/components/index.d.ts +1 -0
- package/components/mui_extended/Autocomplete/Autocomplete.js +12 -6
- package/components/mui_extended/Autocomplete/Autocomplete.styles.js +48 -5
- package/components/mui_extended/Autocomplete/hooks/useEndAdornments.d.ts +1 -0
- package/components/mui_extended/Autocomplete/hooks/useEndAdornments.js +4 -3
- package/components/mui_extended/Autocomplete/hooks/useStartAdornments.js +4 -4
- package/components/mui_extended/Autocomplete/hooks/useValuesAndHandlers.js +39 -4
- package/components/mui_extended/Autocomplete/slots/AutocompleteEnum.d.ts +3 -1
- package/components/mui_extended/Autocomplete/slots/AutocompleteEnum.js +2 -0
- package/components/mui_extended/Autocomplete/slots/AutocompleteSlots.d.ts +6 -0
- package/components/mui_extended/Autocomplete/slots/AutocompleteSlots.js +11 -1
- package/components/mui_extended/Autocomplete/types.d.ts +1 -1
- package/components/mui_extended/Button/ButtonStyles.js +3 -6
- package/components/mui_extended/Popper/Popper.js +9 -2
- package/components/mui_extended/Popper/types.d.ts +1 -0
- package/components/mui_extended/Select/Select.js +17 -10
- package/components/mui_extended/Select/Select.styles.js +17 -10
- package/components/mui_extended/Select/types.d.ts +1 -1
- package/components/mui_extended/TextField/TextField.d.ts +2 -1
- package/components/mui_extended/TextField/TextField.js +25 -4
- package/components/mui_extended/TextField/TextField.styles.js +132 -125
- package/components/mui_extended/TextField/slots/TextFieldSlots.d.ts +3 -9
- package/components/mui_extended/TextField/slots/TextFieldSlots.js +2 -1
- package/components/mui_extended/Typography/Typography.js +1 -1
- package/package.json +1 -1
- package/test/mocks/dictionary-mock.d.ts +433 -0
|
@@ -76,8 +76,7 @@ const stepperStyles = {
|
|
|
76
76
|
const isLastStep = step === totalSteps - 1;
|
|
77
77
|
return {
|
|
78
78
|
cursor: "pointer",
|
|
79
|
-
display: "flex",
|
|
80
|
-
visibility: ownerState?.isStepVisible ? "visible" : "hidden",
|
|
79
|
+
display: ownerState?.isStepVisible ? "flex" : "none",
|
|
81
80
|
flexDirection: ownerState?.orientation === "vertical" || theme.generalSettings.isMobile ? "column" : "row",
|
|
82
81
|
alignItems: ownerState?.orientation === "vertical" || theme.generalSettings.isMobile ? "center" : "start",
|
|
83
82
|
justifyContent: ownerState?.visibleTitle ? "space-between" : "center",
|
|
@@ -131,7 +130,7 @@ const stepperStyles = {
|
|
|
131
130
|
whiteSpace: "normal",
|
|
132
131
|
order: ownerState?.orientation === "vertical" || theme.generalSettings.isMobile ? 1 : 0,
|
|
133
132
|
"&.M4LTypography-root": {
|
|
134
|
-
color:
|
|
133
|
+
color: ownerState?.originalStepIndex !== void 0 && typeof ownerState.originalStepIndex === "number" ? (ownerState.currentStep ?? 0) > ownerState.originalStepIndex ? theme.vars.palette.primary.semanticText : (ownerState.currentStep ?? 0) === ownerState.originalStepIndex ? theme.vars.palette.text.primary : theme.vars.palette.text.secondary : theme.vars.palette.text.secondary,
|
|
135
134
|
textAlign: ownerState?.orientation === "vertical" || theme.generalSettings.isMobile ? "center" : "right"
|
|
136
135
|
}
|
|
137
136
|
}),
|
|
@@ -139,13 +138,12 @@ const stepperStyles = {
|
|
|
139
138
|
* Estilos para el indicador numérico de cada paso del Stepper.
|
|
140
139
|
*/
|
|
141
140
|
indicator: ({ theme, ownerState }) => {
|
|
142
|
-
const currentStep = ownerState?.currentStep ?? 0;
|
|
143
141
|
const step = ownerState?.step ?? 0;
|
|
144
142
|
const totalSteps = ownerState?.totalSteps ?? 0;
|
|
145
|
-
const isCompleted =
|
|
146
|
-
const isCurrent =
|
|
143
|
+
const isCompleted = ownerState?.isCompleted ?? false;
|
|
144
|
+
const isCurrent = ownerState?.isCurrent ?? false;
|
|
145
|
+
const isValidStep = ownerState?.isValidStep ?? true;
|
|
147
146
|
const isLastStep = step === totalSteps - 1;
|
|
148
|
-
const isValidStep = ownerState?.stepValidationStatus?.[step] ?? true;
|
|
149
147
|
return {
|
|
150
148
|
...ownerState?.orientation === "horizontal" ? {
|
|
151
149
|
marginTop: theme.generalSettings.isMobile ? "6px" : theme.vars.size.baseSpacings.sp1
|
|
@@ -155,7 +153,7 @@ const stepperStyles = {
|
|
|
155
153
|
justifyContent: "center",
|
|
156
154
|
flexShrink: 0,
|
|
157
155
|
order: ownerState?.orientation === "vertical" || theme.generalSettings.isMobile ? 0 : 1,
|
|
158
|
-
background: isCompleted ? ownerState?.indicatorType === "dot" || theme.generalSettings.isMobile ? theme.vars.palette.background.default : theme.vars.palette.primary.toneOpacity :
|
|
156
|
+
background: !isValidStep && ownerState?.hasBeenValidated ? theme.vars.palette.error.enabled : isCompleted && isValidStep ? ownerState?.indicatorType === "dot" || theme.generalSettings.isMobile ? theme.vars.palette.background.default : theme.vars.palette.primary.toneOpacity : isCurrent ? ownerState?.indicatorType === "dot" || theme.generalSettings.isMobile ? theme.vars.palette.background.default : theme.vars.palette.primary.enabled : ownerState?.indicatorType === "dot" || theme.generalSettings.isMobile ? theme.vars.palette.background.default : theme.vars.palette.default.enabled,
|
|
159
157
|
borderRadius: theme.vars.size.borderRadius.r2,
|
|
160
158
|
...ownerState?.indicatorType === "number" && !theme.generalSettings.isMobile && {
|
|
161
159
|
boxShadow: isCurrent ? "0 2px 8px 0 rgb(0, 100, 255, 0.16)" : "none"
|
|
@@ -183,13 +181,13 @@ const stepperStyles = {
|
|
|
183
181
|
* Estilos para el número de texto dentro del indicador numérico del Stepper.
|
|
184
182
|
*/
|
|
185
183
|
textNumber: ({ theme, ownerState }) => {
|
|
186
|
-
const
|
|
187
|
-
const
|
|
188
|
-
const
|
|
189
|
-
const
|
|
184
|
+
const isCompleted = ownerState?.isCompleted ?? false;
|
|
185
|
+
const isCurrent = ownerState?.isCurrent ?? false;
|
|
186
|
+
const isValidStep = ownerState?.isValidStep ?? true;
|
|
187
|
+
const hasBeenValidated = ownerState?.hasBeenValidated ?? false;
|
|
190
188
|
return {
|
|
191
189
|
"&.M4LTypography-root": {
|
|
192
|
-
color: isCompleted || isCurrent ? theme.vars.palette.primary.contrastText : theme.vars.palette.text.primary
|
|
190
|
+
color: !isValidStep && hasBeenValidated ? theme.vars.palette.error.contrastText : isCompleted || isCurrent ? theme.vars.palette.primary.contrastText : theme.vars.palette.text.primary
|
|
193
191
|
}
|
|
194
192
|
};
|
|
195
193
|
},
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Obtiene los valores iniciales de campos específicos del formulario.
|
|
3
|
+
* Se usa para inicializar el ref que trackea cambios en los campos.
|
|
4
|
+
* @param allValues - Todos los valores del formulario (de getValues())
|
|
5
|
+
* @param fields - Lista de nombres de campos de los que queremos obtener valores
|
|
6
|
+
* @returns Objeto con solo los valores de los campos especificados
|
|
7
|
+
* @example
|
|
8
|
+
* const formValues = { name: 'John', age: 25, city: 'NY', country: 'USA' };
|
|
9
|
+
* getInitialFieldValues(formValues, ['name', 'age'])
|
|
10
|
+
* // Retorna: { name: 'John', age: 25 }
|
|
11
|
+
*/
|
|
12
|
+
export declare function getInitialFieldValues(allValues: Record<string, any>, fields?: string[]): Record<string, any>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
function getInitialFieldValues(allValues, fields = []) {
|
|
2
|
+
if (fields.length === 0) {
|
|
3
|
+
return {};
|
|
4
|
+
}
|
|
5
|
+
return fields.reduce((acc, field) => {
|
|
6
|
+
if (field in allValues) {
|
|
7
|
+
acc[field] = allValues[field];
|
|
8
|
+
}
|
|
9
|
+
return acc;
|
|
10
|
+
}, {});
|
|
11
|
+
}
|
|
12
|
+
export {
|
|
13
|
+
getInitialFieldValues as g
|
|
14
|
+
};
|
|
@@ -2,3 +2,5 @@ export { evaluateVisibilityStepCondition } from './evaluateVisibilityStepConditi
|
|
|
2
2
|
export { findNextVisibleValidStep } from './findNextVisibleValidStep';
|
|
3
3
|
export { findPrevVisibleValidStep } from './findPrevVisibleValidStep';
|
|
4
4
|
export { isLastVisibleValidStep } from './isLastVisibleValidStep';
|
|
5
|
+
export { parseWatchedValues } from './parseWatchedValues';
|
|
6
|
+
export { getInitialFieldValues } from './getInitialFieldValues';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convierte los valores observados de useWatch en un objeto estructurado con los nombres de campos como keys.
|
|
3
|
+
*
|
|
4
|
+
* useWatch de react-hook-form retorna diferentes estructuras según la cantidad de campos observados:
|
|
5
|
+
* - Un solo campo: retorna el valor directamente
|
|
6
|
+
* - Múltiples campos: retorna un array con los valores en el mismo orden de los campos
|
|
7
|
+
* @param watchValues - Valores observados de useWatch (puede ser un valor único o un array)
|
|
8
|
+
* @param fields - Lista de nombres de campos que se están observando
|
|
9
|
+
* @returns Objeto con los valores actuales mapeados a sus respectivos nombres de campo
|
|
10
|
+
* @example
|
|
11
|
+
* // Para un solo campo
|
|
12
|
+
* parseWatchedValues('John', ['name']) // { name: 'John' }
|
|
13
|
+
*
|
|
14
|
+
* // Para múltiples campos
|
|
15
|
+
* parseWatchedValues(['John', 25], ['name', 'age']) // { name: 'John', age: 25 }
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseWatchedValues(watchValues: any, fields: string[]): Record<string, any>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
function parseWatchedValues(watchValues, fields) {
|
|
2
|
+
if (fields.length === 1) {
|
|
3
|
+
return { [fields[0]]: watchValues };
|
|
4
|
+
}
|
|
5
|
+
return fields.reduce((acc, field, index) => {
|
|
6
|
+
acc[field] = Array.isArray(watchValues) ? watchValues[index] : watchValues;
|
|
7
|
+
return acc;
|
|
8
|
+
}, {});
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
parseWatchedValues as p
|
|
12
|
+
};
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
* @returns Objeto con funciones para manejar la validación dinámica
|
|
4
4
|
*/
|
|
5
5
|
export declare function useDynamicValidation(): {
|
|
6
|
-
activateFieldsValidation: (fields: string[]) => void;
|
|
6
|
+
activateFieldsValidation: (fields: string[], skipIfValidating?: boolean) => void;
|
|
7
7
|
clearAllValidation: () => void;
|
|
8
8
|
activeFields: string[];
|
|
9
|
+
startExternalValidation: () => void;
|
|
10
|
+
endExternalValidation: () => void;
|
|
9
11
|
};
|
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
import { useState, useRef, useEffect, useCallback } from "react";
|
|
2
2
|
import { useFormContext, useWatch } from "react-hook-form";
|
|
3
|
+
import { p as parseWatchedValues } from "../../helpers/parseWatchedValues/index.js";
|
|
4
|
+
import { g as getInitialFieldValues } from "../../helpers/getInitialFieldValues/index.js";
|
|
3
5
|
function useDynamicValidation() {
|
|
4
|
-
const { trigger } = useFormContext();
|
|
6
|
+
const { trigger, getValues } = useFormContext();
|
|
5
7
|
const [activeFields, setActiveFields] = useState([]);
|
|
8
|
+
const [isValidating, setIsValidating] = useState(false);
|
|
9
|
+
const statusLoad = useWatch({
|
|
10
|
+
name: "statusLoad"
|
|
11
|
+
});
|
|
6
12
|
const watchValues = useWatch({
|
|
7
13
|
name: activeFields.length > 0 ? activeFields : ["__dummy__"]
|
|
8
14
|
});
|
|
9
15
|
const lastValuesRef = useRef({});
|
|
10
16
|
useEffect(() => {
|
|
11
|
-
if (activeFields.length === 0) {
|
|
17
|
+
if (activeFields.length === 0 || statusLoad !== "ready" || isValidating) {
|
|
12
18
|
return;
|
|
13
19
|
}
|
|
14
|
-
const currentValues =
|
|
15
|
-
acc[field] = Array.isArray(watchValues) ? watchValues[index] : watchValues;
|
|
16
|
-
return acc;
|
|
17
|
-
}, {});
|
|
20
|
+
const currentValues = parseWatchedValues(watchValues, activeFields);
|
|
18
21
|
const changedFields = activeFields.filter((field) => {
|
|
19
22
|
const currentValue = currentValues[field];
|
|
20
23
|
const lastValue = lastValuesRef.current[field];
|
|
@@ -30,18 +33,25 @@ function useDynamicValidation() {
|
|
|
30
33
|
}, 100);
|
|
31
34
|
return () => clearTimeout(timeoutId);
|
|
32
35
|
}
|
|
33
|
-
}, [activeFields, trigger, watchValues]);
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
fields.forEach((field) => {
|
|
40
|
-
if (!lastValuesRef.current.hasOwnProperty(field)) {
|
|
41
|
-
lastValuesRef.current[field] = void 0;
|
|
42
|
-
}
|
|
43
|
-
});
|
|
36
|
+
}, [activeFields, trigger, watchValues, statusLoad, isValidating]);
|
|
37
|
+
const startExternalValidation = useCallback(() => {
|
|
38
|
+
setIsValidating(true);
|
|
39
|
+
}, []);
|
|
40
|
+
const endExternalValidation = useCallback(() => {
|
|
41
|
+
setIsValidating(false);
|
|
44
42
|
}, []);
|
|
43
|
+
const activateFieldsValidation = useCallback(
|
|
44
|
+
(fields, skipIfValidating = true) => {
|
|
45
|
+
if (skipIfValidating && isValidating) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const formValues = getValues();
|
|
49
|
+
setActiveFields(fields);
|
|
50
|
+
const initialValues = getInitialFieldValues(formValues, fields);
|
|
51
|
+
lastValuesRef.current = initialValues;
|
|
52
|
+
},
|
|
53
|
+
[getValues, isValidating]
|
|
54
|
+
);
|
|
45
55
|
const clearAllValidation = useCallback(() => {
|
|
46
56
|
setActiveFields([]);
|
|
47
57
|
lastValuesRef.current = {};
|
|
@@ -49,7 +59,9 @@ function useDynamicValidation() {
|
|
|
49
59
|
return {
|
|
50
60
|
activateFieldsValidation,
|
|
51
61
|
clearAllValidation,
|
|
52
|
-
activeFields
|
|
62
|
+
activeFields,
|
|
63
|
+
startExternalValidation,
|
|
64
|
+
endExternalValidation
|
|
53
65
|
};
|
|
54
66
|
}
|
|
55
67
|
export {
|
|
@@ -54,9 +54,7 @@ function useStepperActions() {
|
|
|
54
54
|
const currentStepData = steps[currentStep - 1];
|
|
55
55
|
const fieldsJustValidated = currentStepData?.validationFields || [];
|
|
56
56
|
if (fieldsJustValidated.length > 0) {
|
|
57
|
-
|
|
58
|
-
clearAllValidation();
|
|
59
|
-
}, 100);
|
|
57
|
+
clearAllValidation();
|
|
60
58
|
}
|
|
61
59
|
}
|
|
62
60
|
if (success && futureFields.length > 0) {
|
|
@@ -35,6 +35,18 @@ const createStepperStore = (initProps, storeDevtoolsEnabled = false) => {
|
|
|
35
35
|
if (!preserveStepValidationStatus) {
|
|
36
36
|
state.stepValidationStatus = {};
|
|
37
37
|
}
|
|
38
|
+
if (!preserveStepValidationStatus) {
|
|
39
|
+
const firstVisibleStepIndex = findNextVisibleValidStep(
|
|
40
|
+
-1,
|
|
41
|
+
// Comenzar desde -1 para encontrar el primer step visible
|
|
42
|
+
steps,
|
|
43
|
+
{},
|
|
44
|
+
state.visibilityData
|
|
45
|
+
);
|
|
46
|
+
if (firstVisibleStepIndex !== 0 && firstVisibleStepIndex < steps.length) {
|
|
47
|
+
state.currentStep = firstVisibleStepIndex;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
38
50
|
});
|
|
39
51
|
},
|
|
40
52
|
/**
|
|
@@ -114,9 +126,16 @@ const createStepperStore = (initProps, storeDevtoolsEnabled = false) => {
|
|
|
114
126
|
*/
|
|
115
127
|
resetStepper: () => {
|
|
116
128
|
set((state) => {
|
|
117
|
-
state.currentStep = 0;
|
|
118
129
|
state.stepValidationStatus = {};
|
|
119
130
|
state.isValidating = false;
|
|
131
|
+
const firstVisibleStepIndex = findNextVisibleValidStep(
|
|
132
|
+
-1,
|
|
133
|
+
// Comenzar desde -1 para encontrar el primer step visible
|
|
134
|
+
state.steps,
|
|
135
|
+
{},
|
|
136
|
+
state.visibilityData
|
|
137
|
+
);
|
|
138
|
+
state.currentStep = firstVisibleStepIndex < state.steps.length ? firstVisibleStepIndex : 0;
|
|
120
139
|
});
|
|
121
140
|
}
|
|
122
141
|
}
|
|
@@ -10,7 +10,7 @@ import { e as evaluateVisibilityStepCondition } from "../../helpers/evaluateVisi
|
|
|
10
10
|
function StepArea() {
|
|
11
11
|
const { trigger, clearErrors } = useFormContext();
|
|
12
12
|
const formValues = useWatch();
|
|
13
|
-
const { activateFieldsValidation } = useDynamicValidation();
|
|
13
|
+
const { activateFieldsValidation, startExternalValidation, endExternalValidation } = useDynamicValidation();
|
|
14
14
|
const {
|
|
15
15
|
currentStep,
|
|
16
16
|
steps,
|
|
@@ -34,16 +34,19 @@ function StepArea() {
|
|
|
34
34
|
}),
|
|
35
35
|
shallow
|
|
36
36
|
);
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
const allSteps = steps;
|
|
38
|
+
const visibleSteps = useMemo(() => {
|
|
39
|
+
return steps.filter(
|
|
40
|
+
(step) => evaluateVisibilityStepCondition(step, formValues || {}, visibilityData)
|
|
41
|
+
);
|
|
42
|
+
}, [steps, formValues, visibilityData]);
|
|
40
43
|
const ownerState = {
|
|
41
44
|
visibleTitle,
|
|
42
45
|
orientation,
|
|
43
|
-
totalSteps:
|
|
46
|
+
totalSteps: visibleSteps.length
|
|
44
47
|
};
|
|
45
48
|
const handleStepClick = async (targetIndex) => {
|
|
46
|
-
const currentIndex =
|
|
49
|
+
const currentIndex = visibleSteps.findIndex(
|
|
47
50
|
(step) => step.key === steps[currentStep].key
|
|
48
51
|
);
|
|
49
52
|
if (targetIndex === currentIndex) {
|
|
@@ -51,7 +54,7 @@ function StepArea() {
|
|
|
51
54
|
}
|
|
52
55
|
const isNavigatingForward = targetIndex > currentIndex;
|
|
53
56
|
const targetOriginalIndex = steps.findIndex(
|
|
54
|
-
(s) => s.key ===
|
|
57
|
+
(s) => s.key === visibleSteps[targetIndex].key
|
|
55
58
|
);
|
|
56
59
|
if (!isNavigatingForward) {
|
|
57
60
|
setCurrentStep(targetOriginalIndex);
|
|
@@ -60,9 +63,11 @@ function StepArea() {
|
|
|
60
63
|
const isSkippingSteps = targetIndex > currentIndex + 1;
|
|
61
64
|
if (isSkippingSteps) {
|
|
62
65
|
for (let i = currentIndex; i < targetIndex; i++) {
|
|
63
|
-
const step =
|
|
66
|
+
const step = visibleSteps[i];
|
|
64
67
|
const stepOriginalIndex = steps.findIndex((s) => s.key === step.key);
|
|
68
|
+
startExternalValidation();
|
|
65
69
|
const isValid = await trigger(step.validationFields);
|
|
70
|
+
endExternalValidation();
|
|
66
71
|
if (!isValid) {
|
|
67
72
|
setCurrentStep(stepOriginalIndex);
|
|
68
73
|
setStepValidationStatus(stepOriginalIndex, false);
|
|
@@ -72,11 +77,13 @@ function StepArea() {
|
|
|
72
77
|
setStepValidationStatus(stepOriginalIndex, true);
|
|
73
78
|
}
|
|
74
79
|
} else {
|
|
75
|
-
const currentStepData =
|
|
80
|
+
const currentStepData = visibleSteps[currentIndex];
|
|
76
81
|
const currentStepOriginalIndex = steps.findIndex(
|
|
77
82
|
(s) => s.key === currentStepData.key
|
|
78
83
|
);
|
|
84
|
+
startExternalValidation();
|
|
79
85
|
const isCurrentValid = await trigger(currentStepData.validationFields);
|
|
86
|
+
endExternalValidation();
|
|
80
87
|
if (!isCurrentValid) {
|
|
81
88
|
setStepValidationStatus(currentStepOriginalIndex, false);
|
|
82
89
|
activateFieldsValidation(currentStepData.validationFields || []);
|
|
@@ -86,13 +93,13 @@ function StepArea() {
|
|
|
86
93
|
}
|
|
87
94
|
setCurrentStep(targetOriginalIndex);
|
|
88
95
|
if (isNavigatingForward) {
|
|
89
|
-
const currentStepData =
|
|
96
|
+
const currentStepData = visibleSteps[currentIndex];
|
|
90
97
|
const currentStepOriginalIndex = steps.findIndex(
|
|
91
98
|
(s) => s.key === currentStepData.key
|
|
92
99
|
);
|
|
93
100
|
const isCurrentStepValid = stepValidationStatus[currentStepOriginalIndex] !== false;
|
|
94
101
|
if (isCurrentStepValid) {
|
|
95
|
-
const targetStep =
|
|
102
|
+
const targetStep = visibleSteps[targetIndex];
|
|
96
103
|
const targetStepFields = targetStep.validationFields || [];
|
|
97
104
|
if (targetStepFields.length > 0) {
|
|
98
105
|
clearErrors(targetStepFields);
|
|
@@ -104,32 +111,37 @@ function StepArea() {
|
|
|
104
111
|
}
|
|
105
112
|
}
|
|
106
113
|
};
|
|
107
|
-
return /* @__PURE__ */ jsx(StepAreaStyled, { ownerState, children:
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
114
|
+
return /* @__PURE__ */ jsx(StepAreaStyled, { ownerState, children: allSteps.map((step, originalIndex) => {
|
|
115
|
+
const isStepVisible = evaluateVisibilityStepCondition(
|
|
116
|
+
step,
|
|
117
|
+
formValues || {},
|
|
118
|
+
visibilityData
|
|
119
|
+
);
|
|
120
|
+
const visibleStepIndex = isStepVisible ? visibleSteps.findIndex((visStep) => visStep.key === step.key) : -1;
|
|
112
121
|
return /* @__PURE__ */ jsxs(
|
|
113
122
|
StepStyled,
|
|
114
123
|
{
|
|
115
124
|
role: "button",
|
|
116
|
-
onClick: () => handleStepClick(
|
|
125
|
+
onClick: () => isStepVisible ? handleStepClick(visibleStepIndex) : void 0,
|
|
117
126
|
ownerState: {
|
|
118
127
|
...ownerState,
|
|
119
128
|
currentStep,
|
|
120
|
-
step:
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
formValues || {},
|
|
124
|
-
visibilityData
|
|
125
|
-
)
|
|
129
|
+
step: visibleStepIndex,
|
|
130
|
+
// Usa el índice en la secuencia visible
|
|
131
|
+
isStepVisible
|
|
126
132
|
},
|
|
127
133
|
children: [
|
|
128
134
|
visibleTitle && /* @__PURE__ */ jsx(
|
|
129
135
|
StepNameStyled,
|
|
130
136
|
{
|
|
131
137
|
variant: "body",
|
|
132
|
-
ownerState: {
|
|
138
|
+
ownerState: {
|
|
139
|
+
...ownerState,
|
|
140
|
+
currentStep,
|
|
141
|
+
step: visibleStepIndex,
|
|
142
|
+
originalStepIndex: originalIndex,
|
|
143
|
+
isStepVisible
|
|
144
|
+
},
|
|
133
145
|
children: step.title
|
|
134
146
|
}
|
|
135
147
|
),
|
|
@@ -137,8 +149,8 @@ function StepArea() {
|
|
|
137
149
|
Indicator,
|
|
138
150
|
{
|
|
139
151
|
currentStep,
|
|
140
|
-
step:
|
|
141
|
-
totalSteps:
|
|
152
|
+
step: visibleStepIndex,
|
|
153
|
+
totalSteps: visibleSteps.length,
|
|
142
154
|
originalStepIndex: originalIndex
|
|
143
155
|
}
|
|
144
156
|
)
|
|
@@ -21,15 +21,6 @@ function Indicator(props) {
|
|
|
21
21
|
);
|
|
22
22
|
const { host_static_assets, environment_assets } = useEnvironment();
|
|
23
23
|
const { currentSize } = useComponentSize(size);
|
|
24
|
-
const ownerState = {
|
|
25
|
-
size: currentSize,
|
|
26
|
-
currentStep,
|
|
27
|
-
step,
|
|
28
|
-
totalSteps,
|
|
29
|
-
orientation,
|
|
30
|
-
indicatorType,
|
|
31
|
-
stepValidationStatus
|
|
32
|
-
};
|
|
33
24
|
const isMobile = useIsMobile();
|
|
34
25
|
const effectiveIndicatorType = useMemo(() => {
|
|
35
26
|
return isMobile ? "dot" : indicatorType;
|
|
@@ -45,6 +36,20 @@ function Indicator(props) {
|
|
|
45
36
|
hasBeenValidated: validated
|
|
46
37
|
};
|
|
47
38
|
}, [currentStep, originalStepIndex, stepValidationStatus]);
|
|
39
|
+
const ownerState = {
|
|
40
|
+
size: currentSize,
|
|
41
|
+
currentStep,
|
|
42
|
+
step,
|
|
43
|
+
totalSteps,
|
|
44
|
+
orientation,
|
|
45
|
+
indicatorType,
|
|
46
|
+
stepValidationStatus,
|
|
47
|
+
originalStepIndex,
|
|
48
|
+
isCompleted,
|
|
49
|
+
isCurrent: currentStep === originalStepIndex,
|
|
50
|
+
isValidStep,
|
|
51
|
+
hasBeenValidated
|
|
52
|
+
};
|
|
48
53
|
return /* @__PURE__ */ jsx(IndicatorStyled, { ownerState, children: hasBeenValidated && !isValidStep ? (
|
|
49
54
|
// Mostrar error solo si ha sido validado y es inválido
|
|
50
55
|
/* @__PURE__ */ jsx(
|
|
@@ -67,7 +72,10 @@ function Indicator(props) {
|
|
|
67
72
|
)
|
|
68
73
|
) : (
|
|
69
74
|
// Mostrar estado normal (número o dot) para pasos no validados o actuales
|
|
70
|
-
/* @__PURE__ */ jsx(TextNumberStyled, { variant: "body", ownerState
|
|
75
|
+
/* @__PURE__ */ jsx(TextNumberStyled, { variant: "body", ownerState, children: effectiveIndicatorType === "number" ? (
|
|
76
|
+
// Solo mostrar número si el step es visible (step >= 0)
|
|
77
|
+
step >= 0 ? step + 1 : ""
|
|
78
|
+
) : /* @__PURE__ */ jsx(
|
|
71
79
|
Icon,
|
|
72
80
|
{
|
|
73
81
|
src: `${host_static_assets}/${environment_assets}/${currentStep === originalStepIndex ? pathIcons.dotSelected : pathIcons.dotOutline}`,
|
|
@@ -12,28 +12,47 @@ function Step(props) {
|
|
|
12
12
|
steps: state.steps,
|
|
13
13
|
visibilityData: state.visibilityData
|
|
14
14
|
}));
|
|
15
|
-
const currentStepConfig = useMemo(() => {
|
|
16
|
-
return steps[currentStep];
|
|
17
|
-
}, [steps, currentStep]);
|
|
18
15
|
const stepConfig = useMemo(() => {
|
|
19
16
|
return steps.find((step) => step.key === stepKey);
|
|
20
17
|
}, [steps, stepKey]);
|
|
21
18
|
const isStepVisible = useMemo(() => {
|
|
22
|
-
if (!
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
if (stepKey !== currentStepConfig.key) {
|
|
19
|
+
if (!stepConfig) {
|
|
26
20
|
return false;
|
|
27
21
|
}
|
|
28
|
-
|
|
22
|
+
const meetsVisibilityCondition = evaluateVisibilityStepCondition(
|
|
29
23
|
stepConfig,
|
|
30
24
|
formValues || {},
|
|
31
25
|
visibilityData
|
|
32
|
-
)
|
|
26
|
+
);
|
|
27
|
+
if (!meetsVisibilityCondition) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
const currentStepConfig = steps[currentStep];
|
|
31
|
+
if (!currentStepConfig) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
if (evaluateVisibilityStepCondition(currentStepConfig, formValues || {}, visibilityData)) {
|
|
35
|
+
return stepKey === currentStepConfig.key;
|
|
36
|
+
}
|
|
37
|
+
const visibleStepsUpToCurrent = [];
|
|
38
|
+
for (let i = 0; i <= currentStep; i++) {
|
|
39
|
+
const step = steps[i];
|
|
40
|
+
if (evaluateVisibilityStepCondition(step, formValues || {}, visibilityData)) {
|
|
41
|
+
visibleStepsUpToCurrent.push(step);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (visibleStepsUpToCurrent.length === 0) {
|
|
45
|
+
for (let i = currentStep + 1; i < steps.length; i++) {
|
|
46
|
+
const step = steps[i];
|
|
47
|
+
if (evaluateVisibilityStepCondition(step, formValues || {}, visibilityData)) {
|
|
48
|
+
return stepKey === step.key;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
33
51
|
return false;
|
|
34
52
|
}
|
|
35
|
-
|
|
36
|
-
|
|
53
|
+
const activeVisibleStep = visibleStepsUpToCurrent[visibleStepsUpToCurrent.length - 1];
|
|
54
|
+
return stepKey === activeVisibleStep.key;
|
|
55
|
+
}, [currentStep, stepKey, stepConfig, steps, formValues, visibilityData]);
|
|
37
56
|
return /* @__PURE__ */ jsx(StepContentStyled, { ownerState: { isStepVisible }, children });
|
|
38
57
|
}
|
|
39
58
|
export {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import React, { useMemo } from "react";
|
|
2
|
+
import React, { useState, useEffect, useMemo } from "react";
|
|
3
3
|
import { u as useIsLastVisibleValidStep } from "../../../../hooks/useIsLastVisibleValidStep/index.js";
|
|
4
4
|
import { m as StepperFooterRightActionsStyled } from "../../../../slots/StepperSlot.js";
|
|
5
5
|
import { S as StepperSubmitButton } from "../../../StepperButtons/StepperSubmitButton/index.js";
|
|
@@ -7,13 +7,15 @@ import { S as StepperNextButton } from "../../../StepperButtons/StepperNextButto
|
|
|
7
7
|
function StepperFooterRightActions(props) {
|
|
8
8
|
const { children } = props;
|
|
9
9
|
const isLastVisibleValidStep = useIsLastVisibleValidStep();
|
|
10
|
-
const hasCustomSubmitButton =
|
|
11
|
-
|
|
10
|
+
const [hasCustomSubmitButton, setHasCustomSubmitButton] = useState(false);
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
const hasCustomButton = React.Children.toArray(children).some((child) => {
|
|
12
13
|
if (React.isValidElement(child)) {
|
|
13
14
|
return child.type === StepperSubmitButton;
|
|
14
15
|
}
|
|
15
16
|
return false;
|
|
16
17
|
});
|
|
18
|
+
setHasCustomSubmitButton(hasCustomButton);
|
|
17
19
|
}, [children]);
|
|
18
20
|
const filteredChildren = useMemo(() => {
|
|
19
21
|
return React.Children.toArray(children).filter((child) => {
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { getPropertyByString } from "@m4l/core";
|
|
3
|
-
import { useIsMobile } from "@m4l/graphics";
|
|
4
|
-
import { useTheme } from "@mui/material";
|
|
5
2
|
import { useId, useState, useCallback, useEffect } from "react";
|
|
6
3
|
import { useFormContext, Controller } from "react-hook-form";
|
|
7
4
|
import { A as AutocompleteRootStyled, L as LabelStyled } from "./slots/RHFAutocompleteSlots.js";
|
|
@@ -13,28 +10,22 @@ function RHFAutocomplete(props) {
|
|
|
13
10
|
getOptionLabel,
|
|
14
11
|
isOptionEqualToValue,
|
|
15
12
|
label,
|
|
16
|
-
color,
|
|
17
13
|
options,
|
|
18
14
|
disabled,
|
|
19
15
|
onOpen,
|
|
20
16
|
onClose,
|
|
21
17
|
loading,
|
|
22
|
-
variant,
|
|
23
18
|
helperMessage,
|
|
24
19
|
size,
|
|
25
20
|
onChangeFilterParmsLocal,
|
|
26
21
|
mandatory,
|
|
27
22
|
mandatoryMessage,
|
|
28
23
|
multiple,
|
|
29
|
-
imageScale = true,
|
|
30
|
-
imageRepeat,
|
|
31
24
|
refresh
|
|
32
25
|
// onChange: onChangeRHF,
|
|
33
26
|
} = props;
|
|
34
27
|
const htmlForId = useId();
|
|
35
|
-
const theme = useTheme();
|
|
36
28
|
const [open, setOpen] = useState(false);
|
|
37
|
-
const isDesktop = !useIsMobile();
|
|
38
29
|
const onCloseLocal = useCallback((event, reason) => {
|
|
39
30
|
setOpen(false);
|
|
40
31
|
if (onClose) {
|
|
@@ -59,34 +50,11 @@ function RHFAutocomplete(props) {
|
|
|
59
50
|
},
|
|
60
51
|
[getOptionLabel]
|
|
61
52
|
);
|
|
62
|
-
const paletteColor = getPropertyByString(
|
|
63
|
-
theme.vars.palette,
|
|
64
|
-
disabled ? "default" : color || "default",
|
|
65
|
-
theme.vars.palette.default
|
|
66
|
-
);
|
|
67
53
|
const {
|
|
68
|
-
control
|
|
69
|
-
formState: { errors }
|
|
54
|
+
control
|
|
70
55
|
} = useFormContext();
|
|
71
|
-
const [currentVariant, setCurrentVariant] = useState(null);
|
|
72
|
-
useEffect(() => {
|
|
73
|
-
const hasError = errors[nameRHF];
|
|
74
|
-
if (hasError) {
|
|
75
|
-
setCurrentVariant("error");
|
|
76
|
-
} else if (variant) {
|
|
77
|
-
setCurrentVariant(variant);
|
|
78
|
-
} else {
|
|
79
|
-
setCurrentVariant(null);
|
|
80
|
-
}
|
|
81
|
-
}, [errors, nameRHF, variant, control]);
|
|
82
56
|
const ownerState = {
|
|
83
|
-
|
|
84
|
-
semantics: currentVariant,
|
|
85
|
-
disabled,
|
|
86
|
-
multiple: Boolean(multiple),
|
|
87
|
-
imageScale: Boolean(imageScale),
|
|
88
|
-
imageRepeat: Boolean(imageRepeat),
|
|
89
|
-
paletteColor
|
|
57
|
+
disabled
|
|
90
58
|
};
|
|
91
59
|
return /* @__PURE__ */ jsx(
|
|
92
60
|
AutocompleteRootStyled,
|
|
@@ -147,7 +115,7 @@ function RHFAutocomplete(props) {
|
|
|
147
115
|
htmlFor: htmlForId
|
|
148
116
|
}
|
|
149
117
|
),
|
|
150
|
-
|
|
118
|
+
error?.message ? /* @__PURE__ */ jsx(HelperError, { message: error?.message }) : null
|
|
151
119
|
] });
|
|
152
120
|
}
|
|
153
121
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AutocompleteCloseReason, AutocompleteFreeSoloValueMapping, AutocompleteInputChangeReason, AutocompleteProps as MUIAutocompleteProps, Theme,
|
|
1
|
+
import { AutocompleteCloseReason, AutocompleteFreeSoloValueMapping, AutocompleteInputChangeReason, AutocompleteProps as MUIAutocompleteProps, Theme, PopperProps } from '@mui/material';
|
|
2
2
|
import { ComponentPalletColor, Sizes } from '@m4l/styles';
|
|
3
3
|
import { TextFieldProps } from '../../mui_extended/TextField/types';
|
|
4
4
|
import { RFHAUTOCOMPLETE_KEY_COMPONENT } from './constants';
|
|
@@ -52,11 +52,6 @@ export interface RHFAutocompleteProps<T = any, Multiple extends boolean | undefi
|
|
|
52
52
|
*/
|
|
53
53
|
export interface RHFAutocompleteOwnerState extends Pick<RHFAutocompleteProps<any>, 'size' | 'disabled' | 'variant'> {
|
|
54
54
|
disabled?: boolean;
|
|
55
|
-
semantics: RHFAutocompleteVariants | 'error' | null;
|
|
56
|
-
multiple: boolean;
|
|
57
|
-
imageScale?: boolean;
|
|
58
|
-
imageRepeat?: boolean;
|
|
59
|
-
paletteColor: PaletteColor;
|
|
60
55
|
}
|
|
61
56
|
/**
|
|
62
57
|
* Defines the types of Slots available for the Autocomplete.
|