@bikdotai/bik-component-library 0.0.856-beta.0 → 0.0.857-beta.0
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/README.md +25 -4
- package/dist/cjs/components/bik-copilot/BIKCopilot.js +2 -0
- package/dist/cjs/components/bik-copilot/BIKCopilot.js.map +1 -0
- package/dist/cjs/components/bik-copilot/ControlledCopilot.js +2 -0
- package/dist/cjs/components/bik-copilot/ControlledCopilot.js.map +1 -0
- package/dist/cjs/components/bik-copilot/ControlledCopilot.styled.js +27 -0
- package/dist/cjs/components/bik-copilot/ControlledCopilot.styled.js.map +1 -0
- package/dist/cjs/components/bik-copilot/CopilotBall.js +2 -0
- package/dist/cjs/components/bik-copilot/CopilotBall.js.map +1 -0
- package/dist/cjs/components/bik-copilot/CopilotBall.styled.js +42 -0
- package/dist/cjs/components/bik-copilot/CopilotBall.styled.js.map +1 -0
- package/dist/cjs/components/bik-copilot/CopilotPanel.js +2 -0
- package/dist/cjs/components/bik-copilot/CopilotPanel.js.map +1 -0
- package/dist/cjs/components/bik-copilot/CopilotPanel.styled.js +419 -0
- package/dist/cjs/components/bik-copilot/CopilotPanel.styled.js.map +1 -0
- package/dist/cjs/components/bik-copilot/copilotPlacement.js +2 -0
- package/dist/cjs/components/bik-copilot/copilotPlacement.js.map +1 -0
- package/dist/cjs/components/bik-copilot/services/copilotDb.js +2 -0
- package/dist/cjs/components/bik-copilot/services/copilotDb.js.map +1 -0
- package/dist/cjs/components/bik-copilot/services/copilotIcebreakersClient.js +2 -0
- package/dist/cjs/components/bik-copilot/services/copilotIcebreakersClient.js.map +1 -0
- package/dist/cjs/components/bik-copilot/services/copilotMessagesClient.js +2 -0
- package/dist/cjs/components/bik-copilot/services/copilotMessagesClient.js.map +1 -0
- package/dist/cjs/components/bik-copilot/services/copilotPageSession.js +2 -0
- package/dist/cjs/components/bik-copilot/services/copilotPageSession.js.map +1 -0
- package/dist/cjs/components/bik-copilot/services/copilotSseParser.js +7 -0
- package/dist/cjs/components/bik-copilot/services/copilotSseParser.js.map +1 -0
- package/dist/cjs/components/bik-copilot/services/copilotStreamClient.js +2 -0
- package/dist/cjs/components/bik-copilot/services/copilotStreamClient.js.map +1 -0
- package/dist/cjs/components/bik-copilot/useCopilotIcebreakers.js +2 -0
- package/dist/cjs/components/bik-copilot/useCopilotIcebreakers.js.map +1 -0
- package/dist/cjs/components/bik-copilot/useCopilotStreamChat.js +2 -0
- package/dist/cjs/components/bik-copilot/useCopilotStreamChat.js.map +1 -0
- package/dist/cjs/components/bik-copilot/useDraggableFloater.js +2 -0
- package/dist/cjs/components/bik-copilot/useDraggableFloater.js.map +1 -0
- package/dist/cjs/components/tag/Tag.js +1 -1
- package/dist/cjs/components/tag/Tag.js.map +1 -1
- package/dist/cjs/components/tag/Tag.styled.js +2 -2
- package/dist/cjs/components/tag/Tag.styled.js.map +1 -1
- package/dist/cjs/components/tag/model.js.map +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/esm/components/bik-copilot/BIKCopilot.d.ts +32 -0
- package/dist/esm/components/bik-copilot/BIKCopilot.js +114 -0
- package/dist/esm/components/bik-copilot/BIKCopilot.js.map +1 -0
- package/dist/esm/components/bik-copilot/ControlledCopilot.d.ts +14 -0
- package/dist/esm/components/bik-copilot/ControlledCopilot.js +170 -0
- package/dist/esm/components/bik-copilot/ControlledCopilot.js.map +1 -0
- package/dist/esm/components/bik-copilot/ControlledCopilot.styled.d.ts +7 -0
- package/dist/esm/components/bik-copilot/ControlledCopilot.styled.js +31 -0
- package/dist/esm/components/bik-copilot/ControlledCopilot.styled.js.map +1 -0
- package/dist/esm/components/bik-copilot/CopilotBall.d.ts +13 -0
- package/dist/esm/components/bik-copilot/CopilotBall.js +50 -0
- package/dist/esm/components/bik-copilot/CopilotBall.js.map +1 -0
- package/dist/esm/components/bik-copilot/CopilotBall.styled.d.ts +9 -0
- package/dist/esm/components/bik-copilot/CopilotBall.styled.js +46 -0
- package/dist/esm/components/bik-copilot/CopilotBall.styled.js.map +1 -0
- package/dist/esm/components/bik-copilot/CopilotPanel.d.ts +9 -0
- package/dist/esm/components/bik-copilot/CopilotPanel.js +309 -0
- package/dist/esm/components/bik-copilot/CopilotPanel.js.map +1 -0
- package/dist/esm/components/bik-copilot/CopilotPanel.styled.d.ts +58 -0
- package/dist/esm/components/bik-copilot/CopilotPanel.styled.js +453 -0
- package/dist/esm/components/bik-copilot/CopilotPanel.styled.js.map +1 -0
- package/dist/esm/components/bik-copilot/copilotPlacement.d.ts +24 -0
- package/dist/esm/components/bik-copilot/copilotPlacement.js +38 -0
- package/dist/esm/components/bik-copilot/copilotPlacement.js.map +1 -0
- package/dist/esm/components/bik-copilot/index.d.ts +16 -0
- package/dist/esm/components/bik-copilot/model.d.ts +674 -0
- package/dist/esm/components/bik-copilot/services/copilotDb.d.ts +90 -0
- package/dist/esm/components/bik-copilot/services/copilotDb.js +96 -0
- package/dist/esm/components/bik-copilot/services/copilotDb.js.map +1 -0
- package/dist/esm/components/bik-copilot/services/copilotIcebreakersClient.d.ts +11 -0
- package/dist/esm/components/bik-copilot/services/copilotIcebreakersClient.js +54 -0
- package/dist/esm/components/bik-copilot/services/copilotIcebreakersClient.js.map +1 -0
- package/dist/esm/components/bik-copilot/services/copilotMessagesClient.d.ts +23 -0
- package/dist/esm/components/bik-copilot/services/copilotMessagesClient.js +78 -0
- package/dist/esm/components/bik-copilot/services/copilotMessagesClient.js.map +1 -0
- package/dist/esm/components/bik-copilot/services/copilotPageSession.d.ts +37 -0
- package/dist/esm/components/bik-copilot/services/copilotPageSession.js +35 -0
- package/dist/esm/components/bik-copilot/services/copilotPageSession.js.map +1 -0
- package/dist/esm/components/bik-copilot/services/copilotSseParser.d.ts +22 -0
- package/dist/esm/components/bik-copilot/services/copilotSseParser.js +52 -0
- package/dist/esm/components/bik-copilot/services/copilotSseParser.js.map +1 -0
- package/dist/esm/components/bik-copilot/services/copilotStreamClient.d.ts +31 -0
- package/dist/esm/components/bik-copilot/services/copilotStreamClient.js +103 -0
- package/dist/esm/components/bik-copilot/services/copilotStreamClient.js.map +1 -0
- package/dist/esm/components/bik-copilot/useCopilotIcebreakers.d.ts +17 -0
- package/dist/esm/components/bik-copilot/useCopilotIcebreakers.js +60 -0
- package/dist/esm/components/bik-copilot/useCopilotIcebreakers.js.map +1 -0
- package/dist/esm/components/bik-copilot/useCopilotStreamChat.d.ts +20 -0
- package/dist/esm/components/bik-copilot/useCopilotStreamChat.js +333 -0
- package/dist/esm/components/bik-copilot/useCopilotStreamChat.js.map +1 -0
- package/dist/esm/components/bik-copilot/useDraggableFloater.d.ts +9 -0
- package/dist/esm/components/bik-copilot/useDraggableFloater.js +118 -0
- package/dist/esm/components/bik-copilot/useDraggableFloater.js.map +1 -0
- package/dist/esm/components/tag/Tag.d.ts +1 -1
- package/dist/esm/components/tag/Tag.js +15 -19
- package/dist/esm/components/tag/Tag.js.map +1 -1
- package/dist/esm/components/tag/Tag.styled.d.ts +0 -2
- package/dist/esm/components/tag/Tag.styled.js +5 -2
- package/dist/esm/components/tag/Tag.styled.js.map +1 -1
- package/dist/esm/components/tag/model.d.ts +0 -11
- package/dist/esm/components/tag/model.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +793 -743
- package/dist/esm/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,14 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/BikDotAiDev/bik-component-library/actions/workflows/publish-prod.yaml)
|
|
4
4
|
|
|
5
|
+
## Documentation
|
|
6
|
+
|
|
7
|
+
- [Integration guide](./docs/INTEGRATION.md) — installing and consuming the library
|
|
8
|
+
- [Icons](./docs/ICONS.md) — the icon set and how it is generated
|
|
9
|
+
- [Contributing conventions](./.github/instructions/) — folder layout, props, stories, docs
|
|
10
|
+
|
|
11
|
+
### Component guides
|
|
12
|
+
|
|
13
|
+
- [BIK Copilot](./src/components/bik-copilot/README.md) — the merchant copilot ball
|
|
14
|
+
and chat panel, and the props the dashboard passes it
|
|
15
|
+
|
|
16
|
+
## Local development
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install
|
|
20
|
+
npm run storybook # http://localhost:6006 — the source of truth for components
|
|
21
|
+
npm test # jest
|
|
22
|
+
npm run lint # eslint + prettier
|
|
23
|
+
npm run build # library build into dist/
|
|
24
|
+
```
|
|
25
|
+
|
|
5
26
|
## Testing (Jest + SWC)
|
|
6
27
|
|
|
7
28
|
Tests use **Jest** with **`@swc/jest`** instead of `ts-jest` for faster TypeScript and JSX transforms.
|
|
8
29
|
|
|
9
|
-
| Command
|
|
10
|
-
|
|
|
11
|
-
| `npm test`
|
|
12
|
-
| `npm run test:watch`
|
|
30
|
+
| Command | Purpose |
|
|
31
|
+
| ----------------------- | -------------------------------- |
|
|
32
|
+
| `npm test` | Run unit tests |
|
|
33
|
+
| `npm run test:watch` | Watch mode |
|
|
13
34
|
| `npm run test:coverage` | Generate coverage in `coverage/` |
|
|
14
35
|
|
|
15
36
|
Configuration: `jest.config.js`; SWC: `.swcrc`; test setup: `jest-setup.ts`.
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const V=require("react/jsx-runtime"),e=require("react"),W=require("./ControlledCopilot.js"),X=require("./useCopilotIcebreakers.js"),Y=require("./useCopilotStreamChat.js"),Z=({baseUrl:s,endpointPath:b,icebreakersPath:M,headers:o,authToken:t,getAuthToken:r,fetchImpl:i,storeId:n,agent:a,route:l,email:m,systemPrompt:h,model:q,maxOutputTokens:k,sessionId:y,persist:O,loadIcebreakers:R=!0,onError:j,onResponseComplete:H,onSessionIdChange:v,suggestions:B,inputDisabled:I,onRefresh:u,open:c,defaultOpen:C,onOpenChange:d,...K})=>{const[L,f]=e.useState(C===!0||c===!0),{messages:w,isThinking:x,isStreaming:g,isRestoring:D,error:N,isLoadingHistory:P,hasMoreHistory:z,sendMessage:E,loadOlderMessages:F,stopStreaming:G,startNewConversation:p}=Y.useCopilotStreamChat({baseUrl:s,endpointPath:b,headers:o,authToken:t,getAuthToken:r,fetchImpl:i,storeId:n,agent:a,route:l,email:m,systemPrompt:h,model:q,maxOutputTokens:k,sessionId:y,persist:O,onError:j,onResponseComplete:H,onSessionIdChange:v}),{icebreakers:J}=X.useCopilotIcebreakers({baseUrl:s,icebreakersPath:M,headers:o,authToken:t,getAuthToken:r,fetchImpl:i,agent:a,route:l,storeId:n,enabled:R&&L}),Q=e.useCallback(S=>{S&&f(!0),d?.(S)},[d]),T=e.useCallback(()=>{p(),u?.()},[u,p]);return V.jsx(W.ControlledCopilot,{...K,open:c,defaultOpen:C,onOpenChange:Q,messages:w,onSendMessage:E,isThinking:x,isStreaming:g,onStop:G,isLoadingHistory:P,hasMoreHistory:z,onLoadOlderMessages:F,errorMessage:N,suggestions:B??J,inputDisabled:I||D||g,onRefresh:T})};exports.BIKCopilot=Z;
|
|
2
|
+
//# sourceMappingURL=BIKCopilot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BIKCopilot.js","sources":["../../../../src/components/bik-copilot/BIKCopilot.tsx"],"sourcesContent":["import React, { useCallback, useState } from 'react';\nimport { ControlledCopilot } from './ControlledCopilot';\nimport { BIKCopilotProps } from './model';\nimport { useCopilotIcebreakers } from './useCopilotIcebreakers';\nimport { useCopilotStreamChat } from './useCopilotStreamChat';\n\n/**\n * The copilot ball and panel wired to the streaming `/bik-ai/copilot-chatbot`\n * endpoint, with the transcript persisted in IndexedDB and route-aware ice\n * breakers from `/bik-ai/copilot-icebreakers`.\n *\n * Chunks arrive as `STREAM` events and are appended live; the final `TEXT` event\n * replaces the bubble with the authoritative full message and carries the\n * `responseId` that threads the next turn. A session id is created on first use\n * and restored on reload, so a refresh resumes the same conversation. The\n * header's reset button starts a new session id and a new OpenAI thread.\n *\n * Ice breakers are fetched for the current `agent` + `route` the first time the\n * panel is opened, and refetched when the route changes.\n *\n * ```tsx\n * <BIKCopilot\n * baseUrl={AI_BACKEND_URL}\n * getAuthToken={() => firebaseUser.getIdToken()}\n * headers={{ 'bik-referer': 'dashboard' }}\n * storeId={storeId}\n * email={user.email}\n * route={currentRoute}\n * title=\"Copilot\"\n * badge=\"New\"\n * subtitle=\"Way smarter, wildly more capable\"\n * />\n * ```\n */\nexport const BIKCopilot: React.FC<BIKCopilotProps> = ({\n\t// Transport + turn config\n\tbaseUrl,\n\tendpointPath,\n\ticebreakersPath,\n\theaders,\n\tauthToken,\n\tgetAuthToken,\n\tfetchImpl,\n\tstoreId,\n\tagent,\n\troute,\n\temail,\n\tsystemPrompt,\n\tmodel,\n\tmaxOutputTokens,\n\tsessionId,\n\tpersist,\n\tloadIcebreakers = true,\n\tonError,\n\tonResponseComplete,\n\tonSessionIdChange,\n\t// Shell\n\tsuggestions,\n\tinputDisabled,\n\tonRefresh,\n\topen,\n\tdefaultOpen,\n\tonOpenChange,\n\t...shellProps\n}) => {\n\t// Ice breakers only matter once the panel is visible, so a merchant who never\n\t// opens the copilot costs no request.\n\tconst [hasOpened, setHasOpened] = useState(\n\t\tdefaultOpen === true || open === true,\n\t);\n\n\tconst {\n\t\tmessages,\n\t\tisThinking,\n\t\tisStreaming,\n\t\tisRestoring,\n\t\terror,\n\t\tisLoadingHistory,\n\t\thasMoreHistory,\n\t\tsendMessage,\n\t\tloadOlderMessages,\n\t\tstopStreaming,\n\t\tstartNewConversation,\n\t} = useCopilotStreamChat({\n\t\tbaseUrl,\n\t\tendpointPath,\n\t\theaders,\n\t\tauthToken,\n\t\tgetAuthToken,\n\t\tfetchImpl,\n\t\tstoreId,\n\t\tagent,\n\t\troute,\n\t\temail,\n\t\tsystemPrompt,\n\t\tmodel,\n\t\tmaxOutputTokens,\n\t\tsessionId,\n\t\tpersist,\n\t\tonError,\n\t\tonResponseComplete,\n\t\tonSessionIdChange,\n\t});\n\n\tconst { icebreakers } = useCopilotIcebreakers({\n\t\tbaseUrl,\n\t\ticebreakersPath,\n\t\theaders,\n\t\tauthToken,\n\t\tgetAuthToken,\n\t\tfetchImpl,\n\t\tagent,\n\t\troute,\n\t\tstoreId,\n\t\tenabled: loadIcebreakers && hasOpened,\n\t});\n\n\tconst handleOpenChange = useCallback(\n\t\t(nextOpen: boolean) => {\n\t\t\tif (nextOpen) {\n\t\t\t\tsetHasOpened(true);\n\t\t\t}\n\t\t\tonOpenChange?.(nextOpen);\n\t\t},\n\t\t[onOpenChange],\n\t);\n\n\tconst handleRefresh = useCallback(() => {\n\t\tstartNewConversation();\n\t\tonRefresh?.();\n\t}, [onRefresh, startNewConversation]);\n\n\treturn (\n\t\t<ControlledCopilot\n\t\t\t{...shellProps}\n\t\t\topen={open}\n\t\t\tdefaultOpen={defaultOpen}\n\t\t\tonOpenChange={handleOpenChange}\n\t\t\tmessages={messages}\n\t\t\tonSendMessage={sendMessage}\n\t\t\tisThinking={isThinking}\n\t\t\tisStreaming={isStreaming}\n\t\t\tonStop={stopStreaming}\n\t\t\tisLoadingHistory={isLoadingHistory}\n\t\t\thasMoreHistory={hasMoreHistory}\n\t\t\tonLoadOlderMessages={loadOlderMessages}\n\t\t\terrorMessage={error}\n\t\t\t// An explicit list wins; otherwise the route's fetched prompts show. A\n\t\t\t// failed or empty fetch simply leaves the empty state without chips.\n\t\t\tsuggestions={suggestions ?? icebreakers}\n\t\t\t// A second prompt mid-stream would race the thread's responseId.\n\t\t\tinputDisabled={inputDisabled || isRestoring || isStreaming}\n\t\t\tonRefresh={handleRefresh}\n\t\t/>\n\t);\n};\n\nexport default BIKCopilot;\n"],"names":["BIKCopilot","baseUrl","endpointPath","icebreakersPath","headers","authToken","getAuthToken","fetchImpl","storeId","agent","route","email","systemPrompt","model","maxOutputTokens","sessionId","persist","loadIcebreakers","onError","onResponseComplete","onSessionIdChange","suggestions","inputDisabled","onRefresh","open","defaultOpen","onOpenChange","shellProps","hasOpened","setHasOpened","useState","messages","isThinking","isStreaming","isRestoring","error","isLoadingHistory","hasMoreHistory","sendMessage","loadOlderMessages","stopStreaming","startNewConversation","useCopilotStreamChat","icebreakers","useCopilotIcebreakers","handleOpenChange","useCallback","nextOpen","handleRefresh","jsx","ControlledCopilot"],"mappings":"2PAkCaA,EAAwC,CAAC,CAErD,QAAAC,EACA,aAAAC,EACA,gBAAAC,EACA,QAAAC,EACA,UAAAC,EACA,aAAAC,EACA,UAAAC,EACA,QAAAC,EACA,MAAAC,EACA,MAAAC,EACA,MAAAC,EACA,aAAAC,EACA,MAAAC,EACA,gBAAAC,EACA,UAAAC,EACA,QAAAC,EACA,gBAAAC,EAAkB,GAClB,QAAAC,EACA,mBAAAC,EACA,kBAAAC,EAEA,YAAAC,EACA,cAAAC,EACA,UAAAC,EACA,KAAAC,EACA,YAAAC,EACA,aAAAC,EACA,GAAGC,CACJ,IAAM,CAGL,KAAM,CAACC,EAAWC,CAAY,EAAIC,EAAAA,SACjCL,IAAgB,IAAQD,IAAS,EAAA,EAG5B,CACL,SAAAO,EACA,WAAAC,EACA,YAAAC,EACA,YAAAC,EACA,MAAAC,EACA,iBAAAC,EACA,eAAAC,EACA,YAAAC,EACA,kBAAAC,EACA,cAAAC,EACA,qBAAAC,CAAA,EACGC,uBAAqB,CACxB,QAAAzC,EACA,aAAAC,EACA,QAAAE,EACA,UAAAC,EACA,aAAAC,EACA,UAAAC,EACA,QAAAC,EACA,MAAAC,EACA,MAAAC,EACA,MAAAC,EACA,aAAAC,EACA,MAAAC,EACA,gBAAAC,EACA,UAAAC,EACA,QAAAC,EACA,QAAAE,EACA,mBAAAC,EACA,kBAAAC,CAAA,CACA,EAEK,CAAE,YAAAuB,CAAA,EAAgBC,wBAAsB,CAC7C,QAAA3C,EACA,gBAAAE,EACA,QAAAC,EACA,UAAAC,EACA,aAAAC,EACA,UAAAC,EACA,MAAAE,EACA,MAAAC,EACA,QAAAF,EACA,QAASS,GAAmBW,CAAA,CAC5B,EAEKiB,EAAmBC,EAAAA,YACvBC,GAAsB,CAClBA,GACHlB,EAAa,EAAI,EAElBH,IAAeqB,CAAQ,CACxB,EACA,CAACrB,CAAY,CAAA,EAGRsB,EAAgBF,EAAAA,YAAY,IAAM,CACvCL,EAAA,EACAlB,IAAA,CACD,EAAG,CAACA,EAAWkB,CAAoB,CAAC,EAEpC,OACCQ,EAAAA,IAACC,EAAAA,kBAAA,CACC,GAAGvB,EACJ,KAAAH,EACA,YAAAC,EACA,aAAcoB,EACd,SAAAd,EACA,cAAeO,EACf,WAAAN,EACA,YAAAC,EACA,OAAQO,EACR,iBAAAJ,EACA,eAAAC,EACA,oBAAqBE,EACrB,aAAcJ,EAGd,YAAad,GAAesB,EAE5B,cAAerB,GAAiBY,GAAeD,EAC/C,UAAWe,CAAA,CAAA,CAGd"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),n=require("react"),fe=require("../../constants/Theme.js"),pe=require("./ControlledCopilot.styled.js"),v=require("./CopilotBall.js"),ge=require("./CopilotPanel.js"),Ce=require("./copilotPlacement.js"),me=require("./useDraggableFloater.js"),he=({messages:P,onSendMessage:b,isThinking:w=!1,thinkingLabel:L,isStreaming:q=!1,onStop:E,interruptedLabel:k,followUpsLabel:y,hasMoreHistory:T=!1,isLoadingHistory:j=!1,onLoadOlderMessages:O,historyLoadingLabel:R,errorMessage:$,ballSize:s=56,corner:x="bottom-right",offset:B=24,initialPosition:D,draggable:u=!0,snapToEdge:I=!0,onPositionChange:F,ballIcon:S,ballOpenIcon:_,ballColor:A=fe.COLORS.background.brand,zIndex:d=1200,ballAriaLabel:U,panelWidth:z=380,panelHeight:H=540,panelGap:K=12,title:M="Copilot",badge:G,subtitle:J,avatar:N,placeholder:Q,disclaimer:V,emptyStateTitle:W,emptyStateSubtitle:X,suggestions:Y,onSuggestionClick:Z,showRefresh:ee=!0,onRefresh:te,inputDisabled:oe=!1,open:f,defaultOpen:ne=!1,onOpenChange:p,closeOnClickOutside:g=!1,className:re,style:le})=>{const[se,ie]=n.useState(ne),C=n.useRef(null),i=f!==void 0,e=i?f:se,o=n.useCallback(t=>{i||ie(t),p?.(t)},[i,p]),{position:m,isDragging:ae,viewport:ce,dragHandlers:ue,shouldIgnoreClick:h}=me.useDraggableFloater({size:s,corner:x,offset:B,enabled:u,snapToEdge:I,initialPosition:D,onPositionChange:F}),de=n.useCallback(()=>{h()||o(!e)},[e,o,h]);n.useEffect(()=>{if(!e)return;const t=a=>{a.key==="Escape"&&o(!1)};return document.addEventListener("keydown",t),()=>document.removeEventListener("keydown",t)},[e,o]),n.useEffect(()=>{if(!e||!g)return;const t=a=>{const c=a.target;c&&(C.current?.contains(c)||c.closest(`[${v.COPILOT_BALL_ATTRIBUTE}]`)||o(!1))};return document.addEventListener("pointerdown",t),()=>document.removeEventListener("pointerdown",t)},[g,e,o]);const l=Ce.getCopilotPanelPlacement({ballPosition:m,ballSize:s,panelWidth:z,panelHeight:H,gap:K,viewport:ce});return r.jsxs(r.Fragment,{children:[e&&r.jsx(pe.PanelPositioner,{ref:C,$left:l.left,$top:l.top,$width:l.width,$height:l.height,$zIndex:d,children:r.jsx(ge.CopilotPanel,{messages:P,onSend:b,onClose:()=>o(!1),title:M,badge:G,subtitle:J,avatar:N,placeholder:Q,disclaimer:V,emptyStateTitle:W,emptyStateSubtitle:X,suggestions:Y,onSuggestionClick:Z,showRefresh:ee,onRefresh:te,isThinking:w,thinkingLabel:L,isStreaming:q,onStop:E,interruptedLabel:k,followUpsLabel:y,hasMoreHistory:T,isLoadingHistory:j,onLoadOlderMessages:O,historyLoadingLabel:R,inputDisabled:oe,errorMessage:$,className:re,style:le})}),r.jsx(v.CopilotBall,{isOpen:e,onToggle:de,position:m,size:s,isDragging:ae,draggable:u,color:A,zIndex:d+1,icon:S,openIcon:_,ariaLabel:U,...ue})]})};exports.ControlledCopilot=he;
|
|
2
|
+
//# sourceMappingURL=ControlledCopilot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ControlledCopilot.js","sources":["../../../../src/components/bik-copilot/ControlledCopilot.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { COLORS } from '@src/constants/Theme';\nimport { PanelPositioner } from './ControlledCopilot.styled';\nimport { COPILOT_BALL_ATTRIBUTE, CopilotBall } from './CopilotBall';\nimport { CopilotPanel } from './CopilotPanel';\nimport { getCopilotPanelPlacement } from './copilotPlacement';\nimport { ControlledCopilotProps } from './model';\nimport { useDraggableFloater } from './useDraggableFloater';\n\n/**\n * The presentational half of the copilot: a draggable floating ball that opens a\n * chat panel beside it.\n *\n * Fully controlled — it renders the `messages` it is handed and reports every\n * user action through callbacks, so it carries no backend knowledge. **Use\n * `BIKCopilot` instead** unless you are wiring a backend other than\n * `/bik-ai/copilot-chatbot`; `BIKCopilot` is this component plus the streaming\n * transport, IndexedDB history and route-aware ice breakers.\n */\nexport const ControlledCopilot: React.FC<ControlledCopilotProps> = ({\n\t// Conversation\n\tmessages,\n\tonSendMessage,\n\tisThinking = false,\n\tthinkingLabel,\n\tisStreaming = false,\n\tonStop,\n\tinterruptedLabel,\n\tfollowUpsLabel,\n\thasMoreHistory = false,\n\tisLoadingHistory = false,\n\tonLoadOlderMessages,\n\thistoryLoadingLabel,\n\terrorMessage,\n\t// Ball\n\tballSize = 56,\n\tcorner = 'bottom-right',\n\toffset = 24,\n\tinitialPosition,\n\tdraggable = true,\n\tsnapToEdge = true,\n\tonPositionChange,\n\tballIcon,\n\tballOpenIcon,\n\tballColor = COLORS.background.brand,\n\tzIndex = 1200,\n\tballAriaLabel,\n\t// Panel\n\tpanelWidth = 380,\n\tpanelHeight = 540,\n\tpanelGap = 12,\n\ttitle = 'Copilot',\n\tbadge,\n\tsubtitle,\n\tavatar,\n\tplaceholder,\n\tdisclaimer,\n\temptyStateTitle,\n\temptyStateSubtitle,\n\tsuggestions,\n\tonSuggestionClick,\n\tshowRefresh = true,\n\tonRefresh,\n\tinputDisabled = false,\n\t// Open state\n\topen,\n\tdefaultOpen = false,\n\tonOpenChange,\n\tcloseOnClickOutside = false,\n\tclassName,\n\tstyle,\n}) => {\n\tconst [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n\tconst panelRef = useRef<HTMLDivElement>(null);\n\n\tconst isControlled = open !== undefined;\n\tconst isOpen = isControlled ? open : uncontrolledOpen;\n\n\tconst setOpen = useCallback(\n\t\t(next: boolean) => {\n\t\t\tif (!isControlled) {\n\t\t\t\tsetUncontrolledOpen(next);\n\t\t\t}\n\t\t\tonOpenChange?.(next);\n\t\t},\n\t\t[isControlled, onOpenChange],\n\t);\n\n\tconst { position, isDragging, viewport, dragHandlers, shouldIgnoreClick } =\n\t\tuseDraggableFloater({\n\t\t\tsize: ballSize,\n\t\t\tcorner,\n\t\t\toffset,\n\t\t\tenabled: draggable,\n\t\t\tsnapToEdge,\n\t\t\tinitialPosition,\n\t\t\tonPositionChange,\n\t\t});\n\n\tconst handleBallClick = useCallback(() => {\n\t\t// The click that ends a drag gesture must not toggle the panel.\n\t\tif (shouldIgnoreClick()) {\n\t\t\treturn;\n\t\t}\n\t\tsetOpen(!isOpen);\n\t}, [isOpen, setOpen, shouldIgnoreClick]);\n\n\t// Escape closes the panel.\n\tuseEffect(() => {\n\t\tif (!isOpen) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst handleKeyDown = (event: KeyboardEvent) => {\n\t\t\tif (event.key === 'Escape') {\n\t\t\t\tsetOpen(false);\n\t\t\t}\n\t\t};\n\t\tdocument.addEventListener('keydown', handleKeyDown);\n\t\treturn () => document.removeEventListener('keydown', handleKeyDown);\n\t}, [isOpen, setOpen]);\n\n\tuseEffect(() => {\n\t\tif (!isOpen || !closeOnClickOutside) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst handlePointerDown = (event: PointerEvent) => {\n\t\t\tconst target = event.target as HTMLElement | null;\n\t\t\tif (!target) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (panelRef.current?.contains(target)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (target.closest(`[${COPILOT_BALL_ATTRIBUTE}]`)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsetOpen(false);\n\t\t};\n\t\tdocument.addEventListener('pointerdown', handlePointerDown);\n\t\treturn () => document.removeEventListener('pointerdown', handlePointerDown);\n\t}, [closeOnClickOutside, isOpen, setOpen]);\n\n\tconst placement = getCopilotPanelPlacement({\n\t\tballPosition: position,\n\t\tballSize,\n\t\tpanelWidth,\n\t\tpanelHeight,\n\t\tgap: panelGap,\n\t\tviewport,\n\t});\n\n\treturn (\n\t\t<>\n\t\t\t{isOpen && (\n\t\t\t\t<PanelPositioner\n\t\t\t\t\tref={panelRef}\n\t\t\t\t\t$left={placement.left}\n\t\t\t\t\t$top={placement.top}\n\t\t\t\t\t$width={placement.width}\n\t\t\t\t\t$height={placement.height}\n\t\t\t\t\t$zIndex={zIndex}\n\t\t\t\t>\n\t\t\t\t\t<CopilotPanel\n\t\t\t\t\t\tmessages={messages}\n\t\t\t\t\t\tonSend={onSendMessage}\n\t\t\t\t\t\tonClose={() => setOpen(false)}\n\t\t\t\t\t\ttitle={title}\n\t\t\t\t\t\tbadge={badge}\n\t\t\t\t\t\tsubtitle={subtitle}\n\t\t\t\t\t\tavatar={avatar}\n\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\tdisclaimer={disclaimer}\n\t\t\t\t\t\temptyStateTitle={emptyStateTitle}\n\t\t\t\t\t\temptyStateSubtitle={emptyStateSubtitle}\n\t\t\t\t\t\tsuggestions={suggestions}\n\t\t\t\t\t\tonSuggestionClick={onSuggestionClick}\n\t\t\t\t\t\tshowRefresh={showRefresh}\n\t\t\t\t\t\tonRefresh={onRefresh}\n\t\t\t\t\t\tisThinking={isThinking}\n\t\t\t\t\t\tthinkingLabel={thinkingLabel}\n\t\t\t\t\t\tisStreaming={isStreaming}\n\t\t\t\t\t\tonStop={onStop}\n\t\t\t\t\t\tinterruptedLabel={interruptedLabel}\n\t\t\t\t\t\tfollowUpsLabel={followUpsLabel}\n\t\t\t\t\t\thasMoreHistory={hasMoreHistory}\n\t\t\t\t\t\tisLoadingHistory={isLoadingHistory}\n\t\t\t\t\t\tonLoadOlderMessages={onLoadOlderMessages}\n\t\t\t\t\t\thistoryLoadingLabel={historyLoadingLabel}\n\t\t\t\t\t\tinputDisabled={inputDisabled}\n\t\t\t\t\t\terrorMessage={errorMessage}\n\t\t\t\t\t\tclassName={className}\n\t\t\t\t\t\tstyle={style}\n\t\t\t\t\t/>\n\t\t\t\t</PanelPositioner>\n\t\t\t)}\n\n\t\t\t<CopilotBall\n\t\t\t\tisOpen={isOpen}\n\t\t\t\tonToggle={handleBallClick}\n\t\t\t\tposition={position}\n\t\t\t\tsize={ballSize}\n\t\t\t\tisDragging={isDragging}\n\t\t\t\tdraggable={draggable}\n\t\t\t\tcolor={ballColor}\n\t\t\t\tzIndex={zIndex + 1}\n\t\t\t\ticon={ballIcon}\n\t\t\t\topenIcon={ballOpenIcon}\n\t\t\t\tariaLabel={ballAriaLabel}\n\t\t\t\t{...dragHandlers}\n\t\t\t/>\n\t\t</>\n\t);\n};\n\nexport default ControlledCopilot;\n"],"names":["ControlledCopilot","messages","onSendMessage","isThinking","thinkingLabel","isStreaming","onStop","interruptedLabel","followUpsLabel","hasMoreHistory","isLoadingHistory","onLoadOlderMessages","historyLoadingLabel","errorMessage","ballSize","corner","offset","initialPosition","draggable","snapToEdge","onPositionChange","ballIcon","ballOpenIcon","ballColor","COLORS","zIndex","ballAriaLabel","panelWidth","panelHeight","panelGap","title","badge","subtitle","avatar","placeholder","disclaimer","emptyStateTitle","emptyStateSubtitle","suggestions","onSuggestionClick","showRefresh","onRefresh","inputDisabled","open","defaultOpen","onOpenChange","closeOnClickOutside","className","style","uncontrolledOpen","setUncontrolledOpen","useState","panelRef","useRef","isControlled","isOpen","setOpen","useCallback","next","position","isDragging","viewport","dragHandlers","shouldIgnoreClick","useDraggableFloater","handleBallClick","useEffect","handleKeyDown","event","handlePointerDown","target","COPILOT_BALL_ATTRIBUTE","placement","getCopilotPanelPlacement","jsxs","Fragment","jsx","PanelPositioner","CopilotPanel","CopilotBall"],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("styled-components"),o=t=>t&&typeof t=="object"&&"default"in t?t:{default:t},i=o(e),a=i.default.div`
|
|
2
|
+
position: fixed;
|
|
3
|
+
left: ${t=>t.$left}px;
|
|
4
|
+
top: ${t=>t.$top}px;
|
|
5
|
+
width: ${t=>t.$width}px;
|
|
6
|
+
height: ${t=>t.$height}px;
|
|
7
|
+
z-index: ${t=>t.$zIndex};
|
|
8
|
+
display: flex;
|
|
9
|
+
animation: bikCopilotPanelIn 0.16s ease-out;
|
|
10
|
+
|
|
11
|
+
> * {
|
|
12
|
+
flex: 1;
|
|
13
|
+
min-width: 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@keyframes bikCopilotPanelIn {
|
|
17
|
+
from {
|
|
18
|
+
opacity: 0;
|
|
19
|
+
transform: translateY(6px) scale(0.98);
|
|
20
|
+
}
|
|
21
|
+
to {
|
|
22
|
+
opacity: 1;
|
|
23
|
+
transform: translateY(0) scale(1);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
`;exports.PanelPositioner=a;
|
|
27
|
+
//# sourceMappingURL=ControlledCopilot.styled.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ControlledCopilot.styled.js","sources":["../../../../src/components/bik-copilot/ControlledCopilot.styled.ts"],"sourcesContent":["import styled from 'styled-components';\n\nexport const PanelPositioner = styled.div<{\n\t$left: number;\n\t$top: number;\n\t$width: number;\n\t$height: number;\n\t$zIndex: number;\n}>`\n\tposition: fixed;\n\tleft: ${(props) => props.$left}px;\n\ttop: ${(props) => props.$top}px;\n\twidth: ${(props) => props.$width}px;\n\theight: ${(props) => props.$height}px;\n\tz-index: ${(props) => props.$zIndex};\n\tdisplay: flex;\n\tanimation: bikCopilotPanelIn 0.16s ease-out;\n\n\t> * {\n\t\tflex: 1;\n\t\tmin-width: 0;\n\t}\n\n\t@keyframes bikCopilotPanelIn {\n\t\tfrom {\n\t\t\topacity: 0;\n\t\t\ttransform: translateY(6px) scale(0.98);\n\t\t}\n\t\tto {\n\t\t\topacity: 1;\n\t\t\ttransform: translateY(0) scale(1);\n\t\t}\n\t}\n`;\n"],"names":["PanelPositioner","styled","props"],"mappings":"oLAEaA,EAAkBC,EAAAA,QAAO;AAAA;AAAA,SAQ5BC,GAAUA,EAAM,KAAK;AAAA,QACtBA,GAAUA,EAAM,IAAI;AAAA,UAClBA,GAAUA,EAAM,MAAM;AAAA,WACrBA,GAAUA,EAAM,OAAO;AAAA,YACtBA,GAAUA,EAAM,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),I=require("../../assets/icons/bik_ai_stars_icon.svg.js"),$=require("../../assets/icons/chevronDown.svg.js"),p=require("./CopilotBall.styled.js"),n="data-bik-copilot-ball",L=({isOpen:o,onToggle:r,position:l,size:i,isDragging:c,draggable:s,color:u,zIndex:d,icon:g,openIcon:h,ariaLabel:B,onPointerDown:T,onPointerMove:b,onPointerUp:_,onPointerCancel:x})=>{const t=Math.round(i*.42),a=o?e.jsx($.default,{width:t,height:t}):e.jsx(I.default,{width:t,height:t}),C=o?h??a:g??a;return e.jsx(p.BallButton,{type:"button",[n]:"true",$size:i,$left:l.x,$top:l.y,$color:u,$zIndex:d,$isDragging:c,$draggable:s,"aria-label":B||"Copilot","aria-expanded":o,onClick:r,onPointerDown:T,onPointerMove:b,onPointerUp:_,onPointerCancel:x,children:C})};exports.COPILOT_BALL_ATTRIBUTE=n;exports.CopilotBall=L;
|
|
2
|
+
//# sourceMappingURL=CopilotBall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CopilotBall.js","sources":["../../../../src/components/bik-copilot/CopilotBall.tsx"],"sourcesContent":["import AiStarsIcon from '@src/assets/icons/bik_ai_stars_icon.svg';\nimport ChevronDownIcon from '@src/assets/icons/chevronDown.svg';\nimport React from 'react';\nimport { BallButton } from './CopilotBall.styled';\nimport { CopilotBallProps } from './model';\n\n/**\n * Marks the ball in the DOM so an outside-click handler can tell the ball apart\n * from the rest of the page and not fight the ball's own toggle.\n */\nexport const COPILOT_BALL_ATTRIBUTE = 'data-bik-copilot-ball';\n\n/**\n * The floating ball that opens the copilot panel. Purely presentational — the\n * drag gesture lives in `useDraggableFloater` and is passed in as handlers.\n */\nexport const CopilotBall: React.FC<CopilotBallProps> = ({\n\tisOpen,\n\tonToggle,\n\tposition,\n\tsize,\n\tisDragging,\n\tdraggable,\n\tcolor,\n\tzIndex,\n\ticon,\n\topenIcon,\n\tariaLabel,\n\tonPointerDown,\n\tonPointerMove,\n\tonPointerUp,\n\tonPointerCancel,\n}) => {\n\tconst iconSize = Math.round(size * 0.42);\n\tconst defaultIcon = isOpen ? (\n\t\t<ChevronDownIcon width={iconSize} height={iconSize} />\n\t) : (\n\t\t<AiStarsIcon width={iconSize} height={iconSize} />\n\t);\n\tconst activeIcon = isOpen ? openIcon ?? defaultIcon : icon ?? defaultIcon;\n\n\treturn (\n\t\t<BallButton\n\t\t\ttype=\"button\"\n\t\t\t{...{ [COPILOT_BALL_ATTRIBUTE]: 'true' }}\n\t\t\t$size={size}\n\t\t\t$left={position.x}\n\t\t\t$top={position.y}\n\t\t\t$color={color}\n\t\t\t$zIndex={zIndex}\n\t\t\t$isDragging={isDragging}\n\t\t\t$draggable={draggable}\n\t\t\t/* A disclosure button keeps a stable name and reports its state through\n\t\t\t aria-expanded, so this must not become \"Open/Close copilot\" — that\n\t\t\t would also collide with the panel's own close button. */\n\t\t\taria-label={ariaLabel || 'Copilot'}\n\t\t\taria-expanded={isOpen}\n\t\t\tonClick={onToggle}\n\t\t\tonPointerDown={onPointerDown}\n\t\t\tonPointerMove={onPointerMove}\n\t\t\tonPointerUp={onPointerUp}\n\t\t\tonPointerCancel={onPointerCancel}\n\t\t>\n\t\t\t{activeIcon}\n\t\t</BallButton>\n\t);\n};\n\nexport default CopilotBall;\n"],"names":["COPILOT_BALL_ATTRIBUTE","CopilotBall","isOpen","onToggle","position","size","isDragging","draggable","color","zIndex","icon","openIcon","ariaLabel","onPointerDown","onPointerMove","onPointerUp","onPointerCancel","iconSize","defaultIcon","jsx","ChevronDownIcon","AiStarsIcon","activeIcon","BallButton"],"mappings":"sQAUaA,EAAyB,wBAMzBC,EAA0C,CAAC,CACvD,OAAAC,EACA,SAAAC,EACA,SAAAC,EACA,KAAAC,EACA,WAAAC,EACA,UAAAC,EACA,MAAAC,EACA,OAAAC,EACA,KAAAC,EACA,SAAAC,EACA,UAAAC,EACA,cAAAC,EACA,cAAAC,EACA,YAAAC,EACA,gBAAAC,CACD,IAAM,CACL,MAAMC,EAAW,KAAK,MAAMZ,EAAO,GAAI,EACjCa,EAAchB,EACnBiB,EAAAA,IAACC,EAAAA,QAAA,CAAgB,MAAOH,EAAU,OAAQA,CAAA,CAAU,EAEpDE,EAAAA,IAACE,UAAA,CAAY,MAAOJ,EAAU,OAAQA,EAAU,EAE3CK,EAAapB,EAASS,GAAYO,EAAcR,GAAQQ,EAE9D,OACCC,EAAAA,IAACI,EAAAA,WAAA,CACA,KAAK,SACC,CAACvB,CAAsB,EAAG,OAChC,MAAOK,EACP,MAAOD,EAAS,EAChB,KAAMA,EAAS,EACf,OAAQI,EACR,QAASC,EACT,YAAaH,EACb,WAAYC,EAIZ,aAAYK,GAAa,UACzB,gBAAeV,EACf,QAASC,EACT,cAAAU,EACA,cAAAC,EACA,YAAAC,EACA,gBAAAC,EAEC,SAAAM,CAAA,CAAA,CAGJ"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("styled-components"),o=e=>e&&typeof e=="object"&&"default"in e?e:{default:e},s=o(t),n=s.default.button`
|
|
2
|
+
position: fixed;
|
|
3
|
+
left: ${e=>e.$left}px;
|
|
4
|
+
top: ${e=>e.$top}px;
|
|
5
|
+
width: ${e=>e.$size}px;
|
|
6
|
+
height: ${e=>e.$size}px;
|
|
7
|
+
z-index: ${e=>e.$zIndex};
|
|
8
|
+
|
|
9
|
+
display: flex;
|
|
10
|
+
align-items: center;
|
|
11
|
+
justify-content: center;
|
|
12
|
+
padding: 0;
|
|
13
|
+
border: none;
|
|
14
|
+
border-radius: 50%;
|
|
15
|
+
background: ${e=>e.$color};
|
|
16
|
+
color: #ffffff;
|
|
17
|
+
box-shadow: ${e=>e.$isDragging?"0 12px 32px rgba(40, 3, 78, 0.36)":"0 6px 20px rgba(40, 3, 78, 0.24)"};
|
|
18
|
+
|
|
19
|
+
cursor: ${e=>e.$isDragging?"grabbing":e.$draggable?"grab":"pointer"};
|
|
20
|
+
touch-action: none;
|
|
21
|
+
user-select: none;
|
|
22
|
+
-webkit-user-select: none;
|
|
23
|
+
|
|
24
|
+
/* Position changes animate on release but must track the pointer 1:1 while
|
|
25
|
+
the user is dragging. */
|
|
26
|
+
transition: ${e=>e.$isDragging?"box-shadow 0.15s ease, transform 0.15s ease":"left 0.22s ease, top 0.22s ease, box-shadow 0.15s ease, transform 0.15s ease"};
|
|
27
|
+
transform: ${e=>e.$isDragging?"scale(1.06)":"scale(1)"};
|
|
28
|
+
|
|
29
|
+
&:hover {
|
|
30
|
+
transform: scale(1.06);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&:focus-visible {
|
|
34
|
+
outline: 2px solid #ffffff;
|
|
35
|
+
outline-offset: 2px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
svg {
|
|
39
|
+
pointer-events: none;
|
|
40
|
+
}
|
|
41
|
+
`;exports.BallButton=n;
|
|
42
|
+
//# sourceMappingURL=CopilotBall.styled.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CopilotBall.styled.js","sources":["../../../../src/components/bik-copilot/CopilotBall.styled.ts"],"sourcesContent":["import styled from 'styled-components';\n\nexport const BallButton = styled.button<{\n\t$size: number;\n\t$left: number;\n\t$top: number;\n\t$color: string;\n\t$zIndex: number;\n\t$isDragging: boolean;\n\t$draggable: boolean;\n}>`\n\tposition: fixed;\n\tleft: ${(props) => props.$left}px;\n\ttop: ${(props) => props.$top}px;\n\twidth: ${(props) => props.$size}px;\n\theight: ${(props) => props.$size}px;\n\tz-index: ${(props) => props.$zIndex};\n\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tpadding: 0;\n\tborder: none;\n\tborder-radius: 50%;\n\tbackground: ${(props) => props.$color};\n\tcolor: #ffffff;\n\tbox-shadow: ${(props) =>\n\t\tprops.$isDragging\n\t\t\t? '0 12px 32px rgba(40, 3, 78, 0.36)'\n\t\t\t: '0 6px 20px rgba(40, 3, 78, 0.24)'};\n\n\tcursor: ${(props) =>\n\t\tprops.$isDragging ? 'grabbing' : props.$draggable ? 'grab' : 'pointer'};\n\ttouch-action: none;\n\tuser-select: none;\n\t-webkit-user-select: none;\n\n\t/* Position changes animate on release but must track the pointer 1:1 while\n\t the user is dragging. */\n\ttransition: ${(props) =>\n\t\tprops.$isDragging\n\t\t\t? 'box-shadow 0.15s ease, transform 0.15s ease'\n\t\t\t: 'left 0.22s ease, top 0.22s ease, box-shadow 0.15s ease, transform 0.15s ease'};\n\ttransform: ${(props) => (props.$isDragging ? 'scale(1.06)' : 'scale(1)')};\n\n\t&:hover {\n\t\ttransform: scale(1.06);\n\t}\n\n\t&:focus-visible {\n\t\toutline: 2px solid #ffffff;\n\t\toutline-offset: 2px;\n\t}\n\n\tsvg {\n\t\tpointer-events: none;\n\t}\n`;\n"],"names":["BallButton","styled","props"],"mappings":"oLAEaA,EAAaC,EAAAA,QAAO;AAAA;AAAA,SAUvBC,GAAUA,EAAM,KAAK;AAAA,QACtBA,GAAUA,EAAM,IAAI;AAAA,UAClBA,GAAUA,EAAM,KAAK;AAAA,WACpBA,GAAUA,EAAM,KAAK;AAAA,YACpBA,GAAUA,EAAM,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAQpBA,GAAUA,EAAM,MAAM;AAAA;AAAA,eAEtBA,GACdA,EAAM,YACH,oCACA,kCAAkC;AAAA;AAAA,WAE3BA,GACVA,EAAM,YAAc,WAAaA,EAAM,WAAa,OAAS,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAOxDA,GACdA,EAAM,YACH,8CACA,8EAA8E;AAAA,cACpEA,GAAWA,EAAM,YAAc,cAAgB,UAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),x=require("../../assets/icons/bik_ai_stars_icon.svg.js"),je=require("../../assets/icons/cross.svg.js"),pe=require("../../assets/icons/refresh.svg.js"),s=require("react"),a=require("../../constants/Theme.js"),fe=require("../bik-chatbot/utils/markdown.js"),j=require("../TypographyStyle.js"),r=require("./CopilotPanel.styled.js"),X=require("../dot-pulse/DotPulse.js"),ge=n=>n&&typeof n=="object"&&"default"in n?n:{default:n},we=ge(s),ye=96,Ce=24,Se=48,me=()=>e.jsxs("svg",{viewBox:"0 0 24 24",width:"16",height:"16",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[e.jsx("path",{d:"M12 19V5"}),e.jsx("path",{d:"M6 11l6-6 6 6"})]}),Ie=()=>e.jsxs("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[e.jsx("path",{d:"M5 12h14"}),e.jsx("path",{d:"M13 6l6 6-6 6"})]}),D=({size:n=16})=>e.jsx("svg",{viewBox:"0 0 24 24",width:n,height:n,fill:"currentColor","aria-hidden":"true",children:e.jsx("rect",{x:"7",y:"7",width:"10",height:"10",rx:"2"})}),Te=()=>e.jsx("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:e.jsx("path",{d:"M6 9l6 6 6-6"})}),ke=({messages:n,onSend:p,onClose:K,title:f="Copilot",badge:b,subtitle:R,avatar:z,placeholder:J="Write your message...",disclaimer:B="AI can make mistakes, Verify the responses.",emptyStateTitle:G,emptyStateSubtitle:L="Here are some things you can try",suggestions:g,onSuggestionClick:Q,showRefresh:Y=!0,onRefresh:_,isThinking:h=!1,thinkingLabel:A="Thinking",isStreaming:Z=!1,onStop:M,interruptedLabel:O="This message was interrupted",followUpsLabel:F="Follow ups",hasMoreHistory:ee=!1,isLoadingHistory:d=!1,onLoadOlderMessages:P,historyLoadingLabel:te="Loading earlier messages",inputDisabled:l=!1,errorMessage:E,width:re,height:ne,className:oe,style:se})=>{const[w,H]=s.useState(""),[le,q]=s.useState(!1),[y,C]=s.useState(!0),W=s.useRef(null),S=s.useRef(null),m=s.useRef(null),I=s.useRef(0),T=s.useRef(null),u=n.filter(t=>t.content.length>0||t.wasInterrupted),$=u.length===0&&!h,c=h||Z,N=!l&&!c&&w.trim().length>0,i=c&&!!M,U=u[u.length-1],k=!c&&U?.role==="assistant"?U.followUps:void 0,v=!$&&!y;s.useEffect(()=>{y&&S.current?.scrollIntoView({behavior:"smooth"})},[n,h,y]),s.useEffect(()=>{const t=m.current,o=T.current;!t||o===null||d||(T.current=null,t.scrollTop=t.scrollHeight-o,I.current=t.scrollTop)},[n,d]);const ce=()=>{const t=m.current;if(!t)return;const o=t.scrollHeight-t.scrollTop-t.clientHeight;t.scrollTop<=Se&&ee&&!d&&P&&(T.current=t.scrollHeight-t.scrollTop,P());const xe=t.scrollTop<I.current-1;if(I.current=t.scrollTop,o<=Ce){C(!0);return}xe&&C(!1)},ie=()=>{C(!0),S.current?.scrollIntoView({behavior:"smooth"})},V=()=>{const t=w.trim();if(!t||l||c)return;p(t),H("");const o=W.current;o&&(o.style.height="auto")},ae=t=>{H(t.target.value);const o=t.target;o.style.height="auto",o.style.height=`${Math.min(o.scrollHeight,ye)}px`},he=t=>{t.key==="Enter"&&!t.shiftKey&&(t.preventDefault(),V())},de=t=>{l||c||(Q?.(t),p(t.text))},ue=t=>{l||c||p(t)};return e.jsxs(r.PanelContainer,{className:oe,style:{width:re,height:ne,...se},role:"dialog","aria-label":f,children:[e.jsxs(r.PanelHeader,{children:[e.jsx(r.HeaderAvatar,{children:z??e.jsx(x.default,{width:18,height:18})}),e.jsxs(r.HeaderText,{children:[e.jsxs(r.HeaderTitleRow,{children:[e.jsx(j.TitleSmall,{children:f}),b&&e.jsx(r.HeaderBadge,{children:b})]}),R&&e.jsx(j.BodyCaption,{color:a.COLORS.content.secondary,children:R})]}),e.jsxs(r.HeaderActions,{children:[Y&&_&&e.jsx(r.IconAction,{type:"button",onClick:_,"aria-label":"Start a new conversation",children:e.jsx(pe.default,{width:16,height:16})}),e.jsx(r.IconAction,{type:"button",onClick:K,"aria-label":"Close copilot",children:e.jsx(je.default,{width:18,height:18})})]})]}),e.jsxs(r.MessagesViewport,{children:[e.jsx(r.MessagesArea,{ref:m,onScroll:ce,role:"region","aria-label":"Conversation",children:$?e.jsxs(r.EmptyState,{children:[e.jsx(r.EmptyStateIcon,{children:e.jsx(x.default,{width:28,height:28})}),e.jsx(j.BodySecondary,{style:{fontWeight:600},children:G||f}),L&&e.jsx(j.BodyCaption,{color:a.COLORS.content.secondary,children:L}),g&&g.length>0&&e.jsx(r.SuggestionList,{children:g.map(t=>e.jsxs(r.SuggestionChip,{type:"button",disabled:l||c,onClick:()=>de(t),children:[e.jsx(x.default,{width:14,height:14}),t.text]},t.id))})]}):e.jsxs(e.Fragment,{children:[d&&e.jsxs(r.HistoryLoader,{role:"status","aria-live":"polite",children:[e.jsx(X.DotPulse,{color:a.COLORS.content.placeholder,size:4}),te]}),u.map(t=>e.jsxs(we.default.Fragment,{children:[t.content.length>0&&e.jsx(r.MessageBubble,{$role:t.role,children:t.role==="assistant"?e.jsx("div",{dangerouslySetInnerHTML:{__html:fe.renderMarkdownLite(t.content)}}):e.jsx("div",{style:{whiteSpace:"pre-wrap"},children:t.content})}),t.wasInterrupted&&O&&e.jsxs(r.InterruptedNote,{children:[e.jsx(D,{size:12}),O]})]},t.id)),k&&k.length>0&&e.jsxs(r.FollowUpList,{children:[F&&e.jsx(r.FollowUpsLabel,{children:F}),k.map(t=>e.jsxs(r.FollowUpChip,{type:"button",disabled:l,onClick:()=>ue(t),children:[e.jsx(Ie,{}),t]},t))]}),h&&e.jsxs(r.ThinkingBubble,{role:"status","aria-live":"polite",children:[e.jsx(x.default,{width:14,height:14,color:a.COLORS.content.brand}),A&&e.jsx(r.ThinkingLabel,{children:A}),e.jsx(X.DotPulse,{color:a.COLORS.background.brand,size:5})]}),e.jsx("div",{ref:S})]})}),e.jsx(r.ScrollFade,{$visible:v,"aria-hidden":"true"}),e.jsx(r.JumpToLatestButton,{type:"button",$visible:v,onClick:ie,tabIndex:v?0:-1,"aria-label":"Scroll to the latest message",children:e.jsx(Te,{})})]}),E&&e.jsx(r.ErrorBanner,{role:"alert",children:E}),e.jsx(r.InputArea,{children:e.jsxs(r.InputWrapper,{$focused:le,children:[e.jsx(r.MessageInput,{ref:W,rows:1,value:w,placeholder:J,disabled:l,onChange:ae,onKeyDown:he,onFocus:()=>q(!0),onBlur:()=>q(!1)}),e.jsx(r.SendButton,{type:"button",$active:i||N,disabled:!i&&!N,onClick:i?M:V,"aria-label":i?"Stop generating":"Send message",children:i?e.jsx(D,{}):e.jsx(me,{})})]})}),B&&e.jsx(r.Disclaimer,{children:B})]})};exports.CopilotPanel=ke;
|
|
2
|
+
//# sourceMappingURL=CopilotPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CopilotPanel.js","sources":["../../../../src/components/bik-copilot/CopilotPanel.tsx"],"sourcesContent":["import AiStarsIcon from '@src/assets/icons/bik_ai_stars_icon.svg';\nimport CrossIcon from '@src/assets/icons/cross.svg';\nimport RefreshIcon from '@src/assets/icons/refresh.svg';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { COLORS } from '@src/constants/Theme';\nimport { renderMarkdownLite } from '../bik-chatbot/utils/markdown';\nimport { DotPulse } from '../dot-pulse';\nimport { BodyCaption, BodySecondary, TitleSmall } from '../TypographyStyle';\nimport {\n\tDisclaimer,\n\tEmptyState,\n\tEmptyStateIcon,\n\tErrorBanner,\n\tFollowUpChip,\n\tFollowUpList,\n\tFollowUpsLabel,\n\tHeaderActions,\n\tHeaderAvatar,\n\tHeaderBadge,\n\tHeaderText,\n\tHeaderTitleRow,\n\tHistoryLoader,\n\tIconAction,\n\tInputArea,\n\tInputWrapper,\n\tInterruptedNote,\n\tJumpToLatestButton,\n\tMessageBubble,\n\tMessageInput,\n\tMessagesArea,\n\tMessagesViewport,\n\tPanelContainer,\n\tPanelHeader,\n\tScrollFade,\n\tSendButton,\n\tSuggestionChip,\n\tSuggestionList,\n\tThinkingBubble,\n\tThinkingLabel,\n} from './CopilotPanel.styled';\nimport { CopilotPanelProps } from './model';\n\nconst MAX_INPUT_HEIGHT_PX = 96;\n\n/** Slack at the bottom of the scroller that still counts as \"at the latest\". */\nconst AT_BOTTOM_TOLERANCE_PX = 24;\n\n/** How close to the top counts as asking for the previous page. */\nconst NEAR_TOP_TOLERANCE_PX = 48;\n\nconst SendArrowIcon = () => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth=\"16\"\n\t\theight=\"16\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<path d=\"M12 19V5\" />\n\t\t<path d=\"M6 11l6-6 6 6\" />\n\t</svg>\n);\n\nconst ArrowRightIcon = () => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<path d=\"M5 12h14\" />\n\t\t<path d=\"M13 6l6 6-6 6\" />\n\t</svg>\n);\n\nconst StopIcon = ({ size = 16 }: { size?: number }) => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth={size}\n\t\theight={size}\n\t\tfill=\"currentColor\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<rect x=\"7\" y=\"7\" width=\"10\" height=\"10\" rx=\"2\" />\n\t</svg>\n);\n\nconst ChevronDownIcon = () => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tfill=\"none\"\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"2.5\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<path d=\"M6 9l6 6 6-6\" />\n\t</svg>\n);\n\n/**\n * Chat panel used by the copilot. Fully presentational: it renders the\n * transcript it is given and reports user intent through callbacks, so it works\n * against any backend.\n */\nexport const CopilotPanel: React.FC<CopilotPanelProps> = ({\n\tmessages,\n\tonSend,\n\tonClose,\n\ttitle = 'Copilot',\n\tbadge,\n\tsubtitle,\n\tavatar,\n\tplaceholder = 'Write your message...',\n\tdisclaimer = 'AI can make mistakes, Verify the responses.',\n\temptyStateTitle,\n\temptyStateSubtitle = 'Here are some things you can try',\n\tsuggestions,\n\tonSuggestionClick,\n\tshowRefresh = true,\n\tonRefresh,\n\tisThinking = false,\n\tthinkingLabel = 'Thinking',\n\tisStreaming = false,\n\tonStop,\n\tinterruptedLabel = 'This message was interrupted',\n\tfollowUpsLabel = 'Follow ups',\n\thasMoreHistory = false,\n\tisLoadingHistory = false,\n\tonLoadOlderMessages,\n\thistoryLoadingLabel = 'Loading earlier messages',\n\tinputDisabled = false,\n\terrorMessage,\n\twidth,\n\theight,\n\tclassName,\n\tstyle,\n}) => {\n\tconst [input, setInput] = useState('');\n\tconst [isInputFocused, setIsInputFocused] = useState(false);\n\tconst [isAtLatest, setIsAtLatest] = useState(true);\n\tconst inputRef = useRef<HTMLTextAreaElement>(null);\n\tconst bottomRef = useRef<HTMLDivElement>(null);\n\tconst scrollerRef = useRef<HTMLDivElement>(null);\n\tconst lastScrollTopRef = useRef(0);\n\t// Distance from the bottom at the moment an older page was asked for. Older\n\t// messages land *above* the viewport, so without restoring against this the\n\t// content under the reader jumps down by the height of what arrived.\n\tconst anchorFromBottomRef = useRef<number | null>(null);\n\n\t// An assistant bubble is pushed the moment a turn starts, before any text has\n\t// arrived; the thinking indicator stands in for it until then, so rendering it\n\t// too would show an empty balloon next to the dots. A turn stopped before its\n\t// first token keeps its place, carrying only the interrupted note.\n\tconst visibleMessages = messages.filter(\n\t\t(message) => message.content.length > 0 || message.wasInterrupted,\n\t);\n\tconst isEmpty = visibleMessages.length === 0 && !isThinking;\n\tconst isTurnInFlight = isThinking || isStreaming;\n\tconst canSend = !inputDisabled && !isTurnInFlight && input.trim().length > 0;\n\t// Stopping is the only thing the button can do mid-answer, so it becomes the\n\t// stop button rather than sitting there disabled.\n\tconst canStop = isTurnInFlight && Boolean(onStop);\n\t// Only the newest reply's suggestions are on offer — older ones answer a\n\t// question the conversation has already moved past.\n\tconst newestMessage = visibleMessages[visibleMessages.length - 1];\n\tconst followUps =\n\t\t!isTurnInFlight && newestMessage?.role === 'assistant'\n\t\t\t? newestMessage.followUps\n\t\t\t: undefined;\n\t// A long answer that the reader has scrolled up from: the tail is clipped, so\n\t// the fade and the arrow say there is more below.\n\tconst showScrollAffordance = !isEmpty && !isAtLatest;\n\n\t// Following the conversation is the default, but a reader who has scrolled up\n\t// mid-answer must not be yanked back down by the next chunk.\n\tuseEffect(() => {\n\t\tif (!isAtLatest) {\n\t\t\treturn;\n\t\t}\n\t\tbottomRef.current?.scrollIntoView({ behavior: 'smooth' });\n\t}, [messages, isThinking, isAtLatest]);\n\n\t// Older messages have landed: put the reader back on the message they were\n\t// looking at, which is now that much further down.\n\tuseEffect(() => {\n\t\tconst scroller = scrollerRef.current;\n\t\tconst anchor = anchorFromBottomRef.current;\n\t\tif (!scroller || anchor === null || isLoadingHistory) {\n\t\t\treturn;\n\t\t}\n\t\tanchorFromBottomRef.current = null;\n\t\tscroller.scrollTop = scroller.scrollHeight - anchor;\n\t\tlastScrollTopRef.current = scroller.scrollTop;\n\t}, [messages, isLoadingHistory]);\n\n\tconst handleScroll = () => {\n\t\tconst scroller = scrollerRef.current;\n\t\tif (!scroller) {\n\t\t\treturn;\n\t\t}\n\t\tconst distanceFromBottom =\n\t\t\tscroller.scrollHeight - scroller.scrollTop - scroller.clientHeight;\n\n\t\t// Reaching the top asks for the page before this one. The threshold gives\n\t\t// the request a head start, so the page is usually there by the time the\n\t\t// reader arrives.\n\t\tif (\n\t\t\tscroller.scrollTop <= NEAR_TOP_TOLERANCE_PX &&\n\t\t\thasMoreHistory &&\n\t\t\t!isLoadingHistory &&\n\t\t\tonLoadOlderMessages\n\t\t) {\n\t\t\tanchorFromBottomRef.current = scroller.scrollHeight - scroller.scrollTop;\n\t\t\tonLoadOlderMessages();\n\t\t}\n\t\t// Scrolling *up* is the only thing that detaches from the latest message:\n\t\t// growing content also pushes the bottom away, and auto-scroll itself only\n\t\t// ever moves down, so distance alone would flap mid-stream.\n\t\tconst scrolledUp = scroller.scrollTop < lastScrollTopRef.current - 1;\n\t\tlastScrollTopRef.current = scroller.scrollTop;\n\n\t\tif (distanceFromBottom <= AT_BOTTOM_TOLERANCE_PX) {\n\t\t\tsetIsAtLatest(true);\n\t\t\treturn;\n\t\t}\n\t\tif (scrolledUp) {\n\t\t\tsetIsAtLatest(false);\n\t\t}\n\t};\n\n\tconst handleJumpToLatest = () => {\n\t\tsetIsAtLatest(true);\n\t\tbottomRef.current?.scrollIntoView({ behavior: 'smooth' });\n\t};\n\n\tconst handleSend = () => {\n\t\tconst trimmed = input.trim();\n\t\tif (!trimmed || inputDisabled || isTurnInFlight) {\n\t\t\treturn;\n\t\t}\n\t\tonSend(trimmed);\n\t\tsetInput('');\n\t\tconst textarea = inputRef.current;\n\t\tif (textarea) {\n\t\t\ttextarea.style.height = 'auto';\n\t\t}\n\t};\n\n\tconst handleInputChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {\n\t\tsetInput(event.target.value);\n\t\tconst textarea = event.target;\n\t\ttextarea.style.height = 'auto';\n\t\ttextarea.style.height = `${Math.min(\n\t\t\ttextarea.scrollHeight,\n\t\t\tMAX_INPUT_HEIGHT_PX,\n\t\t)}px`;\n\t};\n\n\tconst handleKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {\n\t\tif (event.key === 'Enter' && !event.shiftKey) {\n\t\t\tevent.preventDefault();\n\t\t\thandleSend();\n\t\t}\n\t};\n\n\tconst handleSuggestionClick = (\n\t\tsuggestion: NonNullable<CopilotPanelProps['suggestions']>[number],\n\t) => {\n\t\tif (inputDisabled || isTurnInFlight) {\n\t\t\treturn;\n\t\t}\n\t\tonSuggestionClick?.(suggestion);\n\t\tonSend(suggestion.text);\n\t};\n\n\tconst handleFollowUpClick = (followUp: string) => {\n\t\tif (inputDisabled || isTurnInFlight) {\n\t\t\treturn;\n\t\t}\n\t\tonSend(followUp);\n\t};\n\n\treturn (\n\t\t<PanelContainer\n\t\t\tclassName={className}\n\t\t\tstyle={{ width, height, ...style }}\n\t\t\trole=\"dialog\"\n\t\t\taria-label={title}\n\t\t>\n\t\t\t<PanelHeader>\n\t\t\t\t<HeaderAvatar>\n\t\t\t\t\t{avatar ?? <AiStarsIcon width={18} height={18} />}\n\t\t\t\t</HeaderAvatar>\n\t\t\t\t<HeaderText>\n\t\t\t\t\t<HeaderTitleRow>\n\t\t\t\t\t\t<TitleSmall>{title}</TitleSmall>\n\t\t\t\t\t\t{badge && <HeaderBadge>{badge}</HeaderBadge>}\n\t\t\t\t\t</HeaderTitleRow>\n\t\t\t\t\t{subtitle && (\n\t\t\t\t\t\t<BodyCaption color={COLORS.content.secondary}>\n\t\t\t\t\t\t\t{subtitle}\n\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t)}\n\t\t\t\t</HeaderText>\n\t\t\t\t<HeaderActions>\n\t\t\t\t\t{showRefresh && onRefresh && (\n\t\t\t\t\t\t<IconAction\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\tonClick={onRefresh}\n\t\t\t\t\t\t\taria-label=\"Start a new conversation\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<RefreshIcon width={16} height={16} />\n\t\t\t\t\t\t</IconAction>\n\t\t\t\t\t)}\n\t\t\t\t\t<IconAction\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tonClick={onClose}\n\t\t\t\t\t\taria-label=\"Close copilot\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<CrossIcon width={18} height={18} />\n\t\t\t\t\t</IconAction>\n\t\t\t\t</HeaderActions>\n\t\t\t</PanelHeader>\n\n\t\t\t<MessagesViewport>\n\t\t\t\t<MessagesArea\n\t\t\t\t\tref={scrollerRef}\n\t\t\t\t\tonScroll={handleScroll}\n\t\t\t\t\trole=\"region\"\n\t\t\t\t\taria-label=\"Conversation\"\n\t\t\t\t>\n\t\t\t\t\t{isEmpty ? (\n\t\t\t\t\t\t<EmptyState>\n\t\t\t\t\t\t\t<EmptyStateIcon>\n\t\t\t\t\t\t\t\t<AiStarsIcon width={28} height={28} />\n\t\t\t\t\t\t\t</EmptyStateIcon>\n\t\t\t\t\t\t\t<BodySecondary style={{ fontWeight: 600 }}>\n\t\t\t\t\t\t\t\t{emptyStateTitle || title}\n\t\t\t\t\t\t\t</BodySecondary>\n\t\t\t\t\t\t\t{emptyStateSubtitle && (\n\t\t\t\t\t\t\t\t<BodyCaption color={COLORS.content.secondary}>\n\t\t\t\t\t\t\t\t\t{emptyStateSubtitle}\n\t\t\t\t\t\t\t\t</BodyCaption>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{suggestions && suggestions.length > 0 && (\n\t\t\t\t\t\t\t\t<SuggestionList>\n\t\t\t\t\t\t\t\t\t{suggestions.map((suggestion) => (\n\t\t\t\t\t\t\t\t\t\t<SuggestionChip\n\t\t\t\t\t\t\t\t\t\t\tkey={suggestion.id}\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tdisabled={inputDisabled || isTurnInFlight}\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleSuggestionClick(suggestion)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<AiStarsIcon width={14} height={14} />\n\t\t\t\t\t\t\t\t\t\t\t{suggestion.text}\n\t\t\t\t\t\t\t\t\t\t</SuggestionChip>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</SuggestionList>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</EmptyState>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t{isLoadingHistory && (\n\t\t\t\t\t\t\t\t<HistoryLoader role=\"status\" aria-live=\"polite\">\n\t\t\t\t\t\t\t\t\t<DotPulse color={COLORS.content.placeholder} size={4} />\n\t\t\t\t\t\t\t\t\t{historyLoadingLabel}\n\t\t\t\t\t\t\t\t</HistoryLoader>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{visibleMessages.map((message) => (\n\t\t\t\t\t\t\t\t<React.Fragment key={message.id}>\n\t\t\t\t\t\t\t\t\t{message.content.length > 0 && (\n\t\t\t\t\t\t\t\t\t\t<MessageBubble $role={message.role}>\n\t\t\t\t\t\t\t\t\t\t\t{message.role === 'assistant' ? (\n\t\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\t\tdangerouslySetInnerHTML={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t__html: renderMarkdownLite(message.content),\n\t\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t\t<div style={{ whiteSpace: 'pre-wrap' }}>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{message.content}\n\t\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t</MessageBubble>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t{message.wasInterrupted && interruptedLabel && (\n\t\t\t\t\t\t\t\t\t\t<InterruptedNote>\n\t\t\t\t\t\t\t\t\t\t\t<StopIcon size={12} />\n\t\t\t\t\t\t\t\t\t\t\t{interruptedLabel}\n\t\t\t\t\t\t\t\t\t\t</InterruptedNote>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t</React.Fragment>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t{followUps && followUps.length > 0 && (\n\t\t\t\t\t\t\t\t<FollowUpList>\n\t\t\t\t\t\t\t\t\t{followUpsLabel && (\n\t\t\t\t\t\t\t\t\t\t<FollowUpsLabel>{followUpsLabel}</FollowUpsLabel>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t{followUps.map((followUp) => (\n\t\t\t\t\t\t\t\t\t\t<FollowUpChip\n\t\t\t\t\t\t\t\t\t\t\tkey={followUp}\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tdisabled={inputDisabled}\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleFollowUpClick(followUp)}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t<ArrowRightIcon />\n\t\t\t\t\t\t\t\t\t\t\t{followUp}\n\t\t\t\t\t\t\t\t\t\t</FollowUpChip>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</FollowUpList>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{isThinking && (\n\t\t\t\t\t\t\t\t<ThinkingBubble role=\"status\" aria-live=\"polite\">\n\t\t\t\t\t\t\t\t\t<AiStarsIcon\n\t\t\t\t\t\t\t\t\t\twidth={14}\n\t\t\t\t\t\t\t\t\t\theight={14}\n\t\t\t\t\t\t\t\t\t\tcolor={COLORS.content.brand}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t{thinkingLabel && (\n\t\t\t\t\t\t\t\t\t\t<ThinkingLabel>{thinkingLabel}</ThinkingLabel>\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t<DotPulse color={COLORS.background.brand} size={5} />\n\t\t\t\t\t\t\t\t</ThinkingBubble>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<div ref={bottomRef} />\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t</MessagesArea>\n\n\t\t\t\t<ScrollFade $visible={showScrollAffordance} aria-hidden=\"true\" />\n\t\t\t\t<JumpToLatestButton\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t$visible={showScrollAffordance}\n\t\t\t\t\tonClick={handleJumpToLatest}\n\t\t\t\t\ttabIndex={showScrollAffordance ? 0 : -1}\n\t\t\t\t\taria-label=\"Scroll to the latest message\"\n\t\t\t\t>\n\t\t\t\t\t<ChevronDownIcon />\n\t\t\t\t</JumpToLatestButton>\n\t\t\t</MessagesViewport>\n\n\t\t\t{errorMessage && <ErrorBanner role=\"alert\">{errorMessage}</ErrorBanner>}\n\n\t\t\t<InputArea>\n\t\t\t\t<InputWrapper $focused={isInputFocused}>\n\t\t\t\t\t<MessageInput\n\t\t\t\t\t\tref={inputRef}\n\t\t\t\t\t\trows={1}\n\t\t\t\t\t\tvalue={input}\n\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\tdisabled={inputDisabled}\n\t\t\t\t\t\tonChange={handleInputChange}\n\t\t\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\t\t\tonFocus={() => setIsInputFocused(true)}\n\t\t\t\t\t\tonBlur={() => setIsInputFocused(false)}\n\t\t\t\t\t/>\n\t\t\t\t\t<SendButton\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t$active={canStop || canSend}\n\t\t\t\t\t\tdisabled={!canStop && !canSend}\n\t\t\t\t\t\tonClick={canStop ? onStop : handleSend}\n\t\t\t\t\t\taria-label={canStop ? 'Stop generating' : 'Send message'}\n\t\t\t\t\t>\n\t\t\t\t\t\t{canStop ? <StopIcon /> : <SendArrowIcon />}\n\t\t\t\t\t</SendButton>\n\t\t\t\t</InputWrapper>\n\t\t\t</InputArea>\n\n\t\t\t{disclaimer && <Disclaimer>{disclaimer}</Disclaimer>}\n\t\t</PanelContainer>\n\t);\n};\n\nexport default CopilotPanel;\n"],"names":["MAX_INPUT_HEIGHT_PX","AT_BOTTOM_TOLERANCE_PX","NEAR_TOP_TOLERANCE_PX","SendArrowIcon","jsxs","jsx","ArrowRightIcon","StopIcon","size","ChevronDownIcon","CopilotPanel","messages","onSend","onClose","title","badge","subtitle","avatar","placeholder","disclaimer","emptyStateTitle","emptyStateSubtitle","suggestions","onSuggestionClick","showRefresh","onRefresh","isThinking","thinkingLabel","isStreaming","onStop","interruptedLabel","followUpsLabel","hasMoreHistory","isLoadingHistory","onLoadOlderMessages","historyLoadingLabel","inputDisabled","errorMessage","width","height","className","style","input","setInput","useState","isInputFocused","setIsInputFocused","isAtLatest","setIsAtLatest","inputRef","useRef","bottomRef","scrollerRef","lastScrollTopRef","anchorFromBottomRef","visibleMessages","message","isEmpty","isTurnInFlight","canSend","canStop","newestMessage","followUps","showScrollAffordance","useEffect","scroller","anchor","handleScroll","distanceFromBottom","scrolledUp","handleJumpToLatest","handleSend","trimmed","textarea","handleInputChange","event","handleKeyDown","handleSuggestionClick","suggestion","handleFollowUpClick","followUp","PanelContainer","PanelHeader","HeaderAvatar","AiStarsIcon","HeaderText","HeaderTitleRow","TitleSmall","HeaderBadge","BodyCaption","COLORS","HeaderActions","IconAction","RefreshIcon","CrossIcon","MessagesViewport","MessagesArea","EmptyState","EmptyStateIcon","BodySecondary","SuggestionList","SuggestionChip","Fragment","HistoryLoader","DotPulse","React","MessageBubble","renderMarkdownLite","InterruptedNote","FollowUpList","FollowUpsLabel","FollowUpChip","ThinkingBubble","ThinkingLabel","ScrollFade","JumpToLatestButton","ErrorBanner","InputArea","InputWrapper","MessageInput","SendButton","Disclaimer"],"mappings":"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"}
|