@visns-studio/visns-components 5.4.4 → 5.4.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
@@ -14,9 +14,9 @@
14
14
  "akar-icons": "^1.9.31",
15
15
  "array-move": "^4.0.0",
16
16
  "awesome-debounce-promise": "^2.1.0",
17
- "axios": "^1.8.3",
17
+ "axios": "^1.8.4",
18
18
  "dayjs": "^1.11.13",
19
- "fabric": "^6.5.4",
19
+ "fabric": "^6.6.2",
20
20
  "file-saver": "^2.0.5",
21
21
  "framer-motion": "^11.18.2",
22
22
  "html-react-parser": "^5.2.3",
@@ -27,20 +27,20 @@
27
27
  "numeral": "^2.0.6",
28
28
  "pluralize": "^8.0.0",
29
29
  "quill-image-uploader": "^1.3.0",
30
- "react-big-calendar": "^1.17.1",
30
+ "react-big-calendar": "^1.18.0",
31
31
  "react-color": "^2.19.3",
32
32
  "react-confirm-alert": "^3.0.6",
33
33
  "react-copy-to-clipboard": "^5.1.0",
34
34
  "react-datepicker": "^7.6.0",
35
- "react-dropzone": "^14.3.5",
35
+ "react-dropzone": "^14.3.8",
36
36
  "react-grid-gallery": "^1.0.1",
37
37
  "react-number-format": "^5.4.3",
38
38
  "react-password-strength-bar": "^0.4.1",
39
39
  "react-promise-tracker": "^2.1.1",
40
40
  "react-quill": "^2.0.0",
41
41
  "react-reveal": "^1.2.2",
42
- "react-router-dom": "^6.28.2",
43
- "react-select": "^5.9.0",
42
+ "react-router-dom": "^6.30.0",
43
+ "react-select": "^5.10.1",
44
44
  "react-signature-pad-wrapper": "^4.1.0",
45
45
  "react-slugify": "^4.0.1",
46
46
  "react-sortable-hoc": "^2.0.0",
@@ -55,30 +55,30 @@
55
55
  "truncate": "^3.0.0",
56
56
  "uuid": "^10.0.0",
57
57
  "validator": "^13.15.0",
58
- "vite": "^5.4.15",
58
+ "vite": "^5.4.16",
59
59
  "yarn": "^1.22.22"
60
60
  },
61
61
  "devDependencies": {
62
- "@babel/core": "^7.26.0",
63
- "@babel/plugin-transform-runtime": "^7.25.9",
64
- "@babel/preset-env": "^7.26.0",
62
+ "@babel/core": "^7.26.10",
63
+ "@babel/plugin-transform-runtime": "^7.26.10",
64
+ "@babel/preset-env": "^7.26.9",
65
65
  "@babel/preset-react": "^7.26.3",
66
66
  "babel-loader": "^9.2.1",
67
67
  "copy-webpack-plugin": "^12.0.2",
68
68
  "css-loader": "^7.1.2",
69
- "css-minimizer-webpack-plugin": "^7.0.0",
69
+ "css-minimizer-webpack-plugin": "^7.0.2",
70
70
  "mini-css-extract-plugin": "^2.9.2",
71
71
  "react": "^18.3.1",
72
72
  "react-dom": "^18.3.1",
73
- "sass": "^1.83.4",
74
- "sass-loader": "^16.0.4"
73
+ "sass": "^1.86.2",
74
+ "sass-loader": "^16.0.5"
75
75
  },
76
76
  "peerDependencies": {
77
77
  "react": "^17.0.0 || ^18.0.0",
78
78
  "react-dom": "^17.0.0 || ^18.0.0"
79
79
  },
80
80
  "name": "@visns-studio/visns-components",
81
- "version": "5.4.4",
81
+ "version": "5.4.6",
82
82
  "description": "Various packages to assist in the development of our Custom Applications.",
83
83
  "main": "src/index.js",
