@cossistant/react 0.0.14 → 0.0.17

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 (125) hide show
  1. package/hooks/index.d.ts +2 -1
  2. package/hooks/index.js +2 -1
  3. package/hooks/use-home-page.js +1 -1
  4. package/hooks/use-home-page.js.map +1 -1
  5. package/hooks/use-scroll-mask.d.ts +24 -0
  6. package/hooks/use-scroll-mask.d.ts.map +1 -0
  7. package/hooks/use-scroll-mask.js +90 -0
  8. package/hooks/use-scroll-mask.js.map +1 -0
  9. package/hooks/use-send-message.js +1 -1
  10. package/hooks/use-send-message.js.map +1 -1
  11. package/index.d.ts +7 -2
  12. package/index.js +9 -5
  13. package/package.json +8 -4
  14. package/parse.d.ts.map +1 -1
  15. package/primitives/avatar/image.d.ts +1 -1
  16. package/primitives/bubble.d.ts +10 -2
  17. package/primitives/bubble.d.ts.map +1 -1
  18. package/primitives/bubble.js +11 -3
  19. package/primitives/bubble.js.map +1 -1
  20. package/primitives/conversation-timeline.d.ts.map +1 -1
  21. package/primitives/conversation-timeline.js +10 -20
  22. package/primitives/conversation-timeline.js.map +1 -1
  23. package/primitives/index.d.ts +5 -2
  24. package/primitives/index.js +11 -3
  25. package/primitives/index.parts.d.ts +4 -1
  26. package/primitives/index.parts.js +5 -2
  27. package/primitives/multimodal-input.d.ts +2 -2
  28. package/primitives/multimodal-input.d.ts.map +1 -1
  29. package/primitives/page-registry.d.ts +30 -0
  30. package/primitives/page-registry.d.ts.map +1 -0
  31. package/primitives/page-registry.js +45 -0
  32. package/primitives/page-registry.js.map +1 -0
  33. package/primitives/page.d.ts +21 -0
  34. package/primitives/page.d.ts.map +1 -0
  35. package/primitives/page.js +18 -0
  36. package/primitives/page.js.map +1 -0
  37. package/primitives/router.d.ts +35 -0
  38. package/primitives/router.d.ts.map +1 -0
  39. package/primitives/router.js +22 -0
  40. package/primitives/router.js.map +1 -0
  41. package/primitives/window.d.ts +8 -3
  42. package/primitives/window.d.ts.map +1 -1
  43. package/primitives/window.js +8 -3
  44. package/primitives/window.js.map +1 -1
  45. package/realtime/index.js +1 -1
  46. package/realtime/provider.js +1 -1
  47. package/realtime/support-provider.js +0 -4
  48. package/realtime/support-provider.js.map +1 -1
  49. package/schemas2.d.ts.map +1 -1
  50. package/support/components/avatar-stack.js +1 -1
  51. package/support/components/avatar-stack.js.map +1 -1
  52. package/support/components/bubble.js +1 -1
  53. package/support/components/bubble.js.map +1 -1
  54. package/support/components/button.js +3 -3
  55. package/support/components/button.js.map +1 -1
  56. package/support/components/container.js +1 -1
  57. package/support/components/container.js.map +1 -1
  58. package/support/components/conversation-timeline.js +1 -1
  59. package/support/components/conversation-timeline.js.map +1 -1
  60. package/support/components/multimodal-input.js +2 -2
  61. package/support/components/multimodal-input.js.map +1 -1
  62. package/support/components/support-content.d.ts +5 -7
  63. package/support/components/support-content.d.ts.map +1 -1
  64. package/support/components/support-content.js +9 -11
  65. package/support/components/support-content.js.map +1 -1
  66. package/support/components/theme-wrapper.d.ts +15 -0
  67. package/support/components/theme-wrapper.d.ts.map +1 -0
  68. package/support/components/theme-wrapper.js +18 -0
  69. package/support/components/theme-wrapper.js.map +1 -0
  70. package/support/components/timeline-identification-tool.js +2 -2
  71. package/support/components/timeline-identification-tool.js.map +1 -1
  72. package/support/components/watermark.js +2 -2
  73. package/support/components/watermark.js.map +1 -1
  74. package/support/index.d.ts +36 -6
  75. package/support/index.d.ts.map +1 -1
  76. package/support/index.js +43 -20
  77. package/support/index.js.map +1 -1
  78. package/support/pages/articles.d.ts +4 -1
  79. package/support/pages/articles.d.ts.map +1 -1
  80. package/support/pages/articles.js +1 -1
  81. package/support/pages/articles.js.map +1 -1
  82. package/support/pages/conversation-history.d.ts +5 -10
  83. package/support/pages/conversation-history.d.ts.map +1 -1
  84. package/support/pages/conversation-history.js +2 -9
  85. package/support/pages/conversation-history.js.map +1 -1
  86. package/support/pages/conversation.d.ts +17 -12
  87. package/support/pages/conversation.d.ts.map +1 -1
  88. package/support/pages/conversation.js +5 -2
  89. package/support/pages/conversation.js.map +1 -1
  90. package/support/pages/home.d.ts +5 -12
  91. package/support/pages/home.d.ts.map +1 -1
  92. package/support/pages/home.js +3 -12
  93. package/support/pages/home.js.map +1 -1
  94. package/support/router.d.ts +9 -4
  95. package/support/router.d.ts.map +1 -1
  96. package/support/router.js +34 -15
  97. package/support/router.js.map +1 -1
  98. package/support/store/support-store.d.ts +17 -14
  99. package/support/store/support-store.d.ts.map +1 -1
  100. package/support/store/support-store.js +13 -10
  101. package/support/store/support-store.js.map +1 -1
  102. package/support/{support-D0JydWRx.css → support-BQhCt9Za.css} +10 -9
  103. package/support/support-BQhCt9Za.css.map +1 -0
  104. package/support/types.d.ts +28 -0
  105. package/support/types.d.ts.map +1 -0
  106. package/support/types.js +1 -0
  107. package/support.css +1 -1
  108. package/tailwind.css +9 -8
  109. package/utils/conversation.d.ts.map +1 -1
  110. package/utils/conversation.js +3 -1
  111. package/utils/conversation.js.map +1 -1
  112. package/zod-extensions.d.ts.map +1 -1
  113. package/index4.d.ts +0 -18
  114. package/index4.d.ts.map +0 -1
  115. package/index5.d.ts +0 -999
  116. package/index5.d.ts.map +0 -1
  117. package/index6.d.ts +0 -6
  118. package/react.d.ts +0 -4
  119. package/support/components/text-effect.d.ts +0 -53
  120. package/support/components/text-effect.d.ts.map +0 -1
  121. package/support/components/text-effect.js +0 -225
  122. package/support/components/text-effect.js.map +0 -1
  123. package/support/support-D0JydWRx.css.map +0 -1
  124. package/types.d-BJcRxCew.d.ts +0 -39
  125. package/types.d-BJcRxCew.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"conversation-timeline.js","names":["React","renderProps: ConversationTimelineRenderProps"],"sources":["../../src/primitives/conversation-timeline.tsx"],"sourcesContent":["import type { TimelineItem as TimelineItemType } from \"@cossistant/types/api/timeline-item\";\nimport * as React from \"react\";\nimport { useRenderElement } from \"../utils/use-render-element\";\n\n/**\n * High-level state of the timeline handed to render-prop children so they can show\n * skeletons, empty states or pagination affordances.\n */\nexport type ConversationTimelineRenderProps = {\n\titemCount: number;\n\tisLoading?: boolean;\n\thasMore?: boolean;\n\tisEmpty: boolean;\n};\n\nexport type ConversationTimelineProps = Omit<\n\tReact.HTMLAttributes<HTMLDivElement>,\n\t\"children\"\n> & {\n\tchildren?:\n\t\t| React.ReactNode\n\t\t| ((props: ConversationTimelineRenderProps) => React.ReactNode);\n\tasChild?: boolean;\n\tclassName?: string;\n\titems?: TimelineItemType[];\n\tisLoading?: boolean;\n\thasMore?: boolean;\n\tautoScroll?: boolean;\n\tonScrollEnd?: () => void;\n\tonScrollStart?: () => void;\n};\n\nconst BOTTOM_THRESHOLD_PX = 12;\nconst TOP_THRESHOLD_PX = 2;\n\nfunction getLastItemKey(items: TimelineItemType[]): string | number | null {\n\tif (items.length === 0) {\n\t\treturn null;\n\t}\n\n\tconst lastItem = items.at(-1);\n\n\tif (lastItem?.id) {\n\t\treturn lastItem.id;\n\t}\n\n\treturn lastItem?.createdAt ?? null;\n}\n\n/**\n * Scrollable conversation timeline that wires auto-scroll behaviour, live-region semantics and\n * pagination callbacks for displaying timeline items (messages, events, etc.).\n */\nexport const ConversationTimeline = (() => {\n\tconst Component = React.forwardRef<HTMLDivElement, ConversationTimelineProps>(\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\titems = [],\n\t\t\t\tisLoading = false,\n\t\t\t\thasMore = false,\n\t\t\t\tautoScroll = true,\n\t\t\t\tonScrollEnd,\n\t\t\t\tonScrollStart,\n\t\t\t\t...props\n\t\t\t},\n\t\t\tref\n\t\t) => {\n\t\t\tconst internalRef = React.useRef<HTMLDivElement>(null);\n\t\t\tconst setRefs = React.useCallback(\n\t\t\t\t(node: HTMLDivElement | null) => {\n\t\t\t\t\tinternalRef.current = node;\n\t\t\t\t\tif (typeof ref === \"function\") {\n\t\t\t\t\t\tref(node);\n\t\t\t\t\t} else if (ref) {\n\t\t\t\t\t\t(ref as React.MutableRefObject<HTMLDivElement | null>).current =\n\t\t\t\t\t\t\tnode;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t[ref]\n\t\t\t);\n\n\t\t\tconst isInitialRender = React.useRef(true);\n\t\t\tconst previousItemCount = React.useRef(items.length);\n\t\t\tconst previousLastItemKey = React.useRef<string | number | null>(\n\t\t\t\tgetLastItemKey(items)\n\t\t\t);\n\t\t\tconst isPinnedToBottom = React.useRef(true);\n\t\t\tconst isAtTop = React.useRef(true);\n\n\t\t\tconst renderProps: ConversationTimelineRenderProps = {\n\t\t\t\titemCount: items.length,\n\t\t\t\tisLoading,\n\t\t\t\thasMore,\n\t\t\t\tisEmpty: items.length === 0,\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 lastItemKey = getLastItemKey(items);\n\n\t\t\t// Auto-scroll to bottom when new timeline items are added\n\t\t\tReact.useEffect(() => {\n\t\t\t\tconst element = internalRef.current;\n\n\t\t\t\tif (!(element && autoScroll)) {\n\t\t\t\t\tpreviousItemCount.current = items.length;\n\t\t\t\t\tpreviousLastItemKey.current = lastItemKey;\n\t\t\t\t\tisInitialRender.current = false;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst hasNewItems = items.length > previousItemCount.current;\n\t\t\t\tconst itemsRemoved = items.length < previousItemCount.current;\n\t\t\t\tconst appendedNewItem =\n\t\t\t\t\thasNewItems &&\n\t\t\t\t\tlastItemKey !== null &&\n\t\t\t\t\tlastItemKey !== previousLastItemKey.current;\n\t\t\t\tconst replacedLastItem =\n\t\t\t\t\t!hasNewItems &&\n\t\t\t\t\tlastItemKey !== null &&\n\t\t\t\t\tlastItemKey !== previousLastItemKey.current;\n\n\t\t\t\tconst shouldSnapToBottom =\n\t\t\t\t\tisInitialRender.current ||\n\t\t\t\t\t(itemsRemoved && isPinnedToBottom.current) ||\n\t\t\t\t\t(appendedNewItem && isPinnedToBottom.current) ||\n\t\t\t\t\t(replacedLastItem && isPinnedToBottom.current);\n\n\t\t\t\tif (shouldSnapToBottom) {\n\t\t\t\t\telement.scrollTop = element.scrollHeight;\n\t\t\t\t\tisPinnedToBottom.current = true;\n\t\t\t\t\tisAtTop.current = false;\n\t\t\t\t}\n\n\t\t\t\tpreviousItemCount.current = items.length;\n\t\t\t\tpreviousLastItemKey.current = lastItemKey;\n\t\t\t\tisInitialRender.current = false;\n\t\t\t}, [autoScroll, items.length, lastItemKey]);\n\n\t\t\t// Handle scroll events for infinite scrolling\n\t\t\tconst handleScroll = React.useCallback(\n\t\t\t\t(e: React.UIEvent<HTMLDivElement>) => {\n\t\t\t\t\tconst element = e.currentTarget;\n\t\t\t\t\tconst { scrollTop, scrollHeight, clientHeight } = element;\n\n\t\t\t\t\tconst distanceFromBottom = scrollHeight - scrollTop - clientHeight;\n\t\t\t\t\tconst pinnedNow = distanceFromBottom <= BOTTOM_THRESHOLD_PX;\n\t\t\t\t\tif (pinnedNow && !isPinnedToBottom.current) {\n\t\t\t\t\t\tonScrollEnd?.();\n\t\t\t\t\t}\n\t\t\t\t\tisPinnedToBottom.current = pinnedNow;\n\n\t\t\t\t\tconst atTop = scrollTop <= TOP_THRESHOLD_PX;\n\t\t\t\t\tif (atTop && !isAtTop.current) {\n\t\t\t\t\t\tonScrollStart?.();\n\t\t\t\t\t}\n\t\t\t\t\tisAtTop.current = atTop;\n\t\t\t\t},\n\t\t\t\t[onScrollStart, onScrollEnd]\n\t\t\t);\n\n\t\t\t// Static fade effect on top and bottom\n\t\t\tconst fadeStyle = React.useMemo(() => {\n\t\t\t\tconst maskHeight = \"90px\";\n\t\t\t\tconst scrollbarWidth = \"8px\";\n\n\t\t\t\tconst maskImage = `linear-gradient(to bottom, transparent, black ${maskHeight}, black calc(100% - ${maskHeight}), transparent), linear-gradient(black, black)`;\n\t\t\t\tconst maskSize = `calc(100% - ${scrollbarWidth}) 100%, ${scrollbarWidth} 100%`;\n\t\t\t\tconst maskPosition = \"0 0, 100% 0\";\n\t\t\t\tconst maskRepeat = \"no-repeat, no-repeat\";\n\n\t\t\t\treturn {\n\t\t\t\t\tmaskImage,\n\t\t\t\t\tmaskSize,\n\t\t\t\t\tmaskPosition,\n\t\t\t\t\tmaskRepeat,\n\t\t\t\t\tWebkitMaskImage: maskImage,\n\t\t\t\t\tWebkitMaskSize: maskSize,\n\t\t\t\t\tWebkitMaskPosition: maskPosition,\n\t\t\t\t\tWebkitMaskRepeat: maskRepeat,\n\t\t\t\t};\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: setRefs,\n\t\t\t\t\tstate: renderProps,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\trole: \"log\",\n\t\t\t\t\t\t\"aria-label\": \"Conversation timeline\",\n\t\t\t\t\t\t\"aria-live\": \"polite\",\n\t\t\t\t\t\t\"aria-relevant\": \"additions\",\n\t\t\t\t\t\tonScroll: handleScroll,\n\t\t\t\t\t\tstyle: fadeStyle,\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 = \"ConversationTimeline\";\n\treturn Component;\n})();\n\nexport type ConversationTimelineContainerProps = Omit<\n\tReact.HTMLAttributes<HTMLDivElement>,\n\t\"children\"\n> & {\n\tchildren?: React.ReactNode;\n\tasChild?: boolean;\n\tclassName?: string;\n};\n\n/**\n * Wrapper around the scrollable timeline giving consumers an easy hook to add\n * padding, backgrounds or transitions without touching the core timeline logic.\n */\nexport const ConversationTimelineContainer = (() => {\n\tconst Component = React.forwardRef<\n\t\tHTMLDivElement,\n\t\tConversationTimelineContainerProps\n\t>(({ children, className, asChild = false, ...props }, ref) =>\n\t\tuseRenderElement(\n\t\t\t\"div\",\n\t\t\t{\n\t\t\t\tclassName,\n\t\t\t\tasChild,\n\t\t\t},\n\t\t\t{\n\t\t\t\tref,\n\t\t\t\tprops: {\n\t\t\t\t\t...props,\n\t\t\t\t\tchildren,\n\t\t\t\t},\n\t\t\t}\n\t\t)\n\t);\n\n\tComponent.displayName = \"ConversationTimelineContainer\";\n\treturn Component;\n})();\n\nexport type ConversationTimelineLoadingProps = Omit<\n\tReact.HTMLAttributes<HTMLDivElement>,\n\t\"children\"\n> & {\n\tchildren?: React.ReactNode;\n\tasChild?: boolean;\n\tclassName?: string;\n};\n\n/**\n * Accessible status region for loading more timeline items. Lets host apps render\n * skeletons or shimmer states without reimplementing ARIA wiring.\n */\nexport const ConversationTimelineLoading = (() => {\n\tconst Component = React.forwardRef<\n\t\tHTMLDivElement,\n\t\tConversationTimelineLoadingProps\n\t>(({ children, className, asChild = false, ...props }, ref) =>\n\t\tuseRenderElement(\n\t\t\t\"div\",\n\t\t\t{\n\t\t\t\tclassName,\n\t\t\t\tasChild,\n\t\t\t},\n\t\t\t{\n\t\t\t\tref,\n\t\t\t\tprops: {\n\t\t\t\t\trole: \"status\",\n\t\t\t\t\t\"aria-label\": \"Loading timeline items\",\n\t\t\t\t\t...props,\n\t\t\t\t\tchildren,\n\t\t\t\t},\n\t\t\t}\n\t\t)\n\t);\n\n\tComponent.displayName = \"ConversationTimelineLoading\";\n\treturn Component;\n})();\n\nexport type ConversationTimelineEmptyProps = Omit<\n\tReact.HTMLAttributes<HTMLDivElement>,\n\t\"children\"\n> & {\n\tchildren?: React.ReactNode;\n\tasChild?: boolean;\n\tclassName?: string;\n};\n\n/**\n * Placeholder state rendered when no timeline items are present. Uses a polite status\n * region so screen readers announce the empty state.\n */\nexport const ConversationTimelineEmpty = (() => {\n\tconst Component = React.forwardRef<\n\t\tHTMLDivElement,\n\t\tConversationTimelineEmptyProps\n\t>(({ children, className, asChild = false, ...props }, ref) =>\n\t\tuseRenderElement(\n\t\t\t\"div\",\n\t\t\t{\n\t\t\t\tclassName,\n\t\t\t\tasChild,\n\t\t\t},\n\t\t\t{\n\t\t\t\tref,\n\t\t\t\tprops: {\n\t\t\t\t\trole: \"status\",\n\t\t\t\t\t\"aria-label\": \"No timeline items\",\n\t\t\t\t\t...props,\n\t\t\t\t\tchildren,\n\t\t\t\t},\n\t\t\t}\n\t\t)\n\t);\n\n\tComponent.displayName = \"ConversationTimelineEmpty\";\n\treturn Component;\n})();\n"],"mappings":";;;;AAgCA,MAAM,sBAAsB;AAC5B,MAAM,mBAAmB;AAEzB,SAAS,eAAe,OAAmD;AAC1E,KAAI,MAAM,WAAW,EACpB,QAAO;CAGR,MAAM,WAAW,MAAM,GAAG,GAAG;AAE7B,KAAI,UAAU,GACb,QAAO,SAAS;AAGjB,QAAO,UAAU,aAAa;;;;;;AAO/B,MAAa,8BAA8B;CAC1C,MAAM,YAAYA,QAAM,YAEtB,EACC,UACA,WACA,UAAU,OACV,QAAQ,EAAE,EACV,YAAY,OACZ,UAAU,OACV,aAAa,MACb,aACA,cACA,GAAG,SAEJ,QACI;EACJ,MAAM,cAAcA,QAAM,OAAuB,KAAK;EACtD,MAAM,UAAUA,QAAM,aACpB,SAAgC;AAChC,eAAY,UAAU;AACtB,OAAI,OAAO,QAAQ,WAClB,KAAI,KAAK;YACC,IACV,CAAC,IAAsD,UACtD;KAGH,CAAC,IAAI,CACL;EAED,MAAM,kBAAkBA,QAAM,OAAO,KAAK;EAC1C,MAAM,oBAAoBA,QAAM,OAAO,MAAM,OAAO;EACpD,MAAM,sBAAsBA,QAAM,OACjC,eAAe,MAAM,CACrB;EACD,MAAM,mBAAmBA,QAAM,OAAO,KAAK;EAC3C,MAAM,UAAUA,QAAM,OAAO,KAAK;EAElC,MAAMC,cAA+C;GACpD,WAAW,MAAM;GACjB;GACA;GACA,SAAS,MAAM,WAAW;GAC1B;EAED,MAAM,UACL,OAAO,aAAa,aAAa,SAAS,YAAY,GAAG;EAE1D,MAAM,cAAc,eAAe,MAAM;AAGzC,UAAM,gBAAgB;GACrB,MAAM,UAAU,YAAY;AAE5B,OAAI,EAAE,WAAW,aAAa;AAC7B,sBAAkB,UAAU,MAAM;AAClC,wBAAoB,UAAU;AAC9B,oBAAgB,UAAU;AAC1B;;GAGD,MAAM,cAAc,MAAM,SAAS,kBAAkB;GACrD,MAAM,eAAe,MAAM,SAAS,kBAAkB;GACtD,MAAM,kBACL,eACA,gBAAgB,QAChB,gBAAgB,oBAAoB;GACrC,MAAM,mBACL,CAAC,eACD,gBAAgB,QAChB,gBAAgB,oBAAoB;AAQrC,OALC,gBAAgB,WACf,gBAAgB,iBAAiB,WACjC,mBAAmB,iBAAiB,WACpC,oBAAoB,iBAAiB,SAEf;AACvB,YAAQ,YAAY,QAAQ;AAC5B,qBAAiB,UAAU;AAC3B,YAAQ,UAAU;;AAGnB,qBAAkB,UAAU,MAAM;AAClC,uBAAoB,UAAU;AAC9B,mBAAgB,UAAU;KACxB;GAAC;GAAY,MAAM;GAAQ;GAAY,CAAC;EAG3C,MAAM,eAAeD,QAAM,aACzB,MAAqC;GAErC,MAAM,EAAE,WAAW,cAAc,iBADjB,EAAE;GAIlB,MAAM,YADqB,eAAe,YAAY,gBACd;AACxC,OAAI,aAAa,CAAC,iBAAiB,QAClC,gBAAe;AAEhB,oBAAiB,UAAU;GAE3B,MAAM,QAAQ,aAAa;AAC3B,OAAI,SAAS,CAAC,QAAQ,QACrB,kBAAiB;AAElB,WAAQ,UAAU;KAEnB,CAAC,eAAe,YAAY,CAC5B;EAGD,MAAM,YAAYA,QAAM,cAAc;GACrC,MAAM,aAAa;GACnB,MAAM,iBAAiB;GAEvB,MAAM,YAAY,iDAAiD,WAAW,sBAAsB,WAAW;GAC/G,MAAM,WAAW,eAAe,eAAe,UAAU,eAAe;GACxE,MAAM,eAAe;GACrB,MAAM,aAAa;AAEnB,UAAO;IACN;IACA;IACA;IACA;IACA,iBAAiB;IACjB,gBAAgB;IAChB,oBAAoB;IACpB,kBAAkB;IAClB;KACC,EAAE,CAAC;AAEN,SAAO,iBACN,OACA;GACC;GACA;GACA,EACD;GACC,KAAK;GACL,OAAO;GACP,OAAO;IACN,MAAM;IACN,cAAc;IACd,aAAa;IACb,iBAAiB;IACjB,UAAU;IACV,OAAO;IACP,GAAG;IACH,UAAU;IACV;GACD,CACD;GAEF;AAED,WAAU,cAAc;AACxB,QAAO;IACJ;;;;;AAeJ,MAAa,uCAAuC;CACnD,MAAM,YAAYA,QAAM,YAGrB,EAAE,UAAU,WAAW,UAAU,MAAO,GAAG,SAAS,QACtD,iBACC,OACA;EACC;EACA;EACA,EACD;EACC;EACA,OAAO;GACN,GAAG;GACH;GACA;EACD,CACD,CACD;AAED,WAAU,cAAc;AACxB,QAAO;IACJ;;;;;AAeJ,MAAa,qCAAqC;CACjD,MAAM,YAAYA,QAAM,YAGrB,EAAE,UAAU,WAAW,UAAU,MAAO,GAAG,SAAS,QACtD,iBACC,OACA;EACC;EACA;EACA,EACD;EACC;EACA,OAAO;GACN,MAAM;GACN,cAAc;GACd,GAAG;GACH;GACA;EACD,CACD,CACD;AAED,WAAU,cAAc;AACxB,QAAO;IACJ;;;;;AAeJ,MAAa,mCAAmC;CAC/C,MAAM,YAAYA,QAAM,YAGrB,EAAE,UAAU,WAAW,UAAU,MAAO,GAAG,SAAS,QACtD,iBACC,OACA;EACC;EACA;EACA,EACD;EACC;EACA,OAAO;GACN,MAAM;GACN,cAAc;GACd,GAAG;GACH;GACA;EACD,CACD,CACD;AAED,WAAU,cAAc;AACxB,QAAO;IACJ"}
