@visns-studio/visns-components 5.11.3 → 5.11.4
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/README.md +55 -0
- package/package.json +1 -1
- package/src/components/crm/BusinessCardOcr.jsx +190 -6
- package/src/components/crm/Navigation.jsx +65 -5
- package/src/components/crm/generic/GenericReport.jsx +1457 -434
- package/src/components/crm/generic/styles/GenericReport.module.scss +598 -24
- package/src/components/crm/styles/BusinessCardOcr.module.scss +362 -94
- package/src/components/crm/styles/Navigation.module.scss +95 -23
package/README.md
CHANGED
|
@@ -1650,6 +1650,61 @@ Modal components support vertical alignment configuration with the `verticalAlig
|
|
|
1650
1650
|
|
|
1651
1651
|
The ReactDataGrid's `defaultGroupBy` prop enables internal grouping functionality that creates collapsible group headers within the table structure. It does NOT create any external UI elements that need relocation, as all grouping controls are internal to the table component.
|
|
1652
1652
|
|
|
1653
|
+
### Navigation Component Icon Visibility Issues
|
|
1654
|
+
|
|
1655
|
+
#### Browser Rendering Optimization Fix
|
|
1656
|
+
|
|
1657
|
+
**Problem:** Navigation action icons (specifically anchor/Link elements) would disappear during page scroll in production environments. The issue only affected anchor tags while button elements remained visible. Notably, the problem disappeared when browser dev tools were open, indicating a browser rendering optimization conflict.
|
|
1658
|
+
|
|
1659
|
+
**Root Cause:** Firefox and other browsers apply aggressive rendering optimizations that can incorrectly cull elements from the paint tree. The combination of CSS `contain: layout` property with sticky positioning was causing anchor elements to be optimized out of view during scroll events.
|
|
1660
|
+
|
|
1661
|
+
**Solution Applied:**
|
|
1662
|
+
|
|
1663
|
+
1. **Removed problematic containment properties:**
|
|
1664
|
+
- Removed `contain: layout` from `.content-header` and action elements
|
|
1665
|
+
- This property was causing layout optimization conflicts
|
|
1666
|
+
|
|
1667
|
+
2. **Enhanced compositor layer creation:**
|
|
1668
|
+
- Changed `transform: translateZ(0)` to `transform: translateZ(0) translateX(0) translateY(0)`
|
|
1669
|
+
- Added `isolation: isolate` to force elements onto their own render layers
|
|
1670
|
+
- Added `backface-visibility: hidden` to prevent rendering glitches
|
|
1671
|
+
|
|
1672
|
+
3. **Improved z-index stacking:**
|
|
1673
|
+
- Elevated z-index values from 100-103 range to 1000-1003 range
|
|
1674
|
+
- Ensures action icons stay above sticky header's stacking context
|
|
1675
|
+
|
|
1676
|
+
**Files Modified:**
|
|
1677
|
+
- `src/components/crm/styles/Navigation.module.scss` (content-header and action styling)
|
|
1678
|
+
- Enhanced both regular and alternate theme action containers
|
|
1679
|
+
|
|
1680
|
+
#### Navigation Component Debug Mode
|
|
1681
|
+
|
|
1682
|
+
The Navigation component now includes optional debugging capabilities to help diagnose rendering issues:
|
|
1683
|
+
|
|
1684
|
+
**Enable Debug Mode:**
|
|
1685
|
+
```jsx
|
|
1686
|
+
<Navigation debugIcons={true} {...otherProps} />
|
|
1687
|
+
```
|
|
1688
|
+
|
|
1689
|
+
**Debug Features:**
|
|
1690
|
+
- **Visual indicators:** Red borders around anchor elements with 'A' labels, blue borders around buttons with 'B' labels
|
|
1691
|
+
- **Console logging:** Detailed scroll event logs showing element positions, visibility, z-index, transforms, and containment properties
|
|
1692
|
+
- **Real-time monitoring:** Tracks icon visibility changes during scroll events
|
|
1693
|
+
|
|
1694
|
+
**Debug CSS Classes:**
|
|
1695
|
+
The component includes `.debug-icons` styles that can be applied for visual debugging:
|
|
1696
|
+
```scss
|
|
1697
|
+
.debug-icons {
|
|
1698
|
+
a, button {
|
|
1699
|
+
border: 2px solid red !important;
|
|
1700
|
+
background: rgba(255, 0, 0, 0.1) !important;
|
|
1701
|
+
// Additional debug styling...
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
```
|
|
1705
|
+
|
|
1706
|
+
This fix ensures navigation icons remain visible during scroll across all browser environments and rendering contexts.
|
|
1707
|
+
|
|
1653
1708
|
## Support
|
|
1654
1709
|
|
|
1655
1710
|
For support, please contact the VISNS Studio team or open an issue on GitHub.
|
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.
|
|
90
|
+
"version": "5.11.4",
|
|
91
91
|
"description": "Various packages to assist in the development of our Custom Applications.",
|
|
92
92
|
"main": "src/index.js",
|
|
93
93
|
"files": [
|
|
@@ -18,6 +18,8 @@ import {
|
|
|
18
18
|
Zap,
|
|
19
19
|
ZapOff,
|
|
20
20
|
Focus,
|
|
21
|
+
Bot,
|
|
22
|
+
Play,
|
|
21
23
|
} from 'lucide-react';
|
|
22
24
|
|
|
23
25
|
import CustomFetch from './Fetch';
|
|
@@ -50,10 +52,20 @@ const BusinessCardOcr = ({
|
|
|
50
52
|
const [contactDecision, setContactDecision] = useState(null); // 'create', 'update', 'merge'
|
|
51
53
|
const [isConsulting, setIsConsulting] = useState(false);
|
|
52
54
|
const [isSaving, setIsSaving] = useState(false);
|
|
55
|
+
|
|
56
|
+
// Auto-capture states
|
|
57
|
+
const [autoCapture, setAutoCapture] = useState(true);
|
|
58
|
+
const [focusScore, setFocusScore] = useState(0);
|
|
59
|
+
const [isCountingDown, setIsCountingDown] = useState(false);
|
|
60
|
+
const [countdown, setCountdown] = useState(0);
|
|
61
|
+
const [focusThreshold] = useState(0.15); // Adjustable focus threshold
|
|
53
62
|
|
|
54
63
|
const videoRef = useRef(null);
|
|
55
64
|
const canvasRef = useRef(null);
|
|
56
65
|
const fileInputRef = useRef(null);
|
|
66
|
+
const focusDetectionRef = useRef(null);
|
|
67
|
+
const countdownRef = useRef(null);
|
|
68
|
+
const capturePhotoRef = useRef(null);
|
|
57
69
|
|
|
58
70
|
// Detect available cameras when component opens
|
|
59
71
|
useEffect(() => {
|
|
@@ -203,6 +215,121 @@ const BusinessCardOcr = ({
|
|
|
203
215
|
}
|
|
204
216
|
};
|
|
205
217
|
|
|
218
|
+
// Calculate image sharpness/focus score using Laplacian variance
|
|
219
|
+
const calculateFocusScore = useCallback((videoElement) => {
|
|
220
|
+
if (!videoElement || videoElement.videoWidth === 0) return 0;
|
|
221
|
+
|
|
222
|
+
const canvas = document.createElement('canvas');
|
|
223
|
+
const ctx = canvas.getContext('2d');
|
|
224
|
+
|
|
225
|
+
// Use smaller canvas for performance
|
|
226
|
+
const width = 320;
|
|
227
|
+
const height = 240;
|
|
228
|
+
canvas.width = width;
|
|
229
|
+
canvas.height = height;
|
|
230
|
+
|
|
231
|
+
ctx.drawImage(videoElement, 0, 0, width, height);
|
|
232
|
+
const imageData = ctx.getImageData(0, 0, width, height);
|
|
233
|
+
const data = imageData.data;
|
|
234
|
+
|
|
235
|
+
// Convert to grayscale and apply Laplacian operator
|
|
236
|
+
let sum = 0;
|
|
237
|
+
let count = 0;
|
|
238
|
+
|
|
239
|
+
for (let y = 1; y < height - 1; y++) {
|
|
240
|
+
for (let x = 1; x < width - 1; x++) {
|
|
241
|
+
const i = (y * width + x) * 4;
|
|
242
|
+
|
|
243
|
+
// Convert to grayscale
|
|
244
|
+
const gray = data[i] * 0.299 + data[i + 1] * 0.587 + data[i + 2] * 0.114;
|
|
245
|
+
|
|
246
|
+
// Apply Laplacian operator (edge detection)
|
|
247
|
+
const laplacian = Math.abs(
|
|
248
|
+
-4 * gray +
|
|
249
|
+
data[((y - 1) * width + x) * 4] * 0.299 + data[((y - 1) * width + x) * 4 + 1] * 0.587 + data[((y - 1) * width + x) * 4 + 2] * 0.114 +
|
|
250
|
+
data[((y + 1) * width + x) * 4] * 0.299 + data[((y + 1) * width + x) * 4 + 1] * 0.587 + data[((y + 1) * width + x) * 4 + 2] * 0.114 +
|
|
251
|
+
data[(y * width + (x - 1)) * 4] * 0.299 + data[(y * width + (x - 1)) * 4 + 1] * 0.587 + data[(y * width + (x - 1)) * 4 + 2] * 0.114 +
|
|
252
|
+
data[(y * width + (x + 1)) * 4] * 0.299 + data[(y * width + (x + 1)) * 4 + 1] * 0.587 + data[(y * width + (x + 1)) * 4 + 2] * 0.114
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
sum += laplacian * laplacian;
|
|
256
|
+
count++;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Return normalized variance (higher = sharper)
|
|
261
|
+
return count > 0 ? Math.sqrt(sum / count) / 255 : 0;
|
|
262
|
+
}, []);
|
|
263
|
+
|
|
264
|
+
// Auto-capture countdown logic
|
|
265
|
+
const startCountdown = useCallback(async () => {
|
|
266
|
+
if (isCountingDown || isFocusing) return;
|
|
267
|
+
|
|
268
|
+
setIsCountingDown(true);
|
|
269
|
+
|
|
270
|
+
for (let i = 3; i > 0; i--) {
|
|
271
|
+
setCountdown(i);
|
|
272
|
+
await new Promise(resolve => {
|
|
273
|
+
countdownRef.current = setTimeout(resolve, 1000);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
// Check if still focused during countdown
|
|
277
|
+
if (videoRef.current) {
|
|
278
|
+
const currentFocus = calculateFocusScore(videoRef.current);
|
|
279
|
+
if (currentFocus < focusThreshold) {
|
|
280
|
+
setIsCountingDown(false);
|
|
281
|
+
setCountdown(0);
|
|
282
|
+
return; // Cancel if focus lost
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
setCountdown(0);
|
|
288
|
+
setIsCountingDown(false);
|
|
289
|
+
|
|
290
|
+
// Trigger capture using ref
|
|
291
|
+
if (capturePhotoRef.current) {
|
|
292
|
+
await capturePhotoRef.current();
|
|
293
|
+
}
|
|
294
|
+
}, [isCountingDown, isFocusing, calculateFocusScore, focusThreshold]);
|
|
295
|
+
|
|
296
|
+
// Focus detection loop
|
|
297
|
+
useEffect(() => {
|
|
298
|
+
if (!videoRef.current || !cameraReady || !autoCapture || currentStep !== 'camera') {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const detectFocus = () => {
|
|
303
|
+
if (videoRef.current && !isCountingDown && !isFocusing) {
|
|
304
|
+
const score = calculateFocusScore(videoRef.current);
|
|
305
|
+
setFocusScore(score);
|
|
306
|
+
|
|
307
|
+
// Start countdown if image is in focus
|
|
308
|
+
if (score > focusThreshold && !isCountingDown) {
|
|
309
|
+
startCountdown();
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
// Check focus every 500ms
|
|
315
|
+
focusDetectionRef.current = setInterval(detectFocus, 500);
|
|
316
|
+
|
|
317
|
+
return () => {
|
|
318
|
+
if (focusDetectionRef.current) {
|
|
319
|
+
clearInterval(focusDetectionRef.current);
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
}, [cameraReady, autoCapture, currentStep, isCountingDown, isFocusing, calculateFocusScore, focusThreshold, startCountdown]);
|
|
323
|
+
|
|
324
|
+
// Cleanup countdown on unmount
|
|
325
|
+
useEffect(() => {
|
|
326
|
+
return () => {
|
|
327
|
+
if (countdownRef.current) {
|
|
328
|
+
clearTimeout(countdownRef.current);
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
}, []);
|
|
332
|
+
|
|
206
333
|
// Image preprocessing pipeline
|
|
207
334
|
const preprocessImage = async (imageBlob) => {
|
|
208
335
|
return new Promise((resolve) => {
|
|
@@ -274,6 +401,11 @@ const BusinessCardOcr = ({
|
|
|
274
401
|
);
|
|
275
402
|
}, [cameraStream]);
|
|
276
403
|
|
|
404
|
+
// Assign capturePhoto to ref for use in startCountdown
|
|
405
|
+
useEffect(() => {
|
|
406
|
+
capturePhotoRef.current = capturePhoto;
|
|
407
|
+
}, [capturePhoto]);
|
|
408
|
+
|
|
277
409
|
const switchCamera = () => {
|
|
278
410
|
if (availableCameras.length > 1) {
|
|
279
411
|
setCurrentCameraIndex(
|
|
@@ -1652,7 +1784,20 @@ const BusinessCardOcr = ({
|
|
|
1652
1784
|
{currentStep === 'camera' && (
|
|
1653
1785
|
<div className={ocrStyles.cameraContainer}>
|
|
1654
1786
|
<div className={ocrStyles.captureGuide}>
|
|
1655
|
-
<p>
|
|
1787
|
+
<p>
|
|
1788
|
+
{autoCapture
|
|
1789
|
+
? 'Position business card within frame - auto-capture when focused'
|
|
1790
|
+
: 'Position business card within the frame and tap to focus'
|
|
1791
|
+
}
|
|
1792
|
+
</p>
|
|
1793
|
+
<button
|
|
1794
|
+
onClick={() => setAutoCapture(!autoCapture)}
|
|
1795
|
+
className={`${ocrStyles.autoCaptureToggle} ${autoCapture ? ocrStyles.active : ''}`}
|
|
1796
|
+
title={autoCapture ? 'Disable auto-capture' : 'Enable auto-capture'}
|
|
1797
|
+
>
|
|
1798
|
+
{autoCapture ? <Bot size={16} /> : <Play size={16} />}
|
|
1799
|
+
{autoCapture ? 'Auto' : 'Manual'}
|
|
1800
|
+
</button>
|
|
1656
1801
|
</div>
|
|
1657
1802
|
<div className={ocrStyles.videoWrapper}>
|
|
1658
1803
|
<video
|
|
@@ -1663,15 +1808,54 @@ const BusinessCardOcr = ({
|
|
|
1663
1808
|
className={ocrStyles.cameraVideo}
|
|
1664
1809
|
onClick={triggerAutofocus}
|
|
1665
1810
|
/>
|
|
1811
|
+
<canvas
|
|
1812
|
+
ref={canvasRef}
|
|
1813
|
+
style={{ display: 'none' }}
|
|
1814
|
+
/>
|
|
1666
1815
|
{/* Enhanced camera overlay with focus frame */}
|
|
1667
1816
|
<div className={ocrStyles.cameraOverlay}>
|
|
1668
|
-
<div className={ocrStyles.focusFrame}
|
|
1817
|
+
<div className={`${ocrStyles.focusFrame} ${
|
|
1818
|
+
focusScore > focusThreshold ? ocrStyles.focused : ''
|
|
1819
|
+
} ${isCountingDown ? ocrStyles.countingDown : ''}`}>
|
|
1820
|
+
|
|
1821
|
+
{/* Focus corners */}
|
|
1822
|
+
<div className={`${ocrStyles.focusCorner} ${ocrStyles.topLeft}`}></div>
|
|
1823
|
+
<div className={`${ocrStyles.focusCorner} ${ocrStyles.topRight}`}></div>
|
|
1824
|
+
<div className={`${ocrStyles.focusCorner} ${ocrStyles.bottomLeft}`}></div>
|
|
1825
|
+
<div className={`${ocrStyles.focusCorner} ${ocrStyles.bottomRight}`}></div>
|
|
1826
|
+
|
|
1827
|
+
{/* Countdown display */}
|
|
1828
|
+
{isCountingDown && countdown > 0 && (
|
|
1829
|
+
<div className={ocrStyles.countdownDisplay}>
|
|
1830
|
+
<div className={ocrStyles.countdownNumber}>{countdown}</div>
|
|
1831
|
+
<div className={ocrStyles.countdownText}>Auto-capturing...</div>
|
|
1832
|
+
</div>
|
|
1833
|
+
)}
|
|
1834
|
+
|
|
1835
|
+
{/* Focus indicator */}
|
|
1669
1836
|
{isFocusing && (
|
|
1670
1837
|
<div className={ocrStyles.focusIndicator}>
|
|
1671
1838
|
<Focus className={ocrStyles.focusIcon} />
|
|
1672
1839
|
<span>Focusing...</span>
|
|
1673
1840
|
</div>
|
|
1674
1841
|
)}
|
|
1842
|
+
|
|
1843
|
+
{/* Focus status */}
|
|
1844
|
+
{autoCapture && !isFocusing && !isCountingDown && (
|
|
1845
|
+
<div className={ocrStyles.focusStatus}>
|
|
1846
|
+
<div className={`${ocrStyles.focusBar} ${
|
|
1847
|
+
focusScore > focusThreshold ? ocrStyles.good : ocrStyles.poor
|
|
1848
|
+
}`}>
|
|
1849
|
+
<div
|
|
1850
|
+
className={ocrStyles.focusBarFill}
|
|
1851
|
+
style={{ width: `${Math.min(focusScore * 300, 100)}%` }}
|
|
1852
|
+
></div>
|
|
1853
|
+
</div>
|
|
1854
|
+
<span className={ocrStyles.focusText}>
|
|
1855
|
+
{focusScore > focusThreshold ? '✓ In Focus' : 'Move closer or adjust angle'}
|
|
1856
|
+
</span>
|
|
1857
|
+
</div>
|
|
1858
|
+
)}
|
|
1675
1859
|
</div>
|
|
1676
1860
|
</div>
|
|
1677
1861
|
</div>
|
|
@@ -1704,8 +1888,9 @@ const BusinessCardOcr = ({
|
|
|
1704
1888
|
fileInputRef.current?.click()
|
|
1705
1889
|
}
|
|
1706
1890
|
className={ocrStyles.secondaryButton}
|
|
1891
|
+
title="Upload image from device"
|
|
1707
1892
|
>
|
|
1708
|
-
<ImagePlus size={
|
|
1893
|
+
<ImagePlus size={18} />
|
|
1709
1894
|
Upload
|
|
1710
1895
|
</button>
|
|
1711
1896
|
|
|
@@ -1713,9 +1898,10 @@ const BusinessCardOcr = ({
|
|
|
1713
1898
|
onClick={capturePhoto}
|
|
1714
1899
|
className={`${ocrStyles.captureButton} ${isFocusing ? ocrStyles.focusing : ''}`}
|
|
1715
1900
|
disabled={isFocusing}
|
|
1901
|
+
title={isFocusing ? 'Focusing camera...' : 'Capture business card'}
|
|
1716
1902
|
>
|
|
1717
1903
|
<Camera size={28} />
|
|
1718
|
-
{isFocusing ? '
|
|
1904
|
+
{isFocusing ? 'Focus...' : 'Capture'}
|
|
1719
1905
|
</button>
|
|
1720
1906
|
|
|
1721
1907
|
<input
|
|
@@ -1725,8 +1911,6 @@ const BusinessCardOcr = ({
|
|
|
1725
1911
|
accept="image/jpeg,image/png,image/jpg,image/gif,image/webp"
|
|
1726
1912
|
style={{ display: 'none' }}
|
|
1727
1913
|
/>
|
|
1728
|
-
|
|
1729
|
-
<div className={ocrStyles.placeholder}></div>
|
|
1730
1914
|
</div>
|
|
1731
1915
|
</div>
|
|
1732
1916
|
</div>
|
|
@@ -183,6 +183,7 @@ function Navigation({
|
|
|
183
183
|
setSystemAuth,
|
|
184
184
|
themeType,
|
|
185
185
|
userProfile,
|
|
186
|
+
debugIcons = false, // Add debug flag
|
|
186
187
|
}) {
|
|
187
188
|
const [search, setSearch] = useState('');
|
|
188
189
|
const [searchResultShow, setSearchResultShow] = useState(false);
|
|
@@ -197,6 +198,7 @@ function Navigation({
|
|
|
197
198
|
const [isScrolled, setIsScrolled] = useState(false);
|
|
198
199
|
const [navData, setNavData] = useState(navConfig);
|
|
199
200
|
const [showBusinessCardOcr, setShowBusinessCardOcr] = useState(false);
|
|
201
|
+
const actionItemsRef = useRef(null);
|
|
200
202
|
|
|
201
203
|
const appNavClasses = styles['app-nav'];
|
|
202
204
|
|
|
@@ -294,7 +296,7 @@ function Navigation({
|
|
|
294
296
|
to={n.url}
|
|
295
297
|
data-tooltip-id="system-tooltip"
|
|
296
298
|
data-tooltip-content={n.label}
|
|
297
|
-
className={
|
|
299
|
+
className={`${activeClass}`}
|
|
298
300
|
target={n.target ? n.target : '_self'}
|
|
299
301
|
title={n.label}
|
|
300
302
|
>
|
|
@@ -532,13 +534,65 @@ function Navigation({
|
|
|
532
534
|
useEffect(() => {
|
|
533
535
|
function handleScroll() {
|
|
534
536
|
setIsScrolled(window.scrollY > 0);
|
|
537
|
+
|
|
538
|
+
// Debug logging for icon visibility
|
|
539
|
+
if (debugIcons && actionItemsRef.current) {
|
|
540
|
+
const anchors = actionItemsRef.current.querySelectorAll('a');
|
|
541
|
+
const buttons =
|
|
542
|
+
actionItemsRef.current.querySelectorAll('button');
|
|
543
|
+
|
|
544
|
+
console.log('=== SCROLL DEBUG ===');
|
|
545
|
+
console.log('Scroll Y:', window.scrollY);
|
|
546
|
+
console.log('Anchors found:', anchors.length);
|
|
547
|
+
console.log('Buttons found:', buttons.length);
|
|
548
|
+
|
|
549
|
+
anchors.forEach((anchor, index) => {
|
|
550
|
+
const rect = anchor.getBoundingClientRect();
|
|
551
|
+
const computedStyle = window.getComputedStyle(anchor);
|
|
552
|
+
console.log(`Anchor ${index}:`, {
|
|
553
|
+
visible: rect.width > 0 && rect.height > 0,
|
|
554
|
+
position: {
|
|
555
|
+
top: rect.top,
|
|
556
|
+
left: rect.left,
|
|
557
|
+
width: rect.width,
|
|
558
|
+
height: rect.height,
|
|
559
|
+
},
|
|
560
|
+
zIndex: computedStyle.zIndex,
|
|
561
|
+
display: computedStyle.display,
|
|
562
|
+
visibility: computedStyle.visibility,
|
|
563
|
+
opacity: computedStyle.opacity,
|
|
564
|
+
transform: computedStyle.transform,
|
|
565
|
+
contain: computedStyle.contain,
|
|
566
|
+
});
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
buttons.forEach((button, index) => {
|
|
570
|
+
const rect = button.getBoundingClientRect();
|
|
571
|
+
const computedStyle = window.getComputedStyle(button);
|
|
572
|
+
console.log(`Button ${index}:`, {
|
|
573
|
+
visible: rect.width > 0 && rect.height > 0,
|
|
574
|
+
position: {
|
|
575
|
+
top: rect.top,
|
|
576
|
+
left: rect.left,
|
|
577
|
+
width: rect.width,
|
|
578
|
+
height: rect.height,
|
|
579
|
+
},
|
|
580
|
+
zIndex: computedStyle.zIndex,
|
|
581
|
+
display: computedStyle.display,
|
|
582
|
+
visibility: computedStyle.visibility,
|
|
583
|
+
opacity: computedStyle.opacity,
|
|
584
|
+
transform: computedStyle.transform,
|
|
585
|
+
contain: computedStyle.contain,
|
|
586
|
+
});
|
|
587
|
+
});
|
|
588
|
+
}
|
|
535
589
|
}
|
|
536
590
|
|
|
537
591
|
window.addEventListener('scroll', handleScroll);
|
|
538
592
|
return () => {
|
|
539
593
|
window.removeEventListener('scroll', handleScroll);
|
|
540
594
|
};
|
|
541
|
-
}, []);
|
|
595
|
+
}, [debugIcons]);
|
|
542
596
|
|
|
543
597
|
return layout === 'simple' || layout === 'cms' ? (
|
|
544
598
|
<div className={styles.cwrap}>
|
|
@@ -601,7 +655,12 @@ function Navigation({
|
|
|
601
655
|
<span></span>
|
|
602
656
|
</button>
|
|
603
657
|
</div>
|
|
604
|
-
<div
|
|
658
|
+
<div
|
|
659
|
+
className={`${styles['hactions-alternate']} ${
|
|
660
|
+
debugIcons ? styles['debug-icons'] : ''
|
|
661
|
+
}`}
|
|
662
|
+
ref={actionItemsRef}
|
|
663
|
+
>
|
|
605
664
|
<ul>
|
|
606
665
|
{navData.settings.map((setting, settingKey) =>
|
|
607
666
|
setting.permission === true ? (
|
|
@@ -653,11 +712,12 @@ function Navigation({
|
|
|
653
712
|
</ul>
|
|
654
713
|
</div>
|
|
655
714
|
<div
|
|
656
|
-
className={
|
|
715
|
+
className={`${
|
|
657
716
|
themeType === 'alternate'
|
|
658
717
|
? styles['hactions-alternate']
|
|
659
718
|
: styles.hactions
|
|
660
|
-
}
|
|
719
|
+
} ${debugIcons ? styles['debug-icons'] : ''}`}
|
|
720
|
+
ref={actionItemsRef}
|
|
661
721
|
>
|
|
662
722
|
<ul>
|
|
663
723
|
{navData.settings.map((setting, settingKey) =>
|