84
84
  "files": [
@@ -133,6 +133,7 @@ const DataGrid = forwardRef(
133
133
  columns,
134
134
  form,
135
135
  gridHeight,
136
+ hoverColor,
136
137
  mapbox,
137
138
  pageData,
138
139
  pageSetting,
@@ -2856,6 +2857,7 @@ const DataGrid = forwardRef(
2856
2857
  : 450
2857
2858
  : 400,
2858
2859
  boxShadow: 'none',
2860
+ ...(hoverColor ? { '--hover-color': hoverColor } : {}),
2859
2861
  });
2860
2862
  const headerProps = {
2861
2863
  style: style ? style : {},
@@ -0,0 +1,70 @@
1
+ # DataGrid Component
2
+
3
+ ## Customizing Hover Color
4
+
5
+ The DataGrid component now supports customizable hover colors. This allows you to set different hover colors for different instances of the DataGrid.
6
+
7
+ ### Method 1: Using the hoverColor Prop (Recommended)
8
+
9
+ The simplest way to set a custom hover color is to use the `hoverColor` prop directly:
10
+
11
+ ```jsx
12
+ import DataGrid from './components/crm/DataGrid';
13
+
14
+ // In your component
15
+ <DataGrid
16
+ hoverColor="rgb(255, 240, 230)" // Custom hover color
17
+ // other props...
18
+ />;
19
+ ```
20
+
21
+ ### Method 2: Using CSS Variables in Component Props
22
+
23
+ You can pass a custom style object to the DataGrid component with the `--hover-color` CSS variable:
24
+
25
+ ```jsx
26
+ import DataGrid from './components/crm/DataGrid';
27
+
28
+ // Define custom styles with hover color
29
+ const customStyle = {
30
+ '--hover-color': 'rgb(255, 240, 230)', // Custom hover color
31
+ };
32
+
33
+ // In your component
34
+ <DataGrid
35
+ style={customStyle}
36
+ // other props...
37
+ />;
38
+ ```
39
+
40
+ ### Method 3: Using CSS/SCSS
41
+
42
+ You can define the `--hover-color` CSS variable in your CSS or SCSS files:
43
+
44
+ ```css
45
+ /* Global default hover color */
46
+ :root {
47
+ --hover-color: rgb(230, 240, 250);
48
+ }
49
+
50
+ /* For specific containers */
51
+ .special-grid-container {
52
+ --hover-color: rgb(255, 240, 230);
53
+ }
54
+ ```
55
+
56
+ Then apply the class to your container:
57
+
58
+ ```jsx
59
+ <div className="special-grid-container">
60
+ <DataGrid {...props} />
61
+ </div>
62
+ ```
63
+
64
+ ### Default Value
65
+
66
+ If no hover color is specified (via prop or CSS variable), the DataGrid will use a default light blue color (`rgb(230, 240, 250)`).
67
+
68
+ ### Example
69
+
70
+ See the `src/examples/CustomHoverDataGrid.jsx` file for a complete example of how to implement custom hover colors using all three methods.
@@ -23,8 +23,9 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
23
23
  const swapy = useRef(null);
24
24
  const container = useRef(null);
25
25
  const navigate = useNavigate();
26
+ const initialLoadRef = useRef(true); // Ref to track initial load
26
27
  const [dashboardSetting, setDashboardSetting] = useState(
27
- userProfile.dashboard_setting || setting
28
+ dynamicDashboard ? userProfile.dashboard_setting || setting : setting
28
29
  );
29
30
  const [data, setData] = useState({});
30
31
  const [dropdowns, setDropdowns] = useState({});
@@ -84,6 +85,7 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
84
85
  try {
85
86
  const promises = dashboardSetting.widgets.map(async (widget) => {
86
87
  const widgetFilters = appliedFilters[widget.id] || {};
88
+
87
89
  if (widget.filters) {
88
90
  for (const filter of widget.filters) {
89
91
  if (filter.url) {
@@ -110,12 +112,12 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
110
112
  }
111
113
  }
112
114
  }
113
-
114
115
  if (widget.api?.url && widget.api?.method) {
115
116
  const requestParams = {
116
- ...widgetFilters,
117
117
  ...(widget.api.params || {}),
118
+ ...widgetFilters,
118
119
  };
120
+
119
121
  return CustomFetch(
120
122
  widget.api.url,
121
123
  widget.api.method,
@@ -124,11 +126,21 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
124
126
  }
125
127
  return null;
126
128
  });
129
+
127
130
  const results = await Promise.all(promises);
131
+
128
132
  const fetchedData = dashboardSetting.widgets.reduce(
129
133
  (acc, widget, index) => {
130
134
  if (results[index]) {
131
- acc[widget.id] = results[index]?.data;
135
+ // Check if the response indicates an error
136
+ if (results[index]?.data?.value) {
137
+ console.error(
138
+ `API error for widget ${widget.id}:`,
139
+ results[index].data.value
140
+ );
141
+ } else {
142
+ acc[widget.id] = results[index]?.data;
143
+ }
132
144
  }
133
145
  return acc;
134
146
  },
@@ -140,19 +152,41 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
140
152
  }
141
153
  };
142
154
 
155
+ // Single useEffect for initial data fetch
143
156
  useEffect(() => {
144
- // Check if any widget has a "filters" property.
145
- const widgetHasFilters = dashboardSetting?.widgets?.some((widget) =>
146
- widget.hasOwnProperty('filters')
147
- );
157
+ // This will run once after filters are initialized
158
+ if (Object.keys(filters).length > 0 && initialLoadRef.current) {
159
+ // Fetch data once with initial filters
160
+ fetchData(filters);
161
+ // Mark initial load as complete
162
+ initialLoadRef.current = false;
163
+ }
164
+ }, [filters]);
165
+
166
+ // Handle filter changes after initial load
167
+ const isInitialFilterChangeRef = useRef(true);
148
168
 
149
- // If a widget has filters and our filters object is empty, do nothing.
150
- if (widgetHasFilters && Object.keys(filters).length === 0) {
169
+ useEffect(() => {
170
+ // Skip the first filter change (which happens during initialization)
171
+ if (isInitialFilterChangeRef.current) {
172
+ isInitialFilterChangeRef.current = false;
151
173
  return;
152
174
  }
153
175
 
154
- fetchData(filters);
155
- }, [filters, dashboardSetting]);
176
+ // Only fetch data if filters have been initialized
177
+ if (!initialLoadRef.current && Object.keys(filters).length > 0) {
178
+ fetchData(filters);
179
+ }
180
+ }, [filters]);
181
+
182
+ // Handle dashboardSetting changes
183
+ useEffect(() => {
184
+ // Skip the initial render
185
+ if (!initialLoadRef.current) {
186
+ // Only fetch data if it's not the initial load
187
+ fetchData(filters);
188
+ }
189
+ }, [dashboardSetting]);
156
190
 
157
191
  const openModal = (widgetId) => {
158
192
  setModalContent(widgetId);
@@ -453,10 +487,12 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
453
487
  <button
454
488
  className={`${styles.btn} ${styles['btn-secondary']}`}
455
489
  onClick={() => {
490
+ // Clear filters
456
491
  setFilters((prevFilters) => ({
457
492
  ...prevFilters,
458
493
  [widget.id]: {},
459
494
  }));
495
+
460
496
  fetchData();
461
497
  }}
462
498
  >
@@ -470,11 +506,22 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
470
506
 
471
507
  const renderWidget = (widget) => {
472
508
  const widgetData = data[widget.id] || [];
473
- if (
474
- widgetData.length > 0 ||
475
- widgetData?.data?.length > 0 ||
476
- widgetData
477
- ) {
509
+
510
+ // More detailed check for valid data
511
+ const hasData =
512
+ // Array with items
513
+ (Array.isArray(widgetData) && widgetData.length > 0) ||
514
+ // Object with data array
515
+ (widgetData?.data &&
516
+ Array.isArray(widgetData.data) &&
517
+ widgetData.data.length > 0) ||
518
+ // Simple value for counter widgets
519
+ (widget.type === 'counter' &&
520
+ widgetData !== null &&
521
+ widgetData !== undefined);
522
+
523
+ if (hasData || widget.type === 'bar') {
524
+ // Always try to render bar charts for debugging
478
525
  switch (widget.type) {
479
526
  case 'counter':
480
527
  return (
@@ -524,8 +571,33 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
524
571
  let colors = {};
525
572
  let keys = [];
526
573
 
527
- // Handle new data structure (from your first example)
574
+ // Handle specific structure with bar.data property
528
575
  if (
576
+ widgetData.bar &&
577
+ widgetData.bar.data &&
578
+ Array.isArray(widgetData.bar.data)
579
+ ) {
580
+ barData = widgetData.bar.data;
581
+
582
+ // Use the keys from the data
583
+ if (widgetData.keys && Array.isArray(widgetData.keys)) {
584
+ keys = widgetData.keys;
585
+ } else if (barData[0]) {
586
+ // Extract keys from the first item, excluding indexBy field (usually 'supervisor')
587
+ const indexField =
588
+ widget.props.indexBy || 'supervisor';
589
+ keys = Object.keys(barData[0] || {}).filter(
590
+ (key) => key !== indexField
591
+ );
592
+ }
593
+
594
+ // Set the indexBy field based on the data structure
595
+ if (barData[0] && barData[0].supervisor) {
596
+ widget.props.indexBy = 'supervisor';
597
+ }
598
+ }
599
+ // Handle new data structure (from your first example)
600
+ else if (
529
601
  widgetData.data &&
530
602
  Array.isArray(widgetData.data) &&
531
603
  widgetData.colors
@@ -533,9 +605,13 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
533
605
  barData = widgetData.data;
534
606
  colors = widgetData.colors;
535
607
  // Extract keys from the first data item, excluding 'month' or any other index field
536
- keys = Object.keys(barData[0] || {}).filter(
537
- (key) => key !== 'month'
538
- );
608
+ if (barData[0]) {
609
+ keys = Object.keys(barData[0] || {}).filter(
610
+ (key) => key !== 'month'
611
+ );
612
+ } else {
613
+ console.log(`No data items found in barData`);
614
+ }
539
615
  }
540
616
  // Handle newer data structure (from your second example)
541
617
  else if (
@@ -545,6 +621,7 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
545
621
  ) {
546
622
  barData = widgetData.data;
547
623
  keys = widgetData.keys;
624
+
548
625
  // Extract colors from the first data item
549
626
  if (barData[0]) {
550
627
  keys.forEach((key) => {
@@ -555,25 +632,103 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
555
632
  });
556
633
  }
557
634
  }
635
+ // Handle array of arrays structure
636
+ else if (
637
+ Array.isArray(widgetData) &&
638
+ widgetData.length > 0 &&
639
+ Array.isArray(widgetData[0])
640
+ ) {
641
+ barData = widgetData[0];
642
+ // Try to extract keys from the first item
643
+ if (barData[0]) {
644
+ keys = Object.keys(barData[0] || {}).filter(
645
+ (key) => key !== 'month'
646
+ );
647
+ }
648
+ }
558
649
  // Handle legacy data structure
559
650
  else {
560
651
  barData =
561
652
  widgetData.bar?.data ||
562
653
  widgetData.data ||
563
654
  widgetData;
655
+
656
+ // Check if barData is an array of arrays and use the first one
657
+ if (
658
+ Array.isArray(barData) &&
659
+ barData.length > 0 &&
660
+ Array.isArray(barData[0])
661
+ ) {
662
+ barData = barData[0];
663
+ }
664
+
564
665
  if (widgetData.keys) {
565
- keys = widgetData.keys;
666
+ keys = Array.isArray(widgetData.keys)
667
+ ? widgetData.keys
668
+ : [];
669
+ } else if (barData && barData[0]) {
670
+ // Try to extract keys from the first item
671
+ keys = Object.keys(barData[0] || {}).filter(
672
+ (key) => key !== 'month'
673
+ );
566
674
  }
567
675
  }
568
676
 
569
- // Set up colors if they exist
570
- if (Object.keys(colors).length > 0) {
677
+ // Always use static colors from props if available
678
+ // First check if we have stored original colors
679
+ if (
680
+ widget.props._originalColors &&
681
+ Array.isArray(widget.props._originalColors)
682
+ ) {
683
+ // Use the stored original colors
684
+ const originalColors = widget.props._originalColors;
685
+
686
+ // Create a direct mapping of keys to colors
687
+ const colorMap = {};
688
+ if (Array.isArray(keys)) {
689
+ keys.forEach((key, index) => {
690
+ colorMap[key] =
691
+ originalColors[
692
+ index % originalColors.length
693
+ ];
694
+ });
695
+ }
696
+ }
697
+ // Otherwise use the colors from the props
698
+ else if (
699
+ widget.props.colors &&
700
+ Array.isArray(widget.props.colors) &&
701
+ widget.props.colors.length > 0
702
+ ) {
703
+ // Store the original colors array
704
+ const originalColors = [...widget.props.colors];
705
+
706
+ // Create a direct mapping of keys to colors
707
+ const colorMap = {};
708
+ if (Array.isArray(keys)) {
709
+ keys.forEach((key, index) => {
710
+ colorMap[key] =
711
+ originalColors[
712
+ index % originalColors.length
713
+ ];
714
+ });
715
+ }
716
+
717
+ // Store the original colors array in a separate property
718
+ // This ensures it's preserved for future renders
719
+ widget.props._originalColors = originalColors;
720
+ }
721
+ // Fallback to API colors if no static colors in props
722
+ else if (Object.keys(colors).length > 0) {
571
723
  widget.props.colors = ({ id }) => colors[id];
572
724
  }
573
725
 
574
726
  // Set keys in props if they exist
575
- if (keys.length > 0) {
727
+ if (Array.isArray(keys) && keys.length > 0) {
576
728
  widget.props.keys = keys;
729
+ } else {
730
+ // Set default keys if none are found
731
+ widget.props.keys = ['value'];
577
732
  }
578
733
 
579
734
  // Handle legend setup
@@ -604,19 +759,60 @@ function GenericDashboard({ setting, userProfile, dynamicDashboard = false }) {
604
759
  widget.props.tooltip = CustomTooltip;
605
760
  }
606
761
 
607
- if (barData?.length > 0) {
762
+ // Ensure barData is an array and has items
763
+ if (Array.isArray(barData) && barData.length > 0) {
764
+ // Make sure we have an indexBy field in each data item
765
+ const indexField = widget.props.indexBy || 'month';
766
+ const hasIndexField = barData.every(
767
+ (item) =>
768
+ item &&
769
+ typeof item === 'object' &&
770
+ indexField in item
771
+ );
772
+
773
+ if (!hasIndexField) {
774
+ console.warn(
775
+ `Bar data items missing required index field '${indexField}'`
776
+ );
777
+ // Add a default index if missing
778
+ barData = barData.map((item, i) => ({
779
+ ...item,
780
+ [indexField]:
781
+ item[indexField] || `Item ${i + 1}`,
782
+ }));
783
+ }
784
+
608
785
  return (
609
786
  <div style={{ height: widget.height || '600px' }}>
610
787
  <ResponsiveBar
611
788
  key={`${widget.id}-${widget.size}`}
612
789
  data={barData}
790
+ indexBy={indexField}
791
+ {...widget.props}
792
+ />
793
+ </div>
794
+ );
795
+ } else {
796
+ // Create dummy data if no data is available
797
+ const dummyData = [
798
+ {
799
+ month: 'No Data',
800
+ value: 0,
801
+ },
802
+ ];
803
+
804
+ return (
805
+ <div style={{ height: widget.height || '600px' }}>
806
+ <ResponsiveBar
807
+ key={`${widget.id}-${widget.size}`}
808
+ data={dummyData}
613
809
  indexBy="month"
810
+ keys={['value']}
614
811
  {...widget.props}
615
812
  />
616
813
  </div>
617
814
  );
618
815
  }
619
- break;
620
816
  }
621
817
  case 'line':
622
818
  if (widgetData.length > 0) {
@@ -40,6 +40,7 @@ function useConfig(setting, tabs, filters, setRowsSelected, tableSetting) {
40
40
  columns: setting.columns,
41
41
  setRowsSelected,
42
42
  settings: setting.settings,
43
+ style: setting.style || {},
43
44
  tableSetting,
44
45
  type: setting.type ? setting.type : 'table',
45
46
  });
@@ -340,6 +341,7 @@ function GenericIndex({
340
341
  <Table
341
342
  {...config}
342
343
  ref={gridRef}
344
+ hoverColor={config.style.hoverColor}
343
345
  gridHeight={windowHeight * 0.65}
344
346
  setConfig={setConfig}
345
347
  setTableData={setTableData}
@@ -23,7 +23,7 @@
23
23
 
24
24
  .vs-datagrid--row:hover {
25
25
  .InovuaReactDataGrid__row-cell-wrap {
26
- background: rgb(240, 240, 240) !important;
26
+ background: var(--hover-color, rgb(230, 240, 250)) !important;
27
27
  cursor: pointer;
28
28
  }
29
29
  }
@@ -38,7 +38,7 @@
38
38
 
39
39
  .InovuaReactDataGrid__row-hover-target:hover {
40
40
  color: var(--primary-color) !important;
41
- background: rgb(240, 240, 240) !important;
41
+ background: var(--hover-color, rgb(230, 240, 250)) !important;
42
42
  }
43
43
 
44
44
  .InovuaReactDataGrid__row:hover {
@@ -161,7 +161,7 @@ input[type]:not([type='search']):not([type='url']):not([type='hidden']):not(
161
161
 
162
162
  .vs-datagrid--row:hover {
163
163
  .InovuaReactDataGrid__row-cell-wrap {
164
- background: rgb(240, 240, 240) !important;
164
+ background: var(--hover-color, rgb(230, 240, 250)) !important;
165
165
  cursor: pointer;
166
166
  }
167
167
  }
@@ -176,7 +176,7 @@ input[type]:not([type='search']):not([type='url']):not([type='hidden']):not(
176
176
 
177
177
  .InovuaReactDataGrid__row-hover-target:hover {
178
178
  color: var(--paragraph-color) !important;
179
- background: rgb(240, 240, 240) !important;
179
+ background: var(--hover-color, rgb(230, 240, 250)) !important;
180
180
  }
181
181
 
182
182
  .InovuaReactDataGrid__row:hover {
@@ -0,0 +1,92 @@
1
+ import React from 'react';
2
+ import DataGrid from '../components/crm/DataGrid';
3
+
4
+ // Example of using custom hover color with DataGrid
5
+ const CustomHoverDataGrid = () => {
6
+ // Example DataGrid props with direct hoverColor prop
7
+ const exampleProps = {
8
+ // Your DataGrid props here
9
+ hoverColor: 'rgb(255, 240, 230)', // Peachy hover color
10
+ // Other props...
11
+ };
12
+
13
+ // Define custom styles with hover color (alternative method)
14
+ const customStyle = {
15
+ // You can define any CSS variables here
16
+ '--hover-color': 'rgb(230, 255, 230)', // Light green hover color
17
+ };
18
+
19
+ return (
20
+ <div>
21
+ <h2>DataGrid with Custom Hover Color</h2>
22
+ <p>
23
+ This example shows how to customize the hover color of the
24
+ DataGrid.
25
+ </p>
26
+
27
+ <h3>Method 1: Using the hoverColor prop (Recommended)</h3>
28
+ <div>
29
+ <DataGrid {...exampleProps} />
30
+ </div>
31
+
32
+ <h3>Method 2: Using CSS Variables in style prop</h3>
33
+ <div>
34
+ <DataGrid style={customStyle} />
35
+ </div>
36
+
37
+ <h3>Method 3: Using CSS/SCSS classes</h3>
38
+ <div className="custom-hover-grid">
39
+ <DataGrid />
40
+ </div>
41
+
42
+ <h3>How to Use Custom Hover Colors</h3>
43
+ <p>You can set a custom hover color in three ways:</p>
44
+ <ol>
45
+ <li>
46
+ <strong>Using the hoverColor prop (Recommended):</strong>
47
+ <pre>
48
+ {`
49
+ // Direct prop approach
50
+ <DataGrid
51
+ hoverColor="rgb(255, 240, 230)"
52
+ {...otherProps}
53
+ />
54
+ `}
55
+ </pre>
56
+ </li>
57
+ <li>
58
+ <strong>Using CSS Variables in style prop:</strong>
59
+ <pre>
60
+ {`
61
+ // Define in your component
62
+ const customStyle = {
63
+ '--hover-color': 'rgb(230, 255, 230)'
64
+ };
65
+
66
+ // Apply to DataGrid
67
+ <DataGrid style={customStyle} {...otherProps} />
68
+ `}
69
+ </pre>
70
+ </li>
71
+ <li>
72
+ <strong>Using CSS/SCSS:</strong>
73
+ <pre>
74
+ {`
75
+ /* In your CSS/SCSS file */
76
+ :root {
77
+ --hover-color: rgb(230, 240, 250);
78
+ }
79
+
80
+ /* For specific containers */
81
+ .custom-hover-grid {
82
+ --hover-color: rgb(200, 220, 255);
83
+ }
84
+ `}
85
+ </pre>
86
+ </li>
87
+ </ol>
88
+ </div>
89
+ );
90
+ };
91
+
92
+ export default CustomHoverDataGrid;