@m4l/components 9.4.6-BE20260109-beta.1 → 9.4.6-BE20260111-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 (26) hide show
  1. package/components/CommonActions/components/ActionFormSubmitProgrammatic/ActionFormSubmitProgrammatic.d.ts +34 -0
  2. package/components/CommonActions/components/ActionFormSubmitProgrammatic/ActionFormSubmitProgrammatic.js +46 -0
  3. package/components/CommonActions/components/ActionFormSubmitProgrammatic/ActionFormSubmitProgrammatic.styles.d.ts +2 -0
  4. package/components/CommonActions/components/ActionFormSubmitProgrammatic/ActionFormSubmitProgrammatic.styles.js +7 -0
  5. package/components/CommonActions/components/ActionFormSubmitProgrammatic/constanst.d.ts +6 -0
  6. package/components/CommonActions/components/ActionFormSubmitProgrammatic/constanst.js +7 -0
  7. package/components/CommonActions/components/ActionFormSubmitProgrammatic/index.d.ts +2 -0
  8. package/components/CommonActions/components/ActionFormSubmitProgrammatic/slots/ActionFormSubmitProgrammaticEnum.d.ts +3 -0
  9. package/components/CommonActions/components/ActionFormSubmitProgrammatic/slots/ActionFormSubmitProgrammaticEnum.js +7 -0
  10. package/components/CommonActions/components/ActionFormSubmitProgrammatic/slots/ActionFormSubmitProgrammaticSlots.d.ts +1 -0
  11. package/components/CommonActions/components/ActionFormSubmitProgrammatic/slots/ActionFormSubmitProgrammaticSlots.js +12 -0
  12. package/components/CommonActions/components/ActionFormSubmitProgrammatic/slots/index.d.ts +2 -0
  13. package/components/CommonActions/components/ActionFormSubmitProgrammatic/slots/index.js +1 -0
  14. package/components/CommonActions/components/ActionFormSubmitProgrammatic/types.d.ts +36 -0
  15. package/components/CommonActions/index.d.ts +1 -0
  16. package/components/DynamicFilter/subcomponents/PopoverFilter/PopoverFilter.js +7 -26
  17. package/components/DynamicFilter/subcomponents/PopoverMenuFields/PopoverMenuFields.d.ts +1 -1
  18. package/components/DynamicFilter/subcomponents/PopoverMenuFields/PopoverMenuFields.js +5 -3
  19. package/components/DynamicSort/subcomponents/PopoverMenuFields/PopoverMenuFields.d.ts +1 -1
  20. package/components/DynamicSort/subcomponents/PopoverMenuFields/PopoverMenuFields.js +5 -3
  21. package/components/DynamicSort/subcomponents/PopoverSort/PopoverSort.js +7 -30
  22. package/components/areas/contexts/AreasContext/store.js +1 -1
  23. package/hooks/usePopoverContainer/usePopoverContainer.d.ts +35 -6
  24. package/hooks/usePopoverContainer/usePopoverContainer.js +18 -10
  25. package/index.js +8 -6
  26. package/package.json +1 -1
