'<template>\n <TransitionFade :duration="500" appear tag="template">\n <Teleport v-if="fullPage && open" to="#teleports">\n <div :class="loaderStyles().backdrop({ class: backdropClass, fullPage })">\n <Icon :class="loaderStyles().icon({ class: props.class })" :name="props.icon" />\n <slot :open>{{ text }}</slot>\n </div>\n </Teleport>\n <div\n v-if="!fullPage && open"\n :class="loaderStyles().backdrop({ class: props.backdropClass, fullPage })"\n >\n <Icon :class="loaderStyles().icon({ class: props.class })" :name="props.icon" />\n <slot :open>{{ text }}</slot>\n </div>\n </TransitionFade>\n</template>\n\n<script lang="ts">\n import { useMagicKeys } from "@vueuse/core";\n import { useBodyScrollLock } from "radix-vue";\n import type { PrimitiveProps } from "radix-vue";\n\n export type LoaderProps = PrimitiveProps & {\n /**\n * The icon to display in the loader.\n *\n * @default "svg-spinners:bars-rotate-fade"\n */\n icon?: string;\n /**\n * The class to apply to the loader Icon\n */\n class?: any;\n /**\n * The class to apply to the backdrop\n */\n backdropClass?: any;\n /**\n * Whether the loader should take up the full page.\n *\n * When this is `true`, the loader will be displayed in a fixed position that covers the entire page. You can press the `esc` key to close the loader.\n */\n fullPage?: boolean;\n /**\n * Whether to lock the scroll when the loader is open.\n *\n * @default true\n */\n lockScroll?: boolean;\n /**\n * The role of the component.\n *\n * @default "progressbar"\n */\n role?: string;\n /**\n * The text to display in the loader.\n *\n * This is displayed below the loader icon.\n */\n text?: string;\n /**\n * Whether to close the loader when the `esc` key is pressed.\n *\n * @default true\n */\n closeOnEscape?: boolean;\n };\n\n export const loaderStyles = tv({\n slots: {\n icon: "size-5",\n backdrop: "flex flex-col items-center justify-center gap-3",\n },\n variants: {\n fullPage: {\n true: {\n backdrop:\n "pointer-events-auto fixed inset-0 z-[999] size-full bg-background/80 backdrop-blur-md",\n },\n false: {\n backdrop: "relative",\n },\n },\n },\n });\n</script>\n\n<script lang="ts" setup>\n defineOptions({ inheritAttrs: false });\n const props = withDefaults(defineProps<LoaderProps>(), {\n icon: "svg-spinners:bars-rotate-fade",\n role: "progressbar",\n closeOnEscape: true,\n });\n\n const open = defineModel<boolean>({ default: true });\n const isLocked = useBodyScrollLock();\n\n const { escape } = useMagicKeys();\n\n watchEffect(() => {\n if (props.fullPage && open.value && escape?.value && props.closeOnEscape) {\n open.value = false;\n }\n if (props.lockScroll && !open.value) {\n isLocked.value = false;\n }\n if (props.lockScroll && open.value) {\n isLocked.value = true;\n }\n });\n</script>\n',
0 commit comments