1
+ /**
2
+ * Hey! Welcome to @chakra-ui/vue-next CBreadcrumb
3
+ *
4
+ * Breadcrumbs help users visualize their current location in relation to the rest of the website or application by showing the hierarchy of pages
5
+ *
6
+ * @see Docs https://next.vue.chakra-ui.com/breadcrumb
7
+ * @see Source https://github.com/chakra-ui/chakra-ui-vue-next/blob/master/packages/c-breadcrumb/src/c-breadcrumb/c-breadcrumb.ts
8
+ * @see WAI-ARIA https://www.w3.org/TR/wai-aria-practices-1.2
9
+ */
10
+
11
+ import { h , defineComponent , PropType , ConcreteComponent , Component , computed , cloneVNode , VNode , VNodeProps , mergeProps } from 'vue'
12
+ import {
13
+ chakra ,
14
+ HTMLChakraProps ,
15
+ SystemProps ,
16
+ ThemingProps ,
17
+ StylesProvider ,
18
+ useMultiStyleConfig ,
19
+ useStyles ,
20
+ SystemStyleObject
21
+ } from '@chakra-ui/vue-system'
22
+ import { filterUndefined } from '@chakra-ui/utils'
23
+ import { getValidChildren , SNA , SNAO } from '@chakra-ui/vue-utils'
24
+
25
+ /**
26
+ * CBreadcrumb (root)
27
+ */
28
+
29
+
30
+ export interface BreadcrumbOptions {
31
+ /**
32
+ * The visual separator between each breadcrumb item
33
+ * @type string | ConcreteComponent | Component
34
+ */
35
+ separator ?: string | ConcreteComponent | Component
36
+ /**
37
+ * The left and right margin applied to the separator
38
+ * @type SystemProps["mx"]
39
+ */
40
+ spacing ?: SystemProps [ 'mx' ]
41
+ }
42
+
43
+ export interface BreadcrumbProps
44
+ extends HTMLChakraProps < 'nav' > ,
45
+ BreadcrumbOptions ,
46
+ ThemingProps < 'Breadcrumb' > { }
47
+
48
+
49
+ /**
50
+ * CBreadcrumb is used to render a breadcrumb navigation landmark.
51
+ * It renders a `nav` element with `aria-label` set to `breadcrumb`
52
+ *
53
+ * @see Docs https://next.vue.chakra-ui.com/breadcrumb
54
+ */
55
+ export const CBreadcrumb = defineComponent (
56
+ ( props : BreadcrumbProps , { attrs, slots } ) => {
57
+ const themingProps = computed < ThemingProps > ( ( ) =>
58
+ filterUndefined ( {
59
+ colorScheme : props . colorScheme ,
60
+ variant : props . variant ,
61
+ size : props . size ,
62
+ styleConfig : props . styleConfig ,
63
+ } )
64
+ )
65
+
66
+ const styles = useMultiStyleConfig ( 'Breadcrumb' , themingProps . value )
67
+ StylesProvider ( styles )
68
+
69
+ const separator = computed ( ( ) => slots ?. separator ?.( ) || props . separator )
70
+
71
+ return ( ) => {
72
+ const validChildren = getValidChildren ( slots )
73
+ const count = validChildren . length
74
+
75
+ const children = validChildren . map ( ( vnode : VNode < unknown , unknown , BreadcrumbOptions > , index : number ) => cloneVNode ( vnode , {
76
+ separator : separator . value ,
77
+ spacing : props . spacing ,
78
+ isLastChild : count === index + 1 ,
79
+ } ) )
80
+
81
+ return (
82
+ < chakra . nav
83
+ as = { props . as }
84
+ aria-label = "breadcrumb"
85
+ __css = { styles . value . container }
86
+ { ...attrs }
87
+ >
88
+ < chakra . ol __label = "chakra-breadcrumb__list" >
89
+ { ( ) => children }
90
+ </ chakra . ol >
91
+ </ chakra . nav >
92
+ )
93
+ }
94
+ }
95
+ )
96
+
97
+ // @ts -ignore "name" property is typically read-only for functional components
98
+ CBreadcrumb . name = 'CBreadcrumb'
99
+ CBreadcrumb . props = {
100
+ separator : {
101
+ type : SNAO as PropType < BreadcrumbOptions [ 'separator' ] > ,
102
+ default : '/'
103
+ } ,
104
+ spacing : {
105
+ type : SNA as PropType < BreadcrumbOptions [ 'spacing' ] > ,
106
+ default : '0.5rem'
107
+ } ,
108
+ as : {
109
+ type : [ String , Object ] as PropType < DOMElements | Component | string > ,
110
+ default : 'nav' ,
111
+ } ,
112
+ }
113
+
114
+
115
+ /**
116
+ * CBreadcrumbSeparator
117
+ */
118
+
119
+ export interface BreadcrumbSeparatorProps extends HTMLChakraProps < "div" > {
120
+ /**
121
+ * @type SystemProps["mx"]
122
+ */
123
+ spacing ?: SystemProps [ "mx" ]
124
+ }
125
+
126
+ /**
127
+ * The `CBreadcrumbSeparator` component is the separator for
128
+ * each breacrumb item.
129
+ */
130
+ export const CBreadcrumbSeparator = defineComponent ( ( props : BreadcrumbSeparatorProps , { attrs, slots } ) => {
131
+ const styles = useStyles ( )
132
+ const separatorStyles = computed < SystemStyleObject > ( ( ) => ( {
133
+ display : 'flex' ,
134
+ mx : props . spacing ,
135
+ ...styles . value . separator ,
136
+ } ) )
137
+
138
+ return ( ) => (
139
+ < chakra . span
140
+ role = "presentation"
141
+ __label = "chakra-breadcrumb__separator"
142
+ { ...attrs }
143
+ __css = { separatorStyles . value }
144
+ >
145
+ { slots }
146
+ </ chakra . span >
147
+ )
148
+ } )
149
+
150
+ CBreadcrumbSeparator . props = {
151
+ spacing : CBreadcrumb . props . spacing ,
152
+ }
153
+
154
+
155
+ // @ts -ignore "name" property is typically read-only for functional components
156
+ CBreadcrumbSeparator . name = 'CBreadcrumbSeparator'
157
+
158
+
159
+ /**
160
+ * CBreadcrumbItem
161
+ */
162
+
163
+ interface BreadcrumbItemOptions extends BreadcrumbOptions {
164
+ isCurrentPage ?: boolean
165
+ isLastChild ?: boolean
166
+ }
167
+
168
+ export interface BreadcrumbItemProps
169
+ extends BreadcrumbItemOptions ,
170
+ HTMLChakraProps < "li" > { }
171
+
172
+ export const CBreadcrumbItem = defineComponent ( ( props : BreadcrumbItemProps , { attrs, slots } ) => {
173
+ const styles = useStyles ( )
174
+ const itemStyles = computed < SystemStyleObject > ( ( ) => ( {
175
+ display : "inline-flex" ,
176
+ alignItems : "center" ,
177
+ ...styles . value . item ,
178
+ } ) )
179
+
180
+ return ( ) => {
181
+ const validChildren = getValidChildren ( slots )
182
+ const children = validChildren . map ( ( vnode : VNode < unknown , unknown , BreadcrumbItemOptions > ) => {
183
+ // @ts -expect-error The "name" property is not typed on `VNodeTypes` but we need to access it during runtime
184
+ if ( vnode . type . name === 'CBreadcrumbLink' ) {
185
+ return cloneVNode ( vnode , {
186
+ isCurrentPage : props . isCurrentPage ,
187
+ } )
188
+ }
189
+
190
+ // @ts -expect-error The "name" property is not typed on `VNodeTypes` but we need to access it during runtime
191
+ if ( vnode . type . name === 'CBreadcrumbSeparator' ) {
192
+ return cloneVNode ( vnode , {
193
+ spacing : props . spacing ,
194
+ children : vnode . children || { default : ( ) => props . separator } ,
195
+ } )
196
+ }
197
+
198
+ return vnode
199
+ } )
200
+
201
+ return (
202
+ < chakra . li __label = "chakra-breadcrumb__list-it" __css = { itemStyles . value } >
203
+ { children }
204
+ { ! props . isLastChild && (
205
+ // @ts -expect-error
206
+ < CBreadcrumbSeparator spacing = { props . spacing } >
207
+ { ( ) => props . separator }
208
+ </ CBreadcrumbSeparator >
209
+ ) }
210
+ </ chakra . li >
211
+ )
212
+ }
213
+ } )
214
+
215
+ // @ts -ignore "name" property is typically read-only for functional components
216
+ CBreadcrumbItem . name = 'CBreadcrumbItem'
217
+ CBreadcrumbItem . props = {
218
+ ...CBreadcrumb . props ,
219
+ isLastChild : Boolean as PropType < boolean > ,
220
+ isCurrentPage : Boolean as PropType < boolean > ,
221
+ }
222
+
223
+ /**
224
+ * CBreadcrumbLink
225
+ */
226
+
227
+ export interface BreadcrumbLinkProps extends HTMLChakraProps < "a" > {
228
+ isCurrentPage ?: boolean
229
+ }
230
+
231
+ /**
232
+ * BreadcrumbLink link.
233
+ *
234
+ * It renders a `span` when it matches the current link. Otherwise,
235
+ * it renders an anchor tag.
236
+ */
237
+ export const CBreadcrumbLink = defineComponent ( ( props : BreadcrumbLinkProps , { attrs, slots } ) => {
238
+ const styles = useStyles ( )
239
+
240
+ return ( ) => {
241
+ if ( props . isCurrentPage ) {
242
+ return (
243
+ < chakra . span __label = "chakra-breadcrumb__link" aria-current = "page" __css = { styles . value . link } as = { props . as } { ...attrs } >
244
+ { slots }
245
+ </ chakra . span >
246
+ )
247
+ }
248
+
249
+ return (
250
+ < chakra . a __label = "chakra-breadcrumb__link" as = { props . as } __css = { styles . value . link } { ...attrs } >
251
+ { slots }
252
+ </ chakra . a >
253
+ )
254
+ }
255
+ } )
256
+
257
+ // @ts -ignore "name" property is typically read-only for functional components
258
+ CBreadcrumbLink . name = 'CBreadcrumbLink'
259
+ CBreadcrumbLink . props = {
260
+ isCurrentPage : Boolean as PropType < boolean > ,
261
+ }
0 commit comments