@soyfri/shared-library 2.0.0-beta.9 → 2.0.0

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 (232) hide show
  1. package/Button-C17mExpd.cjs.map +1 -1
  2. package/Button-UkkP-bNw.js.map +1 -1
  3. package/README.md +182 -150
  4. package/components/ActionMenu/ActionMenu.cjs +52 -52
  5. package/components/ActionMenu/ActionMenu.cjs.map +1 -1
  6. package/components/ActionMenu/ActionMenu.d.ts +20 -36
  7. package/components/ActionMenu/ActionMenu.js +55 -55
  8. package/components/ActionMenu/ActionMenu.js.map +1 -1
  9. package/components/ActionMenu/index.d.ts +2 -2
  10. package/components/AppBar/AppBar.cjs +2 -219
  11. package/components/AppBar/AppBar.cjs.map +1 -1
  12. package/components/AppBar/AppBar.d.ts +6 -6
  13. package/components/AppBar/AppBar.js +5 -222
  14. package/components/AppBar/AppBar.js.map +1 -1
  15. package/components/AppBar/index.d.ts +0 -6
  16. package/components/Autocomplete/Autocomplete.cjs +93 -94
  17. package/components/Autocomplete/Autocomplete.cjs.map +1 -1
  18. package/components/Autocomplete/Autocomplete.d.ts +29 -26
  19. package/components/Autocomplete/Autocomplete.definitions.d.ts +2 -1
  20. package/components/Autocomplete/Autocomplete.helpers.d.ts +12 -8
  21. package/components/Autocomplete/Autocomplete.js +94 -95
  22. package/components/Autocomplete/Autocomplete.js.map +1 -1
  23. package/components/Autocomplete/_parts/AutocompleteChips.d.ts +7 -6
  24. package/components/Autocomplete/_parts/AutocompleteOption.d.ts +10 -13
  25. package/components/Autocomplete/index.d.ts +1 -1
  26. package/components/Avatar/Avatar.cjs +17 -18
  27. package/components/Avatar/Avatar.cjs.map +1 -1
  28. package/components/Avatar/Avatar.js +17 -18
  29. package/components/Avatar/Avatar.js.map +1 -1
  30. package/components/Avatar/index.d.ts +1 -0
  31. package/components/Button/Button.d.ts +5 -5
  32. package/components/Button/index.d.ts +1 -0
  33. package/components/Card/Card.cjs +3 -92
  34. package/components/Card/Card.cjs.map +1 -1
  35. package/components/Card/Card.d.ts +3 -50
  36. package/components/Card/Card.js +5 -94
  37. package/components/Card/Card.js.map +1 -1
  38. package/components/Card/Card.sx.d.ts +3 -6
  39. package/components/Card/index.d.ts +1 -1
  40. package/components/Checkbox/Checkbox.cjs +189 -0
  41. package/components/Checkbox/Checkbox.cjs.map +1 -0
  42. package/components/Checkbox/Checkbox.d.ts +55 -0
  43. package/components/Checkbox/Checkbox.js +189 -0
  44. package/components/Checkbox/Checkbox.js.map +1 -0
  45. package/components/Checkbox/Checkbox.sx.d.ts +13 -0
  46. package/components/Checkbox/index.d.ts +2 -0
  47. package/components/Checkbox.d.ts +6 -0
  48. package/components/Chip/Chip.cjs +2 -1
  49. package/components/Chip/Chip.cjs.map +1 -1
  50. package/components/Chip/Chip.js +2 -1
  51. package/components/Chip/Chip.js.map +1 -1
  52. package/components/Chip/index.d.ts +2 -1
  53. package/components/Chip.d.ts +4 -0
  54. package/components/DatePicker/DatePicker.cjs +40 -63
  55. package/components/DatePicker/DatePicker.cjs.map +1 -1
  56. package/components/DatePicker/DatePicker.d.ts +1 -13
  57. package/components/DatePicker/DatePicker.js +36 -59
  58. package/components/DatePicker/DatePicker.js.map +1 -1
  59. package/components/DatePicker/index.d.ts +1 -1
  60. package/components/DateTimePicker/DateTimePicker.cjs +58 -82
  61. package/components/DateTimePicker/DateTimePicker.cjs.map +1 -1
  62. package/components/DateTimePicker/DateTimePicker.d.ts +9 -17
  63. package/components/DateTimePicker/DateTimePicker.definitions.d.ts +2 -0
  64. package/components/DateTimePicker/DateTimePicker.helpers.d.ts +4 -2
  65. package/components/DateTimePicker/DateTimePicker.js +54 -78
  66. package/components/DateTimePicker/DateTimePicker.js.map +1 -1
  67. package/components/DateTimePicker/index.d.ts +1 -1
  68. package/components/Drawer/Drawer.cjs +12 -6
  69. package/components/Drawer/Drawer.cjs.map +1 -1
  70. package/components/Drawer/Drawer.d.ts +3 -1
  71. package/components/Drawer/Drawer.js +13 -7
  72. package/components/Drawer/Drawer.js.map +1 -1
  73. package/components/Drawer/DrawerItem.d.ts +6 -1
  74. package/components/Gallery/Gallery.cjs +154 -79
  75. package/components/Gallery/Gallery.cjs.map +1 -1
  76. package/components/Gallery/Gallery.d.ts +25 -9
  77. package/components/Gallery/Gallery.js +154 -79
  78. package/components/Gallery/Gallery.js.map +1 -1
  79. package/components/Gallery/GalleryLightbox.d.ts +6 -10
  80. package/components/Gallery/GalleryMain.d.ts +3 -7
  81. package/components/Gallery/GalleryThumbnails.d.ts +7 -11
  82. package/components/Gallery/index.d.ts +2 -1
  83. package/components/Gallery.d.ts +4 -0
  84. package/components/Icon/Icon.cjs +6 -8
  85. package/components/Icon/Icon.cjs.map +1 -1
  86. package/components/Icon/Icon.d.ts +11 -17
  87. package/components/Icon/Icon.js +6 -8
  88. package/components/Icon/Icon.js.map +1 -1
  89. package/components/Icon/index.d.ts +2 -1
  90. package/components/Icon.d.ts +4 -0
  91. package/components/Input/Input.cjs +26 -13
  92. package/components/Input/Input.cjs.map +1 -1
  93. package/components/Input/Input.d.ts +9 -2
  94. package/components/Input/Input.helpers.d.ts +3 -3
  95. package/components/Input/Input.js +23 -10
  96. package/components/Input/Input.js.map +1 -1
  97. package/components/Input/index.d.ts +1 -1
  98. package/components/InputGroup/InputGroup.cjs +23 -22
  99. package/components/InputGroup/InputGroup.cjs.map +1 -1
  100. package/components/InputGroup/InputGroup.d.ts +4 -4
  101. package/components/InputGroup/InputGroup.js +22 -21
  102. package/components/InputGroup/InputGroup.js.map +1 -1
  103. package/components/InputGroup/index.d.ts +2 -1
  104. package/components/InputGroup.d.ts +4 -0
  105. package/components/Modal/Modal.cjs +127 -98
  106. package/components/Modal/Modal.cjs.map +1 -1
  107. package/components/Modal/Modal.d.ts +20 -5
  108. package/components/Modal/Modal.js +130 -101
  109. package/components/Modal/Modal.js.map +1 -1
  110. package/components/Modal/ModalBody.d.ts +6 -1
  111. package/components/Modal/ModalFooter.d.ts +4 -4
  112. package/components/Modal/ModalHeader.d.ts +6 -1
  113. package/components/Modal/index.d.ts +4 -2
  114. package/components/Modal.d.ts +4 -0
  115. package/components/RadioGroup/RadioGroup.cjs +9 -7
  116. package/components/RadioGroup/RadioGroup.cjs.map +1 -1
  117. package/components/RadioGroup/RadioGroup.d.ts +9 -3
  118. package/components/RadioGroup/RadioGroup.js +9 -7
  119. package/components/RadioGroup/RadioGroup.js.map +1 -1
  120. package/components/RadioGroup/index.d.ts +1 -1
  121. package/components/Select/Select.cjs +129 -264
  122. package/components/Select/Select.cjs.map +1 -1
  123. package/components/Select/Select.d.ts +35 -20
  124. package/components/Select/Select.helpers.d.ts +6 -19
  125. package/components/Select/Select.js +134 -269
  126. package/components/Select/Select.js.map +1 -1
  127. package/components/Select/index.d.ts +1 -1
  128. package/components/Stat/Stat.cjs +2 -2
  129. package/components/Stat/Stat.cjs.map +1 -1
  130. package/components/Stat/Stat.js +2 -2
  131. package/components/Stat/Stat.js.map +1 -1
  132. package/components/Stat/index.d.ts +2 -1
  133. package/components/Stat.d.ts +4 -0
  134. package/components/StatusMessage/StatusMessage.cjs +84 -55
  135. package/components/StatusMessage/StatusMessage.cjs.map +1 -1
  136. package/components/StatusMessage/StatusMessage.d.ts +20 -36
  137. package/components/StatusMessage/StatusMessage.js +86 -57
  138. package/components/StatusMessage/StatusMessage.js.map +1 -1
  139. package/components/StatusMessage/StatusMessageContext.d.ts +16 -0
  140. package/components/StatusMessage/index.d.ts +4 -1
  141. package/components/StatusMessage.d.ts +4 -0
  142. package/components/Stepper/Stepper.cjs +289 -55
  143. package/components/Stepper/Stepper.cjs.map +1 -1
  144. package/components/Stepper/Stepper.d.ts +9 -20
  145. package/components/Stepper/Stepper.js +291 -57
  146. package/components/Stepper/Stepper.js.map +1 -1
  147. package/{hooks/Wizard/WizardContext.d.ts → components/Stepper/StepperContext.d.ts} +29 -23
  148. package/components/Stepper/_hooks/useHorizontalScroll.d.ts +19 -0
  149. package/components/Stepper/_parts/StepperScrollArrow.d.ts +19 -0
  150. package/components/Stepper/index.d.ts +6 -2
  151. package/components/Stepper.d.ts +4 -0
  152. package/components/Switch/Switch.cjs +5 -2
  153. package/components/Switch/Switch.cjs.map +1 -1
  154. package/components/Switch/Switch.d.ts +7 -2
  155. package/components/Switch/Switch.js +5 -2
  156. package/components/Switch/Switch.js.map +1 -1
  157. package/components/Tabs/Tabs.cjs +45 -29
  158. package/components/Tabs/Tabs.cjs.map +1 -1
  159. package/components/Tabs/Tabs.d.ts +21 -16
  160. package/components/Tabs/Tabs.js +46 -30
  161. package/components/Tabs/Tabs.js.map +1 -1
  162. package/components/Tabs/index.d.ts +4 -2
  163. package/components/Tabs.d.ts +4 -0
  164. package/components/Timeline/Timeline.cjs +3 -2
  165. package/components/Timeline/Timeline.cjs.map +1 -1
  166. package/components/Timeline/Timeline.d.ts +4 -8
  167. package/components/Timeline/Timeline.js +3 -2
  168. package/components/Timeline/Timeline.js.map +1 -1
  169. package/components/Timeline/index.d.ts +4 -2
  170. package/components/Timeline.d.ts +4 -0
  171. package/components/_shared/mergeSx.d.ts +7 -0
  172. package/{formField.sx-DfVbMe0V.js → formField.sx-8_QRnKxv.js} +2 -11
  173. package/formField.sx-8_QRnKxv.js.map +1 -0
  174. package/{formField.sx-CQ1mbk9M.cjs → formField.sx-BAX7KwMR.cjs} +10 -19
  175. package/formField.sx-BAX7KwMR.cjs.map +1 -0
  176. package/index.cjs +31 -2
  177. package/index.cjs.map +1 -1
  178. package/index.d.ts +1 -0
  179. package/index.js +16 -2
  180. package/index.js.map +1 -1
  181. package/mergeSx-BXoNZjB_.js +10 -0
  182. package/mergeSx-BXoNZjB_.js.map +1 -0
  183. package/mergeSx-Dbccoo_H.cjs +9 -0
  184. package/mergeSx-Dbccoo_H.cjs.map +1 -0
  185. package/mui.d.ts +3 -2
  186. package/package.json +6 -16
  187. package/theme/componentStyles.d.ts +1 -1
  188. package/tokens-BRrcP_p_.js +21 -0
  189. package/tokens-BRrcP_p_.js.map +1 -0
  190. package/tokens-jaWWNk39.cjs +20 -0
  191. package/tokens-jaWWNk39.cjs.map +1 -0
  192. package/utils/index.d.ts +2 -0
  193. package/{components/ScrollTopButton → utils}/scrollToTop.d.ts +6 -7
  194. package/components/AppBar/AppBarBrand.d.ts +0 -31
  195. package/components/AppBar/AppBarUserMenu.d.ts +0 -65
  196. package/components/Autocomplete/Autocomplete.types.d.ts +0 -1
  197. package/components/DatePicker/DatePicker.types.d.ts +0 -1
  198. package/components/DateTimePicker/DateTimePicker.types.d.ts +0 -1
  199. package/components/Input/Input.types.d.ts +0 -1
  200. package/components/PageLoader/PageLoader.cjs +0 -61
  201. package/components/PageLoader/PageLoader.cjs.map +0 -1
  202. package/components/PageLoader/PageLoader.d.ts +0 -38
  203. package/components/PageLoader/PageLoader.js +0 -61
  204. package/components/PageLoader/PageLoader.js.map +0 -1
  205. package/components/PageLoader/index.d.ts +0 -2
  206. package/components/PageLoader.d.ts +0 -6
  207. package/components/RadioGroup/RadioGroup.types.d.ts +0 -1
  208. package/components/ScrollTopButton/ScrollTopButton.cjs +0 -79
  209. package/components/ScrollTopButton/ScrollTopButton.cjs.map +0 -1
  210. package/components/ScrollTopButton/ScrollTopButton.d.ts +0 -48
  211. package/components/ScrollTopButton/ScrollTopButton.js +0 -79
  212. package/components/ScrollTopButton/ScrollTopButton.js.map +0 -1
  213. package/components/ScrollTopButton/index.d.ts +0 -4
  214. package/components/ScrollTopButton.d.ts +0 -6
  215. package/components/Select/Select.definitions.d.ts +0 -17
  216. package/components/Select/Select.types.d.ts +0 -1
  217. package/components/Select/_parts/SelectSearchHeader.d.ts +0 -15
  218. package/components/Select/_parts/SelectValue.d.ts +0 -22
  219. package/formField.sx-CQ1mbk9M.cjs.map +0 -1
  220. package/formField.sx-DfVbMe0V.js.map +0 -1
  221. package/hooks/Wizard/Wizard.cjs +0 -7
  222. package/hooks/Wizard/Wizard.cjs.map +0 -1
  223. package/hooks/Wizard/Wizard.js +0 -7
  224. package/hooks/Wizard/Wizard.js.map +0 -1
  225. package/hooks/Wizard/index.d.ts +0 -3
  226. package/hooks/Wizard/useWizard.d.ts +0 -9
  227. package/hooks/Wizard.d.ts +0 -2
  228. package/useWizard-CWdIxZzX.cjs +0 -94
  229. package/useWizard-CWdIxZzX.cjs.map +0 -1
  230. package/useWizard-CWq--C3o.js +0 -95
  231. package/useWizard-CWq--C3o.js.map +0 -1
  232. /package/{styles.css → index.css} +0 -0
