{"version":3,"file":"CopilotPopupView.mjs","names":["CopilotChatView"],"sources":["../../../src/components/chat/CopilotPopupView.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport CopilotChatView, {\n  CopilotChatViewProps,\n  WelcomeScreenProps,\n} from \"./CopilotChatView\";\nimport CopilotChatToggleButton from \"./CopilotChatToggleButton\";\nimport { CopilotModalHeader } from \"./CopilotModalHeader\";\nimport { cn } from \"@/lib/utils\";\nimport { renderSlot, SlotValue } from \"@/lib/slots\";\nimport {\n  CopilotChatConfigurationProvider,\n  CopilotChatDefaultLabels,\n  useCopilotChatConfiguration,\n} from \"@/providers/CopilotChatConfigurationProvider\";\n\nconst DEFAULT_POPUP_WIDTH = 420;\nconst DEFAULT_POPUP_HEIGHT = 560;\n\nexport type CopilotPopupViewProps = CopilotChatViewProps & {\n  header?: SlotValue<typeof CopilotModalHeader>;\n  toggleButton?: SlotValue<typeof CopilotChatToggleButton>;\n  width?: number | string;\n  height?: number | string;\n  clickOutsideToClose?: boolean;\n  defaultOpen?: boolean;\n};\n\nconst dimensionToCss = (\n  value: number | string | undefined,\n  fallback: number,\n): string => {\n  if (typeof value === \"number\" && Number.isFinite(value)) {\n    return `${value}px`;\n  }\n\n  if (typeof value === \"string\" && value.trim().length > 0) {\n    return value;\n  }\n\n  return `${fallback}px`;\n};\n\nexport function CopilotPopupView({\n  header,\n  toggleButton,\n  width,\n  height,\n  clickOutsideToClose,\n  defaultOpen = true,\n  className,\n  ...restProps\n}: CopilotPopupViewProps) {\n  return (\n    <CopilotChatConfigurationProvider isModalDefaultOpen={defaultOpen}>\n      <CopilotPopupViewInternal\n        header={header}\n        toggleButton={toggleButton}\n        width={width}\n        height={height}\n        clickOutsideToClose={clickOutsideToClose}\n        className={className}\n        {...restProps}\n      />\n    </CopilotChatConfigurationProvider>\n  );\n}\n\nfunction CopilotPopupViewInternal({\n  header,\n  toggleButton,\n  width,\n  height,\n  clickOutsideToClose,\n  className,\n  ...restProps\n}: Omit<CopilotPopupViewProps, \"defaultOpen\">) {\n  const configuration = useCopilotChatConfiguration();\n  const isPopupOpen = configuration?.isModalOpen ?? false;\n  const setModalOpen = configuration?.setModalOpen;\n  const labels = configuration?.labels ?? CopilotChatDefaultLabels;\n\n  const containerRef = useRef<HTMLDivElement>(null);\n  const [isRendered, setIsRendered] = useState(isPopupOpen);\n  const [isAnimatingOut, setIsAnimatingOut] = useState(false);\n\n  useEffect(() => {\n    if (isPopupOpen) {\n      setIsRendered(true);\n      setIsAnimatingOut(false);\n      return;\n    }\n\n    if (!isRendered) {\n      return;\n    }\n\n    setIsAnimatingOut(true);\n    const timeout = setTimeout(() => {\n      setIsRendered(false);\n      setIsAnimatingOut(false);\n    }, 200);\n\n    return () => clearTimeout(timeout);\n  }, [isPopupOpen, isRendered]);\n\n  useEffect(() => {\n    if (!isPopupOpen) {\n      return;\n    }\n\n    if (typeof window === \"undefined\") {\n      return;\n    }\n\n    const handleKeyDown = (event: KeyboardEvent) => {\n      if (event.key === \"Escape\") {\n        event.preventDefault();\n        setModalOpen?.(false);\n      }\n    };\n\n    window.addEventListener(\"keydown\", handleKeyDown);\n    return () => window.removeEventListener(\"keydown\", handleKeyDown);\n  }, [isPopupOpen, setModalOpen]);\n\n  useEffect(() => {\n    if (!isPopupOpen) {\n      return;\n    }\n\n    const focusTimer = setTimeout(() => {\n      const container = containerRef.current;\n      // Don't steal focus if something inside the popup (like the input) is already focused\n      if (container && !container.contains(document.activeElement)) {\n        container.focus({ preventScroll: true });\n      }\n    }, 200);\n\n    return () => clearTimeout(focusTimer);\n  }, [isPopupOpen]);\n\n  useEffect(() => {\n    if (!isPopupOpen || !clickOutsideToClose) {\n      return;\n    }\n\n    if (typeof document === \"undefined\") {\n      return;\n    }\n\n    const handlePointerDown = (event: PointerEvent) => {\n      const target = event.target as Node | null;\n      if (!target) {\n        return;\n      }\n\n      const container = containerRef.current;\n      if (container?.contains(target)) {\n        return;\n      }\n\n      const toggleButton = document.querySelector(\n        \"[data-slot='chat-toggle-button']\",\n      );\n      if (toggleButton && toggleButton.contains(target)) {\n        return;\n      }\n\n      setModalOpen?.(false);\n    };\n\n    document.addEventListener(\"pointerdown\", handlePointerDown);\n    return () => document.removeEventListener(\"pointerdown\", handlePointerDown);\n  }, [isPopupOpen, clickOutsideToClose, setModalOpen]);\n\n  const headerElement = useMemo(\n    () => renderSlot(header, CopilotModalHeader, {}),\n    [header],\n  );\n  const toggleButtonElement = useMemo(\n    () => renderSlot(toggleButton, CopilotChatToggleButton, {}),\n    [toggleButton],\n  );\n\n  const resolvedWidth = dimensionToCss(width, DEFAULT_POPUP_WIDTH);\n  const resolvedHeight = dimensionToCss(height, DEFAULT_POPUP_HEIGHT);\n\n  const popupStyle = useMemo(\n    () =>\n      ({\n        \"--copilot-popup-width\": resolvedWidth,\n        \"--copilot-popup-height\": resolvedHeight,\n        \"--copilot-popup-max-width\": \"calc(100vw - 3rem)\",\n        \"--copilot-popup-max-height\": \"calc(100dvh - 7.5rem)\",\n        paddingTop: \"env(safe-area-inset-top)\",\n        paddingBottom: \"env(safe-area-inset-bottom)\",\n        paddingLeft: \"env(safe-area-inset-left)\",\n        paddingRight: \"env(safe-area-inset-right)\",\n      }) as React.CSSProperties,\n    [resolvedHeight, resolvedWidth],\n  );\n\n  const popupAnimationClass =\n    isPopupOpen && !isAnimatingOut\n      ? \"cpk:pointer-events-auto cpk:translate-y-0 cpk:opacity-100 cpk:md:scale-100\"\n      : \"cpk:pointer-events-none cpk:translate-y-4 cpk:opacity-0 cpk:md:translate-y-5 cpk:md:scale-[0.95]\";\n\n  const popupContent = isRendered ? (\n    <div\n      data-copilotkit\n      className={cn(\n        \"cpk:fixed cpk:inset-0 cpk:z-[1200] cpk:flex cpk:max-w-full cpk:flex-col cpk:items-stretch\",\n        \"cpk:md:inset-auto cpk:md:bottom-24 cpk:md:right-6 cpk:md:items-end cpk:md:gap-4\",\n      )}\n    >\n      <div\n        ref={containerRef}\n        tabIndex={-1}\n        role=\"dialog\"\n        aria-label={labels.modalHeaderTitle}\n        data-testid=\"copilot-popup\"\n        data-copilot-popup\n        className={cn(\n          \"copilotKitPopup copilotKitWindow\",\n          \"cpk:relative cpk:flex cpk:h-full cpk:w-full cpk:flex-col cpk:overflow-hidden cpk:bg-background cpk:text-foreground\",\n          \"cpk:origin-bottom cpk:focus:outline-none cpk:transform-gpu cpk:transition-transform cpk:transition-opacity cpk:duration-200 cpk:ease-out\",\n          \"cpk:md:transition-transform cpk:md:transition-opacity\",\n          \"cpk:rounded-none cpk:border cpk:border-border/0 cpk:shadow-none cpk:ring-0\",\n          \"cpk:md:h-[var(--copilot-popup-height)] cpk:md:w-[var(--copilot-popup-width)]\",\n          \"cpk:md:max-h-[var(--copilot-popup-max-height)] cpk:md:max-w-[var(--copilot-popup-max-width)]\",\n          \"cpk:md:origin-bottom-right cpk:md:rounded-2xl cpk:md:border-border cpk:md:shadow-xl cpk:md:ring-1 cpk:md:ring-border/40\",\n          popupAnimationClass,\n        )}\n        style={popupStyle}\n      >\n        {headerElement}\n        <div className=\"cpk:flex-1 cpk:overflow-hidden\" data-popup-chat>\n          <CopilotChatView\n            {...restProps}\n            className={cn(\"cpk:h-full cpk:min-h-0\", className)}\n          />\n        </div>\n      </div>\n    </div>\n  ) : null;\n\n  return (\n    <>\n      {toggleButtonElement}\n      {popupContent}\n    </>\n  );\n}\n\nCopilotPopupView.displayName = \"CopilotPopupView\";\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace CopilotPopupView {\n  /**\n   * Popup-specific welcome screen layout:\n   * - Welcome message centered vertically\n   * - Suggestions just above input\n   * - Input fixed at the bottom\n   */\n  export const WelcomeScreen: React.FC<WelcomeScreenProps> = ({\n    welcomeMessage,\n    input,\n    suggestionView,\n    className,\n    children,\n    ...props\n  }) => {\n    // Render the welcomeMessage slot internally\n    const BoundWelcomeMessage = renderSlot(\n      welcomeMessage,\n      CopilotChatView.WelcomeMessage,\n      {},\n    );\n\n    if (children) {\n      return (\n        <div data-copilotkit style={{ display: \"contents\" }}>\n          {children({\n            welcomeMessage: BoundWelcomeMessage,\n            input,\n            suggestionView,\n            className,\n            ...props,\n          })}\n        </div>\n      );\n    }\n\n    return (\n      <div\n        className={cn(\"cpk:h-full cpk:flex cpk:flex-col\", className)}\n        {...props}\n      >\n        {/* Welcome message - centered vertically */}\n        <div className=\"cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4\">\n          {BoundWelcomeMessage}\n        </div>\n\n        {/* Suggestions and input at bottom */}\n        <div>\n          {/* Suggestions above input */}\n          <div className=\"cpk:mb-4 cpk:flex cpk:justify-center cpk:px-4\">\n            {suggestionView}\n          </div>\n          {input}\n        </div>\n      </div>\n    );\n  };\n}\n\nexport default CopilotPopupView;\n"],"mappings":"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"}