@m4l/components 9.4.8-BE20260108-beta.1 → 9.4.9

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.
@@ -143,9 +143,19 @@ const CheckableList = (props) => {
143
143
  ownerState,
144
144
  className: clsx(className, CHECKABLE_LIST_CLASSES.root),
145
145
  "data-testid": dataTestId,
146
- "aria-label": ariaLabel,
146
+ "aria-label": ariaLabel || "checkable list",
147
147
  "aria-labelledby": ariaLabelledBy,
148
- children: /* @__PURE__ */ jsx(LoadingContainerStyled, { ownerState, children: /* @__PURE__ */ jsx(Skeleton, { variant: "rectangular", width: "100%", height: 200 }) })
148
+ children: /* @__PURE__ */ jsx(LoadingContainerStyled, { ownerState, children: /* @__PURE__ */ jsx(
149
+ Skeleton,
150
+ {
151
+ variant: "rectangular",
152
+ width: "100%",
153
+ height: 200,
154
+ role: "status",
155
+ "aria-label": "Cargando lista de elementos",
156
+ "aria-live": "polite"
157
+ }
158
+ ) })
149
159
  }
150
160
  );
151
161
  }
@@ -156,24 +166,28 @@ const CheckableList = (props) => {
156
166
  ownerState,
157
167
  className: clsx(className, CHECKABLE_LIST_CLASSES.root),
158
168
  "data-testid": dataTestId,
159
- "aria-label": ariaLabel,
169
+ role: "group",
170
+ "aria-label": ariaLabel || "checkable list",
160
171
  "aria-labelledby": ariaLabelledBy,
161
172
  children: [
162
- searchable && /* @__PURE__ */ jsx(SearchContainerStyled, { ownerState, children: /* @__PURE__ */ jsx(
173
+ searchable && /* @__PURE__ */ jsx(SearchContainerStyled, { ownerState, role: "search", children: /* @__PURE__ */ jsx(
163
174
  SearchInputStyled,
164
175
  {
176
+ role: "searchbox",
177
+ "aria-label": "search",
165
178
  ownerState,
166
179
  value: searchQuery,
167
180
  onChange: (e) => setSearchQuery(e.target.value),
168
181
  placeholder: getLabel(DICCTIONARY.label_search_placeholder),
169
182
  size,
183
+ className: CHECKABLE_LIST_CLASSES.searchInput,
170
184
  variant: "contained",
171
185
  InputProps: {
172
186
  startAdornment: /* @__PURE__ */ jsx(Icon, { src: urlIconSearch })
173
187
  }
174
188
  }
175
189
  ) }),
176
- selectAll && hasItems && /* @__PURE__ */ jsxs(SelectAllContainerStyled, { ownerState, children: [
190
+ selectAll && hasItems && /* @__PURE__ */ jsxs(SelectAllContainerStyled, { ownerState, role: "group", "aria-label": "Seleccionar todo", children: [
177
191
  /* @__PURE__ */ jsx(
178
192
  SelectAllCheckboxStyled,
179
193
  {
@@ -196,26 +210,35 @@ const CheckableList = (props) => {
196
210
  }
197
211
  )
198
212
  ] }),
199
- /* @__PURE__ */ jsx(ListContainerStyled, { ref: setContainerElement, ownerState: { ...ownerState }, children: hasItems ? refHeight.current > 0 ? /* @__PURE__ */ jsx(
200
- VirtualizedListStyled,
201
- {
202
- ref: listRef,
203
- height: refHeight.current,
204
- width,
205
- itemCount: virtualizedItems.length,
206
- itemSize: getItemSize,
207
- itemData: virtualizedItems,
208
- layout: "vertical",
209
- children: renderVirtualizedItem
210
- }
211
- ) : null : /* @__PURE__ */ jsx(EmptyMessageWrapperStyled, { ownerState, children: /* @__PURE__ */ jsx(
212
- ImageText,
213
+ /* @__PURE__ */ jsx(
214
+ ListContainerStyled,
213
215
  {
214
- title: getLabel(DICCTIONARY.label_no_results),
215
- message: getLabel(DICCTIONARY.label_no_results_description),
216
- imageUrl: urlIconNoResults
216
+ ref: setContainerElement,
217
+ ownerState: { ...ownerState },
218
+ "aria-multiselectable": multiple ? "true" : "false",
219
+ children: hasItems ? refHeight.current > 0 ? /* @__PURE__ */ jsx(
220
+ VirtualizedListStyled,
221
+ {
222
+ ref: listRef,
223
+ height: refHeight.current,
224
+ width,
225
+ itemCount: virtualizedItems.length,
226
+ itemSize: getItemSize,
227
+ itemData: virtualizedItems,
228
+ layout: "vertical",
229
+ className: CHECKABLE_LIST_CLASSES.virtualizedList,
230
+ children: renderVirtualizedItem
231
+ }
232
+ ) : null : /* @__PURE__ */ jsx(EmptyMessageWrapperStyled, { ownerState, role: "status", "aria-live": "polite", children: /* @__PURE__ */ jsx(
233
+ ImageText,
234
+ {
235
+ title: getLabel(DICCTIONARY.label_no_results),
236
+ message: getLabel(DICCTIONARY.label_no_results_description),
237
+ imageUrl: urlIconNoResults
238
+ }
239
+ ) })
217
240
  }
218
- ) }) })
241
+ )
219
242
  ]
220
243
  }
221
244
  );
@@ -0,0 +1 @@
1
+ export {};
@@ -10,5 +10,6 @@ export declare const DICCTIONARY: {
10
10
  readonly label_no_results_description: "checkable_list.label_no_results_description";
11
11
  readonly label_group_title: "checkable_list.label_group_title";
12
12
  readonly label_select_all: "checkable_list.label_select_all";
13
+ readonly label_loading: "checkable_list.label_loading";
13
14
  };
14
15
  export type TypeDictionary = typeof DICCTIONARY;
@@ -14,25 +14,27 @@ const useCheckableListItems = ({
14
14
  return items;
15
15
  }, [items, groups, isGrouped]);
16
16
  const filteredItems = useMemo(() => {
17
- if (!searchQuery.trim()) {
17
+ const trimmedQuery = searchQuery.trim();
18
+ if (!trimmedQuery) {
18
19
  return normalizedItems;
19
20
  }
20
- const query = searchQuery.toLowerCase();
21
+ const query = trimmedQuery.toLowerCase();
21
22
  const defaultFilter = (item) => item.label.toLowerCase().includes(query) || item.description?.toLowerCase().includes(query);
22
23
  return normalizedItems.filter(
23
- (item) => filterFn ? filterFn(item, searchQuery) : defaultFilter(item)
24
+ (item) => filterFn ? filterFn(item, trimmedQuery) : defaultFilter(item)
24
25
  );
25
26
  }, [normalizedItems, searchQuery, filterFn]);
26
27
  const filteredGroups = useMemo(() => {
27
- if (!isGrouped || !searchQuery.trim()) {
28
+ const trimmedQuery = searchQuery.trim();
29
+ if (!isGrouped || !trimmedQuery) {
28
30
  return groups || [];
29
31
  }
30
- const normalizedQuery = searchQuery.toLowerCase();
32
+ const normalizedQuery = trimmedQuery.toLowerCase();
31
33
  const defaultGroupFilter = (candidate) => candidate.label.toLowerCase().includes(normalizedQuery) || candidate.description?.toLowerCase().includes(normalizedQuery);
32
34
  return (groups || []).map((group) => ({
33
35
  ...group,
34
36
  items: group.items.filter(
35
- (groupItem) => filterFn ? filterFn(groupItem, searchQuery) : defaultGroupFilter(groupItem)
37
+ (groupItem) => filterFn ? filterFn(groupItem, trimmedQuery) : defaultGroupFilter(groupItem)
36
38
  )
37
39
  })).filter((group) => group.items.length > 0);
38
40
  }, [groups, isGrouped, searchQuery, filterFn]);
@@ -65,6 +65,10 @@ const useCheckableListRender = ({
65
65
  ItemWrapperStyled,
66
66
  {
67
67
  ownerState: { size, variant, disabled: itemDisabled, selected: checked },
68
+ role: "option",
69
+ "aria-label": "item",
70
+ "aria-selected": checked,
71
+ "aria-disabled": itemDisabled,
68
72
  onClick: () => !itemDisabled && handleItemToggle(item.id),
69
73
  children: [
70
74
  /* @__PURE__ */ jsx(
@@ -160,37 +164,48 @@ const useCheckableListRender = ({
160
164
  )
161
165
  ] });
162
166
  const groupBodyContent = customGroupContent ?? fallbackGroupLabel;
163
- return /* @__PURE__ */ jsx(GroupWrapperStyled, { ownerState: { size, variant, grouped: true, selected: checkboxState === true }, children: /* @__PURE__ */ jsxs(
164
- GroupHeaderStyled,
167
+ return /* @__PURE__ */ jsx(
168
+ GroupWrapperStyled,
165
169
  {
166
- ownerState: { size, variant, disabled: groupDisabled },
167
- onClick: handleExpand,
168
- children: [
169
- showCheckboxOnGroup && /* @__PURE__ */ jsx(
170
- GroupCheckboxStyled,
171
- {
172
- checked: checkboxState === true,
173
- indeterminate: checkboxState === "indeterminate",
174
- disabled: groupDisabled,
175
- size: checkboxSize,
176
- onChange: handleToggleGroup,
177
- onClick: (e) => e.stopPropagation()
178
- }
179
- ),
180
- group.icon && /* @__PURE__ */ jsx(GroupIconStyled, { children: group.icon }),
181
- /* @__PURE__ */ jsx("div", { style: { flex: 1, minWidth: 0 }, children: groupBodyContent }),
182
- groupable && /* @__PURE__ */ jsx(
183
- GroupToggleButtonStyled,
184
- {
185
- size,
186
- variant: "text",
187
- icon: isExpanded ? urlIconCompact : urlIconExpanded,
188
- onClick: handleExpand
189
- }
190
- )
191
- ]
170
+ ownerState: { size, variant, grouped: true, selected: checkboxState === true },
171
+ role: "group",
172
+ "aria-label": group.label,
173
+ "aria-expanded": isExpanded,
174
+ "aria-disabled": groupDisabled,
175
+ children: /* @__PURE__ */ jsxs(
176
+ GroupHeaderStyled,
177
+ {
178
+ ownerState: { size, variant, disabled: groupDisabled },
179
+ onClick: handleExpand,
180
+ children: [
181
+ showCheckboxOnGroup && /* @__PURE__ */ jsx(
182
+ GroupCheckboxStyled,
183
+ {
184
+ checked: checkboxState === true,
185
+ indeterminate: checkboxState === "indeterminate",
186
+ disabled: groupDisabled,
187
+ size: checkboxSize,
188
+ onChange: handleToggleGroup,
189
+ onClick: (e) => e.stopPropagation()
190
+ }
191
+ ),
192
+ group.icon && /* @__PURE__ */ jsx(GroupIconStyled, { children: group.icon }),
193
+ /* @__PURE__ */ jsx("div", { style: { flex: 1, minWidth: 0 }, children: groupBodyContent }),
194
+ groupable && /* @__PURE__ */ jsx(
195
+ GroupToggleButtonStyled,
196
+ {
197
+ size,
198
+ variant: "text",
199
+ icon: isExpanded ? urlIconCompact : urlIconExpanded,
200
+ onClick: handleExpand,
201
+ "aria-label": isExpanded ? "Colapsar grupo" : "Expandir grupo"
202
+ }
203
+ )
204
+ ]
205
+ }
206
+ )
192
207
  }
193
- ) });
208
+ );
194
209
  },
195
210
  [expandedGroups, disabled, isGroupFullySelected, isGroupPartiallySelected, getGroupItems, indeterminateBehavior, renderGroup, size, variant, showCheckboxOnGroup, checkboxSize, groupable, urlIconCompact, urlIconExpanded, handleGroupExpandToggle, handleGroupToggle, isItemSelected]
196
211
  );
@@ -1,13 +1,12 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { useEnvironment, FlagsProvider, ModuleDictionaryProvider, ModuleSkeletonProvider, CommonFlags } from "@m4l/core";
3
3
  import { useLocales, useThemeSettingsStore } from "@m4l/graphics";
4
- import { S as SETTINGS_LAYOUT_DEFAULT_MODULE_ID, a as SETTINGS_LAYOUT_DEFAULT_WIDTH } from "./constants.js";
4
+ import { S as SETTINGS_LAYOUT_DEFAULT_WIDTH } from "./constants.js";
5
5
  import { useMemo } from "react";
6
6
  import { S as SettingsLayoutBase } from "./subcomponents/SettingsLayoutBase/SettingsLayoutBase.js";
7
7
  const SettingsLayout = (props) => {
8
8
  const {
9
- width = SETTINGS_LAYOUT_DEFAULT_WIDTH,
10
- moduleId = SETTINGS_LAYOUT_DEFAULT_MODULE_ID
9
+ width = SETTINGS_LAYOUT_DEFAULT_WIDTH
11
10
  } = props;
12
11
  const currentLang = useLocales().currentLocale?.localeString;
13
12
  const { host_static_assets, environment_assets } = useEnvironment();
@@ -23,7 +22,7 @@ const SettingsLayout = (props) => {
23
22
  ModuleDictionaryProvider,
24
23
  {
25
24
  isAuth: false,
26
- moduleId,
25
+ moduleId: "theme_settings",
27
26
  componentsDictionary,
28
27
  currentLang,
29
28
  children: /* @__PURE__ */ jsx(ModuleSkeletonProvider, { flags: [CommonFlags.FLAG_DICTIONARY_LOADED], children: /* @__PURE__ */ jsx(SettingsLayoutBase, { prefixPathIcon, width }) })
@@ -5,4 +5,3 @@ import { SettingsLayoutSlots } from './slots/SettingsLayoutEnum';
5
5
  export declare const SETTINGS_LAYOUT_COMPONENT_KEY = "M4LSettingsLayout";
6
6
  export declare const SETTINGS_LAYOUT_CLASSES: Record<keyof typeof SettingsLayoutSlots, string>;
7
7
  export declare const SETTINGS_LAYOUT_DEFAULT_WIDTH = 300;
8
- export declare const SETTINGS_LAYOUT_DEFAULT_MODULE_ID = "theme_settings";
@@ -3,10 +3,8 @@ import { S as SettingsLayoutSlots } from "./slots/SettingsLayoutEnum.js";
3
3
  const SETTINGS_LAYOUT_COMPONENT_KEY = "M4LSettingsLayout";
4
4
  const SETTINGS_LAYOUT_CLASSES = getComponentClasses(SETTINGS_LAYOUT_COMPONENT_KEY, SettingsLayoutSlots);
5
5
  const SETTINGS_LAYOUT_DEFAULT_WIDTH = 300;
6
- const SETTINGS_LAYOUT_DEFAULT_MODULE_ID = "theme_settings";
7
6
  export {
8
- SETTINGS_LAYOUT_DEFAULT_MODULE_ID as S,
9
- SETTINGS_LAYOUT_DEFAULT_WIDTH as a,
10
- SETTINGS_LAYOUT_COMPONENT_KEY as b,
11
- SETTINGS_LAYOUT_CLASSES as c
7
+ SETTINGS_LAYOUT_DEFAULT_WIDTH as S,
8
+ SETTINGS_LAYOUT_COMPONENT_KEY as a,
9
+ SETTINGS_LAYOUT_CLASSES as b
12
10
  };
@@ -1,6 +1,6 @@
1
1
  import { styled } from "@mui/material/styles";
2
2
  import { S as SettingsLayoutSlots } from "./SettingsLayoutEnum.js";
3
- import { b as SETTINGS_LAYOUT_COMPONENT_KEY } from "../constants.js";
3
+ import { a as SETTINGS_LAYOUT_COMPONENT_KEY } from "../constants.js";
4
4
  import { s as settingsLayoutStyles } from "../SettingsLayout.styles.js";
5
5
  import { Backdrop } from "@mui/material";
6
6
  import { I as Icon } from "../../Icon/Icon.js";
@@ -6,7 +6,7 @@ import { B as BackdropStyled, g as SettingsLayoutRootStyled, H as HeaderContaine
6
6
  import { S as SettingDirection } from "../SettingDirection/SettingDirection.js";
7
7
  import { D as DICTIONARY } from "../../dictionary.js";
8
8
  import { useThemeSettingsStore } from "@m4l/graphics";
9
- import { c as SETTINGS_LAYOUT_CLASSES } from "../../constants.js";
9
+ import { b as SETTINGS_LAYOUT_CLASSES } from "../../constants.js";
10
10
  import { I as IconButton } from "../../../mui_extended/IconButton/IconButton.js";
11
11
  import { S as SettingMode } from "../SettingMode/SettingMode.js";
12
12
  import { S as SettingColorPresets } from "../SettingColorPresets/SettingColorPresets.js";
@@ -21,10 +21,6 @@ export interface SettingsLayoutProps {
21
21
  * Identificador usado para pruebas del componente.
22
22
  */
23
23
  dataTestId?: string;
24
- /**
25
- * Identificador del módulo.
26
- */
27
- moduleId?: string;
28
24
  }
29
25
  /**
30
26
  * Tipo para las ranuras del componente.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m4l/components",
3
- "version": "9.4.8-BE20260108-beta.1",
3
+ "version": "9.4.9",
4
4
  "license": "UNLICENSED",
5
5
  "description": "M4L Components",
6
6
  "lint-staged": {