@@ -0,0 +1,34 @@
1
+ import { ActionFormSubmitProgrammaticProps } from './types';
2
+ /**
3
+ * ActionFormSubmitProgrammatic: Componente que ejecuta el submit del formulario programáticamente.
4
+ * Este componente utiliza un botón tipo `button` (en lugar de `submit`) y ejecuta el submit
5
+ * de manera programática mediante `handleSubmit` de react-hook-form. Esta implementación es
6
+ * necesaria para garantizar que el componente funcione correctamente tanto cuando está
7
+ * contenido dentro de un `RHFormProvider` ancestro como cuando está aislado.
8
+ *
9
+ * **Razón técnica:**
10
+ * El estándar HTML no permite el anidamiento de elementos `<form>`. Cuando un navegador
11
+ * encuentra un formulario dentro de otro, el markup resultante es inválido y el navegador
12
+ * puede cerrar implícitamente el formulario externo antes de abrir el interno, o generar
13
+ * un DOM no determinístico. Como consecuencia, el evento `submit` no sigue el ciclo normal
14
+ * de propagación de eventos del DOM, ya que el envío del formulario es manejado directamente
15
+ * por el navegador. Esto implica que no es posible garantizar la retención o aislamiento
16
+ * del evento usando mecanismos como `event.stopPropagation()` o `event.preventDefault()` desde
17
+ * el formulario interno.
18
+ *
19
+ * **Beneficios de esta implementación:**
20
+ * - **Resiliencia:** El componente funciona de manera idéntica tanto cuando está contenido
21
+ * por un `RHFormProvider` ancestro como cuando está aislado, sin afectar el comportamiento
22
+ * del formulario contenedor.
23
+ * - **Control explícito:** Permite controlar cuándo y cómo se ejecuta el proceso de envío,
24
+ * evitando efectos colaterales entre formularios.
25
+ * - **Comportamiento predecible:** Garantiza un comportamiento estable y alineado con el
26
+ * estándar HTML, sin depender de comportamientos no determinísticos del navegador.
27
+ * - **Compatibilidad:** Mantiene la validación y el flujo completo de react-hook-form mediante
28
+ * el uso de `handleSubmit`, asegurando que todas las validaciones se ejecuten correctamente.
29
+ * @param props - Propiedades del componente
30
+ * @param props.onSubmit - Función que se ejecuta cuando el formulario se envía exitosamente
31
+ * @param props.size - Tamaño del botón (opcional)
32
+ * @returns Componente de botón que ejecuta el submit programáticamente
33
+ */
34
+ export declare function ActionFormSubmitProgrammatic(props: ActionFormSubmitProgrammaticProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,46 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useFormContext } from "react-hook-form";
3
+ import { useModuleDictionary } from "@m4l/core";
4
+ import { c as classActionFormSubmitProgrammaticRoot } from "./constanst.js";
5
+ import { clsx } from "clsx";
6
+ import { D as DICTIONARY } from "../../dictionary.js";
7
+ import { u as useComponentSize } from "../../../../hooks/useComponentSize/useComponentSize.js";
8
+ import { B as ButtonActionFormSubmitProgrammaticRootStyled } from "./slots/ActionFormSubmitProgrammaticSlots.js";
9
+ function ActionFormSubmitProgrammatic(props) {
10
+ const {
11
+ onSubmit,
12
+ variant = "contained",
13
+ color = "primary",
14
+ className,
15
+ size = "medium",
16
+ skeletonWidth,
17
+ "aria-label": ariaLabel,
18
+ ...others
19
+ } = props;
20
+ const { getLabel } = useModuleDictionary();
21
+ const { handleSubmit } = useFormContext();
22
+ const { currentSize } = useComponentSize(size);
23
+ const adjustedSize = currentSize === "small" || currentSize === "medium" ? currentSize : "medium";
24
+ const handleClick = () => {
25
+ handleSubmit(onSubmit)();
26
+ };
27
+ const finalSkeletonWidth = skeletonWidth || (adjustedSize === "small" ? "80px" : "100px");
28
+ return /* @__PURE__ */ jsx(
29
+ ButtonActionFormSubmitProgrammaticRootStyled,
30
+ {
31
+ variant,
32
+ type: "button",
33
+ color,
34
+ size: adjustedSize,
35
+ className: clsx(classActionFormSubmitProgrammaticRoot, className),
36
+ label: getLabel(DICTIONARY.LABEL_INTRO),
37
+ skeletonWidth: finalSkeletonWidth,
38
+ "aria-label": ariaLabel,
39
+ onClick: handleClick,
40
+ ...others
41
+ }
42
+ );
43
+ }
44
+ export {
45
+ ActionFormSubmitProgrammatic as A
46
+ };
@@ -0,0 +1,2 @@
1
+ import { ActionFormSubmitProgrammaticStyles } from './types';
2
+ export declare const actionFormSubmitProgrammaticStyles: ActionFormSubmitProgrammaticStyles;
@@ -0,0 +1,7 @@
1
+ const actionFormSubmitProgrammaticStyles = {
2
+ /** 🌳 Estilos para el componente raiz 🌳 */
3
+ root: () => ({})
4
+ };
5
+ export {
6
+ actionFormSubmitProgrammaticStyles as a
7
+ };
@@ -0,0 +1,6 @@
1
+ export declare const ACTION_FORM_SUBMIT_PROGRAMMATIC_KEY_COMPONENT = "M4LActionFormSubmitProgrammatic";
2
+ /**
3
+ * Nombre de clase creado para aportar especificidad a los estilos del componente. Es usado para sobreescribir los estilos de MUI sin
4
+ * tener la necesidad de agregar valores en !important.
5
+ */
6
+ export declare const classActionFormSubmitProgrammaticRoot: string;
@@ -0,0 +1,7 @@
1
+ import { a as getComponentSlotRoot } from "../../../../utils/getComponentSlotRoot.js";
2
+ const ACTION_FORM_SUBMIT_PROGRAMMATIC_KEY_COMPONENT = "M4LActionFormSubmitProgrammatic";
3
+ const classActionFormSubmitProgrammaticRoot = getComponentSlotRoot(ACTION_FORM_SUBMIT_PROGRAMMATIC_KEY_COMPONENT);
4
+ export {
5
+ ACTION_FORM_SUBMIT_PROGRAMMATIC_KEY_COMPONENT as A,
6
+ classActionFormSubmitProgrammaticRoot as c
7
+ };
@@ -0,0 +1,2 @@
1
+ export * from './ActionFormSubmitProgrammatic';
2
+ export * from './types';
@@ -0,0 +1,3 @@
1
+ export declare enum ActionFormSubmitProgrammaticSlots {
2
+ root = "root"
3
+ }
@@ -0,0 +1,7 @@
1
+ var ActionFormSubmitProgrammaticSlots = /* @__PURE__ */ ((ActionFormSubmitProgrammaticSlots2) => {
2
+ ActionFormSubmitProgrammaticSlots2["root"] = "root";
3
+ return ActionFormSubmitProgrammaticSlots2;
4
+ })(ActionFormSubmitProgrammaticSlots || {});
5
+ export {
6
+ ActionFormSubmitProgrammaticSlots as A
7
+ };
@@ -0,0 +1 @@
1
+ export declare const ButtonActionFormSubmitProgrammaticRootStyled: import('@emotion/styled').StyledComponent<Pick<Omit<import('../../../../mui_extended/Button').ButtonProps, "ref"> & import('react').RefAttributes<HTMLButtonElement>, "value" | "size" | "children" | "title" | "component" | "name" | "id" | "type" | "disabled" | "action" | "variant" | "color" | "content" | "translate" | "className" | "style" | "classes" | "sx" | "form" | "label" | "slot" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "autoCapitalize" | "autoFocus" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "enterKeyHint" | "hidden" | "lang" | "nonce" | "spellCheck" | "tabIndex" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "rel" | "resource" | "rev" | "typeof" | "vocab" | "autoCorrect" | "autoSave" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "exportparts" | "part" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-braillelabel" | "aria-brailleroledescription" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colindextext" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-description" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowindextext" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerLeave" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "centerRipple" | "disableRipple" | "disableTouchRipple" | "focusRipple" | "focusVisibleClassName" | "LinkComponent" | "onFocusVisible" | "TouchRippleProps" | "touchRippleRef" | "disableFocusRipple" | "formAction" | "formEncType" | "formMethod" | "formNoValidate" | "formTarget" | "href" | "skeletonWidth" | "startIcon" | "endIcon" | keyof import('react').RefAttributes<HTMLButtonElement> | "fullWidth" | "disableElevation"> & import('@mui/system').MUIStyledCommonProps<import('@mui/material').Theme> & Record<string, unknown>, {}, {}>;
@@ -0,0 +1,12 @@
1
+ import { styled } from "@mui/material";
2
+ import { A as ACTION_FORM_SUBMIT_PROGRAMMATIC_KEY_COMPONENT } from "../constanst.js";
3
+ import { A as ActionFormSubmitProgrammaticSlots } from "./ActionFormSubmitProgrammaticEnum.js";
4
+ import { a as actionFormSubmitProgrammaticStyles } from "../ActionFormSubmitProgrammatic.styles.js";
5
+ import { B as Button } from "../../../../mui_extended/Button/Button.js";
6
+ const ButtonActionFormSubmitProgrammaticRootStyled = styled(Button, {
7
+ name: ACTION_FORM_SUBMIT_PROGRAMMATIC_KEY_COMPONENT,
8
+ slot: ActionFormSubmitProgrammaticSlots.root
9
+ })(actionFormSubmitProgrammaticStyles?.root);
10
+ export {
11
+ ButtonActionFormSubmitProgrammaticRootStyled as B
12
+ };
@@ -0,0 +1,2 @@
1
+ export * from './ActionFormSubmitProgrammaticEnum';
2
+ export * from './ActionFormSubmitProgrammaticSlots';
@@ -0,0 +1,36 @@
1
+ import { Sizes } from '@m4l/styles';
2
+ import { Theme } from '@mui/material';
3
+ import { ButtonProps } from '../../../mui_extended/Button/types';
4
+ import { ACTION_FORM_SUBMIT_PROGRAMMATIC_KEY_COMPONENT } from './constanst';
5
+ import { ActionFormSubmitProgrammaticSlots } from './slots/ActionFormSubmitProgrammaticEnum';
6
+ import { M4LOverridesStyleRules } from '../../../../@types/augmentations';
7
+ import { FieldValues } from 'react-hook-form';
8
+ export interface ActionFormSubmitProgrammaticProps extends Omit<ButtonProps, 'label' | 'type'> {
9
+ /**
10
+ * Función que se ejecuta cuando el formulario se envía exitosamente.
11
+ * Esta función recibe los datos del formulario validados.
12
+ */
13
+ onSubmit: (data: FieldValues) => void | Promise<void>;
14
+ /**
15
+ * Tamaño del botón (opcional).
16
+ * @default 'medium'
17
+ */
18
+ size?: Extract<Sizes, 'small' | 'medium'>;
19
+ /**
20
+ * Clase CSS adicional para el componente.
21
+ */
22
+ className?: string;
23
+ /**
24
+ * Ancho del skeleton cuando está en estado de carga.
25
+ */
26
+ skeletonWidth?: string;
27
+ /**
28
+ * Etiqueta aria-label para accesibilidad.
29
+ */
30
+ 'aria-label'?: string;
31
+ }
32
+ export type OwnerState = Pick<ButtonProps, 'size'>;
33
+ export interface ActionFormSubmitProgrammaticOwnerState extends ButtonProps, OwnerState {
34
+ }
35
+ export type ActionFormSubmitProgrammaticType = keyof typeof ActionFormSubmitProgrammaticSlots;
36
+ export type ActionFormSubmitProgrammaticStyles = M4LOverridesStyleRules<ActionFormSubmitProgrammaticSlots, typeof ACTION_FORM_SUBMIT_PROGRAMMATIC_KEY_COMPONENT, Theme>;
@@ -3,5 +3,6 @@ export { ActionCancel } from './components/ActionCancel';
3
3
  export { ActionIntro } from './components/ActionIntro';
