UNPKG

@progress/kendo-vue-buttons

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