@bikdotai/bik-component-library 0.0.868-beta.9 → 0.0.868
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 +0 -3
- package/dist/cjs/components/agent-builder/constants/tools.js +1 -1
- package/dist/cjs/components/agent-builder/constants/tools.js.map +1 -1
- 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/CopilotFeedbackModal.js +2 -0
- package/dist/cjs/components/bik-copilot/CopilotFeedbackModal.js.map +1 -0
- package/dist/cjs/components/bik-copilot/CopilotFeedbackModal.styled.js +108 -0
- package/dist/cjs/components/bik-copilot/CopilotFeedbackModal.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 +534 -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/copilotRegenerate.js +2 -0
- package/dist/cjs/components/bik-copilot/copilotRegenerate.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/copilotFeedbackClient.js +2 -0
- package/dist/cjs/components/bik-copilot/services/copilotFeedbackClient.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/bik-copilot/utils/markdown.js +4 -0
- package/dist/cjs/components/bik-copilot/utils/markdown.js.map +1 -0
- package/dist/cjs/components/bik-copilot/utils/toolCtas.js +2 -0
- package/dist/cjs/components/bik-copilot/utils/toolCtas.js.map +1 -0
- package/dist/cjs/components/button/themes.js +2 -2
- package/dist/cjs/components/button/themes.js.map +1 -1
- package/dist/cjs/components/datePicker/DatePickerWrapper.js +1 -1
- package/dist/cjs/components/datePicker/DatePickerWrapper.js.map +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/esm/components/agent-builder/constants/tools.d.ts +1 -0
- package/dist/esm/components/agent-builder/constants/tools.js +18 -18
- package/dist/esm/components/agent-builder/constants/tools.js.map +1 -1
- package/dist/esm/components/bik-copilot/BIKCopilot.d.ts +31 -0
- package/dist/esm/components/bik-copilot/BIKCopilot.js +118 -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 +174 -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/CopilotFeedbackModal.d.ts +29 -0
- package/dist/esm/components/bik-copilot/CopilotFeedbackModal.js +73 -0
- package/dist/esm/components/bik-copilot/CopilotFeedbackModal.js.map +1 -0
- package/dist/esm/components/bik-copilot/CopilotFeedbackModal.styled.d.ts +12 -0
- package/dist/esm/components/bik-copilot/CopilotFeedbackModal.styled.js +122 -0
- package/dist/esm/components/bik-copilot/CopilotFeedbackModal.styled.js.map +1 -0
- package/dist/esm/components/bik-copilot/CopilotPanel.d.ts +9 -0
- package/dist/esm/components/bik-copilot/CopilotPanel.js +536 -0
- package/dist/esm/components/bik-copilot/CopilotPanel.js.map +1 -0
- package/dist/esm/components/bik-copilot/CopilotPanel.styled.d.ts +67 -0
- package/dist/esm/components/bik-copilot/CopilotPanel.styled.js +573 -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/copilotRegenerate.d.ts +22 -0
- package/dist/esm/components/bik-copilot/copilotRegenerate.js +6 -0
- package/dist/esm/components/bik-copilot/copilotRegenerate.js.map +1 -0
- package/dist/esm/components/bik-copilot/index.d.ts +19 -0
- package/dist/esm/components/bik-copilot/model.d.ts +804 -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/copilotFeedbackClient.d.ts +15 -0
- package/dist/esm/components/bik-copilot/services/copilotFeedbackClient.js +55 -0
- package/dist/esm/components/bik-copilot/services/copilotFeedbackClient.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 +35 -0
- package/dist/esm/components/bik-copilot/services/copilotStreamClient.js +110 -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 +377 -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/bik-copilot/utils/markdown.d.ts +1 -0
- package/dist/esm/components/bik-copilot/utils/markdown.js +48 -0
- package/dist/esm/components/bik-copilot/utils/markdown.js.map +1 -0
- package/dist/esm/components/bik-copilot/utils/toolCtas.d.ts +6 -0
- package/dist/esm/components/bik-copilot/utils/toolCtas.js +27 -0
- package/dist/esm/components/bik-copilot/utils/toolCtas.js.map +1 -0
- package/dist/esm/components/button/themes.js +1 -2
- package/dist/esm/components/button/themes.js.map +1 -1
- package/dist/esm/components/datePicker/DatePickerWrapper.d.ts +0 -7
- package/dist/esm/components/datePicker/DatePickerWrapper.js +64 -66
- package/dist/esm/components/datePicker/DatePickerWrapper.js.map +1 -1
- package/dist/esm/components/datePicker/index.d.ts +0 -1
- package/dist/esm/index.d.ts +1 -3
- package/dist/esm/index.js +844 -828
- package/dist/esm/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/cjs/components/chip-selector/ChipSelector.js +0 -2
- package/dist/cjs/components/chip-selector/ChipSelector.js.map +0 -1
- package/dist/cjs/components/chip-selector/ChipSelector.styled.js +0 -36
- package/dist/cjs/components/chip-selector/ChipSelector.styled.js.map +0 -1
- package/dist/cjs/components/chip-selector/ChipSelectorGroup.js +0 -2
- package/dist/cjs/components/chip-selector/ChipSelectorGroup.js.map +0 -1
- package/dist/cjs/components/combo-box/ComboBox.js +0 -2
- package/dist/cjs/components/combo-box/ComboBox.js.map +0 -1
- package/dist/cjs/components/combo-box/ComboBox.styled.js +0 -33
- package/dist/cjs/components/combo-box/ComboBox.styled.js.map +0 -1
- package/dist/cjs/components/schedule-builder/RefreshSegmentToggle.js +0 -2
- package/dist/cjs/components/schedule-builder/RefreshSegmentToggle.js.map +0 -1
- package/dist/cjs/components/schedule-builder/ScheduleBuilder.js +0 -2
- package/dist/cjs/components/schedule-builder/ScheduleBuilder.js.map +0 -1
- package/dist/cjs/components/schedule-builder/ScheduleBuilder.styled.js +0 -138
- package/dist/cjs/components/schedule-builder/ScheduleBuilder.styled.js.map +0 -1
- package/dist/cjs/components/schedule-builder/ScheduleEndPicker.js +0 -2
- package/dist/cjs/components/schedule-builder/ScheduleEndPicker.js.map +0 -1
- package/dist/cjs/components/schedule-builder/ScheduleFrequencyPicker.js +0 -2
- package/dist/cjs/components/schedule-builder/ScheduleFrequencyPicker.js.map +0 -1
- package/dist/cjs/components/schedule-builder/ScheduleHelper.js +0 -2
- package/dist/cjs/components/schedule-builder/ScheduleHelper.js.map +0 -1
- package/dist/cjs/components/schedule-builder/SendModeSelector.js +0 -2
- package/dist/cjs/components/schedule-builder/SendModeSelector.js.map +0 -1
- package/dist/cjs/components/schedule-builder/StartDateTimePicker.js +0 -2
- package/dist/cjs/components/schedule-builder/StartDateTimePicker.js.map +0 -1
- package/dist/cjs/components/schedule-builder/UpcomingRunsPreview.js +0 -2
- package/dist/cjs/components/schedule-builder/UpcomingRunsPreview.js.map +0 -1
- package/dist/cjs/components/schedule-builder/model.js +0 -2
- package/dist/cjs/components/schedule-builder/model.js.map +0 -1
- package/dist/esm/components/chip-selector/ChipSelector.d.ts +0 -9
- package/dist/esm/components/chip-selector/ChipSelector.js +0 -27
- package/dist/esm/components/chip-selector/ChipSelector.js.map +0 -1
- package/dist/esm/components/chip-selector/ChipSelector.styled.d.ts +0 -10
- package/dist/esm/components/chip-selector/ChipSelector.styled.js +0 -48
- package/dist/esm/components/chip-selector/ChipSelector.styled.js.map +0 -1
- package/dist/esm/components/chip-selector/ChipSelectorGroup.d.ts +0 -10
- package/dist/esm/components/chip-selector/ChipSelectorGroup.js +0 -48
- package/dist/esm/components/chip-selector/ChipSelectorGroup.js.map +0 -1
- package/dist/esm/components/chip-selector/index.d.ts +0 -4
- package/dist/esm/components/chip-selector/model.d.ts +0 -106
- package/dist/esm/components/combo-box/ComboBox.d.ts +0 -15
- package/dist/esm/components/combo-box/ComboBox.js +0 -118
- package/dist/esm/components/combo-box/ComboBox.js.map +0 -1
- package/dist/esm/components/combo-box/ComboBox.styled.d.ts +0 -12
- package/dist/esm/components/combo-box/ComboBox.styled.js +0 -40
- package/dist/esm/components/combo-box/ComboBox.styled.js.map +0 -1
- package/dist/esm/components/combo-box/index.d.ts +0 -3
- package/dist/esm/components/combo-box/model.d.ts +0 -55
- package/dist/esm/components/schedule-builder/RefreshSegmentToggle.d.ts +0 -22
- package/dist/esm/components/schedule-builder/RefreshSegmentToggle.js +0 -31
- package/dist/esm/components/schedule-builder/RefreshSegmentToggle.js.map +0 -1
- package/dist/esm/components/schedule-builder/ScheduleBuilder.d.ts +0 -88
- package/dist/esm/components/schedule-builder/ScheduleBuilder.js +0 -105
- package/dist/esm/components/schedule-builder/ScheduleBuilder.js.map +0 -1
- package/dist/esm/components/schedule-builder/ScheduleBuilder.styled.d.ts +0 -81
- package/dist/esm/components/schedule-builder/ScheduleBuilder.styled.js +0 -168
- package/dist/esm/components/schedule-builder/ScheduleBuilder.styled.js.map +0 -1
- package/dist/esm/components/schedule-builder/ScheduleEndPicker.d.ts +0 -17
- package/dist/esm/components/schedule-builder/ScheduleEndPicker.js +0 -105
- package/dist/esm/components/schedule-builder/ScheduleEndPicker.js.map +0 -1
- package/dist/esm/components/schedule-builder/ScheduleFrequencyPicker.d.ts +0 -21
- package/dist/esm/components/schedule-builder/ScheduleFrequencyPicker.js +0 -136
- package/dist/esm/components/schedule-builder/ScheduleFrequencyPicker.js.map +0 -1
- package/dist/esm/components/schedule-builder/ScheduleHelper.d.ts +0 -110
- package/dist/esm/components/schedule-builder/ScheduleHelper.js +0 -196
- package/dist/esm/components/schedule-builder/ScheduleHelper.js.map +0 -1
- package/dist/esm/components/schedule-builder/SendModeSelector.d.ts +0 -29
- package/dist/esm/components/schedule-builder/SendModeSelector.js +0 -41
- package/dist/esm/components/schedule-builder/SendModeSelector.js.map +0 -1
- package/dist/esm/components/schedule-builder/StartDateTimePicker.d.ts +0 -51
- package/dist/esm/components/schedule-builder/StartDateTimePicker.js +0 -120
- package/dist/esm/components/schedule-builder/StartDateTimePicker.js.map +0 -1
- package/dist/esm/components/schedule-builder/UpcomingRunsPreview.d.ts +0 -19
- package/dist/esm/components/schedule-builder/UpcomingRunsPreview.js +0 -44
- package/dist/esm/components/schedule-builder/UpcomingRunsPreview.js.map +0 -1
- package/dist/esm/components/schedule-builder/index.d.ts +0 -18
- package/dist/esm/components/schedule-builder/model.d.ts +0 -69
- package/dist/esm/components/schedule-builder/model.js +0 -8
- package/dist/esm/components/schedule-builder/model.js.map +0 -1
package/README.md
CHANGED
|
@@ -10,9 +10,6 @@
|
|
|
10
10
|
- [Editor](docs/editor/01-overview.md) — the rich-text editor: props, ref API, toolbar, email mode, customisation
|
|
11
11
|
- [FunnelChart & ComparisonBarChart](docs/charts/funnel-and-comparison-charts.md) — the analytics charts behind the Helpdesk AI Impact tab: branching funnel geometry, the shared chart card/palette/format helpers, and the zero states
|
|
12
12
|
- [Channel Playground](src/components/channel-playground/README.md) — driving the AI on email / WhatsApp / Instagram: the transport seam, the channel skins, and the stream frame protocol
|
|
13
|
-
- [ScheduleBuilder](src/components/schedule-builder/README.md) — the send-now / schedule / recurring picker: the sub-components, the recurrence patch contract, and the run-date maths in `ScheduleHelper`
|
|
14
|
-
- [ComboBox](src/components/combo-box/README.md) — a type-or-pick field: the sanitize / validate / format / filter hooks and why typed text is validated rather than constrained
|
|
15
|
-
- [ChipSelector](src/components/chip-selector/README.md) — chip rows and grids: single vs multi select, `allowEmpty`, and fixed-width chips for grids that must align
|
|
16
13
|
- [Frontend Testing Guide](docs/testing/writing-tests.md) — test authoring, linting, mandate exceptions, required status checks
|
|
17
14
|
|
|
18
15
|
## Testing (Jest + SWC)
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=[{key:"tool",label:"Tools"},{key:"subagent",label:"Sub-agent"},{key:"variable",label:"Variables"}];var t=(e=>(e.Manifest="manifest",e.Shopify="shopify",e.Bigcommerce="bigcommerce",e.Shipstation="shipstation",e.Skio="skio",e.Gorgias="gorgias",e.Integration="integration",e.RestApi="rest_api",e.EmailHandover="email_handover",e.Slack="slack",e))(t||{});const O={manifest:"Manifest",shopify:"Shopify",bigcommerce:"BigCommerce",shipstation:"ShipStation",skio:"Skio",gorgias:"Gorgias",integration:"Integration",rest_api:"Rest API",email_handover:"Email",slack:"Slack"},o={rest_api:"REST API",email_handover:"Send email",slack:"Send Slack message"},_=["rest_api","email_handover","slack"],i={manifest:0,shopify:1,bigcommerce:2,skio:3,gorgias:4,shipstation:6,slack:7,email_handover:8,rest_api:9},s=["shopify","bigcommerce","shipstation","skio","gorgias","integration"],E=new Set(s),S=e=>E.has(e),a=["shipstation","integration"],
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=[{key:"tool",label:"Tools"},{key:"subagent",label:"Sub-agent"},{key:"variable",label:"Variables"}];var t=(e=>(e.Manifest="manifest",e.Shopify="shopify",e.Bigcommerce="bigcommerce",e.Shipstation="shipstation",e.Skio="skio",e.Gorgias="gorgias",e.Aftership="aftership",e.Integration="integration",e.RestApi="rest_api",e.EmailHandover="email_handover",e.Slack="slack",e))(t||{});const O={manifest:"Manifest",shopify:"Shopify",bigcommerce:"BigCommerce",shipstation:"ShipStation",skio:"Skio",gorgias:"Gorgias",aftership:"AfterShip",integration:"Integration",rest_api:"Rest API",email_handover:"Email",slack:"Slack"},o={rest_api:"REST API",email_handover:"Send email",slack:"Send Slack message"},_=["rest_api","email_handover","slack"],i={manifest:0,shopify:1,bigcommerce:2,skio:3,gorgias:4,aftership:5,shipstation:6,slack:7,email_handover:8,rest_api:9},s=["shopify","bigcommerce","shipstation","skio","gorgias","aftership","integration"],E=new Set(s),S=e=>E.has(e),a=["shipstation","integration"],r=new Set(a),R=e=>r.has(e),I="more_integrations",c="More Integrations",N=10,T=Object.keys(i).length,g=e=>i[e]??T,A={email_handover:"send_email",slack:"send_slack_message"};exports.CATEGORIES=n;exports.CONFIG_TOOL_SOURCES=A;exports.INTEGRATION_SOURCES=s;exports.MORE_INTEGRATIONS_KEY=I;exports.MORE_INTEGRATIONS_LABEL=c;exports.MORE_INTEGRATIONS_RANK=N;exports.MORE_INTEGRATION_SOURCES=a;exports.TOOL_ACTION_LABELS=o;exports.TOOL_ACTION_SOURCES=_;exports.TOOL_SOURCE_LABELS=O;exports.TOOL_SOURCE_RANK=i;exports.ToolSource=t;exports.isIntegrationSource=S;exports.isMoreIntegrationSource=R;exports.toolSourceRank=g;
|
|
2
2
|
//# sourceMappingURL=tools.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sources":["../../../../../src/components/agent-builder/constants/tools.ts"],"sourcesContent":["import type { ToolSource as ModelToolSource } from '@bikdotai/bik-models/ai-agents/models/agent-tool';\nimport type { FunctionComponent, SVGAttributes } from 'react';\n\n/**\n * Static tool-related constants for the builder's Step 3 (tools & sub-agents):\n * the reference-picker category tabs and the per-source display labels. Kept here\n * (rather than inline in the picker / serialization utils) so the labels a user\n * sees are all in one obvious place.\n */\n\n/** A reference-picker category tab. */\nexport type Category = 'tool' | 'subagent' | 'variable';\n\n/** Category tabs shown at the root of the `@` reference picker. */\nexport const CATEGORIES: { key: Category; label: string }[] = [\n\t{ key: 'tool', label: 'Tools' },\n\t{ key: 'subagent', label: 'Sub-agent' },\n\t{ key: 'variable', label: 'Variables' },\n];\n\n/**\n * Every tool \"source\" the builder renders an icon / label / picker entry for.\n * Enum VALUES are the backend's canonical read-only `source` wire strings\n * (`app/agents/config/schema.py` → `ToolSource`, derived from `tool_key`): the\n * configurable tools are `email_handover` / `rest_api` / `slack`, every native\n * tool is `manifest`. `shopify` / `integration` are legacy bik-models sources\n * kept for back-compat (the backend now collapses natives to `manifest`).\n * Dynamic/unknown sources are looked up leniently — see `toolSourceLabel` and\n * `sourceIcon`.\n *\n * This is the RUNTIME mirror of the canonical `@bikdotai/bik-models` `ToolSource`\n * union (the shape the backend persists as `AgentToolDoc.source`). We keep an\n * enum — not a re-export of the type — because the members are needed at runtime\n * for labels, ranks, icons and `===` comparisons; a type-only union can't do\n * that. The two are kept in lock-step by {@link ToolSourceMatchesBikModels}\n * below, which fails to compile if they ever drift.\n */\nexport enum ToolSource {\n\tManifest = 'manifest',\n\tShopify = 'shopify',\n\tBigcommerce = 'bigcommerce',\n\tShipstation = 'shipstation',\n\tSkio = 'skio',\n\tGorgias = 'gorgias',\n\t// Aftership = 'aftership',\n\tIntegration = 'integration',\n\tRestApi = 'rest_api',\n\tEmailHandover = 'email_handover',\n\tSlack = 'slack',\n}\n\n/**\n * Compile-time guard that {@link ToolSource} stays a faithful mirror of the\n * canonical `@bikdotai/bik-models` `ToolSource` union. If a source is added to\n * (or removed from) either side without the other, `AssertTrue` receives `false`\n * and this type stops compiling — so the runtime enum can never silently diverge\n * from what the backend persists as `AgentToolDoc.source`. The tuple wrappers\n * (`[…]`) stop the conditionals from distributing over the unions, so it checks\n * set-equality in both directions.\n *\n * Type-only (erased at build): a drift shows up as a compile error on\n * `ToolSourceMatchesBikModels` telling you to reconcile this enum with\n * `@bikdotai/bik-models` (bump the dep and/or the enum).\n */\ntype AssertTrue<T extends true> = T;\ntype ToolSourceMatchesBikModels = AssertTrue<\n\t[`${ToolSource}`] extends [ModelToolSource]\n\t\t? [ModelToolSource] extends [`${ToolSource}`]\n\t\t\t? true\n\t\t\t: false\n\t\t: false\n>;\n\n/**\n * Display labels for the known tool sources — the CATEGORY/integration name, used\n * for the picker's source headers (drill-in groups), the empty-state source\n * buttons and the mention-chip prefix. A source is a category (\"Slack\") you drill\n * into; the specific addable action inside it (\"Send Slack message\") is\n * `TOOL_ACTION_LABELS`. Unknown sources fall back to the raw key (see\n * `toolSourceLabel`).\n */\nexport const TOOL_SOURCE_LABELS: Record<ToolSource, string> = {\n\t[ToolSource.Manifest]: 'Manifest',\n\t[ToolSource.Shopify]: 'Shopify',\n\t[ToolSource.Bigcommerce]: 'BigCommerce',\n\t[ToolSource.Shipstation]: 'ShipStation',\n\t[ToolSource.Skio]: 'Skio',\n\t[ToolSource.Gorgias]: 'Gorgias',\n\t// [ToolSource.Aftership]: 'AfterShip',\n\t[ToolSource.Integration]: 'Integration',\n\t[ToolSource.RestApi]: 'Rest API',\n\t[ToolSource.EmailHandover]: 'Email',\n\t[ToolSource.Slack]: 'Slack',\n};\n\n/**\n * The addable action inside a configurable/rest source — shown as the \"add\" row\n * in the `@` picker (below any existing instances) and the empty-state button.\n * Distinct from `TOOL_SOURCE_LABELS`, which names the category the action lives in\n * (e.g. category \"Slack\" → action \"Send Slack message\").\n */\nexport const TOOL_ACTION_LABELS: Partial<Record<ToolSource, string>> = {\n\t[ToolSource.RestApi]: 'REST API',\n\t[ToolSource.EmailHandover]: 'Send email',\n\t[ToolSource.Slack]: 'Send Slack message',\n};\n\n/** A tool source's brand-glyph component. */\nexport type IconComp = FunctionComponent<SVGAttributes<SVGElement>>;\n\n/** Brand glyph for a tool source, with its own size so each keeps its aspect ratio. */\nexport interface SourceIcon {\n\tIcon: IconComp;\n\tw: number;\n\th: number;\n}\n\n/**\n * A built-in \"tool\" that opens a config drawer (Rest API / email handover /\n * Slack) rather than inserting a mention. Surfaced as an empty-state source\n * button in the Tools section and as a row in the `@`-picker Tools view; picking\n * it opens the drawer and never writes into the instructions text.\n */\nexport interface ToolAction {\n\tsource: ToolSource;\n\tlabel: string;\n\ticon?: SourceIcon;\n\t/** Open this tool's config drawer. */\n\tonSelect: () => void;\n\t/**\n\t * Integration connection state for this source. `undefined` = no connection\n\t * gating (default). `false` = the store hasn't connected this integration →\n\t * the `@` picker shows a \"Connect\" row that calls {@link onConnect} instead of\n\t * drilling in / offering \"Create new\". `true` = connected (renders normally).\n\t * Set by the consumer via `config.integrationStatus` (today: Slack only).\n\t */\n\tconnected?: boolean;\n\t/** Open the parent's connect flow for this source (used when `connected === false`). */\n\tonConnect?: () => void;\n}\n\n/** Sources of the built-in drawer tools, in display order. */\nexport const TOOL_ACTION_SOURCES: ToolSource[] = [\n\tToolSource.RestApi,\n\tToolSource.EmailHandover,\n\tToolSource.Slack,\n];\n\n/**\n * Fixed display rank for the `@`-picker's tool-source groups (lower = higher). The\n * picker sorts its source rows by this so adding/updating a tool never reshuffles\n * them. Manifest (the native tools) leads; any source not listed here\n * (dynamic/unknown, e.g. Integration) sorts AFTER Slack, keeping its discovery\n * order among the rest (Array.sort is stable).\n */\nexport const TOOL_SOURCE_RANK: Partial<Record<ToolSource, number>> = {\n\t[ToolSource.Manifest]: 0,\n\t[ToolSource.Shopify]: 1,\n\t// BigCommerce / Skio / Gorgias / AfterShip are their OWN top-level rows; rank\n\t// orders them so adding/updating a tool never reshuffles them.\n\t[ToolSource.Bigcommerce]: 2,\n\t[ToolSource.Skio]: 3,\n\t[ToolSource.Gorgias]: 4,\n\t// [ToolSource.Aftership]: 5,\n\t// ShipStation lives under the \"More Integrations\" umbrella; its rank only\n\t// orders it inside that drill-in view (never shown at the root).\n\t[ToolSource.Shipstation]: 6,\n\t[ToolSource.Slack]: 7,\n\t// Send Email then REST API sit after the integration sources at the top level.\n\t[ToolSource.EmailHandover]: 8,\n\t[ToolSource.RestApi]: 9,\n};\n\n/**\n * External integration / vendor sources. Each renders as its OWN top-level\n * drill-in group in the picker — even when it has a single tool — so the vendor\n * reads as its own discoverable, connectable unit (never collapsed to a lone\n * leaf; see the single-leaf flatten in `MentionPicker`). Deliberately excludes\n * `Manifest` (the built-in natives) and the config/rest action sources (Rest API\n * / Email / Slack), whose single capability is surfaced flat.\n */\nexport const INTEGRATION_SOURCES: ToolSource[] = [\n\tToolSource.Shopify,\n\tToolSource.Bigcommerce,\n\tToolSource.Shipstation,\n\tToolSource.Skio,\n\tToolSource.Gorgias,\n\t// ToolSource.Aftership,\n\tToolSource.Integration,\n];\n\nconst INTEGRATION_SOURCE_SET = new Set<string>(INTEGRATION_SOURCES);\n\n/** True for an external integration/vendor source (never collapsed to a single leaf). */\nexport const isIntegrationSource = (source: string): boolean =>\n\tINTEGRATION_SOURCE_SET.has(source);\n\n/**\n * Vendor integrations that live UNDER the \"More Integrations\" umbrella in the `@`\n * picker (a single top-level row → their list), instead of each being its own\n * root row. Shopify, BigCommerce, Skio, Gorgias and AfterShip stay top-level\n * sources of their own; only the less-common vendors (ShipStation) and the\n * generic catch-all Integration are tucked away here.\n */\nexport const MORE_INTEGRATION_SOURCES: ToolSource[] = [\n\tToolSource.Shipstation,\n\tToolSource.Integration,\n];\n\nconst MORE_INTEGRATION_SOURCE_SET = new Set<string>(MORE_INTEGRATION_SOURCES);\n\n/** True for a source shown under the \"More Integrations\" umbrella. */\nexport const isMoreIntegrationSource = (source: string): boolean =>\n\tMORE_INTEGRATION_SOURCE_SET.has(source);\n\n/**\n * Synthetic picker key / label / rank for the \"More Integrations\" umbrella row.\n * The rank lives here (not in {@link TOOL_SOURCE_RANK}) because that map is keyed\n * by the drift-guarded {@link ToolSource} enum — the backend's canonical wire\n * strings — and `more_integrations` is a picker-only key, not a real source.\n */\nexport const MORE_INTEGRATIONS_KEY = 'more_integrations';\nexport const MORE_INTEGRATIONS_LABEL = 'More Integrations';\n/** Always last — sits after every named top-level source (REST API, rank 9). */\nexport const MORE_INTEGRATIONS_RANK = 10;\n\nconst UNRANKED_SOURCE_RANK = Object.keys(TOOL_SOURCE_RANK).length;\n\n/** Sort rank for a source string; unknown sources rank after all known ones. */\nexport const toolSourceRank = (source: string): number =>\n\tTOOL_SOURCE_RANK[source as ToolSource] ?? UNRANKED_SOURCE_RANK;\n\n/**\n * `tool_key` of a configurable shared-drawer tool (email / Slack). Lives here (not\n * in AgentBuilder.model) so this leaf constants file has no back-edge to the model\n * — the dependency stays one-way (model → constants), avoiding a circular import.\n */\nexport type ConfigToolKey = 'send_email' | 'send_slack_message';\n\n/**\n * Drawer sources rendered by the shared dynamic panel (`ConfigToolPanel`), each\n * mapped to its backend `tool_key`. Rest API is absent — it has a bespoke panel.\n */\nexport const CONFIG_TOOL_SOURCES: Partial<Record<ToolSource, ConfigToolKey>> = {\n\t[ToolSource.EmailHandover]: 'send_email',\n\t[ToolSource.Slack]: 'send_slack_message',\n};\n"],"names":["CATEGORIES","ToolSource","TOOL_SOURCE_LABELS","TOOL_ACTION_LABELS","TOOL_ACTION_SOURCES","TOOL_SOURCE_RANK","INTEGRATION_SOURCES","INTEGRATION_SOURCE_SET","isIntegrationSource","source","MORE_INTEGRATION_SOURCES","MORE_INTEGRATION_SOURCE_SET","isMoreIntegrationSource","MORE_INTEGRATIONS_KEY","MORE_INTEGRATIONS_LABEL","MORE_INTEGRATIONS_RANK","UNRANKED_SOURCE_RANK","toolSourceRank","CONFIG_TOOL_SOURCES"],"mappings":"gFAcO,MAAMA,EAAiD,CAC7D,CAAE,IAAK,OAAQ,MAAO,OAAA,EACtB,CAAE,IAAK,WAAY,MAAO,WAAA,EAC1B,CAAE,IAAK,WAAY,MAAO,WAAA,CAC3B,EAmBO,IAAKC,GAAAA,IACXA,EAAA,SAAW,WACXA,EAAA,QAAU,UACVA,EAAA,YAAc,cACdA,EAAA,YAAc,cACdA,EAAA,KAAO,OACPA,EAAA,QAAU,UAEVA,EAAA,YAAc,cACdA,EAAA,QAAU,WACVA,EAAA,cAAgB,iBAChBA,EAAA,MAAQ,QAXGA,IAAAA,GAAA,CAAA,CAAA,EA4CL,MAAMC,EAAiD,CAC5D,SAAsB,WACtB,QAAqB,UACrB,YAAyB,cACzB,YAAyB,cACzB,KAAkB,OAClB,QAAqB,UAErB,YAAyB,cACzB,SAAqB,WACrB,eAA2B,QAC3B,MAAmB,OACrB,EAQaC,EAA0D,CACrE,SAAqB,WACrB,eAA2B,aAC3B,MAAmB,oBACrB,EAqCaC,EAAoC,CAChD,WACA,iBACA,OACD,EASaC,EAAwD,CACnE,SAAsB,EACtB,QAAqB,EAGrB,YAAyB,EACzB,KAAkB,EAClB,QAAqB,EAIrB,YAAyB,EACzB,MAAmB,EAEnB,eAA2B,EAC3B,SAAqB,CACvB,EAUaC,EAAoC,CAChD,UACA,cACA,cACA,OACA,UAEA,aACD,EAEMC,EAAyB,IAAI,IAAYD,CAAmB,EAGrDE,EAAuBC,GACnCF,EAAuB,IAAIE,CAAM,EASrBC,EAAyC,CACrD,cACA,aACD,EAEMC,EAA8B,IAAI,IAAYD,CAAwB,EAG/DE,EAA2BH,GACvCE,EAA4B,IAAIF,CAAM,EAQ1BI,EAAwB,oBACxBC,EAA0B,oBAE1BC,EAAyB,GAEhCC,EAAuB,OAAO,KAAKX,CAAgB,EAAE,OAG9CY,EAAkBR,GAC9BJ,EAAiBI,CAAoB,GAAKO,EAa9BE,EAAkE,CAC7E,eAA2B,aAC3B,MAAmB,oBACrB"}
|
|
1
|
+
{"version":3,"file":"tools.js","sources":["../../../../../src/components/agent-builder/constants/tools.ts"],"sourcesContent":["import type { ToolSource as ModelToolSource } from '@bikdotai/bik-models/ai-agents/models/agent-tool';\nimport type { FunctionComponent, SVGAttributes } from 'react';\n\n/**\n * Static tool-related constants for the builder's Step 3 (tools & sub-agents):\n * the reference-picker category tabs and the per-source display labels. Kept here\n * (rather than inline in the picker / serialization utils) so the labels a user\n * sees are all in one obvious place.\n */\n\n/** A reference-picker category tab. */\nexport type Category = 'tool' | 'subagent' | 'variable';\n\n/** Category tabs shown at the root of the `@` reference picker. */\nexport const CATEGORIES: { key: Category; label: string }[] = [\n\t{ key: 'tool', label: 'Tools' },\n\t{ key: 'subagent', label: 'Sub-agent' },\n\t{ key: 'variable', label: 'Variables' },\n];\n\n/**\n * Every tool \"source\" the builder renders an icon / label / picker entry for.\n * Enum VALUES are the backend's canonical read-only `source` wire strings\n * (`app/agents/config/schema.py` → `ToolSource`, derived from `tool_key`): the\n * configurable tools are `email_handover` / `rest_api` / `slack`, every native\n * tool is `manifest`. `shopify` / `integration` are legacy bik-models sources\n * kept for back-compat (the backend now collapses natives to `manifest`).\n * Dynamic/unknown sources are looked up leniently — see `toolSourceLabel` and\n * `sourceIcon`.\n *\n * This is the RUNTIME mirror of the canonical `@bikdotai/bik-models` `ToolSource`\n * union (the shape the backend persists as `AgentToolDoc.source`). We keep an\n * enum — not a re-export of the type — because the members are needed at runtime\n * for labels, ranks, icons and `===` comparisons; a type-only union can't do\n * that. The two are kept in lock-step by {@link ToolSourceMatchesBikModels}\n * below, which fails to compile if they ever drift.\n */\nexport enum ToolSource {\n\tManifest = 'manifest',\n\tShopify = 'shopify',\n\tBigcommerce = 'bigcommerce',\n\tShipstation = 'shipstation',\n\tSkio = 'skio',\n\tGorgias = 'gorgias',\n\tAftership = 'aftership',\n\tIntegration = 'integration',\n\tRestApi = 'rest_api',\n\tEmailHandover = 'email_handover',\n\tSlack = 'slack',\n}\n\n/**\n * Compile-time guard that {@link ToolSource} stays a faithful mirror of the\n * canonical `@bikdotai/bik-models` `ToolSource` union. If a source is added to\n * (or removed from) either side without the other, `AssertTrue` receives `false`\n * and this type stops compiling — so the runtime enum can never silently diverge\n * from what the backend persists as `AgentToolDoc.source`. The tuple wrappers\n * (`[…]`) stop the conditionals from distributing over the unions, so it checks\n * set-equality in both directions.\n *\n * Type-only (erased at build): a drift shows up as a compile error on\n * `ToolSourceMatchesBikModels` telling you to reconcile this enum with\n * `@bikdotai/bik-models` (bump the dep and/or the enum).\n */\ntype AssertTrue<T extends true> = T;\ntype ToolSourceMatchesBikModels = AssertTrue<\n\t[`${ToolSource}`] extends [ModelToolSource]\n\t\t? [ModelToolSource] extends [`${ToolSource}`]\n\t\t\t? true\n\t\t\t: false\n\t\t: false\n>;\n\n/**\n * Display labels for the known tool sources — the CATEGORY/integration name, used\n * for the picker's source headers (drill-in groups), the empty-state source\n * buttons and the mention-chip prefix. A source is a category (\"Slack\") you drill\n * into; the specific addable action inside it (\"Send Slack message\") is\n * `TOOL_ACTION_LABELS`. Unknown sources fall back to the raw key (see\n * `toolSourceLabel`).\n */\nexport const TOOL_SOURCE_LABELS: Record<ToolSource, string> = {\n\t[ToolSource.Manifest]: 'Manifest',\n\t[ToolSource.Shopify]: 'Shopify',\n\t[ToolSource.Bigcommerce]: 'BigCommerce',\n\t[ToolSource.Shipstation]: 'ShipStation',\n\t[ToolSource.Skio]: 'Skio',\n\t[ToolSource.Gorgias]: 'Gorgias',\n\t[ToolSource.Aftership]: 'AfterShip',\n\t[ToolSource.Integration]: 'Integration',\n\t[ToolSource.RestApi]: 'Rest API',\n\t[ToolSource.EmailHandover]: 'Email',\n\t[ToolSource.Slack]: 'Slack',\n};\n\n/**\n * The addable action inside a configurable/rest source — shown as the \"add\" row\n * in the `@` picker (below any existing instances) and the empty-state button.\n * Distinct from `TOOL_SOURCE_LABELS`, which names the category the action lives in\n * (e.g. category \"Slack\" → action \"Send Slack message\").\n */\nexport const TOOL_ACTION_LABELS: Partial<Record<ToolSource, string>> = {\n\t[ToolSource.RestApi]: 'REST API',\n\t[ToolSource.EmailHandover]: 'Send email',\n\t[ToolSource.Slack]: 'Send Slack message',\n};\n\n/** A tool source's brand-glyph component. */\nexport type IconComp = FunctionComponent<SVGAttributes<SVGElement>>;\n\n/** Brand glyph for a tool source, with its own size so each keeps its aspect ratio. */\nexport interface SourceIcon {\n\tIcon: IconComp;\n\tw: number;\n\th: number;\n}\n\n/**\n * A built-in \"tool\" that opens a config drawer (Rest API / email handover /\n * Slack) rather than inserting a mention. Surfaced as an empty-state source\n * button in the Tools section and as a row in the `@`-picker Tools view; picking\n * it opens the drawer and never writes into the instructions text.\n */\nexport interface ToolAction {\n\tsource: ToolSource;\n\tlabel: string;\n\ticon?: SourceIcon;\n\t/** Open this tool's config drawer. */\n\tonSelect: () => void;\n\t/**\n\t * Integration connection state for this source. `undefined` = no connection\n\t * gating (default). `false` = the store hasn't connected this integration →\n\t * the `@` picker shows a \"Connect\" row that calls {@link onConnect} instead of\n\t * drilling in / offering \"Create new\". `true` = connected (renders normally).\n\t * Set by the consumer via `config.integrationStatus` (today: Slack only).\n\t */\n\tconnected?: boolean;\n\t/** Open the parent's connect flow for this source (used when `connected === false`). */\n\tonConnect?: () => void;\n}\n\n/** Sources of the built-in drawer tools, in display order. */\nexport const TOOL_ACTION_SOURCES: ToolSource[] = [\n\tToolSource.RestApi,\n\tToolSource.EmailHandover,\n\tToolSource.Slack,\n];\n\n/**\n * Fixed display rank for the `@`-picker's tool-source groups (lower = higher). The\n * picker sorts its source rows by this so adding/updating a tool never reshuffles\n * them. Manifest (the native tools) leads; any source not listed here\n * (dynamic/unknown, e.g. Integration) sorts AFTER Slack, keeping its discovery\n * order among the rest (Array.sort is stable).\n */\nexport const TOOL_SOURCE_RANK: Partial<Record<ToolSource, number>> = {\n\t[ToolSource.Manifest]: 0,\n\t[ToolSource.Shopify]: 1,\n\t// BigCommerce / Skio / Gorgias / AfterShip are their OWN top-level rows; rank\n\t// orders them so adding/updating a tool never reshuffles them.\n\t[ToolSource.Bigcommerce]: 2,\n\t[ToolSource.Skio]: 3,\n\t[ToolSource.Gorgias]: 4,\n\t[ToolSource.Aftership]: 5,\n\t// ShipStation lives under the \"More Integrations\" umbrella; its rank only\n\t// orders it inside that drill-in view (never shown at the root).\n\t[ToolSource.Shipstation]: 6,\n\t[ToolSource.Slack]: 7,\n\t// Send Email then REST API sit after the integration sources at the top level.\n\t[ToolSource.EmailHandover]: 8,\n\t[ToolSource.RestApi]: 9,\n};\n\n/**\n * External integration / vendor sources. Each renders as its OWN top-level\n * drill-in group in the picker — even when it has a single tool — so the vendor\n * reads as its own discoverable, connectable unit (never collapsed to a lone\n * leaf; see the single-leaf flatten in `MentionPicker`). Deliberately excludes\n * `Manifest` (the built-in natives) and the config/rest action sources (Rest API\n * / Email / Slack), whose single capability is surfaced flat.\n */\nexport const INTEGRATION_SOURCES: ToolSource[] = [\n\tToolSource.Shopify,\n\tToolSource.Bigcommerce,\n\tToolSource.Shipstation,\n\tToolSource.Skio,\n\tToolSource.Gorgias,\n\tToolSource.Aftership,\n\tToolSource.Integration,\n];\n\nconst INTEGRATION_SOURCE_SET = new Set<string>(INTEGRATION_SOURCES);\n\n/** True for an external integration/vendor source (never collapsed to a single leaf). */\nexport const isIntegrationSource = (source: string): boolean =>\n\tINTEGRATION_SOURCE_SET.has(source);\n\n/**\n * Vendor integrations that live UNDER the \"More Integrations\" umbrella in the `@`\n * picker (a single top-level row → their list), instead of each being its own\n * root row. Shopify, BigCommerce, Skio, Gorgias and AfterShip stay top-level\n * sources of their own; only the less-common vendors (ShipStation) and the\n * generic catch-all Integration are tucked away here.\n */\nexport const MORE_INTEGRATION_SOURCES: ToolSource[] = [\n\tToolSource.Shipstation,\n\tToolSource.Integration,\n];\n\nconst MORE_INTEGRATION_SOURCE_SET = new Set<string>(MORE_INTEGRATION_SOURCES);\n\n/** True for a source shown under the \"More Integrations\" umbrella. */\nexport const isMoreIntegrationSource = (source: string): boolean =>\n\tMORE_INTEGRATION_SOURCE_SET.has(source);\n\n/**\n * Synthetic picker key / label / rank for the \"More Integrations\" umbrella row.\n * The rank lives here (not in {@link TOOL_SOURCE_RANK}) because that map is keyed\n * by the drift-guarded {@link ToolSource} enum — the backend's canonical wire\n * strings — and `more_integrations` is a picker-only key, not a real source.\n */\nexport const MORE_INTEGRATIONS_KEY = 'more_integrations';\nexport const MORE_INTEGRATIONS_LABEL = 'More Integrations';\n/** Always last — sits after every named top-level source (REST API, rank 9). */\nexport const MORE_INTEGRATIONS_RANK = 10;\n\nconst UNRANKED_SOURCE_RANK = Object.keys(TOOL_SOURCE_RANK).length;\n\n/** Sort rank for a source string; unknown sources rank after all known ones. */\nexport const toolSourceRank = (source: string): number =>\n\tTOOL_SOURCE_RANK[source as ToolSource] ?? UNRANKED_SOURCE_RANK;\n\n/**\n * `tool_key` of a configurable shared-drawer tool (email / Slack). Lives here (not\n * in AgentBuilder.model) so this leaf constants file has no back-edge to the model\n * — the dependency stays one-way (model → constants), avoiding a circular import.\n */\nexport type ConfigToolKey = 'send_email' | 'send_slack_message';\n\n/**\n * Drawer sources rendered by the shared dynamic panel (`ConfigToolPanel`), each\n * mapped to its backend `tool_key`. Rest API is absent — it has a bespoke panel.\n */\nexport const CONFIG_TOOL_SOURCES: Partial<Record<ToolSource, ConfigToolKey>> = {\n\t[ToolSource.EmailHandover]: 'send_email',\n\t[ToolSource.Slack]: 'send_slack_message',\n};\n"],"names":["CATEGORIES","ToolSource","TOOL_SOURCE_LABELS","TOOL_ACTION_LABELS","TOOL_ACTION_SOURCES","TOOL_SOURCE_RANK","INTEGRATION_SOURCES","INTEGRATION_SOURCE_SET","isIntegrationSource","source","MORE_INTEGRATION_SOURCES","MORE_INTEGRATION_SOURCE_SET","isMoreIntegrationSource","MORE_INTEGRATIONS_KEY","MORE_INTEGRATIONS_LABEL","MORE_INTEGRATIONS_RANK","UNRANKED_SOURCE_RANK","toolSourceRank","CONFIG_TOOL_SOURCES"],"mappings":"gFAcO,MAAMA,EAAiD,CAC7D,CAAE,IAAK,OAAQ,MAAO,OAAA,EACtB,CAAE,IAAK,WAAY,MAAO,WAAA,EAC1B,CAAE,IAAK,WAAY,MAAO,WAAA,CAC3B,EAmBO,IAAKC,GAAAA,IACXA,EAAA,SAAW,WACXA,EAAA,QAAU,UACVA,EAAA,YAAc,cACdA,EAAA,YAAc,cACdA,EAAA,KAAO,OACPA,EAAA,QAAU,UACVA,EAAA,UAAY,YACZA,EAAA,YAAc,cACdA,EAAA,QAAU,WACVA,EAAA,cAAgB,iBAChBA,EAAA,MAAQ,QAXGA,IAAAA,GAAA,CAAA,CAAA,EA4CL,MAAMC,EAAiD,CAC5D,SAAsB,WACtB,QAAqB,UACrB,YAAyB,cACzB,YAAyB,cACzB,KAAkB,OAClB,QAAqB,UACrB,UAAuB,YACvB,YAAyB,cACzB,SAAqB,WACrB,eAA2B,QAC3B,MAAmB,OACrB,EAQaC,EAA0D,CACrE,SAAqB,WACrB,eAA2B,aAC3B,MAAmB,oBACrB,EAqCaC,EAAoC,CAChD,WACA,iBACA,OACD,EASaC,EAAwD,CACnE,SAAsB,EACtB,QAAqB,EAGrB,YAAyB,EACzB,KAAkB,EAClB,QAAqB,EACrB,UAAuB,EAGvB,YAAyB,EACzB,MAAmB,EAEnB,eAA2B,EAC3B,SAAqB,CACvB,EAUaC,EAAoC,CAChD,UACA,cACA,cACA,OACA,UACA,YACA,aACD,EAEMC,EAAyB,IAAI,IAAYD,CAAmB,EAGrDE,EAAuBC,GACnCF,EAAuB,IAAIE,CAAM,EASrBC,EAAyC,CACrD,cACA,aACD,EAEMC,EAA8B,IAAI,IAAYD,CAAwB,EAG/DE,EAA2BH,GACvCE,EAA4B,IAAIF,CAAM,EAQ1BI,EAAwB,oBACxBC,EAA0B,oBAE1BC,EAAyB,GAEhCC,EAAuB,OAAO,KAAKX,CAAgB,EAAE,OAG9CY,EAAkBR,GAC9BJ,EAAiBI,CAAoB,GAAKO,EAa9BE,EAAkE,CAC7E,eAA2B,aAC3B,MAAmB,oBACrB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Y=require("react/jsx-runtime"),s=require("react"),Z=require("./ControlledCopilot.js"),_=require("./useCopilotIcebreakers.js"),$=require("./useCopilotStreamChat.js"),A=({baseUrl:o,endpointPath:m,icebreakersPath:q,headers:r,authToken:t,getAuthToken:n,fetchImpl:a,storeId:i,agent:l,route:c,systemPrompt:R,sessionId:y,persist:O,loadIcebreakers:j=!0,onError:H,onResponseComplete:B,onSessionIdChange:F,suggestions:K,inputDisabled:L,onRefresh:u,onFeedback:C,open:d,defaultOpen:g,onOpenChange:b,...f})=>{const[v,w]=s.useState(g===!0||d===!0),{messages:x,isThinking:D,isStreaming:p,isRestoring:I,error:N,isLoadingHistory:P,hasMoreHistory:z,sendMessage:E,regenerate:G,submitFeedback:S,loadOlderMessages:J,stopStreaming:Q,startNewConversation:k}=$.useCopilotStreamChat({baseUrl:o,endpointPath:m,headers:r,authToken:t,getAuthToken:n,fetchImpl:a,storeId:i,agent:l,route:c,systemPrompt:R,sessionId:y,persist:O,onError:H,onResponseComplete:B,onSessionIdChange:F}),{icebreakers:T}=_.useCopilotIcebreakers({baseUrl:o,icebreakersPath:q,headers:r,authToken:t,getAuthToken:n,fetchImpl:a,agent:l,route:c,storeId:i,enabled:j&&v}),V=s.useCallback(e=>{e&&w(!0),b?.(e)},[b]),W=s.useCallback(()=>{k(),u?.()},[u,k]),X=s.useCallback((e,M,h)=>{S(e,M,h),C?.(e,M,h)},[C,S]);return Y.jsx(Z.ControlledCopilot,{...f,open:d,defaultOpen:g,onOpenChange:V,messages:x,onSendMessage:E,onRegenerate:G,onFeedback:X,isThinking:D,isStreaming:p,onStop:Q,isLoadingHistory:P,hasMoreHistory:z,onLoadOlderMessages:J,errorMessage:N,suggestions:K??T,inputDisabled:L||I||p,onRefresh:W})};exports.BIKCopilot=A;
|
|
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 {\n\tBIKCopilotProps,\n\tCopilotFeedbackDetail,\n\tCopilotFeedbackVote,\n} 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-bikchatbot`\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 * 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\tsystemPrompt,\n\tsessionId,\n\tpersist,\n\tloadIcebreakers = true,\n\tonError,\n\tonResponseComplete,\n\tonSessionIdChange,\n\t// Shell\n\tsuggestions,\n\tinputDisabled,\n\tonRefresh,\n\tonFeedback,\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\tregenerate,\n\t\tsubmitFeedback,\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\tsystemPrompt,\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\t// The vote is recorded either way; a host's own handler only observes it.\n\tconst handleFeedback = useCallback(\n\t\t(\n\t\t\tmessageId: string,\n\t\t\tvote: CopilotFeedbackVote,\n\t\t\tdetail?: CopilotFeedbackDetail,\n\t\t) => {\n\t\t\tsubmitFeedback(messageId, vote, detail);\n\t\t\tonFeedback?.(messageId, vote, detail);\n\t\t},\n\t\t[onFeedback, submitFeedback],\n\t);\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\tonRegenerate={regenerate}\n\t\t\tonFeedback={handleFeedback}\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","systemPrompt","sessionId","persist","loadIcebreakers","onError","onResponseComplete","onSessionIdChange","suggestions","inputDisabled","onRefresh","onFeedback","open","defaultOpen","onOpenChange","shellProps","hasOpened","setHasOpened","useState","messages","isThinking","isStreaming","isRestoring","error","isLoadingHistory","hasMoreHistory","sendMessage","regenerate","submitFeedback","loadOlderMessages","stopStreaming","startNewConversation","useCopilotStreamChat","icebreakers","useCopilotIcebreakers","handleOpenChange","useCallback","nextOpen","handleRefresh","handleFeedback","messageId","vote","detail","jsx","ControlledCopilot"],"mappings":"2PAqCaA,EAAwC,CAAC,CAErD,QAAAC,EACA,aAAAC,EACA,gBAAAC,EACA,QAAAC,EACA,UAAAC,EACA,aAAAC,EACA,UAAAC,EACA,QAAAC,EACA,MAAAC,EACA,MAAAC,EACA,aAAAC,EACA,UAAAC,EACA,QAAAC,EACA,gBAAAC,EAAkB,GAClB,QAAAC,EACA,mBAAAC,EACA,kBAAAC,EAEA,YAAAC,EACA,cAAAC,EACA,UAAAC,EACA,WAAAC,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,WAAAC,EACA,eAAAC,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,aAAAC,EACA,UAAAC,EACA,QAAAC,EACA,QAAAE,EACA,mBAAAC,EACA,kBAAAC,CAAA,CACA,EAEK,CAAE,YAAA0B,CAAA,EAAgBC,wBAAsB,CAC7C,QAAA3C,EACA,gBAAAE,EACA,QAAAC,EACA,UAAAC,EACA,aAAAC,EACA,UAAAC,EACA,MAAAE,EACA,MAAAC,EACA,QAAAF,EACA,QAASM,GAAmBY,CAAA,CAC5B,EAEKmB,EAAmBC,EAAAA,YACvBC,GAAsB,CAClBA,GACHpB,EAAa,EAAI,EAElBH,IAAeuB,CAAQ,CACxB,EACA,CAACvB,CAAY,CAAA,EAGRwB,EAAgBF,EAAAA,YAAY,IAAM,CACvCL,EAAA,EACArB,IAAA,CACD,EAAG,CAACA,EAAWqB,CAAoB,CAAC,EAG9BQ,EAAiBH,EAAAA,YACtB,CACCI,EACAC,EACAC,IACI,CACJd,EAAeY,EAAWC,EAAMC,CAAM,EACtC/B,IAAa6B,EAAWC,EAAMC,CAAM,CACrC,EACA,CAAC/B,EAAYiB,CAAc,CAAA,EAG5B,OACCe,EAAAA,IAACC,EAAAA,kBAAA,CACC,GAAG7B,EACJ,KAAAH,EACA,YAAAC,EACA,aAAcsB,EACd,SAAAhB,EACA,cAAeO,EACf,aAAcC,EACd,WAAYY,EACZ,WAAAnB,EACA,YAAAC,EACA,OAAQS,EACR,iBAAAN,EACA,eAAAC,EACA,oBAAqBI,EACrB,aAAcN,EAGd,YAAaf,GAAeyB,EAE5B,cAAexB,GAAiBa,GAAeD,EAC/C,UAAWiB,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"),ge=require("../../constants/Theme.js"),Ce=require("./ControlledCopilot.styled.js"),v=require("./CopilotBall.js"),me=require("./CopilotPanel.js"),he=require("./copilotPlacement.js"),ve=require("./useDraggableFloater.js"),Pe=({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=ge.COLORS.background.brand,zIndex:d=1200,ballAriaLabel:U,panelWidth:z=400,panelHeight:H=700,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,onRegenerate:oe,onFeedback:ne,inputDisabled:re=!1,open:f,defaultOpen:le=!1,onOpenChange:p,closeOnClickOutside:g=!1,className:se,style:ie})=>{const[ae,ce]=n.useState(le),C=n.useRef(null),i=f!==void 0,e=i?f:ae,o=n.useCallback(t=>{i||ce(t),p?.(t)},[i,p]),{position:m,isDragging:ue,viewport:de,dragHandlers:fe,shouldIgnoreClick:h}=ve.useDraggableFloater({size:s,corner:x,offset:B,enabled:u,snapToEdge:I,initialPosition:D,onPositionChange:F}),pe=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=he.getCopilotPanelPlacement({ballPosition:m,ballSize:s,panelWidth:z,panelHeight:H,gap:K,viewport:de});return r.jsxs(r.Fragment,{children:[e&&r.jsx(Ce.PanelPositioner,{ref:C,$left:l.left,$top:l.top,$width:l.width,$height:l.height,$zIndex:d,children:r.jsx(me.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,onRegenerate:oe,onFeedback:ne,isThinking:w,thinkingLabel:L,isStreaming:q,onStop:E,interruptedLabel:k,followUpsLabel:y,hasMoreHistory:T,isLoadingHistory:j,onLoadOlderMessages:O,historyLoadingLabel:R,inputDisabled:re,errorMessage:$,className:se,style:ie})}),r.jsx(v.CopilotBall,{isOpen:e,onToggle:pe,position:m,size:s,isDragging:ue,draggable:u,color:A,zIndex:d+1,icon:S,openIcon:_,ariaLabel:U,...fe})]})};exports.ControlledCopilot=Pe;
|
|
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-bikchatbot`; `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\tonRegenerate,\n\tonFeedback,\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\tonRegenerate={onRegenerate}\n\t\t\t\t\t\tonFeedback={onFeedback}\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","onRegenerate","onFeedback","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":"oWAmBaA,GAAsD,CAAC,CAEnE,SAAAC,EACA,cAAAC,EACA,WAAAC,EAAa,GACb,cAAAC,EACA,YAAAC,EAAc,GACd,OAAAC,EACA,iBAAAC,EACA,eAAAC,EACA,eAAAC,EAAiB,GACjB,iBAAAC,EAAmB,GACnB,oBAAAC,EACA,oBAAAC,EACA,aAAAC,EAEA,SAAAC,EAAW,GACX,OAAAC,EAAS,eACT,OAAAC,EAAS,GACT,gBAAAC,EACA,UAAAC,EAAY,GACZ,WAAAC,EAAa,GACb,iBAAAC,EACA,SAAAC,EACA,aAAAC,EACA,UAAAC,EAAYC,GAAAA,OAAO,WAAW,MAC9B,OAAAC,EAAS,KACT,cAAAC,EAEA,WAAAC,EAAa,IACb,YAAAC,EAAc,IACd,SAAAC,EAAW,GACX,MAAAC,EAAQ,UACR,MAAAC,EACA,SAAAC,EACA,OAAAC,EACA,YAAAC,EACA,WAAAC,EACA,gBAAAC,EACA,mBAAAC,EACA,YAAAC,EACA,kBAAAC,EACA,YAAAC,GAAc,GACd,UAAAC,GACA,aAAAC,GACA,WAAAC,GACA,cAAAC,GAAgB,GAEhB,KAAAC,EACA,YAAAC,GAAc,GACd,aAAAC,EACA,oBAAAC,EAAsB,GACtB,UAAAC,GACA,MAAAC,EACD,IAAM,CACL,KAAM,CAACC,GAAkBC,EAAmB,EAAIC,EAAAA,SAASP,EAAW,EAC9DQ,EAAWC,EAAAA,OAAuB,IAAI,EAEtCC,EAAeX,IAAS,OACxBY,EAASD,EAAeX,EAAOM,GAE/BO,EAAUC,EAAAA,YACdC,GAAkB,CACbJ,GACJJ,GAAoBQ,CAAI,EAEzBb,IAAea,CAAI,CACpB,EACA,CAACJ,EAAcT,CAAY,CAAA,EAGtB,CAAE,SAAAc,EAAU,WAAAC,GAAY,SAAAC,GAAU,aAAAC,GAAc,kBAAAC,CAAA,EACrDC,uBAAoB,CACnB,KAAMpD,EACN,OAAAC,EACA,OAAAC,EACA,QAASE,EACT,WAAAC,EACA,gBAAAF,EACA,iBAAAG,CAAA,CACA,EAEI+C,GAAkBR,EAAAA,YAAY,IAAM,CAErCM,KAGJP,EAAQ,CAACD,CAAM,CAChB,EAAG,CAACA,EAAQC,EAASO,CAAiB,CAAC,EAGvCG,EAAAA,UAAU,IAAM,CACf,GAAI,CAACX,EACJ,OAED,MAAMY,EAAiBC,GAAyB,CAC3CA,EAAM,MAAQ,UACjBZ,EAAQ,EAAK,CAEf,EACA,gBAAS,iBAAiB,UAAWW,CAAa,EAC3C,IAAM,SAAS,oBAAoB,UAAWA,CAAa,CACnE,EAAG,CAACZ,EAAQC,CAAO,CAAC,EAEpBU,EAAAA,UAAU,IAAM,CACf,GAAI,CAACX,GAAU,CAACT,EACf,OAED,MAAMuB,EAAqBD,GAAwB,CAClD,MAAME,EAASF,EAAM,OAChBE,IAGDlB,EAAS,SAAS,SAASkB,CAAM,GAGjCA,EAAO,QAAQ,IAAIC,EAAAA,sBAAsB,GAAG,GAGhDf,EAAQ,EAAK,EACd,EACA,gBAAS,iBAAiB,cAAea,CAAiB,EACnD,IAAM,SAAS,oBAAoB,cAAeA,CAAiB,CAC3E,EAAG,CAACvB,EAAqBS,EAAQC,CAAO,CAAC,EAEzC,MAAMgB,EAAYC,GAAAA,yBAAyB,CAC1C,aAAcd,EACd,SAAA/C,EACA,WAAAa,EACA,YAAAC,EACA,IAAKC,EACL,SAAAkC,EAAA,CACA,EAED,OACCa,EAAAA,KAAAC,WAAA,CACE,SAAA,CAAApB,GACAqB,EAAAA,IAACC,GAAAA,gBAAA,CACA,IAAKzB,EACL,MAAOoB,EAAU,KACjB,KAAMA,EAAU,IAChB,OAAQA,EAAU,MAClB,QAASA,EAAU,OACnB,QAASjD,EAET,SAAAqD,EAAAA,IAACE,GAAAA,aAAA,CACA,SAAA/E,EACA,OAAQC,EACR,QAAS,IAAMwD,EAAQ,EAAK,EAC5B,MAAA5B,EACA,MAAAC,EACA,SAAAC,EACA,OAAAC,EACA,YAAAC,EACA,WAAAC,EACA,gBAAAC,EACA,mBAAAC,EACA,YAAAC,EACA,kBAAAC,EACA,YAAAC,GACA,UAAAC,GACA,aAAAC,GACA,WAAAC,GACA,WAAAxC,EACA,cAAAC,EACA,YAAAC,EACA,OAAAC,EACA,iBAAAC,EACA,eAAAC,EACA,eAAAC,EACA,iBAAAC,EACA,oBAAAC,EACA,oBAAAC,EACA,cAAAgC,GACA,aAAA/B,EACA,UAAAoC,GACA,MAAAC,EAAA,CAAA,CACD,CAAA,EAIF4B,EAAAA,IAACG,EAAAA,YAAA,CACA,OAAAxB,EACA,SAAUU,GACV,SAAAN,EACA,KAAM/C,EACN,WAAAgD,GACA,UAAA5C,EACA,MAAOK,EACP,OAAQE,EAAS,EACjB,KAAMJ,EACN,SAAUC,EACV,UAAWI,EACV,GAAGsC,EAAA,CAAA,CACL,EACD,CAEF"}
|
|
@@ -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 l=require("react/jsx-runtime"),i=require("react"),t=require("./CopilotFeedbackModal.styled.js"),c=[{value:"TOO_SLOW",label:"Too slow"},{value:"DIDNT_REMEMBER",label:"Didn't remember something"},{value:"WRONG_RESULT",label:"Wrong result"},{value:"COULDNT_FIND_DATA",label:"Couldn't find data"},{value:"DIDNT_UNDERSTAND_CONTEXT",label:"Didn't understand context"}],D=()=>l.jsx("svg",{width:"12",height:"12",viewBox:"0 0 12 12",fill:"none",children:l.jsx("path",{d:"M9 3L3 9M3 3l6 6",stroke:"currentColor",strokeWidth:"1.3",strokeLinecap:"round"})}),O=({title:a="What went wrong?",subtitle:s,reasons:r=c,notePlaceholder:u="Add a quick note...",submitLabel:h="Share feedback",onSubmit:b,onDismiss:C,className:x})=>{const[o,j]=i.useState([]),[d,S]=i.useState(""),M=e=>{j(n=>n.includes(e)?n.filter(g=>g!==e):[...n,e])},T=()=>{const e=d.trim();b({reasons:o,...e?{comment:e}:{}})};return l.jsxs(t.ModalCard,{className:x,role:"dialog","aria-label":a,children:[l.jsxs(t.ModalHeader,{children:[l.jsxs(t.ModalHeading,{children:[l.jsx(t.ModalTitle,{children:a}),s?l.jsx(t.ModalSubtitle,{children:s}):null]}),l.jsx(t.ModalClose,{type:"button",onClick:C,"aria-label":"Close",children:l.jsx(D,{})})]}),l.jsx(t.ReasonList,{children:r.map(e=>l.jsx(t.ReasonChip,{type:"button",$selected:o.includes(e.value),"aria-pressed":o.includes(e.value),onClick:()=>M(e.value),children:e.label},e.value))}),l.jsx(t.NoteInput,{value:d,placeholder:u,onChange:e=>S(e.target.value)}),l.jsx(t.SubmitButton,{type:"button",onClick:T,children:h})]})};exports.COPILOT_FEEDBACK_REASONS=c;exports.CopilotFeedbackModal=O;
|
|
2
|
+
//# sourceMappingURL=CopilotFeedbackModal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CopilotFeedbackModal.js","sources":["../../../../src/components/bik-copilot/CopilotFeedbackModal.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport {\n\tModalCard,\n\tModalClose,\n\tModalHeader,\n\tModalHeading,\n\tModalSubtitle,\n\tModalTitle,\n\tNoteInput,\n\tReasonChip,\n\tReasonList,\n\tSubmitButton,\n} from './CopilotFeedbackModal.styled';\nimport { CopilotFeedbackDetail, CopilotFeedbackReasonOption } from './model';\n\n/** The chips the modal offers, in the order they are shown. */\nexport const COPILOT_FEEDBACK_REASONS: CopilotFeedbackReasonOption[] = [\n\t{ value: 'TOO_SLOW', label: 'Too slow' },\n\t{ value: 'DIDNT_REMEMBER', label: \"Didn't remember something\" },\n\t{ value: 'WRONG_RESULT', label: 'Wrong result' },\n\t{ value: 'COULDNT_FIND_DATA', label: \"Couldn't find data\" },\n\t{ value: 'DIDNT_UNDERSTAND_CONTEXT', label: \"Didn't understand context\" },\n];\n\nconst CloseIcon = () => (\n\t<svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\n\t\t<path\n\t\t\td=\"M9 3L3 9M3 3l6 6\"\n\t\t\tstroke=\"currentColor\"\n\t\t\tstrokeWidth=\"1.3\"\n\t\t\tstrokeLinecap=\"round\"\n\t\t/>\n\t</svg>\n);\n\nexport interface CopilotFeedbackModalProps {\n\ttitle?: string;\n\tsubtitle?: string;\n\treasons?: CopilotFeedbackReasonOption[];\n\tnotePlaceholder?: string;\n\tsubmitLabel?: string;\n\t/**\n\t * The detail the reader chose to share. Called once, on submit.\n\t */\n\tonSubmit: (detail: CopilotFeedbackDetail) => void;\n\t/**\n\t * Dismissed without sharing. The rating itself is the host's business — see\n\t * `CopilotPanel`, which records the thumbs-down either way.\n\t */\n\tonDismiss: () => void;\n\tclassName?: string;\n}\n\n/**\n * Asks what was wrong with a reply that was just rated down.\n *\n * Chips plus an optional note, and nothing is required: a reader who only wants\n * to press the thumb can dismiss this and the rating still stands. Every string\n * is overridable so a host can reword or localise it.\n */\nexport const CopilotFeedbackModal: React.FC<CopilotFeedbackModalProps> = ({\n\ttitle = 'What went wrong?',\n\tsubtitle,\n\treasons = COPILOT_FEEDBACK_REASONS,\n\tnotePlaceholder = 'Add a quick note...',\n\tsubmitLabel = 'Share feedback',\n\tonSubmit,\n\tonDismiss,\n\tclassName,\n}) => {\n\tconst [selected, setSelected] = useState<string[]>([]);\n\tconst [note, setNote] = useState('');\n\n\tconst toggle = (value: string) => {\n\t\tsetSelected((previous) =>\n\t\t\tprevious.includes(value)\n\t\t\t\t? previous.filter((item) => item !== value)\n\t\t\t\t: [...previous, value],\n\t\t);\n\t};\n\n\tconst submit = () => {\n\t\tconst comment = note.trim();\n\t\tonSubmit({\n\t\t\treasons: selected,\n\t\t\t...(comment ? { comment } : {}),\n\t\t});\n\t};\n\n\treturn (\n\t\t<ModalCard className={className} role=\"dialog\" aria-label={title}>\n\t\t\t<ModalHeader>\n\t\t\t\t<ModalHeading>\n\t\t\t\t\t<ModalTitle>{title}</ModalTitle>\n\t\t\t\t\t{subtitle ? <ModalSubtitle>{subtitle}</ModalSubtitle> : null}\n\t\t\t\t</ModalHeading>\n\t\t\t\t<ModalClose type=\"button\" onClick={onDismiss} aria-label=\"Close\">\n\t\t\t\t\t<CloseIcon />\n\t\t\t\t</ModalClose>\n\t\t\t</ModalHeader>\n\n\t\t\t<ReasonList>\n\t\t\t\t{reasons.map((reason) => (\n\t\t\t\t\t<ReasonChip\n\t\t\t\t\t\tkey={reason.value}\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t$selected={selected.includes(reason.value)}\n\t\t\t\t\t\taria-pressed={selected.includes(reason.value)}\n\t\t\t\t\t\tonClick={() => toggle(reason.value)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{reason.label}\n\t\t\t\t\t</ReasonChip>\n\t\t\t\t))}\n\t\t\t</ReasonList>\n\n\t\t\t<NoteInput\n\t\t\t\tvalue={note}\n\t\t\t\tplaceholder={notePlaceholder}\n\t\t\t\tonChange={(event) => setNote(event.target.value)}\n\t\t\t/>\n\n\t\t\t<SubmitButton type=\"button\" onClick={submit}>\n\t\t\t\t{submitLabel}\n\t\t\t</SubmitButton>\n\t\t</ModalCard>\n\t);\n};\n"],"names":["COPILOT_FEEDBACK_REASONS","CloseIcon","jsx","CopilotFeedbackModal","title","subtitle","reasons","notePlaceholder","submitLabel","onSubmit","onDismiss","className","selected","setSelected","useState","note","setNote","toggle","value","previous","item","submit","comment","ModalCard","jsxs","ModalHeader","ModalHeading","ModalTitle","ModalSubtitle","ModalClose","ReasonList","reason","ReasonChip","NoteInput","event","SubmitButton"],"mappings":"sLAgBaA,EAA0D,CACtE,CAAE,MAAO,WAAY,MAAO,UAAA,EAC5B,CAAE,MAAO,iBAAkB,MAAO,2BAAA,EAClC,CAAE,MAAO,eAAgB,MAAO,cAAA,EAChC,CAAE,MAAO,oBAAqB,MAAO,oBAAA,EACrC,CAAE,MAAO,2BAA4B,MAAO,2BAAA,CAC7C,EAEMC,EAAY,IACjBC,EAAAA,IAAC,MAAA,CAAI,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OACpD,SAAAA,EAAAA,IAAC,OAAA,CACA,EAAE,mBACF,OAAO,eACP,YAAY,MACZ,cAAc,OAAA,CACf,EACD,EA4BYC,EAA4D,CAAC,CACzE,MAAAC,EAAQ,mBACR,SAAAC,EACA,QAAAC,EAAUN,EACV,gBAAAO,EAAkB,sBAClB,YAAAC,EAAc,iBACd,SAAAC,EACA,UAAAC,EACA,UAAAC,CACD,IAAM,CACL,KAAM,CAACC,EAAUC,CAAW,EAAIC,EAAAA,SAAmB,CAAA,CAAE,EAC/C,CAACC,EAAMC,CAAO,EAAIF,EAAAA,SAAS,EAAE,EAE7BG,EAAUC,GAAkB,CACjCL,EAAaM,GACZA,EAAS,SAASD,CAAK,EACpBC,EAAS,OAAQC,GAASA,IAASF,CAAK,EACxC,CAAC,GAAGC,EAAUD,CAAK,CAAA,CAExB,EAEMG,EAAS,IAAM,CACpB,MAAMC,EAAUP,EAAK,KAAA,EACrBN,EAAS,CACR,QAASG,EACT,GAAIU,EAAU,CAAE,QAAAA,GAAY,CAAA,CAAC,CAC7B,CACF,EAEA,cACEC,EAAAA,UAAA,CAAU,UAAAZ,EAAsB,KAAK,SAAS,aAAYP,EAC1D,SAAA,CAAAoB,OAACC,EAAAA,YAAA,CACA,SAAA,CAAAD,OAACE,EAAAA,aAAA,CACA,SAAA,CAAAxB,EAAAA,IAACyB,EAAAA,YAAY,SAAAvB,CAAA,CAAM,EAClBC,EAAWH,EAAAA,IAAC0B,EAAAA,cAAA,CAAe,SAAAvB,CAAA,CAAS,EAAmB,IAAA,EACzD,EACAH,EAAAA,IAAC2B,EAAAA,WAAA,CAAW,KAAK,SAAS,QAASnB,EAAW,aAAW,QACxD,SAAAR,EAAAA,IAACD,EAAA,CAAA,CAAU,CAAA,CACZ,CAAA,EACD,EAEAC,EAAAA,IAAC4B,EAAAA,WAAA,CACC,SAAAxB,EAAQ,IAAKyB,GACb7B,EAAAA,IAAC8B,EAAAA,WAAA,CAEA,KAAK,SACL,UAAWpB,EAAS,SAASmB,EAAO,KAAK,EACzC,eAAcnB,EAAS,SAASmB,EAAO,KAAK,EAC5C,QAAS,IAAMd,EAAOc,EAAO,KAAK,EAEjC,SAAAA,EAAO,KAAA,EANHA,EAAO,KAAA,CAQb,EACF,EAEA7B,EAAAA,IAAC+B,EAAAA,UAAA,CACA,MAAOlB,EACP,YAAaR,EACb,SAAW2B,GAAUlB,EAAQkB,EAAM,OAAO,KAAK,CAAA,CAAA,QAG/CC,EAAAA,aAAA,CAAa,KAAK,SAAS,QAASd,EACnC,SAAAb,CAAA,CACF,CAAA,EACD,CAEF"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("styled-components"),e=require("../../constants/Theme.js"),n=o=>o&&typeof o=="object"&&"default"in o?o:{default:o},t=n(r),a=t.default.div`
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
gap: 10px;
|
|
5
|
+
width: 220px;
|
|
6
|
+
padding: 14px;
|
|
7
|
+
background: ${e.COLORS.surface.standard};
|
|
8
|
+
border: 1px solid ${e.COLORS.stroke.primary};
|
|
9
|
+
border-radius: 12px;
|
|
10
|
+
box-shadow: 0 12px 32px rgba(40, 3, 78, 0.16);
|
|
11
|
+
`,d=t.default.div`
|
|
12
|
+
display: flex;
|
|
13
|
+
align-items: flex-start;
|
|
14
|
+
justify-content: space-between;
|
|
15
|
+
gap: 8px;
|
|
16
|
+
`,i=t.default.div`
|
|
17
|
+
display: flex;
|
|
18
|
+
flex-direction: column;
|
|
19
|
+
gap: 2px;
|
|
20
|
+
`,l=t.default.span`
|
|
21
|
+
font-family: Inter;
|
|
22
|
+
font-size: 13px;
|
|
23
|
+
font-weight: 600;
|
|
24
|
+
line-height: 18px;
|
|
25
|
+
color: ${e.COLORS.content.primary};
|
|
26
|
+
`,s=t.default.span`
|
|
27
|
+
font-family: Inter;
|
|
28
|
+
font-size: 11px;
|
|
29
|
+
line-height: 16px;
|
|
30
|
+
color: ${e.COLORS.content.placeholder};
|
|
31
|
+
`,c=t.default.button`
|
|
32
|
+
display: inline-flex;
|
|
33
|
+
align-items: center;
|
|
34
|
+
justify-content: center;
|
|
35
|
+
width: 20px;
|
|
36
|
+
height: 20px;
|
|
37
|
+
flex-shrink: 0;
|
|
38
|
+
padding: 0;
|
|
39
|
+
border: none;
|
|
40
|
+
border-radius: 4px;
|
|
41
|
+
background: transparent;
|
|
42
|
+
color: ${e.COLORS.content.placeholder};
|
|
43
|
+
cursor: pointer;
|
|
44
|
+
transition: background 0.15s ease, color 0.15s ease;
|
|
45
|
+
|
|
46
|
+
&:hover {
|
|
47
|
+
background: ${e.COLORS.surface.hovered};
|
|
48
|
+
color: ${e.COLORS.content.primary};
|
|
49
|
+
}
|
|
50
|
+
`,p=t.default.div`
|
|
51
|
+
display: flex;
|
|
52
|
+
flex-wrap: wrap;
|
|
53
|
+
gap: 6px;
|
|
54
|
+
`,u=t.default.button`
|
|
55
|
+
padding: 4px 8px;
|
|
56
|
+
border-radius: 6px;
|
|
57
|
+
border: 1px solid
|
|
58
|
+
${({$selected:o})=>o?e.COLORS.stroke.brand:e.COLORS.stroke.primary};
|
|
59
|
+
background: ${({$selected:o})=>o?e.COLORS.background.brandVeryLight:e.COLORS.surface.standard};
|
|
60
|
+
color: ${({$selected:o})=>o?e.COLORS.content.brand:e.COLORS.content.secondary};
|
|
61
|
+
font-family: Inter;
|
|
62
|
+
font-size: 11px;
|
|
63
|
+
line-height: 16px;
|
|
64
|
+
text-align: left;
|
|
65
|
+
cursor: pointer;
|
|
66
|
+
transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
|
|
67
|
+
|
|
68
|
+
&:hover {
|
|
69
|
+
background: ${({$selected:o})=>o?e.COLORS.background.brandVeryLight:e.COLORS.surface.hovered};
|
|
70
|
+
}
|
|
71
|
+
`,f=t.default.textarea`
|
|
72
|
+
min-height: 64px;
|
|
73
|
+
padding: 8px;
|
|
74
|
+
border: 1px solid ${e.COLORS.stroke.primary};
|
|
75
|
+
border-radius: 8px;
|
|
76
|
+
background: ${e.COLORS.surface.standard};
|
|
77
|
+
color: ${e.COLORS.content.primary};
|
|
78
|
+
font-family: Inter;
|
|
79
|
+
font-size: 11px;
|
|
80
|
+
line-height: 16px;
|
|
81
|
+
resize: none;
|
|
82
|
+
outline: none;
|
|
83
|
+
|
|
84
|
+
&::placeholder {
|
|
85
|
+
color: ${e.COLORS.content.placeholder};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
&:focus {
|
|
89
|
+
border-color: ${e.COLORS.stroke.brand};
|
|
90
|
+
}
|
|
91
|
+
`,b=t.default.button`
|
|
92
|
+
padding: 8px;
|
|
93
|
+
border: none;
|
|
94
|
+
border-radius: 8px;
|
|
95
|
+
background: ${e.COLORS.background.brand};
|
|
96
|
+
color: ${e.COLORS.content.primaryInverse};
|
|
97
|
+
font-family: Inter;
|
|
98
|
+
font-size: 12px;
|
|
99
|
+
font-weight: 600;
|
|
100
|
+
line-height: 16px;
|
|
101
|
+
cursor: pointer;
|
|
102
|
+
transition: background 0.15s ease;
|
|
103
|
+
|
|
104
|
+
&:hover {
|
|
105
|
+
background: ${e.COLORS.background.brandHovered};
|
|
106
|
+
}
|
|
107
|
+
`;exports.ModalCard=a;exports.ModalClose=c;exports.ModalHeader=d;exports.ModalHeading=i;exports.ModalSubtitle=s;exports.ModalTitle=l;exports.NoteInput=f;exports.ReasonChip=u;exports.ReasonList=p;exports.SubmitButton=b;
|
|
108
|
+
//# sourceMappingURL=CopilotFeedbackModal.styled.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CopilotFeedbackModal.styled.js","sources":["../../../../src/components/bik-copilot/CopilotFeedbackModal.styled.ts"],"sourcesContent":["import styled from 'styled-components';\nimport { COLORS } from '@src/constants/Theme';\n\nexport const ModalCard = styled.div`\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 10px;\n\twidth: 220px;\n\tpadding: 14px;\n\tbackground: ${COLORS.surface.standard};\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tborder-radius: 12px;\n\tbox-shadow: 0 12px 32px rgba(40, 3, 78, 0.16);\n`;\n\nexport const ModalHeader = styled.div`\n\tdisplay: flex;\n\talign-items: flex-start;\n\tjustify-content: space-between;\n\tgap: 8px;\n`;\n\nexport const ModalHeading = styled.div`\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n`;\n\nexport const ModalTitle = styled.span`\n\tfont-family: Inter;\n\tfont-size: 13px;\n\tfont-weight: 600;\n\tline-height: 18px;\n\tcolor: ${COLORS.content.primary};\n`;\n\nexport const ModalSubtitle = styled.span`\n\tfont-family: Inter;\n\tfont-size: 11px;\n\tline-height: 16px;\n\tcolor: ${COLORS.content.placeholder};\n`;\n\nexport const ModalClose = styled.button`\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 20px;\n\theight: 20px;\n\tflex-shrink: 0;\n\tpadding: 0;\n\tborder: none;\n\tborder-radius: 4px;\n\tbackground: transparent;\n\tcolor: ${COLORS.content.placeholder};\n\tcursor: pointer;\n\ttransition: background 0.15s ease, color 0.15s ease;\n\n\t&:hover {\n\t\tbackground: ${COLORS.surface.hovered};\n\t\tcolor: ${COLORS.content.primary};\n\t}\n`;\n\nexport const ReasonList = styled.div`\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 6px;\n`;\n\n/* A toggle, not a radio: more than one thing can be wrong with one reply. */\nexport const ReasonChip = styled.button<{ $selected: boolean }>`\n\tpadding: 4px 8px;\n\tborder-radius: 6px;\n\tborder: 1px solid\n\t\t${({ $selected }) =>\n\t\t\t$selected ? COLORS.stroke.brand : COLORS.stroke.primary};\n\tbackground: ${({ $selected }) =>\n\t\t$selected ? COLORS.background.brandVeryLight : COLORS.surface.standard};\n\tcolor: ${({ $selected }) =>\n\t\t$selected ? COLORS.content.brand : COLORS.content.secondary};\n\tfont-family: Inter;\n\tfont-size: 11px;\n\tline-height: 16px;\n\ttext-align: left;\n\tcursor: pointer;\n\ttransition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;\n\n\t&:hover {\n\t\tbackground: ${({ $selected }) =>\n\t\t\t$selected ? COLORS.background.brandVeryLight : COLORS.surface.hovered};\n\t}\n`;\n\nexport const NoteInput = styled.textarea`\n\tmin-height: 64px;\n\tpadding: 8px;\n\tborder: 1px solid ${COLORS.stroke.primary};\n\tborder-radius: 8px;\n\tbackground: ${COLORS.surface.standard};\n\tcolor: ${COLORS.content.primary};\n\tfont-family: Inter;\n\tfont-size: 11px;\n\tline-height: 16px;\n\tresize: none;\n\toutline: none;\n\n\t&::placeholder {\n\t\tcolor: ${COLORS.content.placeholder};\n\t}\n\n\t&:focus {\n\t\tborder-color: ${COLORS.stroke.brand};\n\t}\n`;\n\nexport const SubmitButton = styled.button`\n\tpadding: 8px;\n\tborder: none;\n\tborder-radius: 8px;\n\tbackground: ${COLORS.background.brand};\n\tcolor: ${COLORS.content.primaryInverse};\n\tfont-family: Inter;\n\tfont-size: 12px;\n\tfont-weight: 600;\n\tline-height: 16px;\n\tcursor: pointer;\n\ttransition: background 0.15s ease;\n\n\t&:hover {\n\t\tbackground: ${COLORS.background.brandHovered};\n\t}\n`;\n"],"names":["ModalCard","styled","COLORS","ModalHeader","ModalHeading","ModalTitle","ModalSubtitle","ModalClose","ReasonList","ReasonChip","$selected","NoteInput","SubmitButton"],"mappings":"0NAGaA,EAAYC,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAMjBC,EAAAA,OAAO,QAAQ,QAAQ;AAAA,qBACjBA,EAAAA,OAAO,OAAO,OAAO;AAAA;AAAA;AAAA,EAK7BC,EAAcF,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrBG,EAAeH,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA,EAMtBI,EAAaJ,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA,UAKvBC,EAAAA,OAAO,QAAQ,OAAO;AAAA,EAGnBI,EAAgBL,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA,UAI1BC,EAAAA,OAAO,QAAQ,WAAW;AAAA,EAGvBK,EAAaN,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAWvBC,EAAAA,OAAO,QAAQ,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA,gBAKpBA,EAAAA,OAAO,QAAQ,OAAO;AAAA,WAC3BA,EAAAA,OAAO,QAAQ,OAAO;AAAA;AAAA,EAIpBM,EAAaP,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA,EAOpBQ,EAAaR,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA,IAI7B,CAAC,CAAE,UAAAS,CAAA,IACJA,EAAYR,EAAAA,OAAO,OAAO,MAAQA,EAAAA,OAAO,OAAO,OAAO;AAAA,eAC3C,CAAC,CAAE,UAAAQ,CAAA,IAChBA,EAAYR,EAAAA,OAAO,WAAW,eAAiBA,EAAAA,OAAO,QAAQ,QAAQ;AAAA,UAC9D,CAAC,CAAE,UAAAQ,CAAA,IACXA,EAAYR,EAAAA,OAAO,QAAQ,MAAQA,EAAAA,OAAO,QAAQ,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAS7C,CAAC,CAAE,UAAAQ,CAAA,IAChBA,EAAYR,EAAAA,OAAO,WAAW,eAAiBA,EAAAA,OAAO,QAAQ,OAAO;AAAA;AAAA,EAI3DS,EAAYV,EAAAA,QAAO;AAAA;AAAA;AAAA,qBAGXC,EAAAA,OAAO,OAAO,OAAO;AAAA;AAAA,eAE3BA,EAAAA,OAAO,QAAQ,QAAQ;AAAA,UAC5BA,EAAAA,OAAO,QAAQ,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAQrBA,EAAAA,OAAO,QAAQ,WAAW;AAAA;AAAA;AAAA;AAAA,kBAInBA,EAAAA,OAAO,OAAO,KAAK;AAAA;AAAA,EAIxBU,EAAeX,EAAAA,QAAO;AAAA;AAAA;AAAA;AAAA,eAIpBC,EAAAA,OAAO,WAAW,KAAK;AAAA,UAC5BA,EAAAA,OAAO,QAAQ,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBASvBA,EAAAA,OAAO,WAAW,YAAY;AAAA;AAAA"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),He=require("../../assets/icons/arrow_down.svg.js"),b=require("../../assets/icons/bik_ai_stars_icon.svg.js"),Pe=require("../../assets/icons/cross.svg.js"),Ee=require("../../assets/icons/refresh.svg.js"),i=require("react"),x=require("../../constants/Theme.js"),g=require("../TypographyStyle.js"),Fe=require("./CopilotFeedbackModal.js"),o=require("./CopilotPanel.styled.js"),Oe=require("./copilotRegenerate.js"),qe=require("./utils/markdown.js"),We=require("./utils/toolCtas.js"),ne=require("../dot-pulse/DotPulse.js"),Ne=r=>r&&typeof r=="object"&&"default"in r?r:{default:r},$e=Ne(i),De=96,Ue=24,Ve=1800,Ke=async r=>{try{if(navigator.clipboard?.writeText)return await navigator.clipboard.writeText(r),!0}catch{}try{const l=document.createElement("textarea");l.value=r,l.setAttribute("readonly",""),l.style.position="fixed",l.style.top="-1000px",l.style.opacity="0",document.body.appendChild(l),l.select();const T=document.execCommand("copy");return document.body.removeChild(l),T}catch{return!1}},Xe=48,Ge=r=>{if(!r||!Number.isFinite(r))return"";const l=new Date(r);return Number.isNaN(l.getTime())?"":l.toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"})},ze=()=>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"})]}),Je=()=>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"})]}),ie=({size:r=16})=>e.jsx("svg",{viewBox:"0 0 24 24",width:r,height:r,fill:"currentColor","aria-hidden":"true",children:e.jsx("rect",{x:"7",y:"7",width:"10",height:"10",rx:"2"})}),Ze=()=>e.jsxs("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[e.jsx("rect",{x:"9",y:"9",width:"11",height:"11",rx:"2"}),e.jsx("path",{d:"M15 5.5A1.5 1.5 0 0 0 13.5 4H5.5A1.5 1.5 0 0 0 4 5.5v8A1.5 1.5 0 0 0 5.5 15"})]}),Qe=()=>e.jsx("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:"none",stroke:"currentColor",strokeWidth:"2.2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:e.jsx("path",{d:"M5 13l4 4L19 7"})}),Ye=()=>e.jsxs("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[e.jsx("path",{d:"M20 12a8 8 0 1 1-2.34-5.66"}),e.jsx("path",{d:"M20 4v4h-4"})]}),et=({filled:r=!1})=>e.jsxs("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:r?"currentColor":"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[e.jsx("path",{d:"M7 10v11H4a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1h3Z"}),e.jsx("path",{d:"M7 10l4.5-7a2 2 0 0 1 3.7 1.3L14.5 9H19a2 2 0 0 1 2 2.3l-1.1 7A2 2 0 0 1 18 20H7"})]}),tt=({filled:r=!1})=>e.jsxs("svg",{viewBox:"0 0 24 24",width:"14",height:"14",fill:r?"currentColor":"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[e.jsx("path",{d:"M7 14V3H4a1 1 0 0 0-1 1v9a1 1 0 0 0 1 1h3Z"}),e.jsx("path",{d:"M7 14l4.5 7a2 2 0 0 0 3.7-1.3L14.5 15H19a2 2 0 0 0 2-2.3l-1.1-7A2 2 0 0 0 18 4H7"})]}),ot=({messages:r,onSend:l,onClose:T,title:j="Copilot",badge:F,subtitle:O,avatar:le,placeholder:se="Write your message...",disclaimer:q="AI can make mistakes, Verify the responses.",emptyStateTitle:ce,emptyStateSubtitle:W="Here are some things you can try",suggestions:v,onSuggestionClick:ae,showRefresh:de=!0,onRefresh:N,onRegenerate:$,onFeedback:S,dislikeTitle:he,dislikeSubtitle:ue,dislikeReasons:pe,dislikeNotePlaceholder:xe,dislikeSubmitLabel:je,isThinking:f=!1,thinkingLabel:D="Thinking",isStreaming:fe=!1,onStop:U,interruptedLabel:V="This message was interrupted",followUpsLabel:K="Follow ups",onToolCtaClick:ke,hasMoreHistory:Ce=!1,isLoadingHistory:k=!1,onLoadOlderMessages:X,historyLoadingLabel:we="Loading earlier messages",inputDisabled:a=!1,errorMessage:G,width:ye,height:be,className:ge,style:Te})=>{const[M,z]=i.useState(""),[ve,J]=i.useState(!1),[L,R]=i.useState(!0),[C,Z]=i.useState(null),[h,Se]=i.useState({}),[w,A]=i.useState(null),Q=i.useRef(null),u=i.useRef(null),I=i.useRef(null),m=i.useRef(null),B=i.useRef(0),_=i.useRef(null),y=r.filter(t=>(t.content.length>0||t.wasInterrupted)&&!Oe.isCopilotRegeneratePrompt(t.content)),Y=y.length===0&&!f,d=f||fe,ee=!a&&!d&&M.trim().length>0,p=d&&!!U,H=y[y.length-1],P=!d&&H?.role==="assistant"?H.followUps:void 0,E=!Y&&!L;i.useEffect(()=>{L&&I.current?.scrollIntoView({behavior:"smooth"})},[r,f,L]),i.useEffect(()=>{const t=m.current,n=_.current;!t||n===null||k||(_.current=null,t.scrollTop=t.scrollHeight-n,B.current=t.scrollTop)},[r,k]);const Me=()=>{const t=m.current;if(!t)return;const n=t.scrollHeight-t.scrollTop-t.clientHeight;t.scrollTop<=Xe&&Ce&&!k&&X&&(_.current=t.scrollHeight-t.scrollTop,X());const c=t.scrollTop<B.current-1;if(B.current=t.scrollTop,n<=Ue){R(!0);return}c&&R(!1)},Le=()=>{R(!0),I.current?.scrollIntoView({behavior:"smooth"})};i.useEffect(()=>()=>{u.current&&window.clearTimeout(u.current)},[]);const Re=async t=>{await Ke(t.content)&&(u.current&&window.clearTimeout(u.current),Z(t.id),u.current=window.setTimeout(()=>Z(null),Ve))},te=(t,n)=>{const c=h[t]===n;if(Se(s=>({...s,[t]:s[t]===n?void 0:n})),c){n==="dislike"&&A(s=>s===t?null:s);return}if(n==="like"){S?.(t,"like");return}w&&w!==t&&S?.(w,"dislike"),A(t)},oe=(t,n)=>{A(c=>c===t?null:c),S?.(t,"dislike",n)},Ae=()=>{a||d||$?.()},re=()=>{const t=M.trim();if(!t||a||d)return;l(t),z("");const n=Q.current;n&&(n.style.height="auto")},Ie=t=>{z(t.target.value);const n=t.target;n.style.height="auto",n.style.height=`${Math.min(n.scrollHeight,De)}px`},me=t=>{t.key==="Enter"&&!t.shiftKey&&(t.preventDefault(),re())},Be=t=>{a||d||(ae?.(t),l(t.text))},_e=t=>{a||d||l(t)};return e.jsxs(o.PanelContainer,{className:ge,style:{width:ye,height:be,...Te},role:"dialog","aria-label":j,children:[e.jsxs(o.PanelHeader,{children:[e.jsx(o.HeaderAvatar,{children:le??e.jsx(b.default,{width:18,height:18})}),e.jsxs(o.HeaderText,{children:[e.jsxs(o.HeaderTitleRow,{children:[e.jsx(g.TitleSmall,{children:j}),F&&e.jsx(o.HeaderBadge,{children:F})]}),O&&e.jsx(g.BodyCaption,{color:x.COLORS.content.secondary,children:O})]}),e.jsxs(o.HeaderActions,{children:[de&&N&&e.jsx(o.IconAction,{type:"button",onClick:N,"aria-label":"Start a new conversation",children:e.jsx(Ee.default,{width:16,height:16})}),e.jsx(o.IconAction,{type:"button",onClick:T,"aria-label":"Close copilot",children:e.jsx(Pe.default,{width:18,height:18})})]})]}),e.jsxs(o.MessagesViewport,{children:[e.jsx(o.MessagesArea,{ref:m,onScroll:Me,role:"region","aria-label":"Conversation",children:Y?e.jsxs(o.EmptyState,{children:[e.jsx(o.EmptyStateIcon,{children:e.jsx(b.default,{width:28,height:28})}),e.jsx(g.BodySecondary,{style:{fontWeight:600},children:ce||j}),W&&e.jsx(g.BodyCaption,{color:x.COLORS.content.secondary,children:W}),v&&v.length>0&&e.jsx(o.SuggestionList,{children:v.map(t=>e.jsxs(o.SuggestionChip,{type:"button",disabled:a||d,onClick:()=>Be(t),children:[e.jsx(b.default,{width:14,height:14}),t.text]},t.id))})]}):e.jsxs(e.Fragment,{children:[k&&e.jsxs(o.HistoryLoader,{role:"status","aria-live":"polite",children:[e.jsx(ne.DotPulse,{color:x.COLORS.content.placeholder,size:4}),we]}),y.map(t=>{const n=t.role==="user"?Ge(t.timestamp):"";return e.jsxs($e.default.Fragment,{children:[t.content.length>0&&e.jsx(o.MessageBubble,{$role:t.role,children:t.role==="assistant"?e.jsx("div",{dangerouslySetInnerHTML:{__html:qe.renderCopilotMarkdown(t.content)}}):e.jsx("div",{style:{whiteSpace:"pre-wrap"},children:t.content})}),t.role==="assistant"&&!t.isStreaming&&(()=>{const c=We.toolResultCtas(t.toolResults);return c.length===0?null:e.jsx(o.ToolCtaList,{children:c.map(s=>e.jsx(o.ToolCtaLink,{href:s.url,target:"_blank",rel:"noopener noreferrer",onClick:()=>ke?.({tool:s.tool,url:s.url}),children:s.label},`${s.tool}-${s.url}`))})})(),n&&e.jsx(o.MessageTimestamp,{children:n}),t.wasInterrupted&&V&&e.jsxs(o.InterruptedNote,{children:[e.jsx(ie,{size:12}),V]}),t.role==="assistant"&&t.content.length>0&&!t.isStreaming&&e.jsxs(o.MessageActions,{children:[e.jsx(o.MessageAction,{type:"button",onClick:()=>{Re(t)},"data-copied":C===t.id,title:C===t.id?"Copied":"Copy","aria-label":C===t.id?"Response copied to clipboard":"Copy response",children:C===t.id?e.jsx(Qe,{}):e.jsx(Ze,{})}),$&&t.id===H?.id&&e.jsx(o.MessageAction,{type:"button",onClick:Ae,disabled:a||d,title:"Regenerate","aria-label":"Regenerate response",children:e.jsx(Ye,{})}),e.jsx(o.MessageAction,{type:"button",onClick:()=>te(t.id,"like"),"data-selected":h[t.id]==="like","aria-pressed":h[t.id]==="like",title:"Good response","aria-label":"Good response",children:e.jsx(et,{filled:h[t.id]==="like"})}),e.jsx(o.MessageAction,{type:"button",onClick:()=>te(t.id,"dislike"),"data-selected":h[t.id]==="dislike","aria-pressed":h[t.id]==="dislike",title:"Bad response","aria-label":"Bad response",children:e.jsx(tt,{filled:h[t.id]==="dislike"})})]}),w===t.id&&e.jsx(Fe.CopilotFeedbackModal,{title:he,subtitle:ue??`Help us improve ${j}`,reasons:pe,notePlaceholder:xe,submitLabel:je,onSubmit:c=>oe(t.id,c),onDismiss:()=>oe(t.id)})]},t.id)}),P&&P.length>0&&e.jsxs(o.FollowUpList,{children:[K&&e.jsx(o.FollowUpsLabel,{children:K}),P.map(t=>e.jsxs(o.FollowUpChip,{type:"button",disabled:a,onClick:()=>_e(t),children:[e.jsx(Je,{}),t]},t))]}),f&&e.jsxs(o.ThinkingBubble,{role:"status","aria-live":"polite",children:[e.jsx(b.default,{width:14,height:14,color:x.COLORS.content.brand}),D&&e.jsx(o.ThinkingLabel,{children:D}),e.jsx(ne.DotPulse,{color:x.COLORS.background.brand,size:5})]}),e.jsx("div",{ref:I})]})}),e.jsx(o.ScrollFade,{$visible:E,"aria-hidden":"true"}),e.jsx(o.JumpToLatestButton,{type:"button",$visible:E,onClick:Le,tabIndex:E?0:-1,"aria-label":"Scroll to the latest message",children:e.jsx(He.default,{width:16,height:16})})]}),G&&e.jsx(o.ErrorBanner,{role:"alert",children:G}),e.jsx(o.InputArea,{children:e.jsxs(o.InputWrapper,{$focused:ve,children:[e.jsx(o.MessageInput,{ref:Q,rows:1,value:M,placeholder:se,disabled:a,onChange:Ie,onKeyDown:me,onFocus:()=>J(!0),onBlur:()=>J(!1)}),e.jsx(o.SendButton,{type:"button",$active:p||ee,disabled:!p&&!ee,onClick:p?U:re,"aria-label":p?"Stop generating":"Send message",children:p?e.jsx(ie,{}):e.jsx(ze,{})})]})}),q&&e.jsx(o.Disclaimer,{children:q})]})};exports.CopilotPanel=ot;
|
|
2
|
+
//# sourceMappingURL=CopilotPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CopilotPanel.js","sources":["../../../../src/components/bik-copilot/CopilotPanel.tsx"],"sourcesContent":["import ArrowDownIcon from '@src/assets/icons/arrow_down.svg';\nimport 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 { DotPulse } from '../dot-pulse';\nimport { BodyCaption, BodySecondary, TitleSmall } from '../TypographyStyle';\nimport { CopilotFeedbackModal } from './CopilotFeedbackModal';\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\tMessageAction,\n\tMessageActions,\n\tMessageBubble,\n\tMessageInput,\n\tMessagesArea,\n\tMessagesViewport,\n\tMessageTimestamp,\n\tPanelContainer,\n\tPanelHeader,\n\tScrollFade,\n\tSendButton,\n\tSuggestionChip,\n\tSuggestionList,\n\tThinkingBubble,\n\tThinkingLabel,\n\tToolCtaLink,\n\tToolCtaList,\n} from './CopilotPanel.styled';\nimport { isCopilotRegeneratePrompt } from './copilotRegenerate';\nimport { CopilotFeedbackDetail, CopilotPanelProps } from './model';\nimport { renderCopilotMarkdown } from './utils/markdown';\nimport { toolResultCtas } from './utils/toolCtas';\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 long the copy button shows its confirmation before reverting. */\nconst COPIED_FEEDBACK_MS = 1800;\n\n/**\n * Writes text to the clipboard.\n *\n * `navigator.clipboard` is missing outside a secure context and can reject when\n * the document is not focused, so a hidden-textarea `execCommand` fallback keeps\n * the button working there rather than failing silently.\n */\nconst writeToClipboard = async (text: string): Promise<boolean> => {\n\ttry {\n\t\tif (navigator.clipboard?.writeText) {\n\t\t\tawait navigator.clipboard.writeText(text);\n\t\t\treturn true;\n\t\t}\n\t} catch {\n\t\t// Fall through to the legacy path.\n\t}\n\n\ttry {\n\t\tconst textarea = document.createElement('textarea');\n\t\ttextarea.value = text;\n\t\t// Off-screen rather than hidden: `display: none` cannot be selected.\n\t\ttextarea.setAttribute('readonly', '');\n\t\ttextarea.style.position = 'fixed';\n\t\ttextarea.style.top = '-1000px';\n\t\ttextarea.style.opacity = '0';\n\t\tdocument.body.appendChild(textarea);\n\t\ttextarea.select();\n\t\tconst copied = document.execCommand('copy');\n\t\tdocument.body.removeChild(textarea);\n\t\treturn copied;\n\t} catch {\n\t\treturn false;\n\t}\n};\n\n/** How close to the top counts as asking for the previous page. */\nconst NEAR_TOP_TOLERANCE_PX = 48;\n\nconst formatMessageTime = (timestamp: number): string => {\n\tif (!timestamp || !Number.isFinite(timestamp)) {\n\t\treturn '';\n\t}\n\tconst date = new Date(timestamp);\n\tif (Number.isNaN(date.getTime())) {\n\t\treturn '';\n\t}\n\treturn date.toLocaleTimeString('en-US', {\n\t\thour: 'numeric',\n\t\tminute: '2-digit',\n\t});\n};\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 CopyIcon = () => (\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=\"1.8\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<rect x=\"9\" y=\"9\" width=\"11\" height=\"11\" rx=\"2\" />\n\t\t<path d=\"M15 5.5A1.5 1.5 0 0 0 13.5 4H5.5A1.5 1.5 0 0 0 4 5.5v8A1.5 1.5 0 0 0 5.5 15\" />\n\t</svg>\n);\n\nconst CheckIcon = () => (\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.2\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<path d=\"M5 13l4 4L19 7\" />\n\t</svg>\n);\n\nconst RegenerateIcon = () => (\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=\"1.8\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<path d=\"M20 12a8 8 0 1 1-2.34-5.66\" />\n\t\t<path d=\"M20 4v4h-4\" />\n\t</svg>\n);\n\nconst ThumbUpIcon = ({ filled = false }: { filled?: boolean }) => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tfill={filled ? 'currentColor' : 'none'}\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"1.8\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<path d=\"M7 10v11H4a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1h3Z\" />\n\t\t<path d=\"M7 10l4.5-7a2 2 0 0 1 3.7 1.3L14.5 9H19a2 2 0 0 1 2 2.3l-1.1 7A2 2 0 0 1 18 20H7\" />\n\t</svg>\n);\n\nconst ThumbDownIcon = ({ filled = false }: { filled?: boolean }) => (\n\t<svg\n\t\tviewBox=\"0 0 24 24\"\n\t\twidth=\"14\"\n\t\theight=\"14\"\n\t\tfill={filled ? 'currentColor' : 'none'}\n\t\tstroke=\"currentColor\"\n\t\tstrokeWidth=\"1.8\"\n\t\tstrokeLinecap=\"round\"\n\t\tstrokeLinejoin=\"round\"\n\t\taria-hidden=\"true\"\n\t>\n\t\t<path d=\"M7 14V3H4a1 1 0 0 0-1 1v9a1 1 0 0 0 1 1h3Z\" />\n\t\t<path d=\"M7 14l4.5 7a2 2 0 0 0 3.7-1.3L14.5 15H19a2 2 0 0 0 2-2.3l-1.1-7A2 2 0 0 0 18 4H7\" />\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\tonRegenerate,\n\tonFeedback,\n\tdislikeTitle,\n\tdislikeSubtitle,\n\tdislikeReasons,\n\tdislikeNotePlaceholder,\n\tdislikeSubmitLabel,\n\tisThinking = false,\n\tthinkingLabel = 'Thinking',\n\tisStreaming = false,\n\tonStop,\n\tinterruptedLabel = 'This message was interrupted',\n\tfollowUpsLabel = 'Follow ups',\n\tonToolCtaClick,\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\t// Which reply is showing \"Copied\" — per message, so copying one does not tick\n\t// the button under another.\n\tconst [copiedMessageId, setCopiedMessageId] = useState<string | null>(null);\n\n\tconst [feedback, setFeedback] = useState<\n\t\tRecord<string, 'like' | 'dislike' | undefined>\n\t>({});\n\t// Which reply is being asked about. A thumbs-down opens the prompt and the\n\t// rating is reported once it is answered or dismissed -- so pressing the\n\t// thumb is never lost, and one thumb never becomes two ratings.\n\tconst [dislikePromptId, setDislikePromptId] = useState<string | null>(null);\n\tconst inputRef = useRef<HTMLTextAreaElement>(null);\n\tconst copiedTimeoutRef = useRef<number | null>(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) =>\n\t\t\t(message.content.length > 0 || message.wasInterrupted) &&\n\t\t\t!isCopilotRegeneratePrompt(message.content),\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\tuseEffect(\n\t\t() => () => {\n\t\t\tif (copiedTimeoutRef.current) {\n\t\t\t\twindow.clearTimeout(copiedTimeoutRef.current);\n\t\t\t}\n\t\t},\n\t\t[],\n\t);\n\n\tconst handleCopyMessage = async (\n\t\tmessage: CopilotPanelProps['messages'][number],\n\t) => {\n\t\t// The raw markdown, not the rendered HTML — that is what a reader wants to\n\t\t// paste into a doc or a ticket.\n\t\tconst copied = await writeToClipboard(message.content);\n\t\tif (!copied) {\n\t\t\treturn;\n\t\t}\n\t\tif (copiedTimeoutRef.current) {\n\t\t\twindow.clearTimeout(copiedTimeoutRef.current);\n\t\t}\n\t\tsetCopiedMessageId(message.id);\n\t\tcopiedTimeoutRef.current = window.setTimeout(\n\t\t\t() => setCopiedMessageId(null),\n\t\t\tCOPIED_FEEDBACK_MS,\n\t\t);\n\t};\n\n\tconst handleFeedback = (messageId: string, vote: 'like' | 'dislike') => {\n\t\t// Pressing the same thumb again clears the vote. Nothing is reported for\n\t\t// that: the backend records ratings, not their absence.\n\t\tconst cleared = feedback[messageId] === vote;\n\t\tsetFeedback((previous) => ({\n\t\t\t...previous,\n\t\t\t[messageId]: previous[messageId] === vote ? undefined : vote,\n\t\t}));\n\t\t// Everything below sits outside the updater on purpose: React may run an\n\t\t// updater twice, which would report the same vote twice.\n\t\tif (cleared) {\n\t\t\tif (vote === 'dislike') {\n\t\t\t\tsetDislikePromptId((current) =>\n\t\t\t\t\tcurrent === messageId ? null : current,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (vote === 'like') {\n\t\t\tonFeedback?.(messageId, 'like');\n\t\t\treturn;\n\t\t}\n\t\t// A thumbs-down asks what went wrong first. Moving the prompt to another\n\t\t// reply still records the one it is leaving.\n\t\tif (dislikePromptId && dislikePromptId !== messageId) {\n\t\t\tonFeedback?.(dislikePromptId, 'dislike');\n\t\t}\n\t\tsetDislikePromptId(messageId);\n\t};\n\n\tconst reportDislike = (messageId: string, detail?: CopilotFeedbackDetail) => {\n\t\tsetDislikePromptId((current) => (current === messageId ? null : current));\n\t\tonFeedback?.(messageId, 'dislike', detail);\n\t};\n\n\tconst handleRegenerate = () => {\n\t\tif (inputDisabled || isTurnInFlight) {\n\t\t\treturn;\n\t\t}\n\t\tonRegenerate?.();\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\tconst sentAt =\n\t\t\t\t\t\t\t\t\tmessage.role === 'user'\n\t\t\t\t\t\t\t\t\t\t? formatMessageTime(message.timestamp)\n\t\t\t\t\t\t\t\t\t\t: '';\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<React.Fragment key={message.id}>\n\t\t\t\t\t\t\t\t\t\t{message.content.length > 0 && (\n\t\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\t{message.role === 'assistant' ? (\n\t\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\t\tdangerouslySetInnerHTML={{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t__html: renderCopilotMarkdown(message.content),\n\t\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\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\t\t<div style={{ whiteSpace: 'pre-wrap' }}>\n\t\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\t</div>\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</MessageBubble>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{/* Tool CTAs (e.g. the support-portal link) — only once the\n\t\t\t\t\t\t\t\t\t\t reply has finished, so a button cannot flash mid-stream. */}\n\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!message.isStreaming &&\n\t\t\t\t\t\t\t\t\t\t\t(() => {\n\t\t\t\t\t\t\t\t\t\t\t\tconst ctas = toolResultCtas(message.toolResults);\n\t\t\t\t\t\t\t\t\t\t\t\tif (ctas.length === 0) {\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn null;\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\treturn (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<ToolCtaList>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ctas.map((cta) => (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<ToolCtaLink\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tkey={`${cta.tool}-${cta.url}`}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thref={cta.url}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonToolCtaClick?.({\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttool: cta.tool,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\turl: cta.url,\n\t\t\t\t\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\t\t\t\t}\n\t\t\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\t\t\t\t{cta.label}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</ToolCtaLink>\n\t\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\t</ToolCtaList>\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{sentAt && <MessageTimestamp>{sentAt}</MessageTimestamp>}\n\t\t\t\t\t\t\t\t\t\t{message.wasInterrupted && interruptedLabel && (\n\t\t\t\t\t\t\t\t\t\t\t<InterruptedNote>\n\t\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\t{interruptedLabel}\n\t\t\t\t\t\t\t\t\t\t\t</InterruptedNote>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{/* Only under a finished reply: mid-stream the text is still\n\t\t\t\t\t\t\t\t\t\t changing, so copying it would capture a partial answer. */}\n\t\t\t\t\t\t\t\t\t\t{message.role === 'assistant' &&\n\t\t\t\t\t\t\t\t\t\t\tmessage.content.length > 0 &&\n\t\t\t\t\t\t\t\t\t\t\t!message.isStreaming && (\n\t\t\t\t\t\t\t\t\t\t\t\t<MessageActions>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<MessageAction\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => void handleCopyMessage(message)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata-copied={copiedMessageId === message.id}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle={\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcopiedMessageId === message.id ? 'Copied' : 'Copy'\n\t\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\t\taria-label={\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcopiedMessageId === message.id\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? 'Response copied to clipboard'\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: 'Copy response'\n\t\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\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{copiedMessageId === message.id ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<CheckIcon />\n\t\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\t\t\t<CopyIcon />\n\t\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\t</MessageAction>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{/* Only under the newest reply: regenerating appends a\n\t\t\t\t\t\t\t\t\t\t\t\t\t fresh turn at the end, so offering it against an\n\t\t\t\t\t\t\t\t\t\t\t\t\t older answer would not replace that answer. */}\n\t\t\t\t\t\t\t\t\t\t\t\t\t{onRegenerate && message.id === newestMessage?.id && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<MessageAction\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={handleRegenerate}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdisabled={inputDisabled || isTurnInFlight}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle=\"Regenerate\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-label=\"Regenerate response\"\n\t\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\t\t\t<RegenerateIcon />\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</MessageAction>\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\t<MessageAction\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => handleFeedback(message.id, 'like')}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdata-selected={feedback[message.id] === 'like'}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-pressed={feedback[message.id] === 'like'}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle=\"Good response\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-label=\"Good response\"\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\t\t<ThumbUpIcon\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfilled={feedback[message.id] === 'like'}\n\t\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\t</MessageAction>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<MessageAction\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tonClick={() =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\thandleFeedback(message.id, 'dislike')\n\t\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\t\tdata-selected={feedback[message.id] === 'dislike'}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-pressed={feedback[message.id] === 'dislike'}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle=\"Bad response\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\taria-label=\"Bad response\"\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\t\t<ThumbDownIcon\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfilled={feedback[message.id] === 'dislike'}\n\t\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\t</MessageAction>\n\t\t\t\t\t\t\t\t\t\t\t\t</MessageActions>\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t{dislikePromptId === message.id && (\n\t\t\t\t\t\t\t\t\t\t\t<CopilotFeedbackModal\n\t\t\t\t\t\t\t\t\t\t\t\ttitle={dislikeTitle}\n\t\t\t\t\t\t\t\t\t\t\t\tsubtitle={dislikeSubtitle ?? `Help us improve ${title}`}\n\t\t\t\t\t\t\t\t\t\t\t\treasons={dislikeReasons}\n\t\t\t\t\t\t\t\t\t\t\t\tnotePlaceholder={dislikeNotePlaceholder}\n\t\t\t\t\t\t\t\t\t\t\t\tsubmitLabel={dislikeSubmitLabel}\n\t\t\t\t\t\t\t\t\t\t\t\tonSubmit={(detail) => reportDislike(message.id, detail)}\n\t\t\t\t\t\t\t\t\t\t\t\tonDismiss={() => reportDislike(message.id)}\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</React.Fragment>\n\t\t\t\t\t\t\t\t);\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<ArrowDownIcon width={16} height={16} />\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","COPIED_FEEDBACK_MS","writeToClipboard","text","textarea","copied","NEAR_TOP_TOLERANCE_PX","formatMessageTime","timestamp","date","SendArrowIcon","jsxs","jsx","ArrowRightIcon","StopIcon","size","CopyIcon","CheckIcon","RegenerateIcon","ThumbUpIcon","filled","ThumbDownIcon","CopilotPanel","messages","onSend","onClose","title","badge","subtitle","avatar","placeholder","disclaimer","emptyStateTitle","emptyStateSubtitle","suggestions","onSuggestionClick","showRefresh","onRefresh","onRegenerate","onFeedback","dislikeTitle","dislikeSubtitle","dislikeReasons","dislikeNotePlaceholder","dislikeSubmitLabel","isThinking","thinkingLabel","isStreaming","onStop","interruptedLabel","followUpsLabel","onToolCtaClick","hasMoreHistory","isLoadingHistory","onLoadOlderMessages","historyLoadingLabel","inputDisabled","errorMessage","width","height","className","style","input","setInput","useState","isInputFocused","setIsInputFocused","isAtLatest","setIsAtLatest","copiedMessageId","setCopiedMessageId","feedback","setFeedback","dislikePromptId","setDislikePromptId","inputRef","useRef","copiedTimeoutRef","bottomRef","scrollerRef","lastScrollTopRef","anchorFromBottomRef","visibleMessages","message","isCopilotRegeneratePrompt","isEmpty","isTurnInFlight","canSend","canStop","newestMessage","followUps","showScrollAffordance","useEffect","scroller","anchor","handleScroll","distanceFromBottom","scrolledUp","handleJumpToLatest","handleCopyMessage","handleFeedback","messageId","vote","cleared","previous","current","reportDislike","detail","handleRegenerate","handleSend","trimmed","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","sentAt","React","MessageBubble","renderCopilotMarkdown","ctas","toolResultCtas","ToolCtaList","cta","ToolCtaLink","MessageTimestamp","InterruptedNote","MessageActions","MessageAction","CopilotFeedbackModal","FollowUpList","FollowUpsLabel","FollowUpChip","ThinkingBubble","ThinkingLabel","ScrollFade","JumpToLatestButton","ArrowDownIcon","ErrorBanner","InputArea","InputWrapper","MessageInput","SendButton","Disclaimer"],"mappings":"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"}
|