@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.5",
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
+ &#9744;
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
- column.keys.reduce(
409
- (
410
- rowSum,
411
- key
412
- ) =>
413
- rowSum +
414
- (parseFloat(
415
- entry[
416
- key
417
- ]
418
- ) || 0),
419
- 0
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
+ }