groovinads-ui 1.2.41 → 1.2.43

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.41",
4
+ "version": "1.2.43",
5
5
  "keywords": [
6
6
  "css",
7
7
  "sass",
@@ -1,4 +1,4 @@
1
- import React, { useState } from 'react';
1
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
 
4
4
  // BOOTSTRAP
@@ -18,13 +18,18 @@ const DropdownFilter = ({
18
18
  locked = false,
19
19
  onRemoveFilter,
20
20
  show,
21
+ setShow,
21
22
  onToggle,
22
23
  overflow = false,
23
24
  className = '',
24
-
25
+ autoClose,
25
26
  }) => {
26
27
  const [query, setQuery] = useState('');
27
28
 
29
+ const [innerShow, setInnerShow] = useState(!!show);
30
+
31
+ const dropdownRef = useRef(null);
32
+
28
33
  const EmptySpace = () => {
29
34
  return (
30
35
  <div className='dropdown-filter-empty-space'>
@@ -37,46 +42,69 @@ const DropdownFilter = ({
37
42
  <p>It looks like this value does not exist.</p>
38
43
  </div>
39
44
  </div>
40
- )
41
- }
45
+ );
46
+ };
42
47
 
43
48
  const handleCheckbox = (value, i) => {
44
- if (value) setValuesSelected([...valuesSelected, values[i]]);
45
- else setValuesSelected(valuesSelected.filter((item) => item !== values[i]));
46
- };
49
+ if (value) setValuesSelected([...valuesSelected, values[i]]);
50
+ else setValuesSelected(valuesSelected.filter((item) => item !== values[i]));
51
+ };
47
52
 
48
53
  const selectAll = () => {
49
54
  setValuesSelected([...values]);
50
- }
55
+ };
51
56
 
52
57
  const clearSelection = () => {
53
58
  setValuesSelected([]);
54
- }
59
+ };
55
60
 
56
61
  const handlePill = (index) =>
57
- setValuesSelected(valuesSelected.filter((item, i) => i !== index));
62
+ setValuesSelected(valuesSelected.filter((item, i) => i !== index));
63
+
64
+ useEffect(() => {
65
+ setInnerShow(show);
66
+ }, [show]);
67
+
68
+ const handleClickOutside = useCallback((event) => {
69
+ if (
70
+ dropdownRef?.current &&
71
+ !dropdownRef?.current.contains(event?.target) &&
72
+ (autoClose === true || autoClose === 'outside')
73
+ ) {
74
+ setInnerShow(false);
75
+ setShow(false);
76
+ }
77
+ }, []);
78
+
79
+ useEffect(() => {
80
+ document.addEventListener('click', handleClickOutside);
81
+ return () => {
82
+ document.removeEventListener('click', handleClickOutside);
83
+ };
84
+ }, []);
58
85
 
59
86
  return (
60
87
  <Dropdown
61
- show={show}
62
88
  onToggle={onToggle}
63
89
  className={`dropdown-filter ${locked ? 'locked' : ''} ${className}`}
64
- autoClose={false}
90
+ autoClose={autoClose}
91
+ show={innerShow}
92
+ ref={dropdownRef}
65
93
  >
66
94
  <Dropdown.Toggle
67
95
  variant='toggle-filter'
96
+ onClick={(e) => {
97
+ e.stopPropagation(); // Detiene la propagación del clic
98
+ setInnerShow((prevShow) => !prevShow); // Alterna el estado interno del dropdown
99
+ setShow((prevShow) => !prevShow); // Alterna el estado del dropdown en el estado externo también
100
+ }}
68
101
  >
69
102
  <div className='filter-heading'>
70
-
71
103
  <div className='filter-title'>
72
104
  <span>{title}</span>
73
105
  {locked && (
74
- <Icon
75
- style={'solid'}
76
- iconName={'lock-keyhole'}
77
- scale={0.7}
78
- />
79
- )}
106
+ <Icon style={'solid'} iconName={'lock-keyhole'} scale={0.7} />
107
+ )}
80
108
  </div>
81
109
  <Icon
82
110
  style={'solid'}
