@copilotkitnext/react 1.52.2-next.2 → 1.52.2-next.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/chat/CopilotChat.cjs +32 -8
- package/dist/components/chat/CopilotChat.cjs.map +1 -1
- package/dist/components/chat/CopilotChat.d.cts +12 -0
- package/dist/components/chat/CopilotChat.d.cts.map +1 -1
- package/dist/components/chat/CopilotChat.d.mts +12 -0
- package/dist/components/chat/CopilotChat.d.mts.map +1 -1
- package/dist/components/chat/CopilotChat.mjs +34 -10
- package/dist/components/chat/CopilotChat.mjs.map +1 -1
- package/dist/components/chat/CopilotChatAssistantMessage.cjs +1 -1
- package/dist/components/chat/CopilotChatAssistantMessage.cjs.map +1 -1
- package/dist/components/chat/CopilotChatAssistantMessage.d.cts.map +1 -1
- package/dist/components/chat/CopilotChatAssistantMessage.d.mts.map +1 -1
- package/dist/components/chat/CopilotChatAssistantMessage.mjs +1 -1
- package/dist/components/chat/CopilotChatAssistantMessage.mjs.map +1 -1
- package/dist/components/chat/CopilotChatInput.cjs +1 -1
- package/dist/components/chat/CopilotChatInput.cjs.map +1 -1
- package/dist/components/chat/CopilotChatInput.d.cts.map +1 -1
- package/dist/components/chat/CopilotChatInput.d.mts.map +1 -1
- package/dist/components/chat/CopilotChatInput.mjs +1 -1
- package/dist/components/chat/CopilotChatInput.mjs.map +1 -1
- package/dist/components/chat/CopilotChatMessageView.cjs +1 -1
- package/dist/components/chat/CopilotChatMessageView.cjs.map +1 -1
- package/dist/components/chat/CopilotChatMessageView.mjs +1 -1
- package/dist/components/chat/CopilotChatMessageView.mjs.map +1 -1
- package/dist/components/chat/CopilotChatToggleButton.cjs +1 -1
- package/dist/components/chat/CopilotChatToggleButton.cjs.map +1 -1
- package/dist/components/chat/CopilotChatToggleButton.d.cts.map +1 -1
- package/dist/components/chat/CopilotChatToggleButton.d.mts.map +1 -1
- package/dist/components/chat/CopilotChatToggleButton.mjs +1 -1
- package/dist/components/chat/CopilotChatToggleButton.mjs.map +1 -1
- package/dist/components/chat/CopilotChatUserMessage.cjs +1 -1
- package/dist/components/chat/CopilotChatUserMessage.cjs.map +1 -1
- package/dist/components/chat/CopilotChatUserMessage.mjs +1 -1
- package/dist/components/chat/CopilotChatUserMessage.mjs.map +1 -1
- package/dist/components/chat/CopilotChatView.cjs +2 -2
- package/dist/components/chat/CopilotChatView.cjs.map +1 -1
- package/dist/components/chat/CopilotChatView.mjs +2 -2
- package/dist/components/chat/CopilotChatView.mjs.map +1 -1
- package/dist/components/chat/CopilotModalHeader.cjs +1 -1
- package/dist/components/chat/CopilotModalHeader.cjs.map +1 -1
- package/dist/components/chat/CopilotModalHeader.d.cts.map +1 -1
- package/dist/components/chat/CopilotModalHeader.d.mts.map +1 -1
- package/dist/components/chat/CopilotModalHeader.mjs +1 -1
- package/dist/components/chat/CopilotModalHeader.mjs.map +1 -1
- package/dist/components/chat/CopilotPopupView.cjs +1 -1
- package/dist/components/chat/CopilotPopupView.cjs.map +1 -1
- package/dist/components/chat/CopilotPopupView.d.cts.map +1 -1
- package/dist/components/chat/CopilotPopupView.d.mts.map +1 -1
- package/dist/components/chat/CopilotPopupView.mjs +1 -1
- package/dist/components/chat/CopilotPopupView.mjs.map +1 -1
- package/dist/components/chat/CopilotSidebarView.cjs +1 -1
- package/dist/components/chat/CopilotSidebarView.cjs.map +1 -1
- package/dist/components/chat/CopilotSidebarView.d.cts.map +1 -1
- package/dist/components/chat/CopilotSidebarView.d.mts.map +1 -1
- package/dist/components/chat/CopilotSidebarView.mjs +1 -1
- package/dist/components/chat/CopilotSidebarView.mjs.map +1 -1
- package/dist/hooks/use-agent.cjs +21 -3
- package/dist/hooks/use-agent.cjs.map +1 -1
- package/dist/hooks/use-agent.mjs +22 -4
- package/dist/hooks/use-agent.mjs.map +1 -1
- package/dist/index.umd.js +132 -46
- package/dist/index.umd.js.map +1 -1
- package/dist/lib/react-core.cjs +6 -0
- package/dist/lib/react-core.cjs.map +1 -1
- package/dist/lib/react-core.d.cts +2 -0
- package/dist/lib/react-core.d.cts.map +1 -1
- package/dist/lib/react-core.d.mts +2 -0
- package/dist/lib/react-core.d.mts.map +1 -1
- package/dist/lib/react-core.mjs +6 -0
- package/dist/lib/react-core.mjs.map +1 -1
- package/dist/providers/CopilotKitProvider.cjs +58 -25
- package/dist/providers/CopilotKitProvider.cjs.map +1 -1
- package/dist/providers/CopilotKitProvider.d.cts +10 -0
- package/dist/providers/CopilotKitProvider.d.cts.map +1 -1
- package/dist/providers/CopilotKitProvider.d.mts +10 -0
- package/dist/providers/CopilotKitProvider.d.mts.map +1 -1
- package/dist/providers/CopilotKitProvider.mjs +58 -25
- package/dist/providers/CopilotKitProvider.mjs.map +1 -1
- package/package.json +8 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotChatToggleButton.d.mts","names":[],"sources":["../../../src/components/chat/CopilotChatToggleButton.tsx"],"mappings":";;;;cAUM,eAAA,EAAiB,KAAA,CAAM,EAAA,CAAG,KAAA,CAAM,QAAA,CAAS,aAAA;AAAA,cAYzC,gBAAA,EAAkB,KAAA,CAAM,EAAA,CAAG,KAAA,CAAM,QAAA,CAAS,aAAA;AAAA,UAc/B,4BAAA,SAAqC,IAAA,CACpD,KAAA,CAAM,oBAAA,CAAqB,iBAAA;EAjB5B;EAqBC,QAAA,GAAW,SAAA,QAAiB,eAAA;EA/BiB;EAiC7C,SAAA,GAAY,SAAA,QAAiB,gBAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"CopilotChatToggleButton.d.mts","names":[],"sources":["../../../src/components/chat/CopilotChatToggleButton.tsx"],"mappings":";;;;cAUM,eAAA,EAAiB,KAAA,CAAM,EAAA,CAAG,KAAA,CAAM,QAAA,CAAS,aAAA;AAAA,cAYzC,gBAAA,EAAkB,KAAA,CAAM,EAAA,CAAG,KAAA,CAAM,QAAA,CAAS,aAAA;AAAA,UAc/B,4BAAA,SAAqC,IAAA,CACpD,KAAA,CAAM,oBAAA,CAAqB,iBAAA;EAjB5B;EAqBC,QAAA,GAAW,SAAA,QAAiB,eAAA;EA/BiB;EAiC7C,SAAA,GAAY,SAAA,QAAiB,gBAAA;AAAA;AAAA,cAuBlB,uBAAA,EAAuB,KAAA,CAAA,yBAAA,CAAA,4BAAA,GAAA,KAAA,CAAA,aAAA,CAAA,iBAAA"}
|
|
@@ -21,7 +21,7 @@ DefaultOpenIcon.displayName = "CopilotChatToggleButton.OpenIcon";
|
|
|
21
21
|
DefaultCloseIcon.displayName = "CopilotChatToggleButton.CloseIcon";
|
|
22
22
|
const ICON_TRANSITION_STYLE = Object.freeze({ transition: "opacity 120ms ease-out, transform 260ms cubic-bezier(0.22, 1, 0.36, 1)" });
|
|
23
23
|
const ICON_WRAPPER_BASE = "cpk:pointer-events-none cpk:absolute cpk:inset-0 cpk:flex cpk:items-center cpk:justify-center cpk:will-change-transform";
|
|
24
|
-
const BUTTON_BASE_CLASSES = cn("cpk:fixed cpk:bottom-6 cpk:right-6 cpk:z-[1100] cpk:flex cpk:h-14 cpk:w-14 cpk:items-center cpk:justify-center", "cpk:rounded-full cpk:border cpk:border-primary cpk:bg-primary cpk:text-primary-foreground", "cpk:shadow-sm cpk:transition-all cpk:duration-200 cpk:ease-out", "cpk:hover:scale-[1.04] cpk:hover:shadow-md", "cpk:cursor-pointer", "cpk:active:scale-[0.96]", "cpk:focus-visible:outline-none cpk:focus-visible:ring-2 cpk:focus-visible:ring-primary/50 cpk:focus-visible:ring-offset-2 cpk:focus-visible:ring-offset-background", "cpk:disabled:pointer-events-none cpk:disabled:opacity-60");
|
|
24
|
+
const BUTTON_BASE_CLASSES = cn("copilotKitButton", "cpk:fixed cpk:bottom-6 cpk:right-6 cpk:z-[1100] cpk:flex cpk:h-14 cpk:w-14 cpk:items-center cpk:justify-center", "cpk:rounded-full cpk:border cpk:border-primary cpk:bg-primary cpk:text-primary-foreground", "cpk:shadow-sm cpk:transition-all cpk:duration-200 cpk:ease-out", "cpk:hover:scale-[1.04] cpk:hover:shadow-md", "cpk:cursor-pointer", "cpk:active:scale-[0.96]", "cpk:focus-visible:outline-none cpk:focus-visible:ring-2 cpk:focus-visible:ring-primary/50 cpk:focus-visible:ring-offset-2 cpk:focus-visible:ring-offset-background", "cpk:disabled:pointer-events-none cpk:disabled:opacity-60");
|
|
25
25
|
const CopilotChatToggleButton = React.forwardRef(function CopilotChatToggleButton({ openIcon, closeIcon, className, ...buttonProps }, ref) {
|
|
26
26
|
const { onClick, type, disabled, ...restProps } = buttonProps;
|
|
27
27
|
const configuration = useCopilotChatConfiguration();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotChatToggleButton.mjs","names":[],"sources":["../../../src/components/chat/CopilotChatToggleButton.tsx"],"sourcesContent":["import React, { useState, MouseEvent } from \"react\";\nimport { MessageCircle, X } from \"lucide-react\";\n\nimport { renderSlot, SlotValue } from \"@/lib/slots\";\nimport { cn } from \"@/lib/utils\";\nimport {\n CopilotChatDefaultLabels,\n useCopilotChatConfiguration,\n} from \"@/providers/CopilotChatConfigurationProvider\";\n\nconst DefaultOpenIcon: React.FC<React.SVGProps<SVGSVGElement>> = ({\n className,\n ...props\n}) => (\n <MessageCircle\n className={cn(\"cpk:h-6 cpk:w-6\", className)}\n strokeWidth={1.75}\n fill=\"currentColor\"\n {...props}\n />\n);\n\nconst DefaultCloseIcon: React.FC<React.SVGProps<SVGSVGElement>> = ({\n className,\n ...props\n}) => (\n <X\n className={cn(\"cpk:h-6 cpk:w-6\", className)}\n strokeWidth={1.75}\n {...props}\n />\n);\n\nDefaultOpenIcon.displayName = \"CopilotChatToggleButton.OpenIcon\";\nDefaultCloseIcon.displayName = \"CopilotChatToggleButton.CloseIcon\";\n\nexport interface CopilotChatToggleButtonProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n \"children\"\n> {\n /** Optional slot override for the chat (closed) icon. */\n openIcon?: SlotValue<typeof DefaultOpenIcon>;\n /** Optional slot override for the close icon. */\n closeIcon?: SlotValue<typeof DefaultCloseIcon>;\n}\n\nconst ICON_TRANSITION_STYLE: React.CSSProperties = Object.freeze({\n transition:\n \"opacity 120ms ease-out, transform 260ms cubic-bezier(0.22, 1, 0.36, 1)\",\n});\n\nconst ICON_WRAPPER_BASE =\n \"cpk:pointer-events-none cpk:absolute cpk:inset-0 cpk:flex cpk:items-center cpk:justify-center cpk:will-change-transform\";\n\nconst BUTTON_BASE_CLASSES = cn(\n \"cpk:fixed cpk:bottom-6 cpk:right-6 cpk:z-[1100] cpk:flex cpk:h-14 cpk:w-14 cpk:items-center cpk:justify-center\",\n \"cpk:rounded-full cpk:border cpk:border-primary cpk:bg-primary cpk:text-primary-foreground\",\n \"cpk:shadow-sm cpk:transition-all cpk:duration-200 cpk:ease-out\",\n \"cpk:hover:scale-[1.04] cpk:hover:shadow-md\",\n \"cpk:cursor-pointer\",\n \"cpk:active:scale-[0.96]\",\n \"cpk:focus-visible:outline-none cpk:focus-visible:ring-2 cpk:focus-visible:ring-primary/50 cpk:focus-visible:ring-offset-2 cpk:focus-visible:ring-offset-background\",\n \"cpk:disabled:pointer-events-none cpk:disabled:opacity-60\",\n);\n\nexport const CopilotChatToggleButton = React.forwardRef<\n HTMLButtonElement,\n CopilotChatToggleButtonProps\n>(function CopilotChatToggleButton(\n { openIcon, closeIcon, className, ...buttonProps },\n ref,\n) {\n const { onClick, type, disabled, ...restProps } = buttonProps;\n\n const configuration = useCopilotChatConfiguration();\n const labels = configuration?.labels ?? CopilotChatDefaultLabels;\n\n const [fallbackOpen, setFallbackOpen] = useState(false);\n\n const isOpen = configuration?.isModalOpen ?? fallbackOpen;\n const setModalOpen = configuration?.setModalOpen ?? setFallbackOpen;\n\n const handleClick = (event: MouseEvent<HTMLButtonElement>) => {\n if (disabled) {\n return;\n }\n\n if (onClick) {\n onClick(event);\n }\n\n if (event.defaultPrevented) {\n return;\n }\n\n const nextOpen = !isOpen;\n setModalOpen(nextOpen);\n };\n\n const renderedOpenIcon = renderSlot(openIcon, DefaultOpenIcon, {\n className: \"cpk:h-6 cpk:w-6\",\n \"aria-hidden\": true,\n focusable: false,\n });\n\n const renderedCloseIcon = renderSlot(closeIcon, DefaultCloseIcon, {\n className: \"cpk:h-6 cpk:w-6\",\n \"aria-hidden\": true,\n focusable: false,\n });\n\n const openIconElement = (\n <span\n aria-hidden=\"true\"\n data-slot=\"chat-toggle-button-open-icon\"\n className={ICON_WRAPPER_BASE}\n style={{\n ...ICON_TRANSITION_STYLE,\n opacity: isOpen ? 0 : 1,\n transform: `scale(${isOpen ? 0.75 : 1}) rotate(${isOpen ? 90 : 0}deg)`,\n }}\n >\n {renderedOpenIcon}\n </span>\n );\n\n const closeIconElement = (\n <span\n aria-hidden=\"true\"\n data-slot=\"chat-toggle-button-close-icon\"\n className={ICON_WRAPPER_BASE}\n style={{\n ...ICON_TRANSITION_STYLE,\n opacity: isOpen ? 1 : 0,\n transform: `scale(${isOpen ? 1 : 0.75}) rotate(${isOpen ? 0 : -90}deg)`,\n }}\n >\n {renderedCloseIcon}\n </span>\n );\n\n return (\n <button\n ref={ref}\n type={type ?? \"button\"}\n data-copilotkit\n data-testid=\"copilot-chat-toggle\"\n data-slot=\"chat-toggle-button\"\n data-state={isOpen ? \"open\" : \"closed\"}\n className={cn(BUTTON_BASE_CLASSES, className)}\n aria-label={\n isOpen ? labels.chatToggleCloseLabel : labels.chatToggleOpenLabel\n }\n aria-pressed={isOpen}\n disabled={disabled}\n onClick={handleClick}\n {...restProps}\n >\n {openIconElement}\n {closeIconElement}\n </button>\n );\n});\nCopilotChatToggleButton.displayName = \"CopilotChatToggleButton\";\nexport default CopilotChatToggleButton;\n\nexport {\n DefaultOpenIcon as CopilotChatToggleButtonOpenIcon,\n DefaultCloseIcon as CopilotChatToggleButtonCloseIcon,\n};\n"],"mappings":";;;;;;;;AAUA,MAAM,mBAA4D,EAChE,WACA,GAAG,YAEH,oBAAC;CACC,WAAW,GAAG,mBAAmB,UAAU;CAC3C,aAAa;CACb,MAAK;CACL,GAAI;EACJ;AAGJ,MAAM,oBAA6D,EACjE,WACA,GAAG,YAEH,oBAAC;CACC,WAAW,GAAG,mBAAmB,UAAU;CAC3C,aAAa;CACb,GAAI;EACJ;AAGJ,gBAAgB,cAAc;AAC9B,iBAAiB,cAAc;AAY/B,MAAM,wBAA6C,OAAO,OAAO,EAC/D,YACE,0EACH,CAAC;AAEF,MAAM,oBACJ;AAEF,MAAM,sBAAsB,GAC1B,kHACA,6FACA,kEACA,8CACA,sBACA,2BACA,sKACA,2DACD;AAED,MAAa,0BAA0B,MAAM,WAG3C,SAAS,wBACT,EAAE,UAAU,WAAW,WAAW,GAAG,eACrC,KACA;CACA,MAAM,EAAE,SAAS,MAAM,UAAU,GAAG,cAAc;CAElD,MAAM,gBAAgB,6BAA6B;CACnD,MAAM,SAAS,eAAe,UAAU;CAExC,MAAM,CAAC,cAAc,mBAAmB,SAAS,MAAM;CAEvD,MAAM,SAAS,eAAe,eAAe;CAC7C,MAAM,eAAe,eAAe,gBAAgB;CAEpD,MAAM,eAAe,UAAyC;AAC5D,MAAI,SACF;AAGF,MAAI,QACF,SAAQ,MAAM;AAGhB,MAAI,MAAM,iBACR;AAIF,eADiB,CAAC,OACI;;CAGxB,MAAM,mBAAmB,WAAW,UAAU,iBAAiB;EAC7D,WAAW;EACX,eAAe;EACf,WAAW;EACZ,CAAC;CAEF,MAAM,oBAAoB,WAAW,WAAW,kBAAkB;EAChE,WAAW;EACX,eAAe;EACf,WAAW;EACZ,CAAC;CAEF,MAAM,kBACJ,oBAAC;EACC,eAAY;EACZ,aAAU;EACV,WAAW;EACX,OAAO;GACL,GAAG;GACH,SAAS,SAAS,IAAI;GACtB,WAAW,SAAS,SAAS,MAAO,EAAE,WAAW,SAAS,KAAK,EAAE;GAClE;YAEA;GACI;CAGT,MAAM,mBACJ,oBAAC;EACC,eAAY;EACZ,aAAU;EACV,WAAW;EACX,OAAO;GACL,GAAG;GACH,SAAS,SAAS,IAAI;GACtB,WAAW,SAAS,SAAS,IAAI,IAAK,WAAW,SAAS,IAAI,IAAI;GACnE;YAEA;GACI;AAGT,QACE,qBAAC;EACM;EACL,MAAM,QAAQ;EACd;EACA,eAAY;EACZ,aAAU;EACV,cAAY,SAAS,SAAS;EAC9B,WAAW,GAAG,qBAAqB,UAAU;EAC7C,cACE,SAAS,OAAO,uBAAuB,OAAO;EAEhD,gBAAc;EACJ;EACV,SAAS;EACT,GAAI;aAEH,iBACA;GACM;EAEX;AACF,wBAAwB,cAAc"}
|
|
1
|
+
{"version":3,"file":"CopilotChatToggleButton.mjs","names":[],"sources":["../../../src/components/chat/CopilotChatToggleButton.tsx"],"sourcesContent":["import React, { useState, MouseEvent } from \"react\";\nimport { MessageCircle, X } from \"lucide-react\";\n\nimport { renderSlot, SlotValue } from \"@/lib/slots\";\nimport { cn } from \"@/lib/utils\";\nimport {\n CopilotChatDefaultLabels,\n useCopilotChatConfiguration,\n} from \"@/providers/CopilotChatConfigurationProvider\";\n\nconst DefaultOpenIcon: React.FC<React.SVGProps<SVGSVGElement>> = ({\n className,\n ...props\n}) => (\n <MessageCircle\n className={cn(\"cpk:h-6 cpk:w-6\", className)}\n strokeWidth={1.75}\n fill=\"currentColor\"\n {...props}\n />\n);\n\nconst DefaultCloseIcon: React.FC<React.SVGProps<SVGSVGElement>> = ({\n className,\n ...props\n}) => (\n <X\n className={cn(\"cpk:h-6 cpk:w-6\", className)}\n strokeWidth={1.75}\n {...props}\n />\n);\n\nDefaultOpenIcon.displayName = \"CopilotChatToggleButton.OpenIcon\";\nDefaultCloseIcon.displayName = \"CopilotChatToggleButton.CloseIcon\";\n\nexport interface CopilotChatToggleButtonProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n \"children\"\n> {\n /** Optional slot override for the chat (closed) icon. */\n openIcon?: SlotValue<typeof DefaultOpenIcon>;\n /** Optional slot override for the close icon. */\n closeIcon?: SlotValue<typeof DefaultCloseIcon>;\n}\n\nconst ICON_TRANSITION_STYLE: React.CSSProperties = Object.freeze({\n transition:\n \"opacity 120ms ease-out, transform 260ms cubic-bezier(0.22, 1, 0.36, 1)\",\n});\n\nconst ICON_WRAPPER_BASE =\n \"cpk:pointer-events-none cpk:absolute cpk:inset-0 cpk:flex cpk:items-center cpk:justify-center cpk:will-change-transform\";\n\nconst BUTTON_BASE_CLASSES = cn(\n \"copilotKitButton\",\n \"cpk:fixed cpk:bottom-6 cpk:right-6 cpk:z-[1100] cpk:flex cpk:h-14 cpk:w-14 cpk:items-center cpk:justify-center\",\n \"cpk:rounded-full cpk:border cpk:border-primary cpk:bg-primary cpk:text-primary-foreground\",\n \"cpk:shadow-sm cpk:transition-all cpk:duration-200 cpk:ease-out\",\n \"cpk:hover:scale-[1.04] cpk:hover:shadow-md\",\n \"cpk:cursor-pointer\",\n \"cpk:active:scale-[0.96]\",\n \"cpk:focus-visible:outline-none cpk:focus-visible:ring-2 cpk:focus-visible:ring-primary/50 cpk:focus-visible:ring-offset-2 cpk:focus-visible:ring-offset-background\",\n \"cpk:disabled:pointer-events-none cpk:disabled:opacity-60\",\n);\n\nexport const CopilotChatToggleButton = React.forwardRef<\n HTMLButtonElement,\n CopilotChatToggleButtonProps\n>(function CopilotChatToggleButton(\n { openIcon, closeIcon, className, ...buttonProps },\n ref,\n) {\n const { onClick, type, disabled, ...restProps } = buttonProps;\n\n const configuration = useCopilotChatConfiguration();\n const labels = configuration?.labels ?? CopilotChatDefaultLabels;\n\n const [fallbackOpen, setFallbackOpen] = useState(false);\n\n const isOpen = configuration?.isModalOpen ?? fallbackOpen;\n const setModalOpen = configuration?.setModalOpen ?? setFallbackOpen;\n\n const handleClick = (event: MouseEvent<HTMLButtonElement>) => {\n if (disabled) {\n return;\n }\n\n if (onClick) {\n onClick(event);\n }\n\n if (event.defaultPrevented) {\n return;\n }\n\n const nextOpen = !isOpen;\n setModalOpen(nextOpen);\n };\n\n const renderedOpenIcon = renderSlot(openIcon, DefaultOpenIcon, {\n className: \"cpk:h-6 cpk:w-6\",\n \"aria-hidden\": true,\n focusable: false,\n });\n\n const renderedCloseIcon = renderSlot(closeIcon, DefaultCloseIcon, {\n className: \"cpk:h-6 cpk:w-6\",\n \"aria-hidden\": true,\n focusable: false,\n });\n\n const openIconElement = (\n <span\n aria-hidden=\"true\"\n data-slot=\"chat-toggle-button-open-icon\"\n className={ICON_WRAPPER_BASE}\n style={{\n ...ICON_TRANSITION_STYLE,\n opacity: isOpen ? 0 : 1,\n transform: `scale(${isOpen ? 0.75 : 1}) rotate(${isOpen ? 90 : 0}deg)`,\n }}\n >\n {renderedOpenIcon}\n </span>\n );\n\n const closeIconElement = (\n <span\n aria-hidden=\"true\"\n data-slot=\"chat-toggle-button-close-icon\"\n className={ICON_WRAPPER_BASE}\n style={{\n ...ICON_TRANSITION_STYLE,\n opacity: isOpen ? 1 : 0,\n transform: `scale(${isOpen ? 1 : 0.75}) rotate(${isOpen ? 0 : -90}deg)`,\n }}\n >\n {renderedCloseIcon}\n </span>\n );\n\n return (\n <button\n ref={ref}\n type={type ?? \"button\"}\n data-copilotkit\n data-testid=\"copilot-chat-toggle\"\n data-slot=\"chat-toggle-button\"\n data-state={isOpen ? \"open\" : \"closed\"}\n className={cn(BUTTON_BASE_CLASSES, className)}\n aria-label={\n isOpen ? labels.chatToggleCloseLabel : labels.chatToggleOpenLabel\n }\n aria-pressed={isOpen}\n disabled={disabled}\n onClick={handleClick}\n {...restProps}\n >\n {openIconElement}\n {closeIconElement}\n </button>\n );\n});\nCopilotChatToggleButton.displayName = \"CopilotChatToggleButton\";\nexport default CopilotChatToggleButton;\n\nexport {\n DefaultOpenIcon as CopilotChatToggleButtonOpenIcon,\n DefaultCloseIcon as CopilotChatToggleButtonCloseIcon,\n};\n"],"mappings":";;;;;;;;AAUA,MAAM,mBAA4D,EAChE,WACA,GAAG,YAEH,oBAAC;CACC,WAAW,GAAG,mBAAmB,UAAU;CAC3C,aAAa;CACb,MAAK;CACL,GAAI;EACJ;AAGJ,MAAM,oBAA6D,EACjE,WACA,GAAG,YAEH,oBAAC;CACC,WAAW,GAAG,mBAAmB,UAAU;CAC3C,aAAa;CACb,GAAI;EACJ;AAGJ,gBAAgB,cAAc;AAC9B,iBAAiB,cAAc;AAY/B,MAAM,wBAA6C,OAAO,OAAO,EAC/D,YACE,0EACH,CAAC;AAEF,MAAM,oBACJ;AAEF,MAAM,sBAAsB,GAC1B,oBACA,kHACA,6FACA,kEACA,8CACA,sBACA,2BACA,sKACA,2DACD;AAED,MAAa,0BAA0B,MAAM,WAG3C,SAAS,wBACT,EAAE,UAAU,WAAW,WAAW,GAAG,eACrC,KACA;CACA,MAAM,EAAE,SAAS,MAAM,UAAU,GAAG,cAAc;CAElD,MAAM,gBAAgB,6BAA6B;CACnD,MAAM,SAAS,eAAe,UAAU;CAExC,MAAM,CAAC,cAAc,mBAAmB,SAAS,MAAM;CAEvD,MAAM,SAAS,eAAe,eAAe;CAC7C,MAAM,eAAe,eAAe,gBAAgB;CAEpD,MAAM,eAAe,UAAyC;AAC5D,MAAI,SACF;AAGF,MAAI,QACF,SAAQ,MAAM;AAGhB,MAAI,MAAM,iBACR;AAIF,eADiB,CAAC,OACI;;CAGxB,MAAM,mBAAmB,WAAW,UAAU,iBAAiB;EAC7D,WAAW;EACX,eAAe;EACf,WAAW;EACZ,CAAC;CAEF,MAAM,oBAAoB,WAAW,WAAW,kBAAkB;EAChE,WAAW;EACX,eAAe;EACf,WAAW;EACZ,CAAC;CAEF,MAAM,kBACJ,oBAAC;EACC,eAAY;EACZ,aAAU;EACV,WAAW;EACX,OAAO;GACL,GAAG;GACH,SAAS,SAAS,IAAI;GACtB,WAAW,SAAS,SAAS,MAAO,EAAE,WAAW,SAAS,KAAK,EAAE;GAClE;YAEA;GACI;CAGT,MAAM,mBACJ,oBAAC;EACC,eAAY;EACZ,aAAU;EACV,WAAW;EACX,OAAO;GACL,GAAG;GACH,SAAS,SAAS,IAAI;GACtB,WAAW,SAAS,SAAS,IAAI,IAAK,WAAW,SAAS,IAAI,IAAI;GACnE;YAEA;GACI;AAGT,QACE,qBAAC;EACM;EACL,MAAM,QAAQ;EACd;EACA,eAAY;EACZ,aAAU;EACV,cAAY,SAAS,SAAS;EAC9B,WAAW,GAAG,qBAAqB,UAAU;EAC7C,cACE,SAAS,OAAO,uBAAuB,OAAO;EAEhD,gBAAc;EACJ;EACV,SAAS;EACT,GAAI;aAEH,iBACA;GACM;EAEX;AACF,wBAAwB,cAAc"}
|
|
@@ -62,7 +62,7 @@ function CopilotChatUserMessage({ message, onEditMessage, branchIndex, numberOfB
|
|
|
62
62
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
63
63
|
"data-copilotkit": true,
|
|
64
64
|
"data-testid": "copilot-user-message",
|
|
65
|
-
className: (0, tailwind_merge.twMerge)("cpk:flex cpk:flex-col cpk:items-end cpk:group cpk:pt-10", className),
|
|
65
|
+
className: (0, tailwind_merge.twMerge)("copilotKitMessage copilotKitUserMessage cpk:flex cpk:flex-col cpk:items-end cpk:group cpk:pt-10", className),
|
|
66
66
|
"data-message-id": message.id,
|
|
67
67
|
...props,
|
|
68
68
|
children: [BoundMessageRenderer, BoundToolbar]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotChatUserMessage.cjs","names":["renderSlot","Tooltip","TooltipTrigger","Button","TooltipContent","useCopilotChatConfiguration","CopilotChatDefaultLabels","Check","Copy","Edit","ChevronLeft","ChevronRight"],"sources":["../../../src/components/chat/CopilotChatUserMessage.tsx"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport { Copy, Check, Edit, ChevronLeft, ChevronRight } from \"lucide-react\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { twMerge } from \"tailwind-merge\";\nimport { Button } from \"@/components/ui/button\";\nimport { UserMessage } from \"@ag-ui/core\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@/components/ui/tooltip\";\nimport { renderSlot, WithSlots } from \"@/lib/slots\";\n\nfunction flattenUserMessageContent(content?: UserMessage[\"content\"]): string {\n if (!content) {\n return \"\";\n }\n\n if (typeof content === \"string\") {\n return content;\n }\n\n return content\n .map((part) => {\n if (\n part &&\n typeof part === \"object\" &&\n \"type\" in part &&\n (part as { type?: unknown }).type === \"text\" &&\n typeof (part as { text?: unknown }).text === \"string\"\n ) {\n return (part as { text: string }).text;\n }\n return \"\";\n })\n .filter((text) => text.length > 0)\n .join(\"\\n\");\n}\n\nexport interface CopilotChatUserMessageOnEditMessageProps {\n message: UserMessage;\n}\n\nexport interface CopilotChatUserMessageOnSwitchToBranchProps {\n message: UserMessage;\n branchIndex: number;\n numberOfBranches: number;\n}\n\nexport type CopilotChatUserMessageProps = WithSlots<\n {\n messageRenderer: typeof CopilotChatUserMessage.MessageRenderer;\n toolbar: typeof CopilotChatUserMessage.Toolbar;\n copyButton: typeof CopilotChatUserMessage.CopyButton;\n editButton: typeof CopilotChatUserMessage.EditButton;\n branchNavigation: typeof CopilotChatUserMessage.BranchNavigation;\n },\n {\n onEditMessage?: (props: CopilotChatUserMessageOnEditMessageProps) => void;\n onSwitchToBranch?: (\n props: CopilotChatUserMessageOnSwitchToBranchProps,\n ) => void;\n message: UserMessage;\n branchIndex?: number;\n numberOfBranches?: number;\n additionalToolbarItems?: React.ReactNode;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport function CopilotChatUserMessage({\n message,\n onEditMessage,\n branchIndex,\n numberOfBranches,\n onSwitchToBranch,\n additionalToolbarItems,\n messageRenderer,\n toolbar,\n copyButton,\n editButton,\n branchNavigation,\n children,\n className,\n ...props\n}: CopilotChatUserMessageProps) {\n const flattenedContent = useMemo(\n () => flattenUserMessageContent(message.content),\n [message.content],\n );\n\n const BoundMessageRenderer = renderSlot(\n messageRenderer,\n CopilotChatUserMessage.MessageRenderer,\n {\n content: flattenedContent,\n },\n );\n\n const BoundCopyButton = renderSlot(\n copyButton,\n CopilotChatUserMessage.CopyButton,\n {\n onClick: async () => {\n if (flattenedContent) {\n try {\n await navigator.clipboard.writeText(flattenedContent);\n } catch (err) {\n console.error(\"Failed to copy message:\", err);\n }\n }\n },\n },\n );\n\n const BoundEditButton = renderSlot(\n editButton,\n CopilotChatUserMessage.EditButton,\n {\n onClick: () => onEditMessage?.({ message }),\n },\n );\n\n const BoundBranchNavigation = renderSlot(\n branchNavigation,\n CopilotChatUserMessage.BranchNavigation,\n {\n currentBranch: branchIndex,\n numberOfBranches,\n onSwitchToBranch,\n message,\n },\n );\n\n const showBranchNavigation =\n numberOfBranches && numberOfBranches > 1 && onSwitchToBranch;\n\n const BoundToolbar = renderSlot(toolbar, CopilotChatUserMessage.Toolbar, {\n children: (\n <div className=\"cpk:flex cpk:items-center cpk:gap-1 cpk:justify-end\">\n {additionalToolbarItems}\n {BoundCopyButton}\n {onEditMessage && BoundEditButton}\n {showBranchNavigation && BoundBranchNavigation}\n </div>\n ),\n });\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n messageRenderer: BoundMessageRenderer,\n toolbar: BoundToolbar,\n copyButton: BoundCopyButton,\n editButton: BoundEditButton,\n branchNavigation: BoundBranchNavigation,\n message,\n branchIndex,\n numberOfBranches,\n additionalToolbarItems,\n })}\n </div>\n );\n }\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-user-message\"\n className={twMerge(\n \"cpk:flex cpk:flex-col cpk:items-end cpk:group cpk:pt-10\",\n className,\n )}\n data-message-id={message.id}\n {...props}\n >\n {BoundMessageRenderer}\n {BoundToolbar}\n </div>\n );\n}\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace CopilotChatUserMessage {\n export const Container: React.FC<\n React.PropsWithChildren<React.HTMLAttributes<HTMLDivElement>>\n > = ({ children, className, ...props }) => (\n <div\n className={twMerge(\n \"cpk:flex cpk:flex-col cpk:items-end cpk:group\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n\n export const MessageRenderer: React.FC<{\n content: string;\n className?: string;\n }> = ({ content, className }) => (\n <div\n className={twMerge(\n \"cpk:prose cpk:dark:prose-invert cpk:bg-muted cpk:relative cpk:max-w-[80%] cpk:rounded-[18px] cpk:px-4 cpk:py-1.5 cpk:data-[multiline]:py-3 cpk:inline-block cpk:whitespace-pre-wrap\",\n className,\n )}\n >\n {content}\n </div>\n );\n\n export const Toolbar: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n ...props\n }) => (\n <div\n data-testid=\"copilot-user-toolbar\"\n className={twMerge(\n \"cpk:w-full cpk:bg-transparent cpk:flex cpk:items-center cpk:justify-end cpk:-mr-[5px] cpk:mt-[4px] cpk:invisible cpk:group-hover:visible\",\n className,\n )}\n {...props}\n />\n );\n\n export const ToolbarButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement> & {\n title: string;\n children: React.ReactNode;\n }\n > = ({ title, children, className, ...props }) => {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n type=\"button\"\n variant=\"assistantMessageToolbarButton\"\n aria-label={title}\n className={twMerge(className)}\n {...props}\n >\n {children}\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">\n <p>{title}</p>\n </TooltipContent>\n </Tooltip>\n );\n };\n\n export const CopyButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement> & { copied?: boolean }\n > = ({ className, title, onClick, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n const [copied, setCopied] = useState(false);\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n\n if (onClick) {\n onClick(event);\n }\n };\n\n return (\n <ToolbarButton\n data-testid=\"copilot-user-copy-button\"\n title={title || labels.userMessageToolbarCopyMessageLabel}\n onClick={handleClick}\n className={className}\n {...props}\n >\n {copied ? (\n <Check className=\"cpk:size-[18px]\" />\n ) : (\n <Copy className=\"cpk:size-[18px]\" />\n )}\n </ToolbarButton>\n );\n };\n\n export const EditButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, title, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n return (\n <ToolbarButton\n data-testid=\"copilot-edit-button\"\n title={title || labels.userMessageToolbarEditMessageLabel}\n className={className}\n {...props}\n >\n <Edit className=\"cpk:size-[18px]\" />\n </ToolbarButton>\n );\n };\n\n export const BranchNavigation: React.FC<\n React.HTMLAttributes<HTMLDivElement> & {\n currentBranch?: number;\n numberOfBranches?: number;\n onSwitchToBranch?: (\n props: CopilotChatUserMessageOnSwitchToBranchProps,\n ) => void;\n message: UserMessage;\n }\n > = ({\n className,\n currentBranch = 0,\n numberOfBranches = 1,\n onSwitchToBranch,\n message,\n ...props\n }) => {\n if (!numberOfBranches || numberOfBranches <= 1 || !onSwitchToBranch) {\n return null;\n }\n\n const canGoPrev = currentBranch > 0;\n const canGoNext = currentBranch < numberOfBranches - 1;\n\n return (\n <div\n data-testid=\"copilot-branch-navigation\"\n className={twMerge(\"cpk:flex cpk:items-center cpk:gap-1\", className)}\n {...props}\n >\n <Button\n type=\"button\"\n variant=\"assistantMessageToolbarButton\"\n onClick={() =>\n onSwitchToBranch?.({\n branchIndex: currentBranch - 1,\n numberOfBranches,\n message,\n })\n }\n disabled={!canGoPrev}\n className=\"cpk:h-6 cpk:w-6 cpk:p-0\"\n >\n <ChevronLeft className=\"cpk:size-[20px]\" />\n </Button>\n <span className=\"cpk:text-sm cpk:text-muted-foreground cpk:px-0 cpk:font-medium\">\n {currentBranch + 1}/{numberOfBranches}\n </span>\n <Button\n type=\"button\"\n variant=\"assistantMessageToolbarButton\"\n onClick={() =>\n onSwitchToBranch?.({\n branchIndex: currentBranch + 1,\n numberOfBranches,\n message,\n })\n }\n disabled={!canGoNext}\n className=\"cpk:h-6 cpk:w-6 cpk:p-0\"\n >\n <ChevronRight className=\"cpk:size-[20px]\" />\n </Button>\n </div>\n );\n };\n}\n\nCopilotChatUserMessage.Container.displayName =\n \"CopilotChatUserMessage.Container\";\nCopilotChatUserMessage.MessageRenderer.displayName =\n \"CopilotChatUserMessage.MessageRenderer\";\nCopilotChatUserMessage.Toolbar.displayName = \"CopilotChatUserMessage.Toolbar\";\nCopilotChatUserMessage.ToolbarButton.displayName =\n \"CopilotChatUserMessage.ToolbarButton\";\nCopilotChatUserMessage.CopyButton.displayName =\n \"CopilotChatUserMessage.CopyButton\";\nCopilotChatUserMessage.EditButton.displayName =\n \"CopilotChatUserMessage.EditButton\";\nCopilotChatUserMessage.BranchNavigation.displayName =\n \"CopilotChatUserMessage.BranchNavigation\";\n\nexport default CopilotChatUserMessage;\n"],"mappings":";;;;;;;;;;;AAgBA,SAAS,0BAA0B,SAA0C;AAC3E,KAAI,CAAC,QACH,QAAO;AAGT,KAAI,OAAO,YAAY,SACrB,QAAO;AAGT,QAAO,QACJ,KAAK,SAAS;AACb,MACE,QACA,OAAO,SAAS,YAChB,UAAU,QACT,KAA4B,SAAS,UACtC,OAAQ,KAA4B,SAAS,SAE7C,QAAQ,KAA0B;AAEpC,SAAO;GACP,CACD,QAAQ,SAAS,KAAK,SAAS,EAAE,CACjC,KAAK,KAAK;;AAiCf,SAAgB,uBAAuB,EACrC,SACA,eACA,aACA,kBACA,kBACA,wBACA,iBACA,SACA,YACA,YACA,kBACA,UACA,WACA,GAAG,SAC2B;CAC9B,MAAM,4CACE,0BAA0B,QAAQ,QAAQ,EAChD,CAAC,QAAQ,QAAQ,CAClB;CAED,MAAM,uBAAuBA,yBAC3B,iBACA,uBAAuB,iBACvB,EACE,SAAS,kBACV,CACF;CAED,MAAM,kBAAkBA,yBACtB,YACA,uBAAuB,YACvB,EACE,SAAS,YAAY;AACnB,MAAI,iBACF,KAAI;AACF,SAAM,UAAU,UAAU,UAAU,iBAAiB;WAC9C,KAAK;AACZ,WAAQ,MAAM,2BAA2B,IAAI;;IAIpD,CACF;CAED,MAAM,kBAAkBA,yBACtB,YACA,uBAAuB,YACvB,EACE,eAAe,gBAAgB,EAAE,SAAS,CAAC,EAC5C,CACF;CAED,MAAM,wBAAwBA,yBAC5B,kBACA,uBAAuB,kBACvB;EACE,eAAe;EACf;EACA;EACA;EACD,CACF;CAED,MAAM,uBACJ,oBAAoB,mBAAmB,KAAK;CAE9C,MAAM,eAAeA,yBAAW,SAAS,uBAAuB,SAAS,EACvE,UACE,4CAAC;EAAI,WAAU;;GACZ;GACA;GACA,iBAAiB;GACjB,wBAAwB;;GACrB,EAET,CAAC;AAEF,KAAI,SACF,QACE,2CAAC;EAAI;EAAgB,OAAO,EAAE,SAAS,YAAY;YAChD,SAAS;GACR,iBAAiB;GACjB,SAAS;GACT,YAAY;GACZ,YAAY;GACZ,kBAAkB;GAClB;GACA;GACA;GACA;GACD,CAAC;GACE;AAIV,QACE,4CAAC;EACC;EACA,eAAY;EACZ,uCACE,2DACA,UACD;EACD,mBAAiB,QAAQ;EACzB,GAAI;aAEH,sBACA;GACG;;;sCAQH,EAAE,UAAU,WAAW,GAAG,YAC7B,2CAAC;EACC,uCACE,iDACA,UACD;EACD,GAAI;EAEH;GACG;4CAMF,EAAE,SAAS,gBACf,2CAAC;EACC,uCACE,uLACA,UACD;YAEA;GACG;oCAGgE,EACtE,WACA,GAAG,YAEH,2CAAC;EACC,eAAY;EACZ,uCACE,4IACA,UACD;EACD,GAAI;GACJ;CAGG,MAAM,yDAKR,EAAE,OAAO,UAAU,WAAW,GAAG,YAAY;AAChD,SACE,4CAACC,sCACC,2CAACC;GAAe;aACd,2CAACC;IACC,MAAK;IACL,SAAQ;IACR,cAAY;IACZ,uCAAmB,UAAU;IAC7B,GAAI;IAEH;KACM;IACM,EACjB,2CAACC;GAAe,MAAK;aACnB,2CAAC,iBAAG,QAAU;IACC,IACT;;uCAMT,EAAE,WAAW,OAAO,SAAS,GAAG,YAAY;EAE/C,MAAM,SADSC,sEAA6B,EACrB,UAAUC;EACjC,MAAM,CAAC,QAAQ,iCAAsB,MAAM;EAE3C,MAAM,eAAe,UAA+C;AAClE,aAAU,KAAK;AACf,oBAAiB,UAAU,MAAM,EAAE,IAAK;AAExC,OAAI,QACF,SAAQ,MAAM;;AAIlB,SACE,2CAAC;GACC,eAAY;GACZ,OAAO,SAAS,OAAO;GACvB,SAAS;GACE;GACX,GAAI;aAEH,SACC,2CAACC,sBAAM,WAAU,oBAAoB,GAErC,2CAACC,qBAAK,WAAU,oBAAoB;IAExB;;uCAMf,EAAE,WAAW,OAAO,GAAG,YAAY;EAEtC,MAAM,SADSH,sEAA6B,EACrB,UAAUC;AACjC,SACE,2CAAC;GACC,eAAY;GACZ,OAAO,SAAS,OAAO;GACZ;GACX,GAAI;aAEJ,2CAACG,qBAAK,WAAU,oBAAoB;IACtB;;6CAaf,EACH,WACA,gBAAgB,GAChB,mBAAmB,GACnB,kBACA,SACA,GAAG,YACC;AACJ,MAAI,CAAC,oBAAoB,oBAAoB,KAAK,CAAC,iBACjD,QAAO;EAGT,MAAM,YAAY,gBAAgB;EAClC,MAAM,YAAY,gBAAgB,mBAAmB;AAErD,SACE,4CAAC;GACC,eAAY;GACZ,uCAAmB,uCAAuC,UAAU;GACpE,GAAI;;IAEJ,2CAACN;KACC,MAAK;KACL,SAAQ;KACR,eACE,mBAAmB;MACjB,aAAa,gBAAgB;MAC7B;MACA;MACD,CAAC;KAEJ,UAAU,CAAC;KACX,WAAU;eAEV,2CAACO,4BAAY,WAAU,oBAAoB;MACpC;IACT,4CAAC;KAAK,WAAU;;MACb,gBAAgB;MAAE;MAAE;;MAChB;IACP,2CAACP;KACC,MAAK;KACL,SAAQ;KACR,eACE,mBAAmB;MACjB,aAAa,gBAAgB;MAC7B;MACA;MACD,CAAC;KAEJ,UAAU,CAAC;KACX,WAAU;eAEV,2CAACQ,6BAAa,WAAU,oBAAoB;MACrC;;IACL;;;AAKZ,uBAAuB,UAAU,cAC/B;AACF,uBAAuB,gBAAgB,cACrC;AACF,uBAAuB,QAAQ,cAAc;AAC7C,uBAAuB,cAAc,cACnC;AACF,uBAAuB,WAAW,cAChC;AACF,uBAAuB,WAAW,cAChC;AACF,uBAAuB,iBAAiB,cACtC;AAEF,qCAAe"}
|
|
1
|
+
{"version":3,"file":"CopilotChatUserMessage.cjs","names":["renderSlot","Tooltip","TooltipTrigger","Button","TooltipContent","useCopilotChatConfiguration","CopilotChatDefaultLabels","Check","Copy","Edit","ChevronLeft","ChevronRight"],"sources":["../../../src/components/chat/CopilotChatUserMessage.tsx"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport { Copy, Check, Edit, ChevronLeft, ChevronRight } from \"lucide-react\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { twMerge } from \"tailwind-merge\";\nimport { Button } from \"@/components/ui/button\";\nimport { UserMessage } from \"@ag-ui/core\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@/components/ui/tooltip\";\nimport { renderSlot, WithSlots } from \"@/lib/slots\";\n\nfunction flattenUserMessageContent(content?: UserMessage[\"content\"]): string {\n if (!content) {\n return \"\";\n }\n\n if (typeof content === \"string\") {\n return content;\n }\n\n return content\n .map((part) => {\n if (\n part &&\n typeof part === \"object\" &&\n \"type\" in part &&\n (part as { type?: unknown }).type === \"text\" &&\n typeof (part as { text?: unknown }).text === \"string\"\n ) {\n return (part as { text: string }).text;\n }\n return \"\";\n })\n .filter((text) => text.length > 0)\n .join(\"\\n\");\n}\n\nexport interface CopilotChatUserMessageOnEditMessageProps {\n message: UserMessage;\n}\n\nexport interface CopilotChatUserMessageOnSwitchToBranchProps {\n message: UserMessage;\n branchIndex: number;\n numberOfBranches: number;\n}\n\nexport type CopilotChatUserMessageProps = WithSlots<\n {\n messageRenderer: typeof CopilotChatUserMessage.MessageRenderer;\n toolbar: typeof CopilotChatUserMessage.Toolbar;\n copyButton: typeof CopilotChatUserMessage.CopyButton;\n editButton: typeof CopilotChatUserMessage.EditButton;\n branchNavigation: typeof CopilotChatUserMessage.BranchNavigation;\n },\n {\n onEditMessage?: (props: CopilotChatUserMessageOnEditMessageProps) => void;\n onSwitchToBranch?: (\n props: CopilotChatUserMessageOnSwitchToBranchProps,\n ) => void;\n message: UserMessage;\n branchIndex?: number;\n numberOfBranches?: number;\n additionalToolbarItems?: React.ReactNode;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport function CopilotChatUserMessage({\n message,\n onEditMessage,\n branchIndex,\n numberOfBranches,\n onSwitchToBranch,\n additionalToolbarItems,\n messageRenderer,\n toolbar,\n copyButton,\n editButton,\n branchNavigation,\n children,\n className,\n ...props\n}: CopilotChatUserMessageProps) {\n const flattenedContent = useMemo(\n () => flattenUserMessageContent(message.content),\n [message.content],\n );\n\n const BoundMessageRenderer = renderSlot(\n messageRenderer,\n CopilotChatUserMessage.MessageRenderer,\n {\n content: flattenedContent,\n },\n );\n\n const BoundCopyButton = renderSlot(\n copyButton,\n CopilotChatUserMessage.CopyButton,\n {\n onClick: async () => {\n if (flattenedContent) {\n try {\n await navigator.clipboard.writeText(flattenedContent);\n } catch (err) {\n console.error(\"Failed to copy message:\", err);\n }\n }\n },\n },\n );\n\n const BoundEditButton = renderSlot(\n editButton,\n CopilotChatUserMessage.EditButton,\n {\n onClick: () => onEditMessage?.({ message }),\n },\n );\n\n const BoundBranchNavigation = renderSlot(\n branchNavigation,\n CopilotChatUserMessage.BranchNavigation,\n {\n currentBranch: branchIndex,\n numberOfBranches,\n onSwitchToBranch,\n message,\n },\n );\n\n const showBranchNavigation =\n numberOfBranches && numberOfBranches > 1 && onSwitchToBranch;\n\n const BoundToolbar = renderSlot(toolbar, CopilotChatUserMessage.Toolbar, {\n children: (\n <div className=\"cpk:flex cpk:items-center cpk:gap-1 cpk:justify-end\">\n {additionalToolbarItems}\n {BoundCopyButton}\n {onEditMessage && BoundEditButton}\n {showBranchNavigation && BoundBranchNavigation}\n </div>\n ),\n });\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n messageRenderer: BoundMessageRenderer,\n toolbar: BoundToolbar,\n copyButton: BoundCopyButton,\n editButton: BoundEditButton,\n branchNavigation: BoundBranchNavigation,\n message,\n branchIndex,\n numberOfBranches,\n additionalToolbarItems,\n })}\n </div>\n );\n }\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-user-message\"\n className={twMerge(\n \"copilotKitMessage copilotKitUserMessage cpk:flex cpk:flex-col cpk:items-end cpk:group cpk:pt-10\",\n className,\n )}\n data-message-id={message.id}\n {...props}\n >\n {BoundMessageRenderer}\n {BoundToolbar}\n </div>\n );\n}\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace CopilotChatUserMessage {\n export const Container: React.FC<\n React.PropsWithChildren<React.HTMLAttributes<HTMLDivElement>>\n > = ({ children, className, ...props }) => (\n <div\n className={twMerge(\n \"cpk:flex cpk:flex-col cpk:items-end cpk:group\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n\n export const MessageRenderer: React.FC<{\n content: string;\n className?: string;\n }> = ({ content, className }) => (\n <div\n className={twMerge(\n \"cpk:prose cpk:dark:prose-invert cpk:bg-muted cpk:relative cpk:max-w-[80%] cpk:rounded-[18px] cpk:px-4 cpk:py-1.5 cpk:data-[multiline]:py-3 cpk:inline-block cpk:whitespace-pre-wrap\",\n className,\n )}\n >\n {content}\n </div>\n );\n\n export const Toolbar: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n ...props\n }) => (\n <div\n data-testid=\"copilot-user-toolbar\"\n className={twMerge(\n \"cpk:w-full cpk:bg-transparent cpk:flex cpk:items-center cpk:justify-end cpk:-mr-[5px] cpk:mt-[4px] cpk:invisible cpk:group-hover:visible\",\n className,\n )}\n {...props}\n />\n );\n\n export const ToolbarButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement> & {\n title: string;\n children: React.ReactNode;\n }\n > = ({ title, children, className, ...props }) => {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n type=\"button\"\n variant=\"assistantMessageToolbarButton\"\n aria-label={title}\n className={twMerge(className)}\n {...props}\n >\n {children}\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">\n <p>{title}</p>\n </TooltipContent>\n </Tooltip>\n );\n };\n\n export const CopyButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement> & { copied?: boolean }\n > = ({ className, title, onClick, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n const [copied, setCopied] = useState(false);\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n\n if (onClick) {\n onClick(event);\n }\n };\n\n return (\n <ToolbarButton\n data-testid=\"copilot-user-copy-button\"\n title={title || labels.userMessageToolbarCopyMessageLabel}\n onClick={handleClick}\n className={className}\n {...props}\n >\n {copied ? (\n <Check className=\"cpk:size-[18px]\" />\n ) : (\n <Copy className=\"cpk:size-[18px]\" />\n )}\n </ToolbarButton>\n );\n };\n\n export const EditButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, title, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n return (\n <ToolbarButton\n data-testid=\"copilot-edit-button\"\n title={title || labels.userMessageToolbarEditMessageLabel}\n className={className}\n {...props}\n >\n <Edit className=\"cpk:size-[18px]\" />\n </ToolbarButton>\n );\n };\n\n export const BranchNavigation: React.FC<\n React.HTMLAttributes<HTMLDivElement> & {\n currentBranch?: number;\n numberOfBranches?: number;\n onSwitchToBranch?: (\n props: CopilotChatUserMessageOnSwitchToBranchProps,\n ) => void;\n message: UserMessage;\n }\n > = ({\n className,\n currentBranch = 0,\n numberOfBranches = 1,\n onSwitchToBranch,\n message,\n ...props\n }) => {\n if (!numberOfBranches || numberOfBranches <= 1 || !onSwitchToBranch) {\n return null;\n }\n\n const canGoPrev = currentBranch > 0;\n const canGoNext = currentBranch < numberOfBranches - 1;\n\n return (\n <div\n data-testid=\"copilot-branch-navigation\"\n className={twMerge(\"cpk:flex cpk:items-center cpk:gap-1\", className)}\n {...props}\n >\n <Button\n type=\"button\"\n variant=\"assistantMessageToolbarButton\"\n onClick={() =>\n onSwitchToBranch?.({\n branchIndex: currentBranch - 1,\n numberOfBranches,\n message,\n })\n }\n disabled={!canGoPrev}\n className=\"cpk:h-6 cpk:w-6 cpk:p-0\"\n >\n <ChevronLeft className=\"cpk:size-[20px]\" />\n </Button>\n <span className=\"cpk:text-sm cpk:text-muted-foreground cpk:px-0 cpk:font-medium\">\n {currentBranch + 1}/{numberOfBranches}\n </span>\n <Button\n type=\"button\"\n variant=\"assistantMessageToolbarButton\"\n onClick={() =>\n onSwitchToBranch?.({\n branchIndex: currentBranch + 1,\n numberOfBranches,\n message,\n })\n }\n disabled={!canGoNext}\n className=\"cpk:h-6 cpk:w-6 cpk:p-0\"\n >\n <ChevronRight className=\"cpk:size-[20px]\" />\n </Button>\n </div>\n );\n };\n}\n\nCopilotChatUserMessage.Container.displayName =\n \"CopilotChatUserMessage.Container\";\nCopilotChatUserMessage.MessageRenderer.displayName =\n \"CopilotChatUserMessage.MessageRenderer\";\nCopilotChatUserMessage.Toolbar.displayName = \"CopilotChatUserMessage.Toolbar\";\nCopilotChatUserMessage.ToolbarButton.displayName =\n \"CopilotChatUserMessage.ToolbarButton\";\nCopilotChatUserMessage.CopyButton.displayName =\n \"CopilotChatUserMessage.CopyButton\";\nCopilotChatUserMessage.EditButton.displayName =\n \"CopilotChatUserMessage.EditButton\";\nCopilotChatUserMessage.BranchNavigation.displayName =\n \"CopilotChatUserMessage.BranchNavigation\";\n\nexport default CopilotChatUserMessage;\n"],"mappings":"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"}
|
|
@@ -61,7 +61,7 @@ function CopilotChatUserMessage({ message, onEditMessage, branchIndex, numberOfB
|
|
|
61
61
|
return /* @__PURE__ */ jsxs("div", {
|
|
62
62
|
"data-copilotkit": true,
|
|
63
63
|
"data-testid": "copilot-user-message",
|
|
64
|
-
className: twMerge("cpk:flex cpk:flex-col cpk:items-end cpk:group cpk:pt-10", className),
|
|
64
|
+
className: twMerge("copilotKitMessage copilotKitUserMessage cpk:flex cpk:flex-col cpk:items-end cpk:group cpk:pt-10", className),
|
|
65
65
|
"data-message-id": message.id,
|
|
66
66
|
...props,
|
|
67
67
|
children: [BoundMessageRenderer, BoundToolbar]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotChatUserMessage.mjs","names":[],"sources":["../../../src/components/chat/CopilotChatUserMessage.tsx"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport { Copy, Check, Edit, ChevronLeft, ChevronRight } from \"lucide-react\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { twMerge } from \"tailwind-merge\";\nimport { Button } from \"@/components/ui/button\";\nimport { UserMessage } from \"@ag-ui/core\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@/components/ui/tooltip\";\nimport { renderSlot, WithSlots } from \"@/lib/slots\";\n\nfunction flattenUserMessageContent(content?: UserMessage[\"content\"]): string {\n if (!content) {\n return \"\";\n }\n\n if (typeof content === \"string\") {\n return content;\n }\n\n return content\n .map((part) => {\n if (\n part &&\n typeof part === \"object\" &&\n \"type\" in part &&\n (part as { type?: unknown }).type === \"text\" &&\n typeof (part as { text?: unknown }).text === \"string\"\n ) {\n return (part as { text: string }).text;\n }\n return \"\";\n })\n .filter((text) => text.length > 0)\n .join(\"\\n\");\n}\n\nexport interface CopilotChatUserMessageOnEditMessageProps {\n message: UserMessage;\n}\n\nexport interface CopilotChatUserMessageOnSwitchToBranchProps {\n message: UserMessage;\n branchIndex: number;\n numberOfBranches: number;\n}\n\nexport type CopilotChatUserMessageProps = WithSlots<\n {\n messageRenderer: typeof CopilotChatUserMessage.MessageRenderer;\n toolbar: typeof CopilotChatUserMessage.Toolbar;\n copyButton: typeof CopilotChatUserMessage.CopyButton;\n editButton: typeof CopilotChatUserMessage.EditButton;\n branchNavigation: typeof CopilotChatUserMessage.BranchNavigation;\n },\n {\n onEditMessage?: (props: CopilotChatUserMessageOnEditMessageProps) => void;\n onSwitchToBranch?: (\n props: CopilotChatUserMessageOnSwitchToBranchProps,\n ) => void;\n message: UserMessage;\n branchIndex?: number;\n numberOfBranches?: number;\n additionalToolbarItems?: React.ReactNode;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport function CopilotChatUserMessage({\n message,\n onEditMessage,\n branchIndex,\n numberOfBranches,\n onSwitchToBranch,\n additionalToolbarItems,\n messageRenderer,\n toolbar,\n copyButton,\n editButton,\n branchNavigation,\n children,\n className,\n ...props\n}: CopilotChatUserMessageProps) {\n const flattenedContent = useMemo(\n () => flattenUserMessageContent(message.content),\n [message.content],\n );\n\n const BoundMessageRenderer = renderSlot(\n messageRenderer,\n CopilotChatUserMessage.MessageRenderer,\n {\n content: flattenedContent,\n },\n );\n\n const BoundCopyButton = renderSlot(\n copyButton,\n CopilotChatUserMessage.CopyButton,\n {\n onClick: async () => {\n if (flattenedContent) {\n try {\n await navigator.clipboard.writeText(flattenedContent);\n } catch (err) {\n console.error(\"Failed to copy message:\", err);\n }\n }\n },\n },\n );\n\n const BoundEditButton = renderSlot(\n editButton,\n CopilotChatUserMessage.EditButton,\n {\n onClick: () => onEditMessage?.({ message }),\n },\n );\n\n const BoundBranchNavigation = renderSlot(\n branchNavigation,\n CopilotChatUserMessage.BranchNavigation,\n {\n currentBranch: branchIndex,\n numberOfBranches,\n onSwitchToBranch,\n message,\n },\n );\n\n const showBranchNavigation =\n numberOfBranches && numberOfBranches > 1 && onSwitchToBranch;\n\n const BoundToolbar = renderSlot(toolbar, CopilotChatUserMessage.Toolbar, {\n children: (\n <div className=\"cpk:flex cpk:items-center cpk:gap-1 cpk:justify-end\">\n {additionalToolbarItems}\n {BoundCopyButton}\n {onEditMessage && BoundEditButton}\n {showBranchNavigation && BoundBranchNavigation}\n </div>\n ),\n });\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n messageRenderer: BoundMessageRenderer,\n toolbar: BoundToolbar,\n copyButton: BoundCopyButton,\n editButton: BoundEditButton,\n branchNavigation: BoundBranchNavigation,\n message,\n branchIndex,\n numberOfBranches,\n additionalToolbarItems,\n })}\n </div>\n );\n }\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-user-message\"\n className={twMerge(\n \"cpk:flex cpk:flex-col cpk:items-end cpk:group cpk:pt-10\",\n className,\n )}\n data-message-id={message.id}\n {...props}\n >\n {BoundMessageRenderer}\n {BoundToolbar}\n </div>\n );\n}\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace CopilotChatUserMessage {\n export const Container: React.FC<\n React.PropsWithChildren<React.HTMLAttributes<HTMLDivElement>>\n > = ({ children, className, ...props }) => (\n <div\n className={twMerge(\n \"cpk:flex cpk:flex-col cpk:items-end cpk:group\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n\n export const MessageRenderer: React.FC<{\n content: string;\n className?: string;\n }> = ({ content, className }) => (\n <div\n className={twMerge(\n \"cpk:prose cpk:dark:prose-invert cpk:bg-muted cpk:relative cpk:max-w-[80%] cpk:rounded-[18px] cpk:px-4 cpk:py-1.5 cpk:data-[multiline]:py-3 cpk:inline-block cpk:whitespace-pre-wrap\",\n className,\n )}\n >\n {content}\n </div>\n );\n\n export const Toolbar: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n ...props\n }) => (\n <div\n data-testid=\"copilot-user-toolbar\"\n className={twMerge(\n \"cpk:w-full cpk:bg-transparent cpk:flex cpk:items-center cpk:justify-end cpk:-mr-[5px] cpk:mt-[4px] cpk:invisible cpk:group-hover:visible\",\n className,\n )}\n {...props}\n />\n );\n\n export const ToolbarButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement> & {\n title: string;\n children: React.ReactNode;\n }\n > = ({ title, children, className, ...props }) => {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n type=\"button\"\n variant=\"assistantMessageToolbarButton\"\n aria-label={title}\n className={twMerge(className)}\n {...props}\n >\n {children}\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">\n <p>{title}</p>\n </TooltipContent>\n </Tooltip>\n );\n };\n\n export const CopyButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement> & { copied?: boolean }\n > = ({ className, title, onClick, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n const [copied, setCopied] = useState(false);\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n\n if (onClick) {\n onClick(event);\n }\n };\n\n return (\n <ToolbarButton\n data-testid=\"copilot-user-copy-button\"\n title={title || labels.userMessageToolbarCopyMessageLabel}\n onClick={handleClick}\n className={className}\n {...props}\n >\n {copied ? (\n <Check className=\"cpk:size-[18px]\" />\n ) : (\n <Copy className=\"cpk:size-[18px]\" />\n )}\n </ToolbarButton>\n );\n };\n\n export const EditButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, title, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n return (\n <ToolbarButton\n data-testid=\"copilot-edit-button\"\n title={title || labels.userMessageToolbarEditMessageLabel}\n className={className}\n {...props}\n >\n <Edit className=\"cpk:size-[18px]\" />\n </ToolbarButton>\n );\n };\n\n export const BranchNavigation: React.FC<\n React.HTMLAttributes<HTMLDivElement> & {\n currentBranch?: number;\n numberOfBranches?: number;\n onSwitchToBranch?: (\n props: CopilotChatUserMessageOnSwitchToBranchProps,\n ) => void;\n message: UserMessage;\n }\n > = ({\n className,\n currentBranch = 0,\n numberOfBranches = 1,\n onSwitchToBranch,\n message,\n ...props\n }) => {\n if (!numberOfBranches || numberOfBranches <= 1 || !onSwitchToBranch) {\n return null;\n }\n\n const canGoPrev = currentBranch > 0;\n const canGoNext = currentBranch < numberOfBranches - 1;\n\n return (\n <div\n data-testid=\"copilot-branch-navigation\"\n className={twMerge(\"cpk:flex cpk:items-center cpk:gap-1\", className)}\n {...props}\n >\n <Button\n type=\"button\"\n variant=\"assistantMessageToolbarButton\"\n onClick={() =>\n onSwitchToBranch?.({\n branchIndex: currentBranch - 1,\n numberOfBranches,\n message,\n })\n }\n disabled={!canGoPrev}\n className=\"cpk:h-6 cpk:w-6 cpk:p-0\"\n >\n <ChevronLeft className=\"cpk:size-[20px]\" />\n </Button>\n <span className=\"cpk:text-sm cpk:text-muted-foreground cpk:px-0 cpk:font-medium\">\n {currentBranch + 1}/{numberOfBranches}\n </span>\n <Button\n type=\"button\"\n variant=\"assistantMessageToolbarButton\"\n onClick={() =>\n onSwitchToBranch?.({\n branchIndex: currentBranch + 1,\n numberOfBranches,\n message,\n })\n }\n disabled={!canGoNext}\n className=\"cpk:h-6 cpk:w-6 cpk:p-0\"\n >\n <ChevronRight className=\"cpk:size-[20px]\" />\n </Button>\n </div>\n );\n };\n}\n\nCopilotChatUserMessage.Container.displayName =\n \"CopilotChatUserMessage.Container\";\nCopilotChatUserMessage.MessageRenderer.displayName =\n \"CopilotChatUserMessage.MessageRenderer\";\nCopilotChatUserMessage.Toolbar.displayName = \"CopilotChatUserMessage.Toolbar\";\nCopilotChatUserMessage.ToolbarButton.displayName =\n \"CopilotChatUserMessage.ToolbarButton\";\nCopilotChatUserMessage.CopyButton.displayName =\n \"CopilotChatUserMessage.CopyButton\";\nCopilotChatUserMessage.EditButton.displayName =\n \"CopilotChatUserMessage.EditButton\";\nCopilotChatUserMessage.BranchNavigation.displayName =\n \"CopilotChatUserMessage.BranchNavigation\";\n\nexport default CopilotChatUserMessage;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CopilotChatUserMessage.mjs","names":[],"sources":["../../../src/components/chat/CopilotChatUserMessage.tsx"],"sourcesContent":["import { useMemo, useState } from \"react\";\nimport { Copy, Check, Edit, ChevronLeft, ChevronRight } from \"lucide-react\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { twMerge } from \"tailwind-merge\";\nimport { Button } from \"@/components/ui/button\";\nimport { UserMessage } from \"@ag-ui/core\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@/components/ui/tooltip\";\nimport { renderSlot, WithSlots } from \"@/lib/slots\";\n\nfunction flattenUserMessageContent(content?: UserMessage[\"content\"]): string {\n if (!content) {\n return \"\";\n }\n\n if (typeof content === \"string\") {\n return content;\n }\n\n return content\n .map((part) => {\n if (\n part &&\n typeof part === \"object\" &&\n \"type\" in part &&\n (part as { type?: unknown }).type === \"text\" &&\n typeof (part as { text?: unknown }).text === \"string\"\n ) {\n return (part as { text: string }).text;\n }\n return \"\";\n })\n .filter((text) => text.length > 0)\n .join(\"\\n\");\n}\n\nexport interface CopilotChatUserMessageOnEditMessageProps {\n message: UserMessage;\n}\n\nexport interface CopilotChatUserMessageOnSwitchToBranchProps {\n message: UserMessage;\n branchIndex: number;\n numberOfBranches: number;\n}\n\nexport type CopilotChatUserMessageProps = WithSlots<\n {\n messageRenderer: typeof CopilotChatUserMessage.MessageRenderer;\n toolbar: typeof CopilotChatUserMessage.Toolbar;\n copyButton: typeof CopilotChatUserMessage.CopyButton;\n editButton: typeof CopilotChatUserMessage.EditButton;\n branchNavigation: typeof CopilotChatUserMessage.BranchNavigation;\n },\n {\n onEditMessage?: (props: CopilotChatUserMessageOnEditMessageProps) => void;\n onSwitchToBranch?: (\n props: CopilotChatUserMessageOnSwitchToBranchProps,\n ) => void;\n message: UserMessage;\n branchIndex?: number;\n numberOfBranches?: number;\n additionalToolbarItems?: React.ReactNode;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport function CopilotChatUserMessage({\n message,\n onEditMessage,\n branchIndex,\n numberOfBranches,\n onSwitchToBranch,\n additionalToolbarItems,\n messageRenderer,\n toolbar,\n copyButton,\n editButton,\n branchNavigation,\n children,\n className,\n ...props\n}: CopilotChatUserMessageProps) {\n const flattenedContent = useMemo(\n () => flattenUserMessageContent(message.content),\n [message.content],\n );\n\n const BoundMessageRenderer = renderSlot(\n messageRenderer,\n CopilotChatUserMessage.MessageRenderer,\n {\n content: flattenedContent,\n },\n );\n\n const BoundCopyButton = renderSlot(\n copyButton,\n CopilotChatUserMessage.CopyButton,\n {\n onClick: async () => {\n if (flattenedContent) {\n try {\n await navigator.clipboard.writeText(flattenedContent);\n } catch (err) {\n console.error(\"Failed to copy message:\", err);\n }\n }\n },\n },\n );\n\n const BoundEditButton = renderSlot(\n editButton,\n CopilotChatUserMessage.EditButton,\n {\n onClick: () => onEditMessage?.({ message }),\n },\n );\n\n const BoundBranchNavigation = renderSlot(\n branchNavigation,\n CopilotChatUserMessage.BranchNavigation,\n {\n currentBranch: branchIndex,\n numberOfBranches,\n onSwitchToBranch,\n message,\n },\n );\n\n const showBranchNavigation =\n numberOfBranches && numberOfBranches > 1 && onSwitchToBranch;\n\n const BoundToolbar = renderSlot(toolbar, CopilotChatUserMessage.Toolbar, {\n children: (\n <div className=\"cpk:flex cpk:items-center cpk:gap-1 cpk:justify-end\">\n {additionalToolbarItems}\n {BoundCopyButton}\n {onEditMessage && BoundEditButton}\n {showBranchNavigation && BoundBranchNavigation}\n </div>\n ),\n });\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n messageRenderer: BoundMessageRenderer,\n toolbar: BoundToolbar,\n copyButton: BoundCopyButton,\n editButton: BoundEditButton,\n branchNavigation: BoundBranchNavigation,\n message,\n branchIndex,\n numberOfBranches,\n additionalToolbarItems,\n })}\n </div>\n );\n }\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-user-message\"\n className={twMerge(\n \"copilotKitMessage copilotKitUserMessage cpk:flex cpk:flex-col cpk:items-end cpk:group cpk:pt-10\",\n className,\n )}\n data-message-id={message.id}\n {...props}\n >\n {BoundMessageRenderer}\n {BoundToolbar}\n </div>\n );\n}\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace CopilotChatUserMessage {\n export const Container: React.FC<\n React.PropsWithChildren<React.HTMLAttributes<HTMLDivElement>>\n > = ({ children, className, ...props }) => (\n <div\n className={twMerge(\n \"cpk:flex cpk:flex-col cpk:items-end cpk:group\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n\n export const MessageRenderer: React.FC<{\n content: string;\n className?: string;\n }> = ({ content, className }) => (\n <div\n className={twMerge(\n \"cpk:prose cpk:dark:prose-invert cpk:bg-muted cpk:relative cpk:max-w-[80%] cpk:rounded-[18px] cpk:px-4 cpk:py-1.5 cpk:data-[multiline]:py-3 cpk:inline-block cpk:whitespace-pre-wrap\",\n className,\n )}\n >\n {content}\n </div>\n );\n\n export const Toolbar: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n ...props\n }) => (\n <div\n data-testid=\"copilot-user-toolbar\"\n className={twMerge(\n \"cpk:w-full cpk:bg-transparent cpk:flex cpk:items-center cpk:justify-end cpk:-mr-[5px] cpk:mt-[4px] cpk:invisible cpk:group-hover:visible\",\n className,\n )}\n {...props}\n />\n );\n\n export const ToolbarButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement> & {\n title: string;\n children: React.ReactNode;\n }\n > = ({ title, children, className, ...props }) => {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n type=\"button\"\n variant=\"assistantMessageToolbarButton\"\n aria-label={title}\n className={twMerge(className)}\n {...props}\n >\n {children}\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">\n <p>{title}</p>\n </TooltipContent>\n </Tooltip>\n );\n };\n\n export const CopyButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement> & { copied?: boolean }\n > = ({ className, title, onClick, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n const [copied, setCopied] = useState(false);\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n\n if (onClick) {\n onClick(event);\n }\n };\n\n return (\n <ToolbarButton\n data-testid=\"copilot-user-copy-button\"\n title={title || labels.userMessageToolbarCopyMessageLabel}\n onClick={handleClick}\n className={className}\n {...props}\n >\n {copied ? (\n <Check className=\"cpk:size-[18px]\" />\n ) : (\n <Copy className=\"cpk:size-[18px]\" />\n )}\n </ToolbarButton>\n );\n };\n\n export const EditButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, title, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n return (\n <ToolbarButton\n data-testid=\"copilot-edit-button\"\n title={title || labels.userMessageToolbarEditMessageLabel}\n className={className}\n {...props}\n >\n <Edit className=\"cpk:size-[18px]\" />\n </ToolbarButton>\n );\n };\n\n export const BranchNavigation: React.FC<\n React.HTMLAttributes<HTMLDivElement> & {\n currentBranch?: number;\n numberOfBranches?: number;\n onSwitchToBranch?: (\n props: CopilotChatUserMessageOnSwitchToBranchProps,\n ) => void;\n message: UserMessage;\n }\n > = ({\n className,\n currentBranch = 0,\n numberOfBranches = 1,\n onSwitchToBranch,\n message,\n ...props\n }) => {\n if (!numberOfBranches || numberOfBranches <= 1 || !onSwitchToBranch) {\n return null;\n }\n\n const canGoPrev = currentBranch > 0;\n const canGoNext = currentBranch < numberOfBranches - 1;\n\n return (\n <div\n data-testid=\"copilot-branch-navigation\"\n className={twMerge(\"cpk:flex cpk:items-center cpk:gap-1\", className)}\n {...props}\n >\n <Button\n type=\"button\"\n variant=\"assistantMessageToolbarButton\"\n onClick={() =>\n onSwitchToBranch?.({\n branchIndex: currentBranch - 1,\n numberOfBranches,\n message,\n })\n }\n disabled={!canGoPrev}\n className=\"cpk:h-6 cpk:w-6 cpk:p-0\"\n >\n <ChevronLeft className=\"cpk:size-[20px]\" />\n </Button>\n <span className=\"cpk:text-sm cpk:text-muted-foreground cpk:px-0 cpk:font-medium\">\n {currentBranch + 1}/{numberOfBranches}\n </span>\n <Button\n type=\"button\"\n variant=\"assistantMessageToolbarButton\"\n onClick={() =>\n onSwitchToBranch?.({\n branchIndex: currentBranch + 1,\n numberOfBranches,\n message,\n })\n }\n disabled={!canGoNext}\n className=\"cpk:h-6 cpk:w-6 cpk:p-0\"\n >\n <ChevronRight className=\"cpk:size-[20px]\" />\n </Button>\n </div>\n );\n };\n}\n\nCopilotChatUserMessage.Container.displayName =\n \"CopilotChatUserMessage.Container\";\nCopilotChatUserMessage.MessageRenderer.displayName =\n \"CopilotChatUserMessage.MessageRenderer\";\nCopilotChatUserMessage.Toolbar.displayName = \"CopilotChatUserMessage.Toolbar\";\nCopilotChatUserMessage.ToolbarButton.displayName =\n \"CopilotChatUserMessage.ToolbarButton\";\nCopilotChatUserMessage.CopyButton.displayName =\n \"CopilotChatUserMessage.CopyButton\";\nCopilotChatUserMessage.EditButton.displayName =\n \"CopilotChatUserMessage.EditButton\";\nCopilotChatUserMessage.BranchNavigation.displayName =\n \"CopilotChatUserMessage.BranchNavigation\";\n\nexport default CopilotChatUserMessage;\n"],"mappings":"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"}
|
|
@@ -115,7 +115,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
115
115
|
"data-copilotkit": true,
|
|
116
116
|
"data-testid": "copilot-chat",
|
|
117
117
|
"data-copilot-running": isRunning ? "true" : "false",
|
|
118
|
-
className: (0, tailwind_merge.twMerge)("cpk:relative cpk:h-full cpk:flex cpk:flex-col", className),
|
|
118
|
+
className: (0, tailwind_merge.twMerge)("copilotKitChat cpk:relative cpk:h-full cpk:flex cpk:flex-col", className),
|
|
119
119
|
...props,
|
|
120
120
|
children: BoundWelcomeScreen
|
|
121
121
|
});
|
|
@@ -134,7 +134,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
134
134
|
"data-copilotkit": true,
|
|
135
135
|
"data-testid": "copilot-chat",
|
|
136
136
|
"data-copilot-running": isRunning ? "true" : "false",
|
|
137
|
-
className: (0, tailwind_merge.twMerge)("cpk:relative cpk:h-full", className),
|
|
137
|
+
className: (0, tailwind_merge.twMerge)("copilotKitChat cpk:relative cpk:h-full", className),
|
|
138
138
|
...props,
|
|
139
139
|
children: [BoundScrollView, BoundInput]
|
|
140
140
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotChatView.cjs","names":["useKeyboardHeight","renderSlot","CopilotChatMessageView","CopilotChatInput","CopilotChatSuggestionView","StickToBottom","cn","Button","ChevronDown","useCopilotChatConfiguration","CopilotChatDefaultLabels"],"sources":["../../../src/components/chat/CopilotChatView.tsx"],"sourcesContent":["import React, { useRef, useState, useEffect } from \"react\";\nimport { WithSlots, SlotValue, renderSlot } from \"@/lib/slots\";\nimport CopilotChatMessageView from \"./CopilotChatMessageView\";\nimport CopilotChatInput, {\n CopilotChatInputProps,\n CopilotChatInputMode,\n} from \"./CopilotChatInput\";\nimport CopilotChatSuggestionView, {\n CopilotChatSuggestionViewProps,\n} from \"./CopilotChatSuggestionView\";\nimport { Suggestion } from \"@copilotkitnext/core\";\nimport { Message } from \"@ag-ui/core\";\nimport { twMerge } from \"tailwind-merge\";\nimport {\n StickToBottom,\n useStickToBottom,\n useStickToBottomContext,\n} from \"use-stick-to-bottom\";\nimport { ChevronDown } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { useKeyboardHeight } from \"@/hooks/use-keyboard-height\";\n\n// Height of the feather gradient overlay (h-24 = 6rem = 96px)\nconst FEATHER_HEIGHT = 96;\n\n// Forward declaration for WelcomeScreen component type\nexport type WelcomeScreenProps = WithSlots<\n {\n welcomeMessage: React.FC<React.HTMLAttributes<HTMLDivElement>>;\n },\n {\n input: React.ReactElement;\n suggestionView: React.ReactElement;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport type CopilotChatViewProps = WithSlots<\n {\n messageView: typeof CopilotChatMessageView;\n scrollView: typeof CopilotChatView.ScrollView;\n input: typeof CopilotChatInput;\n suggestionView: typeof CopilotChatSuggestionView;\n },\n {\n messages?: Message[];\n autoScroll?: boolean;\n isRunning?: boolean;\n suggestions?: Suggestion[];\n suggestionLoadingIndexes?: ReadonlyArray<number>;\n onSelectSuggestion?: (suggestion: Suggestion, index: number) => void;\n welcomeScreen?: SlotValue<React.FC<WelcomeScreenProps>> | boolean;\n // Input behavior props\n onSubmitMessage?: (value: string) => void;\n onStop?: () => void;\n inputMode?: CopilotChatInputMode;\n inputValue?: string;\n onInputChange?: (value: string) => void;\n onStartTranscribe?: () => void;\n onCancelTranscribe?: () => void;\n onFinishTranscribe?: () => void;\n onFinishTranscribeWithAudio?: (audioBlob: Blob) => Promise<void>;\n /**\n * @deprecated Use the `input` slot's `disclaimer` prop instead:\n * ```tsx\n * <CopilotChat input={{ disclaimer: MyDisclaimer }} />\n * ```\n */\n disclaimer?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport function CopilotChatView({\n messageView,\n input,\n scrollView,\n suggestionView,\n welcomeScreen,\n messages = [],\n autoScroll = true,\n isRunning = false,\n suggestions,\n suggestionLoadingIndexes,\n onSelectSuggestion,\n // Input behavior props\n onSubmitMessage,\n onStop,\n inputMode,\n inputValue,\n onInputChange,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n // Deprecated — forwarded to input slot\n disclaimer,\n children,\n className,\n ...props\n}: CopilotChatViewProps) {\n const inputContainerRef = useRef<HTMLDivElement>(null);\n const [inputContainerHeight, setInputContainerHeight] = useState(0);\n const [isResizing, setIsResizing] = useState(false);\n const resizeTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n // Track keyboard state for mobile\n const { isKeyboardOpen, keyboardHeight, availableHeight } =\n useKeyboardHeight();\n\n // Track input container height changes\n useEffect(() => {\n const element = inputContainerRef.current;\n if (!element) return;\n\n const resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const newHeight = entry.contentRect.height;\n\n // Update height and set resizing state\n setInputContainerHeight((prevHeight) => {\n if (newHeight !== prevHeight) {\n setIsResizing(true);\n\n // Clear existing timeout\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n\n // Set isResizing to false after a short delay\n resizeTimeoutRef.current = setTimeout(() => {\n setIsResizing(false);\n }, 250);\n\n return newHeight;\n }\n return prevHeight;\n });\n }\n });\n\n resizeObserver.observe(element);\n\n // Set initial height\n setInputContainerHeight(element.offsetHeight);\n\n return () => {\n resizeObserver.disconnect();\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n };\n }, []);\n\n const BoundMessageView = renderSlot(messageView, CopilotChatMessageView, {\n messages,\n isRunning,\n });\n\n const BoundInput = renderSlot(input, CopilotChatInput, {\n onSubmitMessage,\n onStop,\n mode: inputMode,\n value: inputValue,\n onChange: onInputChange,\n isRunning,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n positioning: \"absolute\",\n keyboardHeight: isKeyboardOpen ? keyboardHeight : 0,\n containerRef: inputContainerRef,\n showDisclaimer: true,\n ...(disclaimer !== undefined ? { disclaimer } : {}),\n } as CopilotChatInputProps);\n\n const hasSuggestions = Array.isArray(suggestions) && suggestions.length > 0;\n const BoundSuggestionView = hasSuggestions\n ? renderSlot(suggestionView, CopilotChatSuggestionView, {\n suggestions,\n loadingIndexes: suggestionLoadingIndexes,\n onSelectSuggestion,\n className: \"cpk:mb-3 cpk:lg:ml-4 cpk:lg:mr-4 cpk:ml-0 cpk:mr-0\",\n })\n : null;\n\n const BoundScrollView = renderSlot(scrollView, CopilotChatView.ScrollView, {\n autoScroll,\n inputContainerHeight,\n isResizing,\n children: (\n <div\n style={{\n paddingBottom: `${inputContainerHeight + FEATHER_HEIGHT + (hasSuggestions ? 4 : 32)}px`,\n }}\n >\n <div className=\"cpk:max-w-3xl cpk:mx-auto\">\n {BoundMessageView}\n {hasSuggestions ? (\n <div className=\"cpk:pl-0 cpk:pr-4 cpk:sm:px-0 cpk:mt-4\">\n {BoundSuggestionView}\n </div>\n ) : null}\n </div>\n </div>\n ),\n });\n\n // Welcome screen logic\n const isEmpty = messages.length === 0;\n // Type assertion needed because TypeScript doesn't fully propagate `| boolean` through WithSlots\n const welcomeScreenDisabled = (welcomeScreen as unknown) === false;\n const shouldShowWelcomeScreen = isEmpty && !welcomeScreenDisabled;\n\n if (shouldShowWelcomeScreen) {\n // Create a separate input for welcome screen with static positioning and disclaimer visible\n const BoundInputForWelcome = renderSlot(input, CopilotChatInput, {\n onSubmitMessage,\n onStop,\n mode: inputMode,\n value: inputValue,\n onChange: onInputChange,\n isRunning,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n positioning: \"static\",\n showDisclaimer: true,\n ...(disclaimer !== undefined ? { disclaimer } : {}),\n } as CopilotChatInputProps);\n\n // Convert boolean `true` to undefined (use default), and exclude `false` since we've checked for it\n const welcomeScreenSlot = (\n welcomeScreen === true ? undefined : welcomeScreen\n ) as SlotValue<React.FC<WelcomeScreenProps>> | undefined;\n const BoundWelcomeScreen = renderSlot(\n welcomeScreenSlot,\n CopilotChatView.WelcomeScreen,\n {\n input: BoundInputForWelcome,\n suggestionView: BoundSuggestionView ?? <></>,\n },\n );\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-chat\"\n data-copilot-running={isRunning ? \"true\" : \"false\"}\n className={twMerge(\n \"cpk:relative cpk:h-full cpk:flex cpk:flex-col\",\n className,\n )}\n {...props}\n >\n {BoundWelcomeScreen}\n </div>\n );\n }\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n messageView: BoundMessageView,\n input: BoundInput,\n scrollView: BoundScrollView,\n suggestionView: BoundSuggestionView ?? <></>,\n })}\n </div>\n );\n }\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-chat\"\n data-copilot-running={isRunning ? \"true\" : \"false\"}\n className={twMerge(\"cpk:relative cpk:h-full\", className)}\n {...props}\n >\n {BoundScrollView}\n\n {BoundInput}\n </div>\n );\n}\n\nexport namespace CopilotChatView {\n // Inner component that has access to StickToBottom context\n const ScrollContent: React.FC<{\n children: React.ReactNode;\n scrollToBottomButton?: SlotValue<\n React.FC<React.ButtonHTMLAttributes<HTMLButtonElement>>\n >;\n feather?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n inputContainerHeight: number;\n isResizing: boolean;\n }> = ({\n children,\n scrollToBottomButton,\n feather,\n inputContainerHeight,\n isResizing,\n }) => {\n const { isAtBottom, scrollToBottom } = useStickToBottomContext();\n\n const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});\n\n return (\n <>\n <StickToBottom.Content\n className=\"cpk:overflow-y-scroll cpk:overflow-x-hidden\"\n style={{ flex: \"1 1 0%\", minHeight: 0 }}\n >\n <div className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\">\n {children}\n </div>\n </StickToBottom.Content>\n\n {/* Feather gradient overlay */}\n {BoundFeather}\n\n {/* Scroll to bottom button - hidden during resize */}\n {!isAtBottom && !isResizing && (\n <div\n className=\"cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none\"\n style={{\n bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px`,\n }}\n >\n {renderSlot(\n scrollToBottomButton,\n CopilotChatView.ScrollToBottomButton,\n {\n onClick: () => scrollToBottom(),\n },\n )}\n </div>\n )}\n </>\n );\n };\n\n export const ScrollView: React.FC<\n React.HTMLAttributes<HTMLDivElement> & {\n autoScroll?: boolean;\n scrollToBottomButton?: SlotValue<\n React.FC<React.ButtonHTMLAttributes<HTMLButtonElement>>\n >;\n feather?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n inputContainerHeight?: number;\n isResizing?: boolean;\n }\n > = ({\n children,\n autoScroll = true,\n scrollToBottomButton,\n feather,\n inputContainerHeight = 0,\n isResizing = false,\n className,\n ...props\n }) => {\n const [hasMounted, setHasMounted] = useState(false);\n const { scrollRef, contentRef, scrollToBottom } = useStickToBottom();\n const [showScrollButton, setShowScrollButton] = useState(false);\n\n useEffect(() => {\n setHasMounted(true);\n }, []);\n\n // Monitor scroll position for non-autoscroll mode\n useEffect(() => {\n if (autoScroll) return; // Skip for autoscroll mode\n\n const scrollElement = scrollRef.current;\n if (!scrollElement) return;\n\n const checkScroll = () => {\n const atBottom =\n scrollElement.scrollHeight -\n scrollElement.scrollTop -\n scrollElement.clientHeight <\n 10;\n setShowScrollButton(!atBottom);\n };\n\n checkScroll();\n scrollElement.addEventListener(\"scroll\", checkScroll);\n\n // Also check on resize\n const resizeObserver = new ResizeObserver(checkScroll);\n resizeObserver.observe(scrollElement);\n\n return () => {\n scrollElement.removeEventListener(\"scroll\", checkScroll);\n resizeObserver.disconnect();\n };\n }, [scrollRef, autoScroll]);\n\n if (!hasMounted) {\n return (\n <div className=\"cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:overflow-y-scroll cpk:overflow-x-hidden\">\n <div className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\">\n {children}\n </div>\n </div>\n );\n }\n\n // When autoScroll is false, we don't use StickToBottom\n if (!autoScroll) {\n const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});\n\n return (\n <div\n ref={scrollRef}\n className={cn(\n \"cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:overflow-y-scroll cpk:overflow-x-hidden cpk:relative\",\n className,\n )}\n {...props}\n >\n <div\n ref={contentRef}\n className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\"\n >\n {children}\n </div>\n\n {/* Feather gradient overlay */}\n {BoundFeather}\n\n {/* Scroll to bottom button for manual mode */}\n {showScrollButton && !isResizing && (\n <div\n className=\"cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none\"\n style={{\n bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px`,\n }}\n >\n {renderSlot(\n scrollToBottomButton,\n CopilotChatView.ScrollToBottomButton,\n {\n onClick: () => scrollToBottom(),\n },\n )}\n </div>\n )}\n </div>\n );\n }\n\n return (\n <StickToBottom\n className={cn(\n \"cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:relative\",\n className,\n )}\n resize=\"smooth\"\n initial=\"smooth\"\n {...props}\n >\n <ScrollContent\n scrollToBottomButton={scrollToBottomButton}\n feather={feather}\n inputContainerHeight={inputContainerHeight}\n isResizing={isResizing}\n >\n {children}\n </ScrollContent>\n </StickToBottom>\n );\n };\n\n export const ScrollToBottomButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, ...props }) => (\n <Button\n data-testid=\"copilot-scroll-to-bottom\"\n variant=\"outline\"\n size=\"sm\"\n className={twMerge(\n \"cpk:rounded-full cpk:w-10 cpk:h-10 cpk:p-0 cpk:pointer-events-auto\",\n \"cpk:bg-white cpk:dark:bg-gray-900\",\n \"cpk:shadow-lg cpk:border cpk:border-gray-200 cpk:dark:border-gray-700\",\n \"cpk:hover:bg-gray-50 cpk:dark:hover:bg-gray-800\",\n \"cpk:flex cpk:items-center cpk:justify-center cpk:cursor-pointer\",\n className,\n )}\n {...props}\n >\n <ChevronDown className=\"cpk:w-4 cpk:h-4 cpk:text-gray-600 cpk:dark:text-white\" />\n </Button>\n );\n\n export const Feather: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n style,\n ...props\n }) => (\n <div\n className={cn(\n \"cpk:absolute cpk:bottom-0 cpk:left-0 cpk:right-4 cpk:h-24 cpk:pointer-events-none cpk:z-10 cpk:bg-gradient-to-t\",\n \"cpk:from-white cpk:via-white cpk:to-transparent\",\n \"cpk:dark:from-[rgb(33,33,33)] cpk:dark:via-[rgb(33,33,33)]\",\n className,\n )}\n style={style}\n {...props}\n />\n );\n\n export const WelcomeMessage: React.FC<\n React.HTMLAttributes<HTMLDivElement>\n > = ({ className, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n\n return (\n <h1\n className={cn(\n \"cpk:text-xl cpk:sm:text-2xl cpk:font-medium cpk:text-foreground cpk:text-center\",\n className,\n )}\n {...props}\n >\n {labels.welcomeMessageText}\n </h1>\n );\n };\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 data-testid=\"copilot-welcome-screen\"\n className={cn(\n \"cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4\",\n className,\n )}\n {...props}\n >\n <div className=\"cpk:w-full cpk:max-w-3xl cpk:flex cpk:flex-col cpk:items-center\">\n {/* Welcome message */}\n <div className=\"cpk:mb-6\">{BoundWelcomeMessage}</div>\n\n {/* Input */}\n <div className=\"cpk:w-full\">{input}</div>\n\n {/* Suggestions */}\n <div className=\"cpk:mt-4 cpk:flex cpk:justify-center\">\n {suggestionView}\n </div>\n </div>\n </div>\n );\n };\n}\n\nexport default CopilotChatView;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CopilotChatView.cjs","names":["useKeyboardHeight","renderSlot","CopilotChatMessageView","CopilotChatInput","CopilotChatSuggestionView","StickToBottom","cn","Button","ChevronDown","useCopilotChatConfiguration","CopilotChatDefaultLabels"],"sources":["../../../src/components/chat/CopilotChatView.tsx"],"sourcesContent":["import React, { useRef, useState, useEffect } from \"react\";\nimport { WithSlots, SlotValue, renderSlot } from \"@/lib/slots\";\nimport CopilotChatMessageView from \"./CopilotChatMessageView\";\nimport CopilotChatInput, {\n CopilotChatInputProps,\n CopilotChatInputMode,\n} from \"./CopilotChatInput\";\nimport CopilotChatSuggestionView, {\n CopilotChatSuggestionViewProps,\n} from \"./CopilotChatSuggestionView\";\nimport { Suggestion } from \"@copilotkitnext/core\";\nimport { Message } from \"@ag-ui/core\";\nimport { twMerge } from \"tailwind-merge\";\nimport {\n StickToBottom,\n useStickToBottom,\n useStickToBottomContext,\n} from \"use-stick-to-bottom\";\nimport { ChevronDown } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { useKeyboardHeight } from \"@/hooks/use-keyboard-height\";\n\n// Height of the feather gradient overlay (h-24 = 6rem = 96px)\nconst FEATHER_HEIGHT = 96;\n\n// Forward declaration for WelcomeScreen component type\nexport type WelcomeScreenProps = WithSlots<\n {\n welcomeMessage: React.FC<React.HTMLAttributes<HTMLDivElement>>;\n },\n {\n input: React.ReactElement;\n suggestionView: React.ReactElement;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport type CopilotChatViewProps = WithSlots<\n {\n messageView: typeof CopilotChatMessageView;\n scrollView: typeof CopilotChatView.ScrollView;\n input: typeof CopilotChatInput;\n suggestionView: typeof CopilotChatSuggestionView;\n },\n {\n messages?: Message[];\n autoScroll?: boolean;\n isRunning?: boolean;\n suggestions?: Suggestion[];\n suggestionLoadingIndexes?: ReadonlyArray<number>;\n onSelectSuggestion?: (suggestion: Suggestion, index: number) => void;\n welcomeScreen?: SlotValue<React.FC<WelcomeScreenProps>> | boolean;\n // Input behavior props\n onSubmitMessage?: (value: string) => void;\n onStop?: () => void;\n inputMode?: CopilotChatInputMode;\n inputValue?: string;\n onInputChange?: (value: string) => void;\n onStartTranscribe?: () => void;\n onCancelTranscribe?: () => void;\n onFinishTranscribe?: () => void;\n onFinishTranscribeWithAudio?: (audioBlob: Blob) => Promise<void>;\n /**\n * @deprecated Use the `input` slot's `disclaimer` prop instead:\n * ```tsx\n * <CopilotChat input={{ disclaimer: MyDisclaimer }} />\n * ```\n */\n disclaimer?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport function CopilotChatView({\n messageView,\n input,\n scrollView,\n suggestionView,\n welcomeScreen,\n messages = [],\n autoScroll = true,\n isRunning = false,\n suggestions,\n suggestionLoadingIndexes,\n onSelectSuggestion,\n // Input behavior props\n onSubmitMessage,\n onStop,\n inputMode,\n inputValue,\n onInputChange,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n // Deprecated — forwarded to input slot\n disclaimer,\n children,\n className,\n ...props\n}: CopilotChatViewProps) {\n const inputContainerRef = useRef<HTMLDivElement>(null);\n const [inputContainerHeight, setInputContainerHeight] = useState(0);\n const [isResizing, setIsResizing] = useState(false);\n const resizeTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n // Track keyboard state for mobile\n const { isKeyboardOpen, keyboardHeight, availableHeight } =\n useKeyboardHeight();\n\n // Track input container height changes\n useEffect(() => {\n const element = inputContainerRef.current;\n if (!element) return;\n\n const resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const newHeight = entry.contentRect.height;\n\n // Update height and set resizing state\n setInputContainerHeight((prevHeight) => {\n if (newHeight !== prevHeight) {\n setIsResizing(true);\n\n // Clear existing timeout\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n\n // Set isResizing to false after a short delay\n resizeTimeoutRef.current = setTimeout(() => {\n setIsResizing(false);\n }, 250);\n\n return newHeight;\n }\n return prevHeight;\n });\n }\n });\n\n resizeObserver.observe(element);\n\n // Set initial height\n setInputContainerHeight(element.offsetHeight);\n\n return () => {\n resizeObserver.disconnect();\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n };\n }, []);\n\n const BoundMessageView = renderSlot(messageView, CopilotChatMessageView, {\n messages,\n isRunning,\n });\n\n const BoundInput = renderSlot(input, CopilotChatInput, {\n onSubmitMessage,\n onStop,\n mode: inputMode,\n value: inputValue,\n onChange: onInputChange,\n isRunning,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n positioning: \"absolute\",\n keyboardHeight: isKeyboardOpen ? keyboardHeight : 0,\n containerRef: inputContainerRef,\n showDisclaimer: true,\n ...(disclaimer !== undefined ? { disclaimer } : {}),\n } as CopilotChatInputProps);\n\n const hasSuggestions = Array.isArray(suggestions) && suggestions.length > 0;\n const BoundSuggestionView = hasSuggestions\n ? renderSlot(suggestionView, CopilotChatSuggestionView, {\n suggestions,\n loadingIndexes: suggestionLoadingIndexes,\n onSelectSuggestion,\n className: \"cpk:mb-3 cpk:lg:ml-4 cpk:lg:mr-4 cpk:ml-0 cpk:mr-0\",\n })\n : null;\n\n const BoundScrollView = renderSlot(scrollView, CopilotChatView.ScrollView, {\n autoScroll,\n inputContainerHeight,\n isResizing,\n children: (\n <div\n style={{\n paddingBottom: `${inputContainerHeight + FEATHER_HEIGHT + (hasSuggestions ? 4 : 32)}px`,\n }}\n >\n <div className=\"cpk:max-w-3xl cpk:mx-auto\">\n {BoundMessageView}\n {hasSuggestions ? (\n <div className=\"cpk:pl-0 cpk:pr-4 cpk:sm:px-0 cpk:mt-4\">\n {BoundSuggestionView}\n </div>\n ) : null}\n </div>\n </div>\n ),\n });\n\n // Welcome screen logic\n const isEmpty = messages.length === 0;\n // Type assertion needed because TypeScript doesn't fully propagate `| boolean` through WithSlots\n const welcomeScreenDisabled = (welcomeScreen as unknown) === false;\n const shouldShowWelcomeScreen = isEmpty && !welcomeScreenDisabled;\n\n if (shouldShowWelcomeScreen) {\n // Create a separate input for welcome screen with static positioning and disclaimer visible\n const BoundInputForWelcome = renderSlot(input, CopilotChatInput, {\n onSubmitMessage,\n onStop,\n mode: inputMode,\n value: inputValue,\n onChange: onInputChange,\n isRunning,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n positioning: \"static\",\n showDisclaimer: true,\n ...(disclaimer !== undefined ? { disclaimer } : {}),\n } as CopilotChatInputProps);\n\n // Convert boolean `true` to undefined (use default), and exclude `false` since we've checked for it\n const welcomeScreenSlot = (\n welcomeScreen === true ? undefined : welcomeScreen\n ) as SlotValue<React.FC<WelcomeScreenProps>> | undefined;\n const BoundWelcomeScreen = renderSlot(\n welcomeScreenSlot,\n CopilotChatView.WelcomeScreen,\n {\n input: BoundInputForWelcome,\n suggestionView: BoundSuggestionView ?? <></>,\n },\n );\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-chat\"\n data-copilot-running={isRunning ? \"true\" : \"false\"}\n className={twMerge(\n \"copilotKitChat cpk:relative cpk:h-full cpk:flex cpk:flex-col\",\n className,\n )}\n {...props}\n >\n {BoundWelcomeScreen}\n </div>\n );\n }\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n messageView: BoundMessageView,\n input: BoundInput,\n scrollView: BoundScrollView,\n suggestionView: BoundSuggestionView ?? <></>,\n })}\n </div>\n );\n }\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-chat\"\n data-copilot-running={isRunning ? \"true\" : \"false\"}\n className={twMerge(\"copilotKitChat cpk:relative cpk:h-full\", className)}\n {...props}\n >\n {BoundScrollView}\n\n {BoundInput}\n </div>\n );\n}\n\nexport namespace CopilotChatView {\n // Inner component that has access to StickToBottom context\n const ScrollContent: React.FC<{\n children: React.ReactNode;\n scrollToBottomButton?: SlotValue<\n React.FC<React.ButtonHTMLAttributes<HTMLButtonElement>>\n >;\n feather?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n inputContainerHeight: number;\n isResizing: boolean;\n }> = ({\n children,\n scrollToBottomButton,\n feather,\n inputContainerHeight,\n isResizing,\n }) => {\n const { isAtBottom, scrollToBottom } = useStickToBottomContext();\n\n const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});\n\n return (\n <>\n <StickToBottom.Content\n className=\"cpk:overflow-y-scroll cpk:overflow-x-hidden\"\n style={{ flex: \"1 1 0%\", minHeight: 0 }}\n >\n <div className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\">\n {children}\n </div>\n </StickToBottom.Content>\n\n {/* Feather gradient overlay */}\n {BoundFeather}\n\n {/* Scroll to bottom button - hidden during resize */}\n {!isAtBottom && !isResizing && (\n <div\n className=\"cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none\"\n style={{\n bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px`,\n }}\n >\n {renderSlot(\n scrollToBottomButton,\n CopilotChatView.ScrollToBottomButton,\n {\n onClick: () => scrollToBottom(),\n },\n )}\n </div>\n )}\n </>\n );\n };\n\n export const ScrollView: React.FC<\n React.HTMLAttributes<HTMLDivElement> & {\n autoScroll?: boolean;\n scrollToBottomButton?: SlotValue<\n React.FC<React.ButtonHTMLAttributes<HTMLButtonElement>>\n >;\n feather?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n inputContainerHeight?: number;\n isResizing?: boolean;\n }\n > = ({\n children,\n autoScroll = true,\n scrollToBottomButton,\n feather,\n inputContainerHeight = 0,\n isResizing = false,\n className,\n ...props\n }) => {\n const [hasMounted, setHasMounted] = useState(false);\n const { scrollRef, contentRef, scrollToBottom } = useStickToBottom();\n const [showScrollButton, setShowScrollButton] = useState(false);\n\n useEffect(() => {\n setHasMounted(true);\n }, []);\n\n // Monitor scroll position for non-autoscroll mode\n useEffect(() => {\n if (autoScroll) return; // Skip for autoscroll mode\n\n const scrollElement = scrollRef.current;\n if (!scrollElement) return;\n\n const checkScroll = () => {\n const atBottom =\n scrollElement.scrollHeight -\n scrollElement.scrollTop -\n scrollElement.clientHeight <\n 10;\n setShowScrollButton(!atBottom);\n };\n\n checkScroll();\n scrollElement.addEventListener(\"scroll\", checkScroll);\n\n // Also check on resize\n const resizeObserver = new ResizeObserver(checkScroll);\n resizeObserver.observe(scrollElement);\n\n return () => {\n scrollElement.removeEventListener(\"scroll\", checkScroll);\n resizeObserver.disconnect();\n };\n }, [scrollRef, autoScroll]);\n\n if (!hasMounted) {\n return (\n <div className=\"cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:overflow-y-scroll cpk:overflow-x-hidden\">\n <div className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\">\n {children}\n </div>\n </div>\n );\n }\n\n // When autoScroll is false, we don't use StickToBottom\n if (!autoScroll) {\n const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});\n\n return (\n <div\n ref={scrollRef}\n className={cn(\n \"cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:overflow-y-scroll cpk:overflow-x-hidden cpk:relative\",\n className,\n )}\n {...props}\n >\n <div\n ref={contentRef}\n className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\"\n >\n {children}\n </div>\n\n {/* Feather gradient overlay */}\n {BoundFeather}\n\n {/* Scroll to bottom button for manual mode */}\n {showScrollButton && !isResizing && (\n <div\n className=\"cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none\"\n style={{\n bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px`,\n }}\n >\n {renderSlot(\n scrollToBottomButton,\n CopilotChatView.ScrollToBottomButton,\n {\n onClick: () => scrollToBottom(),\n },\n )}\n </div>\n )}\n </div>\n );\n }\n\n return (\n <StickToBottom\n className={cn(\n \"cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:relative\",\n className,\n )}\n resize=\"smooth\"\n initial=\"smooth\"\n {...props}\n >\n <ScrollContent\n scrollToBottomButton={scrollToBottomButton}\n feather={feather}\n inputContainerHeight={inputContainerHeight}\n isResizing={isResizing}\n >\n {children}\n </ScrollContent>\n </StickToBottom>\n );\n };\n\n export const ScrollToBottomButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, ...props }) => (\n <Button\n data-testid=\"copilot-scroll-to-bottom\"\n variant=\"outline\"\n size=\"sm\"\n className={twMerge(\n \"cpk:rounded-full cpk:w-10 cpk:h-10 cpk:p-0 cpk:pointer-events-auto\",\n \"cpk:bg-white cpk:dark:bg-gray-900\",\n \"cpk:shadow-lg cpk:border cpk:border-gray-200 cpk:dark:border-gray-700\",\n \"cpk:hover:bg-gray-50 cpk:dark:hover:bg-gray-800\",\n \"cpk:flex cpk:items-center cpk:justify-center cpk:cursor-pointer\",\n className,\n )}\n {...props}\n >\n <ChevronDown className=\"cpk:w-4 cpk:h-4 cpk:text-gray-600 cpk:dark:text-white\" />\n </Button>\n );\n\n export const Feather: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n style,\n ...props\n }) => (\n <div\n className={cn(\n \"cpk:absolute cpk:bottom-0 cpk:left-0 cpk:right-4 cpk:h-24 cpk:pointer-events-none cpk:z-10 cpk:bg-gradient-to-t\",\n \"cpk:from-white cpk:via-white cpk:to-transparent\",\n \"cpk:dark:from-[rgb(33,33,33)] cpk:dark:via-[rgb(33,33,33)]\",\n className,\n )}\n style={style}\n {...props}\n />\n );\n\n export const WelcomeMessage: React.FC<\n React.HTMLAttributes<HTMLDivElement>\n > = ({ className, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n\n return (\n <h1\n className={cn(\n \"cpk:text-xl cpk:sm:text-2xl cpk:font-medium cpk:text-foreground cpk:text-center\",\n className,\n )}\n {...props}\n >\n {labels.welcomeMessageText}\n </h1>\n );\n };\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 data-testid=\"copilot-welcome-screen\"\n className={cn(\n \"cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4\",\n className,\n )}\n {...props}\n >\n <div className=\"cpk:w-full cpk:max-w-3xl cpk:flex cpk:flex-col cpk:items-center\">\n {/* Welcome message */}\n <div className=\"cpk:mb-6\">{BoundWelcomeMessage}</div>\n\n {/* Input */}\n <div className=\"cpk:w-full\">{input}</div>\n\n {/* Suggestions */}\n <div className=\"cpk:mt-4 cpk:flex cpk:justify-center\">\n {suggestionView}\n </div>\n </div>\n </div>\n );\n };\n}\n\nexport default CopilotChatView;\n"],"mappings":"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"}
|
|
@@ -113,7 +113,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
113
113
|
"data-copilotkit": true,
|
|
114
114
|
"data-testid": "copilot-chat",
|
|
115
115
|
"data-copilot-running": isRunning ? "true" : "false",
|
|
116
|
-
className: twMerge("cpk:relative cpk:h-full cpk:flex cpk:flex-col", className),
|
|
116
|
+
className: twMerge("copilotKitChat cpk:relative cpk:h-full cpk:flex cpk:flex-col", className),
|
|
117
117
|
...props,
|
|
118
118
|
children: BoundWelcomeScreen
|
|
119
119
|
});
|
|
@@ -132,7 +132,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
132
132
|
"data-copilotkit": true,
|
|
133
133
|
"data-testid": "copilot-chat",
|
|
134
134
|
"data-copilot-running": isRunning ? "true" : "false",
|
|
135
|
-
className: twMerge("cpk:relative cpk:h-full", className),
|
|
135
|
+
className: twMerge("copilotKitChat cpk:relative cpk:h-full", className),
|
|
136
136
|
...props,
|
|
137
137
|
children: [BoundScrollView, BoundInput]
|
|
138
138
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotChatView.mjs","names":["CopilotChatInput"],"sources":["../../../src/components/chat/CopilotChatView.tsx"],"sourcesContent":["import React, { useRef, useState, useEffect } from \"react\";\nimport { WithSlots, SlotValue, renderSlot } from \"@/lib/slots\";\nimport CopilotChatMessageView from \"./CopilotChatMessageView\";\nimport CopilotChatInput, {\n CopilotChatInputProps,\n CopilotChatInputMode,\n} from \"./CopilotChatInput\";\nimport CopilotChatSuggestionView, {\n CopilotChatSuggestionViewProps,\n} from \"./CopilotChatSuggestionView\";\nimport { Suggestion } from \"@copilotkitnext/core\";\nimport { Message } from \"@ag-ui/core\";\nimport { twMerge } from \"tailwind-merge\";\nimport {\n StickToBottom,\n useStickToBottom,\n useStickToBottomContext,\n} from \"use-stick-to-bottom\";\nimport { ChevronDown } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { useKeyboardHeight } from \"@/hooks/use-keyboard-height\";\n\n// Height of the feather gradient overlay (h-24 = 6rem = 96px)\nconst FEATHER_HEIGHT = 96;\n\n// Forward declaration for WelcomeScreen component type\nexport type WelcomeScreenProps = WithSlots<\n {\n welcomeMessage: React.FC<React.HTMLAttributes<HTMLDivElement>>;\n },\n {\n input: React.ReactElement;\n suggestionView: React.ReactElement;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport type CopilotChatViewProps = WithSlots<\n {\n messageView: typeof CopilotChatMessageView;\n scrollView: typeof CopilotChatView.ScrollView;\n input: typeof CopilotChatInput;\n suggestionView: typeof CopilotChatSuggestionView;\n },\n {\n messages?: Message[];\n autoScroll?: boolean;\n isRunning?: boolean;\n suggestions?: Suggestion[];\n suggestionLoadingIndexes?: ReadonlyArray<number>;\n onSelectSuggestion?: (suggestion: Suggestion, index: number) => void;\n welcomeScreen?: SlotValue<React.FC<WelcomeScreenProps>> | boolean;\n // Input behavior props\n onSubmitMessage?: (value: string) => void;\n onStop?: () => void;\n inputMode?: CopilotChatInputMode;\n inputValue?: string;\n onInputChange?: (value: string) => void;\n onStartTranscribe?: () => void;\n onCancelTranscribe?: () => void;\n onFinishTranscribe?: () => void;\n onFinishTranscribeWithAudio?: (audioBlob: Blob) => Promise<void>;\n /**\n * @deprecated Use the `input` slot's `disclaimer` prop instead:\n * ```tsx\n * <CopilotChat input={{ disclaimer: MyDisclaimer }} />\n * ```\n */\n disclaimer?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport function CopilotChatView({\n messageView,\n input,\n scrollView,\n suggestionView,\n welcomeScreen,\n messages = [],\n autoScroll = true,\n isRunning = false,\n suggestions,\n suggestionLoadingIndexes,\n onSelectSuggestion,\n // Input behavior props\n onSubmitMessage,\n onStop,\n inputMode,\n inputValue,\n onInputChange,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n // Deprecated — forwarded to input slot\n disclaimer,\n children,\n className,\n ...props\n}: CopilotChatViewProps) {\n const inputContainerRef = useRef<HTMLDivElement>(null);\n const [inputContainerHeight, setInputContainerHeight] = useState(0);\n const [isResizing, setIsResizing] = useState(false);\n const resizeTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n // Track keyboard state for mobile\n const { isKeyboardOpen, keyboardHeight, availableHeight } =\n useKeyboardHeight();\n\n // Track input container height changes\n useEffect(() => {\n const element = inputContainerRef.current;\n if (!element) return;\n\n const resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const newHeight = entry.contentRect.height;\n\n // Update height and set resizing state\n setInputContainerHeight((prevHeight) => {\n if (newHeight !== prevHeight) {\n setIsResizing(true);\n\n // Clear existing timeout\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n\n // Set isResizing to false after a short delay\n resizeTimeoutRef.current = setTimeout(() => {\n setIsResizing(false);\n }, 250);\n\n return newHeight;\n }\n return prevHeight;\n });\n }\n });\n\n resizeObserver.observe(element);\n\n // Set initial height\n setInputContainerHeight(element.offsetHeight);\n\n return () => {\n resizeObserver.disconnect();\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n };\n }, []);\n\n const BoundMessageView = renderSlot(messageView, CopilotChatMessageView, {\n messages,\n isRunning,\n });\n\n const BoundInput = renderSlot(input, CopilotChatInput, {\n onSubmitMessage,\n onStop,\n mode: inputMode,\n value: inputValue,\n onChange: onInputChange,\n isRunning,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n positioning: \"absolute\",\n keyboardHeight: isKeyboardOpen ? keyboardHeight : 0,\n containerRef: inputContainerRef,\n showDisclaimer: true,\n ...(disclaimer !== undefined ? { disclaimer } : {}),\n } as CopilotChatInputProps);\n\n const hasSuggestions = Array.isArray(suggestions) && suggestions.length > 0;\n const BoundSuggestionView = hasSuggestions\n ? renderSlot(suggestionView, CopilotChatSuggestionView, {\n suggestions,\n loadingIndexes: suggestionLoadingIndexes,\n onSelectSuggestion,\n className: \"cpk:mb-3 cpk:lg:ml-4 cpk:lg:mr-4 cpk:ml-0 cpk:mr-0\",\n })\n : null;\n\n const BoundScrollView = renderSlot(scrollView, CopilotChatView.ScrollView, {\n autoScroll,\n inputContainerHeight,\n isResizing,\n children: (\n <div\n style={{\n paddingBottom: `${inputContainerHeight + FEATHER_HEIGHT + (hasSuggestions ? 4 : 32)}px`,\n }}\n >\n <div className=\"cpk:max-w-3xl cpk:mx-auto\">\n {BoundMessageView}\n {hasSuggestions ? (\n <div className=\"cpk:pl-0 cpk:pr-4 cpk:sm:px-0 cpk:mt-4\">\n {BoundSuggestionView}\n </div>\n ) : null}\n </div>\n </div>\n ),\n });\n\n // Welcome screen logic\n const isEmpty = messages.length === 0;\n // Type assertion needed because TypeScript doesn't fully propagate `| boolean` through WithSlots\n const welcomeScreenDisabled = (welcomeScreen as unknown) === false;\n const shouldShowWelcomeScreen = isEmpty && !welcomeScreenDisabled;\n\n if (shouldShowWelcomeScreen) {\n // Create a separate input for welcome screen with static positioning and disclaimer visible\n const BoundInputForWelcome = renderSlot(input, CopilotChatInput, {\n onSubmitMessage,\n onStop,\n mode: inputMode,\n value: inputValue,\n onChange: onInputChange,\n isRunning,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n positioning: \"static\",\n showDisclaimer: true,\n ...(disclaimer !== undefined ? { disclaimer } : {}),\n } as CopilotChatInputProps);\n\n // Convert boolean `true` to undefined (use default), and exclude `false` since we've checked for it\n const welcomeScreenSlot = (\n welcomeScreen === true ? undefined : welcomeScreen\n ) as SlotValue<React.FC<WelcomeScreenProps>> | undefined;\n const BoundWelcomeScreen = renderSlot(\n welcomeScreenSlot,\n CopilotChatView.WelcomeScreen,\n {\n input: BoundInputForWelcome,\n suggestionView: BoundSuggestionView ?? <></>,\n },\n );\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-chat\"\n data-copilot-running={isRunning ? \"true\" : \"false\"}\n className={twMerge(\n \"cpk:relative cpk:h-full cpk:flex cpk:flex-col\",\n className,\n )}\n {...props}\n >\n {BoundWelcomeScreen}\n </div>\n );\n }\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n messageView: BoundMessageView,\n input: BoundInput,\n scrollView: BoundScrollView,\n suggestionView: BoundSuggestionView ?? <></>,\n })}\n </div>\n );\n }\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-chat\"\n data-copilot-running={isRunning ? \"true\" : \"false\"}\n className={twMerge(\"cpk:relative cpk:h-full\", className)}\n {...props}\n >\n {BoundScrollView}\n\n {BoundInput}\n </div>\n );\n}\n\nexport namespace CopilotChatView {\n // Inner component that has access to StickToBottom context\n const ScrollContent: React.FC<{\n children: React.ReactNode;\n scrollToBottomButton?: SlotValue<\n React.FC<React.ButtonHTMLAttributes<HTMLButtonElement>>\n >;\n feather?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n inputContainerHeight: number;\n isResizing: boolean;\n }> = ({\n children,\n scrollToBottomButton,\n feather,\n inputContainerHeight,\n isResizing,\n }) => {\n const { isAtBottom, scrollToBottom } = useStickToBottomContext();\n\n const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});\n\n return (\n <>\n <StickToBottom.Content\n className=\"cpk:overflow-y-scroll cpk:overflow-x-hidden\"\n style={{ flex: \"1 1 0%\", minHeight: 0 }}\n >\n <div className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\">\n {children}\n </div>\n </StickToBottom.Content>\n\n {/* Feather gradient overlay */}\n {BoundFeather}\n\n {/* Scroll to bottom button - hidden during resize */}\n {!isAtBottom && !isResizing && (\n <div\n className=\"cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none\"\n style={{\n bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px`,\n }}\n >\n {renderSlot(\n scrollToBottomButton,\n CopilotChatView.ScrollToBottomButton,\n {\n onClick: () => scrollToBottom(),\n },\n )}\n </div>\n )}\n </>\n );\n };\n\n export const ScrollView: React.FC<\n React.HTMLAttributes<HTMLDivElement> & {\n autoScroll?: boolean;\n scrollToBottomButton?: SlotValue<\n React.FC<React.ButtonHTMLAttributes<HTMLButtonElement>>\n >;\n feather?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n inputContainerHeight?: number;\n isResizing?: boolean;\n }\n > = ({\n children,\n autoScroll = true,\n scrollToBottomButton,\n feather,\n inputContainerHeight = 0,\n isResizing = false,\n className,\n ...props\n }) => {\n const [hasMounted, setHasMounted] = useState(false);\n const { scrollRef, contentRef, scrollToBottom } = useStickToBottom();\n const [showScrollButton, setShowScrollButton] = useState(false);\n\n useEffect(() => {\n setHasMounted(true);\n }, []);\n\n // Monitor scroll position for non-autoscroll mode\n useEffect(() => {\n if (autoScroll) return; // Skip for autoscroll mode\n\n const scrollElement = scrollRef.current;\n if (!scrollElement) return;\n\n const checkScroll = () => {\n const atBottom =\n scrollElement.scrollHeight -\n scrollElement.scrollTop -\n scrollElement.clientHeight <\n 10;\n setShowScrollButton(!atBottom);\n };\n\n checkScroll();\n scrollElement.addEventListener(\"scroll\", checkScroll);\n\n // Also check on resize\n const resizeObserver = new ResizeObserver(checkScroll);\n resizeObserver.observe(scrollElement);\n\n return () => {\n scrollElement.removeEventListener(\"scroll\", checkScroll);\n resizeObserver.disconnect();\n };\n }, [scrollRef, autoScroll]);\n\n if (!hasMounted) {\n return (\n <div className=\"cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:overflow-y-scroll cpk:overflow-x-hidden\">\n <div className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\">\n {children}\n </div>\n </div>\n );\n }\n\n // When autoScroll is false, we don't use StickToBottom\n if (!autoScroll) {\n const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});\n\n return (\n <div\n ref={scrollRef}\n className={cn(\n \"cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:overflow-y-scroll cpk:overflow-x-hidden cpk:relative\",\n className,\n )}\n {...props}\n >\n <div\n ref={contentRef}\n className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\"\n >\n {children}\n </div>\n\n {/* Feather gradient overlay */}\n {BoundFeather}\n\n {/* Scroll to bottom button for manual mode */}\n {showScrollButton && !isResizing && (\n <div\n className=\"cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none\"\n style={{\n bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px`,\n }}\n >\n {renderSlot(\n scrollToBottomButton,\n CopilotChatView.ScrollToBottomButton,\n {\n onClick: () => scrollToBottom(),\n },\n )}\n </div>\n )}\n </div>\n );\n }\n\n return (\n <StickToBottom\n className={cn(\n \"cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:relative\",\n className,\n )}\n resize=\"smooth\"\n initial=\"smooth\"\n {...props}\n >\n <ScrollContent\n scrollToBottomButton={scrollToBottomButton}\n feather={feather}\n inputContainerHeight={inputContainerHeight}\n isResizing={isResizing}\n >\n {children}\n </ScrollContent>\n </StickToBottom>\n );\n };\n\n export const ScrollToBottomButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, ...props }) => (\n <Button\n data-testid=\"copilot-scroll-to-bottom\"\n variant=\"outline\"\n size=\"sm\"\n className={twMerge(\n \"cpk:rounded-full cpk:w-10 cpk:h-10 cpk:p-0 cpk:pointer-events-auto\",\n \"cpk:bg-white cpk:dark:bg-gray-900\",\n \"cpk:shadow-lg cpk:border cpk:border-gray-200 cpk:dark:border-gray-700\",\n \"cpk:hover:bg-gray-50 cpk:dark:hover:bg-gray-800\",\n \"cpk:flex cpk:items-center cpk:justify-center cpk:cursor-pointer\",\n className,\n )}\n {...props}\n >\n <ChevronDown className=\"cpk:w-4 cpk:h-4 cpk:text-gray-600 cpk:dark:text-white\" />\n </Button>\n );\n\n export const Feather: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n style,\n ...props\n }) => (\n <div\n className={cn(\n \"cpk:absolute cpk:bottom-0 cpk:left-0 cpk:right-4 cpk:h-24 cpk:pointer-events-none cpk:z-10 cpk:bg-gradient-to-t\",\n \"cpk:from-white cpk:via-white cpk:to-transparent\",\n \"cpk:dark:from-[rgb(33,33,33)] cpk:dark:via-[rgb(33,33,33)]\",\n className,\n )}\n style={style}\n {...props}\n />\n );\n\n export const WelcomeMessage: React.FC<\n React.HTMLAttributes<HTMLDivElement>\n > = ({ className, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n\n return (\n <h1\n className={cn(\n \"cpk:text-xl cpk:sm:text-2xl cpk:font-medium cpk:text-foreground cpk:text-center\",\n className,\n )}\n {...props}\n >\n {labels.welcomeMessageText}\n </h1>\n );\n };\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 data-testid=\"copilot-welcome-screen\"\n className={cn(\n \"cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4\",\n className,\n )}\n {...props}\n >\n <div className=\"cpk:w-full cpk:max-w-3xl cpk:flex cpk:flex-col cpk:items-center\">\n {/* Welcome message */}\n <div className=\"cpk:mb-6\">{BoundWelcomeMessage}</div>\n\n {/* Input */}\n <div className=\"cpk:w-full\">{input}</div>\n\n {/* Suggestions */}\n <div className=\"cpk:mt-4 cpk:flex cpk:justify-center\">\n {suggestionView}\n </div>\n </div>\n </div>\n );\n };\n}\n\nexport default CopilotChatView;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CopilotChatView.mjs","names":["CopilotChatInput"],"sources":["../../../src/components/chat/CopilotChatView.tsx"],"sourcesContent":["import React, { useRef, useState, useEffect } from \"react\";\nimport { WithSlots, SlotValue, renderSlot } from \"@/lib/slots\";\nimport CopilotChatMessageView from \"./CopilotChatMessageView\";\nimport CopilotChatInput, {\n CopilotChatInputProps,\n CopilotChatInputMode,\n} from \"./CopilotChatInput\";\nimport CopilotChatSuggestionView, {\n CopilotChatSuggestionViewProps,\n} from \"./CopilotChatSuggestionView\";\nimport { Suggestion } from \"@copilotkitnext/core\";\nimport { Message } from \"@ag-ui/core\";\nimport { twMerge } from \"tailwind-merge\";\nimport {\n StickToBottom,\n useStickToBottom,\n useStickToBottomContext,\n} from \"use-stick-to-bottom\";\nimport { ChevronDown } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { useKeyboardHeight } from \"@/hooks/use-keyboard-height\";\n\n// Height of the feather gradient overlay (h-24 = 6rem = 96px)\nconst FEATHER_HEIGHT = 96;\n\n// Forward declaration for WelcomeScreen component type\nexport type WelcomeScreenProps = WithSlots<\n {\n welcomeMessage: React.FC<React.HTMLAttributes<HTMLDivElement>>;\n },\n {\n input: React.ReactElement;\n suggestionView: React.ReactElement;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport type CopilotChatViewProps = WithSlots<\n {\n messageView: typeof CopilotChatMessageView;\n scrollView: typeof CopilotChatView.ScrollView;\n input: typeof CopilotChatInput;\n suggestionView: typeof CopilotChatSuggestionView;\n },\n {\n messages?: Message[];\n autoScroll?: boolean;\n isRunning?: boolean;\n suggestions?: Suggestion[];\n suggestionLoadingIndexes?: ReadonlyArray<number>;\n onSelectSuggestion?: (suggestion: Suggestion, index: number) => void;\n welcomeScreen?: SlotValue<React.FC<WelcomeScreenProps>> | boolean;\n // Input behavior props\n onSubmitMessage?: (value: string) => void;\n onStop?: () => void;\n inputMode?: CopilotChatInputMode;\n inputValue?: string;\n onInputChange?: (value: string) => void;\n onStartTranscribe?: () => void;\n onCancelTranscribe?: () => void;\n onFinishTranscribe?: () => void;\n onFinishTranscribeWithAudio?: (audioBlob: Blob) => Promise<void>;\n /**\n * @deprecated Use the `input` slot's `disclaimer` prop instead:\n * ```tsx\n * <CopilotChat input={{ disclaimer: MyDisclaimer }} />\n * ```\n */\n disclaimer?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport function CopilotChatView({\n messageView,\n input,\n scrollView,\n suggestionView,\n welcomeScreen,\n messages = [],\n autoScroll = true,\n isRunning = false,\n suggestions,\n suggestionLoadingIndexes,\n onSelectSuggestion,\n // Input behavior props\n onSubmitMessage,\n onStop,\n inputMode,\n inputValue,\n onInputChange,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n // Deprecated — forwarded to input slot\n disclaimer,\n children,\n className,\n ...props\n}: CopilotChatViewProps) {\n const inputContainerRef = useRef<HTMLDivElement>(null);\n const [inputContainerHeight, setInputContainerHeight] = useState(0);\n const [isResizing, setIsResizing] = useState(false);\n const resizeTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n // Track keyboard state for mobile\n const { isKeyboardOpen, keyboardHeight, availableHeight } =\n useKeyboardHeight();\n\n // Track input container height changes\n useEffect(() => {\n const element = inputContainerRef.current;\n if (!element) return;\n\n const resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const newHeight = entry.contentRect.height;\n\n // Update height and set resizing state\n setInputContainerHeight((prevHeight) => {\n if (newHeight !== prevHeight) {\n setIsResizing(true);\n\n // Clear existing timeout\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n\n // Set isResizing to false after a short delay\n resizeTimeoutRef.current = setTimeout(() => {\n setIsResizing(false);\n }, 250);\n\n return newHeight;\n }\n return prevHeight;\n });\n }\n });\n\n resizeObserver.observe(element);\n\n // Set initial height\n setInputContainerHeight(element.offsetHeight);\n\n return () => {\n resizeObserver.disconnect();\n if (resizeTimeoutRef.current) {\n clearTimeout(resizeTimeoutRef.current);\n }\n };\n }, []);\n\n const BoundMessageView = renderSlot(messageView, CopilotChatMessageView, {\n messages,\n isRunning,\n });\n\n const BoundInput = renderSlot(input, CopilotChatInput, {\n onSubmitMessage,\n onStop,\n mode: inputMode,\n value: inputValue,\n onChange: onInputChange,\n isRunning,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n positioning: \"absolute\",\n keyboardHeight: isKeyboardOpen ? keyboardHeight : 0,\n containerRef: inputContainerRef,\n showDisclaimer: true,\n ...(disclaimer !== undefined ? { disclaimer } : {}),\n } as CopilotChatInputProps);\n\n const hasSuggestions = Array.isArray(suggestions) && suggestions.length > 0;\n const BoundSuggestionView = hasSuggestions\n ? renderSlot(suggestionView, CopilotChatSuggestionView, {\n suggestions,\n loadingIndexes: suggestionLoadingIndexes,\n onSelectSuggestion,\n className: \"cpk:mb-3 cpk:lg:ml-4 cpk:lg:mr-4 cpk:ml-0 cpk:mr-0\",\n })\n : null;\n\n const BoundScrollView = renderSlot(scrollView, CopilotChatView.ScrollView, {\n autoScroll,\n inputContainerHeight,\n isResizing,\n children: (\n <div\n style={{\n paddingBottom: `${inputContainerHeight + FEATHER_HEIGHT + (hasSuggestions ? 4 : 32)}px`,\n }}\n >\n <div className=\"cpk:max-w-3xl cpk:mx-auto\">\n {BoundMessageView}\n {hasSuggestions ? (\n <div className=\"cpk:pl-0 cpk:pr-4 cpk:sm:px-0 cpk:mt-4\">\n {BoundSuggestionView}\n </div>\n ) : null}\n </div>\n </div>\n ),\n });\n\n // Welcome screen logic\n const isEmpty = messages.length === 0;\n // Type assertion needed because TypeScript doesn't fully propagate `| boolean` through WithSlots\n const welcomeScreenDisabled = (welcomeScreen as unknown) === false;\n const shouldShowWelcomeScreen = isEmpty && !welcomeScreenDisabled;\n\n if (shouldShowWelcomeScreen) {\n // Create a separate input for welcome screen with static positioning and disclaimer visible\n const BoundInputForWelcome = renderSlot(input, CopilotChatInput, {\n onSubmitMessage,\n onStop,\n mode: inputMode,\n value: inputValue,\n onChange: onInputChange,\n isRunning,\n onStartTranscribe,\n onCancelTranscribe,\n onFinishTranscribe,\n onFinishTranscribeWithAudio,\n positioning: \"static\",\n showDisclaimer: true,\n ...(disclaimer !== undefined ? { disclaimer } : {}),\n } as CopilotChatInputProps);\n\n // Convert boolean `true` to undefined (use default), and exclude `false` since we've checked for it\n const welcomeScreenSlot = (\n welcomeScreen === true ? undefined : welcomeScreen\n ) as SlotValue<React.FC<WelcomeScreenProps>> | undefined;\n const BoundWelcomeScreen = renderSlot(\n welcomeScreenSlot,\n CopilotChatView.WelcomeScreen,\n {\n input: BoundInputForWelcome,\n suggestionView: BoundSuggestionView ?? <></>,\n },\n );\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-chat\"\n data-copilot-running={isRunning ? \"true\" : \"false\"}\n className={twMerge(\n \"copilotKitChat cpk:relative cpk:h-full cpk:flex cpk:flex-col\",\n className,\n )}\n {...props}\n >\n {BoundWelcomeScreen}\n </div>\n );\n }\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n messageView: BoundMessageView,\n input: BoundInput,\n scrollView: BoundScrollView,\n suggestionView: BoundSuggestionView ?? <></>,\n })}\n </div>\n );\n }\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-chat\"\n data-copilot-running={isRunning ? \"true\" : \"false\"}\n className={twMerge(\"copilotKitChat cpk:relative cpk:h-full\", className)}\n {...props}\n >\n {BoundScrollView}\n\n {BoundInput}\n </div>\n );\n}\n\nexport namespace CopilotChatView {\n // Inner component that has access to StickToBottom context\n const ScrollContent: React.FC<{\n children: React.ReactNode;\n scrollToBottomButton?: SlotValue<\n React.FC<React.ButtonHTMLAttributes<HTMLButtonElement>>\n >;\n feather?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n inputContainerHeight: number;\n isResizing: boolean;\n }> = ({\n children,\n scrollToBottomButton,\n feather,\n inputContainerHeight,\n isResizing,\n }) => {\n const { isAtBottom, scrollToBottom } = useStickToBottomContext();\n\n const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});\n\n return (\n <>\n <StickToBottom.Content\n className=\"cpk:overflow-y-scroll cpk:overflow-x-hidden\"\n style={{ flex: \"1 1 0%\", minHeight: 0 }}\n >\n <div className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\">\n {children}\n </div>\n </StickToBottom.Content>\n\n {/* Feather gradient overlay */}\n {BoundFeather}\n\n {/* Scroll to bottom button - hidden during resize */}\n {!isAtBottom && !isResizing && (\n <div\n className=\"cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none\"\n style={{\n bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px`,\n }}\n >\n {renderSlot(\n scrollToBottomButton,\n CopilotChatView.ScrollToBottomButton,\n {\n onClick: () => scrollToBottom(),\n },\n )}\n </div>\n )}\n </>\n );\n };\n\n export const ScrollView: React.FC<\n React.HTMLAttributes<HTMLDivElement> & {\n autoScroll?: boolean;\n scrollToBottomButton?: SlotValue<\n React.FC<React.ButtonHTMLAttributes<HTMLButtonElement>>\n >;\n feather?: SlotValue<React.FC<React.HTMLAttributes<HTMLDivElement>>>;\n inputContainerHeight?: number;\n isResizing?: boolean;\n }\n > = ({\n children,\n autoScroll = true,\n scrollToBottomButton,\n feather,\n inputContainerHeight = 0,\n isResizing = false,\n className,\n ...props\n }) => {\n const [hasMounted, setHasMounted] = useState(false);\n const { scrollRef, contentRef, scrollToBottom } = useStickToBottom();\n const [showScrollButton, setShowScrollButton] = useState(false);\n\n useEffect(() => {\n setHasMounted(true);\n }, []);\n\n // Monitor scroll position for non-autoscroll mode\n useEffect(() => {\n if (autoScroll) return; // Skip for autoscroll mode\n\n const scrollElement = scrollRef.current;\n if (!scrollElement) return;\n\n const checkScroll = () => {\n const atBottom =\n scrollElement.scrollHeight -\n scrollElement.scrollTop -\n scrollElement.clientHeight <\n 10;\n setShowScrollButton(!atBottom);\n };\n\n checkScroll();\n scrollElement.addEventListener(\"scroll\", checkScroll);\n\n // Also check on resize\n const resizeObserver = new ResizeObserver(checkScroll);\n resizeObserver.observe(scrollElement);\n\n return () => {\n scrollElement.removeEventListener(\"scroll\", checkScroll);\n resizeObserver.disconnect();\n };\n }, [scrollRef, autoScroll]);\n\n if (!hasMounted) {\n return (\n <div className=\"cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:overflow-y-scroll cpk:overflow-x-hidden\">\n <div className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\">\n {children}\n </div>\n </div>\n );\n }\n\n // When autoScroll is false, we don't use StickToBottom\n if (!autoScroll) {\n const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});\n\n return (\n <div\n ref={scrollRef}\n className={cn(\n \"cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:overflow-y-scroll cpk:overflow-x-hidden cpk:relative\",\n className,\n )}\n {...props}\n >\n <div\n ref={contentRef}\n className=\"cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6\"\n >\n {children}\n </div>\n\n {/* Feather gradient overlay */}\n {BoundFeather}\n\n {/* Scroll to bottom button for manual mode */}\n {showScrollButton && !isResizing && (\n <div\n className=\"cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none\"\n style={{\n bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px`,\n }}\n >\n {renderSlot(\n scrollToBottomButton,\n CopilotChatView.ScrollToBottomButton,\n {\n onClick: () => scrollToBottom(),\n },\n )}\n </div>\n )}\n </div>\n );\n }\n\n return (\n <StickToBottom\n className={cn(\n \"cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:relative\",\n className,\n )}\n resize=\"smooth\"\n initial=\"smooth\"\n {...props}\n >\n <ScrollContent\n scrollToBottomButton={scrollToBottomButton}\n feather={feather}\n inputContainerHeight={inputContainerHeight}\n isResizing={isResizing}\n >\n {children}\n </ScrollContent>\n </StickToBottom>\n );\n };\n\n export const ScrollToBottomButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, ...props }) => (\n <Button\n data-testid=\"copilot-scroll-to-bottom\"\n variant=\"outline\"\n size=\"sm\"\n className={twMerge(\n \"cpk:rounded-full cpk:w-10 cpk:h-10 cpk:p-0 cpk:pointer-events-auto\",\n \"cpk:bg-white cpk:dark:bg-gray-900\",\n \"cpk:shadow-lg cpk:border cpk:border-gray-200 cpk:dark:border-gray-700\",\n \"cpk:hover:bg-gray-50 cpk:dark:hover:bg-gray-800\",\n \"cpk:flex cpk:items-center cpk:justify-center cpk:cursor-pointer\",\n className,\n )}\n {...props}\n >\n <ChevronDown className=\"cpk:w-4 cpk:h-4 cpk:text-gray-600 cpk:dark:text-white\" />\n </Button>\n );\n\n export const Feather: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n style,\n ...props\n }) => (\n <div\n className={cn(\n \"cpk:absolute cpk:bottom-0 cpk:left-0 cpk:right-4 cpk:h-24 cpk:pointer-events-none cpk:z-10 cpk:bg-gradient-to-t\",\n \"cpk:from-white cpk:via-white cpk:to-transparent\",\n \"cpk:dark:from-[rgb(33,33,33)] cpk:dark:via-[rgb(33,33,33)]\",\n className,\n )}\n style={style}\n {...props}\n />\n );\n\n export const WelcomeMessage: React.FC<\n React.HTMLAttributes<HTMLDivElement>\n > = ({ className, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n\n return (\n <h1\n className={cn(\n \"cpk:text-xl cpk:sm:text-2xl cpk:font-medium cpk:text-foreground cpk:text-center\",\n className,\n )}\n {...props}\n >\n {labels.welcomeMessageText}\n </h1>\n );\n };\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 data-testid=\"copilot-welcome-screen\"\n className={cn(\n \"cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4\",\n className,\n )}\n {...props}\n >\n <div className=\"cpk:w-full cpk:max-w-3xl cpk:flex cpk:flex-col cpk:items-center\">\n {/* Welcome message */}\n <div className=\"cpk:mb-6\">{BoundWelcomeMessage}</div>\n\n {/* Input */}\n <div className=\"cpk:w-full\">{input}</div>\n\n {/* Suggestions */}\n <div className=\"cpk:mt-4 cpk:flex cpk:justify-center\">\n {suggestionView}\n </div>\n </div>\n </div>\n );\n };\n}\n\nexport default CopilotChatView;\n"],"mappings":"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"}
|
|
@@ -26,7 +26,7 @@ function CopilotModalHeader({ title, titleContent, closeButton, children, classN
|
|
|
26
26
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("header", {
|
|
27
27
|
"data-testid": "copilot-modal-header",
|
|
28
28
|
"data-slot": "copilot-modal-header",
|
|
29
|
-
className: require_utils.cn("cpk:flex cpk:items-center cpk:justify-between cpk:border-b cpk:border-border cpk:px-4 cpk:py-4", "cpk:bg-background/95 cpk:backdrop-blur cpk:supports-[backdrop-filter]:bg-background/80", className),
|
|
29
|
+
className: require_utils.cn("copilotKitHeader", "cpk:flex cpk:items-center cpk:justify-between cpk:border-b cpk:border-border cpk:px-4 cpk:py-4", "cpk:bg-background/95 cpk:backdrop-blur cpk:supports-[backdrop-filter]:bg-background/80", className),
|
|
30
30
|
...rest,
|
|
31
31
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
32
32
|
className: "cpk:flex cpk:w-full cpk:items-center cpk:gap-2",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotModalHeader.cjs","names":["useCopilotChatConfiguration","CopilotChatDefaultLabels","renderSlot","cn","X"],"sources":["../../../src/components/chat/CopilotModalHeader.tsx"],"sourcesContent":["import React, { useCallback } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { renderSlot, WithSlots } from \"@/lib/slots\";\nimport { X } from \"lucide-react\";\n\ntype HeaderSlots = {\n titleContent: typeof CopilotModalHeader.Title;\n closeButton: typeof CopilotModalHeader.CloseButton;\n};\n\ntype HeaderRestProps = {\n title?: string;\n} & Omit<React.HTMLAttributes<HTMLDivElement>, \"children\">;\n\nexport type CopilotModalHeaderProps = WithSlots<HeaderSlots, HeaderRestProps>;\n\nexport function CopilotModalHeader({\n title,\n titleContent,\n closeButton,\n children,\n className,\n ...rest\n}: CopilotModalHeaderProps) {\n const configuration = useCopilotChatConfiguration();\n\n const fallbackTitle =\n configuration?.labels.modalHeaderTitle ??\n CopilotChatDefaultLabels.modalHeaderTitle;\n const resolvedTitle = title ?? fallbackTitle;\n\n const handleClose = useCallback(() => {\n configuration?.setModalOpen?.(false);\n }, [configuration]);\n\n const BoundTitle = renderSlot(titleContent, CopilotModalHeader.Title, {\n children: resolvedTitle,\n });\n\n const BoundCloseButton = renderSlot(\n closeButton,\n CopilotModalHeader.CloseButton,\n {\n onClick: handleClose,\n },\n );\n\n if (children) {\n return children({\n titleContent: BoundTitle,\n closeButton: BoundCloseButton,\n title: resolvedTitle,\n ...rest,\n });\n }\n\n return (\n <header\n data-testid=\"copilot-modal-header\"\n data-slot=\"copilot-modal-header\"\n className={cn(\n \"cpk:flex cpk:items-center cpk:justify-between cpk:border-b cpk:border-border cpk:px-4 cpk:py-4\",\n \"cpk:bg-background/95 cpk:backdrop-blur cpk:supports-[backdrop-filter]:bg-background/80\",\n className,\n )}\n {...rest}\n >\n <div className=\"cpk:flex cpk:w-full cpk:items-center cpk:gap-2\">\n <div className=\"cpk:flex-1\" aria-hidden=\"true\" />\n <div className=\"cpk:flex cpk:flex-1 cpk:justify-center cpk:text-center\">\n {BoundTitle}\n </div>\n <div className=\"cpk:flex cpk:flex-1 cpk:justify-end\">\n {BoundCloseButton}\n </div>\n </div>\n </header>\n );\n}\n\nCopilotModalHeader.displayName = \"CopilotModalHeader\";\n\nexport namespace CopilotModalHeader {\n export const Title: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n children,\n className,\n ...props\n }) => (\n <div\n data-testid=\"copilot-header-title\"\n className={cn(\n \"cpk:w-full cpk:text-base cpk:font-medium cpk:leading-none cpk:tracking-tight cpk:text-foreground\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n\n export const CloseButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, ...props }) => (\n <button\n type=\"button\"\n data-testid=\"copilot-close-button\"\n className={cn(\n \"cpk:inline-flex cpk:size-8 cpk:items-center cpk:justify-center cpk:rounded-full cpk:text-muted-foreground cpk:transition cpk:cursor-pointer\",\n \"cpk:hover:bg-muted cpk:hover:text-foreground cpk:focus-visible:outline-none cpk:focus-visible:ring-2 cpk:focus-visible:ring-ring\",\n className,\n )}\n aria-label=\"Close\"\n {...props}\n >\n <X className=\"cpk:h-4 cpk:w-4\" aria-hidden=\"true\" />\n </button>\n );\n}\n\nCopilotModalHeader.Title.displayName = \"CopilotModalHeader.Title\";\nCopilotModalHeader.CloseButton.displayName = \"CopilotModalHeader.CloseButton\";\n\nexport default CopilotModalHeader;\n"],"mappings":";;;;;;;;;;AAqBA,SAAgB,mBAAmB,EACjC,OACA,cACA,aACA,UACA,WACA,GAAG,QACuB;CAC1B,MAAM,gBAAgBA,sEAA6B;CAEnD,MAAM,gBACJ,eAAe,OAAO,oBACtBC,kEAAyB;CAC3B,MAAM,gBAAgB,SAAS;CAE/B,MAAM,2CAAgC;AACpC,iBAAe,eAAe,MAAM;IACnC,CAAC,cAAc,CAAC;CAEnB,MAAM,aAAaC,yBAAW,cAAc,mBAAmB,OAAO,EACpE,UAAU,eACX,CAAC;CAEF,MAAM,mBAAmBA,yBACvB,aACA,mBAAmB,aACnB,EACE,SAAS,aACV,CACF;AAED,KAAI,SACF,QAAO,SAAS;EACd,cAAc;EACd,aAAa;EACb,OAAO;EACP,GAAG;EACJ,CAAC;AAGJ,QACE,2CAAC;EACC,eAAY;EACZ,aAAU;EACV,WAAWC,iBACT,kGACA,0FACA,UACD;EACD,GAAI;YAEJ,4CAAC;GAAI,WAAU;;IACb,2CAAC;KAAI,WAAU;KAAa,eAAY;MAAS;IACjD,2CAAC;KAAI,WAAU;eACZ;MACG;IACN,2CAAC;KAAI,WAAU;eACZ;MACG;;IACF;GACC;;AAIb,mBAAmB,cAAc;;8BAGuC,EACpE,UACA,WACA,GAAG,YAEH,2CAAC;EACC,eAAY;EACZ,WAAWA,iBACT,oGACA,UACD;EACD,GAAI;EAEH;GACG;oCAKH,EAAE,WAAW,GAAG,YACnB,2CAAC;EACC,MAAK;EACL,eAAY;EACZ,WAAWA,iBACT,+IACA,oIACA,UACD;EACD,cAAW;EACX,GAAI;YAEJ,2CAACC;GAAE,WAAU;GAAkB,eAAY;IAAS;GAC7C;;AAIb,mBAAmB,MAAM,cAAc;AACvC,mBAAmB,YAAY,cAAc"}
|
|
1
|
+
{"version":3,"file":"CopilotModalHeader.cjs","names":["useCopilotChatConfiguration","CopilotChatDefaultLabels","renderSlot","cn","X"],"sources":["../../../src/components/chat/CopilotModalHeader.tsx"],"sourcesContent":["import React, { useCallback } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { renderSlot, WithSlots } from \"@/lib/slots\";\nimport { X } from \"lucide-react\";\n\ntype HeaderSlots = {\n titleContent: typeof CopilotModalHeader.Title;\n closeButton: typeof CopilotModalHeader.CloseButton;\n};\n\ntype HeaderRestProps = {\n title?: string;\n} & Omit<React.HTMLAttributes<HTMLDivElement>, \"children\">;\n\nexport type CopilotModalHeaderProps = WithSlots<HeaderSlots, HeaderRestProps>;\n\nexport function CopilotModalHeader({\n title,\n titleContent,\n closeButton,\n children,\n className,\n ...rest\n}: CopilotModalHeaderProps) {\n const configuration = useCopilotChatConfiguration();\n\n const fallbackTitle =\n configuration?.labels.modalHeaderTitle ??\n CopilotChatDefaultLabels.modalHeaderTitle;\n const resolvedTitle = title ?? fallbackTitle;\n\n const handleClose = useCallback(() => {\n configuration?.setModalOpen?.(false);\n }, [configuration]);\n\n const BoundTitle = renderSlot(titleContent, CopilotModalHeader.Title, {\n children: resolvedTitle,\n });\n\n const BoundCloseButton = renderSlot(\n closeButton,\n CopilotModalHeader.CloseButton,\n {\n onClick: handleClose,\n },\n );\n\n if (children) {\n return children({\n titleContent: BoundTitle,\n closeButton: BoundCloseButton,\n title: resolvedTitle,\n ...rest,\n });\n }\n\n return (\n <header\n data-testid=\"copilot-modal-header\"\n data-slot=\"copilot-modal-header\"\n className={cn(\n \"copilotKitHeader\",\n \"cpk:flex cpk:items-center cpk:justify-between cpk:border-b cpk:border-border cpk:px-4 cpk:py-4\",\n \"cpk:bg-background/95 cpk:backdrop-blur cpk:supports-[backdrop-filter]:bg-background/80\",\n className,\n )}\n {...rest}\n >\n <div className=\"cpk:flex cpk:w-full cpk:items-center cpk:gap-2\">\n <div className=\"cpk:flex-1\" aria-hidden=\"true\" />\n <div className=\"cpk:flex cpk:flex-1 cpk:justify-center cpk:text-center\">\n {BoundTitle}\n </div>\n <div className=\"cpk:flex cpk:flex-1 cpk:justify-end\">\n {BoundCloseButton}\n </div>\n </div>\n </header>\n );\n}\n\nCopilotModalHeader.displayName = \"CopilotModalHeader\";\n\nexport namespace CopilotModalHeader {\n export const Title: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n children,\n className,\n ...props\n }) => (\n <div\n data-testid=\"copilot-header-title\"\n className={cn(\n \"cpk:w-full cpk:text-base cpk:font-medium cpk:leading-none cpk:tracking-tight cpk:text-foreground\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n\n export const CloseButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, ...props }) => (\n <button\n type=\"button\"\n data-testid=\"copilot-close-button\"\n className={cn(\n \"cpk:inline-flex cpk:size-8 cpk:items-center cpk:justify-center cpk:rounded-full cpk:text-muted-foreground cpk:transition cpk:cursor-pointer\",\n \"cpk:hover:bg-muted cpk:hover:text-foreground cpk:focus-visible:outline-none cpk:focus-visible:ring-2 cpk:focus-visible:ring-ring\",\n className,\n )}\n aria-label=\"Close\"\n {...props}\n >\n <X className=\"cpk:h-4 cpk:w-4\" aria-hidden=\"true\" />\n </button>\n );\n}\n\nCopilotModalHeader.Title.displayName = \"CopilotModalHeader.Title\";\nCopilotModalHeader.CloseButton.displayName = \"CopilotModalHeader.CloseButton\";\n\nexport default CopilotModalHeader;\n"],"mappings":";;;;;;;;;;AAqBA,SAAgB,mBAAmB,EACjC,OACA,cACA,aACA,UACA,WACA,GAAG,QACuB;CAC1B,MAAM,gBAAgBA,sEAA6B;CAEnD,MAAM,gBACJ,eAAe,OAAO,oBACtBC,kEAAyB;CAC3B,MAAM,gBAAgB,SAAS;CAE/B,MAAM,2CAAgC;AACpC,iBAAe,eAAe,MAAM;IACnC,CAAC,cAAc,CAAC;CAEnB,MAAM,aAAaC,yBAAW,cAAc,mBAAmB,OAAO,EACpE,UAAU,eACX,CAAC;CAEF,MAAM,mBAAmBA,yBACvB,aACA,mBAAmB,aACnB,EACE,SAAS,aACV,CACF;AAED,KAAI,SACF,QAAO,SAAS;EACd,cAAc;EACd,aAAa;EACb,OAAO;EACP,GAAG;EACJ,CAAC;AAGJ,QACE,2CAAC;EACC,eAAY;EACZ,aAAU;EACV,WAAWC,iBACT,oBACA,kGACA,0FACA,UACD;EACD,GAAI;YAEJ,4CAAC;GAAI,WAAU;;IACb,2CAAC;KAAI,WAAU;KAAa,eAAY;MAAS;IACjD,2CAAC;KAAI,WAAU;eACZ;MACG;IACN,2CAAC;KAAI,WAAU;eACZ;MACG;;IACF;GACC;;AAIb,mBAAmB,cAAc;;8BAGuC,EACpE,UACA,WACA,GAAG,YAEH,2CAAC;EACC,eAAY;EACZ,WAAWA,iBACT,oGACA,UACD;EACD,GAAI;EAEH;GACG;oCAKH,EAAE,WAAW,GAAG,YACnB,2CAAC;EACC,MAAK;EACL,eAAY;EACZ,WAAWA,iBACT,+IACA,oIACA,UACD;EACD,cAAW;EACX,GAAI;YAEJ,2CAACC;GAAE,WAAU;GAAkB,eAAY;IAAS;GAC7C;;AAIb,mBAAmB,MAAM,cAAc;AACvC,mBAAmB,YAAY,cAAc"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotModalHeader.d.cts","names":[],"sources":["../../../src/components/chat/CopilotModalHeader.tsx"],"mappings":";;;;;KAUK,WAAA;EACH,YAAA,SAAqB,kBAAA,CAAmB,KAAA;EACxC,WAAA,SAAoB,kBAAA,CAAmB,WAAA;AAAA;AAAA,KAGpC,eAAA;EACH,KAAA;AAAA,IACE,IAAA,CAAK,KAAA,CAAM,cAAA,CAAe,cAAA;AAAA,KAElB,uBAAA,GAA0B,SAAA,CAAU,WAAA,EAAa,eAAA;AAAA,iBAE7C,kBAAA,CAAA;EACd,KAAA;EACA,YAAA;EACA,WAAA;EACA,QAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,uBAAA,wCAAuB,kBAAA,CAAA,GAAA,CAAA,OAAA,GAAA,QAAA,CAAA,KAAA,CAAA,SAAA,IAAA,OAAA,sCAAA,KAAA,CAAA,WAAA,GAAA,KAAA,CAAA,YAAA,mBAAA,KAAA,CAAA,qBAAA,SAAA,QAAA,CAAA,KAAA,CAAA,SAAA;AAAA,kBAPV,kBAAA;EAAA,IAAkB,WAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"CopilotModalHeader.d.cts","names":[],"sources":["../../../src/components/chat/CopilotModalHeader.tsx"],"mappings":";;;;;KAUK,WAAA;EACH,YAAA,SAAqB,kBAAA,CAAmB,KAAA;EACxC,WAAA,SAAoB,kBAAA,CAAmB,WAAA;AAAA;AAAA,KAGpC,eAAA;EACH,KAAA;AAAA,IACE,IAAA,CAAK,KAAA,CAAM,cAAA,CAAe,cAAA;AAAA,KAElB,uBAAA,GAA0B,SAAA,CAAU,WAAA,EAAa,eAAA;AAAA,iBAE7C,kBAAA,CAAA;EACd,KAAA;EACA,YAAA;EACA,WAAA;EACA,QAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,uBAAA,wCAAuB,kBAAA,CAAA,GAAA,CAAA,OAAA,GAAA,QAAA,CAAA,KAAA,CAAA,SAAA,IAAA,OAAA,sCAAA,KAAA,CAAA,WAAA,GAAA,KAAA,CAAA,YAAA,mBAAA,KAAA,CAAA,qBAAA,SAAA,QAAA,CAAA,KAAA,CAAA,SAAA;AAAA,kBAPV,kBAAA;EAAA,IAAkB,WAAA;AAAA;AAAA,kBAmEjB,kBAAA;EAAA,MACF,KAAA,EAAO,KAAA,CAAM,EAAA,CAAG,KAAA,CAAM,cAAA,CAAe,cAAA;EAAA,MAiBrC,WAAA,EAAa,KAAA,CAAM,EAAA,CAC9B,KAAA,CAAM,oBAAA,CAAqB,iBAAA;AAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotModalHeader.d.mts","names":[],"sources":["../../../src/components/chat/CopilotModalHeader.tsx"],"mappings":";;;;;KAUK,WAAA;EACH,YAAA,SAAqB,kBAAA,CAAmB,KAAA;EACxC,WAAA,SAAoB,kBAAA,CAAmB,WAAA;AAAA;AAAA,KAGpC,eAAA;EACH,KAAA;AAAA,IACE,IAAA,CAAK,KAAA,CAAM,cAAA,CAAe,cAAA;AAAA,KAElB,uBAAA,GAA0B,SAAA,CAAU,WAAA,EAAa,eAAA;AAAA,iBAE7C,kBAAA,CAAA;EACd,KAAA;EACA,YAAA;EACA,WAAA;EACA,QAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,uBAAA,wCAAuB,kBAAA,CAAA,GAAA,CAAA,OAAA,GAAA,QAAA,CAAA,KAAA,CAAA,SAAA,IAAA,OAAA,sCAAA,KAAA,CAAA,WAAA,GAAA,KAAA,CAAA,YAAA,mBAAA,KAAA,CAAA,qBAAA,SAAA,QAAA,CAAA,KAAA,CAAA,SAAA;AAAA,kBAPV,kBAAA;EAAA,IAAkB,WAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"CopilotModalHeader.d.mts","names":[],"sources":["../../../src/components/chat/CopilotModalHeader.tsx"],"mappings":";;;;;KAUK,WAAA;EACH,YAAA,SAAqB,kBAAA,CAAmB,KAAA;EACxC,WAAA,SAAoB,kBAAA,CAAmB,WAAA;AAAA;AAAA,KAGpC,eAAA;EACH,KAAA;AAAA,IACE,IAAA,CAAK,KAAA,CAAM,cAAA,CAAe,cAAA;AAAA,KAElB,uBAAA,GAA0B,SAAA,CAAU,WAAA,EAAa,eAAA;AAAA,iBAE7C,kBAAA,CAAA;EACd,KAAA;EACA,YAAA;EACA,WAAA;EACA,QAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,uBAAA,wCAAuB,kBAAA,CAAA,GAAA,CAAA,OAAA,GAAA,QAAA,CAAA,KAAA,CAAA,SAAA,IAAA,OAAA,sCAAA,KAAA,CAAA,WAAA,GAAA,KAAA,CAAA,YAAA,mBAAA,KAAA,CAAA,qBAAA,SAAA,QAAA,CAAA,KAAA,CAAA,SAAA;AAAA,kBAPV,kBAAA;EAAA,IAAkB,WAAA;AAAA;AAAA,kBAmEjB,kBAAA;EAAA,MACF,KAAA,EAAO,KAAA,CAAM,EAAA,CAAG,KAAA,CAAM,cAAA,CAAe,cAAA;EAAA,MAiBrC,WAAA,EAAa,KAAA,CAAM,EAAA,CAC9B,KAAA,CAAM,oBAAA,CAAqB,iBAAA;AAAA"}
|
|
@@ -24,7 +24,7 @@ function CopilotModalHeader({ title, titleContent, closeButton, children, classN
|
|
|
24
24
|
return /* @__PURE__ */ jsx("header", {
|
|
25
25
|
"data-testid": "copilot-modal-header",
|
|
26
26
|
"data-slot": "copilot-modal-header",
|
|
27
|
-
className: cn("cpk:flex cpk:items-center cpk:justify-between cpk:border-b cpk:border-border cpk:px-4 cpk:py-4", "cpk:bg-background/95 cpk:backdrop-blur cpk:supports-[backdrop-filter]:bg-background/80", className),
|
|
27
|
+
className: cn("copilotKitHeader", "cpk:flex cpk:items-center cpk:justify-between cpk:border-b cpk:border-border cpk:px-4 cpk:py-4", "cpk:bg-background/95 cpk:backdrop-blur cpk:supports-[backdrop-filter]:bg-background/80", className),
|
|
28
28
|
...rest,
|
|
29
29
|
children: /* @__PURE__ */ jsxs("div", {
|
|
30
30
|
className: "cpk:flex cpk:w-full cpk:items-center cpk:gap-2",
|