<template> <div class="context-menu-dropdown"> <div class="dropdown"> <button :data-offset="$attrs.dataOffset ?? undefined" class="btn" type="button" id="context-menu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" > <span class="tavasi tavasi-more-vert"></span> </button> <div :style="{ width: $attrs.width ?? undefined, height: $attrs.height ?? undefined, 'max-height': $attrs.maxHeight ?? '10rem', }" class="dropdown-menu" aria-labelledby="context-menu" > <div v-for="(action, index) in contextMenu"> <div v-if="action.show"> <div v-if="action.can"> <button v-if="!action.showOutside ?? true" v-can="action.can" class="dropdown-item" type="button" :key="index" @click="handleAction(action)" > <!-- put below line if authorization is ok. --> <!-- v-can="action.can" --> <NuxtImg :src="prepareIcon(action)" alt="" class="img-fluid" /> {{ action.title }} </button> </div> <div v-else> <button v-if="!action.showOutside ?? true" class="dropdown-item" type="button" :key="index" @click="handleAction(action)" > <!-- put below line if authorization is ok. --> <!-- v-can="action.can" --> <NuxtImg :src="prepareIcon(action)" alt="" class="img-fluid" /> {{ action.title }} </button> </div> </div> </div> </div> </div> </div> </template> <script> /** * @vue-prop {Array} list - لیست * @vue-prop {*} clickedItem - آیتمی که کلیک شده است * @vue-prop {*} contextMenu - منو که از سمت والد دریافت میگردد * @vue-prop {*} parentComponent - کامپوننت والد */ export default { // contextMenu: right click actions // list: folder or file list. // clickedItem: selected item in the loop. props: ["list", "clickedItem", "contextMenu", "parentComponent"], emits: [ "rename-item", "remove-item", "update-order", "import", "reply-to", "filter", "notifications", "search", "edit-item", ], methods: { /** * آمادهسازی آیکون. * * @param {object} options - گزینههای آیکون * @returns {string} - مسیر فایل SVG آیکون */ prepareIcon({ icon }) { try { return import(`assets/common/img/${icon}.svg`).default; } catch (err) { return import(`assets/common/img/icomoon/SVG/${icon}.svg`).default; } }, /** * انجام اقدامات کلیک راست بر روی پوشه. * * انجام تمام اقدامات کلیک راست بر روی پوشه/فایل. * * @param {object} selectedAction - اقدام انتخابشده توسط کاربر */ handleAction(selectedAction) { switch (selectedAction.action) { case "search": this.$emit("search"); break; case "notifications": this.$emit("notifications"); break; case "filter": this.$emit("filter"); break; case "new-sub-folder": this.$emit("new-sub-folder"); break; case "remove": this.$emit("remove-item"); break; case "remove-item": this.$emit("remove-item"); break; case "rename": this.toggleRenameForm(this.list, this.clickedItem); this.$emit("rename-item"); break; case "order": this.$emit("update-order", selectedAction.value); break; case "move": break; case "details": break; case "copy": this.$emit("copy-text"); break; case "import": this.$emit("import"); break; case "export": break; case "archive": break; case "reply-to": this.$emit("reply-to"); break; case "edit-item": this.$emit("edit-item"); break; case "close": this.$emit("close"); break; case "join-to-group": this.$emit("join-to-group"); break; case "remove-from-lobby": this.$emit("remove-from-lobby"); break; case "subjecting": this.$emit("subjecting"); break; case "show-text": this.$emit("show-text"); break; default: this.$emit("other", selectedAction.action); } }, /** * نمایش/مخفی کردن فرم تغییر نام. * * نمایش یا مخفی کردن فرم تغییر نام در صورت انتخاب گزینه تغییر نام یا بستن فرم تغییر نام. * 1- یافتن شاخص مورد انتخاب شده * 2- بررسی اینکه آیتم وجود دارد یا خیر. * 3- اگر آیتم وجود دارد، سپس تغییر وضعیت editMode را انجام میدهد * 4- و در نهایت وضعیت editMode آیتم یافتشده را تنظیم میکند. * * @param {array} list - لیست پوشه یا فایل * @param {object} clickedItem - پوشه/فایلی که کاربر میخواهد آن را تغییر نام دهد. */ toggleRenameForm(list, clickedItem) { const resultIndex = list.findIndex((item) => clickedItem.id === item.id); if (resultIndex > -1) { const editMode = list[resultIndex]?.editMode ?? false; this.$set(list[resultIndex], "editMode", !editMode); this.$set(list[resultIndex], "parentComponent", this.parentComponent); } }, }, }; </script> <style scoped lang="scss"> .context-menu-dropdown { position: absolute; left: 0; top: 0; height: 100%; transition: all 0.3s ease; display: flex; align-items: center; .dropdown { .dropdown-menu { width: 156px; // max-height: 291px; min-height: 5em; height: auto; max-height: 10rem; border-radius: 10px; background: #fff; border: 1px solid #bac4ce; overflow-y: auto; padding: 1em; z-index: 99; //top: -3.5em !important; left: 2.5em; // height: 10rem; .dropdown-item { font-weight: normal; font-size: 14px; text-align: right; color: #1b2733; border: 1px solid rgba(0, 0, 0, 0); padding: 0.2em 0; &:hover, &:focus { background-color: #f0f0f0; //font-weight: bold; } .img-fluid { width: 1.8em; } } } .btn { padding: 0; display: flex; align-items: center; background: rgba(255, 255, 255, 0.8); height: 100%; &[aria-expanded="true"] { .tavasi-more-vert:before { content: "\e940"; color: #dc3545; } } .tavasi { // transition: all 0.2s; // font-size: 20px; // color: #6f6f6f; } &:hover .tavasi { transform: scale(1.2); // transition: all 0.2s; // font-weight: bold; } } } } </style>