Skip to content

Commit f210cea

Browse files
authored
Merge branch 'dev' into feat-datepicker-timepicker-add-reset-method
2 parents befea12 + c0959c4 commit f210cea

File tree

10 files changed

+162
-86
lines changed

10 files changed

+162
-86
lines changed

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,14 +97,14 @@
9797
"@babel/plugin-transform-runtime": "^7.12.10",
9898
"@babel/preset-env": "^7.12.11",
9999
"@babel/standalone": "^7.12.12",
100-
"@nuxt/content": "^1.11.1",
100+
"@nuxt/content": "^1.12.0",
101101
"@nuxtjs/google-analytics": "^2.4.0",
102102
"@nuxtjs/pwa": "^3.3.5",
103103
"@nuxtjs/robots": "^2.4.2",
104104
"@nuxtjs/sitemap": "^2.4.0",
105105
"@testing-library/jest-dom": "^5.11.9",
106106
"@vue/test-utils": "^1.1.2",
107-
"autoprefixer": "^10.2.3",
107+
"autoprefixer": "^10.2.4",
108108
"babel-core": "^7.0.0-bridge.0",
109109
"babel-eslint": "^10.1.0",
110110
"babel-jest": "^26.6.3",
@@ -116,7 +116,7 @@
116116
"codesandbox": "^2.2.1",
117117
"core-js": "^3.8.3",
118118
"cross-env": "^7.0.3",
119-
"eslint": "^7.18.0",
119+
"eslint": "^7.19.0",
120120
"eslint-config-prettier": "^7.2.0",
121121
"eslint-config-standard": "^16.0.2",
122122
"eslint-config-vue": "^2.0.2",
@@ -143,7 +143,7 @@
143143
"postcss-cli": "^8.3.1",
144144
"prettier": "1.14.3",
145145
"require-context": "^1.1.0",
146-
"rollup": "^2.38.1",
146+
"rollup": "^2.38.3",
147147
"rollup-plugin-babel": "^4.4.0",
148148
"rollup-plugin-commonjs": "^10.1.0",
149149
"rollup-plugin-node-resolve": "^5.2.0",

