Skip to content

Commit d5bb018

Browse files
committed
Feat: Added some components mirrored from BootstrapVue
1 parent 3c63444 commit d5bb018

File tree

13 files changed

+571
-32
lines changed

13 files changed

+571
-32
lines changed

src/components/Badge/CBadge.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { mergeData } from 'vue-functional-data-merge'
2+
// import pluckProps from '../../utils/pluck-props'
3+
import Link, { propsFactory as linkPropsFactory } from '../Link/CLink'
4+
5+
let linkProps = linkPropsFactory()
6+
delete linkProps.href.default
7+
delete linkProps.to.default
8+
9+
export const props = Object.assign(linkProps, {
10+
tag: {
11+
type: String,
12+
default: 'span'
13+
},
14+
variant: {
15+
type: String,
16+
default: 'secondary'
17+
},
18+
pill: {
19+
type: Boolean,
20+
default: false
21+
}
22+
})
23+
24+
export default {
25+
functional: true,
26+
name:'CBadge',
27+
props,
28+
render (h, { props, data, children }) {
29+
const tag = !props.href && !props.to ? props.tag : Link
30+
31+
const componentData = {
32+
staticClass: 'badge',
33+
class: [
34+
!props.variant ? 'badge-secondary' : `badge-${props.variant}`,
35+
{
36+
'badge-pill': Boolean(props.pill),
37+
active: props.active,
38+
disabled: props.disabled
39+
}
40+
],
41+
// props: pluckProps(linkProps, props)
42+
props: props
43+
}
44+
45+
return h(tag, mergeData(data, componentData), children)
46+
}
47+
}

src/components/Badge/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import CBadge from './CBadge'
2+
3+
export {
4+
CBadge
5+
}

src/components/Header/CHeaderDropdown.vue

Lines changed: 0 additions & 29 deletions
This file was deleted.

src/components/Header/index.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
import Header from './Header'
22
import HeaderDropdown from './HeaderDropdown'
33
import CHeader from './CHeader'
4-
import CHeaderDropdown from './CHeaderDropdown'
54

65
export {
76
Header,
87
HeaderDropdown,
9-
CHeader,
10-
CHeaderDropdown
8+
CHeader
119
}

