@widergy/energy-ui 3.172.2 → 3.173.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 (42) hide show
  1. package/CHANGELOG.md +20 -6
  2. package/dist/components/UTDataCategory/README.md +3 -1
  3. package/dist/components/UTDataCategory/UTDataCategory.stories.js +405 -0
  4. package/dist/components/UTDataCategory/components/MainAction/index.js +47 -0
  5. package/dist/components/UTDataCategory/constants.js +6 -2
  6. package/dist/components/UTDataCategory/index.js +46 -16
  7. package/dist/components/UTDataCategory/styles.module.scss +11 -0
  8. package/dist/components/UTDataElement/README.md +15 -2
  9. package/dist/components/UTDataElement/UTDataElement.stories.js +29 -1
  10. package/dist/components/UTDataElement/index.js +96 -49
  11. package/dist/components/UTDataElement/styles.module.scss +5 -0
  12. package/dist/components/UTDataElement/theme.js +11 -9
  13. package/dist/components/UTRadioGroup/UTRadioGroup.stories.js +124 -4
  14. package/dist/components/UTRadioGroup/versions/V1/components/Radio/index.js +12 -6
  15. package/dist/components/UTRadioGroup/versions/V1/constants.js +1 -0
  16. package/dist/components/UTRadioGroup/versions/V1/index.js +23 -7
  17. package/dist/components/UTRadioGroup/versions/V1/styles.module.scss +5 -0
  18. package/dist/components/UTRadioGroup/versions/V1/utils.js +40 -0
  19. package/dist/constants/Palette.js +18 -2
  20. package/dist/esm/components/UTDataCategory/README.md +3 -1
  21. package/dist/esm/components/UTDataCategory/UTDataCategory.stories.js +400 -0
  22. package/dist/esm/components/UTDataCategory/components/MainAction/index.js +40 -0
  23. package/dist/esm/components/UTDataCategory/constants.js +5 -1
  24. package/dist/esm/components/UTDataCategory/index.js +48 -18
  25. package/dist/esm/components/UTDataCategory/styles.module.scss +11 -0
  26. package/dist/esm/components/UTDataElement/README.md +15 -2
  27. package/dist/esm/components/UTDataElement/UTDataElement.stories.js +28 -0
  28. package/dist/esm/components/UTDataElement/index.js +98 -51
  29. package/dist/esm/components/UTDataElement/styles.module.scss +5 -0
  30. package/dist/esm/components/UTDataElement/theme.js +12 -10
  31. package/dist/esm/components/UTRadioGroup/UTRadioGroup.stories.js +123 -3
  32. package/dist/esm/components/UTRadioGroup/versions/V1/components/Radio/index.js +12 -6
  33. package/dist/esm/components/UTRadioGroup/versions/V1/constants.js +1 -0
  34. package/dist/esm/components/UTRadioGroup/versions/V1/index.js +25 -9
  35. package/dist/esm/components/UTRadioGroup/versions/V1/styles.module.scss +5 -0
  36. package/dist/esm/components/UTRadioGroup/versions/V1/utils.js +34 -0
  37. package/dist/esm/constants/Palette.js +17 -1
  38. package/dist/esm/utils/colorUtils.js +15 -0
  39. package/dist/esm/utils/hooks/useCSSVariables/constants.js +1 -0
  40. package/dist/utils/colorUtils.js +16 -1
  41. package/dist/utils/hooks/useCSSVariables/constants.js +1 -0
  42. package/package.json +1 -1
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getAreaStyle = void 0;
7
+ var _Palette = require("../../../../constants/Palette");
8
+ var _colorUtils = require("../../../../utils/colorUtils");
9
+ // colorTheme sin entrada real en la paleta del tenant (ej. 'primary', o un valor inválido) -> se trata como si no
10
+ // se hubiera pasado ningún colorTheme (getAreaStyle no agrega fondo/borde para ese lado del área).
11
+ const resolvePaletteColorTheme = colorTheme => _Palette.VALID_PALETTE_COLOR_THEMES.has(colorTheme) ? colorTheme : undefined;
12
+
13
+ /**
14
+ * Calcula el estilo del área de fondo de UTRadioGroup según areaProps. Sin `area`, no agrega borde ni fondo.
15
+ * A diferencia de UTDataCategory/UTDataElement, acá el fondo no tiene un colorTheme por defecto: solo se
16
+ * aplica si `areaProps.colorTheme` está configurado explícitamente.
17
+ * @param {boolean} area - Si el área debe mostrarse.
18
+ * @param {{ colorTheme?: string, shade?: string, borderColorTheme?: string, borderShade?: string }} [areaProps] - Personalización del área. Sin `colorTheme` no se agrega fondo; sin `borderColorTheme` no se agrega borde.
19
+ * @returns {object} Estilos inline a aplicar sobre el contenedor.
20
+ */
21
+ const getAreaStyle = function (area) {
22
+ let areaProps = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
23
+ if (!area) return {};
24
+ const colorTheme = resolvePaletteColorTheme(areaProps.colorTheme);
25
+ const borderColorTheme = resolvePaletteColorTheme(areaProps.borderColorTheme);
26
+ const shade = areaProps.shade || (colorTheme === _Palette.COLOR_THEMES.light ? _Palette.COLOR_SHADES.shade03 : _Palette.COLOR_SHADES.shade01);
27
+ const borderShade = areaProps.borderShade || (borderColorTheme === _Palette.COLOR_THEMES.light ? _Palette.COLOR_SHADES.shade03 : _Palette.COLOR_SHADES.shade01);
28
+ return {
29
+ ...(colorTheme && {
30
+ backgroundColor: (0, _colorUtils.getPaletteCssVar)(colorTheme, shade)
31
+ }),
32
+ ...(borderColorTheme && {
33
+ border: "1px solid ".concat((0, _colorUtils.getPaletteCssVar)(borderColorTheme, borderShade))
34
+ }),
35
+ borderRadius: 8,
36
+ boxSizing: 'border-box',
37
+ padding: 8
38
+ };
39
+ };
40
+ exports.getAreaStyle = getAreaStyle;
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.COLOR_THEMES = exports.COLOR_SHADES = void 0;
6
+ exports.VALID_PALETTE_COLOR_THEMES = exports.PALETTE_CSS_VAR_PREFIX_MAPPER = exports.COLOR_THEMES = exports.COLOR_SHADES = void 0;
7
7
  const COLOR_SHADES = exports.COLOR_SHADES = {
8
8
  shade01: '01',
9
9
  shade02: '02',
@@ -23,4 +23,20 @@ const COLOR_THEMES = exports.COLOR_THEMES = {
23
23
  primary: 'primary',
24
24
  success: 'success',
25
25
  warning: 'warning'
26
- };
26
+ };
27
+
28
+ // Prefijo real de la CSS var de la paleta multi-tenant para cada colorTheme (ej. 'accent' -> 'actionAccent01').
29
+ // Los themes sin entrada acá (dark, gray, light, primary) no llevan prefijo: la CSS var coincide con el colorTheme.
30
+ const PALETTE_CSS_VAR_PREFIX_MAPPER = exports.PALETTE_CSS_VAR_PREFIX_MAPPER = {
31
+ [COLOR_THEMES.accent]: 'actionAccent',
32
+ [COLOR_THEMES.error]: 'semanticError',
33
+ [COLOR_THEMES.information]: 'semanticInformation',
34
+ [COLOR_THEMES.negative]: 'actionNegative',
35
+ [COLOR_THEMES.neutral]: 'actionNeutral',
36
+ [COLOR_THEMES.success]: 'semanticSuccess',
37
+ [COLOR_THEMES.warning]: 'semanticWarning'
38
+ };
39
+
40
+ // colorTheme de COLOR_THEMES que sí tienen una entrada real en la paleta de cada tenant (ver .storybook/palettes/palette.js).
41
+ // 'primary' queda afuera a propósito: es un valor válido de COLOR_THEMES pero ningún tenant define esa key.
42
+ const VALID_PALETTE_COLOR_THEMES = exports.VALID_PALETTE_COLOR_THEMES = new Set([COLOR_THEMES.accent, COLOR_THEMES.dark, COLOR_THEMES.error, COLOR_THEMES.gray, COLOR_THEMES.information, COLOR_THEMES.light, COLOR_THEMES.negative, COLOR_THEMES.neutral, COLOR_THEMES.success, COLOR_THEMES.warning]);
@@ -12,6 +12,8 @@ A collapsible container component that displays a list of data elements with an
12
12
  | classNames | object | | Custom CSS class names for styling the component. |
