UNPKG

@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/).

1 lines 5.75 kB
{"version":3,"file":"mt-snackbar-9786f84c.mjs","sources":["../src/components/feedback-indicator/mt-snackbar/composables/use-snackbar.ts","../src/components/feedback-indicator/mt-snackbar/mt-snackbar.vue"],"sourcesContent":["import { createId } from \"@/utils/id\";\nimport { ref, reactive, readonly, type Ref } from \"vue\";\n\nexport interface Snackbar {\n id: string;\n message: string;\n variant?: \"success\" | \"error\" | \"warning\" | \"progress\";\n icon?: string;\n link?: {\n text: string;\n url: string;\n };\n duration?: number;\n progressPercentage?: number;\n uploadState?: \"success\" | \"error\";\n successMessage?: string;\n errorMessage?: string;\n}\n\n// Global snackbars state\nconst globalSnackbars = ref<Snackbar[]>([]);\n\nexport function useSnackbar() {\n function addSnackbar(snackbarData: Omit<Snackbar, \"id\">) {\n const snackbar = reactive({\n id: createId(),\n duration: 5000,\n ...snackbarData,\n });\n\n globalSnackbars.value.push(snackbar);\n\n return snackbar;\n }\n\n function removeSnackbar(id: string) {\n const index = globalSnackbars.value.findIndex((s) => s.id === id);\n if (index > -1) {\n globalSnackbars.value.splice(index, 1);\n }\n }\n\n function clearSnackbars() {\n globalSnackbars.value = [];\n }\n\n return {\n snackbars: readonly(globalSnackbars) as Ref<Snackbar[]>,\n addSnackbar,\n removeSnackbar,\n clearSnackbars,\n };\n}\n","<template>\n <Teleport to=\"body\">\n <div class=\"mt-snackbar\" @mouseenter=\"isHovered = true\" @mouseleave=\"isHovered = false\">\n <mt-snackbar-notification\n v-for=\"snackbar in snackbars\"\n :key=\"snackbar.id\"\n :snackbar=\"snackbar\"\n :is-hovered=\"isHovered\"\n :heights=\"heights\"\n @remove-snackbar=\"removeSnackbarWithHeightCleanup\"\n @update:height=\"updateHeight\"\n />\n </div>\n </Teleport>\n</template>\n\n<script setup lang=\"ts\">\nimport MtSnackbarNotification from \"./_internal/mt-snackbar-notification.vue\";\nimport { useSnackbar, type Snackbar } from \"./composables/use-snackbar\";\nimport { ref } from \"vue\";\n\nexport interface HeightT {\n height: number;\n snackbarId: string;\n}\n\nconst { snackbars, removeSnackbar } = useSnackbar();\n\nconst heights = ref<HeightT[]>([]);\nconst isHovered = ref(false);\n\nfunction updateHeight(h: HeightT) {\n // Find the index of the snackbar in the heights array\n const index = heights.value.findIndex((item) => item.snackbarId === h.snackbarId);\n // If the snackbar is found, update its height\n if (index !== -1) {\n heights.value[index] = h;\n } else {\n // If the snackbar is not found, add it to the heights array\n heights.value.unshift(h);\n }\n}\n\nfunction removeSnackbarWithHeightCleanup(snackbarToRemove: Snackbar) {\n // Remove the snackbar from the snackbars array\n removeSnackbar(snackbarToRemove.id);\n\n // Delay cleaning heights to give animation time to complete\n setTimeout(() => {\n if (!snackbars.value.find((s) => s.id === snackbarToRemove.id)) {\n heights.value = heights.value.filter((h) => h.snackbarId !== snackbarToRemove.id);\n }\n }, 250);\n}\n</script>\n\n<style scoped>\n.mt-snackbar {\n width: 360px;\n position: fixed;\n bottom: var(--scale-size-16);\n right: var(--scale-size-16);\n z-index: 1600;\n pointer-events: none;\n transition: transform 300ms cubic-bezier(0.16, 1, 0.3, 1);\n}\n\n.mt-snackbar :deep(.mt-snackbar-notification) {\n --y: translateY(100%);\n --lift: -1;\n position: absolute;\n transform: var(--y);\n bottom: var(--scale-size-0);\n right: var(--scale-size-0);\n opacity: 0;\n touch-action: none;\n pointer-events: auto;\n transition:\n transform 500ms cubic-bezier(0.16, 1, 0.3, 1),\n opacity 500ms cubic-bezier(0.16, 1, 0.3, 1),\n height 500ms cubic-bezier(0.16, 1, 0.3, 1);\n animation: slideInFromRight 0.5s cubic-bezier(0.66, 0, 0.34, 1);\n}\n\n.mt-snackbar :deep(.mt-snackbar-notification[data-mounted=\"true\"]) {\n --y: translateY(calc(var(--lift) * var(--offset)));\n opacity: 1;\n}\n\n/* Exit animation */\n.mt-snackbar :deep(.mt-snackbar-notification[data-removed=\"true\"]) {\n animation: slideOutToBottom 0.4s cubic-bezier(0.32, 0, 0.67, 0) forwards;\n}\n\n@keyframes slideInFromRight {\n 0% {\n transform: translateX(100%) var(--y);\n opacity: 0;\n }\n 100% {\n transform: translateX(0) var(--y);\n opacity: 1;\n }\n}\n\n@keyframes slideOutToBottom {\n 0% {\n transform: translateY(0) var(--y);\n opacity: 1;\n }\n 75% {\n opacity: 0;\n }\n 100% {\n transform: translateY(100%) var(--y);\n opacity: 0;\n }\n}\n</style>\n"],"names":[],"mappings":";;;;AAoBA,MAAM,kBAAkB,IAAgB,CAAA,CAAE;AAEnC,SAAS,cAAc;AAC5B,WAAS,YAAY,cAAoC;AACvD,UAAM,WAAW,SAAS;AAAA,MACxB,IAAI,SAAS;AAAA,MACb,UAAU;AAAA,MACV,GAAG;AAAA,IAAA,CACJ;AAEe,oBAAA,MAAM,KAAK,QAAQ;AAE5B,WAAA;AAAA,EACT;AAEA,WAAS,eAAe,IAAY;AAC5B,UAAA,QAAQ,gBAAgB,MAAM,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE;AAChE,QAAI,QAAQ,IAAI;AACE,sBAAA,MAAM,OAAO,OAAO,CAAC;AAAA,IACvC;AAAA,EACF;AAEA,WAAS,iBAAiB;AACxB,oBAAgB,QAAQ;EAC1B;AAEO,SAAA;AAAA,IACL,WAAW,SAAS,eAAe;AAAA,IACnC;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;;;;AC1BA,UAAM,EAAE,WAAW,eAAe,IAAI,YAAY;AAE5C,UAAA,UAAU,IAAe,CAAA,CAAE;AAC3B,UAAA,YAAY,IAAI,KAAK;AAE3B,aAAS,aAAa,GAAY;AAE1B,YAAA,QAAQ,QAAQ,MAAM,UAAU,CAAC,SAAS,KAAK,eAAe,EAAE,UAAU;AAEhF,UAAI,UAAU,IAAI;AACR,gBAAA,MAAM,KAAK,IAAI;AAAA,MAAA,OAClB;AAEG,gBAAA,MAAM,QAAQ,CAAC;AAAA,MACzB;AAAA,IACF;AAEA,aAAS,gCAAgC,kBAA4B;AAEnE,qBAAe,iBAAiB,EAAE;AAGlC,iBAAW,MAAM;AACX,YAAA,CAAC,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,iBAAiB,EAAE,GAAG;AACtD,kBAAA,QAAQ,QAAQ,MAAM,OAAO,CAAC,MAAM,EAAE,eAAe,iBAAiB,EAAE;AAAA,QAClF;AAAA,SACC,GAAG;AAAA,IACR;;;;;;;;;;;;;;;;;;;;;;;;;"}