UNPKG

@progress/kendo-vue-buttons

Version:
288 lines (287 loc) 10.2 kB
/** * @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 d, createVNode as a, Fragment as u, cloneVNode as b } from "vue"; import { Keys as h, getDefaultSlots as p, canUseDOM as c, kendoThemeMaps as v, validatePackage as S } from "@progress/kendo-vue-common"; import { internalButtons as w, toolbarButtons as g } from "../util.mjs"; import { packageMetadata as m } from "../package-metadata.mjs"; import { ToolbarScrollable as y } from "./tools/ToolbarScrollable.mjs"; import { ToolbarOverflowSection as T } from "./tools/ToolbarOverflowSection.mjs"; const I = /* @__PURE__ */ d({ name: "KendoToolbar", props: { tabIndex: { type: Number, default: 0 }, dir: { type: String, validator: function(t) { return [null, "ltr", "rtl"].includes(t); }, default: "ltr" }, keyboardNavigation: { type: Boolean, default: !0 }, buttons: { type: Array, default: function() { } }, size: { type: String, default: "medium", validator: function(t) { return [null, "small", "medium", "large"].includes(t); } }, fillMode: { type: String, default: "solid", validator: function(t) { return [null, "solid", "flat", "outline"].includes(t); } }, ariaLabel: String, overflow: { type: String, default: "section", validator: function(t) { return [null, "none", "section", "scroll"].includes(t); } }, scrollButtons: { type: String, default: "auto", validator: function(t) { return [null, "hidden", "visible", "auto"].includes(t); } }, scrollButtonsPosition: { type: String, default: "split", validator: function(t) { return [null, "start", "end", "split"].includes(t); } }, buttonScrollSpeed: { type: Number, default: 100 } }, emits: { resize: (t) => !0 }, data() { return { defaultSlot: null, offsetWidth: 0, offsetHeight: 0, currentButtons: [], focusedSelector: "", isScrollStartPosition: !0, isScrollEndPosition: !1, focusableButtons: [], isOverflowing: !1, scrollContentRef: null, lastToolbarWidthRef: 0, overFlowToolsRef: [], overFlowOpened: !1, visibleToolsRef: void 0 }; }, created() { this.focusedSelector = this.selectors.map((t) => t + ":focus").join(","), S(m); }, computed: { selectors() { return this.$props.buttons || g; }, wrapperClass() { const { size: t, fillMode: e, overflow: o, scrollButtons: s } = this.$props; return { "k-toolbar": !0, [`k-toolbar-${e}`]: e, [`k-toolbar-${v.sizeMap[t] || t}`]: t, "k-toolbar-scrollable": o === "scroll", "k-toolbar-scrollable-overlay": o === "scroll" && (s === "hidden" || s === void 0), "k-toolbar-scrollable-start": o === "scroll" && s === "hidden" && this.isScrollStartPosition, "k-toolbar-scrollable-end": o === "scroll" && s === "hidden" && this.isScrollEndPosition, "k-toolbar-section": o && o === "section" }; } }, mounted() { c && window.ResizeObserver && (this.observerResize = new window.ResizeObserver(this.onWindowResize), this.observerResize.observe(this.$el)); const t = this.$el; t && (this.offsetWidth = t.offsetWidth, this.offsetHeight = t.offsetHeight, this.$props.keyboardNavigation !== !1 && (this.currentButtons = this.getCurrentButtons(), this.setTabIndex(0))), this.scrollContentRef = this.$refs.toolbarScrollable && this.$refs.toolbarScrollable.scrollContentRef, this.defaultSlot && (this.visibleToolsRef = this.defaultSlot.filter((e) => e && e.type).map((e, o) => b(e, { key: e.key || o })), this.$nextTick(() => { this.checkOverflow(), this.initOverflow(this.$refs.toolbar); })); }, updated() { !this.$el || this.$props.keyboardNavigation === !1 || (this.currentButtons = this.getCurrentButtons(), this.setTabIndex(this.focusedIndex())); }, unmounted() { c && this.observerResize && this.observerResize.disconnect(), this.currentButtons.length = 0; }, render() { const { overflow: t, scrollButtons: e, scrollButtonsPosition: o, prevButton: s, nextButton: l, buttonScrollSpeed: n, dir: f, fillMode: i, size: r } = this.$props; return this.defaultSlot = p(this), a("div", { ref: "toolbar", class: this.wrapperClass, role: "toolbar", dir: f, "aria-label": this.$props.ariaLabel, onKeydown: this.onKeyDown }, [t === "scroll" && a(u, null, [a(y, { ref: "toolbarScrollable", scrollButtons: e, scrollButtonsPosition: o, prevButton: s, nextButton: l, isOverflowing: this.isOverflowing, buttonScrollSpeed: n, dir: f, isScrollStartPosition: this.isScrollStartPosition, isScrollEndPosition: this.isScrollEndPosition, toolbarItems: this.defaultSlot, onContentscroll: this.onContentScroll }, null)]), t === "section" && a(T, { opened: this.overFlowOpened, toolbarRef: this.$refs.toolbar, toolbarWidth: this.offsetWidth, fillMode: i, size: r, visibleTools: this.visibleToolsRef, overFlowTools: this.overFlowToolsRef, onToggleoverflow: this.onToggleoverflow, allTools: this.defaultSlot }, null), t === "none" && this.defaultSlot]); }, methods: { getCurrentButtons() { return this.$el && this.$el.querySelectorAll ? Array.from(this.$el.querySelectorAll(this.selectors.join(","))) : []; }, getInternalButtons() { return this.$el && this.$el.querySelectorAll ? Array.from(this.$el.querySelectorAll(w)) : []; }, focusedIndex() { const t = this.$el && this.$el.querySelector && this.$el.querySelector(this.focusedSelector); return Math.max(0, this.currentButtons.findIndex((e) => e === t)); }, setTabIndex(t) { const { tabIndex: e } = this.$props; this.currentButtons.forEach((o, s) => { o.tabIndex = s === t ? e : -1; }), this.getInternalButtons().forEach((o) => { o.tabIndex = -1; }); }, onKeyDown(t) { if (this.$props.keyboardNavigation === !1) return; const e = t.target; if (!(t.keyCode === h.left || t.keyCode === h.right) || t.defaultPrevented || this.currentButtons.findIndex((l) => l === e) === -1) return; const s = this.focusedIndex(); t.keyCode === h.left ? this.focusButton(s, s - 1) : this.focusButton(s, s + 1); }, focusButton(t, e) { const { tabIndex: o } = this.$props, s = this.currentButtons[e]; if (s) { s.tabIndex = o, s.focus(); const l = this.currentButtons[t]; l && (l.tabIndex = -1); } }, initOverflow(t, e) { let o = 200; const s = [], l = []; Array.from(t.children).forEach((n, f) => { o += Math.ceil(n.clientWidth), o <= this.$refs.toolbar.offsetWidth - 50 ? s.push(this.visibleToolsRef[f]) : l.push(this.visibleToolsRef[f]); }), this.visibleToolsRef = s, this.overFlowToolsRef = l; }, checkOverflow() { if (this.$props.overflow === "scroll") { const t = this.scrollContentRef; t && (this.isOverflowing = t.scrollWidth > t.clientWidth || t.scrollHeight > t.clientHeight, this.isOverflowing ? this.onContentScroll() : (this.isScrollStartPosition = !0, this.isScrollEndPosition = !0)); } else if (this.$props.overflow === "section" || this.$props.overflow === void 0) { const t = this.$refs.toolbar; let e = 0; if (t) { const o = t.offsetWidth, s = parseInt(window.getComputedStyle(t).gap || "0", 10), l = Array.from(t.children).reduce((i, r) => (i += Math.ceil(r.clientWidth), i), 0), n = Array.from(t.children).length, f = s * 2; if (e = 36 + Number(l) + n * s + f, e > o) { const i = [...this.visibleToolsRef], r = i.pop(); this.visibleToolsRef = i, r && (this.overFlowToolsRef = [r, ...this.overFlowToolsRef]), this.lastToolbarWidthRef = o; } else if (o > this.lastToolbarWidthRef + s * n / 2.75) { const i = [...this.overFlowToolsRef], r = i.shift(); r && this.lastToolbarWidthRef + s * n > 30 && (this.overFlowToolsRef = i, this.visibleToolsRef = [...this.visibleToolsRef, r]), this.lastToolbarWidthRef = o; } else this.$forceUpdate(); } } }, onWindowResize(t) { window.requestAnimationFrame(() => { const e = this.$el; if (this.overFlowOpened = !1, !e) return; const o = e.offsetWidth, s = e.offsetHeight; if (this.offsetWidth !== o || this.offsetHeight !== s) { this.offsetWidth = o, this.offsetHeight = s; const l = { offsetWidth: this.offsetWidth, offsetHeight: this.offsetHeight }; this.$emit("resize", { target: this, ...l, nativeEvent: t }); } this.checkOverflow(); }); }, onContentScroll(t) { const e = this.scrollContentRef; if (t && e) { let o, s; t === "next" ? o = !1 : e.scrollLeft <= this.$props.buttonScrollSpeed ? o = !0 : o = e.scrollLeft === 0, t === "prev" ? s = !1 : e.scrollLeft + e.clientWidth + this.$props.buttonScrollSpeed >= e.scrollWidth ? s = !0 : s = e.scrollLeft + e.clientWidth === e.scrollWidth, this.isScrollStartPosition = !!o, this.isScrollEndPosition = !!s; } else this.isScrollStartPosition = !0, this.isScrollEndPosition = !1; }, onToggleoverflow(t) { this.overFlowOpened = t; } } }); export { I as Toolbar };