13
13
  | collapsable | bool | `true` | Specifies if the data list is collapsible. |
14
14
  | dataTestId | string | | Test ID for testing purposes. |
15
+ | description | string | | Description text displayed below the title. |
16
+ | descriptionProps | object | | Additional props for customizing the description UTLabel component. |
15
17
  | elements | array | `[]` | Array of objects to be rendered as UTDataElement components. |
16
18
  | elementsProps | object | `{}` | Additional props that apply to all UTDataElement components. |
17
19
  | expanded | bool | `false` | Controls the initial expanded state of the component. |
@@ -21,7 +23,7 @@ A collapsible container component that displays a list of data elements with an
21
23
 
22
24
  ## Behavior
23
25
 
24
- - **Collapsible**: The component is only collapsible if it has a `title` and `collapsable` is `true`
26
+ - **Collapsible**: The component is only collapsible if it has a `title` and `collapsable` is `true`. Clicking anywhere on the header (title, description) toggles it; the chevron next to the title is only a visual indicator. Clicks on `action` don't affect the toggle.
25
27
  - **Initial State**: The component starts collapsed by default unless `expanded` is `true`
26
28
  - **Area Styling**: When `area` is `true`, the component gets background color and padding
27
29
  - **Smooth Transitions**: Collapse/expand animations use CSS transitions for smooth UX
