@bikdotai/bik-component-library 0.0.863-beta.1 → 0.0.863-beta.2

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.
Files changed (127) hide show
  1. package/dist/cjs/components/agent-builder/AgentBuilder.js +1 -1
  2. package/dist/cjs/components/agent-builder/AgentBuilder.js.map +1 -1
  3. package/dist/cjs/components/agent-builder/AgentBuilder.styled.js +54 -44
  4. package/dist/cjs/components/agent-builder/AgentBuilder.styled.js.map +1 -1
  5. package/dist/cjs/components/agent-builder/components/AgentStateModal.js +2 -0
  6. package/dist/cjs/components/agent-builder/components/AgentStateModal.js.map +1 -0
  7. package/dist/cjs/components/agent-builder/components/MentionPicker.js +1 -1
  8. package/dist/cjs/components/agent-builder/components/MentionPicker.js.map +1 -1
  9. package/dist/cjs/components/agent-builder/components/SelectableListSection.js +1 -1
  10. package/dist/cjs/components/agent-builder/components/SelectableListSection.js.map +1 -1
  11. package/dist/cjs/components/agent-builder/context/AgentBuilderContext.js +1 -1
  12. package/dist/cjs/components/agent-builder/context/AgentBuilderContext.js.map +1 -1
  13. package/dist/cjs/components/agent-builder/steps/Step2WhenItStepsIn.js +1 -1
  14. package/dist/cjs/components/agent-builder/steps/Step2WhenItStepsIn.js.map +1 -1
  15. package/dist/cjs/components/agent-listing/AgentTableRow.js +1 -1
  16. package/dist/cjs/components/agent-listing/AgentTableRow.js.map +1 -1
  17. package/dist/cjs/index.js +1 -1
  18. package/dist/esm/components/agent-builder/AgentBuilder.js +3 -3
  19. package/dist/esm/components/agent-builder/AgentBuilder.js.map +1 -1
  20. package/dist/esm/components/agent-builder/AgentBuilder.styled.d.ts +23 -0
  21. package/dist/esm/components/agent-builder/AgentBuilder.styled.js +99 -86
  22. package/dist/esm/components/agent-builder/AgentBuilder.styled.js.map +1 -1
  23. package/dist/esm/components/agent-builder/components/AgentStateModal.d.ts +47 -0
  24. package/dist/esm/components/agent-builder/components/AgentStateModal.js +82 -0
  25. package/dist/esm/components/agent-builder/components/AgentStateModal.js.map +1 -0
  26. package/dist/esm/components/agent-builder/components/MentionPicker.js +27 -27
  27. package/dist/esm/components/agent-builder/components/MentionPicker.js.map +1 -1
  28. package/dist/esm/components/agent-builder/components/SelectableListSection.js +16 -23
  29. package/dist/esm/components/agent-builder/components/SelectableListSection.js.map +1 -1
  30. package/dist/esm/components/agent-builder/context/AgentBuilderContext.js +132 -124
  31. package/dist/esm/components/agent-builder/context/AgentBuilderContext.js.map +1 -1
  32. package/dist/esm/components/agent-builder/index.d.ts +2 -0
  33. package/dist/esm/components/agent-builder/steps/Step2WhenItStepsIn.js +13 -15
  34. package/dist/esm/components/agent-builder/steps/Step2WhenItStepsIn.js.map +1 -1
  35. package/dist/esm/components/agent-listing/AgentTableRow.js +71 -38
  36. package/dist/esm/components/agent-listing/AgentTableRow.js.map +1 -1
  37. package/dist/esm/index.d.ts +0 -1
  38. package/dist/esm/index.js +784 -832
  39. package/dist/esm/index.js.map +1 -1
  40. package/package.json +1 -1
  41. package/dist/cjs/components/bik-copilot/BIKCopilot.js +0 -2
  42. package/dist/cjs/components/bik-copilot/BIKCopilot.js.map +0 -1
  43. package/dist/cjs/components/bik-copilot/ControlledCopilot.js +0 -2
  44. package/dist/cjs/components/bik-copilot/ControlledCopilot.js.map +0 -1
  45. package/dist/cjs/components/bik-copilot/ControlledCopilot.styled.js +0 -27
  46. package/dist/cjs/components/bik-copilot/ControlledCopilot.styled.js.map +0 -1
  47. package/dist/cjs/components/bik-copilot/CopilotBall.js +0 -2
  48. package/dist/cjs/components/bik-copilot/CopilotBall.js.map +0 -1
  49. package/dist/cjs/components/bik-copilot/CopilotBall.styled.js +0 -42
  50. package/dist/cjs/components/bik-copilot/CopilotBall.styled.js.map +0 -1
  51. package/dist/cjs/components/bik-copilot/CopilotPanel.js +0 -2
  52. package/dist/cjs/components/bik-copilot/CopilotPanel.js.map +0 -1
  53. package/dist/cjs/components/bik-copilot/CopilotPanel.styled.js +0 -460
  54. package/dist/cjs/components/bik-copilot/CopilotPanel.styled.js.map +0 -1
  55. package/dist/cjs/components/bik-copilot/copilotPlacement.js +0 -2
  56. package/dist/cjs/components/bik-copilot/copilotPlacement.js.map +0 -1
  57. package/dist/cjs/components/bik-copilot/services/copilotDb.js +0 -2
  58. package/dist/cjs/components/bik-copilot/services/copilotDb.js.map +0 -1
  59. package/dist/cjs/components/bik-copilot/services/copilotIcebreakersClient.js +0 -2
  60. package/dist/cjs/components/bik-copilot/services/copilotIcebreakersClient.js.map +0 -1
  61. package/dist/cjs/components/bik-copilot/services/copilotMessagesClient.js +0 -2
  62. package/dist/cjs/components/bik-copilot/services/copilotMessagesClient.js.map +0 -1
  63. package/dist/cjs/components/bik-copilot/services/copilotPageSession.js +0 -2
  64. package/dist/cjs/components/bik-copilot/services/copilotPageSession.js.map +0 -1
  65. package/dist/cjs/components/bik-copilot/services/copilotSseParser.js +0 -7
  66. package/dist/cjs/components/bik-copilot/services/copilotSseParser.js.map +0 -1
  67. package/dist/cjs/components/bik-copilot/services/copilotStreamClient.js +0 -2
  68. package/dist/cjs/components/bik-copilot/services/copilotStreamClient.js.map +0 -1
  69. package/dist/cjs/components/bik-copilot/useCopilotIcebreakers.js +0 -2
  70. package/dist/cjs/components/bik-copilot/useCopilotIcebreakers.js.map +0 -1
  71. package/dist/cjs/components/bik-copilot/useCopilotStreamChat.js +0 -2
  72. package/dist/cjs/components/bik-copilot/useCopilotStreamChat.js.map +0 -1
  73. package/dist/cjs/components/bik-copilot/useDraggableFloater.js +0 -2
  74. package/dist/cjs/components/bik-copilot/useDraggableFloater.js.map +0 -1
  75. package/dist/esm/components/bik-copilot/BIKCopilot.d.ts +0 -32
  76. package/dist/esm/components/bik-copilot/BIKCopilot.js +0 -114
  77. package/dist/esm/components/bik-copilot/BIKCopilot.js.map +0 -1
  78. package/dist/esm/components/bik-copilot/ControlledCopilot.d.ts +0 -14
  79. package/dist/esm/components/bik-copilot/ControlledCopilot.js +0 -170
  80. package/dist/esm/components/bik-copilot/ControlledCopilot.js.map +0 -1
  81. package/dist/esm/components/bik-copilot/ControlledCopilot.styled.d.ts +0 -7
  82. package/dist/esm/components/bik-copilot/ControlledCopilot.styled.js +0 -31
  83. package/dist/esm/components/bik-copilot/ControlledCopilot.styled.js.map +0 -1
  84. package/dist/esm/components/bik-copilot/CopilotBall.d.ts +0 -13
  85. package/dist/esm/components/bik-copilot/CopilotBall.js +0 -50
  86. package/dist/esm/components/bik-copilot/CopilotBall.js.map +0 -1
  87. package/dist/esm/components/bik-copilot/CopilotBall.styled.d.ts +0 -9
  88. package/dist/esm/components/bik-copilot/CopilotBall.styled.js +0 -46
  89. package/dist/esm/components/bik-copilot/CopilotBall.styled.js.map +0 -1
  90. package/dist/esm/components/bik-copilot/CopilotPanel.d.ts +0 -9
  91. package/dist/esm/components/bik-copilot/CopilotPanel.js +0 -379
  92. package/dist/esm/components/bik-copilot/CopilotPanel.js.map +0 -1
  93. package/dist/esm/components/bik-copilot/CopilotPanel.styled.d.ts +0 -64
  94. package/dist/esm/components/bik-copilot/CopilotPanel.styled.js +0 -496
  95. package/dist/esm/components/bik-copilot/CopilotPanel.styled.js.map +0 -1
  96. package/dist/esm/components/bik-copilot/copilotPlacement.d.ts +0 -24
  97. package/dist/esm/components/bik-copilot/copilotPlacement.js +0 -38
  98. package/dist/esm/components/bik-copilot/copilotPlacement.js.map +0 -1
  99. package/dist/esm/components/bik-copilot/index.d.ts +0 -16
  100. package/dist/esm/components/bik-copilot/model.d.ts +0 -674
  101. package/dist/esm/components/bik-copilot/services/copilotDb.d.ts +0 -90
  102. package/dist/esm/components/bik-copilot/services/copilotDb.js +0 -96
  103. package/dist/esm/components/bik-copilot/services/copilotDb.js.map +0 -1
  104. package/dist/esm/components/bik-copilot/services/copilotIcebreakersClient.d.ts +0 -11
  105. package/dist/esm/components/bik-copilot/services/copilotIcebreakersClient.js +0 -54
  106. package/dist/esm/components/bik-copilot/services/copilotIcebreakersClient.js.map +0 -1
  107. package/dist/esm/components/bik-copilot/services/copilotMessagesClient.d.ts +0 -23
  108. package/dist/esm/components/bik-copilot/services/copilotMessagesClient.js +0 -78
  109. package/dist/esm/components/bik-copilot/services/copilotMessagesClient.js.map +0 -1
  110. package/dist/esm/components/bik-copilot/services/copilotPageSession.d.ts +0 -37
  111. package/dist/esm/components/bik-copilot/services/copilotPageSession.js +0 -35
  112. package/dist/esm/components/bik-copilot/services/copilotPageSession.js.map +0 -1
  113. package/dist/esm/components/bik-copilot/services/copilotSseParser.d.ts +0 -22
  114. package/dist/esm/components/bik-copilot/services/copilotSseParser.js +0 -52
  115. package/dist/esm/components/bik-copilot/services/copilotSseParser.js.map +0 -1
  116. package/dist/esm/components/bik-copilot/services/copilotStreamClient.d.ts +0 -31
  117. package/dist/esm/components/bik-copilot/services/copilotStreamClient.js +0 -103
  118. package/dist/esm/components/bik-copilot/services/copilotStreamClient.js.map +0 -1
  119. package/dist/esm/components/bik-copilot/useCopilotIcebreakers.d.ts +0 -17
  120. package/dist/esm/components/bik-copilot/useCopilotIcebreakers.js +0 -60
  121. package/dist/esm/components/bik-copilot/useCopilotIcebreakers.js.map +0 -1
  122. package/dist/esm/components/bik-copilot/useCopilotStreamChat.d.ts +0 -20
  123. package/dist/esm/components/bik-copilot/useCopilotStreamChat.js +0 -333
  124. package/dist/esm/components/bik-copilot/useCopilotStreamChat.js.map +0 -1
  125. package/dist/esm/components/bik-copilot/useDraggableFloater.d.ts +0 -9
  126. package/dist/esm/components/bik-copilot/useDraggableFloater.js +0 -118
  127. package/dist/esm/components/bik-copilot/useDraggableFloater.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"copilotStreamClient.js","sources":["../../../../../src/components/bik-copilot/services/copilotStreamClient.ts"],"sourcesContent":["import {\n\tCopilotStreamEvent,\n\tCopilotStreamHandlers,\n\tCopilotStreamRequest,\n\tStreamCopilotChatOptions,\n} from '../model';\nimport { CopilotSseParser } from './copilotSseParser';\n\n/** Default path of the streaming copilot endpoint. */\nexport const COPILOT_ENDPOINT_PATH = '/bik-ai/copilot-chatbot';\n\nconst buildRequestBody = (request: CopilotStreamRequest) => ({\n\tstore_id: request.storeId,\n\tagent: request.agent,\n\troute: request.route,\n\tuser_prompt: request.userPrompt,\n\tsession_id: request.sessionId,\n\t// Trimmed, then left out rather than sent empty: the backend reads a missing\n\t// key as \"no signed-in user\", which a blank string would not.\n\t...(request.email?.trim() ? { email: request.email.trim() } : {}),\n\t// Omitted on the first turn; from the second turn on it is the `responseId`\n\t// of the previous TEXT event, which is how OpenAI keeps the thread's context.\n\t...(request.previousResponseId\n\t\t? { previous_response_id: request.previousResponseId }\n\t\t: {}),\n\t...(request.systemPrompt ? { system_prompt: request.systemPrompt } : {}),\n\t...(request.model ? { model: request.model } : {}),\n\t...(request.maxOutputTokens\n\t\t? { max_output_tokens: request.maxOutputTokens }\n\t\t: {}),\n});\n\n/**\n * Reads an event's `content`, which the backend sends two ways: a bare string on\n * `STREAM` and `ERROR`, and an `{ type, message, followUps }` payload on `TEXT`.\n *\n * Anything unrecognised reads as empty text rather than throwing, so a shape the\n * backend adds later cannot break a turn that is otherwise fine.\n */\nexport const readCopilotEventContent = (\n\tevent: CopilotStreamEvent,\n): { text: string; followUps?: string[] } => {\n\tconst { content } = event;\n\n\tif (typeof content === 'string') {\n\t\treturn { text: content };\n\t}\n\tif (!content || typeof content !== 'object') {\n\t\treturn { text: '' };\n\t}\n\n\tconst followUps = Array.isArray(content.followUps)\n\t\t? content.followUps.filter(\n\t\t\t\t(followUp): followUp is string =>\n\t\t\t\t\ttypeof followUp === 'string' && followUp.trim().length > 0,\n\t\t )\n\t\t: undefined;\n\n\treturn {\n\t\ttext: typeof content.message === 'string' ? content.message : '',\n\t\t...(followUps && followUps.length > 0 ? { followUps } : {}),\n\t};\n};\n\nconst parseEvent = (payload: string): CopilotStreamEvent | null => {\n\ttry {\n\t\tconst parsed = JSON.parse(payload) as unknown;\n\t\tif (typeof parsed !== 'object' || parsed === null) {\n\t\t\treturn null;\n\t\t}\n\t\tconst event = parsed as CopilotStreamEvent;\n\t\treturn event.type ? event : null;\n\t} catch {\n\t\t// A frame that is not JSON is not something this endpoint emits; dropping\n\t\t// it is better than tearing down a stream that is otherwise fine.\n\t\treturn null;\n\t}\n};\n\n/**\n * Opens one streaming copilot turn and drives the handlers until the server\n * closes the stream.\n *\n * The endpoint's `STOP` never reaches the client as a frame — the server breaks\n * out of its generator, which ends the HTTP stream. So \"the reader is done\" is\n * what completion means here, and `onComplete` fires from there.\n *\n * `TEXT` carries the **whole** message, so it is authoritative: a caller should\n * replace the text accumulated from `STREAM` chunks with it rather than append.\n * When a turn fails halfway the server still sends `TEXT` with the partial\n * answer but **without** `responseId` — that intentionally drops the thread, so\n * the next turn must start fresh.\n *\n * @returns a function that aborts the in-flight stream.\n */\nexport const streamCopilotChat = (\n\t{\n\t\tbaseUrl,\n\t\tendpointPath = COPILOT_ENDPOINT_PATH,\n\t\theaders,\n\t\tauthToken,\n\t\tgetAuthToken,\n\t\tfetchImpl,\n\t\t...request\n\t}: StreamCopilotChatOptions,\n\thandlers: CopilotStreamHandlers,\n): (() => void) => {\n\tconst abortController = new AbortController();\n\n\tconst run = async () => {\n\t\tconst url = `${baseUrl.replace(/\\/$/, '')}${endpointPath}`;\n\t\tconst token = getAuthToken ? await getAuthToken() : authToken;\n\t\tconst doFetch = fetchImpl ?? fetch;\n\n\t\tconst response = await doFetch(url, {\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\tAccept: 'text/event-stream',\n\t\t\t\t...(token ? { authorization: token } : {}),\n\t\t\t\t...headers,\n\t\t\t},\n\t\t\tbody: JSON.stringify(buildRequestBody(request)),\n\t\t\tsignal: abortController.signal,\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst detail = await response.text().catch(() => '');\n\t\t\tthrow new Error(\n\t\t\t\t`Copilot request failed with ${response.status}${\n\t\t\t\t\tdetail ? `: ${detail}` : ''\n\t\t\t\t}`,\n\t\t\t);\n\t\t}\n\t\tif (!response.body) {\n\t\t\tthrow new Error('Copilot response carried no stream body');\n\t\t}\n\n\t\tconst reader = response.body.getReader();\n\t\tconst parser = new CopilotSseParser();\n\t\tlet decoder: TextDecoder | undefined;\n\n\t\tconst dispatch = (payloads: string[]) => {\n\t\t\tpayloads.forEach((payload) => {\n\t\t\t\tconst event = parseEvent(payload);\n\t\t\t\tif (event) {\n\t\t\t\t\thandlers.onEvent(event);\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\t// eslint-disable-next-line no-constant-condition\n\t\twhile (true) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tif (done) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (value === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Tests feed strings; the network feeds bytes.\n\t\t\tlet chunk: string;\n\t\t\tif (typeof value === 'string') {\n\t\t\t\tchunk = value;\n\t\t\t} else {\n\t\t\t\tdecoder = decoder ?? new TextDecoder();\n\t\t\t\tchunk = decoder.decode(value, { stream: true });\n\t\t\t}\n\t\t\tdispatch(parser.push(chunk));\n\t\t}\n\n\t\tdispatch(parser.flush());\n\t};\n\n\trun()\n\t\t.then(() => handlers.onComplete?.())\n\t\t.catch((error: unknown) => {\n\t\t\tif (abortController.signal.aborted) {\n\t\t\t\thandlers.onAbort?.();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\thandlers.onError?.(\n\t\t\t\terror instanceof Error ? error : new Error(String(error)),\n\t\t\t);\n\t\t});\n\n\treturn () => abortController.abort();\n};\n"],"names":["COPILOT_ENDPOINT_PATH","buildRequestBody","request","readCopilotEventContent","event","content","followUps","followUp","parseEvent","payload","parsed","streamCopilotChat","baseUrl","endpointPath","headers","authToken","getAuthToken","fetchImpl","handlers","abortController","url","token","response","detail","reader","parser","CopilotSseParser","decoder","dispatch","payloads","done","value","chunk","error"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react"),_=require("./services/copilotIcebreakersClient.js"),f="BIK_ASSISTANT_AGENT",g="campaigns/overview",m=({baseUrl:a,icebreakersPath:n,headers:d,authToken:p,getAuthToken:C,fetchImpl:O,agent:c=f,route:i=g,storeId:u,enabled:l=!0})=>{const[o,k]=t.useState(null),[A,s]=t.useState(!1),[E,T]=t.useState(),[I,L]=t.useState(0),b=t.useRef(null);t.useEffect(()=>{if(!l)return;const e=new AbortController;return b.current?.abort(),b.current=e,s(!0),T(void 0),_.fetchCopilotIcebreakers({baseUrl:a,endpointPath:n,headers:d,authToken:p,getAuthToken:C,fetchImpl:O,agent:c,route:i,storeId:u,signal:e.signal}).then(r=>{e.signal.aborted||(k(r),s(!1))}).catch(r=>{e.signal.aborted||(T(r instanceof Error?r.message:String(r)),s(!1))}),()=>e.abort()},[c,i,u,l,a,n,I]);const S=t.useCallback(()=>L(e=>e+1),[]);return{icebreakers:t.useMemo(()=>(o?.icebreakers??[]).map((e,r)=>({id:`copilot-icebreaker-${r}`,text:e})),[o]),pageName:o?.pageName,matchedRoute:o?.route,isLoading:A,error:E,refresh:S}};exports.DEFAULT_COPILOT_AGENT=f;exports.DEFAULT_COPILOT_ROUTE=g;exports.useCopilotIcebreakers=m;
2
- //# sourceMappingURL=useCopilotIcebreakers.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useCopilotIcebreakers.js","sources":["../../../../src/components/bik-copilot/useCopilotIcebreakers.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n\tCopilotIcebreakersResult,\n\tUseCopilotIcebreakersOptions,\n\tUseCopilotIcebreakersResult,\n} from './model';\nimport { fetchCopilotIcebreakers } from './services/copilotIcebreakersClient';\n\n/** Agent hardcoded until more than one exists server side. */\nexport const DEFAULT_COPILOT_AGENT = 'BIK_ASSISTANT_AGENT';\n\n/**\n * Placeholder route. Replace it with the route the merchant is actually on —\n * the backend resolves both the ice breakers and the turn's page knowledge from\n * it, so a stale value means the copilot answers about the wrong page.\n */\nexport const DEFAULT_COPILOT_ROUTE = 'campaigns/overview';\n\n/**\n * Loads the suggested opening prompts for a route and maps them into the shape\n * the panel's suggestion chips take.\n *\n * Refetches whenever `agent` or `route` changes, so the chips follow the\n * merchant as they navigate, and aborts the in-flight request when they do.\n */\nexport const useCopilotIcebreakers = ({\n\tbaseUrl,\n\ticebreakersPath,\n\theaders,\n\tauthToken,\n\tgetAuthToken,\n\tfetchImpl,\n\tagent = DEFAULT_COPILOT_AGENT,\n\troute = DEFAULT_COPILOT_ROUTE,\n\tstoreId,\n\tenabled = true,\n}: UseCopilotIcebreakersOptions): UseCopilotIcebreakersResult => {\n\tconst [result, setResult] = useState<CopilotIcebreakersResult | null>(null);\n\tconst [isLoading, setIsLoading] = useState(false);\n\tconst [error, setError] = useState<string | undefined>();\n\tconst [reloadToken, setReloadToken] = useState(0);\n\n\tconst abortRef = useRef<AbortController | null>(null);\n\n\tuseEffect(() => {\n\t\tif (!enabled) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst abortController = new AbortController();\n\t\tabortRef.current?.abort();\n\t\tabortRef.current = abortController;\n\n\t\tsetIsLoading(true);\n\t\tsetError(undefined);\n\n\t\tfetchCopilotIcebreakers({\n\t\t\tbaseUrl,\n\t\t\tendpointPath: icebreakersPath,\n\t\t\theaders,\n\t\t\tauthToken,\n\t\t\tgetAuthToken,\n\t\t\tfetchImpl,\n\t\t\tagent,\n\t\t\troute,\n\t\t\tstoreId,\n\t\t\tsignal: abortController.signal,\n\t\t})\n\t\t\t.then((fetched) => {\n\t\t\t\tif (abortController.signal.aborted) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsetResult(fetched);\n\t\t\t\tsetIsLoading(false);\n\t\t\t})\n\t\t\t.catch((fetchError: unknown) => {\n\t\t\t\tif (abortController.signal.aborted) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsetError(\n\t\t\t\t\tfetchError instanceof Error ? fetchError.message : String(fetchError),\n\t\t\t\t);\n\t\t\t\tsetIsLoading(false);\n\t\t\t});\n\n\t\treturn () => abortController.abort();\n\t\t// The transport options are stable config in practice; re-running on a new\n\t\t// inline `headers` object would refetch on every render.\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [agent, route, storeId, enabled, baseUrl, icebreakersPath, reloadToken]);\n\n\tconst refresh = useCallback(() => setReloadToken((token) => token + 1), []);\n\n\tconst icebreakers = useMemo(\n\t\t() =>\n\t\t\t(result?.icebreakers ?? []).map((text, index) => ({\n\t\t\t\tid: `copilot-icebreaker-${index}`,\n\t\t\t\ttext,\n\t\t\t})),\n\t\t[result],\n\t);\n\n\treturn {\n\t\ticebreakers,\n\t\tpageName: result?.pageName,\n\t\tmatchedRoute: result?.route,\n\t\tisLoading,\n\t\terror,\n\t\trefresh,\n\t};\n};\n"],"names":["DEFAULT_COPILOT_AGENT","DEFAULT_COPILOT_ROUTE","useCopilotIcebreakers","baseUrl","icebreakersPath","headers","authToken","getAuthToken","fetchImpl","agent","route","storeId","enabled","result","setResult","useState","isLoading","setIsLoading","error","setError","reloadToken","setReloadToken","abortRef","useRef","useEffect","abortController","fetchCopilotIcebreakers","fetched","fetchError","refresh","useCallback","token","useMemo","text","index"],"mappings":"6JASaA,EAAwB,sBAOxBC,EAAwB,qBASxBC,EAAwB,CAAC,CACrC,QAAAC,EACA,gBAAAC,EACA,QAAAC,EACA,UAAAC,EACA,aAAAC,EACA,UAAAC,EACA,MAAAC,EAAQT,EACR,MAAAU,EAAQT,EACR,QAAAU,EACA,QAAAC,EAAU,EACX,IAAiE,CAChE,KAAM,CAACC,EAAQC,CAAS,EAAIC,EAAAA,SAA0C,IAAI,EACpE,CAACC,EAAWC,CAAY,EAAIF,EAAAA,SAAS,EAAK,EAC1C,CAACG,EAAOC,CAAQ,EAAIJ,WAAA,EACpB,CAACK,EAAaC,CAAc,EAAIN,EAAAA,SAAS,CAAC,EAE1CO,EAAWC,EAAAA,OAA+B,IAAI,EAEpDC,EAAAA,UAAU,IAAM,CACf,GAAI,CAACZ,EACJ,OAGD,MAAMa,EAAkB,IAAI,gBAC5B,OAAAH,EAAS,SAAS,MAAA,EAClBA,EAAS,QAAUG,EAEnBR,EAAa,EAAI,EACjBE,EAAS,MAAS,EAElBO,0BAAwB,CACvB,QAAAvB,EACA,aAAcC,EACd,QAAAC,EACA,UAAAC,EACA,aAAAC,EACA,UAAAC,EACA,MAAAC,EACA,MAAAC,EACA,QAAAC,EACA,OAAQc,EAAgB,MAAA,CACxB,EACC,KAAME,GAAY,CACdF,EAAgB,OAAO,UAG3BX,EAAUa,CAAO,EACjBV,EAAa,EAAK,EACnB,CAAC,EACA,MAAOW,GAAwB,CAC3BH,EAAgB,OAAO,UAG3BN,EACCS,aAAsB,MAAQA,EAAW,QAAU,OAAOA,CAAU,CAAA,EAErEX,EAAa,EAAK,EACnB,CAAC,EAEK,IAAMQ,EAAgB,MAAA,CAI9B,EAAG,CAAChB,EAAOC,EAAOC,EAASC,EAAST,EAASC,EAAiBgB,CAAW,CAAC,EAE1E,MAAMS,EAAUC,EAAAA,YAAY,IAAMT,EAAgBU,GAAUA,EAAQ,CAAC,EAAG,EAAE,EAW1E,MAAO,CACN,YAVmBC,EAAAA,QACnB,KACEnB,GAAQ,aAAe,CAAA,GAAI,IAAI,CAACoB,EAAMC,KAAW,CACjD,GAAI,sBAAsBA,CAAK,GAC/B,KAAAD,CAAA,EACC,EACH,CAACpB,CAAM,CAAA,EAKP,SAAUA,GAAQ,SAClB,aAAcA,GAAQ,MACtB,UAAAG,EACA,MAAAE,EACA,QAAAW,CAAA,CAEF"}
@@ -1,2 +0,0 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react"),x=require("./services/copilotDb.js"),te=require("./services/copilotMessagesClient.js"),$=require("./services/copilotPageSession.js"),q=require("./services/copilotStreamClient.js"),re=require("./useCopilotIcebreakers.js"),se="Something went wrong. Please try again.",Ce=({storeId:a,agent:w=re.DEFAULT_COPILOT_AGENT,route:f=re.DEFAULT_COPILOT_ROUTE,email:j,messagesPath:z,loadHistory:X=!0,systemPrompt:Y,model:Z,maxOutputTokens:J,sessionId:p,persist:l=!0,onError:M,onResponseComplete:K,onSessionIdChange:A,baseUrl:T,endpointPath:Q,headers:k,authToken:O,getAuthToken:P,fetchImpl:H})=>{const[F,D]=r.useState([]),[ne,V]=r.useState(p??null),[b,y]=r.useState(!1),[oe,W]=r.useState(!0),[ce,h]=r.useState(),[ue,ae]=r.useState(),[ie,L]=r.useState(!1),[G,d]=r.useState(!1),C=r.useRef([]),N=r.useRef(void 0),g=r.useRef(null),c=r.useRef(null),E=r.useRef(p??null),U=r.useRef(f);U.current=f;const I=r.useRef(1),v=r.useRef(!1),u=r.useCallback(e=>{const t=e(C.current);C.current=t,D(t)},[]),m=r.useCallback(e=>{N.current=e,ae(e)},[]),R=r.useCallback(()=>{const e=E.current;!l||!e||x.persistCopilotTurn({route:U.current,sessionId:e,messages:C.current,previousResponseId:N.current,storeId:a,agent:w})},[w,l,a]),B=r.useRef({baseUrl:T,messagesPath:z,headers:k,authToken:O,getAuthToken:P,fetchImpl:H,storeId:a,loadHistory:X});B.current={baseUrl:T,messagesPath:z,headers:k,authToken:O,getAuthToken:P,fetchImpl:H,storeId:a,loadHistory:X};const _=r.useCallback(async e=>{const t=B.current,s=E.current;return!t.loadHistory||!s?null:te.fetchCopilotMessages({baseUrl:t.baseUrl,endpointPath:t.messagesPath,headers:t.headers,authToken:t.authToken,getAuthToken:t.getAuthToken,fetchImpl:t.fetchImpl,storeId:t.storeId,sessionId:s,page:e,pageSize:te.COPILOT_HISTORY_PAGE_SIZE})},[]);r.useEffect(()=>{let e=!1;return(async()=>{c.current?.(),c.current=null,g.current=null,y(!1),h(void 0),W(!0),d(!1),v.current=!1,L(!1);const s=p??(l?await $.resolveCopilotSessionIdForRoute({route:f,storeId:a}):$.getCopilotSessionIdForRoute({route:f,storeId:a})),n=l?await x.loadCopilotSession(f,s):null;if(!e){if(E.current=s,V(s),C.current=n?.messages??[],D(C.current),m(n?.previousResponseId),W(!1),A?.(s),C.current.length>0){I.current=2,d(B.current.loadHistory);return}if(!p){I.current=1,d(!1);return}I.current=1;try{const o=await _(1);if(e||!o)return;I.current=2,u(()=>o.messages),d(o.hasMore)}catch{d(!1)}}})(),()=>{e=!0}},[f,a,p,l,m,u,_]);const le=r.useCallback(()=>{if(v.current||!G)return;v.current=!0,L(!0);const e=I.current;(async()=>{try{const t=await _(e);if(!t){d(!1);return}I.current=e+1,d(t.hasMore),u(s=>{const n=new Set(s.flatMap(i=>i.messageId?[i.id,i.messageId]:[i.id])),o=t.messages.filter(i=>!n.has(i.id));return o.length>0?[...o,...s]:s})}catch(t){M?.(t instanceof Error?t:new Error(String(t)))}finally{v.current=!1,L(!1)}})()},[u,G,M,_]);r.useEffect(()=>{l&&x.pruneCopilotSessions()},[l]),r.useEffect(()=>()=>c.current?.(),[]);const S=r.useCallback(e=>{const t=g.current;g.current=null,t&&u(s=>s.map(n=>{if(n.id!==t)return n;const o={...n,isStreaming:!1};return e?e(o):o}).filter(n=>n.id!==t||n.content.length>0||n.wasInterrupted===!0))},[u]),ee=r.useCallback(e=>{const t=g.current;if(e.type==="STREAM"){const s=q.readCopilotEventContent(e).text;if(!t||!s)return;u(n=>n.map(o=>o.id===t?{...o,content:o.content+s,messageId:e.messageId??o.messageId}:o));return}if(e.type==="TEXT"){const{text:s,followUps:n}=q.readCopilotEventContent(e);S(o=>({...o,content:s,messageId:e.messageId??o.messageId,...n?{followUps:n}:{}})),m(e.responseId),R(),K?.({text:s,responseId:e.responseId,followUps:n});return}e.type==="ERROR"&&(h(q.readCopilotEventContent(e).text||se),S(),R())},[u,S,K,R,m]),fe=r.useCallback(e=>{const t=e.trim(),s=E.current;if(!t||!s||b)return;h(void 0);const n=Date.now(),o=`copilot-a-${n}`;g.current=o,u(i=>[...i,{id:`copilot-u-${n}`,role:"user",content:t,timestamp:n},{id:o,role:"assistant",content:"",timestamp:n+1,isStreaming:!0}]),y(!0),R(),c.current=q.streamCopilotChat({baseUrl:T,endpointPath:Q,headers:k,authToken:O,getAuthToken:P,fetchImpl:H,storeId:a,agent:w,route:f,email:j,userPrompt:t,sessionId:s,previousResponseId:N.current,systemPrompt:Y,model:Z,maxOutputTokens:J},{onEvent:ee,onComplete:()=>{S(),y(!1),c.current=null,R()},onError:i=>{h(i.message||se),S(),y(!1),c.current=null,R(),M?.(i)},onAbort:()=>{S(),y(!1),c.current=null,R()}})},[w,u,O,T,j,Q,H,S,P,ee,k,b,J,Z,M,f,R,a,Y]),de=r.useCallback(()=>{if(!c.current)return;const e=g.current;e&&u(t=>t.map(s=>s.id===e?{...s,wasInterrupted:!0}:s)),c.current(),c.current=null},[u]),Re=r.useCallback(()=>{c.current?.(),c.current=null,g.current=null,y(!1),h(void 0),I.current=1,v.current=!1,L(!1),d(!1);const e=U.current,t=E.current,s=p??$.resetCopilotSessionForRoute({route:e,storeId:a});E.current=s,V(s),C.current=[],D([]),m(void 0),l&&t&&x.deleteCopilotSession(e,t),A?.(s)},[A,l,p,m,a]),pe=r.useMemo(()=>b&&!F.some(e=>e.isStreaming&&e.content),[b,F]);return{messages:F,sessionId:ne,previousResponseId:ue,isStreaming:b,isThinking:pe,isRestoring:oe,isLoadingHistory:ie,hasMoreHistory:G,error:ce,sendMessage:fe,loadOlderMessages:le,stopStreaming:de,startNewConversation:Re}};exports.useCopilotStreamChat=Ce;
2
- //# sourceMappingURL=useCopilotStreamChat.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useCopilotStreamChat.js","sources":["../../../../src/components/bik-copilot/useCopilotStreamChat.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n\tCopilotMessage,\n\tCopilotStreamEvent,\n\tUseCopilotStreamChatOptions,\n\tUseCopilotStreamChatResult,\n} from './model';\nimport {\n\tdeleteCopilotSession,\n\tloadCopilotSession,\n\tpersistCopilotTurn,\n\tpruneCopilotSessions,\n} from './services/copilotDb';\nimport {\n\tCOPILOT_HISTORY_PAGE_SIZE,\n\tfetchCopilotMessages,\n} from './services/copilotMessagesClient';\nimport {\n\tgetCopilotSessionIdForRoute,\n\tresetCopilotSessionForRoute,\n\tresolveCopilotSessionIdForRoute,\n} from './services/copilotPageSession';\nimport {\n\treadCopilotEventContent,\n\tstreamCopilotChat,\n} from './services/copilotStreamClient';\nimport {\n\tDEFAULT_COPILOT_AGENT,\n\tDEFAULT_COPILOT_ROUTE,\n} from './useCopilotIcebreakers';\n\nconst GENERIC_ERROR = 'Something went wrong. Please try again.';\n\n/**\n * Runs a merchant copilot conversation against the streaming\n * `/bik-ai/copilot-chatbot` endpoint.\n *\n * Owns three things the endpoint's contract requires:\n *\n * 1. **The session id.** One per route. Navigating away and back to the same\n * route continues that conversation, and so does a refresh: the ids live in\n * memory but are recovered from the stored records, which is what keeps them\n * lined up with the history the backend keys by them (see\n * `copilotPageSession`).\n * 2. **`previousResponseId`.** Absent on the first turn; from then on it is the\n * `responseId` of the last `TEXT` event, which is what makes OpenAI replay the\n * earlier turns server side. A turn that breaks halfway returns no\n * `responseId`, and the backend means that — the next turn starts fresh.\n * 3. **The transcript**, stored in IndexedDB under `{sessionId}:{route}` and\n * written every turn, so leaving the page mid-conversation loses nothing.\n */\nexport const useCopilotStreamChat = ({\n\tstoreId,\n\tagent = DEFAULT_COPILOT_AGENT,\n\troute = DEFAULT_COPILOT_ROUTE,\n\temail,\n\tmessagesPath,\n\tloadHistory = true,\n\tsystemPrompt,\n\tmodel,\n\tmaxOutputTokens,\n\tsessionId: pinnedSessionId,\n\tpersist = true,\n\tonError,\n\tonResponseComplete,\n\tonSessionIdChange,\n\tbaseUrl,\n\tendpointPath,\n\theaders,\n\tauthToken,\n\tgetAuthToken,\n\tfetchImpl,\n}: UseCopilotStreamChatOptions): UseCopilotStreamChatResult => {\n\tconst [messages, setMessages] = useState<CopilotMessage[]>([]);\n\tconst [sessionId, setSessionId] = useState<string | null>(\n\t\tpinnedSessionId ?? null,\n\t);\n\tconst [isStreaming, setIsStreaming] = useState(false);\n\tconst [isRestoring, setIsRestoring] = useState(true);\n\tconst [error, setError] = useState<string | undefined>();\n\tconst [previousResponseId, setPreviousResponseId] = useState<\n\t\tstring | undefined\n\t>();\n\tconst [isLoadingHistory, setIsLoadingHistory] = useState(false);\n\tconst [hasMoreHistory, setHasMoreHistory] = useState(false);\n\n\t// Async stream handlers run long after the render that created them, so the\n\t// live values live in refs and state is only the render mirror.\n\tconst messagesRef = useRef<CopilotMessage[]>([]);\n\tconst previousResponseIdRef = useRef<string | undefined>(undefined);\n\tconst streamingIdRef = useRef<string | null>(null);\n\tconst abortRef = useRef<(() => void) | null>(null);\n\tconst sessionIdRef = useRef<string | null>(pinnedSessionId ?? null);\n\t// The active route, for the async handlers that write the transcript.\n\tconst routeRef = useRef<string>(route);\n\trouteRef.current = route;\n\t// Next page of stored history to ask for. Starts at 2 when the local cache\n\t// already holds page 1's worth, which is the steady state.\n\tconst nextHistoryPageRef = useRef(1);\n\tconst isLoadingHistoryRef = useRef(false);\n\n\tconst applyMessages = useCallback(\n\t\t(updater: (previous: CopilotMessage[]) => CopilotMessage[]) => {\n\t\t\tconst next = updater(messagesRef.current);\n\t\t\tmessagesRef.current = next;\n\t\t\tsetMessages(next);\n\t\t},\n\t\t[],\n\t);\n\n\tconst setThreadResponseId = useCallback((responseId: string | undefined) => {\n\t\tpreviousResponseIdRef.current = responseId;\n\t\tsetPreviousResponseId(responseId);\n\t}, []);\n\n\tconst save = useCallback(() => {\n\t\tconst id = sessionIdRef.current;\n\t\tif (!persist || !id) {\n\t\t\treturn;\n\t\t}\n\t\tvoid persistCopilotTurn({\n\t\t\troute: routeRef.current,\n\t\t\tsessionId: id,\n\t\t\tmessages: messagesRef.current,\n\t\t\tpreviousResponseId: previousResponseIdRef.current,\n\t\t\tstoreId,\n\t\t\tagent,\n\t\t});\n\t}, [agent, persist, storeId]);\n\n\t// Transport config for the async readers below. Held in a ref rather than in\n\t// the effect's deps: a host that passes an inline `headers` object would\n\t// otherwise re-run restore on every render and wipe the transcript.\n\tconst transportRef = useRef({\n\t\tbaseUrl,\n\t\tmessagesPath,\n\t\theaders,\n\t\tauthToken,\n\t\tgetAuthToken,\n\t\tfetchImpl,\n\t\tstoreId,\n\t\tloadHistory,\n\t});\n\ttransportRef.current = {\n\t\tbaseUrl,\n\t\tmessagesPath,\n\t\theaders,\n\t\tauthToken,\n\t\tgetAuthToken,\n\t\tfetchImpl,\n\t\tstoreId,\n\t\tloadHistory,\n\t};\n\n\tconst readHistoryPage = useCallback(async (page: number) => {\n\t\tconst transport = transportRef.current;\n\t\tconst id = sessionIdRef.current;\n\t\tif (!transport.loadHistory || !id) {\n\t\t\treturn null;\n\t\t}\n\t\treturn fetchCopilotMessages({\n\t\t\tbaseUrl: transport.baseUrl,\n\t\t\tendpointPath: transport.messagesPath,\n\t\t\theaders: transport.headers,\n\t\t\tauthToken: transport.authToken,\n\t\t\tgetAuthToken: transport.getAuthToken,\n\t\t\tfetchImpl: transport.fetchImpl,\n\t\t\tstoreId: transport.storeId,\n\t\t\tsessionId: id,\n\t\t\tpage,\n\t\t\tpageSize: COPILOT_HISTORY_PAGE_SIZE,\n\t\t});\n\t}, []);\n\n\t// Resolve the conversation for this route and read it back from IndexedDB.\n\t// Runs again when `route` changes, because the route is half of a\n\t// conversation's identity — a different page is a different chat.\n\tuseEffect(() => {\n\t\tlet cancelled = false;\n\n\t\tconst restore = async () => {\n\t\t\t// Chunks from the previous route's turn must not land in this one.\n\t\t\tabortRef.current?.();\n\t\t\tabortRef.current = null;\n\t\t\tstreamingIdRef.current = null;\n\t\t\tsetIsStreaming(false);\n\t\t\tsetError(undefined);\n\t\t\tsetIsRestoring(true);\n\t\t\tsetHasMoreHistory(false);\n\t\t\tisLoadingHistoryRef.current = false;\n\t\t\tsetIsLoadingHistory(false);\n\n\t\t\tconst id =\n\t\t\t\tpinnedSessionId ??\n\t\t\t\t(persist\n\t\t\t\t\t? await resolveCopilotSessionIdForRoute({ route, storeId })\n\t\t\t\t\t: getCopilotSessionIdForRoute({ route, storeId }));\n\t\t\tconst record = persist ? await loadCopilotSession(route, id) : null;\n\t\t\tif (cancelled) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsessionIdRef.current = id;\n\t\t\tsetSessionId(id);\n\t\t\tmessagesRef.current = record?.messages ?? [];\n\t\t\tsetMessages(messagesRef.current);\n\t\t\tsetThreadResponseId(record?.previousResponseId);\n\t\t\tsetIsRestoring(false);\n\t\t\tonSessionIdChange?.(id);\n\n\t\t\t// The cache holds at most one page, so what is on screen already *is*\n\t\t\t// page 1 and the reader's first scroll-up wants page 2.\n\t\t\tif (messagesRef.current.length > 0) {\n\t\t\t\tnextHistoryPageRef.current = 2;\n\t\t\t\tsetHasMoreHistory(transportRef.current.loadHistory);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Nothing cached and nothing to scroll, so page 1 has to be fetched for\n\t\t\t// the history to be reachable at all — but only for an id the host\n\t\t\t// pinned. An id this library resolved came out of the local records, so\n\t\t\t// an empty cache for it means an empty conversation, and a freshly\n\t\t\t// minted one has nothing behind it by definition. Asking anyway would\n\t\t\t// put a pointless request on the start of every new conversation.\n\t\t\tif (!pinnedSessionId) {\n\t\t\t\tnextHistoryPageRef.current = 1;\n\t\t\t\tsetHasMoreHistory(false);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tnextHistoryPageRef.current = 1;\n\t\t\ttry {\n\t\t\t\tconst firstPage = await readHistoryPage(1);\n\t\t\t\tif (cancelled || !firstPage) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tnextHistoryPageRef.current = 2;\n\t\t\t\tapplyMessages(() => firstPage.messages);\n\t\t\t\tsetHasMoreHistory(firstPage.hasMore);\n\t\t\t} catch {\n\t\t\t\t// A session the backend has never heard of is the normal case for a\n\t\t\t\t// host-pinned id on its first use; the empty state covers it.\n\t\t\t\tsetHasMoreHistory(false);\n\t\t\t}\n\t\t};\n\n\t\tvoid restore();\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t\t// onSessionIdChange is event-like: re-running restore because the host\n\t\t// passed a new inline callback would wipe the transcript.\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [\n\t\troute,\n\t\tstoreId,\n\t\tpinnedSessionId,\n\t\tpersist,\n\t\tsetThreadResponseId,\n\t\tapplyMessages,\n\t\treadHistoryPage,\n\t]);\n\n\t/**\n\t * Prepends the page before the oldest message on screen.\n\t *\n\t * Guarded by a ref rather than the state flag because a scroll handler can\n\t * fire many times before React re-renders, and each of those would otherwise\n\t * start its own request for the same page.\n\t */\n\tconst loadOlderMessages = useCallback(() => {\n\t\tif (isLoadingHistoryRef.current || !hasMoreHistory) {\n\t\t\treturn;\n\t\t}\n\t\tisLoadingHistoryRef.current = true;\n\t\tsetIsLoadingHistory(true);\n\n\t\tconst page = nextHistoryPageRef.current;\n\t\tvoid (async () => {\n\t\t\ttry {\n\t\t\t\tconst older = await readHistoryPage(page);\n\t\t\t\tif (!older) {\n\t\t\t\t\tsetHasMoreHistory(false);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tnextHistoryPageRef.current = page + 1;\n\t\t\t\tsetHasMoreHistory(older.hasMore);\n\t\t\t\tapplyMessages((previous) => {\n\t\t\t\t\tconst known = new Set(\n\t\t\t\t\t\tprevious.flatMap((message) =>\n\t\t\t\t\t\t\tmessage.messageId\n\t\t\t\t\t\t\t\t? [message.id, message.messageId]\n\t\t\t\t\t\t\t\t: [message.id],\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tconst fresh = older.messages.filter(\n\t\t\t\t\t\t(message) => !known.has(message.id),\n\t\t\t\t\t);\n\t\t\t\t\treturn fresh.length > 0 ? [...fresh, ...previous] : previous;\n\t\t\t\t});\n\t\t\t} catch (historyError) {\n\t\t\t\t// Left silent in the transcript on purpose: failing to reach further\n\t\t\t\t// back is not a failure of the conversation on screen. Another\n\t\t\t\t// scroll-up retries the same page.\n\t\t\t\tonError?.(\n\t\t\t\t\thistoryError instanceof Error\n\t\t\t\t\t\t? historyError\n\t\t\t\t\t\t: new Error(String(historyError)),\n\t\t\t\t);\n\t\t\t} finally {\n\t\t\t\tisLoadingHistoryRef.current = false;\n\t\t\t\tsetIsLoadingHistory(false);\n\t\t\t}\n\t\t})();\n\t}, [applyMessages, hasMoreHistory, onError, readHistoryPage]);\n\n\t// Records pile up one per route per page load otherwise, since every refresh\n\t// writes under a new key.\n\tuseEffect(() => {\n\t\tif (persist) {\n\t\t\tvoid pruneCopilotSessions();\n\t\t}\n\t}, [persist]);\n\n\t// Abort an in-flight turn if the copilot unmounts.\n\tuseEffect(() => () => abortRef.current?.(), []);\n\n\tconst finishStreamingBubble = useCallback(\n\t\t(mutate?: (message: CopilotMessage) => CopilotMessage) => {\n\t\t\tconst streamingId = streamingIdRef.current;\n\t\t\tstreamingIdRef.current = null;\n\t\t\tif (!streamingId) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tapplyMessages((previous) =>\n\t\t\t\tprevious\n\t\t\t\t\t.map((message) => {\n\t\t\t\t\t\tif (message.id !== streamingId) {\n\t\t\t\t\t\t\treturn message;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst settled: CopilotMessage = {\n\t\t\t\t\t\t\t...message,\n\t\t\t\t\t\t\tisStreaming: false,\n\t\t\t\t\t\t};\n\t\t\t\t\t\treturn mutate ? mutate(settled) : settled;\n\t\t\t\t\t})\n\t\t\t\t\t// An assistant bubble that never received text would render as an\n\t\t\t\t\t// empty balloon; the error banner carries the information instead.\n\t\t\t\t\t// A stopped turn keeps its bubble either way — the interrupted note\n\t\t\t\t\t// is the only trace a turn the reader cut short ever happened.\n\t\t\t\t\t.filter(\n\t\t\t\t\t\t(message) =>\n\t\t\t\t\t\t\tmessage.id !== streamingId ||\n\t\t\t\t\t\t\tmessage.content.length > 0 ||\n\t\t\t\t\t\t\tmessage.wasInterrupted === true,\n\t\t\t\t\t),\n\t\t\t);\n\t\t},\n\t\t[applyMessages],\n\t);\n\n\tconst handleEvent = useCallback(\n\t\t(event: CopilotStreamEvent) => {\n\t\t\tconst streamingId = streamingIdRef.current;\n\n\t\t\tif (event.type === 'STREAM') {\n\t\t\t\tconst chunk = readCopilotEventContent(event).text;\n\t\t\t\tif (!streamingId || !chunk) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tapplyMessages((previous) =>\n\t\t\t\t\tprevious.map((message) =>\n\t\t\t\t\t\tmessage.id === streamingId\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t...message,\n\t\t\t\t\t\t\t\t\tcontent: message.content + chunk,\n\t\t\t\t\t\t\t\t\tmessageId: event.messageId ?? message.messageId,\n\t\t\t\t\t\t\t }\n\t\t\t\t\t\t\t: message,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (event.type === 'TEXT') {\n\t\t\t\t// TEXT carries the whole message, so it replaces the accumulated\n\t\t\t\t// chunks rather than appending — that keeps the bubble correct even if\n\t\t\t\t// a STREAM frame was dropped or duplicated.\n\t\t\t\tconst { text: fullText, followUps } = readCopilotEventContent(event);\n\t\t\t\tfinishStreamingBubble((message) => ({\n\t\t\t\t\t...message,\n\t\t\t\t\tcontent: fullText,\n\t\t\t\t\tmessageId: event.messageId ?? message.messageId,\n\t\t\t\t\t...(followUps ? { followUps } : {}),\n\t\t\t\t}));\n\t\t\t\tsetThreadResponseId(event.responseId);\n\t\t\t\tsave();\n\t\t\t\tonResponseComplete?.({\n\t\t\t\t\ttext: fullText,\n\t\t\t\t\tresponseId: event.responseId,\n\t\t\t\t\tfollowUps,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (event.type === 'ERROR') {\n\t\t\t\tsetError(readCopilotEventContent(event).text || GENERIC_ERROR);\n\t\t\t\tfinishStreamingBubble();\n\t\t\t\tsave();\n\t\t\t}\n\n\t\t\t// Unknown types (TOOL_STATUS is declared server side but not emitted)\n\t\t\t// are ignored so a new event type cannot break an existing client.\n\t\t},\n\t\t[\n\t\t\tapplyMessages,\n\t\t\tfinishStreamingBubble,\n\t\t\tonResponseComplete,\n\t\t\tsave,\n\t\t\tsetThreadResponseId,\n\t\t],\n\t);\n\n\tconst sendMessage = useCallback(\n\t\t(message: string) => {\n\t\t\tconst userPrompt = message.trim();\n\t\t\tconst id = sessionIdRef.current;\n\t\t\tif (!userPrompt || !id || isStreaming) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetError(undefined);\n\t\t\tconst now = Date.now();\n\t\t\tconst assistantBubbleId = `copilot-a-${now}`;\n\t\t\tstreamingIdRef.current = assistantBubbleId;\n\n\t\t\tapplyMessages((previous) => [\n\t\t\t\t...previous,\n\t\t\t\t{\n\t\t\t\t\tid: `copilot-u-${now}`,\n\t\t\t\t\trole: 'user',\n\t\t\t\t\tcontent: userPrompt,\n\t\t\t\t\ttimestamp: now,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: assistantBubbleId,\n\t\t\t\t\trole: 'assistant',\n\t\t\t\t\tcontent: '',\n\t\t\t\t\ttimestamp: now + 1,\n\t\t\t\t\tisStreaming: true,\n\t\t\t\t},\n\t\t\t]);\n\t\t\tsetIsStreaming(true);\n\t\t\tsave();\n\n\t\t\tabortRef.current = streamCopilotChat(\n\t\t\t\t{\n\t\t\t\t\tbaseUrl,\n\t\t\t\t\tendpointPath,\n\t\t\t\t\theaders,\n\t\t\t\t\tauthToken,\n\t\t\t\t\tgetAuthToken,\n\t\t\t\t\tfetchImpl,\n\t\t\t\t\tstoreId,\n\t\t\t\t\tagent,\n\t\t\t\t\troute,\n\t\t\t\t\temail,\n\t\t\t\t\tuserPrompt,\n\t\t\t\t\tsessionId: id,\n\t\t\t\t\tpreviousResponseId: previousResponseIdRef.current,\n\t\t\t\t\tsystemPrompt,\n\t\t\t\t\tmodel,\n\t\t\t\t\tmaxOutputTokens,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tonEvent: handleEvent,\n\t\t\t\t\tonComplete: () => {\n\t\t\t\t\t\t// STOP closes the stream without a frame, so this is where a turn\n\t\t\t\t\t\t// ends. TEXT has usually already settled the bubble.\n\t\t\t\t\t\tfinishStreamingBubble();\n\t\t\t\t\t\tsetIsStreaming(false);\n\t\t\t\t\t\tabortRef.current = null;\n\t\t\t\t\t\tsave();\n\t\t\t\t\t},\n\t\t\t\t\tonError: (streamError) => {\n\t\t\t\t\t\tsetError(streamError.message || GENERIC_ERROR);\n\t\t\t\t\t\tfinishStreamingBubble();\n\t\t\t\t\t\tsetIsStreaming(false);\n\t\t\t\t\t\tabortRef.current = null;\n\t\t\t\t\t\tsave();\n\t\t\t\t\t\tonError?.(streamError);\n\t\t\t\t\t},\n\t\t\t\t\tonAbort: () => {\n\t\t\t\t\t\tfinishStreamingBubble();\n\t\t\t\t\t\tsetIsStreaming(false);\n\t\t\t\t\t\tabortRef.current = null;\n\t\t\t\t\t\tsave();\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t\t[\n\t\t\tagent,\n\t\t\tapplyMessages,\n\t\t\tauthToken,\n\t\t\tbaseUrl,\n\t\t\temail,\n\t\t\tendpointPath,\n\t\t\tfetchImpl,\n\t\t\tfinishStreamingBubble,\n\t\t\tgetAuthToken,\n\t\t\thandleEvent,\n\t\t\theaders,\n\t\t\tisStreaming,\n\t\t\tmaxOutputTokens,\n\t\t\tmodel,\n\t\t\tonError,\n\t\t\troute,\n\t\t\tsave,\n\t\t\tstoreId,\n\t\t\tsystemPrompt,\n\t\t],\n\t);\n\n\tconst stopStreaming = useCallback(() => {\n\t\tif (!abortRef.current) {\n\t\t\treturn;\n\t\t}\n\t\t// Flagged here rather than in `onAbort`, because an abort that lands between\n\t\t// frames ends the stream through `onComplete` instead. Whichever fires, the\n\t\t// reader stopped this turn, and whatever text had arrived stays.\n\t\tconst streamingId = streamingIdRef.current;\n\t\tif (streamingId) {\n\t\t\tapplyMessages((previous) =>\n\t\t\t\tprevious.map((message) =>\n\t\t\t\t\tmessage.id === streamingId\n\t\t\t\t\t\t? { ...message, wasInterrupted: true }\n\t\t\t\t\t\t: message,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tabortRef.current();\n\t\tabortRef.current = null;\n\t}, [applyMessages]);\n\n\tconst startNewConversation = useCallback(() => {\n\t\tabortRef.current?.();\n\t\tabortRef.current = null;\n\t\tstreamingIdRef.current = null;\n\t\tsetIsStreaming(false);\n\t\tsetError(undefined);\n\t\t// A new conversation has no history behind it; the old session's pages\n\t\t// belong to the old session id.\n\t\tnextHistoryPageRef.current = 1;\n\t\tisLoadingHistoryRef.current = false;\n\t\tsetIsLoadingHistory(false);\n\t\tsetHasMoreHistory(false);\n\n\t\tconst activeRoute = routeRef.current;\n\t\t// The conversation being cleared, so its stored transcript can go with it.\n\t\tconst clearedId = sessionIdRef.current;\n\t\t// A host-pinned id is the host's to change, so only clear its transcript.\n\t\tconst nextId =\n\t\t\tpinnedSessionId ??\n\t\t\tresetCopilotSessionForRoute({ route: activeRoute, storeId });\n\t\tsessionIdRef.current = nextId;\n\t\tsetSessionId(nextId);\n\t\tmessagesRef.current = [];\n\t\tsetMessages([]);\n\t\tsetThreadResponseId(undefined);\n\n\t\t// \"Refresh chat\" wipes the record, not just the screen: the cleared\n\t\t// conversation is deleted from IndexedDB so reopening the tab starts fresh\n\t\t// instead of resuming it. Nothing is written for the new session here — its\n\t\t// first record is stamped when the first turn is sent, which is also what\n\t\t// keeps an untouched refresh from leaving an empty record behind.\n\t\tif (persist && clearedId) {\n\t\t\tvoid deleteCopilotSession(activeRoute, clearedId);\n\t\t}\n\t\tonSessionIdChange?.(nextId);\n\t}, [\n\t\tonSessionIdChange,\n\t\tpersist,\n\t\tpinnedSessionId,\n\t\tsetThreadResponseId,\n\t\tstoreId,\n\t]);\n\n\t// The thinking bubble is only for the wait before the first token; once text\n\t// starts arriving the bubble itself shows progress.\n\tconst isThinking = useMemo(\n\t\t() =>\n\t\t\tisStreaming &&\n\t\t\t!messages.some((message) => message.isStreaming && message.content),\n\t\t[isStreaming, messages],\n\t);\n\n\treturn {\n\t\tmessages,\n\t\tsessionId,\n\t\tpreviousResponseId,\n\t\tisStreaming,\n\t\tisThinking,\n\t\tisRestoring,\n\t\tisLoadingHistory,\n\t\thasMoreHistory,\n\t\terror,\n\t\tsendMessage,\n\t\tloadOlderMessages,\n\t\tstopStreaming,\n\t\tstartNewConversation,\n\t};\n};\n"],"names":["GENERIC_ERROR","useCopilotStreamChat","storeId","agent","DEFAULT_COPILOT_AGENT","route","DEFAULT_COPILOT_ROUTE","email","messagesPath","loadHistory","systemPrompt","model","maxOutputTokens","pinnedSessionId","persist","onError","onResponseComplete","onSessionIdChange","baseUrl","endpointPath","headers","authToken","getAuthToken","fetchImpl","messages","setMessages","useState","sessionId","setSessionId","isStreaming","setIsStreaming","isRestoring","setIsRestoring","error","setError","previousResponseId","setPreviousResponseId","isLoadingHistory","setIsLoadingHistory","hasMoreHistory","setHasMoreHistory","messagesRef","useRef","previousResponseIdRef","streamingIdRef","abortRef","sessionIdRef","routeRef","nextHistoryPageRef","isLoadingHistoryRef","applyMessages","useCallback","updater","next","setThreadResponseId","responseId","save","id","persistCopilotTurn","transportRef","readHistoryPage","page","transport","fetchCopilotMessages","COPILOT_HISTORY_PAGE_SIZE","useEffect","cancelled","resolveCopilotSessionIdForRoute","getCopilotSessionIdForRoute","record","loadCopilotSession","firstPage","loadOlderMessages","older","previous","known","message","fresh","historyError","pruneCopilotSessions","finishStreamingBubble","mutate","streamingId","settled","handleEvent","event","chunk","readCopilotEventContent","fullText","followUps","sendMessage","userPrompt","now","assistantBubbleId","streamCopilotChat","streamError","stopStreaming","startNewConversation","activeRoute","clearedId","nextId","resetCopilotSessionForRoute","deleteCopilotSession","isThinking","useMemo"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react"),C=4,u=8,g=()=>typeof window>"u"?{width:0,height:0}:{width:window.innerWidth,height:window.innerHeight},p=(r,a,n)=>{if(!n.width||!n.height)return r;const s=Math.max(u,n.width-a-u),c=Math.max(u,n.height-a-u);return{x:Math.min(Math.max(r.x,u),s),y:Math.min(Math.max(r.y,u),c)}},k=(r,a,n,s)=>{const c=s.width-a-n,h=s.height-a-n;switch(r){case"top-left":return{x:n,y:n};case"top-right":return{x:c,y:n};case"bottom-left":return{x:n,y:h};default:return{x:c,y:h}}},E=({size:r,corner:a,offset:n,enabled:s,snapToEdge:c,initialPosition:h,onPositionChange:b})=>{const[R,X]=o.useState(g),[l,x]=o.useState(()=>{const t=g();return p(h??k(a,r,n,t),r,t)}),[D,y]=o.useState(!1),w=o.useRef(null),m=o.useRef(!1);o.useEffect(()=>{const t=()=>{const e=g();X(e),x(i=>p(i,r,e))};return window.addEventListener("resize",t),()=>window.removeEventListener("resize",t)},[r]);const I=o.useCallback(t=>{m.current=!1,!(!s||t.button!==0)&&(t.currentTarget.setPointerCapture(t.pointerId),w.current={pointerId:t.pointerId,startX:t.clientX,startY:t.clientY,originX:l.x,originY:l.y,moved:!1,latest:l})},[s,l]),M=o.useCallback(t=>{const e=w.current;if(!e||e.pointerId!==t.pointerId)return;const i=t.clientX-e.startX,d=t.clientY-e.startY;if(!e.moved){if(Math.abs(i)<C&&Math.abs(d)<C)return;e.moved=!0,y(!0)}const f=p({x:e.originX+i,y:e.originY+d},r,g());e.latest=f,x(f)},[r]),P=o.useCallback(t=>{const e=w.current;if(!e||e.pointerId!==t.pointerId||(w.current=null,t.currentTarget.hasPointerCapture(t.pointerId)&&t.currentTarget.releasePointerCapture(t.pointerId),!e.moved))return;m.current=!0,y(!1);const i=g(),d=c?p({x:e.latest.x+r/2<i.width/2?n:i.width-r-n,y:e.latest.y},r,i):e.latest;x(d),b?.(d)},[n,b,r,c]),Y=o.useCallback(()=>{const t=m.current;return m.current=!1,t},[]),V=o.useMemo(()=>({onPointerDown:I,onPointerMove:M,onPointerUp:P,onPointerCancel:P}),[P,I,M]);return{position:l,isDragging:D,viewport:R,dragHandlers:V,shouldIgnoreClick:Y}};exports.useDraggableFloater=E;
2
- //# sourceMappingURL=useDraggableFloater.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useDraggableFloater.js","sources":["../../../../src/components/bik-copilot/useDraggableFloater.ts"],"sourcesContent":["import {\n\tPointerEvent as ReactPointerEvent,\n\tuseCallback,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from 'react';\nimport {\n\tCopilotBallPosition,\n\tCopilotCorner,\n\tCopilotViewport,\n\tUseDraggableFloaterOptions,\n\tUseDraggableFloaterResult,\n} from './model';\n\n/** Movement (px) a gesture must cover before it counts as a drag, not a tap. */\nconst DRAG_THRESHOLD_PX = 4;\n\n/** Smallest gap kept between the dragged element and the viewport edges. */\nconst VIEWPORT_MARGIN_PX = 8;\n\nconst getViewport = (): CopilotViewport =>\n\ttypeof window === 'undefined'\n\t\t? { width: 0, height: 0 }\n\t\t: { width: window.innerWidth, height: window.innerHeight };\n\nconst clampToViewport = (\n\tposition: CopilotBallPosition,\n\tsize: number,\n\tviewport: CopilotViewport,\n): CopilotBallPosition => {\n\tif (!viewport.width || !viewport.height) {\n\t\treturn position;\n\t}\n\tconst maxX = Math.max(\n\t\tVIEWPORT_MARGIN_PX,\n\t\tviewport.width - size - VIEWPORT_MARGIN_PX,\n\t);\n\tconst maxY = Math.max(\n\t\tVIEWPORT_MARGIN_PX,\n\t\tviewport.height - size - VIEWPORT_MARGIN_PX,\n\t);\n\treturn {\n\t\tx: Math.min(Math.max(position.x, VIEWPORT_MARGIN_PX), maxX),\n\t\ty: Math.min(Math.max(position.y, VIEWPORT_MARGIN_PX), maxY),\n\t};\n};\n\nconst getCornerPosition = (\n\tcorner: CopilotCorner,\n\tsize: number,\n\toffset: number,\n\tviewport: CopilotViewport,\n): CopilotBallPosition => {\n\tconst rightEdge = viewport.width - size - offset;\n\tconst bottomEdge = viewport.height - size - offset;\n\tswitch (corner) {\n\t\tcase 'top-left':\n\t\t\treturn { x: offset, y: offset };\n\t\tcase 'top-right':\n\t\t\treturn { x: rightEdge, y: offset };\n\t\tcase 'bottom-left':\n\t\t\treturn { x: offset, y: bottomEdge };\n\t\tcase 'bottom-right':\n\t\tdefault:\n\t\t\treturn { x: rightEdge, y: bottomEdge };\n\t}\n};\n\ninterface DragGesture {\n\tpointerId: number;\n\tstartX: number;\n\tstartY: number;\n\toriginX: number;\n\toriginY: number;\n\tmoved: boolean;\n\tlatest: CopilotBallPosition;\n}\n\n/**\n * Drives a fixed-position element the user can drag anywhere in the viewport.\n *\n * The hook owns the element's coordinates, keeps them inside the viewport as the\n * window resizes, and separates a tap from a drag so the same element can both\n * be dragged and clicked.\n */\nexport const useDraggableFloater = ({\n\tsize,\n\tcorner,\n\toffset,\n\tenabled,\n\tsnapToEdge,\n\tinitialPosition,\n\tonPositionChange,\n}: UseDraggableFloaterOptions): UseDraggableFloaterResult => {\n\tconst [viewport, setViewport] = useState<CopilotViewport>(getViewport);\n\tconst [position, setPosition] = useState<CopilotBallPosition>(() => {\n\t\tconst initialViewport = getViewport();\n\t\treturn clampToViewport(\n\t\t\tinitialPosition ??\n\t\t\t\tgetCornerPosition(corner, size, offset, initialViewport),\n\t\t\tsize,\n\t\t\tinitialViewport,\n\t\t);\n\t});\n\tconst [isDragging, setIsDragging] = useState(false);\n\n\tconst gestureRef = useRef<DragGesture | null>(null);\n\tconst ignoreNextClickRef = useRef(false);\n\n\t// Keep the element reachable when the window is resized around it.\n\tuseEffect(() => {\n\t\tconst handleResize = () => {\n\t\t\tconst nextViewport = getViewport();\n\t\t\tsetViewport(nextViewport);\n\t\t\tsetPosition((previous) => clampToViewport(previous, size, nextViewport));\n\t\t};\n\t\twindow.addEventListener('resize', handleResize);\n\t\treturn () => window.removeEventListener('resize', handleResize);\n\t}, [size]);\n\n\tconst handlePointerDown = useCallback(\n\t\t(event: ReactPointerEvent<HTMLElement>) => {\n\t\t\t// A stale flag would otherwise swallow the next legitimate click.\n\t\t\tignoreNextClickRef.current = false;\n\t\t\tif (!enabled || event.button !== 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tevent.currentTarget.setPointerCapture(event.pointerId);\n\t\t\tgestureRef.current = {\n\t\t\t\tpointerId: event.pointerId,\n\t\t\t\tstartX: event.clientX,\n\t\t\t\tstartY: event.clientY,\n\t\t\t\toriginX: position.x,\n\t\t\t\toriginY: position.y,\n\t\t\t\tmoved: false,\n\t\t\t\tlatest: position,\n\t\t\t};\n\t\t},\n\t\t[enabled, position],\n\t);\n\n\tconst handlePointerMove = useCallback(\n\t\t(event: ReactPointerEvent<HTMLElement>) => {\n\t\t\tconst gesture = gestureRef.current;\n\t\t\tif (!gesture || gesture.pointerId !== event.pointerId) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst deltaX = event.clientX - gesture.startX;\n\t\t\tconst deltaY = event.clientY - gesture.startY;\n\n\t\t\tif (!gesture.moved) {\n\t\t\t\tif (\n\t\t\t\t\tMath.abs(deltaX) < DRAG_THRESHOLD_PX &&\n\t\t\t\t\tMath.abs(deltaY) < DRAG_THRESHOLD_PX\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tgesture.moved = true;\n\t\t\t\tsetIsDragging(true);\n\t\t\t}\n\n\t\t\tconst next = clampToViewport(\n\t\t\t\t{ x: gesture.originX + deltaX, y: gesture.originY + deltaY },\n\t\t\t\tsize,\n\t\t\t\tgetViewport(),\n\t\t\t);\n\t\t\tgesture.latest = next;\n\t\t\tsetPosition(next);\n\t\t},\n\t\t[size],\n\t);\n\n\tconst endGesture = useCallback(\n\t\t(event: ReactPointerEvent<HTMLElement>) => {\n\t\t\tconst gesture = gestureRef.current;\n\t\t\tif (!gesture || gesture.pointerId !== event.pointerId) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tgestureRef.current = null;\n\t\t\tif (event.currentTarget.hasPointerCapture(event.pointerId)) {\n\t\t\t\tevent.currentTarget.releasePointerCapture(event.pointerId);\n\t\t\t}\n\t\t\tif (!gesture.moved) {\n\t\t\t\t// A tap: let the click handler run untouched.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tignoreNextClickRef.current = true;\n\t\t\tsetIsDragging(false);\n\n\t\t\tconst currentViewport = getViewport();\n\t\t\tconst settled = snapToEdge\n\t\t\t\t? clampToViewport(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tx:\n\t\t\t\t\t\t\t\tgesture.latest.x + size / 2 < currentViewport.width / 2\n\t\t\t\t\t\t\t\t\t? offset\n\t\t\t\t\t\t\t\t\t: currentViewport.width - size - offset,\n\t\t\t\t\t\t\ty: gesture.latest.y,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsize,\n\t\t\t\t\t\tcurrentViewport,\n\t\t\t\t )\n\t\t\t\t: gesture.latest;\n\n\t\t\tsetPosition(settled);\n\t\t\tonPositionChange?.(settled);\n\t\t},\n\t\t[offset, onPositionChange, size, snapToEdge],\n\t);\n\n\tconst shouldIgnoreClick = useCallback(() => {\n\t\tconst ignore = ignoreNextClickRef.current;\n\t\tignoreNextClickRef.current = false;\n\t\treturn ignore;\n\t}, []);\n\n\tconst dragHandlers = useMemo(\n\t\t() => ({\n\t\t\tonPointerDown: handlePointerDown,\n\t\t\tonPointerMove: handlePointerMove,\n\t\t\tonPointerUp: endGesture,\n\t\t\tonPointerCancel: endGesture,\n\t\t}),\n\t\t[endGesture, handlePointerDown, handlePointerMove],\n\t);\n\n\treturn { position, isDragging, viewport, dragHandlers, shouldIgnoreClick };\n};\n"],"names":["DRAG_THRESHOLD_PX","VIEWPORT_MARGIN_PX","getViewport","clampToViewport","position","size","viewport","maxX","maxY","getCornerPosition","corner","offset","rightEdge","bottomEdge","useDraggableFloater","enabled","snapToEdge","initialPosition","onPositionChange","setViewport","useState","setPosition","initialViewport","isDragging","setIsDragging","gestureRef","useRef","ignoreNextClickRef","useEffect","handleResize","nextViewport","previous","handlePointerDown","useCallback","event","handlePointerMove","gesture","deltaX","deltaY","next","endGesture","currentViewport","settled","shouldIgnoreClick","ignore","dragHandlers","useMemo"],"mappings":"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"}
@@ -1,32 +0,0 @@
1
- import { default as React } from 'react';
2
- import { BIKCopilotProps } from './model';
3
- /**
4
- * The copilot ball and panel wired to the streaming `/bik-ai/copilot-chatbot`
5
- * endpoint, with the transcript persisted in IndexedDB and route-aware ice
6
- * breakers from `/bik-ai/copilot-icebreakers`.
7
- *
8
- * Chunks arrive as `STREAM` events and are appended live; the final `TEXT` event
9
- * replaces the bubble with the authoritative full message and carries the
10
- * `responseId` that threads the next turn. A session id is created on first use
11
- * and restored on reload, so a refresh resumes the same conversation. The
12
- * header's reset button starts a new session id and a new OpenAI thread.
13
- *
14
- * Ice breakers are fetched for the current `agent` + `route` the first time the
15
- * panel is opened, and refetched when the route changes.
16
- *
17
- * ```tsx
18
- * <BIKCopilot
19
- * baseUrl={AI_BACKEND_URL}
20
- * getAuthToken={() => firebaseUser.getIdToken()}
21
- * headers={{ 'bik-referer': 'dashboard' }}
22
- * storeId={storeId}
23
- * email={user.email}
24
- * route={currentRoute}
25
- * title="Copilot"
26
- * badge="New"
27
- * subtitle="Way smarter, wildly more capable"
28
- * />
29
- * ```
30
- */
31
- export declare const BIKCopilot: React.FC<BIKCopilotProps>;
32
- export default BIKCopilot;
@@ -1,114 +0,0 @@
1
- import { jsx as W } from "react/jsx-runtime";
2
- import { useState as X, useCallback as u } from "react";
3
- import { ControlledCopilot as Y } from "./ControlledCopilot.js";
4
- import { useCopilotIcebreakers as Z } from "./useCopilotIcebreakers.js";
5
- import { useCopilotStreamChat as _ } from "./useCopilotStreamChat.js";
6
- const es = ({
7
- // Transport + turn config
8
- baseUrl: s,
9
- endpointPath: M,
10
- icebreakersPath: S,
11
- headers: e,
12
- authToken: o,
13
- getAuthToken: r,
14
- fetchImpl: t,
15
- storeId: i,
16
- agent: a,
17
- route: n,
18
- email: f,
19
- systemPrompt: b,
20
- model: h,
21
- maxOutputTokens: H,
22
- sessionId: O,
23
- persist: k,
24
- loadIcebreakers: y = !0,
25
- onError: L,
26
- onResponseComplete: R,
27
- onSessionIdChange: j,
28
- // Shell
29
- suggestions: v,
30
- inputDisabled: w,
31
- onRefresh: m,
32
- open: g,
33
- defaultOpen: l,
34
- onOpenChange: p,
35
- ...x
36
- }) => {
37
- const [B, D] = X(
38
- l === !0 || g === !0
39
- ), {
40
- messages: K,
41
- isThinking: N,
42
- isStreaming: d,
43
- isRestoring: q,
44
- error: z,
45
- isLoadingHistory: E,
46
- hasMoreHistory: F,
47
- sendMessage: G,
48
- loadOlderMessages: I,
49
- stopStreaming: J,
50
- startNewConversation: C
51
- } = _({
52
- baseUrl: s,
53
- endpointPath: M,
54
- headers: e,
55
- authToken: o,
56
- getAuthToken: r,
57
- fetchImpl: t,
58
- storeId: i,
59
- agent: a,
60
- route: n,
61
- email: f,
62
- systemPrompt: b,
63
- model: h,
64
- maxOutputTokens: H,
65
- sessionId: O,
66
- persist: k,
67
- onError: L,
68
- onResponseComplete: R,
69
- onSessionIdChange: j
70
- }), { icebreakers: P } = Z({
71
- baseUrl: s,
72
- icebreakersPath: S,
73
- headers: e,
74
- authToken: o,
75
- getAuthToken: r,
76
- fetchImpl: t,
77
- agent: a,
78
- route: n,
79
- storeId: i,
80
- enabled: y && B
81
- }), Q = u(
82
- (c) => {
83
- c && D(!0), p?.(c);
84
- },
85
- [p]
86
- ), V = u(() => {
87
- C(), m?.();
88
- }, [m, C]);
89
- return /* @__PURE__ */ W(
90
- Y,
91
- {
92
- ...x,
93
- open: g,
94
- defaultOpen: l,
95
- onOpenChange: Q,
96
- messages: K,
97
- onSendMessage: G,
98
- isThinking: N,
99
- isStreaming: d,
100
- onStop: J,
101
- isLoadingHistory: E,
102
- hasMoreHistory: F,
103
- onLoadOlderMessages: I,
104
- errorMessage: z,
105
- suggestions: v ?? P,
106
- inputDisabled: w || q || d,
107
- onRefresh: V
108
- }
109
- );
110
- };
111
- export {
112
- es as BIKCopilot
113
- };
114
- //# sourceMappingURL=BIKCopilot.js.map
@@ -1 +0,0 @@
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":";;;;;AAkCO,MAAMA,KAAwC,CAAC;AAAA;AAAA,EAErD,SAAAC;AAAA,EACA,cAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,SAAAC;AAAA,EACA,WAAAC;AAAA,EACA,cAAAC;AAAA,EACA,WAAAC;AAAA,EACA,SAAAC;AAAA,EACA,OAAAC;AAAA,EACA,OAAAC;AAAA,EACA,OAAAC;AAAA,EACA,cAAAC;AAAA,EACA,OAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,WAAAC;AAAA,EACA,SAAAC;AAAA,EACA,iBAAAC,IAAkB;AAAA,EAClB,SAAAC;AAAA,EACA,oBAAAC;AAAA,EACA,mBAAAC;AAAA;AAAA,EAEA,aAAAC;AAAA,EACA,eAAAC;AAAA,EACA,WAAAC;AAAA,EACA,MAAAC;AAAA,EACA,aAAAC;AAAA,EACA,cAAAC;AAAA,EACA,GAAGC;AACJ,MAAM;AAGL,QAAM,CAACC,GAAWC,CAAY,IAAIC;AAAA,IACjCL,MAAgB,MAAQD,MAAS;AAAA,EAAA,GAG5B;AAAA,IACL,UAAAO;AAAA,IACA,YAAAC;AAAA,IACA,aAAAC;AAAA,IACA,aAAAC;AAAA,IACA,OAAAC;AAAA,IACA,kBAAAC;AAAA,IACA,gBAAAC;AAAA,IACA,aAAAC;AAAA,IACA,mBAAAC;AAAA,IACA,eAAAC;AAAA,IACA,sBAAAC;AAAA,EAAA,IACGC,EAAqB;AAAA,IACxB,SAAAzC;AAAA,IACA,cAAAC;AAAA,IACA,SAAAE;AAAA,IACA,WAAAC;AAAA,IACA,cAAAC;AAAA,IACA,WAAAC;AAAA,IACA,SAAAC;AAAA,IACA,OAAAC;AAAA,IACA,OAAAC;AAAA,IACA,OAAAC;AAAA,IACA,cAAAC;AAAA,IACA,OAAAC;AAAA,IACA,iBAAAC;AAAA,IACA,WAAAC;AAAA,IACA,SAAAC;AAAA,IACA,SAAAE;AAAA,IACA,oBAAAC;AAAA,IACA,mBAAAC;AAAA,EAAA,CACA,GAEK,EAAE,aAAAuB,EAAA,IAAgBC,EAAsB;AAAA,IAC7C,SAAA3C;AAAA,IACA,iBAAAE;AAAA,IACA,SAAAC;AAAA,IACA,WAAAC;AAAA,IACA,cAAAC;AAAA,IACA,WAAAC;AAAA,IACA,OAAAE;AAAA,IACA,OAAAC;AAAA,IACA,SAAAF;AAAA,IACA,SAASS,KAAmBW;AAAA,EAAA,CAC5B,GAEKiB,IAAmBC;AAAA,IACxB,CAACC,MAAsB;AACtB,MAAIA,KACHlB,EAAa,EAAI,GAElBH,IAAeqB,CAAQ;AAAA,IACxB;AAAA,IACA,CAACrB,CAAY;AAAA,EAAA,GAGRsB,IAAgBF,EAAY,MAAM;AACvC,IAAAL,EAAA,GACAlB,IAAA;AAAA,EACD,GAAG,CAACA,GAAWkB,CAAoB,CAAC;AAEpC,SACC,gBAAAQ;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,GAAGvB;AAAA,MACJ,MAAAH;AAAA,MACA,aAAAC;AAAA,MACA,cAAcoB;AAAA,MACd,UAAAd;AAAA,MACA,eAAeO;AAAA,MACf,YAAAN;AAAA,MACA,aAAAC;AAAA,MACA,QAAQO;AAAA,MACR,kBAAAJ;AAAA,MACA,gBAAAC;AAAA,MACA,qBAAqBE;AAAA,MACrB,cAAcJ;AAAA,MAGd,aAAad,KAAesB;AAAA,MAE5B,eAAerB,KAAiBY,KAAeD;AAAA,MAC/C,WAAWe;AAAA,IAAA;AAAA,EAAA;AAGd;"}
@@ -1,14 +0,0 @@
1
- import { default as React } from 'react';
2
- import { ControlledCopilotProps } from './model';
3
- /**
4
- * The presentational half of the copilot: a draggable floating ball that opens a
5
- * chat panel beside it.
6
- *
7
- * Fully controlled — it renders the `messages` it is handed and reports every
8
- * user action through callbacks, so it carries no backend knowledge. **Use
9
- * `BIKCopilot` instead** unless you are wiring a backend other than
10
- * `/bik-ai/copilot-chatbot`; `BIKCopilot` is this component plus the streaming
11
- * transport, IndexedDB history and route-aware ice breakers.
12
- */
13
- export declare const ControlledCopilot: React.FC<ControlledCopilotProps>;
14
- export default ControlledCopilot;
@@ -1,170 +0,0 @@
1
- import { jsxs as pe, Fragment as me, jsx as a } from "react/jsx-runtime";
2
- import { useState as ue, useRef as ge, useCallback as C, useEffect as v } from "react";
3
- import { COLORS as he } from "../../constants/Theme.js";
4
- import { PanelPositioner as Ce } from "./ControlledCopilot.styled.js";
5
- import { CopilotBall as ve, COPILOT_BALL_ATTRIBUTE as we } from "./CopilotBall.js";
6
- import { CopilotPanel as Le } from "./CopilotPanel.js";
7
- import { getCopilotPanelPlacement as Pe } from "./copilotPlacement.js";
8
- import { useDraggableFloater as Ee } from "./useDraggableFloater.js";
9
- const De = ({
10
- // Conversation
11
- messages: w,
12
- onSendMessage: L,
13
- isThinking: P = !1,
14
- thinkingLabel: E,
15
- isStreaming: k = !1,
16
- onStop: $,
17
- interruptedLabel: b,
18
- followUpsLabel: I,
19
- hasMoreHistory: O = !1,
20
- isLoadingHistory: T = !1,
21
- onLoadOlderMessages: y,
22
- historyLoadingLabel: B,
23
- errorMessage: D,
24
- // Ball
25
- ballSize: r = 56,
26
- corner: R = "bottom-right",
27
- offset: x = 24,
28
- initialPosition: j,
29
- draggable: f = !0,
30
- snapToEdge: A = !0,
31
- onPositionChange: F,
32
- ballIcon: U,
33
- ballOpenIcon: _,
34
- ballColor: z = he.background.brand,
35
- zIndex: c = 1200,
36
- ballAriaLabel: H,
37
- // Panel
38
- panelWidth: K = 400,
39
- panelHeight: S = 700,
40
- panelGap: q = 12,
41
- title: G = "Copilot",
42
- badge: J,
43
- subtitle: M,
44
- avatar: N,
45
- placeholder: Q,
46
- disclaimer: V,
47
- emptyStateTitle: W,
48
- emptyStateSubtitle: X,
49
- suggestions: Y,
50
- onSuggestionClick: Z,
51
- showRefresh: ee = !0,
52
- onRefresh: oe,
53
- inputDisabled: te = !1,
54
- // Open state
55
- open: d,
56
- defaultOpen: ne = !1,
57
- onOpenChange: p,
58
- closeOnClickOutside: m = !1,
59
- className: re,
60
- style: ie
61
- }) => {
62
- const [le, se] = ue(ne), u = ge(null), i = d !== void 0, e = i ? d : le, t = C(
63
- (o) => {
64
- i || se(o), p?.(o);
65
- },
66
- [i, p]
67
- ), { position: g, isDragging: ae, viewport: fe, dragHandlers: ce, shouldIgnoreClick: h } = Ee({
68
- size: r,
69
- corner: R,
70
- offset: x,
71
- enabled: f,
72
- snapToEdge: A,
73
- initialPosition: j,
74
- onPositionChange: F
75
- }), de = C(() => {
76
- h() || t(!e);
77
- }, [e, t, h]);
78
- v(() => {
79
- if (!e)
80
- return;
81
- const o = (l) => {
82
- l.key === "Escape" && t(!1);
83
- };
84
- return document.addEventListener("keydown", o), () => document.removeEventListener("keydown", o);
85
- }, [e, t]), v(() => {
86
- if (!e || !m)
87
- return;
88
- const o = (l) => {
89
- const s = l.target;
90
- s && (u.current?.contains(s) || s.closest(`[${we}]`) || t(!1));
91
- };
92
- return document.addEventListener("pointerdown", o), () => document.removeEventListener("pointerdown", o);
93
- }, [m, e, t]);
94
- const n = Pe({
95
- ballPosition: g,
96
- ballSize: r,
97
- panelWidth: K,
98
- panelHeight: S,
99
- gap: q,
100
- viewport: fe
101
- });
102
- return /* @__PURE__ */ pe(me, { children: [
103
- e && /* @__PURE__ */ a(
104
- Ce,
105
- {
106
- ref: u,
107
- $left: n.left,
108
- $top: n.top,
109
- $width: n.width,
110
- $height: n.height,
111
- $zIndex: c,
112
- children: /* @__PURE__ */ a(
113
- Le,
114
- {
115
- messages: w,
116
- onSend: L,
117
- onClose: () => t(!1),
118
- title: G,
119
- badge: J,
120
- subtitle: M,
121
- avatar: N,
122
- placeholder: Q,
123
- disclaimer: V,
124
- emptyStateTitle: W,
125
- emptyStateSubtitle: X,
126
- suggestions: Y,
127
- onSuggestionClick: Z,
128
- showRefresh: ee,
129
- onRefresh: oe,
130
- isThinking: P,
131
- thinkingLabel: E,
132
- isStreaming: k,
133
- onStop: $,
134
- interruptedLabel: b,
135
- followUpsLabel: I,
136
- hasMoreHistory: O,
137
- isLoadingHistory: T,
138
- onLoadOlderMessages: y,
139
- historyLoadingLabel: B,
140
- inputDisabled: te,
141
- errorMessage: D,
142
- className: re,
143
- style: ie
144
- }
145
- )
146
- }
147
- ),
148
- /* @__PURE__ */ a(
149
- ve,
150
- {
151
- isOpen: e,
152
- onToggle: de,
153
- position: g,
154
- size: r,
155
- isDragging: ae,
156
- draggable: f,
157
- color: z,
158
- zIndex: c + 1,
159
- icon: U,
160
- openIcon: _,
161
- ariaLabel: H,
162
- ...ce
163
- }
164
- )
165
- ] });
166
- };
167
- export {
168
- De as ControlledCopilot
169
- };
170
- //# sourceMappingURL=ControlledCopilot.js.map
@@ -1 +0,0 @@
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 = 400,\n\tpanelHeight = 700,\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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"}
@@ -1,7 +0,0 @@
1
- export declare const PanelPositioner: import('styled-components').StyledComponent<"div", any, {
2
- $left: number;
3
- $top: number;
4
- $width: number;
5
- $height: number;
6
- $zIndex: number;
7
- }, never>;
@@ -1,31 +0,0 @@
1
- import e from "styled-components";
2
- const o = e.div`
3
- position: fixed;
4
- left: ${(t) => t.$left}px;
5
- top: ${(t) => t.$top}px;
6
- width: ${(t) => t.$width}px;
7
- height: ${(t) => t.$height}px;
8
- z-index: ${(t) => t.$zIndex};
9
- display: flex;
10
- animation: bikCopilotPanelIn 0.16s ease-out;
11
-
12
- > * {
13
- flex: 1;
14
- min-width: 0;
15
- }
16
-
17
- @keyframes bikCopilotPanelIn {
18
- from {
19
- opacity: 0;
20
- transform: translateY(6px) scale(0.98);
21
- }
22
- to {
23
- opacity: 1;
24
- transform: translateY(0) scale(1);
25
- }
26
- }
27
- `;
28
- export {
29
- o as PanelPositioner
30
- };
31
- //# sourceMappingURL=ControlledCopilot.styled.js.map
@@ -1 +0,0 @@
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":";AAEO,MAAMA,IAAkBC,EAAO;AAAA;AAAA,SAQ7B,CAACC,MAAUA,EAAM,KAAK;AAAA,QACvB,CAACA,MAAUA,EAAM,IAAI;AAAA,UACnB,CAACA,MAAUA,EAAM,MAAM;AAAA,WACtB,CAACA,MAAUA,EAAM,OAAO;AAAA,YACvB,CAACA,MAAUA,EAAM,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;"}
@@ -1,13 +0,0 @@
1
- import { default as React } from 'react';
2
- import { CopilotBallProps } from './model';
3
- /**
4
- * Marks the ball in the DOM so an outside-click handler can tell the ball apart
5
- * from the rest of the page and not fight the ball's own toggle.
6
- */
7
- export declare const COPILOT_BALL_ATTRIBUTE = "data-bik-copilot-ball";
8
- /**
9
- * The floating ball that opens the copilot panel. Purely presentational — the
10
- * drag gesture lives in `useDraggableFloater` and is passed in as handlers.
11
- */
12
- export declare const CopilotBall: React.FC<CopilotBallProps>;
13
- export default CopilotBall;