@m4l/components 9.2.52 → 9.2.54-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 (55) hide show
  1. package/.storybook/utils/getStylesColorsByMode.d.ts +4 -4
  2. package/components/Chip/Chip.js +3 -1
  3. package/components/Chip/types.d.ts +4 -0
  4. package/components/DataGrid/constants.d.ts +21 -0
  5. package/components/DataGrid/constants.js +24 -1
  6. package/components/DataGrid/index.d.ts +1 -0
  7. package/components/DataGrid/subcomponents/Table/subcomponents/ActionsColumn.js +2 -2
  8. package/components/DynamicFilter/subcomponents/FieldTypes/DateTimeFilter/helpers.js +3 -2
  9. package/components/DynamicFilter/types.d.ts +2 -2
  10. package/components/ObjectLogs/subcomponents/ObjectLogsByOthers/ObjectLogsByOthers.js +1 -1
  11. package/components/hook-form/RHFAutocomplete/RHFAutocomplete.js +30 -19
  12. package/components/hook-form/RHFAutocomplete/tests/common.d.ts +37 -0
  13. package/components/hook-form/RHFAutocomplete/types.d.ts +3 -8
  14. package/components/hook-form/RHFAutocompleteAsync/RHFAutocompleteAsync.d.ts +32 -5
  15. package/components/hook-form/RHFAutocompleteAsync/RHFAutocompleteAsync.js +49 -84
  16. package/components/hook-form/RHFAutocompleteAsync/RHFAutocompleteAsyncStyles.d.ts +2 -2
  17. package/components/hook-form/RHFAutocompleteAsync/hooks/useFetchOptions.d.ts +5 -0
  18. package/components/hook-form/RHFAutocompleteAsync/hooks/useFetchOptions.js +64 -0
  19. package/components/hook-form/RHFAutocompleteAsync/reducer/RHFAutocompleteReducer.d.ts +14 -0
  20. package/components/hook-form/RHFAutocompleteAsync/reducer/RHFAutocompleteReducer.js +74 -0
  21. package/components/hook-form/RHFAutocompleteAsync/slots/RHFAutocompleteSlotsAsync.d.ts +1 -1
  22. package/components/hook-form/RHFAutocompleteAsync/tests/OnChangFilterParmsDefined.test.d.ts +1 -0
  23. package/components/hook-form/RHFAutocompleteAsync/tests/OnChangFilterParmsUndefined.test.d.ts +1 -0
  24. package/components/hook-form/RHFAutocompleteAsync/tests/RHFAutocompleteReducer.test.d.ts +1 -0
  25. package/components/hook-form/RHFAutocompleteAsync/tests/common.d.ts +41 -0
  26. package/components/hook-form/RHFAutocompleteAsync/types.d.ts +120 -4
  27. package/components/hook-form/RHFAutocompleteAsync/types.js +44 -0
  28. package/components/hook-form/RHFTextField/RHFTextField.js +3 -2
  29. package/components/mui_extended/Autocomplete/Autocomplete.d.ts +7 -0
  30. package/components/mui_extended/Autocomplete/Autocomplete.js +68 -196
  31. package/components/mui_extended/Autocomplete/Autocomplete.styles.js +27 -16
  32. package/components/mui_extended/Autocomplete/hooks/useEndAdornments.d.ts +14 -0
  33. package/components/mui_extended/Autocomplete/hooks/useEndAdornments.js +47 -0
  34. package/components/mui_extended/Autocomplete/hooks/useStartAdornments.d.ts +21 -0
  35. package/components/mui_extended/Autocomplete/hooks/useStartAdornments.js +31 -0
  36. package/components/mui_extended/Autocomplete/hooks/useValuesAndHandlers.d.ts +23 -0
  37. package/components/mui_extended/Autocomplete/hooks/useValuesAndHandlers.js +135 -0
  38. package/components/mui_extended/Autocomplete/icons.d.ts +4 -0
  39. package/components/mui_extended/Autocomplete/icons.js +7 -0
  40. package/components/mui_extended/Autocomplete/renderOptions/index.d.ts +7 -2
  41. package/components/mui_extended/Autocomplete/renderOptions/index.js +7 -6
  42. package/components/mui_extended/Autocomplete/slots/AutocompleteSlots.js +6 -7
  43. package/components/mui_extended/Autocomplete/types.d.ts +2 -0
  44. package/hooks/useDynamicFilterAndSort/useDynamicFilterAndSort.js +13 -10
  45. package/index.js +8 -6
  46. package/mockServiceWorker.js +1 -1
  47. package/package.json +3 -3
  48. package/storybook/components/extended/mui/Autocomplete/AutoComple.stories.d.ts +1 -0
  49. package/storybook/hook-form/RHFAutocomplete/RHFAutocomplete.stories.d.ts +8 -6
  50. package/storybook/hook-form/RHFAutocomplete/constants.d.ts +23 -0
  51. package/storybook/hook-form/RHFAutocompleteAsync/RHFAutocompleteAsync.stories.d.ts +11 -4
  52. package/storybook/hook-form/RHFAutocompleteAsync/constants.d.ts +10 -1
  53. package/storybook/hook-form/RHFAutocompleteAsync/handlers.d.ts +1 -0
  54. package/components/hook-form/RHFAutocomplete/oldTypes.d.ts +0 -43
  55. /package/components/hook-form/RHFAutocomplete/{RHFAutocomplete.test.d.ts → tests/RHFAutocomplete.test.d.ts} +0 -0