4
4
  export { ActionFormCancel } from './components/ActionFormCancel/ActionFormCancel';
5
5
  export { ActionFormIntro } from './components/ActionFormIntro/ActionFormIntro';
6
+ export { ActionFormSubmitProgrammatic } from './components/ActionFormSubmitProgrammatic/ActionFormSubmitProgrammatic';
6
7
  export { getCommonActionsDictionary } from './dictionary';
7
8
  export * from './dictionary';
@@ -1,33 +1,12 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { useModuleDictionary } from "@m4l/core";
3
- import { useFormContext } from "react-hook-form";
4
2
  import { D as DataTypeComponent } from "../FieldTypes/DataTypeComponent.js";
5
3
  import { u as usePopoverFilter } from "./usePopoverFilter.js";
6
- import { P as POPOVER_CONTAINER_ID } from "../../../../hooks/usePopoverContainer/constants.js";
7
4
  import { u as usePopoverContainer } from "../../../../hooks/usePopoverContainer/usePopoverContainer.js";
8
5
  import { P as PopoverStyled, h as PopoverContainerFieldsStyled, i as PopoverHeaderActionsStyled } from "../../slots/dynamicFilterSlots.js";
9
6
  import { R as RHFormProvider } from "../../../hook-form/RHFormProvider/RHFormProvider.js";