@@ -0,0 +1,400 @@
1
+ /* eslint-disable no-alert */
2
+ import { ACTION_TYPE } from './constants';
3
+ import UTDataCategory from '.';
4
+
5
+ // Mock data for examples
6
+ const mockElements = [{
7
+ title: 'Plan Mensual',
8
+ Data: '$4.999',
9
+ Icon: 'IconCreditCard',
10
+ badge: 'Activo'
11
+ }, {
12
+ title: 'Almacenamiento',
13
+ Data: '50GB disponibles',
14
+ Icon: 'IconCloud'
15
+ }, {
16
+ title: 'Soporte Prioritario',
17
+ Data: 'Atención 24/7',
18
+ Icon: 'IconHeadset'
19
+ }];
20
+ const mockElementsWithActions = [{
21
+ title: 'Streaming Plus',
22
+ Data: 'Plan mensual',
23
+ Icon: 'IconDeviceTv',
24
+ badge: 'Activo',
25
+ action: {
26
+ type: ACTION_TYPE.SWITCH,
27
+ checked: true,
28
+ onChange: checked => alert("Streaming Plus ".concat(checked ? 'activado' : 'desactivado'))
29
+ }
30
+ }, {
31
+ title: 'Almacenamiento en la Nube',
32
+ Data: '50GB disponibles',
33
+ Icon: 'IconCloud',
34
+ action: {
35
+ type: ACTION_TYPE.BUTTON,
36
+ text: 'Editar',
37
+ variant: 'text',
38
+ onClick: () => alert('Editar plan de almacenamiento')
39
+ }
40
+ }, {
41
+ title: 'Soporte Premium',
42
+ Data: 'Atención prioritaria 24/7',
43
+ Icon: 'IconHeadset',
44
+ action: {
45
+ type: ACTION_TYPE.SWITCH,
46
+ checked: false,
47
+ onChange: checked => alert("Soporte Premium ".concat(checked ? 'activado' : 'desactivado'))
48
+ }
49
+ }];
50
+ export default {
51
+ args: {
52
+ title: 'Categoría de Datos',
53
+ elements: mockElements,
54
+ collapsable: true,
55
+ expanded: false
56
+ },
57
+ argTypes: {
58
+ title: {
59
+ control: 'text',
60
+ description: 'Título que se muestra en el encabezado de la categoría.',
61
+ table: {
62
+ defaultValue: {
63
+ summary: 'undefined'
64
+ },
65
+ type: {
66
+ summary: 'string'
67
+ }
68
+ }
69
+ },
70
+ description: {
71
+ control: 'text',
72
+ description: 'Descripción que se muestra debajo del título.',
73
+ table: {
74
+ defaultValue: {
75
+ summary: 'undefined'
76
+ },
77
+ type: {
78
+ summary: 'string'
79
+ }
80
+ }
81
+ },
82
+ descriptionProps: {
83
+ control: false,
84
+ description: 'Props adicionales para el UTLabel de la descripción.',
85
+ table: {
86
+ defaultValue: {
87
+ summary: '{}'
88
+ },
89
+ type: {
90
+ summary: 'object'
91
+ }
92
+ }
93
+ },
94
+ Icon: {
95
+ control: 'text',
96
+ description: 'Icono que se muestra al inicio del título. Nombre de icono de UTIcon.',
97
+ table: {
98
+ defaultValue: {
99
+ summary: 'undefined'
100
+ },
101
+ type: {
102
+ summary: 'string'
103
+ }
104
+ }
105
+ },
106
+ iconProps: {
107
+ control: false,
108
+ description: 'Props adicionales para el icono del título.',
109
+ table: {
110
+ defaultValue: {
111
+ summary: 'undefined'
112
+ },
113
+ type: {
114
+ summary: 'object'
115
+ }
116
+ }
117
+ },
118
+ collapsable: {
119
+ control: 'boolean',
120
+ description: 'Determina si la categoría es colapsable. Al hacer clic en el encabezado (título, descripción) se expande/colapsa; el chevron junto al título es solo un indicador visual.',
121
+ table: {
122
+ defaultValue: {
123
+ summary: 'true'
124
+ },
125
+ type: {
126
+ summary: 'boolean'
127
+ }
128
+ }
129
+ },
130
+ expanded: {
131
+ control: 'boolean',
132
+ description: 'Controla el estado inicial expandido del componente.',
133
+ table: {
134
+ defaultValue: {
135
+ summary: 'false'
136
+ },
137
+ type: {
138
+ summary: 'boolean'
139
+ }
140
+ }
141
+ },
142
+ action: {
143
+ control: false,
144
+ description: 'Configuración de la acción principal del encabezado (botón o switch). No dispara el colapso al hacer clic.',
145
+ table: {
146
+ defaultValue: {
147
+ summary: 'undefined'
148
+ },
149
+ type: {
150
+ summary: 'object'
151
+ }
152
+ }
153
+ },
154
+ elements: {
155
+ control: false,
156
+ description: 'Array de objetos que se renderizan como componentes UTDataElement.',
157
+ table: {
158
+ defaultValue: {
159
+ summary: '[]'
160
+ },
161
+ type: {
162
+ summary: 'array'
163
+ }
164
+ }
165
+ },
166
+ elementsProps: {
167
+ control: false,
168
+ description: 'Props adicionales aplicadas a todos los UTDataElement renderizados.',
169
+ table: {
170
+ defaultValue: {
171
+ summary: '{}'
172
+ },
173
+ type: {
174
+ summary: 'object'
175
+ }
176
+ }
177
+ },
178
+ area: {
179
+ control: 'boolean',
180
+ description: 'Cuando es true, aplica color de fondo y padding para dar apariencia de área.',
181
+ table: {
182
+ defaultValue: {
183
+ summary: 'false'
184
+ },
185
+ type: {
186
+ summary: 'boolean'
187
+ }
188
+ }
189
+ },
190
+ areaProps: {
191
+ control: false,
192
+ description: "Personaliza el fondo del área. Acepta `colorTheme` (cualquier valor de COLOR_THEMES) y `shade` ('01'–'05'). Solo aplica cuando `area` es `true`.",
193
+ table: {
194
+ defaultValue: {
195
+ summary: '{}'
196
+ },
197
+ type: {
198
+ summary: 'object'
199
+ }
200
+ }
201
+ },
202
+ dataTestId: {
203
+ control: 'text',
204
+ description: 'ID de test para pruebas automatizadas.',
205
+ table: {
206
+ defaultValue: {
207
+ summary: 'undefined'
208
+ },
209
+ type: {
210
+ summary: 'string'
211
+ }
212
+ }
213
+ },
214
+ titleProps: {
215
+ control: false,
216
+ description: 'Props adicionales para el UTLabel del título.',
217
+ table: {
218
+ defaultValue: {
219
+ summary: 'undefined'
220
+ },
221
+ type: {
222
+ summary: 'object'
223
+ }
224
+ }
225
+ },
226
+ classes: {
227
+ control: false,
228
+ description: 'Clases de tema para estilos.',
229
+ table: {
230
+ defaultValue: {
231
+ summary: 'undefined'
232
+ },
233
+ type: {
234
+ summary: 'object'
235
+ }
236
+ }
237
+ },
238
+ classNames: {
239
+ control: false,
240
+ description: 'Clases CSS personalizadas para diferentes elementos.',
241
+ table: {
242
+ defaultValue: {
243
+ summary: 'undefined'
244
+ },
245
+ type: {
246
+ summary: 'object'
247
+ }
248
+ }
249
+ }
250
+ },
251
+ component: UTDataCategory,
252
+ parameters: {
253
+ controls: {
254
+ exclude: []
255
+ },
256
+ docs: {
257
+ description: {
258
+ component: 'Contenedor colapsable que agrupa una lista de UTDataElement bajo un título y descripción opcionales.'
259
+ }
260
+ }
261
+ },
262
+ title: 'Energy-UI/UTDataCategory'
263
+ };
264
+
265
+ // Basic Stories
266
+ export const Default = {
267
+ args: {
268
+ title: 'Información de la Cuenta',
269
+ elements: mockElements
270
+ },
271
+ name: 'Básico'
272
+ };
273
+ export const WithDescription = {
274
+ args: {
275
+ title: 'Información de la Cuenta',
276
+ description: 'Datos generales asociados a tu cuenta actual.',
277
+ Icon: 'IconUser',
278
+ elements: mockElements
279
+ },
280
+ name: 'Con Descripción'
281
+ };
282
+ export const NonCollapsable = {
283
+ args: {
284
+ title: 'Resumen Fijo',
285
+ description: 'Esta categoría siempre está expandida.',
286
+ collapsable: false,
287
+ elements: mockElements
288
+ },
289
+ name: 'No Colapsable'
290
+ };
291
+ export const ExpandedByDefault = {
292
+ args: {
293
+ title: 'Categoría Expandida',
294
+ elements: mockElements,
295
+ expanded: true
296
+ },
297
+ name: 'Expandida por Defecto'
298
+ };
299
+ export const WithHeaderAction = {
300
+ args: {
301
+ title: 'Métodos de Pago',
302
+ description: 'Administrá los métodos de pago asociados a tu cuenta.',
303
+ Icon: 'IconWallet',
304
+ action: {
305
+ type: ACTION_TYPE.BUTTON,
306
+ text: 'Agregar',
307
+ variant: 'text',
308
+ onClick: () => alert('Agregar nuevo método de pago')
309
+ },
310
+ elements: mockElements
311
+ },
312
+ name: 'Con Acción en el Encabezado'
313
+ };
314
+ export const WithButtonAction = {
315
+ args: {
316
+ title: 'Datos de Facturación',
317
+ description: 'Información asociada a tu método de pago activo.',
318
+ Icon: 'IconCreditCard',
319
+ action: {
320
+ type: ACTION_TYPE.BUTTON,
321
+ text: 'Editar',
322
+ variant: 'text',
323
+ onClick: () => alert('Editar datos de facturación')
324
+ },
325
+ elements: mockElements
326
+ },
327
+ name: 'Con Acción Botón'
328
+ };
329
+ export const WithSwitchAction = {
330
+ args: {
331
+ title: 'Notificaciones Push',
332
+ description: 'Activá o desactivá las notificaciones de tu cuenta.',
333
+ Icon: 'IconBell',
334
+ action: {
335
+ type: ACTION_TYPE.SWITCH,
336
+ checked: true,
337
+ onChange: checked => alert("Switch ".concat(checked ? 'activado' : 'desactivado'))
338
+ },
339
+ elements: mockElements
340
+ },
341
+ name: 'Con Acción Switch'
342
+ };
343
+ export const CollapsableWithActions = {
344
+ args: {
345
+ title: 'Suscripciones Activas',
346
+ description: 'Gestioná los servicios a los que estás suscripto.',
347
+ Icon: 'IconApps',
348
+ collapsable: true,
349
+ action: {
350
+ type: ACTION_TYPE.BUTTON,
351
+ text: 'Agregar',
352
+ variant: 'text',
353
+ onClick: () => alert('Agregar nueva suscripción')
354
+ },
355
+ elements: mockElementsWithActions
356
+ },
357
+ name: 'Colapsable con Acciones (Encabezado y Elementos)'
358
+ };
359
+ export const AreaMode = {
360
+ args: {
361
+ title: 'Categoría con Área',
362
+ description: 'Esta categoría tiene un fondo destacado.',
363
+ area: true,
364
+ elements: mockElements
365
+ },
366
+ name: 'Modo Área'
367
+ };
368
+ export const AreaModeCustomProps = {
369
+ args: {
370
+ title: 'Área con Color Personalizado',
371
+ area: true,
372
+ areaProps: {
373
+ colorTheme: 'accent',
374
+ shade: '01'
375
+ },
376
+ elements: mockElements
377
+ },
378
+ name: 'Modo Área — Color Personalizado'
379
+ };
380
+ export const CustomDataTestId = {
381
+ args: {
382
+ title: 'Con Test ID',
383
+ elements: mockElements,
384
+ dataTestId: 'custom-data-category'
385
+ },
386
+ name: 'Con Test ID Personalizado'
387
+ };
388
+ export const Playground = {
389
+ args: {
390
+ title: 'Categoría de Datos',
391
+ description: '',
392
+ Icon: 'IconFolder',
393
+ collapsable: true,
394
+ expanded: false,
395
+ area: false,
396
+ elements: mockElementsWithActions,
397
+ dataTestId: 'playground-data-category'
398
+ },
399
+ name: 'Playground'
400
+ };
@@ -0,0 +1,40 @@
1
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
2
+ import React from 'react';
3
+ import { bool, oneOf, func, string, number, oneOfType } from 'prop-types';
4
+ import { TEST_IDS } from '../../../../constants/testIds';
5
+ import UTSwitch from '../../../UTSwitch';
6
+ import UTButton from '../../../UTButton';
7
+ import { ACTION_TYPE } from '../../constants';
8
+ const {
9
+ dataElement
10
+ } = TEST_IDS;
11
+ const MainAction = _ref => {
12
+ let {
13
+ type = ACTION_TYPE.BUTTON,
14
+ onChange,
15
+ value,
16
+ onClick,
17
+ dataTestId,
18
+ ...props
19
+ } = _ref;
20
+ return type === ACTION_TYPE.SWITCH && onChange ? /*#__PURE__*/React.createElement(UTSwitch, _extends({
21
+ onChange: onChange,
22
+ value: value
23
+ }, props, {
24
+ dataTestId: dataTestId ? "".concat(dataTestId, ".").concat(dataElement.switchAction) : undefined,
25
+ version: "V1"
26
+ })) : type === ACTION_TYPE.BUTTON && onClick ? /*#__PURE__*/React.createElement(UTButton, _extends({
27
+ dataTestId: dataTestId ? "".concat(dataTestId, ".").concat(dataElement.buttonAction) : undefined,
28
+ variant: "text",
29
+ onClick: onClick
30
+ }, props)) : null;
31
+ };
32
+ MainAction.propTypes = {
33
+ dataTestId: string,
34
+ id: oneOfType([string, number]),
35
+ onChange: func,
36
+ onClick: func,
37
+ type: oneOf(Object.values(ACTION_TYPE)),
38
+ value: bool
39
+ };
40
+ export default MainAction;
@@ -1 +1,5 @@
1
- export const WITHOUT_DATA_TEXT = 'Sin datos';
1
+ export const WITHOUT_DATA_TEXT = 'Sin datos';
2
+ export const ACTION_TYPE = {
3
+ SWITCH: 'switch',
4
+ BUTTON: 'button'
5
+ };
@@ -1,18 +1,18 @@
1
1
  function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
