88
99import React from 'react' ;
1010import { ComponentRegistry } from '@object-ui/core' ;
11- import type { HeaderBarSchema } from '@object-ui/types' ;
12- import { resolveI18nLabel } from '@object-ui/react' ;
11+ import type { HeaderBarSchema , BreadcrumbItem as BreadcrumbItemType } from '@object-ui/types' ;
12+ import { resolveI18nLabel , SchemaRenderer } from '@object-ui/react' ;
1313import {
1414 SidebarTrigger ,
1515 Separator ,
@@ -18,8 +18,45 @@ import {
1818 BreadcrumbItem ,
1919 BreadcrumbLink ,
2020 BreadcrumbSeparator ,
21- BreadcrumbPage
21+ BreadcrumbPage ,
22+ DropdownMenu ,
23+ DropdownMenuTrigger ,
24+ DropdownMenuContent ,
25+ DropdownMenuItem ,
26+ Input ,
2227} from '../../ui' ;
28+ import { ChevronDown , Search } from 'lucide-react' ;
29+
30+ function BreadcrumbLabel ( { crumb, isLast } : { crumb : BreadcrumbItemType ; isLast : boolean } ) {
31+ const label = resolveI18nLabel ( crumb . label ) ?? '' ;
32+
33+ if ( crumb . siblings && crumb . siblings . length > 0 ) {
34+ return (
35+ < DropdownMenu >
36+ < DropdownMenuTrigger className = "flex items-center gap-1" >
37+ { isLast ? (
38+ < span className = "font-semibold" > { label } </ span >
39+ ) : (
40+ < span > { label } </ span >
41+ ) }
42+ < ChevronDown className = "h-3 w-3" />
43+ </ DropdownMenuTrigger >
44+ < DropdownMenuContent align = "start" >
45+ { crumb . siblings . map ( ( sibling , i ) => (
46+ < DropdownMenuItem key = { i } asChild >
47+ < a href = { sibling . href } > { sibling . label } </ a >
48+ </ DropdownMenuItem >
49+ ) ) }
50+ </ DropdownMenuContent >
51+ </ DropdownMenu >
52+ ) ;
53+ }
54+
55+ if ( isLast ) {
56+ return < BreadcrumbPage > { label } </ BreadcrumbPage > ;
57+ }
58+ return < BreadcrumbLink href = { crumb . href || '#' } > { label } </ BreadcrumbLink > ;
59+ }
2360
2461ComponentRegistry . register ( 'header-bar' ,
2562 ( { schema } : { schema : HeaderBarSchema } ) => (
@@ -28,27 +65,48 @@ ComponentRegistry.register('header-bar',
2865 < Separator orientation = "vertical" className = "mr-2 h-4" />
2966 < Breadcrumb >
3067 < BreadcrumbList >
31- { schema . crumbs ?. map ( ( crumb : any , idx : number ) => (
68+ { schema . crumbs ?. map ( ( crumb : BreadcrumbItemType , idx : number ) => (
3269 < React . Fragment key = { idx } >
3370 < BreadcrumbItem >
34- { idx === schema . crumbs . length - 1 ? (
35- < BreadcrumbPage > { resolveI18nLabel ( crumb . label ) ?? '' } </ BreadcrumbPage >
36- ) : (
37- < BreadcrumbLink href = { crumb . href || '#' } > { resolveI18nLabel ( crumb . label ) ?? '' } </ BreadcrumbLink >
38- ) }
71+ < BreadcrumbLabel crumb = { crumb } isLast = { idx === schema . crumbs ! . length - 1 } />
3972 </ BreadcrumbItem >
40- { idx < schema . crumbs . length - 1 && < BreadcrumbSeparator /> }
73+ { idx < schema . crumbs ! . length - 1 && < BreadcrumbSeparator /> }
4174 </ React . Fragment >
4275 ) ) }
4376 </ BreadcrumbList >
4477 </ Breadcrumb >
78+
79+ < div className = "ml-auto flex items-center gap-2" >
80+ { schema . search ?. enabled && (
81+ < div className = "relative" >
82+ < Search className = "absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
83+ < Input
84+ type = "search"
85+ placeholder = { schema . search . placeholder }
86+ className = "pl-8 w-[200px] lg:w-[300px]"
87+ />
88+ { schema . search . shortcut && (
89+ < kbd className = "pointer-events-none absolute right-2 top-2 hidden h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium opacity-100 sm:flex" >
90+ { schema . search . shortcut }
91+ </ kbd >
92+ ) }
93+ </ div >
94+ ) }
95+ { schema . actions ?. map ( ( action , idx ) => (
96+ < SchemaRenderer key = { idx } schema = { action } />
97+ ) ) }
98+ { schema . rightContent && < SchemaRenderer schema = { schema . rightContent } /> }
99+ </ div >
45100 </ header >
46101 ) ,
47102 {
48103 namespace : 'ui' ,
49104 label : 'Header Bar' ,
50105 inputs : [
51- { name : 'crumbs' , type : 'array' , label : 'Breadcrumbs' }
106+ { name : 'crumbs' , type : 'array' , label : 'Breadcrumbs' } ,
107+ { name : 'search' , type : 'object' , label : 'Search Configuration' } ,
108+ { name : 'actions' , type : 'array' , label : 'Action Slots' } ,
109+ { name : 'rightContent' , type : 'object' , label : 'Right Content' } ,
52110 ] ,
53111 defaultProps : {
54112 crumbs : [
0 commit comments