@shopware-ag/meteor-component-library
Version:
The meteor component library is a Vue component library developed by Shopware. It is based on the [Meteor Design System](https://shopware.design/).
548 lines (547 loc) • 20.7 kB
JavaScript
import './mt-popover-item-result.css';
;
const vue = require("vue");
const MtSearch = require("./common/MtSearch.js");
const MtPopoverItem = require("./common/MtPopoverItem.js");
const MtSmoothReflow = require("./common/MtSmoothReflow.js");
const MtText = require("./common/MtText.js");
const _pluginVue_exportHelper = require("./_plugin-vue_export-helper-9c783a34.js");
let currentDrag = null;
let currentDrop = null;
let dragElement = null;
let dragMouseOffsetX = 0;
let dragMouseOffsetY = 0;
let delayTimeout = null;
const dropZones = [];
const defaultDragConfig = {
delay: 100,
dragGroup: 1,
draggableCls: "is--draggable",
draggingStateCls: "is--dragging",
dragElementCls: "is--drag-element",
validDragCls: "is--valid-drag",
invalidDragCls: "is--invalid-drag",
preventEvent: true,
validateDrop: null,
validateDrag: null,
validateDragStart: null,
onDragStart: null,
onDragEnter: null,
onDragLeave: null,
onDrop: null,
data: null,
disabled: false
};
const defaultDropConfig = {
dragGroup: 1,
droppableCls: "is--droppable",
validDropCls: "is--valid-drop",
invalidDropCls: "is--invalid-drop",
validateDrop: null,
onDrop: null,
data: null
};
function onDrag(el, dragConfig, event) {
if (event instanceof MouseEvent && event.buttons !== 1) {
return false;
}
if (dragConfig.preventEvent) {
event.preventDefault();
event.stopPropagation();
}
if (dragConfig.delay === null || dragConfig.delay <= 0) {
startDrag(el, dragConfig, event);
} else {
delayTimeout = window.setTimeout(startDrag.bind({}, el, dragConfig, event), dragConfig.delay);
}
document.addEventListener("mouseup", stopDrag);
document.addEventListener("touchend", stopDrag);
return true;
}
function startDrag(el, dragConfig, event) {
if (dragConfig.validateDragStart !== null && !dragConfig.validateDragStart(dragConfig.data, el, event)) {
return;
}
delayTimeout = null;
if (currentDrag !== null) {
return;
}
currentDrag = { el, dragConfig };
const elBoundingBox = el.getBoundingClientRect();
const pageX = event instanceof MouseEvent && event.pageX || event instanceof TouchEvent && event.touches[0].pageX;
const pageY = event instanceof MouseEvent && event.pageY || event instanceof TouchEvent && event.touches[0].pageY;
dragMouseOffsetX = pageX - elBoundingBox.left;
dragMouseOffsetY = pageY - elBoundingBox.top;
dragElement = el.cloneNode(true);
dragElement.classList.add(dragConfig.dragElementCls);
dragElement.style.width = `${elBoundingBox.width}px`;
dragElement.style.translate = `${pageX - dragMouseOffsetX}px ${pageY - dragMouseOffsetY}px`;
dragElement.style.left = "0";
dragElement.style.top = "0";
document.body.appendChild(dragElement);
el.classList.add(dragConfig.draggingStateCls);
if (typeof currentDrag.dragConfig.onDragStart === "function") {
currentDrag.dragConfig.onDragStart(currentDrag.dragConfig, el, dragElement);
}
document.addEventListener("mousemove", moveDrag);
document.addEventListener("touchmove", moveDrag);
}
let rotationTimeout = 0;
function calculateRotation(oldX, newX) {
if (oldX && Math.abs(newX - oldX) > 2) {
const moveRight = newX - oldX > 0;
return `${moveRight ? 5 : -5}deg`;
}
return "";
}
function moveDrag(event) {
if (currentDrag === null) {
stopDrag();
return;
}
const pageX = event instanceof MouseEvent && event.pageX || event instanceof TouchEvent && event.touches[0].pageX;
const pageY = event instanceof MouseEvent && event.pageY || event instanceof TouchEvent && event.touches[0].pageY;
if (dragElement) {
const oldX = Number(dragElement.dataset.translateX);
const newX = pageX - dragMouseOffsetX;
const newY = pageY - dragMouseOffsetY;
dragElement.style.rotate = calculateRotation(oldX, newX);
clearTimeout(rotationTimeout);
rotationTimeout = window.setTimeout(() => {
if (dragElement)
dragElement.style.rotate = "0deg";
}, 100);
dragElement.style.translate = `${newX}px ${newY}px`;
dragElement.dataset.translateX = newX.toString();
}
if (event.type === "touchmove") {
const foundZone = dropZones.find((zone) => isEventOverElement(event, zone.el));
clearAllDropZoneHighlights();
if (foundZone) {
enterDropZone(foundZone.el, foundZone.dropConfig);
} else if (currentDrop) {
leaveDropZone(currentDrop.el, currentDrop.dropConfig);
}
}
}
function isEventOverElement(event, el) {
const pageX = event instanceof MouseEvent && event.pageX || event instanceof TouchEvent && event.touches[0].pageX;
const pageY = event instanceof MouseEvent && event.pageY || event instanceof TouchEvent && event.touches[0].pageY;
const box = el.getBoundingClientRect();
return pageX >= box.x && pageX <= box.x + box.width && pageY >= box.y && pageY <= box.y + box.height;
}
function stopDrag() {
var _a;
if (delayTimeout !== null) {
window.clearTimeout(delayTimeout);
delayTimeout = null;
return;
}
const validDrag = validateDrag();
const validDrop = validateDrop();
if (validDrag && currentDrag) {
if (typeof currentDrag.dragConfig.onDrop === "function") {
currentDrag.dragConfig.onDrop(
currentDrag.dragConfig.data,
validDrop ? (_a = currentDrop == null ? void 0 : currentDrop.dropConfig) == null ? void 0 : _a.data : null
);
}
}
if (validDrop && currentDrop) {
if (typeof currentDrop.dropConfig.onDrop === "function") {
currentDrop.dropConfig.onDrop(currentDrag == null ? void 0 : currentDrag.dragConfig.data, currentDrop.dropConfig.data);
}
}
document.removeEventListener("mousemove", moveDrag);
document.removeEventListener("touchmove", moveDrag);
document.removeEventListener("mouseup", stopDrag);
document.removeEventListener("touchend", stopDrag);
if (dragElement !== null) {
dragElement.remove();
dragElement = null;
}
if (currentDrag !== null) {
currentDrag.el.classList.remove(currentDrag.dragConfig.draggingStateCls);
currentDrag.el.classList.remove(currentDrag.dragConfig.validDragCls);
currentDrag.el.classList.remove(currentDrag.dragConfig.invalidDragCls);
currentDrag = null;
}
if (currentDrop !== null) {
currentDrop.el.classList.remove(currentDrop.dropConfig.validDropCls);
currentDrop.el.classList.remove(currentDrop.dropConfig.invalidDropCls);
currentDrop = null;
}
dragMouseOffsetX = 0;
dragMouseOffsetY = 0;
}
function enterDropZone(el, dropConfig) {
if (currentDrag === null) {
return;
}
currentDrop = { el, dropConfig };
const valid = validateDrop();
if (valid) {
el.classList.add(dropConfig.validDropCls);
el.classList.remove(dropConfig.invalidDropCls);
if (dragElement) {
dragElement.classList.add(currentDrag.dragConfig.validDragCls);
dragElement.classList.remove(currentDrag.dragConfig.invalidDragCls);
}
} else {
el.classList.add(dropConfig.invalidDropCls);
el.classList.remove(dropConfig.validDropCls);
if (dragElement) {
dragElement.classList.add(currentDrag.dragConfig.invalidDragCls);
dragElement.classList.remove(currentDrag.dragConfig.validDragCls);
}
}
if (typeof currentDrag.dragConfig.onDragEnter === "function") {
currentDrag.dragConfig.onDragEnter(
currentDrag.dragConfig.data,
currentDrop.dropConfig.data,
valid
);
}
}
function leaveDropZone(el, dropConfig) {
if (currentDrag === null) {
return;
}
if (currentDrop === null) {
return;
}
if (typeof currentDrag.dragConfig.onDragLeave === "function") {
currentDrag.dragConfig.onDragLeave(currentDrag.dragConfig.data, currentDrop.dropConfig.data);
}
el.classList.remove(dropConfig.validDropCls);
el.classList.remove(dropConfig.invalidDropCls);
if (dragElement) {
dragElement.classList.remove(currentDrag.dragConfig.validDragCls);
dragElement.classList.remove(currentDrag.dragConfig.invalidDragCls);
}
currentDrop = null;
}
function validateDrop() {
let valid = true;
let customDragValidation = true;
let customDropValidation = true;
if (currentDrag === null || currentDrop === null || currentDrop.dropConfig.dragGroup !== currentDrag.dragConfig.dragGroup) {
valid = false;
}
if (currentDrag !== null && typeof currentDrag.dragConfig.validateDrop === "function") {
customDragValidation = currentDrag.dragConfig.validateDrop(
currentDrag.dragConfig.data,
currentDrop == null ? void 0 : currentDrop.dropConfig.data
);
}
if (currentDrop !== null && typeof currentDrop.dropConfig.validateDrop === "function") {
customDropValidation = currentDrop.dropConfig.validateDrop(
currentDrag == null ? void 0 : currentDrag.dragConfig.data,
currentDrop.dropConfig.data
);
}
return valid && customDragValidation && customDropValidation;
}
function validateDrag() {
let valid = true;
let customDragValidation = true;
if (currentDrag === null) {
valid = false;
}
if (currentDrag !== null && typeof currentDrag.dragConfig.validateDrag === "function") {
customDragValidation = currentDrag.dragConfig.validateDrag(
currentDrag.dragConfig.data,
currentDrop == null ? void 0 : currentDrop.dropConfig.data
);
}
return valid && customDragValidation;
}
function mergeConfigs(defaultConfig, binding) {
const mergedConfig = { ...defaultConfig };
if (binding.value instanceof Object) {
Object.assign(mergedConfig, binding.value);
} else {
Object.assign(mergedConfig, { data: binding.value });
}
return mergedConfig;
}
const draggable = {
mounted(el, binding) {
const dragConfig = mergeConfigs(defaultDragConfig, binding);
el.dragConfig = dragConfig;
el.boundDragListener = onDrag.bind(this, el, el.dragConfig);
if (!dragConfig.disabled) {
el.classList.add(dragConfig.draggableCls);
el.addEventListener("mousedown", el.boundDragListener);
el.addEventListener("touchstart", el.boundDragListener);
}
},
updated(el, binding) {
const dragConfig = mergeConfigs(defaultDragConfig, binding);
if (el.dragConfig && el.dragConfig.disabled !== dragConfig.disabled) {
if (!dragConfig.disabled) {
el.classList.remove(el.dragConfig.draggableCls);
el.classList.add(dragConfig.draggableCls);
if (el.boundDragListener) {
el.addEventListener("mousedown", el.boundDragListener);
el.addEventListener("touchstart", el.boundDragListener);
}
} else {
el.classList.remove(el.dragConfig.draggableCls);
if (el.boundDragListener) {
el.removeEventListener("mousedown", el.boundDragListener);
el.removeEventListener("touchstart", el.boundDragListener);
}
}
}
Object.assign(el.dragConfig, dragConfig);
},
unmounted(el, binding) {
const dragConfig = mergeConfigs(defaultDragConfig, binding);
el.classList.remove(dragConfig.draggableCls);
if (el.boundDragListener) {
el.removeEventListener("mousedown", el.boundDragListener);
el.removeEventListener("touchstart", el.boundDragListener);
}
}
};
const droppable = {
mounted(el, binding) {
const dropConfig = mergeConfigs(defaultDropConfig, binding);
dropZones.push({ el, dropConfig });
el.classList.add(dropConfig.droppableCls);
el.addEventListener("mouseenter", enterDropZone.bind(this, el, dropConfig));
el.addEventListener("mouseleave", leaveDropZone.bind(this, el, dropConfig));
},
unmounted(el, binding) {
const dropConfig = mergeConfigs(defaultDropConfig, binding);
dropZones.splice(
dropZones.findIndex((zone) => zone.el === el),
1
);
el.classList.remove(dropConfig.droppableCls);
el.removeEventListener("mouseenter", enterDropZone.bind(this, el, dropConfig));
el.removeEventListener("mouseleave", leaveDropZone.bind(this, el, dropConfig));
},
updated: (el, binding) => {
const dropZone = dropZones.find((zone) => zone.el === el);
if (binding.value instanceof Object) {
Object.assign(dropZone == null ? void 0 : dropZone.dropConfig, binding.value);
} else {
Object.assign(dropZone == null ? void 0 : dropZone.dropConfig, { data: binding.value });
}
}
};
function clearAllDropZoneHighlights() {
dropZones.forEach((zone) => {
zone.el.classList.remove(zone.dropConfig.validDropCls);
zone.el.classList.remove(zone.dropConfig.invalidDropCls);
});
}
const _sfc_main = vue.defineComponent({
name: "MtPopoverItemResult",
directives: {
draggable,
droppable
},
components: {
"mt-search": MtSearch,
"mt-popover-item": MtPopoverItem,
"mt-smooth-reflow": MtSmoothReflow,
"mt-text": MtText
},
props: {
options: {
type: Array,
required: true
},
groups: {
type: Array,
required: false,
default: () => []
},
hideSearch: {
type: Boolean,
default: false
},
draggable: {
type: Boolean,
default: false
},
selectable: {
type: Boolean,
default: false
},
hidable: {
type: Boolean,
default: false
}
},
emits: [
"change-checkbox",
"change-visibility",
"click-group-action",
"click-option",
"change-order",
"search"
],
setup(props, { emit }) {
const dropConfig = {};
const dragConfig = {
disabled: !props.draggable,
delay: 200,
onDragStart: () => {
document.body.classList.add("is-popover-item-result-dragging");
},
onDrop: (dragConfigData, dropConfigData) => {
document.body.classList.remove("is-popover-item-result-dragging");
emit("change-order", {
itemId: dragConfigData == null ? void 0 : dragConfigData.id,
dropZone: dropConfigData == null ? void 0 : dropConfigData.dropZone,
dropId: dropConfigData == null ? void 0 : dropConfigData.id
});
}
};
const isOptionDraggable = (option) => {
return props.draggable && option.isSortable;
};
const getDragConfigForOption = (option) => {
return {
...dragConfig,
disabled: !isOptionDraggable(option)
};
};
const getOptionsForGroup = (groupId) => {
return props.options.filter((option) => option.parentGroup === groupId);
};
const getIconForOption = (option) => {
if (isOptionDraggable(option)) {
return "solid-grip-vertical-s";
}
if (props.draggable) {
return "solid-thumbtack";
}
return void 0;
};
return {
getOptionsForGroup,
getDragConfigForOption,
isOptionDraggable,
getIconForOption,
dropConfig,
dragConfig
};
}
});
const mtPopoverItemResult_vue_vue_type_style_index_0_lang = "";
const _hoisted_1 = { class: "mt-popover-item-result" };
const _hoisted_2 = ["aria-label"];
const _hoisted_3 = ["onClick"];
const _hoisted_4 = ["aria-label"];
const _hoisted_5 = {
key: 0,
class: "mt-popover-item-result__option_drop_before"
};
const _hoisted_6 = {
key: 1,
class: "mt-popover-item-result__option_drop_after"
};
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
const _component_mt_search = vue.resolveComponent("mt-search");
const _component_mt_text = vue.resolveComponent("mt-text");
const _component_mt_popover_item = vue.resolveComponent("mt-popover-item");
const _component_mt_smooth_reflow = vue.resolveComponent("mt-smooth-reflow");
const _directive_droppable = vue.resolveDirective("droppable");
const _directive_draggable = vue.resolveDirective("draggable");
return vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [
!_ctx.hideSearch ? (vue.openBlock(), vue.createBlock(_component_mt_search, {
key: 0,
size: "small",
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => _ctx.$emit("search", $event))
})) : vue.createCommentVNode("", true),
(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList([void 0, ..._ctx.groups], (group) => {
return vue.openBlock(), vue.createElementBlock(vue.Fragment, {
key: "transition-group-" + (group && group.id)
}, [
vue.createVNode(vue.Transition, { name: "option-fade" }, {
default: vue.withCtx(() => [
group && _ctx.getOptionsForGroup(group.id).length > 0 ? (vue.openBlock(), vue.createElementBlock("div", {
key: group.id,
class: "mt-popover-item-result__group-header",
"aria-label": group.label
}, [
vue.createVNode(_component_mt_text, {
as: "span",
size: "xs",
color: "color-text-secondary-default",
class: "mt-popover-item-result__group-label"
}, {
default: vue.withCtx(() => [
vue.createTextVNode(vue.toDisplayString(group.label), 1)
]),
_: 2
}, 1024),
group.actionLabel ? (vue.openBlock(), vue.createElementBlock("button", {
key: 0,
type: "button",
class: "mt-popover-item-result__group-action",
onClick: () => _ctx.$emit("click-group-action", group.id)
}, vue.toDisplayString(group.actionLabel), 9, _hoisted_3)) : vue.createCommentVNode("", true)
], 8, _hoisted_2)) : vue.createCommentVNode("", true)
]),
_: 2
}, 1024),
vue.createVNode(_component_mt_smooth_reflow, null, {
default: vue.withCtx(() => [
vue.createVNode(vue.TransitionGroup, {
name: "option-item",
tag: "div"
}, {
default: vue.withCtx(() => [
(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(_ctx.getOptionsForGroup(group && group.id), (option) => {
return vue.openBlock(), vue.createElementBlock("div", {
key: option.id,
class: "mt-popover-item-result__option",
"aria-label": (group && group.label ? group.label : "No group") + ": " + option.label
}, [
_ctx.isOptionDraggable(option) ? vue.withDirectives((vue.openBlock(), vue.createElementBlock("div", _hoisted_5, null, 512)), [
[_directive_droppable, { ..._ctx.dropConfig, data: { ...option, dropZone: "before" } }]
]) : vue.createCommentVNode("", true),
vue.withDirectives(vue.createVNode(_component_mt_popover_item, {
class: "mt-popover-item-result__option_item",
"is-option-item": _ctx.isOptionDraggable(option),
label: option.label,
"show-checkbox": _ctx.selectable,
"checkbox-checked": option.isSelected,
"contextual-detail": option.contextualDetail,
"meta-copy": option.metaCopy,
"show-visibility": _ctx.hidable && option.isHidable,
visible: option.isVisible,
icon: _ctx.getIconForOption(option),
"on-label-click": option.isClickable ? () => _ctx.$emit("click-option", option.id) : void 0,
disabled: option.disabled,
onChangeCheckbox: ($event) => _ctx.$emit("change-checkbox", option.id, $event),
onChangeVisibility: ($event) => _ctx.$emit("change-visibility", option.id, $event)
}, null, 8, ["is-option-item", "label", "show-checkbox", "checkbox-checked", "contextual-detail", "meta-copy", "show-visibility", "visible", "icon", "on-label-click", "disabled", "onChangeCheckbox", "onChangeVisibility"]), [
[_directive_draggable, { ..._ctx.getDragConfigForOption(option), data: option }]
]),
_ctx.isOptionDraggable(option) ? vue.withDirectives((vue.openBlock(), vue.createElementBlock("div", _hoisted_6, null, 512)), [
[_directive_droppable, { ..._ctx.dropConfig, data: { ...option, dropZone: "after" } }]
]) : vue.createCommentVNode("", true)
], 8, _hoisted_4);
}), 128))
]),
_: 2
}, 1024)
]),
_: 2
}, 1024)
], 64);
}), 128))
]);
}
const MtPopoverItemResult = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main, [["render", _sfc_render]]);
exports.MtPopoverItemResult = MtPopoverItemResult;
exports.draggable = draggable;
exports.droppable = droppable;
//# sourceMappingURL=mt-popover-item-result-77871fb7.js.map