2
- import { array, bool, object, objectOf, string } from 'prop-types';
3
- import React, { useMemo, useRef, useState } from 'react';
2
+ import { array, bool, object, objectOf, shape, string } from 'prop-types';
3
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
4
4
  import isEmpty from 'lodash/isEmpty';
5
5
  import WithTheme from '../WithTheme';
6
6
  import UTDataElement from '../UTDataElement';
7
7
  import UTLabel from '../UTLabel';
8
- import UTButton from '../UTButton';
8
+ import UTTouchableWithoutFeedback from '../UTTouchableWithoutFeedback';
9
9
  import { mergeClasses } from '../../utils/classesUtils';
10
10
  import { TEST_IDS } from '../../constants/testIds';
11
11
  import UTIcon from '../UTIcon';
12
- import MainAction from '../UTDataElement/components/MainAction';
13
12
  import styles from './styles.module.scss';
14
13
  import { retrieveStyle } from './theme';
15
14
  import { WITHOUT_DATA_TEXT } from './constants';
15
+ import MainAction from './components/MainAction';
16
16
  const {
17
17
  dataCategory
18
18
  } = TEST_IDS;
@@ -24,6 +24,8 @@ const UTDataCategory = _ref => {
24
24
  classNames,
25
25
  collapsable = true,
26
26
  dataTestId,
27
+ description,
28
+ descriptionProps = {},
27
29
  elements = [],
28
30
  elementsProps = {},
29
31
  expanded = false,
@@ -37,13 +39,20 @@ const UTDataCategory = _ref => {
37
39
  const classes = useMemo(() => mergeClasses(theme, classNames), [classNames, theme]);
38
40
  const [isCollapsed, setIsCollapsed] = useState(showTitle && collapsable && !expanded);
39
41
  const childrenRef = useRef(null);
42
+ useEffect(() => {
43
+ setIsCollapsed(showTitle && collapsable && !expanded);
44
+ }, [expanded, showTitle, collapsable]);
40
45
  const toggleCollapsed = () => setIsCollapsed(!isCollapsed);
46
+ const handleHeaderKeyDown = useCallback(event => {
47
+ if (event.target === event.currentTarget && (event.key === 'Enter' || event.key === ' ')) {
48
+ event.preventDefault();
49
+ toggleCollapsed();
50
+ }
51
+ }, [toggleCollapsed]);
52
+ const stopActionPropagation = useCallback(event => event.stopPropagation(), []);
41
53
  const containerClasses = "".concat(styles.container, " ").concat(classes.container || '', " ").concat(area ? classes.area : '');
42
- const collapseButtonClasses = "".concat(styles.collapseButton, " ").concat(isCollapsed ? styles.collapsed : '');
43
- return /*#__PURE__*/React.createElement("div", {
44
- className: containerClasses,
45
- "data-testid": dataTestId ? "".concat(dataTestId, ".").concat(dataCategory.container) : undefined
46
- }, title && /*#__PURE__*/React.createElement("div", {
54
+ const collapseIconClasses = "".concat(styles.collapseButton, " ").concat(isCollapsed ? styles.collapsed : '');
55
+ const headerContent = /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
47
56
  className: styles.title
48
57
  }, IconComponent && /*#__PURE__*/React.createElement(IconComponent, _extends({
49
58
  name: Icon,
@@ -51,15 +60,31 @@ const UTDataCategory = _ref => {
51
60
  }, iconProps)), /*#__PURE__*/React.createElement(UTLabel, _extends({
52
61
  colorTheme: "gray",
53
62
  weight: "medium"
54
- }, titleProps), title), collapsable && /*#__PURE__*/React.createElement("div", {
55
- className: collapseButtonClasses
56
- }, /*#__PURE__*/React.createElement(UTButton, {
57
- Icon: "IconChevronUp",
58
- variant: "text",
59
- onClick: toggleCollapsed,
60
- size: "small",
63
+ }, titleProps), title), collapsable && /*#__PURE__*/React.createElement(UTIcon, {
64
+ className: collapseIconClasses,
65
+ colorTheme: "gray",
66
+ name: "IconChevronUp",
61
67
  dataTestId: dataTestId ? "".concat(dataTestId, ".").concat(dataCategory.collapseButton) : undefined
62
- })), action && /*#__PURE__*/React.createElement(MainAction, action)), /*#__PURE__*/React.createElement("div", {
68
+ }), action &&
69
+ /*#__PURE__*/
70
+ // Sin role="button": este div solo corta la propagación del click/keydown hacia el toggle de colapso, no es un control propio.
71
+ React.createElement("div", {
72
+ onClick: stopActionPropagation,
73
+ onKeyDown: stopActionPropagation
74
+ }, /*#__PURE__*/React.createElement(MainAction, action))), description && /*#__PURE__*/React.createElement(UTLabel, _extends({
75
+ colorTheme: "gray"
76
+ }, descriptionProps), description));
77
+ return /*#__PURE__*/React.createElement("div", {
78
+ className: containerClasses,
79
+ "data-testid": dataTestId ? "".concat(dataTestId, ".").concat(dataCategory.container) : undefined
80
+ }, title && (collapsable ? /*#__PURE__*/React.createElement(UTTouchableWithoutFeedback, {
81
+ className: "".concat(styles.header, " ").concat(styles.clickable),
82
+ onClick: toggleCollapsed,
83
+ onKeyDown: handleHeaderKeyDown,
84
+ "aria-expanded": !isCollapsed
85
+ }, headerContent) : /*#__PURE__*/React.createElement("div", {
86
+ className: styles.header
87
+ }, headerContent)), /*#__PURE__*/React.createElement("div", {
63
88
  style: {
64
89
  gridTemplateRows: isCollapsed ? '0fr' : '1fr',
65
90
  marginTop: isCollapsed || !showTitle ? 0 : 16
@@ -86,11 +111,16 @@ const UTDataCategory = _ref => {
86
111
  UTDataCategory.propTypes = {
87
112
  action: object,
88
113
  area: bool,
89
- areaProps: object,
114
+ areaProps: shape({
115
+ colorTheme: string,
116
+ shade: string
117
+ }),
90
118
  classes: objectOf(string),
91
119
  classNames: objectOf(string),
92
120
  collapsable: bool,
93
121
  dataTestId: string,
122
+ description: string,
123
+ descriptionProps: object,
94
124
  elements: array,
95
125
  elementsProps: object,
96
126
  expanded: bool,
@@ -3,6 +3,17 @@
3
3
  flex-direction: column;
4
4
  }
5
5
 
6
+ .header {
7
+ align-items: stretch;
8
+ display: flex;
9
+ flex-direction: column;
10
+ grid-gap: var(--UT-dataCategory-title-gap, 0.5rem);
11
+ }
12
+
13
+ .clickable {
14
+ cursor: pointer;
15
+ }
16
+
6
17
  .title {
7
18
  align-items: center;
8
19
  display: flex;