@@ -86,7 +114,11 @@ const DropdownFilter = ({
86
114
  />
87
115
  </div>
88
116
  <div className='filter-values'>
89
- { valuesSelected.length === values.length ? 'All selected' : valuesSelected.length ? valuesSelected.join('; ') : 'None'}
117
+ {valuesSelected.length === values.length
118
+ ? 'All selected'
119
+ : valuesSelected.length
120
+ ? valuesSelected.join('; ')
121
+ : 'None'}
90
122
  </div>
91
123
  </Dropdown.Toggle>
92
124
  {!locked && (
@@ -100,9 +132,17 @@ const DropdownFilter = ({
100
132
  )}
101
133
 
102
134
  {menuType === 'simple' && (
103
- <Dropdown.Menu
135
+ <Dropdown.Menu
104
136
  className='dropdown-menu-simple'
105
- popperConfig={overflow ? { strategy: 'fixed', onFirstUpdate: () => window.dispatchEvent(new CustomEvent('scroll')) } : undefined}
137
+ popperConfig={
138
+ overflow
139
+ ? {
140
+ strategy: 'fixed',
141
+ onFirstUpdate: () =>
142
+ window.dispatchEvent(new CustomEvent('scroll')),
143
+ }
144
+ : undefined
145
+ }
106
146
  >
107
147
  <div className='dropdown-menu-wrapper'>
108
148
  <Input
@@ -111,35 +151,50 @@ const DropdownFilter = ({
111
151
  icon='magnifying-glass'
112
152
  className='w-100'
113
153
  value={query}
114
- onChange={({target}) => setQuery(target.value)}
154
+ onChange={({ target }) => setQuery(target.value)}
115
155
  customRef={show}
116
156
  />
117
- {values.filter( (item) => item.toLowerCase().includes(query.toLowerCase() ) ).length > 0 ? (
157
+ {values.filter((item) =>
158
+ item.toString().toLowerCase().includes(query.toLowerCase()),
159
+ ).length > 0 ? (
118
160
  <ul className='dropdown-filter-list'>
119
161
  {/* List values */}
120
- {values.filter( (item) => item.toLowerCase().includes(query.toLowerCase() ) ).map((value, index) => {
121
- return (
122
- <Checkbox
123
- setStatus={ (status) => {handleCheckbox(status, index)} }
124
- status={valuesSelected.includes(value)}
125
- key={'Dropdown.Simple.Checkbox' + index}
126
- >
127
- {value}
128
- </Checkbox>
162
+ {values
163
+ .filter((item) =>
164
+ item.toString().toLowerCase().includes(query.toLowerCase()),
129
165
  )
130
- })}
166
+ .map((value, index) => {
167
+ return (
168
+ <Checkbox
169
+ setStatus={(status) => {
170
+ handleCheckbox(status, index);
171
+ }}
172
+ status={valuesSelected.includes(value)}
173
+ key={'Dropdown.Simple.Checkbox' + index}
174
+ >
175
+ {value}
176
+ </Checkbox>
177
+ );
178
+ })}
131
179
  </ul>
132
180
  ) : (
133
181
  <EmptySpace />
134
182
  )}
135
183
  </div>
136
-
137
- </Dropdown.Menu>
138
- )}
139
- {menuType === 'selection' && (
140
- <Dropdown.Menu
141
- className='dropdown-menu-selection'
142
- popperConfig={overflow ? { strategy: 'fixed', onFirstUpdate: () => window.dispatchEvent(new CustomEvent('scroll')) } : undefined}
184
+ </Dropdown.Menu>
185
+ )}
186
+ {menuType === 'selection' && (
187
+ <Dropdown.Menu
188
+ className='dropdown-menu-selection'
189
+ popperConfig={
190
+ overflow
191
+ ? {
192
+ strategy: 'fixed',
193
+ onFirstUpdate: () =>
194
+ window.dispatchEvent(new CustomEvent('scroll')),
195
+ }
196
+ : undefined
197
+ }
143
198
  >
144
199
  <div className='dropdown-menu-wrapper'>
145
200
  <div className='dropdown-filter-list-wrapper'>
@@ -149,25 +204,36 @@ const DropdownFilter = ({
149
204
  icon='magnifying-glass'
150
205
  className='w-100'
151
206
  value={query}
152
- onChange={({target}) => setQuery(target.value)}
207
+ onChange={({ target }) => setQuery(target.value)}
153
208
  customRef={show}
154
209
  />
155
210
  <h4>All values ({values.length})</h4>
156
- {values.filter( (item) => item.toLowerCase().includes(query.toLowerCase() ) ).length > 0 ? (
211
+ {values.filter((item) =>
212
+ item.toString().toLowerCase().includes(query.toLowerCase()),
213
+ ).length > 0 ? (
157
214
  <>
158
215
  <ul className='dropdown-filter-list'>
159
216
  {/* List values */}
160
- {values.filter( (item) => item.toLowerCase().includes(query.toLowerCase() ) ).map((value, index) => {
161
- return (
162
- <Checkbox
163
- setStatus={ (status) => {handleCheckbox(status, index)} }
164
- status={valuesSelected.includes(value)}
165
- key={'Dropdown.Selection.Checkbox' + index}
166
- >
167
- {value}
168
- </Checkbox>
217
+ {values
218
+ .filter((item) =>
219
+ item
220
+ .toString()
221
+ .toLowerCase()
222
+ .includes(query.toLowerCase()),
169
223
  )
170
- })}
224
+ .map((value, index) => {
225
+ return (
226
+ <Checkbox
227
+ setStatus={(status) => {
228
+ handleCheckbox(status, index);
229
+ }}
230
+ status={valuesSelected.includes(value)}
231
+ key={'Dropdown.Selection.Checkbox' + index}
232
+ >
233
+ {value}
234
+ </Checkbox>
235
+ );
236
+ })}
171
237
  </ul>
172
238
  </>
173
239
  ) : (
@@ -201,19 +267,20 @@ const DropdownFilter = ({
201
267
  <PillComponent
202
268
  color='light'
203
269
  closeButton={true}
204
- onClick={ () => { handlePill(index) } }
270
+ onClick={() => {
271
+ handlePill(index);
272
+ }}
205
273
  key={'Dropdown.PillComponent' + index}
206
274
  >
207
275
  {value}
208
276
  </PillComponent>
209
- )
277
+ );
210
278
  })}
211
279
  </div>
212
280
  </div>
213
281
  </div>
214
-
215
- </Dropdown.Menu>
216
- )}
282
+ </Dropdown.Menu>
283
+ )}
217
284
  </Dropdown>
218
285
  );
219
286
  };
@@ -227,9 +294,11 @@ DropdownFilter.propTypes = {
227
294
  locked: PropTypes.bool,
228
295
  onRemoveFilter: PropTypes.func,
229
296
  show: PropTypes.bool,
297
+ setShow: PropTypes.func,
230
298
  onToggle: PropTypes.func,
231
299
  overflow: PropTypes.bool,
232
300
  className: PropTypes.string,
301
+ autoClose: PropTypes.bool,
233
302
  };
234
303
 
235
- export default DropdownFilter;
304
+ export default DropdownFilter;
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useRef, useState } from 'react';
1
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
 
4
4
  // BOOTSTRAP
@@ -26,6 +26,7 @@ const DropdownMultiSelect = ({
26
26
  setValuesSelected,
27
27
  values = [],
28
28
  show,
29
+ setShow,
29
30
  idInPill = false,
30
31
  showStatus = '',
31
32
  focus = false,
@@ -33,6 +34,9 @@ const DropdownMultiSelect = ({
33
34
  nowrap = false,
34
35
  }) => {
35
36
  const [query, setQuery] = useState('');
37
+ const [innerShow, setInnerShow] = useState(!!show);
38
+
39
+ const dropdownRef = useRef(null);
36
40
 
37
41
  const { highlightText } = useTextFormatter();
38
42
 
@@ -69,16 +73,47 @@ const DropdownMultiSelect = ({
69
73
  (showStatus ? parseInt(item.status) === parseInt(showStatus) : true),
70
74
  );
71
75
 
76
+ useEffect(() => {
77
+ setInnerShow(show);
78
+ }, [show]);
79
+
80
+ const handleClickOutside = useCallback((event) => {
81
+ if (
82
+ dropdownRef?.current &&
83
+ !dropdownRef?.current.contains(event?.target) &&
84
+ (autoClose === true || autoClose === 'outside')
85
+ ) {
86
+ setInnerShow(false);
87
+ setShow(false);
88
+ }
89
+ }, []);
90
+
91
+ useEffect(() => {
92
+ document.addEventListener('click', handleClickOutside);
93
+ return () => {
94
+ document.removeEventListener('click', handleClickOutside);
95
+ };
96
+ }, []);
97
+
72
98
  return (
73
99
  <Dropdown
74
100
  className={className}
75
101
  autoClose={autoClose}
76
- show={show}
102
+ show={innerShow}
103
+ ref={dropdownRef}
77
104
  onToggle={onToggle}
78
105
  drop={drop}
79
106
  >
80
- <Dropdown.Toggle as={'div'} className={`btn btn-${buttonVariant} w-100 ${nowrap ? 'nowrap' : ''}`}>
81
- {( valuesSelected.length > 0 && buttonVariant === 'input' ) && (
107
+ <Dropdown.Toggle
108
+ as={'div'}
109
+ className={`btn btn-${buttonVariant} w-100 ${nowrap ? 'nowrap' : ''}`}
110
+ onClick={(e) => {
111
+ e.stopPropagation(); // Detiene la propagación del clic
112
+ setInnerShow((prevShow) => !prevShow); // Alterna el estado interno del dropdown
113
+ setShow((prevShow) => !prevShow); // Alterna el estado del dropdown en el estado externo también
114
+ }}
115
+ >
116
+ {valuesSelected.length > 0 && buttonVariant === 'input' && (
82
117
  <div className='wrapper'>
83
118
  {valuesSelected.map((value, index) => {
84
119
  return (
@@ -181,6 +216,7 @@ DropdownMultiSelect.propTypes = {
181
216
  setValuesSelected: PropTypes.func,
182
217
  values: PropTypes.array,
183
218
  show: PropTypes.bool,
219
+ setShow: PropTypes.func,
184
220
  object: PropTypes.bool,
185
221
  nameKey: PropTypes.string,
186
222
  idKey: PropTypes.string,
@@ -11,8 +11,9 @@ import useTextFormatter from '../../hooks/useTextFormatter';
11
11
  function Tabnav({
12
12
  tabs = [],
13
13
  activeTab = 1,
14
- navigateTab= false,
14
+ navigateTab = false,
15
15
  setActiveTab,
16
+ onNavigate,
16
17
  }) {
17
18
  const { toCamelCase } = useTextFormatter();
18
19
 
@@ -22,19 +23,16 @@ function Tabnav({
22
23
  const handleSelect = (k) => {
23
24
  if (navigateTab) {
24
25
  const tab = tabs.find((tab) => toCamelCase(tab.tab) === k);
25
- console.log(tab.url);
26
- window.location.href = tab.url;
27
- }else{
28
- // console.log('Valor de k:', k);
26
+ onNavigate(tab.url);
27
+ } else {
29
28
  const tabIndex = tabs.findIndex((tab) => toCamelCase(tab.tab) === k) + 1;
30
29
  setActiveTab ? setActiveTab(tabIndex) : setActiveTabState(tabIndex);
31
30
  }
32
31
  };
33
32
 
34
33
  const formatTabsName = (tab) => {
35
- if (tab === 'api_keys') {
36
- return 'API Keys';
37
- }
34
+ if (tab === 'api_keys') return 'API Keys';
35
+
38
36
  const tabReplace = tab.replace('_', ' ');
39
37
  return tabReplace.charAt(0).toUpperCase() + tabReplace.slice(1);
40
38
  };
@@ -67,7 +65,7 @@ function Tabnav({
67
65
  Tabnav.propTypes = {
68
66
  tabs: PropTypes.array.isRequired,
69
67
  activeTab: PropTypes.number,
70
- customFunction: PropTypes.bool,
68
+ customFunction: PropTypes.bool,
71
69
  navigateTab: PropTypes.bool,
72
70
  setExternalTab: PropTypes.func,
73
71
  };