@cossistant/react 0.0.14 → 0.0.16
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/hooks/index.d.ts +2 -1
- package/hooks/index.js +2 -1
- package/hooks/use-home-page.js +1 -1
- package/hooks/use-home-page.js.map +1 -1
- package/hooks/use-scroll-mask.d.ts +24 -0
- package/hooks/use-scroll-mask.d.ts.map +1 -0
- package/hooks/use-scroll-mask.js +90 -0
- package/hooks/use-scroll-mask.js.map +1 -0
- package/hooks/use-send-message.js +1 -1
- package/hooks/use-send-message.js.map +1 -1
- package/index.d.ts +7 -2
- package/index.js +9 -5
- package/package.json +3 -3
- package/parse.d.ts.map +1 -1
- package/primitives/avatar/image.d.ts +1 -1
- package/primitives/bubble.d.ts +10 -2
- package/primitives/bubble.d.ts.map +1 -1
- package/primitives/bubble.js +11 -3
- package/primitives/bubble.js.map +1 -1
- package/primitives/conversation-timeline.d.ts.map +1 -1
- package/primitives/conversation-timeline.js +10 -20
- package/primitives/conversation-timeline.js.map +1 -1
- package/primitives/index.d.ts +5 -2
- package/primitives/index.js +11 -3
- package/primitives/index.parts.d.ts +4 -1
- package/primitives/index.parts.js +5 -2
- package/primitives/page-registry.d.ts +30 -0
- package/primitives/page-registry.d.ts.map +1 -0
- package/primitives/page-registry.js +45 -0
- package/primitives/page-registry.js.map +1 -0
- package/primitives/page.d.ts +21 -0
- package/primitives/page.d.ts.map +1 -0
- package/primitives/page.js +18 -0
- package/primitives/page.js.map +1 -0
- package/primitives/router.d.ts +35 -0
- package/primitives/router.d.ts.map +1 -0
- package/primitives/router.js +22 -0
- package/primitives/router.js.map +1 -0
- package/primitives/window.d.ts +8 -3
- package/primitives/window.d.ts.map +1 -1
- package/primitives/window.js +8 -3
- package/primitives/window.js.map +1 -1
- package/realtime/index.js +1 -1
- package/realtime/provider.js +1 -1
- package/realtime/support-provider.js +0 -4
- package/realtime/support-provider.js.map +1 -1
- package/realtime-events.d.ts +1 -1
- package/schemas2.d.ts.map +1 -1
- package/support/components/avatar-stack.js +1 -1
- package/support/components/avatar-stack.js.map +1 -1
- package/support/components/bubble.js +1 -1
- package/support/components/bubble.js.map +1 -1
- package/support/components/button.d.ts +1 -1
- package/support/components/button.js +3 -3
- package/support/components/button.js.map +1 -1
- package/support/components/container.js +1 -1
- package/support/components/container.js.map +1 -1
- package/support/components/conversation-timeline.js +1 -1
- package/support/components/conversation-timeline.js.map +1 -1
- package/support/components/multimodal-input.js +2 -2
- package/support/components/multimodal-input.js.map +1 -1
- package/support/components/support-content.d.ts +5 -7
- package/support/components/support-content.d.ts.map +1 -1
- package/support/components/support-content.js +9 -11
- package/support/components/support-content.js.map +1 -1
- package/support/components/theme-wrapper.d.ts +15 -0
- package/support/components/theme-wrapper.d.ts.map +1 -0
- package/support/components/theme-wrapper.js +18 -0
- package/support/components/theme-wrapper.js.map +1 -0
- package/support/components/timeline-identification-tool.js +2 -2
- package/support/components/timeline-identification-tool.js.map +1 -1
- package/support/components/watermark.js +2 -2
- package/support/components/watermark.js.map +1 -1
- package/support/index.d.ts +36 -6
- package/support/index.d.ts.map +1 -1
- package/support/index.js +43 -20
- package/support/index.js.map +1 -1
- package/support/pages/articles.d.ts +4 -1
- package/support/pages/articles.d.ts.map +1 -1
- package/support/pages/articles.js +1 -1
- package/support/pages/articles.js.map +1 -1
- package/support/pages/conversation-history.d.ts +5 -10
- package/support/pages/conversation-history.d.ts.map +1 -1
- package/support/pages/conversation-history.js +2 -9
- package/support/pages/conversation-history.js.map +1 -1
- package/support/pages/conversation.d.ts +17 -12
- package/support/pages/conversation.d.ts.map +1 -1
- package/support/pages/conversation.js +5 -2
- package/support/pages/conversation.js.map +1 -1
- package/support/pages/home.d.ts +5 -12
- package/support/pages/home.d.ts.map +1 -1
- package/support/pages/home.js +3 -12
- package/support/pages/home.js.map +1 -1
- package/support/router.d.ts +9 -4
- package/support/router.d.ts.map +1 -1
- package/support/router.js +34 -15
- package/support/router.js.map +1 -1
- package/support/store/support-store.d.ts +17 -14
- package/support/store/support-store.d.ts.map +1 -1
- package/support/store/support-store.js +13 -10
- package/support/store/support-store.js.map +1 -1
- package/support/{support-D0JydWRx.css → support-BQhCt9Za.css} +10 -9
- package/support/support-BQhCt9Za.css.map +1 -0
- package/support/types.d.ts +28 -0
- package/support/types.d.ts.map +1 -0
- package/support/types.js +1 -0
- package/support.css +1 -1
- package/tailwind.css +9 -8
- package/utils/conversation.d.ts.map +1 -1
- package/utils/conversation.js +3 -1
- package/utils/conversation.js.map +1 -1
- package/utils/use-render-element.d.ts.map +1 -1
- package/zod-extensions.d.ts.map +1 -1
- package/index4.d.ts +0 -18
- package/index4.d.ts.map +0 -1
- package/index5.d.ts +0 -999
- package/index5.d.ts.map +0 -1
- package/index6.d.ts +0 -6
- package/react.d.ts +0 -4
- package/support/components/text-effect.d.ts +0 -53
- package/support/components/text-effect.d.ts.map +0 -1
- package/support/components/text-effect.js +0 -225
- package/support/components/text-effect.js.map +0 -1
- package/support/support-D0JydWRx.css.map +0 -1
- package/types.d-BJcRxCew.d.ts +0 -39
- package/types.d-BJcRxCew.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-timeline.js","names":["EMPTY_SEEN_BY_IDS: readonly string[]","EMPTY_SEEN_BY_NAMES: readonly string[]","ConversationTimelineList: React.FC<ConversationTimelineProps>","names: string[]","PrimitiveConversationTimeline"],"sources":["../../../src/support/components/conversation-timeline.tsx"],"sourcesContent":["import type { AvailableAIAgent, AvailableHumanAgent } from \"@cossistant/types\";\nimport type {\n\tTimelineItem,\n\tTimelinePartEvent,\n} from \"@cossistant/types/api/timeline-item\";\nimport type React from \"react\";\nimport { useCallback, useMemo } from \"react\";\nimport { useConversationTimeline } from \"../../hooks/use-conversation-timeline\";\nimport {\n\tConversationTimelineContainer,\n\tConversationTimeline as PrimitiveConversationTimeline,\n} from \"../../primitives/conversation-timeline\";\nimport { cn } from \"../utils\";\nimport { ConversationEvent } from \"./conversation-event\";\nimport { TimelineMessageGroup } from \"./timeline-message-group\";\nimport { TypingIndicator, type TypingParticipant } from \"./typing-indicator\";\n\n// Helper to extract event part from timeline item\nfunction extractEventPart(item: TimelineItem): TimelinePartEvent | null {\n\tif (item.type !== \"event\") {\n\t\treturn null;\n\t}\n\n\tconst eventPart = item.parts.find(\n\t\t(part): part is TimelinePartEvent => part.type === \"event\"\n\t);\n\n\treturn eventPart || null;\n}\n\nconst EMPTY_SEEN_BY_IDS: readonly string[] = Object.freeze([]);\nconst EMPTY_SEEN_BY_NAMES: readonly string[] = Object.freeze([]);\n\nexport type ConversationTimelineToolProps = {\n\titem: TimelineItem;\n\tconversationId: string;\n};\n\nexport type ConversationTimelineToolDefinition = {\n\tcomponent: React.ComponentType<ConversationTimelineToolProps>;\n};\n\nexport type ConversationTimelineTools = Record<\n\tstring,\n\tConversationTimelineToolDefinition\n>;\n\nexport type ConversationTimelineProps = {\n\tconversationId: string;\n\titems: TimelineItem[];\n\tclassName?: string;\n\tavailableAIAgents: AvailableAIAgent[];\n\tavailableHumanAgents: AvailableHumanAgent[];\n\tcurrentVisitorId?: string;\n\ttools?: ConversationTimelineTools;\n};\n\nexport const ConversationTimelineList: React.FC<ConversationTimelineProps> = ({\n\tconversationId,\n\titems: timelineItems,\n\tclassName,\n\tavailableAIAgents = [],\n\tavailableHumanAgents = [],\n\tcurrentVisitorId,\n\ttools,\n}) => {\n\tconst timeline = useConversationTimeline({\n\t\tconversationId,\n\t\titems: timelineItems,\n\t\tcurrentVisitorId,\n\t});\n\n\tconst typingIndicatorParticipants = useMemo(\n\t\t() =>\n\t\t\ttimeline.typingParticipants.map<TypingParticipant>((participant) => ({\n\t\t\t\tid: participant.id,\n\t\t\t\ttype: participant.type,\n\t\t\t})),\n\t\t[timeline.typingParticipants]\n\t);\n\n\tconst seenNameLookup = useMemo(() => {\n\t\tconst map = new Map<string, string>();\n\n\t\tfor (const agent of availableHumanAgents) {\n\t\t\tif (agent.name) {\n\t\t\t\tmap.set(agent.id, agent.name);\n\t\t\t}\n\t\t}\n\n\t\tfor (const agent of availableAIAgents) {\n\t\t\tif (agent.name) {\n\t\t\t\tmap.set(agent.id, agent.name);\n\t\t\t}\n\t\t}\n\n\t\treturn map;\n\t}, [availableHumanAgents, availableAIAgents]);\n\n\tconst getSeenByNames = useCallback(\n\t\t(ids: readonly string[] = EMPTY_SEEN_BY_IDS): readonly string[] => {\n\t\t\tif (ids.length === 0 || seenNameLookup.size === 0) {\n\t\t\t\treturn EMPTY_SEEN_BY_NAMES;\n\t\t\t}\n\n\t\t\tconst uniqueNames = new Set<string>();\n\t\t\tconst names: string[] = [];\n\n\t\t\tfor (const id of ids) {\n\t\t\t\tconst name = seenNameLookup.get(id);\n\t\t\t\tif (!name || uniqueNames.has(name)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tuniqueNames.add(name);\n\t\t\t\tnames.push(name);\n\t\t\t}\n\n\t\t\tif (names.length === 0) {\n\t\t\t\treturn EMPTY_SEEN_BY_NAMES;\n\t\t\t}\n\n\t\t\treturn Object.freeze(names);\n\t\t},\n\t\t[seenNameLookup]\n\t);\n\n\treturn (\n\t\t<PrimitiveConversationTimeline\n\t\t\tautoScroll={true}\n\t\t\tclassName={cn(\n\t\t\t\t\"overflow-y-
|
|
1
|
+
{"version":3,"file":"conversation-timeline.js","names":["EMPTY_SEEN_BY_IDS: readonly string[]","EMPTY_SEEN_BY_NAMES: readonly string[]","ConversationTimelineList: React.FC<ConversationTimelineProps>","names: string[]","PrimitiveConversationTimeline"],"sources":["../../../src/support/components/conversation-timeline.tsx"],"sourcesContent":["import type { AvailableAIAgent, AvailableHumanAgent } from \"@cossistant/types\";\nimport type {\n\tTimelineItem,\n\tTimelinePartEvent,\n} from \"@cossistant/types/api/timeline-item\";\nimport type React from \"react\";\nimport { useCallback, useMemo } from \"react\";\nimport { useConversationTimeline } from \"../../hooks/use-conversation-timeline\";\nimport {\n\tConversationTimelineContainer,\n\tConversationTimeline as PrimitiveConversationTimeline,\n} from \"../../primitives/conversation-timeline\";\nimport { cn } from \"../utils\";\nimport { ConversationEvent } from \"./conversation-event\";\nimport { TimelineMessageGroup } from \"./timeline-message-group\";\nimport { TypingIndicator, type TypingParticipant } from \"./typing-indicator\";\n\n// Helper to extract event part from timeline item\nfunction extractEventPart(item: TimelineItem): TimelinePartEvent | null {\n\tif (item.type !== \"event\") {\n\t\treturn null;\n\t}\n\n\tconst eventPart = item.parts.find(\n\t\t(part): part is TimelinePartEvent => part.type === \"event\"\n\t);\n\n\treturn eventPart || null;\n}\n\nconst EMPTY_SEEN_BY_IDS: readonly string[] = Object.freeze([]);\nconst EMPTY_SEEN_BY_NAMES: readonly string[] = Object.freeze([]);\n\nexport type ConversationTimelineToolProps = {\n\titem: TimelineItem;\n\tconversationId: string;\n};\n\nexport type ConversationTimelineToolDefinition = {\n\tcomponent: React.ComponentType<ConversationTimelineToolProps>;\n};\n\nexport type ConversationTimelineTools = Record<\n\tstring,\n\tConversationTimelineToolDefinition\n>;\n\nexport type ConversationTimelineProps = {\n\tconversationId: string;\n\titems: TimelineItem[];\n\tclassName?: string;\n\tavailableAIAgents: AvailableAIAgent[];\n\tavailableHumanAgents: AvailableHumanAgent[];\n\tcurrentVisitorId?: string;\n\ttools?: ConversationTimelineTools;\n};\n\nexport const ConversationTimelineList: React.FC<ConversationTimelineProps> = ({\n\tconversationId,\n\titems: timelineItems,\n\tclassName,\n\tavailableAIAgents = [],\n\tavailableHumanAgents = [],\n\tcurrentVisitorId,\n\ttools,\n}) => {\n\tconst timeline = useConversationTimeline({\n\t\tconversationId,\n\t\titems: timelineItems,\n\t\tcurrentVisitorId,\n\t});\n\n\tconst typingIndicatorParticipants = useMemo(\n\t\t() =>\n\t\t\ttimeline.typingParticipants.map<TypingParticipant>((participant) => ({\n\t\t\t\tid: participant.id,\n\t\t\t\ttype: participant.type,\n\t\t\t})),\n\t\t[timeline.typingParticipants]\n\t);\n\n\tconst seenNameLookup = useMemo(() => {\n\t\tconst map = new Map<string, string>();\n\n\t\tfor (const agent of availableHumanAgents) {\n\t\t\tif (agent.name) {\n\t\t\t\tmap.set(agent.id, agent.name);\n\t\t\t}\n\t\t}\n\n\t\tfor (const agent of availableAIAgents) {\n\t\t\tif (agent.name) {\n\t\t\t\tmap.set(agent.id, agent.name);\n\t\t\t}\n\t\t}\n\n\t\treturn map;\n\t}, [availableHumanAgents, availableAIAgents]);\n\n\tconst getSeenByNames = useCallback(\n\t\t(ids: readonly string[] = EMPTY_SEEN_BY_IDS): readonly string[] => {\n\t\t\tif (ids.length === 0 || seenNameLookup.size === 0) {\n\t\t\t\treturn EMPTY_SEEN_BY_NAMES;\n\t\t\t}\n\n\t\t\tconst uniqueNames = new Set<string>();\n\t\t\tconst names: string[] = [];\n\n\t\t\tfor (const id of ids) {\n\t\t\t\tconst name = seenNameLookup.get(id);\n\t\t\t\tif (!name || uniqueNames.has(name)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tuniqueNames.add(name);\n\t\t\t\tnames.push(name);\n\t\t\t}\n\n\t\t\tif (names.length === 0) {\n\t\t\t\treturn EMPTY_SEEN_BY_NAMES;\n\t\t\t}\n\n\t\t\treturn Object.freeze(names);\n\t\t},\n\t\t[seenNameLookup]\n\t);\n\n\treturn (\n\t\t<PrimitiveConversationTimeline\n\t\t\tautoScroll={true}\n\t\t\tclassName={cn(\n\t\t\t\t\"overflow-y-scroll scroll-smooth px-3 py-6\",\n\t\t\t\t\"scrollbar-thin scrollbar-thumb-co-primary/30 scrollbar-track-transparent\",\n\t\t\t\t\"h-full w-full\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\tid=\"conversation-timeline\"\n\t\t\titems={timelineItems}\n\t\t>\n\t\t\t<ConversationTimelineContainer className=\"flex min-h-full w-full flex-col gap-3\">\n\t\t\t\t{timeline.groupedMessages.items.map((item, index) => {\n\t\t\t\t\tif (item.type === \"timeline_event\") {\n\t\t\t\t\t\t// Extract event data from parts\n\t\t\t\t\t\tconst eventPart = extractEventPart(item.item);\n\n\t\t\t\t\t\t// Only render if we have valid event data\n\t\t\t\t\t\tif (!eventPart) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<ConversationEvent\n\t\t\t\t\t\t\t\tavailableAIAgents={availableAIAgents}\n\t\t\t\t\t\t\t\tavailableHumanAgents={availableHumanAgents}\n\t\t\t\t\t\t\t\tcreatedAt={item.item.createdAt}\n\t\t\t\t\t\t\t\tevent={eventPart}\n\t\t\t\t\t\t\t\tkey={item.item.id ?? `timeline-event-${item.item.createdAt}`}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (item.type === \"timeline_tool\") {\n\t\t\t\t\t\tconst toolName = item.tool ?? item.item.tool ?? item.item.type;\n\t\t\t\t\t\tconst toolDefinition = toolName ? tools?.[toolName] : undefined;\n\n\t\t\t\t\t\tif (!toolDefinition) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst ToolComponent = toolDefinition.component;\n\n\t\t\t\t\t\tconst toolKey =\n\t\t\t\t\t\t\titem.item.id ?? `${toolName}-${item.item.createdAt}-${index}`;\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<ToolComponent\n\t\t\t\t\t\t\t\tconversationId={conversationId}\n\t\t\t\t\t\t\t\titem={item.item}\n\t\t\t\t\t\t\t\tkey={toolKey}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only show seen indicator on the LAST message group sent by the visitor\n\t\t\t\t\tconst isLastVisitorGroup =\n\t\t\t\t\t\tindex === timeline.lastVisitorMessageGroupIndex;\n\t\t\t\t\tconst seenByIds =\n\t\t\t\t\t\tisLastVisitorGroup && item.lastMessageId\n\t\t\t\t\t\t\t? timeline.groupedMessages.getMessageSeenBy(item.lastMessageId)\n\t\t\t\t\t\t\t: EMPTY_SEEN_BY_IDS;\n\t\t\t\t\tconst seenByNames =\n\t\t\t\t\t\tseenByIds.length > 0\n\t\t\t\t\t\t\t? getSeenByNames(seenByIds)\n\t\t\t\t\t\t\t: EMPTY_SEEN_BY_NAMES;\n\n\t\t\t\t\t// Use first timeline item ID as stable key\n\t\t\t\t\tconst groupKey =\n\t\t\t\t\t\titem.lastMessageId ??\n\t\t\t\t\t\titem.items?.[0]?.id ??\n\t\t\t\t\t\t`group-${item.items?.[0]?.createdAt ?? index}`;\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<TimelineMessageGroup\n\t\t\t\t\t\t\tavailableAIAgents={availableAIAgents}\n\t\t\t\t\t\t\tavailableHumanAgents={availableHumanAgents}\n\t\t\t\t\t\t\tcurrentVisitorId={currentVisitorId}\n\t\t\t\t\t\t\titems={item.items || []}\n\t\t\t\t\t\t\tkey={groupKey}\n\t\t\t\t\t\t\tseenByIds={seenByIds}\n\t\t\t\t\t\t\tseenByNames={seenByNames}\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t\t<div className=\"h-6 w-full\">\n\t\t\t\t\t{typingIndicatorParticipants.length > 0 ? (\n\t\t\t\t\t\t<TypingIndicator\n\t\t\t\t\t\t\tavailableAIAgents={availableAIAgents}\n\t\t\t\t\t\t\tavailableHumanAgents={availableHumanAgents}\n\t\t\t\t\t\t\tclassName=\"mt-2\"\n\t\t\t\t\t\t\tparticipants={typingIndicatorParticipants}\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t</ConversationTimelineContainer>\n\t\t</PrimitiveConversationTimeline>\n\t);\n};\n"],"mappings":";;;;;;;;;;AAkBA,SAAS,iBAAiB,MAA8C;AACvE,KAAI,KAAK,SAAS,QACjB,QAAO;AAOR,QAJkB,KAAK,MAAM,MAC3B,SAAoC,KAAK,SAAS,QACnD,IAEmB;;AAGrB,MAAMA,oBAAuC,OAAO,OAAO,EAAE,CAAC;AAC9D,MAAMC,sBAAyC,OAAO,OAAO,EAAE,CAAC;AA0BhE,MAAaC,4BAAiE,EAC7E,gBACA,OAAO,eACP,WACA,oBAAoB,EAAE,EACtB,uBAAuB,EAAE,EACzB,kBACA,YACK;CACL,MAAM,WAAW,wBAAwB;EACxC;EACA,OAAO;EACP;EACA,CAAC;CAEF,MAAM,8BAA8B,cAElC,SAAS,mBAAmB,KAAwB,iBAAiB;EACpE,IAAI,YAAY;EAChB,MAAM,YAAY;EAClB,EAAE,EACJ,CAAC,SAAS,mBAAmB,CAC7B;CAED,MAAM,iBAAiB,cAAc;EACpC,MAAM,sBAAM,IAAI,KAAqB;AAErC,OAAK,MAAM,SAAS,qBACnB,KAAI,MAAM,KACT,KAAI,IAAI,MAAM,IAAI,MAAM,KAAK;AAI/B,OAAK,MAAM,SAAS,kBACnB,KAAI,MAAM,KACT,KAAI,IAAI,MAAM,IAAI,MAAM,KAAK;AAI/B,SAAO;IACL,CAAC,sBAAsB,kBAAkB,CAAC;CAE7C,MAAM,iBAAiB,aACrB,MAAyB,sBAAyC;AAClE,MAAI,IAAI,WAAW,KAAK,eAAe,SAAS,EAC/C,QAAO;EAGR,MAAM,8BAAc,IAAI,KAAa;EACrC,MAAMC,QAAkB,EAAE;AAE1B,OAAK,MAAM,MAAM,KAAK;GACrB,MAAM,OAAO,eAAe,IAAI,GAAG;AACnC,OAAI,CAAC,QAAQ,YAAY,IAAI,KAAK,CACjC;AAGD,eAAY,IAAI,KAAK;AACrB,SAAM,KAAK,KAAK;;AAGjB,MAAI,MAAM,WAAW,EACpB,QAAO;AAGR,SAAO,OAAO,OAAO,MAAM;IAE5B,CAAC,eAAe,CAChB;AAED,QACC,oBAACC;EACA,YAAY;EACZ,WAAW,GACV,6CACA,4EACA,iBACA,UACA;EACD,IAAG;EACH,OAAO;YAEP,qBAAC;GAA8B,WAAU;cACvC,SAAS,gBAAgB,MAAM,KAAK,MAAM,UAAU;AACpD,QAAI,KAAK,SAAS,kBAAkB;KAEnC,MAAM,YAAY,iBAAiB,KAAK,KAAK;AAG7C,SAAI,CAAC,UACJ,QAAO;AAGR,YACC,oBAAC;MACmB;MACG;MACtB,WAAW,KAAK,KAAK;MACrB,OAAO;QACF,KAAK,KAAK,MAAM,kBAAkB,KAAK,KAAK,YAChD;;AAIJ,QAAI,KAAK,SAAS,iBAAiB;KAClC,MAAM,WAAW,KAAK,QAAQ,KAAK,KAAK,QAAQ,KAAK,KAAK;KAC1D,MAAM,iBAAiB,WAAW,QAAQ,YAAY;AAEtD,SAAI,CAAC,eACJ,QAAO;KAGR,MAAM,gBAAgB,eAAe;KAErC,MAAM,UACL,KAAK,KAAK,MAAM,GAAG,SAAS,GAAG,KAAK,KAAK,UAAU,GAAG;AAEvD,YACC,oBAAC;MACgB;MAChB,MAAM,KAAK;QACN,QACJ;;IAOJ,MAAM,YADL,UAAU,SAAS,gCAEG,KAAK,gBACxB,SAAS,gBAAgB,iBAAiB,KAAK,cAAc,GAC7D;IACJ,MAAM,cACL,UAAU,SAAS,IAChB,eAAe,UAAU,GACzB;IAGJ,MAAM,WACL,KAAK,iBACL,KAAK,QAAQ,IAAI,MACjB,SAAS,KAAK,QAAQ,IAAI,aAAa;AAExC,WACC,oBAAC;KACmB;KACG;KACJ;KAClB,OAAO,KAAK,SAAS,EAAE;KAEZ;KACE;OAFR,SAGJ;KAEF,EACF,oBAAC;IAAI,WAAU;cACb,4BAA4B,SAAS,IACrC,oBAAC;KACmB;KACG;KACtB,WAAU;KACV,cAAc;MACb,GACC;KACC;IACyB;GACD"}
|
|
@@ -81,9 +81,9 @@ const MultimodalInput = ({ className, value, onChange, onSubmit, onFileSelect, p
|
|
|
81
81
|
}, `${file.name}-${index}`))
|
|
82
82
|
}),
|
|
83
83
|
/* @__PURE__ */ jsxs("div", {
|
|
84
|
-
className: "flex flex-col rounded border border-co-border
|
|
84
|
+
className: "group/multimodal-input flex flex-col rounded border border-co-border bg-co-background ring-offset-2 focus-within:ring-1 focus-within:ring-co-primary/10 dark:bg-co-background-200",
|
|
85
85
|
children: [/* @__PURE__ */ jsx(MultimodalInput$1, {
|
|
86
|
-
className: cn("flex-1 resize-none overflow-hidden p-3 text-co-foreground text-sm placeholder:text-co-primary/
|
|
86
|
+
className: cn("flex-1 resize-none overflow-hidden p-3 text-co-foreground text-sm placeholder:text-co-primary/50 focus-visible:outline-none", className),
|
|
87
87
|
disabled: disabled || isSubmitting,
|
|
88
88
|
error,
|
|
89
89
|
onChange,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multimodal-input.js","names":["MultimodalInput: React.FC<MultimodalInputProps>","Icon","Primitive.MultimodalInput","SendButton: React.FC<SendButtonProps>","Primitive.Button"],"sources":["../../../src/support/components/multimodal-input.tsx"],"sourcesContent":["\"use client\";\n\nimport type React from \"react\";\nimport { useRef } from \"react\";\nimport { useComposerRefocus } from \"../../hooks/use-composer-refocus\";\nimport * as Primitive from \"../../primitives\";\nimport { useSupportText } from \"../text\";\nimport { cn } from \"../utils\";\nimport Icon from \"./icons\";\nimport { Watermark } from \"./watermark\";\n\nexport type MultimodalInputProps = {\n\tclassName?: string;\n\tvalue: string;\n\tonChange: (value: string) => void;\n\tonSubmit: () => void;\n\tonFileSelect?: (files: File[]) => void;\n\tplaceholder?: string;\n\tdisabled?: boolean;\n\tisSubmitting?: boolean;\n\terror?: Error | null;\n\tfiles?: File[];\n\tonRemoveFile?: (index: number) => void;\n\tmaxFiles?: number;\n\tmaxFileSize?: number;\n\tallowedFileTypes?: string[];\n};\n\nexport const MultimodalInput: React.FC<MultimodalInputProps> = ({\n\tclassName,\n\tvalue,\n\tonChange,\n\tonSubmit,\n\tonFileSelect,\n\tplaceholder,\n\tdisabled = false,\n\tisSubmitting = false,\n\terror,\n\tfiles = [],\n\tonRemoveFile,\n\tmaxFiles = 5,\n\tmaxFileSize = 10 * 1024 * 1024, // 10MB\n\tallowedFileTypes = [\"image/*\", \"application/pdf\", \"text/*\"],\n}) => {\n\tconst fileInputRef = useRef<HTMLInputElement>(null);\n\tconst hasContent = value.trim().length > 0 || files.length > 0;\n\tconst { focusComposer, inputRef } = useComposerRefocus({\n\t\tdisabled,\n\t\thasContent,\n\t\tisSubmitting,\n\t});\n\tconst canSubmit = !(disabled || isSubmitting) && hasContent;\n\tconst text = useSupportText();\n\tconst resolvedPlaceholder =\n\t\tplaceholder ?? text(\"component.multimodalInput.placeholder\");\n\n\tconst handleSubmit = () => {\n\t\tif (!canSubmit) {\n\t\t\treturn;\n\t\t}\n\n\t\tonSubmit();\n\t\tfocusComposer();\n\t};\n\n\tconst handleFormSubmit = (e: React.FormEvent) => {\n\t\te.preventDefault();\n\t\thandleSubmit();\n\t};\n\n\tconst handleAttachClick = () => {\n\t\tif (files.length < maxFiles) {\n\t\t\tfileInputRef.current?.click();\n\t\t}\n\t};\n\n\tconst formatFileSize = (bytes: number) => {\n\t\tif (bytes < 1024) {\n\t\t\treturn `${bytes} B`;\n\t\t}\n\t\tif (bytes < 1024 * 1024) {\n\t\t\treturn `${(bytes / 1024).toFixed(1)} KB`;\n\t\t}\n\t\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n\t};\n\n\treturn (\n\t\t<form className=\"flex flex-col gap-2\" onSubmit={handleFormSubmit}>\n\t\t\t{/* Error message */}\n\t\t\t{error && (\n\t\t\t\t<div\n\t\t\t\t\tclassName=\"rounded-md bg-co-destructive-muted p-2 text-co-destructive text-xs\"\n\t\t\t\t\tid=\"multimodal-input-error\"\n\t\t\t\t>\n\t\t\t\t\t{error.message}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* File attachments */}\n\t\t\t{files.length > 0 && (\n\t\t\t\t<div className=\"flex flex-wrap gap-2 p-2\">\n\t\t\t\t\t{files.map((file, index) => (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName=\"flex items-center gap-2 rounded-md bg-co-muted px-2 py-1 text-xs\"\n\t\t\t\t\t\t\tkey={`${file.name}-${index}`}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Icon className=\"h-3 w-3\" name=\"attachment\" />\n\t\t\t\t\t\t\t<span className=\"max-w-[150px] truncate\">{file.name}</span>\n\t\t\t\t\t\t\t<span className=\"text-co-muted-foreground\">\n\t\t\t\t\t\t\t\t{formatFileSize(file.size)}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t{onRemoveFile && (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\taria-label={text(\"common.actions.removeFile\", {\n\t\t\t\t\t\t\t\t\t\tfileName: file.name,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\tclassName=\"ml-1 hover:text-co-destructive\"\n\t\t\t\t\t\t\t\t\tonClick={() => onRemoveFile(index)}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Icon className=\"h-3 w-3\" name=\"close\" />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Input area */}\n\t\t\t<div className=\"flex flex-col rounded border border-co-border
|
|
1
|
+
{"version":3,"file":"multimodal-input.js","names":["MultimodalInput: React.FC<MultimodalInputProps>","Icon","Primitive.MultimodalInput","SendButton: React.FC<SendButtonProps>","Primitive.Button"],"sources":["../../../src/support/components/multimodal-input.tsx"],"sourcesContent":["\"use client\";\n\nimport type React from \"react\";\nimport { useRef } from \"react\";\nimport { useComposerRefocus } from \"../../hooks/use-composer-refocus\";\nimport * as Primitive from \"../../primitives\";\nimport { useSupportText } from \"../text\";\nimport { cn } from \"../utils\";\nimport Icon from \"./icons\";\nimport { Watermark } from \"./watermark\";\n\nexport type MultimodalInputProps = {\n\tclassName?: string;\n\tvalue: string;\n\tonChange: (value: string) => void;\n\tonSubmit: () => void;\n\tonFileSelect?: (files: File[]) => void;\n\tplaceholder?: string;\n\tdisabled?: boolean;\n\tisSubmitting?: boolean;\n\terror?: Error | null;\n\tfiles?: File[];\n\tonRemoveFile?: (index: number) => void;\n\tmaxFiles?: number;\n\tmaxFileSize?: number;\n\tallowedFileTypes?: string[];\n};\n\nexport const MultimodalInput: React.FC<MultimodalInputProps> = ({\n\tclassName,\n\tvalue,\n\tonChange,\n\tonSubmit,\n\tonFileSelect,\n\tplaceholder,\n\tdisabled = false,\n\tisSubmitting = false,\n\terror,\n\tfiles = [],\n\tonRemoveFile,\n\tmaxFiles = 5,\n\tmaxFileSize = 10 * 1024 * 1024, // 10MB\n\tallowedFileTypes = [\"image/*\", \"application/pdf\", \"text/*\"],\n}) => {\n\tconst fileInputRef = useRef<HTMLInputElement>(null);\n\tconst hasContent = value.trim().length > 0 || files.length > 0;\n\tconst { focusComposer, inputRef } = useComposerRefocus({\n\t\tdisabled,\n\t\thasContent,\n\t\tisSubmitting,\n\t});\n\tconst canSubmit = !(disabled || isSubmitting) && hasContent;\n\tconst text = useSupportText();\n\tconst resolvedPlaceholder =\n\t\tplaceholder ?? text(\"component.multimodalInput.placeholder\");\n\n\tconst handleSubmit = () => {\n\t\tif (!canSubmit) {\n\t\t\treturn;\n\t\t}\n\n\t\tonSubmit();\n\t\tfocusComposer();\n\t};\n\n\tconst handleFormSubmit = (e: React.FormEvent) => {\n\t\te.preventDefault();\n\t\thandleSubmit();\n\t};\n\n\tconst handleAttachClick = () => {\n\t\tif (files.length < maxFiles) {\n\t\t\tfileInputRef.current?.click();\n\t\t}\n\t};\n\n\tconst formatFileSize = (bytes: number) => {\n\t\tif (bytes < 1024) {\n\t\t\treturn `${bytes} B`;\n\t\t}\n\t\tif (bytes < 1024 * 1024) {\n\t\t\treturn `${(bytes / 1024).toFixed(1)} KB`;\n\t\t}\n\t\treturn `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n\t};\n\n\treturn (\n\t\t<form className=\"flex flex-col gap-2\" onSubmit={handleFormSubmit}>\n\t\t\t{/* Error message */}\n\t\t\t{error && (\n\t\t\t\t<div\n\t\t\t\t\tclassName=\"rounded-md bg-co-destructive-muted p-2 text-co-destructive text-xs\"\n\t\t\t\t\tid=\"multimodal-input-error\"\n\t\t\t\t>\n\t\t\t\t\t{error.message}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* File attachments */}\n\t\t\t{files.length > 0 && (\n\t\t\t\t<div className=\"flex flex-wrap gap-2 p-2\">\n\t\t\t\t\t{files.map((file, index) => (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName=\"flex items-center gap-2 rounded-md bg-co-muted px-2 py-1 text-xs\"\n\t\t\t\t\t\t\tkey={`${file.name}-${index}`}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<Icon className=\"h-3 w-3\" name=\"attachment\" />\n\t\t\t\t\t\t\t<span className=\"max-w-[150px] truncate\">{file.name}</span>\n\t\t\t\t\t\t\t<span className=\"text-co-muted-foreground\">\n\t\t\t\t\t\t\t\t{formatFileSize(file.size)}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t{onRemoveFile && (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\taria-label={text(\"common.actions.removeFile\", {\n\t\t\t\t\t\t\t\t\t\tfileName: file.name,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\tclassName=\"ml-1 hover:text-co-destructive\"\n\t\t\t\t\t\t\t\t\tonClick={() => onRemoveFile(index)}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Icon className=\"h-3 w-3\" name=\"close\" />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Input area */}\n\t\t\t<div className=\"group/multimodal-input flex flex-col rounded border border-co-border bg-co-background ring-offset-2 focus-within:ring-1 focus-within:ring-co-primary/10 dark:bg-co-background-200\">\n\t\t\t\t<Primitive.MultimodalInput\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"flex-1 resize-none overflow-hidden p-3 text-co-foreground text-sm placeholder:text-co-primary/50 focus-visible:outline-none\",\n\t\t\t\t\t\tclassName\n\t\t\t\t\t)}\n\t\t\t\t\tdisabled={disabled || isSubmitting}\n\t\t\t\t\terror={error}\n\t\t\t\t\tonChange={onChange}\n\t\t\t\t\tonFileSelect={onFileSelect}\n\t\t\t\t\tonSubmit={handleSubmit}\n\t\t\t\t\tplaceholder={resolvedPlaceholder}\n\t\t\t\t\tref={inputRef}\n\t\t\t\t\tvalue={value}\n\t\t\t\t/>\n\n\t\t\t\t<div className=\"flex items-center justify-between py-1 pr-1 pl-3\">\n\t\t\t\t\t<Watermark />\n\n\t\t\t\t\t<div className=\"flex items-center gap-0.5\">\n\t\t\t\t\t\t{/* File attachment button */}\n\t\t\t\t\t\t{/* {onFileSelect && (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\taria-label={text(\"common.actions.attachFiles\")}\n\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\"group flex h-8 w-8 items-center justify-center rounded-md text-co-muted-foreground hover:bg-co-muted hover:text-co-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\t\t\t\t\t\t\t\tfiles.length >= maxFiles && \"opacity-50\"\n\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\tdisabled={\n\t\t\t\t\t\t\t\t\t\tdisabled || isSubmitting || files.length >= maxFiles\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tonClick={handleAttachClick}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Icon className=\"h-4 w-4\" name=\"attachment\" />\n\t\t\t\t\t\t\t\t</button>\n\n\t\t\t\t\t\t\t\t<Primitive.FileInput\n\t\t\t\t\t\t\t\t\taccept={allowedFileTypes.join(\",\")}\n\t\t\t\t\t\t\t\t\tclassName=\"hidden\"\n\t\t\t\t\t\t\t\t\tdisabled={\n\t\t\t\t\t\t\t\t\t\tdisabled || isSubmitting || files.length >= maxFiles\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tonFileSelect={onFileSelect}\n\t\t\t\t\t\t\t\t\tref={fileInputRef}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)} */}\n\n\t\t\t\t\t\t{/* Send button */}\n\t\t\t\t\t\t<SendButton disabled={!canSubmit} />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</form>\n\t);\n};\n\nexport type SendButtonProps = {\n\tclassName?: string;\n\tdisabled?: boolean;\n};\n\nexport const SendButton: React.FC<SendButtonProps> = ({\n\tclassName,\n\tdisabled = false,\n}) => (\n\t<Primitive.Button\n\t\tclassName={cn(\n\t\t\t\"group flex h-8 w-8 items-center justify-center rounded-md text-co-primary hover:bg-co-muted disabled:cursor-not-allowed disabled:opacity-50\",\n\t\t\tclassName\n\t\t)}\n\t\tdisabled={disabled}\n\t\ttype=\"submit\"\n\t>\n\t\t<Icon className=\"h-4 w-4\" filledOnHover name=\"send\" />\n\t</Primitive.Button>\n);\n"],"mappings":";;;;;;;;;;;;;;AA4BA,MAAaA,mBAAmD,EAC/D,WACA,OACA,UACA,UACA,cACA,aACA,WAAW,OACX,eAAe,OACf,OACA,QAAQ,EAAE,EACV,cACA,WAAW,GACX,cAAc,KAAK,OAAO,MAC1B,mBAAmB;CAAC;CAAW;CAAmB;CAAS,OACtD;AACgB,QAAyB,KAAK;CACnD,MAAM,aAAa,MAAM,MAAM,CAAC,SAAS,KAAK,MAAM,SAAS;CAC7D,MAAM,EAAE,eAAe,aAAa,mBAAmB;EACtD;EACA;EACA;EACA,CAAC;CACF,MAAM,YAAY,EAAE,YAAY,iBAAiB;CACjD,MAAM,OAAO,gBAAgB;CAC7B,MAAM,sBACL,eAAe,KAAK,wCAAwC;CAE7D,MAAM,qBAAqB;AAC1B,MAAI,CAAC,UACJ;AAGD,YAAU;AACV,iBAAe;;CAGhB,MAAM,oBAAoB,MAAuB;AAChD,IAAE,gBAAgB;AAClB,gBAAc;;CASf,MAAM,kBAAkB,UAAkB;AACzC,MAAI,QAAQ,KACX,QAAO,GAAG,MAAM;AAEjB,MAAI,QAAQ,OAAO,KAClB,QAAO,IAAI,QAAQ,MAAM,QAAQ,EAAE,CAAC;AAErC,SAAO,IAAI,SAAS,OAAO,OAAO,QAAQ,EAAE,CAAC;;AAG9C,QACC,qBAAC;EAAK,WAAU;EAAsB,UAAU;;GAE9C,SACA,oBAAC;IACA,WAAU;IACV,IAAG;cAEF,MAAM;KACF;GAIN,MAAM,SAAS,KACf,oBAAC;IAAI,WAAU;cACb,MAAM,KAAK,MAAM,UACjB,qBAAC;KACA,WAAU;;MAGV,oBAACC;OAAK,WAAU;OAAU,MAAK;QAAe;MAC9C,oBAAC;OAAK,WAAU;iBAA0B,KAAK;QAAY;MAC3D,oBAAC;OAAK,WAAU;iBACd,eAAe,KAAK,KAAK;QACpB;MACN,gBACA,oBAAC;OACA,cAAY,KAAK,6BAA6B,EAC7C,UAAU,KAAK,MACf,CAAC;OACF,WAAU;OACV,eAAe,aAAa,MAAM;OAClC,MAAK;iBAEL,oBAACA;QAAK,WAAU;QAAU,MAAK;SAAU;QACjC;;OAjBL,GAAG,KAAK,KAAK,GAAG,QAmBhB,CACL;KACG;GAIP,qBAAC;IAAI,WAAU;eACd,oBAACC;KACA,WAAW,GACV,+HACA,UACA;KACD,UAAU,YAAY;KACf;KACG;KACI;KACd,UAAU;KACV,aAAa;KACb,KAAK;KACE;MACN,EAEF,qBAAC;KAAI,WAAU;gBACd,oBAAC,cAAY,EAEb,oBAAC;MAAI,WAAU;gBAgCd,oBAAC,cAAW,UAAU,CAAC,YAAa;OAC/B;MACD;KACD;;GACA;;AAST,MAAaC,cAAyC,EACrD,WACA,WAAW,YAEX,oBAACC;CACA,WAAW,GACV,+IACA,UACA;CACS;CACV,MAAK;WAEL,oBAACH;EAAK,WAAU;EAAU;EAAc,MAAK;GAAS;EACpC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SupportProps } from "../index.js";
|
|
1
2
|
import React from "react";
|
|
2
3
|
|
|
3
4
|
//#region src/support/components/support-content.d.ts
|
|
@@ -6,15 +7,12 @@ type SupportContentProps = {
|
|
|
6
7
|
position?: "top" | "bottom";
|
|
7
8
|
align?: "right" | "left";
|
|
8
9
|
positioning?: "fixed" | "absolute";
|
|
10
|
+
slots?: SupportProps["slots"];
|
|
11
|
+
classNames?: SupportProps["classNames"];
|
|
12
|
+
children?: React.ReactNode;
|
|
9
13
|
};
|
|
10
14
|
/**
|
|
11
|
-
* Main support widget
|
|
12
|
-
*
|
|
13
|
-
* Handles the layout and positioning of the support widget,
|
|
14
|
-
* and renders the appropriate page via SupportRouter.
|
|
15
|
-
*
|
|
16
|
-
* Each page (e.g., conversation, home) manages its own state internally,
|
|
17
|
-
* so this component is purely presentational.
|
|
15
|
+
* Main support widget container handling layout, positioning, and routing.
|
|
18
16
|
*/
|
|
19
17
|
declare const SupportContent: React.FC<SupportContentProps>;
|
|
20
18
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"support-content.d.ts","names":[],"sources":["../../../src/support/components/support-content.tsx"],"sourcesContent":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"support-content.d.ts","names":[],"sources":["../../../src/support/components/support-content.tsx"],"sourcesContent":[],"mappings":";;;;KAWK,mBAAA;;EAAA,QAAA,CAAA,EAAA,KAAA,GAAA,QAAmB;EAKf,KAAA,CAAA,EAAA,OAAA,GAAA,MAAA;EACK,WAAA,CAAA,EAAA,OAAA,GAAA,UAAA;EACF,KAAM,CAAA,EAFT,YAES,CAAA,OAAA,CAAA;EAAS,UAAA,CAAA,EADb,YACa,CAAA,YAAA,CAAA;EAMd,QAAA,CAAA,EAND,KAAA,CAAM,SAwDjB;;;;;cAlDY,gBAAgB,KAAA,CAAM,GAAG"}
|
|
@@ -10,21 +10,18 @@ import { motion } from "motion/react";
|
|
|
10
10
|
|
|
11
11
|
//#region src/support/components/support-content.tsx
|
|
12
12
|
/**
|
|
13
|
-
* Main support widget
|
|
14
|
-
*
|
|
15
|
-
* Handles the layout and positioning of the support widget,
|
|
16
|
-
* and renders the appropriate page via SupportRouter.
|
|
17
|
-
*
|
|
18
|
-
* Each page (e.g., conversation, home) manages its own state internally,
|
|
19
|
-
* so this component is purely presentational.
|
|
13
|
+
* Main support widget container handling layout, positioning, and routing.
|
|
20
14
|
*/
|
|
21
|
-
const SupportContent = ({ className, position = "bottom", align = "right", positioning = "fixed" }) => {
|
|
15
|
+
const SupportContent = ({ className, position = "bottom", align = "right", positioning = "fixed", slots = {}, classNames = {}, children }) => {
|
|
16
|
+
const BubbleComponent = slots.bubble ?? Bubble;
|
|
17
|
+
const ContainerComponent = slots.container ?? Container;
|
|
18
|
+
const RouterComponent = slots.router ?? SupportRouter;
|
|
22
19
|
const containerClasses = cn("cossistant z-[9999]", positioning === "fixed" ? "fixed" : "absolute", {
|
|
23
20
|
"bottom-4": position === "bottom",
|
|
24
21
|
"top-4": position === "top",
|
|
25
22
|
"right-4": align === "right",
|
|
26
23
|
"left-4": align === "left"
|
|
27
|
-
}, className);
|
|
24
|
+
}, classNames.root, className);
|
|
28
25
|
return /* @__PURE__ */ jsxs(motion.div, {
|
|
29
26
|
animate: { opacity: 1 },
|
|
30
27
|
className: containerClasses,
|
|
@@ -34,10 +31,11 @@ const SupportContent = ({ className, position = "bottom", align = "right", posit
|
|
|
34
31
|
default: { ease: "anticipate" },
|
|
35
32
|
layout: { duration: .3 }
|
|
36
33
|
},
|
|
37
|
-
children: [/* @__PURE__ */ jsx(
|
|
34
|
+
children: [/* @__PURE__ */ jsx(BubbleComponent, { className: cn("z-[1000] md:z-[9999]", classNames.bubble) }), /* @__PURE__ */ jsx(ContainerComponent, {
|
|
38
35
|
align,
|
|
36
|
+
className: classNames.container,
|
|
39
37
|
position,
|
|
40
|
-
children: /* @__PURE__ */ jsx(
|
|
38
|
+
children: /* @__PURE__ */ jsx(RouterComponent, { children })
|
|
41
39
|
})]
|
|
42
40
|
});
|
|
43
41
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"support-content.js","names":["SupportContent: React.FC<SupportContentProps>"],"sources":["../../../src/support/components/support-content.tsx"],"sourcesContent":["\"use client\";\n\nimport { motion } from \"motion/react\";\nimport type React from \"react\";\n\nimport { SupportRouter } from \"../router\";\nimport { cn } from \"../utils\";\nimport { Bubble } from \"./bubble\";\nimport { Container } from \"./container\";\n\ntype SupportContentProps = {\n\tclassName?: string;\n\tposition?: \"top\" | \"bottom\";\n\talign?: \"right\" | \"left\";\n\tpositioning?: \"fixed\" | \"absolute\";\n};\n\n/**\n * Main support widget
|
|
1
|
+
{"version":3,"file":"support-content.js","names":["SupportContent: React.FC<SupportContentProps>"],"sources":["../../../src/support/components/support-content.tsx"],"sourcesContent":["\"use client\";\n\nimport { motion } from \"motion/react\";\nimport type React from \"react\";\n\nimport type { SupportProps } from \"../index\";\nimport { SupportRouter } from \"../router\";\nimport { cn } from \"../utils\";\nimport { Bubble } from \"./bubble\";\nimport { Container } from \"./container\";\n\ntype SupportContentProps = {\n\tclassName?: string;\n\tposition?: \"top\" | \"bottom\";\n\talign?: \"right\" | \"left\";\n\tpositioning?: \"fixed\" | \"absolute\";\n\tslots?: SupportProps[\"slots\"];\n\tclassNames?: SupportProps[\"classNames\"];\n\tchildren?: React.ReactNode;\n};\n\n/**\n * Main support widget container handling layout, positioning, and routing.\n */\nexport const SupportContent: React.FC<SupportContentProps> = ({\n\tclassName,\n\tposition = \"bottom\",\n\talign = \"right\",\n\tpositioning = \"fixed\",\n\tslots = {},\n\tclassNames = {},\n\tchildren,\n}) => {\n\t// Use custom components if provided, otherwise use defaults\n\tconst BubbleComponent = slots.bubble ?? Bubble;\n\tconst ContainerComponent = slots.container ?? Container;\n\tconst RouterComponent = slots.router ?? SupportRouter;\n\n\tconst containerClasses = cn(\n\t\t\"cossistant z-[9999]\",\n\t\tpositioning === \"fixed\" ? \"fixed\" : \"absolute\",\n\t\t{\n\t\t\t\"bottom-4\": position === \"bottom\",\n\t\t\t\"top-4\": position === \"top\",\n\t\t\t\"right-4\": align === \"right\",\n\t\t\t\"left-4\": align === \"left\",\n\t\t},\n\t\tclassNames.root,\n\t\tclassName\n\t);\n\n\treturn (\n\t\t<motion.div\n\t\t\tanimate={{ opacity: 1 }}\n\t\t\tclassName={containerClasses}\n\t\t\tinitial={{ opacity: 0 }}\n\t\t\tlayout=\"position\"\n\t\t\ttransition={{\n\t\t\t\tdefault: { ease: \"anticipate\" },\n\t\t\t\tlayout: { duration: 0.3 },\n\t\t\t}}\n\t\t>\n\t\t\t<BubbleComponent\n\t\t\t\tclassName={cn(\"z-[1000] md:z-[9999]\", classNames.bubble)}\n\t\t\t/>\n\t\t\t<ContainerComponent\n\t\t\t\talign={align}\n\t\t\t\tclassName={classNames.container}\n\t\t\t\tposition={position}\n\t\t\t>\n\t\t\t\t<RouterComponent>{children}</RouterComponent>\n\t\t\t</ContainerComponent>\n\t\t</motion.div>\n\t);\n};\n"],"mappings":";;;;;;;;;;;;;;AAwBA,MAAaA,kBAAiD,EAC7D,WACA,WAAW,UACX,QAAQ,SACR,cAAc,SACd,QAAQ,EAAE,EACV,aAAa,EAAE,EACf,eACK;CAEL,MAAM,kBAAkB,MAAM,UAAU;CACxC,MAAM,qBAAqB,MAAM,aAAa;CAC9C,MAAM,kBAAkB,MAAM,UAAU;CAExC,MAAM,mBAAmB,GACxB,uBACA,gBAAgB,UAAU,UAAU,YACpC;EACC,YAAY,aAAa;EACzB,SAAS,aAAa;EACtB,WAAW,UAAU;EACrB,UAAU,UAAU;EACpB,EACD,WAAW,MACX,UACA;AAED,QACC,qBAAC,OAAO;EACP,SAAS,EAAE,SAAS,GAAG;EACvB,WAAW;EACX,SAAS,EAAE,SAAS,GAAG;EACvB,QAAO;EACP,YAAY;GACX,SAAS,EAAE,MAAM,cAAc;GAC/B,QAAQ,EAAE,UAAU,IAAK;GACzB;aAED,oBAAC,mBACA,WAAW,GAAG,wBAAwB,WAAW,OAAO,GACvD,EACF,oBAAC;GACO;GACP,WAAW,WAAW;GACZ;aAEV,oBAAC,mBAAiB,WAA2B;IACzB;GACT"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/support/components/theme-wrapper.d.ts
|
|
4
|
+
type ThemeWrapperProps = {
|
|
5
|
+
theme?: "light" | "dark";
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Applies theme data attribute when dark mode is requested.
|
|
10
|
+
* Omit theme for automatic detection from parent elements.
|
|
11
|
+
*/
|
|
12
|
+
declare const ThemeWrapper: React.FC<ThemeWrapperProps>;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { ThemeWrapper };
|
|
15
|
+
//# sourceMappingURL=theme-wrapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-wrapper.d.ts","names":[],"sources":["../../../src/support/components/theme-wrapper.tsx"],"sourcesContent":[],"mappings":";;;KAEK,iBAAA;;EAAA,QAAA,EAEM,KAAA,CAAM,SAFK;AAStB,CAAA;;;;;cAAa,cAAc,KAAA,CAAM,GAAG"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Fragment, jsx } from "react/jsx-runtime";
|
|
2
|
+
|
|
3
|
+
//#region src/support/components/theme-wrapper.tsx
|
|
4
|
+
/**
|
|
5
|
+
* Applies theme data attribute when dark mode is requested.
|
|
6
|
+
* Omit theme for automatic detection from parent elements.
|
|
7
|
+
*/
|
|
8
|
+
const ThemeWrapper = ({ theme, children }) => {
|
|
9
|
+
if (theme === "dark") return /* @__PURE__ */ jsx("div", {
|
|
10
|
+
"data-color-scheme": "dark",
|
|
11
|
+
children
|
|
12
|
+
});
|
|
13
|
+
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
17
|
+
export { ThemeWrapper };
|
|
18
|
+
//# sourceMappingURL=theme-wrapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-wrapper.js","names":["ThemeWrapper: React.FC<ThemeWrapperProps>"],"sources":["../../../src/support/components/theme-wrapper.tsx"],"sourcesContent":["import type React from \"react\";\n\ntype ThemeWrapperProps = {\n\ttheme?: \"light\" | \"dark\";\n\tchildren: React.ReactNode;\n};\n\n/**\n * Applies theme data attribute when dark mode is requested.\n * Omit theme for automatic detection from parent elements.\n */\nexport const ThemeWrapper: React.FC<ThemeWrapperProps> = ({\n\ttheme,\n\tchildren,\n}) => {\n\tif (theme === \"dark\") {\n\t\treturn <div data-color-scheme=\"dark\">{children}</div>;\n\t}\n\n\t// Light or undefined - render children directly to inherit theme from parent\n\treturn <>{children}</>;\n};\n"],"mappings":";;;;;;;AAWA,MAAaA,gBAA6C,EACzD,OACA,eACK;AACL,KAAI,UAAU,OACb,QAAO,oBAAC;EAAI,qBAAkB;EAAQ;GAAe;AAItD,QAAO,gCAAG,WAAY"}
|
|
@@ -90,7 +90,7 @@ const IdentificationTimelineTool = ({ conversationId }) => {
|
|
|
90
90
|
successLabel
|
|
91
91
|
]);
|
|
92
92
|
return /* @__PURE__ */ jsx("div", {
|
|
93
|
-
className: "rounded border border-co-border
|
|
93
|
+
className: "mt-6 rounded border border-co-border bg-co-background p-4",
|
|
94
94
|
children: /* @__PURE__ */ jsxs("div", {
|
|
95
95
|
className: "flex flex-col gap-3",
|
|
96
96
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
@@ -112,7 +112,7 @@ const IdentificationTimelineTool = ({ conversationId }) => {
|
|
|
112
112
|
/* @__PURE__ */ jsx("input", {
|
|
113
113
|
"aria-label": text("component.identificationTool.inputLabel"),
|
|
114
114
|
autoComplete: "email",
|
|
115
|
-
className: "h-10 w-full rounded border border-co-border
|
|
115
|
+
className: "h-10 w-full rounded border border-co-border bg-transparent px-3 py-2 text-sm outline-none focus:border-co-primary focus:ring-2 focus:ring-co-primary/20",
|
|
116
116
|
disabled: submitDisabled,
|
|
117
117
|
inputMode: "email",
|
|
118
118
|
onChange: (event) => setEmail(event.target.value),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeline-identification-tool.js","names":["IdentificationTimelineTool: React.FC<\n\tConversationTimelineToolProps\n>","payload: SendTimelineItemRequest"],"sources":["../../../src/support/components/timeline-identification-tool.tsx"],"sourcesContent":["import type { SendTimelineItemRequest } from \"@cossistant/types/api/timeline-item\";\nimport {\n\tConversationEventType,\n\tConversationTimelineType,\n\tTimelineItemVisibility,\n} from \"@cossistant/types/enums\";\nimport { type FormEventHandler, useCallback, useMemo, useState } from \"react\";\n\nimport { useVisitor } from \"../../hooks/use-visitor\";\nimport { useSupport } from \"../../provider\";\nimport { useSupportText } from \"../text\";\nimport { CoButton } from \"./button\";\nimport type { ConversationTimelineToolProps } from \"./conversation-timeline\";\n\nexport const IdentificationTimelineTool: React.FC<\n\tConversationTimelineToolProps\n> = ({ conversationId }) => {\n\tconst text = useSupportText();\n\tconst { identify, visitor } = useVisitor();\n\tconst { client } = useSupport();\n\tconst [email, setEmail] = useState(\"\");\n\tconst [status, setStatus] = useState<\n\t\t\"idle\" | \"submitting\" | \"success\" | \"error\"\n\t>(\"idle\");\n\tconst [errorMessage, setErrorMessage] = useState<string | null>(null);\n\n\tconst isAlreadyIdentified = Boolean(visitor?.contact);\n\tconst hasSucceeded = status === \"success\" || isAlreadyIdentified;\n\n\tconst ctaLabel = text(\"component.identificationTool.cta\");\n\tconst successLabel = text(\"component.identificationTool.success\");\n\tconst description = text(\"component.identificationTool.description\");\n\tconst title = text(\"component.identificationTool.title\");\n\n\tconst submitDisabled = hasSucceeded || status === \"submitting\";\n\n\tconst handleSubmit = useCallback<FormEventHandler<HTMLFormElement>>(\n\t\tasync (event) => {\n\t\t\tevent.preventDefault();\n\n\t\t\tif (submitDisabled) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst trimmedEmail = email.trim();\n\t\t\tif (!trimmedEmail) {\n\t\t\t\tsetErrorMessage(text(\"component.identificationTool.validation\"));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetStatus(\"submitting\");\n\t\t\tsetErrorMessage(null);\n\n\t\t\ttry {\n\t\t\t\tconst identifyResult = await identify({ email: trimmedEmail });\n\n\t\t\t\tif (!identifyResult) {\n\t\t\t\t\tsetStatus(\"error\");\n\t\t\t\t\tsetErrorMessage(text(\"component.identificationTool.error\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst payload: SendTimelineItemRequest = {\n\t\t\t\t\tconversationId,\n\t\t\t\t\titem: {\n\t\t\t\t\t\ttype: ConversationTimelineType.EVENT,\n\t\t\t\t\t\ttext: text(\"component.identificationTool.eventLog\"),\n\t\t\t\t\t\ttool: null,\n\t\t\t\t\t\tparts: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: \"event\" as const,\n\t\t\t\t\t\t\t\teventType: ConversationEventType.VISITOR_IDENTIFIED,\n\t\t\t\t\t\t\t\tactorUserId: null,\n\t\t\t\t\t\t\t\tactorAiAgentId: null,\n\t\t\t\t\t\t\t\ttargetUserId: null,\n\t\t\t\t\t\t\t\ttargetAiAgentId: null,\n\t\t\t\t\t\t\t\tmessage: text(\"component.identificationTool.eventLog\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tvisitorId: identifyResult.visitorId,\n\t\t\t\t\t\tvisibility: TimelineItemVisibility.PUBLIC,\n\t\t\t\t\t},\n\t\t\t\t};\n\n\t\t\t\tawait client.sendMessage(payload);\n\n\t\t\t\tsetStatus(\"success\");\n\t\t\t\tsetEmail(\"\");\n\n\t\t\t\tvoid client.fetchWebsite({ force: true }).catch(() => {});\n\t\t\t} catch {\n\t\t\t\tsetStatus(\"error\");\n\t\t\t\tsetErrorMessage(text(\"component.identificationTool.error\"));\n\t\t\t}\n\t\t},\n\t\t[conversationId, email, identify, client, submitDisabled, text]\n\t);\n\n\tconst helperMessage = useMemo(() => {\n\t\tif (errorMessage) {\n\t\t\treturn (\n\t\t\t\t<p className=\"text-co-destructive text-xs\" role=\"alert\">\n\t\t\t\t\t{errorMessage}\n\t\t\t\t</p>\n\t\t\t);\n\t\t}\n\n\t\tif (hasSucceeded) {\n\t\t\treturn <p className=\"text-co-primary text-xs\">{successLabel}</p>;\n\t\t}\n\n\t\treturn null;\n\t}, [errorMessage, hasSucceeded, successLabel]);\n\n\treturn (\n\t\t<div className=\"rounded border border-co-border
|
|
1
|
+
{"version":3,"file":"timeline-identification-tool.js","names":["IdentificationTimelineTool: React.FC<\n\tConversationTimelineToolProps\n>","payload: SendTimelineItemRequest"],"sources":["../../../src/support/components/timeline-identification-tool.tsx"],"sourcesContent":["import type { SendTimelineItemRequest } from \"@cossistant/types/api/timeline-item\";\nimport {\n\tConversationEventType,\n\tConversationTimelineType,\n\tTimelineItemVisibility,\n} from \"@cossistant/types/enums\";\nimport { type FormEventHandler, useCallback, useMemo, useState } from \"react\";\n\nimport { useVisitor } from \"../../hooks/use-visitor\";\nimport { useSupport } from \"../../provider\";\nimport { useSupportText } from \"../text\";\nimport { CoButton } from \"./button\";\nimport type { ConversationTimelineToolProps } from \"./conversation-timeline\";\n\nexport const IdentificationTimelineTool: React.FC<\n\tConversationTimelineToolProps\n> = ({ conversationId }) => {\n\tconst text = useSupportText();\n\tconst { identify, visitor } = useVisitor();\n\tconst { client } = useSupport();\n\tconst [email, setEmail] = useState(\"\");\n\tconst [status, setStatus] = useState<\n\t\t\"idle\" | \"submitting\" | \"success\" | \"error\"\n\t>(\"idle\");\n\tconst [errorMessage, setErrorMessage] = useState<string | null>(null);\n\n\tconst isAlreadyIdentified = Boolean(visitor?.contact);\n\tconst hasSucceeded = status === \"success\" || isAlreadyIdentified;\n\n\tconst ctaLabel = text(\"component.identificationTool.cta\");\n\tconst successLabel = text(\"component.identificationTool.success\");\n\tconst description = text(\"component.identificationTool.description\");\n\tconst title = text(\"component.identificationTool.title\");\n\n\tconst submitDisabled = hasSucceeded || status === \"submitting\";\n\n\tconst handleSubmit = useCallback<FormEventHandler<HTMLFormElement>>(\n\t\tasync (event) => {\n\t\t\tevent.preventDefault();\n\n\t\t\tif (submitDisabled) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst trimmedEmail = email.trim();\n\t\t\tif (!trimmedEmail) {\n\t\t\t\tsetErrorMessage(text(\"component.identificationTool.validation\"));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetStatus(\"submitting\");\n\t\t\tsetErrorMessage(null);\n\n\t\t\ttry {\n\t\t\t\tconst identifyResult = await identify({ email: trimmedEmail });\n\n\t\t\t\tif (!identifyResult) {\n\t\t\t\t\tsetStatus(\"error\");\n\t\t\t\t\tsetErrorMessage(text(\"component.identificationTool.error\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst payload: SendTimelineItemRequest = {\n\t\t\t\t\tconversationId,\n\t\t\t\t\titem: {\n\t\t\t\t\t\ttype: ConversationTimelineType.EVENT,\n\t\t\t\t\t\ttext: text(\"component.identificationTool.eventLog\"),\n\t\t\t\t\t\ttool: null,\n\t\t\t\t\t\tparts: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: \"event\" as const,\n\t\t\t\t\t\t\t\teventType: ConversationEventType.VISITOR_IDENTIFIED,\n\t\t\t\t\t\t\t\tactorUserId: null,\n\t\t\t\t\t\t\t\tactorAiAgentId: null,\n\t\t\t\t\t\t\t\ttargetUserId: null,\n\t\t\t\t\t\t\t\ttargetAiAgentId: null,\n\t\t\t\t\t\t\t\tmessage: text(\"component.identificationTool.eventLog\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tvisitorId: identifyResult.visitorId,\n\t\t\t\t\t\tvisibility: TimelineItemVisibility.PUBLIC,\n\t\t\t\t\t},\n\t\t\t\t};\n\n\t\t\t\tawait client.sendMessage(payload);\n\n\t\t\t\tsetStatus(\"success\");\n\t\t\t\tsetEmail(\"\");\n\n\t\t\t\tvoid client.fetchWebsite({ force: true }).catch(() => {});\n\t\t\t} catch {\n\t\t\t\tsetStatus(\"error\");\n\t\t\t\tsetErrorMessage(text(\"component.identificationTool.error\"));\n\t\t\t}\n\t\t},\n\t\t[conversationId, email, identify, client, submitDisabled, text]\n\t);\n\n\tconst helperMessage = useMemo(() => {\n\t\tif (errorMessage) {\n\t\t\treturn (\n\t\t\t\t<p className=\"text-co-destructive text-xs\" role=\"alert\">\n\t\t\t\t\t{errorMessage}\n\t\t\t\t</p>\n\t\t\t);\n\t\t}\n\n\t\tif (hasSucceeded) {\n\t\t\treturn <p className=\"text-co-primary text-xs\">{successLabel}</p>;\n\t\t}\n\n\t\treturn null;\n\t}, [errorMessage, hasSucceeded, successLabel]);\n\n\treturn (\n\t\t<div className=\"mt-6 rounded border border-co-border bg-co-background p-4\">\n\t\t\t<div className=\"flex flex-col gap-3\">\n\t\t\t\t<div className=\"flex flex-col gap-1\">\n\t\t\t\t\t<h3 className=\"font-semibold text-sm\">{title}</h3>\n\t\t\t\t\t<p className=\"text-co-muted-foreground text-xs\">{description}</p>\n\t\t\t\t</div>\n\t\t\t\t{hasSucceeded ? (\n\t\t\t\t\t<div className=\"rounded-md bg-co-primary/10 px-3 py-2 text-co-primary text-sm\">\n\t\t\t\t\t\t{successLabel}\n\t\t\t\t\t</div>\n\t\t\t\t) : (\n\t\t\t\t\t<form className=\"flex gap-2\" onSubmit={handleSubmit}>\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\taria-label={text(\"component.identificationTool.inputLabel\")}\n\t\t\t\t\t\t\tautoComplete=\"email\"\n\t\t\t\t\t\t\tclassName=\"h-10 w-full rounded border border-co-border bg-transparent px-3 py-2 text-sm outline-none focus:border-co-primary focus:ring-2 focus:ring-co-primary/20\"\n\t\t\t\t\t\t\tdisabled={submitDisabled}\n\t\t\t\t\t\t\tinputMode=\"email\"\n\t\t\t\t\t\t\tonChange={(event) => setEmail(event.target.value)}\n\t\t\t\t\t\t\tplaceholder={text(\n\t\t\t\t\t\t\t\t\"component.identificationTool.inputPlaceholder\"\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\ttype=\"email\"\n\t\t\t\t\t\t\tvalue={email}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t{helperMessage}\n\t\t\t\t\t\t<CoButton className=\"h-10\" disabled={submitDisabled} type=\"submit\">\n\t\t\t\t\t\t\t{status === \"submitting\"\n\t\t\t\t\t\t\t\t? text(\"component.identificationTool.loading\")\n\t\t\t\t\t\t\t\t: ctaLabel}\n\t\t\t\t\t\t</CoButton>\n\t\t\t\t\t</form>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n\nIdentificationTimelineTool.displayName = \"IdentificationTimelineTool\";\n"],"mappings":";;;;;;;;;AAcA,MAAaA,8BAER,EAAE,qBAAqB;CAC3B,MAAM,OAAO,gBAAgB;CAC7B,MAAM,EAAE,UAAU,YAAY,YAAY;CAC1C,MAAM,EAAE,WAAW,YAAY;CAC/B,MAAM,CAAC,OAAO,YAAY,SAAS,GAAG;CACtC,MAAM,CAAC,QAAQ,aAAa,SAE1B,OAAO;CACT,MAAM,CAAC,cAAc,mBAAmB,SAAwB,KAAK;CAErE,MAAM,sBAAsB,QAAQ,SAAS,QAAQ;CACrD,MAAM,eAAe,WAAW,aAAa;CAE7C,MAAM,WAAW,KAAK,mCAAmC;CACzD,MAAM,eAAe,KAAK,uCAAuC;CACjE,MAAM,cAAc,KAAK,2CAA2C;CACpE,MAAM,QAAQ,KAAK,qCAAqC;CAExD,MAAM,iBAAiB,gBAAgB,WAAW;CAElD,MAAM,eAAe,YACpB,OAAO,UAAU;AAChB,QAAM,gBAAgB;AAEtB,MAAI,eACH;EAGD,MAAM,eAAe,MAAM,MAAM;AACjC,MAAI,CAAC,cAAc;AAClB,mBAAgB,KAAK,0CAA0C,CAAC;AAChE;;AAGD,YAAU,aAAa;AACvB,kBAAgB,KAAK;AAErB,MAAI;GACH,MAAM,iBAAiB,MAAM,SAAS,EAAE,OAAO,cAAc,CAAC;AAE9D,OAAI,CAAC,gBAAgB;AACpB,cAAU,QAAQ;AAClB,oBAAgB,KAAK,qCAAqC,CAAC;AAC3D;;GAGD,MAAMC,UAAmC;IACxC;IACA,MAAM;KACL,MAAM,yBAAyB;KAC/B,MAAM,KAAK,wCAAwC;KACnD,MAAM;KACN,OAAO,CACN;MACC,MAAM;MACN,WAAW,sBAAsB;MACjC,aAAa;MACb,gBAAgB;MAChB,cAAc;MACd,iBAAiB;MACjB,SAAS,KAAK,wCAAwC;MACtD,CACD;KACD,WAAW,eAAe;KAC1B,YAAY,uBAAuB;KACnC;IACD;AAED,SAAM,OAAO,YAAY,QAAQ;AAEjC,aAAU,UAAU;AACpB,YAAS,GAAG;AAEZ,GAAK,OAAO,aAAa,EAAE,OAAO,MAAM,CAAC,CAAC,YAAY,GAAG;UAClD;AACP,aAAU,QAAQ;AAClB,mBAAgB,KAAK,qCAAqC,CAAC;;IAG7D;EAAC;EAAgB;EAAO;EAAU;EAAQ;EAAgB;EAAK,CAC/D;CAED,MAAM,gBAAgB,cAAc;AACnC,MAAI,aACH,QACC,oBAAC;GAAE,WAAU;GAA8B,MAAK;aAC9C;IACE;AAIN,MAAI,aACH,QAAO,oBAAC;GAAE,WAAU;aAA2B;IAAiB;AAGjE,SAAO;IACL;EAAC;EAAc;EAAc;EAAa,CAAC;AAE9C,QACC,oBAAC;EAAI,WAAU;YACd,qBAAC;GAAI,WAAU;cACd,qBAAC;IAAI,WAAU;eACd,oBAAC;KAAG,WAAU;eAAyB;MAAW,EAClD,oBAAC;KAAE,WAAU;eAAoC;MAAgB;KAC5D,EACL,eACA,oBAAC;IAAI,WAAU;cACb;KACI,GAEN,qBAAC;IAAK,WAAU;IAAa,UAAU;;KACtC,oBAAC;MACA,cAAY,KAAK,0CAA0C;MAC3D,cAAa;MACb,WAAU;MACV,UAAU;MACV,WAAU;MACV,WAAW,UAAU,SAAS,MAAM,OAAO,MAAM;MACjD,aAAa,KACZ,gDACA;MACD,MAAK;MACL,OAAO;OACN;KACD;KACD,oBAAC;MAAS,WAAU;MAAO,UAAU;MAAgB,MAAK;gBACxD,WAAW,eACT,KAAK,uCAAuC,GAC5C;OACO;;KACL;IAEH;GACD;;AAIR,2BAA2B,cAAc"}
|
|
@@ -17,7 +17,7 @@ const Watermark = ({ className }) => {
|
|
|
17
17
|
return url.toString();
|
|
18
18
|
}, [website]);
|
|
19
19
|
return /* @__PURE__ */ jsxs("a", {
|
|
20
|
-
className: cn("flex items-center gap-1.5 font-medium
|
|
20
|
+
className: cn("group/watermark flex items-center gap-1.5 font-medium text-co-primary/80 hover:text-co-blue", className),
|
|
21
21
|
href: cossistantUrl,
|
|
22
22
|
rel: "noopener noreferrer",
|
|
23
23
|
target: "_blank",
|
|
@@ -25,7 +25,7 @@ const Watermark = ({ className }) => {
|
|
|
25
25
|
as: "span",
|
|
26
26
|
className: "text-co-muted-foreground text-xs",
|
|
27
27
|
textKey: "common.brand.watermark"
|
|
28
|
-
}), /* @__PURE__ */ jsx(CossistantLogo, { className: "h-3" })]
|
|
28
|
+
}), /* @__PURE__ */ jsx(CossistantLogo, { className: "h-3 transition-transform duration-200 group-focus-within/watermark:rotate-5 group-hover/watermark:scale-105" })]
|
|
29
29
|
});
|
|
30
30
|
};
|
|
31
31
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watermark.js","names":["Watermark: React.FC<WatermarkProps>"],"sources":["../../../src/support/components/watermark.tsx"],"sourcesContent":["import { useSupport } from \"@cossistant/react\";\nimport { useMemo } from \"react\";\nimport { Text } from \"../text\";\nimport { cn } from \"../utils\";\nimport { CossistantLogo } from \"./cossistant-branding\";\n\nexport type WatermarkProps = {\n\tclassName?: string;\n};\n\nexport const Watermark: React.FC<WatermarkProps> = ({ className }) => {\n\tconst { website } = useSupport();\n\n\tconst cossistantUrl = useMemo(() => {\n\t\tif (!website) {\n\t\t\treturn \"https://cossistant.com\";\n\t\t}\n\n\t\tconst url = new URL(\"https://cossistant.com\");\n\n\t\turl.searchParams.set(\"ref\", \"chatbox\");\n\t\turl.searchParams.set(\"domain\", website.domain);\n\t\turl.searchParams.set(\"name\", website.name);\n\n\t\treturn url.toString();\n\t}, [website]);\n\n\treturn (\n\t\t<a\n\t\t\tclassName={cn(\n\t\t\t\t\"flex items-center gap-1.5 font-medium
|
|
1
|
+
{"version":3,"file":"watermark.js","names":["Watermark: React.FC<WatermarkProps>"],"sources":["../../../src/support/components/watermark.tsx"],"sourcesContent":["import { useSupport } from \"@cossistant/react\";\nimport { useMemo } from \"react\";\nimport { Text } from \"../text\";\nimport { cn } from \"../utils\";\nimport { CossistantLogo } from \"./cossistant-branding\";\n\nexport type WatermarkProps = {\n\tclassName?: string;\n};\n\nexport const Watermark: React.FC<WatermarkProps> = ({ className }) => {\n\tconst { website } = useSupport();\n\n\tconst cossistantUrl = useMemo(() => {\n\t\tif (!website) {\n\t\t\treturn \"https://cossistant.com\";\n\t\t}\n\n\t\tconst url = new URL(\"https://cossistant.com\");\n\n\t\turl.searchParams.set(\"ref\", \"chatbox\");\n\t\turl.searchParams.set(\"domain\", website.domain);\n\t\turl.searchParams.set(\"name\", website.name);\n\n\t\treturn url.toString();\n\t}, [website]);\n\n\treturn (\n\t\t<a\n\t\t\tclassName={cn(\n\t\t\t\t\"group/watermark flex items-center gap-1.5 font-medium text-co-primary/80 hover:text-co-blue\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\thref={cossistantUrl}\n\t\t\trel=\"noopener noreferrer\"\n\t\t\ttarget=\"_blank\"\n\t\t>\n\t\t\t<Text\n\t\t\t\tas=\"span\"\n\t\t\t\tclassName=\"text-co-muted-foreground text-xs\"\n\t\t\t\ttextKey=\"common.brand.watermark\"\n\t\t\t/>\n\t\t\t<CossistantLogo className=\"h-3 transition-transform duration-200 group-focus-within/watermark:rotate-5 group-hover/watermark:scale-105\" />\n\t\t</a>\n\t);\n};\n"],"mappings":";;;;;;;;AAUA,MAAaA,aAAuC,EAAE,gBAAgB;CACrE,MAAM,EAAE,YAAY,YAAY;CAEhC,MAAM,gBAAgB,cAAc;AACnC,MAAI,CAAC,QACJ,QAAO;EAGR,MAAM,MAAM,IAAI,IAAI,yBAAyB;AAE7C,MAAI,aAAa,IAAI,OAAO,UAAU;AACtC,MAAI,aAAa,IAAI,UAAU,QAAQ,OAAO;AAC9C,MAAI,aAAa,IAAI,QAAQ,QAAQ,KAAK;AAE1C,SAAO,IAAI,UAAU;IACnB,CAAC,QAAQ,CAAC;AAEb,QACC,qBAAC;EACA,WAAW,GACV,+FACA,UACA;EACD,MAAM;EACN,KAAI;EACJ,QAAO;aAEP,oBAAC;GACA,IAAG;GACH,WAAU;GACV,SAAQ;IACP,EACF,oBAAC,kBAAe,WAAU,gHAAgH;GACvI"}
|
package/support/index.d.ts
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { SupportLocale, SupportTextContentOverrides } from "./text/locales/keys.js";
|
|
2
|
+
import { Page, PageProps } from "../primitives/page.js";
|
|
3
|
+
import "../primitives/index.js";
|
|
2
4
|
import { Text, useSupportText } from "./text/index.js";
|
|
5
|
+
import { BubbleSlotProps, ContainerSlotProps, RouterSlotProps } from "./types.js";
|
|
6
|
+
import { CoButton } from "./components/button.js";
|
|
7
|
+
import { Header } from "./components/header.js";
|
|
3
8
|
import { WebSocketContextValue, WebSocketProvider, useWebSocket } from "./context/websocket.js";
|
|
4
9
|
import { useSupportConfig, useSupportNavigation, useSupportStore } from "./store/support-store.js";
|
|
5
10
|
import "./store/index.js";
|
|
6
|
-
import { ReactElement } from "react";
|
|
11
|
+
import React, { ReactElement } from "react";
|
|
12
|
+
import { DefaultRoutes, NavigationState, RouteRegistry, SupportPage } from "@cossistant/core";
|
|
7
13
|
import { DefaultMessage } from "@cossistant/types";
|
|
8
14
|
|
|
9
15
|
//#region src/support/index.d.ts
|
|
@@ -17,11 +23,31 @@ type SupportProps<Locale extends string = SupportLocale> = {
|
|
|
17
23
|
defaultOpen?: boolean;
|
|
18
24
|
locale?: Locale;
|
|
19
25
|
content?: SupportTextContentOverrides<Locale>;
|
|
26
|
+
theme?: "light" | "dark";
|
|
27
|
+
slots?: {
|
|
28
|
+
bubble?: React.ComponentType<BubbleSlotProps>;
|
|
29
|
+
container?: React.ComponentType<ContainerSlotProps>;
|
|
30
|
+
router?: React.ComponentType<RouterSlotProps>;
|
|
31
|
+
};
|
|
32
|
+
classNames?: {
|
|
33
|
+
root?: string;
|
|
34
|
+
bubble?: string;
|
|
35
|
+
container?: string;
|
|
36
|
+
};
|
|
37
|
+
children?: React.ReactNode;
|
|
20
38
|
};
|
|
21
39
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
40
|
+
* Complete support widget with chat, routing, and real-time features.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* // Zero config
|
|
44
|
+
* <Support />
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* // With customization
|
|
48
|
+
* <Support theme="dark" classNames={{ bubble: "bg-purple-600" }}>
|
|
49
|
+
* <Page name="FAQ" component={FAQPage} />
|
|
50
|
+
* </Support>
|
|
25
51
|
*/
|
|
26
52
|
declare function Support<Locale extends string = SupportLocale>({
|
|
27
53
|
className,
|
|
@@ -32,8 +58,12 @@ declare function Support<Locale extends string = SupportLocale>({
|
|
|
32
58
|
defaultMessages,
|
|
33
59
|
defaultOpen,
|
|
34
60
|
locale,
|
|
35
|
-
content
|
|
61
|
+
content,
|
|
62
|
+
theme,
|
|
63
|
+
slots,
|
|
64
|
+
classNames,
|
|
65
|
+
children
|
|
36
66
|
}: SupportProps<Locale>): ReactElement | null;
|
|
37
67
|
//#endregion
|
|
38
|
-
export { Support, Support as default, type SupportLocale, SupportProps, type SupportTextContentOverrides, Text, type WebSocketContextValue, WebSocketProvider, useSupportConfig, useSupportNavigation, useSupportStore, useSupportText, useWebSocket };
|
|
68
|
+
export { type BubbleSlotProps, CoButton as Button, type ContainerSlotProps, type DefaultRoutes, Header, type NavigationState, Page, type PageProps, type RouteRegistry, type RouterSlotProps, Support, Support as default, type SupportLocale, type SupportPage, SupportProps, type SupportTextContentOverrides, Text, type WebSocketContextValue, WebSocketProvider, useSupportConfig, useSupportNavigation, useSupportStore, useSupportText, useWebSocket };
|
|
39
69
|
//# sourceMappingURL=index.d.ts.map
|
package/support/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/support/index.tsx"],"sourcesContent":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/support/index.tsx"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;KAmBY,qCAAqC;;;;;;oBAO9B;;WAET;YACC,4BAA4B;EAV3B,KAAA,CAAA,EAAA,OAAY,GAAA,MAAA;EAAyB,KAAA,CAAA,EAAA;IAO9B,MAAA,CAAA,EAUR,KAAA,CAAM,aAVE,CAUY,eAVZ,CAAA;IAET,SAAA,CAAA,EASI,KAAA,CAAM,aATV,CASwB,kBATxB,CAAA;IAC6B,MAAA,CAAA,EAS5B,KAAA,CAAM,aATsB,CASR,eATQ,CAAA;EAA5B,CAAA;EAOoB,UAAA,CAAA,EAAA;IAAd,IAAA,CAAA,EAAA,MAAA;IACiB,MAAA,CAAA,EAAA,MAAA;IAAd,SAAA,CAAA,EAAA,MAAA;EACW,CAAA;EAApB,QAAM,CAAA,EAWL,KAAA,CAAM,SAXD;CAWL;;AAgBZ;;;;;;;;;;;;AAWC,iBAXe,OAWf,CAAA,eAAA,MAAA,GAX+C,aAW/C,CAAA,CAAA;EAAA,SAAA;EAAA,QAAA;EAAA,KAAA;EAAA,WAAA;EAAA,YAAA;EAAA,eAAA;EAAA,WAAA;EAAA,MAAA;EAAA,OAAA;EAAA,KAAA;EAAA,KAAA;EAAA,UAAA;EAAA;AAAA,CAAA,EAGE,YAHF,CAGe,MAHf,CAAA,CAAA,EAGyB,YAHzB,GAAA,IAAA"}
|
package/support/index.js
CHANGED
|
@@ -1,43 +1,66 @@
|
|
|
1
1
|
import "./support.js";
|
|
2
|
-
import { SupportRealtimeProvider } from "../realtime/support-provider.js";
|
|
3
2
|
import { SupportConfig } from "../support-config.js";
|
|
3
|
+
import { PageRegistryProvider } from "../primitives/page-registry.js";
|
|
4
|
+
import { Page } from "../primitives/page.js";
|
|
4
5
|
import { initializeSupportStore, useSupportConfig, useSupportNavigation, useSupportStore } from "./store/support-store.js";
|
|
6
|
+
import { SupportRealtimeProvider } from "../realtime/support-provider.js";
|
|
7
|
+
import { CoButton } from "./components/button.js";
|
|
8
|
+
import { Header } from "./components/header.js";
|
|
5
9
|
import { SupportTextProvider, Text, useSupportText } from "./text/index.js";
|
|
6
10
|
import { SupportContent } from "./components/support-content.js";
|
|
11
|
+
import { ThemeWrapper } from "./components/theme-wrapper.js";
|
|
7
12
|
import { WebSocketProvider, useWebSocket } from "./context/websocket.js";
|
|
8
13
|
import { useSupport } from "../provider.js";
|
|
9
14
|
import React from "react";
|
|
10
|
-
import {
|
|
15
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
16
|
|
|
12
17
|
//#region src/support/index.tsx
|
|
13
18
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
19
|
+
* Complete support widget with chat, routing, and real-time features.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // Zero config
|
|
23
|
+
* <Support />
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* // With customization
|
|
27
|
+
* <Support theme="dark" classNames={{ bubble: "bg-purple-600" }}>
|
|
28
|
+
* <Page name="FAQ" component={FAQPage} />
|
|
29
|
+
* </Support>
|
|
17
30
|
*/
|
|
18
|
-
function Support({ className, position = "bottom", align = "right", positioning = "fixed", quickOptions, defaultMessages, defaultOpen, locale, content }) {
|
|
31
|
+
function Support({ className, position = "bottom", align = "right", positioning = "fixed", quickOptions, defaultMessages, defaultOpen, locale, content, theme, slots, classNames, children }) {
|
|
19
32
|
const { website } = useSupport();
|
|
20
33
|
const isVisitorBlocked = website?.visitor?.isBlocked ?? false;
|
|
21
34
|
React.useEffect(() => {
|
|
22
35
|
if (defaultOpen !== void 0) initializeSupportStore({ defaultOpen });
|
|
23
36
|
}, [defaultOpen]);
|
|
24
37
|
if (!website || isVisitorBlocked) return null;
|
|
25
|
-
return /* @__PURE__ */
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
return /* @__PURE__ */ jsx(ThemeWrapper, {
|
|
39
|
+
theme,
|
|
40
|
+
children: /* @__PURE__ */ jsxs(PageRegistryProvider, { children: [
|
|
41
|
+
children,
|
|
42
|
+
/* @__PURE__ */ jsx(SupportRealtimeProvider, { children: /* @__PURE__ */ jsx(SupportTextProvider, {
|
|
43
|
+
content,
|
|
44
|
+
locale,
|
|
45
|
+
children: /* @__PURE__ */ jsx(SupportContent, {
|
|
46
|
+
align,
|
|
47
|
+
className,
|
|
48
|
+
classNames,
|
|
49
|
+
position,
|
|
50
|
+
positioning,
|
|
51
|
+
slots,
|
|
52
|
+
children
|
|
53
|
+
})
|
|
54
|
+
}) }),
|
|
55
|
+
/* @__PURE__ */ jsx(SupportConfig, {
|
|
56
|
+
defaultMessages,
|
|
57
|
+
quickOptions
|
|
58
|
+
})
|
|
59
|
+
] })
|
|
60
|
+
});
|
|
38
61
|
}
|
|
39
62
|
var support_default = Support;
|
|
40
63
|
|
|
41
64
|
//#endregion
|
|
42
|
-
export { Support, Text, WebSocketProvider, support_default as default, useSupportConfig, useSupportNavigation, useSupportStore, useSupportText, useWebSocket };
|
|
65
|
+
export { CoButton as Button, Header, Page, Support, Text, WebSocketProvider, support_default as default, useSupportConfig, useSupportNavigation, useSupportStore, useSupportText, useWebSocket };
|
|
43
66
|
//# sourceMappingURL=index.js.map
|
package/support/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/support/index.tsx"],"sourcesContent":["import \"./support.css\";\n\nimport type { DefaultMessage } from \"@cossistant/types\";\nimport React, { type ReactElement } from \"react\";\nimport { useSupport } from \"../provider\";\nimport { SupportRealtimeProvider } from \"../realtime\";\nimport { SupportConfig } from \"../support-config\";\nimport { SupportContent } from \"./components/support-content\";\nimport { initializeSupportStore } from \"./store/support-store\";\nimport type { SupportLocale, SupportTextContentOverrides } from \"./text\";\nimport { SupportTextProvider } from \"./text\";\n\nexport type SupportProps<Locale extends string = SupportLocale> = {\n\tclassName?: string;\n\tposition?: \"top\" | \"bottom\";\n\talign?: \"right\" | \"left\";\n\tpositioning?: \"fixed\" | \"absolute\";\n\tquickOptions?: string[];\n\tdefaultMessages?: DefaultMessage[];\n\tdefaultOpen?: boolean;\n\tlocale?: Locale;\n\tcontent?: SupportTextContentOverrides<Locale>;\n};\n\n//
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/support/index.tsx"],"sourcesContent":["import \"./support.css\";\n\nimport type { DefaultMessage } from \"@cossistant/types\";\nimport React, { type ReactElement } from \"react\";\nimport { PageRegistryProvider } from \"../primitives\";\nimport { useSupport } from \"../provider\";\nimport { SupportRealtimeProvider } from \"../realtime\";\nimport { SupportConfig } from \"../support-config\";\nimport { SupportContent } from \"./components/support-content\";\nimport { ThemeWrapper } from \"./components/theme-wrapper\";\nimport { initializeSupportStore } from \"./store/support-store\";\nimport type { SupportLocale, SupportTextContentOverrides } from \"./text\";\nimport { SupportTextProvider } from \"./text\";\nimport type {\n\tBubbleSlotProps,\n\tContainerSlotProps,\n\tRouterSlotProps,\n} from \"./types\";\n\nexport type SupportProps<Locale extends string = SupportLocale> = {\n\t// Existing props\n\tclassName?: string;\n\tposition?: \"top\" | \"bottom\";\n\talign?: \"right\" | \"left\";\n\tpositioning?: \"fixed\" | \"absolute\";\n\tquickOptions?: string[];\n\tdefaultMessages?: DefaultMessage[];\n\tdefaultOpen?: boolean;\n\tlocale?: Locale;\n\tcontent?: SupportTextContentOverrides<Locale>;\n\n\t// NEW: Theme control\n\ttheme?: \"light\" | \"dark\";\n\n\t// NEW: Slot customization\n\tslots?: {\n\t\tbubble?: React.ComponentType<BubbleSlotProps>;\n\t\tcontainer?: React.ComponentType<ContainerSlotProps>;\n\t\trouter?: React.ComponentType<RouterSlotProps>;\n\t};\n\n\t// NEW: Granular className overrides\n\tclassNames?: {\n\t\troot?: string;\n\t\tbubble?: string;\n\t\tcontainer?: string;\n\t};\n\n\t// NEW: Allow declarative children (Page components)\n\tchildren?: React.ReactNode;\n};\n\n/**\n * Complete support widget with chat, routing, and real-time features.\n *\n * @example\n * // Zero config\n * <Support />\n *\n * @example\n * // With customization\n * <Support theme=\"dark\" classNames={{ bubble: \"bg-purple-600\" }}>\n * <Page name=\"FAQ\" component={FAQPage} />\n * </Support>\n */\nexport function Support<Locale extends string = SupportLocale>({\n\tclassName,\n\tposition = \"bottom\",\n\talign = \"right\",\n\tpositioning = \"fixed\",\n\tquickOptions,\n\tdefaultMessages,\n\tdefaultOpen,\n\tlocale,\n\tcontent,\n\ttheme,\n\tslots,\n\tclassNames,\n\tchildren,\n}: SupportProps<Locale>): ReactElement | null {\n\tconst { website } = useSupport();\n\tconst isVisitorBlocked = website?.visitor?.isBlocked ?? false;\n\n\t// Initialize support store with defaultOpen when component mounts or prop changes\n\tReact.useEffect(() => {\n\t\tif (defaultOpen !== undefined) {\n\t\t\tinitializeSupportStore({ defaultOpen });\n\t\t}\n\t}, [defaultOpen]);\n\n\tif (!website || isVisitorBlocked) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<ThemeWrapper theme={theme}>\n\t\t\t<PageRegistryProvider>\n\t\t\t\t{children}\n\t\t\t\t<SupportRealtimeProvider>\n\t\t\t\t\t<SupportTextProvider content={content} locale={locale}>\n\t\t\t\t\t\t<SupportContent\n\t\t\t\t\t\t\talign={align}\n\t\t\t\t\t\t\tclassName={className}\n\t\t\t\t\t\t\tclassNames={classNames}\n\t\t\t\t\t\t\tposition={position}\n\t\t\t\t\t\t\tpositioning={positioning}\n\t\t\t\t\t\t\tslots={slots}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t</SupportContent>\n\t\t\t\t\t</SupportTextProvider>\n\t\t\t\t</SupportRealtimeProvider>\n\t\t\t\t<SupportConfig\n\t\t\t\t\tdefaultMessages={defaultMessages}\n\t\t\t\t\tquickOptions={quickOptions}\n\t\t\t\t/>\n\t\t\t</PageRegistryProvider>\n\t\t</ThemeWrapper>\n\t);\n}\n\nexport default Support;\n\n// Type exports from core\nexport type {\n\tDefaultRoutes,\n\tNavigationState,\n\tRouteRegistry,\n\tSupportPage,\n} from \"@cossistant/core\";\nexport type { PageProps } from \"../primitives\";\n// Page component for declarative routing (re-exported from primitives)\nexport { Page } from \"../primitives\";\nexport { CoButton as Button } from \"./components/button\";\n// UI components for building custom pages\nexport { Header } from \"./components/header\";\n// WebSocket context\nexport type { WebSocketContextValue } from \"./context/websocket\";\nexport { useWebSocket, WebSocketProvider } from \"./context/websocket\";\n// Navigation hooks and store\nexport {\n\tuseSupportConfig,\n\tuseSupportNavigation,\n\tuseSupportStore,\n} from \"./store\";\n// Text and localization\nexport type { SupportLocale, SupportTextContentOverrides } from \"./text\";\nexport { Text, useSupportText } from \"./text\";\n\n// Slot prop types\nexport type {\n\tBubbleSlotProps,\n\tContainerSlotProps,\n\tRouterSlotProps,\n} from \"./types\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiEA,SAAgB,QAA+C,EAC9D,WACA,WAAW,UACX,QAAQ,SACR,cAAc,SACd,cACA,iBACA,aACA,QACA,SACA,OACA,OACA,YACA,YAC6C;CAC7C,MAAM,EAAE,YAAY,YAAY;CAChC,MAAM,mBAAmB,SAAS,SAAS,aAAa;AAGxD,OAAM,gBAAgB;AACrB,MAAI,gBAAgB,OACnB,wBAAuB,EAAE,aAAa,CAAC;IAEtC,CAAC,YAAY,CAAC;AAEjB,KAAI,CAAC,WAAW,iBACf,QAAO;AAGR,QACC,oBAAC;EAAoB;YACpB,qBAAC;GACC;GACD,oBAAC,qCACA,oBAAC;IAA6B;IAAiB;cAC9C,oBAAC;KACO;KACI;KACC;KACF;KACG;KACN;KAEN;MACe;KACI,GACG;GAC1B,oBAAC;IACiB;IACH;KACb;MACoB;GACT;;AAIjB,sBAAe"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
3
|
//#region src/support/pages/articles.d.ts
|
|
4
|
-
|
|
4
|
+
type ArticlesPageProps = {
|
|
5
|
+
params?: undefined;
|
|
6
|
+
};
|
|
7
|
+
declare const ArticlesPage: React.FC<ArticlesPageProps>;
|
|
5
8
|
//#endregion
|
|
6
9
|
export { ArticlesPage };
|
|
7
10
|
//# sourceMappingURL=articles.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"articles.d.ts","names":[],"sources":["../../../src/support/pages/articles.tsx"],"sourcesContent":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"articles.d.ts","names":[],"sources":["../../../src/support/pages/articles.tsx"],"sourcesContent":[],"mappings":";;;KAKK,iBAAA;;AAL0B,CAAA;AASlB,cAAA,YAAuB,EAAT,KAAA,CAAM,EAAG,CAAA,iBAAD,CAAA"}
|
|
@@ -4,7 +4,7 @@ import { NavigationTab } from "../components/navigation-tab.js";
|
|
|
4
4
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
|
|
6
6
|
//#region src/support/pages/articles.tsx
|
|
7
|
-
const ArticlesPage = () => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Header, { children: /* @__PURE__ */ jsx(NavigationTab, {}) }), /* @__PURE__ */ jsx(Container, { children: /* @__PURE__ */ jsx("div", {
|
|
7
|
+
const ArticlesPage = (_props = {}) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Header, { children: /* @__PURE__ */ jsx(NavigationTab, {}) }), /* @__PURE__ */ jsx(Container, { children: /* @__PURE__ */ jsx("div", {
|
|
8
8
|
className: "p-2",
|
|
9
9
|
children: /* @__PURE__ */ jsxs("div", {
|
|
10
10
|
className: "flex flex-col gap-5",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"articles.js","names":["ArticlesPage: React.FC"],"sources":["../../../src/support/pages/articles.tsx"],"sourcesContent":["import type React from \"react\";\nimport { Container } from \"../components/container\";\nimport { Header } from \"../components/header\";\nimport { NavigationTab } from \"../components/navigation-tab\";\n\nexport const ArticlesPage: React.FC = () => (\n\t<>\n\t\t<Header>\n\t\t\t<NavigationTab />\n\t\t</Header>\n\t\t<Container>\n\t\t\t<div className=\"p-2\">\n\t\t\t\t<div className=\"flex flex-col gap-5\">\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<h3 className=\"mb-2 font-medium text-base text-co-primary\">\n\t\t\t\t\t\t\tHow do I start a conversation?\n\t\t\t\t\t\t</h3>\n\t\t\t\t\t\t<p className=\"text-co-primary/60 text-sm leading-relaxed\">\n\t\t\t\t\t\t\tClick the \"Start New Conversation\" button on the home page to\n\t\t\t\t\t\t\tbegin chatting with our support team.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<h3 className=\"mb-2 font-medium text-base text-co-primary\">\n\t\t\t\t\t\t\tCan I view previous conversations?\n\t\t\t\t\t\t</h3>\n\t\t\t\t\t\t<p className=\"text-co-primary/60 text-sm leading-relaxed\">\n\t\t\t\t\t\t\tYes! Navigate to the Conversation History page to see all your\n\t\t\t\t\t\t\tpast conversations.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<h3 className=\"mb-2 font-medium text-base text-co-primary\">\n\t\t\t\t\t\t\tHow quickly will I get a response?\n\t\t\t\t\t\t</h3>\n\t\t\t\t\t\t<p className=\"text-co-primary/60 text-sm leading-relaxed\">\n\t\t\t\t\t\t\tOur team typically responds within a few minutes during business\n\t\t\t\t\t\t\thours.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</Container>\n\t</>\n);\n"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"articles.js","names":["ArticlesPage: React.FC<ArticlesPageProps>"],"sources":["../../../src/support/pages/articles.tsx"],"sourcesContent":["import type React from \"react\";\nimport { Container } from \"../components/container\";\nimport { Header } from \"../components/header\";\nimport { NavigationTab } from \"../components/navigation-tab\";\n\ntype ArticlesPageProps = {\n\tparams?: undefined;\n};\n\nexport const ArticlesPage: React.FC<ArticlesPageProps> = (_props = {}) => (\n\t<>\n\t\t<Header>\n\t\t\t<NavigationTab />\n\t\t</Header>\n\t\t<Container>\n\t\t\t<div className=\"p-2\">\n\t\t\t\t<div className=\"flex flex-col gap-5\">\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<h3 className=\"mb-2 font-medium text-base text-co-primary\">\n\t\t\t\t\t\t\tHow do I start a conversation?\n\t\t\t\t\t\t</h3>\n\t\t\t\t\t\t<p className=\"text-co-primary/60 text-sm leading-relaxed\">\n\t\t\t\t\t\t\tClick the \"Start New Conversation\" button on the home page to\n\t\t\t\t\t\t\tbegin chatting with our support team.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<h3 className=\"mb-2 font-medium text-base text-co-primary\">\n\t\t\t\t\t\t\tCan I view previous conversations?\n\t\t\t\t\t\t</h3>\n\t\t\t\t\t\t<p className=\"text-co-primary/60 text-sm leading-relaxed\">\n\t\t\t\t\t\t\tYes! Navigate to the Conversation History page to see all your\n\t\t\t\t\t\t\tpast conversations.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<h3 className=\"mb-2 font-medium text-base text-co-primary\">\n\t\t\t\t\t\t\tHow quickly will I get a response?\n\t\t\t\t\t\t</h3>\n\t\t\t\t\t\t<p className=\"text-co-primary/60 text-sm leading-relaxed\">\n\t\t\t\t\t\t\tOur team typically responds within a few minutes during business\n\t\t\t\t\t\t\thours.\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</Container>\n\t</>\n);\n"],"mappings":";;;;;;AASA,MAAaA,gBAA6C,SAAS,EAAE,KACpE,4CACC,oBAAC,oBACA,oBAAC,kBAAgB,GACT,EACT,oBAAC,uBACA,oBAAC;CAAI,WAAU;WACd,qBAAC;EAAI,WAAU;;GACd,qBAAC,oBACA,oBAAC;IAAG,WAAU;cAA6C;KAEtD,EACL,oBAAC;IAAE,WAAU;cAA6C;KAGtD,IACC;GACN,qBAAC,oBACA,oBAAC;IAAG,WAAU;cAA6C;KAEtD,EACL,oBAAC;IAAE,WAAU;cAA6C;KAGtD,IACC;GACN,qBAAC,oBACA,oBAAC;IAAG,WAAU;cAA6C;KAEtD,EACL,oBAAC;IAAE,WAAU;cAA6C;KAGtD,IACC;;GACD;EACD,GACK,IACV"}
|
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
3
|
//#region src/support/pages/conversation-history.d.ts
|
|
4
|
-
|
|
4
|
+
type ConversationHistoryPageProps = {
|
|
5
|
+
params?: undefined;
|
|
6
|
+
};
|
|
5
7
|
/**
|
|
6
|
-
* Conversation history page
|
|
7
|
-
*
|
|
8
|
-
* Displays:
|
|
9
|
-
* - List of all conversations
|
|
10
|
-
* - Pagination controls
|
|
11
|
-
* - Button to start new conversation
|
|
12
|
-
*
|
|
13
|
-
* All logic is handled by the useConversationHistoryPage hook.
|
|
8
|
+
* Conversation history page with list of past conversations and pagination.
|
|
14
9
|
*/
|
|
15
|
-
declare const ConversationHistoryPage: React.FC
|
|
10
|
+
declare const ConversationHistoryPage: React.FC<ConversationHistoryPageProps>;
|
|
16
11
|
//#endregion
|
|
17
12
|
export { ConversationHistoryPage };
|
|
18
13
|
//# sourceMappingURL=conversation-history.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-history.d.ts","names":[],"sources":["../../../src/support/pages/conversation-history.tsx"],"sourcesContent":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"conversation-history.d.ts","names":[],"sources":["../../../src/support/pages/conversation-history.tsx"],"sourcesContent":[],"mappings":";;;KAaK,4BAAA;;AAX0B,CAAA;AAkB/B;;;cAAa,yBAAyB,KAAA,CAAM,GAAG"}
|