@cossistant/react 0.0.31 → 0.0.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/hooks/index.d.ts +2 -2
  2. package/hooks/index.js +2 -2
  3. package/hooks/private/use-grouped-messages.d.ts +27 -2
  4. package/hooks/private/use-grouped-messages.d.ts.map +1 -1
  5. package/hooks/private/use-grouped-messages.js +156 -103
  6. package/hooks/private/use-grouped-messages.js.map +1 -1
  7. package/hooks/use-new-message-sound.d.ts.map +1 -1
  8. package/hooks/use-new-message-sound.js +2 -2
  9. package/hooks/use-new-message-sound.js.map +1 -1
  10. package/hooks/use-send-message.js +1 -1
  11. package/hooks/use-send-message.js.map +1 -1
  12. package/hooks/use-typing-sound.d.ts.map +1 -1
  13. package/hooks/use-typing-sound.js +2 -2
  14. package/hooks/use-typing-sound.js.map +1 -1
  15. package/index.d.ts +2 -2
  16. package/index.js +2 -2
  17. package/package.json +4 -6
  18. package/packages/tiny-markdown/src/context/index.d.ts +1 -0
  19. package/packages/tiny-markdown/src/context/tiny-markdown-context.d.ts +3 -0
  20. package/packages/tiny-markdown/src/hooks/index.d.ts +4 -0
  21. package/packages/tiny-markdown/src/hooks/use-caret-position.d.ts +1 -0
  22. package/packages/tiny-markdown/src/hooks/use-tiny-markdown.d.ts +1 -0
  23. package/packages/tiny-markdown/src/hooks/use-tiny-mention.d.ts +1 -0
  24. package/packages/tiny-markdown/src/hooks/use-tiny-shortcuts.d.ts +1 -0
  25. package/packages/tiny-markdown/src/index.d.ts +4 -0
  26. package/packages/tiny-markdown/src/types.d.ts +75 -0
  27. package/packages/tiny-markdown/src/types.d.ts.map +1 -0
  28. package/packages/tiny-markdown/src/utils/index.d.ts +3 -0
  29. package/packages/tiny-markdown/src/utils/markdown-parser.d.ts +1 -0
  30. package/packages/tiny-markdown/src/utils/mention-parser.d.ts +1 -0
  31. package/packages/tiny-markdown/src/utils/merge-refs.d.ts +1 -0
  32. package/packages/types/src/api/conversation.d.ts +316 -12
  33. package/packages/types/src/api/conversation.d.ts.map +1 -1
  34. package/packages/types/src/api/timeline-item.d.ts +236 -9
  35. package/packages/types/src/api/timeline-item.d.ts.map +1 -1
  36. package/packages/types/src/realtime-events.d.ts +259 -13
  37. package/packages/types/src/realtime-events.d.ts.map +1 -1
  38. package/packages/types/src/schemas.d.ts +79 -3
  39. package/packages/types/src/schemas.d.ts.map +1 -1
  40. package/primitives/avatar/image.d.ts +1 -1
  41. package/primitives/command-block-utils.d.ts +26 -0
  42. package/primitives/command-block-utils.d.ts.map +1 -0
  43. package/primitives/command-block-utils.js +310 -0
  44. package/primitives/command-block-utils.js.map +1 -0
  45. package/primitives/index.d.ts +7 -3
  46. package/primitives/index.js +11 -2
  47. package/primitives/index.parts.d.ts +6 -2
  48. package/primitives/index.parts.js +5 -1
  49. package/primitives/multimodal-input.d.ts +2 -2
  50. package/primitives/multimodal-input.d.ts.map +1 -1
  51. package/primitives/timeline-code-block.d.ts +32 -0
  52. package/primitives/timeline-code-block.d.ts.map +1 -0
  53. package/primitives/timeline-code-block.js +66 -0
  54. package/primitives/timeline-code-block.js.map +1 -0
  55. package/primitives/timeline-command-block.d.ts +29 -0
  56. package/primitives/timeline-command-block.d.ts.map +1 -0
  57. package/primitives/timeline-command-block.js +97 -0
  58. package/primitives/timeline-command-block.js.map +1 -0
  59. package/primitives/timeline-item-group.d.ts.map +1 -1
  60. package/primitives/timeline-item-group.js +5 -15
  61. package/primitives/timeline-item-group.js.map +1 -1
  62. package/primitives/timeline-item.d.ts +23 -3
  63. package/primitives/timeline-item.d.ts.map +1 -1
  64. package/primitives/timeline-item.js +151 -80
  65. package/primitives/timeline-item.js.map +1 -1
  66. package/primitives/timeline-message-layout.d.ts +9 -0
  67. package/primitives/timeline-message-layout.d.ts.map +1 -0
  68. package/primitives/timeline-message-layout.js +20 -0
  69. package/primitives/timeline-message-layout.js.map +1 -0
  70. package/provider.d.ts.map +1 -1
  71. package/provider.js +6 -3
  72. package/provider.js.map +1 -1
  73. package/realtime/event-filter.js +4 -3
  74. package/realtime/event-filter.js.map +1 -1
  75. package/sounds/sound-data.d.ts +6 -0
  76. package/sounds/sound-data.d.ts.map +1 -0
  77. package/sounds/sound-data.js +7 -0
  78. package/sounds/sound-data.js.map +1 -0
  79. package/support/components/avatar-stack.js +1 -1
  80. package/support/components/avatar-stack.js.map +1 -1
  81. package/support/components/avatar.d.ts +1 -2
  82. package/support/components/avatar.d.ts.map +1 -1
  83. package/support/components/avatar.js +9 -7
  84. package/support/components/avatar.js.map +1 -1
  85. package/support/components/button.d.ts +2 -2
  86. package/support/components/button.d.ts.map +1 -1
  87. package/support/components/button.js +1 -0
  88. package/support/components/button.js.map +1 -1
  89. package/support/components/conversation-button-link.js +2 -1
  90. package/support/components/conversation-button-link.js.map +1 -1
  91. package/support/components/conversation-event.d.ts +3 -0
  92. package/support/components/conversation-event.d.ts.map +1 -1
  93. package/support/components/conversation-event.js +46 -15
  94. package/support/components/conversation-event.js.map +1 -1
  95. package/support/components/conversation-resolved-feedback.d.ts +1 -1
  96. package/support/components/conversation-resolved-feedback.d.ts.map +1 -1
  97. package/support/components/conversation-resolved-feedback.js +56 -13
  98. package/support/components/conversation-resolved-feedback.js.map +1 -1
  99. package/support/components/conversation-timeline.d.ts.map +1 -1
  100. package/support/components/conversation-timeline.js +12 -0
  101. package/support/components/conversation-timeline.js.map +1 -1
  102. package/support/components/index.d.ts +2 -1
  103. package/support/components/index.js +2 -1
  104. package/support/components/timeline-activity-group.d.ts +25 -0
  105. package/support/components/timeline-activity-group.d.ts.map +1 -0
  106. package/support/components/timeline-activity-group.js +104 -0
  107. package/support/components/timeline-activity-group.js.map +1 -0
  108. package/support/components/timeline-code-block.d.ts +14 -0
  109. package/support/components/timeline-code-block.d.ts.map +1 -0
  110. package/support/components/timeline-code-block.js +44 -0
  111. package/support/components/timeline-code-block.js.map +1 -0
  112. package/support/components/timeline-command-block.d.ts +12 -0
  113. package/support/components/timeline-command-block.d.ts.map +1 -0
  114. package/support/components/timeline-command-block.js +42 -0
  115. package/support/components/timeline-command-block.js.map +1 -0
  116. package/support/components/timeline-message-item.d.ts +2 -1
  117. package/support/components/timeline-message-item.d.ts.map +1 -1
  118. package/support/components/timeline-message-item.js +23 -3
  119. package/support/components/timeline-message-item.js.map +1 -1
  120. package/support/components/typing-indicator.d.ts.map +1 -1
  121. package/support/components/typing-indicator.js +15 -7
  122. package/support/components/typing-indicator.js.map +1 -1
  123. package/support/index.d.ts +4 -4
  124. package/support/pages/conversation-history.js +1 -1
  125. package/support/pages/conversation.js +4 -2
  126. package/support/pages/conversation.js.map +1 -1
  127. package/support/pages/home.js +1 -1
  128. package/support/store/support-store.d.ts +5 -5
  129. package/support/text/locales/en.js +3 -0
  130. package/support/text/locales/en.js.map +1 -1
  131. package/support/text/locales/es.js +3 -0
  132. package/support/text/locales/es.js.map +1 -1
  133. package/support/text/locales/fr.js +3 -0
  134. package/support/text/locales/fr.js.map +1 -1
  135. package/support/text/locales/keys.d.ts +9 -0
  136. package/support/text/locales/keys.d.ts.map +1 -1
  137. package/support/text/locales/keys.js +3 -0
  138. package/support/text/locales/keys.js.map +1 -1
  139. package/utils/metadata-hash.d.ts +1 -1
  140. package/utils/metadata-hash.js +9 -4
  141. package/utils/metadata-hash.js.map +1 -1
  142. package/utils/timeline-item-sender.d.ts +17 -0
  143. package/utils/timeline-item-sender.d.ts.map +1 -0
  144. package/utils/timeline-item-sender.js +43 -0
  145. package/utils/timeline-item-sender.js.map +1 -0
