import React, { useEffect, useRef } from 'react'; import { Button, Checkbox, ScrollView, Separator, Text, XStack, YStack } from 'tamagui'; import { getIcon } from '../IconMapper.jsx'; import { PageNavBar } from '../PageNavBar.jsx'; import { useGridView } from './context.js'; import { getTypographyRoleProps } from '../../styles/index.js'; import { formatValueByColumn, getColumnJustify, getColumnLayoutStyle, resolveCellAlignment, resolveCellValue } from './utils.js'; function DefaultGridCellRenderer({ value, column }) { return ( {formatValueByColumn(value, column)} ); } function UtilityCell({ rowId }) { const grid = useGridView(); const ChevronRightIcon = getIcon('chevron-right'); if (!grid.selectable && !grid.nested) { return null; } if (grid.nested) { return ( {ChevronRightIcon ? : {'>'}} ); } return ( grid.toggleSelectRow(rowId)} borderColor="$lineStrong" backgroundColor="$bgPanel" focusStyle={{ borderColor: '$accent' }} > {(() => { const Check = getIcon('check'); return Check ? : null; })()} ); } function useViewportTracking(enabled = true) { const grid = useGridView(); const bodyRef = useRef(null); useEffect(() => { if (!enabled || typeof window === 'undefined') { return undefined; } const updateViewportWidth = () => { const element = bodyRef.current; if (!element) { return; } const nextWidth = Math.max(0, Math.round(element.getBoundingClientRect().width)); grid.setTableViewportWidth((current) => (current === nextWidth ? current : nextWidth)); }; updateViewportWidth(); window.addEventListener('resize', updateViewportWidth); return () => { window.removeEventListener('resize', updateViewportWidth); }; }, [enabled, grid]); return bodyRef; } export function TableHeader({ visible = true, showTopBorder = true }) { const grid = useGridView(); if (visible === false) { return null; } const activeColumns = grid.visibleColumns?.length ? grid.visibleColumns : grid.resolvedColumns; const CaretUp = getIcon('caret-up'); const CaretDown = getIcon('caret-down'); const allIds = (grid.rows || []).map((row) => row?.id).filter((id) => id != null); const selectedCount = allIds.filter((id) => grid.selectedIds.has(id)).length; const allSelected = allIds.length > 0 && selectedCount === allIds.length; const someSelected = selectedCount > 0 && !allSelected; const getNextSortDirection = (column) => { const activeSort = grid.sortBy.find((entry) => entry.field === column.field); if (!activeSort) { return 'ascending'; } if (activeSort.direction === 'asc') { return 'descending'; } return 'none'; }; return ( {grid.selectable || grid.nested ? ( {grid.selectable ? ( grid.toggleSelectAll?.()} borderColor="$lineStrong" backgroundColor="$bgPanel" focusStyle={{ borderColor: '$accent' }} > {(() => { const Check = getIcon('check'); return Check ? : null; })()} ) : null} ) : null} {activeColumns.map((column) => { const activeSort = grid.sortBy.find((entry) => entry.field === column.field); const isActive = Boolean(activeSort); const direction = activeSort?.direction; const sortButtonLabel = `Sort ${column.label} ${getNextSortDirection(column)}`; const ChevronIcon = isActive ? (direction === 'asc' ? CaretUp : CaretDown) : CaretDown; const iconColor = isActive ? '$textSecondary' : '$textMuted'; return ( {column.label} {column.sortable ? (