UNPKG

primevue

Version:

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![npm version](https://badge.fury.io/js/primevue.svg)](https://badge.fury.io/js/primevue) [![Discord Chat](https://img.shields.io/discord/55794023

655 lines (619 loc) 25.1 kB
import { ObjectUtils, DomHandler, ZIndexUtils, ConnectedOverlayScrollHandler } from 'primevue/utils'; import OverlayEventBus from 'primevue/overlayeventbus'; import Ripple from 'primevue/ripple'; import { resolveComponent, resolveDirective, openBlock, createBlock, Fragment, renderList, withDirectives, createVNode, resolveDynamicComponent, toDisplayString, createCommentVNode, renderSlot, createTextVNode, Teleport, Transition, withCtx } from 'vue'; var script = { name: 'CascadeSelectSub', emits: ['option-select','optiongroup-select'], props: { selectionPath: Array, level: Number, options: Array, optionLabel: String, optionValue: String, optionGroupLabel: String, optionGroupChildren: Array, parentActive: Boolean, dirty: Boolean, templates: null, root: Boolean }, data() { return { activeOption: null } }, mounted() { if (this.selectionPath && this.options && !this.dirty) { for (let option of this.options) { if (this.selectionPath.includes(option)) { this.activeOption = option; break; } } } if (!this.root) { this.position(); } }, watch: { parentActive(newValue) { if (!newValue) { this.activeOption = null; } } }, methods: { onOptionClick(event, option) { if (this.isOptionGroup(option)) { this.activeOption = (this.activeOption === option) ? null : option; this.$emit('optiongroup-select', { originalEvent: event, value: option }); } else { this.$emit('option-select', { originalEvent: event, value: this.getOptionValue(option) }); } }, onOptionSelect(event) { this.$emit('option-select', event); }, onOptionGroupSelect(event) { this.$emit('optiongroup-select', event); }, getOptionLabel(option) { return this.optionLabel ? ObjectUtils.resolveFieldData(option, this.optionLabel) : option; }, getOptionValue(option) { return this.optionValue ? ObjectUtils.resolveFieldData(option, this.optionValue) : option; }, getOptionGroupLabel(optionGroup) { return this.optionGroupLabel ? ObjectUtils.resolveFieldData(optionGroup, this.optionGroupLabel) : null; }, getOptionGroupChildren(optionGroup) { return ObjectUtils.resolveFieldData(optionGroup, this.optionGroupChildren[this.level]); }, isOptionGroup(option) { return Object.prototype.hasOwnProperty.call(option, this.optionGroupChildren[this.level]); }, getOptionLabelToRender(option) { return this.isOptionGroup(option) ? this.getOptionGroupLabel(option) : this.getOptionLabel(option); }, getItemClass(option) { return [ 'p-cascadeselect-item', { 'p-cascadeselect-item-group': this.isOptionGroup(option), 'p-cascadeselect-item-active p-highlight': this.isOptionActive(option) } ] }, isOptionActive(option) { return this.activeOption === option; }, onKeyDown(event, option, index) { switch (event.key) { case 'Down': case 'ArrowDown': var nextItem = this.$el.children[index + 1]; if (nextItem) { nextItem.children[0].focus(); } break; case 'Up': case 'ArrowUp': var prevItem = this.$el.children[index - 1]; if (prevItem) { prevItem.children[0].focus(); } break; case 'Right': case 'ArrowRight': if (this.isOptionGroup(option)) { if (this.isOptionActive(option)) { event.currentTarget.nextElementSibling.children[0].children[0].focus(); } else { this.activeOption = option; } } break; case 'Left': case 'ArrowLeft': this.activeOption = null; var parentList = event.currentTarget.parentElement.parentElement.previousElementSibling; if (parentList) { parentList.focus(); } break; case 'Enter': this.onOptionClick(event, option); break; } event.preventDefault(); }, position() { const parentItem = this.$el.parentElement; const containerOffset = DomHandler.getOffset(parentItem); const viewport = DomHandler.getViewport(); const sublistWidth = this.$el.offsetParent ? this.$el.offsetWidth : DomHandler.getHiddenElementOuterWidth(this.$el); const itemOuterWidth = DomHandler.getOuterWidth(parentItem.children[0]); if ((parseInt(containerOffset.left, 10) + itemOuterWidth + sublistWidth) > (viewport.width - DomHandler.calculateScrollbarWidth())) { this.$el.style.left = '-100%'; } } }, directives: { 'ripple': Ripple } }; const _hoisted_1 = { class: "p-cascadeselect-panel p-cascadeselect-items", role: "listbox", "aria-orientation": "horizontal" }; const _hoisted_2 = { key: 1, class: "p-cascadeselect-item-text" }; const _hoisted_3 = { key: 2, class: "p-cascadeselect-group-icon pi pi-angle-right" }; function render(_ctx, _cache, $props, $setup, $data, $options) { const _component_CascadeSelectSub = resolveComponent("CascadeSelectSub", true); const _directive_ripple = resolveDirective("ripple"); return (openBlock(), createBlock("ul", _hoisted_1, [ (openBlock(true), createBlock(Fragment, null, renderList($props.options, (option, i) => { return (openBlock(), createBlock("li", { key: $options.getOptionLabelToRender(option), class: $options.getItemClass(option), role: "none" }, [ withDirectives(createVNode("div", { class: "p-cascadeselect-item-content", onClick: $event => ($options.onOptionClick($event, option)), tabindex: "0", onKeydown: $event => ($options.onKeyDown($event, option, i)) }, [ ($props.templates['option']) ? (openBlock(), createBlock(resolveDynamicComponent($props.templates['option']), { key: 0, option: option }, null, 8, ["option"])) : (openBlock(), createBlock("span", _hoisted_2, toDisplayString($options.getOptionLabelToRender(option)), 1)), ($options.isOptionGroup(option)) ? (openBlock(), createBlock("span", _hoisted_3)) : createCommentVNode("", true) ], 40, ["onClick", "onKeydown"]), [ [_directive_ripple] ]), ($options.isOptionGroup(option) && $options.isOptionActive(option)) ? (openBlock(), createBlock(_component_CascadeSelectSub, { key: 0, class: "p-cascadeselect-sublist", selectionPath: $props.selectionPath, options: $options.getOptionGroupChildren(option), optionLabel: $props.optionLabel, optionValue: $props.optionValue, level: $props.level + 1, onOptionSelect: $options.onOptionSelect, onOptiongroupSelect: $options.onOptionGroupSelect, optionGroupLabel: $props.optionGroupLabel, optionGroupChildren: $props.optionGroupChildren, parentActive: $options.isOptionActive(option), dirty: $props.dirty, templates: $props.templates }, null, 8, ["selectionPath", "options", "optionLabel", "optionValue", "level", "onOptionSelect", "onOptiongroupSelect", "optionGroupLabel", "optionGroupChildren", "parentActive", "dirty", "templates"])) : createCommentVNode("", true) ], 2)) }), 128)) ])) } script.render = render; var script$1 = { name: 'CascadeSelect', emits: ['update:modelValue','change','group-change', 'before-show','before-hide','hide','show'], data() { return { selectionPath: null, focused: false, overlayVisible: false, dirty: false }; }, props: { modelValue: null, options: Array, optionLabel: String, optionValue: String, optionGroupLabel: String, optionGroupChildren: Array, placeholder: String, disabled: Boolean, dataKey: null, inputId: String, tabindex: String, ariaLabelledBy: null, appendTo: { type: String, default: 'body' }, panelClass: null, loading: { type: Boolean, default: false }, loadingIcon: { type: String, default: 'pi pi-spinner pi-spin' } }, outsideClickListener: null, scrollHandler: null, resizeListener: null, overlay: null, beforeUnmount() { this.unbindOutsideClickListener(); this.unbindResizeListener(); if (this.scrollHandler) { this.scrollHandler.destroy(); this.scrollHandler = null; } if (this.overlay) { ZIndexUtils.clear(this.overlay); this.overlay = null; } }, mounted() { this.updateSelectionPath(); }, watch: { modelValue() { this.updateSelectionPath(); } }, methods: { onOptionSelect(event) { this.$emit('update:modelValue', event.value); this.$emit('change', event); this.hide(); this.$refs.focusInput.focus(); }, onOptionGroupSelect(event) { this.dirty = true; this.$emit('group-change', event); }, getOptionLabel(option) { return this.optionLabel ? ObjectUtils.resolveFieldData(option, this.optionLabel) : option; }, getOptionValue(option) { return this.optionValue ? ObjectUtils.resolveFieldData(option, this.optionValue) : option; }, getOptionGroupChildren(optionGroup, level) { return ObjectUtils.resolveFieldData(optionGroup, this.optionGroupChildren[level]); }, isOptionGroup(option, level) { return Object.prototype.hasOwnProperty.call(option, this.optionGroupChildren[level]); }, updateSelectionPath() { let path; if (this.modelValue != null && this.options) { for (let option of this.options) { path = this.findModelOptionInGroup(option, 0); if (path) { break; } } } this.selectionPath = path; }, findModelOptionInGroup(option, level) { if (this.isOptionGroup(option, level)) { let selectedOption; for (let childOption of this.getOptionGroupChildren(option, level)) { selectedOption = this.findModelOptionInGroup(childOption, level + 1); if (selectedOption) { selectedOption.unshift(option); return selectedOption; } } } else if ((ObjectUtils.equals(this.modelValue, this.getOptionValue(option), this.dataKey))) { return [option]; } return null; }, show() { this.$emit('before-show'); this.overlayVisible = true; }, hide() { this.$emit('before-hide'); this.overlayVisible = false; }, onFocus() { this.focused = true; }, onBlur() { this.focused = false; }, onClick(event) { if (this.disabled || this.loading) { return; } if (!this.overlay || !this.overlay.contains(event.target)) { if (this.overlayVisible) this.hide(); else this.show(); this.$refs.focusInput.focus(); } }, onOverlayEnter(el) { ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay); this.alignOverlay(); this.bindOutsideClickListener(); this.bindScrollListener(); this.bindResizeListener(); this.$emit('show'); }, onOverlayLeave() { this.unbindOutsideClickListener(); this.unbindScrollListener(); this.unbindResizeListener(); this.$emit('hide'); this.overlay = null; this.dirty = false; }, onOverlayAfterLeave(el) { ZIndexUtils.clear(el); }, alignOverlay() { if (this.appendDisabled) { DomHandler.relativePosition(this.overlay, this.$el); } else { this.overlay.style.minWidth = DomHandler.getOuterWidth(this.$el) + 'px'; DomHandler.absolutePosition(this.overlay, this.$el); } }, bindOutsideClickListener() { if (!this.outsideClickListener) { this.outsideClickListener = (event) => { if (this.overlayVisible && this.overlay && !this.$el.contains(event.target) && !this.overlay.contains(event.target)) { this.hide(); } }; document.addEventListener('click', this.outsideClickListener); } }, unbindOutsideClickListener() { if (this.outsideClickListener) { document.removeEventListener('click', this.outsideClickListener); this.outsideClickListener = null; } }, bindScrollListener() { if (!this.scrollHandler) { this.scrollHandler = new ConnectedOverlayScrollHandler(this.$refs.container, () => { if (this.overlayVisible) { this.hide(); } }); } this.scrollHandler.bindScrollListener(); }, unbindScrollListener() { if (this.scrollHandler) { this.scrollHandler.unbindScrollListener(); } }, bindResizeListener() { if (!this.resizeListener) { this.resizeListener = () => { if (this.overlayVisible) { this.hide(); } }; window.addEventListener('resize', this.resizeListener); } }, unbindResizeListener() { if (this.resizeListener) { window.removeEventListener('resize', this.resizeListener); this.resizeListener = null; } }, overlayRef(el) { this.overlay = el; }, onKeyDown(event) { switch(event.key) { case 'Down': case 'ArrowDown': if (this.overlayVisible) { DomHandler.findSingle(this.overlay, '.p-cascadeselect-item').children[0].focus(); } else if (event.altKey && this.options && this.options.length) { this.show(); } event.preventDefault(); break; case 'Escape': if (this.overlayVisible) { this.hide(); event.preventDefault(); } break; case 'Tab': this.hide(); break; } }, onOverlayClick(event) { OverlayEventBus.emit('overlay-click', { originalEvent: event, target: this.$el }); } }, computed: { containerClass() { return [ 'p-cascadeselect p-component p-inputwrapper', { 'p-disabled': this.disabled, 'p-focus': this.focused, 'p-inputwrapper-filled': this.modelValue, 'p-inputwrapper-focus': this.focused || this.overlayVisible } ]; }, labelClass() { return [ 'p-cascadeselect-label', { 'p-placeholder': this.label === this.placeholder, 'p-cascadeselect-label-empty': !this.$slots['value'] && (this.label === 'p-emptylabel' || this.label.length === 0) } ]; }, label() { if (this.selectionPath) return this.getOptionLabel(this.selectionPath[this.selectionPath.length - 1]); else return this.placeholder||'p-emptylabel'; }, panelStyleClass() { return ['p-cascadeselect-panel p-component', this.panelClass, { 'p-input-filled': this.$primevue.config.inputStyle === 'filled', 'p-ripple-disabled': this.$primevue.config.ripple === false }]; }, appendDisabled() { return this.appendTo === 'self'; }, appendTarget() { return this.appendDisabled ? null : this.appendTo; }, dropdownIconClass() { return ['p-cascadeselect-trigger-icon', this.loading ? this.loadingIcon : 'pi pi-chevron-down']; } }, components: { 'CascadeSelectSub': script } }; const _hoisted_1$1 = { class: "p-hidden-accessible" }; const _hoisted_2$1 = { class: "p-cascadeselect-items-wrapper" }; function render$1(_ctx, _cache, $props, $setup, $data, $options) { const _component_CascadeSelectSub = resolveComponent("CascadeSelectSub"); return (openBlock(), createBlock("div", { ref: "container", class: $options.containerClass, onClick: _cache[5] || (_cache[5] = $event => ($options.onClick($event))) }, [ createVNode("div", _hoisted_1$1, [ createVNode("input", { ref: "focusInput", type: "text", id: $props.inputId, readonly: "", disabled: $props.disabled, onFocus: _cache[1] || (_cache[1] = (...args) => ($options.onFocus && $options.onFocus(...args))), onBlur: _cache[2] || (_cache[2] = (...args) => ($options.onBlur && $options.onBlur(...args))), onKeydown: _cache[3] || (_cache[3] = (...args) => ($options.onKeyDown && $options.onKeyDown(...args))), tabindex: $props.tabindex, "aria-haspopup": "listbox", "aria-expanded": $data.overlayVisible, "aria-labelledby": $props.ariaLabelledBy }, null, 40, ["id", "disabled", "tabindex", "aria-expanded", "aria-labelledby"]) ]), createVNode("span", { class: $options.labelClass }, [ renderSlot(_ctx.$slots, "value", { value: $props.modelValue, placeholder: $props.placeholder }, () => [ createTextVNode(toDisplayString($options.label), 1) ]) ], 2), createVNode("div", { class: "p-cascadeselect-trigger", role: "button", "aria-haspopup": "listbox", "aria-expanded": $data.overlayVisible }, [ createVNode("span", { class: $options.dropdownIconClass }, null, 2) ], 8, ["aria-expanded"]), (openBlock(), createBlock(Teleport, { to: $options.appendTarget, disabled: $options.appendDisabled }, [ createVNode(Transition, { name: "p-connected-overlay", onEnter: $options.onOverlayEnter, onLeave: $options.onOverlayLeave, onAfterLeave: $options.onOverlayAfterLeave }, { default: withCtx(() => [ ($data.overlayVisible) ? (openBlock(), createBlock("div", { key: 0, ref: $options.overlayRef, class: $options.panelStyleClass, onClick: _cache[4] || (_cache[4] = (...args) => ($options.onOverlayClick && $options.onOverlayClick(...args))) }, [ createVNode("div", _hoisted_2$1, [ createVNode(_component_CascadeSelectSub, { options: $props.options, selectionPath: $data.selectionPath, optionLabel: $props.optionLabel, optionValue: $props.optionValue, level: 0, templates: _ctx.$slots, optionGroupLabel: $props.optionGroupLabel, optionGroupChildren: $props.optionGroupChildren, onOptionSelect: $options.onOptionSelect, onOptiongroupSelect: $options.onOptionGroupSelect, dirty: $data.dirty, root: true }, null, 8, ["options", "selectionPath", "optionLabel", "optionValue", "templates", "optionGroupLabel", "optionGroupChildren", "onOptionSelect", "onOptiongroupSelect", "dirty"]) ]) ], 2)) : createCommentVNode("", true) ]), _: 1 }, 8, ["onEnter", "onLeave", "onAfterLeave"]) ], 8, ["to", "disabled"])) ], 2)) } function styleInject(css, ref) { if ( ref === void 0 ) ref = {}; var insertAt = ref.insertAt; if (!css || typeof document === 'undefined') { return; } var head = document.head || document.getElementsByTagName('head')[0]; var style = document.createElement('style'); style.type = 'text/css'; if (insertAt === 'top') { if (head.firstChild) { head.insertBefore(style, head.firstChild); } else { head.appendChild(style); } } else { head.appendChild(style); } if (style.styleSheet) { style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); } } var css_248z = "\n.p-cascadeselect {\n display: -webkit-inline-box;\n display: -ms-inline-flexbox;\n display: inline-flex;\n cursor: pointer;\n position: relative;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n.p-cascadeselect-trigger {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -webkit-box-align: center;\n -ms-flex-align: center;\n align-items: center;\n -webkit-box-pack: center;\n -ms-flex-pack: center;\n justify-content: center;\n -ms-flex-negative: 0;\n flex-shrink: 0;\n}\n.p-cascadeselect-label {\n display: block;\n white-space: nowrap;\n overflow: hidden;\n -webkit-box-flex: 1;\n -ms-flex: 1 1 auto;\n flex: 1 1 auto;\n width: 1%;\n text-overflow: ellipsis;\n cursor: pointer;\n}\n.p-cascadeselect-label-empty {\n overflow: hidden;\n visibility: hidden;\n}\n.p-cascadeselect .p-cascadeselect-panel {\n min-width: 100%;\n}\n.p-cascadeselect-panel {\n position: absolute;\n}\n.p-cascadeselect-item {\n cursor: pointer;\n font-weight: normal;\n white-space: nowrap;\n}\n.p-cascadeselect-item-content {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -webkit-box-align: center;\n -ms-flex-align: center;\n align-items: center;\n overflow: hidden;\n position: relative;\n}\n.p-cascadeselect-group-icon {\n margin-left: auto;\n}\n.p-cascadeselect-items {\n margin: 0;\n padding: 0;\n list-style-type: none;\n min-width: 100%;\n}\n.p-fluid .p-cascadeselect {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n}\n.p-fluid .p-cascadeselect .p-cascadeselect-label {\n width: 1%;\n}\n.p-cascadeselect-sublist {\n position: absolute;\n min-width: 100%;\n z-index: 1;\n display: none;\n}\n.p-cascadeselect-item-active {\n overflow: visible !important;\n}\n.p-cascadeselect-item-active > .p-cascadeselect-sublist {\n display: block;\n left: 100%;\n top: 0;\n}\n"; styleInject(css_248z); script$1.render = render$1; export default script$1;