{
  "name": "responsive-dialog",
  "type": "registry:ui",
  "dependencies": [
    "vaul"
  ],
  "registryDependencies": [
    "dialog",
    "drawer",
    "@diceui/use-as-ref",
    "@diceui/use-isomorphic-layout-effect",
    "@diceui/use-lazy-ref",
    "@diceui/use-mobile"
  ],
  "files": [
    {
      "path": "ui/responsive-dialog.tsx",
      "type": "registry:ui",
      "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport { useAsRef } from \"@/registry/bases/radix/hooks/use-as-ref\";\nimport { useIsomorphicLayoutEffect } from \"@/registry/bases/radix/hooks/use-isomorphic-layout-effect\";\nimport { useLazyRef } from \"@/registry/bases/radix/hooks/use-lazy-ref\";\nimport { useIsMobile } from \"@/registry/bases/radix/hooks/use-mobile\";\nimport {\n  Dialog,\n  DialogClose,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogOverlay,\n  DialogPortal,\n  DialogTitle,\n  DialogTrigger,\n} from \"@/registry/bases/radix/ui/dialog\";\nimport {\n  Drawer,\n  DrawerClose,\n  DrawerContent,\n  DrawerDescription,\n  DrawerFooter,\n  DrawerHeader,\n  DrawerOverlay,\n  DrawerPortal,\n  DrawerTitle,\n  DrawerTrigger,\n} from \"@/registry/bases/radix/ui/drawer\";\n\nconst ROOT_NAME = \"ResponsiveDialog\";\n\ninterface StoreState {\n  open: boolean;\n  isMobile: boolean;\n}\n\ninterface Store {\n  subscribe: (callback: () => void) => () => void;\n  getState: () => StoreState;\n  setState: <K extends keyof StoreState>(key: K, value: StoreState[K]) => void;\n  notify: () => void;\n}\n\nconst StoreContext = React.createContext<Store | null>(null);\n\nfunction useStore<T>(\n  selector: (state: StoreState) => T,\n  ogStore?: Store | null,\n): T {\n  const contextStore = React.useContext(StoreContext);\n  const store = ogStore ?? contextStore;\n\n  if (!store) {\n    throw new Error(`\\`useStore\\` must be used within \\`${ROOT_NAME}\\``);\n  }\n\n  const getSnapshot = React.useCallback(\n    () => selector(store.getState()),\n    [store, selector],\n  );\n\n  return React.useSyncExternalStore(store.subscribe, getSnapshot, getSnapshot);\n}\n\ninterface ResponsiveDialogProps extends React.ComponentProps<typeof Dialog> {\n  breakpoint?: number;\n}\n\nfunction ResponsiveDialog({\n  breakpoint = 768,\n  open: openProp,\n  defaultOpen = false,\n  onOpenChange: onOpenChangeProp,\n  ...props\n}: ResponsiveDialogProps) {\n  const isMobile = useIsMobile(breakpoint);\n\n  const listenersRef = useLazyRef(() => new Set<() => void>());\n  const stateRef = useLazyRef<StoreState>(() => ({\n    open: openProp ?? defaultOpen,\n    isMobile,\n  }));\n\n  const onOpenChangeRef = useAsRef(onOpenChangeProp);\n\n  const store = React.useMemo<Store>(() => {\n    return {\n      subscribe: (cb) => {\n        listenersRef.current.add(cb);\n        return () => listenersRef.current.delete(cb);\n      },\n      getState: () => stateRef.current,\n      setState: (key, value) => {\n        if (Object.is(stateRef.current[key], value)) return;\n\n        if (key === \"open\" && typeof value === \"boolean\") {\n          stateRef.current.open = value;\n          onOpenChangeRef.current?.(value);\n        } else {\n          stateRef.current[key] = value;\n        }\n\n        store.notify();\n      },\n      notify: () => {\n        for (const cb of listenersRef.current) {\n          cb();\n        }\n      },\n    };\n  }, [listenersRef, stateRef, onOpenChangeRef]);\n\n  if (stateRef.current.isMobile !== isMobile) {\n    stateRef.current.isMobile = isMobile;\n  }\n\n  const open = useStore((state) => state.open, store);\n\n  useIsomorphicLayoutEffect(() => {\n    if (openProp !== undefined) {\n      store.setState(\"open\", openProp);\n    }\n  }, [openProp]);\n\n  const onOpenChange = React.useCallback(\n    (value: boolean) => {\n      store.setState(\"open\", value);\n    },\n    [store],\n  );\n\n  if (isMobile) {\n    return (\n      <StoreContext.Provider value={store}>\n        <Drawer open={open} onOpenChange={onOpenChange} {...props} />\n      </StoreContext.Provider>\n    );\n  }\n\n  return (\n    <StoreContext.Provider value={store}>\n      <Dialog open={open} onOpenChange={onOpenChange} {...props} />\n    </StoreContext.Provider>\n  );\n}\n\nfunction ResponsiveDialogTrigger({\n  ...props\n}: React.ComponentProps<typeof DialogTrigger>) {\n  const isMobile = useStore((state) => state.isMobile);\n\n  if (isMobile) {\n    return <DrawerTrigger data-variant=\"drawer\" {...props} />;\n  }\n\n  return <DialogTrigger data-variant=\"dialog\" {...props} />;\n}\n\nfunction ResponsiveDialogClose({\n  ...props\n}: React.ComponentProps<typeof DialogClose>) {\n  const isMobile = useStore((state) => state.isMobile);\n\n  if (isMobile) {\n    return <DrawerClose data-variant=\"drawer\" {...props} />;\n  }\n\n  return <DialogClose data-variant=\"dialog\" {...props} />;\n}\n\nfunction ResponsiveDialogPortal({\n  ...props\n}: React.ComponentProps<typeof DialogPortal>) {\n  const isMobile = useStore((state) => state.isMobile);\n\n  if (isMobile) {\n    return <DrawerPortal data-variant=\"drawer\" {...props} />;\n  }\n\n  return <DialogPortal data-variant=\"dialog\" {...props} />;\n}\n\nfunction ResponsiveDialogOverlay({\n  ...props\n}: React.ComponentProps<typeof DialogOverlay>) {\n  const isMobile = useStore((state) => state.isMobile);\n\n  if (isMobile) {\n    return <DrawerOverlay data-variant=\"drawer\" {...props} />;\n  }\n\n  return <DialogOverlay data-variant=\"dialog\" {...props} />;\n}\n\nfunction ResponsiveDialogContent({\n  className,\n  ...props\n}: React.ComponentProps<typeof DialogContent>) {\n  const isMobile = useStore((state) => state.isMobile);\n\n  if (isMobile) {\n    return (\n      <DrawerContent\n        data-variant=\"drawer\"\n        className={cn(\"px-4 pb-4\", className)}\n        {...props}\n      />\n    );\n  }\n\n  return (\n    <DialogContent data-variant=\"dialog\" className={className} {...props} />\n  );\n}\n\nfunction ResponsiveDialogHeader({\n  ...props\n}: React.ComponentProps<typeof DialogHeader>) {\n  const isMobile = useStore((state) => state.isMobile);\n\n  if (isMobile) {\n    return <DrawerHeader data-variant=\"drawer\" {...props} />;\n  }\n\n  return <DialogHeader data-variant=\"dialog\" {...props} />;\n}\n\nfunction ResponsiveDialogFooter({\n  showCloseButton,\n  ...props\n}: React.ComponentProps<typeof DialogFooter>) {\n  const isMobile = useStore((state) => state.isMobile);\n\n  if (isMobile) {\n    return <DrawerFooter data-variant=\"drawer\" {...props} />;\n  }\n\n  return (\n    <DialogFooter\n      data-variant=\"dialog\"\n      showCloseButton={showCloseButton}\n      {...props}\n    />\n  );\n}\n\nfunction ResponsiveDialogTitle({\n  ...props\n}: React.ComponentProps<typeof DialogTitle>) {\n  const isMobile = useStore((state) => state.isMobile);\n\n  if (isMobile) {\n    return <DrawerTitle data-variant=\"drawer\" {...props} />;\n  }\n\n  return <DialogTitle data-variant=\"dialog\" {...props} />;\n}\n\nfunction ResponsiveDialogDescription({\n  ...props\n}: React.ComponentProps<typeof DialogDescription>) {\n  const isMobile = useStore((state) => state.isMobile);\n\n  if (isMobile) {\n    return <DrawerDescription data-variant=\"drawer\" {...props} />;\n  }\n\n  return <DialogDescription data-variant=\"dialog\" {...props} />;\n}\n\nexport {\n  ResponsiveDialog,\n  ResponsiveDialogClose,\n  ResponsiveDialogContent,\n  ResponsiveDialogDescription,\n  ResponsiveDialogFooter,\n  ResponsiveDialogHeader,\n  ResponsiveDialogOverlay,\n  ResponsiveDialogPortal,\n  ResponsiveDialogTitle,\n  ResponsiveDialogTrigger,\n};\n",
      "target": ""
    }
  ]
}