diff --git a/apps/playground/package.json b/apps/playground/package.json index ec82294cc..adc5204e7 100644 --- a/apps/playground/package.json +++ b/apps/playground/package.json @@ -27,12 +27,12 @@ "eslint": "^9.39.1", "eslint-plugin-react-hooks": "^7.0.1", "eslint-plugin-react-refresh": "^0.4.24", - "globals": "^15.14.0", + "globals": "^16.5.0", "postcss": "^8.5.6", "tailwindcss": "^3.4.19", "tailwindcss-animate": "^1.0.7", "typescript": "~5.7.3", - "vite": "^5.0.0", - "typescript-eslint": "^8.46.4" + "typescript-eslint": "^8.46.4", + "vite": "^5.0.0" } } diff --git a/apps/playground/src/data/examples.ts b/apps/playground/src/data/examples.ts index bd8ce568b..d9d619819 100644 --- a/apps/playground/src/data/examples.ts +++ b/apps/playground/src/data/examples.ts @@ -861,6 +861,264 @@ export const examples = { ] } ] +}`, + + // Enterprise Data Table - Airtable-like functionality + 'enterprise-table': `{ + "type": "div", + "className": "space-y-6", + "body": [ + { + "type": "div", + "className": "space-y-2", + "body": [ + { + "type": "text", + "content": "Enterprise Data Table", + "className": "text-2xl font-bold" + }, + { + "type": "text", + "content": "Full-featured data table with sorting, filtering, pagination, row selection, export, column resizing, and column reordering - similar to Airtable", + "className": "text-muted-foreground" + } + ] + }, + { + "type": "data-table", + "caption": "User Management Table", + "pagination": true, + "pageSize": 10, + "searchable": true, + "selectable": true, + "sortable": true, + "exportable": true, + "rowActions": true, + "resizableColumns": true, + "reorderableColumns": true, + "columns": [ + { + "header": "ID", + "accessorKey": "id", + "width": "80px", + "sortable": true + }, + { + "header": "Name", + "accessorKey": "name", + "sortable": true + }, + { + "header": "Email", + "accessorKey": "email", + "sortable": true + }, + { + "header": "Department", + "accessorKey": "department", + "sortable": true + }, + { + "header": "Status", + "accessorKey": "status", + "width": "100px", + "sortable": true + }, + { + "header": "Role", + "accessorKey": "role", + "sortable": true + }, + { + "header": "Join Date", + "accessorKey": "joinDate", + "sortable": true + } + ], + "data": [ + { + "id": 1, + "name": "John Doe", + "email": "john.doe@company.com", + "department": "Engineering", + "status": "Active", + "role": "Senior Developer", + "joinDate": "2022-01-15" + }, + { + "id": 2, + "name": "Jane Smith", + "email": "jane.smith@company.com", + "department": "Product", + "status": "Active", + "role": "Product Manager", + "joinDate": "2021-11-20" + }, + { + "id": 3, + "name": "Bob Johnson", + "email": "bob.johnson@company.com", + "department": "Sales", + "status": "Inactive", + "role": "Sales Representative", + "joinDate": "2020-05-10" + }, + { + "id": 4, + "name": "Alice Williams", + "email": "alice.williams@company.com", + "department": "Engineering", + "status": "Active", + "role": "Tech Lead", + "joinDate": "2019-08-22" + }, + { + "id": 5, + "name": "Charlie Brown", + "email": "charlie.brown@company.com", + "department": "Marketing", + "status": "Active", + "role": "Marketing Manager", + "joinDate": "2021-03-14" + }, + { + "id": 6, + "name": "Diana Prince", + "email": "diana.prince@company.com", + "department": "HR", + "status": "Active", + "role": "HR Director", + "joinDate": "2018-12-01" + }, + { + "id": 7, + "name": "Ethan Hunt", + "email": "ethan.hunt@company.com", + "department": "Operations", + "status": "Inactive", + "role": "Operations Coordinator", + "joinDate": "2022-06-30" + }, + { + "id": 8, + "name": "Fiona Gallagher", + "email": "fiona.gallagher@company.com", + "department": "Finance", + "status": "Active", + "role": "Financial Analyst", + "joinDate": "2020-09-18" + }, + { + "id": 9, + "name": "George Wilson", + "email": "george.wilson@company.com", + "department": "Engineering", + "status": "Active", + "role": "DevOps Engineer", + "joinDate": "2021-04-25" + }, + { + "id": 10, + "name": "Hannah Montana", + "email": "hannah.montana@company.com", + "department": "Product", + "status": "Active", + "role": "Product Designer", + "joinDate": "2022-02-10" + }, + { + "id": 11, + "name": "Ivan Drago", + "email": "ivan.drago@company.com", + "department": "Engineering", + "status": "Inactive", + "role": "Backend Developer", + "joinDate": "2020-07-12" + }, + { + "id": 12, + "name": "Julia Roberts", + "email": "julia.roberts@company.com", + "department": "Marketing", + "status": "Active", + "role": "Content Strategist", + "joinDate": "2021-10-05" + }, + { + "id": 13, + "name": "Kevin Hart", + "email": "kevin.hart@company.com", + "department": "Sales", + "status": "Active", + "role": "Sales Director", + "joinDate": "2019-03-20" + }, + { + "id": 14, + "name": "Laura Croft", + "email": "laura.croft@company.com", + "department": "Operations", + "status": "Active", + "role": "Operations Analyst", + "joinDate": "2021-12-08" + }, + { + "id": 15, + "name": "Mike Tyson", + "email": "mike.tyson@company.com", + "department": "Operations", + "status": "Active", + "role": "Operations Manager", + "joinDate": "2021-07-05" + } + ] + } + ] +}`, + + 'data-table-simple': `{ + "type": "div", + "className": "space-y-6", + "body": [ + { + "type": "div", + "className": "space-y-2", + "body": [ + { + "type": "text", + "content": "Simple Data Table", + "className": "text-2xl font-bold" + }, + { + "type": "text", + "content": "Minimal configuration with essential features only", + "className": "text-muted-foreground" + } + ] + }, + { + "type": "data-table", + "pagination": false, + "searchable": false, + "selectable": false, + "sortable": true, + "exportable": false, + "rowActions": false, + "columns": [ + { "header": "Product", "accessorKey": "product" }, + { "header": "Price", "accessorKey": "price" }, + { "header": "Stock", "accessorKey": "stock" }, + { "header": "Category", "accessorKey": "category" } + ], + "data": [ + { "product": "Laptop", "price": "$999", "stock": "45", "category": "Electronics" }, + { "product": "Mouse", "price": "$29", "stock": "150", "category": "Accessories" }, + { "product": "Keyboard", "price": "$79", "stock": "89", "category": "Accessories" }, + { "product": "Monitor", "price": "$299", "stock": "32", "category": "Electronics" }, + { "product": "Desk Chair", "price": "$199", "stock": "18", "category": "Furniture" } + ] + } + ] }` }; @@ -869,6 +1127,6 @@ export type ExampleKey = keyof typeof examples; export const exampleCategories = { 'Primitives': ['simple-page', 'input-states', 'button-variants'], 'Layouts': ['grid-layout', 'dashboard', 'tabs-demo'], + 'Data Display': ['calendar-view', 'enterprise-table', 'data-table-simple'], 'Forms': ['form-demo', 'airtable-form'], - 'Data Display': ['calendar-view'] }; diff --git a/apps/playground/test-import.js b/apps/playground/test-import.js new file mode 100644 index 000000000..ff75fd40e --- /dev/null +++ b/apps/playground/test-import.js @@ -0,0 +1,20 @@ +try { + await import('eslint/config'); + console.log('eslint/config imported successfully'); +} catch (e) { + console.error('Failed to import eslint/config:', e.message); +} + +try { + await import('eslint-plugin-react-hooks'); + console.log('eslint-plugin-react-hooks imported successfully'); +} catch (e) { + console.error('Failed to import eslint-plugin-react-hooks:', e.message); +} + +try { + await import('typescript-eslint'); + console.log('typescript-eslint imported successfully'); +} catch (e) { + console.error('Failed to import typescript-eslint:', e.message); +} diff --git a/packages/components/src/renderers/complex/__tests__/data-table.test.ts b/packages/components/src/renderers/complex/__tests__/data-table.test.ts new file mode 100644 index 000000000..854141a4c --- /dev/null +++ b/packages/components/src/renderers/complex/__tests__/data-table.test.ts @@ -0,0 +1,52 @@ +import { describe, it, expect, beforeAll } from 'vitest'; +import { ComponentRegistry } from '@object-ui/core'; + +// Import the component to ensure it's registered +import '../data-table'; + +describe('Data Table Component', () => { + it('should register data-table component', () => { + expect(ComponentRegistry.has('data-table')).toBe(true); + }); + + it('should have correct component metadata', () => { + const config = ComponentRegistry.getConfig('data-table'); + expect(config).toBeDefined(); + expect(config?.label).toBe('Data Table'); + expect(config?.inputs).toBeDefined(); + expect(config?.defaultProps).toBeDefined(); + }); + + it('should have required inputs defined', () => { + const config = ComponentRegistry.getConfig('data-table'); + const inputNames = config?.inputs?.map(input => input.name) || []; + + expect(inputNames).toContain('columns'); + expect(inputNames).toContain('data'); + expect(inputNames).toContain('pagination'); + expect(inputNames).toContain('searchable'); + expect(inputNames).toContain('selectable'); + expect(inputNames).toContain('sortable'); + expect(inputNames).toContain('exportable'); + expect(inputNames).toContain('rowActions'); + }); + + it('should have default props with sample data', () => { + const config = ComponentRegistry.getConfig('data-table'); + expect(config?.defaultProps).toBeDefined(); + expect(config?.defaultProps?.columns).toBeDefined(); + expect(Array.isArray(config?.defaultProps?.columns)).toBe(true); + expect(config?.defaultProps?.data).toBeDefined(); + expect(Array.isArray(config?.defaultProps?.data)).toBe(true); + }); + + it('should have correct default feature flags', () => { + const config = ComponentRegistry.getConfig('data-table'); + expect(config?.defaultProps?.pagination).toBe(true); + expect(config?.defaultProps?.searchable).toBe(true); + expect(config?.defaultProps?.selectable).toBe(true); + expect(config?.defaultProps?.sortable).toBe(true); + expect(config?.defaultProps?.exportable).toBe(true); + expect(config?.defaultProps?.rowActions).toBe(true); + }); +}); diff --git a/packages/components/src/renderers/complex/data-table.tsx b/packages/components/src/renderers/complex/data-table.tsx new file mode 100644 index 000000000..0c4c6d58f --- /dev/null +++ b/packages/components/src/renderers/complex/data-table.tsx @@ -0,0 +1,714 @@ +// Enterprise-level DataTable Component (Airtable-like) +import React, { useState, useMemo, useRef, useEffect } from 'react'; +import { ComponentRegistry } from '@object-ui/core'; +import { + Table, + TableHeader, + TableBody, + TableFooter, + TableHead, + TableRow, + TableCell, + TableCaption +} from '@/ui/table'; +import { Button } from '@/ui/button'; +import { Input } from '@/ui/input'; +import { Checkbox } from '@/ui/checkbox'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/ui/select'; +import { + ChevronUp, + ChevronDown, + ChevronsUpDown, + Search, + Download, + Edit, + Trash2, + ChevronLeft, + ChevronRight, + ChevronsLeft, + ChevronsRight, + GripVertical, +} from 'lucide-react'; + +type SortDirection = 'asc' | 'desc' | null; + +/** + * Column configuration for the data table. + * @interface Column + */ +interface Column { + /** Display name of the column */ + header: string; + /** Key to access the data field in each row object */ + accessorKey: string; + /** Optional CSS classes for the column header */ + className?: string; + /** Optional CSS classes for the column cells */ + cellClassName?: string; + /** Width of the column (e.g., '80px' or 80) */ + width?: string | number; + /** Whether sorting is enabled for this column (default: true) */ + sortable?: boolean; + /** Whether filtering is enabled for this column (default: true) */ + filterable?: boolean; + /** Whether column resizing is enabled (default: true) */ + resizable?: boolean; +} + +/** + * Schema definition for the enterprise data table component. + * Supports sorting, pagination, search, row selection, CSV export, and row actions. + * @interface DataTableSchema + */ +interface DataTableSchema { + /** Optional caption text displayed above the table */ + caption?: string; + /** Array of column definitions */ + columns: Column[]; + /** Array of data objects to display. Each object should have an 'id' field for stable row identification */ + data: any[]; + /** Enable/disable pagination (default: true) */ + pagination?: boolean; + /** Number of rows per page (default: 10) */ + pageSize?: number; + /** Enable/disable search across all columns (default: true) */ + searchable?: boolean; + /** Enable/disable row selection with checkboxes (default: false) */ + selectable?: boolean; + /** Enable/disable column sorting (default: true) */ + sortable?: boolean; + /** Enable/disable CSV export button (default: false) */ + exportable?: boolean; + /** Show/hide edit and delete action buttons for each row (default: false) */ + rowActions?: boolean; + /** Enable/disable column resizing by dragging (default: true) */ + resizableColumns?: boolean; + /** Enable/disable column reordering by dragging (default: true) */ + reorderableColumns?: boolean; + /** Callback function triggered when the edit button is clicked */ + onRowEdit?: (row: any) => void; + /** Callback function triggered when the delete button is clicked */ + onRowDelete?: (row: any) => void; + /** Callback function triggered when row selection changes, receives array of selected rows */ + onSelectionChange?: (selectedRows: any[]) => void; + /** Callback function triggered when columns are reordered */ + onColumnsReorder?: (columns: Column[]) => void; + /** Optional CSS classes for the table container */ + className?: string; +} + +/** + * Enterprise-level data table component with Airtable-like features. + * + * Provides comprehensive table functionality including: + * - Multi-column sorting (ascending/descending/none) + * - Real-time search across all columns + * - Pagination with configurable page sizes + * - Row selection with persistence across pages + * - CSV export of filtered/sorted data + * - Row action buttons (edit/delete) + * + * @example + * ```json + * { + * "type": "data-table", + * "pagination": true, + * "searchable": true, + * "selectable": true, + * "sortable": true, + * "exportable": true, + * "rowActions": true, + * "columns": [ + * { "header": "ID", "accessorKey": "id", "width": "80px" }, + * { "header": "Name", "accessorKey": "name" } + * ], + * "data": [ + * { "id": 1, "name": "John Doe" } + * ] + * } + * ``` + * + * @param {Object} props - Component props + * @param {DataTableSchema} props.schema - Table schema configuration + * @returns {JSX.Element} Rendered data table component + */ +const DataTableRenderer = ({ schema }: { schema: DataTableSchema }) => { + const { + caption, + columns: initialColumns = [], + data = [], + pagination = true, + pageSize: initialPageSize = 10, + searchable = true, + selectable = false, + sortable = true, + exportable = false, + rowActions = false, + resizableColumns = true, + reorderableColumns = true, + className, + } = schema; + + // State management + const [searchQuery, setSearchQuery] = useState(''); + const [sortColumn, setSortColumn] = useState(null); + const [sortDirection, setSortDirection] = useState(null); + const [selectedRowIds, setSelectedRowIds] = useState>(new Set()); + const [currentPage, setCurrentPage] = useState(1); + const [pageSize, setPageSize] = useState(initialPageSize); + const [columns, setColumns] = useState(initialColumns); + const [columnWidths, setColumnWidths] = useState>({}); + const [draggedColumn, setDraggedColumn] = useState(null); + const [dragOverColumn, setDragOverColumn] = useState(null); + + // Refs for column resizing + const resizingColumn = useRef(null); + const startX = useRef(0); + const startWidth = useRef(0); + + // Update columns when schema changes + useEffect(() => { + setColumns(initialColumns); + }, [initialColumns]); + + // Filtering + const filteredData = useMemo(() => { + if (!searchQuery) return data; + + return data.filter((row) => + columns.some((col) => { + const value = row[col.accessorKey]; + return value?.toString().toLowerCase().includes(searchQuery.toLowerCase()); + }) + ); + }, [data, searchQuery, columns]); + + // Sorting + const sortedData = useMemo(() => { + if (!sortColumn || !sortDirection) return filteredData; + + return [...filteredData].sort((a, b) => { + const aValue = a[sortColumn]; + const bValue = b[sortColumn]; + + if (aValue === bValue) return 0; + + const comparison = aValue < bValue ? -1 : 1; + return sortDirection === 'asc' ? comparison : -comparison; + }); + }, [filteredData, sortColumn, sortDirection]); + + // Pagination + const totalPages = Math.ceil(sortedData.length / pageSize); + const paginatedData = pagination + ? sortedData.slice((currentPage - 1) * pageSize, currentPage * pageSize) + : sortedData; + + /** + * Generates a unique identifier for each row to maintain stable selection state + * across pagination and sorting operations. + * + * @param {any} row - The data row object + * @param {number} index - The row's index in the dataset + * @returns {string | number} Unique row identifier (uses 'id' field if available, falls back to index) + */ + const getRowId = (row: any, index: number) => { + // Try to use 'id' field, fall back to index + return row.id !== undefined ? row.id : `row-${index}`; + }; + + // Handlers + const handleSort = (columnKey: string) => { + if (!sortable) return; + + if (sortColumn === columnKey) { + if (sortDirection === 'asc') { + setSortDirection('desc'); + } else if (sortDirection === 'desc') { + setSortDirection(null); + setSortColumn(null); + } + } else { + setSortColumn(columnKey); + setSortDirection('asc'); + } + }; + + const handleSelectAll = (checked: boolean) => { + const newSelected = new Set(); + if (checked) { + paginatedData.forEach((row, idx) => { + const globalIndex = (currentPage - 1) * pageSize + idx; + const rowId = getRowId(row, globalIndex); + newSelected.add(rowId); + }); + } + setSelectedRowIds(newSelected); + + // Call callback if provided + if (schema.onSelectionChange) { + const selectedData = sortedData.filter((row, idx) => { + const rowId = getRowId(row, idx); + return newSelected.has(rowId); + }); + schema.onSelectionChange(selectedData); + } + }; + + const handleSelectRow = (rowId: any, checked: boolean) => { + const newSelected = new Set(selectedRowIds); + if (checked) { + newSelected.add(rowId); + } else { + newSelected.delete(rowId); + } + setSelectedRowIds(newSelected); + + // Call callback if provided + if (schema.onSelectionChange) { + const selectedData = sortedData.filter((row, idx) => { + const id = getRowId(row, idx); + return newSelected.has(id); + }); + schema.onSelectionChange(selectedData); + } + }; + + const handleExport = () => { + const csvContent = [ + columns.map(col => col.header).join(','), + ...sortedData.map(row => + columns.map(col => JSON.stringify(row[col.accessorKey] || '')).join(',') + ) + ].join('\n'); + + const blob = new Blob([csvContent], { type: 'text/csv' }); + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = 'table-export.csv'; + a.click(); + window.URL.revokeObjectURL(url); + }; + + const getSortIcon = (columnKey: string) => { + if (sortColumn !== columnKey) { + return ; + } + if (sortDirection === 'asc') { + return ; + } + return ; + }; + + // Column resizing handlers + const handleResizeStart = (e: React.MouseEvent, columnKey: string) => { + if (!resizableColumns) return; + e.preventDefault(); + e.stopPropagation(); + + resizingColumn.current = columnKey; + startX.current = e.clientX; + + const headerCell = (e.target as HTMLElement).closest('th'); + if (headerCell) { + startWidth.current = headerCell.offsetWidth; + } + + document.addEventListener('mousemove', handleResizeMove); + document.addEventListener('mouseup', handleResizeEnd); + }; + + const handleResizeMove = (e: MouseEvent) => { + if (!resizingColumn.current) return; + + const diff = e.clientX - startX.current; + const newWidth = Math.max(50, startWidth.current + diff); // Min width 50px + + setColumnWidths(prev => ({ + ...prev, + [resizingColumn.current!]: newWidth + })); + }; + + const handleResizeEnd = () => { + resizingColumn.current = null; + document.removeEventListener('mousemove', handleResizeMove); + document.removeEventListener('mouseup', handleResizeEnd); + }; + + // Column reordering handlers + const handleColumnDragStart = (e: React.DragEvent, index: number) => { + if (!reorderableColumns) return; + setDraggedColumn(index); + e.dataTransfer.effectAllowed = 'move'; + }; + + const handleColumnDragOver = (e: React.DragEvent, index: number) => { + if (!reorderableColumns) return; + e.preventDefault(); + e.dataTransfer.dropEffect = 'move'; + setDragOverColumn(index); + }; + + const handleColumnDrop = (e: React.DragEvent, dropIndex: number) => { + if (!reorderableColumns || draggedColumn === null) return; + e.preventDefault(); + + if (draggedColumn === dropIndex) { + setDraggedColumn(null); + setDragOverColumn(null); + return; + } + + const newColumns = [...columns]; + const [removed] = newColumns.splice(draggedColumn, 1); + newColumns.splice(dropIndex, 0, removed); + + setColumns(newColumns); + setDraggedColumn(null); + setDragOverColumn(null); + + // Call callback if provided + if (schema.onColumnsReorder) { + schema.onColumnsReorder(newColumns); + } + }; + + const handleColumnDragEnd = () => { + setDraggedColumn(null); + setDragOverColumn(null); + }; + + // Cleanup on unmount + useEffect(() => { + return () => { + document.removeEventListener('mousemove', handleResizeMove); + document.removeEventListener('mouseup', handleResizeEnd); + }; + }, []); + + // Check if all rows on current page are selected + const allPageRowsSelected = paginatedData.length > 0 && paginatedData.every((row, idx) => { + const globalIndex = (currentPage - 1) * pageSize + idx; + const rowId = getRowId(row, globalIndex); + return selectedRowIds.has(rowId); + }); + + const somePageRowsSelected = paginatedData.some((row, idx) => { + const globalIndex = (currentPage - 1) * pageSize + idx; + const rowId = getRowId(row, globalIndex); + return selectedRowIds.has(rowId); + }) && !allPageRowsSelected; + + return ( +
+ {/* Toolbar */} +
+
+ {searchable && ( +
+ + { + setSearchQuery(e.target.value); + setCurrentPage(1); + }} + className="pl-8" + /> +
+ )} +
+ +
+ {exportable && ( + + )} + + {selectable && selectedRowIds.size > 0 && ( +
+ {selectedRowIds.size} selected +
+ )} +
+
+ + {/* Table */} +
+ + {caption && {caption}} + + + {selectable && ( + + + + )} + {columns.map((col, index) => { + const columnWidth = columnWidths[col.accessorKey] || col.width; + const isDragging = draggedColumn === index; + const isDragOver = dragOverColumn === index; + + return ( + handleColumnDragStart(e, index)} + onDragOver={(e) => handleColumnDragOver(e, index)} + onDrop={(e) => handleColumnDrop(e, index)} + onDragEnd={handleColumnDragEnd} + onClick={() => sortable && col.sortable !== false && handleSort(col.accessorKey)} + > +
+
+ {reorderableColumns && ( + + )} + {col.header} + {sortable && col.sortable !== false && getSortIcon(col.accessorKey)} +
+ {resizableColumns && col.resizable !== false && ( +
handleResizeStart(e, col.accessorKey)} + onClick={(e) => e.stopPropagation()} + /> + )} +
+ + ); + })} + {rowActions && ( + Actions + )} + + + + {paginatedData.length === 0 ? ( + + + No data available + + + ) : ( + paginatedData.map((row, rowIndex) => { + const globalIndex = (currentPage - 1) * pageSize + rowIndex; + const rowId = getRowId(row, globalIndex); + const isSelected = selectedRowIds.has(rowId); + + return ( + + {selectable && ( + + handleSelectRow(rowId, checked as boolean)} + /> + + )} + {columns.map((col, colIndex) => { + const columnWidth = columnWidths[col.accessorKey] || col.width; + return ( + + {row[col.accessorKey]} + + ); + })} + {rowActions && ( + +
+ + +
+
+ )} +
+ ); + }) + )} +
+
+
+ + {/* Pagination */} + {pagination && sortedData.length > 0 && ( +
+
+ Rows per page: + +
+ +
+ + Page {currentPage} of {totalPages} ({sortedData.length} total) + +
+ + + + +
+
+
+ )} +
+ ); +}; + +// Register the component +ComponentRegistry.register('data-table', DataTableRenderer, { + label: 'Data Table', + icon: 'table', + inputs: [ + { name: 'caption', type: 'string', label: 'Caption' }, + { + name: 'columns', + type: 'array', + label: 'Columns', + description: 'Array of { header, accessorKey, className, width, sortable, filterable, resizable }', + required: true, + }, + { + name: 'data', + type: 'array', + label: 'Data', + description: 'Array of data objects', + required: true, + }, + { name: 'pagination', type: 'boolean', label: 'Enable Pagination', defaultValue: true }, + { name: 'pageSize', type: 'number', label: 'Page Size', defaultValue: 10 }, + { name: 'searchable', type: 'boolean', label: 'Enable Search', defaultValue: true }, + { name: 'selectable', type: 'boolean', label: 'Enable Row Selection', defaultValue: false }, + { name: 'sortable', type: 'boolean', label: 'Enable Sorting', defaultValue: true }, + { name: 'exportable', type: 'boolean', label: 'Enable Export', defaultValue: false }, + { name: 'rowActions', type: 'boolean', label: 'Show Row Actions', defaultValue: false }, + { name: 'resizableColumns', type: 'boolean', label: 'Enable Column Resizing', defaultValue: true }, + { name: 'reorderableColumns', type: 'boolean', label: 'Enable Column Reordering', defaultValue: true }, + { name: 'className', type: 'string', label: 'CSS Class' }, + ], + defaultProps: { + caption: 'Enterprise Data Table', + pagination: true, + pageSize: 10, + searchable: true, + selectable: true, + sortable: true, + exportable: true, + rowActions: true, + resizableColumns: true, + reorderableColumns: true, + columns: [ + { header: 'ID', accessorKey: 'id', width: '80px' }, + { header: 'Name', accessorKey: 'name' }, + { header: 'Email', accessorKey: 'email' }, + { header: 'Status', accessorKey: 'status' }, + { header: 'Role', accessorKey: 'role' }, + ], + data: [ + { id: 1, name: 'John Doe', email: 'john@example.com', status: 'Active', role: 'Admin' }, + { id: 2, name: 'Jane Smith', email: 'jane@example.com', status: 'Active', role: 'User' }, + { id: 3, name: 'Bob Johnson', email: 'bob@example.com', status: 'Inactive', role: 'User' }, + { id: 4, name: 'Alice Williams', email: 'alice@example.com', status: 'Active', role: 'Manager' }, + { id: 5, name: 'Charlie Brown', email: 'charlie@example.com', status: 'Active', role: 'User' }, + { id: 6, name: 'Diana Prince', email: 'diana@example.com', status: 'Active', role: 'Admin' }, + { id: 7, name: 'Ethan Hunt', email: 'ethan@example.com', status: 'Inactive', role: 'User' }, + { id: 8, name: 'Fiona Gallagher', email: 'fiona@example.com', status: 'Active', role: 'User' }, + { id: 9, name: 'George Wilson', email: 'george@example.com', status: 'Active', role: 'Manager' }, + { id: 10, name: 'Hannah Montana', email: 'hannah@example.com', status: 'Active', role: 'User' }, + { id: 11, name: 'Ivan Drago', email: 'ivan@example.com', status: 'Inactive', role: 'User' }, + { id: 12, name: 'Julia Roberts', email: 'julia@example.com', status: 'Active', role: 'Admin' }, + ], + }, +}); diff --git a/packages/components/src/renderers/complex/index.ts b/packages/components/src/renderers/complex/index.ts index ad1248619..8f5e11331 100644 --- a/packages/components/src/renderers/complex/index.ts +++ b/packages/components/src/renderers/complex/index.ts @@ -5,5 +5,6 @@ import './scroll-area'; import './resizable'; import './scroll-area'; import './table'; +import './data-table'; import './timeline'; import './calendar-view'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7fecc417b..7cbf604bc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -125,8 +125,8 @@ importers: specifier: ^0.4.24 version: 0.4.26(eslint@9.39.2(jiti@1.21.7)) globals: - specifier: ^15.14.0 - version: 15.15.0 + specifier: ^16.5.0 + version: 16.5.0 postcss: specifier: ^8.5.6 version: 8.5.6 @@ -478,7 +478,7 @@ importers: version: 5.9.3 vitest: specifier: ^1.0.0 - version: 1.6.1(@types/node@24.10.8)(@vitest/ui@2.1.9(vitest@2.1.9))(happy-dom@20.1.0)(jsdom@27.4.0) + version: 1.6.1(@types/node@24.10.8)(@vitest/ui@2.1.9)(happy-dom@20.1.0)(jsdom@27.4.0) packages/designer: dependencies: @@ -512,7 +512,7 @@ importers: version: 14.6.1(@testing-library/dom@10.4.1) '@vitejs/plugin-react': specifier: ^5.1.2 - version: 5.1.2(vite@5.4.21(@types/node@24.10.8)) + version: 5.1.2(vite@7.3.1(@types/node@24.10.8)(jiti@1.21.7)) packages/react: dependencies: @@ -791,138 +791,294 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.27.2': + resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.21.5': resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} engines: {node: '>=12'} cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.27.2': + resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.21.5': resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} engines: {node: '>=12'} cpu: [arm] os: [android] + '@esbuild/android-arm@0.27.2': + resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.21.5': resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} engines: {node: '>=12'} cpu: [x64] os: [android] + '@esbuild/android-x64@0.27.2': + resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.21.5': resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.27.2': + resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.21.5': resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} engines: {node: '>=12'} cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.27.2': + resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.21.5': resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.27.2': + resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.21.5': resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.27.2': + resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.21.5': resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} engines: {node: '>=12'} cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.27.2': + resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.21.5': resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} engines: {node: '>=12'} cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.27.2': + resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.21.5': resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} engines: {node: '>=12'} cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.27.2': + resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.21.5': resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} engines: {node: '>=12'} cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.27.2': + resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.21.5': resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.27.2': + resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.21.5': resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.27.2': + resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.21.5': resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.27.2': + resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.21.5': resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} engines: {node: '>=12'} cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.27.2': + resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.21.5': resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} engines: {node: '>=12'} cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.27.2': + resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.27.2': + resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-x64@0.21.5': resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.27.2': + resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.2': + resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.21.5': resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.27.2': + resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.2': + resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + '@esbuild/sunos-x64@0.21.5': resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} engines: {node: '>=12'} cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.27.2': + resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.21.5': resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} engines: {node: '>=12'} cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.27.2': + resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.21.5': resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} engines: {node: '>=12'} cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.27.2': + resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.21.5': resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} engines: {node: '>=12'} cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.27.2': + resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.9.1': resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2737,6 +2893,11 @@ packages: engines: {node: '>=12'} hasBin: true + esbuild@0.27.2: + resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} + engines: {node: '>=18'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -2958,10 +3119,6 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} - globals@15.15.0: - resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} - engines: {node: '>=18'} - globals@16.5.0: resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==} engines: {node: '>=18'} @@ -4338,6 +4495,46 @@ packages: terser: optional: true + vite@7.3.1: + resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + vitepress@1.6.4: resolution: {integrity: sha512-+2ym1/+0VVrbhNyRoFFesVvBvHAVMZMK0rw60E3X/5349M1GuVdKeazuksqopEdvkKwKGs21Q729jX81/bkBJg==} hasBin: true @@ -4825,72 +5022,150 @@ snapshots: '@esbuild/aix-ppc64@0.21.5': optional: true + '@esbuild/aix-ppc64@0.27.2': + optional: true + '@esbuild/android-arm64@0.21.5': optional: true + '@esbuild/android-arm64@0.27.2': + optional: true + '@esbuild/android-arm@0.21.5': optional: true + '@esbuild/android-arm@0.27.2': + optional: true + '@esbuild/android-x64@0.21.5': optional: true + '@esbuild/android-x64@0.27.2': + optional: true + '@esbuild/darwin-arm64@0.21.5': optional: true + '@esbuild/darwin-arm64@0.27.2': + optional: true + '@esbuild/darwin-x64@0.21.5': optional: true + '@esbuild/darwin-x64@0.27.2': + optional: true + '@esbuild/freebsd-arm64@0.21.5': optional: true + '@esbuild/freebsd-arm64@0.27.2': + optional: true + '@esbuild/freebsd-x64@0.21.5': optional: true + '@esbuild/freebsd-x64@0.27.2': + optional: true + '@esbuild/linux-arm64@0.21.5': optional: true + '@esbuild/linux-arm64@0.27.2': + optional: true + '@esbuild/linux-arm@0.21.5': optional: true + '@esbuild/linux-arm@0.27.2': + optional: true + '@esbuild/linux-ia32@0.21.5': optional: true + '@esbuild/linux-ia32@0.27.2': + optional: true + '@esbuild/linux-loong64@0.21.5': optional: true + '@esbuild/linux-loong64@0.27.2': + optional: true + '@esbuild/linux-mips64el@0.21.5': optional: true + '@esbuild/linux-mips64el@0.27.2': + optional: true + '@esbuild/linux-ppc64@0.21.5': optional: true + '@esbuild/linux-ppc64@0.27.2': + optional: true + '@esbuild/linux-riscv64@0.21.5': optional: true + '@esbuild/linux-riscv64@0.27.2': + optional: true + '@esbuild/linux-s390x@0.21.5': optional: true + '@esbuild/linux-s390x@0.27.2': + optional: true + '@esbuild/linux-x64@0.21.5': optional: true + '@esbuild/linux-x64@0.27.2': + optional: true + + '@esbuild/netbsd-arm64@0.27.2': + optional: true + '@esbuild/netbsd-x64@0.21.5': optional: true + '@esbuild/netbsd-x64@0.27.2': + optional: true + + '@esbuild/openbsd-arm64@0.27.2': + optional: true + '@esbuild/openbsd-x64@0.21.5': optional: true + '@esbuild/openbsd-x64@0.27.2': + optional: true + + '@esbuild/openharmony-arm64@0.27.2': + optional: true + '@esbuild/sunos-x64@0.21.5': optional: true + '@esbuild/sunos-x64@0.27.2': + optional: true + '@esbuild/win32-arm64@0.21.5': optional: true + '@esbuild/win32-arm64@0.27.2': + optional: true + '@esbuild/win32-ia32@0.21.5': optional: true + '@esbuild/win32-ia32@0.27.2': + optional: true + '@esbuild/win32-x64@0.21.5': optional: true + '@esbuild/win32-x64@0.27.2': + optional: true + '@eslint-community/eslint-utils@4.9.1(eslint@8.57.1)': dependencies: eslint: 8.57.1 @@ -6214,7 +6489,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@vitejs/plugin-react@5.1.2(vite@5.4.21(@types/node@24.10.8))': + '@vitejs/plugin-react@5.1.2(vite@7.3.1(@types/node@24.10.8)(jiti@1.21.7))': dependencies: '@babel/core': 7.28.6 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.6) @@ -6222,7 +6497,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.53 '@types/babel__core': 7.20.5 react-refresh: 0.18.0 - vite: 5.4.21(@types/node@24.10.8) + vite: 7.3.1(@types/node@24.10.8)(jiti@1.21.7) transitivePeerDependencies: - supports-color @@ -6851,6 +7126,35 @@ snapshots: '@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-x64': 0.21.5 + esbuild@0.27.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.2 + '@esbuild/android-arm': 0.27.2 + '@esbuild/android-arm64': 0.27.2 + '@esbuild/android-x64': 0.27.2 + '@esbuild/darwin-arm64': 0.27.2 + '@esbuild/darwin-x64': 0.27.2 + '@esbuild/freebsd-arm64': 0.27.2 + '@esbuild/freebsd-x64': 0.27.2 + '@esbuild/linux-arm': 0.27.2 + '@esbuild/linux-arm64': 0.27.2 + '@esbuild/linux-ia32': 0.27.2 + '@esbuild/linux-loong64': 0.27.2 + '@esbuild/linux-mips64el': 0.27.2 + '@esbuild/linux-ppc64': 0.27.2 + '@esbuild/linux-riscv64': 0.27.2 + '@esbuild/linux-s390x': 0.27.2 + '@esbuild/linux-x64': 0.27.2 + '@esbuild/netbsd-arm64': 0.27.2 + '@esbuild/netbsd-x64': 0.27.2 + '@esbuild/openbsd-arm64': 0.27.2 + '@esbuild/openbsd-x64': 0.27.2 + '@esbuild/openharmony-arm64': 0.27.2 + '@esbuild/sunos-x64': 0.27.2 + '@esbuild/win32-arm64': 0.27.2 + '@esbuild/win32-ia32': 0.27.2 + '@esbuild/win32-x64': 0.27.2 + escalade@3.2.0: {} escape-string-regexp@4.0.0: {} @@ -7138,8 +7442,6 @@ snapshots: globals@14.0.0: {} - globals@15.15.0: {} - globals@16.5.0: {} graceful-fs@4.2.11: {} @@ -8764,6 +9066,19 @@ snapshots: '@types/node': 24.10.8 fsevents: 2.3.3 + vite@7.3.1(@types/node@24.10.8)(jiti@1.21.7): + dependencies: + esbuild: 0.27.2 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.55.1 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 24.10.8 + fsevents: 2.3.3 + jiti: 1.21.7 + vitepress@1.6.4(@algolia/client-search@5.46.3)(@types/node@24.10.8)(@types/react@18.3.12)(postcss@8.5.6)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.9.3): dependencies: '@docsearch/css': 3.8.2 @@ -8813,7 +9128,7 @@ snapshots: - typescript - universal-cookie - vitest@1.6.1(@types/node@24.10.8)(@vitest/ui@2.1.9(vitest@2.1.9))(happy-dom@20.1.0)(jsdom@27.4.0): + vitest@1.6.1(@types/node@24.10.8)(@vitest/ui@2.1.9)(happy-dom@20.1.0)(jsdom@27.4.0): dependencies: '@vitest/expect': 1.6.1 '@vitest/runner': 1.6.1