@m4l/components 9.4.27 → 9.4.28-BE20260210-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/DynamicForm/DynamicForm.d.ts +28 -0
- package/components/DynamicForm/DynamicForm.js +126 -0
- package/components/DynamicForm/DynamicForm.styles.d.ts +2 -0
- package/components/DynamicForm/DynamicForm.styles.js +93 -0
- package/components/DynamicForm/constants.d.ts +14 -0
- package/components/DynamicForm/constants.js +18 -0
- package/components/DynamicForm/helpers/normalizeValidations.d.ts +15 -0
- package/components/DynamicForm/helpers/normalizeValidations.js +192 -0
- package/components/DynamicForm/helpers/resolveFieldComponent.d.ts +16 -0
- package/components/DynamicForm/helpers/resolveFieldComponent.js +118 -0
- package/components/DynamicForm/helpers/resolveInitialValue.d.ts +14 -0
- package/components/DynamicForm/helpers/resolveInitialValue.js +99 -0
- package/components/DynamicForm/hooks/useDynamicForm/useDynamicForm.d.ts +14 -0
- package/components/DynamicForm/hooks/useDynamicForm/useDynamicForm.js +38 -0
- package/components/DynamicForm/hooks/useDynamicFormConditionals/useDynamicFormConditionals.d.ts +12 -0
- package/components/DynamicForm/hooks/useDynamicFormConditionals/useDynamicFormConditionals.js +69 -0
- package/components/DynamicForm/hooks/useDynamicFormData/types.d.ts +18 -0
- package/components/DynamicForm/hooks/useDynamicFormData/useDynamicFormData.d.ts +12 -0
- package/components/DynamicForm/hooks/useDynamicFormData/useDynamicFormData.js +128 -0
- package/components/DynamicForm/index.d.ts +4 -0
- package/components/DynamicForm/index.js +1 -0
- package/components/DynamicForm/slots/DynamicFormEnum.d.ts +14 -0
- package/components/DynamicForm/slots/DynamicFormEnum.js +15 -0
- package/components/DynamicForm/slots/DynamicFormSlots.d.ts +14 -0
- package/components/DynamicForm/slots/DynamicFormSlots.js +51 -0
- package/components/DynamicForm/slots/index.d.ts +3 -0
- package/components/DynamicForm/slots/index.js +1 -0
- package/components/DynamicForm/subcomponents/DynamicFormContent/DynamicFormContent.d.ts +2 -0
- package/components/DynamicForm/subcomponents/DynamicFormContent/DynamicFormContent.js +71 -0
- package/components/DynamicForm/subcomponents/DynamicFormCoupled/DynamicFormCoupled.d.ts +32 -0
- package/components/DynamicForm/subcomponents/DynamicFormCoupled/DynamicFormCoupled.js +45 -0
- package/components/DynamicForm/subcomponents/DynamicFormCoupledInternal/DynamicFormCoupledInternal.d.ts +7 -0
- package/components/DynamicForm/subcomponents/DynamicFormCoupledInternal/DynamicFormCoupledInternal.js +86 -0
- package/components/DynamicForm/subcomponents/DynamicFormCoupledInternalContent/DynamicFormCoupledInternalContent.d.ts +9 -0
- package/components/DynamicForm/subcomponents/DynamicFormCoupledInternalContent/DynamicFormCoupledInternalContent.js +62 -0
- package/components/DynamicForm/subcomponents/index.d.ts +4 -0
- package/components/DynamicForm/subcomponents/index.js +1 -0
- package/components/DynamicForm/types.d.ts +313 -0
- package/components/extended/mui/Autocomplete/Autocomplete.test.d.ts +1 -0
- package/components/extended/mui/Autocomplete/constants.test.d.ts +1 -0
- package/components/extended/mui/Autocomplete/dictionary.test.d.ts +1 -0
- package/components/extended/mui/Autocomplete/hooks/useAutocomplete/useAutocomplete.test.d.ts +1 -0
- package/components/extended/mui/Autocomplete/hooks/useEndAdornments.test.d.ts +1 -0
- package/components/extended/mui/Autocomplete/hooks/useMultipleChips.js +13 -10
- package/components/extended/mui/Autocomplete/hooks/useMultipleChips.test.d.ts +1 -0
- package/components/extended/mui/Autocomplete/hooks/useValuesAndHandlers.js +0 -5
- package/components/extended/mui/Autocomplete/hooks/useValuesAndHandlers.test.d.ts +1 -0
- package/components/extended/mui/Autocomplete/icons.test.d.ts +1 -0
- package/components/extended/mui/Autocomplete/subcomponents/LoadingText/LoadingText.test.d.ts +1 -0
- package/components/extended/mui/Autocomplete/subcomponents/NoOptionsText/NoOptionsText.test.d.ts +1 -0
- package/components/extended/mui/Autocomplete/subcomponents/PopperComponent/PopperComponent.test.d.ts +1 -0
- package/components/extended/mui/Autocomplete/subcomponents/RenderAdornment/RenderAdornment.js +2 -1
- package/components/extended/mui/Autocomplete/subcomponents/RenderAdornment/RenderAdornment.test.d.ts +1 -0
- package/components/extended/mui/Autocomplete/subcomponents/renderOptions/renderOptions.test.d.ts +1 -0
- package/components/hook-form/RHFCheckbox/index.js +1 -0
- package/components/hook-form/RHFCheckbox/types.js +1 -0
- package/components/index.d.ts +1 -0
- package/index.js +66 -60
- package/package.json +1 -1
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from "react";
|
|
3
|
+
import { useFormContext, Controller } from "react-hook-form";
|
|
4
|
+
import { D as DynamicFormCoupledInternal } from "../DynamicFormCoupledInternal/DynamicFormCoupledInternal.js";
|
|
5
|
+
const DynamicFormCoupled = forwardRef((props) => {
|
|
6
|
+
const {
|
|
7
|
+
name,
|
|
8
|
+
value,
|
|
9
|
+
initialValues,
|
|
10
|
+
validationSchema,
|
|
11
|
+
ownerState,
|
|
12
|
+
currentSize,
|
|
13
|
+
fieldWrapperClassName,
|
|
14
|
+
dataTestId,
|
|
15
|
+
className
|
|
16
|
+
} = props;
|
|
17
|
+
const { control } = useFormContext();
|
|
18
|
+
return /* @__PURE__ */ jsx(
|
|
19
|
+
Controller,
|
|
20
|
+
{
|
|
21
|
+
name,
|
|
22
|
+
control,
|
|
23
|
+
render: ({ field: { onChange } }) => {
|
|
24
|
+
return /* @__PURE__ */ jsx(
|
|
25
|
+
DynamicFormCoupledInternal,
|
|
26
|
+
{
|
|
27
|
+
value,
|
|
28
|
+
initialValues,
|
|
29
|
+
validationSchema,
|
|
30
|
+
ownerState,
|
|
31
|
+
currentSize,
|
|
32
|
+
fieldWrapperClassName,
|
|
33
|
+
dataTestId,
|
|
34
|
+
className,
|
|
35
|
+
onChange
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
});
|
|
42
|
+
DynamicFormCoupled.displayName = "DynamicFormCoupled";
|
|
43
|
+
export {
|
|
44
|
+
DynamicFormCoupled as D
|
|
45
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { DynamicFormCoupledInternalProps } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Formulario acoplado que se monta dentro de un Controller externo.
|
|
4
|
+
* Crea su propio estado de formulario y delega el render en el contenido interno.
|
|
5
|
+
* Se usa cuando coupled=true para exponer el formulario como un campo dentro de un formulario padre.
|
|
6
|
+
*/
|
|
7
|
+
export declare const DynamicFormCoupledInternal: import('react').ForwardRefExoticComponent<DynamicFormCoupledInternalProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useRef, useEffect } from "react";
|
|
3
|
+
import { useForm, FormProvider } from "react-hook-form";
|
|
4
|
+
import { yupResolver } from "@hookform/resolvers/yup";
|
|
5
|
+
import { D as DynamicFormCoupledInternalContent } from "../DynamicFormCoupledInternalContent/DynamicFormCoupledInternalContent.js";
|
|
6
|
+
const DynamicFormCoupledInternal = forwardRef((props) => {
|
|
7
|
+
const {
|
|
8
|
+
value,
|
|
9
|
+
initialValues,
|
|
10
|
+
validationSchema,
|
|
11
|
+
ownerState,
|
|
12
|
+
currentSize,
|
|
13
|
+
fieldWrapperClassName,
|
|
14
|
+
dataTestId,
|
|
15
|
+
className,
|
|
16
|
+
onChange
|
|
17
|
+
} = props;
|
|
18
|
+
const internalFormMethods = useForm({
|
|
19
|
+
resolver: yupResolver(validationSchema),
|
|
20
|
+
defaultValues: initialValues,
|
|
21
|
+
mode: "onTouched"
|
|
22
|
+
});
|
|
23
|
+
const lastSentValueRef = useRef(null);
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
const keys = Object.keys(initialValues);
|
|
26
|
+
keys.forEach((key) => {
|
|
27
|
+
const fieldName = key;
|
|
28
|
+
const fieldValue = initialValues[key];
|
|
29
|
+
internalFormMethods.setValue(fieldName, fieldValue, {
|
|
30
|
+
/**
|
|
31
|
+
* Opciones de setValue para sincronización silenciosa:
|
|
32
|
+
*
|
|
33
|
+
* **shouldValidate: false**
|
|
34
|
+
* - Evita ejecutar las validaciones de Yup cuando se establecen los valores iniciales.
|
|
35
|
+
* - Razón: Los valores iniciales ya vienen validados del backend, no necesitan validarse
|
|
36
|
+
* nuevamente al sincronizarse. Además, validar todos los campos al cargar puede ser
|
|
37
|
+
* costoso en formularios grandes y mostrar errores antes de que el usuario interactúe.
|
|
38
|
+
* - Sin esto: Se ejecutarían todas las validaciones al cargar, mostrando posibles errores
|
|
39
|
+
* de campos que el usuario aún no ha tocado.
|
|
40
|
+
*
|
|
41
|
+
* **shouldDirty: false**
|
|
42
|
+
* - Evita marcar los campos como "sucios" (modificados) cuando se sincronizan valores iniciales.
|
|
43
|
+
* - Razón: Los valores iniciales no son modificaciones del usuario, son el estado base.
|
|
44
|
+
* Marcar campos como "dirty" haría que el formulario parezca modificado cuando en realidad
|
|
45
|
+
* solo se están cargando los datos iniciales.
|
|
46
|
+
* - Sin esto: El formulario se marcaría como "modificado" inmediatamente al cargar,
|
|
47
|
+
* lo que podría activar advertencias de "tienes cambios sin guardar" incorrectamente.
|
|
48
|
+
*
|
|
49
|
+
* **shouldTouch: false**
|
|
50
|
+
* - Evita marcar los campos como "tocados" (visitados) cuando se establecen valores iniciales.
|
|
51
|
+
* - Razón: Un campo "touched" normalmente significa que el usuario lo ha visitado/interactuado.
|
|
52
|
+
* Los valores iniciales no representan interacción del usuario, solo datos precargados.
|
|
53
|
+
* - Sin esto: Los campos se marcarían como "touched" al cargar, lo que podría mostrar
|
|
54
|
+
* mensajes de error o estilos de validación antes de que el usuario interactúe con ellos.
|
|
55
|
+
*
|
|
56
|
+
* **Resumen:**
|
|
57
|
+
* Estas opciones garantizan que la sincronización de valores iniciales sea "silenciosa",
|
|
58
|
+
* actualizando solo los valores sin afectar el estado de validación, modificación o
|
|
59
|
+
* interacción del formulario. El usuario solo verá validaciones y estados cuando
|
|
60
|
+
* realmente interactúe con los campos.
|
|
61
|
+
*/
|
|
62
|
+
shouldValidate: false,
|
|
63
|
+
shouldDirty: false,
|
|
64
|
+
shouldTouch: false
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
}, [initialValues, internalFormMethods]);
|
|
68
|
+
return /* @__PURE__ */ jsx(FormProvider, { ...internalFormMethods, children: /* @__PURE__ */ jsx(
|
|
69
|
+
DynamicFormCoupledInternalContent,
|
|
70
|
+
{
|
|
71
|
+
value,
|
|
72
|
+
ownerState,
|
|
73
|
+
currentSize,
|
|
74
|
+
fieldWrapperClassName,
|
|
75
|
+
dataTestId,
|
|
76
|
+
className,
|
|
77
|
+
onChange,
|
|
78
|
+
lastSentValueRef,
|
|
79
|
+
internalFormMethods
|
|
80
|
+
}
|
|
81
|
+
) });
|
|
82
|
+
});
|
|
83
|
+
DynamicFormCoupledInternal.displayName = "DynamicFormCoupledInternal";
|
|
84
|
+
export {
|
|
85
|
+
DynamicFormCoupledInternal as D
|
|
86
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { DynamicFormCoupledInternalContentProps } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Componente que se encarga de renderizar el contenido del formulario acoplado.
|
|
4
|
+
* Valida y notifica cambios solo en campos visibles al formulario padre.
|
|
5
|
+
*/
|
|
6
|
+
export declare const DynamicFormCoupledInternalContent: {
|
|
7
|
+
(props: DynamicFormCoupledInternalContentProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
displayName: string;
|
|
9
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect } from "react";
|
|
3
|
+
import { u as useDynamicFormConditionals } from "../../hooks/useDynamicFormConditionals/useDynamicFormConditionals.js";
|
|
4
|
+
import { D as DynamicFormContent } from "../DynamicFormContent/DynamicFormContent.js";
|
|
5
|
+
const DynamicFormCoupledInternalContent = (props) => {
|
|
6
|
+
const {
|
|
7
|
+
value,
|
|
8
|
+
ownerState,
|
|
9
|
+
currentSize,
|
|
10
|
+
fieldWrapperClassName,
|
|
11
|
+
dataTestId,
|
|
12
|
+
onChange,
|
|
13
|
+
lastSentValueRef,
|
|
14
|
+
internalFormMethods
|
|
15
|
+
} = props;
|
|
16
|
+
const { visibleFields } = useDynamicFormConditionals(value);
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
const notifyChange = () => {
|
|
19
|
+
const visibleFieldNames = visibleFields.map((field) => field.name);
|
|
20
|
+
internalFormMethods.trigger(visibleFieldNames).then(() => {
|
|
21
|
+
const errors = internalFormMethods.formState.errors;
|
|
22
|
+
const visibleFieldsValid = visibleFieldNames.every((fieldName) => {
|
|
23
|
+
return !errors[fieldName];
|
|
24
|
+
});
|
|
25
|
+
const currentValues = internalFormMethods.getValues();
|
|
26
|
+
const visibleFieldValues = {};
|
|
27
|
+
visibleFieldNames.forEach((fieldName) => {
|
|
28
|
+
if (currentValues[fieldName] !== void 0) {
|
|
29
|
+
visibleFieldValues[fieldName] = currentValues[fieldName];
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
const formFieldsValue = {
|
|
33
|
+
...visibleFieldValues,
|
|
34
|
+
isDynamicFormValidInternal: visibleFieldsValid
|
|
35
|
+
};
|
|
36
|
+
const serializedValue = JSON.stringify(formFieldsValue);
|
|
37
|
+
if (serializedValue !== lastSentValueRef.current) {
|
|
38
|
+
lastSentValueRef.current = serializedValue;
|
|
39
|
+
onChange(formFieldsValue);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
const subscription = internalFormMethods.watch(notifyChange);
|
|
44
|
+
notifyChange();
|
|
45
|
+
return () => subscription.unsubscribe();
|
|
46
|
+
}, [internalFormMethods, visibleFields, onChange, lastSentValueRef]);
|
|
47
|
+
return /* @__PURE__ */ jsx(
|
|
48
|
+
DynamicFormContent,
|
|
49
|
+
{
|
|
50
|
+
data: value,
|
|
51
|
+
ownerState,
|
|
52
|
+
currentSize,
|
|
53
|
+
fieldWrapperClassName,
|
|
54
|
+
dataTestId,
|
|
55
|
+
coupled: true
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
};
|
|
59
|
+
DynamicFormCoupledInternalContent.displayName = "DynamicFormCoupledInternalContent";
|
|
60
|
+
export {
|
|
61
|
+
DynamicFormCoupledInternalContent as D
|
|
62
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { DynamicFormCoupled } from './DynamicFormCoupled/DynamicFormCoupled';
|
|
2
|
+
export { DynamicFormCoupledInternal } from './DynamicFormCoupledInternal/DynamicFormCoupledInternal';
|
|
3
|
+
export { DynamicFormCoupledInternalContent } from './DynamicFormCoupledInternalContent/DynamicFormCoupledInternalContent';
|
|
4
|
+
export { DynamicFormContent } from './DynamicFormContent/DynamicFormContent';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import { Theme } from '@mui/material/styles';
|
|
2
|
+
import { MutableRefObject, ReactNode } from 'react';
|
|
3
|
+
import { Sizes } from '@m4l/styles';
|
|
4
|
+
import { DynamicFormSlots } from './slots';
|
|
5
|
+
import { DYNAMIC_FORM_KEY_COMPONENT } from './constants';
|
|
6
|
+
import { M4LOverridesStyleRules } from '../../@types/augmentations';
|
|
7
|
+
import { RHFormValues, RHFormProviderRef } from '../hook-form/RHFormProvider/types';
|
|
8
|
+
import { ActionsFormIntroProps } from '../CommonActions/components/ActionFormIntro/types';
|
|
9
|
+
import { useForm } from 'react-hook-form';
|
|
10
|
+
/**
|
|
11
|
+
* Tipos del contrato API - FormMetadata
|
|
12
|
+
*/
|
|
13
|
+
export interface FormMetadata {
|
|
14
|
+
id: number;
|
|
15
|
+
name: string;
|
|
16
|
+
version: number;
|
|
17
|
+
nameDictionaryId: number;
|
|
18
|
+
descriptionDictionaryId: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Tipos del contrato API - FieldType
|
|
22
|
+
*/
|
|
23
|
+
export interface FieldType {
|
|
24
|
+
id: string;
|
|
25
|
+
name: string;
|
|
26
|
+
rhfComponent: string;
|
|
27
|
+
rhfComponentProps?: Record<string, unknown>;
|
|
28
|
+
supportsOptions: boolean;
|
|
29
|
+
nameDictionaryId: number;
|
|
30
|
+
supportsValidation: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Tipos del contrato API - ValidationType
|
|
34
|
+
*/
|
|
35
|
+
export interface ValidationType {
|
|
36
|
+
id: string;
|
|
37
|
+
name: string;
|
|
38
|
+
requiresValue: boolean;
|
|
39
|
+
nameDictionaryId: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Tipos del contrato API - Validation
|
|
43
|
+
*/
|
|
44
|
+
export interface FieldValidation {
|
|
45
|
+
id: string;
|
|
46
|
+
isActive: boolean;
|
|
47
|
+
displayOrder: number;
|
|
48
|
+
errorMessage: string;
|
|
49
|
+
validationType?: ValidationType;
|
|
50
|
+
type?: ValidationType;
|
|
51
|
+
value?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Tipos del contrato API - FieldOption
|
|
55
|
+
*/
|
|
56
|
+
export interface FieldOption {
|
|
57
|
+
id: number;
|
|
58
|
+
name: string | null;
|
|
59
|
+
value: string;
|
|
60
|
+
isDefault: boolean;
|
|
61
|
+
displayOrder: number;
|
|
62
|
+
nameDictionaryId: number;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Tipos del contrato API - FieldValue
|
|
66
|
+
*/
|
|
67
|
+
export interface FieldValue {
|
|
68
|
+
id: number;
|
|
69
|
+
name: string | null;
|
|
70
|
+
value: string;
|
|
71
|
+
isVisible: boolean;
|
|
72
|
+
valueDouble: number | null;
|
|
73
|
+
valueString: string | null;
|
|
74
|
+
valueBoolean: boolean | null;
|
|
75
|
+
valueInteger: number | null;
|
|
76
|
+
valueTimestamp: string | null;
|
|
77
|
+
visibilityReason: string;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Tipos del contrato API - Field
|
|
81
|
+
*/
|
|
82
|
+
export interface Field {
|
|
83
|
+
id: number;
|
|
84
|
+
name: string;
|
|
85
|
+
options: FieldOption[];
|
|
86
|
+
fieldType: FieldType;
|
|
87
|
+
helperText: string | null;
|
|
88
|
+
isRequired: boolean;
|
|
89
|
+
placeholder: string | null;
|
|
90
|
+
propertyId: string;
|
|
91
|
+
validations: FieldValidation[];
|
|
92
|
+
currentValue: FieldValue | null;
|
|
93
|
+
defaultValue: string | null;
|
|
94
|
+
displayOrder: number;
|
|
95
|
+
isConditional: boolean;
|
|
96
|
+
validationErrors: unknown[];
|
|
97
|
+
nameDictionaryId: number;
|
|
98
|
+
descriptionDictionaryId: number;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Tipos del contrato API - ConditionalRuleOperator
|
|
102
|
+
*/
|
|
103
|
+
export interface ConditionalRuleOperator {
|
|
104
|
+
id: string;
|
|
105
|
+
name: string;
|
|
106
|
+
nameDictionaryId: number;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Tipos del contrato API - ConditionalRule
|
|
110
|
+
*/
|
|
111
|
+
export interface ConditionalRule {
|
|
112
|
+
id: string;
|
|
113
|
+
operator: ConditionalRuleOperator;
|
|
114
|
+
isActive: boolean;
|
|
115
|
+
actionType: 'show' | 'hide';
|
|
116
|
+
displayOrder: number;
|
|
117
|
+
conditionValue: string;
|
|
118
|
+
sourceFieldId: number;
|
|
119
|
+
targetFieldId: number;
|
|
120
|
+
sourceFieldName: string;
|
|
121
|
+
targetFieldName: string;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Tipos del contrato API - FormInstance
|
|
125
|
+
*/
|
|
126
|
+
export interface FormInstance {
|
|
127
|
+
id: number;
|
|
128
|
+
name: string | null;
|
|
129
|
+
createdAt: string;
|
|
130
|
+
updatedAt: string;
|
|
131
|
+
resourceTypeId: string;
|
|
132
|
+
resourceSerialId: string;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Tipos del contrato API - DynamicFormApiResponse
|
|
136
|
+
*/
|
|
137
|
+
export interface DynamicFormApiResponse {
|
|
138
|
+
form: FormMetadata;
|
|
139
|
+
fields: Field[];
|
|
140
|
+
instance: FormInstance;
|
|
141
|
+
conditionalRules: ConditionalRule[];
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Propiedades del componente DynamicForm.
|
|
145
|
+
*/
|
|
146
|
+
export interface DynamicFormProps {
|
|
147
|
+
/**
|
|
148
|
+
* ID del formulario.
|
|
149
|
+
*/
|
|
150
|
+
idForm?: number;
|
|
151
|
+
/**
|
|
152
|
+
* ID de la instancia del formulario.
|
|
153
|
+
*/
|
|
154
|
+
idFormInstance?: number;
|
|
155
|
+
/**
|
|
156
|
+
* Endpoint de entrada.
|
|
157
|
+
*/
|
|
158
|
+
inputEndpoint?: string;
|
|
159
|
+
/**
|
|
160
|
+
* Endpoint de salida.
|
|
161
|
+
*/
|
|
162
|
+
outputEndpoint?: string;
|
|
163
|
+
/**
|
|
164
|
+
* Datos iniciales del formulario. Si se proporciona, se usarán en lugar de obtenerlos del endpoint.
|
|
165
|
+
*/
|
|
166
|
+
data?: DynamicFormApiResponse | null;
|
|
167
|
+
/**
|
|
168
|
+
* Función que se ejecuta para formatear los datos de entrada.
|
|
169
|
+
*/
|
|
170
|
+
formatInputData?: (data: Record<string, unknown>) => Record<string, unknown>;
|
|
171
|
+
/**
|
|
172
|
+
* Función que se ejecuta para formatear los datos de salida.
|
|
173
|
+
*/
|
|
174
|
+
formatOutputData?: (data: Record<string, unknown>) => Record<string, unknown>;
|
|
175
|
+
/**
|
|
176
|
+
* Función que se ejecuta al enviar el formulario con los datos validados.
|
|
177
|
+
*/
|
|
178
|
+
onSubmit: (data: Record<string, unknown>) => void | Promise<void>;
|
|
179
|
+
/**
|
|
180
|
+
* Función que se ejecuta cuando hay un error en la validación del formulario.
|
|
181
|
+
*/
|
|
182
|
+
onSubmitError?: (errors: Record<string, unknown>) => void;
|
|
183
|
+
/**
|
|
184
|
+
* Tamaño del componente.
|
|
185
|
+
*/
|
|
186
|
+
size?: Extract<Sizes, 'small' | 'medium'>;
|
|
187
|
+
/**
|
|
188
|
+
* Clase CSS adicional.
|
|
189
|
+
*/
|
|
190
|
+
className?: string;
|
|
191
|
+
/**
|
|
192
|
+
* ID para testing.
|
|
193
|
+
*/
|
|
194
|
+
dataTestId?: string;
|
|
195
|
+
/**
|
|
196
|
+
* Clase CSS adicional para el wrapper de cada campo.
|
|
197
|
+
*/
|
|
198
|
+
fieldWrapperClassName?: string;
|
|
199
|
+
/**
|
|
200
|
+
* Si el formulario está acoplado (coupled=true), se expone como un campo de React Hook Form mediante Controller.
|
|
201
|
+
* Si está desacoplado (coupled=false), maneja el submit internamente con RHFormProvider.
|
|
202
|
+
* Por defecto es false (modo desacoplado con RHFormProvider interno).
|
|
203
|
+
*/
|
|
204
|
+
coupled?: boolean;
|
|
205
|
+
/**
|
|
206
|
+
* Nombre del campo cuando el formulario está acoplado (coupled=true).
|
|
207
|
+
* Se usa para suscribir el DynamicForm a React Hook Form a través del Controller.
|
|
208
|
+
* Requerido cuando coupled es true.
|
|
209
|
+
*/
|
|
210
|
+
name?: string;
|
|
211
|
+
/**
|
|
212
|
+
* Props para personalizar el ActionFormIntro.
|
|
213
|
+
* Solo se usa cuando coupled es false (modo desacoplado).
|
|
214
|
+
* Si no se proporciona, se usan los valores por defecto.
|
|
215
|
+
*/
|
|
216
|
+
actionFormIntroProps?: Partial<ActionsFormIntroProps>;
|
|
217
|
+
/**
|
|
218
|
+
* Renderizado personalizado para las acciones del formulario.
|
|
219
|
+
* Solo se usa cuando coupled es false (modo desacoplado).
|
|
220
|
+
* Si se proporciona, reemplaza el ActionsContainer y ActionFormIntro por defecto.
|
|
221
|
+
*/
|
|
222
|
+
renderActions?: () => ReactNode;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Owner state del componente usado para definir propiedades internas de estilo y comportamiento.
|
|
226
|
+
*/
|
|
227
|
+
export interface DynamicFormOwnerState extends Pick<DynamicFormProps, 'size'> {
|
|
228
|
+
[key: string]: unknown;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Define los tipos de Slots disponibles para el componente.
|
|
232
|
+
*/
|
|
233
|
+
export type DynamicFormSlotsType = keyof typeof DynamicFormSlots;
|
|
234
|
+
/**
|
|
235
|
+
* Estilos aplicables al componente usando temas y slots personalizados.
|
|
236
|
+
*/
|
|
237
|
+
export type DynamicFormStyles = M4LOverridesStyleRules<DynamicFormSlotsType, typeof DYNAMIC_FORM_KEY_COMPONENT, Theme>;
|
|
238
|
+
/**
|
|
239
|
+
* Tipo para los valores del formulario dinámico.
|
|
240
|
+
*/
|
|
241
|
+
export type DynamicFormValues = RHFormValues & Record<string, unknown>;
|
|
242
|
+
/**
|
|
243
|
+
* Tipo para el valor que se expone cuando el DynamicForm está acoplado (coupled=true).
|
|
244
|
+
* Contiene los valores de los campos y el estado de validación interno.
|
|
245
|
+
*/
|
|
246
|
+
export interface DynamicFormFieldsValue {
|
|
247
|
+
[fieldName: string]: unknown;
|
|
248
|
+
isDynamicFormValidInternal: boolean;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Tipo que define los métodos expuestos a través de la ref del DynamicForm.
|
|
252
|
+
* Expone la API de RHFormProvider para acceso desde el componente padre.
|
|
253
|
+
*/
|
|
254
|
+
export type DynamicFormRef = RHFormProviderRef<DynamicFormValues>;
|
|
255
|
+
/**
|
|
256
|
+
* Props del componente DynamicFormCoupled.
|
|
257
|
+
* Se usa cuando coupled=true y el formulario debe exponerse como un campo de React Hook Form mediante Controller.
|
|
258
|
+
*/
|
|
259
|
+
export interface DynamicFormCoupledProps {
|
|
260
|
+
name: string;
|
|
261
|
+
value: DynamicFormApiResponse;
|
|
262
|
+
initialValues: DynamicFormValues;
|
|
263
|
+
validationSchema: any;
|
|
264
|
+
ownerState: DynamicFormOwnerState;
|
|
265
|
+
currentSize: 'small' | 'medium';
|
|
266
|
+
fieldWrapperClassName?: string;
|
|
267
|
+
dataTestId?: string;
|
|
268
|
+
className?: string;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Props del componente interno que maneja el formulario acoplado.
|
|
272
|
+
* El formulario interno funciona independientemente y expone sus valores a través del Controller.
|
|
273
|
+
*/
|
|
274
|
+
export interface DynamicFormCoupledInternalProps {
|
|
275
|
+
value: DynamicFormApiResponse;
|
|
276
|
+
initialValues: DynamicFormValues;
|
|
277
|
+
validationSchema: any;
|
|
278
|
+
ownerState: DynamicFormOwnerState;
|
|
279
|
+
currentSize: 'small' | 'medium';
|
|
280
|
+
fieldWrapperClassName?: string;
|
|
281
|
+
dataTestId?: string;
|
|
282
|
+
className?: string;
|
|
283
|
+
onChange: (value: DynamicFormFieldsValue) => void;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Props del componente interno que valida y notifica cambios solo en campos visibles.
|
|
287
|
+
* Se usa cuando coupled=true.
|
|
288
|
+
*/
|
|
289
|
+
export interface DynamicFormCoupledInternalContentProps {
|
|
290
|
+
value: DynamicFormApiResponse;
|
|
291
|
+
ownerState: DynamicFormOwnerState;
|
|
292
|
+
currentSize: 'small' | 'medium';
|
|
293
|
+
fieldWrapperClassName?: string;
|
|
294
|
+
dataTestId?: string;
|
|
295
|
+
className?: string;
|
|
296
|
+
onChange: (value: DynamicFormFieldsValue) => void;
|
|
297
|
+
lastSentValueRef: MutableRefObject<string | null>;
|
|
298
|
+
internalFormMethods: ReturnType<typeof useForm<DynamicFormValues>>;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Props del componente interno que renderiza los campos del formulario.
|
|
302
|
+
* Debe estar dentro del contexto de RHFormProvider para acceder a useFormContext.
|
|
303
|
+
*/
|
|
304
|
+
export interface DynamicFormContentProps {
|
|
305
|
+
data: DynamicFormApiResponse;
|
|
306
|
+
ownerState: DynamicFormOwnerState;
|
|
307
|
+
currentSize: 'small' | 'medium';
|
|
308
|
+
fieldWrapperClassName?: string;
|
|
309
|
+
dataTestId?: string;
|
|
310
|
+
coupled?: boolean;
|
|
311
|
+
actionFormIntroProps?: Partial<DynamicFormProps['actionFormIntroProps']>;
|
|
312
|
+
renderActions?: DynamicFormProps['renderActions'];
|
|
313
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -15,7 +15,7 @@ function useMultipleChips(props) {
|
|
|
15
15
|
getOptionStartAdornment,
|
|
16
16
|
getOptionEndAdornment
|
|
17
17
|
} = props;
|
|
18
|
-
const
|
|
18
|
+
const externalStartAdornment = useMemo(() => {
|
|
19
19
|
if (!startAdornment) {
|
|
20
20
|
return null;
|
|
21
21
|
}
|
|
@@ -53,7 +53,7 @@ function useMultipleChips(props) {
|
|
|
53
53
|
getOptionEndAdornment,
|
|
54
54
|
adjustedSize
|
|
55
55
|
]);
|
|
56
|
-
const
|
|
56
|
+
const selectedOptionStartAdornment = useMemo(() => {
|
|
57
57
|
if (multiple || !selectedValue || Array.isArray(selectedValue) && selectedValue.length === 0) {
|
|
58
58
|
return null;
|
|
59
59
|
}
|
|
@@ -69,7 +69,7 @@ function useMultipleChips(props) {
|
|
|
69
69
|
getOptionStartAdornment,
|
|
70
70
|
adjustedSize
|
|
71
71
|
]);
|
|
72
|
-
const
|
|
72
|
+
const multipleSelectionChips = useMemo(() => {
|
|
73
73
|
if (!(Array.isArray(selectedValue) && multiple && selectedValue.length > 0)) {
|
|
74
74
|
return null;
|
|
75
75
|
}
|
|
@@ -100,18 +100,21 @@ function useMultipleChips(props) {
|
|
|
100
100
|
ownerState,
|
|
101
101
|
memoizedIcons
|
|
102
102
|
]);
|
|
103
|
-
if (
|
|
103
|
+
if (externalStartAdornment && multipleSelectionChips) {
|
|
104
104
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
105
|
-
/* @__PURE__ */ jsx(WrapperStartAdornmentStyled, { role: "img", "aria-hidden": "true", ownerState, children:
|
|
106
|
-
|
|
105
|
+
/* @__PURE__ */ jsx(WrapperStartAdornmentStyled, { role: "img", "aria-hidden": "true", ownerState, children: externalStartAdornment }),
|
|
106
|
+
multipleSelectionChips
|
|
107
107
|
] });
|
|
108
108
|
}
|
|
109
|
-
if (
|
|
109
|
+
if (externalStartAdornment) {
|
|
110
110
|
return /* @__PURE__ */ jsxs(WrapperStartAdornmentStyled, { role: "img", "aria-hidden": "true", ownerState, children: [
|
|
111
|
-
|
|
112
|
-
!multiple &&
|
|
111
|
+
externalStartAdornment,
|
|
112
|
+
!multiple && selectedOptionStartAdornment
|
|
113
113
|
] });
|
|
114
114
|
}
|
|
115
|
+
if (!multiple && selectedOptionStartAdornment && !externalStartAdornment) {
|
|
116
|
+
return /* @__PURE__ */ jsx(WrapperStartAdornmentStyled, { role: "img", "aria-hidden": "true", ownerState, children: selectedOptionStartAdornment });
|
|
117
|
+
}
|
|
115
118
|
if (!getOptionLabelLocal) {
|
|
116
119
|
console.error("useStartAdornments: getOptionLabelLocal is required");
|
|
117
120
|
return null;
|
|
@@ -120,7 +123,7 @@ function useMultipleChips(props) {
|
|
|
120
123
|
console.error("useStartAdornments: handleDelete is required");
|
|
121
124
|
return null;
|
|
122
125
|
}
|
|
123
|
-
return
|
|
126
|
+
return multipleSelectionChips;
|
|
124
127
|
}
|
|
125
128
|
export {
|
|
126
129
|
useMultipleChips as u
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -126,11 +126,6 @@ function useValuesAndHandlers(props) {
|
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
}, [readOnly, value, getOptionLabelLocal, multiple, inputValue]);
|
|
129
|
-
useEffect(() => {
|
|
130
|
-
if (open === false && value === null && inputValue !== "") {
|
|
131
|
-
setInputValue("");
|
|
132
|
-
}
|
|
133
|
-
}, [value, open, inputValue]);
|
|
134
129
|
const checkKeyDown = (e) => {
|
|
135
130
|
if (e.code === "Enter") {
|
|
136
131
|
e.preventDefault();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/components/extended/mui/Autocomplete/subcomponents/NoOptionsText/NoOptionsText.test.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/components/extended/mui/Autocomplete/subcomponents/PopperComponent/PopperComponent.test.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/components/extended/mui/Autocomplete/subcomponents/RenderAdornment/RenderAdornment.test.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/components/extended/mui/Autocomplete/subcomponents/renderOptions/renderOptions.test.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|