{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "dialog",
  "type": "registry:component",
  "title": "Dialog",
  "description": "A task done in a panel over the page, with its buttons in the band beneath it.",
  "dependencies": [
    "@base-ui/react",
    "tailwind-variants"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "components/panelui/dialog.tsx",
      "type": "registry:component",
      "target": "@components/panelui/dialog.tsx",
      "content": "'use client';\n\n/**\n * Dialog — a task taken out of the page and done in a box over it: renaming\n * something, inviting people, filling in a short form.\n *\n * ```tsx\n * <Dialog>\n *   <Dialog.Trigger render={<Button />}>Rename</Dialog.Trigger>\n *   <Dialog.Content>\n *     <Dialog.Header title=\"Rename board\" description=\"Everyone on the board sees the new name.\" />\n *     <Dialog.Body>\n *       <Input defaultValue=\"Spring launch\" aria-label=\"Name\" />\n *     </Dialog.Body>\n *     <Dialog.Footer>\n *       <Dialog.Close render={<Button variant=\"secondary\" />}>Cancel</Dialog.Close>\n *       <Button>Save</Button>\n *     </Dialog.Footer>\n *   </Dialog.Content>\n * </Dialog>\n * ```\n *\n * ## A panel in a band\n *\n * The task sits in a panel, and `Dialog.Footer` moves out of it into the\n * darker band underneath, where the buttons are equal pills: the same shape\n * as Feedback and Alert Dialog, so the three read as one family.\n * `variant=\"plain\"` is a single surface with the footer ruled off at its\n * foot, for a dense form where the band would be one more edge.\n *\n * ## The middle scrolls\n *\n * The dialog is never taller than the screen. The header and footer stay\n * put and `Dialog.Body` scrolls between them, with a thin drawn thumb that\n * shows while it moves.\n *\n * ## Focus goes to the task\n *\n * The close button is drawn in the corner but comes last in the order, so\n * opening the dialog puts focus on its first field rather than on the way\n * out. A press outside, Escape or the close button dismiss it.\n *\n * ## Lists to choose from\n *\n * `Dialog.List` is a list of one-line choices for the body, such as a time\n * zone or a project to move something to: grouped under headings that stay\n * pinned while it scrolls, moved through with the arrow keys, with a check\n * on the chosen one. It opens scrolled to the chosen one.\n *\n * ## On a phone it sits low\n *\n * Under 640px wide it rests at the bottom of the screen, a few pixels clear\n * of the edges, where a thumb reaches its buttons.\n */\nimport { Dialog as Primitive } from '@base-ui/react/dialog';\nimport { ScrollArea } from '@base-ui/react/scroll-area';\nimport {\n  createContext,\n  useContext,\n  useEffect,\n  useId,\n  useMemo,\n  useRef,\n  useState,\n  type ComponentProps,\n  type KeyboardEvent,\n  type ReactElement,\n  type ReactNode,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { tv } from 'tailwind-variants';\nimport { mergeProps } from '@base-ui/react/merge-props';\nimport { useRender } from '@base-ui/react/use-render';\nimport type * as ReactTypes from 'react';\nimport type { ElementType as RenderElementType } from 'react';\n\n/** Draws a part as another element, or composes it with a component: `render={<a href=\"/\" />}`. */\ntype RenderProp<Tag extends RenderElementType> = { render?: useRender.ComponentProps<Tag>['render'] };\n\nconst dialogVariants = tv({\n  slots: {\n    backdrop:\n      'fixed inset-0 z-50 bg-black/40 transition-opacity duration-200 data-ending-style:opacity-0 data-starting-style:opacity-0 motion-reduce:transition-none',\n    viewport: 'fixed inset-0 z-50 grid place-items-center overflow-hidden p-4 max-sm:items-end max-sm:p-2',\n    shell: [\n      'relative flex max-h-[calc(100dvh-2rem)] w-full min-h-0 flex-col text-popover-foreground outline-none max-sm:max-h-[calc(100dvh-1rem)]',\n      // A dialog opened from this one steps it back, smaller and veiled, so\n      // the depth can be counted.\n      'origin-top scale-[calc(1-0.05*var(--nested-dialogs,0))] translate-y-[calc(-0.75rem*var(--nested-dialogs,0))]',\n      \"after:pointer-events-none after:absolute after:inset-0 after:rounded-[inherit] after:bg-black/0 after:transition-colors after:duration-200 after:content-[''] data-nested-dialog-open:after:bg-black/10 dark:data-nested-dialog-open:after:bg-black/30\",\n    ],\n    popup:\n      'transition-[opacity,scale,translate] duration-200 ease-[cubic-bezier(0.2,0,0,1)] data-ending-style:scale-95 data-ending-style:opacity-0 data-starting-style:translate-y-2 data-starting-style:scale-95 data-starting-style:opacity-0 motion-reduce:transition-none',\n    panel: 'relative flex min-h-0 flex-1 flex-col',\n    header: 'flex shrink-0 flex-col gap-1',\n    title: 'text-[19px] font-semibold leading-6 tracking-[-0.01em]',\n    description: 'text-[15px] leading-[22px] text-muted-foreground',\n    body: [\n      'relative flex min-h-0 flex-1 flex-col',\n      // A hairline at an edge the content has been scrolled past, so what is\n      // cut off reads as going under the header, not as stopping there.\n      \"before:pointer-events-none before:absolute before:inset-x-0 before:top-0 before:z-20 before:h-px before:bg-border before:opacity-0 before:transition-opacity before:content-[''] data-overflow-y-start:before:opacity-100\",\n    ],\n    bodyViewport: 'min-h-0 flex-1 overscroll-contain rounded-[inherit] outline-none',\n    bodyContent: 'flex flex-col gap-4',\n    scrollbar:\n      'my-2 me-1 flex w-1.5 opacity-0 transition-opacity delay-300 data-hovering:opacity-100 data-hovering:delay-0 data-scrolling:opacity-100 data-scrolling:delay-0',\n    thumb: 'relative flex-1 rounded-full bg-foreground/20',\n    footer: [\n      'flex shrink-0 items-center',\n      // The footer sits on a tinted surface, and the secondary fill is a tint\n      // too, so the button all but disappears into it. There it takes the\n      // panel's own surface instead, which keeps it lighter than the band.\n      '*:data-[variant=secondary]:bg-popover *:data-[variant=secondary]:shadow-xs',\n      '*:data-[variant=secondary]:hover:not-disabled:bg-[color-mix(in_oklab,var(--popover),var(--foreground)_5%)]',\n    ],\n    close: [\n      'absolute end-4 top-4 z-10 inline-flex size-8 cursor-pointer items-center justify-center rounded-full',\n      'bg-muted text-muted-foreground outline-none transition-[background-color,color,scale] duration-150',\n      'after:absolute after:-inset-1.5 hover:bg-foreground/10 hover:text-foreground active:scale-95',\n      'focus-visible:ring-2 focus-visible:ring-ring motion-reduce:transition-none [&_svg]:size-4',\n    ],\n    // Pulled out by the rows' own padding, so a row's text lines up with the\n    // header's, and no further: the scrollbar runs in the 12px left at each\n    // side, and a heading or a row reaching into it shows through the thumb.\n    list: '-mx-2 flex flex-col outline-none',\n    listGroup: 'flex flex-col [&+&]:mt-2',\n    listGroupLabel: 'sticky top-0 z-10 bg-popover px-2 pb-1.5 pt-2 text-xs font-medium text-muted-foreground',\n    listItem: [\n      'flex h-10 shrink-0 cursor-pointer select-none items-center gap-3 rounded-xl px-2 text-sm outline-none',\n      // Room for the pinned heading above it when the arrow keys scroll it into view.\n      'scroll-mb-2 scroll-mt-10 transition-colors duration-100 hover:bg-foreground/[0.05]',\n      'focus-visible:bg-foreground/[0.06] focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring/60',\n      'data-selected:bg-[color-mix(in_oklab,var(--primary)_9%,transparent)] data-selected:font-medium',\n      'aria-disabled:cursor-default aria-disabled:opacity-50 aria-disabled:hover:bg-transparent motion-reduce:transition-none',\n    ],\n    listItemLabel: 'min-w-0 flex-1 truncate',\n    listItemMeta: 'shrink-0 text-xs font-normal tabular-nums text-muted-foreground',\n    listItemCheck: 'flex size-4 shrink-0 items-center justify-center text-primary [&_svg]:size-4',\n  },\n  variants: {\n    variant: {\n      /*\n       * The band is the popover surface with black mixed in, so it is the\n       * darker of the two in either theme. 38 and 30 are one corner: the\n       * panel's radius is the band's less the 8px between them.\n       */\n      inset: {\n        shell:\n          'rounded-[38px] bg-[color-mix(in_oklab,var(--popover),black_5%)] p-2 shadow-xl ring-1 ring-foreground/[0.06] dark:bg-[color-mix(in_oklab,var(--popover),black_14%)]',\n        panel: 'overflow-hidden rounded-[30px] bg-popover shadow-xs',\n        header: 'px-5 pb-3 pt-5',\n        body: 'first:pt-5',\n        bodyContent: 'px-5 pb-5',\n        // Held in from the band's edge further than the panel is, with the\n        // buttons as equal pills: a row of decisions, not a third edge.\n        footer: 'gap-3 px-[10px] pb-0.5 pt-2.5 *:h-11 *:min-w-0 *:flex-1 *:rounded-full',\n      },\n      plain: {\n        shell: 'overflow-hidden rounded-[28px] border bg-popover shadow-xl',\n        header: 'px-6 pb-4 pt-6',\n        body: 'first:pt-6',\n        bodyContent: 'px-6 pb-6',\n        footer: 'justify-end gap-2 border-t bg-muted/50 px-6 py-3.5',\n      },\n    },\n    size: {\n      sm: { shell: 'max-w-sm' },\n      md: { shell: 'max-w-md' },\n      lg: { shell: 'max-w-xl' },\n    },\n    blur: {\n      true: { backdrop: 'bg-black/20 backdrop-blur-md' },\n    },\n  },\n  defaultVariants: { variant: 'inset', size: 'md' },\n});\n\ninterface DialogContextValue {\n  /** Set by `Dialog.Content`. */\n  inline: boolean;\n  showClose: boolean;\n  variant: 'inset' | 'plain';\n  /** Where an inset footer portals to. `undefined` outside `Dialog.Content`. */\n  band?: HTMLElement | null;\n}\n\nconst DialogContext = createContext<DialogContextValue>({ inline: false, showClose: true, variant: 'inset' });\n\nexport interface DialogProps {\n  children?: ReactNode;\n  /** Whether it is open, when the caller holds that. */\n  open?: boolean;\n  /** Whether it starts open, when the caller does not hold it. */\n  defaultOpen?: boolean;\n  /** Called when it opens or closes. */\n  onOpenChange?: (open: boolean) => void;\n  /**\n   * Called once it has finished opening or closing, after its transition has\n   * ended. `false` means the exit is over, so a dialog mounted from state can\n   * be unmounted.\n   */\n  onOpenChangeComplete?: (open: boolean) => void;\n  /**\n   * Whether a press outside it closes it. Turn it off while a form in it has\n   * changes that would be lost; Escape and the close button still work.\n   * Default `true`.\n   */\n  dismissible?: boolean;\n}\n\nfunction DialogRoot({\n  children,\n  open,\n  defaultOpen,\n  onOpenChange,\n  onOpenChangeComplete,\n  dismissible = true,\n}: DialogProps) {\n  return (\n    <Primitive.Root\n      open={open}\n      defaultOpen={defaultOpen}\n      onOpenChange={onOpenChange ? (next) => onOpenChange(next) : undefined}\n      onOpenChangeComplete={onOpenChangeComplete}\n      disablePointerDismissal={!dismissible}\n    >\n      {children}\n    </Primitive.Root>\n  );\n}\nDialogRoot.displayName = 'Dialog';\n\nexport interface DialogTriggerProps extends Omit<ComponentProps<'button'>, 'children'> {\n  children?: ReactNode;\n  /**\n   * Your own element to be the trigger, such as a styled button. It is given\n   * the click handler and the attributes that tie it to the dialog.\n   */\n  render?: ReactElement;\n}\n\n/** What opens the dialog. A plain button unless `render` supplies one. */\nfunction DialogTrigger({ render, children, ...props }: DialogTriggerProps) {\n  return (\n    <Primitive.Trigger render={render} {...props}>\n      {children}\n    </Primitive.Trigger>\n  );\n}\nDialogTrigger.displayName = 'Dialog.Trigger';\n\nexport interface DialogContentProps extends Omit<ComponentProps<'div'>, 'children'> {\n  children?: ReactNode;\n  /**\n   * `inset` sets the task in a panel inside a darker band that holds the\n   * footer. `plain` is one surface with the footer ruled off. Default `inset`.\n   */\n  variant?: 'inset' | 'plain';\n  /** How wide it may grow: `sm` 24rem, `md` 28rem, `lg` 36rem. Default `md`. */\n  size?: 'sm' | 'md' | 'lg';\n  /** Show the round close button in the top trailing corner. Default `true`. */\n  showClose?: boolean;\n  /** Frost the page behind it instead of only dimming it. */\n  blur?: boolean;\n  /**\n   * Draw it in the page instead of over it: no backdrop, no trigger, always\n   * there. For previews; `open` is ignored.\n   */\n  inline?: boolean;\n}\n\n/** The dialog itself, with the dimmed page behind it. */\nfunction DialogContent({\n  variant = 'inset',\n  size = 'md',\n  showClose = true,\n  blur = false,\n  inline = false,\n  className,\n  children,\n  ...props\n}: DialogContentProps) {\n  const slots = dialogVariants({ variant, size, blur });\n  const [band, setBand] = useState<HTMLElement | null>(null);\n  const context = useMemo(() => ({ inline, showClose, variant, band }), [inline, showClose, variant, band]);\n\n  // In the inset look the footer leaves the panel for the band under it, from any depth.\n  const inside = (\n    <DialogContext.Provider value={context}>\n      <div data-slot=\"dialog-panel\" className={slots.panel()}>\n        {children}\n        {/* Last in the order, so focus starts on the task, not the way out. */}\n        {showClose ? <DialogClose aria-label=\"Close\" className={slots.close()} icon /> : null}\n      </div>\n      {variant === 'inset' ? <div data-slot=\"dialog-band\" className=\"contents\" ref={setBand} /> : null}\n    </DialogContext.Provider>\n  );\n\n  if (inline) {\n    return (\n      <div data-slot=\"dialog-content\" data-variant={variant} className={slots.shell({ className })} {...props}>\n        {inside}\n      </div>\n    );\n  }\n\n  return (\n    <Primitive.Portal>\n      <Primitive.Backdrop className={slots.backdrop()} />\n      <Primitive.Viewport className={slots.viewport()}>\n        <Primitive.Popup\n          data-slot=\"dialog-content\"\n          data-variant={variant}\n          className={slots.shell({ className: [slots.popup(), className] })}\n          {...props}\n        >\n          {inside}\n        </Primitive.Popup>\n      </Primitive.Viewport>\n    </Primitive.Portal>\n  );\n}\nDialogContent.displayName = 'Dialog.Content';\n\nexport interface DialogHeaderProps extends Omit<ComponentProps<'div'>, 'title'> {\n  /** The heading. It is also what the dialog is announced as. */\n  title?: ReactNode;\n  /** A line under the heading. */\n  description?: ReactNode;\n}\n\n/** The heading block. It leaves room for the close button beside the title. */\nfunction DialogHeader({\n  title,\n  description,\n  className,\n  children,\n  render,\n  ...props\n}: DialogHeaderProps & RenderProp<'div'>) {\n  const { showClose, variant } = useContext(DialogContext);\n  const slots = dialogVariants({ variant });\n  return useRender({\n    defaultTagName: 'div',\n    render,\n    props: mergeProps(\n      {\n        'data-slot': 'dialog-header',\n        className: slots.header({ className: [showClose && 'pe-14', className] }),\n        children: (\n          <>\n            {title !== undefined ? <DialogTitle>{title}</DialogTitle> : null}\n            {description !== undefined ? <DialogDescription>{description}</DialogDescription> : null}\n            {children}\n          </>\n        ),\n      },\n      props\n    ),\n  });\n}\nDialogHeader.displayName = 'Dialog.Header';\n\nexport interface DialogTitleProps extends ComponentProps<'h2'> {}\n\n/** The dialog's name, announced when it opens. */\nfunction DialogTitle({ className, ...props }: DialogTitleProps) {\n  const { inline } = useContext(DialogContext);\n  const slots = dialogVariants();\n  if (inline) return <h2 data-slot=\"dialog-title\" className={slots.title({ className })} {...props} />;\n  return <Primitive.Title data-slot=\"dialog-title\" className={slots.title({ className })} {...props} />;\n}\nDialogTitle.displayName = 'Dialog.Title';\n\nexport interface DialogDescriptionProps extends ComponentProps<'p'> {}\n\n/** A sentence under the title, read out after it. */\nfunction DialogDescription({ className, ...props }: DialogDescriptionProps) {\n  const { inline } = useContext(DialogContext);\n  const slots = dialogVariants();\n  if (inline) return <p data-slot=\"dialog-description\" className={slots.description({ className })} {...props} />;\n  return (\n    <Primitive.Description data-slot=\"dialog-description\" className={slots.description({ className })} {...props} />\n  );\n}\nDialogDescription.displayName = 'Dialog.Description';\n\nexport interface DialogBodyProps extends ComponentProps<'div'> {}\n\n/**\n * The part that scrolls, between the header and the footer. Its children are\n * laid out in a column with a gap, so a form's fields need no wrapper.\n */\nfunction DialogBody({ className, children, ...props }: DialogBodyProps) {\n  const { variant } = useContext(DialogContext);\n  const slots = dialogVariants({ variant });\n  return (\n    // With no header above it, it keeps the dialog's top padding itself.\n    <ScrollArea.Root data-slot=\"dialog-body\" className={slots.body()}>\n      <ScrollArea.Viewport className={slots.bodyViewport()}>\n        <ScrollArea.Content className={slots.bodyContent({ className })} {...props}>\n          {children}\n        </ScrollArea.Content>\n      </ScrollArea.Viewport>\n      <ScrollArea.Scrollbar orientation=\"vertical\" className={slots.scrollbar()}>\n        <ScrollArea.Thumb className={slots.thumb()} />\n      </ScrollArea.Scrollbar>\n    </ScrollArea.Root>\n  );\n}\nDialogBody.displayName = 'Dialog.Body';\n\nexport interface DialogFooterProps extends ComponentProps<'div'> {}\n\n/**\n * The buttons. In the inset look they sit in the band under the panel as\n * equal pills, wherever they are written inside `Dialog.Content`; in `plain`\n * they sit at the end of a ruled strip. Moving to the band takes them out of\n * any `<form>`, so a submit button needs `form` set to the form's `id`.\n */\nfunction DialogFooter({ className, render, ...props }: DialogFooterProps & RenderProp<'div'>) {\n  const { variant, band } = useContext(DialogContext);\n  const footer = useRender({\n    defaultTagName: 'div',\n    render,\n    props: mergeProps(\n      { 'data-slot': 'dialog-footer', className: dialogVariants({ variant }).footer({ className }) },\n      props\n    ),\n  });\n  if (variant !== 'inset' || band === undefined) return footer;\n  // The band mounts in the same commit, so the footer lands there before the first paint.\n  return band ? createPortal(footer, band) : null;\n}\nDialogFooter.displayName = 'Dialog.Footer';\n\nexport interface DialogCloseProps extends ComponentProps<'button'> {\n  /** Your own element to close the dialog with, such as a Cancel button. */\n  render?: ReactElement;\n  /** Draw the cross glyph. Set for you on the built-in close button. */\n  icon?: boolean;\n}\n\n/** Closes the dialog. */\nfunction DialogClose({ render, icon = false, children, ...props }: DialogCloseProps) {\n  const { inline } = useContext(DialogContext);\n  const content = icon ? (\n    <svg\n      viewBox=\"0 0 24 24\"\n      aria-hidden=\"true\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth={2.4}\n      strokeLinecap=\"round\"\n    >\n      <path d=\"M6 6l12 12M18 6L6 18\" />\n    </svg>\n  ) : (\n    children\n  );\n  if (inline) {\n    return (\n      <button type=\"button\" data-slot=\"dialog-close\" {...props}>\n        {content}\n      </button>\n    );\n  }\n  return (\n    <Primitive.Close data-slot=\"dialog-close\" render={render} {...props}>\n      {content}\n    </Primitive.Close>\n  );\n}\nDialogClose.displayName = 'Dialog.Close';\n\nexport interface DialogListProps extends ComponentProps<'div'> {}\n\n/**\n * A list of one-line choices in the body. The arrow keys, Home and End move\n * between its items, and it opens scrolled to the selected one.\n */\nfunction DialogList({ className, onKeyDown, children, render, ...props }: DialogListProps & RenderProp<'div'>) {\n  const list = useRef<HTMLDivElement>(null);\n  const items = () => [\n    ...(list.current?.querySelectorAll<HTMLElement>('[data-slot=dialog-list-item]:not([aria-disabled=true])') ?? []),\n  ];\n\n  useEffect(() => {\n    const all = items();\n    const selected = all.find((item) => item.dataset.selected !== undefined);\n    // One item takes Tab: the chosen one, or the first when none is.\n    if (!selected && all[0]) all[0].tabIndex = 0;\n    selected?.scrollIntoView({ block: 'center' });\n  }, []);\n\n  const move = (event: KeyboardEvent<HTMLDivElement>) => {\n    onKeyDown?.(event);\n    const all = items();\n    const index = all.indexOf(document.activeElement as HTMLElement);\n    const next =\n      event.key === 'ArrowDown'\n        ? all[index < 0 ? 0 : Math.min(index + 1, all.length - 1)]\n        : event.key === 'ArrowUp'\n          ? all[Math.max(index - 1, 0)]\n          : event.key === 'Home'\n            ? all[0]\n            : event.key === 'End'\n              ? all[all.length - 1]\n              : undefined;\n    if (!next) return;\n    event.preventDefault();\n    next.focus();\n  };\n\n  return useRender({\n    defaultTagName: 'div',\n    render,\n    props: mergeProps(\n      {\n        ref: list,\n        role: 'listbox',\n        'data-slot': 'dialog-list',\n        className: dialogVariants().list({ className }),\n        onKeyDown: move,\n        children: <>{children}</>,\n      },\n      props\n    ),\n  });\n}\nDialogList.displayName = 'Dialog.List';\n\nexport interface DialogListGroupProps extends Omit<ComponentProps<'div'>, 'title'> {\n  /** The heading over the group, which stays pinned while its items scroll under it. */\n  label: ReactNode;\n}\n\n/** A run of items in `Dialog.List` under a heading of their own. */\nfunction DialogListGroup({ label, className, children, render, ...props }: DialogListGroupProps & RenderProp<'div'>) {\n  const slots = dialogVariants();\n  const id = useId();\n  return useRender({\n    defaultTagName: 'div',\n    render,\n    props: mergeProps(\n      {\n        role: 'group',\n        'aria-labelledby': id,\n        'data-slot': 'dialog-list-group',\n        className: slots.listGroup({ className }),\n        children: (\n          <>\n            <div id={id} className={slots.listGroupLabel()}>\n              {label}\n            </div>\n            {children}\n          </>\n        ),\n      },\n      props\n    ),\n  });\n}\nDialogListGroup.displayName = 'Dialog.ListGroup';\n\nexport interface DialogListItemProps extends Omit<ComponentProps<'div'>, 'onSelect'> {\n  /** Whether it is the chosen one: it is tinted and checked. */\n  selected?: boolean;\n  /** Called when it is pressed, or chosen with Enter or Space. */\n  onSelect?: () => void;\n  /** Quieter text at its end, in figures that line up: a time, a count. */\n  meta?: ReactNode;\n  /** Shown, but cannot be chosen. */\n  disabled?: boolean;\n}\n\n/** One choice in `Dialog.List`, on one line. */\nfunction DialogListItem({\n  selected = false,\n  onSelect,\n  meta,\n  disabled = false,\n  className,\n  onClick,\n  onKeyDown,\n  children,\n  render,\n  ...props\n}: DialogListItemProps & RenderProp<'div'>) {\n  const slots = dialogVariants();\n  return useRender({\n    defaultTagName: 'div',\n    render,\n    props: mergeProps(\n      {\n        role: 'option',\n        'aria-selected': selected,\n        'aria-disabled': disabled || undefined,\n        tabIndex: selected ? 0 : -1,\n        'data-slot': 'dialog-list-item',\n        'data-selected': selected ? '' : undefined,\n        className: slots.listItem({ className }),\n        onClick: (event: ReactTypes.MouseEvent<HTMLDivElement>) => {\n          onClick?.(event);\n          if (!disabled) onSelect?.();\n        },\n        onKeyDown: (event: ReactTypes.KeyboardEvent<HTMLDivElement>) => {\n          onKeyDown?.(event);\n          if ((event.key === 'Enter' || event.key === ' ') && !disabled) {\n            event.preventDefault();\n            onSelect?.();\n          }\n        },\n        children: (\n          <>\n            <span className={slots.listItemLabel()}>{children}</span>\n            {meta !== undefined ? <span className={slots.listItemMeta()}>{meta}</span> : null}\n            <span aria-hidden=\"true\" className={slots.listItemCheck()}>\n              {selected ? (\n                <svg\n                  viewBox=\"0 0 24 24\"\n                  fill=\"none\"\n                  stroke=\"currentColor\"\n                  strokeWidth=\"2.4\"\n                  strokeLinecap=\"round\"\n                  strokeLinejoin=\"round\"\n                >\n                  <path d=\"m5 12.5 4.5 4.5L19 7.5\" />\n                </svg>\n              ) : null}\n            </span>\n          </>\n        ),\n      },\n      props\n    ),\n  });\n}\nDialogListItem.displayName = 'Dialog.ListItem';\n\nexport const Dialog = Object.assign(DialogRoot, {\n  Trigger: DialogTrigger,\n  Content: DialogContent,\n  Header: DialogHeader,\n  Title: DialogTitle,\n  Description: DialogDescription,\n  Body: DialogBody,\n  Footer: DialogFooter,\n  Close: DialogClose,\n  List: DialogList,\n  ListGroup: DialogListGroup,\n  ListItem: DialogListItem,\n});\n\nexport {\n  DialogTrigger,\n  DialogContent,\n  DialogHeader,\n  DialogTitle,\n  DialogDescription,\n  DialogBody,\n  DialogFooter,\n  DialogClose,\n  DialogList,\n  DialogListGroup,\n  DialogListItem,\n};\n"
    }
  ]
}
