import React from 'react'; import './Table.css'; /* 表格(移动端)— 规格 §47。 结构:table(根)> viewport(横向滚动视口)> inner(原生 table)+ empty(空态)。 **横向滚动只发生在 viewport 上**(overflow-x: auto),页面整体不横向溢出(规格 §47.1); 根与视口都写 min-width: 0,否则内部 min-width 会把父级顶宽。 表头 sticky(不是 fixed:fixed 会脱出滚动容器,横向滚动时表头不跟随)。 mode=card 把小屏行摊成键值对,彻底不需要横向滚动。 rows 为二维数组或对象数组;cells 支持 { text, align, ellipsis, number, title }。 */ const ALIGN = { start: 'start', center: 'center', end: 'end', number: 'number' }; function cellOf(row, col, ci) { if (Array.isArray(row)) return { text: row[ci] }; if (row && typeof row === 'object') { const raw = row[col.key === undefined ? ci : col.key]; if (raw && typeof raw === 'object') return raw; return { text: raw }; } return { text: '' }; } function textOf(cell) { if (cell === null || cell === undefined) return ''; return String(cell.text === undefined ? cell : cell.text); } function alignOf(col, cell) { if (cell && cell.number) return 'number'; if (cell && cell.align && ALIGN[cell.align]) return cell.align; if (col && col.number) return 'number'; if (col && col.align && ALIGN[col.align]) return col.align; return 'start'; } export default function Table({ columns = [], rows = [], mode = 'scroll', size = 'default', stripe = false, bordered = false, clickable = false, caption = '', emptyText = '暂无数据', onSelect, children = null, }) { const card = mode === 'card'; const cls = 'kole-m-table' + ` kole-m-table--${card ? 'card' : 'scroll'}` + (size === 'compact' ? ' kole-m-table--compact' : '') + (stripe ? ' kole-m-table--stripe' : '') + (bordered ? ' kole-m-table--bordered' : '') + (clickable ? ' kole-m-table--clickable' : ''); const cols = (Array.isArray(columns) ? columns : []).map((c, i) => c && typeof c === 'object' ? c : { title: String(c === undefined ? '' : c), key: i } ); return (
{caption ? : null} {cols.map((col, ci) => ( ))} {rows.length ? ( {rows.map((row, ri) => { const rowDisabled = !!(row && row.disabled); const rowSelected = !!(row && row.selected); /* 可点行必须同时可聚焦:整行点击不能是唯一的键盘路径(规格 §47.6) */ const rowProps = clickable && !rowDisabled ? { tabIndex: 0, role: 'row', 'aria-selected': rowSelected ? 'true' : 'false', onKeyDown: (e) => { if (e.key !== 'Enter' && e.key !== ' ' && e.key !== 'Spacebar') return; e.preventDefault(); if (onSelect) onSelect(ri, row); }, } : { role: 'row' }; return ( { if (rowDisabled) return; if (onSelect) onSelect(ri, row); }} > {cols.map((col, ci) => { const cell = cellOf(row, col, ci); const align = alignOf(col, cell); return ( ); })} ); })} ) : null}
{caption}
{col && col.title !== undefined ? col.title : ''}
{textOf(cell)}
{rows.length ? null : (

{emptyText}

)} {children}
); }