1
+ {"version":3,"file":"conversation-timeline.js","names":["React","renderProps: ConversationTimelineRenderProps"],"sources":["../../src/primitives/conversation-timeline.tsx"],"sourcesContent":["import type { TimelineItem as TimelineItemType } from \"@cossistant/types/api/timeline-item\";\nimport * as React from \"react\";\nimport { useScrollMask } from \"../hooks/use-scroll-mask\";\nimport { useRenderElement } from \"../utils/use-render-element\";\n\n/**\n * High-level state of the timeline handed to render-prop children so they can show\n * skeletons, empty states or pagination affordances.\n */\nexport type ConversationTimelineRenderProps = {\n\titemCount: number;\n\tisLoading?: boolean;\n\thasMore?: boolean;\n\tisEmpty: boolean;\n};\n\nexport type ConversationTimelineProps = Omit<\n\tReact.HTMLAttributes<HTMLDivElement>,\n\t\"children\"\n> & {\n\tchildren?:\n\t\t| React.ReactNode\n\t\t| ((props: ConversationTimelineRenderProps) => React.ReactNode);\n\tasChild?: boolean;\n\tclassName?: string;\n\titems?: TimelineItemType[];\n\tisLoading?: boolean;\n\thasMore?: boolean;\n\tautoScroll?: boolean;\n\tonScrollEnd?: () => void;\n\tonScrollStart?: () => void;\n};\n\nconst BOTTOM_THRESHOLD_PX = 12;\nconst TOP_THRESHOLD_PX = 2;\n\nfunction getLastItemKey(items: TimelineItemType[]): string | number | null {\n\tif (items.length === 0) {\n\t\treturn null;\n\t}\n\n\tconst lastItem = items.at(-1);\n\n\tif (lastItem?.id) {\n\t\treturn lastItem.id;\n\t}\n\n\treturn lastItem?.createdAt ?? null;\n}\n\n/**\n * Scrollable conversation timeline that wires auto-scroll behaviour, live-region semantics and\n * pagination callbacks for displaying timeline items (messages, events, etc.).\n */\nexport const ConversationTimeline = (() => {\n\tconst Component = React.forwardRef<HTMLDivElement, ConversationTimelineProps>(\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\titems = [],\n\t\t\t\tisLoading = false,\n\t\t\t\thasMore = false,\n\t\t\t\tautoScroll = true,\n\t\t\t\tonScrollEnd,\n\t\t\t\tonScrollStart,\n\t\t\t\t...props\n\t\t\t},\n\t\t\tref\n\t\t) => {\n\t\t\tconst internalRef = React.useRef<HTMLDivElement>(null);\n\t\t\tconst { ref: scrollMaskRef, style: scrollMaskStyle } = useScrollMask({\n\t\t\t\tmaskHeight: \"54px\",\n\t\t\t\tscrollbarWidth: \"8px\",\n\t\t\t\ttopThreshold: TOP_THRESHOLD_PX,\n\t\t\t\tbottomThreshold: BOTTOM_THRESHOLD_PX,\n\t\t\t});\n\n\t\t\tconst setRefs = React.useCallback(\n\t\t\t\t(node: HTMLDivElement | null) => {\n\t\t\t\t\tinternalRef.current = node;\n\t\t\t\t\t(\n\t\t\t\t\t\tscrollMaskRef as React.MutableRefObject<HTMLDivElement | null>\n\t\t\t\t\t).current = node;\n\t\t\t\t\tif (typeof ref === \"function\") {\n\t\t\t\t\t\tref(node);\n\t\t\t\t\t} else if (ref) {\n\t\t\t\t\t\t(ref as React.MutableRefObject<HTMLDivElement | null>).current =\n\t\t\t\t\t\t\tnode;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t[ref, scrollMaskRef]\n\t\t\t);\n\n\t\t\tconst isInitialRender = React.useRef(true);\n\t\t\tconst previousItemCount = React.useRef(items.length);\n\t\t\tconst previousLastItemKey = React.useRef<string | number | null>(\n\t\t\t\tgetLastItemKey(items)\n\t\t\t);\n\t\t\tconst isPinnedToBottom = React.useRef(true);\n\t\t\tconst isAtTop = React.useRef(true);\n\n\t\t\tconst renderProps: ConversationTimelineRenderProps = {\n\t\t\t\titemCount: items.length,\n\t\t\t\tisLoading,\n\t\t\t\thasMore,\n\t\t\t\tisEmpty: items.length === 0,\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 lastItemKey = getLastItemKey(items);\n\n\t\t\t// Auto-scroll to bottom when new timeline items are added\n\t\t\tReact.useEffect(() => {\n\t\t\t\tconst element = internalRef.current;\n\n\t\t\t\tif (!(element && autoScroll)) {\n\t\t\t\t\tpreviousItemCount.current = items.length;\n\t\t\t\t\tpreviousLastItemKey.current = lastItemKey;\n\t\t\t\t\tisInitialRender.current = false;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst hasNewItems = items.length > previousItemCount.current;\n\t\t\t\tconst itemsRemoved = items.length < previousItemCount.current;\n\t\t\t\tconst appendedNewItem =\n\t\t\t\t\thasNewItems &&\n\t\t\t\t\tlastItemKey !== null &&\n\t\t\t\t\tlastItemKey !== previousLastItemKey.current;\n\t\t\t\tconst replacedLastItem =\n\t\t\t\t\t!hasNewItems &&\n\t\t\t\t\tlastItemKey !== null &&\n\t\t\t\t\tlastItemKey !== previousLastItemKey.current;\n\n\t\t\t\tconst shouldSnapToBottom =\n\t\t\t\t\tisInitialRender.current ||\n\t\t\t\t\t(itemsRemoved && isPinnedToBottom.current) ||\n\t\t\t\t\t(appendedNewItem && isPinnedToBottom.current) ||\n\t\t\t\t\t(replacedLastItem && isPinnedToBottom.current);\n\n\t\t\t\tif (shouldSnapToBottom) {\n\t\t\t\t\telement.scrollTop = element.scrollHeight;\n\t\t\t\t\tisPinnedToBottom.current = true;\n\t\t\t\t\tisAtTop.current = false;\n\t\t\t\t}\n\n\t\t\t\tpreviousItemCount.current = items.length;\n\t\t\t\tpreviousLastItemKey.current = lastItemKey;\n\t\t\t\tisInitialRender.current = false;\n\t\t\t}, [autoScroll, items.length, lastItemKey]);\n\n\t\t\t// Handle scroll events for infinite scrolling\n\t\t\tconst handleScroll = React.useCallback(\n\t\t\t\t(e: React.UIEvent<HTMLDivElement>) => {\n\t\t\t\t\tconst element = e.currentTarget;\n\t\t\t\t\tconst { scrollTop, scrollHeight, clientHeight } = element;\n\n\t\t\t\t\tconst distanceFromBottom = scrollHeight - scrollTop - clientHeight;\n\t\t\t\t\tconst pinnedNow = distanceFromBottom <= BOTTOM_THRESHOLD_PX;\n\t\t\t\t\tif (pinnedNow && !isPinnedToBottom.current) {\n\t\t\t\t\t\tonScrollEnd?.();\n\t\t\t\t\t}\n\t\t\t\t\tisPinnedToBottom.current = pinnedNow;\n\n\t\t\t\t\tconst atTop = scrollTop <= TOP_THRESHOLD_PX;\n\t\t\t\t\tif (atTop && !isAtTop.current) {\n\t\t\t\t\t\tonScrollStart?.();\n\t\t\t\t\t}\n\t\t\t\t\tisAtTop.current = atTop;\n\t\t\t\t},\n\t\t\t\t[onScrollStart, onScrollEnd]\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: setRefs,\n\t\t\t\t\tstate: renderProps,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\trole: \"log\",\n\t\t\t\t\t\t\"aria-label\": \"Conversation timeline\",\n\t\t\t\t\t\t\"aria-live\": \"polite\",\n\t\t\t\t\t\t\"aria-relevant\": \"additions\",\n\t\t\t\t\t\tonScroll: handleScroll,\n\t\t\t\t\t\tstyle: scrollMaskStyle,\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 = \"ConversationTimeline\";\n\treturn Component;\n})();\n\nexport type ConversationTimelineContainerProps = Omit<\n\tReact.HTMLAttributes<HTMLDivElement>,\n\t\"children\"\n> & {\n\tchildren?: React.ReactNode;\n\tasChild?: boolean;\n\tclassName?: string;\n};\n\n/**\n * Wrapper around the scrollable timeline giving consumers an easy hook to add\n * padding, backgrounds or transitions without touching the core timeline logic.\n */\nexport const ConversationTimelineContainer = (() => {\n\tconst Component = React.forwardRef<\n\t\tHTMLDivElement,\n\t\tConversationTimelineContainerProps\n\t>(({ children, className, asChild = false, ...props }, ref) =>\n\t\tuseRenderElement(\n\t\t\t\"div\",\n\t\t\t{\n\t\t\t\tclassName,\n\t\t\t\tasChild,\n\t\t\t},\n\t\t\t{\n\t\t\t\tref,\n\t\t\t\tprops: {\n\t\t\t\t\t...props,\n\t\t\t\t\tchildren,\n\t\t\t\t},\n\t\t\t}\n\t\t)\n\t);\n\n\tComponent.displayName = \"ConversationTimelineContainer\";\n\treturn Component;\n})();\n\nexport type ConversationTimelineLoadingProps = Omit<\n\tReact.HTMLAttributes<HTMLDivElement>,\n\t\"children\"\n> & {\n\tchildren?: React.ReactNode;\n\tasChild?: boolean;\n\tclassName?: string;\n};\n\n/**\n * Accessible status region for loading more timeline items. Lets host apps render\n * skeletons or shimmer states without reimplementing ARIA wiring.\n */\nexport const ConversationTimelineLoading = (() => {\n\tconst Component = React.forwardRef<\n\t\tHTMLDivElement,\n\t\tConversationTimelineLoadingProps\n\t>(({ children, className, asChild = false, ...props }, ref) =>\n\t\tuseRenderElement(\n\t\t\t\"div\",\n\t\t\t{\n\t\t\t\tclassName,\n\t\t\t\tasChild,\n\t\t\t},\n\t\t\t{\n\t\t\t\tref,\n\t\t\t\tprops: {\n\t\t\t\t\trole: \"status\",\n\t\t\t\t\t\"aria-label\": \"Loading timeline items\",\n\t\t\t\t\t...props,\n\t\t\t\t\tchildren,\n\t\t\t\t},\n\t\t\t}\n\t\t)\n\t);\n\n\tComponent.displayName = \"ConversationTimelineLoading\";\n\treturn Component;\n})();\n\nexport type ConversationTimelineEmptyProps = Omit<\n\tReact.HTMLAttributes<HTMLDivElement>,\n\t\"children\"\n> & {\n\tchildren?: React.ReactNode;\n\tasChild?: boolean;\n\tclassName?: string;\n};\n\n/**\n * Placeholder state rendered when no timeline items are present. Uses a polite status\n * region so screen readers announce the empty state.\n */\nexport const ConversationTimelineEmpty = (() => {\n\tconst Component = React.forwardRef<\n\t\tHTMLDivElement,\n\t\tConversationTimelineEmptyProps\n\t>(({ children, className, asChild = false, ...props }, ref) =>\n\t\tuseRenderElement(\n\t\t\t\"div\",\n\t\t\t{\n\t\t\t\tclassName,\n\t\t\t\tasChild,\n\t\t\t},\n\t\t\t{\n\t\t\t\tref,\n\t\t\t\tprops: {\n\t\t\t\t\trole: \"status\",\n\t\t\t\t\t\"aria-label\": \"No timeline items\",\n\t\t\t\t\t...props,\n\t\t\t\t\tchildren,\n\t\t\t\t},\n\t\t\t}\n\t\t)\n\t);\n\n\tComponent.displayName = \"ConversationTimelineEmpty\";\n\treturn Component;\n})();\n"],"mappings":"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"}
@@ -7,6 +7,9 @@ import { SupportBubble } from "./bubble.js";
7
7
  import { Button } from "./button.js";
