{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "block-ui",
  "title": "Block Ui",
  "type": "registry:ui",
  "files": [
    {
      "path": "packages/registry-vue/components/block-ui/BlockUi.vue",
      "content": "<script setup lang=\"ts\">\nimport type { HTMLAttributes } from 'vue'\nimport { computed, useSlots } from 'vue'\nimport { cn } from '@/lib/utils'\nimport { blockUiVariants } from './block-ui.variants'\nimport { Spinner } from '@/components/ui/spinner'\n\ninterface Props {\n  modelValue?: boolean\n  message?: string\n  opacity?: number\n  overlayColor?: string\n  blur?: boolean\n  showSpinner?: boolean\n  class?: HTMLAttributes['class']\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n  modelValue: false,\n  message: 'Loading...',\n  opacity: 0.6,\n  overlayColor: '',\n  blur: false,\n  showSpinner: true,\n})\n\nconst emit = defineEmits<{\n  'update:modelValue': [value: boolean]\n}>()\n\nconst slots = useSlots()\nconst hasIconSlot = computed(() => !!slots.icon)\n\nconst overlayStyle = computed(() => {\n  const style: Record<string, string> = {\n    opacity: String(props.opacity),\n  }\n  if (props.overlayColor) style.backgroundColor = props.overlayColor\n  return style\n})\n</script>\n\n<template>\n  <div\n    data-uipkge\n    data-slot=\"block-ui\"\n    :data-blocked=\"modelValue ? '' : undefined\"\n    :class=\"cn(blockUiVariants(), props.class)\"\n  >\n    <!-- Wrapped content -->\n    <div :class=\"cn('block-ui-content', blur && modelValue && 'pointer-events-none blur-[2px] transition-[filter]')\">\n      <slot />\n    </div>\n\n    <!-- Blocking overlay -->\n    <Transition name=\"block-ui-fade\">\n      <div\n        v-if=\"modelValue\"\n        class=\"absolute inset-0 z-50 flex flex-col items-center justify-center gap-3\"\n        role=\"status\"\n        aria-live=\"polite\"\n        aria-busy=\"true\"\n      >\n        <!-- Background layer (opacity only affects this layer) -->\n        <div class=\"absolute inset-0\" :style=\"overlayStyle\" :class=\"!overlayColor && 'bg-background'\" />\n        <!-- Content layer (spinner + message stay fully opaque) -->\n        <slot name=\"icon\">\n          <Spinner v-if=\"showSpinner\" size=\"lg\" />\n        </slot>\n        <p v-if=\"message || slots.message\" class=\"text-foreground text-sm font-medium\">\n          <slot name=\"message\">{{ message }}</slot>\n        </p>\n      </div>\n    </Transition>\n  </div>\n</template>\n\n<style scoped>\n.block-ui-fade-enter-active,\n.block-ui-fade-leave-active {\n  transition: opacity 0.2s ease;\n}\n.block-ui-fade-enter-from,\n.block-ui-fade-leave-to {\n  opacity: 0;\n}\n</style>\n",
      "type": "registry:ui",
      "target": "~/app/components/ui/block-ui/BlockUi.vue"
    },
    {
      "path": "packages/registry-vue/components/block-ui/block-ui.variants.ts",
      "content": "import type { VariantProps } from 'class-variance-authority'\nimport { cva } from 'class-variance-authority'\n\nexport const blockUiVariants = cva('relative inline-block')\n\nexport type BlockUiVariants = VariantProps<typeof blockUiVariants>\n",
      "type": "registry:ui",
      "target": "~/app/components/ui/block-ui/block-ui.variants.ts"
    },
    {
      "path": "packages/registry-vue/components/block-ui/index.ts",
      "content": "export { default as BlockUi } from './BlockUi.vue'\nexport { blockUiVariants, type BlockUiVariants } from './block-ui.variants'\n",
      "type": "registry:ui",
      "target": "~/app/components/ui/block-ui/index.ts"
    }
  ],
  "dependencies": [
    "class-variance-authority"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/spinner.json"
  ],
  "description": "Overlay that blocks interaction during loading. Wraps content and shows a spinner + message overlay. v-model toggles the blocked state with configurable overlay opacity, color, background blur, and custom icon/message slots. Composes the spinner primitive.",
  "categories": [
    "feedback",
    "utility"
  ]
}