UNPKG

aura-glass

Version:

A comprehensive glassmorphism design system for React applications with 142+ production-ready components

269 lines (266 loc) 10.1 kB
'use client'; import { jsx, jsxs } from 'react/jsx-runtime'; import { cn } from '../../../../lib/utilsComprehensive.js'; import React, { forwardRef, useState } from 'react'; import { GlassCore } from '../../../../primitives/GlassCore.js'; import '../../../../primitives/glass/GlassAdvanced.js'; import '../../../../primitives/OptimizedGlassCore.js'; import '../../../../primitives/glass/OptimizedGlassAdvanced.js'; import '../../../../primitives/MotionNative.js'; import '../../../../primitives/motion/MotionFramer.js'; import { GlassButton } from '../../../button/GlassButton.js'; import { GlassBadge } from '../../../data-display/GlassBadge.js'; import { VStack, HStack } from '../../../layout/GlassStack.js'; /** * TableWidget component * Display tabular data with sorting and styling */ const TableWidget = /*#__PURE__*/forwardRef(({ data, variant = "default", size = "md", maxRows = 5, showHeader = true, sortable = true, showRowNumbers = false, hoverable = true, striped = false, loading = false, actions, onRowClick, onSort, className, ...props }, ref) => { const [sortColumn, setSortColumn] = useState(null); const [sortDirection, setSortDirection] = useState("asc"); const sizeClasses = { sm: { padding: "glass-p-3", title: "glass-text-sm", subtitle: "glass-text-xs", cell: "glass-px-2 glass-py-1 glass-text-xs", header: "glass-px-2 glass-py-2 glass-text-xs" }, md: { padding: "glass-p-4", title: "glass-text-base", subtitle: "glass-text-sm", cell: "glass-px-3 glass-py-2 glass-text-sm", header: "glass-px-3 glass-py-2 glass-text-sm" }, lg: { padding: "glass-p-6", title: "glass-text-lg", subtitle: "glass-text-base", cell: "glass-px-4 glass-py-3 glass-text-base", header: "glass-px-4 glass-py-3 glass-text-base" } }; const config = sizeClasses?.[size]; // Handle column sort const handleSort = columnId => { const column = data?.columns.find(col => col.id === columnId); if (!column?.sortable && !sortable) return; const newDirection = sortColumn === columnId && sortDirection === "asc" ? "desc" : "asc"; setSortColumn(columnId); setSortDirection(newDirection); onSort?.(columnId, newDirection); }; // Sort data if local sorting const sortedRows = React.useMemo(() => { if (!sortColumn || onSort) return data?.rows || []; const column = (data?.columns || []).find(col => col.id === sortColumn); if (!column) return data?.rows || []; return [...(data?.rows || [])].sort((a, b) => { const aValue = a[column.accessor]; const bValue = b?.[column.accessor]; if (aValue < bValue) return sortDirection === "asc" ? -1 : 1; if (aValue > bValue) return sortDirection === "asc" ? 1 : -1; return 0; }); }, [data?.rows, data?.columns, sortColumn, sortDirection, onSort]); const displayRows = sortedRows.slice(0, maxRows); const renderCellContent = (column, row) => { const value = row?.[column.accessor]; if (column.render) { return column.render(value, row); } // Default renderers for common data types if (typeof value === "boolean") { return jsx(GlassBadge, { "data-glass-component": true, variant: value ? "success" : "error", size: "xs", children: value ? "Yes" : "No" }); } if (typeof value === "number") { return value.toLocaleString(); } if (value === null || value === undefined) { return jsx("span", { className: "glass-text-secondary", children: "\u2014" }); } return String(value); }; const renderTable = () => { if (loading) { return jsx("div", { className: "glass-flex glass-items-center glass-justify-center glass-py-8", children: jsx("div", { className: 'w-6 h-6 glass-border-2 glass-border-primary glass-border-t-transparent glass-radius-full animate-spin' }) }); } if ((displayRows?.length || 0) === 0) { return jsx("div", { className: "glass-flex glass-items-center glass-justify-center glass-py-8 glass-text-secondary", children: "No data available" }); } return jsx("div", { className: 'overflow-x-auto', children: jsxs("table", { className: "glass-w-full", children: [showHeader && jsx("thead", { children: jsxs("tr", { className: "glass-border-b glass-border-glass-border/20", children: [showRowNumbers && jsx("th", { className: cn(config.header, "w-12 text-left font-medium glass-text-secondary"), children: "#" }), (data?.columns || []).map(column => jsx("th", { className: cn(config.header, "font-medium glass-text-secondary", { "text-left": column.align === "left" || !column.align, "text-center": column.align === "center", "text-right": column.align === "right", "cursor-pointer hover:text-foreground": column.sortable || sortable }), style: { width: column.width }, onClick: e => handleSort(column.id), children: jsxs(HStack, { space: "xs", align: "center", className: "glass-justify-start", children: [jsx("span", { children: column.header }), (column.sortable || sortable) && jsxs("div", { className: "glass-flex glass-flex-col", children: [jsx("div", { className: cn("w-0 h-0 border-l-[3px] border-r-[3px] border-b-[4px] border-transparent", sortColumn === column.id && sortDirection === "asc" ? "border-b-primary" : "border-b-muted-foreground/30") }), jsx("div", { className: cn("w-0 h-0 border-l-[3px] border-r-[3px] border-t-[4px] border-transparent mt-0.5", sortColumn === column.id && sortDirection === "desc" ? "border-t-primary" : "border-t-muted-foreground/30") })] })] }) }, column.id))] }) }), jsx("tbody", { children: displayRows.map((row, index) => jsxs("tr", { className: cn("transition-colors animate-fade-in", { "bg-muted/20": striped && index % 2 === 1, "hover:bg-muted/30": hoverable, "cursor-pointer": onRowClick }), style: { animationDelay: `${Math.min(index, 15) * 50}ms`, animationFillMode: "both" }, onClick: e => onRowClick?.(row), children: [showRowNumbers && jsx("td", { className: cn(config.cell, "glass-text-secondary"), children: index + 1 }), (data?.columns || []).map(column => jsx("td", { className: cn(config.cell, "text-foreground", { "text-left": column.align === "left" || !column.align, "text-center": column.align === "center", "text-right": column.align === "right" }), children: renderCellContent(column, row) }, column.id))] }, row.id)) })] }) }); }; const renderContent = () => { switch (variant) { case "minimal": return renderTable(); case "compact": return jsxs(VStack, { space: "sm", children: [jsxs(HStack, { space: "sm", align: "center", justify: "between", children: [jsx("h3", { className: cn("font-medium text-foreground", config.title), children: data?.title || "Table" }), actions] }), renderTable()] }); default: return jsxs(VStack, { space: "md", children: [jsxs(HStack, { space: "sm", align: "center", justify: "between", children: [jsxs(VStack, { space: "xs", children: [jsx("h3", { className: cn("font-medium text-foreground", config.title), children: data?.title || "Table" }), data?.subtitle && jsx("p", { className: cn("glass-text-secondary", config.subtitle), children: data?.subtitle })] }), actions] }), data?.summary && jsxs(HStack, { space: "sm", align: "center", children: [data?.summary.total && jsxs("span", { className: "glass-text-sm glass-text-secondary", children: ["Total: ", data?.summary.total.toLocaleString()] }), data?.summary.filtered && data?.summary.filtered !== data?.summary.total && jsxs("span", { className: "glass-text-sm glass-text-secondary", children: ["Showing: ", data?.summary.filtered.toLocaleString()] }), data?.summary.message && jsx(GlassBadge, { variant: "outline", size: "xs", children: data?.summary.message })] }), jsx("div", { className: "glass-flex-1", children: renderTable() }), (data?.rows?.length || 0) > maxRows && jsxs(HStack, { space: "sm", align: "center", justify: "center", children: [jsxs("span", { className: "glass-text-xs glass-text-secondary", children: ["Showing ", maxRows, " of ", data?.rows?.length || 0, " rows"] }), jsx(GlassButton, { variant: "ghost", size: "xs", children: "View All" })] })] }); } }; return jsx(GlassCore, { ref: ref, className: cn("w-full h-full glass-radius-lg", config.padding, className), ...props, children: renderContent() }); }); TableWidget.displayName = "TableWidget"; export { TableWidget }; //# sourceMappingURL=TableWidget.js.map