8
8
  import { ConversationTimeline, ConversationTimelineContainer, ConversationTimelineEmpty, ConversationTimelineLoading } from "./conversation-timeline.js";
9
9
  import { FileInput, MultimodalInput, SupportInput } from "./multimodal-input.js";
10
+ import { Page, PageProps } from "./page.js";
11
+ import { PageRegistryProvider, usePageRegistry, useRegisterPage } from "./page-registry.js";
12
+ import { Router, RouterProps } from "./router.js";
10
13
  import { TimelineItem, TimelineItemContent, TimelineItemTimestamp } from "./timeline-item.js";
11
14
  import { TimelineItemGroup, TimelineItemGroupAvatar, TimelineItemGroupContent, TimelineItemGroupHeader, TimelineItemGroupReadIndicator, TimelineItemGroupSeenIndicator } from "./timeline-item-group.js";
12
15
  import { SupportWindow } from "./window.js";
@@ -14,8 +17,8 @@ import "./index.parts.js";
14
17
 
15
18
  //#region src/primitives/index.d.ts
16
19
  declare namespace index_d_exports {
17
- export { Avatar, AvatarFallback, AvatarImage, SupportBubble as Bubble, Button, SupportConfig as Config, ConversationTimeline, ConversationTimelineContainer, ConversationTimelineEmpty, ConversationTimelineLoading, FileInput, SupportInput as Input, MultimodalInput, TimelineItem, TimelineItemContent, TimelineItemGroup, TimelineItemGroupAvatar, TimelineItemGroupContent, TimelineItemGroupHeader, TimelineItemGroupReadIndicator, TimelineItemGroupSeenIndicator, TimelineItemTimestamp, TypingIndicator, TypingIndicatorProps, TypingParticipant, TypingParticipantType, SupportWindow as Window };
20
+ export { Avatar, AvatarFallback, AvatarImage, SupportBubble as Bubble, Button, SupportConfig as Config, ConversationTimeline, ConversationTimelineContainer, ConversationTimelineEmpty, ConversationTimelineLoading, FileInput, SupportInput as Input, MultimodalInput, Page, PageProps, PageRegistryProvider, Router, RouterProps, TimelineItem, TimelineItemContent, TimelineItemGroup, TimelineItemGroupAvatar, TimelineItemGroupContent, TimelineItemGroupHeader, TimelineItemGroupReadIndicator, TimelineItemGroupSeenIndicator, TimelineItemTimestamp, TypingIndicator, TypingIndicatorProps, TypingParticipant, TypingParticipantType, SupportWindow as Window, usePageRegistry, useRegisterPage };
18
21
  }
