@visns-studio/visns-components 5.1.5 → 5.1.6
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
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"react-dom": "^17.0.0 || ^18.0.0"
|
|
78
78
|
},
|
|
79
79
|
"name": "@visns-studio/visns-components",
|
|
80
|
-
"version": "5.1.
|
|
80
|
+
"version": "5.1.6",
|
|
81
81
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
82
82
|
"main": "src/index.js",
|
|
83
83
|
"files": [
|
|
@@ -1,16 +1,93 @@
|
|
|
1
|
-
import React, { useEffect, useMemo, useState } from 'react';
|
|
1
|
+
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import ReactDOM from 'react-dom';
|
|
2
3
|
import debounce from 'lodash.debounce';
|
|
3
4
|
import { toast } from 'react-toastify';
|
|
4
|
-
import Popup from 'reactjs-popup';
|
|
5
5
|
import { confirmAlert } from 'react-confirm-alert';
|
|
6
6
|
import { TrashCan, ArrowUp, ArrowDown } from 'akar-icons';
|
|
7
|
+
import { CompactPicker } from 'react-color';
|
|
7
8
|
|
|
8
9
|
import CustomFetch from '../Fetch';
|
|
9
|
-
import Form from '../Form';
|
|
10
10
|
import MultiSelect from '../MultiSelect';
|
|
11
11
|
|
|
12
12
|
import 'react-confirm-alert/src/react-confirm-alert.css';
|
|
13
13
|
import styles from './styles/GenericEditableTable.module.scss';
|
|
14
|
+
import { set } from 'lodash';
|
|
15
|
+
|
|
16
|
+
const ColourPicker = ({ value, columnId, keyCounter, onChange }) => {
|
|
17
|
+
const [colorPickerShow, setColorPickerShow] = useState(false);
|
|
18
|
+
const colorPickerRef = useRef(null);
|
|
19
|
+
const buttonRef = useRef(null); // Reference to the button for positioning
|
|
20
|
+
const popoverRef = useRef(null); // Reference to the popover
|
|
21
|
+
|
|
22
|
+
// Handle clicks outside of the color picker to close it
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
const handleClickOutside = (event) => {
|
|
25
|
+
// Check if click is outside both the button and the popover
|
|
26
|
+
if (
|
|
27
|
+
popoverRef.current &&
|
|
28
|
+
!popoverRef.current.contains(event.target) &&
|
|
29
|
+
buttonRef.current &&
|
|
30
|
+
!buttonRef.current.contains(event.target)
|
|
31
|
+
) {
|
|
32
|
+
setColorPickerShow(false); // Close the color picker
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
37
|
+
return () =>
|
|
38
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
39
|
+
}, []);
|
|
40
|
+
|
|
41
|
+
const buttonRect = buttonRef.current
|
|
42
|
+
? buttonRef.current.getBoundingClientRect()
|
|
43
|
+
: {}; // Get button position
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<div className={styles.cpicker}>
|
|
47
|
+
<div className={styles.cpicker__btn} ref={colorPickerRef}>
|
|
48
|
+
<button
|
|
49
|
+
ref={buttonRef} // Attach ref to the button
|
|
50
|
+
style={
|
|
51
|
+
value && value !== 'null' ? { background: value } : {}
|
|
52
|
+
}
|
|
53
|
+
onClick={(e) => {
|
|
54
|
+
e.preventDefault();
|
|
55
|
+
setColorPickerShow(!colorPickerShow); // Toggle visibility
|
|
56
|
+
}}
|
|
57
|
+
>
|
|
58
|
+
☐
|
|
59
|
+
</button>
|
|
60
|
+
|
|
61
|
+
{colorPickerShow &&
|
|
62
|
+
ReactDOM.createPortal(
|
|
63
|
+
<div
|
|
64
|
+
ref={popoverRef} // Attach ref to the popover
|
|
65
|
+
className={styles.colour_popover}
|
|
66
|
+
style={{
|
|
67
|
+
position: 'absolute',
|
|
68
|
+
left: buttonRect.left, // Position it based on button's position
|
|
69
|
+
top: buttonRect.bottom + 5, // Position below the button with a small offset
|
|
70
|
+
zIndex: 9999,
|
|
71
|
+
}}
|
|
72
|
+
>
|
|
73
|
+
<div
|
|
74
|
+
className={styles.colour_cover}
|
|
75
|
+
onClick={() => setColorPickerShow(false)}
|
|
76
|
+
/>
|
|
77
|
+
<CompactPicker
|
|
78
|
+
color={value || ''}
|
|
79
|
+
onChangeComplete={(color) => {
|
|
80
|
+
onChange(color.hex, columnId, keyCounter);
|
|
81
|
+
setColorPickerShow(false);
|
|
82
|
+
}}
|
|
83
|
+
/>
|
|
84
|
+
</div>,
|
|
85
|
+
document.body // Render the popover inside the body
|
|
86
|
+
)}
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
90
|
+
};
|
|
14
91
|
|
|
15
92
|
const GenericEditableTable = ({
|
|
16
93
|
schedulingConfig,
|
|
@@ -93,6 +170,7 @@ const GenericEditableTable = ({
|
|
|
93
170
|
};
|
|
94
171
|
|
|
95
172
|
const handleFieldChange = (value, fieldId, keyCounter) => {
|
|
173
|
+
console.info('handleFieldChange', value, fieldId, keyCounter);
|
|
96
174
|
setLocalData((prev) => {
|
|
97
175
|
const updatedDetail = [...prev];
|
|
98
176
|
updatedDetail[keyCounter] = {
|
|
@@ -178,6 +256,15 @@ const GenericEditableTable = ({
|
|
|
178
256
|
if (!entry || !column) return null;
|
|
179
257
|
|
|
180
258
|
switch (column.type) {
|
|
259
|
+
case 'colour':
|
|
260
|
+
return (
|
|
261
|
+
<ColourPicker
|
|
262
|
+
value={entry[column.id] || ''}
|
|
263
|
+
columnId={column.id}
|
|
264
|
+
keyCounter={keyCounter}
|
|
265
|
+
onChange={handleFieldChange}
|
|
266
|
+
/>
|
|
267
|
+
);
|
|
181
268
|
case 'currency':
|
|
182
269
|
case 'number':
|
|
183
270
|
return (
|
|
@@ -405,19 +492,24 @@ const GenericEditableTable = ({
|
|
|
405
492
|
.reduce((sum, entry) => {
|
|
406
493
|
// For each row, sum the values based on column.keys
|
|
407
494
|
const subtotal =
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
495
|
+
Array.isArray(
|
|
496
|
+
column.keys
|
|
497
|
+
) // Ensure column.keys is an array
|
|
498
|
+
? column.keys.reduce(
|
|
499
|
+
(
|
|
500
|
+
rowSum,
|
|
501
|
+
key
|
|
502
|
+
) =>
|
|
503
|
+
rowSum +
|
|
504
|
+
(parseFloat(
|
|
505
|
+
entry[
|
|
506
|
+
key
|
|
507
|
+
]
|
|
508
|
+
) ||
|
|
509
|
+
0),
|
|
510
|
+
0
|
|
511
|
+
)
|
|
512
|
+
: 0; // Default to 0 if column.keys is not an array
|
|
421
513
|
return sum + subtotal;
|
|
422
514
|
}, 0)
|
|
423
515
|
.toLocaleString('en-AU', {
|
|
@@ -197,3 +197,60 @@
|
|
|
197
197
|
color: var(--primary-color); /* Set text color to primary color */
|
|
198
198
|
border-top: 2px solid var(--primary-color); /* Add border top to separate subtotal row */
|
|
199
199
|
}
|
|
200
|
+
|
|
201
|
+
.colour {
|
|
202
|
+
&__cover {
|
|
203
|
+
position: fixed;
|
|
204
|
+
top: 0;
|
|
205
|
+
right: 0;
|
|
206
|
+
bottom: 0;
|
|
207
|
+
left: 0;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
&__popover {
|
|
211
|
+
position: absolute;
|
|
212
|
+
z-index: 9999;
|
|
213
|
+
left: 50%; /* Position to the center or adjust accordingly */
|
|
214
|
+
top: 50%; /* Adjust top based on your layout */
|
|
215
|
+
transform: translate(-50%, -50%); /* Center it */
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.cpicker {
|
|
220
|
+
width: 100%;
|
|
221
|
+
display: flex;
|
|
222
|
+
flex-wrap: nowrap;
|
|
223
|
+
align-items: center;
|
|
224
|
+
|
|
225
|
+
&__btn {
|
|
226
|
+
flex: 1;
|
|
227
|
+
|
|
228
|
+
button {
|
|
229
|
+
width: 40px; /* Keep it compact */
|
|
230
|
+
height: 40px; /* Square button */
|
|
231
|
+
font-size: 1.5rem; /* Adjusted for a better icon size */
|
|
232
|
+
font-weight: 600;
|
|
233
|
+
color: #fff; /* White icon color */
|
|
234
|
+
background-color: #b0b0b0; /* Neutral grey base */
|
|
235
|
+
border: 2px solid #999; /* Light border for definition */
|
|
236
|
+
border-radius: 8px; /* Rounded corners */
|
|
237
|
+
cursor: pointer;
|
|
238
|
+
transition: all 0.3s ease; /* Smooth transition for hover effect */
|
|
239
|
+
|
|
240
|
+
&:hover {
|
|
241
|
+
background-color: #999; /* Darken the background on hover */
|
|
242
|
+
border-color: #666; /* Darken the border on hover */
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
&:focus {
|
|
246
|
+
outline: none; /* Remove default focus outline */
|
|
247
|
+
box-shadow: 0 0 0 2px rgba(72, 168, 58, 0.5); /* Custom focus outline */
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
&:active {
|
|
251
|
+
background-color: #888; /* Lighter grey on click */
|
|
252
|
+
transform: scale(0.98); /* Shrink on click */
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|