@m4l/components 9.3.22 → 9.3.24-JT04112025.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.
Files changed (59) hide show
  1. package/components/CommonActions/components/ActionFormCancel/ActionFormCancel.js +17 -8
  2. package/components/CommonActions/components/ActionFormCancel/types.d.ts +9 -0
  3. package/components/DataGrid/contexts/DataGridContext/index.js +12 -7
  4. package/components/DataGrid/formatters/ColumnIconFormatter/index.d.ts +1 -0
  5. package/components/DataGrid/index.d.ts +1 -1
  6. package/components/DataGrid/tests/helpers/types.d.ts +1 -0
  7. package/components/DataGrid/types.d.ts +2 -0
  8. package/components/DynamicFilter/helpers/formatToInitialFilters.js +3 -3
  9. package/components/DynamicFilter/subcomponents/FieldTypes/BooleanFilter/helpers.js +11 -3
  10. package/components/DynamicFilter/subcomponents/FieldTypes/DateTimeFilter/helpers.js +16 -4
  11. package/components/DynamicFilter/subcomponents/FieldTypes/NumberFilter/helpers.js +11 -8
  12. package/components/DynamicFilter/subcomponents/FieldTypes/SelectAsyncFilter/helpers.js +21 -8
  13. package/components/DynamicFilter/subcomponents/FieldTypes/SelectFilter/helpers.js +18 -8
  14. package/components/DynamicFilter/subcomponents/FieldTypes/StringFilter/helpers.js +5 -3
  15. package/components/Label/Label.js +1 -1
  16. package/components/PaperForm/PaperForm.js +1 -1
  17. package/components/PaperForm/components/Header.js +9 -7
  18. package/components/PaperForm/styles.js +9 -4
  19. package/components/PaperForm/types.d.ts +3 -2
  20. package/components/Stepper/Stepper.styles.js +2 -0
  21. package/components/Stepper/dictionary.js +0 -1
  22. package/components/Stepper/subcomponents/StepArea/hooks/useStepArea.d.ts +13 -0
  23. package/components/Stepper/subcomponents/StepArea/hooks/useStepArea.js +111 -0
  24. package/components/Stepper/subcomponents/StepArea/hooks/useVisibileSteps.d.ts +8 -0
  25. package/components/Stepper/subcomponents/StepArea/hooks/useVisibileSteps.js +79 -0
  26. package/components/Stepper/subcomponents/StepArea/index.js +7 -115
  27. package/components/Stepper/subcomponents/StepperButtons/StepperCancelButton/index.d.ts +2 -2
  28. package/components/Stepper/subcomponents/StepperButtons/StepperCancelButton/index.js +3 -53
  29. package/components/Stepper/subcomponents/StepperButtons/StepperNextButton/index.js +3 -2
  30. package/components/Stepper/subcomponents/StepperButtons/StepperPrevButton/index.js +3 -2
  31. package/components/Stepper/subcomponents/StepperButtons/StepperSubmitButton/index.js +24 -5
  32. package/components/Stepper/subcomponents/StepperContent/subcomponents/Step/hooks/useIsStepVisible.d.ts +8 -0
  33. package/components/Stepper/subcomponents/StepperContent/subcomponents/Step/hooks/useIsStepVisible.js +93 -0
  34. package/components/Stepper/subcomponents/StepperContent/subcomponents/Step/index.js +2 -51
  35. package/components/Stepper/types.d.ts +4 -0
  36. package/components/ToastContainer/ToastContainer.js +1 -0
  37. package/components/ToastContainer/constants.d.ts +1 -1
  38. package/components/ToastContainer/constants.js +1 -1
  39. package/components/WindowBase/contexts/WindowToolsMFContext/WindowToolsMFContext.js +47 -3
  40. package/components/WindowBase/contexts/WindowToolsMFContext/types.d.ts +1 -1
  41. package/components/WindowBase/subcomponents/Component/index.d.ts +12 -1
  42. package/components/WindowBase/subcomponents/Component/index.js +56 -2
  43. package/components/WindowBase/subcomponents/Component/types.d.ts +1 -0
  44. package/components/WindowBase/types.d.ts +1 -1
  45. package/components/areas/components/AreasViewer/subcomponents/Area/subcomponents/Window/Window.js +1 -0
  46. package/components/areas/components/AreasViewer/subcomponents/Area/subcomponents/Window/hooks/useWindow.js +1 -1
  47. package/components/areas/contexts/AreasContext/store.js +5 -1
  48. package/components/areas/contexts/AreasContext/types.d.ts +1 -1
  49. package/components/hook-form/RHFormContext/styles.js +2 -1
  50. package/components/mui_extended/CircularProgress/types.d.ts +1 -1
  51. package/components/popups/components/PopupsProvider/contexts/PopupsContext/store.js +5 -1
  52. package/components/popups/components/PopupsProvider/contexts/PopupsContext/types.d.ts +1 -1
  53. package/components/popups/components/PopupsProvider/hooks/usePopups.d.ts +2 -4
  54. package/components/popups/components/PopupsProvider/hooks/usePopups.js +19 -7
  55. package/components/popups/components/PopupsViewer/PopupsViewer.js +1 -1
  56. package/components/popups/components/PopupsViewer/PopupsViewer.styles.js +1 -1
  57. package/components/popups/components/PopupsViewer/subcomponents/Popup/Popup.js +32 -21
  58. package/index.js +60 -58
  59. package/package.json +1 -1