@@ -1 +1 @@
1
- {"version":3,"file":"timeline-item.js","names":["React","renderProps: TimelineItemRenderProps"],"sources":["../../src/primitives/timeline-item.tsx"],"sourcesContent":["import type { TimelineItem as TimelineItemType } from \"@cossistant/types/api/timeline-item\";\nimport * as React from \"react\";\nimport ReactMarkdown from \"react-markdown\";\nimport remarkBreaks from \"remark-breaks\";\nimport { useRenderElement } from \"../utils/use-render-element\";\n\n/**\n * Metadata describing the origin of a timeline item and pre-parsed content that can\n * be consumed by render-prop children.\n */\nexport type TimelineItemRenderProps = {\n\tisVisitor: boolean;\n\tisAI: boolean;\n\tisHuman: boolean;\n\ttimestamp: Date;\n\ttext: string | null;\n\tsenderType: \"visitor\" | \"ai\" | \"human\";\n\titemType: \"message\" | \"event\" | \"identification\";\n};\n\nexport type TimelineItemProps = Omit<\n\tReact.HTMLAttributes<HTMLDivElement>,\n\t\"children\"\n> & {\n\tchildren?:\n\t\t| React.ReactNode\n\t\t| ((props: TimelineItemRenderProps) => React.ReactNode);\n\tasChild?: boolean;\n\tclassName?: string;\n\titem: TimelineItemType;\n};\n\n/**\n * Generic timeline item wrapper that adds accessibility attributes and resolves the\n * sender type into convenient render props for custom layouts. Works with\n * both MESSAGE and EVENT timeline item types.\n */\nexport const TimelineItem = (() => {\n\tconst Component = React.forwardRef<HTMLDivElement, TimelineItemProps>(\n\t\t({ children, className, asChild = false, item, ...props }, ref) => {\n\t\t\t// Determine sender type from timeline item properties\n\t\t\tconst isVisitor = item.visitorId !== null;\n\t\t\tconst isAI = item.aiAgentId !== null;\n\t\t\tconst isHuman = item.userId !== null && !isVisitor;\n\n\t\t\tconst senderType = isVisitor ? \"visitor\" : isAI ? \"ai\" : \"human\";\n\n\t\t\tconst renderProps: TimelineItemRenderProps = {\n\t\t\t\tisVisitor,\n\t\t\t\tisAI,\n\t\t\t\tisHuman,\n\t\t\t\ttimestamp: new Date(item.createdAt),\n\t\t\t\ttext: item.text,\n\t\t\t\tsenderType,\n\t\t\t\titemType: item.type,\n\t\t\t};\n\n\t\t\tconst content =\n\t\t\t\ttypeof children === \"function\" ? children(renderProps) : children;\n\n\t\t\tconst itemTypeLabel = (() => {\n\t\t\t\tif (item.type === \"event\") {\n\t\t\t\t\treturn \"Event\";\n\t\t\t\t}\n\t\t\t\tif (item.type === \"identification\") {\n\t\t\t\t\treturn \"Identification\";\n\t\t\t\t}\n\t\t\t\tif (isVisitor) {\n\t\t\t\t\treturn \"visitor\";\n\t\t\t\t}\n\t\t\t\tif (isAI) {\n\t\t\t\t\treturn \"AI assistant\";\n\t\t\t\t}\n\t\t\t\treturn \"human agent\";\n\t\t\t})();\n\n\t\t\treturn useRenderElement(\n\t\t\t\t\"div\",\n\t\t\t\t{\n\t\t\t\t\tclassName,\n\t\t\t\t\tasChild,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tref,\n\t\t\t\t\tstate: renderProps,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\trole: \"article\",\n\t\t\t\t\t\t\"aria-label\": `${item.type === \"message\" ? \"Message\" : \"Event\"} from ${itemTypeLabel}`,\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tchildren: content,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n\n\tComponent.displayName = \"TimelineItem\";\n\treturn Component;\n})();\n\nconst MemoizedMarkdownBlock = React.memo(\n\t({ content }: { content: string }) => {\n\t\treturn (\n\t\t\t<ReactMarkdown\n\t\t\t\t// Allow mention: protocol URLs (not sanitized by default)\n\t\t\t\tcomponents={{\n\t\t\t\t\t// Render paragraphs as block elements to preserve multiline spacing\n\t\t\t\t\tp: ({ children }) => {\n\t\t\t\t\t\t// Skip empty paragraphs (caused by consecutive blank lines in markdown)\n\t\t\t\t\t\tconst isEmpty =\n\t\t\t\t\t\t\tchildren === undefined ||\n\t\t\t\t\t\t\tchildren === null ||\n\t\t\t\t\t\t\tchildren === \"\" ||\n\t\t\t\t\t\t\t(Array.isArray(children) &&\n\t\t\t\t\t\t\t\tchildren.every((c) => c === \"\\n\" || c === \"\" || c == null));\n\t\t\t\t\t\tif (isEmpty) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn <span className=\"mt-1 block first:mt-0\">{children}</span>;\n\t\t\t\t\t},\n\t\t\t\t\t// Ensure proper line break handling\n\t\t\t\t\tbr: () => <br />,\n\t\t\t\t\t// Handle code blocks properly\n\t\t\t\t\tcode: ({ children, ...props }) => {\n\t\t\t\t\t\t// Check if it's inline code by looking at the parent element\n\t\t\t\t\t\tconst isInline = !(\n\t\t\t\t\t\t\t\"className\" in props &&\n\t\t\t\t\t\t\ttypeof props.className === \"string\" &&\n\t\t\t\t\t\t\tprops.className.includes(\"language-\")\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn isInline ? (\n\t\t\t\t\t\t\t<code className=\"rounded bg-co-background-300 px-1 py-0.5 text-xs\">\n\t\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t\t</code>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<pre className=\"overflow-x-auto rounded bg-co-background-300 p-2\">\n\t\t\t\t\t\t\t\t<code className=\"text-xs\">{children}</code>\n\t\t\t\t\t\t\t</pre>\n\t\t\t\t\t\t);\n\t\t\t\t\t},\n\t\t\t\t\t// Handle strong/bold text\n\t\t\t\t\tstrong: ({ children }) => (\n\t\t\t\t\t\t<strong className=\"font-semibold\">{children}</strong>\n\t\t\t\t\t),\n\t\t\t\t\t// Handle ordered lists\n\t\t\t\t\tol: ({ children }) => (\n\t\t\t\t\t\t<ol className=\"my-0 list-decimal pl-6\">{children}</ol>\n\t\t\t\t\t),\n\t\t\t\t\t// Handle unordered lists\n\t\t\t\t\tul: ({ children }) => (\n\t\t\t\t\t\t<ul className=\"my-0 list-disc pl-6\">{children}</ul>\n\t\t\t\t\t),\n\t\t\t\t\t// Handle list items\n\t\t\t\t\tli: ({ children }) => (\n\t\t\t\t\t\t<li className=\"[&>span.block]:mt-0 [&>span.block]:inline\">\n\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t),\n\t\t\t\t\t// Handle blockquotes\n\t\t\t\t\tblockquote: ({ children }) => (\n\t\t\t\t\t\t<blockquote className=\"my-1 border-co-border border-l-2 pl-3 italic opacity-80\">\n\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t</blockquote>\n\t\t\t\t\t),\n\t\t\t\t\t// Handle emphasis\n\t\t\t\t\tem: ({ children }) => <em className=\"italic\">{children}</em>,\n\t\t\t\t\t// Handle links - with special handling for mentions\n\t\t\t\t\t// Mention format: [@Name](mention:type:id) - the @ is inside the link\n\t\t\t\t\ta: ({ href, children, node }) => {\n\t\t\t\t\t\t// Get the raw href from the AST node if available (react-markdown may sanitize href)\n\t\t\t\t\t\tconst rawHref =\n\t\t\t\t\t\t\thref || (node?.properties?.href as string | undefined) || \"\";\n\n\t\t\t\t\t\t// Check if this is a mention link: mention:type:id\n\t\t\t\t\t\tif (rawHref.startsWith(\"mention:\")) {\n\t\t\t\t\t\t\t// Parse mention:type:id format\n\t\t\t\t\t\t\tconst parts = rawHref.split(\":\");\n\t\t\t\t\t\t\tconst mentionType = parts[1]; // visitor, ai-agent, human-agent\n\t\t\t\t\t\t\tconst mentionId = parts.slice(2).join(\":\"); // id (may contain colons)\n\n\t\t\t\t\t\t\t// Render as styled orange pill (same design as input)\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tclassName=\"rounded bg-co-orange/15 font-medium text-co-orange\"\n\t\t\t\t\t\t\t\t\tdata-mention-id={mentionId}\n\t\t\t\t\t\t\t\t\tdata-mention-type={mentionType}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Regular link\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\tclassName=\"underline hover:opacity-80\"\n\t\t\t\t\t\t\t\thref={href}\n\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t);\n\t\t\t\t\t},\n\t\t\t\t}}\n\t\t\t\tremarkPlugins={[remarkBreaks]}\n\t\t\t\turlTransform={(url) => url}\n\t\t\t>\n\t\t\t\t{content}\n\t\t\t</ReactMarkdown>\n\t\t);\n\t},\n\t(prevProps, nextProps) => {\n\t\tif (prevProps.content !== nextProps.content) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n);\n\nMemoizedMarkdownBlock.displayName = \"MemoizedMarkdownBlock\";\n\nexport type TimelineItemContentProps = Omit<\n\tReact.HTMLAttributes<HTMLDivElement>,\n\t\"children\"\n> & {\n\tchildren?: React.ReactNode | ((content: string) => React.ReactNode);\n\tasChild?: boolean;\n\tclassName?: string;\n\ttext?: string | null;\n\trenderMarkdown?: boolean;\n};\n\n/**\n * Renders the content of a timeline item, optionally piping Markdown content through a\n * memoised renderer or handing the raw text to a render prop for custom\n * formatting.\n */\nexport const TimelineItemContent = (() => {\n\tconst Component = React.forwardRef<HTMLDivElement, TimelineItemContentProps>(\n\t\t(\n\t\t\t{\n\t\t\t\tchildren,\n\t\t\t\tclassName,\n\t\t\t\tasChild = false,\n\t\t\t\ttext = \"\",\n\t\t\t\trenderMarkdown = true,\n\t\t\t\t...props\n\t\t\t},\n\t\t\tref\n\t\t) => {\n\t\t\tconst content = React.useMemo(() => {\n\t\t\t\tconst textContent = text ?? \"\";\n\t\t\t\tif (typeof children === \"function\") {\n\t\t\t\t\treturn children(textContent);\n\t\t\t\t}\n\t\t\t\tif (children) {\n\t\t\t\t\treturn children;\n\t\t\t\t}\n\t\t\t\tif (renderMarkdown && textContent) {\n\t\t\t\t\treturn <MemoizedMarkdownBlock content={textContent} />;\n\t\t\t\t}\n\t\t\t\treturn textContent;\n\t\t\t}, [children, text, renderMarkdown]);\n\n\t\t\treturn useRenderElement(\n\t\t\t\t\"div\",\n\t\t\t\t{\n\t\t\t\t\tclassName,\n\t\t\t\t\tasChild,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tref,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tchildren: content,\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t...props.style,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n\n\tComponent.displayName = \"TimelineItemContent\";\n\treturn Component;\n})();\n\nexport type TimelineItemTimestampProps = Omit<\n\tReact.HTMLAttributes<HTMLSpanElement>,\n\t\"children\"\n> & {\n\tchildren?: React.ReactNode | ((timestamp: Date) => React.ReactNode);\n\tasChild?: boolean;\n\tclassName?: string;\n\ttimestamp: Date;\n\tformat?: (date: Date) => string;\n};\n\n/**\n * Timestamp helper that renders a formatted date or allows callers to supply a\n * render prop for custom time displays while preserving semantic markup.\n */\nexport const TimelineItemTimestamp = (() => {\n\tconst Component = React.forwardRef<\n\t\tHTMLSpanElement,\n\t\tTimelineItemTimestampProps\n\t>(\n\t\t(\n\t\t\t{\n\t\t\t\tchildren,\n\t\t\t\tclassName,\n\t\t\t\tasChild = false,\n\t\t\t\ttimestamp,\n\t\t\t\tformat = (date) =>\n\t\t\t\t\tdate.toLocaleTimeString([], {\n\t\t\t\t\t\thour: \"2-digit\",\n\t\t\t\t\t\tminute: \"2-digit\",\n\t\t\t\t\t}),\n\t\t\t\t...props\n\t\t\t},\n\t\t\tref\n\t\t) => {\n\t\t\tconst content =\n\t\t\t\ttypeof children === \"function\"\n\t\t\t\t\t? children(timestamp)\n\t\t\t\t\t: children || format(timestamp);\n\n\t\t\treturn useRenderElement(\n\t\t\t\t\"span\",\n\t\t\t\t{\n\t\t\t\t\tclassName,\n\t\t\t\t\tasChild,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tref,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tchildren: content,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n\n\tComponent.displayName = \"TimelineItemTimestamp\";\n\treturn Component;\n})();\n"],"mappings":"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"}
1
+ {"version":3,"file":"timeline-item.js","names":["React","renderProps: TimelineItemRenderProps"],"sources":["../../src/primitives/timeline-item.tsx"],"sourcesContent":["import type { MarkdownToken } from \"@cossistant/tiny-markdown\";\nimport {\n\thasMarkdownFormatting,\n\tparseMarkdown,\n} from \"@cossistant/tiny-markdown/utils\";\nimport type { TimelineItem as TimelineItemType } from \"@cossistant/types/api/timeline-item\";\nimport * as React from \"react\";\nimport { useRenderElement } from \"../utils/use-render-element\";\nimport {\n\ttype CommandVariants,\n\tmapCommandVariants,\n\tmapInlineCommandFromParagraphChildren,\n} from \"./command-block-utils\";\nimport { TimelineCodeBlock } from \"./timeline-code-block\";\nimport { TimelineCommandBlock } from \"./timeline-command-block\";\n\n/**\n * Metadata describing the origin of a timeline item and pre-parsed content that can\n * be consumed by render-prop children.\n */\nexport type TimelineItemRenderProps = {\n\tisVisitor: boolean;\n\tisAI: boolean;\n\tisHuman: boolean;\n\ttimestamp: Date;\n\ttext: string | null;\n\tsenderType: \"visitor\" | \"ai\" | \"human\";\n\titemType: \"message\" | \"event\" | \"identification\" | \"tool\";\n};\n\nexport type TimelineItemProps = Omit<\n\tReact.HTMLAttributes<HTMLDivElement>,\n\t\"children\"\n> & {\n\tchildren?:\n\t\t| React.ReactNode\n\t\t| ((props: TimelineItemRenderProps) => React.ReactNode);\n\tasChild?: boolean;\n\tclassName?: string;\n\titem: TimelineItemType;\n};\n\n/**\n * Generic timeline item wrapper that adds accessibility attributes and resolves the\n * sender type into convenient render props for custom layouts. Works with\n * message, event, identification, and tool timeline item types.\n */\nexport const TimelineItem = (() => {\n\tconst Component = React.forwardRef<HTMLDivElement, TimelineItemProps>(\n\t\t({ children, className, asChild = false, item, ...props }, ref) => {\n\t\t\t// Determine sender type from timeline item properties\n\t\t\tconst isVisitor = item.visitorId !== null;\n\t\t\tconst isAI = item.aiAgentId !== null;\n\t\t\tconst isHuman = item.userId !== null && !isVisitor;\n\n\t\t\tconst senderType = isVisitor ? \"visitor\" : isAI ? \"ai\" : \"human\";\n\n\t\t\tconst renderProps: TimelineItemRenderProps = {\n\t\t\t\tisVisitor,\n\t\t\t\tisAI,\n\t\t\t\tisHuman,\n\t\t\t\ttimestamp: new Date(item.createdAt),\n\t\t\t\ttext: item.text,\n\t\t\t\tsenderType,\n\t\t\t\titemType: item.type,\n\t\t\t};\n\n\t\t\tconst content =\n\t\t\t\ttypeof children === \"function\" ? children(renderProps) : children;\n\n\t\t\tconst itemTypeLabel = (() => {\n\t\t\t\tif (item.type === \"event\") {\n\t\t\t\t\treturn \"Event\";\n\t\t\t\t}\n\t\t\t\tif (item.type === \"identification\") {\n\t\t\t\t\treturn \"Identification\";\n\t\t\t\t}\n\t\t\t\tif (item.type === \"tool\") {\n\t\t\t\t\treturn \"Tool call\";\n\t\t\t\t}\n\t\t\t\tif (isVisitor) {\n\t\t\t\t\treturn \"visitor\";\n\t\t\t\t}\n\t\t\t\tif (isAI) {\n\t\t\t\t\treturn \"AI assistant\";\n\t\t\t\t}\n\t\t\t\treturn \"human agent\";\n\t\t\t})();\n\n\t\t\treturn useRenderElement(\n\t\t\t\t\"div\",\n\t\t\t\t{\n\t\t\t\t\tclassName,\n\t\t\t\t\tasChild,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tref,\n\t\t\t\t\tstate: renderProps,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\trole: \"article\",\n\t\t\t\t\t\t\"aria-label\": `${item.type === \"message\" ? \"Message\" : item.type === \"tool\" ? \"Tool call\" : \"Event\"} from ${itemTypeLabel}`,\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tchildren: content,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n\n\tComponent.displayName = \"TimelineItem\";\n\treturn Component;\n})();\n\nfunction parseMentionHref(\n\thref: string\n): { mentionType: string; mentionId: string } | null {\n\tif (!href.startsWith(\"mention:\")) {\n\t\treturn null;\n\t}\n\n\tconst parts = href.split(\":\");\n\tconst mentionType = parts[1];\n\tconst mentionId = parts.slice(2).join(\":\");\n\n\tif (!(mentionType && mentionId)) {\n\t\treturn null;\n\t}\n\n\treturn { mentionType, mentionId };\n}\n\nexport type TimelineInlineCodeRendererProps = {\n\tcode: string;\n};\n\nexport type TimelineCodeBlockRendererProps = {\n\tcode: string;\n\tlanguage?: string;\n\tfileName?: string;\n};\n\nexport type TimelineCommandBlockRendererProps = {\n\tcommand: string;\n\tcommands: CommandVariants;\n};\n\nexport type TimelineItemContentMarkdownRenderers = {\n\tinlineCode?: (props: TimelineInlineCodeRendererProps) => React.ReactNode;\n\tcodeBlock?: (props: TimelineCodeBlockRendererProps) => React.ReactNode;\n\tcommandBlock?: (props: TimelineCommandBlockRendererProps) => React.ReactNode;\n};\n\nfunction renderInlineCode(\n\tcode: string,\n\tkey: string,\n\trenderers?: TimelineItemContentMarkdownRenderers\n): React.ReactNode {\n\tif (renderers?.inlineCode) {\n\t\treturn (\n\t\t\t<React.Fragment key={key}>\n\t\t\t\t{renderers.inlineCode({ code })}\n\t\t\t</React.Fragment>\n\t\t);\n\t}\n\n\treturn <code key={key}>{code}</code>;\n}\n\nfunction renderCodeBlock(\n\tprops: TimelineCodeBlockRendererProps,\n\tkey: string,\n\trenderers?: TimelineItemContentMarkdownRenderers\n): React.ReactNode {\n\tif (renderers?.codeBlock) {\n\t\treturn (\n\t\t\t<React.Fragment key={key}>{renderers.codeBlock(props)}</React.Fragment>\n\t\t);\n\t}\n\n\treturn (\n\t\t<TimelineCodeBlock\n\t\t\tcode={props.code}\n\t\t\tfileName={props.fileName}\n\t\t\tkey={key}\n\t\t\tlanguage={props.language}\n\t\t/>\n\t);\n}\n\nfunction renderCommandBlock(\n\tprops: TimelineCommandBlockRendererProps,\n\tkey: string,\n\trenderers?: TimelineItemContentMarkdownRenderers\n): React.ReactNode {\n\tif (renderers?.commandBlock) {\n\t\treturn (\n\t\t\t<React.Fragment key={key}>{renderers.commandBlock(props)}</React.Fragment>\n\t\t);\n\t}\n\n\treturn <TimelineCommandBlock commands={props.commands} key={key} />;\n}\n\nfunction hasNonWhitespaceParagraphContent(children: MarkdownToken[]): boolean {\n\treturn children.some(\n\t\t(child) => child.type !== \"text\" || child.content.trim().length > 0\n\t);\n}\n\nfunction renderMarkdownToken(\n\ttoken: MarkdownToken,\n\tkey: string,\n\trenderers?: TimelineItemContentMarkdownRenderers\n): React.ReactNode {\n\tswitch (token.type) {\n\t\tcase \"text\":\n\t\t\treturn token.content;\n\t\tcase \"strong\":\n\t\t\treturn (\n\t\t\t\t<strong className=\"font-semibold\" key={key}>\n\t\t\t\t\t{token.children.map((child, index) =>\n\t\t\t\t\t\trenderMarkdownToken(child, `${key}-${index}`, renderers)\n\t\t\t\t\t)}\n\t\t\t\t</strong>\n\t\t\t);\n\t\tcase \"em\":\n\t\t\treturn (\n\t\t\t\t<em className=\"italic\" key={key}>\n\t\t\t\t\t{token.children.map((child, index) =>\n\t\t\t\t\t\trenderMarkdownToken(child, `${key}-${index}`, renderers)\n\t\t\t\t\t)}\n\t\t\t\t</em>\n\t\t\t);\n\t\tcase \"code\": {\n\t\t\tif (token.inline) {\n\t\t\t\treturn renderInlineCode(token.content, key, renderers);\n\t\t\t}\n\n\t\t\tconst commandVariants = mapCommandVariants(token.content);\n\t\t\tif (commandVariants) {\n\t\t\t\treturn renderCommandBlock(\n\t\t\t\t\t{\n\t\t\t\t\t\tcommand: token.content,\n\t\t\t\t\t\tcommands: commandVariants,\n\t\t\t\t\t},\n\t\t\t\t\tkey,\n\t\t\t\t\trenderers\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn renderCodeBlock(\n\t\t\t\t{\n\t\t\t\t\tcode: token.content,\n\t\t\t\t\tfileName: token.fileName,\n\t\t\t\t\tlanguage: token.language,\n\t\t\t\t},\n\t\t\t\tkey,\n\t\t\t\trenderers\n\t\t\t);\n\t\t}\n\t\tcase \"p\": {\n\t\t\tconst inlineCommand = mapInlineCommandFromParagraphChildren(\n\t\t\t\ttoken.children\n\t\t\t);\n\t\t\tif (inlineCommand) {\n\t\t\t\tconst beforeChildren = token.children.slice(0, inlineCommand.index);\n\t\t\t\tconst afterChildren = token.children.slice(inlineCommand.index + 1);\n\t\t\t\tconst hasBefore = hasNonWhitespaceParagraphContent(beforeChildren);\n\t\t\t\tconst hasAfter = hasNonWhitespaceParagraphContent(afterChildren);\n\n\t\t\t\tif (!(hasBefore || hasAfter)) {\n\t\t\t\t\treturn renderCommandBlock(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcommand: inlineCommand.command,\n\t\t\t\t\t\t\tcommands: inlineCommand.variants,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\trenderers\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn (\n\t\t\t\t\t<div className=\"mt-1 block first:mt-0\" key={key}>\n\t\t\t\t\t\t{hasBefore ? (\n\t\t\t\t\t\t\t<span className=\"block\">\n\t\t\t\t\t\t\t\t{beforeChildren.map((child, index) =>\n\t\t\t\t\t\t\t\t\trenderMarkdownToken(\n\t\t\t\t\t\t\t\t\t\tchild,\n\t\t\t\t\t\t\t\t\t\t`${key}-before-${index}`,\n\t\t\t\t\t\t\t\t\t\trenderers\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t) : null}\n\n\t\t\t\t\t\t{renderCommandBlock(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcommand: inlineCommand.command,\n\t\t\t\t\t\t\t\tcommands: inlineCommand.variants,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t`${key}-command`,\n\t\t\t\t\t\t\trenderers\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{hasAfter ? (\n\t\t\t\t\t\t\t<span className=\"mt-1 block\">\n\t\t\t\t\t\t\t\t{afterChildren.map((child, index) =>\n\t\t\t\t\t\t\t\t\trenderMarkdownToken(child, `${key}-after-${index}`, renderers)\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn (\n\t\t\t\t<span className=\"mt-1 block first:mt-0\" key={key}>\n\t\t\t\t\t{token.children.map((child, index) =>\n\t\t\t\t\t\trenderMarkdownToken(child, `${key}-${index}`, renderers)\n\t\t\t\t\t)}\n\t\t\t\t</span>\n\t\t\t);\n\t\t}\n\t\tcase \"blockquote\":\n\t\t\treturn (\n\t\t\t\t<blockquote\n\t\t\t\t\tclassName=\"my-1 border-co-border border-l-2 pl-3 italic opacity-80\"\n\t\t\t\t\tkey={key}\n\t\t\t\t>\n\t\t\t\t\t{token.children.map((child, index) =>\n\t\t\t\t\t\trenderMarkdownToken(child, `${key}-${index}`, renderers)\n\t\t\t\t\t)}\n\t\t\t\t</blockquote>\n\t\t\t);\n\t\tcase \"ul\":\n\t\t\treturn (\n\t\t\t\t<ul className=\"my-0 list-disc pl-6\" key={key}>\n\t\t\t\t\t{token.children.map((child, index) =>\n\t\t\t\t\t\trenderMarkdownToken(child, `${key}-${index}`, renderers)\n\t\t\t\t\t)}\n\t\t\t\t</ul>\n\t\t\t);\n\t\tcase \"ol\":\n\t\t\treturn (\n\t\t\t\t<ol className=\"my-0 list-decimal pl-6\" key={key}>\n\t\t\t\t\t{token.children.map((child, index) =>\n\t\t\t\t\t\trenderMarkdownToken(child, `${key}-${index}`, renderers)\n\t\t\t\t\t)}\n\t\t\t\t</ol>\n\t\t\t);\n\t\tcase \"li\":\n\t\t\treturn (\n\t\t\t\t<li className=\"[&>span.block]:mt-0 [&>span.block]:inline\" key={key}>\n\t\t\t\t\t{token.children.map((child, index) =>\n\t\t\t\t\t\trenderMarkdownToken(child, `${key}-${index}`, renderers)\n\t\t\t\t\t)}\n\t\t\t\t</li>\n\t\t\t);\n\t\tcase \"a\": {\n\t\t\tconst mention = parseMentionHref(token.href);\n\n\t\t\tif (mention) {\n\t\t\t\treturn (\n\t\t\t\t\t<span\n\t\t\t\t\t\tclassName=\"rounded bg-co-orange/15 font-medium text-co-orange\"\n\t\t\t\t\t\tdata-mention-id={mention.mentionId}\n\t\t\t\t\t\tdata-mention-type={mention.mentionType}\n\t\t\t\t\t\tkey={key}\n\t\t\t\t\t>\n\t\t\t\t\t\t{token.children.map((child, index) =>\n\t\t\t\t\t\t\trenderMarkdownToken(child, `${key}-${index}`, renderers)\n\t\t\t\t\t\t)}\n\t\t\t\t\t</span>\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn (\n\t\t\t\t<a\n\t\t\t\t\tclassName=\"underline hover:opacity-80\"\n\t\t\t\t\thref={token.href}\n\t\t\t\t\tkey={key}\n\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t>\n\t\t\t\t\t{token.children.map((child, index) =>\n\t\t\t\t\t\trenderMarkdownToken(child, `${key}-${index}`, renderers)\n\t\t\t\t\t)}\n\t\t\t\t</a>\n\t\t\t);\n\t\t}\n\t\tcase \"mention\":\n\t\t\treturn (\n\t\t\t\t<span\n\t\t\t\t\tclassName=\"rounded bg-co-orange/15 font-medium text-co-orange\"\n\t\t\t\t\tdata-mention-id={token.mention.id}\n\t\t\t\t\tdata-mention-type={token.mention.type}\n\t\t\t\t\tkey={key}\n\t\t\t\t>\n\t\t\t\t\t@{token.mention.name}\n\t\t\t\t</span>\n\t\t\t);\n\t\tcase \"header\": {\n\t\t\tconst headerClass =\n\t\t\t\ttoken.level === 1\n\t\t\t\t\t? \"mt-1 block text-base font-semibold first:mt-0\"\n\t\t\t\t\t: token.level === 2\n\t\t\t\t\t\t? \"mt-1 block text-sm font-semibold first:mt-0\"\n\t\t\t\t\t\t: \"mt-1 block text-sm font-medium first:mt-0\";\n\n\t\t\treturn (\n\t\t\t\t<span className={headerClass} key={key}>\n\t\t\t\t\t{token.children.map((child, index) =>\n\t\t\t\t\t\trenderMarkdownToken(child, `${key}-${index}`, renderers)\n\t\t\t\t\t)}\n\t\t\t\t</span>\n\t\t\t);\n\t\t}\n\t\tcase \"br\":\n\t\t\treturn <br key={key} />;\n\t\tdefault:\n\t\t\treturn null;\n\t}\n}\n\nconst MemoizedMarkdownBlock = React.memo(\n\t({\n\t\tcontent,\n\t\tmarkdownRenderers,\n\t}: {\n\t\tcontent: string;\n\t\tmarkdownRenderers?: TimelineItemContentMarkdownRenderers;\n\t}) => {\n\t\tconst shouldRenderMarkdown = hasMarkdownFormatting(content);\n\n\t\tif (!shouldRenderMarkdown) {\n\t\t\treturn <span className=\"whitespace-pre-wrap break-words\">{content}</span>;\n\t\t}\n\n\t\tconst tokens = parseMarkdown(content);\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{tokens.map((token, index) =>\n\t\t\t\t\trenderMarkdownToken(token, `markdown-${index}`, markdownRenderers)\n\t\t\t\t)}\n\t\t\t</>\n\t\t);\n\t},\n\t(prevProps, nextProps) =>\n\t\tprevProps.content === nextProps.content &&\n\t\tprevProps.markdownRenderers === nextProps.markdownRenderers\n);\n\nMemoizedMarkdownBlock.displayName = \"MemoizedMarkdownBlock\";\n\nexport type TimelineItemContentProps = Omit<\n\tReact.HTMLAttributes<HTMLDivElement>,\n\t\"children\"\n> & {\n\tchildren?: React.ReactNode | ((content: string) => React.ReactNode);\n\tasChild?: boolean;\n\tclassName?: string;\n\ttext?: string | null;\n\trenderMarkdown?: boolean;\n\tmarkdownRenderers?: TimelineItemContentMarkdownRenderers;\n};\n\n/**\n * Renders the content of a timeline item, optionally piping Markdown content through a\n * memoised renderer or handing the raw text to a render prop for custom\n * formatting.\n */\nexport const TimelineItemContent = (() => {\n\tconst Component = React.forwardRef<HTMLDivElement, TimelineItemContentProps>(\n\t\t(\n\t\t\t{\n\t\t\t\tchildren,\n\t\t\t\tclassName,\n\t\t\t\tasChild = false,\n\t\t\t\ttext = \"\",\n\t\t\t\trenderMarkdown = true,\n\t\t\t\tmarkdownRenderers,\n\t\t\t\t...props\n\t\t\t},\n\t\t\tref\n\t\t) => {\n\t\t\tconst content = React.useMemo(() => {\n\t\t\t\tconst textContent = text ?? \"\";\n\t\t\t\tif (typeof children === \"function\") {\n\t\t\t\t\treturn children(textContent);\n\t\t\t\t}\n\t\t\t\tif (children) {\n\t\t\t\t\treturn children;\n\t\t\t\t}\n\t\t\t\tif (renderMarkdown && textContent) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<MemoizedMarkdownBlock\n\t\t\t\t\t\t\tcontent={textContent}\n\t\t\t\t\t\t\tmarkdownRenderers={markdownRenderers}\n\t\t\t\t\t\t/>\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn textContent;\n\t\t\t}, [children, markdownRenderers, text, renderMarkdown]);\n\n\t\t\treturn useRenderElement(\n\t\t\t\t\"div\",\n\t\t\t\t{\n\t\t\t\t\tclassName,\n\t\t\t\t\tasChild,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tref,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tchildren: content,\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\t...props.style,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n\n\tComponent.displayName = \"TimelineItemContent\";\n\treturn Component;\n})();\n\nexport type TimelineItemTimestampProps = Omit<\n\tReact.HTMLAttributes<HTMLSpanElement>,\n\t\"children\"\n> & {\n\tchildren?: React.ReactNode | ((timestamp: Date) => React.ReactNode);\n\tasChild?: boolean;\n\tclassName?: string;\n\ttimestamp: Date;\n\tformat?: (date: Date) => string;\n};\n\n/**\n * Timestamp helper that renders a formatted date or allows callers to supply a\n * render prop for custom time displays while preserving semantic markup.\n */\nexport const TimelineItemTimestamp = (() => {\n\tconst Component = React.forwardRef<\n\t\tHTMLSpanElement,\n\t\tTimelineItemTimestampProps\n\t>(\n\t\t(\n\t\t\t{\n\t\t\t\tchildren,\n\t\t\t\tclassName,\n\t\t\t\tasChild = false,\n\t\t\t\ttimestamp,\n\t\t\t\tformat = (date) =>\n\t\t\t\t\tdate.toLocaleTimeString([], {\n\t\t\t\t\t\thour: \"2-digit\",\n\t\t\t\t\t\tminute: \"2-digit\",\n\t\t\t\t\t}),\n\t\t\t\t...props\n\t\t\t},\n\t\t\tref\n\t\t) => {\n\t\t\tconst content =\n\t\t\t\ttypeof children === \"function\"\n\t\t\t\t\t? children(timestamp)\n\t\t\t\t\t: children || format(timestamp);\n\n\t\t\treturn useRenderElement(\n\t\t\t\t\"span\",\n\t\t\t\t{\n\t\t\t\t\tclassName,\n\t\t\t\t\tasChild,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tref,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tchildren: content,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n\n\tComponent.displayName = \"TimelineItemTimestamp\";\n\treturn Component;\n})();\n"],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ //#region src/primitives/timeline-message-layout.d.ts
2
+ /**
3
+ * Detects whether message text includes fenced code content that should use
4
+ * the expanded timeline bubble layout.
5
+ */
6
+ declare function hasExpandedTimelineContent(text: string | null | undefined): boolean;
7
+ //#endregion
8
+ export { hasExpandedTimelineContent };
9
+ //# sourceMappingURL=timeline-message-layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline-message-layout.d.ts","names":[],"sources":["../../src/primitives/timeline-message-layout.ts"],"sourcesContent":[],"mappings":";;AAOA;;;iBAAgB,0BAAA"}
@@ -0,0 +1,20 @@
1
+ import { mapInlineCommandFromParagraphChildren } from "./command-block-utils.js";
2
+ import { parseMarkdown } from "@cossistant/tiny-markdown/utils";
3
+
4
+ //#region src/primitives/timeline-message-layout.ts
5
+ /**
6
+ * Detects whether message text includes fenced code content that should use
7
+ * the expanded timeline bubble layout.
8
+ */
9
+ function hasExpandedTimelineContent(text) {
10
+ if (!text || text.trim().length === 0) return false;
11
+ return parseMarkdown(text).some((token) => {
12
+ if (token.type === "code" && token.inline === false) return true;
13
+ if (token.type === "p") return mapInlineCommandFromParagraphChildren(token.children) !== null;
14
+ return false;
15
+ });
16
+ }
17
+
18
+ //#endregion
19
+ export { hasExpandedTimelineContent };
20
+ //# sourceMappingURL=timeline-message-layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline-message-layout.js","names":[],"sources":["../../src/primitives/timeline-message-layout.ts"],"sourcesContent":["import { parseMarkdown } from \"@cossistant/tiny-markdown/utils\";\nimport { mapInlineCommandFromParagraphChildren } from \"./command-block-utils\";\n\n/**\n * Detects whether message text includes fenced code content that should use\n * the expanded timeline bubble layout.\n */\nexport function hasExpandedTimelineContent(\n\ttext: string | null | undefined\n): boolean {\n\tif (!text || text.trim().length === 0) {\n\t\treturn false;\n\t}\n\n\tconst tokens = parseMarkdown(text);\n\treturn tokens.some((token) => {\n\t\tif (token.type === \"code\" && token.inline === false) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (token.type === \"p\") {\n\t\t\treturn mapInlineCommandFromParagraphChildren(token.children) !== null;\n\t\t}\n\n\t\treturn false;\n\t});\n}\n"],"mappings":";;;;;;;;AAOA,SAAgB,2BACf,MACU;AACV,KAAI,CAAC,QAAQ,KAAK,MAAM,CAAC,WAAW,EACnC,QAAO;AAIR,QADe,cAAc,KAAK,CACpB,MAAM,UAAU;AAC7B,MAAI,MAAM,SAAS,UAAU,MAAM,WAAW,MAC7C,QAAO;AAGR,MAAI,MAAM,SAAS,IAClB,QAAO,sCAAsC,MAAM,SAAS,KAAK;AAGlE,SAAO;GACN"}
package/provider.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","names":[],"sources":["../src/provider.tsx"],"sourcesContent":[],"mappings":";;;;;;KAsEY,oBAAA;YACD,KAAA,CAAM;EADL,WAAA,CAAA,EAAA,OAAA;EACD,MAAM,CAAA,EAAA,MAAA;EAKE,KAAA,CAAA,EAAA,MAAA;EAKE,SAAA,CAAA,EAAA,MAAA;EAAK,eAAA,CAAA,EALP,cAKO,EAAA;EAId,YAAA,CAAA,EAAA,MAAA,EAAA;EAEA,WAAA,CAAA,EAAA,OAAA;EACF,WAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EACQ,cAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAEc,SAAA,CAAA,EAAA,CAAA,KAAA,EAVX,KAUW,EAAA,GAAA,IAAA;EAKxB,IAAA,CAAA,EAAA,QAAA,GAAA,QAAA;CACa;AACZ,KAbG,uBAAA,GAA0B,oBAa7B;AAAgB,KAXb,sBAAA,GAWa;EAOpB,OAAA,EAjBK,qBAiBqB,GAAA,IAAA;EAE1B,eAAA,EAlBa,cAkBI,EAAA;EAAG,YAAA,EAAA,MAAA,EAAA;EAEV,kBAAA,EAAA,CAAA,QAAA,EAlBiB,cAkBjB,EAAA,EAAA,GAAA,IAAA;EAAZ,eAAA,EAAA,CAAA,OAAA,EAAA,MAAA,EAAA,EAAA,GAAA,IAAA;EAAW,WAAA,EAAA,MAAA;EA6CF,cAAA,EAAA,CAAA,KAAe,EAAA,MAAA,EAAA,GAAA,IAAA;EAAG,SAAA,EAAA,OAAA;EACK,KAAA,EA3D3B,KA2D2B,GAAA,IAAA;EAAZ,kBAAA,EA1DF,kBA0DE,GAAA,IAAA;EACS,MAAA,EA1DvB,gBA0DuB,GAAA,IAAA;EAAZ,MAAA,EAAA,OAAA;EACT,IAAA,EAAA,GAAA,GAAA,IAAA;EAAiB,KAAA,EAAA,GAAA,GAAA,IAAA;EAIf,MAAA,EAAA,GAAA,GAAA,IAED;AAqVZ,CAAA;KA/YK,WAAA,GAAc,WAgZlB,CAhZ8B,sBAgZ9B,CAAA,SAAA,CAAA,CAAA;KA9YI,iBAAA,GAAoB,WA+YxB,CAAA,SAAA,CAAA,SAAA,IAAA,GAAA,SAAA,GAAA,SAAA,GA7YE,WA6YF,CA7Yc,WA6Yd,CAAA,SAAA,CAAA,CAAA,GAAA;EACA,MAAA,EAAA,MAAA,GAAA,IAAA;CACA;AACA,KAnWW,eAAA,GAAkB,sBAmW7B,GAAA;EACA,oBAAA,EAnWsB,WAmWtB,CAnWkC,WAmWlC,CAAA,sBAAA,CAAA,CAAA,GAAA,EAAA;EACA,iBAAA,EAnWmB,WAmWnB,CAnW+B,WAmW/B,CAAA,mBAAA,CAAA,CAAA,GAAA,EAAA;EACA,OAAA,CAAA,EAnWU,iBAmWV;EACA,IAAA,EAAA,QAAA,GAAA,QAAA;CACA;AACA,cAlWY,cAkWZ,EAlW0B,KAAA,CAAA,OAkW1B,CAlW0B,sBAkW1B,GAAA,SAAA,CAAA;;;;;AA0BD;;iBArCgB,eAAA;;;;;;;;;;;;;GAab,uBAAuB,KAAA,CAAM;;;;;iBAwBhB,UAAA,CAAA,GAAc"}
1
+ {"version":3,"file":"provider.d.ts","names":[],"sources":["../src/provider.tsx"],"sourcesContent":[],"mappings":";;;;;;KAsEY,oBAAA;YACD,KAAA,CAAM;EADL,WAAA,CAAA,EAAA,OAAA;EACD,MAAM,CAAA,EAAA,MAAA;EAKE,KAAA,CAAA,EAAA,MAAA;EAKE,SAAA,CAAA,EAAA,MAAA;EAAK,eAAA,CAAA,EALP,cAKO,EAAA;EAId,YAAA,CAAA,EAAA,MAAA,EAAA;EAEA,WAAA,CAAA,EAAA,OAAA;EACF,WAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EACQ,cAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAEc,SAAA,CAAA,EAAA,CAAA,KAAA,EAVX,KAUW,EAAA,GAAA,IAAA;EAKxB,IAAA,CAAA,EAAA,QAAA,GAAA,QAAA;CACa;AACZ,KAbG,uBAAA,GAA0B,oBAa7B;AAAgB,KAXb,sBAAA,GAWa;EAOpB,OAAA,EAjBK,qBAiBqB,GAAA,IAAA;EAE1B,eAAA,EAlBa,cAkBI,EAAA;EAAG,YAAA,EAAA,MAAA,EAAA;EAEV,kBAAA,EAAA,CAAA,QAAA,EAlBiB,cAkBjB,EAAA,EAAA,GAAA,IAAA;EAAZ,eAAA,EAAA,CAAA,OAAA,EAAA,MAAA,EAAA,EAAA,GAAA,IAAA;EAAW,WAAA,EAAA,MAAA;EAiDF,cAAA,EAAA,CAAA,KAAe,EAAA,MAAA,EAAA,GAAA,IAAA;EAAG,SAAA,EAAA,OAAA;EACK,KAAA,EA/D3B,KA+D2B,GAAA,IAAA;EAAZ,kBAAA,EA9DF,kBA8DE,GAAA,IAAA;EACS,MAAA,EA9DvB,gBA8DuB,GAAA,IAAA;EAAZ,MAAA,EAAA,OAAA;EACT,IAAA,EAAA,GAAA,GAAA,IAAA;EAAiB,KAAA,EAAA,GAAA,GAAA,IAAA;EAIf,MAAA,EAAA,GAAA,GAAA,IAED;AAgWZ,CAAA;KA9ZK,WAAA,GAAc,WA+ZlB,CA/Z8B,sBA+Z9B,CAAA,SAAA,CAAA,CAAA;KA7ZI,iBAAA,GAAoB,WA8ZxB,CAAA,SAAA,CAAA,SAAA,IAAA,GAAA,SAAA,GAAA,SAAA,GA5ZE,WA4ZF,CA5Zc,WA4Zd,CAAA,SAAA,CAAA,CAAA,GAAA;EACA,MAAA,EAAA,MAAA,GAAA,IAAA;CACA;AACA,KA9WW,eAAA,GAAkB,sBA8W7B,GAAA;EACA,oBAAA,EA9WsB,WA8WtB,CA9WkC,WA8WlC,CAAA,sBAAA,CAAA,CAAA,GAAA,EAAA;EACA,iBAAA,EA9WmB,WA8WnB,CA9W+B,WA8W/B,CAAA,mBAAA,CAAA,CAAA,GAAA,EAAA;EACA,OAAA,CAAA,EA9WU,iBA8WV;EACA,IAAA,EAAA,QAAA,GAAA,QAAA;CACA;AACA,cA7WY,cA6WZ,EA7W0B,KAAA,CAAA,OA6W1B,CA7W0B,sBA6W1B,GAAA,SAAA,CAAA;;;;;AA0BD;;iBArCgB,eAAA;;;;;;;;;;;;;GAab,uBAAuB,KAAA,CAAM;;;;;iBAwBhB,UAAA,CAAA,GAAc"}
package/provider.js CHANGED
@@ -52,7 +52,7 @@ function areConversationSnapshotsEqual(a, b) {
52
52
  if (!snapshotB) return false;
53
53
  const aLastCreatedAt = snapshotA.lastTimelineItem?.createdAt ?? null;
54
54
  const bLastCreatedAt = snapshotB.lastTimelineItem?.createdAt ?? null;
55
- if (snapshotA.id !== snapshotB.id || aLastCreatedAt !== bLastCreatedAt || snapshotA.visitorLastSeenAt !== snapshotB.visitorLastSeenAt) return false;
55
+ if (snapshotA.id !== snapshotB.id || aLastCreatedAt !== bLastCreatedAt || snapshotA.visitorLastSeenAt !== snapshotB.visitorLastSeenAt || snapshotA.status !== snapshotB.status || snapshotA.deletedAt !== snapshotB.deletedAt) return false;
56
56
  }
57
57
  return true;
58
58
  }
