docs(plan): add feature complete implementation plan
This commit is contained in:
702
src/Griddy/plan.md
Normal file
702
src/Griddy/plan.md
Normal file
@@ -0,0 +1,702 @@
|
|||||||
|
# Griddy - Feature Complete Implementation Plan
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
Griddy is a native TypeScript HTML table/grid component designed as a lightweight, extensible alternative to both Glide Data Editor and Mantine React Table. It will provide a zero-dependency core with optional plugin architecture, built on TanStack React Virtual for efficient virtualization.
|
||||||
|
|
||||||
|
## Architecture & Core Design Principles
|
||||||
|
|
||||||
|
### 1. Core Philosophy
|
||||||
|
- **Independent**: Minimal peer dependencies (React, React DOM only at minimum)
|
||||||
|
- **Lightweight**: Pure HTML table rendering with CSS styling
|
||||||
|
- **Virtual-First**: Virtualization from the ground up using TanStack React Virtual
|
||||||
|
- **Plugin-Based**: All advanced features as pluggable modules
|
||||||
|
- **State Agnostic**: Works with any state management solution or local state
|
||||||
|
- **Callback-Driven**: Similar to Glide Data Editor's read-only data principle
|
||||||
|
|
||||||
|
### 1.5. Lessons from Gridler
|
||||||
|
Gridly (existing implementation) provides valuable patterns:
|
||||||
|
- **Zustand Store Pattern**: Central state management using `createSyncStore` for reactive updates
|
||||||
|
- **Data Adapter Pattern**: Wrapper components that interface with store (LocalDataAdaptor, FormAdaptor, APIAdaptor)
|
||||||
|
- **Event System**: Uses CustomEvent for inter-component communication
|
||||||
|
- **Provider/Context Pattern**: Wraps grid in Provider for configuration and state sharing
|
||||||
|
- **Column Definition System**: Type-safe, extensible column definitions with custom rendering
|
||||||
|
- **Ref-based API**: Forward refs for imperative commands (refresh, reload, scrollTo, selectRow)
|
||||||
|
- **Persistence**: Automatic localStorage persistence for column order and sizing
|
||||||
|
|
||||||
|
**Griddy will adopt these proven patterns while building on TanStack React Virtual instead of Glide Data Grid**
|
||||||
|
|
||||||
|
### 2. Component Structure
|
||||||
|
|
||||||
|
Following Gridler's proven architecture, with improvements:
|
||||||
|
|
||||||
|
```
|
||||||
|
Griddy/
|
||||||
|
├── core/
|
||||||
|
│ ├── Griddy.tsx (main component, similar to Gridler.tsx)
|
||||||
|
│ ├── GriddyStore.ts (zustand store, similar to Gridler's createSyncStore)
|
||||||
|
│ ├── GriddyProvider.tsx (context provider for configuration)
|
||||||
|
│ └── types.ts (core type definitions)
|
||||||
|
├── virtualization/
|
||||||
|
│ ├── VirtualBody.tsx (uses TanStack React Virtual)
|
||||||
|
│ ├── VirtualHeader.tsx
|
||||||
|
│ └── hooks/useVirtualize.ts
|
||||||
|
├── features/
|
||||||
|
│ ├── filtering/ (column filtering)
|
||||||
|
│ ├── sorting/ (multi-column sorting)
|
||||||
|
│ ├── grouping/ (header grouping & data grouping)
|
||||||
|
│ ├── search/ (global & column-specific search)
|
||||||
|
│ ├── selection/ (row/column/range selection)
|
||||||
|
│ ├── editing/ (in-place cell editors)
|
||||||
|
│ ├── pagination/ (cursor & offset-based)
|
||||||
|
│ ├── resizing/ (column width resizing)
|
||||||
|
│ ├── pinning/ (freeze columns/rows)
|
||||||
|
│ └── export/ (CSV/data export)
|
||||||
|
├── editors/
|
||||||
|
│ ├── TextEditor.tsx
|
||||||
|
│ ├── NumericEditor.tsx
|
||||||
|
│ ├── DateEditor.tsx
|
||||||
|
│ ├── SelectEditor.tsx
|
||||||
|
│ └── CustomEditor.tsx (extensibility point)
|
||||||
|
├── renderers/
|
||||||
|
│ ├── defaultRenderers.ts
|
||||||
|
│ ├── CustomRenderer.tsx (extensibility point)
|
||||||
|
│ └── formatters.ts (value formatting)
|
||||||
|
├── hooks/
|
||||||
|
│ ├── useGriddy.ts (main hook)
|
||||||
|
│ ├── useFiltering.ts
|
||||||
|
│ ├── useSorting.ts
|
||||||
|
│ ├── useSearch.ts
|
||||||
|
│ ├── useSelection.ts
|
||||||
|
│ ├── usePagination.ts
|
||||||
|
│ ├── useEditing.ts
|
||||||
|
│ └── useVirtualization.ts
|
||||||
|
├── adapters/
|
||||||
|
│ ├── LocalDataAdapter.ts
|
||||||
|
│ ├── RemoteServerAdapter.ts
|
||||||
|
│ ├── GraphQLAdapter.ts (optional)
|
||||||
|
│ └── RESTAdapter.ts (optional)
|
||||||
|
├── styles/
|
||||||
|
│ ├── griddy.module.css
|
||||||
|
│ └── themes.ts (theme system)
|
||||||
|
└── index.ts (exports)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Feature Specifications
|
||||||
|
|
||||||
|
### Core Features
|
||||||
|
|
||||||
|
#### 1. Data Handling
|
||||||
|
- **Local Data**: Direct array-based data binding
|
||||||
|
- **Remote Server Data**: Async data fetching with loading states
|
||||||
|
- **Cursor-Based Paging**: Server-side paging with cursor tokens (for performance)
|
||||||
|
- **Offset-Based Paging**: Traditional offset/limit paging
|
||||||
|
- **Lazy Loading**: Data loaded as user scrolls (virtual scrolling integration)
|
||||||
|
- **Data Adapters**: Pluggable adapters for different data sources
|
||||||
|
|
||||||
|
API:
|
||||||
|
```typescript
|
||||||
|
interface GriddyDataSource {
|
||||||
|
data: T[]
|
||||||
|
total?: number
|
||||||
|
pageInfo?: { hasNextPage: boolean, cursor?: string }
|
||||||
|
isLoading?: boolean
|
||||||
|
error?: Error
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GriddyProps<T> {
|
||||||
|
data: T[]
|
||||||
|
columns: Column<T>[]
|
||||||
|
onDataChange?: (data: T[]) => void
|
||||||
|
dataAdapter?: DataAdapter<T>
|
||||||
|
// ... other props
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Virtualization
|
||||||
|
- **Row Virtualization**: Only render visible rows using TanStack React Virtual
|
||||||
|
- **Column Virtualization**: Optionally virtualize columns for wide tables
|
||||||
|
- **Scrolling Performance**: Smooth scrolling with overscan optimization
|
||||||
|
- **Height Calculation**: Fixed height container with auto-height option
|
||||||
|
- **Sticky Headers**: Virtual header stays fixed while scrolling
|
||||||
|
|
||||||
|
Implementation:
|
||||||
|
- Use `@tanstack/react-virtual` for row/column virtualization
|
||||||
|
- Configurable overscan count for smooth scrolling
|
||||||
|
- Support both fixed and variable row heights
|
||||||
|
|
||||||
|
#### 3. Column Management
|
||||||
|
- **Column Definition**: Type-safe column definitions with accessors
|
||||||
|
- **Header Grouping**: Multi-level header groups (similar to Glide)
|
||||||
|
- **Column Pinning**: Freeze left/right columns
|
||||||
|
- **Column Resizing**: Drag-to-resize with min/max constraints
|
||||||
|
- **Column Hiding**: Show/hide columns dynamically
|
||||||
|
- **Column Reordering**: Drag-and-drop column reordering
|
||||||
|
- **Header Customization**: Custom header renderers
|
||||||
|
|
||||||
|
API:
|
||||||
|
```typescript
|
||||||
|
interface Column<T> {
|
||||||
|
id: string
|
||||||
|
header: string | ReactNode
|
||||||
|
accessor: keyof T | ((row: T) => any)
|
||||||
|
width?: number
|
||||||
|
minWidth?: number
|
||||||
|
maxWidth?: number
|
||||||
|
pinned?: 'left' | 'right'
|
||||||
|
sortable?: boolean
|
||||||
|
filterable?: boolean
|
||||||
|
searchable?: boolean
|
||||||
|
editable?: boolean
|
||||||
|
editor?: EditorComponent<T>
|
||||||
|
renderer?: RendererComponent<T>
|
||||||
|
headerGroup?: string
|
||||||
|
hidden?: boolean
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4. Filtering
|
||||||
|
- **Column Filtering**: Per-column filter UI (text, number, date, select)
|
||||||
|
- **Filter Modes**: Exact match, contains, starts with, ends with, between (for numbers/dates)
|
||||||
|
- **Multi-Filter**: Multiple filters per column with AND/OR logic
|
||||||
|
- **Filter Persistence**: Save/restore filter state
|
||||||
|
- **Custom Filters**: User-provided filter functions
|
||||||
|
|
||||||
|
Implementation:
|
||||||
|
- Filter dropdown in column header
|
||||||
|
- Configuration for filter types per column
|
||||||
|
- Debounced filtering for performance
|
||||||
|
|
||||||
|
#### 5. Search
|
||||||
|
- **Global Search**: Search across all searchable columns
|
||||||
|
- **Column Search**: Search within specific columns
|
||||||
|
- **Search Highlighting**: Highlight matching text
|
||||||
|
- **Search Navigation**: Navigate through search results
|
||||||
|
- **Fuzzy Search**: Optional fuzzy search capability
|
||||||
|
|
||||||
|
API:
|
||||||
|
```typescript
|
||||||
|
interface SearchConfig {
|
||||||
|
enabled: boolean
|
||||||
|
debounceMs?: number
|
||||||
|
fuzzy?: boolean
|
||||||
|
highlightMatches?: boolean
|
||||||
|
caseSensitive?: boolean
|
||||||
|
columnsToSearch?: string[] // column IDs
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 6. Sorting
|
||||||
|
- **Single Column Sort**: Sort by one column (default)
|
||||||
|
- **Multi-Column Sort**: Sort by multiple columns with priority
|
||||||
|
- **Sort Direction**: Ascending/descending/unsorted
|
||||||
|
- **Custom Sort Functions**: User-provided sort comparators
|
||||||
|
- **Sort Persistence**: Save/restore sort state
|
||||||
|
- **Server-Side Sort**: Offload sorting to server
|
||||||
|
|
||||||
|
Implementation:
|
||||||
|
- Click header to sort (first click = asc, second = desc, third = unsorted)
|
||||||
|
- Shift+Click for multi-column sort
|
||||||
|
- Visual indicators in header (arrows/icons)
|
||||||
|
|
||||||
|
#### 7. Row/Column Selection
|
||||||
|
- **Row Selection**: Single or multi-select with checkboxes
|
||||||
|
- **Column Selection**: Select entire columns
|
||||||
|
- **Range Selection**: Rectangular range selection (like Glide)
|
||||||
|
- **Selection Callbacks**: On selection change events
|
||||||
|
- **Selection Persistence**: Maintain selection across pagination
|
||||||
|
- **Selection Styling**: Highlight selected rows/columns
|
||||||
|
|
||||||
|
API:
|
||||||
|
```typescript
|
||||||
|
interface SelectionConfig {
|
||||||
|
mode: 'none' | 'row' | 'column' | 'range'
|
||||||
|
multiSelect?: boolean
|
||||||
|
selectOnClick?: boolean
|
||||||
|
deselectOnClick?: boolean
|
||||||
|
onSelectionChange?: (selection: Selection) => void
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 8. Grouping
|
||||||
|
- **Header Grouping**: Multi-level column groups (visual grouping only, no data aggregation initially)
|
||||||
|
- **Data Grouping**: Group rows by column value with collapsible groups
|
||||||
|
- **Aggregation**: Show aggregate values (count, sum, avg, etc.) in group headers
|
||||||
|
- **Group Actions**: Expand/collapse groups, delete groups
|
||||||
|
|
||||||
|
#### 9. In-Place Editing
|
||||||
|
- **Text Editor**: Simple text input with validation
|
||||||
|
- **Numeric Editor**: Number input with constraints
|
||||||
|
- **Date Editor**: Date picker or input
|
||||||
|
- **Select Editor**: Dropdown with predefined options
|
||||||
|
- **Custom Editors**: User-provided editor components
|
||||||
|
- **Validation**: Per-cell or per-row validation
|
||||||
|
- **Undo/Redo**: Optional undo/redo support
|
||||||
|
- **Batch Edits**: Edit multiple cells and submit together
|
||||||
|
|
||||||
|
API:
|
||||||
|
```typescript
|
||||||
|
interface EditorProps<T> {
|
||||||
|
value: any
|
||||||
|
column: Column<T>
|
||||||
|
row: T
|
||||||
|
onCommit: (newValue: any) => void
|
||||||
|
onCancel: () => void
|
||||||
|
onBlur?: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Column<T> {
|
||||||
|
editor?: EditorComponent<T>
|
||||||
|
editable?: boolean | ((row: T) => boolean)
|
||||||
|
onEditCommit?: (newValue: any, row: T) => Promise<void>
|
||||||
|
validation?: (value: any) => string | null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 10. Pagination
|
||||||
|
- **Offset Pagination**: Page/limit based (e.g., page 1-10, 20 items per page)
|
||||||
|
- **Cursor Pagination**: Cursor-based (for infinite scroll or server-side)
|
||||||
|
- **Page Navigation**: Next/prev buttons, page input, jump to page
|
||||||
|
- **Items Per Page**: Configurable items per page with preset options
|
||||||
|
- **Total Count**: Display total items and current range
|
||||||
|
|
||||||
|
API:
|
||||||
|
```typescript
|
||||||
|
interface PaginationConfig {
|
||||||
|
enabled: boolean
|
||||||
|
type: 'offset' | 'cursor'
|
||||||
|
pageSize: number
|
||||||
|
pageSizeOptions?: number[]
|
||||||
|
onPageChange?: (page: number) => void
|
||||||
|
onPageSizeChange?: (pageSize: number) => void
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 11. Extensibility
|
||||||
|
|
||||||
|
**Custom Cell Renderers**:
|
||||||
|
```typescript
|
||||||
|
interface RendererProps<T> {
|
||||||
|
value: any
|
||||||
|
row: T
|
||||||
|
column: Column<T>
|
||||||
|
rowIndex: number
|
||||||
|
columnIndex: number
|
||||||
|
isEditing?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
type CellRenderer<T> = (props: RendererProps<T>) => ReactNode
|
||||||
|
```
|
||||||
|
|
||||||
|
**Custom Features via Hooks**:
|
||||||
|
- Users can wrap Griddy with custom hooks to add features
|
||||||
|
- Plugin architecture through context and callbacks
|
||||||
|
|
||||||
|
**Custom Editors**:
|
||||||
|
- Any component can be an editor if it implements EditorProps interface
|
||||||
|
|
||||||
|
**Custom Data Adapters**:
|
||||||
|
```typescript
|
||||||
|
interface DataAdapter<T> {
|
||||||
|
fetch: (config: FetchConfig) => Promise<GriddyDataSource<T>>
|
||||||
|
save: (row: T) => Promise<void>
|
||||||
|
delete: (row: T) => Promise<void>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architectural Patterns from Gridler to Adopt
|
||||||
|
|
||||||
|
### 1. Zustand Store Pattern
|
||||||
|
Gridler's `GridlerStore.tsx` demonstrates effective state management:
|
||||||
|
```typescript
|
||||||
|
// Griddy will follow similar pattern
|
||||||
|
const { Provider, useGriddyStore } = createSyncStore<GriddyState, GriddyProps>(
|
||||||
|
(set, get) => ({
|
||||||
|
// State mutations and getters
|
||||||
|
// Immer integration for immutable updates
|
||||||
|
// Custom methods for grid operations
|
||||||
|
})
|
||||||
|
)
|
||||||
|
```
|
||||||
|
**Benefits**: Reactive updates, easy testing, dev tools support, persistence support
|
||||||
|
|
||||||
|
### 2. Data Adapter Pattern
|
||||||
|
Gridler's adapters (LocalDataAdaptor, FormAdaptor, APIAdaptor) show clean separation:
|
||||||
|
- Adapters are wrapper components that consume store and trigger data operations
|
||||||
|
- They handle filtering, sorting, searching via store mutations
|
||||||
|
- Support both local and remote data without core changes
|
||||||
|
- Each adapter implements `useAPIQuery` pattern for pagination
|
||||||
|
|
||||||
|
**Griddy will adopt this for extensibility**:
|
||||||
|
```typescript
|
||||||
|
// Location: src/Griddy/adapters/
|
||||||
|
// - LocalDataAdapter.tsx (array data)
|
||||||
|
// - RemoteServerAdapter.tsx (API with cursor/offset paging)
|
||||||
|
// - CustomAdapter pattern for user extensions
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Event System
|
||||||
|
Gridler uses `CustomEvent` for loose coupling between components:
|
||||||
|
```typescript
|
||||||
|
state._events.dispatchEvent(new CustomEvent('loadPage', { detail }))
|
||||||
|
state._events.addEventListener('reload', handler)
|
||||||
|
```
|
||||||
|
**Griddy benefit**: Allows features to trigger actions without tight coupling
|
||||||
|
|
||||||
|
### 4. Column Definition System
|
||||||
|
Gridler's `GridlerColumn` interface shows best practices:
|
||||||
|
- Optional `Cell` renderer for custom cell display
|
||||||
|
- `disableSort`, `disableFilter`, `disableMove`, `disableResize` flags
|
||||||
|
- Custom menu items via `getMenuItems`
|
||||||
|
- Tooltip support (string or function)
|
||||||
|
- Nested field access via dot notation
|
||||||
|
|
||||||
|
**Griddy will enhance this**:
|
||||||
|
```typescript
|
||||||
|
interface Column<T> {
|
||||||
|
id: string
|
||||||
|
header: string
|
||||||
|
accessor: keyof T | ((row: T) => any)
|
||||||
|
renderer?: (props: RendererProps<T>) => ReactNode
|
||||||
|
editor?: EditorComponent<T>
|
||||||
|
sortable?: boolean
|
||||||
|
filterable?: boolean
|
||||||
|
resizable?: boolean
|
||||||
|
pinned?: 'left' | 'right'
|
||||||
|
// ... more options
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Ref-Based Imperative API
|
||||||
|
Gridler's `GridlerRef` provides necessary imperative operations:
|
||||||
|
```typescript
|
||||||
|
interface GridlerRef {
|
||||||
|
getState: () => GridlerState
|
||||||
|
refresh: () => Promise<void>
|
||||||
|
scrollToRow: (key: string | number) => Promise<void>
|
||||||
|
selectRow: (key: string | number) => Promise<void>
|
||||||
|
reloadRow: (key: string | number) => Promise<void>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
**Griddy will provide similar imperative API for parent control**
|
||||||
|
|
||||||
|
### 6. Persistence Layer
|
||||||
|
Gridler uses localStorage for column state:
|
||||||
|
```typescript
|
||||||
|
persist={{
|
||||||
|
name: `Gridler_${props.uniqueid}`,
|
||||||
|
partialize: (s) => ({ colOrder: s.colOrder, colSize: s.colSize }),
|
||||||
|
version: 1,
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
**Griddy will support this optional persistence**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Implementation Phases
|
||||||
|
|
||||||
|
### Phase 1: Core Foundation (Weeks 1-2)
|
||||||
|
- [ ] Set up Griddy package structure
|
||||||
|
- [ ] Create core types and interfaces
|
||||||
|
- [ ] Implement basic Griddy component with:
|
||||||
|
- Simple table rendering (HTML `<table>`)
|
||||||
|
- Column definition system
|
||||||
|
- Basic props interface
|
||||||
|
- Initial Zustand store (optional, minimal state)
|
||||||
|
- [ ] Implement LocalDataAdapter
|
||||||
|
- [ ] Add Storybook stories for basic table
|
||||||
|
|
||||||
|
**Deliverable**: Functional table rendering local data with column definitions
|
||||||
|
|
||||||
|
### Phase 2: Virtualization & Performance (Weeks 2-3)
|
||||||
|
- [ ] Integrate TanStack React Virtual
|
||||||
|
- [ ] Implement row virtualization
|
||||||
|
- [ ] Implement sticky header with virtual scroll
|
||||||
|
- [ ] Add column resizing
|
||||||
|
- [ ] Performance optimization (memo, useMemo)
|
||||||
|
- [ ] Test with large datasets (10k+ rows)
|
||||||
|
|
||||||
|
**Deliverable**: High-performance virtualized table
|
||||||
|
|
||||||
|
### Phase 3: Data Handling (Weeks 3-4)
|
||||||
|
- [ ] Implement RemoteServerAdapter
|
||||||
|
- [ ] Add cursor-based pagination
|
||||||
|
- [ ] Add offset-based pagination
|
||||||
|
- [ ] Implement loading states
|
||||||
|
- [ ] Error handling and display
|
||||||
|
- [ ] Infinite scroll pattern
|
||||||
|
|
||||||
|
**Deliverable**: Full data source flexibility (local, remote, paginated)
|
||||||
|
|
||||||
|
### Phase 4: Selection & Interaction (Week 4)
|
||||||
|
- [ ] Row selection (checkbox + keyboard)
|
||||||
|
- [ ] Column selection
|
||||||
|
- [ ] Range selection
|
||||||
|
- [ ] Selection persistence
|
||||||
|
- [ ] Keyboard navigation (arrows, shift+click, etc.)
|
||||||
|
|
||||||
|
**Deliverable**: Full selection capabilities
|
||||||
|
|
||||||
|
### Phase 5: Filtering, Sorting, Search (Week 5)
|
||||||
|
- [ ] Sorting (single & multi-column)
|
||||||
|
- [ ] Column filtering UI and logic
|
||||||
|
- [ ] Global search
|
||||||
|
- [ ] Search highlighting
|
||||||
|
- [ ] Filter/sort state persistence
|
||||||
|
|
||||||
|
**Deliverable**: Data manipulation features
|
||||||
|
|
||||||
|
### Phase 6: In-Place Editing (Week 5-6)
|
||||||
|
- [ ] Text, Numeric, Date editors
|
||||||
|
- [ ] Select editor
|
||||||
|
- [ ] Validation system
|
||||||
|
- [ ] Edit callbacks (onEditCommit, onEditCancel)
|
||||||
|
- [ ] Undo/redo (optional)
|
||||||
|
- [ ] Trailing row for new records (optional)
|
||||||
|
|
||||||
|
**Deliverable**: Full editing capabilities
|
||||||
|
|
||||||
|
### Phase 7: Advanced Features (Week 6-7)
|
||||||
|
- [ ] Grouping (header groups)
|
||||||
|
- [ ] Data grouping with aggregation
|
||||||
|
- [ ] Column pinning/freezing
|
||||||
|
- [ ] Column reordering
|
||||||
|
- [ ] Column hiding/showing
|
||||||
|
- [ ] Export to CSV
|
||||||
|
|
||||||
|
**Deliverable**: Advanced features
|
||||||
|
|
||||||
|
### Phase 8: Polish & Documentation (Week 7-8)
|
||||||
|
- [ ] Comprehensive Storybook stories
|
||||||
|
- [ ] API documentation
|
||||||
|
- [ ] TypeScript definitions and examples
|
||||||
|
- [ ] Integration examples
|
||||||
|
- [ ] Performance benchmarks
|
||||||
|
- [ ] Accessibility improvements (ARIA, keyboard nav)
|
||||||
|
- [ ] Theme system documentation
|
||||||
|
|
||||||
|
**Deliverable**: Production-ready component
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Comparison with Competitors
|
||||||
|
|
||||||
|
### vs. Glide Data Editor
|
||||||
|
**Advantages**:
|
||||||
|
- No proprietary license needed
|
||||||
|
- Simpler API, less callback hell
|
||||||
|
- Smaller bundle size
|
||||||
|
- Framework agnostic (could be ported to Vue, Svelte, etc.)
|
||||||
|
- More transparent development
|
||||||
|
|
||||||
|
**Disadvantages**:
|
||||||
|
- Less mature (initially)
|
||||||
|
- Fewer enterprise features
|
||||||
|
- No rich text editing (not planned for MVP)
|
||||||
|
|
||||||
|
### vs. Mantine React Table
|
||||||
|
**Advantages**:
|
||||||
|
- Lighter weight
|
||||||
|
- Pure virtual rendering (no DOM overhead)
|
||||||
|
- More flexible CSS styling (pure HTML table)
|
||||||
|
- Better performance with large datasets
|
||||||
|
- Simpler core API
|
||||||
|
|
||||||
|
**Disadvantages**:
|
||||||
|
- No built-in Modal editing (only in-line)
|
||||||
|
- No tree/hierarchical data (initially)
|
||||||
|
- Requires Mantine knowledge (eventually provide integrations)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Technology Stack
|
||||||
|
|
||||||
|
- **React**: 19.x (peer dependency)
|
||||||
|
- **TypeScript**: 5.9+
|
||||||
|
- **Virtualization**: @tanstack/react-virtual 3.13+
|
||||||
|
- **State Management**: Zustand (optional, for advanced features)
|
||||||
|
- **Styling**: CSS Modules + Mantine theming integration (optional)
|
||||||
|
- **Testing**: Vitest, React Testing Library
|
||||||
|
- **Build**: Vite with TypeScript declaration generation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
**Peer Dependencies**:
|
||||||
|
- react >= 19.0.0
|
||||||
|
- react-dom >= 19.0.0
|
||||||
|
- @tanstack/react-virtual >= 3.13.0
|
||||||
|
|
||||||
|
**Optional Peer Dependencies**:
|
||||||
|
- @mantine/core (for integrated theming)
|
||||||
|
- @tanstack/react-query (for server-side data)
|
||||||
|
|
||||||
|
**Dev Dependencies**:
|
||||||
|
- Same as Oranguru project (Vitest, Storybook, etc.)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Testing Strategy
|
||||||
|
|
||||||
|
1. **Unit Tests**:
|
||||||
|
- Editor components
|
||||||
|
- Filter/Sort logic
|
||||||
|
- Data adapter functions
|
||||||
|
- Hook logic
|
||||||
|
|
||||||
|
2. **Integration Tests**:
|
||||||
|
- Column definition system
|
||||||
|
- Data flow end-to-end
|
||||||
|
- Selection with filtering
|
||||||
|
- Editing with validation
|
||||||
|
|
||||||
|
3. **Performance Tests**:
|
||||||
|
- Rendering 10k+ rows
|
||||||
|
- Filtering/sorting on large datasets
|
||||||
|
- Memory usage monitoring
|
||||||
|
|
||||||
|
4. **Accessibility Tests**:
|
||||||
|
- Keyboard navigation
|
||||||
|
- ARIA labels and roles
|
||||||
|
- Screen reader compatibility
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Browser Support
|
||||||
|
|
||||||
|
- Chrome/Edge: Latest 2 versions
|
||||||
|
- Firefox: Latest 2 versions
|
||||||
|
- Safari: Latest 2 versions
|
||||||
|
- No IE11 support (modern React requirement)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Success Criteria
|
||||||
|
|
||||||
|
1. ✅ Table renders 10k+ rows smoothly (60fps)
|
||||||
|
2. ✅ Filtering/sorting on 10k rows completes in <500ms
|
||||||
|
3. ✅ TypeScript types cover 95%+ of code
|
||||||
|
4. ✅ Bundle size < 50KB (gzipped, excluding Mantine)
|
||||||
|
5. ✅ Full keyboard accessibility (WCAG AA)
|
||||||
|
6. ✅ 100+ Storybook stories covering all features
|
||||||
|
7. ✅ Zero external styling dependencies (works with any CSS)
|
||||||
|
8. ✅ All features tested with >80% coverage
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Known Limitations (Phase 1)
|
||||||
|
|
||||||
|
- Tree/hierarchical data: Planned for Phase 2
|
||||||
|
- Drag-and-drop column reordering: Phase 2
|
||||||
|
- Copy/paste: Phase 2
|
||||||
|
- Rich text/HTML content: Not planned
|
||||||
|
- Master-detail/expandable rows: Phase 2
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File Structure (Detailed)
|
||||||
|
|
||||||
|
```
|
||||||
|
src/Griddy/
|
||||||
|
├── core/
|
||||||
|
│ ├── Griddy.tsx # Main component
|
||||||
|
│ ├── GriddyContext.ts # React context
|
||||||
|
│ ├── GriddyStore.ts # Zustand store (optional)
|
||||||
|
│ ├── types.ts # Core types
|
||||||
|
│ ├── defaults.ts # Default config
|
||||||
|
│ └── constants.ts # Constants
|
||||||
|
├── virtualization/
|
||||||
|
│ ├── VirtualBody.tsx # Virtual row rendering
|
||||||
|
│ ├── VirtualHeader.tsx # Virtual column header
|
||||||
|
│ ├── hooks/
|
||||||
|
│ │ ├── useVirtualize.ts # Virtualization logic
|
||||||
|
│ │ └── useVirtualizeColumns.ts
|
||||||
|
│ └── utils/
|
||||||
|
│ └── sizing.ts # Size calculations
|
||||||
|
├── features/
|
||||||
|
│ ├── filtering/
|
||||||
|
│ │ ├── FilterControl.tsx
|
||||||
|
│ │ ├── useFiltering.ts
|
||||||
|
│ │ ├── types.ts
|
||||||
|
│ │ └── operators.ts
|
||||||
|
│ ├── sorting/
|
||||||
|
│ │ ├── SortIndicator.tsx
|
||||||
|
│ │ ├── useSorting.ts
|
||||||
|
│ │ └── types.ts
|
||||||
|
│ ├── search/
|
||||||
|
│ │ ├── SearchBox.tsx
|
||||||
|
│ │ ├── useSearch.ts
|
||||||
|
│ │ └── types.ts
|
||||||
|
│ ├── selection/
|
||||||
|
│ │ ├── SelectionCheckbox.tsx
|
||||||
|
│ │ ├── useSelection.ts
|
||||||
|
│ │ ├── types.ts
|
||||||
|
│ │ └── keyboard.ts
|
||||||
|
│ ├── grouping/
|
||||||
|
│ │ ├── HeaderGroup.tsx
|
||||||
|
│ │ ├── DataGrouping.tsx
|
||||||
|
│ │ ├── useGrouping.ts
|
||||||
|
│ │ └── types.ts
|
||||||
|
│ ├── editing/
|
||||||
|
│ │ ├── EditableCell.tsx
|
||||||
|
│ │ ├── useEditing.ts
|
||||||
|
│ │ ├── validation.ts
|
||||||
|
│ │ └── types.ts
|
||||||
|
│ ├── pagination/
|
||||||
|
│ │ ├── PaginationControl.tsx
|
||||||
|
│ │ ├── usePagination.ts
|
||||||
|
│ │ └── types.ts
|
||||||
|
│ ├── pinning/
|
||||||
|
│ │ ├── usePinning.ts
|
||||||
|
│ │ └── types.ts
|
||||||
|
│ └── resizing/
|
||||||
|
│ ├── useColumnResizing.ts
|
||||||
|
│ └── types.ts
|
||||||
|
├── editors/
|
||||||
|
│ ├── TextEditor.tsx
|
||||||
|
│ ├── NumericEditor.tsx
|
||||||
|
│ ├── DateEditor.tsx
|
||||||
|
│ ├── SelectEditor.tsx
|
||||||
|
│ ├── CheckboxEditor.tsx
|
||||||
|
│ └── index.ts
|
||||||
|
├── renderers/
|
||||||
|
│ ├── defaultRenderers.tsx
|
||||||
|
│ ├── formatters.ts
|
||||||
|
│ └── types.ts
|
||||||
|
├── adapters/
|
||||||
|
│ ├── LocalDataAdapter.ts
|
||||||
|
│ ├── RemoteServerAdapter.ts
|
||||||
|
│ ├── base.ts
|
||||||
|
│ └── types.ts
|
||||||
|
├── hooks/
|
||||||
|
│ ├── useGriddy.ts # Main hook composing all features
|
||||||
|
│ ├── useMergedRefs.ts
|
||||||
|
│ ├── useAsync.ts
|
||||||
|
│ └── index.ts
|
||||||
|
├── styles/
|
||||||
|
│ ├── griddy.module.css
|
||||||
|
│ ├── themes.ts
|
||||||
|
│ ├── variables.css
|
||||||
|
│ └── reset.css
|
||||||
|
├── utils/
|
||||||
|
│ ├── merge.ts
|
||||||
|
│ ├── classNames.ts
|
||||||
|
│ ├── keyboard.ts
|
||||||
|
│ ├── accessibility.ts
|
||||||
|
│ └── index.ts
|
||||||
|
├── index.ts # Main export
|
||||||
|
├── Griddy.test.tsx
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
1. Review and approve this plan
|
||||||
|
2. Create project directory structure
|
||||||
|
3. Set up initial TypeScript types and interfaces
|
||||||
|
4. Begin Phase 1 implementation
|
||||||
|
5. Create Storybook stories alongside implementation
|
||||||
Reference in New Issue
Block a user