UNPKG

@mezereon/ui-components-vue

Version:

UI components for Mezereon - Vue

294 lines (289 loc) 7.08 kB
import { isEmpty } from 'lodash' import { createPopper } from '@popperjs/core' import MzTooltip from './../components/MzTooltip' export default { name: 'Refinement', components: { MzTooltip }, props: { horizontal: { type: Boolean, required: true }, aggregation: { type: Object, required: true }, iconSet: { type: String, required: true } }, data() { return { hiddenProxy: null, popper: null } }, computed: { isBox() { return this.display.style === 'box' }, isSingle() { return this.display.selection === 'single' }, hidden: { get() { // if horizontal, then do not read cookie if (this.horizontal) { if (this.hiddenProxy == null) { this.hiddenProxy = true } return this.hiddenProxy } if (typeof process === 'object' || this.hiddenProxy === null) { if (!this.$cookies) { return false } let collapsed = this.$cookies.get( this.aggregation.name + '_collapsed' ) if (collapsed === undefined) { collapsed = this.display.collapsed } this.hiddenProxy = collapsed } return this.hiddenProxy }, set(value) { this.hiddenProxy = value // do not store state in cookies for horizontal facet if (this.horizontal) { return } if (this.$cookies) { this.$cookies.set(this.aggregation.name + '_collapsed', value, { sameSite: 'strict' }) } } }, isFilter() { return !this.hidden && !isEmpty(this.selected) }, items() { return this.aggregation.items }, display() { return this.aggregation.display }, selected() { return this.aggregation.selected } }, methods: { clickHandler(e) { if (!this.$el.contains(e.target)) { this.hide() } }, keyHandler(e) { if (e.key === 'Escape') { this.hide() } }, hide() { if (!this.hidden) this.toggleVisibility() }, toggleVisibility() { this.hidden = !this.hidden if (!this.hidden) { this.showPopper() } else { this.hidePopper() } }, setupPopper() { if (!this.horizontal) { return } const button = this.$refs.button const tooltip = this.$refs.tooltip if (button) { this.popper = createPopper(button, tooltip, { modifiers: [ { name: 'preventOverflow', options: { padding: 5 } }, { name: 'flip', options: { fallbackPlacements: ['top-start', 'bottom-start'] } }, { name: 'offset', options: { offset: [0, -1] } } ], placement: 'bottom-start' }) } }, showPopper() { if (!this.horizontal) { return } if (!this.$refs || !this.$refs.tooltip) { return } this.$refs.tooltip.setAttribute('data-show', '') this.popper.update() document.addEventListener('click', this.clickHandler) }, hidePopper() { if (!this.horizontal) { return } document.removeEventListener('click', this.clickHandler) this.$refs.tooltip.removeAttribute('data-show') }, showTooltip() { return { 'data-tooltip-position': 'top-right', 'data-tooltip-size': 'medium', role: 'tooltip' } }, checked(item) { return this.selected ? this.selected.find((x) => x === item.key) !== undefined : false }, clearSelections() { this.$emit('input', []) const event = { name: this.aggregation.name, value: [], last: { name: this.aggregation.name, action: 'remove-all' } } this.$emit('change', event) }, clear() { this.search = '' this.$nextTick(() => this.$refs.search.focus()) }, expand() { this.state = 'expanded' this.$nextTick(() => this.$refs.search.focus()) }, collapse() { this.state = 'collapsed' this.search = '' }, onClick(item) { // click event is relevant only for box if (this.isBox) { this.onChange(item) } }, uncheckParent(item, selected) { if (!item.parent) { return selected } selected = selected.filter((x) => x !== item.parent.key) this.$store.dispatch( 'search/updateSelections', { name: this.aggregation.name, label: this.aggregation.label, key: item.parent.key, value: item.parent.value, action: 'remove' }, { root: true } ) return selected }, uncheckChildren(item, selected) { if (!item.children) { return selected } for (const child of item.children) { selected = selected.filter((x) => x !== child.key) this.$store.dispatch( 'search/updateSelections', { name: this.aggregation.name, label: this.aggregation.label, key: child.key, value: child.value, action: 'remove' }, { root: true } ) } return selected }, onChange(item) { if (item.url && this.display.link == 'filters') { if (this.$queryState && this.$queryState.stringifyFilters) { const params = this.$queryState.stringifyFilters(this.filters) const conn = params ? (item.url.includes('?') ? '&' : '?') : '' const url = `${item.url}${conn}${params}` document.location.href = url return } } if (item.url) { document.location.href = item.url return } if (!this.selected) { return } const remove = this.checked(item) let selected = this.selected if (!remove) { selected = this.uncheckParent(item, selected) selected = this.uncheckChildren(item, selected) } const result = remove ? selected.filter((x) => x !== item.key) : this.isSingle ? [item.key] : [...selected, item.key] this.$emit('input', result) const event = { name: this.aggregation.name, value: result, last: { name: this.aggregation.name, label: this.aggregation.label, key: item.key, value: item.value, action: remove ? 'remove' : this.isSingle ? 'replace' : 'add' } } this.$emit('change', event) } }, mounted() { this.setupPopper() }, beforeDestroy() { if (!this.popper) { return } this.popper.destroy() } }