{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "dialog-02",
  "description": "Image gallery with nested auth dialogs. Inspired by Unsplash.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "@lumi-ui/dialog",
    "@lumi-ui/alert-dialog",
    "@lumi-ui/dropdown-menu",
    "@lumi-ui/button",
    "@lumi-ui/select",
    "@lumi-ui/toast",
    "@lumi-ui/separator"
  ],
  "files": [
    {
      "path": "registry/blocks/dialog-02/page.tsx",
      "content": "\"use client\";\n\nimport type { DialogRootChangeEventDetails } from \"@base-ui/react\";\nimport { ChevronLeft, ChevronRight, XIcon } from \"lucide-react\";\nimport * as React from \"react\";\nimport { Button } from \"@/registry/ui/button\";\nimport {\n  createDialogHandle,\n  Dialog,\n  DialogBackdrop,\n  DialogClose,\n  DialogPopup,\n  DialogPortal,\n  DialogTrigger,\n  DialogViewport,\n} from \"@/registry/ui/dialog\";\nimport { InfoMenu } from \"./components/info-menu\";\nimport { ProfileCard } from \"./components/profile-card\";\nimport { ShareMenu } from \"./components/share-menu\";\nimport { TooltipGroup } from \"./components/tooltip-group\";\n\nconst galleryHandle = createDialogHandle<IImage>();\n\nexport default function UnsplashDialog() {\n  const [open, setOpen] = React.useState(false);\n  const [triggerId, setTriggerId] = React.useState<string | null>(null);\n\n  const handleOpenChange = (\n    isOpen: boolean,\n    eventDetails: DialogRootChangeEventDetails,\n  ) => {\n    setOpen(isOpen);\n    setTriggerId(eventDetails.trigger?.id ?? null);\n  };\n  const navigate = React.useCallback(\n    (direction: \"next\" | \"prev\") => {\n      if (!triggerId) return;\n      const currentIndex = parseInt(triggerId.replace(\"trigger-\", \"\"), 10);\n      if (Number.isNaN(currentIndex)) return;\n\n      let nextIndex = 0;\n      if (direction === \"next\") {\n        nextIndex = (currentIndex + 1) % IMAGES.length;\n      } else {\n        nextIndex = (currentIndex - 1 + IMAGES.length) % IMAGES.length;\n      }\n\n      setTriggerId(`trigger-${nextIndex}`);\n    },\n    [triggerId],\n  );\n\n  return (\n    <>\n      <div className=\"grid grid-cols-3 gap-4 max-w-4xl\">\n        {IMAGES.map((img, i) => (\n          <DialogTrigger\n            handle={galleryHandle}\n            id={`trigger-${i}`}\n            key={img.alt}\n            payload={img}\n            render={\n              <button\n                className=\"relative aspect-square overflow-hidden rounded-lg cursor-pointer\"\n                type=\"button\"\n              >\n                <img\n                  alt={img.alt}\n                  className=\"h-full w-full object-cover\"\n                  src={img.src}\n                />\n              </button>\n            }\n          />\n        ))}\n      </div>\n      <Dialog\n        handle={galleryHandle}\n        onOpenChange={handleOpenChange}\n        open={open}\n        triggerId={triggerId}\n      >\n        {({ payload }) => (\n          <DialogPortal>\n            <DialogBackdrop />\n            <DialogViewport className=\"grid place-items-center overflow-y-auto\">\n              <DialogPopup className=\"flex h-full w-full justify-center pointer-events-none bg-transparent outline-0 animate-fade pt-12 sm:px-12\">\n                <div className=\"pointer-events-auto h-full w-full flex flex-col shadow-md bg-background sm:max-w-[calc(100vw-12rem)] rounded-2xl\">\n                  <DialogClose\n                    className=\"fixed left-2 top-2 rounded-full\"\n                    render={\n                      <Button\n                        className=\"size-8 rounded-full text-white/70 hover:bg-white/20 hover:text-white\"\n                        size=\"icon\"\n                        variant=\"ghost\"\n                      >\n                        <XIcon className=\"size-6\" />\n                        <span className=\"sr-only\">Close</span>\n                      </Button>\n                    }\n                  />\n                  <DialogClose\n                    className=\"absolute -top-12 right-0 md:hidden\"\n                    render={\n                      <Button\n                        className=\"rounded-full text-white/70 hover:bg-white/20 hover:text-white\"\n                        size=\"icon\"\n                        variant=\"ghost\"\n                      >\n                        <XIcon className=\"size-6\" />\n                        <span className=\"sr-only\">Close</span>\n                      </Button>\n                    }\n                  />\n                  <Button\n                    className=\"fixed hidden md:flex left-4 top-1/2 -translate-y-1/2 rounded-full text-white/70 hover:bg-white/20 hover:text-white md:left-8 md:size-12\"\n                    onClick={() => navigate(\"prev\")}\n                    size=\"icon\"\n                    variant=\"ghost\"\n                  >\n                    <ChevronLeft className=\"size-8\" />\n                    <span className=\"sr-only\">Previous image</span>\n                  </Button>\n\n                  <Button\n                    className=\"fixed hidden md:flex right-4 top-1/2 -translate-y-1/2 rounded-full text-white/70 hover:bg-white/20 hover:text-white md:right-8 md:size-12\"\n                    onClick={() => navigate(\"next\")}\n                    size=\"icon\"\n                    variant=\"ghost\"\n                  >\n                    <ChevronRight className=\"size-8\" />\n                    <span className=\"sr-only\">Next image</span>\n                  </Button>\n                  <div className=\"relative grid grid-rows-[auto_1fr_auto] h-[calc(100vh-3rem)]\">\n                    <div className=\"flex justify-between px-4 py-2\">\n                      <ProfileCard />\n                      {payload && <TooltipGroup currentImage={payload} />}\n                    </div>\n\n                    {payload && (\n                      <div className=\"flex flex-col max-w-4xl mx-auto items-center justify-center flex-1 w-full\">\n                        <img\n                          alt={payload.alt}\n                          className=\"h-full w-full h-[70vh] rounded-md object-contain\"\n                          key={payload.src}\n                          src={payload.src}\n                        />\n                      </div>\n                    )}\n\n                    {payload && (\n                      <div className=\"flex gap-8 p-4 text-sm justify-between\">\n                        <div className=\"flex gap-12\">\n                          <div className=\"flex flex-col gap-2\">\n                            <div className=\"text-muted-foreground font-semibold\">\n                              Views\n                            </div>\n                            <div>{payload?.views}</div>\n                          </div>\n                          <div className=\"flex flex-col gap-2\">\n                            <div className=\"text-muted-foreground font-semibold\">\n                              Downloads\n                            </div>\n                            <div>{payload?.downloads}</div>\n                          </div>\n                        </div>\n\n                        <div className=\"flex gap-2\">\n                          <ShareMenu />\n                          <InfoMenu />\n                        </div>\n                      </div>\n                    )}\n                  </div>\n                  <div className=\"max-w-7xl flex-1 w-full mx-auto space-y-4 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 min-h-screen pt-6\">\n                    {Array.from({ length: 12 }).map((_, i) => (\n                      <div\n                        className=\"flex h-64 w-full shrink-0 items-center justify-center rounded-md bg-muted\"\n                        key={String(i)}\n                      />\n                    ))}\n                  </div>\n                </div>\n              </DialogPopup>\n            </DialogViewport>\n          </DialogPortal>\n        )}\n      </Dialog>\n    </>\n  );\n}\n\nconst IMAGES: IImage[] = [\n  {\n    alt: \"Brown trees beside river under blue sky during daytime\",\n    downloads: 3578,\n    src: \"https://images.unsplash.com/photo-1579353977828-2a4eab540b9a?q=80&w=1000&auto=format&fit=crop\",\n    views: 5726,\n  },\n  {\n    alt: \"People watching illuminated japanese lanterns\",\n    downloads: 373,\n    src: \"https://images.unsplash.com/photo-1765614244329-22ca4157345a?q=80&w=1000&auto=format&fit=crop\",\n    views: 1253,\n  },\n  {\n    alt: \"Abstract colorful waves\",\n    downloads: 2354,\n    src: \"https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?q=80&w=1000&auto=format&fit=crop\",\n    views: 7676,\n  },\n];\n\nexport type IImage = {\n  alt: string;\n  src: string;\n  views: number;\n  downloads: number;\n};\n",
      "type": "registry:page",
      "target": "app/dashboard/page.tsx"
    },
    {
      "path": "registry/blocks/dialog-02/components/info-menu.tsx",
      "content": "import { InfoIcon } from \"lucide-react\";\nimport { Button } from \"@/registry/ui/button\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@/registry/ui/popover\";\nimport { Tabs, TabsListContent, TabsPanel, TabsTab } from \"@/registry/ui/tabs\";\nimport { StatsChart } from \"./stats-chart\";\n\nexport const InfoMenu = () => {\n  return (\n    <Popover>\n      <PopoverTrigger render={<Button variant=\"outline\" />}>\n        <InfoIcon /> Info\n      </PopoverTrigger>\n      <PopoverContent align=\"end\" className=\"bg-secondary\" side=\"top\">\n        <Tabs className=\"w-72\" defaultValue=\"views\">\n          <TabsPanel value=\"downloads\">\n            <StatsChart data=\"downloads\" />\n          </TabsPanel>\n          <TabsPanel value=\"views\">\n            <StatsChart data=\"views\" />\n          </TabsPanel>\n          <TabsListContent>\n            <TabsTab value=\"downloads\">Downloads</TabsTab>\n            <TabsTab value=\"views\">Views</TabsTab>\n          </TabsListContent>\n        </Tabs>\n      </PopoverContent>\n    </Popover>\n  );\n};\n",
      "type": "registry:component"
    },
    {
      "path": "registry/blocks/dialog-02/components/stats-chart.tsx",
      "content": "\"use client\";\n\nimport { Bar, BarChart, CartesianGrid, XAxis } from \"recharts\";\nimport {\n  type ChartConfig,\n  ChartContainer,\n  ChartTooltip,\n  ChartTooltipContent,\n} from \"@/registry/ui/chart\";\n\nconst chartConfig: ChartConfig = {\n  downloads: {\n    color: \"var(--color-green-100)\",\n    label: \"Downloads\",\n  },\n  views: {\n    color: \"var(--color-green-100)\",\n    label: \"Views\",\n  },\n};\n\nexport const StatsChart = ({\n  data = \"views\",\n}: {\n  data?: \"views\" | \"downloads\";\n}) => {\n  return (\n    <ChartContainer\n      className=\"aspect-auto h-[120px] w-full\"\n      config={chartConfig}\n    >\n      <BarChart\n        accessibilityLayer\n        data={chartData}\n        margin={{\n          left: 12,\n          right: 12,\n        }}\n      >\n        <CartesianGrid vertical={false} />\n        <XAxis dataKey=\"date\" hide />\n        <ChartTooltip\n          content={\n            <ChartTooltipContent\n              className=\"bg-foreground text-background border-transparent shadow-none w-fit\"\n              hideIndicator\n              labelFormatter={(value) => {\n                return new Date(value as string).toLocaleDateString(\"en-US\", {\n                  day: \"numeric\",\n                  month: \"short\",\n                  year: \"numeric\",\n                });\n              }}\n            />\n          }\n          cursor={false}\n        />\n        <Bar\n          className=\"hover:fill-green-600 transition-colors duration-50\"\n          dataKey={data}\n          fill={`var(--color-${data})`}\n          radius={4}\n        />\n      </BarChart>\n    </ChartContainer>\n  );\n};\n\nconst chartData = [\n  { date: \"2025-12-24\", downloads: 350, views: 6452 },\n  { date: \"2025-12-25\", downloads: 120, views: 1945 },\n  { date: \"2025-12-26\", downloads: 420, views: 6576 },\n  { date: \"2025-12-27\", downloads: 180, views: 2371 },\n  { date: \"2025-12-28\", downloads: 150, views: 2335 },\n  { date: \"2025-12-29\", downloads: 380, views: 6237 },\n  { date: \"2025-12-30\", downloads: 520, views: 7528 },\n  { date: \"2025-12-31\", downloads: 110, views: 1944 },\n  { date: \"2026-01-01\", downloads: 290, views: 4837 },\n  { date: \"2026-01-02\", downloads: 160, views: 2358 },\n  { date: \"2026-01-03\", downloads: 140, views: 2350 },\n  { date: \"2026-01-04\", downloads: 410, views: 6734 },\n  { date: \"2026-01-05\", downloads: 90, views: 1232 },\n  { date: \"2026-01-06\", downloads: 230, views: 3677 },\n  { date: \"2026-01-07\", downloads: 85, views: 1269 },\n  { date: \"2026-01-08\", downloads: 115, views: 1658 },\n  {\n    date: \"2026-01-09\",\n    downloads: 145,\n    views: 2001,\n  },\n  {\n    date: \"2026-01-10\",\n    downloads: 395,\n    views: 6352,\n  },\n  {\n    date: \"2026-01-11\",\n    downloads: 190,\n    views: 2954,\n  },\n  {\n    date: \"2026-01-12\",\n    downloads: 310,\n    views: 4590,\n  },\n  {\n    date: \"2026-01-13\",\n    downloads: 110,\n    views: 1843,\n  },\n];\n",
      "type": "registry:component"
    },
    {
      "path": "registry/blocks/dialog-02/components/login-form.tsx",
      "content": "\"use client\";\n\nimport { Chrome, Eye, EyeOff, Github } from \"lucide-react\";\nimport * as React from \"react\";\nimport { Button } from \"@/registry/ui/button\";\nimport {\n  Field,\n  FieldControl,\n  FieldError,\n  FieldLabel,\n} from \"@/registry/ui/field\";\nimport { Form } from \"@/registry/ui/form\";\nimport { Input } from \"@/registry/ui/input\";\nimport { Tabs, TabsListContent, TabsPanel, TabsTab } from \"@/registry/ui/tabs\";\n\nexport function LoginForm({ onSuccess }: { onSuccess: () => void }) {\n  const [isLoading, setIsLoading] = React.useState(false);\n  const [showPassword, setShowPassword] = React.useState(false);\n\n  const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {\n    event.preventDefault();\n    setIsLoading(true);\n    setTimeout(() => {\n      setIsLoading(false);\n      onSuccess();\n    }, 2000);\n  };\n\n  return (\n    <div className=\"p-4 sm:p-8\">\n      <div className=\"text-center space-y-2\">\n        <h1 className=\"text-3xl font-bold tracking-tight text-foreground\">\n          Welcome back\n        </h1>\n        <p className=\"text-sm text-muted-foreground\">\n          Enter your credentials to access your account\n        </p>\n      </div>\n      <Tabs className=\"w-full mt-6\" defaultValue=\"email\">\n        <TabsListContent>\n          <TabsTab value=\"email\">Email</TabsTab>\n          <TabsTab value=\"phone\">Phone</TabsTab>\n        </TabsListContent>\n\n        <TabsPanel className=\"py-4\" value=\"email\">\n          <Form onSubmit={handleSubmit}>\n            <Field>\n              <FieldLabel>Email</FieldLabel>\n              <FieldControl\n                name=\"email\"\n                placeholder=\"name@example.com\"\n                required\n                type=\"email\"\n              />\n              <FieldError />\n            </Field>\n            <Field>\n              <div className=\"flex items-center justify-between\">\n                <FieldLabel>Password</FieldLabel>\n                <Button\n                  className=\"p-0 h-auto font-normal text-xs\"\n                  variant=\"link\"\n                >\n                  Forgot password?\n                </Button>\n              </div>\n              <div className=\"relative\">\n                <Input\n                  className=\"pr-10\"\n                  name=\"password\"\n                  placeholder=\"Enter your password\"\n                  required\n                  type={showPassword ? \"text\" : \"password\"}\n                />\n                <Button\n                  className=\"absolute right-0 top-0 h-full px-3 py-2 hover:bg-transparent\"\n                  onClick={() => setShowPassword(!showPassword)}\n                  size=\"icon\"\n                  type=\"button\"\n                  variant=\"ghost\"\n                >\n                  {showPassword ? (\n                    <EyeOff className=\"size-4 text-muted-foreground\" />\n                  ) : (\n                    <Eye className=\"size-4 text-muted-foreground\" />\n                  )}\n                  <span className=\"sr-only\">\n                    {showPassword ? \"Hide password\" : \"Show password\"}\n                  </span>\n                </Button>\n              </div>\n              <FieldError />\n            </Field>\n            <Button className=\"w-full\" disabled={isLoading} type=\"submit\">\n              {isLoading ? \"Signing in...\" : \"Sign In\"}\n            </Button>\n          </Form>\n        </TabsPanel>\n\n        <TabsPanel className=\"py-4\" value=\"phone\">\n          <Form onSubmit={handleSubmit}>\n            <Field>\n              <FieldLabel>Phone Number</FieldLabel>\n              <FieldControl\n                name=\"phone\"\n                placeholder=\"+1 (555) 000-0000\"\n                required\n                type=\"tel\"\n              />\n              <FieldError />\n            </Field>\n            <Field>\n              <div className=\"flex items-center justify-between\">\n                <FieldLabel>Verification Code</FieldLabel>\n                <Button\n                  className=\"p-0 h-auto text-xs\"\n                  type=\"button\"\n                  variant=\"link\"\n                >\n                  Send code\n                </Button>\n              </div>\n              <FieldControl\n                maxLength={6}\n                name=\"code\"\n                placeholder=\"Enter 6-digit code\"\n                required\n                type=\"text\"\n              />\n              <FieldError />\n            </Field>\n            <Button className=\"w-full\" disabled={isLoading} type=\"submit\">\n              {isLoading ? \"Signing in...\" : \"Sign In\"}\n            </Button>\n          </Form>\n        </TabsPanel>\n      </Tabs>\n      <div className=\"space-y-4\">\n        <div className=\"relative\">\n          <div className=\"relative flex justify-center text-xs uppercase\">\n            <span className=\"px-2 text-muted-foreground\">Or continue with</span>\n          </div>\n        </div>\n        <div className=\"grid grid-cols-2 gap-4\">\n          <Button className=\"w-full\" type=\"button\" variant=\"outline\">\n            <Github className=\"mr-2 size-4\" />\n            GitHub\n          </Button>\n          <Button className=\"w-full\" type=\"button\" variant=\"outline\">\n            <Chrome className=\"mr-2 size-4\" />\n            Google\n          </Button>\n        </div>\n      </div>\n    </div>\n  );\n}\n",
      "type": "registry:component"
    },
    {
      "path": "registry/blocks/dialog-02/components/signup-form.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Button } from \"@/registry/ui/button\";\nimport {\n  Field,\n  FieldControl,\n  FieldError,\n  FieldLabel,\n} from \"@/registry/ui/field\";\nimport { Form } from \"@/registry/ui/form\";\nimport { Input } from \"@/registry/ui/input\";\n\nexport type IImage = {\n  alt: string;\n  src: string;\n  views: number;\n  downloads: number;\n};\n\ninterface SignUpFormProps {\n  image: IImage;\n  onSuccess?: () => void;\n}\n\nexport function SignUpForm({ image, onSuccess }: SignUpFormProps) {\n  const [isLoading, setIsLoading] = React.useState(false);\n\n  const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {\n    event.preventDefault();\n    setIsLoading(true);\n\n    setTimeout(() => {\n      setIsLoading(false);\n      if (onSuccess) onSuccess();\n    }, 2000);\n  };\n\n  return (\n    <div className=\"flex max-h-full\">\n      <div className=\"hidden w-1/3 lg:block relative\">\n        <img\n          alt={image.alt}\n          className=\"h-full w-full object-cover rounded-l-md\"\n          src={image.src}\n        />\n        <div className=\"absolute bottom-4 left-4 text-white/80 text-xs bg-black/20 p-2 rounded backdrop-blur-sm\">\n          Photo viewed {image.views.toLocaleString()} times\n        </div>\n      </div>\n\n      <div className=\"flex w-full flex-col justify-center p-4 sm:p-8 lg:w-2/3\">\n        <div className=\"mx-auto w-full max-w-md space-y-8\">\n          <div className=\"text-center\">\n            <h1 className=\"text-4xl font-bold tracking-tight text-foreground\">\n              Join Us\n            </h1>\n            <p className=\"mt-2 text-muted-foreground\">\n              Already have an account? <Button variant={\"link\"}>Login</Button>\n            </p>\n          </div>\n\n          <Form className=\"space-y-6\" onSubmit={handleSubmit}>\n            <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n              <Field>\n                <FieldLabel>First name</FieldLabel>\n                <FieldControl name=\"firstName\" placeholder=\"\" required />\n                <FieldError />\n              </Field>\n              <Field>\n                <FieldLabel>Last name</FieldLabel>\n                <FieldControl name=\"lastName\" placeholder=\"\" required />\n                <FieldError />\n              </Field>\n            </div>\n\n            <Field>\n              <FieldLabel>Email</FieldLabel>\n              <FieldControl name=\"email\" required type=\"email\" />\n              <FieldError />\n            </Field>\n\n            <Field>\n              <FieldLabel className=\"flex gap-1\">\n                Username\n                <span className=\"font-normal text-muted-foreground\">\n                  (only letters, numbers and underscores)\n                </span>\n              </FieldLabel>\n              <FieldControl name=\"username\" pattern=\"[a-zA-Z0-9_]+\" required />\n              <FieldError />\n            </Field>\n\n            <Field>\n              <FieldLabel className=\"flex gap-1\">\n                Password\n                <span className=\"font-normal text-muted-foreground\">\n                  (min. 8 char)\n                </span>\n              </FieldLabel>\n              <Input minLength={8} name=\"password\" required type=\"password\" />\n              <FieldError />\n            </Field>\n\n            <Button disabled={isLoading} type=\"submit\">\n              {isLoading ? \"Joining...\" : \"Join\"}\n            </Button>\n          </Form>\n\n          <p className=\"text-center text-sm text-muted-foreground\">\n            By joining, you agree to the{\" \"}\n            <Button className=\"px-0\" variant={\"link\"}>\n              Terms\n            </Button>{\" \"}\n            and{\" \"}\n            <Button className=\"px-0\" variant={\"link\"}>\n              Privacy Policy\n            </Button>\n            .\n          </p>\n        </div>\n      </div>\n    </div>\n  );\n}\n",
      "type": "registry:component"
    },
    {
      "path": "registry/blocks/dialog-02/components/share-menu.tsx",
      "content": "\"use client\";\n\nimport {\n  FacebookIcon,\n  InstagramIcon,\n  LinkIcon,\n  ShareIcon,\n  TwitterIcon,\n} from \"lucide-react\";\nimport { Button } from \"@/registry/ui/button\";\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuGroup,\n  DropdownMenuGroupLabel,\n  DropdownMenuItem,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from \"@/registry/ui/dropdown-menu\";\nimport { toast } from \"@/registry/ui/toast\";\n\nexport const ShareMenu = () => {\n  const handleCopy = () => {\n    navigator.clipboard.writeText(\"https://lumiui.dev\");\n\n    toast.success({\n      title: \"Copied\",\n    });\n  };\n  return (\n    <DropdownMenu>\n      <DropdownMenuTrigger\n        className=\"w-20\"\n        render={\n          <Button variant=\"outline\">\n            <ShareIcon className=\"size-4\" /> Share\n          </Button>\n        }\n      />\n      <DropdownMenuContent align=\"end\" matchAnchorWidth={false} side=\"top\">\n        <DropdownMenuGroup>\n          <DropdownMenuGroupLabel>Socials</DropdownMenuGroupLabel>\n          <DropdownMenuItem>\n            <FacebookIcon className=\"size-4\" /> <span>Facebook</span>\n          </DropdownMenuItem>\n          <DropdownMenuItem>\n            <TwitterIcon className=\"size-4\" /> <span>Twitter</span>\n          </DropdownMenuItem>\n          <DropdownMenuItem>\n            <InstagramIcon className=\"size-4\" /> <span>Instagram</span>\n          </DropdownMenuItem>\n        </DropdownMenuGroup>\n        <DropdownMenuSeparator />\n        <DropdownMenuItem onClick={handleCopy}>\n          <LinkIcon className=\"size-4\" /> Copy link\n        </DropdownMenuItem>\n      </DropdownMenuContent>\n    </DropdownMenu>\n  );\n};\n",
      "type": "registry:component"
    },
    {
      "path": "registry/blocks/dialog-02/components/tooltip-group.tsx",
      "content": "import type { DialogRootChangeEventDetails } from \"@base-ui/react\";\nimport { BookmarkIcon, PlusIcon } from \"lucide-react\";\nimport React from \"react\";\nimport { cn } from \"@/registry/lib/utils\";\nimport { Button } from \"@/registry/ui/button\";\nimport {\n  createDialogHandle,\n  Dialog,\n  DialogBackdrop,\n  DialogPopup,\n  DialogPortal,\n  DialogTrigger,\n} from \"@/registry/ui/dialog\";\nimport { toast } from \"@/registry/ui/toast\";\nimport {\n  createTooltipHandle,\n  Tooltip,\n  TooltipContent,\n  TooltipProvider,\n  TooltipTrigger,\n} from \"@/registry/ui/tooltip\";\nimport type { IImage } from \"../page\";\nimport { LoginForm } from \"./login-form\";\nimport { SignUpForm } from \"./signup-form\";\n\ntype UserAction = \"bookmark\" | \"add-collection\";\ntype FormType = \"signin\" | \"signup\";\n\ntype DialogPayload = {\n  formType: FormType;\n  action: UserAction;\n  title: string;\n};\n\nconst dialogHandle = createDialogHandle<DialogPayload>();\nconst tooltipHandle = createTooltipHandle<{ label: string }>();\n\nexport const TooltipGroup = ({ currentImage }: { currentImage: IImage }) => {\n  const [isOpen, setIsOpen] = React.useState(false);\n  const [triggerId, setTriggerId] = React.useState<string | null>(null);\n\n  const handleOpenChange = (\n    open: boolean,\n    eventDetails: DialogRootChangeEventDetails,\n  ) => {\n    setIsOpen(open);\n    if (eventDetails.trigger) {\n      setTriggerId(eventDetails.trigger.id);\n    }\n  };\n\n  const handleSuccess = (action: UserAction) => {\n    setIsOpen(false);\n\n    const messages: Record<UserAction, string> = {\n      \"add-collection\": `Added ${currentImage.alt} to collection`,\n      bookmark: `Bookmarked ${currentImage.alt}`,\n    };\n\n    toast.success({\n      description: messages[action] || \"Action completed successfully\",\n      title: \"Success\",\n    });\n  };\n\n  return (\n    <>\n      <TooltipProvider>\n        <div className=\"flex gap-2\">\n          <TooltipTrigger\n            handle={tooltipHandle}\n            id=\"trigger-bookmark\"\n            payload={{ label: \"Bookmark this page\" }}\n            render={\n              <DialogTrigger\n                handle={dialogHandle}\n                payload={{\n                  action: \"bookmark\",\n                  formType: \"signin\",\n                  title: \"Welcome Back\",\n                }}\n                render={<Button size={\"icon-sm\"} variant={\"outline\"} />}\n              >\n                <BookmarkIcon aria-label=\"Bookmark\" className=\"size-5\" />\n              </DialogTrigger>\n            }\n          />\n\n          <TooltipTrigger\n            handle={tooltipHandle}\n            id=\"trigger-collection\"\n            payload={{ label: \"Add to collection\" }}\n            render={\n              <DialogTrigger\n                handle={dialogHandle}\n                payload={{\n                  action: \"add-collection\",\n                  formType: \"signup\",\n                  title: \"Create Account\",\n                }}\n                render={<Button size={\"icon-sm\"} variant={\"outline\"} />}\n              >\n                <PlusIcon aria-label=\"Add to collection\" className=\"size-5\" />\n              </DialogTrigger>\n            }\n          />\n\n          <Tooltip handle={tooltipHandle}>\n            {({ payload }) => (\n              <TooltipContent showArrow={false} side=\"bottom\" sideOffset={5}>\n                <p>{payload?.label}</p>\n              </TooltipContent>\n            )}\n          </Tooltip>\n        </div>\n      </TooltipProvider>\n\n      <Dialog\n        handle={dialogHandle}\n        onOpenChange={handleOpenChange}\n        open={isOpen}\n        triggerId={triggerId}\n      >\n        {({ payload }) => {\n          return (\n            <DialogPortal>\n              <DialogBackdrop\n                className=\"backdrop-blur-none bg-black/40\"\n                forceRender\n              />\n              <DialogPopup\n                className={cn(\n                  \"fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 bg-background rounded-md shadow-md dark:shadow-xs w-full\",\n                  payload?.formType === \"signin\" && \"max-w-md\",\n                  payload?.formType === \"signup\" && \"max-w-2xl\",\n                )}\n              >\n                {payload?.formType === \"signin\" && (\n                  <LoginForm onSuccess={() => handleSuccess(payload.action)} />\n                )}\n                {payload?.formType === \"signup\" && (\n                  <SignUpForm\n                    image={currentImage}\n                    onSuccess={() => handleSuccess(payload.action)}\n                  />\n                )}\n              </DialogPopup>\n            </DialogPortal>\n          );\n        }}\n      </Dialog>\n    </>\n  );\n};\n",
      "type": "registry:component"
    },
    {
      "path": "registry/blocks/dialog-02/components/profile-card.tsx",
      "content": "import { Avatar, AvatarFallback, AvatarImage } from \"@/registry/ui/avatar\";\nimport { Button } from \"@/registry/ui/button\";\nimport {\n  PreviewCard,\n  PreviewCardContent,\n  PreviewCardTrigger,\n} from \"@/registry/ui/preview-card\";\n\nexport function ProfileCard() {\n  return (\n    <PreviewCard>\n      <PreviewCardTrigger\n        delay={300}\n        render={\n          <Button className=\"cursor-pointer\" variant=\"unstyled\">\n            <Avatar>\n              <AvatarImage src=\"https://github.com/mui.png\" />\n              <AvatarFallback>VC</AvatarFallback>\n            </Avatar>\n          </Button>\n        }\n      />\n      <PreviewCardContent align=\"start\" className=\"w-80\">\n        <div className=\"flex justify-between gap-4\">\n          <Avatar>\n            <AvatarImage src=\"https://github.com/mui.png\" />\n            <AvatarFallback>VC</AvatarFallback>\n          </Avatar>\n          <div className=\"space-y-1\">\n            <h4 className=\"text-sm font-semibold\">@base-ui</h4>\n            <p className=\"text-sm\">\n              Unstyled UI components for building accessible web apps and design\n              systems. From the creators of Radix, Floating UI, and Material UI.\n            </p>\n            <div className=\"text-muted-foreground text-xs\">\n              Joined December 2021\n            </div>\n          </div>\n        </div>\n      </PreviewCardContent>\n    </PreviewCard>\n  );\n}\n",
      "type": "registry:component"
    }
  ],
  "categories": [
    "dialog"
  ],
  "type": "registry:block"
}