19
22
  //#endregion
20
- export { Avatar, AvatarFallback, AvatarImage, SupportBubble as Bubble, Button, SupportConfig as Config, ConversationTimeline, ConversationTimelineContainer, ConversationTimelineEmpty, ConversationTimelineLoading, FileInput, SupportInput as Input, MultimodalInput, TimelineItem, TimelineItemContent, TimelineItemGroup, TimelineItemGroupAvatar, TimelineItemGroupContent, TimelineItemGroupHeader, TimelineItemGroupReadIndicator, TimelineItemGroupSeenIndicator, TimelineItemTimestamp, TypingIndicator, TypingIndicatorProps, TypingParticipant, TypingParticipantType, SupportWindow as Window, index_d_exports };
23
+ export { Avatar, AvatarFallback, AvatarImage, SupportBubble as Bubble, Button, SupportConfig as Config, ConversationTimeline, ConversationTimelineContainer, ConversationTimelineEmpty, ConversationTimelineLoading, FileInput, SupportInput as Input, MultimodalInput, Page, PageProps, PageRegistryProvider, Router, RouterProps, TimelineItem, TimelineItemContent, TimelineItemGroup, TimelineItemGroupAvatar, TimelineItemGroupContent, TimelineItemGroupHeader, TimelineItemGroupReadIndicator, TimelineItemGroupSeenIndicator, TimelineItemTimestamp, TypingIndicator, TypingIndicatorProps, TypingParticipant, TypingParticipantType, SupportWindow as Window, index_d_exports, usePageRegistry, useRegisterPage };
21
24
  //# sourceMappingURL=index.d.ts.map
@@ -1,13 +1,16 @@
1
1
  import { __export } from "../_virtual/rolldown_runtime.js";
2
- import { SupportConfig } from "../support-config.js";
3
2
  import { Avatar } from "./avatar/avatar.js";
4
3
  import { AvatarFallback } from "./avatar/fallback.js";
5
4
  import { AvatarImage } from "./avatar/image.js";
6
5
  import { TypingIndicator } from "../support/components/typing-indicator.js";
6
+ import { SupportConfig } from "../support-config.js";
7
7
  import { SupportBubble } from "./bubble.js";
8
8
  import { Button } from "./button.js";
9
9
  import { ConversationTimeline, ConversationTimelineContainer, ConversationTimelineEmpty, ConversationTimelineLoading } from "./conversation-timeline.js";
10
10
  import { FileInput, MultimodalInput, SupportInput } from "./multimodal-input.js";
11
+ import { PageRegistryProvider, usePageRegistry, useRegisterPage } from "./page-registry.js";
12
+ import { Page } from "./page.js";
13
+ import { Router } from "./router.js";
11
14
  import { TimelineItem, TimelineItemContent, TimelineItemTimestamp } from "./timeline-item.js";
12
15
  import { TimelineItemGroup, TimelineItemGroupAvatar, TimelineItemGroupContent, TimelineItemGroupHeader, TimelineItemGroupReadIndicator, TimelineItemGroupSeenIndicator } from "./timeline-item-group.js";
13
16
  import { SupportWindow } from "./window.js";