@@ -0,0 +1,111 @@
1
+ import { useCallback, useMemo } from "react";
2
+ import { useFormContext } from "react-hook-form";
3
+ import { u as useStepper } from "../../../hooks/useStepper/index.js";
4
+ import { u as useDynamicValidation } from "../../../hooks/useDynamicValidation/index.js";
5
+ import { d as deepShallow } from "../../../../../utils/deepShallow.js";
6
+ function useStepArea(props) {
7
+ const { visibleSteps } = props;
8
+ const { trigger, clearErrors } = useFormContext();
9
+ const {
10
+ activateFieldsValidation,
11
+ startExternalValidation,
12
+ endExternalValidation
13
+ } = useDynamicValidation();
14
+ const {
15
+ currentStep,
16
+ steps,
17
+ visibleTitle,
18
+ setCurrentStep,
19
+ orientation,
20
+ setStepValidationStatus,
21
+ stepValidationStatus
22
+ } = useStepper(
23
+ (state) => ({
24
+ currentStep: state.currentStep,
25
+ steps: state.steps,
26
+ visibleTitle: state.visibleTitle,
27
+ setCurrentStep: state.actions.setCurrentStep,
28
+ indicatorType: state.indicatorType,
29
+ orientation: state.orientation,
30
+ setStepValidationStatus: state.actions.setStepValidationStatus,
31
+ stepValidationStatus: state.stepValidationStatus
32
+ }),
33
+ deepShallow
34
+ );
35
+ const handleStepClick = useCallback(async (targetIndex) => {
36
+ const currentIndex = visibleSteps.findIndex(
37
+ (step) => step.key === steps[currentStep].key
38
+ );
39
+ if (targetIndex === currentIndex) {
40
+ return;
41
+ }
42
+ const isNavigatingForward = targetIndex > currentIndex;
43
+ const targetOriginalIndex = steps.findIndex(
44
+ (s) => s.key === visibleSteps[targetIndex].key
45
+ );
46
+ if (!isNavigatingForward) {
47
+ setCurrentStep(targetOriginalIndex);
48
+ return;
49
+ }
50
+ const isSkippingSteps = targetIndex > currentIndex + 1;
51
+ if (isSkippingSteps) {
52
+ for (let i = currentIndex; i < targetIndex; i++) {
53
+ const step = visibleSteps[i];
54
+ const stepOriginalIndex = steps.findIndex((s) => s.key === step.key);
55
+ startExternalValidation();
56
+ const isValid = await trigger(step.validationFields);
57
+ endExternalValidation();
58
+ if (!isValid) {
59
+ setCurrentStep(stepOriginalIndex);
60
+ setStepValidationStatus(stepOriginalIndex, false);
61
+ activateFieldsValidation(step.validationFields || []);
62
+ return;
63
+ }
64
+ setStepValidationStatus(stepOriginalIndex, true);
65
+ }
66
+ } else {
67
+ const currentStepData = visibleSteps[currentIndex];
68
+ const currentStepOriginalIndex = steps.findIndex(
69
+ (s) => s.key === currentStepData.key
70
+ );
71
+ startExternalValidation();
72
+ const isCurrentValid = await trigger(currentStepData.validationFields);
73
+ endExternalValidation();
74
+ if (!isCurrentValid) {
75
+ setStepValidationStatus(currentStepOriginalIndex, false);
76
+ activateFieldsValidation(currentStepData.validationFields || []);
77
+ return;
78
+ }
79
+ setStepValidationStatus(currentStepOriginalIndex, true);
80
+ }
81
+ setCurrentStep(targetOriginalIndex);
82
+ if (isNavigatingForward) {
83
+ const currentStepData = visibleSteps[currentIndex];
84
+ const currentStepOriginalIndex = steps.findIndex(
85
+ (s) => s.key === currentStepData.key
86
+ );
87
+ const isCurrentStepValid = stepValidationStatus[currentStepOriginalIndex] !== false;
88
+ if (isCurrentStepValid) {
89
+ const targetStep = visibleSteps[targetIndex];
90
+ const targetStepFields = targetStep.validationFields || [];
91
+ if (targetStepFields.length > 0) {
92
+ clearErrors(targetStepFields);
93
+ setTimeout(() => {
94
+ clearErrors(targetStepFields);
95
+ setStepValidationStatus(targetOriginalIndex, true);
96
+ }, 100);
97
+ }
98
+ }
99
+ }
100
+ }, [visibleSteps, steps, setCurrentStep, currentStep, startExternalValidation, trigger, endExternalValidation, setStepValidationStatus, activateFieldsValidation, stepValidationStatus, clearErrors]);
101
+ return useMemo(() => ({
102
+ visibleTitle,
103
+ orientation,
104
+ handleStepClick,
105
+ steps,
106
+ currentStep
107
+ }), [visibleTitle, orientation, handleStepClick, steps, currentStep]);
108
+ }
109
+ export {
110
+ useStepArea as u
111
+ };
@@ -0,0 +1,8 @@
1
+ import { Step as StepType } from '../../../types';
2
+ /**
3
+ * useVisibileSteps hook is responsible for calculating the visible steps based on the form values and the visibility data
4
+ * Optimizado con useSyncExternalStore para evitar re-renders innecesarios
5
+ */
6
+ export declare function useVisibileSteps(): {
7
+ visibleSteps: StepType[];
8
+ };
@@ -0,0 +1,79 @@
1
+ import { useRef, useCallback, useSyncExternalStore, useMemo } from "react";
2
+ import { useFormContext } from "react-hook-form";
3
+ import { u as useStepper } from "../../../hooks/useStepper/index.js";
4
+ import { e as evaluateVisibilityStepCondition } from "../../../helpers/evaluateVisibilityStepCondition/index.js";
5
+ import { d as deepShallow } from "../../../../../utils/deepShallow.js";
6
+ function calculateVisibleSteps(steps, formValues, visibilityData) {
7
+ return steps.filter(
8
+ (step) => evaluateVisibilityStepCondition(step, formValues || {}, visibilityData || {})
9
+ );
10
+ }
11
+ function generateStepsKey(steps) {
12
+ return steps.map((step) => step.key).join(",");
13
+ }
14
+ function useVisibileSteps() {
15
+ const formContext = useFormContext();
16
+ const {
17
+ steps,
18
+ visibilityData
19
+ } = useStepper(
20
+ (state) => ({
21
+ steps: state.steps,
22
+ visibilityData: state.visibilityData
23
+ }),
24
+ deepShallow
25
+ );
26
+ const previousStepsKeyRef = useRef(null);
27
+ const cachedVisibleStepsRef = useRef([]);
28
+ const listenersRef = useRef(/* @__PURE__ */ new Set());
29
+ const subscribe = useCallback((callback) => {
30
+ listenersRef.current.add(callback);
31
+ const { unsubscribe } = formContext.watch((formValues) => {
32
+ const newVisibleSteps = calculateVisibleSteps(
33
+ steps,
34
+ formValues,
35
+ visibilityData
36
+ );
37
+ const newStepsKey = generateStepsKey(newVisibleSteps);
38
+ if (newStepsKey !== previousStepsKeyRef.current) {
39
+ previousStepsKeyRef.current = newStepsKey;
40
+ cachedVisibleStepsRef.current = newVisibleSteps;
41
+ listenersRef.current.forEach((listener) => listener());
42
+ }
43
+ });
44
+ return () => {
45
+ listenersRef.current.delete(callback);
46
+ unsubscribe();
47
+ };
48
+ }, [formContext, steps, visibilityData]);
49
+ const getSnapshot = useCallback(() => {
50
+ const formValues = formContext.getValues();
51
+ const currentVisibleSteps = calculateVisibleSteps(
52
+ steps,
53
+ formValues,
54
+ visibilityData
55
+ );
56
+ const stepsKey = generateStepsKey(currentVisibleSteps);
57
+ if (previousStepsKeyRef.current === null) {
58
+ previousStepsKeyRef.current = stepsKey;
59
+ cachedVisibleStepsRef.current = currentVisibleSteps;
60
+ }
61
+ if (stepsKey === previousStepsKeyRef.current) {
62
+ return cachedVisibleStepsRef.current;
63
+ }
64
+ previousStepsKeyRef.current = stepsKey;
65
+ cachedVisibleStepsRef.current = currentVisibleSteps;
66
+ return currentVisibleSteps;
67
+ }, [formContext, steps, visibilityData]);
68
+ const visibleSteps = useSyncExternalStore(
69
+ subscribe,
70
+ getSnapshot,
71
+ getSnapshot
72
+ );
73
+ return useMemo(() => ({
74
+ visibleSteps
75
+ }), [visibleSteps]);
76
+ }
77
+ export {
78
+ useVisibileSteps as u
79
+ };
@@ -1,127 +1,19 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { useMemo } from "react";
3
- import { useFormContext, useWatch } from "react-hook-form";
4
- import { u as useStepper } from "../../hooks/useStepper/index.js";
5
2
  import { e as StepAreaStyled, f as StepStyled, g as StepNameStyled } from "../../slots/StepperSlot.js";