@@ -30,11 +30,10 @@ var __objRest = (source, exclude) => {
30
30
  return target;
31
31
  };
32
32
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
33
- import { createElement, useState, useRef, useMemo } from "react";
33
+ import { useState, useRef, useMemo } from "react";
34
34
  import { Chip, Avatar, Box, CircularProgress, Typography, Autocomplete as Autocomplete$1, TextField } from "@mui/material";
35
35
  import { useTheme } from "@mui/material/styles";
36
- import { Controller } from "react-hook-form";
37
- import { b as buildFormFieldSx } from "../../formField.sx-DfVbMe0V.js";
36
+ import { b as buildFormFieldSx } from "../../formField.sx-8_QRnKxv.js";
38
37
  import { r as resolvePreset } from "../../resolvePreset-B-IB0ehH.js";
39
38
  import ClearIcon from "@mui/icons-material/Clear";
40
39
  const buildAutocompleteSx = (borderRadius, labelPosition) => buildFormFieldSx({
@@ -53,24 +52,40 @@ const buildAutocompleteSx = (borderRadius, labelPosition) => buildFormFieldSx({
53
52
  }
54
53
  }
55
54
  });
56
- const resolveSingleValue = (options, value) => {
55
+ const resolveSingleValue = (options, value, getKey) => {
57
56
  var _a;
58
- return (_a = options.find((o) => o.value === value)) != null ? _a : null;
57
+ if (value === null || value === void 0) return null;
58
+ const key = getKey(value);
59
+ return (_a = options.find((o) => getKey(o.value) === key)) != null ? _a : null;
59
60
  };
60
- const resolveMultipleValue = (options, value) => {
61
+ const resolveMultipleValue = (options, value, getKey) => {
61
62
  if (!Array.isArray(value)) return [];
62
- return options.filter((o) => value.includes(o.value));
63
+ const keys = new Set(value.map(getKey));
64
+ return options.filter((o) => keys.has(getKey(o.value)));
63
65
  };
64
- const areResolvedValuesEqual = (prev, next, multiple) => {
66
+ const areOptionsShallowEqual = (a, b, getKey) => {
67
+ const keysA = Object.keys(a);
68
+ const keysB = Object.keys(b);
69
+ if (keysA.length !== keysB.length) return false;
70
+ return keysA.every((k) => {
71
+ if (k === "value") return getKey(a.value) === getKey(b.value);
72
+ return a[k] === b[k];
73
+ });
74
+ };
75
+ const areResolvedValuesEqual = (prev, next, multiple, getKey) => {
65
76
  if (multiple) {
66
77
  if (!Array.isArray(prev) || !Array.isArray(next)) return false;
67
78
  if (prev.length !== next.length) return false;
68
79
  return prev.every((o, i) => {
69
- var _a;
70
- return o.value === ((_a = next[i]) == null ? void 0 : _a.value);
80
+ const n2 = next[i];
81
+ return !!n2 && areOptionsShallowEqual(o, n2, getKey);
71
82
  });
72
83
  }
73
- return (prev == null ? void 0 : prev.value) === (next == null ? void 0 : next.value);
84
+ const p = prev;
85
+ const n = next;
86
+ if (p === n) return true;
87
+ if (!p || !n) return false;
88
+ return areOptionsShallowEqual(p, n, getKey);
74
89
  };
75
90
  const isResolvedValueEmpty = (resolvedValue, multiple) => {
76
91
  if (multiple) {
@@ -83,30 +98,30 @@ const AutocompleteOption = ({
83
98
  option,
84
99
  customRender
85
100
  }) => {
86
- const _a = liProps, { key: _ignored } = _a, liRest = __objRest(_a, ["key"]);
87
- return /* @__PURE__ */ jsx("li", __spreadProps(__spreadValues({}, liRest), { children: customRender ? customRender(option) : option.label }), option.value);
101
+ return /* @__PURE__ */ jsx("li", __spreadProps(__spreadValues({}, liProps), { children: customRender ? customRender(option) : option.label }));
88
102
  };
89
103
  const AutocompleteChips = ({
90
104
  value,
91
105
  getTagProps,
92
106
  size,
93
107
  maxChipsToShow,
94
- renderChipLabel
108
+ renderChipLabel,
109
+ getKey
95
110
  }) => {
96
111
  const displayed = value.slice(0, maxChipsToShow);
97
112
  const hidden = value.length - maxChipsToShow;
98
113
  return /* @__PURE__ */ jsxs(Fragment, { children: [
99
114
  displayed.map((option, index) => {
100
- const tagProps = getTagProps({ index });
101
- return /* @__PURE__ */ createElement(
115
+ const _a = getTagProps({ index }), { key: _ignored } = _a, tagProps = __objRest(_a, ["key"]);
116
+ return /* @__PURE__ */ jsx(
102
117
  Chip,
103
118
  __spreadProps(__spreadValues({}, tagProps), {
104
- key: option.value,
105
119
  size,
106
120
  label: renderChipLabel ? renderChipLabel(option) : option.label,
107
121
  avatar: option.img ? /* @__PURE__ */ jsx(Avatar, { src: option.img }) : void 0,
108
122
  deleteIcon: /* @__PURE__ */ jsx(ClearIcon, {})
109
- })
123
+ }),
124
+ getKey(option.value)
110
125
  );
111
126
  }),
112
127
  hidden > 0 && /* @__PURE__ */ jsx(Chip, { size, label: `+${hidden} más` })
@@ -132,13 +147,13 @@ function Autocomplete(props) {
132
147
  maxChipsToShow = 3,
133
148
  renderOptionItem,
134
149
  renderChipLabel,
150
+ renderSingleValue,
135
151
  borderRadius = 10,
136
152
  labelPosition = "outside",
137
153
  size = "small",
138
154
  noOptionsText = "No hay opciones",
139
155
  loadingText,
140
156
  sx,
141
- className,
142
157
  preset,
143
158
  textFieldProps,
144
159
  onInputChange,
@@ -147,25 +162,23 @@ function Autocomplete(props) {
147
162
  freeSolo,
148
163
  open,
149
164
  onOpen,
150
- onClose
165
+ onClose,
166
+ getOptionKey
151
167
  } = props;
168
+ const getKey = getOptionKey != null ? getOptionKey : ((v) => v);
152
169
  const [isFocused, setIsFocused] = useState(false);
153
- const seenOptionsRef = useRef(
154
- /* @__PURE__ */ new Map()
155
- );
170
+ const seenOptionsRef = useRef(/* @__PURE__ */ new Map());
156
171
  for (const opt of options) {
157
- seenOptionsRef.current.set(opt.value, opt);
172
+ seenOptionsRef.current.set(getKey(opt.value), opt);
158
173
  }
159
174
  const resolvePool = useMemo(() => {
160
175
  const merged = new Map(seenOptionsRef.current);
161
- for (const opt of options) merged.set(opt.value, opt);
176
+ for (const opt of options) merged.set(getKey(opt.value), opt);
162
177
  return Array.from(merged.values());
163
178
  }, [options]);
164
- const prevResolvedRef = useRef(
165
- multiple ? [] : null
166
- );
179
+ const prevResolvedRef = useRef(multiple ? [] : null);
167
180
  const stabilizeResolved = (newVal) => {
168
- if (areResolvedValuesEqual(prevResolvedRef.current, newVal, multiple)) {
181
+ if (areResolvedValuesEqual(prevResolvedRef.current, newVal, multiple, getKey)) {
169
182
  return prevResolvedRef.current;
170
183
  }
171
184
  prevResolvedRef.current = newVal;
@@ -178,11 +191,10 @@ function Autocomplete(props) {
178
191
  ...presetSx ? [presetSx] : [],
179
192
  ...Array.isArray(sx) ? sx : sx ? [sx] : []
180
193
  ];
181
- const renderAutocomplete = (resolvedValue2, handleChange, onBlur, inputRef, rhfError, rhfHelperText) => {
182
- const finalError = !!rhfError || !!errorProp;
183
- const finalHelperText = rhfHelperText || helperText;
194
+ const renderAutocomplete = (resolvedValue2, handleChange) => {
184
195
  const isEmpty = isResolvedValueEmpty(resolvedValue2, multiple);
185
196
  const showPlaceholder = isEmpty && isFocused && !!placeholder;
197
+ const singleAdornment = !multiple && resolvedValue2 && renderSingleValue ? renderSingleValue(resolvedValue2) : null;
186
198
  return /* @__PURE__ */ jsx(
187
199
  Autocomplete$1,
188
200
  {
@@ -192,7 +204,6 @@ function Autocomplete(props) {
192
204
  disabled,
193
205
  readOnly,
194
206
  loading,
195
- className,
196
207
  sx: mergedSx,
197
208
  freeSolo,
198
209
  open,
@@ -205,36 +216,53 @@ function Autocomplete(props) {
205
216
  var _a;
206
217
  return typeof opt === "string" ? opt : (_a = opt == null ? void 0 : opt.label) != null ? _a : "";
207
218
  },
208
- isOptionEqualToValue: (a, b) => (a == null ? void 0 : a.value) === (b == null ? void 0 : b.value),
209
- getOptionDisabled: (opt) => !!(opt == null ? void 0 : opt.disabled),
219
+ isOptionEqualToValue: (a, b) => {
220
+ if (typeof a === "string" || typeof b === "string") return a === b;
221
+ if (!a || !b) return a === b;
222
+ return getKey(a.value) === getKey(b.value);
223
+ },
224
+ getOptionDisabled: (opt) => typeof opt === "string" ? false : !!(opt == null ? void 0 : opt.disabled),
210
225
  onChange: handleChange,
211
226
  onFocus: () => setIsFocused(true),
212
- onBlur: () => {
213
- setIsFocused(false);
214
- onBlur == null ? void 0 : onBlur();
227
+ onBlur: () => setIsFocused(false),
228
+ renderOption: (liProps, option) => {
229
+ const _a = liProps, { key: _muiKey } = _a, liRest = __objRest(_a, ["key"]);
230
+ return /* @__PURE__ */ jsx(
231
+ AutocompleteOption,
232
+ {
233
+ liProps: liRest,
234
+ option,
235
+ customRender: renderOptionItem
236
+ },
237
+ getKey(option.value)
238
+ );
215
239
  },
216
- renderOption: (liProps, option) => /* @__PURE__ */ jsx(
217
- AutocompleteOption,
218
- {
219
- liProps,
220
- option,
221
- customRender: renderOptionItem
222
- }
223
- ),
224
- renderTags: multiple ? (value, getTagProps) => /* @__PURE__ */ jsx(
240
+ renderValue: multiple ? (value, getItemProps) => /* @__PURE__ */ jsx(
225
241
  AutocompleteChips,
226
242
  {
227
243
  value,
228
- getTagProps,
244
+ getTagProps: getItemProps,
229
245
  size,
230
246
  maxChipsToShow,
231
- renderChipLabel
247
+ renderChipLabel,
248
+ getKey
232
249
  }
233
250
  ) : void 0,
234
251
  noOptionsText,
235
252
  loadingText: loadingText != null ? loadingText : /* @__PURE__ */ jsx(AutocompleteLoader, {}),
236
253
  renderInput: (params) => {
237
- var _a;
254
+ var _a, _b, _c, _d;
255
+ const paramsInputLabel = params.InputLabelProps;
256
+ const consumerInputLabel = (_b = (_a = textFieldProps == null ? void 0 : textFieldProps.slotProps) == null ? void 0 : _a.inputLabel) != null ? _b : textFieldProps == null ? void 0 : textFieldProps.InputLabelProps;
257
+ const muiInputProps = params.InputProps;
258
+ const consumerInputProps = (_d = (_c = textFieldProps == null ? void 0 : textFieldProps.slotProps) == null ? void 0 : _c.input) != null ? _d : textFieldProps == null ? void 0 : textFieldProps.InputProps;
259
+ const inputSlot = singleAdornment ? __spreadProps(__spreadValues(__spreadValues({}, muiInputProps), consumerInputProps), {
260
+ startAdornment: /* @__PURE__ */ jsxs(Fragment, { children: [
261
+ singleAdornment,
262
+ consumerInputProps == null ? void 0 : consumerInputProps.startAdornment,
263
+ muiInputProps == null ? void 0 : muiInputProps.startAdornment
264
+ ] })
265
+ }) : void 0;
238
266
  return /* @__PURE__ */ jsx(
239
267
  TextField,
240
268
  __spreadProps(__spreadValues(__spreadProps(__spreadValues({}, params), {
@@ -242,12 +270,13 @@ function Autocomplete(props) {
242
270
  size,
243
271
  variant: "outlined",
244
272
  placeholder: showPlaceholder ? placeholder : void 0,
245
- error: finalError,
246
- helperText: finalHelperText,
247
- inputRef
273
+ error: !!errorProp,
274
+ helperText
248
275
  }), textFieldProps), {
249
- InputLabelProps: __spreadProps(__spreadValues(__spreadValues({}, params.InputLabelProps), textFieldProps == null ? void 0 : textFieldProps.InputLabelProps), {
250
- shrink: labelPosition === "outside" ? !isEmpty || isFocused : (_a = params.InputLabelProps) == null ? void 0 : _a.shrink
276
+ slotProps: __spreadProps(__spreadValues(__spreadValues({}, textFieldProps == null ? void 0 : textFieldProps.slotProps), inputSlot ? { input: inputSlot } : {}), {
277
+ inputLabel: __spreadProps(__spreadValues(__spreadValues({}, paramsInputLabel), consumerInputLabel), {
278
+ shrink: labelPosition === "outside" ? !isEmpty || isFocused : paramsInputLabel == null ? void 0 : paramsInputLabel.shrink
279
+ })
251
280
  })
252
281
  })
253
282
  );
@@ -255,53 +284,23 @@ function Autocomplete(props) {
255
284
  }
256
285
  );
257
286
  };
258
- const handleControlledChange = (_event, newValue) => {
287
+ const extractValue = (opt) => {
259
288
  var _a;
260
- const onChange = props.onChange;
289
+ if (opt === null || opt === void 0) return null;
290
+ if (typeof opt === "string") return opt;
291
+ return (_a = opt == null ? void 0 : opt.value) != null ? _a : null;
292
+ };
293
+ const handleControlledChange = (_event, newValue) => {
294
+ const { onChange } = props;
261
295
  if (multiple) {
262
- const values = (newValue != null ? newValue : []).map((opt) => opt.value);
296
+ const values = (newValue != null ? newValue : []).map((opt) => extractValue(opt)).filter((v) => v !== null);
263
297
  onChange(values);
264
298
  } else {
265
- onChange((_a = newValue == null ? void 0 : newValue.value) != null ? _a : null);
299
+ onChange(extractValue(newValue));
266
300
  }
267
301
  };
268
- if ("control" in props && props.control) {
269
- const { name, control, validation } = props;
270
- return /* @__PURE__ */ jsx(
271
- Controller,
272
- {
273
- name,
274
- control,
275
- rules: validation,
276
- render: ({ field, fieldState: { error: fieldError } }) => {
277
- const resolvedValue2 = stabilizeResolved(
278
- multiple ? resolveMultipleValue(resolvePool, field.value) : resolveSingleValue(resolvePool, field.value)
279
- );
280
- const handleChange = (_event, newValue) => {
281
- var _a;
282
- if (multiple) {
283
- field.onChange(
284
- (newValue != null ? newValue : []).map((opt) => opt.value)
285
- );
286
- } else {
287
- field.onChange((_a = newValue == null ? void 0 : newValue.value) != null ? _a : null);
288
- }
289
- };
290
- return renderAutocomplete(
291
- resolvedValue2,
292
- handleChange,
293
- field.onBlur,
294
- field.ref,
295
- !!fieldError,
296
- fieldError == null ? void 0 : fieldError.message
297
- );
298
- }
299
- }
300
- );
301
- }
302
- const controlledValue = props.value;
303
302
  const resolvedValue = stabilizeResolved(
304
- multiple ? resolveMultipleValue(resolvePool, controlledValue) : resolveSingleValue(resolvePool, controlledValue)
303
+ multiple ? resolveMultipleValue(resolvePool, props.value, getKey) : resolveSingleValue(resolvePool, props.value, getKey)
305
304
  );
306
305
  return renderAutocomplete(resolvedValue, handleControlledChange);
307
306
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Autocomplete.js","sources":["../../../src/components/Autocomplete/Autocomplete.sx.ts","../../../src/components/Autocomplete/Autocomplete.helpers.ts","../../../src/components/Autocomplete/_parts/AutocompleteOption.tsx","../../../src/components/Autocomplete/_parts/AutocompleteChips.tsx","../../../src/components/Autocomplete/_parts/AutocompleteLoader.tsx","../../../src/components/Autocomplete/Autocomplete.tsx"],"sourcesContent":["import type { SxProps, Theme } from '@mui/material/styles';\n\nimport { buildFormFieldSx } from '../_shared/formField.sx';\nimport type { LabelPosition } from './Autocomplete';\n\n/**\n * Builder del sx del Autocomplete. Reutiliza `buildFormFieldSx` y añade\n * los paddings propios del Autocomplete (chips + input interno).\n */\nexport const buildAutocompleteSx = (\n borderRadius: number | string,\n labelPosition: LabelPosition,\n): SxProps<Theme> =>\n buildFormFieldSx({\n borderRadius,\n labelPosition,\n extraOutsideSx: {\n // El input interno del Autocomplete.\n '& .MuiAutocomplete-input': {\n paddingTop: '4px',\n paddingBottom: '4px',\n },\n\n // Contenedor del input (donde viven los chips en modo multiple).\n '& .MuiAutocomplete-inputRoot': {\n paddingTop: '4px',\n paddingBottom: '4px',\n },\n },\n });\n","import type { SxProps, Theme } from '@mui/material/styles';\nimport type { SelectOption } from './Autocomplete';\n\n/** Resuelve un value único a su SelectOption dentro del pool. */\nexport const resolveSingleValue = (\n options: SelectOption[],\n value: SelectOption['value'] | null | undefined,\n): SelectOption | null => options.find((o) => o.value === value) ?? null;\n\n/** Resuelve un array de values a sus SelectOption dentro del pool. */\nexport const resolveMultipleValue = (\n options: SelectOption[],\n value: SelectOption['value'][] | null | undefined,\n): SelectOption[] => {\n if (!Array.isArray(value)) return [];\n return options.filter((o) => value.includes(o.value));\n};\n\n/** Merge de sx base + extra del consumer, respetando el contrato de MUI. */\nexport const mergeSx = (\n base: SxProps<Theme>,\n extra?: SxProps<Theme>,\n): SxProps<Theme> => {\n if (!extra) return base;\n return [base, ...(Array.isArray(extra) ? extra : [extra])] as SxProps<Theme>;\n};\n\n/**\n * Compara dos valores resueltos (single o multiple) por value para decidir\n * si son estructuralmente iguales. Se usa para estabilizar la referencia que\n * se pasa a MUI Autocomplete (MUI compara value por referencia con `!==`,\n * y una nueva referencia — aunque el contenido sea igual — dispara\n * `resetInputValue` y borra el texto mientras el usuario tipea).\n */\nexport const areResolvedValuesEqual = (\n prev: SelectOption | SelectOption[] | null,\n next: SelectOption | SelectOption[] | null,\n multiple: boolean,\n): boolean => {\n if (multiple) {\n if (!Array.isArray(prev) || !Array.isArray(next)) return false;\n if (prev.length !== next.length) return false;\n return prev.every((o, i) => o.value === next[i]?.value);\n }\n return (\n (prev as SelectOption | null)?.value ===\n (next as SelectOption | null)?.value\n );\n};\n\n/** Determina si un valor resuelto está vacío (para placeholder/shrink). */\nexport const isResolvedValueEmpty = (\n resolvedValue: unknown,\n multiple: boolean,\n): boolean => {\n if (multiple) {\n return !Array.isArray(resolvedValue) || resolvedValue.length === 0;\n }\n return !resolvedValue;\n};\n","import React from 'react';\nimport type { SelectOption, RenderOptionItem } from '../Autocomplete';\n\ninterface AutocompleteOptionProps {\n liProps: React.HTMLAttributes<HTMLLIElement> & { key?: React.Key };\n option: SelectOption;\n customRender?: RenderOptionItem;\n}\n\n/**\n * Render por defecto de un <li> del dropdown del Autocomplete.\n * Se expone como componente para testear y extender fácilmente, pero MUI\n * lo llama desde `renderOption={(props, option) => ...}` en el padre.\n *\n * El `key` lo manejamos nosotros (no spreadeamos junto al resto) porque MUI\n * lo inyecta como parte de `propsLi` y React exige que sea prop directo.\n */\nexport const AutocompleteOption: React.FC<AutocompleteOptionProps> = ({\n liProps,\n option,\n customRender,\n}) => {\n const { key: _ignored, ...liRest } = liProps;\n return (\n <li key={option.value} {...liRest}>\n {customRender ? customRender(option) : option.label}\n </li>\n );\n};\n\nexport default AutocompleteOption;\n","import React from 'react';\nimport { Avatar, Chip } from '@mui/material';\nimport ClearIcon from '@mui/icons-material/Clear';\n\nimport type {\n SelectOption,\n RenderChipLabel,\n AutocompleteSize,\n} from '../Autocomplete';\n\ninterface AutocompleteChipsProps {\n value: SelectOption[];\n getTagProps: (args: { index: number }) => Record<string, any>;\n size: AutocompleteSize;\n maxChipsToShow: number;\n renderChipLabel?: RenderChipLabel;\n}\n\n/**\n * Render de los chips del Autocomplete en modo multiple.\n * Trunca después de `maxChipsToShow` con un chip \"+N más\".\n * El `getTagProps({ index })` viene de MUI y contiene el handler de delete,\n * la key, etc. — se spreadea tal cual al Chip.\n */\nexport const AutocompleteChips: React.FC<AutocompleteChipsProps> = ({\n value,\n getTagProps,\n size,\n maxChipsToShow,\n renderChipLabel,\n}) => {\n const displayed = value.slice(0, maxChipsToShow);\n const hidden = value.length - maxChipsToShow;\n\n return (\n <>\n {displayed.map((option, index) => {\n const tagProps = getTagProps({ index });\n return (\n <Chip\n {...tagProps}\n key={option.value}\n size={size}\n label={renderChipLabel ? renderChipLabel(option) : option.label}\n avatar={option.img ? <Avatar src={option.img} /> : undefined}\n deleteIcon={<ClearIcon />}\n />\n );\n })}\n {hidden > 0 && <Chip size={size} label={`+${hidden} más`} />}\n </>\n );\n};\n\nexport default AutocompleteChips;\n","import React from 'react';\nimport { Box, CircularProgress, Typography } from '@mui/material';\n\n/**\n * Loader por defecto para el `loadingText` del Autocomplete.\n * El consumer puede sobrescribirlo pasando `loadingText` al componente padre.\n */\nexport const AutocompleteLoader: React.FC<{ text?: string }> = ({\n text = 'Cargando...',\n}) => (\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>\n <CircularProgress size={16} />\n <Typography variant=\"body2\">{text}</Typography>\n </Box>\n);\n\nexport default AutocompleteLoader;\n","import React, {\n useMemo,\n useRef,\n useState,\n type ReactNode,\n type SyntheticEvent,\n} from 'react';\nimport {\n Autocomplete as MuiAutocomplete,\n TextField,\n type TextFieldProps,\n} from '@mui/material';\nimport { useTheme, type SxProps, type Theme } from '@mui/material/styles';\nimport { Controller, type Control, type RegisterOptions } from 'react-hook-form';\n\nimport { buildAutocompleteSx } from './Autocomplete.sx';\nimport {\n areResolvedValuesEqual,\n isResolvedValueEmpty,\n resolveMultipleValue,\n resolveSingleValue,\n} from './Autocomplete.helpers';\nimport { resolvePreset } from '../_shared/resolvePreset';\nimport { AutocompleteOption } from './_parts/AutocompleteOption';\nimport { AutocompleteChips } from './_parts/AutocompleteChips';\nimport { AutocompleteLoader } from './_parts/AutocompleteLoader';\n\n// ── Tipos de dominio ─────────────────────────────────────────────────────\nexport interface SelectOption {\n value: string | number;\n label: string;\n img?: string;\n disabled?: boolean;\n group?: string;\n [key: string]: any;\n}\n\nexport type LabelPosition = 'outside' | 'floating';\nexport type AutocompleteSize = 'small' | 'medium';\n\n// ── Render slots ─────────────────────────────────────────────────────────\nexport type RenderOptionItem = (item: SelectOption) => ReactNode;\nexport type RenderChipLabel = (item: SelectOption) => ReactNode;\n\n// ── Props base ───────────────────────────────────────────────────────────\nexport type BaseAutocompleteProps<\n _TValue extends SelectOption['value'] = SelectOption['value'],\n> = {\n label?: string;\n options: SelectOption[];\n placeholder?: string;\n multiple?: boolean;\n disabled?: boolean;\n readOnly?: boolean;\n loading?: boolean;\n error?: boolean;\n helperText?: string;\n maxChipsToShow?: number;\n renderOptionItem?: RenderOptionItem;\n renderChipLabel?: RenderChipLabel;\n /** Border radius del input. Default: 10. */\n borderRadius?: number | string;\n /** \"outside\" (default) = label arriba del input; \"floating\" = comportamiento nativo MUI. */\n labelPosition?: LabelPosition;\n /** Tamaño del TextField. Default: 'small'. */\n size?: AutocompleteSize;\n /** Texto cuando no hay coincidencias. */\n noOptionsText?: ReactNode;\n /** Texto cuando está cargando. */\n loadingText?: ReactNode;\n sx?: SxProps<Theme>;\n className?: string;\n /**\n * Nombre del preset de estilo registrado en `theme.styles.Autocomplete`.\n * - `\"default\"` (o ausente) = estilo built-in del paquete.\n * - Cualquier otro string = mergea el preset encima del estilo built-in.\n */\n preset?: string;\n /** Props para el TextField subyacente. */\n textFieldProps?: Partial<TextFieldProps>;\n\n // ── Búsqueda asíncrona / remota ──────────────────────────────────────\n /** Se dispara cada vez que el usuario escribe. Útil para llamadas a servicios\n * (debounce recomendado en el consumer). */\n onInputChange?: (\n event: SyntheticEvent,\n value: string,\n reason: 'input' | 'reset' | 'clear' | 'blur' | 'selectOption' | 'removeOption',\n ) => void;\n /** Valor controlado del texto de búsqueda. */\n inputValue?: string;\n /** Filtro custom. Para búsqueda remota pasar `(x) => x` y confiar sólo en el servicio. */\n filterOptions?: (options: SelectOption[], state: any) => SelectOption[];\n /** Permite valores arbitrarios (no solo de la lista). */\n freeSolo?: boolean;\n open?: boolean;\n onOpen?: (event: SyntheticEvent) => void;\n onClose?: (event: SyntheticEvent, reason: string) => void;\n};\n\n// ── Variantes discriminadas (RHF vs controlado) ──────────────────────────\nexport interface ControlledAutocompleteProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseAutocompleteProps<TValue> {\n value: TValue | TValue[] | null;\n onChange: (val: TValue | TValue[] | null) => void;\n name?: string;\n control?: never;\n validation?: never;\n}\n\nexport interface RHFAutocompleteProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> extends BaseAutocompleteProps<TValue> {\n name: string;\n control: Control<any>;\n validation?: RegisterOptions;\n value?: never;\n onChange?: never;\n}\n\n// ── API pública final ────────────────────────────────────────────────────\nexport type AutocompleteProps<\n TValue extends SelectOption['value'] = SelectOption['value'],\n> = ControlledAutocompleteProps<TValue> | RHFAutocompleteProps<TValue>;\n\nexport function Autocomplete<\n TValue extends SelectOption['value'] = SelectOption['value'],\n>(props: AutocompleteProps<TValue>) {\n const {\n label,\n options,\n placeholder,\n multiple = false,\n disabled = false,\n readOnly = false,\n loading = false,\n error: errorProp = false,\n helperText,\n maxChipsToShow = 3,\n renderOptionItem,\n renderChipLabel,\n borderRadius = 10,\n labelPosition = 'outside',\n size = 'small',\n noOptionsText = 'No hay opciones',\n loadingText,\n sx,\n className,\n preset,\n textFieldProps,\n onInputChange,\n inputValue,\n filterOptions,\n freeSolo,\n open,\n onOpen,\n onClose,\n } = props as BaseAutocompleteProps<TValue>;\n\n // Focus tracking para mostrar placeholder solo cuando el label sube.\n const [isFocused, setIsFocused] = useState(false);\n\n // Cache interno de opciones vistas (indexado por value). Crítico para async\n // multiple: cuando `options` cambian por un nuevo search, los items ya\n // seleccionados no desaparecen de los chips porque los recordamos acá.\n const seenOptionsRef = useRef<Map<SelectOption['value'], SelectOption>>(\n new Map(),\n );\n for (const opt of options) {\n seenOptionsRef.current.set(opt.value, opt);\n }\n\n // Pool de opciones para resolver values (merge de options + vistas).\n const resolvePool = useMemo<SelectOption[]>(() => {\n const merged = new Map(seenOptionsRef.current);\n for (const opt of options) merged.set(opt.value, opt);\n return Array.from(merged.values());\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [options]);\n\n // Estabiliza la referencia del resolvedValue que pasamos a MUI Autocomplete.\n // MUI compara value con `!==`: una referencia nueva con mismo contenido\n // dispara resetInputValue() y borra el texto que el usuario está escribiendo.\n const prevResolvedRef = useRef<SelectOption[] | SelectOption | null>(\n multiple ? [] : null,\n );\n\n const stabilizeResolved = (\n newVal: SelectOption[] | SelectOption | null,\n ): any => {\n if (areResolvedValuesEqual(prevResolvedRef.current, newVal, multiple)) {\n return prevResolvedRef.current;\n }\n prevResolvedRef.current = newVal;\n return newVal;\n };\n\n const theme = useTheme();\n const presetSx = resolvePreset('Autocomplete', preset, theme);\n\n const mergedSx = [\n buildAutocompleteSx(borderRadius, labelPosition),\n ...(presetSx ? [presetSx] : []),\n ...(Array.isArray(sx) ? sx : sx ? [sx] : []),\n ];\n\n const renderAutocomplete = (\n resolvedValue: any,\n handleChange: (event: any, newValue: any) => void,\n onBlur?: () => void,\n inputRef?: React.Ref<any>,\n rhfError?: boolean,\n rhfHelperText?: string,\n ) => {\n const finalError = !!rhfError || !!errorProp;\n const finalHelperText = rhfHelperText || helperText;\n\n const isEmpty = isResolvedValueEmpty(resolvedValue, multiple);\n const showPlaceholder = isEmpty && isFocused && !!placeholder;\n\n return (\n <MuiAutocomplete\n multiple={multiple}\n options={options}\n value={resolvedValue}\n disabled={disabled}\n readOnly={readOnly}\n loading={loading}\n className={className}\n sx={mergedSx}\n freeSolo={freeSolo as any}\n open={open}\n onOpen={onOpen}\n onClose={onClose}\n inputValue={inputValue}\n onInputChange={onInputChange}\n filterOptions={filterOptions as any}\n getOptionLabel={(opt) =>\n typeof opt === 'string' ? opt : (opt?.label ?? '')\n }\n isOptionEqualToValue={(a, b) => a?.value === b?.value}\n getOptionDisabled={(opt) => !!opt?.disabled}\n onChange={handleChange}\n onFocus={() => setIsFocused(true)}\n onBlur={() => {\n setIsFocused(false);\n onBlur?.();\n }}\n renderOption={(liProps, option) => (\n <AutocompleteOption\n liProps={liProps as any}\n option={option}\n customRender={renderOptionItem}\n />\n )}\n renderTags={\n multiple\n ? (value, getTagProps) => (\n <AutocompleteChips\n value={value}\n getTagProps={getTagProps}\n size={size}\n maxChipsToShow={maxChipsToShow}\n renderChipLabel={renderChipLabel}\n />\n )\n : undefined\n }\n noOptionsText={noOptionsText}\n loadingText={loadingText ?? <AutocompleteLoader />}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n size={size}\n variant=\"outlined\"\n placeholder={showPlaceholder ? placeholder : undefined}\n error={finalError}\n helperText={finalHelperText}\n inputRef={inputRef}\n {...textFieldProps}\n InputLabelProps={{\n ...(params.InputLabelProps as Record<string, any>),\n ...(textFieldProps?.InputLabelProps as Record<string, any> | undefined),\n shrink:\n labelPosition === 'outside'\n ? !isEmpty || isFocused\n : (params.InputLabelProps as any)?.shrink,\n }}\n />\n )}\n />\n );\n };\n\n const handleControlledChange = (_event: any, newValue: any) => {\n const onChange = (props as ControlledAutocompleteProps<TValue>).onChange;\n if (multiple) {\n const values = (newValue ?? []).map((opt: SelectOption) => opt.value as TValue);\n onChange(values);\n } else {\n onChange((newValue?.value ?? null) as TValue | null);\n }\n };\n\n // --- RHF mode ---\n if ('control' in props && props.control) {\n const { name, control, validation } = props as RHFAutocompleteProps<TValue>;\n return (\n <Controller\n name={name}\n control={control}\n rules={validation}\n render={({ field, fieldState: { error: fieldError } }) => {\n const resolvedValue = stabilizeResolved(\n multiple\n ? resolveMultipleValue(resolvePool, field.value)\n : resolveSingleValue(resolvePool, field.value),\n );\n\n const handleChange = (_event: any, newValue: any) => {\n if (multiple) {\n field.onChange(\n (newValue ?? []).map((opt: SelectOption) => opt.value),\n );\n } else {\n field.onChange(newValue?.value ?? null);\n }\n };\n\n return renderAutocomplete(\n resolvedValue,\n handleChange,\n field.onBlur,\n field.ref,\n !!fieldError,\n fieldError?.message,\n );\n }}\n />\n );\n }\n\n // --- Controlled mode ---\n const controlledValue = (props as ControlledAutocompleteProps<TValue>).value;\n const resolvedValue = stabilizeResolved(\n multiple\n ? resolveMultipleValue(resolvePool, controlledValue as SelectOption['value'][])\n : resolveSingleValue(resolvePool, controlledValue as SelectOption['value']),\n );\n\n return renderAutocomplete(resolvedValue, handleControlledChange);\n}\n\n/**\n * @deprecated Usar `Autocomplete` en su lugar. Alias mantenido para retro-compatibilidad.\n */\nexport const AutocompleteSelect = Autocomplete;\n\nexport default Autocomplete;\n"],"names":["resolvedValue","MuiAutocomplete"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AASO,MAAM,sBAAsB,CACjC,cACA,kBAEA,iBAAiB;AAAA,EACf;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA;AAAA,IAEd,4BAA4B;AAAA,MAC1B,YAAY;AAAA,MACZ,eAAe;AAAA,IAAA;AAAA;AAAA,IAIjB,gCAAgC;AAAA,MAC9B,YAAY;AAAA,MACZ,eAAe;AAAA,IAAA;AAAA,EACjB;AAEJ,CAAC;ACzBI,MAAM,qBAAqB,CAChC,SACA,UAAA;;AACwB,uBAAQ,KAAK,CAAC,MAAM,EAAE,UAAU,KAAK,MAArC,YAA0C;AAAA;AAG7D,MAAM,uBAAuB,CAClC,SACA,UACmB;AACnB,MAAI,CAAC,MAAM,QAAQ,KAAK,UAAU,CAAA;AAClC,SAAO,QAAQ,OAAO,CAAC,MAAM,MAAM,SAAS,EAAE,KAAK,CAAC;AACtD;AAkBO,MAAM,yBAAyB,CACpC,MACA,MACA,aACY;AACZ,MAAI,UAAU;AACZ,QAAI,CAAC,MAAM,QAAQ,IAAI,KAAK,CAAC,MAAM,QAAQ,IAAI,EAAG,QAAO;AACzD,QAAI,KAAK,WAAW,KAAK,OAAQ,QAAO;AACxC,WAAO,KAAK,MAAM,CAAC,GAAG,MAAA;;AAAM,eAAE,YAAU,UAAK,CAAC,MAAN,mBAAS;AAAA,KAAK;AAAA,EACxD;AACA,UACG,6BAA8B,YAC9B,6BAA8B;AAEnC;AAGO,MAAM,uBAAuB,CAClC,eACA,aACY;AACZ,MAAI,UAAU;AACZ,WAAO,CAAC,MAAM,QAAQ,aAAa,KAAK,cAAc,WAAW;AAAA,EACnE;AACA,SAAO,CAAC;AACV;AC1CO,MAAM,qBAAwD,CAAC;AAAA,EACpE;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAqC,cAA7B,OAAK,aAAwB,IAAX,mBAAW,IAAX,CAAlB;AACR,SACE,oBAAC,MAAA,iCAA0B,SAA1B,EACE,UAAA,eAAe,aAAa,MAAM,IAAI,OAAO,MAAA,IADvC,OAAO,KAEhB;AAEJ;ACJO,MAAM,oBAAsD,CAAC;AAAA,EAClE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,YAAY,MAAM,MAAM,GAAG,cAAc;AAC/C,QAAM,SAAS,MAAM,SAAS;AAE9B,SACE,qBAAA,UAAA,EACG,UAAA;AAAA,IAAA,UAAU,IAAI,CAAC,QAAQ,UAAU;AAChC,YAAM,WAAW,YAAY,EAAE,OAAO;AACtC,aACE;AAAA,QAAC;AAAA,QAAA,iCACK,WADL;AAAA,UAEC,KAAK,OAAO;AAAA,UACZ;AAAA,UACA,OAAO,kBAAkB,gBAAgB,MAAM,IAAI,OAAO;AAAA,UAC1D,QAAQ,OAAO,MAAM,oBAAC,UAAO,KAAK,OAAO,KAAK,IAAK;AAAA,UACnD,gCAAa,WAAA,CAAA,CAAU;AAAA,QAAA;AAAA,MAAA;AAAA,IAG7B,CAAC;AAAA,IACA,SAAS,KAAK,oBAAC,MAAA,EAAK,MAAY,OAAO,IAAI,MAAM,OAAA,CAAQ;AAAA,EAAA,GAC5D;AAEJ;AC7CO,MAAM,qBAAkD,CAAC;AAAA,EAC9D,OAAO;AACT,MACE,qBAAC,KAAA,EAAI,IAAI,EAAE,SAAS,QAAQ,YAAY,UAAU,KAAK,EAAA,GACrD,UAAA;AAAA,EAAA,oBAAC,kBAAA,EAAiB,MAAM,GAAA,CAAI;AAAA,EAC5B,oBAAC,YAAA,EAAW,SAAQ,SAAS,UAAA,KAAA,CAAK;AAAA,GACpC;ACiHK,SAAS,aAEd,OAAkC;AAClC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,WAAW;AAAA,IACX,WAAW;AAAA,IACX,UAAU;AAAA,IACV,OAAO,YAAY;AAAA,IACnB;AAAA,IACA,iBAAiB;AAAA,IACjB;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,OAAO;AAAA,IACP,gBAAgB;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,IACE;AAGJ,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAKhD,QAAM,iBAAiB;AAAA,wBACjB,IAAA;AAAA,EAAI;AAEV,aAAW,OAAO,SAAS;AACzB,mBAAe,QAAQ,IAAI,IAAI,OAAO,GAAG;AAAA,EAC3C;AAGA,QAAM,cAAc,QAAwB,MAAM;AAChD,UAAM,SAAS,IAAI,IAAI,eAAe,OAAO;AAC7C,eAAW,OAAO,QAAS,QAAO,IAAI,IAAI,OAAO,GAAG;AACpD,WAAO,MAAM,KAAK,OAAO,OAAA,CAAQ;AAAA,EAEnC,GAAG,CAAC,OAAO,CAAC;AAKZ,QAAM,kBAAkB;AAAA,IACtB,WAAW,CAAA,IAAK;AAAA,EAAA;AAGlB,QAAM,oBAAoB,CACxB,WACQ;AACR,QAAI,uBAAuB,gBAAgB,SAAS,QAAQ,QAAQ,GAAG;AACrE,aAAO,gBAAgB;AAAA,IACzB;AACA,oBAAgB,UAAU;AAC1B,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,SAAA;AACd,QAAM,WAAW,cAAc,gBAAgB,QAAQ,KAAK;AAE5D,QAAM,WAAW;AAAA,IACf,oBAAoB,cAAc,aAAa;AAAA,IAC/C,GAAI,WAAW,CAAC,QAAQ,IAAI,CAAA;AAAA,IAC5B,GAAI,MAAM,QAAQ,EAAE,IAAI,KAAK,KAAK,CAAC,EAAE,IAAI,CAAA;AAAA,EAAC;AAG5C,QAAM,qBAAqB,CACzBA,gBACA,cACA,QACA,UACA,UACA,kBACG;AACH,UAAM,aAAa,CAAC,CAAC,YAAY,CAAC,CAAC;AACnC,UAAM,kBAAkB,iBAAiB;AAEzC,UAAM,UAAU,qBAAqBA,gBAAe,QAAQ;AAC5D,UAAM,kBAAkB,WAAW,aAAa,CAAC,CAAC;AAElD,WACE;AAAA,MAACC;AAAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,OAAOD;AAAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,gBAAgB,CAAC,QAAA;;AACf,wBAAO,QAAQ,WAAW,OAAO,gCAAK,UAAL,YAAc;AAAA;AAAA,QAEjD,sBAAsB,CAAC,GAAG,OAAM,uBAAG,YAAU,uBAAG;AAAA,QAChD,mBAAmB,CAAC,QAAQ,CAAC,EAAC,2BAAK;AAAA,QACnC,UAAU;AAAA,QACV,SAAS,MAAM,aAAa,IAAI;AAAA,QAChC,QAAQ,MAAM;AACZ,uBAAa,KAAK;AAClB;AAAA,QACF;AAAA,QACA,cAAc,CAAC,SAAS,WACtB;AAAA,UAAC;AAAA,UAAA;AAAA,YACC;AAAA,YACA;AAAA,YACA,cAAc;AAAA,UAAA;AAAA,QAAA;AAAA,QAGlB,YACE,WACI,CAAC,OAAO,gBACN;AAAA,UAAC;AAAA,UAAA;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UAAA;AAAA,QAAA,IAGJ;AAAA,QAEN;AAAA,QACA,aAAa,oCAAe,oBAAC,oBAAA,CAAA,CAAmB;AAAA,QAChD,aAAa,CAAC;;AACZ;AAAA,YAAC;AAAA,YAAA,8DACK,SADL;AAAA,cAEC;AAAA,cACA;AAAA,cACA,SAAQ;AAAA,cACR,aAAa,kBAAkB,cAAc;AAAA,cAC7C,OAAO;AAAA,cACP,YAAY;AAAA,cACZ;AAAA,gBACI,iBATL;AAAA,cAUC,iBAAiB,gDACX,OAAO,kBACP,iDAAgB,kBAFL;AAAA,gBAGf,QACE,kBAAkB,YACd,CAAC,WAAW,aACX,YAAO,oBAAP,mBAAgC;AAAA,cAAA;AAAA,YACzC;AAAA,UAAA;AAAA;AAAA,MACF;AAAA,IAAA;AAAA,EAIR;AAEA,QAAM,yBAAyB,CAAC,QAAa,aAAkB;;AAC7D,UAAM,WAAY,MAA8C;AAChE,QAAI,UAAU;AACZ,YAAM,UAAU,8BAAY,CAAA,GAAI,IAAI,CAAC,QAAsB,IAAI,KAAe;AAC9E,eAAS,MAAM;AAAA,IACjB,OAAO;AACL,gBAAU,0CAAU,UAAV,YAAmB,IAAsB;AAAA,IACrD;AAAA,EACF;AAGA,MAAI,aAAa,SAAS,MAAM,SAAS;AACvC,UAAM,EAAE,MAAM,SAAS,WAAA,IAAe;AACtC,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,OAAO;AAAA,QACP,QAAQ,CAAC,EAAE,OAAO,YAAY,EAAE,OAAO,WAAA,QAAmB;AACxD,gBAAMA,iBAAgB;AAAA,YACpB,WACI,qBAAqB,aAAa,MAAM,KAAK,IAC7C,mBAAmB,aAAa,MAAM,KAAK;AAAA,UAAA;AAGjD,gBAAM,eAAe,CAAC,QAAa,aAAkB;;AACnD,gBAAI,UAAU;AACZ,oBAAM;AAAA,iBACH,8BAAY,CAAA,GAAI,IAAI,CAAC,QAAsB,IAAI,KAAK;AAAA,cAAA;AAAA,YAEzD,OAAO;AACL,oBAAM,UAAS,0CAAU,UAAV,YAAmB,IAAI;AAAA,YACxC;AAAA,UACF;AAEA,iBAAO;AAAA,YACLA;AAAAA,YACA;AAAA,YACA,MAAM;AAAA,YACN,MAAM;AAAA,YACN,CAAC,CAAC;AAAA,YACF,yCAAY;AAAA,UAAA;AAAA,QAEhB;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AAGA,QAAM,kBAAmB,MAA8C;AACvE,QAAM,gBAAgB;AAAA,IACpB,WACI,qBAAqB,aAAa,eAA0C,IAC5E,mBAAmB,aAAa,eAAwC;AAAA,EAAA;AAG9E,SAAO,mBAAmB,eAAe,sBAAsB;AACjE;AAKO,MAAM,qBAAqB;"}
1
+ {"version":3,"file":"Autocomplete.js","sources":["../../../src/components/Autocomplete/Autocomplete.sx.ts","../../../src/components/Autocomplete/Autocomplete.helpers.ts","../../../src/components/Autocomplete/_parts/AutocompleteOption.tsx","../../../src/components/Autocomplete/_parts/AutocompleteChips.tsx","../../../src/components/Autocomplete/_parts/AutocompleteLoader.tsx","../../../src/components/Autocomplete/Autocomplete.tsx"],"sourcesContent":["import type { SxProps, Theme } from '@mui/material/styles';\n\nimport { buildFormFieldSx } from '../_shared/formField.sx';\nimport type { LabelPosition } from './Autocomplete';\n\n/**\n * Builder del sx del Autocomplete. Reutiliza `buildFormFieldSx` y añade\n * los paddings propios del Autocomplete (chips + input interno).\n */\nexport const buildAutocompleteSx = (\n borderRadius: number | string,\n labelPosition: LabelPosition,\n): SxProps<Theme> =>\n buildFormFieldSx({\n borderRadius,\n labelPosition,\n extraOutsideSx: {\n // El input interno del Autocomplete.\n '& .MuiAutocomplete-input': {\n paddingTop: '4px',\n paddingBottom: '4px',\n },\n\n // Contenedor del input (donde viven los chips en modo multiple).\n '& .MuiAutocomplete-inputRoot': {\n paddingTop: '4px',\n paddingBottom: '4px',\n },\n },\n });\n","import type { SxProps, Theme } from '@mui/material/styles';\nimport type { AutocompleteValueKey, SelectOption } from './Autocomplete';\n\n/** Resuelve un value único a su SelectOption dentro del pool. */\nexport const resolveSingleValue = <TValue,>(\n options: SelectOption<TValue>[],\n value: TValue | null | undefined,\n getKey: (v: TValue) => AutocompleteValueKey,\n): SelectOption<TValue> | null => {\n if (value === null || value === undefined) return null;\n const key = getKey(value);\n return options.find((o) => getKey(o.value) === key) ?? null;\n};\n\n/** Resuelve un array de values a sus SelectOption dentro del pool. */\nexport const resolveMultipleValue = <TValue,>(\n options: SelectOption<TValue>[],\n value: TValue[] | null | undefined,\n getKey: (v: TValue) => AutocompleteValueKey,\n): SelectOption<TValue>[] => {\n if (!Array.isArray(value)) return [];\n const keys = new Set(value.map(getKey));\n return options.filter((o) => keys.has(getKey(o.value)));\n};\n\n/** Merge de sx base + extra del consumer, respetando el contrato de MUI. */\nexport const mergeSx = (\n base: SxProps<Theme>,\n extra?: SxProps<Theme>,\n): SxProps<Theme> => {\n if (!extra) return base;\n return [base, ...(Array.isArray(extra) ? extra : [extra])] as SxProps<Theme>;\n};\n\n/**\n * Compara dos SelectOption por todas sus props (shallow). Se usa para detectar\n * cambios de metadata (p.ej. `label`, `img`) cuando `value` no cambió, para\n * que la estabilización no tape datos frescos del server. Para `value` se\n * compara vía `getKey` (no por `===`), de modo que values objeto con misma\n * identidad lógica pero referencia distinta no rompan la estabilización.\n */\nconst areOptionsShallowEqual = <TValue,>(\n a: SelectOption<TValue>,\n b: SelectOption<TValue>,\n getKey: (v: TValue) => AutocompleteValueKey,\n): boolean => {\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n return keysA.every((k) => {\n if (k === 'value') return getKey(a.value) === getKey(b.value);\n return a[k] === b[k];\n });\n};\n\n/**\n * Compara dos valores resueltos (single o multiple) estructuralmente para\n * decidir si se puede reusar la referencia previa. Se usa para estabilizar la\n * referencia que se pasa a MUI Autocomplete (MUI compara value por referencia\n * con `!==`, y una nueva referencia — aunque el contenido sea igual — dispara\n * `resetInputValue` y borra el texto mientras el usuario tipea).\n *\n * Comparamos todas las props del SelectOption, no solo `value`, para que un\n * refresh de metadata (label/img/etc.) invalide la referencia estabilizada\n * y la UI muestre los datos actualizados.\n */\nexport const areResolvedValuesEqual = <TValue,>(\n prev: SelectOption<TValue> | SelectOption<TValue>[] | null,\n next: SelectOption<TValue> | SelectOption<TValue>[] | null,\n multiple: boolean,\n getKey: (v: TValue) => AutocompleteValueKey,\n): boolean => {\n if (multiple) {\n if (!Array.isArray(prev) || !Array.isArray(next)) return false;\n if (prev.length !== next.length) return false;\n return prev.every((o, i) => {\n const n = next[i];\n return !!n && areOptionsShallowEqual(o, n, getKey);\n });\n }\n const p = prev as SelectOption<TValue> | null;\n const n = next as SelectOption<TValue> | null;\n if (p === n) return true;\n if (!p || !n) return false;\n return areOptionsShallowEqual(p, n, getKey);\n};\n\n/** Determina si un valor resuelto está vacío (para placeholder/shrink). */\nexport const isResolvedValueEmpty = (\n resolvedValue: unknown,\n multiple: boolean,\n): boolean => {\n if (multiple) {\n return !Array.isArray(resolvedValue) || resolvedValue.length === 0;\n }\n return !resolvedValue;\n};\n","import React from 'react';\nimport type {\n AutocompleteValueKey,\n RenderOptionItem,\n SelectOption,\n} from '../Autocomplete';\n\ninterface AutocompleteOptionProps<TValue = AutocompleteValueKey> {\n liProps: React.HTMLAttributes<HTMLLIElement>;\n option: SelectOption<TValue>;\n customRender?: RenderOptionItem<TValue>;\n}\n\n/**\n * Render por defecto de un `<li>` del dropdown del Autocomplete.\n * MUI lo invoca desde `renderOption={(props, option) => ...}` en el padre.\n *\n * La `key` la maneja el padre (`renderOption` en Autocomplete.tsx). Este\n * componente solo recibe los props restantes del `<li>` para spread.\n */\nexport const AutocompleteOption = <TValue,>({\n liProps,\n option,\n customRender,\n}: AutocompleteOptionProps<TValue>) => {\n return (\n <li {...liProps}>\n {customRender ? customRender(option) : option.label}\n </li>\n );\n};\n\nexport default AutocompleteOption;\n","import { Avatar, Chip } from '@mui/material';\nimport ClearIcon from '@mui/icons-material/Clear';\n\nimport type {\n AutocompleteSize,\n AutocompleteValueKey,\n RenderChipLabel,\n SelectOption,\n} from '../Autocomplete';\n\ninterface AutocompleteChipsProps<TValue = AutocompleteValueKey> {\n value: SelectOption<TValue>[];\n getTagProps: (args: { index: number }) => Record<string, any>;\n size: AutocompleteSize;\n maxChipsToShow: number;\n renderChipLabel?: RenderChipLabel<TValue>;\n /** Extrae la React key estable a partir del value (necesario para values objeto). */\n getKey: (value: TValue) => AutocompleteValueKey;\n}\n\n/**\n * Render de los chips del Autocomplete en modo multiple.\n * Trunca después de `maxChipsToShow` con un chip \"+N más\".\n * El `getTagProps({ index })` viene de MUI y contiene el handler de delete,\n * la key, etc. — se spreadea tal cual al Chip.\n */\nexport const AutocompleteChips = <TValue,>({\n value,\n getTagProps,\n size,\n maxChipsToShow,\n renderChipLabel,\n getKey,\n}: AutocompleteChipsProps<TValue>) => {\n const displayed = value.slice(0, maxChipsToShow);\n const hidden = value.length - maxChipsToShow;\n\n return (\n <>\n {displayed.map((option, index) => {\n const { key: _ignored, ...tagProps } = getTagProps({ index });\n return (\n <Chip\n key={getKey(option.value)}\n {...tagProps}\n size={size}\n label={renderChipLabel ? renderChipLabel(option) : option.label}\n avatar={option.img ? <Avatar src={option.img} /> : undefined}\n deleteIcon={<ClearIcon />}\n />\n );\n })}\n {hidden > 0 && <Chip size={size} label={`+${hidden} más`} />}\n </>\n );\n};\n\nexport default AutocompleteChips;\n","import React from 'react';\nimport { Box, CircularProgress, Typography } from '@mui/material';\n\n/**\n * Loader por defecto para el `loadingText` del Autocomplete.\n * El consumer puede sobrescribirlo pasando `loadingText` al componente padre.\n */\nexport const AutocompleteLoader: React.FC<{ text?: string }> = ({\n text = 'Cargando...',\n}) => (\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>\n <CircularProgress size={16} />\n <Typography variant=\"body2\">{text}</Typography>\n </Box>\n);\n\nexport default AutocompleteLoader;\n","import React, {\n useMemo,\n useRef,\n useState,\n type ReactNode,\n type SyntheticEvent,\n} from 'react';\nimport {\n Autocomplete as MuiAutocomplete,\n TextField,\n type TextFieldProps,\n} from '@mui/material';\nimport { useTheme, type SxProps, type Theme } from '@mui/material/styles';\n\nimport { buildAutocompleteSx } from './Autocomplete.sx';\nimport {\n areResolvedValuesEqual,\n isResolvedValueEmpty,\n resolveMultipleValue,\n resolveSingleValue,\n} from './Autocomplete.helpers';\nimport { resolvePreset } from '../_shared/resolvePreset';\nimport { AutocompleteOption } from './_parts/AutocompleteOption';\nimport { AutocompleteChips } from './_parts/AutocompleteChips';\nimport { AutocompleteLoader } from './_parts/AutocompleteLoader';\n\n// ── Tipos de dominio ─────────────────────────────────────────────────────\n/** Key estable usada para comparar values, indexar caches y como React key. */\nexport type AutocompleteValueKey = string | number;\n\nexport interface SelectOption<TValue = AutocompleteValueKey> {\n value: TValue;\n label: string;\n img?: string;\n disabled?: boolean;\n group?: string;\n [key: string]: any; //campos extras que puede tener la opcion\n}\n\nexport type LabelPosition = 'outside' | 'floating';\nexport type AutocompleteSize = 'small' | 'medium';\n\n// ── Render slots ─────────────────────────────────────────────────────────\nexport type RenderOptionItem<TValue = AutocompleteValueKey> = (\n item: SelectOption<TValue>,\n) => ReactNode;\nexport type RenderChipLabel<TValue = AutocompleteValueKey> = (\n item: SelectOption<TValue>,\n) => ReactNode;\nexport type RenderSingleValue<TValue = AutocompleteValueKey> = (\n item: SelectOption<TValue>,\n) => ReactNode;\n\n// ── Props base ───────────────────────────────────────────────────────────\nexport type BaseAutocompleteProps<TValue = AutocompleteValueKey> = {\n label?: string;\n options: SelectOption<TValue>[];\n placeholder?: string;\n multiple?: boolean;\n disabled?: boolean;\n readOnly?: boolean;\n loading?: boolean;\n error?: boolean;\n helperText?: string;\n maxChipsToShow?: number;\n renderOptionItem?: RenderOptionItem<TValue>;\n renderChipLabel?: RenderChipLabel<TValue>;\n /**\n * Renderiza JSX custom como `startAdornment` del input en single mode.\n * Recibe la `SelectOption` seleccionada. Útil para mostrar avatars, iconos,\n * etc. junto al texto del label. En `multiple` no aplica (se usa `renderChipLabel`).\n */\n renderSingleValue?: RenderSingleValue<TValue>;\n /**\n * Extrae una key estable (string | number) desde el `value`. Obligatorio\n * cuando `TValue` es un objeto: se usa para comparar values (`isOptionEqualToValue`,\n * resolución desde el value del form), indexar el cache interno de opciones\n * vistas y como React key en chips/options del dropdown. Para primitivos se\n * puede omitir (default: identidad, o sea `===`).\n */\n getOptionKey?: (value: TValue) => AutocompleteValueKey;\n /** Border radius del input. Default: 10. */\n borderRadius?: number | string;\n /** \"outside\" (default) = label arriba del input; \"floating\" = comportamiento nativo MUI. */\n labelPosition?: LabelPosition;\n /** Tamaño del TextField. Default: 'small'. */\n size?: AutocompleteSize;\n /** Texto cuando no hay coincidencias. */\n noOptionsText?: ReactNode;\n /** Texto cuando está cargando. */\n loadingText?: ReactNode;\n sx?: SxProps<Theme>;\n /**\n * Nombre del preset de estilo registrado en `theme.styles.Autocomplete`.\n * - `\"default\"` (o ausente) = estilo built-in del paquete.\n * - Cualquier otro string = mergea el preset encima del estilo built-in.\n */\n preset?: string;\n /** Props para el TextField subyacente. */\n textFieldProps?: Partial<TextFieldProps>;\n\n // ── Búsqueda asíncrona / remota ──────────────────────────────────────\n /** Se dispara cada vez que el usuario escribe. Útil para llamadas a servicios\n * (debounce recomendado en el consumer). */\n onInputChange?: (\n event: SyntheticEvent,\n value: string,\n reason: 'input' | 'reset' | 'clear' | 'blur' | 'selectOption' | 'removeOption',\n ) => void;\n /** Valor controlado del texto de búsqueda. */\n inputValue?: string;\n /** Filtro custom. Para búsqueda remota pasar `(x) => x` y confiar sólo en el servicio. */\n filterOptions?: (\n options: SelectOption<TValue>[],\n state: any,\n ) => SelectOption<TValue>[];\n /** Permite valores arbitrarios (no solo de la lista). */\n freeSolo?: boolean;\n open?: boolean;\n onOpen?: (event: SyntheticEvent) => void;\n onClose?: (event: SyntheticEvent, reason: string) => void;\n};\n\n// ── API pública final ────────────────────────────────────────────────────\nexport interface AutocompleteProps<TValue = AutocompleteValueKey>\n extends BaseAutocompleteProps<TValue> {\n value: TValue | TValue[] | null;\n onChange: (val: TValue | TValue[] | null) => void;\n name?: string;\n}\n\nexport function Autocomplete<TValue = AutocompleteValueKey>(\n props: AutocompleteProps<TValue>,\n) {\n const {\n label,\n options,\n placeholder,\n multiple = false,\n disabled = false,\n readOnly = false,\n loading = false,\n error: errorProp = false,\n helperText,\n maxChipsToShow = 3,\n renderOptionItem,\n renderChipLabel,\n renderSingleValue,\n borderRadius = 10,\n labelPosition = 'outside',\n size = 'small',\n noOptionsText = 'No hay opciones',\n loadingText,\n sx,\n preset,\n textFieldProps,\n onInputChange,\n inputValue,\n filterOptions,\n freeSolo,\n open,\n onOpen,\n onClose,\n getOptionKey,\n } = props as BaseAutocompleteProps<TValue>;\n\n // Default identidad: para primitivos (string|number) funciona como `===`.\n // Para values objeto, el consumer DEBE pasar `getOptionKey` o la igualdad\n // caerá a referencia (Map/Set agruparían por identidad).\n const getKey = (getOptionKey ??\n ((v: TValue) => v as unknown as AutocompleteValueKey)) as (\n v: TValue,\n ) => AutocompleteValueKey;\n\n // Focus tracking para mostrar placeholder solo cuando el label sube.\n const [isFocused, setIsFocused] = useState(false);\n\n // Cache interno de opciones vistas (indexado por key estable). Crítico para\n // async multiple: cuando `options` cambian por un nuevo search, los items\n // ya seleccionados no desaparecen de los chips porque los recordamos acá.\n const seenOptionsRef = useRef<\n Map<AutocompleteValueKey, SelectOption<TValue>>\n >(new Map());\n for (const opt of options) {\n seenOptionsRef.current.set(getKey(opt.value), opt);\n }\n\n // Pool de opciones para resolver values (merge de options + vistas).\n const resolvePool = useMemo<SelectOption<TValue>[]>(() => {\n const merged = new Map(seenOptionsRef.current);\n for (const opt of options) merged.set(getKey(opt.value), opt);\n return Array.from(merged.values());\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [options]);\n\n // Estabiliza la referencia del resolvedValue que pasamos a MUI Autocomplete.\n // MUI compara value con `!==`: una referencia nueva con mismo contenido\n // dispara resetInputValue() y borra el texto que el usuario está escribiendo.\n const prevResolvedRef = useRef<\n SelectOption<TValue>[] | SelectOption<TValue> | null\n >(multiple ? [] : null);\n\n const stabilizeResolved = (\n newVal: SelectOption<TValue>[] | SelectOption<TValue> | null,\n ): SelectOption<TValue>[] | SelectOption<TValue> | null => {\n if (\n areResolvedValuesEqual(prevResolvedRef.current, newVal, multiple, getKey)\n ) {\n return prevResolvedRef.current;\n }\n prevResolvedRef.current = newVal;\n return newVal;\n };\n\n const theme = useTheme();\n const presetSx = resolvePreset('Autocomplete', preset, theme);\n\n const mergedSx = [\n buildAutocompleteSx(borderRadius, labelPosition),\n ...(presetSx ? [presetSx] : []),\n ...(Array.isArray(sx) ? sx : sx ? [sx] : []),\n ];\n\n const renderAutocomplete = (\n resolvedValue: any,\n handleChange: (event: any, newValue: any) => void,\n ) => {\n const isEmpty = isResolvedValueEmpty(resolvedValue, multiple);\n const showPlaceholder = isEmpty && isFocused && !!placeholder;\n const singleAdornment =\n !multiple && resolvedValue && renderSingleValue\n ? renderSingleValue(resolvedValue as SelectOption<TValue>)\n : null;\n\n return (\n <MuiAutocomplete\n multiple={multiple}\n options={options}\n value={resolvedValue}\n disabled={disabled}\n readOnly={readOnly}\n loading={loading}\n sx={mergedSx}\n freeSolo={freeSolo as any}\n open={open}\n onOpen={onOpen}\n onClose={onClose}\n inputValue={inputValue}\n onInputChange={onInputChange}\n filterOptions={filterOptions as any}\n getOptionLabel={(opt) =>\n typeof opt === 'string' ? opt : (opt?.label ?? '')\n }\n isOptionEqualToValue={(a, b) => {\n if (typeof a === 'string' || typeof b === 'string') return a === b;\n if (!a || !b) return a === b;\n return getKey(a.value) === getKey(b.value);\n }}\n getOptionDisabled={(opt) =>\n typeof opt === 'string' ? false : !!opt?.disabled\n }\n onChange={handleChange}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n renderOption={(liProps, option) => {\n // MUI inyecta la `key` dentro de `liProps`. React necesita la key\n // en el elemento más externo que devuelve `renderOption` (acá el\n // wrapper), no en el `<li>` interno. El resto de `liProps` viaja\n // al `<li>`. La key auto-generada por MUI cae a `getOptionLabel`,\n // que colisiona si hay opciones con label duplicado. Usamos\n // `option.value` (único por contrato de SelectOption) para\n // garantizar uniqueness aunque haya labels repetidos.\n const { key: _muiKey, ...liRest } = liProps as React.HTMLAttributes<HTMLLIElement> & {\n key?: React.Key;\n };\n return (\n <AutocompleteOption<TValue>\n key={getKey(option.value)}\n liProps={liRest}\n option={option}\n customRender={renderOptionItem}\n />\n );\n }}\n renderValue={\n multiple\n ? (value, getItemProps) => (\n <AutocompleteChips<TValue>\n value={value as SelectOption<TValue>[]}\n getTagProps={getItemProps}\n size={size}\n maxChipsToShow={maxChipsToShow}\n renderChipLabel={renderChipLabel}\n getKey={getKey}\n />\n )\n : undefined\n }\n noOptionsText={noOptionsText}\n loadingText={loadingText ?? <AutocompleteLoader />}\n renderInput={(params) => {\n const paramsInputLabel =\n (params as any).InputLabelProps as Record<string, any> | undefined;\n const consumerInputLabel =\n (textFieldProps?.slotProps as any)?.inputLabel ??\n (textFieldProps as any)?.InputLabelProps;\n // Para inyectar `singleAdornment` necesitamos pasar `slotProps.input`\n // a TextField, pero `slotProps.input` gana sobre `params.InputProps`\n // (que trae endAdornment con chevron + clear). Por eso, cuando hay\n // adornment custom, mergeamos params.InputProps + lo que el consumer\n // haya pasado por textFieldProps + nuestro startAdornment. Si no hay\n // adornment, no tocamos `slotProps.input` y se preserva el flujo legacy.\n const muiInputProps = (params as any).InputProps as\n | Record<string, any>\n | undefined;\n const consumerInputProps =\n (textFieldProps?.slotProps as any)?.input ??\n (textFieldProps as any)?.InputProps;\n const inputSlot = singleAdornment\n ? {\n ...muiInputProps,\n ...consumerInputProps,\n startAdornment: (\n <>\n {singleAdornment}\n {consumerInputProps?.startAdornment}\n {muiInputProps?.startAdornment}\n </>\n ),\n }\n : undefined;\n\n return (\n <TextField\n {...params}\n label={label}\n size={size}\n variant=\"outlined\"\n placeholder={showPlaceholder ? placeholder : undefined}\n error={!!errorProp}\n helperText={helperText}\n {...textFieldProps}\n slotProps={{\n ...textFieldProps?.slotProps,\n ...(inputSlot ? { input: inputSlot } : {}),\n inputLabel: {\n ...paramsInputLabel,\n ...consumerInputLabel,\n shrink:\n labelPosition === 'outside'\n ? !isEmpty || isFocused\n : paramsInputLabel?.shrink,\n },\n }}\n />\n );\n }}\n />\n );\n };\n\n //obtiene el primitivo (o objeto) value desde la opción seleccionada\n const extractValue = (opt: any): TValue | null => {\n if (opt === null || opt === undefined) return null;\n if (typeof opt === 'string') return opt as unknown as TValue;\n return (opt?.value ?? null) as TValue | null;\n };\n\n const handleControlledChange = (_event: any, newValue: any) => {\n const { onChange } = props;\n if (multiple) {\n const values = (newValue ?? [])\n .map((opt: SelectOption<TValue> | string) => extractValue(opt))\n .filter((v: TValue | null): v is TValue => v !== null);\n onChange(values);\n } else {\n onChange(extractValue(newValue));\n }\n };\n\n const resolvedValue = stabilizeResolved(\n multiple\n ? resolveMultipleValue(resolvePool, props.value as TValue[], getKey)\n : resolveSingleValue(resolvePool, props.value as TValue, getKey),\n );\n\n return renderAutocomplete(resolvedValue, handleControlledChange);\n}\n\n/** Alias de `Autocomplete`. Ambos nombres son equivalentes. */\nexport const AutocompleteSelect = Autocomplete;\n\nexport default Autocomplete;"],"names":["n","resolvedValue","MuiAutocomplete"],"mappings":"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"}
@@ -1,13 +1,14 @@
1
- import { default as React } from 'react';
2
- import { SelectOption, RenderChipLabel, AutocompleteSize } from '../Autocomplete';
3
- interface AutocompleteChipsProps {
4
- value: SelectOption[];
1
+ import { AutocompleteSize, AutocompleteValueKey, RenderChipLabel, SelectOption } from '../Autocomplete';
2
+ interface AutocompleteChipsProps<TValue = AutocompleteValueKey> {
3
+ value: SelectOption<TValue>[];
5
4
  getTagProps: (args: {
6
5
  index: number;
7
6
  }) => Record<string, any>;
8
7
  size: AutocompleteSize;
9
8
  maxChipsToShow: number;
10
- renderChipLabel?: RenderChipLabel;
9
+ renderChipLabel?: RenderChipLabel<TValue>;
10
+ /** Extrae la React key estable a partir del value (necesario para values objeto). */
11
+ getKey: (value: TValue) => AutocompleteValueKey;
11
12
  }
12
13
  /**
13
14
  * Render de los chips del Autocomplete en modo multiple.
@@ -15,5 +16,5 @@ interface AutocompleteChipsProps {
15
16
  * El `getTagProps({ index })` viene de MUI y contiene el handler de delete,
16
17
  * la key, etc. — se spreadea tal cual al Chip.
17
18
  */
18
- export declare const AutocompleteChips: React.FC<AutocompleteChipsProps>;
19
+ export declare const AutocompleteChips: <TValue>({ value, getTagProps, size, maxChipsToShow, renderChipLabel, getKey, }: AutocompleteChipsProps<TValue>) => import("react/jsx-runtime").JSX.Element;
19
20
  export default AutocompleteChips;
@@ -1,19 +1,16 @@
1
1
  import { default as React } from 'react';
2
- import { SelectOption, RenderOptionItem } from '../Autocomplete';
3
- interface AutocompleteOptionProps {
4
- liProps: React.HTMLAttributes<HTMLLIElement> & {
5
- key?: React.Key;
6
- };
7
- option: SelectOption;
8
- customRender?: RenderOptionItem;
2
+ import { AutocompleteValueKey, RenderOptionItem, SelectOption } from '../Autocomplete';
3
+ interface AutocompleteOptionProps<TValue = AutocompleteValueKey> {
4
+ liProps: React.HTMLAttributes<HTMLLIElement>;
5
+ option: SelectOption<TValue>;
6
+ customRender?: RenderOptionItem<TValue>;
9
7
  }
10
8
  /**
11
- * Render por defecto de un <li> del dropdown del Autocomplete.
12
- * Se expone como componente para testear y extender fácilmente, pero MUI
13
- * lo llama desde `renderOption={(props, option) => ...}` en el padre.
9
+ * Render por defecto de un `<li>` del dropdown del Autocomplete.
10
+ * MUI lo invoca desde `renderOption={(props, option) => ...}` en el padre.
14
11
  *
15
- * El `key` lo manejamos nosotros (no spreadeamos junto al resto) porque MUI
16
- * lo inyecta como parte de `propsLi` y React exige que sea prop directo.
12
+ * La `key` la maneja el padre (`renderOption` en Autocomplete.tsx). Este
13
+ * componente solo recibe los props restantes del `<li>` para spread.
17
14
  */
18
- export declare const AutocompleteOption: React.FC<AutocompleteOptionProps>;
15
+ export declare const AutocompleteOption: <TValue>({ liProps, option, customRender, }: AutocompleteOptionProps<TValue>) => import("react/jsx-runtime").JSX.Element;
19
16
  export default AutocompleteOption;
@@ -1,2 +1,2 @@
1
1
  export { Autocomplete, AutocompleteSelect, default } from './Autocomplete';
2
- export type { AutocompleteProps, SelectOption, BaseAutocompleteProps, ControlledAutocompleteProps, RHFAutocompleteProps, RenderOptionItem, RenderChipLabel, LabelPosition, AutocompleteSize, } from './Autocomplete.types';
2
+ export type { AutocompleteProps, SelectOption, BaseAutocompleteProps, RenderOptionItem, RenderChipLabel, RenderSingleValue, LabelPosition, AutocompleteSize, AutocompleteValueKey, } from './Autocomplete';
@@ -59,11 +59,12 @@ const Avatar = ({
59
59
  overlap
60
60
  }) => {
61
61
  var _a;
62
- const [errorIndex, setErrorIndex] = React.useState(/* @__PURE__ */ new Set());
63
- const handleImageError = (index) => {
64
- setErrorIndex((prev) => {
62
+ const [failedUrls, setFailedUrls] = React.useState(/* @__PURE__ */ new Set());
63
+ const handleImageError = (url) => {
64
+ setFailedUrls((prev) => {
65
+ if (prev.has(url)) return prev;
65
66
  const next = new Set(prev);
66
- next.add(index);
67
+ next.add(url);
67
68
  return next;
68
69
  });
69
70
  };
@@ -82,12 +83,13 @@ const Avatar = ({
82
83
  boxSizing: "content-box"
83
84
  };
84
85
  const renderSingleAvatar = (item, i) => {
85
- var _a2, _b;
86
- const hasImage = !!item.imageUrl && !errorIndex.has(i);
86
+ var _a2, _b, _c, _d, _e;
87
+ const hasImage = !!item.imageUrl && !failedUrls.has(item.imageUrl);
87
88
  const showBadgeFallback = !!item.badge;
89
+ const itemKey = (_c = item.imageUrl) != null ? _c : `${(_a2 = item.text) != null ? _a2 : ""}-${(_b = item.badge) != null ? _b : ""}-${i}`;
88
90
  const itemSx = __spreadProps(__spreadValues({
89
- bgcolor: (_a2 = item.backgroundColor) != null ? _a2 : "action.selected",
90
- color: (_b = item.color) != null ? _b : "text.secondary"
91
+ bgcolor: (_d = item.backgroundColor) != null ? _d : "action.selected",
92
+ color: (_e = item.color) != null ? _e : "text.secondary"
91
93
  }, i > 0 && { marginLeft: `-${effectiveOverlap}px` }), {
92
94
  zIndex: visibleItems.length - i
93
95
  });
@@ -95,18 +97,17 @@ const Avatar = ({
95
97
  const avatarEl = /* @__PURE__ */ jsxRuntime.jsx(
96
98
  material.Avatar,
97
99
  {
98
- "data-testid": "avatar",
99
100
  alt: item.text || "User avatar",
100
101
  src: hasImage ? item.imageUrl : void 0,
101
102
  imgProps: {
102
- "data-testid": "image",
103
- onError: () => handleImageError(i)
103
+ onError: () => {
104
+ if (item.imageUrl) handleImageError(item.imageUrl);
105
+ }
104
106
  },
105
107
  sx: finalSx,
106
- children: !hasImage && showBadgeFallback ? /* @__PURE__ */ jsxRuntime.jsx("span", { "data-testid": "badge", "aria-label": item.text, children: item.badge }) : !hasImage ? /* @__PURE__ */ jsxRuntime.jsx(
108
+ children: !hasImage && showBadgeFallback ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-label": item.text, children: item.badge }) : !hasImage ? /* @__PURE__ */ jsxRuntime.jsx(
107
109
  AccountCircleIcon,
108
110
  {
109
- "data-testid": "icon",
110
111
  "aria-label": item.text,
111
112
  sx: { width: "100%", height: "100%" }
112
113
  }
@@ -114,14 +115,13 @@ const Avatar = ({
114
115
  }
115
116
  );
116
117
  if (showTooltip && item.text) {
117
- return /* @__PURE__ */ jsxRuntime.jsx(material.Tooltip, { title: item.text, children: avatarEl }, i);
118
+ return /* @__PURE__ */ jsxRuntime.jsx(material.Tooltip, { title: item.text, children: avatarEl }, itemKey);
118
119
  }
119
- return /* @__PURE__ */ jsxRuntime.jsx(React.Fragment, { children: avatarEl }, i);
120
+ return /* @__PURE__ */ jsxRuntime.jsx(React.Fragment, { children: avatarEl }, itemKey);
120
121
  };
121
122
  return /* @__PURE__ */ jsxRuntime.jsxs(
122
123
  material.Box,
123
124
  {
124
- "data-testid": "avatar-container",
125
125
  className,
126
126
  sx: mergeSx(
127
127
  {
@@ -137,7 +137,6 @@ const Avatar = ({
137
137
  showText && ((_a = items[0]) == null ? void 0 : _a.text) && /* @__PURE__ */ jsxRuntime.jsxs(
138
138
  material.Typography,
139
139
  {
140
- "data-testid": "text",
141
140
  variant: "caption",
142
141
  sx: {
143
142
  ml: 1,
@@ -146,7 +145,7 @@ const Avatar = ({
146
145
  color: "text.primary"
147
146
  },
148
147
  children: [
149
- type && items.length === 1 && /* @__PURE__ */ jsxRuntime.jsxs(material.Box, { component: "span", "data-testid": "type", sx: { mr: 0.5 }, children: [
148
+ type && items.length === 1 && /* @__PURE__ */ jsxRuntime.jsxs(material.Box, { component: "span", sx: { mr: 0.5 }, children: [
150
149
  type,
151
150
  ":"
152
151
  ] }),