Skip to content

Commit 65e12f8

Browse files
authored
feat(pagination-nav): autodetect current page based on $route/URL. Add support array of links (#2836)
1 parent 35595f0 commit 65e12f8

24 files changed

+2247
-1350
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@
134134
"terser": "^3.17.0",
135135
"vue": "^2.6.9",
136136
"vue-jest": "^3.0.4",
137+
"vue-router": "^3.0.2",
137138
"vue-server-renderer": "^2.6.9",
138139
"vue-template-compiler": "^2.6.9"
139140
},

src/_utilities.scss

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Bootstrap Vue Utility classes
2+
3+
$bv-utility-classes-defined: false !default;
4+
5+
@if $bv-utility-classes-defined == false {
6+
// This test will only include these style definitions once
7+
8+
// Create .bv-d-<bp>-down-none helper classes
9+
@each $breakpoint in map-keys($grid-breakpoints) {
10+
@include media-breakpoint-down($breakpoint) {
11+
.bv-d-#{$breakpoint}-down-none { display: none !important; }
12+
}
13+
}
14+
}

src/components/index.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@
55
@import "form-input/index";
66
@import "form-radio/index";
77
@import "input-group/index";
8+
@import "pagination/index";
9+
@import "pagination-nav/index";
810
@import "table/index";

src/components/link/link.js

Lines changed: 15 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { keys } from '../../utils/object'
22
import { arrayIncludes, concat } from '../../utils/array'
3+
import { isRouterLink, computeTag, computeRel, computeHref } from '../../utils/router'
34
import { mergeData } from 'vue-functional-data-merge'
45

56
/**
@@ -77,6 +78,7 @@ export function propsFactory() {
7778

7879
export const props = propsFactory()
7980

81+
// Return a fresh copy of BLink props, containing only the specifeid prop(s)
8082
export function pickLinkProps(propsToPick) {
8183
const freshLinkProps = propsFactory()
8284
// Normalize everything to array.
@@ -91,6 +93,7 @@ export function pickLinkProps(propsToPick) {
9193
}, {})
9294
}
9395

96+
// Return a fresh copy of BLink props, keeping all but the specified omitting prop(s)
9497
export function omitLinkProps(propsToOmit) {
9598
const freshLinkProps = propsFactory()
9699
// Normalize everything to array.
@@ -105,90 +108,29 @@ export function omitLinkProps(propsToOmit) {
105108
}, {})
106109
}
107110

108-
export const computed = {
109-
linkProps() {
110-
let linkProps = {}
111-
let propKeys = keys(props)
112-
113-
for (let i = 0; i < propKeys.length; i++) {
114-
const prop = propKeys[i]
115-
// Computed Vue getters are bound to the instance.
116-
linkProps[prop] = this[prop]
117-
}
118-
119-
return linkProps
120-
}
121-
}
122-
123-
function computeTag(props, parent) {
124-
return parent.$router && props.to && !props.disabled
125-
? parent.$nuxt
126-
? 'nuxt-link'
127-
: 'router-link'
128-
: 'a'
129-
}
130-
131-
function isRouterLink(tag) {
132-
return tag !== 'a'
133-
}
134-
135-
function computeHref({ disabled, href, to }, tag) {
136-
// We've already checked the parent.$router in computeTag,
137-
// so isRouterLink(tag) indicates a live router.
138-
// When deferring to Vue Router's router-link, don't use the href attr at all.
139-
// We return null, and then remove href from the attributes passed to router-link
140-
if (isRouterLink(tag)) {
141-
return null
142-
}
143-
144-
// If href explicitly provided
145-
if (href) {
146-
return href
147-
}
148-
149-
// Reconstruct `href` when `to` used, but no router
150-
if (to) {
151-
// Fallback to `to` prop (if `to` is a string)
152-
if (typeof to === 'string') {
153-
return to
154-
}
155-
// Fallback to `to.path` prop (if `to` is an object)
156-
if (typeof to === 'object' && typeof to.path === 'string') {
157-
return to.path
158-
}
159-
}
160-
161-
// If nothing is provided use '#' as a fallback
162-
return '#'
163-
}
164-
165-
function computeRel({ target, rel }) {
166-
if (target === '_blank' && rel === null) {
167-
return 'noopener'
168-
}
169-
return rel || null
170-
}
171-
172111
function clickHandlerFactory({ disabled, tag, href, suppliedHandler, parent }) {
173-
return function onClick(e) {
174-
if (disabled && e instanceof Event) {
112+
return function onClick(evt) {
113+
if (disabled && evt instanceof Event) {
175114
// Stop event from bubbling up.
176-
e.stopPropagation()
115+
evt.stopPropagation()
177116
// Kill the event loop attached to this specific EventTarget.
178-
e.stopImmediatePropagation()
117+
evt.stopImmediatePropagation()
179118
} else {
180-
if (isRouterLink(tag) && e.target.__vue__) {
181-
e.target.__vue__.$emit('click', e)
119+
if (isRouterLink(tag) && evt.target.__vue__) {
120+
// Router links do not emit instance 'click' events, so we
121+
// add in an $emit('click', evt) on it's vue instance
122+
evt.target.__vue__.$emit('click', evt)
182123
}
183124
if (typeof suppliedHandler === 'function') {
184125
suppliedHandler(...arguments)
185126
}
186-
parent.$root.$emit('clicked::link', e)
127+
parent.$root.$emit('clicked::link', evt)
187128
}
188129

189130
if ((!isRouterLink(tag) && href === '#') || disabled) {
190-
// Stop scroll-to-top behavior or navigation.
191-
e.preventDefault()
131+
// Stop scroll-to-top behavior or navigation on regular links
132+
// when href is just '#'
133+
evt.preventDefault()
192134
}
193135
}
194136
}

src/components/link/link.spec.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { loadFixture, testVM } from '../../../tests/utils'
2+
import { propsFactory, pickLinkProps, omitLinkProps, props as linkProps } from './link'
23

34
describe('link', () => {
45
beforeEach(loadFixture(__dirname, 'link'))
@@ -96,4 +97,34 @@ describe('link', () => {
9697
app.$refs.click.click()
9798
expect(spy).toHaveBeenCalled()
9899
})
100+
101+
describe('propsFactory() helper', () => {
102+
it('works', async () => {
103+
expect(propsFactory()).toEqual(linkProps)
104+
expect(propsFactory()).not.toBe(linkProps)
105+
})
106+
})
107+
108+
describe('pickLinkProps() helper', () => {
109+
it('works', async () => {
110+
expect(pickLinkProps([])).toEqual({})
111+
expect(pickLinkProps(['append'])).toEqual({ append: linkProps.append })
112+
expect(pickLinkProps('to')).toEqual({ to: linkProps.to })
113+
expect(pickLinkProps(['append', 'routerTag'])).toEqual({
114+
append: linkProps.append,
115+
routerTag: linkProps.routerTag
116+
})
117+
})
118+
})
119+
120+
describe('omitLinkProps() helper', () => {
121+
it('works', async () => {
122+
expect(omitLinkProps([])).toEqual({ ...linkProps })
123+
const propsOmitted = Object.keys(linkProps).filter(p => p !== 'to' && p !== 'append')
124+
expect(omitLinkProps(propsOmitted)).toEqual({
125+
to: linkProps.to,
126+
append: linkProps.append
127+
})
128+
})
129+
})
99130
})

0 commit comments

Comments
 (0)