6
3
  import { I as Indicator } from "./subcomponents/Inidicator/index.js";
7
- import { shallow } from "zustand/shallow";
8
- import { u as useDynamicValidation } from "../../hooks/useDynamicValidation/index.js";
9
- import { e as evaluateVisibilityStepCondition } from "../../helpers/evaluateVisibilityStepCondition/index.js";
4
+ import { u as useStepArea } from "./hooks/useStepArea.js";
5
+ import { u as useVisibileSteps } from "./hooks/useVisibileSteps.js";
10
6
  function StepArea() {
11
- const { trigger, clearErrors } = useFormContext();
12
- const formValues = useWatch();
13
- const {
14
- activateFieldsValidation,
15
- startExternalValidation,
16
- endExternalValidation
17
- } = useDynamicValidation();
18
- const {
19
- currentStep,
20
- steps,
21
- visibleTitle,
22
- setCurrentStep,
23
- orientation,
24
- setStepValidationStatus,
25
- stepValidationStatus,
26
- visibilityData
27
- } = useStepper(
28
- (state) => ({
29
- currentStep: state.currentStep,
30
- steps: state.steps,
31
- visibleTitle: state.visibleTitle,
32
- setCurrentStep: state.actions.setCurrentStep,
33
- indicatorType: state.indicatorType,
34
- orientation: state.orientation,
35
- setStepValidationStatus: state.actions.setStepValidationStatus,
36
- stepValidationStatus: state.stepValidationStatus,
37
- visibilityData: state.visibilityData
38
- }),
39
- shallow
40
- );
41
- const allSteps = steps;
42
- const visibleSteps = useMemo(() => {
43
- return steps.filter(
44
- (step) => evaluateVisibilityStepCondition(step, formValues || {}, visibilityData)
45
- );
46
- }, [steps, formValues, visibilityData]);
7
+ const { visibleSteps } = useVisibileSteps();
8
+ const { handleStepClick, visibleTitle, orientation, steps, currentStep } = useStepArea({ visibleSteps });
47
9
  const ownerState = {
48
10
  visibleTitle,
49
11
  orientation,
50
12
  totalSteps: visibleSteps.length
51
13
  };
52
- const handleStepClick = async (targetIndex) => {
53
- const currentIndex = visibleSteps.findIndex(
54
- (step) => step.key === steps[currentStep].key
55
- );
56
- if (targetIndex === currentIndex) {
57
- return;
58
- }
59
- const isNavigatingForward = targetIndex > currentIndex;
60
- const targetOriginalIndex = steps.findIndex(
61
- (s) => s.key === visibleSteps[targetIndex].key
62
- );
63
- if (!isNavigatingForward) {
64
- setCurrentStep(targetOriginalIndex);
65
- return;
66
- }
67
- const isSkippingSteps = targetIndex > currentIndex + 1;
68
- if (isSkippingSteps) {
69
- for (let i = currentIndex; i < targetIndex; i++) {
70
- const step = visibleSteps[i];
71
- const stepOriginalIndex = steps.findIndex((s) => s.key === step.key);
72
- startExternalValidation();
73
- const isValid = await trigger(step.validationFields);
74
- endExternalValidation();
75
- if (!isValid) {
76
- setCurrentStep(stepOriginalIndex);
77
- setStepValidationStatus(stepOriginalIndex, false);
78
- activateFieldsValidation(step.validationFields || []);
79
- return;
80
- }
81
- setStepValidationStatus(stepOriginalIndex, true);
82
- }
83
- } else {
84
- const currentStepData = visibleSteps[currentIndex];
85
- const currentStepOriginalIndex = steps.findIndex(
86
- (s) => s.key === currentStepData.key
87
- );
88
- startExternalValidation();
89
- const isCurrentValid = await trigger(currentStepData.validationFields);
90
- endExternalValidation();
91
- if (!isCurrentValid) {
92
- setStepValidationStatus(currentStepOriginalIndex, false);
93
- activateFieldsValidation(currentStepData.validationFields || []);
94
- return;
95
- }
96
- setStepValidationStatus(currentStepOriginalIndex, true);
97
- }
98
- setCurrentStep(targetOriginalIndex);
99
- if (isNavigatingForward) {
100
- const currentStepData = visibleSteps[currentIndex];
101
- const currentStepOriginalIndex = steps.findIndex(
102
- (s) => s.key === currentStepData.key
103
- );
104
- const isCurrentStepValid = stepValidationStatus[currentStepOriginalIndex] !== false;
105
- if (isCurrentStepValid) {
106
- const targetStep = visibleSteps[targetIndex];
107
- const targetStepFields = targetStep.validationFields || [];
108
- if (targetStepFields.length > 0) {
109
- clearErrors(targetStepFields);
110
- setTimeout(() => {
111
- clearErrors(targetStepFields);
112
- setStepValidationStatus(targetOriginalIndex, true);
113
- }, 100);
114
- }
115
- }
116
- }
117
- };
118
- return /* @__PURE__ */ jsx(StepAreaStyled, { ownerState, children: allSteps.map((step, originalIndex) => {
119
- const isStepVisible = evaluateVisibilityStepCondition(
120
- step,
121
- formValues || {},
122
- visibilityData
123
- );
124
- const visibleStepIndex = isStepVisible ? visibleSteps.findIndex((visStep) => visStep.key === step.key) : -1;
14
+ return /* @__PURE__ */ jsx(StepAreaStyled, { ownerState, children: steps.map((step, originalIndex) => {
15
+ const visibleStepIndex = visibleSteps.findIndex((visibleStep) => visibleStep.key === step.key);
16
+ const isStepVisible = visibleStepIndex !== -1;
125
17
  return /* @__PURE__ */ jsxs(
126
18
  StepStyled,
127
19
  {
@@ -1,5 +1,5 @@
1
- import { StepperButtonProps } from '../../../types';
1
+ import { ActionFormCancelProps } from '../../../../CommonActions/components/ActionFormCancel/types';
2
2
  /**
3
3
  * Botón modular para cancelar el proceso del Stepper
4
4
  */
5
- export declare function StepperCancelButton(props: StepperButtonProps): import("react/jsx-runtime").JSX.Element;
5
+ export declare function StepperCancelButton(props: ActionFormCancelProps): import("react/jsx-runtime").JSX.Element;
@@ -1,58 +1,8 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
- import { useCallback } from "react";
3
- import { useFormContext, useFormState } from "react-hook-form";
4
- import { u as useStepperActions } from "../../../hooks/useStepperActions/index.js";
5
- import { D as DICTIONARY$1 } from "../../../dictionary.js";
6
- import { D as DICTIONARY } from "../../../../CommonActions/dictionary.js";
7
- import { useModuleDictionary } from "@m4l/core";
8
- import { u as useModal } from "../../../../../hooks/useModal/index.js";
9
- import { u as useWindowToolsMF } from "../../../../WindowBase/hooks/useWindowToolsMF/index.js";
10
- import { W as WindowConfirm } from "../../../../WindowConfirm/WindowConfirm.js";
11
- import { B as Button } from "../../../../mui_extended/Button/Button.js";
2
+ import { A as ActionFormCancel } from "../../../../CommonActions/components/ActionFormCancel/ActionFormCancel.js";
12
3
  function StepperCancelButton(props) {
13
- const { label, ...rest } = props;
14
- const { getLabel } = useModuleDictionary();
15
- const { cancelAction } = useStepperActions();
16
- const { openModal } = useModal();
17
- const { close: closeWindow } = useWindowToolsMF();
18
- const { control } = useFormContext();
19
- const { isDirty } = useFormState({
20
- control
21
- });
22
- const onConfirmQuit = useCallback(() => {
23
- cancelAction();
24
- closeWindow();
25
- }, [cancelAction, closeWindow]);
26
- const handleCancel = useCallback(() => {
27
- if (isDirty) {
28
- openModal({
29
- window: /* @__PURE__ */ jsx(
30
- WindowConfirm,
31
- {
32
- variant: "warning",
33
- title: getLabel(DICTIONARY.CONFIRM_QUIT_TITLE),
34
- msg: getLabel(DICTIONARY.CONFIRM_QUIT_MSG),
35
- onClickIntro: onConfirmQuit
36
- }
37
- ),
38
- variant: "warning"
39
- });
40
- } else {
41
- onConfirmQuit();
42
- }
43
- }, [getLabel, isDirty, openModal, onConfirmQuit]);
44
- return /* @__PURE__ */ jsx(
45
- Button,
46
- {
47
- type: "button",
48
- label: label || getLabel(DICTIONARY$1.LABEL_CANCEL_BUTTON),
49
- variant: "outlined",
50
- color: "default",
51
- onClick: handleCancel,
52
- ...rest,
53
- "data-testid": "stepper-cancel-button"
54
- }
55
- );
4
+ const { ...rest } = props;
5
+ return /* @__PURE__ */ jsx(ActionFormCancel, { "data-testid": "stepper-cancel-button", ...rest });
56
6
  }
57
7
  export {
58
8
  StepperCancelButton as S
@@ -7,15 +7,16 @@ import { useModuleDictionary, useEnvironment } from "@m4l/core";
7
7
  import { I as IconButton } from "../../../../mui_extended/IconButton/IconButton.js";
8
8
  import { B as Button } from "../../../../mui_extended/Button/Button.js";
9
9
  function StepperNextButton(props) {
10
- const { label, ...rest } = props;
10
+ const { label, forceIsMobile, ...rest } = props;
11
11
  const { nextStepAction } = useStepperActions();
12
12
  const isMobile = useIsMobile();
13
+ const isMobileForce = forceIsMobile !== void 0 ? forceIsMobile : isMobile;
13
14
  const { getLabel } = useModuleDictionary();
14
15
  const { host_static_assets, environment_assets } = useEnvironment();
15
16
  const handleNext = async () => {
16
17
  await nextStepAction();
17
18
  };
18
- return isMobile ? /* @__PURE__ */ jsx(
19
+ return isMobileForce ? /* @__PURE__ */ jsx(
19
20
  IconButton,
20
21
  {
21
22
  type: "button",
@@ -8,12 +8,13 @@ import { D as DICTIONARY } from "../../../dictionary.js";
8
8
  import { I as IconButton } from "../../../../mui_extended/IconButton/IconButton.js";
9
9
  import { B as Button } from "../../../../mui_extended/Button/Button.js";
10
10
  function StepperPrevButton(props) {
11
- const { label, ...rest } = props;
11
+ const { label, forceIsMobile, ...rest } = props;
12
12
  const { currentStep } = useStepper((state) => ({
13
13
  currentStep: state.currentStep
14
14
  }));
15
15
  const { host_static_assets, environment_assets } = useEnvironment();
16
16
  const isMobile = useIsMobile();
17
+ const isMobileForce = forceIsMobile !== void 0 ? forceIsMobile : isMobile;
17
18
  const { getLabel } = useModuleDictionary();
18
19
  const { prevStepAction } = useStepperActions();
19
20
  const handlePrev = () => {
@@ -22,7 +23,7 @@ function StepperPrevButton(props) {
22
23
  if (currentStep === 0) {
23
24
  return null;
24
25
  }
25
- return isMobile ? /* @__PURE__ */ jsx(
26
+ return isMobileForce ? /* @__PURE__ */ jsx(
26
27
  IconButton,
27
28
  {
28
29
  type: "button",
@@ -1,18 +1,37 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { D as DICTIONARY } from "../../../dictionary.js";
3
- import { useModuleDictionary } from "@m4l/core";
4
- import { B as Button } from "../../../../mui_extended/Button/Button.js";
3
+ import { useModuleDictionary, useEnvironment } from "@m4l/core";
4
+ import { useIsMobile } from "@m4l/graphics";
5
+ import { p as pathIcons } from "../../../icons.js";
6
+ import { useFormContext } from "react-hook-form";
7
+ import { L as LoadingButton } from "../../../../mui_extended/LoadingButton/LoadingButton.js";
8
+ import { I as IconButton } from "../../../../mui_extended/IconButton/IconButton.js";
9
+ import { C as CircularProgress } from "../../../../mui_extended/CircularProgress/CircularProgress.js";
5
10
  function StepperSubmitButton(props) {
6
- const { label, ...rest } = props;
11
+ const { label, forceIsMobile, ...rest } = props;
7
12
  const { getLabel } = useModuleDictionary();
8
- return /* @__PURE__ */ jsx(
9
- Button,
13
+ const { host_static_assets, environment_assets } = useEnvironment();
14
+ const isMobile = useIsMobile();
15
+ const isMobileForce = forceIsMobile !== void 0 ? forceIsMobile : isMobile;
16
+ const { formState: { isSubmitting } } = useFormContext();
17
+ return isMobileForce ? /* @__PURE__ */ jsx(
18
+ IconButton,
19
+ {
20
+ type: "submit",
21
+ icon: isSubmitting ? /* @__PURE__ */ jsx(CircularProgress, { color: "default" }) : `${host_static_assets}/${environment_assets}/${pathIcons.circleCheck}`,
22
+ "data-testid": "stepper-prev-button",
23
+ variant: "contained",
24
+ color: "primary"
25
+ }
26
+ ) : /* @__PURE__ */ jsx(
27
+ LoadingButton,
10
28
  {
11
29
  type: "submit",
12
30
  label: label || getLabel(DICTIONARY.LABEL_SUBMIT_BUTTON),
13
31
  variant: "contained",
14
32
  color: "primary",
15
33
  "data-testid": "stepper-submit-button",
34
+ loading: isSubmitting,
16
35
  ...rest
17
36
  }
18
37
  );
@@ -0,0 +1,8 @@
1
+ import { StepProps } from '../../../../../types';
2
+ /**
3
+ * Hook que determina si un step debe ser visible
4
+ * Usa useSyncExternalStore para optimizar re-renders:
5
+ * - Solo re-renderiza el componente si el valor booleano cambia realmente
6
+ * - Aunque el formulario cambie, si la visibilidad sigue siendo la misma, no re-renderiza
7
+ */
8
+ export declare function useIsStepVisible(props: Pick<StepProps, 'stepKey'>): boolean;
@@ -0,0 +1,93 @@
1
+ import { useRef, useCallback, useSyncExternalStore } from "react";
2
+ import { u as useStepper } from "../../../../../hooks/useStepper/index.js";
3
+ import { useFormContext } from "react-hook-form";
4
+ import { d as deepShallow } from "../../../../../../../utils/deepShallow.js";
5
+ import { e as evaluateVisibilityStepCondition } from "../../../../../helpers/evaluateVisibilityStepCondition/index.js";
6
+ function calculateStepVisibility(stepKey, steps, currentStep, formValues, visibilityData) {
7
+ const stepConfig = steps.find((step) => step.key === stepKey);
8
+ if (!stepConfig) {
9
+ return false;
10
+ }
11
+ const meetsVisibilityCondition = evaluateVisibilityStepCondition(
12
+ stepConfig,
13
+ formValues || {},
14
+ visibilityData || {}
15
+ );
16
+ if (!meetsVisibilityCondition) {
17
+ return false;
18
+ }
19
+ const currentStepConfig = steps[currentStep];
20
+ if (!currentStepConfig) {
21
+ return false;
22
+ }
23
+ if (evaluateVisibilityStepCondition(currentStepConfig, formValues || {}, visibilityData || {})) {
24
+ return stepKey === currentStepConfig.key;
25
+ }
26
+ const visibleStepsUpToCurrent = [];
27
+ for (let i = 0; i <= currentStep; i++) {
28
+ const step = steps[i];
29
+ if (evaluateVisibilityStepCondition(step, formValues || {}, visibilityData || {})) {
30
+ visibleStepsUpToCurrent.push(step);
31
+ }
32
+ }
33
+ if (visibleStepsUpToCurrent.length === 0) {
34
+ for (let i = currentStep + 1; i < steps.length; i++) {
35
+ const step = steps[i];
36
+ if (evaluateVisibilityStepCondition(step, formValues || {}, visibilityData || {})) {
37
+ return stepKey === step.key;
38
+ }
39
+ }
40
+ return false;
41
+ }
42
+ const activeVisibleStep = visibleStepsUpToCurrent[visibleStepsUpToCurrent.length - 1];
43
+ return stepKey === activeVisibleStep.key;
44
+ }
45
+ function useIsStepVisible(props) {
46
+ const { stepKey } = props;
47
+ const formContext = useFormContext();
48
+ const { currentStep, steps, visibilityData } = useStepper((state) => ({
49
+ currentStep: state.currentStep,
50
+ steps: state.steps,
51
+ visibilityData: state.visibilityData
52
+ }), deepShallow);
53
+ const previousValueRef = useRef(null);
54
+ const listenersRef = useRef(/* @__PURE__ */ new Set());
55
+ const subscribe = useCallback((callback) => {
56
+ listenersRef.current.add(callback);
57
+ const { unsubscribe } = formContext.watch((formValues) => {
58
+ const newValue = calculateStepVisibility(
59
+ stepKey,
60
+ steps,
61
+ currentStep,
62
+ formValues,
63
+ visibilityData
64
+ );
65
+ if (newValue !== previousValueRef.current) {
66
+ previousValueRef.current = newValue;
67
+ listenersRef.current.forEach((listener) => listener());
68
+ }
69
+ });
70
+ return () => {
71
+ listenersRef.current.delete(callback);
72
+ unsubscribe();
73
+ };
74
+ }, [formContext, stepKey, steps, currentStep, visibilityData]);
75
+ const getSnapshot = useCallback(() => {
76
+ const formValues = formContext.getValues();
77
+ const value = calculateStepVisibility(
78
+ stepKey,
79
+ steps,
80
+ currentStep,
81
+ formValues,
82
+ visibilityData
83
+ );
84
+ if (previousValueRef.current === null) {
85
+ previousValueRef.current = value;
86
+ }
87
+ return value;
88
+ }, [formContext, stepKey, steps, currentStep, visibilityData]);
89
+ return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
90
+ }
91
+ export {
92
+ useIsStepVisible as u
93
+ };
@@ -1,58 +1,9 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
- import { useMemo } from "react";
3
- import { u as useStepper } from "../../../../hooks/useStepper/index.js";
4
- import { useWatch } from "react-hook-form";
5
2
  import { j as StepContentStyled } from "../../../../slots/StepperSlot.js";
6
- import { e as evaluateVisibilityStepCondition } from "../../../../helpers/evaluateVisibilityStepCondition/index.js";
3
+ import { u as useIsStepVisible } from "./hooks/useIsStepVisible.js";
7
4
  function Step(props) {
8
5
  const { stepKey, children } = props;
9
- const formValues = useWatch();
10
- const { currentStep, steps, visibilityData } = useStepper((state) => ({
11
- currentStep: state.currentStep,
12
- steps: state.steps,
13
- visibilityData: state.visibilityData
14
- }));
15
- const stepConfig = useMemo(() => {
16
- return steps.find((step) => step.key === stepKey);
17
- }, [steps, stepKey]);
18
- const isStepVisible = useMemo(() => {
19
- if (!stepConfig) {
20
- return false;
21
- }
22
- const meetsVisibilityCondition = evaluateVisibilityStepCondition(
23
- stepConfig,
24
- formValues || {},
25
- visibilityData
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
- }
51
- return false;
52
- }
53
- const activeVisibleStep = visibleStepsUpToCurrent[visibleStepsUpToCurrent.length - 1];
54
- return stepKey === activeVisibleStep.key;
55
- }, [currentStep, stepKey, stepConfig, steps, formValues, visibilityData]);
6
+ const isStepVisible = useIsStepVisible({ stepKey });
56
7
  return /* @__PURE__ */ jsx(StepContentStyled, { ownerState: { isStepVisible }, children });
57
8
  }
58
9
  export {
@@ -150,6 +150,10 @@ export interface StepperFooterLeftActionsProps {
150
150
  * Props para los botones del Stepper que extienden las props de Button de mui_extended
151
151
  */
152
152
  export interface StepperButtonProps extends Omit<ButtonProps, 'label'> {
153
+ /**
154
+ * Forzar a un una versión especifica no importando el dispositivo
155
+ */
156
+ forceIsMobile?: boolean;
153
157
  label?: string;
154
158
  }
155
159
  /**