src/components/form-group/form-group.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,6 @@ export const BFormGroup = {
305305
props: {
306306
ariaLive: feedbackAriaLive,
307307
id: invalidFeedbackId,
308-
role: feedbackAriaLive ? 'alert' : null,
309308
// If state is explicitly `false`, always show the feedback
310309
state,
311310
tooltip
@@ -326,7 +325,6 @@ export const BFormGroup = {
326325
props: {
327326
ariaLive: feedbackAriaLive,
328327
id: validFeedbackId,
329-
role: feedbackAriaLive ? 'alert' : null,
330328
// If state is explicitly `true`, always show the feedback
331329
state,
332330
tooltip

src/components/form-group/form-group.spec.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -321,14 +321,12 @@ describe('form-group', () => {
321321
const $invalidFeedback = wrapper.find('.invalid-feedback')
322322
expect($invalidFeedback.exists()).toBe(true)
323323
expect($invalidFeedback.text()).toEqual('bar')
324-
expect($invalidFeedback.attributes('role')).toEqual('alert')
325324
expect($invalidFeedback.attributes('aria-live')).toEqual('assertive')
326325
expect($invalidFeedback.attributes('aria-atomic')).toEqual('true')
327326

328327
const $validFeedback = wrapper.find('.valid-feedback')
329328
expect($validFeedback.exists()).toBe(true)
330329
expect($validFeedback.text()).toEqual('baz')
331-
expect($validFeedback.attributes('role')).toEqual('alert')
332330
expect($validFeedback.attributes('aria-live')).toEqual('assertive')
333331
expect($validFeedback.attributes('aria-atomic')).toEqual('true')
334332

@@ -373,14 +371,12 @@ describe('form-group', () => {
373371
let $invalidFeedback = wrapper.find('.invalid-feedback')
374372
expect($invalidFeedback.exists()).toBe(true)
375373
expect($invalidFeedback.text()).toEqual('bar')
376-
expect($invalidFeedback.attributes('role')).toEqual('alert')
377374
expect($invalidFeedback.attributes('aria-live')).toEqual('polite')
378375
expect($invalidFeedback.attributes('aria-atomic')).toEqual('true')
379376

380377
let $validFeedback = wrapper.find('.valid-feedback')
381378
expect($validFeedback.exists()).toBe(true)
382379
expect($validFeedback.text()).toEqual('baz')
383-
expect($validFeedback.attributes('role')).toEqual('alert')
384380
expect($validFeedback.attributes('aria-live')).toEqual('polite')
385381
expect($validFeedback.attributes('aria-atomic')).toEqual('true')
386382

src/components/form-tags/_form-tags.scss

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,4 @@
11
.b-form-tags {
2-
.b-form-tags-list {
3-
margin-top: -0.25rem;
4-
5-
.b-from-tags-field,
6-
.b-form-tag {
7-
margin-top: 0.25rem;
8-
}
9-
}
10-
112
&.focus {
123
color: $input-focus-color;
134
background-color: $input-focus-bg;
@@ -35,6 +26,19 @@
3526
}
3627
}
3728

29+
.b-form-tags-list {
30+
margin-top: -0.25rem;
31+
32+
.b-from-tags-field,
33+
.b-form-tag {
34+
margin-top: 0.25rem;
35+
}
36+
}
37+
38+
.b-form-tags-input {
39+
color: $input-color;
40+
}
41+
3842
.b-form-tag {
3943
// Override default badge settings
4044
// Due to using text-truncate on the inner content

src/components/form-tags/form-tags.js

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,7 @@ import { RX_SPACES } from '../../constants/regex'
1818
import { SLOT_NAME_DEFAULT, SLOT_NAME_ADD_BUTTON_TEXT } from '../../constants/slots'
1919
import { arrayIncludes, concat } from '../../utils/array'
2020
import { cssEscape } from '../../utils/css-escape'
21-
import {
22-
attemptBlur,
23-
attemptFocus,
24-
closest,
25-
isActiveElement,
26-
matches,
27-
requestAF,
28-
select
29-
} from '../../utils/dom'
21+
import { attemptBlur, attemptFocus, closest, matches, requestAF, select } from '../../utils/dom'
3022
import { eventOn, eventOff, stopEvent } from '../../utils/events'
3123
import { identity } from '../../utils/identity'
3224
import { isEvent, isNumber, isString } from '../../utils/inspect'
@@ -39,6 +31,7 @@ import { formControlMixin, props as formControlProps } from '../../mixins/form-c
3931
import { formSizeMixin, props as formSizeProps } from '../../mixins/form-size'
4032
import { formStateMixin, props as formStateProps } from '../../mixins/form-state'
4133
import { idMixin, props as idProps } from '../../mixins/id'
34+
import { listenersMixin } from '../../mixins/listeners'
4235
import { normalizeSlotMixin } from '../../mixins/normalize-slot'
4336
import { BButton } from '../button/button'
4437
import { BFormInvalidFeedback } from '../form/form-invalid-feedback'
@@ -144,6 +137,7 @@ const props = makePropsConfigurable(
144137
export const BFormTags = /*#__PURE__*/ Vue.extend({
145138
name: NAME_FORM_TAGS,
146139
mixins: [
140+
listenersMixin,
147141
idMixin,
148142
modelMixin,
149143
formControlMixin,
@@ -186,6 +180,7 @@ export const BFormTags = /*#__PURE__*/ Vue.extend({
186180
},
187181
computedInputHandlers() {
188182
return {
183+
...this.bvListeners,
189184
input: this.onInputInput,
190185
change: this.onInputChange,
191186
keydown: this.onInputKeydown,
@@ -338,10 +333,6 @@ export const BFormTags = /*#__PURE__*/ Vue.extend({
338333
// will prevent the tag from being removed (i.e. confirmation)
339334
// Or emit cancelable `BvEvent`
340335
this.tags = this.tags.filter(t => t !== tag)
341-
// Return focus to the input (if possible)
342-
this.$nextTick(() => {
343-
this.focus()
344-
})
345336
},
346337
reset() {
347338
this.newTag = ''
@@ -413,13 +404,8 @@ export const BFormTags = /*#__PURE__*/ Vue.extend({
413404
},
414405
// --- Wrapper event handlers ---
415406
onClick(event) {
416-
const ignoreFocusSelector = this.computeIgnoreInputFocusSelector
417-
const { target } = event
418-
if (
419-
!this.disabled &&
420-
!isActiveElement(target) &&
421-
(!ignoreFocusSelector || !closest(ignoreFocusSelector, target, true))
422-
) {
407+
const { computeIgnoreInputFocusSelector: ignoreFocusSelector } = this
408+
if (!ignoreFocusSelector || !closest(ignoreFocusSelector, event.target, true)) {
423409
this.$nextTick(() => {
424410
this.focus()
425411
})
@@ -434,7 +420,7 @@ export const BFormTags = /*#__PURE__*/ Vue.extend({
434420
handleAutofocus() {
435421
this.$nextTick(() => {
436422
requestAF(() => {
437-
if (this.autofocus && !this.disabled) {
423+
if (this.autofocus) {
438424
this.focus()
439425
}
440426
})

src/components/form-tags/form-tags.spec.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,4 +842,41 @@ describe('form-tags', () => {
842842

843843
wrapper.destroy()
844844
})
845+
846+
it('emits focus and blur events', async () => {
847+
const onFocus = jest.fn()
848+
const onBlur = jest.fn()
849+
const wrapper = mount(BFormTags, {
850+
propsData: {
851+
value: ['apple', 'orange']
852+
},
853+
listeners: {
854+
focus: onFocus,
855+
blur: onBlur
856+
}
857+
})
858+
859+
expect(onFocus).not.toHaveBeenCalled()
860+
expect(onBlur).not.toHaveBeenCalled()
861+
862+
const $input = wrapper.find('input')
863+
expect(typeof wrapper.vm.$listeners.focus).toBe('function')
864+
865+
$input.trigger('focus')
866+
$input.trigger('focusin')
867+
await waitNT(wrapper.vm)
868+
await waitRAF()
869+
870+
expect(onFocus).toHaveBeenCalled()
871+
expect(onBlur).not.toHaveBeenCalled()
872+
873+
$input.trigger('blur')
874+
$input.trigger('focusout')
875+
await waitNT(wrapper.vm)
876+
await waitRAF()
877+
878+
expect(onBlur).toHaveBeenCalled()
879+
880+
wrapper.destroy()
881+
})
845882
})

src/components/table/helpers/mixin-selectable.js

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@ import { isArray, isNumber } from '../../../utils/inspect'
1212
import { looseEqual } from '../../../utils/loose-equal'
1313
import { mathMax, mathMin } from '../../../utils/math'
1414
import { makeProp } from '../../../utils/props'
15+
import { toString } from '../../../utils/string'
1516
import { sanitizeRow } from './sanitize-row'
1617

1718
// --- Constants ---
1819

1920
const SELECT_MODES = ['range', 'multi', 'single']
2021

22+
const ROLE_GRID = 'grid'
23+
2124
// --- Props ---
2225

2326
export const props = {
@@ -70,17 +73,19 @@ export const selectableMixin = Vue.extend({
7073
}
7174
},
7275
selectableTableAttrs() {
73-
const role = this.bvAttrs.role || 'grid'
76+
if (!this.isSelectable) {
77+
return {}
78+
}
7479

75-
return this.isSelectable
76-
? {
77-
role,
78-
// TODO:
79-
// Should this attribute not be included when `no-select-on-click` is set
80-
// since this attribute implies keyboard navigation?
81-
'aria-multiselectable': role === 'grid' ? String(this.selectableIsMultiSelect) : null
82-
}
83-
: {}
80+
const role = this.bvAttrs.role || ROLE_GRID
81+
82+
return {
83+
role,
84+
// TODO:
85+
// Should this attribute not be included when `no-select-on-click` is set
86+
// since this attribute implies keyboard navigation?
87+
'aria-multiselectable': role === ROLE_GRID ? toString(this.selectableIsMultiSelect) : null
88+
}
8489
}
8590
},
8691
watch: {

src/components/table/helpers/mixin-table-renderer.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ export const tableRendererMixin = Vue.extend({
115115
const ariaAttrs = this.isTableSimple
116116
? {}
117117
: {
118-
'aria-busy': this.computedBusy ? 'true' : 'false',
118+
'aria-busy': toString(this.computedBusy),
119119
'aria-colcount': toString(fields.length),
120120
// Preserve user supplied `aria-describedby`, if provided
121121
'aria-describedby':
@@ -135,7 +135,7 @@ export const tableRendererMixin = Vue.extend({
135135
...this.bvAttrs,
136136
// Now we can override any `$attrs` here
137137
id: this.safeId(),
138-
role: 'table',
138+
role: this.bvAttrs.role || 'table',
139139
...ariaAttrs,
140140
...selectableTableAttrs
141141
}

src/components/table/table-selectable.spec.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,47 @@ describe('table > row select', () => {
5252
wrapper.destroy()
5353
})
5454

55+
it('should apply user role if provided, grid role if multiselectable or table role otherwise', async () => {
56+
let wrapper = mount(BTable, {
57+
propsData: {
58+
fields: testFields,
59+
items: testItems
60+
}
61+
})
62+
63+
expect(wrapper).toBeDefined()
64+
await waitNT(wrapper.vm)
65+
66+
expect(wrapper.attributes('role')).toBe('table')
67+
wrapper.destroy()
68+
69+
wrapper = mount(BTable, {
70+
propsData: {
71+
fields: testFields,
72+
items: testItems,
73+
role: 'foobar'
74+
}
75+
})
76+
77+
await waitNT(wrapper.vm)
78+
79+
expect(wrapper.attributes('role')).toBe('foobar')
80+
wrapper.destroy()
81+
82+
wrapper = mount(BTable, {
83+
propsData: {
84+
fields: testFields,
85+
items: testItems,
86+
selectable: true
87+
}
88+
})
89+
90+
await waitNT(wrapper.vm)
91+
92+
expect(wrapper.attributes('role')).toBe('grid')
93+
wrapper.destroy()
94+
})
95+
5596
it('should have tabindex but not aria-selected when not selectable and has row-clicked listener', async () => {
5697
const wrapper = mount(BTable, {
5798
propsData: {

0 commit comments

Comments
 (0)