🌐 AI搜索 & 代理 主页
Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 37 additions & 34 deletions src/components/button-toolbar/button-toolbar.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import Vue from '../../utils/vue'
import KeyCodes from '../../utils/key-codes'
import { attemptFocus, isVisible, selectAll } from '../../utils/dom'
import { attemptFocus, contains, isVisible, selectAll } from '../../utils/dom'
import normalizeSlotMixin from '../../mixins/normalize-slot'

// --- Constants ---

const ITEM_SELECTOR = [
'.btn:not(.disabled):not([disabled]):not(.dropdown-item)',
'.form-control:not(.disabled):not([disabled])',
Expand All @@ -11,6 +13,15 @@ const ITEM_SELECTOR = [
'input[type="radio"]:not(.disabled)'
].join(',')

// --- Utility methods ---

const stopEvent = evt => {
evt.preventDefault()
evt.stopPropagation()
}

// --- Main component ---

// @vue/component
export const BButtonToolbar = /*#__PURE__*/ Vue.extend({
name: 'BButtonToolbar',
Expand All @@ -26,37 +37,20 @@ export const BButtonToolbar = /*#__PURE__*/ Vue.extend({
}
},
mounted() {
// Pre-set the tabindexes if the markup does not include
// `tabindex="-1"` on the toolbar items
if (this.keyNav) {
// Pre-set the tabindexes if the markup does not include tabindex="-1" on the toolbar items
this.getItems()
}
},
methods: {
onFocusin(evt) {
if (evt.target === this.$el) {
evt.preventDefault()
evt.stopPropagation()
this.focusFirst(evt)
}
},
stop(evt) {
evt.preventDefault()
evt.stopPropagation()
},
onKeydown(evt) {
if (!this.keyNav) {
/* istanbul ignore next: should never happen */
return
}
const key = evt.keyCode
const shift = evt.shiftKey
if (key === KeyCodes.UP || key === KeyCodes.LEFT) {
this.stop(evt)
shift ? this.focusFirst(evt) : this.focusPrev(evt)
} else if (key === KeyCodes.DOWN || key === KeyCodes.RIGHT) {
this.stop(evt)
shift ? this.focusLast(evt) : this.focusNext(evt)
}
getItems() {
const items = selectAll(ITEM_SELECTOR, this.$el)
// Ensure `tabindex="-1"` is set on every item
items.forEach(item => {
item.tabIndex = -1
})
return items.filter(el => isVisible(el))
},
focusFirst() {
const items = this.getItems()
Expand All @@ -82,13 +76,22 @@ export const BButtonToolbar = /*#__PURE__*/ Vue.extend({
const items = this.getItems().reverse()
attemptFocus(items[0])
},
getItems() {
const items = selectAll(ITEM_SELECTOR, this.$el)
items.forEach(item => {
// Ensure tabfocus is -1 on any new elements
item.tabIndex = -1
})
return items.filter(el => isVisible(el))
onFocusin(evt) {
const { $el } = this
if (evt.target === $el && !contains($el, evt.relatedTarget)) {
stopEvent(evt)
this.focusFirst(evt)
}
},
onKeydown(evt) {
const { keyCode, shiftKey } = evt
if (keyCode === KeyCodes.UP || keyCode === KeyCodes.LEFT) {
stopEvent(evt)
shiftKey ? this.focusFirst(evt) : this.focusPrev(evt)
} else if (keyCode === KeyCodes.DOWN || keyCode === KeyCodes.RIGHT) {
stopEvent(evt)
shiftKey ? this.focusLast(evt) : this.focusNext(evt)
}
}
},
render(h) {
Expand Down