99 * - ListView delegation for non-grid view types (kanban, calendar, chart, etc.)
1010 */
1111
12- import { useMemo , useState , useCallback , useEffect } from 'react' ;
12+ import { useMemo , useState , useCallback , useEffect , type ComponentType } from 'react' ;
1313import { useParams , useSearchParams , useNavigate } from 'react-router-dom' ;
1414import { ObjectChart } from '@object-ui/plugin-charts' ;
1515import { ListView } from '@object-ui/plugin-list' ;
1616import { DetailView , RecordChatterPanel } from '@object-ui/plugin-detail' ;
17- import { ObjectView as PluginObjectView } from '@object-ui/plugin-view' ;
17+ import { ObjectView as PluginObjectView , ViewTabBar } from '@object-ui/plugin-view' ;
18+ import type { ViewTabItem } from '@object-ui/plugin-view' ;
1819// Import plugins for side-effects (registration)
1920import '@object-ui/plugin-grid' ;
2021import '@object-ui/plugin-kanban' ;
2122import '@object-ui/plugin-calendar' ;
2223import { Button , Empty , EmptyTitle , EmptyDescription , NavigationOverlay , DropdownMenu , DropdownMenuContent , DropdownMenuItem , DropdownMenuTrigger , DropdownMenuSeparator } from '@object-ui/components' ;
23- import { Plus , Table as TableIcon , Settings2 , Wrench } from 'lucide-react' ;
24+ import { Plus , Table as TableIcon , Settings2 , Wrench , KanbanSquare , Calendar , LayoutGrid , Activity , GanttChart , MapPin , BarChart3 } from 'lucide-react' ;
2425import type { ListViewSchema , ViewNavigationConfig , FeedItem } from '@object-ui/types' ;
2526import { MetadataToggle , MetadataPanel , useMetadataInspector } from './MetadataInspector' ;
2627import { ViewConfigPanel } from './ViewConfigPanel' ;
@@ -31,6 +32,18 @@ import { useAuth } from '@object-ui/auth';
3132import { useRealtimeSubscription , useConflictResolution } from '@object-ui/collaboration' ;
3233import { useNavigationOverlay , SchemaRenderer } from '@object-ui/react' ;
3334
35+ /** Map view types to Lucide icons (Airtable-style) */
36+ const VIEW_TYPE_ICONS : Record < string , ComponentType < { className ?: string } > > = {
37+ grid : TableIcon ,
38+ kanban : KanbanSquare ,
39+ calendar : Calendar ,
40+ gallery : LayoutGrid ,
41+ timeline : Activity ,
42+ gantt : GanttChart ,
43+ map : MapPin ,
44+ chart : BarChart3 ,
45+ } ;
46+
3447const FALLBACK_USER = { id : 'current-user' , name : 'Demo User' } ;
3548
3649/**
@@ -732,7 +745,24 @@ export function ObjectView({ dataSource, objects, onEdit }: any) {
732745 </ div >
733746 </ div >
734747
735- { /* View Tabs removed — view switching is handled via ViewConfigPanel (right sidebar) */ }
748+ { /* View Tabs — read-only view switcher (design features like drag/add are in ViewConfigPanel) */ }
749+ { views . length > 1 && (
750+ < div className = "border-b px-3 sm:px-4 bg-background overflow-x-auto shrink-0" >
751+ < ViewTabBar
752+ views = { views . map ( ( view : { id : string ; label : string ; type : string ; filter ?: any [ ] ; sort ?: any [ ] } ) => ( {
753+ id : view . id ,
754+ label : view . label ,
755+ type : view . type ,
756+ hasActiveFilters : Array . isArray ( ( view as any ) . filter ) && ( view as any ) . filter . length > 0 ,
757+ hasActiveSort : Array . isArray ( ( view as any ) . sort ) && ( view as any ) . sort . length > 0 ,
758+ } as ViewTabItem ) ) }
759+ activeViewId = { activeViewId }
760+ onViewChange = { handleViewChange }
761+ viewTypeIcons = { VIEW_TYPE_ICONS }
762+ config = { { reorderable : false } }
763+ />
764+ </ div >
765+ ) }
736766
737767 { /* 2. Content — Plugin ObjectView with ViewSwitcher + Filter + Sort */ }
738768 < div className = "flex-1 overflow-hidden relative flex flex-row" >
0 commit comments