@@ -27,6 +30,9 @@ var primitives_exports = /* @__PURE__ */ __export({
27
30
  FileInput: () => FileInput,
28
31
  Input: () => SupportInput,
29
32
  MultimodalInput: () => MultimodalInput,
33
+ Page: () => Page,
34
+ PageRegistryProvider: () => PageRegistryProvider,
35
+ Router: () => Router,
30
36
  TimelineItem: () => TimelineItem,
31
37
  TimelineItemContent: () => TimelineItemContent,
32
38
  TimelineItemGroup: () => TimelineItemGroup,
@@ -37,9 +43,11 @@ var primitives_exports = /* @__PURE__ */ __export({
37
43
  TimelineItemGroupSeenIndicator: () => TimelineItemGroupSeenIndicator,
38
44
  TimelineItemTimestamp: () => TimelineItemTimestamp,
39
45
  TypingIndicator: () => TypingIndicator,
40
- Window: () => SupportWindow
46
+ Window: () => SupportWindow,
47
+ usePageRegistry: () => usePageRegistry,
48
+ useRegisterPage: () => useRegisterPage
41
49
  });
42
50
 
43
51
  //#endregion
44
- export { Avatar, AvatarFallback, AvatarImage, SupportBubble as Bubble, Button, SupportConfig as Config, ConversationTimeline, ConversationTimelineContainer, ConversationTimelineEmpty, ConversationTimelineLoading, FileInput, SupportInput as Input, MultimodalInput, TimelineItem, TimelineItemContent, TimelineItemGroup, TimelineItemGroupAvatar, TimelineItemGroupContent, TimelineItemGroupHeader, TimelineItemGroupReadIndicator, TimelineItemGroupSeenIndicator, TimelineItemTimestamp, TypingIndicator, SupportWindow as Window, primitives_exports };
52
+ export { Avatar, AvatarFallback, AvatarImage, SupportBubble as Bubble, Button, SupportConfig as Config, ConversationTimeline, ConversationTimelineContainer, ConversationTimelineEmpty, ConversationTimelineLoading, FileInput, SupportInput as Input, MultimodalInput, Page, PageRegistryProvider, Router, TimelineItem, TimelineItemContent, TimelineItemGroup, TimelineItemGroupAvatar, TimelineItemGroupContent, TimelineItemGroupHeader, TimelineItemGroupReadIndicator, TimelineItemGroupSeenIndicator, TimelineItemTimestamp, TypingIndicator, SupportWindow as Window, primitives_exports, usePageRegistry, useRegisterPage };
45
53
  //# sourceMappingURL=index.js.map
@@ -8,7 +8,10 @@ import { SupportBubble } from "./bubble.js";
8
8
  import { Button } from "./button.js";
9
9
  import { ConversationTimeline, ConversationTimelineContainer, ConversationTimelineEmpty, ConversationTimelineLoading } from "./conversation-timeline.js";
10
10
  import { FileInput, MultimodalInput, SupportInput } from "./multimodal-input.js";
11
+ import { Page, PageProps } from "./page.js";
12
+ import { PageRegistryProvider, usePageRegistry, useRegisterPage } from "./page-registry.js";
13
+ import { Router, RouterProps } from "./router.js";
11
14
  import { TimelineItem, TimelineItemContent, TimelineItemTimestamp } from "./timeline-item.js";
12
15
  import { TimelineItemGroup, TimelineItemGroupAvatar, TimelineItemGroupContent, TimelineItemGroupHeader, TimelineItemGroupReadIndicator, TimelineItemGroupSeenIndicator } from "./timeline-item-group.js";
13
16
  import { SupportWindow } from "./window.js";
14
- export { Avatar, AvatarFallback, AvatarImage, SupportBubble as Bubble, Button, SupportConfig as Config, ConversationTimeline, ConversationTimelineContainer, ConversationTimelineEmpty, ConversationTimelineLoading, FileInput, SupportInput as Input, MultimodalInput, TimelineItem, TimelineItemContent, TimelineItemGroup, TimelineItemGroupAvatar, TimelineItemGroupContent, TimelineItemGroupHeader, TimelineItemGroupReadIndicator, TimelineItemGroupSeenIndicator, TimelineItemTimestamp, TypingIndicator, type TypingIndicatorProps, type TypingParticipant, type TypingParticipantType, SupportWindow as Window };
17
+ export { Avatar, AvatarFallback, AvatarImage, SupportBubble as Bubble, Button, SupportConfig as Config, ConversationTimeline, ConversationTimelineContainer, ConversationTimelineEmpty, ConversationTimelineLoading, FileInput, SupportInput as Input, MultimodalInput, Page, type PageProps, PageRegistryProvider, Router, type RouterProps, TimelineItem, TimelineItemContent, TimelineItemGroup, TimelineItemGroupAvatar, TimelineItemGroupContent, TimelineItemGroupHeader, TimelineItemGroupReadIndicator, TimelineItemGroupSeenIndicator, TimelineItemTimestamp, TypingIndicator, type TypingIndicatorProps, type TypingParticipant, type TypingParticipantType, SupportWindow as Window, usePageRegistry, useRegisterPage };
@@ -1,14 +1,17 @@
1
- import { SupportConfig } from "../support-config.js";
2
1
  import { Avatar } from "./avatar/avatar.js";
3
2
  import { AvatarFallback } from "./avatar/fallback.js";
4
3
  import { AvatarImage } from "./avatar/image.js";
5
4
  import { TypingIndicator } from "../support/components/typing-indicator.js";
5
+ import { SupportConfig } from "../support-config.js";
6
6
  import { SupportBubble } from "./bubble.js";
7
7
  import { Button } from "./button.js";
8
8
  import { ConversationTimeline, ConversationTimelineContainer, ConversationTimelineEmpty, ConversationTimelineLoading } from "./conversation-timeline.js";
9
9
  import { FileInput, MultimodalInput, SupportInput } from "./multimodal-input.js";
10
+ import { PageRegistryProvider, usePageRegistry, useRegisterPage } from "./page-registry.js";
11
+ import { Page } from "./page.js";
12
+ import { Router } from "./router.js";
10
13
  import { TimelineItem, TimelineItemContent, TimelineItemTimestamp } from "./timeline-item.js";
11
14
  import { TimelineItemGroup, TimelineItemGroupAvatar, TimelineItemGroupContent, TimelineItemGroupHeader, TimelineItemGroupReadIndicator, TimelineItemGroupSeenIndicator } from "./timeline-item-group.js";
12
15
  import { SupportWindow } from "./window.js";
13
16
 
14
- export { Avatar, AvatarFallback, AvatarImage, SupportBubble as Bubble, Button, SupportConfig as Config, ConversationTimeline, ConversationTimelineContainer, ConversationTimelineEmpty, ConversationTimelineLoading, FileInput, SupportInput as Input, MultimodalInput, TimelineItem, TimelineItemContent, TimelineItemGroup, TimelineItemGroupAvatar, TimelineItemGroupContent, TimelineItemGroupHeader, TimelineItemGroupReadIndicator, TimelineItemGroupSeenIndicator, TimelineItemTimestamp, TypingIndicator, SupportWindow as Window };
17
+ export { Avatar, AvatarFallback, AvatarImage, SupportBubble as Bubble, Button, SupportConfig as Config, ConversationTimeline, ConversationTimelineContainer, ConversationTimelineEmpty, ConversationTimelineLoading, FileInput, SupportInput as Input, MultimodalInput, Page, PageRegistryProvider, Router, TimelineItem, TimelineItemContent, TimelineItemGroup, TimelineItemGroupAvatar, TimelineItemGroupContent, TimelineItemGroupHeader, TimelineItemGroupReadIndicator, TimelineItemGroupSeenIndicator, TimelineItemTimestamp, TypingIndicator, SupportWindow as Window, usePageRegistry, useRegisterPage };
@@ -16,7 +16,7 @@ type MultimodalInputProps = Omit<React$1.TextareaHTMLAttributes<HTMLTextAreaElem
16
16
  * clipboard uploads and auto-resizing while remaining composable via
17
17
  * `asChild`.
18
18
  */
19
- declare const MultimodalInput: React$1.ForwardRefExoticComponent<Omit<React$1.TextareaHTMLAttributes<HTMLTextAreaElement>, "onChange" | "value"> & {
19
+ declare const MultimodalInput: React$1.ForwardRefExoticComponent<Omit<React$1.TextareaHTMLAttributes<HTMLTextAreaElement>, "value" | "onChange"> & {
20
20
  value: string;
21
21
  onChange: (value: string) => void;
22
22
  onSubmit?: () => void;
@@ -38,7 +38,7 @@ declare const FileInput: React$1.ForwardRefExoticComponent<React$1.InputHTMLAttr
38
38
  onFileSelect?: (files: File[]) => void;
39
39
  asChild?: boolean;
40
40
  } & React$1.RefAttributes<HTMLInputElement>>;
41
- declare const SupportInput: React$1.ForwardRefExoticComponent<Omit<React$1.TextareaHTMLAttributes<HTMLTextAreaElement>, "onChange" | "value"> & {
41
+ declare const SupportInput: React$1.ForwardRefExoticComponent<Omit<React$1.TextareaHTMLAttributes<HTMLTextAreaElement>, "value" | "onChange"> & {
42
42
  value: string;
43
43
  onChange: (value: string) => void;
44
44
  onSubmit?: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"multimodal-input.d.ts","names":[],"sources":["../../src/primitives/multimodal-input.tsx"],"sourcesContent":[],"mappings":";;;KAGY,oBAAA,GAAuB,KAClC,OAAA,CAAM,uBAAuB;;EADlB,QAAA,EAAA,CAAA,KAAA,EAAA,MAAoB,EAAA,GAAA,IAAA;EACF,QAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAA7B,YAAM,CAAA,EAAA,CAAA,KAAA,EAMiB,IANjB,EAAA,EAAA,GAAA,IAAA;EAD4B,OAAA,CAAA,EAAA,OAAA;EAOX,SAAA,CAAA,EAAA,MAAA;EAGf,KAAA,CAAA,EAAA,KAAA,GAAA,IAAA;EAAK,QAAA,CAAA,EAAA,OAAA;AASd,CAAA;;;;;;cAAa,iBAAe,OAAA,CAAA,0BAAA,KAAA,OAAA,CAAA,uBAAA;;EAAA,QAAA,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAAA,QAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EA4GhB,YAAA,CAAA,EAAA,CAAA,KAAc,EAxHF,IAwHE,EAAA,EAAA,GAAA,IAAA;EAA6B,OAAA,CAAA,EAAA,OAAA;EAA1B,SAAM,CAAA,EAAA,MAAA;EACX,KAAA,CAAA,EAtHf,KAsHe,GAAA,IAAA;EAAI,QAAA,CAAA,EAAA,OAAA;AAQ5B,CAAA,wBAkCI,oBAAA,CAAA,CAAA;AAlCkB,KATV,cAAA,GAAiB,OAAA,CAAM,mBASb,CATiC,gBASjC,CAAA,GAAA;EAAA,YAAA,CAAA,EAAA,CAAA,KAAA,EARE,IAQF,EAAA,EAAA,GAAA,IAAA;EARE,OAAA,CAAA,EAAA,OAAA;;;;;AA6CxB;AAAyB,cArCZ,SAqCY,EArCH,OAAA,CAAA,yBAqCG,CArCH,OAAA,CAAA,mBAqCG,CArCH,gBAqCG,CAAA,GAAA;EAAA,YAAA,CAAA,EAAA,CAAA,KAAA,EA7CD,IA6CC,EAAA,EAAA,GAAA,IAAA;EAAA,OAAA,CAAA,EAAA,OAAA;CAtKD,wBAAA,iBAAA,CAAA,CAAA;AAGf,cAmKI,YAnKJ,EAmKgB,OAAA,CAAA,yBAnKhB,CAmKgB,IAnKhB,CAmKgB,OAAA,CAAA,sBAnKhB,CAmKgB,mBAnKhB,CAAA,EAAA,UAAA,GAAA,OAAA,CAAA,GAAA;;;EAmKgB,QAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAAA,YAAA,CAAA,EAAA,CAAA,KAAA,EAtKD,IAsKC,EAAA,EAAA,GAAA,IAAA;;;UAnKhB"}
1
+ {"version":3,"file":"multimodal-input.d.ts","names":[],"sources":["../../src/primitives/multimodal-input.tsx"],"sourcesContent":[],"mappings":";;;KAGY,oBAAA,GAAuB,KAClC,OAAA,CAAM,uBAAuB;;EADlB,QAAA,EAAA,CAAA,KAAA,EAAA,MAAoB,EAAA,GAAA,IAAA;EACF,QAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAA7B,YAAM,CAAA,EAAA,CAAA,KAAA,EAMiB,IANjB,EAAA,EAAA,GAAA,IAAA;EAD4B,OAAA,CAAA,EAAA,OAAA;EAOX,SAAA,CAAA,EAAA,MAAA;EAGf,KAAA,CAAA,EAAA,KAAA,GAAA,IAAA;EAAK,QAAA,CAAA,EAAA,OAAA;AASd,CAAA;;;;;;cAAa,iBAAe,OAAA,CAAA,0BAAA,KAAA,OAAA,CAAA,uBAAA;;EAAA,QAAA,EAAA,CAAA,KAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAAA,QAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EA4GhB,YAAA,CAAA,EAAA,CAAA,KAAc,EAxHF,IAwHE,EAAA,EAAA,GAAA,IAAA;EAA6B,OAAA,CAAA,EAAA,OAAA;EAA1B,SAAM,CAAA,EAAA,MAAA;EACX,KAAA,CAAA,EAtHf,KAsHe,GAAA,IAAA;EAAI,QAAA,CAAA,EAAA,OAAA;AAQ5B,CAAA,wBAkCI,oBAAA,CAAA,CAAA;AAlCkB,KATV,cAAA,GAAiB,OAAA,CAAM,mBASb,CATiC,gBASjC,CAAA,GAAA;EAAA,YAAA,CAAA,EAAA,CAAA,KAAA,EARE,IAQF,EAAA,EAAA,GAAA,IAAA;EARE,OAAA,CAAA,EAAA,OAAA;;;;;AA6CxB;AAAyB,cArCZ,SAqCY,EArCH,OAAA,CAAA,yBAqCG,CArCH,OAAA,CAAA,mBAqCG,CArCH,gBAqCG,CAAA,GAAA;EAAA,YAAA,CAAA,EAAA,CAAA,KAAA,EA7CD,IA6CC,EAAA,EAAA,GAAA,IAAA;EAAA,OAAA,CAAA,EAAA,OAAA;CAtKD,wBAAA,iBAAA,CAAA,CAAA;AAGf,cAmKI,YAnKJ,EAmKgB,OAAA,CAAA,yBAnKhB,CAmKgB,IAnKhB,CAmKgB,OAAA,CAAA,sBAnKhB,CAmKgB,mBAnKhB,CAAA,EAAA,OAAA,GAAA,UAAA,CAAA,GAAA;;;EAmKgB,QAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAAA,YAAA,CAAA,EAAA,CAAA,KAAA,EAtKD,IAsKC,EAAA,EAAA,GAAA,IAAA;;;UAnKhB"}
@@ -0,0 +1,30 @@
1
+ import React from "react";
2
+
3
+ //#region src/primitives/page-registry.d.ts
4
+ type PageComponent<P = unknown> = React.ComponentType<{
5
+ params?: P;
6
+ }>;
7
+ type PageRegistry = Map<string, PageComponent>;
8
+ /**
9
+ * Context provider for declarative page registration.
10
+ *
11
+ * @example
12
+ * <PageRegistryProvider>
13
+ * <Page name="HOME" component={HomePage} />
14
+ * <Router page={currentPage} />
15
+ * </PageRegistryProvider>
16
+ */
17
+ declare const PageRegistryProvider: React.FC<{
18
+ children: React.ReactNode;
19
+ }>;
20
+ /**
21
+ * Access the page registry (used internally by Router and Page).
22
+ */
23
+ declare const usePageRegistry: () => PageRegistry;
24
+ /**
25
+ * Register a page in the registry (used internally by Page component).
26
+ */
27
+ declare const useRegisterPage: (name: string, component: PageComponent) => void;
28
+ //#endregion
29
+ export { PageRegistryProvider, usePageRegistry, useRegisterPage };
30
+ //# sourceMappingURL=page-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-registry.d.ts","names":[],"sources":["../../src/primitives/page-registry.tsx"],"sourcesContent":[],"mappings":";;;KAEK,6BAA6B,KAAA,CAAM;WAAyB;AAFC,CAAA,CAAA;AAEb,KAEhD,YAAA,GAAe,GAAH,CAAA,MAAA,EAAe,aAAA,CAAA;AAahC;AAeA;AAKA;;;;;;;cApBa,sBAAsB,KAAA,CAAM;YAAe,KAAA,CAAM;;;;;cAejD,uBAAe;;;;cAKf,2CAA4C"}
@@ -0,0 +1,45 @@
1
+ import React, { createContext, useContext, useMemo } from "react";
2
+ import { jsx } from "react/jsx-runtime";
3
+
4
+ //#region src/primitives/page-registry.tsx
5
+ const PageRegistryContext = createContext(/* @__PURE__ */ new Map());
6
+ /**
7
+ * Context provider for declarative page registration.
8
+ *
9
+ * @example
10
+ * <PageRegistryProvider>
11
+ * <Page name="HOME" component={HomePage} />
12
+ * <Router page={currentPage} />
13
+ * </PageRegistryProvider>
14
+ */
15
+ const PageRegistryProvider = ({ children }) => {
16
+ const registry = useMemo(() => /* @__PURE__ */ new Map(), []);
17
+ return /* @__PURE__ */ jsx(PageRegistryContext.Provider, {
18
+ value: registry,
19
+ children
20
+ });
21
+ };
22
+ /**
23
+ * Access the page registry (used internally by Router and Page).
24
+ */
25
+ const usePageRegistry = () => useContext(PageRegistryContext);
26
+ /**
27
+ * Register a page in the registry (used internally by Page component).
28
+ */
29
+ const useRegisterPage = (name, component) => {
30
+ const registry = usePageRegistry();
31
+ React.useEffect(() => {
32
+ registry.set(name, component);
33
+ return () => {
34
+ registry.delete(name);
35
+ };
36
+ }, [
37
+ name,
38
+ component,
39
+ registry
40
+ ]);
41
+ };
42
+
43
+ //#endregion
44
+ export { PageRegistryProvider, usePageRegistry, useRegisterPage };
45
+ //# sourceMappingURL=page-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-registry.js","names":["PageRegistryProvider: React.FC<{ children: React.ReactNode }>"],"sources":["../../src/primitives/page-registry.tsx"],"sourcesContent":["import React, { createContext, useContext, useMemo } from \"react\";\n\ntype PageComponent<P = unknown> = React.ComponentType<{ params?: P }>;\n\ntype PageRegistry = Map<string, PageComponent>;\n\nconst PageRegistryContext = createContext<PageRegistry>(new Map());\n\n/**\n * Context provider for declarative page registration.\n *\n * @example\n * <PageRegistryProvider>\n * <Page name=\"HOME\" component={HomePage} />\n * <Router page={currentPage} />\n * </PageRegistryProvider>\n */\nexport const PageRegistryProvider: React.FC<{ children: React.ReactNode }> = ({\n\tchildren,\n}) => {\n\tconst registry = useMemo(() => new Map<string, PageComponent>(), []);\n\n\treturn (\n\t\t<PageRegistryContext.Provider value={registry}>\n\t\t\t{children}\n\t\t</PageRegistryContext.Provider>\n\t);\n};\n\n/**\n * Access the page registry (used internally by Router and Page).\n */\nexport const usePageRegistry = () => useContext(PageRegistryContext);\n\n/**\n * Register a page in the registry (used internally by Page component).\n */\nexport const useRegisterPage = (name: string, component: PageComponent) => {\n\tconst registry = usePageRegistry();\n\n\tReact.useEffect(() => {\n\t\tregistry.set(name, component);\n\t\treturn () => {\n\t\t\tregistry.delete(name);\n\t\t};\n\t}, [name, component, registry]);\n};\n"],"mappings":";;;;AAMA,MAAM,sBAAsB,8BAA4B,IAAI,KAAK,CAAC;;;;;;;;;;AAWlE,MAAaA,wBAAiE,EAC7E,eACK;CACL,MAAM,WAAW,8BAAc,IAAI,KAA4B,EAAE,EAAE,CAAC;AAEpE,QACC,oBAAC,oBAAoB;EAAS,OAAO;EACnC;GAC6B;;;;;AAOjC,MAAa,wBAAwB,WAAW,oBAAoB;;;;AAKpE,MAAa,mBAAmB,MAAc,cAA6B;CAC1E,MAAM,WAAW,iBAAiB;AAElC,OAAM,gBAAgB;AACrB,WAAS,IAAI,MAAM,UAAU;AAC7B,eAAa;AACZ,YAAS,OAAO,KAAK;;IAEpB;EAAC;EAAM;EAAW;EAAS,CAAC"}
@@ -0,0 +1,21 @@
1
+ //#region src/primitives/page.d.ts
2
+ type PageProps<Params = unknown> = {
3
+ name: string;
4
+ component: React.ComponentType<{
5
+ params?: Params;
6
+ }>;
7
+ };
8
+ /**
9
+ * Declaratively register a page component.
10
+ *
11
+ * @example
12
+ * <Page name="HOME" component={HomePage} />
13
+ * <Page name="SETTINGS" component={SettingsPage} />
14
+ */
15
+ declare function Page<Params = unknown>({
16
+ name,
17
+ component
18
+ }: PageProps<Params>): null;
19
+ //#endregion
20
+ export { Page, PageProps };
21
+ //# sourceMappingURL=page.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page.d.ts","names":[],"sources":["../../src/primitives/page.tsx"],"sourcesContent":[],"mappings":";KAEY;EAAA,IAAA,EAAA,MAAS;EAYL,SAAI,EAVR,KAAA,CAAM,aAUE,CAAA;IACnB,MAAA,CAAA,EAX0C,MAW1C;EACA,CAAA,CAAA;CACY;;;;;;;;iBAHG;;;GAGb,UAAU"}
@@ -0,0 +1,18 @@
1
+ import { useRegisterPage } from "./page-registry.js";
2
+
3
+ //#region src/primitives/page.tsx
4
+ /**
5
+ * Declaratively register a page component.
6
+ *
7
+ * @example
8
+ * <Page name="HOME" component={HomePage} />
9
+ * <Page name="SETTINGS" component={SettingsPage} />
10
+ */
11
+ function Page({ name, component }) {
12
+ useRegisterPage(name, component);
13
+ return null;
14
+ }
15
+
16
+ //#endregion
17
+ export { Page };
18
+ //# sourceMappingURL=page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page.js","names":[],"sources":["../../src/primitives/page.tsx"],"sourcesContent":["import { useRegisterPage } from \"./page-registry\";\n\nexport type PageProps<Params = unknown> = {\n\tname: string;\n\tcomponent: React.ComponentType<{ params?: Params }>;\n};\n\n/**\n * Declaratively register a page component.\n *\n * @example\n * <Page name=\"HOME\" component={HomePage} />\n * <Page name=\"SETTINGS\" component={SettingsPage} />\n */\nexport function Page<Params = unknown>({\n\tname,\n\tcomponent,\n}: PageProps<Params>): null {\n\tuseRegisterPage(name, component as React.ComponentType<{ params?: unknown }>);\n\treturn null;\n}\n"],"mappings":";;;;;;;;;;AAcA,SAAgB,KAAuB,EACtC,MACA,aAC2B;AAC3B,iBAAgB,MAAM,UAAuD;AAC7E,QAAO"}
@@ -0,0 +1,35 @@
1
+ import React from "react";
2
+
3
+ //#region src/primitives/router.d.ts
4
+ type RouterProps = {
5
+ /**
6
+ * Current page name to render
7
+ */
8
+ page: string;
9
+ /**
10
+ * Params to pass to the page component
11
+ */
12
+ params?: unknown;
13
+ /**
14
+ * Fallback component when page is not found
15
+ */
16
+ fallback?: React.ComponentType<{
17
+ params?: unknown;
18
+ }>;
19
+ /**
20
+ * Children (Page components for registration)
21
+ */
22
+ children?: React.ReactNode;
23
+ };
24
+ /**
25
+ * Router that renders registered pages based on current page name.
26
+ *
27
+ * @example
28
+ * <Router page={currentPage} params={params} fallback={NotFoundPage}>
29
+ * <Page name="HOME" component={HomePage} />
30
+ * </Router>
31
+ */
32
+ declare const Router: React.FC<RouterProps>;
33
+ //#endregion
34
+ export { Router, RouterProps };
35
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","names":[],"sources":["../../src/primitives/router.tsx"],"sourcesContent":[],"mappings":";;;KAGY,WAAA;;AAAZ;AA8BA;;;;;;;;;aAhBY,KAAA,CAAM;;;;;;aAKN,KAAA,CAAM;;;;;;;;;;cAWL,QAAQ,KAAA,CAAM,GAAG"}
@@ -0,0 +1,22 @@
1
+ import { usePageRegistry } from "./page-registry.js";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+
4
+ //#region src/primitives/router.tsx
5
+ /**
6
+ * Router that renders registered pages based on current page name.
7
+ *
8
+ * @example
9
+ * <Router page={currentPage} params={params} fallback={NotFoundPage}>
10
+ * <Page name="HOME" component={HomePage} />
11
+ * </Router>
12
+ */
13
+ const Router = ({ page, params, fallback: Fallback, children }) => {
14
+ const PageComponent = usePageRegistry().get(page);
15
+ if (PageComponent) return /* @__PURE__ */ jsxs(Fragment, { children: [children, /* @__PURE__ */ jsx(PageComponent, { params })] });
16
+ if (Fallback) return /* @__PURE__ */ jsxs(Fragment, { children: [children, /* @__PURE__ */ jsx(Fallback, { params })] });
17
+ return /* @__PURE__ */ jsx(Fragment, { children });
18
+ };
19
+
20
+ //#endregion
21
+ export { Router };
22
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","names":["Router: React.FC<RouterProps>"],"sources":["../../src/primitives/router.tsx"],"sourcesContent":["import type React from \"react\";\nimport { usePageRegistry } from \"./page-registry\";\n\nexport type RouterProps = {\n\t/**\n\t * Current page name to render\n\t */\n\tpage: string;\n\n\t/**\n\t * Params to pass to the page component\n\t */\n\tparams?: unknown;\n\n\t/**\n\t * Fallback component when page is not found\n\t */\n\tfallback?: React.ComponentType<{ params?: unknown }>;\n\n\t/**\n\t * Children (Page components for registration)\n\t */\n\tchildren?: React.ReactNode;\n};\n\n/**\n * Router that renders registered pages based on current page name.\n *\n * @example\n * <Router page={currentPage} params={params} fallback={NotFoundPage}>\n * <Page name=\"HOME\" component={HomePage} />\n * </Router>\n */\nexport const Router: React.FC<RouterProps> = ({\n\tpage,\n\tparams,\n\tfallback: Fallback,\n\tchildren,\n}) => {\n\tconst registry = usePageRegistry();\n\n\t// Render children first (they register pages via useEffect)\n\t// Page components return null, so this is effectively a no-op render\n\n\t// Get the page component from registry\n\tconst PageComponent = registry.get(page);\n\n\tif (PageComponent) {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{children}\n\t\t\t\t<PageComponent params={params} />\n\t\t\t</>\n\t\t);\n\t}\n\n\t// Fall back if provided\n\tif (Fallback) {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{children}\n\t\t\t\t<Fallback params={params} />\n\t\t\t</>\n\t\t);\n\t}\n\n\treturn <>{children}</>;\n};\n"],"mappings":";;;;;;;;;;;;AAiCA,MAAaA,UAAiC,EAC7C,MACA,QACA,UAAU,UACV,eACK;CAOL,MAAM,gBANW,iBAAiB,CAMH,IAAI,KAAK;AAExC,KAAI,cACH,QACC,4CACE,UACD,oBAAC,iBAAsB,SAAU,IAC/B;AAKL,KAAI,SACH,QACC,4CACE,UACD,oBAAC,YAAiB,SAAU,IAC1B;AAIL,QAAO,gCAAG,WAAY"}
@@ -14,9 +14,14 @@ type WindowProps = Omit<React$1.HTMLAttributes<HTMLDivElement>, "children"> & {
14
14
  id?: string;
15
15
  };
16
16
  /**
17
- * Host container for the support experience. Handles escape
18
- * key dismissal and propagates render props so callers can take over the
19
- * layout.
17
+ * Dialog container with open/close state and escape key handling.
18
+ *
19
+ * @example
20
+ * <Window isOpen={isOpen} onOpenChange={setOpen}>
21
+ * {({ isOpen, close }) => (
22
+ * <div>Content here</div>
23
+ * )}
24
+ * </Window>
20
25
  */
21
26
  declare const SupportWindow: React$1.ForwardRefExoticComponent<Omit<React$1.HTMLAttributes<HTMLDivElement>, "children"> & {
22
27
  isOpen?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"window.d.ts","names":[],"sources":["../../src/primitives/window.tsx"],"sourcesContent":[],"mappings":";;;KAIY,iBAAA;;EAAA,KAAA,EAAA,GAAA,GAAA,IAAA;AAKZ,CAAA;AACsB,KADV,WAAA,GAAc,IACJ,CAArB,OAAA,CAAM,cAAe,CAAA,cAAA,CAAA,EAAA,UAAA,CAAA,GAAA;EAArB,MAAM,CAAA,EAAA,OAAA;EADmB,YAAA,CAAA,EAAA,CAAA,IAAA,EAAA,OAAA,EAAA,GAAA,IAAA;EAMd,QAAM,CAAA,EAAN,OAAA,CAAM,SAAA,GAAA,CAAA,CAAA,KAAA,EAAqB,iBAArB,EAAA,GAA2C,OAAA,CAAM,SAAjD,CAAA;EAAqB,OAAA,CAAA,EAAA,OAAA;EAAsB,aAAM,CAAA,EAAA,OAAA;EAAS,EAAA,CAAA,EAAA,MAAA;AAW5E,CAAA;;;;;;AAX6D,cAWhD,aAXsD,EAWzC,OAAA,CAAA,yBAXyC,CAWzC,IAXyC,CAWzC,OAAA,CAAA,cAXyC,CAWzC,cAXyC,CAAA,EAAA,UAAA,CAAA,GAAA;;;EAWzC,QAAA,CAAA,EAXd,OAAA,CAAM,SAWQ,GAAA,CAAA,CAAA,KAAA,EAXa,iBAWb,EAAA,GAXmC,OAAA,CAAM,SAWzC,CAAA;EAAA,OAAA,CAAA,EAAA,OAAA"}
1
+ {"version":3,"file":"window.d.ts","names":[],"sources":["../../src/primitives/window.tsx"],"sourcesContent":[],"mappings":";;;KAIY,iBAAA;;EAAA,KAAA,EAAA,GAAA,GAAA,IAAA;AAKZ,CAAA;AACsB,KADV,WAAA,GAAc,IACJ,CAArB,OAAA,CAAM,cAAe,CAAA,cAAA,CAAA,EAAA,UAAA,CAAA,GAAA;EAArB,MAAM,CAAA,EAAA,OAAA;EADmB,YAAA,CAAA,EAAA,CAAA,IAAA,EAAA,OAAA,EAAA,GAAA,IAAA;EAMd,QAAM,CAAA,EAAN,OAAA,CAAM,SAAA,GAAA,CAAA,CAAA,KAAA,EAAqB,iBAArB,EAAA,GAA2C,OAAA,CAAM,SAAjD,CAAA;EAAqB,OAAA,CAAA,EAAA,OAAA;EAAsB,aAAM,CAAA,EAAA,OAAA;EAAS,EAAA,CAAA,EAAA,MAAA;AAgB5E,CAAA;;;;;;;;;;;cAAa,eAAa,OAAA,CAAA,0BAAA,KAAA,OAAA,CAAA,eAAA;;;aAhBd,OAAA,CAAM,qBAAqB,sBAAsB,OAAA,CAAM"}
@@ -4,9 +4,14 @@ import * as React$1 from "react";
4
4
 
5
5
  //#region src/primitives/window.tsx
6
6
  /**
7
- * Host container for the support experience. Handles escape
8
- * key dismissal and propagates render props so callers can take over the
9
- * layout.
7
+ * Dialog container with open/close state and escape key handling.
8
+ *
9
+ * @example
10
+ * <Window isOpen={isOpen} onOpenChange={setOpen}>
11
+ * {({ isOpen, close }) => (
12
+ * <div>Content here</div>
13
+ * )}
14
+ * </Window>
10
15
  */
11
16
  const SupportWindow = (() => {
12
17
  const Component = React$1.forwardRef(({ isOpen: isOpenProp, onOpenChange, children, className, asChild = false, closeOnEscape = true, id = "cossistant-window",...props }, ref) => {
@@ -1 +1 @@
1
- {"version":3,"file":"window.js","names":["React","renderProps: WindowRenderProps"],"sources":["../../src/primitives/window.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { useSupportConfig } from \"../support/store/support-store\";\nimport { useRenderElement } from \"../utils/use-render-element\";\n\nexport type WindowRenderProps = {\n\tisOpen: boolean;\n\tclose: () => void;\n};\n\nexport type WindowProps = Omit<\n\tReact.HTMLAttributes<HTMLDivElement>,\n\t\"children\"\n> & {\n\tisOpen?: boolean;\n\tonOpenChange?: (open: boolean) => void;\n\tchildren?: React.ReactNode | ((props: WindowRenderProps) => React.ReactNode);\n\tasChild?: boolean;\n\tcloseOnEscape?: boolean;\n\tid?: string;\n};\n\n/**\n * Host container for the support experience. Handles escape\n * key dismissal and propagates render props so callers can take over the\n * layout.\n */\nexport const SupportWindow = (() => {\n\tconst Component = React.forwardRef<HTMLDivElement, WindowProps>(\n\t\t(\n\t\t\t{\n\t\t\t\tisOpen: isOpenProp,\n\t\t\t\tonOpenChange,\n\t\t\t\tchildren,\n\t\t\t\tclassName,\n\t\t\t\tasChild = false,\n\t\t\t\tcloseOnEscape = true,\n\t\t\t\tid = \"cossistant-window\",\n\t\t\t\t...props\n\t\t\t},\n\t\t\tref\n\t\t) => {\n\t\t\tconst { isOpen, close } = useSupportConfig();\n\n\t\t\tconst open = isOpenProp ?? isOpen ?? false;\n\n\t\t\tconst closeFn = React.useCallback(() => {\n\t\t\t\tif (onOpenChange) {\n\t\t\t\t\tonOpenChange(false);\n\t\t\t\t} else if (close) {\n\t\t\t\t\tclose();\n\t\t\t\t}\n\t\t\t}, [onOpenChange, close]);\n\n\t\t\t// Close on Escape\n\t\t\tReact.useEffect(() => {\n\t\t\t\tif (!(open && closeOnEscape)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst onKey = (e: KeyboardEvent) => {\n\t\t\t\t\tif (e.key === \"Escape\") {\n\t\t\t\t\t\tclose();\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\twindow.addEventListener(\"keydown\", onKey);\n\t\t\t\treturn () => window.removeEventListener(\"keydown\", onKey);\n\t\t\t}, [open, close, closeOnEscape]);\n\n\t\t\tconst renderProps: WindowRenderProps = { isOpen: open, close: closeFn };\n\n\t\t\tconst content =\n\t\t\t\ttypeof children === \"function\" ? children(renderProps) : children;\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: \"dialog\",\n\t\t\t\t\t\t\"aria-modal\": \"true\",\n\t\t\t\t\t\tid,\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\tenabled: open,\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n\n\tComponent.displayName = \"SupportWindow\";\n\treturn Component;\n})();\n"],"mappings":";;;;;;;;;;AA0BA,MAAa,uBAAuB;CACnC,MAAM,YAAYA,QAAM,YAEtB,EACC,QAAQ,YACR,cACA,UACA,WACA,UAAU,OACV,gBAAgB,MAChB,KAAK,oBACL,GAAG,SAEJ,QACI;EACJ,MAAM,EAAE,QAAQ,UAAU,kBAAkB;EAE5C,MAAM,OAAO,cAAc,UAAU;EAErC,MAAM,UAAUA,QAAM,kBAAkB;AACvC,OAAI,aACH,cAAa,MAAM;YACT,MACV,QAAO;KAEN,CAAC,cAAc,MAAM,CAAC;AAGzB,UAAM,gBAAgB;AACrB,OAAI,EAAE,QAAQ,eACb;GAED,MAAM,SAAS,MAAqB;AACnC,QAAI,EAAE,QAAQ,SACb,QAAO;;AAGT,UAAO,iBAAiB,WAAW,MAAM;AACzC,gBAAa,OAAO,oBAAoB,WAAW,MAAM;KACvD;GAAC;GAAM;GAAO;GAAc,CAAC;EAEhC,MAAMC,cAAiC;GAAE,QAAQ;GAAM,OAAO;GAAS;EAEvE,MAAM,UACL,OAAO,aAAa,aAAa,SAAS,YAAY,GAAG;AAE1D,SAAO,iBACN,OACA;GACC;GACA;GACA,EACD;GACC;GACA,OAAO;GACP,OAAO;IACN,MAAM;IACN,cAAc;IACd;IACA,GAAG;IACH,UAAU;IACV;GACD,SAAS;GACT,CACD;GAEF;AAED,WAAU,cAAc;AACxB,QAAO;IACJ"}
1
+ {"version":3,"file":"window.js","names":["React","renderProps: WindowRenderProps"],"sources":["../../src/primitives/window.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { useSupportConfig } from \"../support/store/support-store\";\nimport { useRenderElement } from \"../utils/use-render-element\";\n\nexport type WindowRenderProps = {\n\tisOpen: boolean;\n\tclose: () => void;\n};\n\nexport type WindowProps = Omit<\n\tReact.HTMLAttributes<HTMLDivElement>,\n\t\"children\"\n> & {\n\tisOpen?: boolean;\n\tonOpenChange?: (open: boolean) => void;\n\tchildren?: React.ReactNode | ((props: WindowRenderProps) => React.ReactNode);\n\tasChild?: boolean;\n\tcloseOnEscape?: boolean;\n\tid?: string;\n};\n\n/**\n * Dialog container with open/close state and escape key handling.\n *\n * @example\n * <Window isOpen={isOpen} onOpenChange={setOpen}>\n * {({ isOpen, close }) => (\n * <div>Content here</div>\n * )}\n * </Window>\n */\nexport const SupportWindow = (() => {\n\tconst Component = React.forwardRef<HTMLDivElement, WindowProps>(\n\t\t(\n\t\t\t{\n\t\t\t\tisOpen: isOpenProp,\n\t\t\t\tonOpenChange,\n\t\t\t\tchildren,\n\t\t\t\tclassName,\n\t\t\t\tasChild = false,\n\t\t\t\tcloseOnEscape = true,\n\t\t\t\tid = \"cossistant-window\",\n\t\t\t\t...props\n\t\t\t},\n\t\t\tref\n\t\t) => {\n\t\t\tconst { isOpen, close } = useSupportConfig();\n\n\t\t\tconst open = isOpenProp ?? isOpen ?? false;\n\n\t\t\tconst closeFn = React.useCallback(() => {\n\t\t\t\tif (onOpenChange) {\n\t\t\t\t\tonOpenChange(false);\n\t\t\t\t} else if (close) {\n\t\t\t\t\tclose();\n\t\t\t\t}\n\t\t\t}, [onOpenChange, close]);\n\n\t\t\t// Close on Escape\n\t\t\tReact.useEffect(() => {\n\t\t\t\tif (!(open && closeOnEscape)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst onKey = (e: KeyboardEvent) => {\n\t\t\t\t\tif (e.key === \"Escape\") {\n\t\t\t\t\t\tclose();\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\twindow.addEventListener(\"keydown\", onKey);\n\t\t\t\treturn () => window.removeEventListener(\"keydown\", onKey);\n\t\t\t}, [open, close, closeOnEscape]);\n\n\t\t\tconst renderProps: WindowRenderProps = { isOpen: open, close: closeFn };\n\n\t\t\tconst content =\n\t\t\t\ttypeof children === \"function\" ? children(renderProps) : children;\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: \"dialog\",\n\t\t\t\t\t\t\"aria-modal\": \"true\",\n\t\t\t\t\t\tid,\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\tenabled: open,\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n\n\tComponent.displayName = \"SupportWindow\";\n\treturn Component;\n})();\n"],"mappings":";;;;;;;;;;;;;;;AA+BA,MAAa,uBAAuB;CACnC,MAAM,YAAYA,QAAM,YAEtB,EACC,QAAQ,YACR,cACA,UACA,WACA,UAAU,OACV,gBAAgB,MAChB,KAAK,oBACL,GAAG,SAEJ,QACI;EACJ,MAAM,EAAE,QAAQ,UAAU,kBAAkB;EAE5C,MAAM,OAAO,cAAc,UAAU;EAErC,MAAM,UAAUA,QAAM,kBAAkB;AACvC,OAAI,aACH,cAAa,MAAM;YACT,MACV,QAAO;KAEN,CAAC,cAAc,MAAM,CAAC;AAGzB,UAAM,gBAAgB;AACrB,OAAI,EAAE,QAAQ,eACb;GAED,MAAM,SAAS,MAAqB;AACnC,QAAI,EAAE,QAAQ,SACb,QAAO;;AAGT,UAAO,iBAAiB,WAAW,MAAM;AACzC,gBAAa,OAAO,oBAAoB,WAAW,MAAM;KACvD;GAAC;GAAM;GAAO;GAAc,CAAC;EAEhC,MAAMC,cAAiC;GAAE,QAAQ;GAAM,OAAO;GAAS;EAEvE,MAAM,UACL,OAAO,aAAa,aAAa,SAAS,YAAY,GAAG;AAE1D,SAAO,iBACN,OACA;GACC;GACA;GACA,EACD;GACC;GACA,OAAO;GACP,OAAO;IACN,MAAM;IACN,cAAc;IACd;IACA,GAAG;IACH,UAAU;IACV;GACD,SAAS;GACT,CACD;GAEF;AAED,WAAU,cAAc;AACxB,QAAO;IACJ"}
package/realtime/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { applyConversationSeenEvent, hydrateConversationSeen, upsertConversationSeen } from "./seen-store.js";
2
- import { RealtimeProvider, useRealtimeConnection } from "./provider.js";
3
2
  import { applyConversationTypingEvent, clearTypingFromTimelineItem, clearTypingState, setTypingState } from "./typing-store.js";
3
+ import { RealtimeProvider, useRealtimeConnection } from "./provider.js";
4
4
  import { useRealtime } from "./use-realtime.js";
5
5
  import { SupportRealtimeProvider } from "./support-provider.js";
6
6
 
@@ -2,9 +2,9 @@
2
2
 
3
3
 
4
4
  import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
5
+ import { jsx } from "react/jsx-runtime";
5
6
  import { isValidEventType, validateRealtimeEvent } from "@cossistant/types/realtime-events";
6
7
  import useWebSocket, { ReadyState } from "react-use-websocket";
7
- import { jsx } from "react/jsx-runtime";
8
8
 
9
9
  //#region src/realtime/provider.tsx
10
10
  const DEFAULT_HEARTBEAT_INTERVAL_MS = 15e3;
@@ -36,10 +36,6 @@ function SupportRealtimeProvider({ children }) {
36
36
  conversationTyping: (_data, { event, context }) => {
37
37
  if (context.websiteId && event.payload.websiteId !== context.websiteId) return;
38
38
  applyConversationTypingEvent(event, { ignoreVisitorId: context.visitorId });
39
- },
40
- conversationEventCreated: (_data, { event, context }) => {
41
- if (context.websiteId && event.payload.websiteId !== context.websiteId) return;
42
- context.client.handleRealtimeEvent(event);
43
39
  }
44
40
  }), []),
45
41
  websiteId: realtimeContext.websiteId,
@@ -1 +1 @@
1
- {"version":3,"file":"support-provider.js","names":[],"sources":["../../src/realtime/support-provider.tsx"],"sourcesContent":["import type { CossistantClient } from \"@cossistant/core\";\nimport type { RealtimeEvent } from \"@cossistant/types/realtime-events\";\nimport type React from \"react\";\nimport { useMemo } from \"react\";\nimport { useSupport } from \"../provider\";\nimport { applyConversationSeenEvent } from \"./seen-store\";\nimport {\n\tapplyConversationTypingEvent,\n\tclearTypingFromTimelineItem,\n} from \"./typing-store\";\nimport { useRealtime } from \"./use-realtime\";\n\ntype SupportRealtimeContext = {\n\twebsiteId: string | null;\n\tvisitorId: string | null;\n\tclient: CossistantClient;\n};\n\ntype SupportRealtimeProviderProps = {\n\tchildren: React.ReactNode;\n};\n\n/**\n * Bridges websocket events into the core client stores so support hooks stay\n * in sync without forcing refetches.\n */\nexport function SupportRealtimeProvider({\n\tchildren,\n}: SupportRealtimeProviderProps): React.ReactElement {\n\tconst { website, client, visitor } = useSupport();\n\n\tconst realtimeContext = useMemo<SupportRealtimeContext>(\n\t\t() => ({\n\t\t\twebsiteId: website?.id ?? null,\n\t\t\tvisitorId: visitor?.id ?? null,\n\t\t\tclient,\n\t\t}),\n\t\t[website?.id, visitor?.id, client]\n\t);\n\n\tconst events = useMemo(\n\t\t() => ({\n\t\t\ttimelineItemCreated: (\n\t\t\t\t_data: unknown,\n\t\t\t\t{\n\t\t\t\t\tevent,\n\t\t\t\t\tcontext,\n\t\t\t\t}: {\n\t\t\t\t\tevent: RealtimeEvent<\"timelineItemCreated\">;\n\t\t\t\t\tcontext: SupportRealtimeContext;\n\t\t\t\t}\n\t\t\t) => {\n\t\t\t\tif (\n\t\t\t\t\tcontext.websiteId &&\n\t\t\t\t\tevent.payload.websiteId !== context.websiteId\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Clear typing state when a timeline item is created\n\t\t\t\tclearTypingFromTimelineItem(event);\n\n\t\t\t\tcontext.client.handleRealtimeEvent(event);\n\t\t\t},\n\t\t\tconversationSeen: (\n\t\t\t\t_data: unknown,\n\t\t\t\t{\n\t\t\t\t\tevent,\n\t\t\t\t\tcontext,\n\t\t\t\t}: {\n\t\t\t\t\tevent: RealtimeEvent<\"conversationSeen\">;\n\t\t\t\t\tcontext: SupportRealtimeContext;\n\t\t\t\t}\n\t\t\t) => {\n\t\t\t\tif (\n\t\t\t\t\tcontext.websiteId &&\n\t\t\t\t\tevent.payload.websiteId !== context.websiteId\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Update the seen store so the UI reflects who has seen messages\n\t\t\t\tapplyConversationSeenEvent(event);\n\t\t\t},\n\t\t\tconversationTyping: (\n\t\t\t\t_data: unknown,\n\t\t\t\t{\n\t\t\t\t\tevent,\n\t\t\t\t\tcontext,\n\t\t\t\t}: {\n\t\t\t\t\tevent: RealtimeEvent<\"conversationTyping\">;\n\t\t\t\t\tcontext: SupportRealtimeContext;\n\t\t\t\t}\n\t\t\t) => {\n\t\t\t\tif (\n\t\t\t\t\tcontext.websiteId &&\n\t\t\t\t\tevent.payload.websiteId !== context.websiteId\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Update typing store, but ignore events from the current visitor (their own typing)\n\t\t\t\t// Note: We use context.visitorId which is fresh from the context object\n\t\t\t\tapplyConversationTypingEvent(event, {\n\t\t\t\t\tignoreVisitorId: context.visitorId,\n\t\t\t\t});\n\t\t\t},\n\t\t\tconversationEventCreated: (\n\t\t\t\t_data: unknown,\n\t\t\t\t{\n\t\t\t\t\tevent,\n\t\t\t\t\tcontext,\n\t\t\t\t}: {\n\t\t\t\t\tevent: RealtimeEvent<\"conversationEventCreated\">;\n\t\t\t\t\tcontext: SupportRealtimeContext;\n\t\t\t\t}\n\t\t\t) => {\n\t\t\t\tif (\n\t\t\t\t\tcontext.websiteId &&\n\t\t\t\t\tevent.payload.websiteId !== context.websiteId\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcontext.client.handleRealtimeEvent(event);\n\t\t\t},\n\t\t}),\n\t\t// Empty dependencies is fine here since we use the context parameter\n\t\t// which always has fresh data from the memoized realtimeContext\n\t\t[]\n\t);\n\n\tuseRealtime<SupportRealtimeContext>({\n\t\tcontext: realtimeContext,\n\t\tevents,\n\t\twebsiteId: realtimeContext.websiteId,\n\t\tvisitorId: realtimeContext.visitorId,\n\t});\n\n\treturn <>{children}</>;\n}\n"],"mappings":";;;;;;;;;;;;AA0BA,SAAgB,wBAAwB,EACvC,YACoD;CACpD,MAAM,EAAE,SAAS,QAAQ,YAAY,YAAY;CAEjD,MAAM,kBAAkB,eAChB;EACN,WAAW,SAAS,MAAM;EAC1B,WAAW,SAAS,MAAM;EAC1B;EACA,GACD;EAAC,SAAS;EAAI,SAAS;EAAI;EAAO,CAClC;AA8FD,aAAoC;EACnC,SAAS;EACT,QA9Fc,eACP;GACN,sBACC,OACA,EACC,OACA,cAKG;AACJ,QACC,QAAQ,aACR,MAAM,QAAQ,cAAc,QAAQ,UAEpC;AAID,gCAA4B,MAAM;AAElC,YAAQ,OAAO,oBAAoB,MAAM;;GAE1C,mBACC,OACA,EACC,OACA,cAKG;AACJ,QACC,QAAQ,aACR,MAAM,QAAQ,cAAc,QAAQ,UAEpC;AAID,+BAA2B,MAAM;;GAElC,qBACC,OACA,EACC,OACA,cAKG;AACJ,QACC,QAAQ,aACR,MAAM,QAAQ,cAAc,QAAQ,UAEpC;AAKD,iCAA6B,OAAO,EACnC,iBAAiB,QAAQ,WACzB,CAAC;;GAEH,2BACC,OACA,EACC,OACA,cAKG;AACJ,QACC,QAAQ,aACR,MAAM,QAAQ,cAAc,QAAQ,UAEpC;AAGD,YAAQ,OAAO,oBAAoB,MAAM;;GAE1C,GAGD,EAAE,CACF;EAKA,WAAW,gBAAgB;EAC3B,WAAW,gBAAgB;EAC3B,CAAC;AAEF,QAAO,gCAAG,WAAY"}
1
+ {"version":3,"file":"support-provider.js","names":[],"sources":["../../src/realtime/support-provider.tsx"],"sourcesContent":["import type { CossistantClient } from \"@cossistant/core\";\nimport type { RealtimeEvent } from \"@cossistant/types/realtime-events\";\nimport type React from \"react\";\nimport { useMemo } from \"react\";\nimport { useSupport } from \"../provider\";\nimport { applyConversationSeenEvent } from \"./seen-store\";\nimport {\n\tapplyConversationTypingEvent,\n\tclearTypingFromTimelineItem,\n} from \"./typing-store\";\nimport { useRealtime } from \"./use-realtime\";\n\ntype SupportRealtimeContext = {\n\twebsiteId: string | null;\n\tvisitorId: string | null;\n\tclient: CossistantClient;\n};\n\ntype SupportRealtimeProviderProps = {\n\tchildren: React.ReactNode;\n};\n\n/**\n * Bridges websocket events into the core client stores so support hooks stay\n * in sync without forcing refetches.\n */\nexport function SupportRealtimeProvider({\n\tchildren,\n}: SupportRealtimeProviderProps): React.ReactElement {\n\tconst { website, client, visitor } = useSupport();\n\n\tconst realtimeContext = useMemo<SupportRealtimeContext>(\n\t\t() => ({\n\t\t\twebsiteId: website?.id ?? null,\n\t\t\tvisitorId: visitor?.id ?? null,\n\t\t\tclient,\n\t\t}),\n\t\t[website?.id, visitor?.id, client]\n\t);\n\n\tconst events = useMemo(\n\t\t() => ({\n\t\t\ttimelineItemCreated: (\n\t\t\t\t_data: unknown,\n\t\t\t\t{\n\t\t\t\t\tevent,\n\t\t\t\t\tcontext,\n\t\t\t\t}: {\n\t\t\t\t\tevent: RealtimeEvent<\"timelineItemCreated\">;\n\t\t\t\t\tcontext: SupportRealtimeContext;\n\t\t\t\t}\n\t\t\t) => {\n\t\t\t\tif (\n\t\t\t\t\tcontext.websiteId &&\n\t\t\t\t\tevent.payload.websiteId !== context.websiteId\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Clear typing state when a timeline item is created\n\t\t\t\tclearTypingFromTimelineItem(event);\n\n\t\t\t\tcontext.client.handleRealtimeEvent(event);\n\t\t\t},\n\t\t\tconversationSeen: (\n\t\t\t\t_data: unknown,\n\t\t\t\t{\n\t\t\t\t\tevent,\n\t\t\t\t\tcontext,\n\t\t\t\t}: {\n\t\t\t\t\tevent: RealtimeEvent<\"conversationSeen\">;\n\t\t\t\t\tcontext: SupportRealtimeContext;\n\t\t\t\t}\n\t\t\t) => {\n\t\t\t\tif (\n\t\t\t\t\tcontext.websiteId &&\n\t\t\t\t\tevent.payload.websiteId !== context.websiteId\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Update the seen store so the UI reflects who has seen messages\n\t\t\t\tapplyConversationSeenEvent(event);\n\t\t\t},\n\t\t\tconversationTyping: (\n\t\t\t\t_data: unknown,\n\t\t\t\t{\n\t\t\t\t\tevent,\n\t\t\t\t\tcontext,\n\t\t\t\t}: {\n\t\t\t\t\tevent: RealtimeEvent<\"conversationTyping\">;\n\t\t\t\t\tcontext: SupportRealtimeContext;\n\t\t\t\t}\n\t\t\t) => {\n\t\t\t\tif (\n\t\t\t\t\tcontext.websiteId &&\n\t\t\t\t\tevent.payload.websiteId !== context.websiteId\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Update typing store, but ignore events from the current visitor (their own typing)\n\t\t\t\t// Note: We use context.visitorId which is fresh from the context object\n\t\t\t\tapplyConversationTypingEvent(event, {\n\t\t\t\t\tignoreVisitorId: context.visitorId,\n\t\t\t\t});\n\t\t\t},\n\t\t}),\n\t\t// Empty dependencies is fine here since we use the context parameter\n\t\t// which always has fresh data from the memoized realtimeContext\n\t\t[]\n\t);\n\n\tuseRealtime<SupportRealtimeContext>({\n\t\tcontext: realtimeContext,\n\t\tevents,\n\t\twebsiteId: realtimeContext.websiteId,\n\t\tvisitorId: realtimeContext.visitorId,\n\t});\n\n\treturn <>{children}</>;\n}\n"],"mappings":";;;;;;;;;;;;AA0BA,SAAgB,wBAAwB,EACvC,YACoD;CACpD,MAAM,EAAE,SAAS,QAAQ,YAAY,YAAY;CAEjD,MAAM,kBAAkB,eAChB;EACN,WAAW,SAAS,MAAM;EAC1B,WAAW,SAAS,MAAM;EAC1B;EACA,GACD;EAAC,SAAS;EAAI,SAAS;EAAI;EAAO,CAClC;AA2ED,aAAoC;EACnC,SAAS;EACT,QA3Ec,eACP;GACN,sBACC,OACA,EACC,OACA,cAKG;AACJ,QACC,QAAQ,aACR,MAAM,QAAQ,cAAc,QAAQ,UAEpC;AAID,gCAA4B,MAAM;AAElC,YAAQ,OAAO,oBAAoB,MAAM;;GAE1C,mBACC,OACA,EACC,OACA,cAKG;AACJ,QACC,QAAQ,aACR,MAAM,QAAQ,cAAc,QAAQ,UAEpC;AAID,+BAA2B,MAAM;;GAElC,qBACC,OACA,EACC,OACA,cAKG;AACJ,QACC,QAAQ,aACR,MAAM,QAAQ,cAAc,QAAQ,UAEpC;AAKD,iCAA6B,OAAO,EACnC,iBAAiB,QAAQ,WACzB,CAAC;;GAEH,GAGD,EAAE,CACF;EAKA,WAAW,gBAAgB;EAC3B,WAAW,gBAAgB;EAC3B,CAAC;AAEF,QAAO,gCAAG,WAAY"}