7
+ import { A as ActionFormSubmitProgrammatic } from "../../../CommonActions/components/ActionFormSubmitProgrammatic/ActionFormSubmitProgrammatic.js";
10
8
  import { W as WindowBase } from "../../../WindowBase/WindowBase.js";
11
9
  import { A as ActionCancel } from "../../../CommonActions/components/ActionCancel/ActionCancel.js";
12
- import { B as Button } from "../../../mui_extended/Button/Button.js";
13
- function SubmitButton({ onSubmit }) {
14
- const { getLabel } = useModuleDictionary();
15
- const { handleSubmit } = useFormContext();
16
- const handleClick = () => {
17
- handleSubmit(onSubmit)();
18
- };
19
- return /* @__PURE__ */ jsx(
20
- Button,
21
- {
22
- label: getLabel("common_actions.intro"),
23
- variant: "contained",
24
- color: "primary",
25
- skeletonWidth: "64px",
26
- "aria-label": "applyFilter",
27
- onClick: handleClick
28
- }
29
- );
30
- }
31
10
  function PopoverFilter() {
32
11
  const {
33
12
  field,
@@ -43,8 +22,8 @@ function PopoverFilter() {
43
22
  statusLoad,
44
23
  canRender
45
24
  } = usePopoverFilter();
46
- const popoverContainerRef = usePopoverContainer(POPOVER_CONTAINER_ID, !!canRender);
47
- if (!canRender) {
25
+ const popoverContainerRef = usePopoverContainer(!!canRender);
26
+ if (!canRender || !popoverContainerRef) {
48
27
  return null;
49
28
  }
50
29
  return /* @__PURE__ */ jsx(
@@ -52,6 +31,8 @@ function PopoverFilter() {
52
31
  {
53
32
  open: true,
54
33
  disableRestoreFocus: true,
34
+ disableEnforceFocus: true,
35
+ disableAutoFocus: true,
55
36
  transitionDuration: 0,
56
37
  anchorOrigin: { vertical: "bottom", horizontal: "left" },
57
38
  transformOrigin: { vertical: "top", horizontal: "left" },
@@ -62,7 +43,7 @@ function PopoverFilter() {
62
43
  anchorEl,
63
44
  onKeyDown: handleKeyDownPopper,
64
45
  onClose: handleClosePopover,
65
- container: popoverContainerRef.current,
46
+ container: popoverContainerRef,
66
47
  children: /* @__PURE__ */ jsx(
67
48
  RHFormProvider,
68
49
  {
@@ -83,7 +64,7 @@ function PopoverFilter() {
83
64
  /* @__PURE__ */ jsx(PopoverContainerFieldsStyled, { children: /* @__PURE__ */ jsx(DataTypeComponent, { formFilter, statusLoad }) }),
84
65
  /* @__PURE__ */ jsxs(PopoverHeaderActionsStyled, { children: [
85
66
  /* @__PURE__ */ jsx(ActionCancel, { onClick: onClose, skeletonWidth: "68px" }),
86
- /* @__PURE__ */ jsx(SubmitButton, { onSubmit })
67
+ /* @__PURE__ */ jsx(ActionFormSubmitProgrammatic, { onSubmit, skeletonWidth: "64px", "aria-label": "applyFilter" })
87
68
  ] })
88
69
  ]
89
70
  }
@@ -6,5 +6,5 @@ export type PopoverMenuFieldsProps = {
6
6
  /**
7
7
  * PopoverMenuFields: Componente encargado de mostrar el menú de campos para filtrar
8
8
  */
9
- declare function PopoverMenuFields(props: PopoverMenuFieldsProps): import("react/jsx-runtime").JSX.Element;
9
+ declare function PopoverMenuFields(props: PopoverMenuFieldsProps): import("react/jsx-runtime").JSX.Element | null;
10
10
  export default PopoverMenuFields;
@@ -5,15 +5,17 @@ import { u as useDynamicFilterBase } from "../DynamicFilterBase/useDynamicFilter
5
5
  import { useModuleDictionary } from "@m4l/core";
6
6
  import { a as DICCTIONARY } from "../../dictionary.js";
7
7
  import { u as usePopoverContainer } from "../../../../hooks/usePopoverContainer/usePopoverContainer.js";
8
- import { P as POPOVER_CONTAINER_ID } from "../../../../hooks/usePopoverContainer/constants.js";
9
8
  import { j as PopoverMenuStyled } from "../../slots/dynamicFilterSlots.js";
10
9
  function PopoverMenuFields(props) {
11
10
  const { fields, selectFieldIndex } = props;
12
11
  const { elementRef, handleOpenPopUpClickItem, handleClosePopover, getItemLabel, isOpenPopoverMenuFields } = usePopoverMenuFields();
13
12
  const anchorEl = elementRef?.current;
14
13
  const { getLabel } = useModuleDictionary();
15
- const popoverContainerRef = usePopoverContainer(POPOVER_CONTAINER_ID, !!isOpenPopoverMenuFields);
14
+ const popoverContainerRef = usePopoverContainer(!!isOpenPopoverMenuFields);
16
15
  const { size } = useDynamicFilterBase();
16
+ if (!isOpenPopoverMenuFields || !popoverContainerRef) {
17
+ return null;
18
+ }
17
19
  return /* @__PURE__ */ jsxs(
18
20
  PopoverMenuStyled,
19
21
  {
@@ -28,7 +30,7 @@ function PopoverMenuFields(props) {
28
30
  open: !!isOpenPopoverMenuFields,
29
31
  onClose: handleClosePopover,
30
32
  anchorEl,
31
- container: popoverContainerRef.current,
33
+ container: popoverContainerRef,
32
34
  children: [
33
35
  isOpenPopoverMenuFields && fields.map((field, index) => /* @__PURE__ */ jsx(
34
36
  MenuItem,
@@ -6,5 +6,5 @@ export type PopoverMenuFieldsProps = {
6
6
  /**
7
7
  * PopoverMenuFields es un componente que permite mostrar un menú desplegable con los campos disponibles para ordenar.
8
8
  */
9
- declare function PopoverMenuFields(props: PopoverMenuFieldsProps): import("react/jsx-runtime").JSX.Element;
9
+ declare function PopoverMenuFields(props: PopoverMenuFieldsProps): import("react/jsx-runtime").JSX.Element | null;
10
10
  export default PopoverMenuFields;
@@ -6,7 +6,6 @@ import { I as Icon } from "../../../Icon/Icon.js";
6
6
  import { D as DICCTIONARY } from "../../dictionary.js";
7
7
  import { useModuleDictionary } from "@m4l/core";
8
8
  import { u as usePopoverContainer } from "../../../../hooks/usePopoverContainer/usePopoverContainer.js";
9
- import { P as POPOVER_CONTAINER_ID } from "../../../../hooks/usePopoverContainer/constants.js";
10
9
  import { P as PopoverMenuStyled } from "../../slots/DynamicSortSlots.js";
11
10
  function PopoverMenuFields(props) {
12
11
  const { fields, selectFieldIndex } = props;
@@ -14,7 +13,10 @@ function PopoverMenuFields(props) {
14
13
  const { size } = useDynamicSortBase();
15
14
  const anchorEl = elementRef?.current;
16
15
  const { getLabel } = useModuleDictionary();
17
- const popoverContainerRef = usePopoverContainer(POPOVER_CONTAINER_ID, !!isOpenPopoverMenuFields);
16
+ const popoverContainerRef = usePopoverContainer(!!isOpenPopoverMenuFields);
17
+ if (!isOpenPopoverMenuFields || !popoverContainerRef) {
18
+ return null;
19
+ }
18
20
  return /* @__PURE__ */ jsxs(
19
21
  PopoverMenuStyled,
20
22
  {
@@ -26,7 +28,7 @@ function PopoverMenuFields(props) {
26
28
  open: !!isOpenPopoverMenuFields,
27
29
  onClose: handleClosePopover,
28
30
  anchorEl,
29
- container: popoverContainerRef.current,
31
+ container: popoverContainerRef,
30
32
  sx: (theme) => ({
31
33
  mt: theme.vars.size.baseSpacings.sp2
32
34
  }),
@@ -1,38 +1,13 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { useModuleDictionary } from "@m4l/core";
3
- import { useFormContext } from "react-hook-form";
4
2
  import { u as useDynamicSortBase } from "../DynamicSortBase/useDynamicSortBase.js";
5
3
  import { D as DataTypeComponent } from "../FieldTypes/DataTypeComponent.js";
6
4
  import { u as usePopoverSort } from "./usePopoverSort.js";
7
5
  import { u as usePopoverContainer } from "../../../../hooks/usePopoverContainer/usePopoverContainer.js";
8
- import { P as POPOVER_CONTAINER_ID } from "../../../../hooks/usePopoverContainer/constants.js";
9
6
  import { e as PopoverStyled, f as PopoverContainerFieldsStyled, g as PopoverHeaderActionsStyled } from "../../slots/DynamicSortSlots.js";
10
7
  import { R as RHFormProvider } from "../../../hook-form/RHFormProvider/RHFormProvider.js";
8
+ import { A as ActionFormSubmitProgrammatic } from "../../../CommonActions/components/ActionFormSubmitProgrammatic/ActionFormSubmitProgrammatic.js";
11
9
  import { W as WindowBase } from "../../../WindowBase/WindowBase.js";
12
10
  import { A as ActionCancel } from "../../../CommonActions/components/ActionCancel/ActionCancel.js";
13
- import { B as Button } from "../../../mui_extended/Button/Button.js";
14
- function SubmitButton({
15
- onSubmit,
16
- size
17
- }) {
18
- const { getLabel } = useModuleDictionary();
19
- const { handleSubmit } = useFormContext();
20
- const handleClick = () => {
21
- handleSubmit(onSubmit)();
22
- };
23
- return /* @__PURE__ */ jsx(
24
- Button,
25
- {
26
- label: getLabel("common_actions.intro"),
27
- variant: "contained",
28
- color: "primary",
29
- size,
30
- skeletonWidth: size === "small" ? "80px" : "100px",
31
- "aria-label": "applySort",
32
- onClick: handleClick
33
- }
34
- );
35
- }
36
11
  function PopoverSort() {
37
12
  const {
38
13
  field,
@@ -49,8 +24,8 @@ function PopoverSort() {
49
24
  canRender
50
25
  } = usePopoverSort();
51
26
  const { size } = useDynamicSortBase();
52
- const popoverContainerRef = usePopoverContainer(POPOVER_CONTAINER_ID, !!canRender);
53
- if (!canRender) {
27
+ const popoverContainerRef = usePopoverContainer(!!canRender);
28
+ if (!canRender || !popoverContainerRef) {
54
29
  return null;
55
30
  }
56
31
  return /* @__PURE__ */ jsx(
@@ -58,6 +33,8 @@ function PopoverSort() {
58
33
  {
59
34
  open: true,
60
35
  disableRestoreFocus: true,
36
+ disableEnforceFocus: true,
37
+ disableAutoFocus: true,
61
38
  transitionDuration: 0,
62
39
  anchorOrigin: { vertical: "bottom", horizontal: "left" },
63
40
  transformOrigin: { vertical: "top", horizontal: "left" },
@@ -65,7 +42,7 @@ function PopoverSort() {
65
42
  anchorEl,
66
43
  onKeyDown: handleKeyDownPopper,
67
44
  onClose: handleClosePopover,
68
- container: popoverContainerRef.current,
45
+ container: popoverContainerRef,
69
46
  sx: (theme) => ({
70
47
  mt: theme.vars.size.baseSpacings.sp2
71
48
  }),
@@ -89,7 +66,7 @@ function PopoverSort() {
89
66
  /* @__PURE__ */ jsx(PopoverContainerFieldsStyled, { children: /* @__PURE__ */ jsx(DataTypeComponent, { formSort, statusLoad }) }),
90
67
  /* @__PURE__ */ jsxs(PopoverHeaderActionsStyled, { children: [
91
68
  /* @__PURE__ */ jsx(ActionCancel, { size, onClick: onClose }),
92
- /* @__PURE__ */ jsx(SubmitButton, { onSubmit, size })
69
+ /* @__PURE__ */ jsx(ActionFormSubmitProgrammatic, { onSubmit, size, "aria-label": "applySort" })
93
70
  ] })
94
71
  ]
95
72
  }
@@ -326,7 +326,7 @@ const createAreasStore = (initProps, storeDevtoolsEnabled = false) => {
326
326
  for (let index = 0; index < get().hashAreas[areaId].layoutItemsIds.length; index++) {
327
327
  const layoutItemId = get().hashAreas[areaId].layoutItemsIds[index];
328
328
  const layoutItem = get().hashWindows[layoutItemId];
329
- if (layoutItem.parentId === removeLayoutId) {
329
+ if (layoutItem && layoutItem.parentId === removeLayoutId) {
330
330
  get().areaActions.closeLayout(areaId, layoutItem.windowId);
331
331
  }
332
332
  }
@@ -1,8 +1,37 @@
1
1
  /**
2
- * Hook para manejar un contenedor global para popovers. cuando se requiere que siga teniendo foco el anchorElement
3
- * Este hook garantiza que solo exista un contenedor con el ID especificado,
4
- * incluso si el hook se usa en múltiples componentes.
5
- * @param containerId ID único para el contenedor
6
- * @returns Referencia al contenedor del popover
2
+ * Hook para manejar un contenedor global para popovers cuando se requiere que el anchorElement
3
+ * mantenga el foco mientras el popover está abierto.
4
+ *
5
+ * PROPÓSITO:
6
+ * Este hook crea y gestiona un contenedor DOM personalizado para popovers. Es especialmente útil
7
+ * cuando necesitas que el elemento ancla (anchorElement) mantenga el foco mientras el popover
8
+ * está visible, evitando que el foco se mueva automáticamente al popover.
9
+ *
10
+ * FUNCIONAMIENTO:
11
+ * 1. Busca un contenedor existente en el DOM con el ID especificado
12
+ * 2. Si no existe y `createContainer` es `true`, crea un nuevo contenedor y lo añade al body
13
+ * 3. Retorna una referencia al contenedor que debe pasarse a la prop `container` del Popover
14
+ *
15
+ * IMPORTANTE - TIMING Y RE-RENDERS:
16
+ * Este hook utiliza un re-render forzado para garantizar que el Popover se renderice con la
17
+ * referencia correcta del contenedor. Ver la documentación dentro del código para más detalles
18
+ * sobre por qué esto es necesario y qué ocurre si no se realiza.
19
+ * @param containerId ID único para el contenedor. Si no se proporciona, usa POPOVER_CONTAINER_ID por defecto
20
+ * @param createContainer Si es `true`, crea el contenedor si no existe. Si es `false`, solo busca uno existente
21
+ * @returns Referencia (ref) al contenedor del popover que debe pasarse a la prop `container` del Popover
22
+ * @example
23
+ * ```tsx
24
+ * const containerId = useId();
25
+ * const popoverContainerRef = usePopoverContainer(containerId, !!isOpen);
26
+ *
27
+ * return (
28
+ * <Popover
29
+ * open={isOpen}
30
+ * container={popoverContainerRef.current} // Pasa la referencia aquí
31
+ * >
32
+ * {/* contenido del popover *\/}
33
+ * </Popover>
34
+ * );
35
+ * ```
7
36
  */
8
- export declare function usePopoverContainer(containerId?: string, createContainer?: boolean): import('react').MutableRefObject<HTMLDivElement | null>;
37
+ export declare function usePopoverContainer(createContainer: boolean): HTMLDivElement | null;
@@ -1,22 +1,30 @@
1
- import { useRef, useEffect } from "react";
2
- import { P as POPOVER_CONTAINER_ID } from "./constants.js";
3
- function usePopoverContainer(containerId = POPOVER_CONTAINER_ID, createContainer = false) {
1
+ import { useState, useRef, useId, useLayoutEffect } from "react";
2
+ function usePopoverContainer(createContainer) {
3
+ const [containerElement, setContainerElement] = useState(null);
4
4
  const containerRef = useRef(null);
5
- useEffect(() => {
6
- let container = document.getElementById(containerId);
5
+ const baseId = useId();
6
+ useLayoutEffect(() => {
7
+ if (typeof document === "undefined") {
8
+ return;
9
+ }
10
+ let container = document.getElementById(baseId);
7
11
  if (!container && createContainer) {
8
12
  container = document.createElement("div");
9
- container.id = containerId;
13
+ container.id = baseId;
10
14
  document.body.appendChild(container);
11
15
  }
12
- containerRef.current = container;
16
+ if (containerRef.current !== container) {
17
+ setContainerElement(container);
18
+ containerRef.current = container;
19
+ }
13
20
  return () => {
14
- if (!createContainer && containerRef.current) {
21
+ if (containerRef.current) {
15
22
  containerRef.current.remove();
23
+ containerRef.current = null;
16
24
  }
17
25
  };
18
- }, [containerId]);
19
- return containerRef;
26
+ }, [baseId, createContainer, containerRef]);
27
+ return createContainer ? containerElement : null;
20
28
  }
21
29
  export {
22
30
  usePopoverContainer as u
package/index.js CHANGED
@@ -32,6 +32,7 @@ import { A as A11 } from "./components/CommonActions/components/ActionCancel/Act
32
32
  import { A as A12 } from "./components/CommonActions/components/ActionIntro/ActionIntro.js";
33
33
  import { A as A13 } from "./components/CommonActions/components/ActionFormCancel/ActionFormCancel.js";
34
34
  import { A as A14 } from "./components/CommonActions/components/ActionFormIntro/ActionFormIntro.js";
35
+ import { A as A15 } from "./components/CommonActions/components/ActionFormSubmitProgrammatic/ActionFormSubmitProgrammatic.js";
35
36
  import { D, d, g as g5 } from "./components/CommonActions/dictionary.js";
36
37
  import { C as C4 } from "./components/ContainerFlow/ContainerFlow.js";
37
38
  import { D as D2 } from "./components/datagrids/components/DataGridMain/DataGridMain.js";
@@ -85,7 +86,7 @@ import { P } from "./components/extended/React-Spinners/PropagateLoaderSpinner/P
85
86
  import { F } from "./components/extended/React-Window/FixedSizeList/FixedSizeList.js";
86
87
  import { V } from "./components/extended/React-Window/VariableSizeList/VariableSizeList.js";
87
88
  import { R as R3 } from "./components/extended/React-Json-Viewer/ReactJsonViewer.js";
88
- import { A as A15 } from "./components/mui_extended/Avatar/Avatar.js";
89
+ import { A as A16 } from "./components/mui_extended/Avatar/Avatar.js";
89
90
  import { B as B2 } from "./components/mui_extended/BoxIcon/index.js";
90
91
  import { B as B3 } from "./components/mui_extended/Breadcrumbs/index.js";
91
92
  import { C as C19 } from "./components/mui_extended/CircularProgress/CircularProgress.js";
@@ -94,7 +95,7 @@ import { L as L3 } from "./components/mui_extended/LinearProgress/index.js";
94
95
  import { L as L4 } from "./components/mui_extended/LinkWithRoute/index.js";
95
96
  import { L as L5 } from "./components/mui_extended/LoadingButton/LoadingButton.js";
96
97
  import { g as g12 } from "./components/Pager/dicctionary.js";
97
- import { A as A16 } from "./components/mui_extended/Accordion/Accordion.js";
98
+ import { A as A17 } from "./components/mui_extended/Accordion/Accordion.js";
98
99
  import { T as T3 } from "./components/mui_extended/Tooltip/Tooltip.js";
99
100
  import { I as I2 } from "./components/mui_extended/IconButton/IconButton.js";
100
101
  import { B as B5 } from "./components/mui_extended/Button/Button.js";
@@ -237,7 +238,7 @@ import { g as g30 } from "./components/Stepper/helpers/getStepsAndValidationSche
237
238
  import { g as g31 } from "./components/Stepper/dictionary.js";
238
239
  import { g as g32 } from "./components/hook-form/RHFormProvider/dictionary.js";
239
240
  import { u as u23 } from "./contexts/AppearanceComponentContext/useAppearanceComponentStore.js";
240
- import { A as A17 } from "./contexts/AppearanceComponentContext/AppearanceComponentContext.js";
241
+ import { A as A18 } from "./contexts/AppearanceComponentContext/AppearanceComponentContext.js";
241
242
  import { a as a18, M as M10 } from "./contexts/ModalContext/index.js";
242
243
  import { u as u24 } from "./hooks/useFormAddEdit/useFormAddEdit.js";
243
244
  import { u as u25 } from "./hooks/useModal/index.js";
@@ -273,23 +274,24 @@ import { c as c6, d as d5 } from "./utils/deepShallow.js";
273
274
  export {
274
275
  A8 as AREAS_DICCTIONARY,
275
276
  a3 as AREAS_DICTIONARY_ID,
276
- A16 as Accordion,
277
+ A17 as Accordion,
277
278
  A as AccountPopover,
278
279
  A11 as ActionCancel,
279
280
  A13 as ActionFormCancel,
280
281
  A14 as ActionFormIntro,
282
+ A15 as ActionFormSubmitProgrammatic,
281
283
  A12 as ActionIntro,
282
284
  A10 as ActionsContainer,
283
285
  A2 as ActionsGroup,
284
286
  A3 as AnimatedScroll,
285
287
  A4 as AppBar,
286
288
  A9 as AppBarComercial,
287
- A17 as AppearanceComponentProvider,
289
+ A18 as AppearanceComponentProvider,
288
290
  A5 as AreasAdmin,
289
291
  a2 as AreasContext,
290
292
  A7 as AreasProvider,
291
293
  A6 as AreasViewer,
292
- A15 as Avatar,
294
+ A16 as Avatar,
293
295
  B4 as Badge,
294
296
  B as BaseModule,
295
297
  B6 as BooleanFormatter,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m4l/components",
3
- "version": "9.4.6-BE20260109-beta.1",
3
+ "version": "9.4.6-BE20260111-beta.1",
4
4
  "license": "UNLICENSED",
5
5
  "description": "M4L Components",
6
6
  "lint-staged": {