@@ -55,7 +55,7 @@ export declare const colorsLight: {
55
55
  readonly backdrop: string;
56
56
  readonly base: string;
57
57
  readonly blur: string;
58
- readonly paper: "#000";
58
+ readonly paper: "#fff";
59
59
  };
60
60
  readonly chips: {
61
61
  readonly error: Record<import('@m4l/styles').ChipColorVariant, import('@m4l/styles').ChipColor>;
@@ -288,7 +288,7 @@ export declare const colorsLight: {
288
288
  readonly border: {
289
289
  readonly main: string;
290
290
  readonly dens: string;
291
- readonly default: string | undefined;
291
+ readonly default: string;
292
292
  readonly secondary: string;
293
293
  readonly disabled: string;
294
294
  readonly error: string;
@@ -440,7 +440,7 @@ export declare const colorsDark: {
440
440
  readonly backdrop: string;
441
441
  readonly base: string;
442
442
  readonly blur: string;
443
- readonly paper: "#000";
443
+ readonly paper: "#fff";
444
444
  };
445
445
  readonly chips: {
446
446
  readonly error: Record<import('@m4l/styles').ChipColorVariant, import('@m4l/styles').ChipColor>;
@@ -673,7 +673,7 @@ export declare const colorsDark: {
673
673
  readonly border: {
674
674
  readonly main: string;
675
675
  readonly dens: string;
676
- readonly default: string | undefined;
676
+ readonly default: string;
677
677
  readonly secondary: string;
678
678
  readonly disabled: string;
679
679
  readonly error: string;
@@ -22,6 +22,7 @@ const Chip = forwardRef((props, ref) => {
22
22
  iconButtonProps,
23
23
  className,
24
24
  dataTestId,
25
+ disabledDeleteButton,
25
26
  ...others
26
27
  } = props;
27
28
  const { currentSize } = useComponentSize(size);
@@ -93,7 +94,8 @@ const Chip = forwardRef((props, ref) => {
93
94
  src: iconClose,
94
95
  size: adjustedSize,
95
96
  ownerState: { ...ownerState },
96
- onClick: handleDelete
97
+ onClick: handleDelete,
98
+ disabled: disabledDeleteButton
97
99
  }
98
100
  )
99
101
  ]
@@ -74,6 +74,10 @@ export interface ChipProps {
74
74
  * Test id for the `Chip`.
75
75
  */
76
76
  dataTestId?: string;
77
+ /**
78
+ * If the `Chip` delete button is disabled.
79
+ */
80
+ disabledDeleteButton?: boolean;
77
81
  }
78
82
  /**
79
83
  * Owner state of the `Chip` used to define internal style and behavior properties.
@@ -1,3 +1,24 @@
1
1
  export declare const DATAGRID_PREFIX_NAME = "M4LDataGrid";
2
2
  export declare const DATAGRID_SELECT_COLUMN_KEY = "M4LDataGrid-CheckedColumn";
3
3
  export declare const DATAGRID_ACTIONS_COLUMN_KEY = "M4LDataGrid-ActionsColumn";
4
+ export declare enum DATAGRID_SEMANTIC_WIDTHS {
5
+ actions = 40,
6
+ bigChip = 190,
7
+ bigDescription = 350,
8
+ bigId = 200,
9
+ bigName = 290,
10
+ bigNumber = 150,
11
+ date = 180,
12
+ email = 300,
13
+ mediumChip = 140,
14
+ mediumDescription = 280,
15
+ mediumId = 130,
16
+ mediumName = 180,
17
+ mediumNumber = 150,
18
+ percentNumber = 90,
19
+ smallChip = 70,
20
+ smallDescription = 130,
21
+ smallId = 50,
22
+ smallName = 90,
23
+ smallNumber = 60
24
+ }
@@ -1,8 +1,31 @@
1
1
  const DATAGRID_PREFIX_NAME = "M4LDataGrid";
2
2
  const DATAGRID_SELECT_COLUMN_KEY = "M4LDataGrid-CheckedColumn";
3
3
  const DATAGRID_ACTIONS_COLUMN_KEY = "M4LDataGrid-ActionsColumn";
4
+ var DATAGRID_SEMANTIC_WIDTHS = /* @__PURE__ */ ((DATAGRID_SEMANTIC_WIDTHS2) => {
5
+ DATAGRID_SEMANTIC_WIDTHS2[DATAGRID_SEMANTIC_WIDTHS2["actions"] = 40] = "actions";
6
+ DATAGRID_SEMANTIC_WIDTHS2[DATAGRID_SEMANTIC_WIDTHS2["bigChip"] = 190] = "bigChip";
7
+ DATAGRID_SEMANTIC_WIDTHS2[DATAGRID_SEMANTIC_WIDTHS2["bigDescription"] = 350] = "bigDescription";
8
+ DATAGRID_SEMANTIC_WIDTHS2[DATAGRID_SEMANTIC_WIDTHS2["bigId"] = 200] = "bigId";
9
+ DATAGRID_SEMANTIC_WIDTHS2[DATAGRID_SEMANTIC_WIDTHS2["bigName"] = 290] = "bigName";
10
+ DATAGRID_SEMANTIC_WIDTHS2[DATAGRID_SEMANTIC_WIDTHS2["bigNumber"] = 150] = "bigNumber";
11
+ DATAGRID_SEMANTIC_WIDTHS2[DATAGRID_SEMANTIC_WIDTHS2["date"] = 180] = "date";
12
+ DATAGRID_SEMANTIC_WIDTHS2[DATAGRID_SEMANTIC_WIDTHS2["email"] = 300] = "email";
13
+ DATAGRID_SEMANTIC_WIDTHS2[DATAGRID_SEMANTIC_WIDTHS2["mediumChip"] = 140] = "mediumChip";
14
+ DATAGRID_SEMANTIC_WIDTHS2[DATAGRID_SEMANTIC_WIDTHS2["mediumDescription"] = 280] = "mediumDescription";
15
+ DATAGRID_SEMANTIC_WIDTHS2[DATAGRID_SEMANTIC_WIDTHS2["mediumId"] = 130] = "mediumId";
16
+ DATAGRID_SEMANTIC_WIDTHS2[DATAGRID_SEMANTIC_WIDTHS2["mediumName"] = 180] = "mediumName";
17
+ DATAGRID_SEMANTIC_WIDTHS2[DATAGRID_SEMANTIC_WIDTHS2["mediumNumber"] = 150] = "mediumNumber";
18
+ DATAGRID_SEMANTIC_WIDTHS2[DATAGRID_SEMANTIC_WIDTHS2["percentNumber"] = 90] = "percentNumber";
19
+ DATAGRID_SEMANTIC_WIDTHS2[DATAGRID_SEMANTIC_WIDTHS2["smallChip"] = 70] = "smallChip";
20
+ DATAGRID_SEMANTIC_WIDTHS2[DATAGRID_SEMANTIC_WIDTHS2["smallDescription"] = 130] = "smallDescription";
21
+ DATAGRID_SEMANTIC_WIDTHS2[DATAGRID_SEMANTIC_WIDTHS2["smallId"] = 50] = "smallId";
22
+ DATAGRID_SEMANTIC_WIDTHS2[DATAGRID_SEMANTIC_WIDTHS2["smallName"] = 90] = "smallName";
23
+ DATAGRID_SEMANTIC_WIDTHS2[DATAGRID_SEMANTIC_WIDTHS2["smallNumber"] = 60] = "smallNumber";
24
+ return DATAGRID_SEMANTIC_WIDTHS2;
25
+ })(DATAGRID_SEMANTIC_WIDTHS || {});
4
26
  export {
5
27
  DATAGRID_PREFIX_NAME as D,
6
28
  DATAGRID_SELECT_COLUMN_KEY as a,
7
- DATAGRID_ACTIONS_COLUMN_KEY as b
29
+ DATAGRID_ACTIONS_COLUMN_KEY as b,
30
+ DATAGRID_SEMANTIC_WIDTHS as c
8
31
  };
@@ -6,3 +6,4 @@ export { getDataGridComponentsDictionary } from './dictionary';
6
6
  export { TextEditor, NumberEditor } from './subcomponents/editors/TextEditor';
7
7
  export { getDataGridRowsFromSet } from './utils/getDataGridRowsFromSet';
8
8
  export type { IGridConfig, BaseConfigColumn } from './contexts/DataGridContext/types';
9
+ export { DATAGRID_SEMANTIC_WIDTHS } from './constants';
@@ -1,7 +1,7 @@
1
1
  import { jsx, Fragment } from "react/jsx-runtime";
2
2
  import { u as useDataGrid } from "../../../hooks/useDataGrid.js";
3
3
  import { useTheme } from "@mui/material";
4
- import { b as DATAGRID_ACTIONS_COLUMN_KEY } from "../../../constants.js";
4
+ import { b as DATAGRID_ACTIONS_COLUMN_KEY, c as DATAGRID_SEMANTIC_WIDTHS } from "../../../constants.js";
5
5
  import { M as MenuActions } from "../../../../MenuActions/MenuActions.js";
6
6
  function ActionsFormatter(props) {
7
7
  const { rowActionsGetter } = useDataGrid();
@@ -27,7 +27,7 @@ const ActionsColumn = {
27
27
  key: DATAGRID_ACTIONS_COLUMN_KEY,
28
28
  // name: getLabel(dictionary.LABEL_ACTIONS),
29
29
  name: getActionLabel(),
30
- width: 32,
30
+ width: DATAGRID_SEMANTIC_WIDTHS.actions,
31
31
  minWidth: 32,
32
32
  isDraggable: false,
33
33
  withFilter: false,
@@ -2,6 +2,7 @@ import * as Yup from "yup";
2
2
  import { b as DATE_TIME_OPERATORS } from "../../../constants.js";
3
3
  import { D as DYNAMIC_FILTER_DICTIONARY_ID, a as DICCTIONARY } from "../../../dictionary.js";
4
4
  import { D as DateTimeFilter } from "./index.js";
5
+ import { startOfDay, endOfDay } from "date-fns";
5
6
  import { i as isValidDate } from "../../../../../utils/isValidDate.js";
6
7
  class DateTimeFilterHelpers {
7
8
  getComponent() {
@@ -34,8 +35,8 @@ class DateTimeFilterHelpers {
34
35
  getFormValue(field, getLabel, filterValueDateTime) {
35
36
  const filterValue = filterValueDateTime;
36
37
  const operator = filterValue ? filterValue.operator : field.defaultOperator ?? "b";
37
- const defaultStartDate = /* @__PURE__ */ new Date();
38
- const defaultEndDate = /* @__PURE__ */ new Date();
38
+ const defaultStartDate = startOfDay(/* @__PURE__ */ new Date());
39
+ const defaultEndDate = endOfDay(/* @__PURE__ */ new Date());
39
40
  const defaultOperand1 = field.defaultOperand1 && field.defaultOperand1 instanceof Date ? field.defaultOperand1 : defaultStartDate;
40
41
  const defaultOperand2 = field.defaultOperand2 && field.defaultOperand2 instanceof Date ? field.defaultOperand2 : defaultEndDate;
41
42
  const formValueOperand1 = filterValue ? filterValue.operand1 : defaultOperand1;
@@ -2,7 +2,7 @@ import { Maybe } from '@m4l/core';
2
2
  import { Sizes } from '@m4l/styles';
3
3
  import { Theme } from '@mui/material/styles';
4
4
  import { M4LOverridesStyleRules } from '../../@types/augmentations';
5
- import { RHFAutocompleteAsyncBaseProps } from '../hook-form/RHFAutocompleteAsync/types';
5
+ import { RHFAutocompleteAsyncProps } from '../hook-form/RHFAutocompleteAsync/types';
6
6
  import { RHFSelectProps } from '../hook-form/RHFSelect';
7
7
  import { DynamicFilterSlots } from './slots';
8
8
  export type FieldType = 'number' | 'string' | 'boolean' | 'datetime' | 'select' | 'selectAsync';
@@ -27,7 +27,7 @@ export type OperandsSelectArray = Array<OperandSelect>;
27
27
  export type FieldTypeOperator<T extends FieldType> = T extends 'boolean' ? BooleanOperator : T extends 'datetime' ? DateTimeOperator : T extends 'number' ? NumberOperator : T extends 'select' ? SelectOperator : T extends 'selectAsync' ? SelectOperatorAsync : T extends 'string' ? StringOperator : T;
28
28
  export type FieldTypeOperand<T extends FieldType> = T extends 'boolean' ? boolean : T extends 'datetime' ? Date : T extends 'number' ? number : T extends 'string' ? string : T extends 'select' ? OperandSelect : T extends 'selectAsync' ? OperandSelectAsync : FieldType;
29
29
  export type FieldTypeOperandsArray<T extends FieldType> = T extends 'boolean' ? never : T extends 'datetime' ? never : T extends 'number' ? never : T extends 'string' ? never : T extends 'select' ? OperandsSelectArray : T extends 'selectAsync' ? OperandsArraySelectAsync : never;
30
- type SelectAsyncOptions<TOption = any> = Pick<RHFAutocompleteAsyncBaseProps<TOption>, 'type' | 'endPoint' | 'responseToCamelCase' | 'multiple' | 'autoComplete' | 'autoCapitalize' | 'parms' | 'timeout'> & {
30
+ type SelectAsyncOptions<TOption = any> = Pick<RHFAutocompleteAsyncProps<TOption>, 'type' | 'endPoint' | 'responseToCamelCase' | 'multiple' | 'autoComplete' | 'autoCapitalize' | 'parms' | 'timeout'> & {
31
31
  getOptionLabel: (option: TOption) => string;
32
32
  isOptionEqualToValue: (options: TOption | TOption[], value: TOption) => boolean;
33
33
  getOptionId: (option: TOption) => string | number;
@@ -125,7 +125,7 @@ function ObjectLogsByOthers(props) {
125
125
  columns,
126
126
  rows,
127
127
  rowKeyGetter: (row) => row.id,
128
- withActions: false,
128
+ withActions: true,
129
129
  actionsProps: {}
130
130
  },
131
131
  "users_list_logs"
@@ -2,7 +2,7 @@ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import { getPropertyByString } from "@m4l/core";
3
3
  import { useIsMobile } from "@m4l/graphics";
4
4
  import { useTheme } from "@mui/material";
5
- import { useState, useEffect } from "react";
5
+ import { useId, useState, useCallback, useEffect } from "react";
6
6
  import { useFormContext, Controller } from "react-hook-form";
7
7
  import { A as AutocompleteRootStyled, L as LabelStyled } from "./slots/RHFAutocompleteSlots.js";
8
8
  import { A as Autocomplete } from "../../mui_extended/Autocomplete/Autocomplete.js";
@@ -29,28 +29,36 @@ function RHFAutocomplete(props) {
29
29
  imageScale = true,
30
30
  imageRepeat,
31
31
  refresh
32
+ // onChange: onChangeRHF,
32
33
  } = props;
34
+ const htmlForId = useId();
33
35
  const theme = useTheme();
34
36
  const [open, setOpen] = useState(false);
35
37
  const isDesktop = !useIsMobile();
36
- const onCloseLocal = (event, reason) => {
38
+ const onCloseLocal = useCallback((event, reason) => {
37
39
  setOpen(false);
38
40
  if (onClose) {
39
41
  onClose(event, reason);
40
42
  }
41
- };
42
- const onOpenLocal = (event) => {
43
- setOpen((currentState) => !currentState);
44
- if (onOpen) {
45
- onOpen(event);
46
- }
47
- };
48
- const getOptionLabelLocal = (option) => {
49
- if (option === void 0 || option === null) {
50
- return "";
51
- }
52
- return getOptionLabel(option);
53
- };
43
+ }, [onClose]);
44
+ const onOpenLocal = useCallback(
45
+ (event) => {
46
+ setOpen((currentState) => !currentState);
47
+ if (onOpen) {
48
+ onOpen(event);
49
+ }
50
+ },
51
+ [onOpen]
52
+ );
53
+ const getOptionLabelLocal = useCallback(
54
+ (option) => {
55
+ if (option === void 0 || option === null) {
56
+ return "";
57
+ }
58
+ return getOptionLabel(option);
59
+ },
60
+ [getOptionLabel]
61
+ );
54
62
  const paletteColor = getPropertyByString(
55
63
  theme.vars.palette,
56
64
  disabled ? "default" : color || "default",
@@ -108,11 +116,11 @@ function RHFAutocomplete(props) {
108
116
  {
109
117
  ownerState: { ...ownerState },
110
118
  label,
119
+ htmlFor: htmlForId,
111
120
  size,
112
121
  mandatory,
113
122
  mandatoryMessage,
114
123
  helperMessage,
115
- htmlFor: `autocomplete-${nameRHF}`,
116
124
  disabled
117
125
  }
118
126
  ),
@@ -124,8 +132,10 @@ function RHFAutocomplete(props) {
124
132
  options,
125
133
  getOptionLabel,
126
134
  isOptionEqualToValue,
127
- multiple: multiple ? true : void 0,
128
- onChange: (_e, newValue) => onChange(newValue),
135
+ multiple,
136
+ onChange: (_event, newValue, _reason) => {
137
+ onChange(newValue);
138
+ },
129
139
  onChangeFilterParmsLocal,
130
140
  refresh,
131
141
  disabled,
@@ -133,7 +143,8 @@ function RHFAutocomplete(props) {
133
143
  onOpen: onOpenLocal,
134
144
  onClose: onCloseLocal,
135
145
  size,
136
- value
146
+ value,
147
+ htmlFor: htmlForId
137
148
  }
138
149
  ),
139
150
  currentVariant === "error" ? /* @__PURE__ */ jsx(HelperError, { message: error?.message }) : null
@@ -0,0 +1,37 @@
1
+ import { renderMaterialUI } from '../../../../test';
2
+ import { FieldValues } from 'react-hook-form';
3
+ import { RHFAutocompleteProps } from '../types';
4
+ import * as Yup from 'yup';
5
+ export declare const FIELD_NAME = "rhf-autocomplete";
6
+ export declare const FIELD_NAME_REQUIRED = "rhf-autocomplete-required";
7
+ export declare const FIELD_NAME_PRESELECTED = "rhf-autocomplete-preselected";
8
+ export declare const FIELD_NAME_PRESELECTED_NOT_IN_OPTIONS = "rhf-autocomplete-preselected-not-in-options";
9
+ export declare const FIELD_NAME_PRESELECTED_MULTIPLE = "rhf-autocomplete-preselected-multiple";
10
+ export declare const FIELD_NAME_PRESELECTED_MULTIPLE_NOT_IN_OPTIONS = "rhf-autocomplete-preselected-multiple-not-in-options";
11
+ export interface OptionsTests {
12
+ id: number;
13
+ name: string;
14
+ }
15
+ export declare const mockItems: OptionsTests[];
16
+ export declare const mockItemPreselected: OptionsTests;
17
+ export declare const mockItemPreselectedMultiple: OptionsTests[];
18
+ export declare const mockItemPreselectedNotInOptions: OptionsTests;
19
+ export declare const mockItemPreselectedMultipleNotInOptions: OptionsTests[];
20
+ export declare const INITIAL_FORM_VALUES: FieldValues;
21
+ export declare const DEFAULT_PROPS: RHFAutocompleteProps<OptionsTests>;
22
+ export declare const errorMessage = "This field is required";
23
+ export declare const VALIDATION_SCHEMA: Yup.ObjectSchema<import('yup/lib/object').Assign<import('yup/lib/object').ObjectShape, {
24
+ "rhf-autocomplete-required": import('yup/lib/string').RequiredStringSchema<string | undefined, import('yup/lib/types').AnyObject>;
25
+ }>, import('yup/lib/object').AnyObject, import('yup/lib/object').TypeOfShape<import('yup/lib/object').Assign<import('yup/lib/object').ObjectShape, {
26
+ "rhf-autocomplete-required": import('yup/lib/string').RequiredStringSchema<string | undefined, import('yup/lib/types').AnyObject>;
27
+ }>>, import('yup/lib/object').AssertsShape<import('yup/lib/object').Assign<import('yup/lib/object').ObjectShape, {
28
+ "rhf-autocomplete-required": import('yup/lib/string').RequiredStringSchema<string | undefined, import('yup/lib/types').AnyObject>;
29
+ }>>>;
30
+ /**
31
+ * Renderiza el componente con el contexto de EnvironmentProvider y RHFormProvider.
32
+ */
33
+ export declare const renderWithContexts: (ui: React.ReactElement, initialValuesFormContext?: FieldValues, validationSchema?: any) => ReturnType<typeof renderMaterialUI>;
34
+ /**
35
+ * Renders the RHFAutocompleteAsync component with the provided props.
36
+ */
37
+ export declare const renderRHFAutocomplete: (fieldName: string, overrideProps?: Partial<RHFAutocompleteProps<OptionsTests>>, withFormValidation?: boolean) => ReturnType<typeof renderMaterialUI>;
@@ -1,4 +1,4 @@
1
- import { AutocompleteCloseReason, AutocompleteFreeSoloValueMapping, AutocompleteInputChangeReason, AutocompleteValue, AutocompleteProps as MUIAutocompleteProps, Theme, PaletteColor, PopperProps } from '@mui/material';
1
+ import { AutocompleteCloseReason, AutocompleteFreeSoloValueMapping, AutocompleteInputChangeReason, AutocompleteProps as MUIAutocompleteProps, Theme, PaletteColor, PopperProps } from '@mui/material';
2
2
  import { ComponentPalletColor, Sizes } from '@m4l/styles';
3
3
  import { TextFieldProps } from '../../mui_extended/TextField/types';
4
4
  import { RFHAUTOCOMPLETE_KEY_COMPONENT } from './constants';
@@ -12,7 +12,7 @@ export type RHFAutocompleteType = 'text' | 'image';
12
12
  * Props for the unified Autocomplete component.
13
13
  * Supports both single and multiple selection, and two types: `text` and `image`.
14
14
  */
15
- export interface RHFAutocompleteProps<T, Multiple extends boolean | undefined = true, DisableClearable extends boolean | undefined = true, FreeSolo extends boolean | undefined = false> extends Omit<MUIAutocompleteProps<T, Multiple, DisableClearable, FreeSolo>, 'variant' | 'color' | 'size' | 'value' | 'classes' | 'defaultValue' | 'onBlur' | 'onFocus' | 'autoComplete' | 'renderInput'>, Omit<TextFieldProps, 'label' | 'variant' | 'defaultValue' | 'classes' | 'onBlur' | 'onFocus' | 'onKeyDown' | 'ref' | 'onChange' | 'helperText'>, Omit<LabelProps, 'label'> {
15
+ export interface RHFAutocompleteProps<T = any, Multiple extends boolean | undefined = undefined, DisableClearable extends boolean | undefined = undefined, FreeSolo extends boolean | undefined = undefined> extends Omit<MUIAutocompleteProps<T, Multiple, DisableClearable, FreeSolo>, 'variant' | 'color' | 'size' | 'value' | 'classes' | 'defaultValue' | 'onBlur' | 'onFocus' | 'autoComplete' | 'renderInput' | 'onChange' | 'open' | 'value' | 'multiple'>, Omit<TextFieldProps, 'label' | 'variant' | 'defaultValue' | 'classes' | 'onBlur' | 'onFocus' | 'onKeyDown' | 'ref' | 'onChange' | 'helperText' | 'value'>, Omit<LabelProps, 'label'> {
16
16
  name: string;
17
17
  /**
18
18
  * The label for the autocomplete field.
@@ -20,11 +20,6 @@ export interface RHFAutocompleteProps<T, Multiple extends boolean | undefined =
20
20
  popperProps?: Omit<PopperProps, 'color'>;
21
21
  onFocus?: (event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
22
22
  autoComplete?: string;
23
- /**
24
- * The value of the autocomplete, supports single or multiple selection.
25
- * Extended to include `null` for controlled components.
26
- */
27
- value?: AutocompleteValue<T, Multiple, DisableClearable, FreeSolo> | null | undefined;
28
23
  size?: Extract<Sizes, 'small' | 'medium'>;
29
24
  variant?: RHFAutocompleteVariants;
30
25
  color?: Extract<ComponentPalletColor, 'primary'>;
@@ -42,7 +37,7 @@ export interface RHFAutocompleteProps<T, Multiple extends boolean | undefined =
42
37
  helperMessage?: string;
43
38
  onClose?: (event: React.SyntheticEvent, reason: AutocompleteCloseReason) => void;
44
39
  onChangeFilterParmsLocal?: (newValue: string, reason: AutocompleteInputChangeReason) => void;
45
- multiple?: Multiple;
40
+ multiple?: boolean;
46
41
  type?: RHFAutocompleteType;
47
42
  getOptionUrlImage?: (option: T) => string;
48
43
  imageScale?: boolean;
@@ -1,7 +1,34 @@
1
- import { RHFAutocompleteAsyncBaseProps } from './types';
1
+ import { RHFAutocompleteAsyncProps } from './types';
2
2
  /**
3
- * RHFAutocompleteProps is a component that handles asynchronous autocomplete functionality.
4
- * @param props - The properties passed to the component.
5
- * @returns A React component.
3
+ * RHFAutocompleteProps is a component that handles asynchronous autocomplete functionality
4
+ * Requerimientos:
5
+ *
6
+ * - Generales
7
+ * - (Test OK) Solo cuando se abre el combo se debe hacer el request si nunca se ha hecho .
8
+ *
9
+ *
10
+ *
11
+ * - Si al componente se le define onChangeFilterParms
12
+ * - (Test OK) Solo cuando se abre el combo se debe hacer el request .
13
+ * - (Test OK) Si se abre el combo varias veces, solo se hace el request la primera vez si no han cambiado los parms.
14
+ * - (Test OK) Si cambian los parms (Normalmente cuando el componente depende de otro componente), al volver a abrir el combo se debe volver a hacer el request.
15
+ * - (Test OK) Si el request esta en curso y se cierra el combo, se debe dejar terminar el request para no perder la respuesta.
16
+ * - (Test OK) Si el request genera un error, debe dejar las mismas opciones y en el proximo open se debe volver a hacer el request.
17
+ * - Si es multiple = false
18
+ * - (Test OK) Si el usuario tiene preseleccionada una opcion al cargar el componente, esta opcion debe verse incluso si no se abierto el combo.
19
+ * - (Test OK) Si tiene preseleccionada una opcion, se abre el combo y cuando llega la respuesta no está dentro de las que llegan de la red,
20
+ * no debe desaparecer la opcion preseleccionada, solo si se selecciona otra opcion.
21
+ *
22
+ * - Si es multiple = true
23
+ * - (Test OK) Si el usuario tiene preseleccionadas una opcion al cargar el componente, esta opcion debe verse incluso si no se abierto el combo.
24
+ * - (Test OK) Si tiene preseleccionadas varias opciones, se abre el combo y cuando llega la respuesta no están dentro de las que llegan de la red,
25
+ * no deben desaparecer las opciones preseleccionadas, solo si se selecciona otra opcion.
26
+ *
27
+ * - Si el componente se le define onChangeFilterParms
28
+ * - (Test OK) Si se define multiple y onChangeFilterParms, se debe lanzar un error.
29
+ * - (Test OK) Cuando se ejecuta se hace la primera apertura debe ejecutarse el request con los parms y adicionalmente los que devuelve onChangeFilterParms.
30
+ * - (Test OK) Si el usuario digita y deja espacios de 300ms, se encola otra petición usando onChangeFilterParms.
31
+ * - (Test OK) Si el request esta en curso y el usuario digita, cancela la petición actual.
32
+ *
6
33
  */
7
- export declare function RHFAutocompleteAsync<T>(props: RHFAutocompleteAsyncBaseProps<T>): import("react/jsx-runtime").JSX.Element;
34
+ export declare function RHFAutocompleteAsync<T>(props: RHFAutocompleteAsyncProps<T>): import("react/jsx-runtime").JSX.Element;
@@ -1,14 +1,14 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
- import { useNetwork, getPropertyByString } from "@m4l/core";
3
2
  import debounce from "lodash-es/debounce";
4
- import { useState, useCallback, useEffect } from "react";
3
+ import { useReducer, useCallback } from "react";
4
+ import { a as actionsType } from "./types.js";
5
5
  import { R as RHFAutocomplete } from "../RHFAutocomplete/RHFAutocomplete.js";
6
- import { deepEqual } from "fast-equals";
6
+ import { R as RHFAutocompleteAsyncReducer, g as getInitialStateRHFAutocompleteAsync } from "./reducer/RHFAutocompleteReducer.js";
7
+ import { u as useFetchOptions } from "./hooks/useFetchOptions.js";
7
8
  function RHFAutocompleteAsync(props) {
8
9
  const {
9
10
  name,
10
11
  endPoint,
11
- responseToCamelCase,
12
12
  label,
13
13
  timeout = 5e3,
14
14
  parms,
@@ -17,112 +17,77 @@ function RHFAutocompleteAsync(props) {
17
17
  isRemote = true,
18
18
  isExternalUrl = false,
19
19
  onChangeFilterParms,
20
- onChange,
21
- onOpen,
22
- onClose,
23
20
  getOptionLabel,
24
21
  isOptionEqualToValue,
25
22
  multiple,
26
23
  disabled,
27
24
  skeletonWidth,
28
- open,
29
- value
25
+ responseToCamelCase
30
26
  } = props;
31
- const { networkOperation } = useNetwork();
32
- const [options, setOptions] = useState([]);
33
- const [firstOpen, setFirstOpen] = useState(0);
34
- const [loading, setIsloading] = useState(false);
35
- const [newRefresh, setNewRefresh] = useState(0);
36
- const [canLoadOptions, setCanLoadOptions] = useState(true);
37
- const [filterParms, setFilterParms] = useState(() => onChangeFilterParms ? onChangeFilterParms("") : {});
27
+ const [state, dispatch] = useReducer(
28
+ RHFAutocompleteAsyncReducer(onChangeFilterParms),
29
+ getInitialStateRHFAutocompleteAsync({
30
+ parms,
31
+ onChangeFilterParms
32
+ })
33
+ );
34
+ if (multiple && onChangeFilterParms) {
35
+ throw new Error("multiple no puede estar habilitado cuando se define onChangeFilterParms, definir el filtro en los parms, si es necesario");
36
+ }
37
+ useFetchOptions({
38
+ state,
39
+ dispatch,
40
+ endPoint,
41
+ timeout,
42
+ isExternalUrl,
43
+ parms,
44
+ responseToCamelCase,
45
+ isRemote,
46
+ resultField
47
+ });
38
48
  const refresh = () => {
39
- setNewRefresh((current) => current + 1);
40
- firstOpen === 0 && hanldeFirstOpen();
49
+ dispatch({ type: actionsType.REFRESH });
41
50
  };
42
- const onOpenLocal = (event) => {
43
- if (onOpen) {
44
- onOpen(event);
45
- }
46
- hanldeFirstOpen();
51
+ const onOpenLocal = () => {
52
+ dispatch({ type: actionsType.OPEN });
53
+ };
54
+ const onCloseLocal = () => {
55
+ dispatch({ type: actionsType.CLOSE });
47
56
  };
48
57
  const debouncedFilter = useCallback(
49
- debounce(
50
- (newFilterParms) => {
51
- setCanLoadOptions(true);
52
- setFilterParms((oldValue) => {
53
- if (deepEqual(oldValue, newFilterParms)) {
54
- return oldValue;
55
- }
56
- return newFilterParms;
57
- });
58
- },
59
- 300
60
- ),
61
- [setCanLoadOptions, setFilterParms]
58
+ debounce((newFilterParms) => {
59
+ dispatch({
60
+ type: actionsType.SET_QUERY_PARAMS,
61
+ payload: newFilterParms
62
+ });
63
+ }, 300, {
64
+ // leading: true,
65
+ trailing: true
66
+ }),
67
+ [dispatch]
62
68
  );
63
- const onChangeFilterParmsLocal = (newValue) => {
64
- if (onChangeFilterParms) {
69
+ const onChangeFilterParmsLocal = useCallback((newValue, reason) => {
70
+ if (onChangeFilterParms && reason === "input") {
65
71
  debouncedFilter(onChangeFilterParms(newValue));
66
72
  }
67
- };
68
- useEffect(() => {
69
- setCanLoadOptions(true);
70
- }, [parms, endPoint]);
71
- const hanldeFirstOpen = () => {
72
- if (firstOpen === 0) {
73
- setFirstOpen(1);
74
- }
75
- };
76
- useEffect(() => {
77
- let cancel = false;
78
- if (firstOpen === 1 && !loading && canLoadOptions) {
79
- setIsloading(true);
80
- setOptions([]);
81
- setCanLoadOptions(false);
82
- networkOperation({
83
- method: "GET",
84
- endPoint,
85
- timeout,
86
- isExternalUrl,
87
- parms: { ...parms, ...filterParms },
88
- responseToCamelCase,
89
- isRemote
90
- }).then((response) => {
91
- if (cancel) {
92
- return;
93
- }
94
- const valueMaybeArray = getPropertyByString(response, resultField);
95
- const newOptions = Array.isArray(valueMaybeArray) ? valueMaybeArray : [];
96
- setOptions(newOptions);
97
- }).finally(() => {
98
- setIsloading(false);
99
- setCanLoadOptions(true);
100
- });
101
- }
102
- return () => {
103
- cancel = true;
104
- };
105
- }, [firstOpen, parms, filterParms, endPoint, newRefresh]);
73
+ }, [onChangeFilterParms, debouncedFilter]);
106
74
  return /* @__PURE__ */ jsx(
107
75
  RHFAutocomplete,
108
76
  {
109
77
  name,
110
- loading,
78
+ loading: state.loading,
111
79
  label,
112
- options,
80
+ options: state.options,
113
81
  onChangeFilterParmsLocal: onChangeFilterParms ? onChangeFilterParmsLocal : void 0,
114
82
  size,
115
83
  refresh: () => refresh(),
116
84
  onOpen: onOpenLocal,
117
- onChange,
118
85
  getOptionLabel,
119
86
  isOptionEqualToValue,
120
87
  multiple,
121
88
  disabled,
122
- onClose,
123
- skeletonWidth,
124
- open,
125
- value
89
+ onClose: onCloseLocal,
90
+ skeletonWidth
126
91
  }
127
92
  );
128
93
  }
@@ -1,2 +1,2 @@
1
- import { RHFAutocompleteAyncStyles } from './types';
2
- export declare const rhfAutocompleteAsyncSyles: RHFAutocompleteAyncStyles;
1
+ import { RHFAutocompleteAsyncStyles } from './types';
2
+ export declare const rhfAutocompleteAsyncSyles: RHFAutocompleteAsyncStyles;
@@ -0,0 +1,5 @@
1
+ import { UseFetchOptionsProps } from '../types';
2
+ /**
3
+ * Hook to fetch options for autocomplete.
4
+ */
5
+ export declare const useFetchOptions: <T>(props: UseFetchOptionsProps<T>) => void;