@@ -102,13 +102,16 @@ function SupportProviderInner({ children, apiUrl, wsUrl, publicKey, defaultMessa
102
102
  return {
103
103
  id: conversation.id,
104
104
  lastTimelineItem: conversation.lastTimelineItem ?? null,
105
- visitorLastSeenAt: conversation.visitorLastSeenAt ?? null
105
+ visitorLastSeenAt: conversation.visitorLastSeenAt ?? null,
106
+ status: conversation.status ?? "open",
107
+ deletedAt: conversation.deletedAt ?? null
106
108
  };
107
109
  }).filter((snapshot) => snapshot !== null) : [], []), areConversationSnapshotsEqual);
108
110
  const derivedUnreadCount = React.useMemo(() => {
109
111
  if (!visitorId) return 0;
110
112
  let count = 0;
111
- for (const { id: conversationId, lastTimelineItem, visitorLastSeenAt } of conversationSnapshots) {
113
+ for (const { id: conversationId, lastTimelineItem, visitorLastSeenAt, status, deletedAt } of conversationSnapshots) {
114
+ if (status !== "open" || deletedAt) continue;
112
115
  if (!lastTimelineItem) continue;
113
116
  if (lastTimelineItem.type !== ConversationTimelineType.MESSAGE) continue;
114
117
  if (lastTimelineItem.visitorId && lastTimelineItem.visitorId === visitorId) continue;
package/provider.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"provider.js","names":[],"sources":["../src/provider.tsx"],"sourcesContent":["import type { CossistantClient } from \"@cossistant/core\";\nimport { CossistantAPIError, normalizeLocale } from \"@cossistant/core\";\nimport type { DefaultMessage, PublicWebsiteResponse } from \"@cossistant/types\";\nimport type { TimelineItem } from \"@cossistant/types/api/timeline-item\";\nimport { ConversationTimelineType } from \"@cossistant/types/enums\";\nimport React from \"react\";\nimport { useStoreSelector } from \"./hooks/private/store/use-store-selector\";\nimport { useWebsiteStore } from \"./hooks/private/store/use-website-store\";\nimport {\n\ttype ConfigurationError,\n\tuseClient,\n} from \"./hooks/private/use-rest-client\";\nimport { useSeenStore } from \"./realtime/seen-store\";\nimport { WebSocketProvider } from \"./support\";\nimport { IdentificationProvider } from \"./support/context/identification\";\nimport {\n\tinitializeSupportStore,\n\tuseSupportStore,\n} from \"./support/store/support-store\";\n\n/**\n * Auth-related error codes that indicate API key issues.\n */\nconst AUTH_ERROR_CODES = new Set([\n\t\"UNAUTHORIZED\",\n\t\"FORBIDDEN\",\n\t\"INVALID_API_KEY\",\n\t\"API_KEY_EXPIRED\",\n\t\"API_KEY_MISSING\",\n\t\"HTTP_401\",\n\t\"HTTP_403\",\n]);\n\n/**\n * Check if an error is an authentication/authorization error.\n */\nfunction isAuthError(error: Error | null): boolean {\n\tif (!error) {\n\t\treturn false;\n\t}\n\n\tif (error instanceof CossistantAPIError) {\n\t\tconst code = error.code?.toUpperCase() ?? \"\";\n\t\treturn (\n\t\t\tAUTH_ERROR_CODES.has(code) ||\n\t\t\tcode.includes(\"AUTH\") ||\n\t\t\tcode.includes(\"API_KEY\")\n\t\t);\n\t}\n\n\t// Check error message as fallback\n\tconst message = error.message?.toLowerCase() ?? \"\";\n\treturn (\n\t\tmessage.includes(\"api key\") ||\n\t\tmessage.includes(\"unauthorized\") ||\n\t\tmessage.includes(\"forbidden\") ||\n\t\tmessage.includes(\"not authorized\")\n\t);\n}\n\n/**\n * Detect if running in a Next.js environment.\n */\nfunction isNextJSEnvironment(): boolean {\n\tif (typeof window !== \"undefined\") {\n\t\treturn \"__NEXT_DATA__\" in window;\n\t}\n\treturn typeof process !== \"undefined\" && \"__NEXT_RUNTIME\" in process.env;\n}\n\nexport type SupportProviderProps = {\n\tchildren: React.ReactNode;\n\tdefaultOpen?: boolean;\n\tapiUrl?: string;\n\twsUrl?: string;\n\tpublicKey?: string;\n\tdefaultMessages?: DefaultMessage[];\n\tquickOptions?: string[];\n\tautoConnect?: boolean;\n\tonWsConnect?: () => void;\n\tonWsDisconnect?: () => void;\n\tonWsError?: (error: Error) => void;\n\tsize?: \"normal\" | \"larger\";\n};\n\nexport type CossistantProviderProps = SupportProviderProps;\n\nexport type CossistantContextValue = {\n\twebsite: PublicWebsiteResponse | null;\n\tdefaultMessages: DefaultMessage[];\n\tquickOptions: string[];\n\tsetDefaultMessages: (messages: DefaultMessage[]) => void;\n\tsetQuickOptions: (options: string[]) => void;\n\tunreadCount: number;\n\tsetUnreadCount: (count: number) => void;\n\tisLoading: boolean;\n\terror: Error | null;\n\tconfigurationError: ConfigurationError | null;\n\tclient: CossistantClient | null;\n\tisOpen: boolean;\n\topen: () => void;\n\tclose: () => void;\n\ttoggle: () => void;\n};\n\ntype WebsiteData = NonNullable<CossistantContextValue[\"website\"]>;\n\ntype VisitorWithLocale = WebsiteData[\"visitor\"] extends null | undefined\n\t? undefined\n\t: NonNullable<WebsiteData[\"visitor\"]> & { locale: string | null };\n\ntype ConversationSnapshot = {\n\tid: string;\n\tlastTimelineItem: TimelineItem | null;\n\tvisitorLastSeenAt: string | null;\n};\n\nfunction areConversationSnapshotsEqual(\n\ta: ConversationSnapshot[],\n\tb: ConversationSnapshot[]\n): boolean {\n\tif (a === b) {\n\t\treturn true;\n\t}\n\n\tif (a.length !== b.length) {\n\t\treturn false;\n\t}\n\n\tfor (let index = 0; index < a.length; index += 1) {\n\t\tconst snapshotA = a[index];\n\t\tconst snapshotB = b[index];\n\n\t\tif (!snapshotA) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!snapshotB) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst aLastCreatedAt = snapshotA.lastTimelineItem?.createdAt ?? null;\n\t\tconst bLastCreatedAt = snapshotB.lastTimelineItem?.createdAt ?? null;\n\t\tif (\n\t\t\tsnapshotA.id !== snapshotB.id ||\n\t\t\taLastCreatedAt !== bLastCreatedAt ||\n\t\t\tsnapshotA.visitorLastSeenAt !== snapshotB.visitorLastSeenAt\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\nexport type UseSupportValue = CossistantContextValue & {\n\tavailableHumanAgents: NonNullable<WebsiteData[\"availableHumanAgents\"]> | [];\n\tavailableAIAgents: NonNullable<WebsiteData[\"availableAIAgents\"]> | [];\n\tvisitor?: VisitorWithLocale;\n\tsize: \"normal\" | \"larger\";\n};\n\nexport const SupportContext = React.createContext<\n\tCossistantContextValue | undefined\n>(undefined);\n\n/**\n * Internal implementation that wires the REST client and websocket provider\n * together before exposing the combined context.\n */\nfunction SupportProviderInner({\n\tchildren,\n\tapiUrl,\n\twsUrl,\n\tpublicKey,\n\tdefaultMessages,\n\tquickOptions,\n\tautoConnect,\n\tonWsConnect,\n\tonWsDisconnect,\n\tonWsError,\n\tsize = \"normal\",\n\tdefaultOpen = false,\n}: SupportProviderProps) {\n\tconst [unreadCount, setUnreadCount] = React.useState(0);\n\tconst prefetchedVisitorRef = React.useRef<string | null>(null);\n\tconst [_defaultMessages, _setDefaultMessages] = React.useState<\n\t\tDefaultMessage[]\n\t>(defaultMessages ?? []);\n\tconst [_quickOptions, _setQuickOptions] = React.useState<string[]>(\n\t\tquickOptions ?? []\n\t);\n\n\t// Initialize support store with configuration\n\tReact.useEffect(() => {\n\t\tinitializeSupportStore({ size, defaultOpen });\n\t}, [size, defaultOpen]);\n\n\t// Get support store state and actions\n\tconst { config, open, close, toggle } = useSupportStore();\n\n\t// Update state when props change (for initial values from provider)\n\tReact.useEffect(() => {\n\t\tif (defaultMessages?.length) {\n\t\t\t_setDefaultMessages(defaultMessages);\n\t\t}\n\t}, [defaultMessages]);\n\n\tReact.useEffect(() => {\n\t\tif (quickOptions?.length) {\n\t\t\t_setQuickOptions(quickOptions);\n\t\t}\n\t}, [quickOptions]);\n\n\tconst { client, configurationError: clientConfigError } = useClient(\n\t\tpublicKey,\n\t\tapiUrl,\n\t\twsUrl\n\t);\n\n\t// Only use website store if we have a valid client\n\tconst { website, isLoading, error: websiteError } = useWebsiteStore(client);\n\tconst isVisitorBlocked = website?.visitor?.isBlocked ?? false;\n\tconst visitorId = website?.visitor?.id ?? null;\n\n\t// Derive final configuration error from both client error and API auth errors\n\tconst configurationError = React.useMemo<ConfigurationError | null>(() => {\n\t\t// Client-level config error takes precedence (missing API key)\n\t\tif (clientConfigError) {\n\t\t\treturn clientConfigError;\n\t\t}\n\n\t\t// Check if website error is an auth error (invalid/expired API key)\n\t\tif (websiteError && isAuthError(websiteError)) {\n\t\t\tconst isNextJS = isNextJSEnvironment();\n\t\t\tconst envVarName = isNextJS\n\t\t\t\t? \"NEXT_PUBLIC_COSSISTANT_API_KEY\"\n\t\t\t\t: \"COSSISTANT_API_KEY\";\n\n\t\t\treturn {\n\t\t\t\ttype: \"invalid_api_key\",\n\t\t\t\tmessage: websiteError.message,\n\t\t\t\tenvVarName,\n\t\t\t};\n\t\t}\n\n\t\treturn null;\n\t}, [clientConfigError, websiteError]);\n\n\tconst seenEntriesByConversation = useSeenStore(\n\t\tReact.useCallback((state) => state.conversations, [])\n\t);\n\n\tconst conversationSnapshots = useStoreSelector(\n\t\tclient?.conversationsStore ?? null,\n\t\tReact.useCallback(\n\t\t\t(\n\t\t\t\tstate: {\n\t\t\t\t\tids: string[];\n\t\t\t\t\tbyId: Record<\n\t\t\t\t\t\tstring,\n\t\t\t\t\t\t| {\n\t\t\t\t\t\t\t\tid: string;\n\t\t\t\t\t\t\t\tlastTimelineItem?: TimelineItem | null;\n\t\t\t\t\t\t\t\tvisitorLastSeenAt?: string | null;\n\t\t\t\t\t\t }\n\t\t\t\t\t\t| undefined\n\t\t\t\t\t>;\n\t\t\t\t} | null\n\t\t\t): ConversationSnapshot[] =>\n\t\t\t\tstate\n\t\t\t\t\t? state.ids\n\t\t\t\t\t\t\t.map((id) => {\n\t\t\t\t\t\t\t\tconst conversation = state.byId[id];\n\n\t\t\t\t\t\t\t\tif (!conversation) {\n\t\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\tid: conversation.id,\n\t\t\t\t\t\t\t\t\tlastTimelineItem: conversation.lastTimelineItem ?? null,\n\t\t\t\t\t\t\t\t\tvisitorLastSeenAt: conversation.visitorLastSeenAt ?? null,\n\t\t\t\t\t\t\t\t} satisfies ConversationSnapshot;\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t\t(snapshot): snapshot is ConversationSnapshot =>\n\t\t\t\t\t\t\t\t\tsnapshot !== null\n\t\t\t\t\t\t\t)\n\t\t\t\t\t: [],\n\t\t\t[]\n\t\t),\n\t\tareConversationSnapshotsEqual\n\t);\n\n\tconst derivedUnreadCount = React.useMemo(() => {\n\t\tif (!visitorId) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tlet count = 0;\n\n\t\tfor (const {\n\t\t\tid: conversationId,\n\t\t\tlastTimelineItem,\n\t\t\tvisitorLastSeenAt,\n\t\t} of conversationSnapshots) {\n\t\t\tif (!lastTimelineItem) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (lastTimelineItem.type !== ConversationTimelineType.MESSAGE) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tlastTimelineItem.visitorId &&\n\t\t\t\tlastTimelineItem.visitorId === visitorId\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst createdAtTime = Date.parse(lastTimelineItem.createdAt);\n\n\t\t\tif (Number.isNaN(createdAtTime)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// First check visitorLastSeenAt from the API response (available immediately)\n\t\t\tif (visitorLastSeenAt) {\n\t\t\t\tconst lastSeenTime = Date.parse(visitorLastSeenAt);\n\t\t\t\tif (!Number.isNaN(lastSeenTime) && createdAtTime <= lastSeenTime) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Fall back to seen store (updated via realtime events)\n\t\t\tconst seenEntries = seenEntriesByConversation[conversationId];\n\n\t\t\tif (seenEntries) {\n\t\t\t\tconst visitorSeenEntry = Object.values(seenEntries).find(\n\t\t\t\t\t(entry) =>\n\t\t\t\t\t\tentry.actorType === \"visitor\" && entry.actorId === visitorId\n\t\t\t\t);\n\n\t\t\t\tif (visitorSeenEntry) {\n\t\t\t\t\tconst lastSeenTime = Date.parse(visitorSeenEntry.lastSeenAt);\n\n\t\t\t\t\tif (!Number.isNaN(lastSeenTime) && createdAtTime <= lastSeenTime) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcount += 1;\n\t\t}\n\n\t\treturn count;\n\t}, [conversationSnapshots, seenEntriesByConversation, visitorId]);\n\n\tReact.useEffect(() => {\n\t\tsetUnreadCount(derivedUnreadCount);\n\t}, [derivedUnreadCount, setUnreadCount]);\n\n\t// Prime REST client with website/visitor context so headers are sent reliably\n\tReact.useEffect(() => {\n\t\tif (!(website && client)) {\n\t\t\treturn;\n\t\t}\n\n\t\tclient.setWebsiteContext(website.id, website.visitor?.id ?? undefined);\n\t}, [client, website]);\n\n\tReact.useEffect(() => {\n\t\tif (!client) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (isVisitorBlocked) {\n\t\t\tprefetchedVisitorRef.current = null;\n\t\t\treturn;\n\t\t}\n\n\t\tif (!autoConnect) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!website) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!visitorId) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (prefetchedVisitorRef.current === visitorId) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst hasExistingConversations =\n\t\t\tclient.conversationsStore.getState().ids.length > 0;\n\n\t\tprefetchedVisitorRef.current = visitorId;\n\n\t\tif (hasExistingConversations) {\n\t\t\treturn;\n\t\t}\n\n\t\tvoid client.listConversations().catch((err) => {\n\t\t\tconsole.error(\"[SupportProvider] Failed to prefetch conversations\", err);\n\t\t\tprefetchedVisitorRef.current = null;\n\t\t});\n\t}, [autoConnect, client, isVisitorBlocked, visitorId, website]);\n\n\tconst error = websiteError;\n\n\tReact.useEffect(() => {\n\t\tif (!client) {\n\t\t\treturn;\n\t\t}\n\t\tclient.setVisitorBlocked(isVisitorBlocked);\n\t}, [client, isVisitorBlocked]);\n\n\tconst setDefaultMessages = React.useCallback((messages: DefaultMessage[]) => {\n\t\t_setDefaultMessages(messages);\n\t}, []);\n\n\tconst setQuickOptions = React.useCallback((options: string[]) => {\n\t\t_setQuickOptions(options);\n\t}, []);\n\n\tconst value = React.useMemo<CossistantContextValue>(\n\t\t() => ({\n\t\t\twebsite,\n\t\t\tunreadCount,\n\t\t\tsetUnreadCount,\n\t\t\tisLoading,\n\t\t\terror,\n\t\t\tconfigurationError,\n\t\t\tclient,\n\t\t\tdefaultMessages: _defaultMessages,\n\t\t\tsetDefaultMessages,\n\t\t\tquickOptions: _quickOptions,\n\t\t\tsetQuickOptions,\n\t\t\tisOpen: config.isOpen,\n\t\t\topen,\n\t\t\tclose,\n\t\t\ttoggle,\n\t\t}),\n\t\t[\n\t\t\twebsite,\n\t\t\tunreadCount,\n\t\t\tisLoading,\n\t\t\terror,\n\t\t\tconfigurationError,\n\t\t\tclient,\n\t\t\t_defaultMessages,\n\t\t\t_quickOptions,\n\t\t\tsetDefaultMessages,\n\t\t\tsetQuickOptions,\n\t\t\tconfig.isOpen,\n\t\t\topen,\n\t\t\tclose,\n\t\t\ttoggle,\n\t\t]\n\t);\n\n\tconst webSocketKey = React.useMemo(() => {\n\t\tif (!website) {\n\t\t\treturn \"no-website\";\n\t\t}\n\n\t\tconst visitorKey = website.visitor?.id ?? \"anonymous\";\n\t\tconst blockedState = isVisitorBlocked ? \"blocked\" : \"active\";\n\n\t\treturn `${website.id}:${visitorKey}:${blockedState}`;\n\t}, [isVisitorBlocked, website]);\n\n\treturn (\n\t\t<SupportContext.Provider value={value}>\n\t\t\t<IdentificationProvider>\n\t\t\t\t<WebSocketProvider\n\t\t\t\t\tautoConnect={autoConnect && !isVisitorBlocked && !configurationError}\n\t\t\t\t\tkey={webSocketKey}\n\t\t\t\t\tonConnect={onWsConnect}\n\t\t\t\t\tonDisconnect={onWsDisconnect}\n\t\t\t\t\tonError={onWsError}\n\t\t\t\t\tpublicKey={publicKey}\n\t\t\t\t\tvisitorId={isVisitorBlocked ? undefined : website?.visitor?.id}\n\t\t\t\t\twebsiteId={website?.id}\n\t\t\t\t\twsUrl={wsUrl}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</WebSocketProvider>\n\t\t\t</IdentificationProvider>\n\t\t</SupportContext.Provider>\n\t);\n}\n\n/**\n * Hosts the entire customer support widget ecosystem by handing out context\n * about the current website, visitor, unread counts, realtime subscriptions\n * and the REST client. Provide your Cossistant public key plus optional\n * defaults to configure the widget behaviour.\n */\nexport function SupportProvider({\n\tchildren,\n\tapiUrl = \"https://api.cossistant.com/v1\",\n\twsUrl = \"wss://api.cossistant.com/ws\",\n\tpublicKey,\n\tdefaultMessages,\n\tquickOptions,\n\tautoConnect = true,\n\tonWsConnect,\n\tonWsDisconnect,\n\tonWsError,\n\tsize = \"normal\",\n\tdefaultOpen = false,\n}: SupportProviderProps): React.ReactElement {\n\treturn (\n\t\t<SupportProviderInner\n\t\t\tapiUrl={apiUrl}\n\t\t\tautoConnect={autoConnect}\n\t\t\tdefaultMessages={defaultMessages}\n\t\t\tdefaultOpen={defaultOpen}\n\t\t\tonWsConnect={onWsConnect}\n\t\t\tonWsDisconnect={onWsDisconnect}\n\t\t\tonWsError={onWsError}\n\t\t\tpublicKey={publicKey}\n\t\t\tquickOptions={quickOptions}\n\t\t\tsize={size}\n\t\t\twsUrl={wsUrl}\n\t\t>\n\t\t\t{children}\n\t\t</SupportProviderInner>\n\t);\n}\n\n/**\n * Convenience hook that exposes the aggregated support context. Throws when it\n * is consumed outside of `SupportProvider` to catch integration mistakes.\n */\nexport function useSupport(): UseSupportValue {\n\tconst context = React.useContext(SupportContext);\n\tif (!context) {\n\t\tthrow new Error(\n\t\t\t\"useSupport must be used within a cossistant SupportProvider\"\n\t\t);\n\t}\n\n\tconst availableHumanAgents = context.website?.availableHumanAgents || [];\n\tconst availableAIAgents = context.website?.availableAIAgents || [];\n\tconst visitorLanguage = context.website?.visitor?.language || null;\n\n\t// Get additional config from support store\n\tconst { config } = useSupportStore();\n\n\t// Create visitor object with normalized locale\n\tconst visitor = context.website?.visitor\n\t\t? {\n\t\t\t\t...context.website.visitor,\n\t\t\t\tlocale: normalizeLocale(visitorLanguage),\n\t\t\t}\n\t\t: undefined;\n\n\treturn {\n\t\t...context,\n\t\tavailableHumanAgents,\n\t\tavailableAIAgents,\n\t\tvisitor,\n\t\tsize: config.size,\n\t};\n}\n\n// Re-export ConfigurationError type for consumers\nexport type { ConfigurationError } from \"./hooks/private/use-rest-client\";\n"],"mappings":";;;;;;;;;;;;;;;;AAuBA,MAAM,mBAAmB,IAAI,IAAI;CAChC;CACA;CACA;CACA;CACA;CACA;CACA;CACA,CAAC;;;;AAKF,SAAS,YAAY,OAA8B;AAClD,KAAI,CAAC,MACJ,QAAO;AAGR,KAAI,iBAAiB,oBAAoB;EACxC,MAAM,OAAO,MAAM,MAAM,aAAa,IAAI;AAC1C,SACC,iBAAiB,IAAI,KAAK,IAC1B,KAAK,SAAS,OAAO,IACrB,KAAK,SAAS,UAAU;;CAK1B,MAAM,UAAU,MAAM,SAAS,aAAa,IAAI;AAChD,QACC,QAAQ,SAAS,UAAU,IAC3B,QAAQ,SAAS,eAAe,IAChC,QAAQ,SAAS,YAAY,IAC7B,QAAQ,SAAS,iBAAiB;;;;;AAOpC,SAAS,sBAA+B;AACvC,KAAI,OAAO,WAAW,YACrB,QAAO,mBAAmB;AAE3B,QAAO,OAAO,YAAY,eAAe,oBAAoB,QAAQ;;AAkDtE,SAAS,8BACR,GACA,GACU;AACV,KAAI,MAAM,EACT,QAAO;AAGR,KAAI,EAAE,WAAW,EAAE,OAClB,QAAO;AAGR,MAAK,IAAI,QAAQ,GAAG,QAAQ,EAAE,QAAQ,SAAS,GAAG;EACjD,MAAM,YAAY,EAAE;EACpB,MAAM,YAAY,EAAE;AAEpB,MAAI,CAAC,UACJ,QAAO;AAER,MAAI,CAAC,UACJ,QAAO;EAGR,MAAM,iBAAiB,UAAU,kBAAkB,aAAa;EAChE,MAAM,iBAAiB,UAAU,kBAAkB,aAAa;AAChE,MACC,UAAU,OAAO,UAAU,MAC3B,mBAAmB,kBACnB,UAAU,sBAAsB,UAAU,kBAE1C,QAAO;;AAIT,QAAO;;AAUR,MAAa,iBAAiB,MAAM,cAElC,OAAU;;;;;AAMZ,SAAS,qBAAqB,EAC7B,UACA,QACA,OACA,WACA,iBACA,cACA,aACA,aACA,gBACA,WACA,OAAO,UACP,cAAc,SACU;CACxB,MAAM,CAAC,aAAa,kBAAkB,MAAM,SAAS,EAAE;CACvD,MAAM,uBAAuB,MAAM,OAAsB,KAAK;CAC9D,MAAM,CAAC,kBAAkB,uBAAuB,MAAM,SAEpD,mBAAmB,EAAE,CAAC;CACxB,MAAM,CAAC,eAAe,oBAAoB,MAAM,SAC/C,gBAAgB,EAAE,CAClB;AAGD,OAAM,gBAAgB;AACrB,yBAAuB;GAAE;GAAM;GAAa,CAAC;IAC3C,CAAC,MAAM,YAAY,CAAC;CAGvB,MAAM,EAAE,QAAQ,MAAM,OAAO,WAAW,iBAAiB;AAGzD,OAAM,gBAAgB;AACrB,MAAI,iBAAiB,OACpB,qBAAoB,gBAAgB;IAEnC,CAAC,gBAAgB,CAAC;AAErB,OAAM,gBAAgB;AACrB,MAAI,cAAc,OACjB,kBAAiB,aAAa;IAE7B,CAAC,aAAa,CAAC;CAElB,MAAM,EAAE,QAAQ,oBAAoB,sBAAsB,UACzD,WACA,QACA,MACA;CAGD,MAAM,EAAE,SAAS,WAAW,OAAO,iBAAiB,gBAAgB,OAAO;CAC3E,MAAM,mBAAmB,SAAS,SAAS,aAAa;CACxD,MAAM,YAAY,SAAS,SAAS,MAAM;CAG1C,MAAM,qBAAqB,MAAM,cAAyC;AAEzE,MAAI,kBACH,QAAO;AAIR,MAAI,gBAAgB,YAAY,aAAa,EAAE;GAE9C,MAAM,aADW,qBAAqB,GAEnC,mCACA;AAEH,UAAO;IACN,MAAM;IACN,SAAS,aAAa;IACtB;IACA;;AAGF,SAAO;IACL,CAAC,mBAAmB,aAAa,CAAC;CAErC,MAAM,4BAA4B,aACjC,MAAM,aAAa,UAAU,MAAM,eAAe,EAAE,CAAC,CACrD;CAED,MAAM,wBAAwB,iBAC7B,QAAQ,sBAAsB,MAC9B,MAAM,aAEJ,UAaA,QACG,MAAM,IACL,KAAK,OAAO;EACZ,MAAM,eAAe,MAAM,KAAK;AAEhC,MAAI,CAAC,aACJ,QAAO;AAGR,SAAO;GACN,IAAI,aAAa;GACjB,kBAAkB,aAAa,oBAAoB;GACnD,mBAAmB,aAAa,qBAAqB;GACrD;GACA,CACD,QACC,aACA,aAAa,KACd,GACD,EAAE,EACN,EAAE,CACF,EACD,8BACA;CAED,MAAM,qBAAqB,MAAM,cAAc;AAC9C,MAAI,CAAC,UACJ,QAAO;EAGR,IAAI,QAAQ;AAEZ,OAAK,MAAM,EACV,IAAI,gBACJ,kBACA,uBACI,uBAAuB;AAC3B,OAAI,CAAC,iBACJ;AAGD,OAAI,iBAAiB,SAAS,yBAAyB,QACtD;AAGD,OACC,iBAAiB,aACjB,iBAAiB,cAAc,UAE/B;GAGD,MAAM,gBAAgB,KAAK,MAAM,iBAAiB,UAAU;AAE5D,OAAI,OAAO,MAAM,cAAc,CAC9B;AAID,OAAI,mBAAmB;IACtB,MAAM,eAAe,KAAK,MAAM,kBAAkB;AAClD,QAAI,CAAC,OAAO,MAAM,aAAa,IAAI,iBAAiB,aACnD;;GAKF,MAAM,cAAc,0BAA0B;AAE9C,OAAI,aAAa;IAChB,MAAM,mBAAmB,OAAO,OAAO,YAAY,CAAC,MAClD,UACA,MAAM,cAAc,aAAa,MAAM,YAAY,UACpD;AAED,QAAI,kBAAkB;KACrB,MAAM,eAAe,KAAK,MAAM,iBAAiB,WAAW;AAE5D,SAAI,CAAC,OAAO,MAAM,aAAa,IAAI,iBAAiB,aACnD;;;AAKH,YAAS;;AAGV,SAAO;IACL;EAAC;EAAuB;EAA2B;EAAU,CAAC;AAEjE,OAAM,gBAAgB;AACrB,iBAAe,mBAAmB;IAChC,CAAC,oBAAoB,eAAe,CAAC;AAGxC,OAAM,gBAAgB;AACrB,MAAI,EAAE,WAAW,QAChB;AAGD,SAAO,kBAAkB,QAAQ,IAAI,QAAQ,SAAS,MAAM,OAAU;IACpE,CAAC,QAAQ,QAAQ,CAAC;AAErB,OAAM,gBAAgB;AACrB,MAAI,CAAC,OACJ;AAGD,MAAI,kBAAkB;AACrB,wBAAqB,UAAU;AAC/B;;AAGD,MAAI,CAAC,YACJ;AAGD,MAAI,CAAC,QACJ;AAGD,MAAI,CAAC,UACJ;AAGD,MAAI,qBAAqB,YAAY,UACpC;EAGD,MAAM,2BACL,OAAO,mBAAmB,UAAU,CAAC,IAAI,SAAS;AAEnD,uBAAqB,UAAU;AAE/B,MAAI,yBACH;AAGD,EAAK,OAAO,mBAAmB,CAAC,OAAO,QAAQ;AAC9C,WAAQ,MAAM,sDAAsD,IAAI;AACxE,wBAAqB,UAAU;IAC9B;IACA;EAAC;EAAa;EAAQ;EAAkB;EAAW;EAAQ,CAAC;CAE/D,MAAM,QAAQ;AAEd,OAAM,gBAAgB;AACrB,MAAI,CAAC,OACJ;AAED,SAAO,kBAAkB,iBAAiB;IACxC,CAAC,QAAQ,iBAAiB,CAAC;CAE9B,MAAM,qBAAqB,MAAM,aAAa,aAA+B;AAC5E,sBAAoB,SAAS;IAC3B,EAAE,CAAC;CAEN,MAAM,kBAAkB,MAAM,aAAa,YAAsB;AAChE,mBAAiB,QAAQ;IACvB,EAAE,CAAC;CAEN,MAAM,QAAQ,MAAM,eACZ;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA,iBAAiB;EACjB;EACA,cAAc;EACd;EACA,QAAQ,OAAO;EACf;EACA;EACA;EACA,GACD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,OAAO;EACP;EACA;EACA;EACA,CACD;CAED,MAAM,eAAe,MAAM,cAAc;AACxC,MAAI,CAAC,QACJ,QAAO;EAGR,MAAM,aAAa,QAAQ,SAAS,MAAM;EAC1C,MAAM,eAAe,mBAAmB,YAAY;AAEpD,SAAO,GAAG,QAAQ,GAAG,GAAG,WAAW,GAAG;IACpC,CAAC,kBAAkB,QAAQ,CAAC;AAE/B,QACC,oBAAC,eAAe;EAAgB;YAC/B,oBAAC,oCACA,oBAAC;GACA,aAAa,eAAe,CAAC,oBAAoB,CAAC;GAElD,WAAW;GACX,cAAc;GACd,SAAS;GACE;GACX,WAAW,mBAAmB,SAAY,SAAS,SAAS;GAC5D,WAAW,SAAS;GACb;GAEN;KATI,aAUc,GACI;GACA;;;;;;;;AAU5B,SAAgB,gBAAgB,EAC/B,UACA,SAAS,iCACT,QAAQ,+BACR,WACA,iBACA,cACA,cAAc,MACd,aACA,gBACA,WACA,OAAO,UACP,cAAc,SAC8B;AAC5C,QACC,oBAAC;EACQ;EACK;EACI;EACJ;EACA;EACG;EACL;EACA;EACG;EACR;EACC;EAEN;GACqB;;;;;;AAQzB,SAAgB,aAA8B;CAC7C,MAAM,UAAU,MAAM,WAAW,eAAe;AAChD,KAAI,CAAC,QACJ,OAAM,IAAI,MACT,8DACA;CAGF,MAAM,uBAAuB,QAAQ,SAAS,wBAAwB,EAAE;CACxE,MAAM,oBAAoB,QAAQ,SAAS,qBAAqB,EAAE;CAClE,MAAM,kBAAkB,QAAQ,SAAS,SAAS,YAAY;CAG9D,MAAM,EAAE,WAAW,iBAAiB;CAGpC,MAAM,UAAU,QAAQ,SAAS,UAC9B;EACA,GAAG,QAAQ,QAAQ;EACnB,QAAQ,gBAAgB,gBAAgB;EACxC,GACA;AAEH,QAAO;EACN,GAAG;EACH;EACA;EACA;EACA,MAAM,OAAO;EACb"}
1
+ {"version":3,"file":"provider.js","names":[],"sources":["../src/provider.tsx"],"sourcesContent":["import type { CossistantClient } from \"@cossistant/core\";\nimport { CossistantAPIError, normalizeLocale } from \"@cossistant/core\";\nimport type { DefaultMessage, PublicWebsiteResponse } from \"@cossistant/types\";\nimport type { TimelineItem } from \"@cossistant/types/api/timeline-item\";\nimport { ConversationTimelineType } from \"@cossistant/types/enums\";\nimport React from \"react\";\nimport { useStoreSelector } from \"./hooks/private/store/use-store-selector\";\nimport { useWebsiteStore } from \"./hooks/private/store/use-website-store\";\nimport {\n\ttype ConfigurationError,\n\tuseClient,\n} from \"./hooks/private/use-rest-client\";\nimport { useSeenStore } from \"./realtime/seen-store\";\nimport { WebSocketProvider } from \"./support\";\nimport { IdentificationProvider } from \"./support/context/identification\";\nimport {\n\tinitializeSupportStore,\n\tuseSupportStore,\n} from \"./support/store/support-store\";\n\n/**\n * Auth-related error codes that indicate API key issues.\n */\nconst AUTH_ERROR_CODES = new Set([\n\t\"UNAUTHORIZED\",\n\t\"FORBIDDEN\",\n\t\"INVALID_API_KEY\",\n\t\"API_KEY_EXPIRED\",\n\t\"API_KEY_MISSING\",\n\t\"HTTP_401\",\n\t\"HTTP_403\",\n]);\n\n/**\n * Check if an error is an authentication/authorization error.\n */\nfunction isAuthError(error: Error | null): boolean {\n\tif (!error) {\n\t\treturn false;\n\t}\n\n\tif (error instanceof CossistantAPIError) {\n\t\tconst code = error.code?.toUpperCase() ?? \"\";\n\t\treturn (\n\t\t\tAUTH_ERROR_CODES.has(code) ||\n\t\t\tcode.includes(\"AUTH\") ||\n\t\t\tcode.includes(\"API_KEY\")\n\t\t);\n\t}\n\n\t// Check error message as fallback\n\tconst message = error.message?.toLowerCase() ?? \"\";\n\treturn (\n\t\tmessage.includes(\"api key\") ||\n\t\tmessage.includes(\"unauthorized\") ||\n\t\tmessage.includes(\"forbidden\") ||\n\t\tmessage.includes(\"not authorized\")\n\t);\n}\n\n/**\n * Detect if running in a Next.js environment.\n */\nfunction isNextJSEnvironment(): boolean {\n\tif (typeof window !== \"undefined\") {\n\t\treturn \"__NEXT_DATA__\" in window;\n\t}\n\treturn typeof process !== \"undefined\" && \"__NEXT_RUNTIME\" in process.env;\n}\n\nexport type SupportProviderProps = {\n\tchildren: React.ReactNode;\n\tdefaultOpen?: boolean;\n\tapiUrl?: string;\n\twsUrl?: string;\n\tpublicKey?: string;\n\tdefaultMessages?: DefaultMessage[];\n\tquickOptions?: string[];\n\tautoConnect?: boolean;\n\tonWsConnect?: () => void;\n\tonWsDisconnect?: () => void;\n\tonWsError?: (error: Error) => void;\n\tsize?: \"normal\" | \"larger\";\n};\n\nexport type CossistantProviderProps = SupportProviderProps;\n\nexport type CossistantContextValue = {\n\twebsite: PublicWebsiteResponse | null;\n\tdefaultMessages: DefaultMessage[];\n\tquickOptions: string[];\n\tsetDefaultMessages: (messages: DefaultMessage[]) => void;\n\tsetQuickOptions: (options: string[]) => void;\n\tunreadCount: number;\n\tsetUnreadCount: (count: number) => void;\n\tisLoading: boolean;\n\terror: Error | null;\n\tconfigurationError: ConfigurationError | null;\n\tclient: CossistantClient | null;\n\tisOpen: boolean;\n\topen: () => void;\n\tclose: () => void;\n\ttoggle: () => void;\n};\n\ntype WebsiteData = NonNullable<CossistantContextValue[\"website\"]>;\n\ntype VisitorWithLocale = WebsiteData[\"visitor\"] extends null | undefined\n\t? undefined\n\t: NonNullable<WebsiteData[\"visitor\"]> & { locale: string | null };\n\ntype ConversationSnapshot = {\n\tid: string;\n\tlastTimelineItem: TimelineItem | null;\n\tvisitorLastSeenAt: string | null;\n\tstatus: string;\n\tdeletedAt: string | null;\n};\n\nfunction areConversationSnapshotsEqual(\n\ta: ConversationSnapshot[],\n\tb: ConversationSnapshot[]\n): boolean {\n\tif (a === b) {\n\t\treturn true;\n\t}\n\n\tif (a.length !== b.length) {\n\t\treturn false;\n\t}\n\n\tfor (let index = 0; index < a.length; index += 1) {\n\t\tconst snapshotA = a[index];\n\t\tconst snapshotB = b[index];\n\n\t\tif (!snapshotA) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!snapshotB) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst aLastCreatedAt = snapshotA.lastTimelineItem?.createdAt ?? null;\n\t\tconst bLastCreatedAt = snapshotB.lastTimelineItem?.createdAt ?? null;\n\t\tif (\n\t\t\tsnapshotA.id !== snapshotB.id ||\n\t\t\taLastCreatedAt !== bLastCreatedAt ||\n\t\t\tsnapshotA.visitorLastSeenAt !== snapshotB.visitorLastSeenAt ||\n\t\t\tsnapshotA.status !== snapshotB.status ||\n\t\t\tsnapshotA.deletedAt !== snapshotB.deletedAt\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\nexport type UseSupportValue = CossistantContextValue & {\n\tavailableHumanAgents: NonNullable<WebsiteData[\"availableHumanAgents\"]> | [];\n\tavailableAIAgents: NonNullable<WebsiteData[\"availableAIAgents\"]> | [];\n\tvisitor?: VisitorWithLocale;\n\tsize: \"normal\" | \"larger\";\n};\n\nexport const SupportContext = React.createContext<\n\tCossistantContextValue | undefined\n>(undefined);\n\n/**\n * Internal implementation that wires the REST client and websocket provider\n * together before exposing the combined context.\n */\nfunction SupportProviderInner({\n\tchildren,\n\tapiUrl,\n\twsUrl,\n\tpublicKey,\n\tdefaultMessages,\n\tquickOptions,\n\tautoConnect,\n\tonWsConnect,\n\tonWsDisconnect,\n\tonWsError,\n\tsize = \"normal\",\n\tdefaultOpen = false,\n}: SupportProviderProps) {\n\tconst [unreadCount, setUnreadCount] = React.useState(0);\n\tconst prefetchedVisitorRef = React.useRef<string | null>(null);\n\tconst [_defaultMessages, _setDefaultMessages] = React.useState<\n\t\tDefaultMessage[]\n\t>(defaultMessages ?? []);\n\tconst [_quickOptions, _setQuickOptions] = React.useState<string[]>(\n\t\tquickOptions ?? []\n\t);\n\n\t// Initialize support store with configuration\n\tReact.useEffect(() => {\n\t\tinitializeSupportStore({ size, defaultOpen });\n\t}, [size, defaultOpen]);\n\n\t// Get support store state and actions\n\tconst { config, open, close, toggle } = useSupportStore();\n\n\t// Update state when props change (for initial values from provider)\n\tReact.useEffect(() => {\n\t\tif (defaultMessages?.length) {\n\t\t\t_setDefaultMessages(defaultMessages);\n\t\t}\n\t}, [defaultMessages]);\n\n\tReact.useEffect(() => {\n\t\tif (quickOptions?.length) {\n\t\t\t_setQuickOptions(quickOptions);\n\t\t}\n\t}, [quickOptions]);\n\n\tconst { client, configurationError: clientConfigError } = useClient(\n\t\tpublicKey,\n\t\tapiUrl,\n\t\twsUrl\n\t);\n\n\t// Only use website store if we have a valid client\n\tconst { website, isLoading, error: websiteError } = useWebsiteStore(client);\n\tconst isVisitorBlocked = website?.visitor?.isBlocked ?? false;\n\tconst visitorId = website?.visitor?.id ?? null;\n\n\t// Derive final configuration error from both client error and API auth errors\n\tconst configurationError = React.useMemo<ConfigurationError | null>(() => {\n\t\t// Client-level config error takes precedence (missing API key)\n\t\tif (clientConfigError) {\n\t\t\treturn clientConfigError;\n\t\t}\n\n\t\t// Check if website error is an auth error (invalid/expired API key)\n\t\tif (websiteError && isAuthError(websiteError)) {\n\t\t\tconst isNextJS = isNextJSEnvironment();\n\t\t\tconst envVarName = isNextJS\n\t\t\t\t? \"NEXT_PUBLIC_COSSISTANT_API_KEY\"\n\t\t\t\t: \"COSSISTANT_API_KEY\";\n\n\t\t\treturn {\n\t\t\t\ttype: \"invalid_api_key\",\n\t\t\t\tmessage: websiteError.message,\n\t\t\t\tenvVarName,\n\t\t\t};\n\t\t}\n\n\t\treturn null;\n\t}, [clientConfigError, websiteError]);\n\n\tconst seenEntriesByConversation = useSeenStore(\n\t\tReact.useCallback((state) => state.conversations, [])\n\t);\n\n\tconst conversationSnapshots = useStoreSelector(\n\t\tclient?.conversationsStore ?? null,\n\t\tReact.useCallback(\n\t\t\t(\n\t\t\t\tstate: {\n\t\t\t\t\tids: string[];\n\t\t\t\t\tbyId: Record<\n\t\t\t\t\t\tstring,\n\t\t\t\t\t\t| {\n\t\t\t\t\t\t\t\tid: string;\n\t\t\t\t\t\t\t\tlastTimelineItem?: TimelineItem | null;\n\t\t\t\t\t\t\t\tvisitorLastSeenAt?: string | null;\n\t\t\t\t\t\t\t\tstatus?: string;\n\t\t\t\t\t\t\t\tdeletedAt?: string | null;\n\t\t\t\t\t\t }\n\t\t\t\t\t\t| undefined\n\t\t\t\t\t>;\n\t\t\t\t} | null\n\t\t\t): ConversationSnapshot[] =>\n\t\t\t\tstate\n\t\t\t\t\t? state.ids\n\t\t\t\t\t\t\t.map((id) => {\n\t\t\t\t\t\t\t\tconst conversation = state.byId[id];\n\n\t\t\t\t\t\t\t\tif (!conversation) {\n\t\t\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\tid: conversation.id,\n\t\t\t\t\t\t\t\t\tlastTimelineItem: conversation.lastTimelineItem ?? null,\n\t\t\t\t\t\t\t\t\tvisitorLastSeenAt: conversation.visitorLastSeenAt ?? null,\n\t\t\t\t\t\t\t\t\tstatus: conversation.status ?? \"open\",\n\t\t\t\t\t\t\t\t\tdeletedAt: conversation.deletedAt ?? null,\n\t\t\t\t\t\t\t\t} satisfies ConversationSnapshot;\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t\t(snapshot): snapshot is ConversationSnapshot =>\n\t\t\t\t\t\t\t\t\tsnapshot !== null\n\t\t\t\t\t\t\t)\n\t\t\t\t\t: [],\n\t\t\t[]\n\t\t),\n\t\tareConversationSnapshotsEqual\n\t);\n\n\tconst derivedUnreadCount = React.useMemo(() => {\n\t\tif (!visitorId) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tlet count = 0;\n\n\t\tfor (const {\n\t\t\tid: conversationId,\n\t\t\tlastTimelineItem,\n\t\t\tvisitorLastSeenAt,\n\t\t\tstatus,\n\t\t\tdeletedAt,\n\t\t} of conversationSnapshots) {\n\t\t\t// Skip resolved, spam, or deleted conversations\n\t\t\tif (status !== \"open\" || deletedAt) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!lastTimelineItem) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (lastTimelineItem.type !== ConversationTimelineType.MESSAGE) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tlastTimelineItem.visitorId &&\n\t\t\t\tlastTimelineItem.visitorId === visitorId\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst createdAtTime = Date.parse(lastTimelineItem.createdAt);\n\n\t\t\tif (Number.isNaN(createdAtTime)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// First check visitorLastSeenAt from the API response (available immediately)\n\t\t\tif (visitorLastSeenAt) {\n\t\t\t\tconst lastSeenTime = Date.parse(visitorLastSeenAt);\n\t\t\t\tif (!Number.isNaN(lastSeenTime) && createdAtTime <= lastSeenTime) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Fall back to seen store (updated via realtime events)\n\t\t\tconst seenEntries = seenEntriesByConversation[conversationId];\n\n\t\t\tif (seenEntries) {\n\t\t\t\tconst visitorSeenEntry = Object.values(seenEntries).find(\n\t\t\t\t\t(entry) =>\n\t\t\t\t\t\tentry.actorType === \"visitor\" && entry.actorId === visitorId\n\t\t\t\t);\n\n\t\t\t\tif (visitorSeenEntry) {\n\t\t\t\t\tconst lastSeenTime = Date.parse(visitorSeenEntry.lastSeenAt);\n\n\t\t\t\t\tif (!Number.isNaN(lastSeenTime) && createdAtTime <= lastSeenTime) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcount += 1;\n\t\t}\n\n\t\treturn count;\n\t}, [conversationSnapshots, seenEntriesByConversation, visitorId]);\n\n\tReact.useEffect(() => {\n\t\tsetUnreadCount(derivedUnreadCount);\n\t}, [derivedUnreadCount, setUnreadCount]);\n\n\t// Prime REST client with website/visitor context so headers are sent reliably\n\tReact.useEffect(() => {\n\t\tif (!(website && client)) {\n\t\t\treturn;\n\t\t}\n\n\t\tclient.setWebsiteContext(website.id, website.visitor?.id ?? undefined);\n\t}, [client, website]);\n\n\tReact.useEffect(() => {\n\t\tif (!client) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (isVisitorBlocked) {\n\t\t\tprefetchedVisitorRef.current = null;\n\t\t\treturn;\n\t\t}\n\n\t\tif (!autoConnect) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!website) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!visitorId) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (prefetchedVisitorRef.current === visitorId) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst hasExistingConversations =\n\t\t\tclient.conversationsStore.getState().ids.length > 0;\n\n\t\tprefetchedVisitorRef.current = visitorId;\n\n\t\tif (hasExistingConversations) {\n\t\t\treturn;\n\t\t}\n\n\t\tvoid client.listConversations().catch((err) => {\n\t\t\tconsole.error(\"[SupportProvider] Failed to prefetch conversations\", err);\n\t\t\tprefetchedVisitorRef.current = null;\n\t\t});\n\t}, [autoConnect, client, isVisitorBlocked, visitorId, website]);\n\n\tconst error = websiteError;\n\n\tReact.useEffect(() => {\n\t\tif (!client) {\n\t\t\treturn;\n\t\t}\n\t\tclient.setVisitorBlocked(isVisitorBlocked);\n\t}, [client, isVisitorBlocked]);\n\n\tconst setDefaultMessages = React.useCallback((messages: DefaultMessage[]) => {\n\t\t_setDefaultMessages(messages);\n\t}, []);\n\n\tconst setQuickOptions = React.useCallback((options: string[]) => {\n\t\t_setQuickOptions(options);\n\t}, []);\n\n\tconst value = React.useMemo<CossistantContextValue>(\n\t\t() => ({\n\t\t\twebsite,\n\t\t\tunreadCount,\n\t\t\tsetUnreadCount,\n\t\t\tisLoading,\n\t\t\terror,\n\t\t\tconfigurationError,\n\t\t\tclient,\n\t\t\tdefaultMessages: _defaultMessages,\n\t\t\tsetDefaultMessages,\n\t\t\tquickOptions: _quickOptions,\n\t\t\tsetQuickOptions,\n\t\t\tisOpen: config.isOpen,\n\t\t\topen,\n\t\t\tclose,\n\t\t\ttoggle,\n\t\t}),\n\t\t[\n\t\t\twebsite,\n\t\t\tunreadCount,\n\t\t\tisLoading,\n\t\t\terror,\n\t\t\tconfigurationError,\n\t\t\tclient,\n\t\t\t_defaultMessages,\n\t\t\t_quickOptions,\n\t\t\tsetDefaultMessages,\n\t\t\tsetQuickOptions,\n\t\t\tconfig.isOpen,\n\t\t\topen,\n\t\t\tclose,\n\t\t\ttoggle,\n\t\t]\n\t);\n\n\tconst webSocketKey = React.useMemo(() => {\n\t\tif (!website) {\n\t\t\treturn \"no-website\";\n\t\t}\n\n\t\tconst visitorKey = website.visitor?.id ?? \"anonymous\";\n\t\tconst blockedState = isVisitorBlocked ? \"blocked\" : \"active\";\n\n\t\treturn `${website.id}:${visitorKey}:${blockedState}`;\n\t}, [isVisitorBlocked, website]);\n\n\treturn (\n\t\t<SupportContext.Provider value={value}>\n\t\t\t<IdentificationProvider>\n\t\t\t\t<WebSocketProvider\n\t\t\t\t\tautoConnect={autoConnect && !isVisitorBlocked && !configurationError}\n\t\t\t\t\tkey={webSocketKey}\n\t\t\t\t\tonConnect={onWsConnect}\n\t\t\t\t\tonDisconnect={onWsDisconnect}\n\t\t\t\t\tonError={onWsError}\n\t\t\t\t\tpublicKey={publicKey}\n\t\t\t\t\tvisitorId={isVisitorBlocked ? undefined : website?.visitor?.id}\n\t\t\t\t\twebsiteId={website?.id}\n\t\t\t\t\twsUrl={wsUrl}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</WebSocketProvider>\n\t\t\t</IdentificationProvider>\n\t\t</SupportContext.Provider>\n\t);\n}\n\n/**\n * Hosts the entire customer support widget ecosystem by handing out context\n * about the current website, visitor, unread counts, realtime subscriptions\n * and the REST client. Provide your Cossistant public key plus optional\n * defaults to configure the widget behaviour.\n */\nexport function SupportProvider({\n\tchildren,\n\tapiUrl = \"https://api.cossistant.com/v1\",\n\twsUrl = \"wss://api.cossistant.com/ws\",\n\tpublicKey,\n\tdefaultMessages,\n\tquickOptions,\n\tautoConnect = true,\n\tonWsConnect,\n\tonWsDisconnect,\n\tonWsError,\n\tsize = \"normal\",\n\tdefaultOpen = false,\n}: SupportProviderProps): React.ReactElement {\n\treturn (\n\t\t<SupportProviderInner\n\t\t\tapiUrl={apiUrl}\n\t\t\tautoConnect={autoConnect}\n\t\t\tdefaultMessages={defaultMessages}\n\t\t\tdefaultOpen={defaultOpen}\n\t\t\tonWsConnect={onWsConnect}\n\t\t\tonWsDisconnect={onWsDisconnect}\n\t\t\tonWsError={onWsError}\n\t\t\tpublicKey={publicKey}\n\t\t\tquickOptions={quickOptions}\n\t\t\tsize={size}\n\t\t\twsUrl={wsUrl}\n\t\t>\n\t\t\t{children}\n\t\t</SupportProviderInner>\n\t);\n}\n\n/**\n * Convenience hook that exposes the aggregated support context. Throws when it\n * is consumed outside of `SupportProvider` to catch integration mistakes.\n */\nexport function useSupport(): UseSupportValue {\n\tconst context = React.useContext(SupportContext);\n\tif (!context) {\n\t\tthrow new Error(\n\t\t\t\"useSupport must be used within a cossistant SupportProvider\"\n\t\t);\n\t}\n\n\tconst availableHumanAgents = context.website?.availableHumanAgents || [];\n\tconst availableAIAgents = context.website?.availableAIAgents || [];\n\tconst visitorLanguage = context.website?.visitor?.language || null;\n\n\t// Get additional config from support store\n\tconst { config } = useSupportStore();\n\n\t// Create visitor object with normalized locale\n\tconst visitor = context.website?.visitor\n\t\t? {\n\t\t\t\t...context.website.visitor,\n\t\t\t\tlocale: normalizeLocale(visitorLanguage),\n\t\t\t}\n\t\t: undefined;\n\n\treturn {\n\t\t...context,\n\t\tavailableHumanAgents,\n\t\tavailableAIAgents,\n\t\tvisitor,\n\t\tsize: config.size,\n\t};\n}\n\n// Re-export ConfigurationError type for consumers\nexport type { ConfigurationError } from \"./hooks/private/use-rest-client\";\n"],"mappings":"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"}
@@ -17,19 +17,20 @@ function getTargetVisitorId(event) {
17
17
  */
18
18
  function shouldDeliverEvent(event, websiteId, visitorId) {
19
19
  if (websiteId && event.payload.websiteId !== websiteId) return false;
20
- if (visitorId && isPrivateTimelineEvent(event)) return false;
20
+ if (visitorId && isBlockedTimelineEventForVisitor(event)) return false;
21
21
  if (!visitorId) return true;
22
22
  const targetVisitorId = getTargetVisitorId(event);
23
23
  if (targetVisitorId && targetVisitorId !== visitorId) return false;
24
24
  return true;
25
25
  }
26
26
  /**
27
- * Returns true if the event carries a timeline item with private visibility.
27
+ * Returns true if the event carries a blocked timeline item for visitor delivery.
28
28
  */
29
- function isPrivateTimelineEvent(event) {
29
+ function isBlockedTimelineEventForVisitor(event) {
30
30
  if (event.type === "timelineItemCreated" || event.type === "timelineItemUpdated") {
31
31
  const item = event.payload.item;
32
32
  if (item && item.visibility === "private") return true;
33
+ if (item && item.type === "tool" && (!("visibility" in item) || item.visibility !== "public")) return true;
33
34
  }
34
35
  return false;
35
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"event-filter.js","names":[],"sources":["../../src/realtime/event-filter.ts"],"sourcesContent":["import type { AnyRealtimeEvent } from \"@cossistant/types/realtime-events\";\n\nfunction getTargetVisitorId(event: AnyRealtimeEvent): string | null {\n\tconst payloadVisitorId = event.payload.visitorId;\n\n\tif (typeof payloadVisitorId === \"string\" && payloadVisitorId.length > 0) {\n\t\treturn payloadVisitorId;\n\t}\n\n\tif (event.type === \"timelineItemCreated\") {\n\t\tconst itemVisitorId = event.payload.item.visitorId;\n\n\t\tif (typeof itemVisitorId === \"string\" && itemVisitorId.length > 0) {\n\t\t\treturn itemVisitorId;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Determines whether a realtime event should be processed based on website and\n * visitor identifiers.\n *\n * When a visitorId is provided (i.e. the consumer is a visitor/widget), private\n * timeline items are filtered out to prevent leaking internal data.\n */\nexport function shouldDeliverEvent(\n\tevent: AnyRealtimeEvent,\n\twebsiteId: string | null,\n\tvisitorId: string | null\n): boolean {\n\tif (websiteId && event.payload.websiteId !== websiteId) {\n\t\treturn false;\n\t}\n\n\t// When consuming as a visitor, never deliver private timeline items.\n\t// This is a defense-in-depth measure; the server should also filter these.\n\tif (visitorId && isPrivateTimelineEvent(event)) {\n\t\treturn false;\n\t}\n\n\tif (!visitorId) {\n\t\treturn true;\n\t}\n\n\tconst targetVisitorId = getTargetVisitorId(event);\n\n\tif (targetVisitorId && targetVisitorId !== visitorId) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Returns true if the event carries a timeline item with private visibility.\n */\nfunction isPrivateTimelineEvent(event: AnyRealtimeEvent): boolean {\n\tif (\n\t\tevent.type === \"timelineItemCreated\" ||\n\t\tevent.type === \"timelineItemUpdated\"\n\t) {\n\t\tconst payload = event.payload as Record<string, unknown>;\n\t\tconst item = payload.item as Record<string, unknown> | undefined;\n\t\tif (item && item.visibility === \"private\") {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nexport { getTargetVisitorId };\n"],"mappings":";AAEA,SAAS,mBAAmB,OAAwC;CACnE,MAAM,mBAAmB,MAAM,QAAQ;AAEvC,KAAI,OAAO,qBAAqB,YAAY,iBAAiB,SAAS,EACrE,QAAO;AAGR,KAAI,MAAM,SAAS,uBAAuB;EACzC,MAAM,gBAAgB,MAAM,QAAQ,KAAK;AAEzC,MAAI,OAAO,kBAAkB,YAAY,cAAc,SAAS,EAC/D,QAAO;;AAIT,QAAO;;;;;;;;;AAUR,SAAgB,mBACf,OACA,WACA,WACU;AACV,KAAI,aAAa,MAAM,QAAQ,cAAc,UAC5C,QAAO;AAKR,KAAI,aAAa,uBAAuB,MAAM,CAC7C,QAAO;AAGR,KAAI,CAAC,UACJ,QAAO;CAGR,MAAM,kBAAkB,mBAAmB,MAAM;AAEjD,KAAI,mBAAmB,oBAAoB,UAC1C,QAAO;AAGR,QAAO;;;;;AAMR,SAAS,uBAAuB,OAAkC;AACjE,KACC,MAAM,SAAS,yBACf,MAAM,SAAS,uBACd;EAED,MAAM,OADU,MAAM,QACD;AACrB,MAAI,QAAQ,KAAK,eAAe,UAC/B,QAAO;;AAGT,QAAO"}
1
+ {"version":3,"file":"event-filter.js","names":[],"sources":["../../src/realtime/event-filter.ts"],"sourcesContent":["import type { AnyRealtimeEvent } from \"@cossistant/types/realtime-events\";\n\nfunction getTargetVisitorId(event: AnyRealtimeEvent): string | null {\n\tconst payloadVisitorId = event.payload.visitorId;\n\n\tif (typeof payloadVisitorId === \"string\" && payloadVisitorId.length > 0) {\n\t\treturn payloadVisitorId;\n\t}\n\n\tif (event.type === \"timelineItemCreated\") {\n\t\tconst itemVisitorId = event.payload.item.visitorId;\n\n\t\tif (typeof itemVisitorId === \"string\" && itemVisitorId.length > 0) {\n\t\t\treturn itemVisitorId;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Determines whether a realtime event should be processed based on website and\n * visitor identifiers.\n *\n * When a visitorId is provided (i.e. the consumer is a visitor/widget), private\n * timeline items are filtered out to prevent leaking internal data.\n */\nexport function shouldDeliverEvent(\n\tevent: AnyRealtimeEvent,\n\twebsiteId: string | null,\n\tvisitorId: string | null\n): boolean {\n\tif (websiteId && event.payload.websiteId !== websiteId) {\n\t\treturn false;\n\t}\n\n\t// When consuming as a visitor, never deliver private/non-public tool timeline items.\n\t// This is a defense-in-depth measure; the server should also filter these.\n\tif (visitorId && isBlockedTimelineEventForVisitor(event)) {\n\t\treturn false;\n\t}\n\n\tif (!visitorId) {\n\t\treturn true;\n\t}\n\n\tconst targetVisitorId = getTargetVisitorId(event);\n\n\tif (targetVisitorId && targetVisitorId !== visitorId) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Returns true if the event carries a blocked timeline item for visitor delivery.\n */\nfunction isBlockedTimelineEventForVisitor(event: AnyRealtimeEvent): boolean {\n\tif (\n\t\tevent.type === \"timelineItemCreated\" ||\n\t\tevent.type === \"timelineItemUpdated\"\n\t) {\n\t\tconst payload = event.payload as Record<string, unknown>;\n\t\tconst item = payload.item as Record<string, unknown> | undefined;\n\t\tif (item && item.visibility === \"private\") {\n\t\t\treturn true;\n\t\t}\n\t\tif (\n\t\t\titem &&\n\t\t\titem.type === \"tool\" &&\n\t\t\t(!(\"visibility\" in item) || item.visibility !== \"public\")\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nexport { getTargetVisitorId };\n"],"mappings":";AAEA,SAAS,mBAAmB,OAAwC;CACnE,MAAM,mBAAmB,MAAM,QAAQ;AAEvC,KAAI,OAAO,qBAAqB,YAAY,iBAAiB,SAAS,EACrE,QAAO;AAGR,KAAI,MAAM,SAAS,uBAAuB;EACzC,MAAM,gBAAgB,MAAM,QAAQ,KAAK;AAEzC,MAAI,OAAO,kBAAkB,YAAY,cAAc,SAAS,EAC/D,QAAO;;AAIT,QAAO;;;;;;;;;AAUR,SAAgB,mBACf,OACA,WACA,WACU;AACV,KAAI,aAAa,MAAM,QAAQ,cAAc,UAC5C,QAAO;AAKR,KAAI,aAAa,iCAAiC,MAAM,CACvD,QAAO;AAGR,KAAI,CAAC,UACJ,QAAO;CAGR,MAAM,kBAAkB,mBAAmB,MAAM;AAEjD,KAAI,mBAAmB,oBAAoB,UAC1C,QAAO;AAGR,QAAO;;;;;AAMR,SAAS,iCAAiC,OAAkC;AAC3E,KACC,MAAM,SAAS,yBACf,MAAM,SAAS,uBACd;EAED,MAAM,OADU,MAAM,QACD;AACrB,MAAI,QAAQ,KAAK,eAAe,UAC/B,QAAO;AAER,MACC,QACA,KAAK,SAAS,WACb,EAAE,gBAAgB,SAAS,KAAK,eAAe,UAEhD,QAAO;;AAGT,QAAO"}
@@ -0,0 +1,6 @@
1
+ //#region src/sounds/sound-data.d.ts
2
+ declare const NEW_MESSAGE_SOUND_DATA_URL = "data:audio/mp4;base64,AAAAHGZ0eXBNNEEgAAAAAE00QSBtcDQyaXNvbQAAA1Ztb292AAAAbG12aGQAAAAA5a8JFeWvCRUAAH0AAAAkAAABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAB6HRyYWsAAABcdGtoZAAAAAflrwkV5a8JFQAAAAEAAAAAAAAkAAAAAAAAAAAAAAAAAAEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAYRtZGlhAAAAIG1kaGQAAAAA5a8JFeWvCRUAAH0AAAAkAAAAAAAAAAAiaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAAAAAAABOm1pbmYAAAAQc21oZAAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAAA/nN0YmwAAAB2c3RzZAAAAAAAAAABAAAAZm1wNGEAAAAAAAAAAQAAAAAAAAAAAAIAEAAAAAB9AAAAAAAAM2VzZHMAAAAAA4CAgCIAAAAEgICAFEAUABgAAAAw2AAA+gAFgICAAhKQBoCAgAECAAAAD3NidGQAAAAASTE2AAAAGHN0dHMAAAAAAAAAAQAAAAkAAAQAAAAAHHN0c2MAAAAAAAAAAQAAAAEAAAAJAAAAAQAAADhzdHN6AAAAAAAAAAAAAAAJAAAABgAAAFYAAAG6AAABKgAAAQsAAACxAAAAewAAAKQAAABMAAAAFHN0Y28AAAAAAAAAAQAAEAAAAAD6dWR0YQAAAPJtZXRhAAAAAAAAACJoZGxyAAAAAAAAAABtZGlyYXBwbAAAAAAAAAAAAAAAAADEaWxzdAAAALwtLS0tAAAAHG1lYW4AAAAAY29tLmFwcGxlLmlUdW5lcwAAABRuYW1lAAAAAGlUdW5TTVBCAAAAhGRhdGEAAAABAAAAACAwMDAwMDAwMCAwMDAwMDg0MCAwMDAwMDFEMiAwMDAwMDAwMDAwMDAxOUVFIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwAAAMhmZyZWUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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";
3
+ declare const TYPING_LOOP_SOUND_DATA_URL = "data:audio/mp4;base64,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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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";
4
+ //#endregion
5
+ export { NEW_MESSAGE_SOUND_DATA_URL, TYPING_LOOP_SOUND_DATA_URL };
6
+ //# sourceMappingURL=sound-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sound-data.d.ts","names":[],"sources":["../../src/sounds/sound-data.ts"],"sourcesContent":[],"mappings":";cAGa,0BAAA;AAAA,cAGA,0BAAA,GAH0B,g3fAAA"}
@@ -0,0 +1,7 @@
1
+ //#region src/sounds/sound-data.ts
2
+ const NEW_MESSAGE_SOUND_DATA_URL = "data:audio/mp4;base64,AAAAHGZ0eXBNNEEgAAAAAE00QSBtcDQyaXNvbQAAA1Ztb292AAAAbG12aGQAAAAA5a8JFeWvCRUAAH0AAAAkAAABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAB6HRyYWsAAABcdGtoZAAAAAflrwkV5a8JFQAAAAEAAAAAAAAkAAAAAAAAAAAAAAAAAAEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAYRtZGlhAAAAIG1kaGQAAAAA5a8JFeWvCRUAAH0AAAAkAAAAAAAAAAAiaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAAAAAAABOm1pbmYAAAAQc21oZAAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAAA/nN0YmwAAAB2c3RzZAAAAAAAAAABAAAAZm1wNGEAAAAAAAAAAQAAAAAAAAAAAAIAEAAAAAB9AAAAAAAAM2VzZHMAAAAAA4CAgCIAAAAEgICAFEAUABgAAAAw2AAA+gAFgICAAhKQBoCAgAECAAAAD3NidGQAAAAASTE2AAAAGHN0dHMAAAAAAAAAAQAAAAkAAAQAAAAAHHN0c2MAAAAAAAAAAQAAAAEAAAAJAAAAAQAAADhzdHN6AAAAAAAAAAAAAAAJAAAABgAAAFYAAAG6AAABKgAAAQsAAACxAAAAewAAAKQAAABMAAAAFHN0Y28AAAAAAAAAAQAAEAAAAAD6dWR0YQAAAPJtZXRhAAAAAAAAACJoZGxyAAAAAAAAAABtZGlyYXBwbAAAAAAAAAAAAAAAAADEaWxzdAAAALwtLS0tAAAAHG1lYW4AAAAAY29tLmFwcGxlLmlUdW5lcwAAABRuYW1lAAAAAGlUdW5TTVBCAAAAhGRhdGEAAAABAAAAACAwMDAwMDAwMCAwMDAwMDg0MCAwMDAwMDFEMiAwMDAwMDAwMDAwMDAxOUVFIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwAAAMhmZyZWUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZvbWRhdCEAA0BoHCEr1BgGDocPhW8ii2ouRlaYYcAh4CoVDyjQfwvSJgIZ6nHnx4H9gmbr3to+0RjCJLBIYfC89ZZ0t1guRdaYfeIeAoTsl8+nUcotMH1NHZXPVpegj6eAIU1k//P/n/z/5//hYTckgMIjCEsVoGkvCMC+RswMtuRT9/t/Pbj1d93//Sn6z68fXj2w/u+7+Vr8Y/7P8a1PrNNP/p4+vr6edQbXLrLwE9jl+Ig6DlS9yDEy1CNsUKI2lTUGRxbe5TUgUJiqRxEO7zteeuviAzYEXtn7c5ZIv2fwwFjz500fgHOAmw4hGvlrMzmu/KFDcYSd/Lp+X0dJny9vaq71VZSZnuyWZ2MNOGc7XV0q3I/SEat24xXlRMYc+2FsO0B/mdr5nVCQk0qrtbX2L+KZYG28pLlBEuXXkT20pTFJy2OHtOiqnzUgDET291VJY5tQkPW+7tvZSE6WApA8FH12JRUjsiETw8trV0asnnQbU0f1Q4fSa6K+X9t0RBrUQz0qPr0tHejgMp6XJgKP55X4hxv/+l7L/n7fj18Z1Vf8HH/fIYvf/w6/f29jjn/9vE+P+/v/KIXM4uQH5SESQQGNfkP21EYpGLIQ9QDkcADivXjAORd0rVgHPlTLhIwwX6V/3U62K+QMC3unwBuqvGPuYSwNAQ9qC3coCh2xLY57+N7PBkEgzYqnhiWsl57NrbV4WVsSvyFrz//h////+XpNiJABQxIYRDQgEeexthxfXVl9CaYkUlFqst1GgTwC1BVHKokQThQByjxhmTKxZSrIKyKAfHx8GHv7+5+Hw27Z2y+RcKhVV5Ed82GtDM9S9l7Reh1ZMf9SyaEpXY5SHPcAzd7HvRc3A7p5c5JciBgYLlYHFaFmOegKM1HTWFNGMTe4GBxrdyKu+Y5jjUtLUo71uLADiTbzug7wprM5TnfjCoPxOx1v4pIwVWXsnyeGyWr1y8xUokp21dkol3JE4G9J5qBKgCeQRgURAIREMUAR8bvs5pcyf+zglaYLQFCdjTswyWkJv6c0cAjhpBdeNwAEAAK+iV6DsgLXARlHFprQ16t28/M6rrFhiARYXCMty/Zjsjkw5n06wn7HTMndjAchC9RsJsQDVBHQghQxDAgchb+bNuClkRNxAga2qC4lcU05A64AtmTktWdS45RCjWtdRm2L3j3dLurNfVsAxjCu0F7kJU1OCveAcr7C5Do7hoYkFREYJM+HsceeEE0iqm9OQlTOCVWY0oVuqsSz2tXauajRIlIkK4JTgDtClU8Vc98G+BZhOLlQOWJFg9k0rZV2nqqF9TWOjcGIC184uEJukFOxLdENriIpljviLK0icy4I+AgNCuIDioCCoCs4dw/w6wE4N3MIMmaN2FJCk5v92QhcMPHAmjJCXVYyLgALxFxRTJ7dmv8qr96U513Yfz9CVbhCSF67qVpLFZYlC4g1NiWLVQ3hUkhSqrghC9RtLAaKGAHdW9Daf5C0BZmcbtN2GtFkokgl0M1wC4MuEhJl8zr1aGiiir4WyqBQHSueHykcrOuuxwsY0avUydMbV5d2aPzdYSXkndZjRn9PC0S9c8DnhdsVZ8q4/9+ILlgButj/Qr7wBUlln/HIYeIWpjyLABJzkFcdnkjKNVYHEIJEIFEwHaO8VMf78SFWM/ZQxgAvu19chcC6IBOazDDqYjJcUjf1JgL9FuNfth4hC9RFBY7kQxJA4hBh07mX4u37xZ30BlDWjAOB7YlG9jfv+1OnucJsDiR6yM4dODTCymoa4YfFK0M+8QM8iMNBEVfPuGJiRuDS0qAAIFCMRYDIomCz248DGP8gL2HE9iTZZ0wp9aBi3lrG5fYVnveYypCM02Hx660AmcAhC9Q0KQpKEoDFIFNMKLOkjRYxQWyIXIno///7tQkGARBKKUUJR5JNiClm6IEAAAAABi1Y+yRFplzfbVQOu3fA9qZ7UnNB81QIpNSKYE1GWHMVkFJABjABDSaP6n5OtNM9Fovw9vJKKygzaAfCK6kkYxdcn72PzUhp+d9WbNFq4CiQMNcGTAffQXInv/4A5jSCqpW6qZqfjkAGohywwZLJJ52KPCEL1GM8PhfXaT2B3XS5GTIYeACHgIAd3d3d3eQ2ZK5f3/zHFmAnd3d3d8JHeKRofG++Ghs0uRMyGHgA+fRQUFBQU0N1qahBQUFBTXA=";
3
+ const TYPING_LOOP_SOUND_DATA_URL = "data:audio/mp4;base64,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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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";
4
+
5
+ //#endregion
6
+ export { NEW_MESSAGE_SOUND_DATA_URL, TYPING_LOOP_SOUND_DATA_URL };
7
+ //# sourceMappingURL=sound-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sound-data.js","names":[],"sources":["../../src/sounds/sound-data.ts"],"sourcesContent":["// Inline base64-encoded AAC audio files\n// Converted from WAV to AAC (m4a) at 64kbps for minimal bundle size (~24KB total)\n\nexport const NEW_MESSAGE_SOUND_DATA_URL =\n\t\"data:audio/mp4;base64,AAAAHGZ0eXBNNEEgAAAAAE00QSBtcDQyaXNvbQAAA1Ztb292AAAAbG12aGQAAAAA5a8JFeWvCRUAAH0AAAAkAAABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAB6HRyYWsAAABcdGtoZAAAAAflrwkV5a8JFQAAAAEAAAAAAAAkAAAAAAAAAAAAAAAAAAEAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAYRtZGlhAAAAIG1kaGQAAAAA5a8JFeWvCRUAAH0AAAAkAAAAAAAAAAAiaGRscgAAAAAAAAAAc291bgAAAAAAAAAAAAAAAAAAAAABOm1pbmYAAAAQc21oZAAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAAA/nN0YmwAAAB2c3RzZAAAAAAAAAABAAAAZm1wNGEAAAAAAAAAAQAAAAAAAAAAAAIAEAAAAAB9AAAAAAAAM2VzZHMAAAAAA4CAgCIAAAAEgICAFEAUABgAAAAw2AAA+gAFgICAAhKQBoCAgAECAAAAD3NidGQAAAAASTE2AAAAGHN0dHMAAAAAAAAAAQAAAAkAAAQAAAAAHHN0c2MAAAAAAAAAAQAAAAEAAAAJAAAAAQAAADhzdHN6AAAAAAAAAAAAAAAJAAAABgAAAFYAAAG6AAABKgAAAQsAAACxAAAAewAAAKQAAABMAAAAFHN0Y28AAAAAAAAAAQAAEAAAAAD6dWR0YQAAAPJtZXRhAAAAAAAAACJoZGxyAAAAAAAAAABtZGlyYXBwbAAAAAAAAAAAAAAAAADEaWxzdAAAALwtLS0tAAAAHG1lYW4AAAAAY29tLmFwcGxlLmlUdW5lcwAAABRuYW1lAAAAAGlUdW5TTVBCAAAAhGRhdGEAAAABAAAAACAwMDAwMDAwMCAwMDAwMDg0MCAwMDAwMDFEMiAwMDAwMDAwMDAwMDAxOUVFIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwIDAwMDAwMDAwAAAMhmZyZWUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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\";\n\nexport const TYPING_LOOP_SOUND_DATA_URL =\n\t\"data:audio/mp4;base64,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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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\";\n"],"mappings":";AAGA,MAAa,6BACZ;AAED,MAAa,6BACZ"}
@@ -84,7 +84,7 @@ function AvatarStack({ humanAgents, aiAgents, hideBranding = false, hideDefaultA
84
84
  image: item.agent?.image,
85
85
  isAI: true,
86
86
  name: item.agent?.name || "AI",
87
- showBackground: !!item.agent?.image
87
+ showBackground: true
88
88
  })
89
89
  ]
90
90
  }, `avatar-${index}`))
@@ -1 +1 @@
1
- {"version":3,"file":"avatar-stack.js","names":[],"sources":["../../../src/support/components/avatar-stack.tsx"],"sourcesContent":["import type { AvailableAIAgent, AvailableHumanAgent } from \"@cossistant/types\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport { useRenderElement } from \"../../utils/use-render-element\";\nimport { cn } from \"../utils\";\nimport { Avatar } from \"./avatar\";\n\ntype AvatarStackProps = {\n\thumanAgents: AvailableHumanAgent[];\n\taiAgents: AvailableAIAgent[];\n\thideBranding?: boolean;\n\thideDefaultAIAgent?: boolean;\n\tclassName?: string;\n\t/** Size of avatars (default: 44px) */\n\tsize?: number;\n\t/** Space between avatars (default: 28px) */\n\tspacing?: number;\n\t/** Gap width between avatars (default: 2px) */\n\tgapWidth?: number;\n};\n\n/**\n * Creates an SVG mask with a rounded rectangle cutout on the left side.\n * This respects the border radius of the avatars.\n */\nfunction createRoundedCutoutMask(\n\tsize: number,\n\tcutoutWidth: number,\n\tborderRadius: number\n): string {\n\t// SVG mask: white = visible, black = hidden\n\t// We create a white rectangle (full size) and subtract a rounded rect on the left\n\t// The cutout rect is extended beyond top/bottom bounds so only the right-side curve is visible\n\tconst extension = borderRadius * 0.15;\n\tconst svg = `\n\t\t<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${size}\" height=\"${size}\">\n\t\t\t<defs>\n\t\t\t\t<mask id=\"m\">\n\t\t\t\t\t<rect width=\"${size}\" height=\"${size}\" fill=\"white\"/>\n\t\t\t\t\t<rect x=\"${-size + cutoutWidth}\" y=\"${-extension}\" width=\"${size}\" height=\"${size + extension * 2}\" rx=\"${borderRadius}\" ry=\"${borderRadius}\" fill=\"black\"/>\n\t\t\t\t</mask>\n\t\t\t</defs>\n\t\t\t<rect width=\"${size}\" height=\"${size}\" fill=\"white\" mask=\"url(#m)\"/>\n\t\t</svg>\n\t`.replace(/\\s+/g, \" \");\n\n\treturn `url(\"data:image/svg+xml,${encodeURIComponent(svg)}\")`;\n}\n\nexport const AvatarStackItem = ({\n\tchildren,\n\tindex,\n\tsize = 44,\n\tspacing = 32,\n\tgapWidth = 1,\n\tclassName,\n}: {\n\tchildren: ReactNode;\n\tindex: number;\n\tsize?: number;\n\tspacing?: number;\n\tgapWidth?: number;\n\tclassName?: string;\n}): ReactElement | null => {\n\tconst isFirst = index === 0;\n\n\t// Calculate mask for squared avatars with rounded corners\n\t// The mask creates a cutout on the left side where the previous avatar overlaps\n\tconst cutoutWidth = size - spacing + gapWidth;\n\tconst borderRadius = 4; // Match the 4px border radius used on avatars\n\n\tconst maskImage = createRoundedCutoutMask(size, cutoutWidth, borderRadius);\n\n\treturn useRenderElement(\n\t\t\"div\",\n\t\t{ className },\n\t\t{\n\t\t\tprops: {\n\t\t\t\tclassName: cn(\n\t\t\t\t\t\"relative grid place-items-center\",\n\t\t\t\t\t!isFirst && \"[mask-repeat:no-repeat] [mask-size:100%_100%]\"\n\t\t\t\t),\n\t\t\t\tstyle: {\n\t\t\t\t\twidth: `${size}px`,\n\t\t\t\t\theight: `${size}px`,\n\t\t\t\t\t// Apply mask only to non-first items - uses SVG for rounded cutout\n\t\t\t\t\t...(isFirst\n\t\t\t\t\t\t? {}\n\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\tmaskImage,\n\t\t\t\t\t\t\t\tWebkitMaskImage: maskImage,\n\t\t\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t\tchildren,\n\t\t\t},\n\t\t}\n\t);\n};\n\n/**\n * Displays a compact row of agent avatars with optional branding and overflow\n * counts.\n */\nexport function AvatarStack({\n\thumanAgents,\n\taiAgents,\n\thideBranding = false,\n\thideDefaultAIAgent = true,\n\tclassName,\n\tsize = 44,\n\tspacing = 36,\n\tgapWidth = 3,\n}: AvatarStackProps): ReactElement | null {\n\tconst displayedHumanAgents = humanAgents.slice(0, 2);\n\tconst remainingHumanAgentsCount = Math.max(0, humanAgents.length - 2);\n\n\t// Create array of all items to display\n\tconst items = [\n\t\t...displayedHumanAgents.map((agent) => ({\n\t\t\ttype: \"human\" as const,\n\t\t\tagent,\n\t\t})),\n\t\t...(remainingHumanAgentsCount > 0\n\t\t\t? [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"count\" as const,\n\t\t\t\t\t\tcount: remainingHumanAgentsCount,\n\t\t\t\t\t},\n\t\t\t\t]\n\t\t\t: []),\n\t\t...(hideDefaultAIAgent\n\t\t\t? []\n\t\t\t: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"ai\" as const,\n\t\t\t\t\t\tagent: aiAgents[0],\n\t\t\t\t\t},\n\t\t\t\t]),\n\t];\n\n\treturn useRenderElement(\n\t\t\"div\",\n\t\t{ className },\n\t\t{\n\t\t\tprops: {\n\t\t\t\tclassName: \"inline-grid items-center\",\n\t\t\t\tstyle: {\n\t\t\t\t\tgridTemplateColumns: `repeat(${items.length}, ${spacing}px)`,\n\t\t\t\t},\n\t\t\t\tchildren: items.map((item, index) => (\n\t\t\t\t\t<AvatarStackItem\n\t\t\t\t\t\tgapWidth={gapWidth}\n\t\t\t\t\t\tindex={index}\n\t\t\t\t\t\tkey={`avatar-${index}`}\n\t\t\t\t\t\tsize={size}\n\t\t\t\t\t\tspacing={spacing}\n\t\t\t\t\t>\n\t\t\t\t\t\t{item.type === \"human\" && (\n\t\t\t\t\t\t\t<Avatar\n\t\t\t\t\t\t\t\tclassName={cn(\"size-full\")}\n\t\t\t\t\t\t\t\timage={item.agent.image}\n\t\t\t\t\t\t\t\tlastSeenAt={item.agent.lastSeenAt}\n\t\t\t\t\t\t\t\tname={item.agent.name}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{item.type === \"count\" && (\n\t\t\t\t\t\t\t<div className=\"flex size-full items-center justify-center rounded bg-co-background-200 font-medium text-co-primary text-sm ring-1 ring-co-border/30 dark:bg-co-background-500\">\n\t\t\t\t\t\t\t\t+{item.count}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{item.type === \"ai\" && (\n\t\t\t\t\t\t\t<Avatar\n\t\t\t\t\t\t\t\tclassName=\"z-0 size-full\"\n\t\t\t\t\t\t\t\timage={item.agent?.image}\n\t\t\t\t\t\t\t\tisAI\n\t\t\t\t\t\t\t\tname={item.agent?.name || \"AI\"}\n\t\t\t\t\t\t\t\tshowBackground={!!item.agent?.image}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</AvatarStackItem>\n\t\t\t\t)),\n\t\t\t},\n\t\t}\n\t);\n}\n"],"mappings":";;;;;;;;;;AAwBA,SAAS,wBACR,MACA,aACA,cACS;CAIT,MAAM,YAAY,eAAe;CACjC,MAAM,MAAM;mDACsC,KAAK,YAAY,KAAK;;;oBAGrD,KAAK,YAAY,KAAK;gBAC1B,CAAC,OAAO,YAAY,OAAO,CAAC,UAAU,WAAW,KAAK,YAAY,OAAO,YAAY,EAAE,QAAQ,aAAa,QAAQ,aAAa;;;kBAG/H,KAAK,YAAY,KAAK;;GAErC,QAAQ,QAAQ,IAAI;AAEtB,QAAO,2BAA2B,mBAAmB,IAAI,CAAC;;AAG3D,MAAa,mBAAmB,EAC/B,UACA,OACA,OAAO,IACP,UAAU,IACV,WAAW,GACX,gBAQ0B;CAC1B,MAAM,UAAU,UAAU;CAO1B,MAAM,YAAY,wBAAwB,MAHtB,OAAO,UAAU,UAChB,EAEqD;AAE1E,QAAO,iBACN,OACA,EAAE,WAAW,EACb,EACC,OAAO;EACN,WAAW,GACV,oCACA,CAAC,WAAW,gDACZ;EACD,OAAO;GACN,OAAO,GAAG,KAAK;GACf,QAAQ,GAAG,KAAK;GAEhB,GAAI,UACD,EAAE,GACF;IACA;IACA,iBAAiB;IACjB;GACH;EACD;EACA,EACD,CACD;;;;;;AAOF,SAAgB,YAAY,EAC3B,aACA,UACA,eAAe,OACf,qBAAqB,MACrB,WACA,OAAO,IACP,UAAU,IACV,WAAW,KAC8B;CACzC,MAAM,uBAAuB,YAAY,MAAM,GAAG,EAAE;CACpD,MAAM,4BAA4B,KAAK,IAAI,GAAG,YAAY,SAAS,EAAE;CAGrE,MAAM,QAAQ;EACb,GAAG,qBAAqB,KAAK,WAAW;GACvC,MAAM;GACN;GACA,EAAE;EACH,GAAI,4BAA4B,IAC7B,CACA;GACC,MAAM;GACN,OAAO;GACP,CACD,GACA,EAAE;EACL,GAAI,qBACD,EAAE,GACF,CACA;GACC,MAAM;GACN,OAAO,SAAS;GAChB,CACD;EACH;AAED,QAAO,iBACN,OACA,EAAE,WAAW,EACb,EACC,OAAO;EACN,WAAW;EACX,OAAO,EACN,qBAAqB,UAAU,MAAM,OAAO,IAAI,QAAQ,MACxD;EACD,UAAU,MAAM,KAAK,MAAM,UAC1B,qBAAC;GACU;GACH;GAED;GACG;;IAER,KAAK,SAAS,WACd,oBAAC;KACA,WAAW,GAAG,YAAY;KAC1B,OAAO,KAAK,MAAM;KAClB,YAAY,KAAK,MAAM;KACvB,MAAM,KAAK,MAAM;MAChB;IAEF,KAAK,SAAS,WACd,qBAAC;KAAI,WAAU;gBAAiK,KAC7K,KAAK;MACF;IAEN,KAAK,SAAS,QACd,oBAAC;KACA,WAAU;KACV,OAAO,KAAK,OAAO;KACnB;KACA,MAAM,KAAK,OAAO,QAAQ;KAC1B,gBAAgB,CAAC,CAAC,KAAK,OAAO;MAC7B;;KAxBE,UAAU,QA0BE,CACjB;EACF,EACD,CACD"}
1
+ {"version":3,"file":"avatar-stack.js","names":[],"sources":["../../../src/support/components/avatar-stack.tsx"],"sourcesContent":["import type { AvailableAIAgent, AvailableHumanAgent } from \"@cossistant/types\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport { useRenderElement } from \"../../utils/use-render-element\";\nimport { cn } from \"../utils\";\nimport { Avatar } from \"./avatar\";\n\ntype AvatarStackProps = {\n\thumanAgents: AvailableHumanAgent[];\n\taiAgents: AvailableAIAgent[];\n\thideBranding?: boolean;\n\thideDefaultAIAgent?: boolean;\n\tclassName?: string;\n\t/** Size of avatars (default: 44px) */\n\tsize?: number;\n\t/** Space between avatars (default: 28px) */\n\tspacing?: number;\n\t/** Gap width between avatars (default: 2px) */\n\tgapWidth?: number;\n};\n\n/**\n * Creates an SVG mask with a rounded rectangle cutout on the left side.\n * This respects the border radius of the avatars.\n */\nfunction createRoundedCutoutMask(\n\tsize: number,\n\tcutoutWidth: number,\n\tborderRadius: number\n): string {\n\t// SVG mask: white = visible, black = hidden\n\t// We create a white rectangle (full size) and subtract a rounded rect on the left\n\t// The cutout rect is extended beyond top/bottom bounds so only the right-side curve is visible\n\tconst extension = borderRadius * 0.15;\n\tconst svg = `\n\t\t<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${size}\" height=\"${size}\">\n\t\t\t<defs>\n\t\t\t\t<mask id=\"m\">\n\t\t\t\t\t<rect width=\"${size}\" height=\"${size}\" fill=\"white\"/>\n\t\t\t\t\t<rect x=\"${-size + cutoutWidth}\" y=\"${-extension}\" width=\"${size}\" height=\"${size + extension * 2}\" rx=\"${borderRadius}\" ry=\"${borderRadius}\" fill=\"black\"/>\n\t\t\t\t</mask>\n\t\t\t</defs>\n\t\t\t<rect width=\"${size}\" height=\"${size}\" fill=\"white\" mask=\"url(#m)\"/>\n\t\t</svg>\n\t`.replace(/\\s+/g, \" \");\n\n\treturn `url(\"data:image/svg+xml,${encodeURIComponent(svg)}\")`;\n}\n\nexport const AvatarStackItem = ({\n\tchildren,\n\tindex,\n\tsize = 44,\n\tspacing = 32,\n\tgapWidth = 1,\n\tclassName,\n}: {\n\tchildren: ReactNode;\n\tindex: number;\n\tsize?: number;\n\tspacing?: number;\n\tgapWidth?: number;\n\tclassName?: string;\n}): ReactElement | null => {\n\tconst isFirst = index === 0;\n\n\t// Calculate mask for squared avatars with rounded corners\n\t// The mask creates a cutout on the left side where the previous avatar overlaps\n\tconst cutoutWidth = size - spacing + gapWidth;\n\tconst borderRadius = 4; // Match the 4px border radius used on avatars\n\n\tconst maskImage = createRoundedCutoutMask(size, cutoutWidth, borderRadius);\n\n\treturn useRenderElement(\n\t\t\"div\",\n\t\t{ className },\n\t\t{\n\t\t\tprops: {\n\t\t\t\tclassName: cn(\n\t\t\t\t\t\"relative grid place-items-center\",\n\t\t\t\t\t!isFirst && \"[mask-repeat:no-repeat] [mask-size:100%_100%]\"\n\t\t\t\t),\n\t\t\t\tstyle: {\n\t\t\t\t\twidth: `${size}px`,\n\t\t\t\t\theight: `${size}px`,\n\t\t\t\t\t// Apply mask only to non-first items - uses SVG for rounded cutout\n\t\t\t\t\t...(isFirst\n\t\t\t\t\t\t? {}\n\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\tmaskImage,\n\t\t\t\t\t\t\t\tWebkitMaskImage: maskImage,\n\t\t\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t\tchildren,\n\t\t\t},\n\t\t}\n\t);\n};\n\n/**\n * Displays a compact row of agent avatars with optional branding and overflow\n * counts.\n */\nexport function AvatarStack({\n\thumanAgents,\n\taiAgents,\n\thideBranding = false,\n\thideDefaultAIAgent = true,\n\tclassName,\n\tsize = 44,\n\tspacing = 36,\n\tgapWidth = 3,\n}: AvatarStackProps): ReactElement | null {\n\tconst displayedHumanAgents = humanAgents.slice(0, 2);\n\tconst remainingHumanAgentsCount = Math.max(0, humanAgents.length - 2);\n\n\t// Create array of all items to display\n\tconst items = [\n\t\t...displayedHumanAgents.map((agent) => ({\n\t\t\ttype: \"human\" as const,\n\t\t\tagent,\n\t\t})),\n\t\t...(remainingHumanAgentsCount > 0\n\t\t\t? [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"count\" as const,\n\t\t\t\t\t\tcount: remainingHumanAgentsCount,\n\t\t\t\t\t},\n\t\t\t\t]\n\t\t\t: []),\n\t\t...(hideDefaultAIAgent\n\t\t\t? []\n\t\t\t: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"ai\" as const,\n\t\t\t\t\t\tagent: aiAgents[0],\n\t\t\t\t\t},\n\t\t\t\t]),\n\t];\n\n\treturn useRenderElement(\n\t\t\"div\",\n\t\t{ className },\n\t\t{\n\t\t\tprops: {\n\t\t\t\tclassName: \"inline-grid items-center\",\n\t\t\t\tstyle: {\n\t\t\t\t\tgridTemplateColumns: `repeat(${items.length}, ${spacing}px)`,\n\t\t\t\t},\n\t\t\t\tchildren: items.map((item, index) => (\n\t\t\t\t\t<AvatarStackItem\n\t\t\t\t\t\tgapWidth={gapWidth}\n\t\t\t\t\t\tindex={index}\n\t\t\t\t\t\tkey={`avatar-${index}`}\n\t\t\t\t\t\tsize={size}\n\t\t\t\t\t\tspacing={spacing}\n\t\t\t\t\t>\n\t\t\t\t\t\t{item.type === \"human\" && (\n\t\t\t\t\t\t\t<Avatar\n\t\t\t\t\t\t\t\tclassName={cn(\"size-full\")}\n\t\t\t\t\t\t\t\timage={item.agent.image}\n\t\t\t\t\t\t\t\tlastSeenAt={item.agent.lastSeenAt}\n\t\t\t\t\t\t\t\tname={item.agent.name}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{item.type === \"count\" && (\n\t\t\t\t\t\t\t<div className=\"flex size-full items-center justify-center rounded bg-co-background-200 font-medium text-co-primary text-sm ring-1 ring-co-border/30 dark:bg-co-background-500\">\n\t\t\t\t\t\t\t\t+{item.count}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{item.type === \"ai\" && (\n\t\t\t\t\t\t\t<Avatar\n\t\t\t\t\t\t\t\tclassName=\"z-0 size-full\"\n\t\t\t\t\t\t\t\timage={item.agent?.image}\n\t\t\t\t\t\t\t\tisAI\n\t\t\t\t\t\t\t\tname={item.agent?.name || \"AI\"}\n\t\t\t\t\t\t\t\tshowBackground\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</AvatarStackItem>\n\t\t\t\t)),\n\t\t\t},\n\t\t}\n\t);\n}\n"],"mappings":";;;;;;;;;;AAwBA,SAAS,wBACR,MACA,aACA,cACS;CAIT,MAAM,YAAY,eAAe;CACjC,MAAM,MAAM;mDACsC,KAAK,YAAY,KAAK;;;oBAGrD,KAAK,YAAY,KAAK;gBAC1B,CAAC,OAAO,YAAY,OAAO,CAAC,UAAU,WAAW,KAAK,YAAY,OAAO,YAAY,EAAE,QAAQ,aAAa,QAAQ,aAAa;;;kBAG/H,KAAK,YAAY,KAAK;;GAErC,QAAQ,QAAQ,IAAI;AAEtB,QAAO,2BAA2B,mBAAmB,IAAI,CAAC;;AAG3D,MAAa,mBAAmB,EAC/B,UACA,OACA,OAAO,IACP,UAAU,IACV,WAAW,GACX,gBAQ0B;CAC1B,MAAM,UAAU,UAAU;CAO1B,MAAM,YAAY,wBAAwB,MAHtB,OAAO,UAAU,UAChB,EAEqD;AAE1E,QAAO,iBACN,OACA,EAAE,WAAW,EACb,EACC,OAAO;EACN,WAAW,GACV,oCACA,CAAC,WAAW,gDACZ;EACD,OAAO;GACN,OAAO,GAAG,KAAK;GACf,QAAQ,GAAG,KAAK;GAEhB,GAAI,UACD,EAAE,GACF;IACA;IACA,iBAAiB;IACjB;GACH;EACD;EACA,EACD,CACD;;;;;;AAOF,SAAgB,YAAY,EAC3B,aACA,UACA,eAAe,OACf,qBAAqB,MACrB,WACA,OAAO,IACP,UAAU,IACV,WAAW,KAC8B;CACzC,MAAM,uBAAuB,YAAY,MAAM,GAAG,EAAE;CACpD,MAAM,4BAA4B,KAAK,IAAI,GAAG,YAAY,SAAS,EAAE;CAGrE,MAAM,QAAQ;EACb,GAAG,qBAAqB,KAAK,WAAW;GACvC,MAAM;GACN;GACA,EAAE;EACH,GAAI,4BAA4B,IAC7B,CACA;GACC,MAAM;GACN,OAAO;GACP,CACD,GACA,EAAE;EACL,GAAI,qBACD,EAAE,GACF,CACA;GACC,MAAM;GACN,OAAO,SAAS;GAChB,CACD;EACH;AAED,QAAO,iBACN,OACA,EAAE,WAAW,EACb,EACC,OAAO;EACN,WAAW;EACX,OAAO,EACN,qBAAqB,UAAU,MAAM,OAAO,IAAI,QAAQ,MACxD;EACD,UAAU,MAAM,KAAK,MAAM,UAC1B,qBAAC;GACU;GACH;GAED;GACG;;IAER,KAAK,SAAS,WACd,oBAAC;KACA,WAAW,GAAG,YAAY;KAC1B,OAAO,KAAK,MAAM;KAClB,YAAY,KAAK,MAAM;KACvB,MAAM,KAAK,MAAM;MAChB;IAEF,KAAK,SAAS,WACd,qBAAC;KAAI,WAAU;gBAAiK,KAC7K,KAAK;MACF;IAEN,KAAK,SAAS,QACd,oBAAC;KACA,WAAU;KACV,OAAO,KAAK,OAAO;KACnB;KACA,MAAM,KAAK,OAAO,QAAQ;KAC1B;MACC;;KAxBE,UAAU,QA0BE,CACjB;EACF,EACD,CACD"}
@@ -30,8 +30,7 @@ type AvatarProps = {
30
30
  };
31
31
  /**
32
32
  * Renders a squared avatar with graceful fallbacks using Facehash when no
33
- * image is available. Features squircle corners when supported by the browser
34
- * and a subtle ring border.
33
+ * image is available. Features rounded corners and a subtle ring border.
35
34
  *
36
35
  * For AI agents without an image, displays the Cossistant logo without
37
36
  * a background.
@@ -1 +1 @@
1
- {"version":3,"file":"avatar.d.ts","names":[],"sources":["../../../src/support/components/avatar.tsx"],"sourcesContent":[],"mappings":";;;KAuBK,WAAA;;EAAA,KAAA,CAAA,EAAA,MAAW,GAAA,IAAA;EAoCA,IAAA,EAAA,MAAM;EACrB;EACA,IAAA,CAAA,EAAA,OAAA;EACA;EACA,cAAA,CAAA,EAAA,OAAA;EACA;;;;;EAIgB,YAAA,CAAA,EAAA,MAAA,EAAA;EAAY;;;;;;;;;;;;;;;;;;;;;iBATb,MAAA;;;;;;;;;GASb,cAAc"}
1
+ {"version":3,"file":"avatar.d.ts","names":[],"sources":["../../../src/support/components/avatar.tsx"],"sourcesContent":[],"mappings":";;;KAuBK,WAAA;;EAAA,KAAA,CAAA,EAAA,MAAW,GAAA,IAAA;EAmCA,IAAA,EAAA,MAAM;EACrB;EACA,IAAA,CAAA,EAAA,OAAA;EACA;EACA,cAAA,CAAA,EAAA,OAAA;EACA;;;;;EAIgB,YAAA,CAAA,EAAA,MAAA,EAAA;EAAY;;;;;;;;;;;;;;;;;;;;iBATb,MAAA;;;;;;;;;GASb,cAAc"}