import React, { useEffect, useRef } from 'react'; import { Button, Checkbox, ScrollView, Separator, Text, XStack, YStack } from 'tamagui'; import { getIcon } from '../IconMapper.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; 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; return ( ); })} ); } export function TableBodyView({ visible = true }) { const grid = useGridView(); const bodyRef = useViewportTracking(visible); if (visible === false) { return null; } const activeColumns = grid.visibleColumns?.length ? grid.visibleColumns : grid.resolvedColumns; if (grid.error) { return ( {grid.error} ); } return ( {grid.rows.map((row, index) => ( {grid.selectable || grid.nested ? : null} {activeColumns.map((column) => { const Renderer = column.renderer || DefaultGridCellRenderer; const cellValue = resolveCellValue(row, column); return ( ); })} ))} {!grid.rows.length && !grid.isLoading ? ( No records available There's nothing to show here yet. ) : null} {grid.isLoading && !grid.rows.length ? ( {[0, 1, 2].map((i) => ( ))} ) : null} ); } export function TableFooter({ visible = true }) { const grid = useGridView(); const FirstPageIcon = getIcon('first-page'); const PreviousPageIcon = getIcon('chevron-left'); const NextPageIcon = getIcon('chevron-right'); const LastPageIcon = getIcon('last-page'); if (visible === false) { return null; } return ( {grid.total} records