chordia-ui 3.7.6 → 3.7.8

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.
Files changed (36) hide show
  1. package/README.md +25 -0
  2. package/dist/DataTable2.cjs.js +1 -1
  3. package/dist/DataTable2.cjs.js.map +1 -1
  4. package/dist/DataTable2.es.js +443 -432
  5. package/dist/DataTable2.es.js.map +1 -1
  6. package/dist/PerformancePanel.cjs.js +2 -0
  7. package/dist/PerformancePanel.cjs.js.map +1 -0
  8. package/dist/PerformancePanel.es.js +2218 -0
  9. package/dist/PerformancePanel.es.js.map +1 -0
  10. package/dist/components/Signals.cjs.js +2 -0
  11. package/dist/components/Signals.cjs.js.map +1 -0
  12. package/dist/components/Signals.es.js +1607 -0
  13. package/dist/components/Signals.es.js.map +1 -0
  14. package/dist/components/chat.cjs.js +5 -5
  15. package/dist/components/chat.cjs.js.map +1 -1
  16. package/dist/components/chat.es.js +624 -415
  17. package/dist/components/chat.es.js.map +1 -1
  18. package/dist/components/layout.cjs.js +1 -1
  19. package/dist/components/layout.cjs.js.map +1 -1
  20. package/dist/components/layout.es.js +1 -1
  21. package/dist/components/layout.es.js.map +1 -1
  22. package/dist/components/performance.cjs.js +1 -1
  23. package/dist/components/performance.cjs.js.map +1 -1
  24. package/dist/components/performance.es.js +114 -2318
  25. package/dist/components/performance.es.js.map +1 -1
  26. package/dist/index.cjs.js +1 -1
  27. package/dist/index.es.js +102 -95
  28. package/dist/index.es.js.map +1 -1
  29. package/package.json +5 -1
  30. package/src/components/Signals/SignalDetailsPage.jsx +1139 -0
  31. package/src/components/Signals/SignalsListPage.jsx +604 -0
  32. package/src/components/Signals/index.js +6 -0
  33. package/src/components/chat/ChatHistoryPanel.jsx +325 -58
  34. package/src/components/data/DataTable2.jsx +35 -7
  35. package/src/components/index.js +9 -0
  36. package/src/components/layout/SplitPane.jsx +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"DataTable2.cjs.js","sources":["../src/components/data/DataTableFilters.jsx","../src/components/data/DataTable2.jsx"],"sourcesContent":["\"use client\";\n\nimport React, { useState, useEffect, useRef, Suspense } from \"react\";\nimport { Download, ChevronDown, CalendarClock, CalendarDays } from \"lucide-react\";\nimport { createPortal } from \"react-dom\";\nimport { CustomFilterChips } from \"../common\";\n\n/**\n * DataTableFilters Component\n * Displays filter buttons (Week to Date, Select Date Range, Export) and filter chips\n * \n * @param {Object} props\n * @param {React.ReactNode} props.dateRangePicker - DateRangePicker component (wrapped in Suspense)\n * @param {Function} props.onWeekToDate - Handler for \"Week to Date\" button\n * @param {Object} props.exportConfig - Export configuration\n * @param {boolean} props.exportConfig.isExporting - Whether export is in progress\n * @param {Function} props.exportConfig.onExport - Export handler (type) => void\n * @param {Array} props.exportConfig.types - Export types array (default: ['csv'])\n * @param {Object} props.filterChipsConfig - Filter chips configuration\n * @param {Object} props.filterChipsConfig.filters - Current filter values\n * @param {Function} props.filterChipsConfig.onChange - Filter chips change handler\n * @param {Function} props.filterChipsConfig.onClear - Clear all filters handler\n * @param {Array} props.filterChipsConfig.customFilters - Custom filter chips (e.g., date range)\n */\nexport default function DataTableFilters({\n dateRangePicker,\n onWeekToDate,\n exportConfig,\n filterChipsConfig,\n trailingActions, // Optional extra actions rendered after Export (e.g., Add Users button)\n}) {\n const [showExportMenu, setShowExportMenu] = useState(false);\n const exportButtonRef = useRef(null);\n const exportMenuRef = useRef(null);\n\n // Handle click outside to close export menu\n useEffect(() => {\n const handleClickOutside = (event) => {\n if (\n exportMenuRef.current &&\n !exportMenuRef.current.contains(event.target) &&\n exportButtonRef.current &&\n !exportButtonRef.current.contains(event.target)\n ) {\n setShowExportMenu(false);\n }\n };\n\n if (showExportMenu) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }\n }, [showExportMenu]);\n\n const openExportMenu = () => {\n setShowExportMenu((prev) => !prev);\n };\n\n const handleExport = (type) => {\n setShowExportMenu(false);\n if (exportConfig?.onExport) {\n exportConfig.onExport(type);\n }\n };\n\n // Check if there are any filter chips to display\n const hasFilterChips = () => {\n if (!filterChipsConfig?.filters) return false;\n \n const filters = filterChipsConfig.filters;\n const customFilters = filterChipsConfig.customFilters || [];\n \n // Check if any regular filters have values\n const hasRegularFilters = Object.entries(filters).some(([key, value]) => {\n if (Array.isArray(value) && value.length) return true;\n if (typeof value === \"string\" && value.trim() !== \"\") return true;\n if (value && typeof value === \"object\" && (value.min != null || value.max != null)) return true;\n return false;\n });\n \n // Check if any custom filters are active\n const hasCustomFilters = customFilters.some(filterObj => filterObj.active);\n \n return hasRegularFilters || hasCustomFilters;\n };\n\n const shouldShowChips = hasFilterChips();\n\n return (\n <div className=\"flex items-center gap-3 flex-wrap\">\n {/* Week to Date Button */}\n {onWeekToDate && (\n <button\n onClick={onWeekToDate}\n className=\"inline-flex items-center gap-2 rounded-lg border border-gray-300 bg-white/80 px-4 py-2.5 transition-colors hover:bg-white text-sm font-medium text-gray-900\"\n style={{ fontFamily: 'var(--font-sans)' }}\n >\n <CalendarClock size={16} />\n <span>Week to Date</span>\n </button>\n )}\n\n {/* Select Date Range */}\n {dateRangePicker && (\n <Suspense\n fallback={\n <div className=\"inline-flex items-center gap-2 rounded-lg border border-gray-300 bg-white/80 px-4 py-2.5 text-sm font-medium text-gray-400\">\n <CalendarClock size={16} />\n <span>Loading...</span>\n </div>\n }\n >\n {dateRangePicker}\n </Suspense>\n )}\n\n {/* Export Button */}\n {exportConfig && (\n <div className=\"relative\">\n <button\n ref={exportButtonRef}\n onClick={openExportMenu}\n disabled={exportConfig.isExporting}\n className=\"inline-flex items-center justify-between gap-2 rounded-lg border border-gray-300 bg-white/80 px-4 py-2.5 transition-colors hover:bg-white text-sm font-medium text-gray-900 disabled:opacity-50 disabled:cursor-not-allowed min-w-[120px]\"\n style={{ fontFamily: 'var(--font-sans)' }}\n >\n <div className=\"flex items-center gap-2\">\n <Download size={16} />\n <span>{exportConfig.isExporting ? \"Exporting...\" : \"Export\"}</span>\n </div>\n <ChevronDown size={16} />\n </button>\n {showExportMenu && (\n <div\n ref={exportMenuRef}\n className=\"absolute top-full right-0 mt-2 bg-white rounded-lg shadow-lg border border-gray-200 py-1 z-50 min-w-[120px]\"\n >\n {(exportConfig.types || [\"csv\"]).map((type) => (\n <button\n key={type}\n onClick={() => handleExport(type)}\n className=\"w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 transition-colors\"\n style={{ fontFamily: 'var(--font-sans)' }}\n >\n Export {type.toUpperCase()}\n </button>\n ))}\n </div>\n )}\n </div>\n )}\n\n {/* Filter chips + optional trailing actions (e.g., Add Users / Add Agent) */}\n {(shouldShowChips || trailingActions) && (\n <>\n {/* Vertical line only when there are actual chips; this avoids double lines\n when we only show trailingActions (like Add Agent) with no chips. */}\n {shouldShowChips && (\n <div className=\"h-9 mt-1 w-px bg-gray-300 flex-shrink-0\"></div>\n )}\n\n {/* Filter Chips + trailing actions */}\n <div className=\"flex items-center gap-3 justify-end\">\n {shouldShowChips && filterChipsConfig && (\n <CustomFilterChips\n filters={filterChipsConfig.filters}\n onChange={filterChipsConfig.onChange}\n onClear={filterChipsConfig.onClear}\n customFilters={filterChipsConfig.customFilters || []}\n fieldOptions={filterChipsConfig.fieldOptions || {}}\n />\n )}\n {trailingActions && (\n <div className=\"flex-shrink-0\">\n {trailingActions}\n </div>\n )}\n </div>\n </>\n )}\n </div>\n );\n}\n\n","\"use client\";\n\nimport React, { useState, useMemo, useRef, useEffect, useCallback } from \"react\";\nimport {\n DndContext,\n closestCenter,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n DragOverlay,\n} from \"@dnd-kit/core\";\nimport {\n arrayMove,\n SortableContext,\n sortableKeyboardCoordinates,\n useSortable,\n horizontalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { GripVertical, ChevronUp, ChevronDown, ListFilter, ArrowUp, ArrowDown, Settings2, Search, Check, X, ArrowUpDown } from \"lucide-react\";\nimport { createPortal } from \"react-dom\";\nimport Pagination from \"../common/Pagination.jsx\";\n// TODO: surface column limit errors via callback prop (onMaxColumnsError)\n// TODO: replace with framework-agnostic component\nfunction OpenCloseArrow({ isOpen, iconSize }) { return null; }\n// TODO: replace with framework-agnostic component\nfunction Separator() { return <div style={{ height: 1, background: \"rgba(52,58,64,0.08)\" }} />; }\n\n// ─── Typed-filter helpers ──────────────────────────────────────────────────\nfunction parseNumberLike(s) {\n if (s === null || s === undefined) return NaN;\n const cleaned = String(s).replace(/[,$%]|pp/gi, \"\").trim();\n const n = parseFloat(cleaned);\n return Number.isFinite(n) ? n : NaN;\n}\n\nfunction parseDurationToSeconds(s) {\n if (s === null || s === undefined) return NaN;\n const str = String(s).trim();\n // HH:MM:SS or MM:SS\n const colon = str.match(/^(\\d+):(\\d+)(?::(\\d+))?$/);\n if (colon) {\n const a = +colon[1], b = +colon[2], c = colon[3] != null ? +colon[3] : null;\n return c != null ? a * 3600 + b * 60 + c : a * 60 + b;\n }\n // 1d 2h 3m 4s\n let total = 0;\n let matched = false;\n const dM = str.match(/(\\d+)\\s*d\\b/i);\n const hM = str.match(/(\\d+)\\s*h\\b/i);\n const mM = str.match(/(\\d+)\\s*m(?!s)\\b/i);\n const sM = str.match(/(\\d+)\\s*s\\b/i);\n if (dM) { total += +dM[1] * 86400; matched = true; }\n if (hM) { total += +hM[1] * 3600; matched = true; }\n if (mM) { total += +mM[1] * 60; matched = true; }\n if (sM) { total += +sM[1]; matched = true; }\n return matched ? total : NaN;\n}\n\nfunction parseDateLike(s) {\n if (!s) return null;\n const str = String(s).trim();\n // MM/DD/YYYY or M/D/YY\n const slash = str.match(/^(\\d{1,2})\\/(\\d{1,2})\\/(\\d{2,4})$/);\n if (slash) {\n const yyyy = slash[3].length === 2 ? 2000 + +slash[3] : +slash[3];\n const d = new Date(yyyy, +slash[1] - 1, +slash[2]);\n return isNaN(d.getTime()) ? null : d;\n }\n const d = new Date(str);\n return isNaN(d.getTime()) ? null : d;\n}\n\nfunction detectFilterType(values) {\n if (!values || values.length === 0) return \"text\";\n const sample = values.slice(0, 25);\n const allMatch = (test) => sample.every(test);\n if (allMatch((v) => /^\\d{1,2}\\/\\d{1,2}\\/\\d{2,4}$/.test(v) || /^\\d{4}-\\d{2}-\\d{2}/.test(v))) return \"date\";\n if (allMatch((v) => /^\\d+\\s*[dhms]\\b/i.test(v) || /^\\d+:\\d+(:\\d+)?$/.test(v))) return \"duration\";\n if (allMatch((v) => /^-?[\\d,.]+(%|pp)?$/i.test(v))) return \"number\";\n return \"text\";\n}\n\nfunction isFilterActive(filter) {\n if (!filter) return false;\n if (Array.isArray(filter)) return filter.length > 0;\n if (filter.type === \"range\") return filter.min !== \"\" && filter.min !== undefined && filter.min !== null\n || filter.max !== \"\" && filter.max !== undefined && filter.max !== null;\n if (filter.type === \"durationRange\") return (filter.minSec !== \"\" && filter.minSec != null) || (filter.maxSec !== \"\" && filter.maxSec != null);\n if (filter.type === \"scoreRange\") return (Array.isArray(filter.values) && filter.values.length > 0)\n || (filter.min !== \"\" && filter.min != null) || (filter.max !== \"\" && filter.max != null);\n if (filter.type === \"dateRange\") return Boolean(filter.from || filter.to);\n return false;\n}\n\nfunction secondsToHMS(sec) {\n if (sec == null || sec === \"\" || isNaN(sec)) return \"\";\n const n = Number(sec);\n const h = Math.floor(n / 3600);\n const m = Math.floor((n % 3600) / 60);\n const s = Math.floor(n % 60);\n if (h > 0) return `${h}h ${m}m`;\n if (m > 0) return `${m}m ${s}s`;\n return `${s}s`;\n}\n\nfunction chipSummary(filter) {\n if (!filter) return \"\";\n if (Array.isArray(filter)) return filter.length === 0 ? \"\" : String(filter[0]);\n if (filter.type === \"range\") {\n const lo = filter.min !== \"\" && filter.min != null ? filter.min : null;\n const hi = filter.max !== \"\" && filter.max != null ? filter.max : null;\n if (lo != null && hi != null) return `${lo} – ${hi}`;\n if (lo != null) return `≥ ${lo}`;\n if (hi != null) return `≤ ${hi}`;\n return \"\";\n }\n if (filter.type === \"durationRange\") {\n const lo = filter.minSec !== \"\" && filter.minSec != null ? secondsToHMS(filter.minSec) : null;\n const hi = filter.maxSec !== \"\" && filter.maxSec != null ? secondsToHMS(filter.maxSec) : null;\n if (lo && hi) return `${lo} – ${hi}`;\n if (lo) return `≥ ${lo}`;\n if (hi) return `≤ ${hi}`;\n return \"\";\n }\n if (filter.type === \"scoreRange\") {\n if (Array.isArray(filter.values) && filter.values.length > 0) {\n return filter.values.slice().sort((a, b) => a - b).join(\", \");\n }\n const lo = filter.min !== \"\" && filter.min != null ? filter.min : null;\n const hi = filter.max !== \"\" && filter.max != null ? filter.max : null;\n if (lo != null && hi != null) return `${lo} – ${hi}`;\n if (lo != null) return `≥ ${lo}`;\n if (hi != null) return `≤ ${hi}`;\n return \"\";\n }\n if (filter.type === \"dateRange\") {\n if (filter.from && filter.to) return `${filter.from} – ${filter.to}`;\n if (filter.from) return `from ${filter.from}`;\n if (filter.to) return `to ${filter.to}`;\n return \"\";\n }\n return \"\";\n}\n\nfunction chipExtraCount(filter) {\n if (Array.isArray(filter)) return Math.max(0, filter.length - 1);\n return 0;\n}\n\nfunction chipExtraValues(filter) {\n if (Array.isArray(filter)) return filter.slice(1).map(String).join(\", \");\n return \"\";\n}\n\nfunction ExtraValuesBadge({ count, values }) {\n const [hover, setHover] = useState(false);\n return (\n <span\n onMouseEnter={() => setHover(true)}\n onMouseLeave={() => setHover(false)}\n style={{\n position: \"relative\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: 22,\n minWidth: 22,\n padding: \"0 6px\",\n background: \"#D8D8D8\",\n color: \"#0B0B0B\",\n borderRadius: 14,\n fontSize: 12,\n fontWeight: 500,\n lineHeight: 1,\n cursor: \"pointer\",\n }}\n >\n +{count}\n {hover && (\n <span\n role=\"tooltip\"\n style={{\n position: \"absolute\",\n bottom: \"calc(100% + 6px)\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n background: \"#1E2125\",\n color: \"#FFFFFF\",\n fontFamily: \"var(--font-sans)\",\n fontSize: 12,\n fontWeight: 400,\n lineHeight: \"20px\",\n padding: \"6px 10px\",\n borderRadius: 8,\n whiteSpace: \"nowrap\",\n pointerEvents: \"none\",\n zIndex: 100,\n boxShadow: \"0 6px 16px rgba(11, 11, 11, 0.18)\",\n }}\n >\n {values}\n </span>\n )}\n </span>\n );\n}\n\nfunction RangeInputs({ leftLabel, rightLabel, leftValue, rightValue, onLeftChange, onRightChange, type = \"number\", placeholderLeft = \"Min\", placeholderRight = \"Max\" }) {\n const fieldStyle = {\n width: \"100%\",\n height: 32,\n borderRadius: 8,\n border: \"1px solid #D9D9D9\",\n background: \"#FFFFFF\",\n padding: \"0 10px\",\n fontFamily: \"var(--font-sans)\",\n fontSize: 14,\n color: \"#0B0B0B\",\n outline: \"none\",\n boxSizing: \"border-box\",\n };\n const labelStyle = { fontSize: 12, color: \"#676767\", marginBottom: 4, fontFamily: \"var(--font-sans)\" };\n return (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 10 }}>\n <div style={{ display: \"flex\", flexDirection: \"column\" }}>\n <span style={labelStyle}>{leftLabel}</span>\n <input\n type={type}\n value={leftValue}\n onChange={(e) => onLeftChange(e.target.value)}\n placeholder={placeholderLeft}\n style={fieldStyle}\n />\n </div>\n <div style={{ display: \"flex\", flexDirection: \"column\" }}>\n <span style={labelStyle}>{rightLabel}</span>\n <input\n type={type}\n value={rightValue}\n onChange={(e) => onRightChange(e.target.value)}\n placeholder={placeholderRight}\n style={fieldStyle}\n />\n </div>\n </div>\n );\n}\n\nconst DURATION_PRESETS = [\n { id: \"0-60\", label: \"0 to 60 Sec\", minSec: 0, maxSec: 60 },\n { id: \"60-120\", label: \"1m to 2 m\", minSec: 60, maxSec: 120 },\n { id: \"120-180\", label: \"2m to 3 m\", minSec: 120, maxSec: 180 },\n { id: \"180-240\", label: \"3m to 4m\", minSec: 180, maxSec: 240 },\n { id: \"240-300\", label: \"4m to 5m\", minSec: 240, maxSec: 300 },\n { id: \"300+\", label: \"5 mins and above\", minSec: 300, maxSec: null },\n];\n\nfunction mmssToSec(str) {\n if (str == null || str === \"\") return null;\n const m = String(str).trim().match(/^(\\d{1,3}):(\\d{2})$/);\n if (m) return Number(m[1]) * 60 + Number(m[2]);\n // Fallback: plain number = seconds.\n const n = Number(str);\n return Number.isFinite(n) ? n : null;\n}\n\nfunction secToMmss(sec) {\n if (sec == null || sec === \"\") return \"\";\n const total = Math.max(0, Math.round(Number(sec)));\n const m = Math.floor(total / 60);\n const s = total % 60;\n return `${String(m).padStart(2, \"0\")}:${String(s).padStart(2, \"0\")}`;\n}\n\n// Shared \"title\" used at the top of every numeric/range filter so all of\n// them render the column label at the same size and weight.\nfunction FilterTitle({ children }) {\n return (\n <div\n style={{\n fontSize: 14,\n fontWeight: 600,\n color: \"#0B0B0B\",\n lineHeight: \"20px\",\n padding: \"4px 0 2px\",\n fontFamily: \"var(--font-sans)\",\n }}\n >\n {children}\n </div>\n );\n}\n\n// Shared Min/Max input pair used by every numeric/range filter (number,\n// score, duration). One render path → identical visuals everywhere.\n// `unit` (e.g. \"sec\") is shown as a small hint below the row instead of\n// being appended to each label — that kept long labels like \"Min From (sec)\"\n// from wrapping and breaking vertical alignment with \"Max (sec)\".\nfunction MinMaxInputs({\n minValue,\n maxValue,\n onMinChange,\n onMaxChange,\n inputType = \"number\",\n inputMode = \"decimal\",\n step,\n placeholder = \"0.0\",\n unit,\n}) {\n const fieldStyle = {\n width: \"100%\",\n height: 30,\n border: \"1px solid #ACADAD\",\n borderRadius: 4,\n padding: \"6px 10px\",\n fontSize: 13,\n color: \"#0B0B0B\",\n fontFamily: \"var(--font-sans)\",\n outline: \"none\",\n boxSizing: \"border-box\",\n };\n return (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 4 }}>\n <div style={{ display: \"flex\", alignItems: \"flex-end\", gap: 8 }}>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 6, flex: 1, minWidth: 0 }}>\n <span style={{ fontSize: 12, color: \"#2E3236\", fontFamily: \"var(--font-sans)\" }}>Min From</span>\n <input\n type={inputType}\n inputMode={inputMode}\n step={step}\n placeholder={placeholder}\n value={minValue}\n onChange={(e) => onMinChange(e.target.value)}\n style={fieldStyle}\n />\n </div>\n <span style={{ fontSize: 12, fontWeight: 600, color: \"#323232\", paddingBottom: 8, fontFamily: \"var(--font-sans)\" }}>to</span>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 6, flex: 1, minWidth: 0 }}>\n <span style={{ fontSize: 12, color: \"#2E3236\", fontFamily: \"var(--font-sans)\" }}>Max</span>\n <input\n type={inputType}\n inputMode={inputMode}\n step={step}\n placeholder={placeholder}\n value={maxValue}\n onChange={(e) => onMaxChange(e.target.value)}\n style={fieldStyle}\n />\n </div>\n </div>\n {unit && (\n <span\n style={{\n fontSize: 11,\n color: \"#676767\",\n fontFamily: \"var(--font-sans)\",\n }}\n >\n Input values in {unit === \"sec\" ? \"seconds\" : unit}\n </span>\n )}\n </div>\n );\n}\n\nfunction FilterValuePicker({ column, columnId, filterType = \"text\", position, popoverRef, distinctValues, initialValue, onApply, onCancel }) {\n const isText = filterType === \"text\";\n const isNumber = filterType === \"number\";\n const isDate = filterType === \"date\";\n const isDuration = filterType === \"duration\";\n const isScore = filterType === \"score\";\n\n // Score columns can hold either 1–5 ratings (compass) or arbitrary numbers\n // (e.g. 78.3% scores). Only render the 1–5 preset checkboxes when the\n // distinct values actually sit in [0, 5]; otherwise fall back to a\n // Min/Max-only layout (same UI as the generic numeric filter).\n const scoreInRange = useMemo(() => {\n if (!isScore || !Array.isArray(distinctValues) || distinctValues.length === 0) return false;\n let min = Infinity;\n let max = -Infinity;\n for (const v of distinctValues) {\n const n = parseNumberLike(v);\n if (!Number.isFinite(n)) continue;\n if (n < min) min = n;\n if (n > max) max = n;\n }\n return Number.isFinite(min) && Number.isFinite(max) && min >= 0 && max <= 5;\n }, [isScore, distinctValues]);\n\n // ── State per filterType ────────────────────────────────────────────\n const [staged, setStaged] = useState(() =>\n isText ? new Set(Array.isArray(initialValue) ? initialValue : []) : new Set()\n );\n const [query, setQuery] = useState(\"\");\n const [rangeMin, setRangeMin] = useState(() => (isNumber && initialValue?.type === \"range\" && initialValue.min != null ? initialValue.min : \"\"));\n const [rangeMax, setRangeMax] = useState(() => (isNumber && initialValue?.type === \"range\" && initialValue.max != null ? initialValue.max : \"\"));\n const [durPresets, setDurPresets] = useState(new Set());\n const [durCustomMin, setDurCustomMin] = useState(() =>\n isDuration && initialValue?.type === \"durationRange\" && initialValue.minSec != null && initialValue.minSec !== \"\"\n ? String(initialValue.minSec)\n : \"\"\n );\n const [durCustomMax, setDurCustomMax] = useState(() =>\n isDuration && initialValue?.type === \"durationRange\" && initialValue.maxSec != null && initialValue.maxSec !== \"\"\n ? String(initialValue.maxSec)\n : \"\"\n );\n const [scorePresets, setScorePresets] = useState(() =>\n isScore && initialValue?.type === \"scoreRange\" && Array.isArray(initialValue.values)\n ? new Set(initialValue.values)\n : new Set()\n );\n const [scoreCustomMin, setScoreCustomMin] = useState(() =>\n isScore && initialValue?.type === \"scoreRange\" && initialValue.min != null && initialValue.min !== \"\"\n ? String(initialValue.min)\n : \"\"\n );\n const [scoreCustomMax, setScoreCustomMax] = useState(() =>\n isScore && initialValue?.type === \"scoreRange\" && initialValue.max != null && initialValue.max !== \"\"\n ? String(initialValue.max)\n : \"\"\n );\n const [dateFrom, setDateFrom] = useState(() => (isDate && initialValue?.type === \"dateRange\" ? initialValue.from || \"\" : \"\"));\n const [dateTo, setDateTo] = useState(() => (isDate && initialValue?.type === \"dateRange\" ? initialValue.to || \"\" : \"\"));\n\n useEffect(() => {\n if (isText) setStaged(new Set(Array.isArray(initialValue) ? initialValue : []));\n }, [columnId, isText]);\n\n const filteredValues = useMemo(() => {\n const q = query.trim().toLowerCase();\n if (!q) return distinctValues;\n return distinctValues.filter((v) => String(v).toLowerCase().includes(q));\n }, [distinctValues, query]);\n\n const toggle = (value) => {\n setStaged((prev) => {\n const next = new Set(prev);\n if (next.has(value)) next.delete(value); else next.add(value);\n return next;\n });\n };\n\n const reset = () => {\n if (isText) setStaged(new Set());\n if (isNumber) { setRangeMin(\"\"); setRangeMax(\"\"); }\n if (isDuration) { setDurPresets(new Set()); setDurCustomMin(\"\"); setDurCustomMax(\"\"); }\n if (isScore) { setScorePresets(new Set()); setScoreCustomMin(\"\"); setScoreCustomMax(\"\"); }\n if (isDate) { setDateFrom(\"\"); setDateTo(\"\"); }\n setQuery(\"\");\n };\n\n const toggleDurPreset = (id) => {\n setDurPresets((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id); else next.add(id);\n return next;\n });\n };\n\n const toggleScorePreset = (n) => {\n setScorePresets((prev) => {\n const next = new Set(prev);\n if (next.has(n)) next.delete(n); else next.add(n);\n return next;\n });\n };\n\n const apply = () => {\n if (isText) return onApply(Array.from(staged));\n if (isNumber) return onApply({ type: \"range\", min: rangeMin === \"\" ? \"\" : Number(rangeMin), max: rangeMax === \"\" ? \"\" : Number(rangeMax) });\n if (isDuration) {\n // Custom range overrides presets when filled. Otherwise the union of\n // selected preset buckets is sent as a single [minSec, maxSec] range.\n const customMinSec = mmssToSec(durCustomMin);\n const customMaxSec = mmssToSec(durCustomMax);\n const hasCustom = customMinSec != null || customMaxSec != null;\n let minSec = \"\";\n let maxSec = \"\";\n if (hasCustom) {\n minSec = customMinSec != null ? customMinSec : \"\";\n maxSec = customMaxSec != null ? customMaxSec : \"\";\n } else if (durPresets.size > 0) {\n const selected = DURATION_PRESETS.filter((p) => durPresets.has(p.id));\n minSec = Math.min(...selected.map((p) => p.minSec));\n const openEnded = selected.some((p) => p.maxSec == null);\n maxSec = openEnded ? \"\" : Math.max(...selected.map((p) => p.maxSec));\n }\n return onApply({ type: \"durationRange\", minSec, maxSec });\n }\n if (isScore) {\n // Custom range overrides preset checkboxes when filled. Otherwise the\n // selected preset integers are sent as a discrete `values` array, which\n // matches rows where Math.floor(score) is in the set.\n const customMinNum = scoreCustomMin === \"\" ? null : Number(scoreCustomMin);\n const customMaxNum = scoreCustomMax === \"\" ? null : Number(scoreCustomMax);\n const hasCustom = customMinNum != null || customMaxNum != null;\n if (hasCustom) {\n return onApply({\n type: \"scoreRange\",\n values: [],\n min: customMinNum != null && Number.isFinite(customMinNum) ? customMinNum : \"\",\n max: customMaxNum != null && Number.isFinite(customMaxNum) ? customMaxNum : \"\",\n });\n }\n return onApply({\n type: \"scoreRange\",\n values: Array.from(scorePresets).sort((a, b) => a - b),\n min: \"\",\n max: \"\",\n });\n }\n if (isDate) return onApply({ type: \"dateRange\", from: dateFrom, to: dateTo });\n };\n\n return (\n <div\n ref={popoverRef}\n role=\"dialog\"\n aria-label={`Filter ${column.label || columnId}`}\n style={{\n position: \"fixed\",\n top: position.top,\n left: position.left,\n zIndex: 50,\n width: isText ? 240 : 220,\n background: \"#FFFFFF\",\n border: \"1px solid #E6E6E6\",\n borderRadius: 10,\n padding: 12,\n display: \"flex\",\n flexDirection: \"column\",\n gap: 10,\n boxShadow: \"0 8px 24px rgba(11, 11, 11, 0.10)\",\n fontFamily: \"var(--font-sans)\",\n }}\n >\n {isText && (\n <>\n <div\n style={{\n background: \"#D8D8D8\",\n height: 32,\n borderRadius: 10,\n padding: 1,\n display: \"flex\",\n alignItems: \"center\",\n }}\n >\n <div\n style={{\n background: \"#FFFFFF\",\n flex: 1,\n height: 30,\n borderRadius: 10,\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"0 8px\",\n }}\n >\n <Search size={16} color=\"#989898\" strokeWidth={2} />\n <input\n autoFocus\n type=\"text\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder=\"Search\"\n style={{\n flex: 1,\n border: \"none\",\n outline: \"none\",\n background: \"transparent\",\n fontSize: 14,\n color: \"#0B0B0B\",\n minWidth: 0,\n fontFamily: \"var(--font-sans)\",\n }}\n />\n </div>\n </div>\n\n <div style={{ maxHeight: 220, overflowY: \"auto\", display: \"flex\", flexDirection: \"column\", gap: 4 }}>\n {filteredValues.length === 0 ? (\n <div style={{ fontSize: 13, color: \"#676767\", padding: \"8px 4px\", textAlign: \"center\" }}>\n No values\n </div>\n ) : (\n filteredValues.map((value) => {\n const checked = staged.has(value);\n return (\n <label\n key={value}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 12,\n padding: \"6px 4px\",\n cursor: \"pointer\",\n borderRadius: 6,\n }}\n >\n <span\n style={{\n width: 20,\n height: 20,\n borderRadius: 4,\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: checked ? \"#0B0B0B\" : \"#FFFFFF\",\n border: `1px solid ${checked ? \"#0B0B0B\" : \"#676767\"}`,\n flexShrink: 0,\n }}\n >\n {checked && <Check size={14} color=\"#FFFFFF\" strokeWidth={3} />}\n </span>\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={() => toggle(value)}\n style={{ position: \"absolute\", opacity: 0, pointerEvents: \"none\" }}\n tabIndex={-1}\n />\n <span\n onClick={(e) => { e.preventDefault(); toggle(value); }}\n style={{\n fontSize: 14,\n lineHeight: \"20px\",\n color: \"#0B0B0B\",\n flex: 1,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {value}\n </span>\n </label>\n );\n })\n )}\n </div>\n </>\n )}\n\n {isNumber && (\n <>\n <FilterTitle>{column.label || \"Filter\"}</FilterTitle>\n <MinMaxInputs\n minValue={rangeMin}\n maxValue={rangeMax}\n onMinChange={setRangeMin}\n onMaxChange={setRangeMax}\n />\n </>\n )}\n\n {isDuration && (\n <>\n {/* Title — compact, shared with the other range filters. */}\n <FilterTitle>{column.label || \"Duration\"}</FilterTitle>\n\n {/* Preset buckets — opt-in. The column must set\n `filterShowPresets: true` to show the bucket checkboxes. By\n default duration columns render just title + MM:SS Min/Max,\n same shape as the number filter. Mirrors the score-filter\n behaviour above for consistency. */}\n {column.filterShowPresets === true && (\n <>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 12 }}>\n {DURATION_PRESETS.map((preset) => {\n const checked = durPresets.has(preset.id);\n return (\n <div\n key={preset.id}\n role=\"checkbox\"\n aria-checked={checked}\n tabIndex={0}\n onClick={() => toggleDurPreset(preset.id)}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n toggleDurPreset(preset.id);\n }\n }}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 12,\n cursor: \"pointer\",\n userSelect: \"none\",\n }}\n >\n <span\n style={{\n width: 20,\n height: 20,\n borderRadius: 4,\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: checked ? \"#0B0B0B\" : \"#FFFFFF\",\n border: `1px solid ${checked ? \"#0B0B0B\" : \"#676767\"}`,\n flexShrink: 0,\n }}\n >\n {checked && <Check size={14} color=\"#FFFFFF\" strokeWidth={3} />}\n </span>\n <span\n style={{\n fontSize: 14,\n lineHeight: \"20px\",\n color: \"#0B0B0B\",\n fontFamily: \"var(--font-sans)\",\n }}\n >\n {preset.label}\n </span>\n </div>\n );\n })}\n </div>\n\n {/* Divider above Custom Range — only when presets render above. */}\n <div style={{ height: 1, background: \"#D9D9D9\", margin: \"0 -12px\" }} />\n\n {/* Custom Range sub-header — redundant when there are no presets. */}\n <div\n style={{\n fontSize: 14,\n fontWeight: 500,\n color: \"#0B0B0B\",\n lineHeight: \"20px\",\n padding: \"4px 0\",\n fontFamily: \"var(--font-sans)\",\n }}\n >\n Custom Range\n </div>\n </>\n )}\n <MinMaxInputs\n minValue={durCustomMin}\n maxValue={durCustomMax}\n onMinChange={setDurCustomMin}\n onMaxChange={setDurCustomMax}\n inputType=\"number\"\n inputMode=\"numeric\"\n placeholder=\"0\"\n unit=\"sec\"\n />\n </>\n )}\n\n {isScore && (\n <>\n {/* Title — driven by column.label so the same picker can serve\n \"Compass Score\", \"Score\", etc. Falls back to \"Score\". */}\n <FilterTitle>{column.label || \"Score\"}</FilterTitle>\n\n {/* Preset values 1..5 — opt-in. The column must set\n `filterShowPresets: true` AND its data must fit in [0, 5]. By\n default the score filter renders just title + Min/Max so it\n works for compass-style decimal scores (where bucketing 1..5\n would lose the precision in 4.06 vs 4.10). */}\n {scoreInRange && column.filterShowPresets === true && (\n <>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 12 }}>\n {[1, 2, 3, 4, 5].map((n) => {\n const checked = scorePresets.has(n);\n return (\n <div\n key={n}\n role=\"checkbox\"\n aria-checked={checked}\n tabIndex={0}\n onClick={() => toggleScorePreset(n)}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n toggleScorePreset(n);\n }\n }}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 12,\n cursor: \"pointer\",\n userSelect: \"none\",\n }}\n >\n <span\n style={{\n width: 20,\n height: 20,\n borderRadius: 4,\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: checked ? \"#0B0B0B\" : \"#FFFFFF\",\n border: `1px solid ${checked ? \"#0B0B0B\" : \"#676767\"}`,\n flexShrink: 0,\n }}\n >\n {checked && <Check size={14} color=\"#FFFFFF\" strokeWidth={3} />}\n </span>\n <span\n style={{\n fontSize: 14,\n lineHeight: \"20px\",\n color: \"#0B0B0B\",\n fontFamily: \"var(--font-sans)\",\n }}\n >\n {n}\n </span>\n </div>\n );\n })}\n </div>\n\n {/* Divider — only when presets are shown above the custom range */}\n <div style={{ height: 1, background: \"#D9D9D9\", margin: \"0 -12px\" }} />\n </>\n )}\n\n {/* Range header — labelled \"Custom Range\" only when the presets\n section sits above it; otherwise the picker is just a Min/Max\n filter and the section header would be redundant. */}\n {scoreInRange && column.filterShowPresets === true && (\n <div\n style={{\n fontSize: 14,\n fontWeight: 500,\n color: \"#0B0B0B\",\n lineHeight: \"20px\",\n padding: \"4px 0\",\n fontFamily: \"var(--font-sans)\",\n }}\n >\n Custom Range\n </div>\n )}\n <MinMaxInputs\n minValue={scoreCustomMin}\n maxValue={scoreCustomMax}\n onMinChange={setScoreCustomMin}\n onMaxChange={setScoreCustomMax}\n step=\"0.1\"\n />\n </>\n )}\n\n {isDate && (\n <RangeInputs\n leftLabel=\"From\"\n rightLabel=\"To\"\n leftValue={dateFrom}\n rightValue={dateTo}\n onLeftChange={setDateFrom}\n onRightChange={setDateTo}\n type=\"date\"\n placeholderLeft=\"\"\n placeholderRight=\"\"\n />\n )}\n\n <div style={{ height: 1, background: \"#D9D9D9\", margin: \"0 -12px\" }} />\n <div style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"space-between\" }}>\n <button\n type=\"button\"\n onClick={reset}\n style={{\n background: \"transparent\",\n border: \"none\",\n padding: 0,\n cursor: \"pointer\",\n fontSize: 14,\n fontWeight: 500,\n color: \"#323232\",\n fontFamily: \"var(--font-sans)\",\n }}\n >\n {(isDuration && column.filterShowPresets === true) || (isScore && scoreInRange && column.filterShowPresets === true) ? \"View All\" : \"Reset\"}\n </button>\n <button\n type=\"button\"\n onClick={apply}\n style={{\n background: \"#0B0B0B\",\n color: \"#FFFFFF\",\n border: \"none\",\n borderRadius: 10,\n height: 28,\n padding: \"0 14px\",\n fontSize: 14,\n fontWeight: 500,\n cursor: \"pointer\",\n fontFamily: \"var(--font-sans)\",\n }}\n >\n Apply\n </button>\n </div>\n </div>\n );\n}\nfunction ResizeColumnsIcon({ size = 10, color = \"currentColor\" }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n style={{ display: \"block\" }}\n aria-hidden=\"true\"\n >\n <path d=\"M3.5 8H12.5\" stroke={color} strokeWidth=\"1.4\" strokeLinecap=\"round\" />\n <path d=\"M5 6.5L3.5 8L5 9.5\" stroke={color} strokeWidth=\"1.4\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n <path d=\"M11 6.5L12.5 8L11 9.5\" stroke={color} strokeWidth=\"1.4\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n <path d=\"M6.8 3V13\" stroke={color} strokeWidth=\"1.2\" strokeLinecap=\"round\" />\n <path d=\"M9.2 3V13\" stroke={color} strokeWidth=\"1.2\" strokeLinecap=\"round\" />\n </svg>\n );\n}\n// TODO: replace with framework-agnostic context\nconst useUserContext = () => ({ userData: { email: \"anonymous\" } });\n// TODO: replace with framework-agnostic image\nconst Image = (props) => <img {...props} />;\nimport DataTableFilters from \"./DataTableFilters\";\n// TODO: replace with framework-agnostic tooltip\nfunction HoverBalloon({\n children,\n content,\n direction = \"top\",\n align = \"center\",\n styling,\n indicatorColor,\n}) {\n const tooltipText =\n typeof content === \"string\" ? content : content != null ? String(content) : \"\";\n const resolvedArrowColor =\n typeof indicatorColor === \"string\" &&\n (indicatorColor.startsWith(\"#\") ||\n indicatorColor.startsWith(\"rgb\") ||\n indicatorColor.startsWith(\"hsl\") ||\n indicatorColor.startsWith(\"var(\"))\n ? indicatorColor\n : \"var(--Grey-Strong, #2E3236)\";\n const [isVisible, setIsVisible] = useState(false);\n const [mounted, setMounted] = useState(false);\n const [position, setPosition] = useState({ top: 0, left: 0, arrowLeft: 0, placement: \"top\" });\n const triggerRef = useRef(null);\n const tooltipRef = useRef(null);\n\n if (!tooltipText) return children;\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n const updatePosition = useCallback(() => {\n if (!triggerRef.current || !tooltipRef.current || typeof window === \"undefined\") return;\n\n const triggerRect = triggerRef.current.getBoundingClientRect();\n const tooltipRect = tooltipRef.current.getBoundingClientRect();\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n\n const viewportPadding = 8;\n const gap = 10;\n const tooltipWidth = tooltipRect.width;\n const tooltipHeight = tooltipRect.height;\n\n const spaceAbove = triggerRect.top;\n const spaceBelow = viewportHeight - triggerRect.bottom;\n const preferredPlacement = direction === \"bottom\" ? \"bottom\" : \"top\";\n\n let placement = preferredPlacement;\n if (preferredPlacement === \"top\" && spaceAbove < tooltipHeight + gap + viewportPadding && spaceBelow > spaceAbove) {\n placement = \"bottom\";\n } else if (preferredPlacement === \"bottom\" && spaceBelow < tooltipHeight + gap + viewportPadding && spaceAbove > spaceBelow) {\n placement = \"top\";\n }\n\n let anchorX = triggerRect.left + triggerRect.width / 2;\n if (align === \"start\") anchorX = triggerRect.left;\n if (align === \"end\") anchorX = triggerRect.right;\n\n let top = placement === \"top\"\n ? triggerRect.top - tooltipHeight - gap\n : triggerRect.bottom + gap;\n let left = align === \"start\"\n ? anchorX\n : align === \"end\"\n ? anchorX - tooltipWidth\n : anchorX - tooltipWidth / 2;\n\n top = Math.max(viewportPadding, Math.min(top, viewportHeight - tooltipHeight - viewportPadding));\n left = Math.max(viewportPadding, Math.min(left, viewportWidth - tooltipWidth - viewportPadding));\n\n const arrowLeft = Math.max(10, Math.min(anchorX - left, tooltipWidth - 10));\n setPosition({ top, left, arrowLeft, placement });\n }, [align, direction]);\n\n useEffect(() => {\n if (!isVisible || !mounted) return;\n\n updatePosition();\n\n const handleReposition = () => updatePosition();\n window.addEventListener(\"resize\", handleReposition);\n window.addEventListener(\"scroll\", handleReposition, true);\n\n return () => {\n window.removeEventListener(\"resize\", handleReposition);\n window.removeEventListener(\"scroll\", handleReposition, true);\n };\n }, [isVisible, mounted, updatePosition]);\n\n return (\n <span\n ref={triggerRef}\n style={{ display: \"block\", width: \"100%\" }}\n onMouseEnter={() => setIsVisible(true)}\n onMouseLeave={() => setIsVisible(false)}\n >\n {children}\n {isVisible && mounted && createPortal(\n <span\n ref={tooltipRef}\n style={{\n position: \"fixed\",\n top: `${position.top}px`,\n left: `${position.left}px`,\n background: \"var(--Grey-Strong, #2E3236)\",\n color: \"var(--Grey-White, #FFF)\",\n fontSize: \"12px\",\n lineHeight: 1.3,\n fontWeight: 500,\n padding: \"8px 10px\",\n borderRadius: \"6px\",\n whiteSpace: \"normal\",\n maxWidth: \"320px\",\n width: \"max-content\",\n boxShadow: \"0 6px 18px rgba(0, 0, 0, 0.2)\",\n zIndex: 99999,\n pointerEvents: \"none\",\n ...(typeof styling === \"object\" ? styling : {}),\n }}\n >\n {tooltipText}\n <span\n style={{\n position: \"absolute\",\n left: `${position.arrowLeft}px`,\n transform: \"translateX(-50%)\",\n width: 0,\n height: 0,\n borderLeft: \"6px solid transparent\",\n borderRight: \"6px solid transparent\",\n ...(position.placement === \"top\"\n ? {\n top: \"100%\",\n borderTop: `7px solid ${resolvedArrowColor}`,\n }\n : {\n bottom: \"100%\",\n borderBottom: `7px solid ${resolvedArrowColor}`,\n }),\n }}\n />\n </span>,\n document.body\n )}\n </span>\n );\n}\n\n/**\n * DataTable Component\n * Interactive table with column reordering, filtering, sorting, sticky headers, and pagination\n * Follows \"No Judgment\" principle - scores and counts displayed uniformly\n */\nexport default function DataTable2({\n data = [], \n columns = [], \n initialPageSize = 10, \n onRowClick,\n // Server-side pagination props (optional)\n totalCount = null, // Total count from server (null = use client-side pagination)\n page: controlledPage = null, // Controlled page (null = use internal state)\n pageSize: controlledPageSize = null, // Controlled pageSize (null = use internal state)\n onPageChange = null, // Callback for page changes (null = use internal state)\n onPageSizeChange = null, // Callback for pageSize changes (null = use internal state)\n onFilterChange = null, // Callback for filter changes (null = use client-side filtering)\n columnFilters = null, // Controlled inline header filters (columnId -> value). Used to rehydrate inputs in server-side filtering mode.\n // Optional callback to surface column limit errors to host app\n onMaxColumnsError = null,\n // Server-side sorting props (optional)\n onSort = null, // Callback for sort changes (null = use client-side sorting)\n sortFields = [], // Array of [field, direction] tuples from parent (null = use internal state)\n tableId = null, // Optional unique identifier for localStorage persistence (e.g., \"history\", \"agents\")\n isLoading = false, // Loading state to show overlay inside table\n // Filter props (optional)\n filtersConfig = null, // Top toolbar filter config (chips/date/export). Note: this is different from `columnFilters` for inline header inputs.\n // Column resize (optional) — min/max in px; columns may override with column.minWidth / column.maxWidth\n columnResizeMinWidth = 100,\n columnResizeMaxWidth = 280,\n // Fires whenever the user-visible column set changes. Useful for hosts that\n // want to scope a CSV export, etc., to whatever the user has selected.\n // Receives an array of column ids (excluding the action column).\n onVisibleColumnsChange = null,\n}) {\n // Get user email for user-specific storage\n const { userData } = useUserContext();\n const userId = userData?.email || 'anonymous';\n\n // Component to show tooltip only when text is actually truncated\n const TruncatedCell = React.memo(({ children, content, className = \"\" }) => {\n const textRef = useRef(null);\n const [isTruncated, setIsTruncated] = useState(false);\n\n useEffect(() => {\n const checkTruncation = () => {\n if (textRef.current) {\n const isOverflowing = textRef.current.scrollWidth > textRef.current.clientWidth;\n setIsTruncated(isOverflowing);\n }\n };\n\n checkTruncation();\n const timeoutId = setTimeout(checkTruncation, 0);\n\n window.addEventListener('resize', checkTruncation);\n return () => {\n clearTimeout(timeoutId);\n window.removeEventListener('resize', checkTruncation);\n };\n }, [children, content]);\n\n const textElement = (\n <span className={`truncate block ${className}`} ref={textRef}>\n {children}\n </span>\n );\n\n if (isTruncated && content) {\n return (\n <HoverBalloon\n content={content}\n styling=\"bg-green-2 text-gray-900 px-3 py-2 text-sm rounded-lg shadow-md border border-gray-300 max-w-xs whitespace-normal\"\n indicatorColor=\"bg-green-2\"\n direction=\"top\"\n >\n {textElement}\n </HoverBalloon>\n );\n }\n\n return textElement;\n });\n TruncatedCell.displayName = 'TruncatedCell';\n\n // Use controlled pagination if props provided, otherwise use internal state\n const isServerSidePagination = totalCount !== null && onPageChange !== null;\n // Use server-side filtering if onFilterChange is provided\n const isServerSideFiltering = onFilterChange !== null;\n // Use server-side sorting if onSort is provided\n const isServerSideSorting = onSort !== null;\n const [internalPage, setInternalPage] = useState(1);\n const [internalPageSize, setInternalPageSize] = useState(initialPageSize);\n \n const page = controlledPage !== null ? controlledPage : internalPage;\n const pageSize = controlledPageSize !== null ? controlledPageSize : internalPageSize;\n \n const setPage = (newPage) => {\n if (onPageChange) {\n onPageChange(newPage);\n } else {\n setInternalPage(newPage);\n }\n };\n \n const setPageSize = (newSize) => {\n if (onPageSizeChange) {\n onPageSizeChange(newSize);\n } else {\n setInternalPageSize(newSize);\n }\n };\n \n const MAX_COLUMNS = 50;\n \n const ACTION_COLUMN_ID = 'action';\n\n // Refs for localStorage persistence\n const userHasManuallyChangedColumns = useRef(false);\n \n // Generate unique storage key for this table (includes userId)\n const storageKey = useMemo(() => {\n if (tableId) {\n return `dataTable_columns_${tableId}:${userId}`;\n }\n // Fallback: use column keys to create unique identifier\n const columnKeys = columns.map(col => (col.id || col.key)).sort().join('_');\n return `dataTable_columns_${columnKeys}:${userId}`;\n }, [tableId, columns, userId]);\n \n const manualChangeFlagKey = useMemo(() => {\n if (tableId) {\n return `dataTable_manual_change_${tableId}:${userId}`;\n }\n return null;\n }, [tableId, userId]);\n\n // Load saved column visibility from localStorage\n const loadSavedColumns = useCallback((key, cols) => {\n if (typeof window === 'undefined' || !key || !cols || cols.length === 0) return null;\n try {\n const saved = localStorage.getItem(key);\n if (saved) {\n const savedColumns = JSON.parse(saved);\n // Validate that saved columns still exist in current columns\n const validColumns = savedColumns.filter(colId => \n cols.some(col => (col.id || col.key) === colId)\n );\n if (validColumns.length > 0) {\n return validColumns;\n }\n }\n } catch (error) {\n console.warn('Failed to load saved columns from localStorage:', error);\n }\n return null;\n }, []);\n \n // filters: { [columnId]: string[] } — array of selected values per column\n const [filters, setFilters] = useState({});\n // Free-text global search applied to all visible string-cells\n const [globalQuery, setGlobalQuery] = useState(\"\");\n // Which column header has its filter popover open (columnId or null)\n const [openFilterColumnId, setOpenFilterColumnId] = useState(null);\n const [filterPopoverPosition, setFilterPopoverPosition] = useState({ top: 0, left: 0 });\n const filterPopoverRef = useRef(null);\n const filterIconRefs = useRef({});\n // Internal sorting state (only used for client-side sorting)\n const [internalSortField, setInternalSortField] = useState(null);\n const [internalSortDirection, setInternalSortDirection] = useState(\"asc\");\n\n const setColumnFilter = useCallback((columnId, value) => {\n const active = isFilterActive(value);\n setFilters((prev) => {\n const next = { ...prev };\n if (!active) delete next[columnId];\n else next[columnId] = value;\n return next;\n });\n if (onPageChange) onPageChange(1); else setInternalPage(1);\n if (isServerSideFiltering && onFilterChange) {\n onFilterChange(\n active\n ? { ...filters, [columnId]: value }\n : Object.fromEntries(Object.entries(filters).filter(([k]) => k !== columnId))\n );\n }\n }, [filters, onFilterChange, isServerSideFiltering, onPageChange]);\n\n const clearAllFilters = useCallback(() => {\n setFilters({});\n setGlobalQuery(\"\");\n if (onPageChange) onPageChange(1); else setInternalPage(1);\n if (isServerSideFiltering && onFilterChange) onFilterChange({});\n }, [onFilterChange, isServerSideFiltering, onPageChange]);\n\n const getDistinctValuesForColumn = useCallback((columnId) => {\n if (!data || data.length === 0) return [];\n const seen = new Set();\n const out = [];\n for (const row of data) {\n const v = row[columnId];\n if (v === null || v === undefined) continue;\n const s = typeof v === \"object\" ? JSON.stringify(v) : String(v);\n if (!seen.has(s)) {\n seen.add(s);\n out.push(s);\n }\n }\n return out.sort((a, b) => a.localeCompare(b));\n }, [data]);\n\n const getColumnFilterType = useCallback((columnId) => {\n const col = columns.find((c) => getColumnId(c) === columnId);\n if (col && col.filterType) return col.filterType;\n return detectFilterType(getDistinctValuesForColumn(columnId));\n }, [columns, getDistinctValuesForColumn]);\n\n // Compute a viewport-safe `{top, left}` for the filter popover. Anchors to\n // the trigger's left edge by default; if that would overflow the right edge\n // of the viewport (rightmost columns like Avg Call Duration), shifts the\n // popover left so the right edge of the popover aligns with the trigger.\n const computeFilterPopoverPosition = useCallback((rect) => {\n // Picker width depends on filter type — text is wider, others are 220.\n // Use the larger value as a conservative upper bound so the clamp doesn't\n // depend on knowing the type at compute time.\n const POPOVER_WIDTH = 240;\n const VIEWPORT_PAD = 8;\n const viewportWidth = typeof window !== \"undefined\" ? window.innerWidth : Infinity;\n let left = rect.left;\n if (left + POPOVER_WIDTH > viewportWidth - VIEWPORT_PAD) {\n left = Math.max(VIEWPORT_PAD, rect.right - POPOVER_WIDTH);\n }\n return { top: rect.bottom + 6, left };\n }, []);\n\n const openFilterPopoverFor = useCallback((columnId, anchorEl) => {\n if (!anchorEl) {\n setOpenFilterColumnId(columnId);\n return;\n }\n const rect = anchorEl.getBoundingClientRect();\n setFilterPopoverPosition(computeFilterPopoverPosition(rect));\n setOpenFilterColumnId((prev) => (prev === columnId ? null : columnId));\n }, [computeFilterPopoverPosition]);\n\n // Outside click closes filter popover\n useEffect(() => {\n if (!openFilterColumnId) return;\n const onMouseDown = (e) => {\n if (filterPopoverRef.current && filterPopoverRef.current.contains(e.target)) return;\n const anchor = filterIconRefs.current[openFilterColumnId];\n if (anchor && anchor.contains(e.target)) return;\n setOpenFilterColumnId(null);\n };\n document.addEventListener(\"mousedown\", onMouseDown);\n return () => document.removeEventListener(\"mousedown\", onMouseDown);\n }, [openFilterColumnId]);\n\n // Keep the filter popover anchored to its column header on scroll/resize\n // (matches the Columns dropdown pattern). Without this, the popover stays at\n // the viewport position it was opened at while the trigger scrolls away.\n useEffect(() => {\n if (!openFilterColumnId) return;\n const updatePosition = () => {\n const anchor = filterIconRefs.current[openFilterColumnId];\n if (!anchor) return;\n const rect = anchor.getBoundingClientRect();\n setFilterPopoverPosition(computeFilterPopoverPosition(rect));\n };\n window.addEventListener(\"scroll\", updatePosition, true);\n window.addEventListener(\"resize\", updatePosition);\n return () => {\n window.removeEventListener(\"scroll\", updatePosition, true);\n window.removeEventListener(\"resize\", updatePosition);\n };\n }, [openFilterColumnId, computeFilterPopoverPosition]);\n \n // Normalize inline filters by removing empty/null values.\n // Example usage (server-side mode):\n // <DataTable onFilterChange={handleFilterChange} columnFilters={dataTableFilters} />\n const normalizeColumnFilters = useCallback((incomingFilters) => {\n if (!incomingFilters || typeof incomingFilters !== \"object\") return {};\n return Object.fromEntries(\n Object.entries(incomingFilters).filter(([, value]) => {\n if (value === null || value === undefined) return false;\n if (typeof value === \"string\") return value.trim() !== \"\";\n return true; // allow numbers/booleans\n })\n );\n }, []);\n\n const areFiltersEqual = useCallback((a, b) => {\n const aKeys = Object.keys(a || {});\n const bKeys = Object.keys(b || {});\n if (aKeys.length !== bKeys.length) return false;\n return aKeys.every((key) => a[key] === b[key]);\n }, []);\n\n // Sync internal inline filter input UI from controlled prop in server-side mode.\n // This does not trigger onFilterChange and therefore does not create callback loops.\n useEffect(() => {\n if (!isServerSideFiltering || columnFilters === null) return;\n const normalizedFilters = normalizeColumnFilters(columnFilters);\n setFilters((prev) => (areFiltersEqual(prev, normalizedFilters) ? prev : normalizedFilters));\n }, [isServerSideFiltering, columnFilters, normalizeColumnFilters, areFiltersEqual]);\n \n // Get current sort state (from props if server-side, otherwise from internal state)\n // For server-side sorting, we need to map the sortField back to the column key\n // because History.js's handleSort maps some keys (e.g., \"evaluation.csat_score\" -> \"csat_score\")\n // but we need to compare against the original column key\n const getSortFieldForComparison = useCallback((sortFieldFromProps, columnId) => {\n // Reverse mapping: if sortField is \"csat_score\", it should match column \"evaluation.csat_score\"\n if (sortFieldFromProps === \"csat_score\" && columnId === \"evaluation.csat_score\") {\n return columnId;\n }\n // For other fields, use as-is (they should match)\n return sortFieldFromProps;\n }, []);\n \n const sortField = isServerSideSorting && sortFields.length > 0 ? sortFields[0][0] : internalSortField;\n const sortDirection = isServerSideSorting && sortFields.length > 0 ? sortFields[0][1] : internalSortDirection;\n // Support both 'id' and 'key' for column identifiers\n const [columnOrder, setColumnOrder] = useState(() => \n columns.map((col) => col.id || col.key)\n );\n const enforceActionPosition = useCallback((cols) => {\n if (!cols || cols.length === 0) return cols;\n\n // De-duplicate and enforce max column limit first\n let result = Array.from(new Set(cols));\n if (result.length > MAX_COLUMNS) {\n result = result.slice(0, MAX_COLUMNS);\n }\n\n const allColumnIds = columns.map((col) => col.id || col.key);\n const tableHasActionColumn = allColumnIds.includes(ACTION_COLUMN_ID);\n const hasAction = result.includes(ACTION_COLUMN_ID);\n\n // If the table defines an action column, always include it in the visible set,\n // counting toward the MAX_COLUMNS cap.\n if (!hasAction && tableHasActionColumn) {\n if (result.length >= MAX_COLUMNS) {\n // Replace the last non-action entry with the action column\n result = [...result.slice(0, MAX_COLUMNS - 1), ACTION_COLUMN_ID];\n } else {\n result = [...result, ACTION_COLUMN_ID];\n }\n }\n\n // Ensure the action column is always rendered last\n const withoutAction = result.filter((id) => id !== ACTION_COLUMN_ID);\n return [...withoutAction, ACTION_COLUMN_ID];\n }, [columns]);\n\n // Column selection state - load persisted columns if they exist, otherwise default to first 9\n const [visibleColumns, setVisibleColumns] = useState(() => {\n // Try to load persisted columns immediately on mount\n if (typeof window !== 'undefined' && tableId) {\n try {\n // Check if user has manually changed columns before\n const hasManualChange = localStorage.getItem(`dataTable_manual_change_${tableId}:${userId}`) === 'true';\n \n if (hasManualChange) {\n // User has manually changed columns, load persisted selection immediately\n const saved = localStorage.getItem(`dataTable_columns_${tableId}:${userId}`);\n if (saved) {\n const savedColumns = JSON.parse(saved);\n if (Array.isArray(savedColumns) && savedColumns.length > 0) {\n userHasManuallyChangedColumns.current = true;\n // Validate saved columns exist in current columns\n const validColumns = savedColumns.filter(colId => \n columns.some(col => (col.id || col.key) === colId)\n );\n if (validColumns.length > 0) {\n return validColumns.slice(0, MAX_COLUMNS);\n }\n }\n }\n }\n } catch (error) {\n console.warn('Failed to load saved columns from localStorage:', error);\n }\n }\n \n // If no persisted columns, default to first 9 columns\n const columnIds = columns.map((col) => col.id || col.key);\n const initial = columnIds.slice(0, MAX_COLUMNS);\n return enforceActionPosition(initial);\n });\n const [isColumnDropdownOpen, setIsColumnDropdownOpen] = useState(false);\n // Staged column selection — toggling/reordering inside the dropdown writes here.\n // Only Apply (or Reset) commits staged state to `visibleColumns` and the table.\n const [stagedVisibleColumns, setStagedVisibleColumns] = useState([]);\n const [columnDropdownPosition, setColumnDropdownPosition] = useState({ top: 0, left: 0, width: 0 });\n const [pendingSelection, setPendingSelection] = useState(new Set());\n const [pendingDeselection, setPendingDeselection] = useState(new Set());\n // Snapshot of the columns visible on first mount; used as the Reset target\n const initialVisibleColumnsRef = useRef(null);\n if (initialVisibleColumnsRef.current === null) {\n initialVisibleColumnsRef.current = [...visibleColumns];\n }\n const [draggedColumnIndex, setDraggedColumnIndex] = useState(null);\n const [dragOverColumnIndex, setDragOverColumnIndex] = useState(null);\n const columnDropdownRef = useRef(null);\n const columnDropdownMenuRef = useRef(null);\n const toastTimeoutRef = useRef(null);\n const [activeId, setActiveId] = useState(null);\n const [columnWidths, setColumnWidths] = useState({});\n const tableRef = useRef(null);\n const resizeStateRef = useRef(null);\n\n // Helper to get column identifier (id or key)\n const getColumnId = (col) => col.id || col.key;\n const toPixelWidth = useCallback((value) => {\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value === \"string\") {\n const trimmed = value.trim();\n if (trimmed.endsWith(\"px\")) {\n const parsed = parseFloat(trimmed);\n return Number.isFinite(parsed) ? parsed : null;\n }\n const parsed = parseFloat(trimmed);\n return Number.isFinite(parsed) && `${parsed}` === trimmed ? parsed : null;\n }\n return null;\n }, []);\n const getResolvedColumnWidth = useCallback((columnId, fallbackWidth) => {\n if (columnWidths[columnId] != null) return `${columnWidths[columnId]}px`;\n if (typeof fallbackWidth === \"number\") return `${fallbackWidth}px`;\n return fallbackWidth || \"auto\";\n }, [columnWidths]);\n\n const handleResizeMove = useCallback((event) => {\n if (!resizeStateRef.current) return;\n const { columnId, startX, startWidth, minWidth, maxWidth } = resizeStateRef.current;\n const delta = event.clientX - startX;\n const nextWidth = Math.round(startWidth + delta);\n const clamped = Math.min(maxWidth, Math.max(minWidth, nextWidth));\n setColumnWidths((prev) => ({ ...prev, [columnId]: clamped }));\n }, []);\n\n const stopResize = useCallback(() => {\n resizeStateRef.current = null;\n document.body.style.cursor = \"\";\n document.body.style.userSelect = \"\";\n document.removeEventListener(\"mousemove\", handleResizeMove);\n document.removeEventListener(\"mouseup\", stopResize);\n }, [handleResizeMove]);\n\n const startResize = useCallback((event, column, currentWidth) => {\n event.preventDefault();\n event.stopPropagation();\n const columnId = column.id || column.key;\n const colMin = toPixelWidth(column.minWidth) ?? columnResizeMinWidth;\n const colMax = toPixelWidth(column.maxWidth) ?? columnResizeMaxWidth;\n const minWidth = Math.min(colMin, colMax);\n const maxWidth = Math.max(colMin, colMax);\n const widthFromDom = event.currentTarget.closest(\"th\")?.getBoundingClientRect().width || 0;\n const parsed = toPixelWidth(currentWidth);\n const base =\n parsed != null\n ? parsed\n : Math.max(minWidth, Math.round(widthFromDom) || minWidth);\n const startWidth = Math.min(maxWidth, Math.max(minWidth, base));\n resizeStateRef.current = { columnId, startX: event.clientX, startWidth, minWidth, maxWidth };\n document.body.style.cursor = \"col-resize\";\n document.body.style.userSelect = \"none\";\n document.addEventListener(\"mousemove\", handleResizeMove);\n document.addEventListener(\"mouseup\", stopResize);\n }, [columnResizeMaxWidth, columnResizeMinWidth, handleResizeMove, stopResize, toPixelWidth]);\n\n useEffect(() => () => stopResize(), [stopResize]);\n\n const sensors = useSensors(\n useSensor(PointerSensor),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n })\n );\n\n // Handle column drag end (table-level drag and drop)\n const handleDragEnd = (event) => {\n const { active, over } = event;\n if (over && active.id !== over.id) {\n if (active.id === ACTION_COLUMN_ID || over.id === ACTION_COLUMN_ID) {\n showMaxColumnsError(\"Cannot drop columns on the Action column\");\n setActiveId(null);\n return;\n }\n // Mark that user has manually changed columns\n userHasManuallyChangedColumns.current = true;\n \n // Update visibleColumns order when dragging in table header\n setVisibleColumns((prev) => {\n const oldIndex = prev.indexOf(active.id);\n const newIndex = prev.indexOf(over.id);\n if (oldIndex !== -1 && newIndex !== -1) {\n const reordered = arrayMove(prev, oldIndex, newIndex);\n const constrained = enforceActionPosition(reordered);\n // Save immediately after drag\n saveColumnsToStorage(constrained);\n return constrained;\n }\n return prev;\n });\n \n // Also update columnOrder for consistency\n setColumnOrder((items) => {\n const oldIndex = items.indexOf(active.id);\n const newIndex = items.indexOf(over.id);\n return arrayMove(items, oldIndex, newIndex);\n });\n }\n setActiveId(null);\n };\n\n // Handle column drag start\n const handleDragStart = (event) => {\n setActiveId(event.active.id);\n };\n\n // Filter data based on filter inputs - supports multiple keywords\n // For server-side filtering, skip client-side filtering (data is already filtered by server)\n const filteredData = useMemo(() => {\n if (isServerSideFiltering) {\n // Server-side filtering: data is already filtered, use as-is\n return data || [];\n }\n \n // Client-side filtering: filter the data locally\n if (!data || data.length === 0) return [];\n \n const globalQ = globalQuery.trim().toLowerCase();\n const filterEntries = Object.entries(filters).filter(([, f]) => isFilterActive(f));\n\n return data.filter((row) => {\n for (const [key, filter] of filterEntries) {\n const cellValue = row[key];\n if (cellValue === null || cellValue === undefined) return false;\n // Text-values filter (legacy / default)\n if (Array.isArray(filter)) {\n const cellStr = String(cellValue);\n if (!filter.some((v) => String(v) === cellStr)) return false;\n continue;\n }\n if (filter.type === \"range\") {\n const n = parseNumberLike(cellValue);\n if (isNaN(n)) return false;\n if (filter.min !== \"\" && filter.min != null && n < Number(filter.min)) return false;\n if (filter.max !== \"\" && filter.max != null && n > Number(filter.max)) return false;\n continue;\n }\n if (filter.type === \"durationRange\") {\n const sec = parseDurationToSeconds(cellValue);\n if (isNaN(sec)) return false;\n if (filter.minSec !== \"\" && filter.minSec != null && sec < Number(filter.minSec)) return false;\n if (filter.maxSec !== \"\" && filter.maxSec != null && sec > Number(filter.maxSec)) return false;\n continue;\n }\n if (filter.type === \"scoreRange\") {\n const n = parseNumberLike(cellValue);\n if (isNaN(n)) return false;\n // Discrete preset values: bucket the score by floor (so \"4\" matches\n // 4.00 .. 4.99). If any presets are selected, custom min/max is\n // ignored — the apply() in FilterValuePicker enforces this exclusivity.\n if (Array.isArray(filter.values) && filter.values.length > 0) {\n const bucket = Math.floor(n);\n if (!filter.values.includes(bucket)) return false;\n continue;\n }\n if (filter.min !== \"\" && filter.min != null && n < Number(filter.min)) return false;\n if (filter.max !== \"\" && filter.max != null && n > Number(filter.max)) return false;\n continue;\n }\n if (filter.type === \"dateRange\") {\n const d = parseDateLike(cellValue);\n if (!d) return false;\n if (filter.from) {\n const from = new Date(filter.from + \"T00:00:00\");\n if (d < from) return false;\n }\n if (filter.to) {\n const to = new Date(filter.to + \"T23:59:59\");\n if (d > to) return false;\n }\n continue;\n }\n }\n // Global search — substring match across any cell value\n if (globalQ) {\n const anyMatch = Object.values(row).some((v) => {\n if (v === null || v === undefined) return false;\n return String(v).toLowerCase().includes(globalQ);\n });\n if (!anyMatch) return false;\n }\n return true;\n });\n }, [data, filters, globalQuery, isServerSideFiltering]);\n\n // Sort filtered data\n // For server-side sorting, skip client-side sorting (data is already sorted by server)\n const sortedData = useMemo(() => {\n if (isServerSideSorting) {\n // Server-side sorting: data is already sorted, use as-is\n return filteredData;\n }\n \n // Client-side sorting: sort the filtered data locally\n if (!sortField) return filteredData;\n \n return [...filteredData].sort((a, b) => {\n const aVal = a[sortField];\n const bVal = b[sortField];\n \n // Handle null/undefined\n if (aVal === null || aVal === undefined) return 1;\n if (bVal === null || bVal === undefined) return -1;\n \n // Handle numbers\n if (typeof aVal === \"number\" && typeof bVal === \"number\") {\n return sortDirection === \"asc\" ? aVal - bVal : bVal - aVal;\n }\n \n // Handle strings\n const aStr = String(aVal).toLowerCase();\n const bStr = String(bVal).toLowerCase();\n \n if (sortDirection === \"asc\") {\n return aStr.localeCompare(bStr);\n } else {\n return bStr.localeCompare(aStr);\n }\n });\n }, [filteredData, sortField, sortDirection, isServerSideSorting]);\n\n // Paginate sorted data\n // For server-side pagination, the page slice is already done by the server,\n // but we still want to honour any client-side filter / sort the user applies\n // on top of the visible page (otherwise the filter chips and column sort\n // arrows do nothing). Server-side filter / sort, when wired up, short-circuit\n // those passes inside `filteredData` / `sortedData` so this stays a no-op for\n // fully server-driven setups.\n // For client-side pagination, paginate the sorted data normally.\n const paginatedData = useMemo(() => {\n if (isServerSidePagination) {\n return sortedData;\n } else {\n const startIndex = (page - 1) * pageSize;\n const endIndex = startIndex + pageSize;\n return sortedData.slice(startIndex, endIndex);\n }\n }, [sortedData, page, pageSize, isServerSidePagination]);\n\n // Handle header click for sorting\n const handleSort = (field) => {\n if (isServerSideSorting && onSort) {\n // Server-side sorting: call parent's onSort callback\n onSort(field);\n // Reset to first page on sort (if pagination is controlled)\n if (onPageChange) {\n onPageChange(1);\n } else {\n setInternalPage(1);\n }\n } else {\n // Client-side sorting: update internal state\n if (internalSortField === field) {\n setInternalSortDirection(internalSortDirection === \"asc\" ? \"desc\" : \"asc\");\n } else {\n setInternalSortField(field);\n setInternalSortDirection(\"asc\");\n }\n setPage(1); // Reset to first page on sort\n }\n };\n\n // Legacy handler kept for any callers that still pass a string value;\n // it splits on whitespace and treats the resulting tokens as the selected values.\n const handleFilterChange = (id, value) => {\n const tokens = (value || \"\")\n .split(/\\s+/)\n .map((t) => t.trim())\n .filter(Boolean);\n setColumnFilter(id, tokens);\n };\n\n // Surface max columns limit error via callback, throttled to once per 3s\n const showMaxColumnsError = (message) => {\n if (toastTimeoutRef.current) return;\n if (typeof onMaxColumnsError === 'function') {\n onMaxColumnsError(message);\n }\n toastTimeoutRef.current = setTimeout(() => {\n toastTimeoutRef.current = null;\n }, 3000);\n };\n\n // Save columns to localStorage\n const saveColumnsToStorage = useCallback((cols) => {\n if (typeof window !== 'undefined' && storageKey && cols.length > 0 && userHasManuallyChangedColumns.current) {\n try {\n localStorage.setItem(storageKey, JSON.stringify(cols));\n if (manualChangeFlagKey) {\n localStorage.setItem(manualChangeFlagKey, 'true');\n }\n } catch (error) {\n console.warn('Failed to save columns to localStorage:', error);\n }\n }\n }, [storageKey, manualChangeFlagKey]);\n\n // Toggle column selection — writes to staged state only. The actual table updates\n // when the user clicks Apply (or Reset).\n const toggleColumnSelection = (columnId) => {\n // Prevent toggling the action column visibility; it should always be shown\n if (columnId === ACTION_COLUMN_ID) {\n return;\n }\n setStagedVisibleColumns(prev => {\n if (prev.includes(columnId)) {\n // Don't allow deselecting all columns\n if (prev.length === 1) return prev;\n return prev.filter(id => id !== columnId);\n }\n if (prev.length >= MAX_COLUMNS) {\n showMaxColumnsError(\"Maximum 9 column selection allowed\");\n return prev;\n }\n return enforceActionPosition([...prev, columnId]);\n });\n };\n\n // Column drag handlers for reordering in dropdown\n const handleColumnDragStart = (e, index) => {\n if (stagedVisibleColumns[index] === ACTION_COLUMN_ID) return;\n setDraggedColumnIndex(index);\n };\n\n const handleColumnDragEnd = () => {\n setDraggedColumnIndex(null);\n setDragOverColumnIndex(null);\n };\n\n const handleColumnDragOver = (e, index) => {\n e.preventDefault();\n if (draggedColumnIndex !== null && draggedColumnIndex !== index) {\n setDragOverColumnIndex(index);\n }\n };\n\n const handleColumnDragLeave = () => {\n setDragOverColumnIndex(null);\n };\n\n const handleColumnDrop = (e, dropIndex) => {\n e.preventDefault();\n if (\n draggedColumnIndex !== null &&\n draggedColumnIndex !== dropIndex &&\n stagedVisibleColumns[dropIndex] !== ACTION_COLUMN_ID &&\n stagedVisibleColumns[draggedColumnIndex] !== ACTION_COLUMN_ID\n ) {\n // Drag reorder is staged; commit happens on Apply.\n setStagedVisibleColumns(prev => {\n const reordered = arrayMove(prev, draggedColumnIndex, dropIndex);\n return enforceActionPosition(reordered);\n });\n }\n setDraggedColumnIndex(null);\n setDragOverColumnIndex(null);\n };\n\n // Update columnOrder when visibleColumns changes\n useEffect(() => {\n setColumnOrder(prev => {\n // Keep visible columns in their current order, append any new ones\n const visibleOrder = visibleColumns.filter(id => prev.includes(id));\n const newColumns = visibleColumns.filter(id => !prev.includes(id));\n const hiddenColumns = prev.filter(id => !visibleColumns.includes(id));\n return [...visibleOrder, ...newColumns, ...hiddenColumns];\n });\n }, [visibleColumns]);\n\n // Save to localStorage whenever visibleColumns changes (only if user has manually changed columns)\n useEffect(() => {\n if (typeof window !== 'undefined' && storageKey && visibleColumns.length > 0 && userHasManuallyChangedColumns.current) {\n try {\n const constrained = enforceActionPosition(visibleColumns);\n localStorage.setItem(storageKey, JSON.stringify(constrained));\n if (manualChangeFlagKey) {\n localStorage.setItem(manualChangeFlagKey, 'true');\n }\n } catch (error) {\n console.warn('Failed to save columns to localStorage:', error);\n }\n }\n }, [visibleColumns, storageKey, manualChangeFlagKey]);\n\n // Notify the host whenever the user-visible column set changes so it can\n // scope CSV exports etc. to the current selection. Strips the internal\n // ACTION column id so hosts only see real data columns.\n useEffect(() => {\n if (!onVisibleColumnsChange) return;\n onVisibleColumnsChange(\n visibleColumns.filter((id) => id !== ACTION_COLUMN_ID)\n );\n }, [visibleColumns, onVisibleColumnsChange]);\n\n // Initialize visibleColumns when columns become available (if not already initialized)\n useEffect(() => {\n // Only initialize if columns are available and visibleColumns is empty\n if (columns.length > 0 && visibleColumns.length === 0) {\n // Check if user has manually changed columns before\n if (typeof window !== 'undefined' && tableId) {\n try {\n const hasManualChange = localStorage.getItem(`dataTable_manual_change_${tableId}:${userId}`) === 'true';\n if (hasManualChange) {\n const saved = localStorage.getItem(`dataTable_columns_${tableId}:${userId}`);\n if (saved) {\n const savedColumns = JSON.parse(saved);\n if (Array.isArray(savedColumns) && savedColumns.length > 0) {\n // Validate saved columns exist in current columns\n const validColumns = savedColumns.filter(colId => \n columns.some(col => (col.id || col.key) === colId)\n );\n if (validColumns.length > 0) {\n userHasManuallyChangedColumns.current = true;\n setVisibleColumns(validColumns.slice(0, MAX_COLUMNS));\n return;\n }\n }\n }\n }\n } catch (error) {\n console.warn('Failed to load saved columns from localStorage:', error);\n }\n }\n \n // Default to first 9 columns if no saved columns\n const columnIds = columns.map((col) => col.id || col.key);\n setVisibleColumns(enforceActionPosition(columnIds.slice(0, MAX_COLUMNS)));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [columns, tableId, userId, enforceActionPosition]);\n\n // Get ordered columns based on visibleColumns and columnOrder\n const orderedColumns = useMemo(() => {\n // Filter to only show visible columns, maintaining their order\n const cols = visibleColumns\n .map((id) => columns.find((col) => getColumnId(col) === id))\n .filter(Boolean);\n return enforceActionPosition(cols.map(getColumnId))\n .map((id) => columns.find((col) => getColumnId(col) === id))\n .filter(Boolean);\n }, [columns, visibleColumns]);\n\n // Check if any columns are filterable\n const hasFilterableColumns = useMemo(() => {\n return orderedColumns.some((col) => col.filterable === true);\n }, [orderedColumns]);\n\n // Column dropdown position management\n useEffect(() => {\n if (!isColumnDropdownOpen || !columnDropdownRef.current) return;\n\n const updatePosition = () => {\n if (columnDropdownRef.current) {\n const rect = columnDropdownRef.current.getBoundingClientRect();\n const menuWidth = 217;\n // Right-align the menu to the button so it never overflows the viewport\n // when the trigger sits near the right edge.\n const left = Math.max(8, rect.right - menuWidth);\n setColumnDropdownPosition({\n top: rect.bottom,\n left,\n width: Math.max(rect.width || 220, 220),\n });\n }\n };\n\n updatePosition();\n \n // Use simple scroll listeners like Dropdown component for smooth scrolling\n window.addEventListener(\"scroll\", updatePosition, true);\n window.addEventListener(\"resize\", updatePosition);\n\n return () => {\n window.removeEventListener(\"scroll\", updatePosition, true);\n window.removeEventListener(\"resize\", updatePosition);\n };\n }, [isColumnDropdownOpen]);\n\n // Close dropdown when clicking outside\n useEffect(() => {\n const handleClickOutside = (event) => {\n if (\n isColumnDropdownOpen &&\n columnDropdownRef.current &&\n !columnDropdownRef.current.contains(event.target) &&\n columnDropdownMenuRef.current &&\n !columnDropdownMenuRef.current.contains(event.target)\n ) {\n setIsColumnDropdownOpen(false);\n }\n };\n\n if (isColumnDropdownOpen) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }\n }, [isColumnDropdownOpen]);\n\n // Sync staged selection with the committed selection whenever the dropdown opens.\n // Outside-click closes without committing, so the next open always starts from the\n // last applied state.\n useEffect(() => {\n if (isColumnDropdownOpen) {\n setStagedVisibleColumns(visibleColumns);\n setPendingSelection(new Set());\n setPendingDeselection(new Set());\n }\n }, [isColumnDropdownOpen, visibleColumns]);\n\n // Display text for dropdown button\n const displayText = visibleColumns.length === 1 \n ? columns.find(col => (col.id || col.key) === visibleColumns[0])?.label || \"1 selected\"\n : `${visibleColumns.length} selected`;\n\n // Sortable header cell component\n function SortableHeader({ column, isHeaderRow = true }) {\n const columnId = getColumnId(column);\n const isActionColumn = columnId === ACTION_COLUMN_ID;\n const resolvedWidth = getResolvedColumnWidth(columnId, column.width);\n const [isHeaderHovered, setIsHeaderHovered] = useState(false);\n const {\n attributes,\n listeners,\n setNodeRef,\n transform,\n transition,\n isDragging,\n } = useSortable({ id: columnId });\n\n const style = {\n transform: CSS.Transform.toString(transform),\n transition,\n opacity: isDragging ? 0.5 : 1,\n width: resolvedWidth,\n minWidth: resolvedWidth,\n };\n\n // For server-side sorting, check if the sortField matches this column\n // Handle reverse mapping (e.g., \"csat_score\" matches \"evaluation.csat_score\")\n let isSorted = false;\n if (isServerSideSorting && sortFields.length > 0) {\n const sortFieldFromProps = sortFields[0][0];\n // Direct match\n if (sortFieldFromProps === columnId) {\n isSorted = true;\n }\n // Reverse mapping: \"csat_score\" matches \"evaluation.csat_score\"\n else if (sortFieldFromProps === \"csat_score\" && columnId === \"evaluation.csat_score\") {\n isSorted = true;\n }\n } else {\n // Client-side sorting: direct comparison\n isSorted = sortField === columnId;\n }\n \n const isAsc = sortDirection === \"asc\";\n const isFilterable = column.filterable === true; // Only filterable if explicitly set to true\n\n // Filter row\n if (!isHeaderRow) {\n return (\n <th\n style={{\n width: resolvedWidth,\n minWidth: resolvedWidth,\n backgroundColor: \"var(--primary-foreground)\",\n }}\n className=\"sticky top-[57px] z-10 border-b border-[var(--border-strong)] px-4 py-2 text-left\"\n >\n {isFilterable ? (\n <div className=\"relative\">\n <Filter\n size={12}\n className=\"absolute left-2 top-1/2 -translate-y-1/2 text-[var(--text-faint)] pointer-events-none\"\n />\n <input\n type=\"text\"\n placeholder=\"Filter...\"\n value={filters[columnId] || \"\"}\n onChange={(e) => {\n e.stopPropagation();\n handleFilterChange(columnId, e.target.value);\n }}\n onKeyDown={(e) => e.stopPropagation()}\n onMouseDown={(e) => e.stopPropagation()}\n className=\"w-full pl-7 pr-2 py-1.5 text-xs border border-[var(--border)] rounded text-[var(--text-ink)] placeholder:text-[var(--text-faint)] focus:outline-none focus:border-[var(--border-hover)] focus:ring-1 focus:ring-[var(--focus)] transition-colors\"\n style={{ fontFamily: 'var(--font-sans)', backgroundColor: \"var(--primary-foreground)\" }}\n autoComplete=\"off\"\n />\n </div>\n ) : (\n <div className=\"h-[34px]\"></div>\n )}\n </th>\n );\n }\n\n // Header row\n const filterPopoverOpen = openFilterColumnId === columnId;\n const hasActiveFilter = isFilterActive(filters[columnId]);\n const showSortBtn = column.sortable !== false && (isHeaderHovered || isSorted);\n const showFilterBtn = column.filterable !== false && !isActionColumn && (isHeaderHovered || filterPopoverOpen || hasActiveFilter);\n return (\n <th\n ref={setNodeRef}\n onMouseEnter={() => setIsHeaderHovered(true)}\n onMouseLeave={() => setIsHeaderHovered(false)}\n style={{\n ...style,\n padding: '0 12px',\n height: 36,\n textAlign: isActionColumn ? 'center' : 'left',\n fontWeight: 500,\n fontSize: '14px',\n letterSpacing: 'normal',\n textTransform: 'none',\n color: '#0b0b0b',\n cursor: column.sortable !== false ? 'pointer' : 'default',\n width: resolvedWidth,\n borderRight: 'none',\n userSelect: 'none',\n background: isHeaderHovered || filterPopoverOpen ? '#e6e6e6' : '#f2f2f0',\n borderBottom: '1px solid #e6e6e6',\n position: 'sticky',\n top: 0,\n zIndex: 10,\n fontFamily: 'var(--font-sans)',\n transition: 'background 100ms ease',\n }}\n >\n {/* Left edge separator (1px × 16px, vertically centered) */}\n {!isActionColumn && (\n <span\n aria-hidden=\"true\"\n style={{\n position: \"absolute\",\n left: 0,\n top: \"50%\",\n transform: \"translateY(-50%)\",\n width: 1,\n height: 16,\n background: \"#e6e6e6\",\n pointerEvents: \"none\",\n }}\n />\n )}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n justifyContent: isActionColumn ? 'center' : 'flex-start',\n position: 'relative',\n minHeight: 20,\n }}\n >\n {!isActionColumn && (\n <div\n {...attributes}\n {...listeners}\n style={{\n cursor: 'grab',\n color: 'rgba(11, 11, 11, 0.36)',\n display: 'inline-flex',\n alignItems: 'center',\n visibility: isHeaderHovered ? 'visible' : 'hidden',\n }}\n >\n <GripVertical size={14} />\n </div>\n )}\n <span\n onClick={() => column.sortable !== false && handleSort(columnId)}\n style={{ cursor: column.sortable !== false ? 'pointer' : 'default', flex: 1, lineHeight: '20px' }}\n >\n {column.label}\n </span>\n {showSortBtn && (\n <button\n type=\"button\"\n onClick={(e) => { e.stopPropagation(); handleSort(columnId); }}\n title=\"Sort\"\n style={{\n background: \"transparent\",\n border: \"none\",\n padding: 4,\n borderRadius: 4,\n cursor: \"pointer\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n color: isSorted ? \"#0b0b0b\" : \"rgba(11, 11, 11, 0.55)\",\n }}\n >\n {isSorted\n ? (isAsc ? <ArrowUp size={14} strokeWidth={1.75} /> : <ArrowDown size={14} strokeWidth={1.75} />)\n : <ArrowUpDown size={14} strokeWidth={1.75} />}\n </button>\n )}\n {showFilterBtn && (\n <button\n type=\"button\"\n ref={(el) => { filterIconRefs.current[columnId] = el; }}\n onClick={(e) => { e.stopPropagation(); openFilterPopoverFor(columnId, e.currentTarget); }}\n title=\"Filter\"\n style={{\n position: \"relative\",\n background: filterPopoverOpen || hasActiveFilter ? \"#D8D8D8\" : \"transparent\",\n border: \"none\",\n padding: 4,\n borderRadius: 4,\n cursor: \"pointer\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n color: hasActiveFilter ? \"#0b0b0b\" : \"rgba(11, 11, 11, 0.7)\",\n }}\n >\n <ListFilter size={14} strokeWidth={1.75} />\n {hasActiveFilter && (\n <span\n aria-hidden=\"true\"\n style={{\n position: \"absolute\",\n top: 0,\n right: 0,\n width: 6,\n height: 6,\n borderRadius: \"50%\",\n background: \"#0B0B0B\",\n }}\n />\n )}\n </button>\n )}\n </div>\n {/* Right edge separator (1px × 16px, vertically centered, on the cell's right edge) */}\n {!isActionColumn && (\n <span\n aria-hidden=\"true\"\n style={{\n position: \"absolute\",\n right: 0,\n top: \"50%\",\n transform: \"translateY(-50%)\",\n width: 1,\n height: 16,\n background: \"#e6e6e6\",\n pointerEvents: \"none\",\n }}\n />\n )}\n {/* Resize handle — sits right at the cell's right edge, away from the filter icon */}\n {!isActionColumn && (\n <div\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label={`Resize ${column.label || columnId} column`}\n title=\"Drag to resize column\"\n onMouseDown={(e) => startResize(e, column, resolvedWidth)}\n onClick={(e) => e.stopPropagation()}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = \"rgba(30, 33, 37, 0.18)\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = \"transparent\";\n }}\n style={{\n position: \"absolute\",\n top: 0,\n right: -2,\n width: 4,\n height: \"100%\",\n cursor: \"col-resize\",\n zIndex: 4,\n background: \"transparent\",\n }}\n />\n )}\n </th>\n );\n }\n\n // Drag overlay for column header\n const activeColumn = activeId ? columns.find((col) => getColumnId(col) === activeId) : null;\n\n // Column dropdown menu\n const renderColumnRow = ({ col, columnId, isSelected, draggable, isAction, actualIndex }) => {\n const isDragging = draggable && draggedColumnIndex === actualIndex;\n const isDragOver = draggable && dragOverColumnIndex === actualIndex && draggedColumnIndex !== null && draggedColumnIndex !== actualIndex;\n const isPending = isSelected ? pendingDeselection.has(columnId) : pendingSelection.has(columnId);\n // Visual checked state: selected and not pending deselect, OR unselected and pending select\n const checked = isSelected ? !pendingDeselection.has(columnId) : pendingSelection.has(columnId);\n return (\n <div\n draggable={draggable}\n onDragStart={draggable ? (e) => handleColumnDragStart(e, actualIndex) : undefined}\n onDragEnd={draggable ? handleColumnDragEnd : undefined}\n onDragOver={draggable ? (e) => handleColumnDragOver(e, actualIndex) : undefined}\n onDragLeave={draggable ? handleColumnDragLeave : undefined}\n onDrop={draggable ? (e) => handleColumnDrop(e, actualIndex) : undefined}\n onClick={() => { if (!isAction) toggleColumnSelection(columnId); }}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n padding: \"2px 0\",\n cursor: isAction ? \"default\" : (draggable ? \"grab\" : \"pointer\"),\n opacity: isDragging ? 0.5 : 1,\n background: isDragOver ? \"#F2F2F0\" : \"transparent\",\n borderRadius: 6,\n }}\n >\n {/* Drag handle — visible only for selected (sortable) items */}\n <span\n style={{\n width: 16,\n height: 16,\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"#989898\",\n visibility: draggable ? \"visible\" : \"hidden\",\n flexShrink: 0,\n }}\n >\n <GripVertical size={14} strokeWidth={1.75} />\n </span>\n {/* Checkbox 20x20 */}\n <span\n style={{\n width: 20,\n height: 20,\n borderRadius: 4,\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: checked ? \"#0B0B0B\" : \"#FFFFFF\",\n border: `1px solid ${checked ? \"#0B0B0B\" : \"#676767\"}`,\n flexShrink: 0,\n marginLeft: 8,\n }}\n >\n {checked && <Check size={14} color=\"#FFFFFF\" strokeWidth={3} />}\n </span>\n <span\n style={{\n flex: 1,\n fontFamily: \"var(--font-sans)\",\n fontSize: 14,\n lineHeight: \"20px\",\n color: \"#0B0B0B\",\n marginLeft: 8,\n }}\n >\n {col.label}\n </span>\n </div>\n );\n };\n\n const columnDropdownMenu = isColumnDropdownOpen ? (\n <div\n ref={columnDropdownMenuRef}\n style={{\n position: \"fixed\",\n top: `${columnDropdownPosition.top}px`,\n left: `${columnDropdownPosition.left}px`,\n width: 217,\n maxHeight: 320,\n zIndex: 49,\n background: \"#FFFFFF\",\n border: \"1px solid #E6E6E6\",\n borderRadius: 10,\n overflow: \"hidden\",\n display: \"flex\",\n flexDirection: \"column\",\n fontFamily: \"var(--font-sans)\",\n boxShadow: \"0 8px 24px rgba(11, 11, 11, 0.08)\",\n }}\n >\n {/* Scrollable list — selected rows on top, unselected below. */}\n <div\n style={{\n flex: 1,\n minHeight: 0,\n overflowY: \"auto\",\n padding: 12,\n display: \"flex\",\n flexDirection: \"column\",\n gap: 12,\n }}\n >\n {/* Selected columns — draggable. Reads staged state so the dropdown reflects\n the user's pending toggles before they click Apply. */}\n {stagedVisibleColumns.map((columnId, index) => {\n const col = columns.find((c) => getColumnId(c) === columnId);\n if (!col) return null;\n const isAction = columnId === ACTION_COLUMN_ID;\n return (\n <React.Fragment key={`selected-${columnId}-${index}`}>\n {renderColumnRow({\n col,\n columnId,\n isSelected: true,\n draggable: !isAction,\n isAction,\n actualIndex: index,\n })}\n </React.Fragment>\n );\n })}\n\n {/* Unselected columns */}\n {columns\n .filter((col) => !stagedVisibleColumns.includes(getColumnId(col)))\n .map((col) => {\n const columnId = getColumnId(col);\n return (\n <React.Fragment key={`unselected-${columnId}`}>\n {renderColumnRow({\n col,\n columnId,\n isSelected: false,\n draggable: false,\n isAction: false,\n actualIndex: -1,\n })}\n </React.Fragment>\n );\n })}\n </div>\n\n {/* Sticky footer — Reset + Apply */}\n <div\n style={{\n flexShrink: 0,\n borderTop: \"1px solid #D9D9D9\",\n padding: \"8px 12px\",\n background: \"#FFFFFF\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n height: 46,\n boxSizing: \"border-box\",\n }}\n >\n <button\n type=\"button\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n // Reset both staged (so the dropdown UI updates) and committed columns to\n // the initial snapshot, and clear persisted user changes.\n const snapshot = initialVisibleColumnsRef.current\n ? [...initialVisibleColumnsRef.current]\n : columns.map(getColumnId).slice(0, MAX_COLUMNS);\n const constrained = enforceActionPosition(snapshot);\n userHasManuallyChangedColumns.current = false;\n setStagedVisibleColumns(constrained);\n setVisibleColumns(constrained);\n setPendingSelection(new Set());\n setPendingDeselection(new Set());\n if (typeof window !== \"undefined\" && storageKey) {\n try { localStorage.removeItem(storageKey); } catch (_) {}\n }\n }}\n style={{\n background: \"transparent\",\n border: \"none\",\n padding: 0,\n cursor: \"pointer\",\n fontFamily: \"var(--font-sans)\",\n fontSize: 14,\n fontWeight: 500,\n color: \"#323232\",\n }}\n >\n Reset\n </button>\n <button\n type=\"button\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n // Commit staged selection to the table.\n const constrained = enforceActionPosition(stagedVisibleColumns);\n userHasManuallyChangedColumns.current = true;\n setVisibleColumns(constrained);\n saveColumnsToStorage(constrained);\n setIsColumnDropdownOpen(false);\n }}\n style={{\n background: \"#2E3236\",\n color: \"#FFFFFF\",\n border: \"none\",\n borderRadius: 10,\n height: 28,\n padding: \"0 14px\",\n fontFamily: \"var(--font-sans)\",\n fontSize: 14,\n fontWeight: 600,\n cursor: \"pointer\",\n }}\n >\n Apply\n </button>\n </div>\n </div>\n ) : null;\n\n const openFilterColumn = openFilterColumnId\n ? columns.find((c) => getColumnId(c) === openFilterColumnId)\n : null;\n const filterPopoverNode = openFilterColumn\n ? (\n <FilterValuePicker\n key={openFilterColumnId}\n column={openFilterColumn}\n columnId={openFilterColumnId}\n filterType={getColumnFilterType(openFilterColumnId)}\n position={filterPopoverPosition}\n popoverRef={filterPopoverRef}\n distinctValues={getDistinctValuesForColumn(openFilterColumnId)}\n initialValue={filters[openFilterColumnId]}\n onApply={(value) => {\n setColumnFilter(openFilterColumnId, value);\n setOpenFilterColumnId(null);\n }}\n onCancel={() => setOpenFilterColumnId(null)}\n />\n )\n : null;\n\n return (\n <div className=\"w-full\">\n {/* Filter popover (anchored under the active column header) */}\n {filterPopoverNode && createPortal(filterPopoverNode, document.body)}\n {/* Toolbar: Columns dropdown + Search */}\n {columns.length > 0 && (\n <div\n className=\"pt-2 pb-1\"\n style={{\n position: \"sticky\",\n zIndex: 35,\n backgroundColor: \"var(--primary-foreground)\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"flex-end\",\n gap: 16,\n flexWrap: \"wrap\",\n }}\n >\n {filtersConfig && (\n <div style={{ marginRight: \"auto\" }}>\n <DataTableFilters\n dateRangePicker={filtersConfig.dateRangePicker}\n onWeekToDate={filtersConfig.onWeekToDate}\n exportConfig={filtersConfig.exportConfig}\n filterChipsConfig={filtersConfig.filterChipsConfig}\n trailingActions={filtersConfig.trailingActions}\n />\n </div>\n )}\n\n {/* Columns button — compact */}\n <div style={{ position: \"relative\" }}>\n <button\n ref={columnDropdownRef}\n type=\"button\"\n onClick={() => setIsColumnDropdownOpen(!isColumnDropdownOpen)}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 10,\n height: 32,\n padding: \"0 16px\",\n background: \"#FFFFFF\",\n border: \"1px solid #D9D9D9\",\n borderRadius: 10,\n cursor: \"pointer\",\n fontFamily: \"var(--font-sans)\",\n fontSize: 14,\n fontWeight: 600,\n color: \"#2E3236\",\n whiteSpace: \"nowrap\",\n }}\n >\n <Settings2 size={20} strokeWidth={1.75} />\n Columns\n </button>\n {isColumnDropdownOpen && createPortal(columnDropdownMenu, document.body)}\n </div>\n\n {/* Search input */}\n {/*\n <div\n style={{\n background: \"#D8D8D8\",\n width: 260,\n height: 32,\n borderRadius: 11,\n padding: 1,\n display: \"flex\",\n alignItems: \"center\",\n }}\n >\n <div\n style={{\n background: \"#FFFFFF\",\n flex: 1,\n height: 30,\n borderRadius: 10,\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"0 8px\",\n }}\n >\n <Search size={18} color=\"#989898\" strokeWidth={1.75} />\n <input\n type=\"text\"\n placeholder=\"Search\"\n value={globalQuery}\n onChange={(e) => {\n setGlobalQuery(e.target.value);\n if (onPageChange) onPageChange(1); else setInternalPage(1);\n }}\n style={{\n flex: 1,\n border: \"none\",\n outline: \"none\",\n background: \"transparent\",\n fontFamily: \"var(--font-sans)\",\n fontSize: 14,\n color: \"#0B0B0B\",\n minWidth: 0,\n }}\n />\n </div>\n </div>\n */}\n </div>\n </div>\n )}\n {/* Filter chip strip — appears below the toolbar when any filter is active */}\n {Object.keys(filters).length > 0 && (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n flexWrap: \"wrap\",\n padding: \"8px 0\",\n }}\n >\n {Object.entries(filters).map(([colId, filter]) => {\n const col = columns.find((c) => getColumnId(c) === colId);\n if (!col || !isFilterActive(filter)) return null;\n const first = chipSummary(filter);\n const extra = chipExtraCount(filter);\n const extraValues = chipExtraValues(filter);\n return (\n <span\n key={`chip-${colId}`}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 8,\n height: 28,\n padding: \"0 12px\",\n borderRadius: 20,\n border: \"1px solid #B2B2B0\",\n background: \"#F2F2F0\",\n fontFamily: \"var(--font-sans)\",\n fontSize: 14,\n lineHeight: \"20px\",\n color: \"#0B0B0B\",\n whiteSpace: \"nowrap\",\n }}\n >\n <span>\n <span style={{ color: \"#676767\" }}>{col.label}: </span>\n <span>{first}</span>\n </span>\n {extra > 0 && (\n <ExtraValuesBadge count={extra} values={extraValues} />\n )}\n <button\n type=\"button\"\n onClick={() => setColumnFilter(colId, [])}\n aria-label={`Remove ${col.label} filter`}\n style={{\n background: \"transparent\",\n border: \"none\",\n padding: 0,\n cursor: \"pointer\",\n display: \"inline-flex\",\n color: \"#676767\",\n }}\n >\n <X size={14} strokeWidth={2} />\n </button>\n </span>\n );\n })}\n <button\n type=\"button\"\n onClick={clearAllFilters}\n style={{\n marginLeft: \"auto\",\n background: \"transparent\",\n border: \"none\",\n padding: \"0 4px\",\n cursor: \"pointer\",\n fontFamily: \"var(--font-sans)\",\n fontSize: 14,\n fontWeight: 500,\n color: \"#323232\",\n }}\n >\n Reset\n </button>\n </div>\n )}\n\n {/* Only render table if we have columns */}\n {columns.length > 0 && orderedColumns.length > 0 ? (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n >\n <div style={{\n borderRadius: 8,\n border: '1px solid #E6E6E6',\n overflow: 'hidden',\n background: 'var(--primary-foreground)',\n position: 'relative',\n top: '0.5rem',\n }}>\n {/* Loading overlay */}\n {isLoading && (\n <div style={{\n position: 'absolute',\n inset: 0,\n background: 'rgba(255, 255, 255, 0.9)',\n backdropFilter: 'blur(2px)',\n zIndex: 20,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: '14px'\n }}>\n <div style={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n gap: '12px'\n }}>\n <p style={{\n fontSize: '13px',\n color: 'rgba(30, 33, 37, 0.6)',\n margin: 0\n }}>Loading...</p>\n <Image\n src=\"/BrandLoading.gif\"\n alt=\"Loading\"\n width={50}\n height={50}\n unoptimized\n className=\"mt-1\"\n />\n </div>\n </div>\n )}\n <div className=\"overflow-x-auto custom-thin-scrollbar-hidden\" ref={tableRef} style={{ maxHeight: '500px', overflowY: 'auto', position: 'relative', zIndex: 1 }}>\n <table style={{\n width: 'auto',\n minWidth: '100%',\n borderCollapse: 'collapse',\n fontSize: '13px',\n fontFamily: 'var(--font-sans)'\n }}>\n <thead>\n {/* Header row with column labels */}\n <tr>\n <SortableContext\n items={visibleColumns}\n strategy={horizontalListSortingStrategy}\n >\n {orderedColumns.map((column) => (\n <SortableHeader key={`header-${getColumnId(column)}`} column={column} isHeaderRow={true} />\n ))}\n </SortableContext>\n </tr>\n </thead>\n <tbody>\n {!isLoading && paginatedData.length === 0 ? (\n <tr>\n <td\n colSpan={orderedColumns.length}\n style={{\n padding: '32px',\n textAlign: 'center',\n color: 'rgba(30, 33, 37, 0.42)',\n fontSize: '12px',\n fontFamily: 'var(--font-sans)',\n }}\n >\n No results found\n </td>\n </tr>\n ) : !isLoading && paginatedData.length > 0 ? (\n paginatedData.map((row, rowIndex) => (\n <tr\n key={rowIndex}\n data-row-id={row.id || rowIndex}\n style={{\n borderBottom: '1px solid #e6e6e6',\n cursor: onRowClick ? 'pointer' : 'default',\n transition: 'background 0.15s ease'\n }}\n onClick={onRowClick ? (e) => {\n e.stopPropagation();\n onRowClick(row, rowIndex);\n } : undefined}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = 'rgba(231, 212, 162, 0.12)';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = 'transparent';\n }}\n >\n {orderedColumns.map((column) => {\n const columnId = getColumnId(column);\n const resolvedWidth = getResolvedColumnWidth(columnId, column.width);\n const cellValue = row[columnId];\n const renderValue = column.render\n ? column.render(cellValue, row)\n : cellValue;\n\n // Only show tooltip for string values that might be truncated\n const hasWidthConstraint = resolvedWidth && resolvedWidth !== 'auto';\n const isStringValue = typeof renderValue === 'string' && renderValue.trim() !== '';\n const shouldUseTruncatedCell = hasWidthConstraint && isStringValue;\n\n const displayValue = shouldUseTruncatedCell ? (\n <TruncatedCell content={renderValue}>\n {renderValue}\n </TruncatedCell>\n ) : renderValue;\n\n return (\n <td\n key={columnId}\n style={{\n padding: '10px 14px',\n color: 'rgba(30, 33, 37, 0.78)',\n fontSize: '13px',\n borderRight: '1px solid rgba(52, 58, 64, 0.04)',\n width: resolvedWidth,\n fontFamily: 'var(--font-sans)',\n ...(shouldUseTruncatedCell && { maxWidth: resolvedWidth || '200px' }),\n }}\n >\n {displayValue}\n </td>\n );\n })}\n </tr>\n ))\n ) : null}\n </tbody>\n </table>\n </div>\n </div>\n\n <DragOverlay>\n {activeColumn ? (\n <div className=\"bg-[var(--paper-high)] border border-[var(--border-strong)] rounded px-4 py-2 shadow-lg\">\n <div className=\"flex items-center gap-2\">\n <GripVertical size={14} className=\"text-[var(--text-faint)]\" />\n <span className=\"text-sm font-semibold text-[var(--text-ink)]\">\n {activeColumn.label}\n </span>\n </div>\n </div>\n ) : null}\n </DragOverlay>\n </DndContext>\n ) : null}\n\n {(() => {\n // In server-side pagination mode the client-side filter/sort still\n // operate on the current page, so when the user narrows it down with a\n // chip the footer should reflect the filtered count instead of the\n // server's totalCount (otherwise we render \"1-1 of 508\" with phantom\n // pages 2..51 the user can never reach).\n const hasClientFilter =\n !isServerSideFiltering &&\n (globalQuery.trim() !== \"\" ||\n Object.values(filters).some((f) => isFilterActive(f)));\n const effectiveTotal = isServerSidePagination\n ? hasClientFilter\n ? sortedData.length\n : totalCount\n : sortedData.length;\n if (effectiveTotal <= 0) return null;\n return (\n <Pagination\n page={page}\n pageSizeOptions={[5, 10, 20, 50, 100]}\n pageSize={pageSize}\n totalCount={effectiveTotal}\n currentDataLength={paginatedData.length}\n onPageChange={setPage}\n onPageSizeChange={(newSize) => {\n setPageSize(newSize);\n setPage(1);\n }}\n showPageSizeSelector={true}\n />\n );\n })()}\n </div>\n );\n}\n\n"],"names":["DataTableFilters","dateRangePicker","onWeekToDate","exportConfig","filterChipsConfig","trailingActions","showExportMenu","setShowExportMenu","useState","exportButtonRef","useRef","exportMenuRef","useEffect","handleClickOutside","event","openExportMenu","prev","handleExport","type","shouldShowChips","filters","customFilters","hasRegularFilters","key","value","hasCustomFilters","filterObj","jsxs","jsx","CalendarClock","Suspense","Download","ChevronDown","Fragment","CustomFilterChips","parseNumberLike","s","cleaned","n","parseDurationToSeconds","str","colon","a","b","c","total","matched","dM","hM","mM","sM","parseDateLike","slash","yyyy","d","detectFilterType","values","sample","allMatch","test","v","isFilterActive","filter","secondsToHMS","sec","h","m","chipSummary","lo","hi","chipExtraCount","chipExtraValues","ExtraValuesBadge","count","hover","setHover","RangeInputs","leftLabel","rightLabel","leftValue","rightValue","onLeftChange","onRightChange","placeholderLeft","placeholderRight","fieldStyle","labelStyle","e","DURATION_PRESETS","mmssToSec","FilterTitle","children","MinMaxInputs","minValue","maxValue","onMinChange","onMaxChange","inputType","inputMode","step","placeholder","unit","FilterValuePicker","column","columnId","filterType","position","popoverRef","distinctValues","initialValue","onApply","onCancel","isText","isNumber","isDate","isDuration","isScore","scoreInRange","useMemo","min","max","staged","setStaged","query","setQuery","rangeMin","setRangeMin","rangeMax","setRangeMax","durPresets","setDurPresets","durCustomMin","setDurCustomMin","durCustomMax","setDurCustomMax","scorePresets","setScorePresets","scoreCustomMin","setScoreCustomMin","scoreCustomMax","setScoreCustomMax","dateFrom","setDateFrom","dateTo","setDateTo","filteredValues","q","toggle","next","reset","toggleDurPreset","id","toggleScorePreset","apply","customMinSec","customMaxSec","hasCustom","minSec","maxSec","selected","p","customMinNum","customMaxNum","Search","checked","Check","preset","useUserContext","Image","props","HoverBalloon","content","direction","align","styling","indicatorColor","tooltipText","resolvedArrowColor","isVisible","setIsVisible","mounted","setMounted","setPosition","triggerRef","tooltipRef","updatePosition","useCallback","triggerRect","tooltipRect","viewportWidth","viewportHeight","viewportPadding","gap","tooltipWidth","tooltipHeight","spaceAbove","spaceBelow","preferredPlacement","placement","anchorX","top","left","arrowLeft","handleReposition","createPortal","DataTable2","data","columns","initialPageSize","onRowClick","totalCount","controlledPage","controlledPageSize","onPageChange","onPageSizeChange","onFilterChange","columnFilters","onMaxColumnsError","onSort","sortFields","tableId","isLoading","filtersConfig","columnResizeMinWidth","columnResizeMaxWidth","onVisibleColumnsChange","userData","userId","TruncatedCell","React","className","textRef","isTruncated","setIsTruncated","checkTruncation","isOverflowing","timeoutId","textElement","isServerSidePagination","isServerSideFiltering","isServerSideSorting","internalPage","setInternalPage","internalPageSize","setInternalPageSize","page","pageSize","setPage","newPage","setPageSize","newSize","MAX_COLUMNS","ACTION_COLUMN_ID","userHasManuallyChangedColumns","storageKey","col","manualChangeFlagKey","cols","saved","validColumns","colId","error","setFilters","globalQuery","setGlobalQuery","openFilterColumnId","setOpenFilterColumnId","filterPopoverPosition","setFilterPopoverPosition","filterPopoverRef","filterIconRefs","internalSortField","setInternalSortField","internalSortDirection","setInternalSortDirection","setColumnFilter","active","k","clearAllFilters","getDistinctValuesForColumn","seen","out","row","getColumnFilterType","getColumnId","computeFilterPopoverPosition","rect","openFilterPopoverFor","anchorEl","onMouseDown","anchor","normalizeColumnFilters","incomingFilters","areFiltersEqual","aKeys","bKeys","normalizedFilters","sortFieldFromProps","sortField","sortDirection","columnOrder","setColumnOrder","enforceActionPosition","result","tableHasActionColumn","visibleColumns","setVisibleColumns","savedColumns","initial","isColumnDropdownOpen","setIsColumnDropdownOpen","stagedVisibleColumns","setStagedVisibleColumns","columnDropdownPosition","setColumnDropdownPosition","pendingSelection","setPendingSelection","pendingDeselection","setPendingDeselection","initialVisibleColumnsRef","draggedColumnIndex","setDraggedColumnIndex","dragOverColumnIndex","setDragOverColumnIndex","columnDropdownRef","columnDropdownMenuRef","toastTimeoutRef","activeId","setActiveId","columnWidths","setColumnWidths","tableRef","resizeStateRef","toPixelWidth","trimmed","parsed","getResolvedColumnWidth","fallbackWidth","handleResizeMove","startX","startWidth","minWidth","maxWidth","delta","nextWidth","clamped","stopResize","startResize","currentWidth","colMin","colMax","widthFromDom","_a","base","sensors","useSensors","useSensor","PointerSensor","KeyboardSensor","sortableKeyboardCoordinates","handleDragEnd","over","showMaxColumnsError","oldIndex","newIndex","reordered","arrayMove","constrained","saveColumnsToStorage","items","handleDragStart","filteredData","globalQ","filterEntries","f","cellValue","cellStr","bucket","from","to","sortedData","aVal","bVal","aStr","bStr","paginatedData","startIndex","endIndex","handleSort","field","handleFilterChange","tokens","t","message","toggleColumnSelection","handleColumnDragStart","index","handleColumnDragEnd","handleColumnDragOver","handleColumnDragLeave","handleColumnDrop","dropIndex","visibleOrder","newColumns","hiddenColumns","columnIds","orderedColumns","menuWidth","SortableHeader","isHeaderRow","isActionColumn","resolvedWidth","isHeaderHovered","setIsHeaderHovered","attributes","listeners","setNodeRef","transform","transition","isDragging","useSortable","style","CSS","isSorted","isAsc","isFilterable","filterPopoverOpen","hasActiveFilter","showSortBtn","showFilterBtn","GripVertical","ArrowUp","ArrowDown","ArrowUpDown","el","ListFilter","activeColumn","renderColumnRow","isSelected","draggable","isAction","actualIndex","isDragOver","columnDropdownMenu","snapshot","openFilterColumn","filterPopoverNode","Settings2","first","extra","extraValues","X","DndContext","closestCenter","SortableContext","horizontalListSortingStrategy","rowIndex","renderValue","hasWidthConstraint","isStringValue","shouldUseTruncatedCell","displayValue","DragOverlay","hasClientFilter","effectiveTotal","Pagination"],"mappings":"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"}
1
+ {"version":3,"file":"DataTable2.cjs.js","sources":["../src/components/data/DataTableFilters.jsx","../src/components/data/DataTable2.jsx"],"sourcesContent":["\"use client\";\n\nimport React, { useState, useEffect, useRef, Suspense } from \"react\";\nimport { Download, ChevronDown, CalendarClock, CalendarDays } from \"lucide-react\";\nimport { createPortal } from \"react-dom\";\nimport { CustomFilterChips } from \"../common\";\n\n/**\n * DataTableFilters Component\n * Displays filter buttons (Week to Date, Select Date Range, Export) and filter chips\n * \n * @param {Object} props\n * @param {React.ReactNode} props.dateRangePicker - DateRangePicker component (wrapped in Suspense)\n * @param {Function} props.onWeekToDate - Handler for \"Week to Date\" button\n * @param {Object} props.exportConfig - Export configuration\n * @param {boolean} props.exportConfig.isExporting - Whether export is in progress\n * @param {Function} props.exportConfig.onExport - Export handler (type) => void\n * @param {Array} props.exportConfig.types - Export types array (default: ['csv'])\n * @param {Object} props.filterChipsConfig - Filter chips configuration\n * @param {Object} props.filterChipsConfig.filters - Current filter values\n * @param {Function} props.filterChipsConfig.onChange - Filter chips change handler\n * @param {Function} props.filterChipsConfig.onClear - Clear all filters handler\n * @param {Array} props.filterChipsConfig.customFilters - Custom filter chips (e.g., date range)\n */\nexport default function DataTableFilters({\n dateRangePicker,\n onWeekToDate,\n exportConfig,\n filterChipsConfig,\n trailingActions, // Optional extra actions rendered after Export (e.g., Add Users button)\n}) {\n const [showExportMenu, setShowExportMenu] = useState(false);\n const exportButtonRef = useRef(null);\n const exportMenuRef = useRef(null);\n\n // Handle click outside to close export menu\n useEffect(() => {\n const handleClickOutside = (event) => {\n if (\n exportMenuRef.current &&\n !exportMenuRef.current.contains(event.target) &&\n exportButtonRef.current &&\n !exportButtonRef.current.contains(event.target)\n ) {\n setShowExportMenu(false);\n }\n };\n\n if (showExportMenu) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }\n }, [showExportMenu]);\n\n const openExportMenu = () => {\n setShowExportMenu((prev) => !prev);\n };\n\n const handleExport = (type) => {\n setShowExportMenu(false);\n if (exportConfig?.onExport) {\n exportConfig.onExport(type);\n }\n };\n\n // Check if there are any filter chips to display\n const hasFilterChips = () => {\n if (!filterChipsConfig?.filters) return false;\n \n const filters = filterChipsConfig.filters;\n const customFilters = filterChipsConfig.customFilters || [];\n \n // Check if any regular filters have values\n const hasRegularFilters = Object.entries(filters).some(([key, value]) => {\n if (Array.isArray(value) && value.length) return true;\n if (typeof value === \"string\" && value.trim() !== \"\") return true;\n if (value && typeof value === \"object\" && (value.min != null || value.max != null)) return true;\n return false;\n });\n \n // Check if any custom filters are active\n const hasCustomFilters = customFilters.some(filterObj => filterObj.active);\n \n return hasRegularFilters || hasCustomFilters;\n };\n\n const shouldShowChips = hasFilterChips();\n\n return (\n <div className=\"flex items-center gap-3 flex-wrap\">\n {/* Week to Date Button */}\n {onWeekToDate && (\n <button\n onClick={onWeekToDate}\n className=\"inline-flex items-center gap-2 rounded-lg border border-gray-300 bg-white/80 px-4 py-2.5 transition-colors hover:bg-white text-sm font-medium text-gray-900\"\n style={{ fontFamily: 'var(--font-sans)' }}\n >\n <CalendarClock size={16} />\n <span>Week to Date</span>\n </button>\n )}\n\n {/* Select Date Range */}\n {dateRangePicker && (\n <Suspense\n fallback={\n <div className=\"inline-flex items-center gap-2 rounded-lg border border-gray-300 bg-white/80 px-4 py-2.5 text-sm font-medium text-gray-400\">\n <CalendarClock size={16} />\n <span>Loading...</span>\n </div>\n }\n >\n {dateRangePicker}\n </Suspense>\n )}\n\n {/* Export Button */}\n {exportConfig && (\n <div className=\"relative\">\n <button\n ref={exportButtonRef}\n onClick={openExportMenu}\n disabled={exportConfig.isExporting}\n className=\"inline-flex items-center justify-between gap-2 rounded-lg border border-gray-300 bg-white/80 px-4 py-2.5 transition-colors hover:bg-white text-sm font-medium text-gray-900 disabled:opacity-50 disabled:cursor-not-allowed min-w-[120px]\"\n style={{ fontFamily: 'var(--font-sans)' }}\n >\n <div className=\"flex items-center gap-2\">\n <Download size={16} />\n <span>{exportConfig.isExporting ? \"Exporting...\" : \"Export\"}</span>\n </div>\n <ChevronDown size={16} />\n </button>\n {showExportMenu && (\n <div\n ref={exportMenuRef}\n className=\"absolute top-full right-0 mt-2 bg-white rounded-lg shadow-lg border border-gray-200 py-1 z-50 min-w-[120px]\"\n >\n {(exportConfig.types || [\"csv\"]).map((type) => (\n <button\n key={type}\n onClick={() => handleExport(type)}\n className=\"w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 transition-colors\"\n style={{ fontFamily: 'var(--font-sans)' }}\n >\n Export {type.toUpperCase()}\n </button>\n ))}\n </div>\n )}\n </div>\n )}\n\n {/* Filter chips + optional trailing actions (e.g., Add Users / Add Agent) */}\n {(shouldShowChips || trailingActions) && (\n <>\n {/* Vertical line only when there are actual chips; this avoids double lines\n when we only show trailingActions (like Add Agent) with no chips. */}\n {shouldShowChips && (\n <div className=\"h-9 mt-1 w-px bg-gray-300 flex-shrink-0\"></div>\n )}\n\n {/* Filter Chips + trailing actions */}\n <div className=\"flex items-center gap-3 justify-end\">\n {shouldShowChips && filterChipsConfig && (\n <CustomFilterChips\n filters={filterChipsConfig.filters}\n onChange={filterChipsConfig.onChange}\n onClear={filterChipsConfig.onClear}\n customFilters={filterChipsConfig.customFilters || []}\n fieldOptions={filterChipsConfig.fieldOptions || {}}\n />\n )}\n {trailingActions && (\n <div className=\"flex-shrink-0\">\n {trailingActions}\n </div>\n )}\n </div>\n </>\n )}\n </div>\n );\n}\n\n","\"use client\";\n\nimport React, { useState, useMemo, useRef, useEffect, useLayoutEffect, useCallback } from \"react\";\nimport {\n DndContext,\n closestCenter,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n DragOverlay,\n} from \"@dnd-kit/core\";\nimport {\n arrayMove,\n SortableContext,\n sortableKeyboardCoordinates,\n useSortable,\n horizontalListSortingStrategy,\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { GripVertical, ChevronUp, ChevronDown, ListFilter, ArrowUp, ArrowDown, Settings2, Search, Check, X, ArrowUpDown } from \"lucide-react\";\nimport { createPortal } from \"react-dom\";\nimport Pagination from \"../common/Pagination.jsx\";\n// TODO: surface column limit errors via callback prop (onMaxColumnsError)\n// TODO: replace with framework-agnostic component\nfunction OpenCloseArrow({ isOpen, iconSize }) { return null; }\n// TODO: replace with framework-agnostic component\nfunction Separator() { return <div style={{ height: 1, background: \"rgba(52,58,64,0.08)\" }} />; }\n\n// ─── Typed-filter helpers ──────────────────────────────────────────────────\nfunction parseNumberLike(s) {\n if (s === null || s === undefined) return NaN;\n const cleaned = String(s).replace(/[,$%]|pp/gi, \"\").trim();\n const n = parseFloat(cleaned);\n return Number.isFinite(n) ? n : NaN;\n}\n\nfunction parseDurationToSeconds(s) {\n if (s === null || s === undefined) return NaN;\n const str = String(s).trim();\n // HH:MM:SS or MM:SS\n const colon = str.match(/^(\\d+):(\\d+)(?::(\\d+))?$/);\n if (colon) {\n const a = +colon[1], b = +colon[2], c = colon[3] != null ? +colon[3] : null;\n return c != null ? a * 3600 + b * 60 + c : a * 60 + b;\n }\n // 1d 2h 3m 4s\n let total = 0;\n let matched = false;\n const dM = str.match(/(\\d+)\\s*d\\b/i);\n const hM = str.match(/(\\d+)\\s*h\\b/i);\n const mM = str.match(/(\\d+)\\s*m(?!s)\\b/i);\n const sM = str.match(/(\\d+)\\s*s\\b/i);\n if (dM) { total += +dM[1] * 86400; matched = true; }\n if (hM) { total += +hM[1] * 3600; matched = true; }\n if (mM) { total += +mM[1] * 60; matched = true; }\n if (sM) { total += +sM[1]; matched = true; }\n return matched ? total : NaN;\n}\n\nfunction parseDateLike(s) {\n if (!s) return null;\n const str = String(s).trim();\n // MM/DD/YYYY or M/D/YY\n const slash = str.match(/^(\\d{1,2})\\/(\\d{1,2})\\/(\\d{2,4})$/);\n if (slash) {\n const yyyy = slash[3].length === 2 ? 2000 + +slash[3] : +slash[3];\n const d = new Date(yyyy, +slash[1] - 1, +slash[2]);\n return isNaN(d.getTime()) ? null : d;\n }\n const d = new Date(str);\n return isNaN(d.getTime()) ? null : d;\n}\n\nfunction detectFilterType(values) {\n if (!values || values.length === 0) return \"text\";\n const sample = values.slice(0, 25);\n const allMatch = (test) => sample.every(test);\n if (allMatch((v) => /^\\d{1,2}\\/\\d{1,2}\\/\\d{2,4}$/.test(v) || /^\\d{4}-\\d{2}-\\d{2}/.test(v))) return \"date\";\n if (allMatch((v) => /^\\d+\\s*[dhms]\\b/i.test(v) || /^\\d+:\\d+(:\\d+)?$/.test(v))) return \"duration\";\n if (allMatch((v) => /^-?[\\d,.]+(%|pp)?$/i.test(v))) return \"number\";\n return \"text\";\n}\n\nfunction isFilterActive(filter) {\n if (!filter) return false;\n if (Array.isArray(filter)) return filter.length > 0;\n if (filter.type === \"range\") return filter.min !== \"\" && filter.min !== undefined && filter.min !== null\n || filter.max !== \"\" && filter.max !== undefined && filter.max !== null;\n if (filter.type === \"durationRange\") return (filter.minSec !== \"\" && filter.minSec != null) || (filter.maxSec !== \"\" && filter.maxSec != null);\n if (filter.type === \"scoreRange\") return (Array.isArray(filter.values) && filter.values.length > 0)\n || (filter.min !== \"\" && filter.min != null) || (filter.max !== \"\" && filter.max != null);\n if (filter.type === \"dateRange\") return Boolean(filter.from || filter.to);\n return false;\n}\n\nfunction secondsToHMS(sec) {\n if (sec == null || sec === \"\" || isNaN(sec)) return \"\";\n const n = Number(sec);\n const h = Math.floor(n / 3600);\n const m = Math.floor((n % 3600) / 60);\n const s = Math.floor(n % 60);\n if (h > 0) return `${h}h ${m}m`;\n if (m > 0) return `${m}m ${s}s`;\n return `${s}s`;\n}\n\nfunction chipSummary(filter) {\n if (!filter) return \"\";\n if (Array.isArray(filter)) return filter.length === 0 ? \"\" : String(filter[0]);\n if (filter.type === \"range\") {\n const lo = filter.min !== \"\" && filter.min != null ? filter.min : null;\n const hi = filter.max !== \"\" && filter.max != null ? filter.max : null;\n if (lo != null && hi != null) return `${lo} – ${hi}`;\n if (lo != null) return `≥ ${lo}`;\n if (hi != null) return `≤ ${hi}`;\n return \"\";\n }\n if (filter.type === \"durationRange\") {\n const lo = filter.minSec !== \"\" && filter.minSec != null ? secondsToHMS(filter.minSec) : null;\n const hi = filter.maxSec !== \"\" && filter.maxSec != null ? secondsToHMS(filter.maxSec) : null;\n if (lo && hi) return `${lo} – ${hi}`;\n if (lo) return `≥ ${lo}`;\n if (hi) return `≤ ${hi}`;\n return \"\";\n }\n if (filter.type === \"scoreRange\") {\n if (Array.isArray(filter.values) && filter.values.length > 0) {\n return filter.values.slice().sort((a, b) => a - b).join(\", \");\n }\n const lo = filter.min !== \"\" && filter.min != null ? filter.min : null;\n const hi = filter.max !== \"\" && filter.max != null ? filter.max : null;\n if (lo != null && hi != null) return `${lo} – ${hi}`;\n if (lo != null) return `≥ ${lo}`;\n if (hi != null) return `≤ ${hi}`;\n return \"\";\n }\n if (filter.type === \"dateRange\") {\n if (filter.from && filter.to) return `${filter.from} – ${filter.to}`;\n if (filter.from) return `from ${filter.from}`;\n if (filter.to) return `to ${filter.to}`;\n return \"\";\n }\n return \"\";\n}\n\nfunction chipExtraCount(filter) {\n if (Array.isArray(filter)) return Math.max(0, filter.length - 1);\n return 0;\n}\n\nfunction chipExtraValues(filter) {\n if (Array.isArray(filter)) return filter.slice(1).map(String).join(\", \");\n return \"\";\n}\n\nfunction ExtraValuesBadge({ count, values }) {\n const [hover, setHover] = useState(false);\n return (\n <span\n onMouseEnter={() => setHover(true)}\n onMouseLeave={() => setHover(false)}\n style={{\n position: \"relative\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: 22,\n minWidth: 22,\n padding: \"0 6px\",\n background: \"#D8D8D8\",\n color: \"#0B0B0B\",\n borderRadius: 14,\n fontSize: 12,\n fontWeight: 500,\n lineHeight: 1,\n cursor: \"pointer\",\n }}\n >\n +{count}\n {hover && (\n <span\n role=\"tooltip\"\n style={{\n position: \"absolute\",\n bottom: \"calc(100% + 6px)\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n background: \"#1E2125\",\n color: \"#FFFFFF\",\n fontFamily: \"var(--font-sans)\",\n fontSize: 12,\n fontWeight: 400,\n lineHeight: \"20px\",\n padding: \"6px 10px\",\n borderRadius: 8,\n whiteSpace: \"nowrap\",\n pointerEvents: \"none\",\n zIndex: 100,\n boxShadow: \"0 6px 16px rgba(11, 11, 11, 0.18)\",\n }}\n >\n {values}\n </span>\n )}\n </span>\n );\n}\n\nfunction RangeInputs({ leftLabel, rightLabel, leftValue, rightValue, onLeftChange, onRightChange, type = \"number\", placeholderLeft = \"Min\", placeholderRight = \"Max\" }) {\n const fieldStyle = {\n width: \"100%\",\n height: 32,\n borderRadius: 8,\n border: \"1px solid #D9D9D9\",\n background: \"#FFFFFF\",\n padding: \"0 10px\",\n fontFamily: \"var(--font-sans)\",\n fontSize: 14,\n color: \"#0B0B0B\",\n outline: \"none\",\n boxSizing: \"border-box\",\n };\n const labelStyle = { fontSize: 12, color: \"#676767\", marginBottom: 4, fontFamily: \"var(--font-sans)\" };\n return (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 10 }}>\n <div style={{ display: \"flex\", flexDirection: \"column\" }}>\n <span style={labelStyle}>{leftLabel}</span>\n <input\n type={type}\n value={leftValue}\n onChange={(e) => onLeftChange(e.target.value)}\n placeholder={placeholderLeft}\n style={fieldStyle}\n />\n </div>\n <div style={{ display: \"flex\", flexDirection: \"column\" }}>\n <span style={labelStyle}>{rightLabel}</span>\n <input\n type={type}\n value={rightValue}\n onChange={(e) => onRightChange(e.target.value)}\n placeholder={placeholderRight}\n style={fieldStyle}\n />\n </div>\n </div>\n );\n}\n\nconst DURATION_PRESETS = [\n { id: \"0-60\", label: \"0 to 60 Sec\", minSec: 0, maxSec: 60 },\n { id: \"60-120\", label: \"1m to 2 m\", minSec: 60, maxSec: 120 },\n { id: \"120-180\", label: \"2m to 3 m\", minSec: 120, maxSec: 180 },\n { id: \"180-240\", label: \"3m to 4m\", minSec: 180, maxSec: 240 },\n { id: \"240-300\", label: \"4m to 5m\", minSec: 240, maxSec: 300 },\n { id: \"300+\", label: \"5 mins and above\", minSec: 300, maxSec: null },\n];\n\nfunction mmssToSec(str) {\n if (str == null || str === \"\") return null;\n const m = String(str).trim().match(/^(\\d{1,3}):(\\d{2})$/);\n if (m) return Number(m[1]) * 60 + Number(m[2]);\n // Fallback: plain number = seconds.\n const n = Number(str);\n return Number.isFinite(n) ? n : null;\n}\n\nfunction secToMmss(sec) {\n if (sec == null || sec === \"\") return \"\";\n const total = Math.max(0, Math.round(Number(sec)));\n const m = Math.floor(total / 60);\n const s = total % 60;\n return `${String(m).padStart(2, \"0\")}:${String(s).padStart(2, \"0\")}`;\n}\n\n// Shared \"title\" used at the top of every numeric/range filter so all of\n// them render the column label at the same size and weight.\nfunction FilterTitle({ children }) {\n return (\n <div\n style={{\n fontSize: 14,\n fontWeight: 600,\n color: \"#0B0B0B\",\n lineHeight: \"20px\",\n padding: \"4px 0 2px\",\n fontFamily: \"var(--font-sans)\",\n }}\n >\n {children}\n </div>\n );\n}\n\n// Shared Min/Max input pair used by every numeric/range filter (number,\n// score, duration). One render path → identical visuals everywhere.\n// `unit` (e.g. \"sec\") is shown as a small hint below the row instead of\n// being appended to each label — that kept long labels like \"Min From (sec)\"\n// from wrapping and breaking vertical alignment with \"Max (sec)\".\nfunction MinMaxInputs({\n minValue,\n maxValue,\n onMinChange,\n onMaxChange,\n inputType = \"number\",\n inputMode = \"decimal\",\n step,\n placeholder = \"0.0\",\n unit,\n}) {\n const fieldStyle = {\n width: \"100%\",\n height: 30,\n border: \"1px solid #ACADAD\",\n borderRadius: 4,\n padding: \"6px 10px\",\n fontSize: 13,\n color: \"#0B0B0B\",\n fontFamily: \"var(--font-sans)\",\n outline: \"none\",\n boxSizing: \"border-box\",\n };\n return (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 4 }}>\n <div style={{ display: \"flex\", alignItems: \"flex-end\", gap: 8 }}>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 6, flex: 1, minWidth: 0 }}>\n <span style={{ fontSize: 12, color: \"#2E3236\", fontFamily: \"var(--font-sans)\" }}>Min From</span>\n <input\n type={inputType}\n inputMode={inputMode}\n step={step}\n placeholder={placeholder}\n value={minValue}\n onChange={(e) => onMinChange(e.target.value)}\n style={fieldStyle}\n />\n </div>\n <span style={{ fontSize: 12, fontWeight: 600, color: \"#323232\", paddingBottom: 8, fontFamily: \"var(--font-sans)\" }}>to</span>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 6, flex: 1, minWidth: 0 }}>\n <span style={{ fontSize: 12, color: \"#2E3236\", fontFamily: \"var(--font-sans)\" }}>Max</span>\n <input\n type={inputType}\n inputMode={inputMode}\n step={step}\n placeholder={placeholder}\n value={maxValue}\n onChange={(e) => onMaxChange(e.target.value)}\n style={fieldStyle}\n />\n </div>\n </div>\n {unit && (\n <span\n style={{\n fontSize: 11,\n color: \"#676767\",\n fontFamily: \"var(--font-sans)\",\n }}\n >\n Input values in {unit === \"sec\" ? \"seconds\" : unit}\n </span>\n )}\n </div>\n );\n}\n\nfunction FilterValuePicker({ column, columnId, filterType = \"text\", position, popoverRef, distinctValues, initialValue, onApply, onCancel }) {\n const isText = filterType === \"text\";\n const isNumber = filterType === \"number\";\n const isDate = filterType === \"date\";\n const isDuration = filterType === \"duration\";\n const isScore = filterType === \"score\";\n\n // Score columns can hold either 1–5 ratings (compass) or arbitrary numbers\n // (e.g. 78.3% scores). Only render the 1–5 preset checkboxes when the\n // distinct values actually sit in [0, 5]; otherwise fall back to a\n // Min/Max-only layout (same UI as the generic numeric filter).\n const scoreInRange = useMemo(() => {\n if (!isScore || !Array.isArray(distinctValues) || distinctValues.length === 0) return false;\n let min = Infinity;\n let max = -Infinity;\n for (const v of distinctValues) {\n const n = parseNumberLike(v);\n if (!Number.isFinite(n)) continue;\n if (n < min) min = n;\n if (n > max) max = n;\n }\n return Number.isFinite(min) && Number.isFinite(max) && min >= 0 && max <= 5;\n }, [isScore, distinctValues]);\n\n // ── State per filterType ────────────────────────────────────────────\n const [staged, setStaged] = useState(() =>\n isText ? new Set(Array.isArray(initialValue) ? initialValue : []) : new Set()\n );\n const [query, setQuery] = useState(\"\");\n const [rangeMin, setRangeMin] = useState(() => (isNumber && initialValue?.type === \"range\" && initialValue.min != null ? initialValue.min : \"\"));\n const [rangeMax, setRangeMax] = useState(() => (isNumber && initialValue?.type === \"range\" && initialValue.max != null ? initialValue.max : \"\"));\n const [durPresets, setDurPresets] = useState(new Set());\n const [durCustomMin, setDurCustomMin] = useState(() =>\n isDuration && initialValue?.type === \"durationRange\" && initialValue.minSec != null && initialValue.minSec !== \"\"\n ? String(initialValue.minSec)\n : \"\"\n );\n const [durCustomMax, setDurCustomMax] = useState(() =>\n isDuration && initialValue?.type === \"durationRange\" && initialValue.maxSec != null && initialValue.maxSec !== \"\"\n ? String(initialValue.maxSec)\n : \"\"\n );\n const [scorePresets, setScorePresets] = useState(() =>\n isScore && initialValue?.type === \"scoreRange\" && Array.isArray(initialValue.values)\n ? new Set(initialValue.values)\n : new Set()\n );\n const [scoreCustomMin, setScoreCustomMin] = useState(() =>\n isScore && initialValue?.type === \"scoreRange\" && initialValue.min != null && initialValue.min !== \"\"\n ? String(initialValue.min)\n : \"\"\n );\n const [scoreCustomMax, setScoreCustomMax] = useState(() =>\n isScore && initialValue?.type === \"scoreRange\" && initialValue.max != null && initialValue.max !== \"\"\n ? String(initialValue.max)\n : \"\"\n );\n const [dateFrom, setDateFrom] = useState(() => (isDate && initialValue?.type === \"dateRange\" ? initialValue.from || \"\" : \"\"));\n const [dateTo, setDateTo] = useState(() => (isDate && initialValue?.type === \"dateRange\" ? initialValue.to || \"\" : \"\"));\n\n useEffect(() => {\n if (isText) setStaged(new Set(Array.isArray(initialValue) ? initialValue : []));\n }, [columnId, isText]);\n\n const filteredValues = useMemo(() => {\n const q = query.trim().toLowerCase();\n if (!q) return distinctValues;\n return distinctValues.filter((v) => String(v).toLowerCase().includes(q));\n }, [distinctValues, query]);\n\n const toggle = (value) => {\n setStaged((prev) => {\n const next = new Set(prev);\n if (next.has(value)) next.delete(value); else next.add(value);\n return next;\n });\n };\n\n const reset = () => {\n if (isText) setStaged(new Set());\n if (isNumber) { setRangeMin(\"\"); setRangeMax(\"\"); }\n if (isDuration) { setDurPresets(new Set()); setDurCustomMin(\"\"); setDurCustomMax(\"\"); }\n if (isScore) { setScorePresets(new Set()); setScoreCustomMin(\"\"); setScoreCustomMax(\"\"); }\n if (isDate) { setDateFrom(\"\"); setDateTo(\"\"); }\n setQuery(\"\");\n };\n\n const toggleDurPreset = (id) => {\n setDurPresets((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id); else next.add(id);\n return next;\n });\n };\n\n const toggleScorePreset = (n) => {\n setScorePresets((prev) => {\n const next = new Set(prev);\n if (next.has(n)) next.delete(n); else next.add(n);\n return next;\n });\n };\n\n const apply = () => {\n if (isText) return onApply(Array.from(staged));\n if (isNumber) return onApply({ type: \"range\", min: rangeMin === \"\" ? \"\" : Number(rangeMin), max: rangeMax === \"\" ? \"\" : Number(rangeMax) });\n if (isDuration) {\n // Custom range overrides presets when filled. Otherwise the union of\n // selected preset buckets is sent as a single [minSec, maxSec] range.\n const customMinSec = mmssToSec(durCustomMin);\n const customMaxSec = mmssToSec(durCustomMax);\n const hasCustom = customMinSec != null || customMaxSec != null;\n let minSec = \"\";\n let maxSec = \"\";\n if (hasCustom) {\n minSec = customMinSec != null ? customMinSec : \"\";\n maxSec = customMaxSec != null ? customMaxSec : \"\";\n } else if (durPresets.size > 0) {\n const selected = DURATION_PRESETS.filter((p) => durPresets.has(p.id));\n minSec = Math.min(...selected.map((p) => p.minSec));\n const openEnded = selected.some((p) => p.maxSec == null);\n maxSec = openEnded ? \"\" : Math.max(...selected.map((p) => p.maxSec));\n }\n return onApply({ type: \"durationRange\", minSec, maxSec });\n }\n if (isScore) {\n // Custom range overrides preset checkboxes when filled. Otherwise the\n // selected preset integers are sent as a discrete `values` array, which\n // matches rows where Math.floor(score) is in the set.\n const customMinNum = scoreCustomMin === \"\" ? null : Number(scoreCustomMin);\n const customMaxNum = scoreCustomMax === \"\" ? null : Number(scoreCustomMax);\n const hasCustom = customMinNum != null || customMaxNum != null;\n if (hasCustom) {\n return onApply({\n type: \"scoreRange\",\n values: [],\n min: customMinNum != null && Number.isFinite(customMinNum) ? customMinNum : \"\",\n max: customMaxNum != null && Number.isFinite(customMaxNum) ? customMaxNum : \"\",\n });\n }\n return onApply({\n type: \"scoreRange\",\n values: Array.from(scorePresets).sort((a, b) => a - b),\n min: \"\",\n max: \"\",\n });\n }\n if (isDate) return onApply({ type: \"dateRange\", from: dateFrom, to: dateTo });\n };\n\n return (\n <div\n ref={popoverRef}\n role=\"dialog\"\n aria-label={`Filter ${column.label || columnId}`}\n style={{\n position: \"fixed\",\n top: position.top,\n left: position.left,\n zIndex: 50,\n width: isText ? 240 : 220,\n background: \"#FFFFFF\",\n border: \"1px solid #E6E6E6\",\n borderRadius: 10,\n padding: 12,\n display: \"flex\",\n flexDirection: \"column\",\n gap: 10,\n boxShadow: \"0 8px 24px rgba(11, 11, 11, 0.10)\",\n fontFamily: \"var(--font-sans)\",\n }}\n >\n {isText && (\n <>\n <div\n style={{\n background: \"#D8D8D8\",\n height: 32,\n borderRadius: 10,\n padding: 1,\n display: \"flex\",\n alignItems: \"center\",\n }}\n >\n <div\n style={{\n background: \"#FFFFFF\",\n flex: 1,\n height: 30,\n borderRadius: 10,\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"0 8px\",\n }}\n >\n <Search size={16} color=\"#989898\" strokeWidth={2} />\n <input\n autoFocus\n type=\"text\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder=\"Search\"\n style={{\n flex: 1,\n border: \"none\",\n outline: \"none\",\n background: \"transparent\",\n fontSize: 14,\n color: \"#0B0B0B\",\n minWidth: 0,\n fontFamily: \"var(--font-sans)\",\n }}\n />\n </div>\n </div>\n\n <div style={{ maxHeight: 220, overflowY: \"auto\", display: \"flex\", flexDirection: \"column\", gap: 4 }}>\n {filteredValues.length === 0 ? (\n <div style={{ fontSize: 13, color: \"#676767\", padding: \"8px 4px\", textAlign: \"center\" }}>\n No values\n </div>\n ) : (\n filteredValues.map((value) => {\n const checked = staged.has(value);\n return (\n <label\n key={value}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 12,\n padding: \"6px 4px\",\n cursor: \"pointer\",\n borderRadius: 6,\n }}\n >\n <span\n style={{\n width: 20,\n height: 20,\n borderRadius: 4,\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: checked ? \"#0B0B0B\" : \"#FFFFFF\",\n border: `1px solid ${checked ? \"#0B0B0B\" : \"#676767\"}`,\n flexShrink: 0,\n }}\n >\n {checked && <Check size={14} color=\"#FFFFFF\" strokeWidth={3} />}\n </span>\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={() => toggle(value)}\n style={{ position: \"absolute\", opacity: 0, pointerEvents: \"none\" }}\n tabIndex={-1}\n />\n <span\n onClick={(e) => { e.preventDefault(); toggle(value); }}\n style={{\n fontSize: 14,\n lineHeight: \"20px\",\n color: \"#0B0B0B\",\n flex: 1,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {value}\n </span>\n </label>\n );\n })\n )}\n </div>\n </>\n )}\n\n {isNumber && (\n <>\n <FilterTitle>{column.label || \"Filter\"}</FilterTitle>\n <MinMaxInputs\n minValue={rangeMin}\n maxValue={rangeMax}\n onMinChange={setRangeMin}\n onMaxChange={setRangeMax}\n />\n </>\n )}\n\n {isDuration && (\n <>\n {/* Title — compact, shared with the other range filters. */}\n <FilterTitle>{column.label || \"Duration\"}</FilterTitle>\n\n {/* Preset buckets — opt-in. The column must set\n `filterShowPresets: true` to show the bucket checkboxes. By\n default duration columns render just title + MM:SS Min/Max,\n same shape as the number filter. Mirrors the score-filter\n behaviour above for consistency. */}\n {column.filterShowPresets === true && (\n <>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 12 }}>\n {DURATION_PRESETS.map((preset) => {\n const checked = durPresets.has(preset.id);\n return (\n <div\n key={preset.id}\n role=\"checkbox\"\n aria-checked={checked}\n tabIndex={0}\n onClick={() => toggleDurPreset(preset.id)}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n toggleDurPreset(preset.id);\n }\n }}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 12,\n cursor: \"pointer\",\n userSelect: \"none\",\n }}\n >\n <span\n style={{\n width: 20,\n height: 20,\n borderRadius: 4,\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: checked ? \"#0B0B0B\" : \"#FFFFFF\",\n border: `1px solid ${checked ? \"#0B0B0B\" : \"#676767\"}`,\n flexShrink: 0,\n }}\n >\n {checked && <Check size={14} color=\"#FFFFFF\" strokeWidth={3} />}\n </span>\n <span\n style={{\n fontSize: 14,\n lineHeight: \"20px\",\n color: \"#0B0B0B\",\n fontFamily: \"var(--font-sans)\",\n }}\n >\n {preset.label}\n </span>\n </div>\n );\n })}\n </div>\n\n {/* Divider above Custom Range — only when presets render above. */}\n <div style={{ height: 1, background: \"#D9D9D9\", margin: \"0 -12px\" }} />\n\n {/* Custom Range sub-header — redundant when there are no presets. */}\n <div\n style={{\n fontSize: 14,\n fontWeight: 500,\n color: \"#0B0B0B\",\n lineHeight: \"20px\",\n padding: \"4px 0\",\n fontFamily: \"var(--font-sans)\",\n }}\n >\n Custom Range\n </div>\n </>\n )}\n <MinMaxInputs\n minValue={durCustomMin}\n maxValue={durCustomMax}\n onMinChange={setDurCustomMin}\n onMaxChange={setDurCustomMax}\n inputType=\"number\"\n inputMode=\"numeric\"\n placeholder=\"0\"\n unit=\"sec\"\n />\n </>\n )}\n\n {isScore && (\n <>\n {/* Title — driven by column.label so the same picker can serve\n \"Compass Score\", \"Score\", etc. Falls back to \"Score\". */}\n <FilterTitle>{column.label || \"Score\"}</FilterTitle>\n\n {/* Preset values 1..5 — opt-in. The column must set\n `filterShowPresets: true` AND its data must fit in [0, 5]. By\n default the score filter renders just title + Min/Max so it\n works for compass-style decimal scores (where bucketing 1..5\n would lose the precision in 4.06 vs 4.10). */}\n {scoreInRange && column.filterShowPresets === true && (\n <>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 12 }}>\n {[1, 2, 3, 4, 5].map((n) => {\n const checked = scorePresets.has(n);\n return (\n <div\n key={n}\n role=\"checkbox\"\n aria-checked={checked}\n tabIndex={0}\n onClick={() => toggleScorePreset(n)}\n onKeyDown={(e) => {\n if (e.key === \" \" || e.key === \"Enter\") {\n e.preventDefault();\n toggleScorePreset(n);\n }\n }}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 12,\n cursor: \"pointer\",\n userSelect: \"none\",\n }}\n >\n <span\n style={{\n width: 20,\n height: 20,\n borderRadius: 4,\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: checked ? \"#0B0B0B\" : \"#FFFFFF\",\n border: `1px solid ${checked ? \"#0B0B0B\" : \"#676767\"}`,\n flexShrink: 0,\n }}\n >\n {checked && <Check size={14} color=\"#FFFFFF\" strokeWidth={3} />}\n </span>\n <span\n style={{\n fontSize: 14,\n lineHeight: \"20px\",\n color: \"#0B0B0B\",\n fontFamily: \"var(--font-sans)\",\n }}\n >\n {n}\n </span>\n </div>\n );\n })}\n </div>\n\n {/* Divider — only when presets are shown above the custom range */}\n <div style={{ height: 1, background: \"#D9D9D9\", margin: \"0 -12px\" }} />\n </>\n )}\n\n {/* Range header — labelled \"Custom Range\" only when the presets\n section sits above it; otherwise the picker is just a Min/Max\n filter and the section header would be redundant. */}\n {scoreInRange && column.filterShowPresets === true && (\n <div\n style={{\n fontSize: 14,\n fontWeight: 500,\n color: \"#0B0B0B\",\n lineHeight: \"20px\",\n padding: \"4px 0\",\n fontFamily: \"var(--font-sans)\",\n }}\n >\n Custom Range\n </div>\n )}\n <MinMaxInputs\n minValue={scoreCustomMin}\n maxValue={scoreCustomMax}\n onMinChange={setScoreCustomMin}\n onMaxChange={setScoreCustomMax}\n step=\"0.1\"\n />\n </>\n )}\n\n {isDate && (\n <RangeInputs\n leftLabel=\"From\"\n rightLabel=\"To\"\n leftValue={dateFrom}\n rightValue={dateTo}\n onLeftChange={setDateFrom}\n onRightChange={setDateTo}\n type=\"date\"\n placeholderLeft=\"\"\n placeholderRight=\"\"\n />\n )}\n\n <div style={{ height: 1, background: \"#D9D9D9\", margin: \"0 -12px\" }} />\n <div style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"space-between\" }}>\n <button\n type=\"button\"\n onClick={reset}\n style={{\n background: \"transparent\",\n border: \"none\",\n padding: 0,\n cursor: \"pointer\",\n fontSize: 14,\n fontWeight: 500,\n color: \"#323232\",\n fontFamily: \"var(--font-sans)\",\n }}\n >\n {(isDuration && column.filterShowPresets === true) || (isScore && scoreInRange && column.filterShowPresets === true) ? \"View All\" : \"Reset\"}\n </button>\n <button\n type=\"button\"\n onClick={apply}\n style={{\n background: \"#0B0B0B\",\n color: \"#FFFFFF\",\n border: \"none\",\n borderRadius: 10,\n height: 28,\n padding: \"0 14px\",\n fontSize: 14,\n fontWeight: 500,\n cursor: \"pointer\",\n fontFamily: \"var(--font-sans)\",\n }}\n >\n Apply\n </button>\n </div>\n </div>\n );\n}\nfunction ResizeColumnsIcon({ size = 10, color = \"currentColor\" }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n style={{ display: \"block\" }}\n aria-hidden=\"true\"\n >\n <path d=\"M3.5 8H12.5\" stroke={color} strokeWidth=\"1.4\" strokeLinecap=\"round\" />\n <path d=\"M5 6.5L3.5 8L5 9.5\" stroke={color} strokeWidth=\"1.4\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n <path d=\"M11 6.5L12.5 8L11 9.5\" stroke={color} strokeWidth=\"1.4\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n <path d=\"M6.8 3V13\" stroke={color} strokeWidth=\"1.2\" strokeLinecap=\"round\" />\n <path d=\"M9.2 3V13\" stroke={color} strokeWidth=\"1.2\" strokeLinecap=\"round\" />\n </svg>\n );\n}\n// TODO: replace with framework-agnostic context\nconst useUserContext = () => ({ userData: { email: \"anonymous\" } });\n// TODO: replace with framework-agnostic image\nconst Image = (props) => <img {...props} />;\nimport DataTableFilters from \"./DataTableFilters\";\n// TODO: replace with framework-agnostic tooltip\nfunction HoverBalloon({\n children,\n content,\n direction = \"top\",\n align = \"center\",\n styling,\n indicatorColor,\n}) {\n const tooltipText =\n typeof content === \"string\" ? content : content != null ? String(content) : \"\";\n const resolvedArrowColor =\n typeof indicatorColor === \"string\" &&\n (indicatorColor.startsWith(\"#\") ||\n indicatorColor.startsWith(\"rgb\") ||\n indicatorColor.startsWith(\"hsl\") ||\n indicatorColor.startsWith(\"var(\"))\n ? indicatorColor\n : \"var(--Grey-Strong, #2E3236)\";\n const [isVisible, setIsVisible] = useState(false);\n const [mounted, setMounted] = useState(false);\n const [position, setPosition] = useState({ top: 0, left: 0, arrowLeft: 0, placement: \"top\" });\n const triggerRef = useRef(null);\n const tooltipRef = useRef(null);\n\n if (!tooltipText) return children;\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n const updatePosition = useCallback(() => {\n if (!triggerRef.current || !tooltipRef.current || typeof window === \"undefined\") return;\n\n const triggerRect = triggerRef.current.getBoundingClientRect();\n const tooltipRect = tooltipRef.current.getBoundingClientRect();\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n\n const viewportPadding = 8;\n const gap = 10;\n const tooltipWidth = tooltipRect.width;\n const tooltipHeight = tooltipRect.height;\n\n const spaceAbove = triggerRect.top;\n const spaceBelow = viewportHeight - triggerRect.bottom;\n const preferredPlacement = direction === \"bottom\" ? \"bottom\" : \"top\";\n\n let placement = preferredPlacement;\n if (preferredPlacement === \"top\" && spaceAbove < tooltipHeight + gap + viewportPadding && spaceBelow > spaceAbove) {\n placement = \"bottom\";\n } else if (preferredPlacement === \"bottom\" && spaceBelow < tooltipHeight + gap + viewportPadding && spaceAbove > spaceBelow) {\n placement = \"top\";\n }\n\n let anchorX = triggerRect.left + triggerRect.width / 2;\n if (align === \"start\") anchorX = triggerRect.left;\n if (align === \"end\") anchorX = triggerRect.right;\n\n let top = placement === \"top\"\n ? triggerRect.top - tooltipHeight - gap\n : triggerRect.bottom + gap;\n let left = align === \"start\"\n ? anchorX\n : align === \"end\"\n ? anchorX - tooltipWidth\n : anchorX - tooltipWidth / 2;\n\n top = Math.max(viewportPadding, Math.min(top, viewportHeight - tooltipHeight - viewportPadding));\n left = Math.max(viewportPadding, Math.min(left, viewportWidth - tooltipWidth - viewportPadding));\n\n const arrowLeft = Math.max(10, Math.min(anchorX - left, tooltipWidth - 10));\n setPosition({ top, left, arrowLeft, placement });\n }, [align, direction]);\n\n useEffect(() => {\n if (!isVisible || !mounted) return;\n\n updatePosition();\n\n const handleReposition = () => updatePosition();\n window.addEventListener(\"resize\", handleReposition);\n window.addEventListener(\"scroll\", handleReposition, true);\n\n return () => {\n window.removeEventListener(\"resize\", handleReposition);\n window.removeEventListener(\"scroll\", handleReposition, true);\n };\n }, [isVisible, mounted, updatePosition]);\n\n return (\n <span\n ref={triggerRef}\n style={{ display: \"block\", width: \"100%\" }}\n onMouseEnter={() => setIsVisible(true)}\n onMouseLeave={() => setIsVisible(false)}\n >\n {children}\n {isVisible && mounted && createPortal(\n <span\n ref={tooltipRef}\n style={{\n position: \"fixed\",\n top: `${position.top}px`,\n left: `${position.left}px`,\n background: \"var(--Grey-Strong, #2E3236)\",\n color: \"var(--Grey-White, #FFF)\",\n fontSize: \"12px\",\n lineHeight: 1.3,\n fontWeight: 500,\n padding: \"8px 10px\",\n borderRadius: \"6px\",\n whiteSpace: \"normal\",\n maxWidth: \"320px\",\n width: \"max-content\",\n boxShadow: \"0 6px 18px rgba(0, 0, 0, 0.2)\",\n zIndex: 99999,\n pointerEvents: \"none\",\n ...(typeof styling === \"object\" ? styling : {}),\n }}\n >\n {tooltipText}\n <span\n style={{\n position: \"absolute\",\n left: `${position.arrowLeft}px`,\n transform: \"translateX(-50%)\",\n width: 0,\n height: 0,\n borderLeft: \"6px solid transparent\",\n borderRight: \"6px solid transparent\",\n ...(position.placement === \"top\"\n ? {\n top: \"100%\",\n borderTop: `7px solid ${resolvedArrowColor}`,\n }\n : {\n bottom: \"100%\",\n borderBottom: `7px solid ${resolvedArrowColor}`,\n }),\n }}\n />\n </span>,\n document.body\n )}\n </span>\n );\n}\n\n/**\n * DataTable Component\n * Interactive table with column reordering, filtering, sorting, sticky headers, and pagination\n * Follows \"No Judgment\" principle - scores and counts displayed uniformly\n */\nexport default function DataTable2({\n data = [], \n columns = [], \n initialPageSize = 10, \n onRowClick,\n // Server-side pagination props (optional)\n totalCount = null, // Total count from server (null = use client-side pagination)\n page: controlledPage = null, // Controlled page (null = use internal state)\n pageSize: controlledPageSize = null, // Controlled pageSize (null = use internal state)\n onPageChange = null, // Callback for page changes (null = use internal state)\n onPageSizeChange = null, // Callback for pageSize changes (null = use internal state)\n onFilterChange = null, // Callback for filter changes (null = use client-side filtering)\n columnFilters = null, // Controlled inline header filters (columnId -> value). Used to rehydrate inputs in server-side filtering mode.\n // Optional callback to surface column limit errors to host app\n onMaxColumnsError = null,\n // Server-side sorting props (optional)\n onSort = null, // Callback for sort changes (null = use client-side sorting)\n sortFields = [], // Array of [field, direction] tuples from parent (null = use internal state)\n tableId = null, // Optional unique identifier for localStorage persistence (e.g., \"history\", \"agents\")\n isLoading = false, // Loading state to show overlay inside table\n // Filter props (optional)\n filtersConfig = null, // Top toolbar filter config (chips/date/export). Note: this is different from `columnFilters` for inline header inputs.\n // Column resize (optional) — min/max in px; columns may override with column.minWidth / column.maxWidth\n columnResizeMinWidth = 100,\n columnResizeMaxWidth = 280,\n // Fires whenever the user-visible column set changes. Useful for hosts that\n // want to scope a CSV export, etc., to whatever the user has selected.\n // Receives an array of column ids (excluding the action column).\n onVisibleColumnsChange = null,\n}) {\n // Get user email for user-specific storage\n const { userData } = useUserContext();\n const userId = userData?.email || 'anonymous';\n\n // Component to show tooltip only when text is actually truncated\n const TruncatedCell = React.memo(({ children, content, className = \"\" }) => {\n const textRef = useRef(null);\n const [isTruncated, setIsTruncated] = useState(false);\n\n useEffect(() => {\n const checkTruncation = () => {\n if (textRef.current) {\n const isOverflowing = textRef.current.scrollWidth > textRef.current.clientWidth;\n setIsTruncated(isOverflowing);\n }\n };\n\n checkTruncation();\n const timeoutId = setTimeout(checkTruncation, 0);\n\n window.addEventListener('resize', checkTruncation);\n return () => {\n clearTimeout(timeoutId);\n window.removeEventListener('resize', checkTruncation);\n };\n }, [children, content]);\n\n const textElement = (\n <span className={`truncate block ${className}`} ref={textRef}>\n {children}\n </span>\n );\n\n if (isTruncated && content) {\n return (\n <HoverBalloon\n content={content}\n styling=\"bg-green-2 text-gray-900 px-3 py-2 text-sm rounded-lg shadow-md border border-gray-300 max-w-xs whitespace-normal\"\n indicatorColor=\"bg-green-2\"\n direction=\"top\"\n >\n {textElement}\n </HoverBalloon>\n );\n }\n\n return textElement;\n });\n TruncatedCell.displayName = 'TruncatedCell';\n\n // Use controlled pagination if props provided, otherwise use internal state\n const isServerSidePagination = totalCount !== null && onPageChange !== null;\n // Use server-side filtering if onFilterChange is provided\n const isServerSideFiltering = onFilterChange !== null;\n // Use server-side sorting if onSort is provided\n const isServerSideSorting = onSort !== null;\n const [internalPage, setInternalPage] = useState(1);\n const [internalPageSize, setInternalPageSize] = useState(initialPageSize);\n \n const page = controlledPage !== null ? controlledPage : internalPage;\n const pageSize = controlledPageSize !== null ? controlledPageSize : internalPageSize;\n \n const setPage = (newPage) => {\n if (onPageChange) {\n onPageChange(newPage);\n } else {\n setInternalPage(newPage);\n }\n };\n \n const setPageSize = (newSize) => {\n if (onPageSizeChange) {\n onPageSizeChange(newSize);\n } else {\n setInternalPageSize(newSize);\n }\n };\n \n const MAX_COLUMNS = 50;\n \n const ACTION_COLUMN_ID = 'action';\n\n // Refs for localStorage persistence\n const userHasManuallyChangedColumns = useRef(false);\n \n // Generate unique storage key for this table (includes userId)\n const storageKey = useMemo(() => {\n if (tableId) {\n return `dataTable_columns_${tableId}:${userId}`;\n }\n // Fallback: use column keys to create unique identifier\n const columnKeys = columns.map(col => (col.id || col.key)).sort().join('_');\n return `dataTable_columns_${columnKeys}:${userId}`;\n }, [tableId, columns, userId]);\n \n const manualChangeFlagKey = useMemo(() => {\n if (tableId) {\n return `dataTable_manual_change_${tableId}:${userId}`;\n }\n return null;\n }, [tableId, userId]);\n\n // Load saved column visibility from localStorage\n const loadSavedColumns = useCallback((key, cols) => {\n if (typeof window === 'undefined' || !key || !cols || cols.length === 0) return null;\n try {\n const saved = localStorage.getItem(key);\n if (saved) {\n const savedColumns = JSON.parse(saved);\n // Validate that saved columns still exist in current columns\n const validColumns = savedColumns.filter(colId => \n cols.some(col => (col.id || col.key) === colId)\n );\n if (validColumns.length > 0) {\n return validColumns;\n }\n }\n } catch (error) {\n console.warn('Failed to load saved columns from localStorage:', error);\n }\n return null;\n }, []);\n \n // filters: { [columnId]: string[] } — array of selected values per column\n const [filters, setFilters] = useState({});\n // Free-text global search applied to all visible string-cells\n const [globalQuery, setGlobalQuery] = useState(\"\");\n // Which column header has its filter popover open (columnId or null)\n const [openFilterColumnId, setOpenFilterColumnId] = useState(null);\n const [filterPopoverPosition, setFilterPopoverPosition] = useState({ top: 0, left: 0 });\n const filterPopoverRef = useRef(null);\n const filterIconRefs = useRef({});\n // Internal sorting state (only used for client-side sorting)\n const [internalSortField, setInternalSortField] = useState(null);\n const [internalSortDirection, setInternalSortDirection] = useState(\"asc\");\n\n const setColumnFilter = useCallback((columnId, value) => {\n const active = isFilterActive(value);\n setFilters((prev) => {\n const next = { ...prev };\n if (!active) delete next[columnId];\n else next[columnId] = value;\n return next;\n });\n if (onPageChange) onPageChange(1); else setInternalPage(1);\n if (isServerSideFiltering && onFilterChange) {\n onFilterChange(\n active\n ? { ...filters, [columnId]: value }\n : Object.fromEntries(Object.entries(filters).filter(([k]) => k !== columnId))\n );\n }\n }, [filters, onFilterChange, isServerSideFiltering, onPageChange]);\n\n const clearAllFilters = useCallback(() => {\n setFilters({});\n setGlobalQuery(\"\");\n if (onPageChange) onPageChange(1); else setInternalPage(1);\n if (isServerSideFiltering && onFilterChange) onFilterChange({});\n }, [onFilterChange, isServerSideFiltering, onPageChange]);\n\n const getDistinctValuesForColumn = useCallback((columnId) => {\n if (!data || data.length === 0) return [];\n const seen = new Set();\n const out = [];\n for (const row of data) {\n const v = row[columnId];\n if (v === null || v === undefined) continue;\n const s = typeof v === \"object\" ? JSON.stringify(v) : String(v);\n if (!seen.has(s)) {\n seen.add(s);\n out.push(s);\n }\n }\n return out.sort((a, b) => a.localeCompare(b));\n }, [data]);\n\n const getColumnFilterType = useCallback((columnId) => {\n const col = columns.find((c) => getColumnId(c) === columnId);\n if (col && col.filterType) return col.filterType;\n return detectFilterType(getDistinctValuesForColumn(columnId));\n }, [columns, getDistinctValuesForColumn]);\n\n // Compute a viewport-safe `{top, left}` for the filter popover. Anchors to\n // the trigger's left edge by default; if that would overflow the right edge\n // of the viewport (rightmost columns like Strength / Compass Score / Avg\n // Call Duration), flips so the popover sits to the left of the trigger.\n //\n // The popover's declared `width` is 220 (240 for text) but `box-sizing` is\n // content-box and there's 12px of padding on each side, so the rendered\n // outer width is 244–264. Use 280 here as a conservative upper bound so the\n // flip kicks in before the popover starts clipping (under-estimating the\n // width was the cause of the rightmost-column overflow).\n const computeFilterPopoverPosition = useCallback((rect) => {\n const POPOVER_WIDTH = 280;\n const VIEWPORT_PAD = 8;\n const viewportWidth = typeof window !== \"undefined\" ? window.innerWidth : Infinity;\n let left = rect.left;\n if (left + POPOVER_WIDTH > viewportWidth - VIEWPORT_PAD) {\n // Align the popover's right edge with the trigger's right edge so it\n // opens leftward (rather than the trigger's left, which left a small\n // hairline gap and was visually mistaken for \"off-screen\").\n left = Math.max(VIEWPORT_PAD, rect.right - POPOVER_WIDTH);\n }\n return { top: rect.bottom + 6, left };\n }, []);\n\n const openFilterPopoverFor = useCallback((columnId, anchorEl) => {\n if (!anchorEl) {\n setOpenFilterColumnId(columnId);\n return;\n }\n const rect = anchorEl.getBoundingClientRect();\n setFilterPopoverPosition(computeFilterPopoverPosition(rect));\n setOpenFilterColumnId((prev) => (prev === columnId ? null : columnId));\n }, [computeFilterPopoverPosition]);\n\n // Outside click closes filter popover\n useEffect(() => {\n if (!openFilterColumnId) return;\n const onMouseDown = (e) => {\n if (filterPopoverRef.current && filterPopoverRef.current.contains(e.target)) return;\n const anchor = filterIconRefs.current[openFilterColumnId];\n if (anchor && anchor.contains(e.target)) return;\n setOpenFilterColumnId(null);\n };\n document.addEventListener(\"mousedown\", onMouseDown);\n return () => document.removeEventListener(\"mousedown\", onMouseDown);\n }, [openFilterColumnId]);\n\n // Keep the filter popover anchored to its column header on scroll/resize\n // (matches the Columns dropdown pattern). Without this, the popover stays at\n // the viewport position it was opened at while the trigger scrolls away.\n useEffect(() => {\n if (!openFilterColumnId) return;\n const updatePosition = () => {\n const anchor = filterIconRefs.current[openFilterColumnId];\n if (!anchor) return;\n const rect = anchor.getBoundingClientRect();\n setFilterPopoverPosition(computeFilterPopoverPosition(rect));\n };\n window.addEventListener(\"scroll\", updatePosition, true);\n window.addEventListener(\"resize\", updatePosition);\n return () => {\n window.removeEventListener(\"scroll\", updatePosition, true);\n window.removeEventListener(\"resize\", updatePosition);\n };\n }, [openFilterColumnId, computeFilterPopoverPosition]);\n\n // After the popover mounts, measure its actual rendered width and flip the\n // anchor to the right edge of the trigger if it would still overflow the\n // viewport. `computeFilterPopoverPosition` uses a conservative constant but\n // a custom-rendered column (longer header / wider picker variant) can grow\n // past that; this layout-effect closes the gap so the rightmost column\n // (Strength, Compass Score, etc.) always opens fully visible — flipping to\n // the left side of the trigger when needed.\n useLayoutEffect(() => {\n if (!openFilterColumnId) return;\n const popover = filterPopoverRef.current;\n const anchor = filterIconRefs.current[openFilterColumnId];\n if (!popover || !anchor) return;\n const popoverWidth = popover.offsetWidth;\n const rect = anchor.getBoundingClientRect();\n const VIEWPORT_PAD = 8;\n const viewportWidth = typeof window !== \"undefined\" ? window.innerWidth : Infinity;\n const wouldOverflow = rect.left + popoverWidth > viewportWidth - VIEWPORT_PAD;\n if (!wouldOverflow) return;\n const correctedLeft = Math.max(VIEWPORT_PAD, rect.right - popoverWidth);\n setFilterPopoverPosition((prev) => (prev.left === correctedLeft ? prev : { ...prev, left: correctedLeft }));\n }, [openFilterColumnId, filterPopoverPosition.top]);\n \n // Normalize inline filters by removing empty/null values.\n // Example usage (server-side mode):\n // <DataTable onFilterChange={handleFilterChange} columnFilters={dataTableFilters} />\n const normalizeColumnFilters = useCallback((incomingFilters) => {\n if (!incomingFilters || typeof incomingFilters !== \"object\") return {};\n return Object.fromEntries(\n Object.entries(incomingFilters).filter(([, value]) => {\n if (value === null || value === undefined) return false;\n if (typeof value === \"string\") return value.trim() !== \"\";\n return true; // allow numbers/booleans\n })\n );\n }, []);\n\n const areFiltersEqual = useCallback((a, b) => {\n const aKeys = Object.keys(a || {});\n const bKeys = Object.keys(b || {});\n if (aKeys.length !== bKeys.length) return false;\n return aKeys.every((key) => a[key] === b[key]);\n }, []);\n\n // Sync internal inline filter input UI from controlled prop in server-side mode.\n // This does not trigger onFilterChange and therefore does not create callback loops.\n useEffect(() => {\n if (!isServerSideFiltering || columnFilters === null) return;\n const normalizedFilters = normalizeColumnFilters(columnFilters);\n setFilters((prev) => (areFiltersEqual(prev, normalizedFilters) ? prev : normalizedFilters));\n }, [isServerSideFiltering, columnFilters, normalizeColumnFilters, areFiltersEqual]);\n \n // Get current sort state (from props if server-side, otherwise from internal state)\n // For server-side sorting, we need to map the sortField back to the column key\n // because History.js's handleSort maps some keys (e.g., \"evaluation.csat_score\" -> \"csat_score\")\n // but we need to compare against the original column key\n const getSortFieldForComparison = useCallback((sortFieldFromProps, columnId) => {\n // Reverse mapping: if sortField is \"csat_score\", it should match column \"evaluation.csat_score\"\n if (sortFieldFromProps === \"csat_score\" && columnId === \"evaluation.csat_score\") {\n return columnId;\n }\n // For other fields, use as-is (they should match)\n return sortFieldFromProps;\n }, []);\n \n const sortField = isServerSideSorting && sortFields.length > 0 ? sortFields[0][0] : internalSortField;\n const sortDirection = isServerSideSorting && sortFields.length > 0 ? sortFields[0][1] : internalSortDirection;\n // Support both 'id' and 'key' for column identifiers\n const [columnOrder, setColumnOrder] = useState(() => \n columns.map((col) => col.id || col.key)\n );\n const enforceActionPosition = useCallback((cols) => {\n if (!cols || cols.length === 0) return cols;\n\n // De-duplicate and enforce max column limit first\n let result = Array.from(new Set(cols));\n if (result.length > MAX_COLUMNS) {\n result = result.slice(0, MAX_COLUMNS);\n }\n\n const allColumnIds = columns.map((col) => col.id || col.key);\n const tableHasActionColumn = allColumnIds.includes(ACTION_COLUMN_ID);\n const hasAction = result.includes(ACTION_COLUMN_ID);\n\n // If the table defines an action column, always include it in the visible set,\n // counting toward the MAX_COLUMNS cap.\n if (!hasAction && tableHasActionColumn) {\n if (result.length >= MAX_COLUMNS) {\n // Replace the last non-action entry with the action column\n result = [...result.slice(0, MAX_COLUMNS - 1), ACTION_COLUMN_ID];\n } else {\n result = [...result, ACTION_COLUMN_ID];\n }\n }\n\n // Ensure the action column is always rendered last\n const withoutAction = result.filter((id) => id !== ACTION_COLUMN_ID);\n return [...withoutAction, ACTION_COLUMN_ID];\n }, [columns]);\n\n // Column selection state - load persisted columns if they exist, otherwise default to first 9\n const [visibleColumns, setVisibleColumns] = useState(() => {\n // Try to load persisted columns immediately on mount\n if (typeof window !== 'undefined' && tableId) {\n try {\n // Check if user has manually changed columns before\n const hasManualChange = localStorage.getItem(`dataTable_manual_change_${tableId}:${userId}`) === 'true';\n \n if (hasManualChange) {\n // User has manually changed columns, load persisted selection immediately\n const saved = localStorage.getItem(`dataTable_columns_${tableId}:${userId}`);\n if (saved) {\n const savedColumns = JSON.parse(saved);\n if (Array.isArray(savedColumns) && savedColumns.length > 0) {\n userHasManuallyChangedColumns.current = true;\n // Validate saved columns exist in current columns\n const validColumns = savedColumns.filter(colId => \n columns.some(col => (col.id || col.key) === colId)\n );\n if (validColumns.length > 0) {\n return validColumns.slice(0, MAX_COLUMNS);\n }\n }\n }\n }\n } catch (error) {\n console.warn('Failed to load saved columns from localStorage:', error);\n }\n }\n \n // If no persisted columns, default to first 9 columns\n const columnIds = columns.map((col) => col.id || col.key);\n const initial = columnIds.slice(0, MAX_COLUMNS);\n return enforceActionPosition(initial);\n });\n const [isColumnDropdownOpen, setIsColumnDropdownOpen] = useState(false);\n // Staged column selection — toggling/reordering inside the dropdown writes here.\n // Only Apply (or Reset) commits staged state to `visibleColumns` and the table.\n const [stagedVisibleColumns, setStagedVisibleColumns] = useState([]);\n const [columnDropdownPosition, setColumnDropdownPosition] = useState({ top: 0, left: 0, width: 0 });\n const [pendingSelection, setPendingSelection] = useState(new Set());\n const [pendingDeselection, setPendingDeselection] = useState(new Set());\n // Snapshot of the columns visible on first mount; used as the Reset target\n const initialVisibleColumnsRef = useRef(null);\n if (initialVisibleColumnsRef.current === null) {\n initialVisibleColumnsRef.current = [...visibleColumns];\n }\n const [draggedColumnIndex, setDraggedColumnIndex] = useState(null);\n const [dragOverColumnIndex, setDragOverColumnIndex] = useState(null);\n const columnDropdownRef = useRef(null);\n const columnDropdownMenuRef = useRef(null);\n const toastTimeoutRef = useRef(null);\n const [activeId, setActiveId] = useState(null);\n const [columnWidths, setColumnWidths] = useState({});\n const tableRef = useRef(null);\n const resizeStateRef = useRef(null);\n\n // Helper to get column identifier (id or key)\n const getColumnId = (col) => col.id || col.key;\n const toPixelWidth = useCallback((value) => {\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value === \"string\") {\n const trimmed = value.trim();\n if (trimmed.endsWith(\"px\")) {\n const parsed = parseFloat(trimmed);\n return Number.isFinite(parsed) ? parsed : null;\n }\n const parsed = parseFloat(trimmed);\n return Number.isFinite(parsed) && `${parsed}` === trimmed ? parsed : null;\n }\n return null;\n }, []);\n const getResolvedColumnWidth = useCallback((columnId, fallbackWidth) => {\n if (columnWidths[columnId] != null) return `${columnWidths[columnId]}px`;\n if (typeof fallbackWidth === \"number\") return `${fallbackWidth}px`;\n return fallbackWidth || \"auto\";\n }, [columnWidths]);\n\n const handleResizeMove = useCallback((event) => {\n if (!resizeStateRef.current) return;\n const { columnId, startX, startWidth, minWidth, maxWidth } = resizeStateRef.current;\n const delta = event.clientX - startX;\n const nextWidth = Math.round(startWidth + delta);\n const clamped = Math.min(maxWidth, Math.max(minWidth, nextWidth));\n setColumnWidths((prev) => ({ ...prev, [columnId]: clamped }));\n }, []);\n\n const stopResize = useCallback(() => {\n resizeStateRef.current = null;\n document.body.style.cursor = \"\";\n document.body.style.userSelect = \"\";\n document.removeEventListener(\"mousemove\", handleResizeMove);\n document.removeEventListener(\"mouseup\", stopResize);\n }, [handleResizeMove]);\n\n const startResize = useCallback((event, column, currentWidth) => {\n event.preventDefault();\n event.stopPropagation();\n const columnId = column.id || column.key;\n const colMin = toPixelWidth(column.minWidth) ?? columnResizeMinWidth;\n const colMax = toPixelWidth(column.maxWidth) ?? columnResizeMaxWidth;\n const minWidth = Math.min(colMin, colMax);\n const maxWidth = Math.max(colMin, colMax);\n const widthFromDom = event.currentTarget.closest(\"th\")?.getBoundingClientRect().width || 0;\n const parsed = toPixelWidth(currentWidth);\n const base =\n parsed != null\n ? parsed\n : Math.max(minWidth, Math.round(widthFromDom) || minWidth);\n const startWidth = Math.min(maxWidth, Math.max(minWidth, base));\n resizeStateRef.current = { columnId, startX: event.clientX, startWidth, minWidth, maxWidth };\n document.body.style.cursor = \"col-resize\";\n document.body.style.userSelect = \"none\";\n document.addEventListener(\"mousemove\", handleResizeMove);\n document.addEventListener(\"mouseup\", stopResize);\n }, [columnResizeMaxWidth, columnResizeMinWidth, handleResizeMove, stopResize, toPixelWidth]);\n\n useEffect(() => () => stopResize(), [stopResize]);\n\n const sensors = useSensors(\n useSensor(PointerSensor),\n useSensor(KeyboardSensor, {\n coordinateGetter: sortableKeyboardCoordinates,\n })\n );\n\n // Handle column drag end (table-level drag and drop)\n const handleDragEnd = (event) => {\n const { active, over } = event;\n if (over && active.id !== over.id) {\n if (active.id === ACTION_COLUMN_ID || over.id === ACTION_COLUMN_ID) {\n showMaxColumnsError(\"Cannot drop columns on the Action column\");\n setActiveId(null);\n return;\n }\n // Mark that user has manually changed columns\n userHasManuallyChangedColumns.current = true;\n \n // Update visibleColumns order when dragging in table header\n setVisibleColumns((prev) => {\n const oldIndex = prev.indexOf(active.id);\n const newIndex = prev.indexOf(over.id);\n if (oldIndex !== -1 && newIndex !== -1) {\n const reordered = arrayMove(prev, oldIndex, newIndex);\n const constrained = enforceActionPosition(reordered);\n // Save immediately after drag\n saveColumnsToStorage(constrained);\n return constrained;\n }\n return prev;\n });\n \n // Also update columnOrder for consistency\n setColumnOrder((items) => {\n const oldIndex = items.indexOf(active.id);\n const newIndex = items.indexOf(over.id);\n return arrayMove(items, oldIndex, newIndex);\n });\n }\n setActiveId(null);\n };\n\n // Handle column drag start\n const handleDragStart = (event) => {\n setActiveId(event.active.id);\n };\n\n // Filter data based on filter inputs - supports multiple keywords\n // For server-side filtering, skip client-side filtering (data is already filtered by server)\n const filteredData = useMemo(() => {\n if (isServerSideFiltering) {\n // Server-side filtering: data is already filtered, use as-is\n return data || [];\n }\n \n // Client-side filtering: filter the data locally\n if (!data || data.length === 0) return [];\n \n const globalQ = globalQuery.trim().toLowerCase();\n const filterEntries = Object.entries(filters).filter(([, f]) => isFilterActive(f));\n\n return data.filter((row) => {\n for (const [key, filter] of filterEntries) {\n const cellValue = row[key];\n if (cellValue === null || cellValue === undefined) return false;\n // Text-values filter (legacy / default)\n if (Array.isArray(filter)) {\n const cellStr = String(cellValue);\n if (!filter.some((v) => String(v) === cellStr)) return false;\n continue;\n }\n if (filter.type === \"range\") {\n const n = parseNumberLike(cellValue);\n if (isNaN(n)) return false;\n if (filter.min !== \"\" && filter.min != null && n < Number(filter.min)) return false;\n if (filter.max !== \"\" && filter.max != null && n > Number(filter.max)) return false;\n continue;\n }\n if (filter.type === \"durationRange\") {\n const sec = parseDurationToSeconds(cellValue);\n if (isNaN(sec)) return false;\n if (filter.minSec !== \"\" && filter.minSec != null && sec < Number(filter.minSec)) return false;\n if (filter.maxSec !== \"\" && filter.maxSec != null && sec > Number(filter.maxSec)) return false;\n continue;\n }\n if (filter.type === \"scoreRange\") {\n const n = parseNumberLike(cellValue);\n if (isNaN(n)) return false;\n // Discrete preset values: bucket the score by floor (so \"4\" matches\n // 4.00 .. 4.99). If any presets are selected, custom min/max is\n // ignored — the apply() in FilterValuePicker enforces this exclusivity.\n if (Array.isArray(filter.values) && filter.values.length > 0) {\n const bucket = Math.floor(n);\n if (!filter.values.includes(bucket)) return false;\n continue;\n }\n if (filter.min !== \"\" && filter.min != null && n < Number(filter.min)) return false;\n if (filter.max !== \"\" && filter.max != null && n > Number(filter.max)) return false;\n continue;\n }\n if (filter.type === \"dateRange\") {\n const d = parseDateLike(cellValue);\n if (!d) return false;\n if (filter.from) {\n const from = new Date(filter.from + \"T00:00:00\");\n if (d < from) return false;\n }\n if (filter.to) {\n const to = new Date(filter.to + \"T23:59:59\");\n if (d > to) return false;\n }\n continue;\n }\n }\n // Global search — substring match across any cell value\n if (globalQ) {\n const anyMatch = Object.values(row).some((v) => {\n if (v === null || v === undefined) return false;\n return String(v).toLowerCase().includes(globalQ);\n });\n if (!anyMatch) return false;\n }\n return true;\n });\n }, [data, filters, globalQuery, isServerSideFiltering]);\n\n // Sort filtered data\n // For server-side sorting, skip client-side sorting (data is already sorted by server)\n const sortedData = useMemo(() => {\n if (isServerSideSorting) {\n // Server-side sorting: data is already sorted, use as-is\n return filteredData;\n }\n \n // Client-side sorting: sort the filtered data locally\n if (!sortField) return filteredData;\n \n return [...filteredData].sort((a, b) => {\n const aVal = a[sortField];\n const bVal = b[sortField];\n \n // Handle null/undefined\n if (aVal === null || aVal === undefined) return 1;\n if (bVal === null || bVal === undefined) return -1;\n \n // Handle numbers\n if (typeof aVal === \"number\" && typeof bVal === \"number\") {\n return sortDirection === \"asc\" ? aVal - bVal : bVal - aVal;\n }\n \n // Handle strings\n const aStr = String(aVal).toLowerCase();\n const bStr = String(bVal).toLowerCase();\n \n if (sortDirection === \"asc\") {\n return aStr.localeCompare(bStr);\n } else {\n return bStr.localeCompare(aStr);\n }\n });\n }, [filteredData, sortField, sortDirection, isServerSideSorting]);\n\n // Paginate sorted data\n // For server-side pagination, the page slice is already done by the server,\n // but we still want to honour any client-side filter / sort the user applies\n // on top of the visible page (otherwise the filter chips and column sort\n // arrows do nothing). Server-side filter / sort, when wired up, short-circuit\n // those passes inside `filteredData` / `sortedData` so this stays a no-op for\n // fully server-driven setups.\n // For client-side pagination, paginate the sorted data normally.\n const paginatedData = useMemo(() => {\n if (isServerSidePagination) {\n return sortedData;\n } else {\n const startIndex = (page - 1) * pageSize;\n const endIndex = startIndex + pageSize;\n return sortedData.slice(startIndex, endIndex);\n }\n }, [sortedData, page, pageSize, isServerSidePagination]);\n\n // Handle header click for sorting\n const handleSort = (field) => {\n if (isServerSideSorting && onSort) {\n // Server-side sorting: call parent's onSort callback\n onSort(field);\n // Reset to first page on sort (if pagination is controlled)\n if (onPageChange) {\n onPageChange(1);\n } else {\n setInternalPage(1);\n }\n } else {\n // Client-side sorting: update internal state\n if (internalSortField === field) {\n setInternalSortDirection(internalSortDirection === \"asc\" ? \"desc\" : \"asc\");\n } else {\n setInternalSortField(field);\n setInternalSortDirection(\"asc\");\n }\n setPage(1); // Reset to first page on sort\n }\n };\n\n // Legacy handler kept for any callers that still pass a string value;\n // it splits on whitespace and treats the resulting tokens as the selected values.\n const handleFilterChange = (id, value) => {\n const tokens = (value || \"\")\n .split(/\\s+/)\n .map((t) => t.trim())\n .filter(Boolean);\n setColumnFilter(id, tokens);\n };\n\n // Surface max columns limit error via callback, throttled to once per 3s\n const showMaxColumnsError = (message) => {\n if (toastTimeoutRef.current) return;\n if (typeof onMaxColumnsError === 'function') {\n onMaxColumnsError(message);\n }\n toastTimeoutRef.current = setTimeout(() => {\n toastTimeoutRef.current = null;\n }, 3000);\n };\n\n // Save columns to localStorage\n const saveColumnsToStorage = useCallback((cols) => {\n if (typeof window !== 'undefined' && storageKey && cols.length > 0 && userHasManuallyChangedColumns.current) {\n try {\n localStorage.setItem(storageKey, JSON.stringify(cols));\n if (manualChangeFlagKey) {\n localStorage.setItem(manualChangeFlagKey, 'true');\n }\n } catch (error) {\n console.warn('Failed to save columns to localStorage:', error);\n }\n }\n }, [storageKey, manualChangeFlagKey]);\n\n // Toggle column selection — writes to staged state only. The actual table updates\n // when the user clicks Apply (or Reset).\n const toggleColumnSelection = (columnId) => {\n // Prevent toggling the action column visibility; it should always be shown\n if (columnId === ACTION_COLUMN_ID) {\n return;\n }\n setStagedVisibleColumns(prev => {\n if (prev.includes(columnId)) {\n // Don't allow deselecting all columns\n if (prev.length === 1) return prev;\n return prev.filter(id => id !== columnId);\n }\n if (prev.length >= MAX_COLUMNS) {\n showMaxColumnsError(\"Maximum 9 column selection allowed\");\n return prev;\n }\n return enforceActionPosition([...prev, columnId]);\n });\n };\n\n // Column drag handlers for reordering in dropdown\n const handleColumnDragStart = (e, index) => {\n if (stagedVisibleColumns[index] === ACTION_COLUMN_ID) return;\n setDraggedColumnIndex(index);\n };\n\n const handleColumnDragEnd = () => {\n setDraggedColumnIndex(null);\n setDragOverColumnIndex(null);\n };\n\n const handleColumnDragOver = (e, index) => {\n e.preventDefault();\n if (draggedColumnIndex !== null && draggedColumnIndex !== index) {\n setDragOverColumnIndex(index);\n }\n };\n\n const handleColumnDragLeave = () => {\n setDragOverColumnIndex(null);\n };\n\n const handleColumnDrop = (e, dropIndex) => {\n e.preventDefault();\n if (\n draggedColumnIndex !== null &&\n draggedColumnIndex !== dropIndex &&\n stagedVisibleColumns[dropIndex] !== ACTION_COLUMN_ID &&\n stagedVisibleColumns[draggedColumnIndex] !== ACTION_COLUMN_ID\n ) {\n // Drag reorder is staged; commit happens on Apply.\n setStagedVisibleColumns(prev => {\n const reordered = arrayMove(prev, draggedColumnIndex, dropIndex);\n return enforceActionPosition(reordered);\n });\n }\n setDraggedColumnIndex(null);\n setDragOverColumnIndex(null);\n };\n\n // Update columnOrder when visibleColumns changes\n useEffect(() => {\n setColumnOrder(prev => {\n // Keep visible columns in their current order, append any new ones\n const visibleOrder = visibleColumns.filter(id => prev.includes(id));\n const newColumns = visibleColumns.filter(id => !prev.includes(id));\n const hiddenColumns = prev.filter(id => !visibleColumns.includes(id));\n return [...visibleOrder, ...newColumns, ...hiddenColumns];\n });\n }, [visibleColumns]);\n\n // Save to localStorage whenever visibleColumns changes (only if user has manually changed columns)\n useEffect(() => {\n if (typeof window !== 'undefined' && storageKey && visibleColumns.length > 0 && userHasManuallyChangedColumns.current) {\n try {\n const constrained = enforceActionPosition(visibleColumns);\n localStorage.setItem(storageKey, JSON.stringify(constrained));\n if (manualChangeFlagKey) {\n localStorage.setItem(manualChangeFlagKey, 'true');\n }\n } catch (error) {\n console.warn('Failed to save columns to localStorage:', error);\n }\n }\n }, [visibleColumns, storageKey, manualChangeFlagKey]);\n\n // Notify the host whenever the user-visible column set changes so it can\n // scope CSV exports etc. to the current selection. Strips the internal\n // ACTION column id so hosts only see real data columns.\n useEffect(() => {\n if (!onVisibleColumnsChange) return;\n onVisibleColumnsChange(\n visibleColumns.filter((id) => id !== ACTION_COLUMN_ID)\n );\n }, [visibleColumns, onVisibleColumnsChange]);\n\n // Initialize visibleColumns when columns become available (if not already initialized)\n useEffect(() => {\n // Only initialize if columns are available and visibleColumns is empty\n if (columns.length > 0 && visibleColumns.length === 0) {\n // Check if user has manually changed columns before\n if (typeof window !== 'undefined' && tableId) {\n try {\n const hasManualChange = localStorage.getItem(`dataTable_manual_change_${tableId}:${userId}`) === 'true';\n if (hasManualChange) {\n const saved = localStorage.getItem(`dataTable_columns_${tableId}:${userId}`);\n if (saved) {\n const savedColumns = JSON.parse(saved);\n if (Array.isArray(savedColumns) && savedColumns.length > 0) {\n // Validate saved columns exist in current columns\n const validColumns = savedColumns.filter(colId => \n columns.some(col => (col.id || col.key) === colId)\n );\n if (validColumns.length > 0) {\n userHasManuallyChangedColumns.current = true;\n setVisibleColumns(validColumns.slice(0, MAX_COLUMNS));\n return;\n }\n }\n }\n }\n } catch (error) {\n console.warn('Failed to load saved columns from localStorage:', error);\n }\n }\n \n // Default to first 9 columns if no saved columns\n const columnIds = columns.map((col) => col.id || col.key);\n setVisibleColumns(enforceActionPosition(columnIds.slice(0, MAX_COLUMNS)));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [columns, tableId, userId, enforceActionPosition]);\n\n // Get ordered columns based on visibleColumns and columnOrder\n const orderedColumns = useMemo(() => {\n // Filter to only show visible columns, maintaining their order\n const cols = visibleColumns\n .map((id) => columns.find((col) => getColumnId(col) === id))\n .filter(Boolean);\n return enforceActionPosition(cols.map(getColumnId))\n .map((id) => columns.find((col) => getColumnId(col) === id))\n .filter(Boolean);\n }, [columns, visibleColumns]);\n\n // Check if any columns are filterable\n const hasFilterableColumns = useMemo(() => {\n return orderedColumns.some((col) => col.filterable === true);\n }, [orderedColumns]);\n\n // Column dropdown position management\n useEffect(() => {\n if (!isColumnDropdownOpen || !columnDropdownRef.current) return;\n\n const updatePosition = () => {\n if (columnDropdownRef.current) {\n const rect = columnDropdownRef.current.getBoundingClientRect();\n const menuWidth = 217;\n // Right-align the menu to the button so it never overflows the viewport\n // when the trigger sits near the right edge.\n const left = Math.max(8, rect.right - menuWidth);\n setColumnDropdownPosition({\n top: rect.bottom,\n left,\n width: Math.max(rect.width || 220, 220),\n });\n }\n };\n\n updatePosition();\n \n // Use simple scroll listeners like Dropdown component for smooth scrolling\n window.addEventListener(\"scroll\", updatePosition, true);\n window.addEventListener(\"resize\", updatePosition);\n\n return () => {\n window.removeEventListener(\"scroll\", updatePosition, true);\n window.removeEventListener(\"resize\", updatePosition);\n };\n }, [isColumnDropdownOpen]);\n\n // Close dropdown when clicking outside\n useEffect(() => {\n const handleClickOutside = (event) => {\n if (\n isColumnDropdownOpen &&\n columnDropdownRef.current &&\n !columnDropdownRef.current.contains(event.target) &&\n columnDropdownMenuRef.current &&\n !columnDropdownMenuRef.current.contains(event.target)\n ) {\n setIsColumnDropdownOpen(false);\n }\n };\n\n if (isColumnDropdownOpen) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }\n }, [isColumnDropdownOpen]);\n\n // Sync staged selection with the committed selection whenever the dropdown opens.\n // Outside-click closes without committing, so the next open always starts from the\n // last applied state.\n useEffect(() => {\n if (isColumnDropdownOpen) {\n setStagedVisibleColumns(visibleColumns);\n setPendingSelection(new Set());\n setPendingDeselection(new Set());\n }\n }, [isColumnDropdownOpen, visibleColumns]);\n\n // Display text for dropdown button\n const displayText = visibleColumns.length === 1 \n ? columns.find(col => (col.id || col.key) === visibleColumns[0])?.label || \"1 selected\"\n : `${visibleColumns.length} selected`;\n\n // Sortable header cell component\n function SortableHeader({ column, isHeaderRow = true }) {\n const columnId = getColumnId(column);\n const isActionColumn = columnId === ACTION_COLUMN_ID;\n const resolvedWidth = getResolvedColumnWidth(columnId, column.width);\n const [isHeaderHovered, setIsHeaderHovered] = useState(false);\n const {\n attributes,\n listeners,\n setNodeRef,\n transform,\n transition,\n isDragging,\n } = useSortable({ id: columnId });\n\n const style = {\n transform: CSS.Transform.toString(transform),\n transition,\n opacity: isDragging ? 0.5 : 1,\n width: resolvedWidth,\n minWidth: resolvedWidth,\n };\n\n // For server-side sorting, check if the sortField matches this column\n // Handle reverse mapping (e.g., \"csat_score\" matches \"evaluation.csat_score\")\n let isSorted = false;\n if (isServerSideSorting && sortFields.length > 0) {\n const sortFieldFromProps = sortFields[0][0];\n // Direct match\n if (sortFieldFromProps === columnId) {\n isSorted = true;\n }\n // Reverse mapping: \"csat_score\" matches \"evaluation.csat_score\"\n else if (sortFieldFromProps === \"csat_score\" && columnId === \"evaluation.csat_score\") {\n isSorted = true;\n }\n } else {\n // Client-side sorting: direct comparison\n isSorted = sortField === columnId;\n }\n \n const isAsc = sortDirection === \"asc\";\n const isFilterable = column.filterable === true; // Only filterable if explicitly set to true\n\n // Filter row\n if (!isHeaderRow) {\n return (\n <th\n style={{\n width: resolvedWidth,\n minWidth: resolvedWidth,\n backgroundColor: \"var(--primary-foreground)\",\n }}\n className=\"sticky top-[57px] z-10 border-b border-[var(--border-strong)] px-4 py-2 text-left\"\n >\n {isFilterable ? (\n <div className=\"relative\">\n <Filter\n size={12}\n className=\"absolute left-2 top-1/2 -translate-y-1/2 text-[var(--text-faint)] pointer-events-none\"\n />\n <input\n type=\"text\"\n placeholder=\"Filter...\"\n value={filters[columnId] || \"\"}\n onChange={(e) => {\n e.stopPropagation();\n handleFilterChange(columnId, e.target.value);\n }}\n onKeyDown={(e) => e.stopPropagation()}\n onMouseDown={(e) => e.stopPropagation()}\n className=\"w-full pl-7 pr-2 py-1.5 text-xs border border-[var(--border)] rounded text-[var(--text-ink)] placeholder:text-[var(--text-faint)] focus:outline-none focus:border-[var(--border-hover)] focus:ring-1 focus:ring-[var(--focus)] transition-colors\"\n style={{ fontFamily: 'var(--font-sans)', backgroundColor: \"var(--primary-foreground)\" }}\n autoComplete=\"off\"\n />\n </div>\n ) : (\n <div className=\"h-[34px]\"></div>\n )}\n </th>\n );\n }\n\n // Header row\n const filterPopoverOpen = openFilterColumnId === columnId;\n const hasActiveFilter = isFilterActive(filters[columnId]);\n const showSortBtn = column.sortable !== false && (isHeaderHovered || isSorted);\n const showFilterBtn = column.filterable !== false && !isActionColumn && (isHeaderHovered || filterPopoverOpen || hasActiveFilter);\n return (\n <th\n ref={setNodeRef}\n onMouseEnter={() => setIsHeaderHovered(true)}\n onMouseLeave={() => setIsHeaderHovered(false)}\n style={{\n ...style,\n padding: '0 12px',\n height: 36,\n textAlign: isActionColumn ? 'center' : 'left',\n fontWeight: 500,\n fontSize: '14px',\n letterSpacing: 'normal',\n textTransform: 'none',\n color: '#0b0b0b',\n cursor: column.sortable !== false ? 'pointer' : 'default',\n width: resolvedWidth,\n borderRight: 'none',\n userSelect: 'none',\n background: isHeaderHovered || filterPopoverOpen ? '#e6e6e6' : '#f2f2f0',\n borderBottom: '1px solid #e6e6e6',\n position: 'sticky',\n top: 0,\n zIndex: 10,\n fontFamily: 'var(--font-sans)',\n transition: 'background 100ms ease',\n }}\n >\n {/* Left edge separator (1px × 16px, vertically centered) */}\n {!isActionColumn && (\n <span\n aria-hidden=\"true\"\n style={{\n position: \"absolute\",\n left: 0,\n top: \"50%\",\n transform: \"translateY(-50%)\",\n width: 1,\n height: 16,\n background: \"#e6e6e6\",\n pointerEvents: \"none\",\n }}\n />\n )}\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n justifyContent: isActionColumn ? 'center' : 'flex-start',\n position: 'relative',\n minHeight: 20,\n }}\n >\n {!isActionColumn && (\n <div\n {...attributes}\n {...listeners}\n style={{\n cursor: 'grab',\n color: 'rgba(11, 11, 11, 0.36)',\n display: 'inline-flex',\n alignItems: 'center',\n visibility: isHeaderHovered ? 'visible' : 'hidden',\n }}\n >\n <GripVertical size={14} />\n </div>\n )}\n <span\n onClick={() => column.sortable !== false && handleSort(columnId)}\n style={{ cursor: column.sortable !== false ? 'pointer' : 'default', flex: 1, lineHeight: '20px' }}\n >\n {column.label}\n </span>\n {showSortBtn && (\n <button\n type=\"button\"\n onClick={(e) => { e.stopPropagation(); handleSort(columnId); }}\n title=\"Sort\"\n style={{\n background: \"transparent\",\n border: \"none\",\n padding: 4,\n borderRadius: 4,\n cursor: \"pointer\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n color: isSorted ? \"#0b0b0b\" : \"rgba(11, 11, 11, 0.55)\",\n }}\n >\n {isSorted\n ? (isAsc ? <ArrowUp size={14} strokeWidth={1.75} /> : <ArrowDown size={14} strokeWidth={1.75} />)\n : <ArrowUpDown size={14} strokeWidth={1.75} />}\n </button>\n )}\n {showFilterBtn && (\n <button\n type=\"button\"\n ref={(el) => { filterIconRefs.current[columnId] = el; }}\n onClick={(e) => { e.stopPropagation(); openFilterPopoverFor(columnId, e.currentTarget); }}\n title=\"Filter\"\n style={{\n position: \"relative\",\n background: filterPopoverOpen || hasActiveFilter ? \"#D8D8D8\" : \"transparent\",\n border: \"none\",\n padding: 4,\n borderRadius: 4,\n cursor: \"pointer\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n color: hasActiveFilter ? \"#0b0b0b\" : \"rgba(11, 11, 11, 0.7)\",\n }}\n >\n <ListFilter size={14} strokeWidth={1.75} />\n {hasActiveFilter && (\n <span\n aria-hidden=\"true\"\n style={{\n position: \"absolute\",\n top: 0,\n right: 0,\n width: 6,\n height: 6,\n borderRadius: \"50%\",\n background: \"#0B0B0B\",\n }}\n />\n )}\n </button>\n )}\n </div>\n {/* Right edge separator (1px × 16px, vertically centered, on the cell's right edge) */}\n {!isActionColumn && (\n <span\n aria-hidden=\"true\"\n style={{\n position: \"absolute\",\n right: 0,\n top: \"50%\",\n transform: \"translateY(-50%)\",\n width: 1,\n height: 16,\n background: \"#e6e6e6\",\n pointerEvents: \"none\",\n }}\n />\n )}\n {/* Resize handle — sits right at the cell's right edge, away from the filter icon */}\n {!isActionColumn && (\n <div\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label={`Resize ${column.label || columnId} column`}\n title=\"Drag to resize column\"\n onMouseDown={(e) => startResize(e, column, resolvedWidth)}\n onClick={(e) => e.stopPropagation()}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = \"rgba(30, 33, 37, 0.18)\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = \"transparent\";\n }}\n style={{\n position: \"absolute\",\n top: 0,\n right: -2,\n width: 4,\n height: \"100%\",\n cursor: \"col-resize\",\n zIndex: 4,\n background: \"transparent\",\n }}\n />\n )}\n </th>\n );\n }\n\n // Drag overlay for column header\n const activeColumn = activeId ? columns.find((col) => getColumnId(col) === activeId) : null;\n\n // Column dropdown menu\n const renderColumnRow = ({ col, columnId, isSelected, draggable, isAction, actualIndex }) => {\n const isDragging = draggable && draggedColumnIndex === actualIndex;\n const isDragOver = draggable && dragOverColumnIndex === actualIndex && draggedColumnIndex !== null && draggedColumnIndex !== actualIndex;\n const isPending = isSelected ? pendingDeselection.has(columnId) : pendingSelection.has(columnId);\n // Visual checked state: selected and not pending deselect, OR unselected and pending select\n const checked = isSelected ? !pendingDeselection.has(columnId) : pendingSelection.has(columnId);\n return (\n <div\n draggable={draggable}\n onDragStart={draggable ? (e) => handleColumnDragStart(e, actualIndex) : undefined}\n onDragEnd={draggable ? handleColumnDragEnd : undefined}\n onDragOver={draggable ? (e) => handleColumnDragOver(e, actualIndex) : undefined}\n onDragLeave={draggable ? handleColumnDragLeave : undefined}\n onDrop={draggable ? (e) => handleColumnDrop(e, actualIndex) : undefined}\n onClick={() => { if (!isAction) toggleColumnSelection(columnId); }}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n padding: \"2px 0\",\n cursor: isAction ? \"default\" : (draggable ? \"grab\" : \"pointer\"),\n opacity: isDragging ? 0.5 : 1,\n background: isDragOver ? \"#F2F2F0\" : \"transparent\",\n borderRadius: 6,\n }}\n >\n {/* Drag handle — visible only for selected (sortable) items */}\n <span\n style={{\n width: 16,\n height: 16,\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"#989898\",\n visibility: draggable ? \"visible\" : \"hidden\",\n flexShrink: 0,\n }}\n >\n <GripVertical size={14} strokeWidth={1.75} />\n </span>\n {/* Checkbox 20x20 */}\n <span\n style={{\n width: 20,\n height: 20,\n borderRadius: 4,\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: checked ? \"#0B0B0B\" : \"#FFFFFF\",\n border: `1px solid ${checked ? \"#0B0B0B\" : \"#676767\"}`,\n flexShrink: 0,\n marginLeft: 8,\n }}\n >\n {checked && <Check size={14} color=\"#FFFFFF\" strokeWidth={3} />}\n </span>\n <span\n style={{\n flex: 1,\n fontFamily: \"var(--font-sans)\",\n fontSize: 14,\n lineHeight: \"20px\",\n color: \"#0B0B0B\",\n marginLeft: 8,\n }}\n >\n {col.label}\n </span>\n </div>\n );\n };\n\n const columnDropdownMenu = isColumnDropdownOpen ? (\n <div\n ref={columnDropdownMenuRef}\n style={{\n position: \"fixed\",\n top: `${columnDropdownPosition.top}px`,\n left: `${columnDropdownPosition.left}px`,\n width: 217,\n maxHeight: 320,\n zIndex: 49,\n background: \"#FFFFFF\",\n border: \"1px solid #E6E6E6\",\n borderRadius: 10,\n overflow: \"hidden\",\n display: \"flex\",\n flexDirection: \"column\",\n fontFamily: \"var(--font-sans)\",\n boxShadow: \"0 8px 24px rgba(11, 11, 11, 0.08)\",\n }}\n >\n {/* Scrollable list — selected rows on top, unselected below. */}\n <div\n style={{\n flex: 1,\n minHeight: 0,\n overflowY: \"auto\",\n padding: 12,\n display: \"flex\",\n flexDirection: \"column\",\n gap: 12,\n }}\n >\n {/* Selected columns — draggable. Reads staged state so the dropdown reflects\n the user's pending toggles before they click Apply. */}\n {stagedVisibleColumns.map((columnId, index) => {\n const col = columns.find((c) => getColumnId(c) === columnId);\n if (!col) return null;\n const isAction = columnId === ACTION_COLUMN_ID;\n return (\n <React.Fragment key={`selected-${columnId}-${index}`}>\n {renderColumnRow({\n col,\n columnId,\n isSelected: true,\n draggable: !isAction,\n isAction,\n actualIndex: index,\n })}\n </React.Fragment>\n );\n })}\n\n {/* Unselected columns */}\n {columns\n .filter((col) => !stagedVisibleColumns.includes(getColumnId(col)))\n .map((col) => {\n const columnId = getColumnId(col);\n return (\n <React.Fragment key={`unselected-${columnId}`}>\n {renderColumnRow({\n col,\n columnId,\n isSelected: false,\n draggable: false,\n isAction: false,\n actualIndex: -1,\n })}\n </React.Fragment>\n );\n })}\n </div>\n\n {/* Sticky footer — Reset + Apply */}\n <div\n style={{\n flexShrink: 0,\n borderTop: \"1px solid #D9D9D9\",\n padding: \"8px 12px\",\n background: \"#FFFFFF\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n height: 46,\n boxSizing: \"border-box\",\n }}\n >\n <button\n type=\"button\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n // Reset both staged (so the dropdown UI updates) and committed columns to\n // the initial snapshot, and clear persisted user changes.\n const snapshot = initialVisibleColumnsRef.current\n ? [...initialVisibleColumnsRef.current]\n : columns.map(getColumnId).slice(0, MAX_COLUMNS);\n const constrained = enforceActionPosition(snapshot);\n userHasManuallyChangedColumns.current = false;\n setStagedVisibleColumns(constrained);\n setVisibleColumns(constrained);\n setPendingSelection(new Set());\n setPendingDeselection(new Set());\n if (typeof window !== \"undefined\" && storageKey) {\n try { localStorage.removeItem(storageKey); } catch (_) {}\n }\n }}\n style={{\n background: \"transparent\",\n border: \"none\",\n padding: 0,\n cursor: \"pointer\",\n fontFamily: \"var(--font-sans)\",\n fontSize: 14,\n fontWeight: 500,\n color: \"#323232\",\n }}\n >\n Reset\n </button>\n <button\n type=\"button\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n // Commit staged selection to the table.\n const constrained = enforceActionPosition(stagedVisibleColumns);\n userHasManuallyChangedColumns.current = true;\n setVisibleColumns(constrained);\n saveColumnsToStorage(constrained);\n setIsColumnDropdownOpen(false);\n }}\n style={{\n background: \"#2E3236\",\n color: \"#FFFFFF\",\n border: \"none\",\n borderRadius: 10,\n height: 28,\n padding: \"0 14px\",\n fontFamily: \"var(--font-sans)\",\n fontSize: 14,\n fontWeight: 600,\n cursor: \"pointer\",\n }}\n >\n Apply\n </button>\n </div>\n </div>\n ) : null;\n\n const openFilterColumn = openFilterColumnId\n ? columns.find((c) => getColumnId(c) === openFilterColumnId)\n : null;\n const filterPopoverNode = openFilterColumn\n ? (\n <FilterValuePicker\n key={openFilterColumnId}\n column={openFilterColumn}\n columnId={openFilterColumnId}\n filterType={getColumnFilterType(openFilterColumnId)}\n position={filterPopoverPosition}\n popoverRef={filterPopoverRef}\n distinctValues={getDistinctValuesForColumn(openFilterColumnId)}\n initialValue={filters[openFilterColumnId]}\n onApply={(value) => {\n setColumnFilter(openFilterColumnId, value);\n setOpenFilterColumnId(null);\n }}\n onCancel={() => setOpenFilterColumnId(null)}\n />\n )\n : null;\n\n return (\n <div className=\"w-full\">\n {/* Filter popover (anchored under the active column header) */}\n {filterPopoverNode && createPortal(filterPopoverNode, document.body)}\n {/* Toolbar: Columns dropdown + Search */}\n {columns.length > 0 && (\n <div\n className=\"pt-2 pb-1\"\n style={{\n position: \"sticky\",\n zIndex: 35,\n backgroundColor: \"var(--primary-foreground)\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"flex-end\",\n gap: 16,\n flexWrap: \"wrap\",\n }}\n >\n {filtersConfig && (\n <div style={{ marginRight: \"auto\" }}>\n <DataTableFilters\n dateRangePicker={filtersConfig.dateRangePicker}\n onWeekToDate={filtersConfig.onWeekToDate}\n exportConfig={filtersConfig.exportConfig}\n filterChipsConfig={filtersConfig.filterChipsConfig}\n trailingActions={filtersConfig.trailingActions}\n />\n </div>\n )}\n\n {/* Columns button — compact */}\n <div style={{ position: \"relative\" }}>\n <button\n ref={columnDropdownRef}\n type=\"button\"\n onClick={() => setIsColumnDropdownOpen(!isColumnDropdownOpen)}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 10,\n height: 32,\n padding: \"0 16px\",\n background: \"#FFFFFF\",\n border: \"1px solid #D9D9D9\",\n borderRadius: 10,\n cursor: \"pointer\",\n fontFamily: \"var(--font-sans)\",\n fontSize: 14,\n fontWeight: 600,\n color: \"#2E3236\",\n whiteSpace: \"nowrap\",\n }}\n >\n <Settings2 size={20} strokeWidth={1.75} />\n Columns\n </button>\n {isColumnDropdownOpen && createPortal(columnDropdownMenu, document.body)}\n </div>\n\n {/* Search input */}\n {/*\n <div\n style={{\n background: \"#D8D8D8\",\n width: 260,\n height: 32,\n borderRadius: 11,\n padding: 1,\n display: \"flex\",\n alignItems: \"center\",\n }}\n >\n <div\n style={{\n background: \"#FFFFFF\",\n flex: 1,\n height: 30,\n borderRadius: 10,\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"0 8px\",\n }}\n >\n <Search size={18} color=\"#989898\" strokeWidth={1.75} />\n <input\n type=\"text\"\n placeholder=\"Search\"\n value={globalQuery}\n onChange={(e) => {\n setGlobalQuery(e.target.value);\n if (onPageChange) onPageChange(1); else setInternalPage(1);\n }}\n style={{\n flex: 1,\n border: \"none\",\n outline: \"none\",\n background: \"transparent\",\n fontFamily: \"var(--font-sans)\",\n fontSize: 14,\n color: \"#0B0B0B\",\n minWidth: 0,\n }}\n />\n </div>\n </div>\n */}\n </div>\n </div>\n )}\n {/* Filter chip strip — appears below the toolbar when any filter is active */}\n {Object.keys(filters).length > 0 && (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n flexWrap: \"wrap\",\n padding: \"8px 0\",\n }}\n >\n {Object.entries(filters).map(([colId, filter]) => {\n const col = columns.find((c) => getColumnId(c) === colId);\n if (!col || !isFilterActive(filter)) return null;\n const first = chipSummary(filter);\n const extra = chipExtraCount(filter);\n const extraValues = chipExtraValues(filter);\n return (\n <span\n key={`chip-${colId}`}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 8,\n height: 28,\n padding: \"0 12px\",\n borderRadius: 20,\n border: \"1px solid #B2B2B0\",\n background: \"#F2F2F0\",\n fontFamily: \"var(--font-sans)\",\n fontSize: 14,\n lineHeight: \"20px\",\n color: \"#0B0B0B\",\n whiteSpace: \"nowrap\",\n }}\n >\n <span>\n <span style={{ color: \"#676767\" }}>{col.label}: </span>\n <span>{first}</span>\n </span>\n {extra > 0 && (\n <ExtraValuesBadge count={extra} values={extraValues} />\n )}\n <button\n type=\"button\"\n onClick={() => setColumnFilter(colId, [])}\n aria-label={`Remove ${col.label} filter`}\n style={{\n background: \"transparent\",\n border: \"none\",\n padding: 0,\n cursor: \"pointer\",\n display: \"inline-flex\",\n color: \"#676767\",\n }}\n >\n <X size={14} strokeWidth={2} />\n </button>\n </span>\n );\n })}\n <button\n type=\"button\"\n onClick={clearAllFilters}\n style={{\n marginLeft: \"auto\",\n background: \"transparent\",\n border: \"none\",\n padding: \"0 4px\",\n cursor: \"pointer\",\n fontFamily: \"var(--font-sans)\",\n fontSize: 14,\n fontWeight: 500,\n color: \"#323232\",\n }}\n >\n Reset\n </button>\n </div>\n )}\n\n {/* Only render table if we have columns */}\n {columns.length > 0 && orderedColumns.length > 0 ? (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n >\n <div style={{\n borderRadius: 8,\n border: '1px solid #E6E6E6',\n overflow: 'hidden',\n background: 'var(--primary-foreground)',\n position: 'relative',\n top: '0.5rem',\n }}>\n {/* Loading overlay */}\n {isLoading && (\n <div style={{\n position: 'absolute',\n inset: 0,\n background: 'rgba(255, 255, 255, 0.9)',\n backdropFilter: 'blur(2px)',\n zIndex: 20,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: '14px'\n }}>\n <div style={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n gap: '12px'\n }}>\n <p style={{\n fontSize: '13px',\n color: 'rgba(30, 33, 37, 0.6)',\n margin: 0\n }}>Loading...</p>\n <Image\n src=\"/BrandLoading.gif\"\n alt=\"Loading\"\n width={50}\n height={50}\n unoptimized\n className=\"mt-1\"\n />\n </div>\n </div>\n )}\n <div className=\"overflow-x-auto custom-thin-scrollbar-hidden\" ref={tableRef} style={{ maxHeight: '500px', overflowY: 'auto', position: 'relative', zIndex: 1 }}>\n <table style={{\n width: 'auto',\n minWidth: '100%',\n borderCollapse: 'collapse',\n fontSize: '13px',\n fontFamily: 'var(--font-sans)'\n }}>\n <thead>\n {/* Header row with column labels */}\n <tr>\n <SortableContext\n items={visibleColumns}\n strategy={horizontalListSortingStrategy}\n >\n {orderedColumns.map((column) => (\n <SortableHeader key={`header-${getColumnId(column)}`} column={column} isHeaderRow={true} />\n ))}\n </SortableContext>\n </tr>\n </thead>\n <tbody>\n {!isLoading && paginatedData.length === 0 ? (\n <tr>\n <td\n colSpan={orderedColumns.length}\n style={{\n padding: '32px',\n textAlign: 'center',\n color: 'rgba(30, 33, 37, 0.42)',\n fontSize: '12px',\n fontFamily: 'var(--font-sans)',\n }}\n >\n No results found\n </td>\n </tr>\n ) : !isLoading && paginatedData.length > 0 ? (\n paginatedData.map((row, rowIndex) => (\n <tr\n key={rowIndex}\n data-row-id={row.id || rowIndex}\n style={{\n borderBottom: '1px solid #e6e6e6',\n cursor: onRowClick ? 'pointer' : 'default',\n transition: 'background 0.15s ease'\n }}\n onClick={onRowClick ? (e) => {\n e.stopPropagation();\n onRowClick(row, rowIndex);\n } : undefined}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = 'rgba(231, 212, 162, 0.12)';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = 'transparent';\n }}\n >\n {orderedColumns.map((column) => {\n const columnId = getColumnId(column);\n const resolvedWidth = getResolvedColumnWidth(columnId, column.width);\n const cellValue = row[columnId];\n const renderValue = column.render\n ? column.render(cellValue, row)\n : cellValue;\n\n // Only show tooltip for string values that might be truncated\n const hasWidthConstraint = resolvedWidth && resolvedWidth !== 'auto';\n const isStringValue = typeof renderValue === 'string' && renderValue.trim() !== '';\n const shouldUseTruncatedCell = hasWidthConstraint && isStringValue;\n\n const displayValue = shouldUseTruncatedCell ? (\n <TruncatedCell content={renderValue}>\n {renderValue}\n </TruncatedCell>\n ) : renderValue;\n\n return (\n <td\n key={columnId}\n style={{\n padding: '10px 14px',\n color: 'rgba(30, 33, 37, 0.78)',\n fontSize: '13px',\n borderRight: '1px solid rgba(52, 58, 64, 0.04)',\n width: resolvedWidth,\n fontFamily: 'var(--font-sans)',\n ...(shouldUseTruncatedCell && { maxWidth: resolvedWidth || '200px' }),\n }}\n >\n {displayValue}\n </td>\n );\n })}\n </tr>\n ))\n ) : null}\n </tbody>\n </table>\n </div>\n </div>\n\n <DragOverlay>\n {activeColumn ? (\n <div className=\"bg-[var(--paper-high)] border border-[var(--border-strong)] rounded px-4 py-2 shadow-lg\">\n <div className=\"flex items-center gap-2\">\n <GripVertical size={14} className=\"text-[var(--text-faint)]\" />\n <span className=\"text-sm font-semibold text-[var(--text-ink)]\">\n {activeColumn.label}\n </span>\n </div>\n </div>\n ) : null}\n </DragOverlay>\n </DndContext>\n ) : null}\n\n {(() => {\n // In server-side pagination mode the client-side filter/sort still\n // operate on the current page, so when the user narrows it down with a\n // chip the footer should reflect the filtered count instead of the\n // server's totalCount (otherwise we render \"1-1 of 508\" with phantom\n // pages 2..51 the user can never reach).\n const hasClientFilter =\n !isServerSideFiltering &&\n (globalQuery.trim() !== \"\" ||\n Object.values(filters).some((f) => isFilterActive(f)));\n const effectiveTotal = isServerSidePagination\n ? hasClientFilter\n ? sortedData.length\n : totalCount\n : sortedData.length;\n if (effectiveTotal <= 0) return null;\n return (\n <Pagination\n page={page}\n pageSizeOptions={[5, 10, 20, 50, 100]}\n pageSize={pageSize}\n totalCount={effectiveTotal}\n currentDataLength={paginatedData.length}\n onPageChange={setPage}\n onPageSizeChange={(newSize) => {\n setPageSize(newSize);\n setPage(1);\n }}\n showPageSizeSelector={true}\n />\n );\n })()}\n </div>\n );\n}\n\n"],"names":["DataTableFilters","dateRangePicker","onWeekToDate","exportConfig","filterChipsConfig","trailingActions","showExportMenu","setShowExportMenu","useState","exportButtonRef","useRef","exportMenuRef","useEffect","handleClickOutside","event","openExportMenu","prev","handleExport","type","shouldShowChips","filters","customFilters","hasRegularFilters","key","value","hasCustomFilters","filterObj","jsxs","jsx","CalendarClock","Suspense","Download","ChevronDown","Fragment","CustomFilterChips","parseNumberLike","s","cleaned","n","parseDurationToSeconds","str","colon","a","b","c","total","matched","dM","hM","mM","sM","parseDateLike","slash","yyyy","d","detectFilterType","values","sample","allMatch","test","v","isFilterActive","filter","secondsToHMS","sec","h","m","chipSummary","lo","hi","chipExtraCount","chipExtraValues","ExtraValuesBadge","count","hover","setHover","RangeInputs","leftLabel","rightLabel","leftValue","rightValue","onLeftChange","onRightChange","placeholderLeft","placeholderRight","fieldStyle","labelStyle","e","DURATION_PRESETS","mmssToSec","FilterTitle","children","MinMaxInputs","minValue","maxValue","onMinChange","onMaxChange","inputType","inputMode","step","placeholder","unit","FilterValuePicker","column","columnId","filterType","position","popoverRef","distinctValues","initialValue","onApply","onCancel","isText","isNumber","isDate","isDuration","isScore","scoreInRange","useMemo","min","max","staged","setStaged","query","setQuery","rangeMin","setRangeMin","rangeMax","setRangeMax","durPresets","setDurPresets","durCustomMin","setDurCustomMin","durCustomMax","setDurCustomMax","scorePresets","setScorePresets","scoreCustomMin","setScoreCustomMin","scoreCustomMax","setScoreCustomMax","dateFrom","setDateFrom","dateTo","setDateTo","filteredValues","q","toggle","next","reset","toggleDurPreset","id","toggleScorePreset","apply","customMinSec","customMaxSec","hasCustom","minSec","maxSec","selected","p","customMinNum","customMaxNum","Search","checked","Check","preset","useUserContext","Image","props","HoverBalloon","content","direction","align","styling","indicatorColor","tooltipText","resolvedArrowColor","isVisible","setIsVisible","mounted","setMounted","setPosition","triggerRef","tooltipRef","updatePosition","useCallback","triggerRect","tooltipRect","viewportWidth","viewportHeight","viewportPadding","gap","tooltipWidth","tooltipHeight","spaceAbove","spaceBelow","preferredPlacement","placement","anchorX","top","left","arrowLeft","handleReposition","createPortal","DataTable2","data","columns","initialPageSize","onRowClick","totalCount","controlledPage","controlledPageSize","onPageChange","onPageSizeChange","onFilterChange","columnFilters","onMaxColumnsError","onSort","sortFields","tableId","isLoading","filtersConfig","columnResizeMinWidth","columnResizeMaxWidth","onVisibleColumnsChange","userData","userId","TruncatedCell","React","className","textRef","isTruncated","setIsTruncated","checkTruncation","isOverflowing","timeoutId","textElement","isServerSidePagination","isServerSideFiltering","isServerSideSorting","internalPage","setInternalPage","internalPageSize","setInternalPageSize","page","pageSize","setPage","newPage","setPageSize","newSize","MAX_COLUMNS","ACTION_COLUMN_ID","userHasManuallyChangedColumns","storageKey","col","manualChangeFlagKey","cols","saved","validColumns","colId","error","setFilters","globalQuery","setGlobalQuery","openFilterColumnId","setOpenFilterColumnId","filterPopoverPosition","setFilterPopoverPosition","filterPopoverRef","filterIconRefs","internalSortField","setInternalSortField","internalSortDirection","setInternalSortDirection","setColumnFilter","active","k","clearAllFilters","getDistinctValuesForColumn","seen","out","row","getColumnFilterType","getColumnId","computeFilterPopoverPosition","rect","openFilterPopoverFor","anchorEl","onMouseDown","anchor","useLayoutEffect","popover","popoverWidth","VIEWPORT_PAD","correctedLeft","normalizeColumnFilters","incomingFilters","areFiltersEqual","aKeys","bKeys","normalizedFilters","sortFieldFromProps","sortField","sortDirection","columnOrder","setColumnOrder","enforceActionPosition","result","tableHasActionColumn","visibleColumns","setVisibleColumns","savedColumns","initial","isColumnDropdownOpen","setIsColumnDropdownOpen","stagedVisibleColumns","setStagedVisibleColumns","columnDropdownPosition","setColumnDropdownPosition","pendingSelection","setPendingSelection","pendingDeselection","setPendingDeselection","initialVisibleColumnsRef","draggedColumnIndex","setDraggedColumnIndex","dragOverColumnIndex","setDragOverColumnIndex","columnDropdownRef","columnDropdownMenuRef","toastTimeoutRef","activeId","setActiveId","columnWidths","setColumnWidths","tableRef","resizeStateRef","toPixelWidth","trimmed","parsed","getResolvedColumnWidth","fallbackWidth","handleResizeMove","startX","startWidth","minWidth","maxWidth","delta","nextWidth","clamped","stopResize","startResize","currentWidth","colMin","colMax","widthFromDom","_a","base","sensors","useSensors","useSensor","PointerSensor","KeyboardSensor","sortableKeyboardCoordinates","handleDragEnd","over","showMaxColumnsError","oldIndex","newIndex","reordered","arrayMove","constrained","saveColumnsToStorage","items","handleDragStart","filteredData","globalQ","filterEntries","f","cellValue","cellStr","bucket","from","to","sortedData","aVal","bVal","aStr","bStr","paginatedData","startIndex","endIndex","handleSort","field","handleFilterChange","tokens","t","message","toggleColumnSelection","handleColumnDragStart","index","handleColumnDragEnd","handleColumnDragOver","handleColumnDragLeave","handleColumnDrop","dropIndex","visibleOrder","newColumns","hiddenColumns","columnIds","orderedColumns","menuWidth","SortableHeader","isHeaderRow","isActionColumn","resolvedWidth","isHeaderHovered","setIsHeaderHovered","attributes","listeners","setNodeRef","transform","transition","isDragging","useSortable","style","CSS","isSorted","isAsc","isFilterable","filterPopoverOpen","hasActiveFilter","showSortBtn","showFilterBtn","GripVertical","ArrowUp","ArrowDown","ArrowUpDown","el","ListFilter","activeColumn","renderColumnRow","isSelected","draggable","isAction","actualIndex","isDragOver","columnDropdownMenu","snapshot","openFilterColumn","filterPopoverNode","Settings2","first","extra","extraValues","X","DndContext","closestCenter","SortableContext","horizontalListSortingStrategy","rowIndex","renderValue","hasWidthConstraint","isStringValue","shouldUseTruncatedCell","displayValue","DragOverlay","hasClientFilter","effectiveTotal","Pagination"],"mappings":"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"}