diff --git a/src/services/pmsGrid/BasicTable.jsx b/src/services/pmsGrid/BasicTable.jsx index b1bd3399..872912a2 100644 --- a/src/services/pmsGrid/BasicTable.jsx +++ b/src/services/pmsGrid/BasicTable.jsx @@ -1,6 +1,7 @@ import React, { useEffect, useRef } from "react"; import { PmsGrid } from "./index"; import { initPopover } from "./GridService"; +import PmsHeaderOption from "./PmsHeaderOption"; /** * CIVIL BOQ / INVENTORY DEMO DATA @@ -719,6 +720,8 @@ export default function DemoBOQGrid() { return (
+ + ({ ...r, diff --git a/src/services/pmsGrid/PmsGrid.jsx b/src/services/pmsGrid/PmsGrid.jsx index aa9d6762..d734d12b 100644 --- a/src/services/pmsGrid/PmsGrid.jsx +++ b/src/services/pmsGrid/PmsGrid.jsx @@ -2,6 +2,7 @@ import React, { useRef } from "react"; import { useGridCore } from "./useGridCore"; import { exportToCSV } from "./utils"; import "./pms-grid.css"; +import PmsHeaderOption from "./PmsHeaderOption"; /* Props: @@ -55,10 +56,17 @@ export default function PmsGrid({ setColState, } = grid; - // simple pin toggle - const togglePin = (key) => { + // --- Pin / Unpin helpers --- + const pinColumn = (key, side) => { const col = colState.find((c) => c.key === key); - updateColumn(key, { pinned: col.pinned === "left" ? null : "left" }); + if (!col) return; + // if already pinned to that side → unpin + const newPinned = col.pinned === side || side === "none" ? null : side; + updateColumn(key, { pinned: newPinned }); + }; + + const unpinColumn = (key) => { + updateColumn(key, { pinned: null }); }; // resizing via mouse down on handle @@ -199,7 +207,7 @@ export default function PmsGrid({ style={{ maxHeight: features.maxHeight || "60vh" }} > onDragStart(e, col.key)} - onDragOver={(e) => e.preventDefault()} + onDragOver={(e)=> e.preventDefault()} onDrop={(e) => onDrop(e, col.key)} className={`pms-col-header vs-th ${ col.pinned ? `pinned pinned-${col.pinned}` : "" @@ -269,17 +277,17 @@ export default function PmsGrid({ }`} > )} + {col.pinned === col.key && }
{features.pinning && ( - + pinColumn(col.key, "left")} + onPinRight={() => pinColumn(col.key, "right")} + onUnpin={() => unpinColumn(col.key)} + /> )} {features.resizing && ( 0 ? groupedRows.map((g) => ( -
+
{ + return ( +
+ + +
    +
  • + +
  • +
  • + +
  • + {pinned && ( + <> +

  • +
  • + +
  • + + )} +
+
+ ); +}; +export default PmsHeaderOption; diff --git a/src/services/pmsGrid/pms-grid.css b/src/services/pmsGrid/pms-grid.css index 90d658e1..18f84f50 100644 --- a/src/services/pmsGrid/pms-grid.css +++ b/src/services/pmsGrid/pms-grid.css @@ -5,24 +5,25 @@ width: 100%; position: relative; font-size: 0.875rem; + } /* ────────────────────────────── SCROLLABLE WRAPPER ────────────────────────────── */ .grid-wrapper { - max-height: 60vh; + max-height: 50vh; overflow-y: auto; overflow-x: auto; position: relative; border: 1px solid #dee2e6; border-radius: 0.2rem; background: #fff; - /* ✅ Force horizontal scroll even if few columns */ + /* Force horizontal scroll even if few columns */ white-space: nowrap; } -/* ✅ Always visible scrollbar (cross browser) */ +/* Always visible scrollbar (cross browser) */ .grid-wrapper::-webkit-scrollbar { height: 3px; width: 3px; @@ -39,13 +40,19 @@ TABLE BASE STYLE ────────────────────────────── */ .pms-grid table { - width: max-content; /* ✅ allows scrolling horizontally */ + width: max-content; /* allows scrolling horizontally */ min-width: 100%; border-collapse: separate; border-spacing: 0; table-layout: fixed; background: #fff; } +.pms-col-header { + position: relative; + overflow: visible !important; + z-index: 20; +} + .pms-grid th, .pms-grid td { @@ -81,7 +88,7 @@ box-shadow: 2px 0 4px rgba(0, 0, 0, 0.05); } -/* ✅ Always sticky first column (checkbox) */ +/* Always sticky first column (checkbox) */ .pms-grid th:first-child, .pms-grid td:first-child { position: sticky; @@ -94,7 +101,7 @@ box-shadow: 2px 0 3px rgba(0, 0, 0, 0.08); } -/* ✅ Always sticky last column (Actions) */ +/* Always sticky last column (Actions) */ .pms-grid th:last-child, .pms-grid td:last-child { position: sticky; @@ -114,7 +121,7 @@ display: inline-block; opacity: 0; transition: opacity 0.2s; - color: #0d6efd; + color: var(--bs-primary); } .pms-col-header:hover .resize-handle { @@ -157,6 +164,9 @@ .z-6 { z-index: 6 !important; } +.z-100{ + z-index: 100 !important; +} /* ────────────────────────────── PINNED HEADER COLUMNS (Fix for misalignment) ────────────────────────────── */ @@ -165,7 +175,7 @@ .pms-grid th.pinned-left { position: sticky; left: 0; - z-index: 9; + z-index: 12; background: #fff; box-shadow: 2px 0 3px rgba(0, 0, 0, 0.08); } @@ -174,9 +184,10 @@ .pms-grid th.pinned-right { position: sticky; right: 0; - z-index: 9; + z-index: 12; background: #fff; box-shadow: -2px 0 3px rgba(0, 0, 0, 0.08); + } /* Match body pinned cell behavior */ @@ -186,6 +197,7 @@ z-index: 8; background: #fff; box-shadow: 2px 0 3px rgba(0, 0, 0, 0.08); + border-right: 1px solid var(--bs-primary); } .pms-grid td.pinned-right { @@ -194,4 +206,27 @@ z-index: 8; background: #fff; box-shadow: -2px 0 3px rgba(0, 0, 0, 0.08); + + } +.dropend:hover > .dropdown-menu { + display: block; +} + + +/* Hover color consistency with Sneat variables */ +.dropdown-item:focus, +.dropdown-item:hover { + background-color: rgba(var(--bs-primary-rgb), 0.08); + color: var(--bs-primary); +} + +/* Responsive fallback: stack submenu below parent on small screens */ +@media (max-width: 768px) { + .dropend .dropdown-menu { + position: relative; + left: 0; + top: 0; + margin-left: 0; + } +} \ No newline at end of file