ekm-ui 0.3.24 → 0.3.28
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/.turbo/turbo-build.log +40 -35
- package/CHANGELOG.md +12 -0
- package/dist/card-payment-block.css +1 -1
- package/dist/card-payment-block.css.map +1 -1
- package/dist/card-payment-block.mjs +7 -6
- package/dist/{chunk-LNK7V5RH.mjs → chunk-45QX7OUO.mjs} +2 -2
- package/dist/chunk-45QX7OUO.mjs.map +1 -0
- package/dist/chunk-5CGIKL2Y.mjs +9 -0
- package/dist/chunk-5CGIKL2Y.mjs.map +1 -0
- package/dist/chunk-BRWFUWH7.mjs +11 -0
- package/dist/chunk-BRWFUWH7.mjs.map +1 -0
- package/dist/{chunk-3LWR4ASZ.mjs → chunk-KJPNVM7M.mjs} +1 -1
- package/dist/chunk-MA4QT7NM.mjs +18 -0
- package/dist/chunk-MA4QT7NM.mjs.map +1 -0
- package/dist/file-picker/file-listing.mjs +2 -1
- package/dist/file-picker/file-picker.d.ts +4 -1
- package/dist/file-picker/file-picker.mjs +3 -2
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +7 -6
- package/dist/layout/layout.css +1 -1
- package/dist/layout/layout.css.map +1 -1
- package/dist/layout/layout.mjs +7 -6
- package/dist/progress-bar.d.ts +19 -0
- package/dist/progress-bar.mjs +5 -0
- package/dist/progress-bar.mjs.map +1 -0
- package/dist/stacked-list-item.css +1 -1
- package/dist/stacked-list-item.css.map +1 -1
- package/dist/stacked-list-item.mjs +7 -6
- package/dist/table-header/table-header.mjs +1 -1
- package/package.json +1 -1
- package/src/file-picker/file-listing.tsx +22 -23
- package/src/file-picker/file-picker.tsx +25 -17
- package/src/index.tsx +1 -0
- package/src/progress-bar.tsx +37 -0
- package/src/table-header/table-header.tsx +113 -87
- package/dist/chunk-A6OC3NNV.mjs +0 -11
- package/dist/chunk-A6OC3NNV.mjs.map +0 -1
- package/dist/chunk-LNK7V5RH.mjs.map +0 -1
- package/dist/chunk-ONI5FUPW.mjs +0 -18
- package/dist/chunk-ONI5FUPW.mjs.map +0 -1
- /package/dist/{chunk-3LWR4ASZ.mjs.map → chunk-KJPNVM7M.mjs.map} +0 -0
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
export { a as StackedListItem } from './chunk-
|
|
1
|
+
export { a as StackedListItem } from './chunk-KJPNVM7M.mjs';
|
|
2
2
|
import './chunk-EHJJX6ZZ.mjs';
|
|
3
3
|
import './chunk-YFGQ3B3L.mjs';
|
|
4
|
-
import './chunk-
|
|
4
|
+
import './chunk-45QX7OUO.mjs';
|
|
5
5
|
import './chunk-QWPN2UNV.mjs';
|
|
6
6
|
import './chunk-ASCPOK5F.mjs';
|
|
7
|
+
import './chunk-25FJ277C.mjs';
|
|
7
8
|
import './chunk-FAFXVD4P.mjs';
|
|
8
|
-
import './chunk-
|
|
9
|
-
import './chunk-
|
|
9
|
+
import './chunk-MA4QT7NM.mjs';
|
|
10
|
+
import './chunk-XFCPRHEY.mjs';
|
|
11
|
+
import './chunk-BRWFUWH7.mjs';
|
|
10
12
|
import './chunk-256SAVHD.mjs';
|
|
11
13
|
import './chunk-VPLCWU7T.mjs';
|
|
12
14
|
import './chunk-PPMW7YAZ.mjs';
|
|
13
|
-
import './chunk-
|
|
15
|
+
import './chunk-5CGIKL2Y.mjs';
|
|
14
16
|
import './chunk-NTGEZMHP.mjs';
|
|
15
17
|
import './chunk-E7S3XFB4.mjs';
|
|
16
18
|
import './chunk-RMX72FR3.mjs';
|
|
17
19
|
import './chunk-2IL2LP47.mjs';
|
|
18
20
|
import './chunk-KBXHNBM5.mjs';
|
|
19
21
|
import './chunk-EPWIDK35.mjs';
|
|
20
|
-
import './chunk-25FJ277C.mjs';
|
|
21
22
|
import './chunk-BIU2AAPZ.mjs';
|
|
22
23
|
import './chunk-D6H235SZ.mjs';
|
|
23
24
|
import './chunk-S4LI5APF.mjs';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
import { useEffect, useRef } from 'react'
|
|
3
|
-
import { Radio } from '
|
|
3
|
+
import { Radio } from '../radio'
|
|
4
4
|
import PropTypes from 'prop-types'
|
|
5
5
|
|
|
6
6
|
// FOR USE WITH THE FILE PICKER COMPONENT - ONLY
|
|
@@ -52,7 +52,7 @@ function FileRow({ file, selected = false, callback }) {
|
|
|
52
52
|
>
|
|
53
53
|
<div className="flex items-center ml-3">
|
|
54
54
|
<div className="flex-shrink-0">
|
|
55
|
-
<Radio name={file.Name} checked={selected} readOnly />
|
|
55
|
+
<Radio id={file.Name} name={file.Name} checked={selected} readOnly />
|
|
56
56
|
</div>
|
|
57
57
|
<div className="ml-4">
|
|
58
58
|
<img className="h-10 w-10 rounded-md" src={`https://files.ekmcdn.com/${file.Uri}`} alt="" />
|
|
@@ -70,29 +70,29 @@ function FileRow({ file, selected = false, callback }) {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
Listing.propTypes = {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
73
|
+
/** Border style to use*/
|
|
74
|
+
border: PropTypes.string,
|
|
75
|
+
/** Array of files to list */
|
|
76
|
+
files: PropTypes.array,
|
|
77
|
+
/** Boolean to indicate if there are more files to load */
|
|
78
|
+
isMore: PropTypes.bool,
|
|
79
|
+
/** Name of the selected file */
|
|
80
|
+
selected: PropTypes.string,
|
|
81
|
+
/** Current page */
|
|
82
|
+
page: PropTypes.number,
|
|
83
|
+
/** Total number of pages */
|
|
84
|
+
pages: PropTypes.number,
|
|
85
|
+
/** Callback function to handle events */
|
|
86
|
+
callback: PropTypes.func,
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
FileRow.propTypes = {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
90
|
+
/** File object to display */
|
|
91
|
+
file: PropTypes.object,
|
|
92
|
+
/** Boolean to indicate if the file is selected */
|
|
93
|
+
selected: PropTypes.bool,
|
|
94
|
+
/** Callback function to handle events */
|
|
95
|
+
callback: PropTypes.func,
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
function InfiniteLoader() {
|
|
@@ -129,4 +129,3 @@ function writeDate(date) {
|
|
|
129
129
|
return 'Unknown'
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
|
-
|
|
@@ -10,12 +10,14 @@ import { HiOutlineSearch } from 'react-icons/hi'
|
|
|
10
10
|
import Listing from './file-listing'
|
|
11
11
|
import PropTypes from 'prop-types'
|
|
12
12
|
|
|
13
|
+
|
|
13
14
|
const apiUrl = '/admin/api/common/directoryinformation/'
|
|
14
15
|
const Status = Object.freeze({
|
|
15
16
|
EMPTY: 'EMPTY',
|
|
16
17
|
SEARCH_LOADING: 'SEARCH-LOADING',
|
|
17
18
|
LOADING: 'LOADING',
|
|
18
19
|
LOADED: 'LOADED',
|
|
20
|
+
LOADED_NO_DRAG: 'LOADED_NO_DRAG',
|
|
19
21
|
SEARCH_RESULTS: 'SEARCH-RESULTS',
|
|
20
22
|
SEARCH_EMPTY: 'SEARCH-EMPTY',
|
|
21
23
|
UPLOAD_ERROR: 'ERROR',
|
|
@@ -24,7 +26,6 @@ const Status = Object.freeze({
|
|
|
24
26
|
|
|
25
27
|
const initialState = Object.freeze({
|
|
26
28
|
mode: Status.LOADING,
|
|
27
|
-
footerBorder: 'border-t',
|
|
28
29
|
actionBtnTxt: 'I Accept',
|
|
29
30
|
actionBtnColor: 'success',
|
|
30
31
|
listSize: 'h-5/6',
|
|
@@ -37,7 +38,6 @@ function FilePickerReducer(state, action) {
|
|
|
37
38
|
case Status.EMPTY:
|
|
38
39
|
return {
|
|
39
40
|
mode: Status.EMPTY,
|
|
40
|
-
footerBorder: 'border-t',
|
|
41
41
|
actionBtnTxt: 'Add Image',
|
|
42
42
|
actionBtnColor: 'blue',
|
|
43
43
|
listSize: 'h-5/6',
|
|
@@ -49,17 +49,24 @@ function FilePickerReducer(state, action) {
|
|
|
49
49
|
case Status.LOADED:
|
|
50
50
|
return {
|
|
51
51
|
mode: Status.LOADED,
|
|
52
|
-
footerBorder: '',
|
|
53
52
|
actionBtnTxt: 'I Accept',
|
|
54
53
|
actionBtnColor: 'success',
|
|
55
|
-
listSize: 'h-
|
|
54
|
+
listSize: 'h-[68.666667%]',
|
|
55
|
+
listBorder: 'border',
|
|
56
|
+
searchDisabled: false,
|
|
57
|
+
}
|
|
58
|
+
case Status.LOADED_NO_DRAG:
|
|
59
|
+
return {
|
|
60
|
+
mode: Status.LOADED_NO_DRAG,
|
|
61
|
+
actionBtnTxt: 'I Accept',
|
|
62
|
+
actionBtnColor: 'success',
|
|
63
|
+
listSize: 'h-[87.666667%]',
|
|
56
64
|
listBorder: 'border',
|
|
57
65
|
searchDisabled: false,
|
|
58
66
|
}
|
|
59
67
|
case Status.SEARCH_RESULTS:
|
|
60
68
|
return {
|
|
61
69
|
mode: Status.SEARCH_RESULTS,
|
|
62
|
-
footerBorder: '',
|
|
63
70
|
actionBtnTxt: 'I Accept',
|
|
64
71
|
actionBtnColor: 'success',
|
|
65
72
|
listSize: 'h-5/6',
|
|
@@ -69,7 +76,6 @@ function FilePickerReducer(state, action) {
|
|
|
69
76
|
case Status.SEARCH_EMPTY:
|
|
70
77
|
return {
|
|
71
78
|
mode: Status.SEARCH_EMPTY,
|
|
72
|
-
footerBorder: 'border-t',
|
|
73
79
|
actionBtnTxt: 'I Accept',
|
|
74
80
|
actionBtnColor: 'success',
|
|
75
81
|
listSize: 'h-5/6',
|
|
@@ -88,7 +94,7 @@ function FilePickerReducer(state, action) {
|
|
|
88
94
|
* be handled by the parent/calling component
|
|
89
95
|
*/
|
|
90
96
|
|
|
91
|
-
export function FilePicker({ appUrl, uri, show, onClose, callback }) {
|
|
97
|
+
export function FilePicker({ appUrl, uri, show, hideDrag = false, onClose, callback }) {
|
|
92
98
|
const searchFieldRef = useRef()
|
|
93
99
|
const [state, dispatch] = useReducer(FilePickerReducer, { mode: Status.LOADING, footerBorder: 'border-t' })
|
|
94
100
|
const [totalPages, setTotalPages] = useState(0)
|
|
@@ -157,7 +163,8 @@ export function FilePicker({ appUrl, uri, show, onClose, callback }) {
|
|
|
157
163
|
if (search?.length > 0) {
|
|
158
164
|
dispatch({ type: data.Items.Data.length > 0 ? Status.SEARCH_RESULTS : Status.SEARCH_EMPTY })
|
|
159
165
|
} else {
|
|
160
|
-
|
|
166
|
+
const loadedState = hideDrag ? Status.LOADED_NO_DRAG : Status.LOADED
|
|
167
|
+
dispatch({ type: data.Items.Data.length > 0 ? loadedState : Status.EMPTY })
|
|
161
168
|
}
|
|
162
169
|
|
|
163
170
|
setUploadedImage('none')
|
|
@@ -170,12 +177,14 @@ export function FilePicker({ appUrl, uri, show, onClose, callback }) {
|
|
|
170
177
|
}
|
|
171
178
|
|
|
172
179
|
const handleDragEnter = (e) => {
|
|
180
|
+
if (hidedrag) return
|
|
173
181
|
setDragging(true)
|
|
174
182
|
searchFieldRef.current.removeFocus()
|
|
175
183
|
e.preventDefault()
|
|
176
184
|
}
|
|
177
185
|
|
|
178
186
|
const handleDragLeave = (e) => {
|
|
187
|
+
if (hidedrag) return
|
|
179
188
|
setDragging(false)
|
|
180
189
|
}
|
|
181
190
|
|
|
@@ -265,7 +274,7 @@ export function FilePicker({ appUrl, uri, show, onClose, callback }) {
|
|
|
265
274
|
if (!err) return state.listSize
|
|
266
275
|
|
|
267
276
|
if (state.mode === Status.LOADED) return 'h-2/4'
|
|
268
|
-
if (state.mode === Status.SEARCH_RESULTS) {
|
|
277
|
+
if (state.mode === Status.SEARCH_RESULTS || state.mode === Status.LOADED_NO_DRAG) {
|
|
269
278
|
return 'h-2/3'
|
|
270
279
|
} else {
|
|
271
280
|
return state.listSize
|
|
@@ -280,9 +289,10 @@ export function FilePicker({ appUrl, uri, show, onClose, callback }) {
|
|
|
280
289
|
return <LoadingPlaceholder />
|
|
281
290
|
case Status.SEARCH_RESULTS:
|
|
282
291
|
case Status.LOADED:
|
|
292
|
+
case Status.LOADED_NO_DRAG:
|
|
283
293
|
return (
|
|
284
294
|
<Listing
|
|
285
|
-
border={
|
|
295
|
+
border={state.listSize}
|
|
286
296
|
files={files}
|
|
287
297
|
isMore={currentPageRef.current < listAttributeRef.current.pages}
|
|
288
298
|
selected={selected?.Name}
|
|
@@ -313,7 +323,7 @@ export function FilePicker({ appUrl, uri, show, onClose, callback }) {
|
|
|
313
323
|
<p>There was an error uploading the file. Please try again.</p>
|
|
314
324
|
</AlertBanner>
|
|
315
325
|
)}
|
|
316
|
-
{state.mode !== Status.SEARCH_RESULTS && state.mode !== Status.SEARCH_EMPTY && (
|
|
326
|
+
{state.mode !== Status.SEARCH_RESULTS && state.mode !== Status.SEARCH_EMPTY && !hideDrag && (
|
|
317
327
|
<div className="h-68">
|
|
318
328
|
<DragAndDrop uploaded={uploadedImage} callback={handleFileUpload} errorCallback={handleDropError} />
|
|
319
329
|
</div>
|
|
@@ -336,13 +346,10 @@ export function FilePicker({ appUrl, uri, show, onClose, callback }) {
|
|
|
336
346
|
return (
|
|
337
347
|
<Drawer show={show} onClose={handleClose} title="File Picker" onHide={() => {}}>
|
|
338
348
|
<div className="h-full" onDragEnter={handleDragEnter}>
|
|
339
|
-
{show && dragging && renderOversizedDropZone()}
|
|
349
|
+
{show && dragging && !hidedrag && renderOversizedDropZone()}
|
|
340
350
|
{show && renderContent()}
|
|
341
351
|
</div>
|
|
342
|
-
<div
|
|
343
|
-
className={`grid grid-cols-2 grid-flow-col gap-4 bottom-0 mt-0 pt-2 ${state.footerBorder} bg-white border-gray-200 dark:border-gray-600`}
|
|
344
|
-
style={{ marginTop: '-50px' }}
|
|
345
|
-
>
|
|
352
|
+
<div className={`grid grid-cols-2 grid-flow-col gap-4 bottom-0 mt-0 pt-2 bg-white dark:border-gray-600`} style={{ marginTop: '-50px' }}>
|
|
346
353
|
<Button color="light" onClick={handleClose}>
|
|
347
354
|
Close
|
|
348
355
|
</Button>
|
|
@@ -354,7 +361,6 @@ export function FilePicker({ appUrl, uri, show, onClose, callback }) {
|
|
|
354
361
|
)
|
|
355
362
|
}
|
|
356
363
|
|
|
357
|
-
|
|
358
364
|
FilePicker.propTypes = {
|
|
359
365
|
/** The url of the app */
|
|
360
366
|
appUrl: PropTypes.string.isRequired,
|
|
@@ -362,6 +368,8 @@ FilePicker.propTypes = {
|
|
|
362
368
|
uri: PropTypes.string.isRequired,
|
|
363
369
|
/** Show the drawer */
|
|
364
370
|
show: PropTypes.bool.isRequired,
|
|
371
|
+
/** Hides the the drag and drop and assosiated functionality */
|
|
372
|
+
hideDrag: PropTypes.bool,
|
|
365
373
|
/** Callback to close the drawer */
|
|
366
374
|
onClose: PropTypes.func.isRequired,
|
|
367
375
|
/** Callback to return the selected image */
|
package/src/index.tsx
CHANGED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
|
|
4
|
+
const colors = Object.freeze({
|
|
5
|
+
primary: 'bg-blue-600 dark:bg-blue-500',
|
|
6
|
+
secondary: 'bg-gray-600 dark:bg-gray-500',
|
|
7
|
+
success: 'bg-green-600 dark:bg-green-500',
|
|
8
|
+
danger: 'bg-red-600 dark:bg-red-500',
|
|
9
|
+
warning: 'bg-yellow-600 dark:bg-yellow-500',
|
|
10
|
+
info: 'bg-blue-600 dark:bg-blue-500',
|
|
11
|
+
light: 'bg-gray-100 dark:bg-gray-900',
|
|
12
|
+
dark: 'bg-gray-800 dark:bg-gray-200',
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
const sizes = Object.freeze({
|
|
16
|
+
sm: 'h-1.5 mb-4',
|
|
17
|
+
md: 'h-2.5 mb-4',
|
|
18
|
+
lg: 'h-4 mb-4',
|
|
19
|
+
xl: 'h-6',
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
export function ProgressBar({ progress, size = 'md', color='primary'}) {
|
|
23
|
+
return (
|
|
24
|
+
<div className={`w-full bg-gray-200 rounded-full ${sizes[size]} mb-4 dark:bg-gray-700`}>
|
|
25
|
+
<div className={`${sizes[size]} rounded-full ${colors[color]}`} style={{ width: `${progress}%` }}></div>
|
|
26
|
+
</div>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
ProgressBar.propTypes = {
|
|
31
|
+
/** Current progress to be shown (defaults to 0) */
|
|
32
|
+
progress: PropTypes.number.isRequired,
|
|
33
|
+
/** Size of the progress bar (defaults to md) */
|
|
34
|
+
size: PropTypes.oneOf(['sm', 'md', 'lg', 'xl']),
|
|
35
|
+
/** Color of the progress bar (defaults to primary) */
|
|
36
|
+
color: PropTypes.oneOf(['primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark']),
|
|
37
|
+
}
|
|
@@ -1,137 +1,151 @@
|
|
|
1
1
|
//@ts-nocheck
|
|
2
|
-
import React, { useState, useEffect, useRef, useCallback } from
|
|
3
|
-
import PropTypes from
|
|
4
|
-
import { Checkbox, Label, Tooltip } from
|
|
5
|
-
import _, { isEqual } from
|
|
6
|
-
import {
|
|
2
|
+
import React, { useState, useEffect, useRef, useCallback } from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { Checkbox, Label, Tooltip } from "flowbite-react";
|
|
5
|
+
import _, { isEqual } from "lodash";
|
|
6
|
+
import {
|
|
7
|
+
HiOutlineChevronUp,
|
|
8
|
+
HiOutlineChevronDown,
|
|
9
|
+
HiExclamationCircle,
|
|
10
|
+
} from "react-icons/hi";
|
|
7
11
|
|
|
8
12
|
function useDebounceEffect(effect, delay, deps) {
|
|
9
|
-
const renderRef = useRef(0)
|
|
10
|
-
const handlerRef = useRef(null)
|
|
11
|
-
const callback = useCallback(effect, deps)
|
|
13
|
+
const renderRef = useRef(0);
|
|
14
|
+
const handlerRef = useRef(null);
|
|
15
|
+
const callback = useCallback(effect, deps);
|
|
12
16
|
|
|
13
17
|
useEffect(() => {
|
|
14
18
|
if (renderRef.current !== 1) {
|
|
15
|
-
renderRef.current += 1 // Ignore running on first render
|
|
19
|
+
renderRef.current += 1; // Ignore running on first render
|
|
16
20
|
} else {
|
|
17
21
|
handlerRef.current = setTimeout(() => {
|
|
18
|
-
callback()
|
|
19
|
-
}, delay)
|
|
22
|
+
callback();
|
|
23
|
+
}, delay);
|
|
20
24
|
}
|
|
21
25
|
return () => {
|
|
22
|
-
clearTimeout(handlerRef.current)
|
|
23
|
-
}
|
|
24
|
-
}, [callback, delay])
|
|
26
|
+
clearTimeout(handlerRef.current);
|
|
27
|
+
};
|
|
28
|
+
}, [callback, delay]);
|
|
25
29
|
}
|
|
26
30
|
// This is used to perform deep object comparisson instead
|
|
27
31
|
// of using the useEffect method.
|
|
28
32
|
function useDeepEffect(effectFunc, deps) {
|
|
29
|
-
const isFirst = useRef(true)
|
|
30
|
-
const prevDeps = useRef(deps)
|
|
33
|
+
const isFirst = useRef(true);
|
|
34
|
+
const prevDeps = useRef(deps);
|
|
31
35
|
|
|
32
36
|
useEffect(() => {
|
|
33
|
-
const isSame = prevDeps.current.every((obj, index) =>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
const isSame = prevDeps.current.every((obj, index) =>
|
|
38
|
+
isEqual(obj, deps[index])
|
|
39
|
+
);
|
|
40
|
+
if (isFirst.current || !isSame) effectFunc();
|
|
41
|
+
isFirst.current = false;
|
|
42
|
+
prevDeps.current = deps;
|
|
43
|
+
}, deps);
|
|
38
44
|
}
|
|
39
45
|
|
|
40
46
|
// This is used to represent a single header and should be
|
|
41
47
|
// used only with the Table header.
|
|
42
48
|
function TableHeaderItem({ ...props }) {
|
|
43
|
-
const HeaderSortModes = { ASC:
|
|
44
|
-
const [sort, setSort] = useState(HeaderSortModes.OFF)
|
|
45
|
-
const [hitCount, setHitCount] = useState(0) // required for debounce
|
|
49
|
+
const HeaderSortModes = { ASC: "ASC", DSC: "DSC", OFF: "OFF" };
|
|
50
|
+
const [sort, setSort] = useState(HeaderSortModes.OFF);
|
|
51
|
+
const [hitCount, setHitCount] = useState(0); // required for debounce
|
|
46
52
|
|
|
47
|
-
const { title, layout, sortable, override, callback, tooltip } = props
|
|
53
|
+
const { title, layout, sortable, override, callback, tooltip } = props;
|
|
48
54
|
|
|
49
55
|
const cycleSortMode = () => {
|
|
50
|
-
if (!sortable) return
|
|
51
|
-
let newSort = sort
|
|
56
|
+
if (!sortable) return;
|
|
57
|
+
let newSort = sort;
|
|
52
58
|
switch (sort) {
|
|
53
59
|
case HeaderSortModes.OFF:
|
|
54
|
-
newSort = HeaderSortModes.DSC
|
|
55
|
-
break
|
|
60
|
+
newSort = HeaderSortModes.DSC;
|
|
61
|
+
break;
|
|
56
62
|
case HeaderSortModes.ASC:
|
|
57
|
-
newSort = HeaderSortModes.OFF
|
|
58
|
-
break
|
|
63
|
+
newSort = HeaderSortModes.OFF;
|
|
64
|
+
break;
|
|
59
65
|
case HeaderSortModes.DSC:
|
|
60
|
-
newSort = HeaderSortModes.ASC
|
|
61
|
-
break
|
|
66
|
+
newSort = HeaderSortModes.ASC;
|
|
67
|
+
break;
|
|
62
68
|
default:
|
|
63
|
-
break
|
|
69
|
+
break;
|
|
64
70
|
}
|
|
65
71
|
// Only update if mode changes.
|
|
66
72
|
if (newSort !== sort) {
|
|
67
|
-
setSort(newSort)
|
|
68
|
-
callback({ title, sort: newSort })
|
|
73
|
+
setSort(newSort);
|
|
74
|
+
callback({ title, sort: newSort });
|
|
69
75
|
}
|
|
70
|
-
}
|
|
76
|
+
};
|
|
71
77
|
|
|
72
78
|
useDebounceEffect(
|
|
73
79
|
() => {
|
|
74
80
|
// Prevents triggering on first render
|
|
75
|
-
if (hitCount > 0) cycleSortMode()
|
|
81
|
+
if (hitCount > 0) cycleSortMode();
|
|
76
82
|
},
|
|
77
83
|
500,
|
|
78
|
-
[hitCount]
|
|
79
|
-
)
|
|
84
|
+
[hitCount]
|
|
85
|
+
);
|
|
80
86
|
|
|
81
87
|
// This is used to force a sort state on the header via props.
|
|
82
88
|
useDeepEffect(() => {
|
|
83
|
-
if (override == null) return
|
|
89
|
+
if (override == null) return;
|
|
84
90
|
|
|
85
91
|
if (title !== override.title) {
|
|
86
92
|
if (sort !== HeaderSortModes.OFF) {
|
|
87
|
-
setSort(HeaderSortModes.OFF)
|
|
93
|
+
setSort(HeaderSortModes.OFF);
|
|
88
94
|
}
|
|
89
|
-
return
|
|
95
|
+
return;
|
|
90
96
|
}
|
|
91
97
|
if (title === override.title && sort !== override.sort) {
|
|
92
|
-
if (Object.values(HeaderSortModes).indexOf(override.sort) === -1) return
|
|
93
|
-
let newSort = override.sort
|
|
98
|
+
if (Object.values(HeaderSortModes).indexOf(override.sort) === -1) return;
|
|
99
|
+
let newSort = override.sort;
|
|
94
100
|
switch (override.sort) {
|
|
95
101
|
case HeaderSortModes.OFF:
|
|
96
|
-
newSort = HeaderSortModes.OFF
|
|
97
|
-
break
|
|
102
|
+
newSort = HeaderSortModes.OFF;
|
|
103
|
+
break;
|
|
98
104
|
case HeaderSortModes.ASC:
|
|
99
|
-
newSort = HeaderSortModes.ASC
|
|
100
|
-
break
|
|
105
|
+
newSort = HeaderSortModes.ASC;
|
|
106
|
+
break;
|
|
101
107
|
case HeaderSortModes.DSC:
|
|
102
|
-
newSort = HeaderSortModes.DSC
|
|
103
|
-
break
|
|
108
|
+
newSort = HeaderSortModes.DSC;
|
|
109
|
+
break;
|
|
104
110
|
default:
|
|
105
|
-
break
|
|
111
|
+
break;
|
|
106
112
|
}
|
|
107
113
|
// Only update if mode changes.
|
|
108
114
|
if (newSort !== sort) {
|
|
109
|
-
setSort(newSort)
|
|
115
|
+
setSort(newSort);
|
|
110
116
|
}
|
|
111
117
|
}
|
|
112
|
-
}, [override])
|
|
118
|
+
}, [override]);
|
|
113
119
|
|
|
114
120
|
const renderCheveron = () => {
|
|
115
121
|
return sort === HeaderSortModes.ASC ? (
|
|
116
122
|
<HiOutlineChevronUp className="float-right ml-2 " fontSize="20px" />
|
|
117
123
|
) : (
|
|
118
124
|
<HiOutlineChevronDown className="float-right ml-2 " fontSize="20px" />
|
|
119
|
-
)
|
|
120
|
-
}
|
|
125
|
+
);
|
|
126
|
+
};
|
|
121
127
|
|
|
122
128
|
return (
|
|
123
|
-
<div
|
|
129
|
+
<div
|
|
130
|
+
className={`${layout} ${sortable ? "cursor-pointer" : ""} ${
|
|
131
|
+
tooltip != null ? " d-flex align-items-center float-left" : ""
|
|
132
|
+
} `}
|
|
133
|
+
>
|
|
124
134
|
<span onClick={() => setHitCount(hitCount + 1)}>{title}</span>
|
|
125
135
|
{sortable && sort !== HeaderSortModes.OFF && renderCheveron()}
|
|
126
136
|
{tooltip != null && (
|
|
127
137
|
<div className="float-right ml-2">
|
|
128
|
-
<Tooltip
|
|
138
|
+
<Tooltip
|
|
139
|
+
key={`tooltipName-${title}`}
|
|
140
|
+
placement="bottom"
|
|
141
|
+
content={tooltip}
|
|
142
|
+
>
|
|
129
143
|
<HiExclamationCircle fontSize="20px" color="#555555" />
|
|
130
144
|
</Tooltip>
|
|
131
145
|
</div>
|
|
132
146
|
)}
|
|
133
147
|
</div>
|
|
134
|
-
)
|
|
148
|
+
);
|
|
135
149
|
}
|
|
136
150
|
|
|
137
151
|
TableHeaderItem.propTypes = {
|
|
@@ -144,61 +158,73 @@ TableHeaderItem.propTypes = {
|
|
|
144
158
|
}),
|
|
145
159
|
callback: PropTypes.func,
|
|
146
160
|
tooltip: PropTypes.string,
|
|
147
|
-
}
|
|
161
|
+
};
|
|
148
162
|
|
|
149
163
|
TableHeaderItem.defaultProps = {
|
|
150
|
-
layout:
|
|
164
|
+
layout: "col-2 font-weight-bold",
|
|
151
165
|
sortable: false,
|
|
152
166
|
override: null,
|
|
153
167
|
tooltip: null,
|
|
154
|
-
}
|
|
168
|
+
};
|
|
155
169
|
|
|
156
170
|
export function TableHeader({
|
|
157
171
|
config,
|
|
158
172
|
callback,
|
|
159
173
|
forceCheckedState = false,
|
|
160
174
|
checkboxCallback,
|
|
161
|
-
layout =
|
|
175
|
+
layout = "form-row tableHeader--custom align-items-center d-none d-lg-flex",
|
|
162
176
|
forceSort,
|
|
163
177
|
selected = 0,
|
|
164
178
|
actions,
|
|
165
179
|
}) {
|
|
166
|
-
const HeaderSortModes = { ASC:
|
|
167
|
-
const [changeSortTo, setChangeSortTo] = useState(null)
|
|
168
|
-
const [checked, setChecked] = useState(forceCheckedState)
|
|
180
|
+
const HeaderSortModes = { ASC: "ASC", DSC: "DSC", OFF: "OFF" };
|
|
181
|
+
const [changeSortTo, setChangeSortTo] = useState(null);
|
|
182
|
+
const [checked, setChecked] = useState(forceCheckedState);
|
|
169
183
|
|
|
170
184
|
const handleHeaderSort = (sortBy) => {
|
|
171
|
-
setChangeSortTo(sortBy)
|
|
172
|
-
callback(sortBy)
|
|
173
|
-
}
|
|
185
|
+
setChangeSortTo(sortBy);
|
|
186
|
+
callback(sortBy);
|
|
187
|
+
};
|
|
174
188
|
|
|
175
189
|
const handleHeaderCheckbox = () => {
|
|
176
|
-
let status = !checked
|
|
177
|
-
setChecked(status)
|
|
178
|
-
checkboxCallback(status)
|
|
179
|
-
}
|
|
190
|
+
let status = !checked;
|
|
191
|
+
setChecked(status);
|
|
192
|
+
checkboxCallback(status);
|
|
193
|
+
};
|
|
180
194
|
|
|
181
195
|
useDeepEffect(() => {
|
|
182
|
-
if (forceSort == null) return
|
|
183
|
-
if (forceSort.title == null || forceSort.sort == null) return
|
|
196
|
+
if (forceSort == null) return;
|
|
197
|
+
if (forceSort.title == null || forceSort.sort == null) return;
|
|
184
198
|
|
|
185
199
|
if (Object.values(HeaderSortModes).indexOf(forceSort.sort) !== -1) {
|
|
186
|
-
setChangeSortTo({ title: forceSort.title, sort: forceSort.sort })
|
|
200
|
+
setChangeSortTo({ title: forceSort.title, sort: forceSort.sort });
|
|
187
201
|
}
|
|
188
|
-
}, [forceSort])
|
|
202
|
+
}, [forceSort]);
|
|
189
203
|
|
|
190
204
|
useEffect(() => {
|
|
191
|
-
setChecked(forceCheckedState)
|
|
192
|
-
}, [forceCheckedState])
|
|
205
|
+
setChecked(forceCheckedState);
|
|
206
|
+
}, [forceCheckedState]);
|
|
193
207
|
|
|
194
208
|
return (
|
|
195
209
|
<div className={layout}>
|
|
196
210
|
{config.checkbox && (
|
|
197
|
-
<div className=
|
|
198
|
-
<Checkbox
|
|
211
|
+
<div className={`col-1 font-weight-bold ${config.checkboxLayout}`}>
|
|
212
|
+
<Checkbox
|
|
213
|
+
id="checkAll"
|
|
214
|
+
className="custom-control-input "
|
|
215
|
+
checked={checked}
|
|
216
|
+
onChange={() => {}}
|
|
217
|
+
/>
|
|
199
218
|
<div className="-mt-1.5">
|
|
200
|
-
<Label
|
|
201
|
-
|
|
219
|
+
<Label
|
|
220
|
+
className="-mt-1.5"
|
|
221
|
+
htmlFor="checkAll"
|
|
222
|
+
style={{ fontSize: "14px", fontWeight: "700 !important" }}
|
|
223
|
+
onClick={handleHeaderCheckbox}
|
|
224
|
+
>
|
|
225
|
+
{!config.hideSelectedNum && (checked || selected > 0)
|
|
226
|
+
? `${selected} Selected`
|
|
227
|
+
: ""}
|
|
202
228
|
</Label>
|
|
203
229
|
</div>
|
|
204
230
|
</div>
|
|
@@ -217,10 +243,10 @@ export function TableHeader({
|
|
|
217
243
|
callback={handleHeaderSort}
|
|
218
244
|
tooltip={val.tooltip}
|
|
219
245
|
/>
|
|
220
|
-
)
|
|
246
|
+
);
|
|
221
247
|
})}
|
|
222
248
|
</div>
|
|
223
|
-
)
|
|
249
|
+
);
|
|
224
250
|
}
|
|
225
251
|
|
|
226
252
|
TableHeader.propTypes = {
|
|
@@ -234,7 +260,7 @@ TableHeader.propTypes = {
|
|
|
234
260
|
layout: PropTypes.string,
|
|
235
261
|
sortable: PropTypes.bool,
|
|
236
262
|
tooltip: PropTypes.string,
|
|
237
|
-
})
|
|
263
|
+
})
|
|
238
264
|
).isRequired,
|
|
239
265
|
}).isRequired,
|
|
240
266
|
/** Optional setting the checkbox*/
|
|
@@ -258,4 +284,4 @@ TableHeader.propTypes = {
|
|
|
258
284
|
callback: PropTypes.func.isRequired,
|
|
259
285
|
/** Optional return call triggered when the optional header checkbox is clicked */
|
|
260
286
|
checkboxCallback: PropTypes.func,
|
|
261
|
-
}
|
|
287
|
+
};
|