src/components/Link/CLink.js

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
import { mergeData } from 'vue-functional-data-merge'
2+
// import { arrayIncludes, concat } from '../../utils/array'
3+
4+
/**
5+
* The Link component is used in many other BV components.
6+
* As such, sharing its props makes supporting all its features easier.
7+
* However, some components need to modify the defaults for their own purpose.
8+
* Prefer sharing a fresh copy of the props to ensure mutations
9+
* do not affect other component references to the props.
10+
*
11+
* https://github.com/vuejs/vue-router/blob/dev/src/components/link.js
12+
* @return {{}}
13+
*/
14+
export function propsFactory () {
15+
return {
16+
href: {
17+
type: String,
18+
default: null
19+
},
20+
rel: {
21+
type: String,
22+
default: null
23+
},
24+
target: {
25+
type: String,
26+
default: '_self'
27+
},
28+
active: {
29+
type: Boolean,
30+
default: false
31+
},
32+
activeClass: {
33+
type: String,
34+
default: 'active'
35+
},
36+
append: {
37+
type: Boolean,
38+
default: false
39+
},
40+
disabled: {
41+
type: Boolean,
42+
default: false
43+
},
44+
event: {
45+
type: [String, Array],
46+
default: 'click'
47+
},
48+
exact: {
49+
type: Boolean,
50+
default: false
51+
},
52+
exactActiveClass: {
53+
type: String,
54+
default: 'active'
55+
},
56+
replace: {
57+
type: Boolean,
58+
default: false
59+
},
60+
routerTag: {
61+
type: String,
62+
default: 'a'
63+
},
64+
to: {
65+
type: [String, Object],
66+
default: null
67+
}
68+
}
69+
}
70+
71+
export const props = propsFactory()
72+
73+
// export function pickLinkProps (propsToPick) {
74+
// const freshLinkProps = propsFactory()
75+
// // Normalize everything to array.
76+
// propsToPick = concat(propsToPick)
77+
//
78+
// return Object.keys(freshLinkProps).reduce((memo, prop) => {
79+
// if (arrayIncludes(propsToPick, prop)) {
80+
// memo[prop] = freshLinkProps[prop]
81+
// }
82+
//
83+
// return memo
84+
// }, {})
85+
// }
86+
//
87+
// export function omitLinkProps (propsToOmit) {
88+
// const freshLinkProps = propsFactory()
89+
// // Normalize everything to array.
90+
// propsToOmit = concat(propsToOmit)
91+
//
92+
// return Object.keys(props).reduce((memo, prop) => {
93+
// if (!arrayIncludes(propsToOmit, prop)) {
94+
// memo[prop] = freshLinkProps[prop]
95+
// }
96+
//
97+
// return memo
98+
// }, {})
99+
// }
100+
101+
export const computed = {
102+
linkProps () {
103+
let linkProps = {}
104+
let propKeys = Object.keys(props)
105+
106+
for (let i = 0; i < propKeys.length; i++) {
107+
const prop = propKeys[i]
108+
// Computed Vue getters are bound to the instance.
109+
linkProps[prop] = this[prop]
110+
}
111+
112+
return linkProps
113+
}
114+
}
115+
116+
function computeTag (props, parent) {
117+
return Boolean(parent.$router) && props.to && !props.disabled ? 'router-link' : 'a'
118+
}
119+
120+
/*eslint no-unused-vars: ["error", {"args": "none"}]*/
121+
function computeHref ({ disabled, href, to }, tag) {
122+
// We've already checked the parent.$router in computeTag,
123+
// so router-link means live router.
124+
// When deferring to Vue Router's router-link,
125+
// don't use the href attr at all.
126+
// Must return undefined for router-link to populate href.
127+
if (tag === 'router-link') return void 0
128+
// If href explicitly provided
129+
if (href) return href
130+
// Reconstruct href when `to` used, but no router
131+
if (to) {
132+
// Fallback to `to` prop (if `to` is a string)
133+
if (typeof to === 'string') return to
134+
// Fallback to `to.path` prop (if `to` is an object)
135+
if (typeof to === 'object' && typeof to.path === 'string') return to.path
136+
}
137+
// If nothing is provided use '#'
138+
return '#'
139+
}
140+
141+
function computeRel ({ target, rel }) {
142+
if (target === '_blank' && rel === null) {
143+
return 'noopener'
144+
}
145+
return rel || null
146+
}
147+
148+
function clickHandlerFactory ({ disabled, tag, href, suppliedHandler, parent }) {
149+
const isRouterLink = tag === 'router-link'
150+
151+
return function onClick (e) {
152+
if (disabled && e instanceof Event) {
153+
// Stop event from bubbling up.
154+
e.stopPropagation()
155+
// Kill the event loop attached to this specific EventTarget.
156+
e.stopImmediatePropagation()
157+
} else {
158+
parent.$root.$emit('clicked::link', e)
159+
160+
if (isRouterLink && e.target.__vue__) {
161+
e.target.__vue__.$emit('click', e)
162+
}
163+
if (typeof suppliedHandler === 'function') {
164+
suppliedHandler(...arguments)
165+
}
166+
}
167+
168+
if ((!isRouterLink && href === '#') || disabled) {
169+
// Stop scroll-to-top behavior or navigation.
170+
e.preventDefault()
171+
}
172+
}
173+
}
174+
175+
export default {
176+
functional: true,
177+
name: 'CLink',
178+
props: propsFactory(),
179+
render (h, { props, data, parent, children }) {
180+
const tag = computeTag(props, parent)
181+
const rel = computeRel(props)
182+
const href = computeHref(props, tag)
183+
const eventType = tag === 'router-link' ? 'nativeOn' : 'on'
184+
const suppliedHandler = (data[eventType] || {}).click
185+
const handlers = { click: clickHandlerFactory({ tag, href, disabled: props.disabled, suppliedHandler, parent }) }
186+
187+
const componentData = mergeData(data, {
188+
class: [
189+
props.active ? (props.exact ? props.exactActiveClass : props.activeClass) : null,
190+
{ disabled: props.disabled }
191+
],
192+
attrs: {
193+
rel,
194+
href,
195+
target: props.target,
196+
tabindex: props.disabled ? '-1' : (data.attrs ? data.attrs.tabindex : null),
197+
'aria-disabled': (tag === 'a' && props.disabled) ? 'true' : null
198+
},
199+
props: Object.assign(props, { tag: props.routerTag })
200+
})
201+
202+
// If href prop exists on router-link (even undefined or null) it fails working on SSR
203+
if (!componentData.attrs.href) {
204+
delete componentData.attrs.href
205+
}
206+
207+
// We want to overwrite any click handler since our callback
208+
// will invoke the supplied handler if !props.disabled
209+
componentData[eventType] = Object.assign(componentData[eventType] || {}, handlers)
210+
211+
return h(tag, componentData, children)
212+
}
213+
}

src/components/Link/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import CLink from './CLink'
2+
3+
export {
4+
CLink
5+
}

0 commit comments

Comments
 (0)