many changes for modules widgets and colors and styling

This commit is contained in:
IGNY8 VPS (Salman)
2025-12-31 23:52:43 +00:00
parent b61bd6e64d
commit 89b64cd737
34 changed files with 2450 additions and 1985 deletions

View File

@@ -1,8 +1,10 @@
/**
* ColumnSelector Component
* Dropdown with checkboxes to show/hide table columns
* Dropdown opens in the direction with most available space
*/
import React, { useState, useRef, useEffect } from 'react';
import { createPortal } from 'react-dom';
import { ChevronDownIcon } from '../../icons';
import Checkbox from '../form/input/Checkbox';
@@ -22,6 +24,7 @@ export default function ColumnSelector({
compact = false,
}: ColumnSelectorProps) {
const [isOpen, setIsOpen] = useState(false);
const [dropdownStyle, setDropdownStyle] = useState<React.CSSProperties>({});
const dropdownRef = useRef<HTMLDivElement>(null);
const buttonRef = useRef<HTMLButtonElement>(null);
@@ -46,6 +49,98 @@ export default function ColumnSelector({
}
}, [isOpen]);
// Calculate dropdown position when opened
useEffect(() => {
if (isOpen && buttonRef.current) {
const buttonRect = buttonRef.current.getBoundingClientRect();
const dropdownHeight = 384; // max-h-96 = 24rem = 384px
const dropdownWidth = 224; // w-56 = 14rem = 224px
const viewportHeight = window.innerHeight;
const viewportWidth = window.innerWidth;
const margin = 8;
// Calculate space above and below
const spaceBelow = viewportHeight - buttonRect.bottom - margin;
const spaceAbove = buttonRect.top - margin;
// Determine vertical position - prefer below if enough space
let top: number;
if (spaceBelow >= dropdownHeight || spaceBelow >= spaceAbove) {
// Open below
top = buttonRect.bottom + margin;
} else {
// Open above
top = buttonRect.top - dropdownHeight - margin;
}
// Ensure dropdown doesn't go off top of screen
top = Math.max(margin, top);
// Calculate horizontal position - align to right edge of button
let left = buttonRect.right - dropdownWidth;
// Ensure dropdown doesn't go off left edge
left = Math.max(margin, left);
// Ensure dropdown doesn't go off right edge
if (left + dropdownWidth > viewportWidth - margin) {
left = viewportWidth - dropdownWidth - margin;
}
setDropdownStyle({
position: 'fixed',
top: `${top}px`,
left: `${left}px`,
width: `${dropdownWidth}px`,
});
}
}, [isOpen]);
// Recalculate on scroll/resize
useEffect(() => {
if (!isOpen) return;
const handleReposition = () => {
if (buttonRef.current) {
const buttonRect = buttonRef.current.getBoundingClientRect();
const dropdownHeight = 384;
const dropdownWidth = 224;
const viewportHeight = window.innerHeight;
const viewportWidth = window.innerWidth;
const margin = 8;
const spaceBelow = viewportHeight - buttonRect.bottom - margin;
const spaceAbove = buttonRect.top - margin;
let top: number;
if (spaceBelow >= dropdownHeight || spaceBelow >= spaceAbove) {
top = buttonRect.bottom + margin;
} else {
top = buttonRect.top - dropdownHeight - margin;
}
top = Math.max(margin, top);
let left = buttonRect.right - dropdownWidth;
left = Math.max(margin, left);
if (left + dropdownWidth > viewportWidth - margin) {
left = viewportWidth - dropdownWidth - margin;
}
setDropdownStyle({
position: 'fixed',
top: `${top}px`,
left: `${left}px`,
width: `${dropdownWidth}px`,
});
}
};
window.addEventListener('scroll', handleReposition, true);
window.addEventListener('resize', handleReposition);
return () => {
window.removeEventListener('scroll', handleReposition, true);
window.removeEventListener('resize', handleReposition);
};
}, [isOpen]);
const visibleCount = visibleColumns.size;
const totalCount = columns.length;
@@ -90,10 +185,11 @@ export default function ColumnSelector({
)}
</button>
{isOpen && (
{isOpen && createPortal(
<div
ref={dropdownRef}
className="absolute right-0 mt-2 w-56 rounded-lg border border-gray-200 bg-white shadow-lg dark:border-gray-700 dark:bg-gray-800 z-50 max-h-96 overflow-y-auto"
style={dropdownStyle}
className="rounded-lg border border-gray-200 bg-white shadow-lg dark:border-gray-700 dark:bg-gray-800 z-[9999] max-h-96 overflow-y-auto"
>
<div className="p-2">
<div className="px-3 py-2 text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wide border-b border-gray-200 dark:border-gray-700 mb-1">
@@ -137,7 +233,8 @@ export default function ColumnSelector({
</button>
</div>
</div>
</div>
</div>,
document.body
)}
</div>
);