@visns-studio/visns-components 5.11.15 → 5.11.17

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
@@ -87,7 +87,7 @@
87
87
  "react-dom": "^17.0.0 || ^18.0.0"
88
88
  },
89
89
  "name": "@visns-studio/visns-components",
90
- "version": "5.11.15",
90
+ "version": "5.11.17",
91
91
  "description": "Various packages to assist in the development of our Custom Applications.",
92
92
  "main": "src/index.js",
93
93
  "files": [
@@ -2639,15 +2639,31 @@ const DataGrid = forwardRef(
2639
2639
  ? column.id.join('-')
2640
2640
  : column.id;
2641
2641
 
2642
+ // Auto-detect columns that should have word wrap enabled
2643
+ const shouldAutoEnableWordWrap =
2644
+ column.wordWrap !== false && // Allow explicit disable with wordWrap: false
2645
+ (
2646
+ // Text-heavy column patterns
2647
+ /^(task|description|notes?|comments?|content|message|details?|summary|reason|remarks?)$/i.test(columnId) ||
2648
+ /.*_(task|description|notes?|comments?|content|message|details?|summary|reason|remarks?)$/i.test(columnId) ||
2649
+ /(task|description|notes?|comments?|content|message|details?|summary|reason|remarks?)_.*$/i.test(columnId) ||
2650
+ // Check for long labels that might indicate text content
2651
+ (column.label && column.label.length > 15 && /description|notes|comments|details|content/i.test(column.label))
2652
+ );
2653
+
2654
+ const finalWordWrap = column.wordWrap === true || shouldAutoEnableWordWrap;
2655
+
2656
+ // Debug logging for word wrap detection
2657
+ if (shouldAutoEnableWordWrap && column.wordWrap !== true) {
2658
+ console.log(`DataGrid: Auto-enabled wordWrap for column "${columnId}" (${column.label})`);
2659
+ }
2660
+
2642
2661
  return {
2643
2662
  ...commonProps,
2644
2663
  name: columnId,
2645
2664
  filterEditor: filterEditor,
2646
2665
  filterEditorProps: filterEditorProps,
2647
- className:
2648
- column.wordWrap === true
2649
- ? 'cell-word-wrap'
2650
- : '',
2666
+ className: finalWordWrap ? 'cell-word-wrap' : '',
2651
2667
  render: ({ data }) => {
2652
2668
  if (
2653
2669
  data &&
@@ -2711,9 +2727,7 @@ const DataGrid = forwardRef(
2711
2727
  <CellWithTooltip
2712
2728
  value={data[column.id]}
2713
2729
  columnType="text"
2714
- wordWrap={
2715
- column.wordWrap === true
2716
- }
2730
+ wordWrap={finalWordWrap}
2717
2731
  >
2718
2732
  <span>
2719
2733
  {parse(content)}
@@ -1,5 +1,4 @@
1
1
  import React, { useEffect, useRef, useState } from 'react';
2
- import { createPortal } from 'react-dom';
3
2
  import { Tooltip } from 'react-tooltip';
4
3
  import moment from 'moment';
5
4
  import numeral from 'numeral';
@@ -13,6 +12,7 @@ const isTextTruncated = (element) => {
13
12
  );
14
13
  };
15
14
 
15
+
16
16
  // Utility function to format cell value for tooltip display
17
17
  const formatCellValueForTooltip = (value, columnType) => {
18
18
  if (value === null || value === undefined || value === '') {
@@ -70,12 +70,46 @@ const CellWithTooltip = ({
70
70
  // Check truncation on mount and when content changes
71
71
  checkTruncation();
72
72
 
73
- // Also check on window resize
74
- const handleResize = () => checkTruncation();
73
+ // Use intersection observer to re-check when cell becomes visible (helps with scrolling)
74
+ const observer = new IntersectionObserver(
75
+ (entries) => {
76
+ entries.forEach((entry) => {
77
+ if (entry.isIntersecting) {
78
+ // Small delay to ensure layout is complete
79
+ setTimeout(checkTruncation, 10);
80
+ } else {
81
+ // Hide tooltip when cell is out of view
82
+ setShowTooltip(false);
83
+ }
84
+ });
85
+ },
86
+ {
87
+ threshold: 0.1,
88
+ rootMargin: '50px' // Add margin to prevent premature hiding
89
+ }
90
+ );
91
+
92
+ if (cellRef.current) {
93
+ observer.observe(cellRef.current);
94
+ }
95
+
96
+ // Also check on window resize and scroll
97
+ const handleResize = () => setTimeout(checkTruncation, 10);
98
+ const handleScroll = () => setTimeout(checkTruncation, 10);
99
+
75
100
  window.addEventListener('resize', handleResize);
101
+ // Listen to scroll events on the grid container
102
+ const gridContainer = cellRef.current?.closest('.InovuaReactDataGrid');
103
+ if (gridContainer) {
104
+ gridContainer.addEventListener('scroll', handleScroll);
105
+ }
76
106
 
77
107
  return () => {
108
+ observer.disconnect();
78
109
  window.removeEventListener('resize', handleResize);
110
+ if (gridContainer) {
111
+ gridContainer.removeEventListener('scroll', handleScroll);
112
+ }
79
113
  };
80
114
  }, [children, value]);
81
115
 
@@ -104,8 +138,8 @@ const CellWithTooltip = ({
104
138
  width: '100%',
105
139
  };
106
140
 
107
- // Render tooltip using createPortal to escape stacking contexts
108
- const tooltipPortal = shouldShowTooltip && createPortal(
141
+ // Render tooltip with improved positioning
142
+ const tooltipPortal = shouldShowTooltip && (
109
143
  <Tooltip
110
144
  id={tooltipId}
111
145
  style={{
@@ -116,12 +150,21 @@ const CellWithTooltip = ({
116
150
  fontSize: '13px',
117
151
  maxWidth: '500px',
118
152
  wordWrap: 'break-word',
119
- zIndex: 9999, // Slightly lower since we're now at document.body level
153
+ zIndex: 999999,
154
+ position: 'fixed', // Ensure fixed positioning for proper calculation
120
155
  }}
121
156
  place="top"
122
- offset={5}
123
- />,
124
- document.body
157
+ offset={8}
158
+ float={false} // Prevent floating behavior that can cause displacement
159
+ clickable={false} // Prevent click interference
160
+ delayShow={300} // Small delay to prevent accidental shows
161
+ delayHide={100}
162
+ noArrow={false}
163
+ variant="dark"
164
+ className="cell-tooltip"
165
+ positionStrategy="fixed" // Use fixed positioning strategy
166
+ fallbackPlacements={['bottom', 'right', 'left']} // Fallback positions if top doesn't fit
167
+ />
125
168
  );
126
169
 
127
170
  return (
@@ -133,6 +176,8 @@ const CellWithTooltip = ({
133
176
  {...(shouldShowTooltip && {
134
177
  'data-tooltip-id': tooltipId,
135
178
  'data-tooltip-html': tooltipContent,
179
+ 'data-tooltip-place': 'top',
180
+ 'data-tooltip-offset': '8',
136
181
  })}
137
182
  >
138
183
  {children}
@@ -106,6 +106,7 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
106
106
  });
107
107
  const [modalFormShow, setModalFormShow] = useState(false);
108
108
  const [roles, setRoles] = useState([]);
109
+ const [hoveredField, setHoveredField] = useState(null);
109
110
 
110
111
  const canvasTypes = SketchConfig.canvasTypes;
111
112
 
@@ -249,9 +250,10 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
249
250
  className={`${fieldClassName} ${styles.interactiveField} ${
250
251
  styles.previewField
251
252
  } ${isDragging ? styles.dragging : ''}`}
252
- data-tooltip-id="field-tooltip"
253
- data-tooltip-content={getFieldTooltip(field)}
253
+ data-tooltip-id={hoveredField === field.id ? null : "field-tooltip"}
254
+ data-tooltip-content={hoveredField === field.id ? null : getFieldTooltip(field)}
254
255
  data-tooltip-place="top"
256
+ data-tooltip-delay-show={200}
255
257
  data-field-size={field.size}
256
258
  >
257
259
  {/* Field info - always visible */}
@@ -270,6 +272,8 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
270
272
  data-tooltip-id="action-tooltip"
271
273
  data-tooltip-content="Drag to Reorder"
272
274
  data-tooltip-place="top"
275
+ onMouseEnter={() => setHoveredField(field.id)}
276
+ onMouseLeave={() => setHoveredField(null)}
273
277
  >
274
278
  <ChevronVertical strokeWidth={3} size={24} />
275
279
  </div>
@@ -286,6 +290,8 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
286
290
  data-tooltip-id="action-tooltip"
287
291
  data-tooltip-content="Edit Field"
288
292
  data-tooltip-place="top"
293
+ onMouseEnter={() => setHoveredField(field.id)}
294
+ onMouseLeave={() => setHoveredField(null)}
289
295
  />
290
296
  <TrashCan
291
297
  className={styles.deleteIcon}
@@ -299,6 +305,8 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
299
305
  data-tooltip-id="action-tooltip"
300
306
  data-tooltip-content="Delete Field"
301
307
  data-tooltip-place="top"
308
+ onMouseEnter={() => setHoveredField(field.id)}
309
+ onMouseLeave={() => setHoveredField(null)}
302
310
  />
303
311
  </div>
304
312
  </div>
@@ -2314,10 +2322,16 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
2314
2322
  lineHeight: '1.4',
2315
2323
  maxWidth: '300px',
2316
2324
  whiteSpace: 'pre-line',
2317
- zIndex: 99999,
2325
+ zIndex: 200000,
2318
2326
  }}
2319
2327
  place="top"
2320
- offset={10}
2328
+ offset={15}
2329
+ float={true}
2330
+ noArrow={false}
2331
+ clickable={false}
2332
+ positionStrategy="fixed"
2333
+ delayShow={200}
2334
+ delayHide={50}
2321
2335
  />
2322
2336
  <Tooltip
2323
2337
  id="action-tooltip"
@@ -2327,8 +2341,33 @@ function GenericFormBuilder({ setting, urlParam, userProfile }) {
2327
2341
  borderRadius: '6px',
2328
2342
  padding: '8px 12px',
2329
2343
  fontSize: '13px',
2330
- zIndex: 9999,
2344
+ zIndex: 200001,
2345
+ }}
2346
+ place="top"
2347
+ offset={10}
2348
+ float={true}
2349
+ noArrow={false}
2350
+ clickable={false}
2351
+ positionStrategy="fixed"
2352
+ delayShow={100}
2353
+ delayHide={50}
2354
+ />
2355
+ <Tooltip
2356
+ id="system-tooltip"
2357
+ style={{
2358
+ backgroundColor: 'rgba(0, 0, 0, 0.9)',
2359
+ color: 'white',
2360
+ borderRadius: '6px',
2361
+ padding: '8px 12px',
2362
+ fontSize: '13px',
2363
+ zIndex: 200000,
2331
2364
  }}
2365
+ place="top"
2366
+ offset={10}
2367
+ float={true}
2368
+ noArrow={false}
2369
+ clickable={false}
2370
+ positionStrategy="fixed"
2332
2371
  />
2333
2372
  </div>
2334
2373
  );
@@ -1195,7 +1195,7 @@ select:not(:placeholder-shown) + .fi__span {
1195
1195
  flex-direction: column;
1196
1196
  min-height: 100px;
1197
1197
  height: 100%;
1198
- margin-top: 15px; // Add margin to provide space for tooltip above
1198
+ margin-top: 5px; // Reduced from 15px for better tooltip positioning
1199
1199
 
1200
1200
  // Ensure proper layout during sorting
1201
1201
  &.sortableHelper {
@@ -1289,25 +1289,25 @@ select:not(:placeholder-shown) + .fi__span {
1289
1289
  .dragHandle {
1290
1290
  color: var(--primary-color) !important;
1291
1291
  cursor: grab;
1292
- padding: 8px;
1293
- border-radius: 8px;
1292
+ padding: 4px;
1293
+ border-radius: 6px;
1294
1294
  background: white;
1295
1295
  border: 2px solid var(--primary-color);
1296
- box-shadow: 0 4px 12px rgba(var(--primary-rgb), 0.25);
1296
+ box-shadow: 0 2px 8px rgba(var(--primary-rgb), 0.2);
1297
1297
  transition: all 0.2s ease;
1298
1298
  font-weight: bold;
1299
1299
  display: flex !important;
1300
1300
  align-items: center;
1301
1301
  justify-content: center;
1302
- min-width: 40px;
1303
- min-height: 40px;
1302
+ min-width: 28px;
1303
+ min-height: 28px;
1304
1304
  position: relative;
1305
1305
  z-index: 1003; // Reduced from 10001 to be below modals but above content
1306
1306
 
1307
1307
  svg {
1308
1308
  display: block !important;
1309
- width: 24px !important;
1310
- height: 24px !important;
1309
+ width: 16px !important;
1310
+ height: 16px !important;
1311
1311
  stroke: currentColor !important;
1312
1312
  fill: none !important;
1313
1313
 
@@ -1320,8 +1320,8 @@ select:not(:placeholder-shown) + .fi__span {
1320
1320
  background: var(--primary-color);
1321
1321
  color: white;
1322
1322
  border-color: var(--primary-color);
1323
- transform: scale(1.1);
1324
- box-shadow: 0 6px 16px rgba(var(--primary-rgb), 0.4);
1323
+ transform: scale(1.05);
1324
+ box-shadow: 0 4px 12px rgba(var(--primary-rgb), 0.3);
1325
1325
  }
1326
1326
 
1327
1327
  &:active {
@@ -1338,26 +1338,26 @@ select:not(:placeholder-shown) + .fi__span {
1338
1338
 
1339
1339
  .editIcon,
1340
1340
  .deleteIcon {
1341
- padding: 8px;
1342
- border-radius: 8px;
1341
+ padding: 4px;
1342
+ border-radius: 6px;
1343
1343
  background: white;
1344
1344
  border: 2px solid;
1345
1345
  cursor: pointer;
1346
1346
  transition: all 0.2s ease;
1347
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1347
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
1348
1348
  font-weight: bold;
1349
1349
  display: flex !important;
1350
1350
  align-items: center;
1351
1351
  justify-content: center;
1352
- min-width: 36px;
1353
- min-height: 36px;
1352
+ min-width: 28px;
1353
+ min-height: 28px;
1354
1354
  position: relative;
1355
1355
  z-index: 1003; // Reduced from 10001 to be below modals but above content
1356
1356
 
1357
1357
  svg {
1358
1358
  display: block !important;
1359
- width: 20px !important;
1360
- height: 20px !important;
1359
+ width: 16px !important;
1360
+ height: 16px !important;
1361
1361
  stroke: currentColor !important;
1362
1362
  fill: none !important;
1363
1363
  }
@@ -1371,8 +1371,8 @@ select:not(:placeholder-shown) + .fi__span {
1371
1371
  background: var(--primary-color);
1372
1372
  color: white !important;
1373
1373
  border-color: var(--primary-color);
1374
- transform: scale(1.1);
1375
- box-shadow: 0 6px 16px rgba(var(--primary-rgb), 0.4);
1374
+ transform: scale(1.05);
1375
+ box-shadow: 0 4px 12px rgba(var(--primary-rgb), 0.3);
1376
1376
  }
1377
1377
  }
1378
1378
 
@@ -1384,8 +1384,8 @@ select:not(:placeholder-shown) + .fi__span {
1384
1384
  background: #d32f2f;
1385
1385
  color: white !important;
1386
1386
  border-color: #d32f2f;
1387
- transform: scale(1.1);
1388
- box-shadow: 0 6px 16px rgba(211, 47, 47, 0.4);
1387
+ transform: scale(1.05);
1388
+ box-shadow: 0 4px 12px rgba(211, 47, 47, 0.3);
1389
1389
  }
1390
1390
  }
1391
1391
 
@@ -1527,7 +1527,7 @@ select:not(:placeholder-shown) + .fi__span {
1527
1527
  .fieldContent {
1528
1528
  position: relative;
1529
1529
  z-index: 1;
1530
- padding-top: 55px; /* Increased space for field info and controls */
1530
+ padding-top: 45px; /* Reduced from 55px for better tooltip positioning */
1531
1531
  flex-grow: 1;
1532
1532
  display: flex;
1533
1533
  flex-direction: column;
@@ -1767,3 +1767,29 @@ select:not(:placeholder-shown) + .fi__span {
1767
1767
  }
1768
1768
  }
1769
1769
  }
1770
+
1771
+ /* Tooltip positioning fixes */
1772
+ [data-tooltip-id] {
1773
+ position: relative;
1774
+ z-index: 200000; /* Ensure tooltips are above all other elements */
1775
+ }
1776
+
1777
+ /* React Tooltip specific z-index override */
1778
+ :global([data-tooltip-id="field-tooltip"]),
1779
+ :global([data-tooltip-id="action-tooltip"]),
1780
+ :global([data-tooltip-id="system-tooltip"]) {
1781
+ position: relative;
1782
+ z-index: 200000 !important;
1783
+ }
1784
+
1785
+ /* Ensure action tooltips take priority over field tooltips */
1786
+ .dragHandle,
1787
+ .editIcon,
1788
+ .deleteIcon {
1789
+ position: relative;
1790
+ z-index: 200002;
1791
+
1792
+ &:hover {
1793
+ z-index: 200003;
1794
+ }
1795
+ }
@@ -12,6 +12,22 @@ div[role="tooltip"],
12
12
  position: fixed !important;
13
13
  }
14
14
 
15
+ /* Specific styles for cell tooltips to prevent positioning issues */
16
+ .cell-tooltip {
17
+ position: fixed !important;
18
+ z-index: 999999 !important;
19
+ pointer-events: none !important; /* Prevent tooltip from interfering with mouse events */
20
+ max-width: 500px !important;
21
+ word-wrap: break-word !important;
22
+ white-space: normal !important;
23
+ line-height: 1.4 !important;
24
+ }
25
+
26
+ /* Ensure cell tooltip arrow positioning works correctly */
27
+ .cell-tooltip .react-tooltip-arrow {
28
+ position: absolute !important;
29
+ }
30
+
15
31
  .InovuaReactDataGrid__header-wrapper {
16
32
  border-top-left-radius: var(--br, 4px) !important;
17
33
  border-top-right-radius: var(--br, 4px) !important;
@@ -46,7 +62,12 @@ div[role="tooltip"],
46
62
  text-overflow: unset !important; /* Disable text truncation */
47
63
  overflow: visible !important; /* Show wrapped content */
48
64
  height: auto !important; /* Allow cell to expand vertically */
49
- min-height: 32px !important; /* Maintain minimum height */
65
+ min-height: 40px !important; /* Increased minimum height for better spacing */
66
+ line-height: 1.4 !important; /* Better line spacing for readability */
67
+ padding: 10px 8px !important; /* Increased vertical padding for multi-line content */
68
+ vertical-align: top !important; /* Align content to top for multi-line cells */
69
+ display: flex !important; /* Use flexbox for better content alignment */
70
+ align-items: flex-start !important; /* Align content to top */
50
71
  }
51
72
 
52
73
  /* Default cell behavior - no word wrap */