groovinads-ui 1.2.69 → 1.2.70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "groovinads-ui",
3
3
  "description": "Groovinads UI is a React component library designed exclusively for Groovinads applications. It provides ready-to-use UI elements styled according to Groovinads design guidelines to facilitate rapid development.",
4
- "version": "1.2.69",
4
+ "version": "1.2.70",
5
5
  "keywords": [
6
6
  "css",
7
7
  "sass",
@@ -18,6 +18,7 @@ const DropdownMultiSelect = ({
18
18
  inputLabel = '',
19
19
  object = false,
20
20
  nameKey,
21
+ customKey,
21
22
  idKey,
22
23
  searchLabel = 'Search',
23
24
  onToggle,
@@ -43,6 +44,8 @@ const DropdownMultiSelect = ({
43
44
  const [innerShow, setInnerShow] = useState(!!show);
44
45
 
45
46
  const dropdownRef = useRef(null);
47
+ const toggleRef = useRef(null);
48
+ const menuRef = useRef(null);
46
49
 
47
50
  const { highlightText } = useTextFormatter();
48
51
 
@@ -73,14 +76,13 @@ const DropdownMultiSelect = ({
73
76
 
74
77
  const valuesFromSearch = () =>
75
78
  values.filter(
76
- (item) =>
77
- (object ? `${item[idKey]} ${item[nameKey]}` : item)
78
- .toLowerCase()
79
- .includes(query.toLowerCase()) &&
80
- (showStatus ? parseInt(item.status) === parseInt(showStatus) : true),
81
- );
79
+ (item) =>
80
+ (object ? `${item[idKey]} ${item[nameKey]} ${item[customKey]}` : item)
81
+ .toLowerCase()
82
+ .includes(query.toLowerCase()) &&
83
+ (showStatus ? parseInt(item.status) === parseInt(showStatus) : true),
84
+ );
82
85
 
83
-
84
86
  const handleClickOutside = useCallback((event) => {
85
87
  if (
86
88
  dropdownRef?.current &&
@@ -91,7 +93,7 @@ const DropdownMultiSelect = ({
91
93
  setShow(false);
92
94
  }
93
95
  }, []);
94
-
96
+
95
97
  // VALIDATION REQUIRED
96
98
  const validateRequired = () => {
97
99
  if (!valuesSelected.length) {
@@ -100,11 +102,11 @@ const DropdownMultiSelect = ({
100
102
  }, 2000);
101
103
  }
102
104
  };
103
-
105
+
104
106
  useEffect(() => {
105
107
  setInnerShow(show);
106
108
  }, [show]);
107
-
109
+
108
110
  useEffect(() => {
109
111
  document.addEventListener('click', handleClickOutside);
110
112
  return () => {
@@ -115,6 +117,33 @@ const DropdownMultiSelect = ({
115
117
  useEffect(() => {
116
118
  if (validate && errorRequired) validateRequired();
117
119
  }, [validate, errorRequired]);
120
+
121
+ useEffect(() => {
122
+ if (overflow && menuRef.current && toggleRef.current) {
123
+ menuRef.current.style.width = `${toggleRef.current.offsetWidth}px`;
124
+ }
125
+ }, [innerShow, overflow]);
126
+
127
+ useEffect(() => {
128
+ function updateMenuWidth() {
129
+ if (overflow && menuRef.current && toggleRef.current) {
130
+ const width = toggleRef.current.offsetWidth;
131
+ menuRef.current.style.width = `${width}px`;
132
+ menuRef.current.style.minWidth = `${width}px`;
133
+ menuRef.current.style.maxWidth = `${width}px`;
134
+ }
135
+ }
136
+
137
+ if (innerShow) {
138
+ updateMenuWidth();
139
+ window.addEventListener('resize', updateMenuWidth);
140
+ }
141
+
142
+ return () => {
143
+ window.removeEventListener('resize', updateMenuWidth);
144
+ };
145
+ }, [innerShow, overflow]);
146
+
118
147
  return (
119
148
  <Dropdown
120
149
  className={className}
@@ -127,7 +156,8 @@ const DropdownMultiSelect = ({
127
156
  >
128
157
  <Dropdown.Toggle
129
158
  as={'div'}
130
- className={`btn btn-${buttonVariant} w-100 ${nowrap ? 'nowrap' : ''}${errorRequired && valuesSelected.length === 0 ? 'not-validated' : ''}`}
159
+ ref={toggleRef}
160
+ className={`btn btn-${buttonVariant} ${nowrap ? 'nowrap' : ''}${errorRequired && valuesSelected.length === 0 ? 'not-validated' : ''}`}
131
161
  onClick={(e) => {
132
162
  e.stopPropagation(); // Detiene la propagación del clic
133
163
  setInnerShow((prevShow) => !prevShow); // Alterna el estado interno del dropdown
@@ -147,8 +177,14 @@ const DropdownMultiSelect = ({
147
177
  }}
148
178
  key={'Dropdown.PillComponent' + index}
149
179
  >
150
- {idInPill ? `#${value[idKey]} - ` : ''}
151
- <span>{object ? value[nameKey] : value}</span>
180
+ {customKey
181
+ ? `${value[nameKey]} - ${value[customKey]}`
182
+ : idInPill
183
+ ? `#${value[idKey]}`
184
+ : value[nameKey] || value}
185
+
186
+ {/* {idInPill ? `#${value[idKey]} - ` : ''}
187
+ <span>{object ? value[nameKey] : value}</span> */}
152
188
  </PillComponent>
153
189
  );
154
190
  })}
@@ -165,6 +201,7 @@ const DropdownMultiSelect = ({
165
201
 
166
202
  <Dropdown.Menu
167
203
  className='w-100'
204
+ ref={menuRef}
168
205
  popperConfig={
169
206
  overflow
170
207
  ? {
@@ -208,7 +245,9 @@ const DropdownMultiSelect = ({
208
245
  >
209
246
  {highlightText(
210
247
  object
211
- ? `${hasId ? `#${value[idKey]} - ` : ''}${value[nameKey]}`
248
+ ? customKey
249
+ ? `${value[nameKey]} - ${value[customKey]}`
250
+ : `${hasId ? `#${value[idKey]} - ` : ''}${value[nameKey]}`
212
251
  : value[nameKey] || value,
213
252
  query,
214
253
  )}
@@ -242,6 +281,7 @@ DropdownMultiSelect.propTypes = {
242
281
  setShow: PropTypes.func,
243
282
  object: PropTypes.bool,
244
283
  nameKey: PropTypes.string,
284
+ customKey: PropTypes.string,
245
285
  idKey: PropTypes.string,
246
286
  idInPill: PropTypes.bool,
247
287
  showStatus: PropTypes.string,
@@ -25,7 +25,9 @@ const Sidebar = ({
25
25
  inModal = false,
26
26
  customUrl,
27
27
  }) => {
28
- const isMobile = inModal ? true : useMediaQuery({ query: '(max-width: 992px)' });
28
+ const isMobile = inModal
29
+ ? true
30
+ : useMediaQuery({ query: '(max-width: 992px)' });
29
31
 
30
32
  const url = customUrl !== undefined ? customUrl : window.location.pathname; // to get current url
31
33
 
@@ -55,7 +57,8 @@ const Sidebar = ({
55
57
 
56
58
  useEffect(() => {
57
59
  if (isMobile && setShow && !inModal) setShow(innerShow);
58
- if (!inModal) setInnerShow(isMobile ? false : firstOpen.current ? defaultOpened : show);
60
+ if (!inModal)
61
+ setInnerShow(isMobile ? false : firstOpen.current ? defaultOpened : show);
59
62
  firstOpen.current = false;
60
63
  }, []);
61
64
 
@@ -80,13 +83,14 @@ const Sidebar = ({
80
83
  <div className='scroll'>
81
84
  {customLinks.map((section, i) => (
82
85
  <div className='sidebar-section' key={`sectionIndex${i}`}>
83
- {section.title ? <h4>{section.title}</h4> : <></> }
86
+ {section.title ? <h4>{section.title}</h4> : <></>}
84
87
 
85
88
  {/* PROPS LINKS */}
86
- {(section.backData ? sidebarLinks : section.links || []).map(
87
- (linkSection, y) => (
88
- <ul className='nav' key={`linksSections${y}`}>
89
- <li className='nav-item'>
89
+
90
+ <ul className='nav'>
91
+ {(section.backData ? sidebarLinks : section.links || []).map(
92
+ (linkSection, y) => (
93
+ <li className='nav-item' key={`linksSections${y}`}>
90
94
  {/* CHILDREN - If has children, the collapse is expanded */}
91
95
  {linkSection.children && linkSection.children.length ? (
92
96
  <>
@@ -121,20 +125,41 @@ const Sidebar = ({
121
125
  </Collapse>
122
126
  </>
123
127
  ) : (
124
- <button
125
- className={`nav-link ${
126
- url === linkSection.url ? 'active' : ''
127
- }`}
128
- onClick={() => onNavigate(linkSection.url)}
129
- >
130
- <Icon iconName={linkSection.icon} />
131
- {linkSection.name}
132
- </button>
128
+ <>
129
+ <button
130
+ className={`nav-link ${
131
+ url === linkSection.url ? 'active' : ''
132
+ }`}
133
+ onClick={() => onNavigate(linkSection.url)}
134
+ >
135
+ <Icon iconName={linkSection.icon} />
136
+
137
+ {linkSection.pendingType ? (
138
+ <div className='link-wrapper'>
139
+ {linkSection.name}
140
+ {linkSection.pendingLength > 0 &&
141
+ (linkSection.pendingType === 'warning' ? (
142
+ <Icon
143
+ iconName='triangle-exclamation'
144
+ className='warning-icon'
145
+ style='duotone'
146
+ />
147
+ ) : linkSection.pendingType === 'badge' ? (
148
+ <span className='badge'>
149
+ {linkSection.pendingLength}
150
+ </span>
151
+ ) : null)}
152
+ </div>
153
+ ) : (
154
+ linkSection.name
155
+ )}
156
+ </button>
157
+ </>
133
158
  )}
134
159
  </li>
135
- </ul>
136
- ),
137
- )}
160
+ ),
161
+ )}
162
+ </ul>
138
163
  </div>
139
164
  ))}
140
165
  </div>
@@ -160,13 +185,14 @@ Sidebar.propTypes = {
160
185
  setShow: PropTypes.func, // Add setShow prop for controlling visibility
161
186
  onNavigate: PropTypes.func.isRequired, // Nueva prop para manejar la navegación
162
187
  selectedClient: PropTypes.object,
163
- showClients:PropTypes.oneOf([true, false, 'single']),
188
+ showClients: PropTypes.oneOf([true, false, 'single']),
164
189
  setGroovinProfile: PropTypes.func,
165
190
  inModal: PropTypes.bool,
166
191
  customUrl: PropTypes.oneOfType([
167
192
  PropTypes.string,
168
- PropTypes.oneOf([undefined])
169
- ]),
193
+ PropTypes.oneOf([undefined]),
194
+ ]),
195
+ pendingType: PropTypes.oneOf(['warning', 'badge']),
170
196
  };
171
197
 
172
198
  export default Sidebar;
@@ -2,8 +2,8 @@ import React, { useState } from 'react';
2
2
  import DropdownMultiSelect from '../components/Dropdowns/DropdownMultiSelect';
3
3
 
4
4
  export default {
5
- title: 'Dropdown/DropdownMultiSelect',
6
- component: DropdownMultiSelect,
5
+ title: 'Dropdown/DropdownMultiSelect',
6
+ component: DropdownMultiSelect,
7
7
  };
8
8
 
9
9
  const Template = (args) => {
@@ -15,12 +15,12 @@ const Template = (args) => {
15
15
  /* ========== */
16
16
  /* OPCION 1 - Opciones y valores seleccionados son array de objetos */
17
17
  const filters = [
18
- { id: 1, name: 'Filter 1', showStatus: '1' },
19
- { id: 2, name: 'Filter 2', showStatus: '0' },
20
- { id: 3, name: 'Filter 3', showStatus: '1' },
21
- { id: 4, name: 'Filter 4', showStatus: '0' },
22
- { id: 5, name: 'Filter 5', showStatus: '0' },
23
- { id: 6, name: 'Filter 6', showStatus: '2' },
18
+ { id: 1, name: 'Filter 1', showStatus: '1', name1: 'loreal' },
19
+ { id: 2, name: 'Filter 2', showStatus: '0', name1: 'jabon' },
20
+ { id: 3, name: 'Filter 3', showStatus: '1', name1: 'blue' },
21
+ { id: 4, name: 'Filter 4', showStatus: '0', name1: 'name' },
22
+ { id: 5, name: 'Filter 5', showStatus: '0', name1: 'name' },
23
+ { id: 6, name: 'Filter 6', showStatus: '2', name1: 'name' },
24
24
  ];
25
25
  const [selectedValues, setSelectedValues] = useState([]);
26
26
  /* ========== */
@@ -35,11 +35,12 @@ const Template = (args) => {
35
35
  'Filter 5',
36
36
  ];
37
37
  const [selectedStringValues, setSelectedStringValues] = useState([]);
38
+
39
+ /* const list= ['palabra1', 'palabra2'] */
38
40
  /* =========== */
39
41
 
40
42
  return (
41
43
  <>
42
- {/* OPCION 1 */}
43
44
  <DropdownMultiSelect
44
45
  {...args}
45
46
  values={filters}
@@ -49,32 +50,21 @@ const Template = (args) => {
49
50
  onToggle={handleToggle}
50
51
  object={true}
51
52
  nameKey='name'
53
+ nameKey1='name1'
52
54
  idKey={'id'}
53
55
  inputLabel={'Filters (array de objetos)'}
54
56
  focus={show}
55
- hasId={true}
57
+ hasId={false}
56
58
  errorRequired={errorRequired}
57
59
  setErrorRequiered={setErrorRequired}
58
60
  validate={true}
61
+ disableHash={true}
62
+ overflow={true}
59
63
  />
60
- <button className='my-3' onClick={() => setErrorRequired(true)}>Validate</button>
61
-
62
64
 
63
- {/* OPCION 2 */}
64
- <DropdownMultiSelect
65
- {...args}
66
- values={stringFilters}
67
- valuesSelected={selectedStringValues}
68
- setValuesSelected={setSelectedStringValues}
69
- show={show}
70
- onToggle={handleToggle}
71
- object={false}
72
- nameKey='name'
73
- idKey={'id'}
74
- inputLabel={'Filters (array de strings)'}
75
- focus={show}
76
- hasId={true}
77
- />
65
+ <button className='my-3' onClick={() => setErrorRequired(true)}>
66
+ Validate
67
+ </button>
78
68
  </>
79
69
  );
80
70
  };
@@ -1,4 +1,4 @@
1
- import React, { Children } from 'react';
1
+ import React, { Children, useState } from 'react';
2
2
  import { Sidebar } from '../components/Navigation';
3
3
 
4
4
  export default {
@@ -12,12 +12,29 @@ const Template = (args) => {
12
12
  {
13
13
  title: 'Main menu', // section.title
14
14
  links: [
15
-
16
15
  {
17
- name: 'Home',
18
- icon: 'home',
16
+ name: 'Campaings',
17
+ icon: 'home',
19
18
  url: '/home',
20
19
  children: [],
20
+ pendingLength: 5, // explanation(number) Pass the length of the array from the relevant endpoint data, for example, if there are pending campaigns.
21
+ // Not required, only if you want to display a type of pendingType ('warning' or 'badge').
22
+ pendingType: 'warning',
23
+ },
24
+ {
25
+ name: 'Reports',
26
+ icon: 'home',
27
+ url: '/home',
28
+ children: [
29
+ /* {
30
+ name: 'Item 1',
31
+ icon: 'home',
32
+ url: '/home',
33
+ children: [],
34
+ }, */
35
+ ],
36
+ pendingLength: 5,
37
+ pendingType: 'badge',
21
38
  },
22
39
  ],
23
40
  },
@@ -26,7 +43,7 @@ const Template = (args) => {
26
43
  links: [
27
44
  {
28
45
  name: 'Impressions',
29
- icon: 'table',
46
+ icon: 'table',
30
47
  url: '',
31
48
  children: [
32
49
  {
@@ -44,6 +61,14 @@ const Template = (args) => {
44
61
  name: 'Monthly impressions by...',
45
62
  url: '/impressions',
46
63
  },
64
+ {
65
+ name: '2Monthly impressions by...',
66
+ url: '/2impressions',
67
+ },
68
+ {
69
+ name: '3Monthly impressions by...',
70
+ url: '/3impressions',
71
+ },
47
72
  ],
48
73
  },
49
74
  ],
@@ -117,7 +142,7 @@ const Template = (args) => {
117
142
  php_session_id: 'u7o2br84i92jmfkdrqen10ngp1',
118
143
  is_api2_login: true,
119
144
  };
120
-
145
+
121
146
  return (
122
147
  <div className='container-fluid'>
123
148
  <Sidebar
package/version.js ADDED
@@ -0,0 +1,8 @@
1
+ import packageJson from './package.json';
2
+
3
+ if (typeof window !== 'undefined') {
4
+ window.GroovinUI = {
5
+ version: packageJson.version,
6
+ };
7
+ }
8
+ export default packageJson.version;