@progress/kendo-vue-buttons
Version:
266 lines (265 loc) • 8.93 kB
JavaScript
/**
* @license
*-------------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the package root for more information
*-------------------------------------------------------------------------------------------
*/
import { defineComponent as $, createVNode as n, ref as k } from "vue";
import { Button as y } from "../Button.mjs";
import { canUseDOM as C, Keys as i, getDefaultSlots as I, guid as a, validatePackage as D, classNames as O, kendoThemeMaps as x, templateRendering as l, getListeners as c } from "@progress/kendo-vue-common";
import w from "./utils/navigation.mjs";
import { ButtonItem as S } from "./ButtonItem.mjs";
import { Popup as B } from "@progress/kendo-vue-popup";
import { getPopupAlign as E, getAnchorAlign as K } from "./utils/popup.mjs";
import { packageMetadata as P } from "../package-metadata.mjs";
const U = /* @__PURE__ */ $({
name: "KendoDropDownButton",
emits: {
focus: null,
blur: null,
itemclick: null,
open: null,
close: null
},
props: {
accessKey: String,
items: {
type: Array,
default: function() {
return [];
}
},
ariaLabel: String,
text: String,
textField: String,
tabIndex: Number,
disabled: Boolean,
icon: String,
svgIcon: Object,
iconClass: String,
imageUrl: String,
popupSettings: Object,
itemRender: [String, Object, Function],
item: Function,
size: {
type: String,
default: "medium"
},
shape: {
type: String,
default: "rectangle",
validator: function(e) {
return [null, "rectangle", "square"].includes(e);
}
},
rounded: {
type: String,
default: "medium"
},
fillMode: {
type: String,
default: "solid",
validator: function(e) {
return [null, "flat", "link", "outline", "solid"].includes(e);
}
},
themeColor: {
type: String,
default: "base",
validator: function(e) {
return [null, "base", "dark", "error", "info", "inverse", "inverse", "light", "primary", "secondary", "success", "tertiary", "warning"].includes(e);
}
},
opened: {
type: Boolean,
default: void 0
},
buttonClass: String,
dir: String
},
created() {
this._blurTimeout = null, this._anchor = a(), this.wrapper = null, this.mainButton = null, this.guid = a(), this.buttonsData = [], D(P);
},
mounted() {
this.mainButton = this.$refs[this._anchor], (this.$props.dir === void 0 && this.isRtl() || this.computedOpened) && this.$forceUpdate();
},
updated() {
this.focused && this.element() && (this.mainButton = this.$refs[this._anchor], this.mainButton.focus());
},
data() {
return {
currentOpened: !1,
focused: !1,
focusedIndex: -1
};
},
computed: {
computedOpened() {
return this.$props.opened === void 0 ? this.currentOpened : this.$props.opened;
},
wrapperClass() {
return {
"k-dropdown-button": !0,
"k-focus": this.focused
};
}
},
setup() {
return {
kendoAnchorRef: k(null)
};
},
render() {
const e = this.isRtl(), t = e ? "rtl" : void 0, {
tabIndex: o,
disabled: p
} = this.$props, h = I(this);
this.buttonsData = this.$props.items;
const f = function() {
const {
item: s,
itemRender: r,
textField: g
} = this.$props;
return this.buttonsData.length > 0 ? this.buttonsData.map(function(u, d) {
const b = typeof u != "string" ? {
...u,
render: l.call(this, u.render, c.call(this))
} : u;
return n(S, {
class: "k-menu-item",
dataItem: b,
textField: g,
focused: this.focusedIndex === d,
onClick: this.onItemClick,
onDown: this.onItemDown,
render: l.call(this, r, c.call(this)),
item: s,
index: d,
key: d,
id: `${this.guid}-${d}`
}, null);
}, this) : null;
}, m = function() {
const {
popupSettings: s = {},
size: r
} = this.$props;
return n(B, {
anchor: this._anchor,
show: this.computedOpened,
animate: s.animate,
popupClass: O("k-menu-popup", s.popupClass),
anchorAlign: s.anchorAlign || K(e),
popupAlign: s.popupAlign || E(e),
style: e ? {
direction: "rtl"
} : void 0
}, {
default: () => [n("ul", {
class: `k-group k-menu-group k-reset k-menu-group-${x.sizeMap[r] || r}`,
role: "menu",
id: this.guid
}, [f.call(this)])]
});
};
return n("div", {
class: this.wrapperClass,
onKeydown: this.onKeyDown,
onFocusin: this.onFocus,
onFocusout: this.onBlur,
dir: t
}, [n(y, {
size: this.$props.size,
shape: this.$props.shape,
rounded: this.$props.rounded,
fillMode: this.$props.fillMode,
themeColor: this.$props.themeColor,
onClick: this.onClickMainButton,
onMousedown: this.mouseDown,
disabled: p || void 0,
tabIndex: o,
accessKey: this.$props.accessKey,
icon: this.$props.icon,
svgIcon: this.$props.svgIcon,
iconClass: this.$props.iconClass,
class: this.$props.buttonClass,
imageUrl: this.$props.imageUrl,
dir: t,
ref: this._anchor,
type: "button",
"aria-disabled": p,
"aria-haspopup": "menu",
"aria-expanded": this.computedOpened,
"aria-label": this.$props.ariaLabel || `${this.$props.text || ""} dropdownbutton`,
"aria-controls": this.guid,
"aria-activedescendant": this.focusedIndex !== void 0 && this.focusedIndex >= 0 ? `${this.guid}-${this.focusedIndex}` : void 0
}, {
default: () => [this.$props.text, h]
}), m.call(this)]);
},
methods: {
element() {
return this.mainButton;
},
onKeyDown(e) {
if (e.altKey) {
!this.computedOpened && e.keyCode === i.down ? (this.dispatchPopupEvent(e, !0), this.focusedIndex = 0, this.currentOpened = !0) : this.computedOpened && e.keyCode === i.up && (this.dispatchPopupEvent(e, !1), this.focusedIndex = -1, this.currentOpened = !1);
return;
}
if (e.keyCode === i.enter || e.keyCode === i.space ? (this.focusedIndex !== void 0 && this.focusedIndex >= 0 && this.dispatchClickEvent(e, this.focusedIndex), e.preventDefault(), this.focusedIndex = this.computedOpened ? -1 : 0, this.currentOpened = !this.computedOpened, this.dispatchPopupEvent(e, this.currentOpened)) : this.computedOpened && e.keyCode === i.esc && (this.focusedIndex = -1, this.currentOpened = !1, this.dispatchPopupEvent(e, this.currentOpened)), this.computedOpened) {
const t = w(this.focusedIndex, e.keyCode, e.altKey, this.buttonsData.length);
this.focusedIndex = t;
const o = e.keyCode === i.up || e.keyCode === i.down || e.keyCode === i.left || e.keyCode === i.right;
!e.altKey && o && e.preventDefault();
}
},
onFocus(e) {
this.focused || (this.focused = !0, this.$emit("focus", e, this, void 0)), this.focusedIndex = this.computedOpened ? 0 : -1, clearTimeout(this._blurTimeout);
},
onBlur(e) {
clearTimeout(this._blurTimeout), this.createBlurTimeout(e);
},
createBlurTimeout(e) {
const t = this;
this._blurTimeout = setTimeout(() => {
C && document.activeElement !== t.$el && (t.focused = !1, t.focusedIndex = -1, t.$emit("blur", e, t, void 0), t.computedOpened && (t.currentOpened = !1, t.dispatchPopupEvent(e, !1)));
}, 200);
},
onItemClick(e, t) {
this.focusedIndex = -1, this.currentOpened = !1, this.dispatchClickEvent(e, t), this.dispatchPopupEvent(e, !1);
},
onItemDown(e) {
document.activeElement === this.element() && e.preventDefault();
},
mouseDown(e) {
e.preventDefault();
},
dispatchClickEvent(e, t) {
this.isItemDisabled(t) || this.$emit("itemclick", {
event: e,
item: this.buttonsData[t],
itemIndex: t
});
},
onClickMainButton(e) {
if (!this.buttonsData.length)
return;
const t = !this.computedOpened;
this.currentOpened = t, this.focused = !0, this.focusedIndex = t ? 0 : -1, this.dispatchPopupEvent(e, t);
},
dispatchPopupEvent(e, t) {
this.$emit(t ? "open" : "close", e, this, void 0);
},
isItemDisabled(e) {
return this.buttonsData[e] ? this.buttonsData[e].disabled : this.$props.disabled;
},
isRtl() {
return this.$props.dir !== void 0 ? this.$props.dir === "rtl" : !!this.$el && getComputedStyle(this.$el).direction === "rtl";
}
}
});
export {
U as DropDownButton
};