import React from 'react';
import { Button, Checkbox, Input, Paragraph, ScrollView, Text, XStack, YStack } from 'tamagui';
import { getIcon } from '../IconMapper.jsx';
import { useGridView } from './context.js';
import { formatValueByColumn } from './utils.js';
import { getTypographyRoleProps } from '../../styles/index.js';
function renderToolbarItem(item) {
if (!item) {
return null;
}
if (React.isValidElement(item)) {
return item;
}
if (item.kind === 'button') {
const IconComponent = item.icon ? getIcon(item.icon) : null;
return (
: undefined}
onPress={item.onClick || item.onPress}
>
{item.label}
);
}
if (item.kind === 'text') {
return (
{item.text}
);
}
if (item.kind === 'search') {
const SearchIcon = getIcon('search');
return (
{SearchIcon ? : null}
item.onChange?.(value)}
backgroundColor="$bgPanel"
borderColor="$lineSubtle"
focusStyle={{ borderColor: '$accent' }}
/>
);
}
if (item.kind === 'node') {
return {item.node};
}
return {item};
}
function DefaultPanelRecordRenderer({ row }) {
const grid = useGridView();
const titleColumn =
grid.resolvedColumns.find((column) =>
['customer', 'name', 'title', 'label'].includes(column.field)
) ||
grid.resolvedColumns.find((column) => column.type === 'text') ||
grid.resolvedColumns[0];
const subtitleColumn = grid.resolvedColumns.find((column) =>
['description', 'region', 'owner', 'status'].includes(column.field)
);
const summaryColumns = grid.resolvedColumns.filter(
(column) => ![titleColumn?.field, subtitleColumn?.field, 'description'].includes(column.field)
);
return (
Record Summary
{titleColumn ? row?.[titleColumn.field] : row?.id}
{subtitleColumn ? (
{row?.[subtitleColumn.field] || ''}
) : null}
{summaryColumns.slice(0, 3).map((column) => (
{column.label}
{formatValueByColumn(row?.[column.field], column)}
))}
{summaryColumns.map((column) => (
{column.label}
{formatValueByColumn(row?.[column.field], column)}
))}
);
}
export function PanelToolBar({ items = [], visible = true }) {
if (visible === false) {
return null;
}
return (
{items.map((item, index) => (
{renderToolbarItem(item)}
))}
);
}
export function PanelFooterStatusBar({ text, visible = true }) {
const grid = useGridView();
if (visible === false) {
return null;
}
return (
{text || grid.statusText}
);
}
export function PanelHeader({ title, toolbarItems = [], visible = true, showDivider = true }) {
const grid = useGridView();
const RefreshIcon = getIcon('refresh');
const CloseIcon = getIcon('close');
if (visible === false) {
return null;
}
return (
{title}
: undefined}
onPress={grid.reload}
/>
{grid.closeable !== false ? (
: undefined}
onPress={grid.close}
/>
) : null}
);
}
export function PanelFooter({ toolbarItems = [], visible = true }) {
if (visible === false) {
return null;
}
return (
);
}
export function PanelBodyView({
visible = true,
recordRenderer: RecordRenderer = DefaultPanelRecordRenderer,
columns = 2
}) {
const grid = useGridView();
if (visible === false) {
return null;
}
if (grid.error) {
const ErrorIcon = getIcon('error');
return (
{ErrorIcon ? : null}
{grid.error}
);
}
if (grid.isLoading && !grid.rows.length) {
return (
Loading cards...
);
}
if (!grid.rows.length) {
const EmptyIcon = getIcon('folder');
return (
{EmptyIcon ? : null}
No records available
There's nothing to show here yet.
);
}
const responsiveColumns = typeof columns === 'number' ? columns : 2;
return (
{grid.rows.map((row) => {
const isSelected = grid.selectedIds.has(row.id);
return (
1 ? 320 : 240}
flex={1}
flexBasis={responsiveColumns > 1 ? '48%' : '100%'}
padding="$4"
borderWidth={1}
borderColor={isSelected ? '$accent' : '$lineSubtle'}
backgroundColor={isSelected ? '$accentBg' : '$bgPanel'}
borderRadius="$radiusLg"
gap="$3"
hoverStyle={isSelected ? undefined : { borderColor: '$lineStrong' }}
>
{grid.selectable ? (
grid.toggleSelectRow(row.id)}
borderColor="$lineStrong"
backgroundColor="$bgPanel"
focusStyle={{ borderColor: '$accent' }}
>
{(() => {
const Check = getIcon('check');
return Check ? : null;
})()}
) : null}
);
})}
{grid.isLoading ? (
Refreshing records...
) : null}
);
}