@cossistant/react 0.0.29 → 0.0.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/_virtual/rolldown_runtime.js +9 -23
- package/hooks/index.d.ts +2 -2
- package/hooks/private/store/use-conversations-store.d.ts +2 -0
- package/hooks/private/store/use-conversations-store.d.ts.map +1 -1
- package/hooks/private/store/use-conversations-store.js +15 -8
- package/hooks/private/store/use-conversations-store.js.map +1 -1
- package/hooks/private/store/use-store-selector.d.ts +3 -0
- package/hooks/private/store/use-store-selector.d.ts.map +1 -1
- package/hooks/private/store/use-store-selector.js +4 -8
- package/hooks/private/store/use-store-selector.js.map +1 -1
- package/hooks/private/store/use-website-store.d.ts +3 -1
- package/hooks/private/store/use-website-store.d.ts.map +1 -1
- package/hooks/private/store/use-website-store.js +14 -6
- package/hooks/private/store/use-website-store.js.map +1 -1
- package/hooks/private/use-client-query.d.ts +1 -1
- package/hooks/private/use-client-query.d.ts.map +1 -1
- package/hooks/private/use-client-query.js +1 -0
- package/hooks/private/use-client-query.js.map +1 -1
- package/hooks/private/use-default-messages.d.ts +1 -1
- package/hooks/private/use-grouped-messages.d.ts +2 -2
- package/hooks/private/use-grouped-messages.d.ts.map +1 -1
- package/hooks/private/use-grouped-messages.js +34 -10
- package/hooks/private/use-grouped-messages.js.map +1 -1
- package/hooks/private/use-rest-client.d.ts +13 -3
- package/hooks/private/use-rest-client.d.ts.map +1 -1
- package/hooks/private/use-rest-client.js +49 -22
- package/hooks/private/use-rest-client.js.map +1 -1
- package/hooks/private/use-visitor-typing-reporter.d.ts +1 -1
- package/hooks/use-conversation-auto-seen.d.ts +1 -1
- package/hooks/use-conversation-page.d.ts +1 -1
- package/hooks/use-conversation-page.d.ts.map +1 -1
- package/hooks/use-conversation-page.js +13 -4
- package/hooks/use-conversation-page.js.map +1 -1
- package/hooks/use-conversation-preview.d.ts +3 -1
- package/hooks/use-conversation-preview.d.ts.map +1 -1
- package/hooks/use-conversation-preview.js +8 -4
- package/hooks/use-conversation-preview.js.map +1 -1
- package/hooks/use-conversation-seen.d.ts +1 -1
- package/hooks/use-conversation-timeline-items.d.ts +1 -1
- package/hooks/use-conversation-timeline-items.js +2 -3
- package/hooks/use-conversation-timeline-items.js.map +1 -1
- package/hooks/use-conversation-timeline.d.ts +1 -1
- package/hooks/use-conversation.d.ts +1 -1
- package/hooks/use-conversation.js +2 -3
- package/hooks/use-conversation.js.map +1 -1
- package/hooks/use-conversations.d.ts +1 -1
- package/hooks/use-conversations.js +5 -3
- package/hooks/use-conversations.js.map +1 -1
- package/hooks/use-create-conversation.d.ts +3 -3
- package/hooks/use-create-conversation.js +1 -0
- package/hooks/use-create-conversation.js.map +1 -1
- package/hooks/use-file-upload.d.ts +1 -1
- package/hooks/use-file-upload.js +3 -3
- package/hooks/use-file-upload.js.map +1 -1
- package/hooks/use-home-page.js +3 -3
- package/hooks/use-home-page.js.map +1 -1
- package/hooks/use-message-composer.d.ts +10 -3
- package/hooks/use-message-composer.d.ts.map +1 -1
- package/hooks/use-message-composer.js +5 -2
- package/hooks/use-message-composer.js.map +1 -1
- package/hooks/use-realtime-support.d.ts +1 -1
- package/hooks/use-send-message.d.ts +8 -2
- package/hooks/use-send-message.d.ts.map +1 -1
- package/hooks/use-send-message.js +5 -3
- package/hooks/use-send-message.js.map +1 -1
- package/hooks/use-visitor.js +2 -2
- package/hooks/use-visitor.js.map +1 -1
- package/identify-visitor.d.ts.map +1 -1
- package/identify-visitor.js +15 -1
- package/identify-visitor.js.map +1 -1
- package/index.d.ts +2 -2
- package/index.js +1 -1
- package/package.json +6 -3
- package/{conversation.d.ts → packages/types/src/api/conversation.d.ts} +374 -64
- package/packages/types/src/api/conversation.d.ts.map +1 -0
- package/packages/types/src/api/timeline-item.d.ts +460 -0
- package/packages/types/src/api/timeline-item.d.ts.map +1 -0
- package/{realtime-events.d.ts → packages/types/src/realtime-events.d.ts} +449 -47
- package/packages/types/src/realtime-events.d.ts.map +1 -0
- package/{schemas3.d.ts → packages/types/src/schemas.d.ts} +97 -19
- package/packages/types/src/schemas.d.ts.map +1 -0
- package/primitives/avatar/avatar.js +1 -1
- package/primitives/avatar/avatar.js.map +1 -1
- package/primitives/avatar/fallback.js +1 -1
- package/primitives/avatar/fallback.js.map +1 -1
- package/primitives/avatar/image.js +1 -1
- package/primitives/avatar/image.js.map +1 -1
- package/primitives/button.js +1 -1
- package/primitives/button.js.map +1 -1
- package/primitives/conversation-timeline.d.ts +1 -1
- package/primitives/conversation-timeline.js +4 -4
- package/primitives/conversation-timeline.js.map +1 -1
- package/primitives/day-separator.js +3 -3
- package/primitives/day-separator.js.map +1 -1
- package/primitives/multimodal-input.d.ts +2 -2
- package/primitives/multimodal-input.d.ts.map +1 -1
- package/primitives/multimodal-input.js +2 -2
- package/primitives/multimodal-input.js.map +1 -1
- package/primitives/timeline-item-attachments.d.ts +1 -1
- package/primitives/timeline-item-attachments.js +6 -7
- package/primitives/timeline-item-attachments.js.map +1 -1
- package/primitives/timeline-item-group.d.ts +1 -1
- package/primitives/timeline-item-group.js +7 -7
- package/primitives/timeline-item-group.js.map +1 -1
- package/primitives/timeline-item.d.ts +1 -1
- package/primitives/timeline-item.d.ts.map +1 -1
- package/primitives/timeline-item.js +54 -14
- package/primitives/timeline-item.js.map +1 -1
- package/primitives/trigger.js +1 -1
- package/primitives/trigger.js.map +1 -1
- package/primitives/window.js +1 -1
- package/primitives/window.js.map +1 -1
- package/provider.d.ts +4 -2
- package/provider.d.ts.map +1 -1
- package/provider.js +56 -8
- package/provider.js.map +1 -1
- package/realtime/event-filter.d.ts +4 -1
- package/realtime/event-filter.d.ts.map +1 -1
- package/realtime/event-filter.js +14 -0
- package/realtime/event-filter.js.map +1 -1
- package/realtime/provider.d.ts +1 -1
- package/realtime/provider.d.ts.map +1 -1
- package/realtime/provider.js +1 -2
- package/realtime/provider.js.map +1 -1
- package/realtime/seen-store.d.ts +2 -2
- package/realtime/support-provider.js +3 -2
- package/realtime/support-provider.js.map +1 -1
- package/realtime/typing-store.d.ts +1 -1
- package/realtime/use-realtime.d.ts +1 -1
- package/support/components/avatar-stack.d.ts.map +1 -1
- package/support/components/avatar-stack.js +32 -12
- package/support/components/avatar-stack.js.map +1 -1
- package/support/components/avatar.d.ts +34 -3
- package/support/components/avatar.d.ts.map +1 -1
- package/support/components/avatar.js +61 -8
- package/support/components/avatar.js.map +1 -1
- package/support/components/button.d.ts +4 -2
- package/support/components/button.d.ts.map +1 -1
- package/support/components/button.js +3 -3
- package/support/components/button.js.map +1 -1
- package/support/components/configuration-error.d.ts +16 -0
- package/support/components/configuration-error.d.ts.map +1 -0
- package/support/components/configuration-error.js +162 -0
- package/support/components/configuration-error.js.map +1 -0
- package/support/components/content.js +1 -2
- package/support/components/content.js.map +1 -1
- package/support/components/conversation-button-link.js +18 -23
- package/support/components/conversation-button-link.js.map +1 -1
- package/support/components/conversation-event.d.ts.map +1 -1
- package/support/components/conversation-event.js +7 -5
- package/support/components/conversation-event.js.map +1 -1
- package/support/components/conversation-resolved-feedback.d.ts +21 -0
- package/support/components/conversation-resolved-feedback.d.ts.map +1 -0
- package/support/components/conversation-resolved-feedback.js +59 -0
- package/support/components/conversation-resolved-feedback.js.map +1 -0
- package/support/components/conversation-timeline-utils.d.ts +5 -0
- package/support/components/conversation-timeline-utils.d.ts.map +1 -0
- package/support/components/conversation-timeline-utils.js +10 -0
- package/support/components/conversation-timeline-utils.js.map +1 -0
- package/support/components/conversation-timeline.d.ts +1 -1
- package/support/components/conversation-timeline.d.ts.map +1 -1
- package/support/components/conversation-timeline.js +5 -4
- package/support/components/conversation-timeline.js.map +1 -1
- package/support/components/header.js +1 -1
- package/support/components/icons.d.ts +1 -1
- package/support/components/icons.d.ts.map +1 -1
- package/support/components/icons.js +6 -2
- package/support/components/icons.js.map +1 -1
- package/support/components/image-lightbox.d.ts +1 -1
- package/support/components/image-lightbox.js +1 -2
- package/support/components/image-lightbox.js.map +1 -1
- package/support/components/index.d.ts +2 -1
- package/support/components/index.js +3 -2
- package/support/components/multimodal-input.js +0 -1
- package/support/components/multimodal-input.js.map +1 -1
- package/support/components/navigation-tab.js +1 -1
- package/support/components/online-indicator.d.ts +50 -0
- package/support/components/online-indicator.d.ts.map +1 -0
- package/support/components/online-indicator.js +65 -0
- package/support/components/online-indicator.js.map +1 -0
- package/support/components/root.js +0 -1
- package/support/components/root.js.map +1 -1
- package/support/components/timeline-identification-tool.js +4 -4
- package/support/components/timeline-identification-tool.js.map +1 -1
- package/support/components/timeline-message-group.d.ts +1 -1
- package/support/components/timeline-message-group.d.ts.map +1 -1
- package/support/components/timeline-message-group.js +6 -4
- package/support/components/timeline-message-group.js.map +1 -1
- package/support/components/timeline-message-item.d.ts +1 -1
- package/support/components/timeline-message-item.js +4 -4
- package/support/components/timeline-message-item.js.map +1 -1
- package/support/components/trigger.js +1 -2
- package/support/components/trigger.js.map +1 -1
- package/support/components/typing-indicator.js +1 -1
- package/support/components/typing-indicator.js.map +1 -1
- package/support/context/controlled-state.js +0 -1
- package/support/context/controlled-state.js.map +1 -1
- package/support/context/events.d.ts +1 -1
- package/support/context/events.js +0 -1
- package/support/context/events.js.map +1 -1
- package/support/context/handle.js +0 -1
- package/support/context/handle.js.map +1 -1
- package/support/context/identification.d.ts +33 -0
- package/support/context/identification.d.ts.map +1 -0
- package/support/context/identification.js +34 -0
- package/support/context/identification.js.map +1 -0
- package/support/context/positioning.js +0 -1
- package/support/context/positioning.js.map +1 -1
- package/support/context/slots.js +0 -1
- package/support/context/slots.js.map +1 -1
- package/support/context/websocket.d.ts +1 -1
- package/support/context/websocket.js +0 -1
- package/support/context/websocket.js.map +1 -1
- package/support/index.d.ts.map +1 -1
- package/support/index.js +51 -18
- package/support/index.js.map +1 -1
- package/support/pages/conversation-history.js +2 -1
- package/support/pages/conversation-history.js.map +1 -1
- package/support/pages/conversation.d.ts +1 -1
- package/support/pages/conversation.d.ts.map +1 -1
- package/support/pages/conversation.js +34 -8
- package/support/pages/conversation.js.map +1 -1
- package/support/pages/home.js +5 -3
- package/support/pages/home.js.map +1 -1
- package/support/router.d.ts.map +1 -1
- package/support/router.js +4 -0
- package/support/router.js.map +1 -1
- package/support/store/support-store.js +0 -1
- package/support/store/support-store.js.map +1 -1
- package/support/{support-C7Xaw-N6.css → support-DmViRaga.css} +2 -2
- package/support/{support-C7Xaw-N6.css.map → support-DmViRaga.css.map} +1 -1
- package/support/text/index.js +1 -1
- package/support/text/index.js.map +1 -1
- package/support/text/locales/en.js +10 -1
- package/support/text/locales/en.js.map +1 -1
- package/support/text/locales/es.js +10 -1
- package/support/text/locales/es.js.map +1 -1
- package/support/text/locales/fr.js +10 -1
- package/support/text/locales/fr.js.map +1 -1
- package/support/text/locales/keys.d.ts +11 -0
- package/support/text/locales/keys.d.ts.map +1 -1
- package/support/text/locales/keys.js +3 -0
- package/support/text/locales/keys.js.map +1 -1
- package/support/utils/index.d.ts +1 -1
- package/support-config.js +0 -1
- package/support-config.js.map +1 -1
- package/support.css +1 -1
- package/tailwind.css +1 -1
- package/utils/conversation.d.ts.map +1 -1
- package/utils/conversation.js +1 -3
- package/utils/conversation.js.map +1 -1
- package/utils/use-render-element.js +2 -2
- package/utils/use-render-element.js.map +1 -1
- package/api.d.ts +0 -71
- package/api.d.ts.map +0 -1
- package/checks.d.ts +0 -189
- package/checks.d.ts.map +0 -1
- package/clsx.d.ts +0 -7
- package/clsx.d.ts.map +0 -1
- package/coerce.d.ts +0 -9
- package/coerce.d.ts.map +0 -1
- package/conversation.d.ts.map +0 -1
- package/core.d.ts +0 -35
- package/core.d.ts.map +0 -1
- package/errors.d.ts +0 -130
- package/errors.d.ts.map +0 -1
- package/errors2.d.ts +0 -24
- package/errors2.d.ts.map +0 -1
- package/index2.d.ts +0 -4
- package/index3.d.ts +0 -1
- package/json-schema.d.ts +0 -70
- package/json-schema.d.ts.map +0 -1
- package/metadata.d.ts +0 -1
- package/openapi-generator.d.ts +0 -1
- package/openapi-generator2.d.ts +0 -1
- package/openapi-generator3.d.ts +0 -1
- package/openapi30.d.ts +0 -125
- package/openapi30.d.ts.map +0 -1
- package/openapi31.d.ts +0 -131
- package/openapi31.d.ts.map +0 -1
- package/parse.d.ts +0 -17
- package/parse.d.ts.map +0 -1
- package/realtime-events.d.ts.map +0 -1
- package/registries.d.ts +0 -32
- package/registries.d.ts.map +0 -1
- package/schemas.d.ts +0 -971
- package/schemas.d.ts.map +0 -1
- package/schemas2.d.ts +0 -345
- package/schemas2.d.ts.map +0 -1
- package/schemas3.d.ts.map +0 -1
- package/specification-extension.d.ts +0 -9
- package/specification-extension.d.ts.map +0 -1
- package/standard-schema.d.ts +0 -121
- package/standard-schema.d.ts.map +0 -1
- package/timeline-item.d.ts +0 -227
- package/timeline-item.d.ts.map +0 -1
- package/to-json-schema.d.ts +0 -96
- package/to-json-schema.d.ts.map +0 -1
- package/util.d.ts +0 -45
- package/util.d.ts.map +0 -1
- package/versions.d.ts +0 -9
- package/versions.d.ts.map +0 -1
- package/zod-extensions.d.ts +0 -39
- package/zod-extensions.d.ts.map +0 -1
|
@@ -35,7 +35,7 @@ function TimelineMessageItem({ item, isLast = false, isSentByViewer = false }) {
|
|
|
35
35
|
className: cn("flex w-full min-w-0 flex-1 flex-col gap-1", isSentByViewerFinal && "items-end"),
|
|
36
36
|
children: [
|
|
37
37
|
hasText && /* @__PURE__ */ jsx(TimelineItemContent, {
|
|
38
|
-
className: cn("block min-w-0 max-w-[300px]
|
|
38
|
+
className: cn("block min-w-0 max-w-[300px] break-words rounded-lg px-3.5 py-2.5 text-sm", {
|
|
39
39
|
"bg-co-background-300 text-co-foreground dark:bg-co-background-600": !isSentByViewerFinal,
|
|
40
40
|
"bg-co-primary text-co-primary-foreground": isSentByViewerFinal,
|
|
41
41
|
"rounded-br-sm": isLast && isSentByViewerFinal && !hasAttachments,
|
|
@@ -51,7 +51,7 @@ function TimelineMessageItem({ item, isLast = false, isSentByViewer = false }) {
|
|
|
51
51
|
onClick: () => openLightbox(index),
|
|
52
52
|
type: "button",
|
|
53
53
|
children: /* @__PURE__ */ jsx("img", {
|
|
54
|
-
alt: image.
|
|
54
|
+
alt: image.filename || `Image ${index + 1}`,
|
|
55
55
|
className: "max-h-[150px] max-w-[200px] cursor-pointer rounded-lg object-cover transition-transform group-hover:scale-105",
|
|
56
56
|
loading: "lazy",
|
|
57
57
|
src: image.url
|
|
@@ -65,7 +65,7 @@ function TimelineMessageItem({ item, isLast = false, isSentByViewer = false }) {
|
|
|
65
65
|
"bg-co-background-300 text-co-foreground hover:bg-co-background-400 dark:bg-co-background-600 dark:hover:bg-co-background-500": !isSentByViewerFinal,
|
|
66
66
|
"bg-co-primary/80 text-co-primary-foreground hover:bg-co-primary": isSentByViewerFinal
|
|
67
67
|
}),
|
|
68
|
-
download: file.
|
|
68
|
+
download: file.filename,
|
|
69
69
|
href: file.url,
|
|
70
70
|
rel: "noopener noreferrer",
|
|
71
71
|
target: "_blank",
|
|
@@ -76,7 +76,7 @@ function TimelineMessageItem({ item, isLast = false, isSentByViewer = false }) {
|
|
|
76
76
|
}),
|
|
77
77
|
/* @__PURE__ */ jsx("span", {
|
|
78
78
|
className: "flex-1 truncate font-medium",
|
|
79
|
-
children: file.
|
|
79
|
+
children: file.filename || "Download file"
|
|
80
80
|
}),
|
|
81
81
|
file.size && /* @__PURE__ */ jsx("span", {
|
|
82
82
|
className: "text-co-muted-foreground opacity-70",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeline-message-item.js","names":["PrimitiveTimelineItem","Icon"],"sources":["../../../src/support/components/timeline-message-item.tsx"],"sourcesContent":["import { formatFileSize } from \"@cossistant/core\";\nimport type { TimelineItem } from \"@cossistant/types/api/timeline-item\";\nimport type React from \"react\";\nimport { useState } from \"react\";\nimport {\n\tTimelineItem as PrimitiveTimelineItem,\n\tTimelineItemContent,\n\tTimelineItemTimestamp,\n} from \"../../primitives/timeline-item\";\nimport {\n\textractFileParts,\n\textractImageParts,\n} from \"../../primitives/timeline-item-attachments\";\nimport { useSupportText } from \"../text\";\nimport { cn } from \"../utils\";\nimport Icon from \"./icons\";\nimport { ImageLightbox } from \"./image-lightbox\";\n\nexport type TimelineMessageItemProps = {\n\titem: TimelineItem;\n\tisLast?: boolean;\n\tisSentByViewer?: boolean;\n};\n\n/**\n * Message bubble renderer that adapts layout depending on whether the visitor\n * or an agent sent the message.\n */\nexport function TimelineMessageItem({\n\titem,\n\tisLast = false,\n\tisSentByViewer = false,\n}: TimelineMessageItemProps): React.ReactElement {\n\tconst text = useSupportText();\n\tconst [lightboxOpen, setLightboxOpen] = useState(false);\n\tconst [lightboxIndex, setLightboxIndex] = useState(0);\n\n\t// Extract image and file parts\n\tconst images = extractImageParts(item.parts);\n\tconst files = extractFileParts(item.parts);\n\tconst hasAttachments = images.length > 0 || files.length > 0;\n\tconst hasText = item.text && item.text.trim().length > 0;\n\n\tconst openLightbox = (index: number) => {\n\t\tsetLightboxIndex(index);\n\t\tsetLightboxOpen(true);\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<PrimitiveTimelineItem item={item}>\n\t\t\t\t{({ isAI, timestamp }) => {\n\t\t\t\t\t// isSentByViewer defaults to false, meaning messages are treated as received\n\t\t\t\t\t// (left side with background) unless explicitly marked as sent by viewer\n\t\t\t\t\tconst isSentByViewerFinal = isSentByViewer;\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"flex w-full gap-2\",\n\t\t\t\t\t\t\t\tisSentByViewerFinal && \"flex-row-reverse\",\n\t\t\t\t\t\t\t\t!isSentByViewerFinal && \"flex-row\"\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\"flex w-full min-w-0 flex-1 flex-col gap-1\",\n\t\t\t\t\t\t\t\t\tisSentByViewerFinal && \"items-end\"\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{/* Text content */}\n\t\t\t\t\t\t\t\t{hasText && (\n\t\t\t\t\t\t\t\t\t<TimelineItemContent\n\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\"block min-w-0 max-w-[300px]
|
|
1
|
+
{"version":3,"file":"timeline-message-item.js","names":["PrimitiveTimelineItem","Icon"],"sources":["../../../src/support/components/timeline-message-item.tsx"],"sourcesContent":["import { formatFileSize } from \"@cossistant/core\";\nimport type { TimelineItem } from \"@cossistant/types/api/timeline-item\";\nimport type React from \"react\";\nimport { useState } from \"react\";\nimport {\n\tTimelineItem as PrimitiveTimelineItem,\n\tTimelineItemContent,\n\tTimelineItemTimestamp,\n} from \"../../primitives/timeline-item\";\nimport {\n\textractFileParts,\n\textractImageParts,\n} from \"../../primitives/timeline-item-attachments\";\nimport { useSupportText } from \"../text\";\nimport { cn } from \"../utils\";\nimport Icon from \"./icons\";\nimport { ImageLightbox } from \"./image-lightbox\";\n\nexport type TimelineMessageItemProps = {\n\titem: TimelineItem;\n\tisLast?: boolean;\n\tisSentByViewer?: boolean;\n};\n\n/**\n * Message bubble renderer that adapts layout depending on whether the visitor\n * or an agent sent the message.\n */\nexport function TimelineMessageItem({\n\titem,\n\tisLast = false,\n\tisSentByViewer = false,\n}: TimelineMessageItemProps): React.ReactElement {\n\tconst text = useSupportText();\n\tconst [lightboxOpen, setLightboxOpen] = useState(false);\n\tconst [lightboxIndex, setLightboxIndex] = useState(0);\n\n\t// Extract image and file parts\n\tconst images = extractImageParts(item.parts);\n\tconst files = extractFileParts(item.parts);\n\tconst hasAttachments = images.length > 0 || files.length > 0;\n\tconst hasText = item.text && item.text.trim().length > 0;\n\n\tconst openLightbox = (index: number) => {\n\t\tsetLightboxIndex(index);\n\t\tsetLightboxOpen(true);\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<PrimitiveTimelineItem item={item}>\n\t\t\t\t{({ isAI, timestamp }) => {\n\t\t\t\t\t// isSentByViewer defaults to false, meaning messages are treated as received\n\t\t\t\t\t// (left side with background) unless explicitly marked as sent by viewer\n\t\t\t\t\tconst isSentByViewerFinal = isSentByViewer;\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"flex w-full gap-2\",\n\t\t\t\t\t\t\t\tisSentByViewerFinal && \"flex-row-reverse\",\n\t\t\t\t\t\t\t\t!isSentByViewerFinal && \"flex-row\"\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\"flex w-full min-w-0 flex-1 flex-col gap-1\",\n\t\t\t\t\t\t\t\t\tisSentByViewerFinal && \"items-end\"\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{/* Text content */}\n\t\t\t\t\t\t\t\t{hasText && (\n\t\t\t\t\t\t\t\t\t<TimelineItemContent\n\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\"block min-w-0 max-w-[300px] break-words rounded-lg px-3.5 py-2.5 text-sm\",\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\"bg-co-background-300 text-co-foreground dark:bg-co-background-600\":\n\t\t\t\t\t\t\t\t\t\t\t\t\t!isSentByViewerFinal,\n\t\t\t\t\t\t\t\t\t\t\t\t\"bg-co-primary text-co-primary-foreground\":\n\t\t\t\t\t\t\t\t\t\t\t\t\tisSentByViewerFinal,\n\t\t\t\t\t\t\t\t\t\t\t\t\"rounded-br-sm\":\n\t\t\t\t\t\t\t\t\t\t\t\t\tisLast && isSentByViewerFinal && !hasAttachments,\n\t\t\t\t\t\t\t\t\t\t\t\t\"rounded-bl-sm\":\n\t\t\t\t\t\t\t\t\t\t\t\t\tisLast && !isSentByViewerFinal && !hasAttachments,\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\trenderMarkdown\n\t\t\t\t\t\t\t\t\t\ttext={item.text}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t{/* Image attachments */}\n\t\t\t\t\t\t\t\t{images.length > 0 && (\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\"flex flex-wrap gap-2\",\n\t\t\t\t\t\t\t\t\t\t\tisSentByViewerFinal && \"justify-end\"\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{images.map((image, index) => (\n\t\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"group relative overflow-hidden rounded-lg focus:outline-none focus:ring-2 focus:ring-co-primary/50\"\n\t\t\t\t\t\t\t\t\t\t\t\tkey={image.url}\n\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => openLightbox(index)}\n\t\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{/* biome-ignore lint/performance/noImgElement: React package, not Next.js specific */}\n\t\t\t\t\t\t\t\t\t\t\t\t{/* biome-ignore lint/nursery/useImageSize: Dynamic image dimensions not known at render time */}\n\t\t\t\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\t\t\t\talt={image.filename || `Image ${index + 1}`}\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"max-h-[150px] max-w-[200px] cursor-pointer rounded-lg object-cover transition-transform group-hover:scale-105\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tloading=\"lazy\"\n\t\t\t\t\t\t\t\t\t\t\t\t\tsrc={image.url}\n\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t{/* File attachments */}\n\t\t\t\t\t\t\t\t{files.length > 0 && (\n\t\t\t\t\t\t\t\t\t<div className=\"flex flex-col gap-1\">\n\t\t\t\t\t\t\t\t\t\t{files.map((file) => (\n\t\t\t\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"flex items-center gap-2 rounded-lg px-3 py-2 text-xs transition-colors\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"bg-co-background-300 text-co-foreground hover:bg-co-background-400 dark:bg-co-background-600 dark:hover:bg-co-background-500\":\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t!isSentByViewerFinal,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"bg-co-primary/80 text-co-primary-foreground hover:bg-co-primary\":\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tisSentByViewerFinal,\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\tdownload={file.filename}\n\t\t\t\t\t\t\t\t\t\t\t\thref={file.url}\n\t\t\t\t\t\t\t\t\t\t\t\tkey={file.url}\n\t\t\t\t\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t<Icon className=\"h-4 w-4 shrink-0\" name=\"file\" />\n\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"flex-1 truncate font-medium\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t{file.filename || \"Download file\"}\n\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t{file.size && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-co-muted-foreground opacity-70\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{formatFileSize(file.size)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t{isLast && (\n\t\t\t\t\t\t\t\t\t<TimelineItemTimestamp\n\t\t\t\t\t\t\t\t\t\tclassName=\"px-1 text-co-muted-foreground text-xs\"\n\t\t\t\t\t\t\t\t\t\ttimestamp={timestamp}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{() => (\n\t\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t\t{timestamp.toLocaleTimeString([], {\n\t\t\t\t\t\t\t\t\t\t\t\t\thour: \"2-digit\",\n\t\t\t\t\t\t\t\t\t\t\t\t\tminute: \"2-digit\",\n\t\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t\t\t{isAI &&\n\t\t\t\t\t\t\t\t\t\t\t\t\t` ${text(\"component.message.timestamp.aiIndicator\")}`}\n\t\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</TimelineItemTimestamp>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t}}\n\t\t\t</PrimitiveTimelineItem>\n\n\t\t\t{/* Lightbox for images */}\n\t\t\t{images.length > 0 && (\n\t\t\t\t<ImageLightbox\n\t\t\t\t\timages={images}\n\t\t\t\t\tinitialIndex={lightboxIndex}\n\t\t\t\t\tisOpen={lightboxOpen}\n\t\t\t\t\tonClose={() => setLightboxOpen(false)}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t);\n}\n"],"mappings":";;;;;;;;;;;;;;;AA4BA,SAAgB,oBAAoB,EACnC,MACA,SAAS,OACT,iBAAiB,SAC+B;CAChD,MAAM,OAAO,gBAAgB;CAC7B,MAAM,CAAC,cAAc,mBAAmB,SAAS,MAAM;CACvD,MAAM,CAAC,eAAe,oBAAoB,SAAS,EAAE;CAGrD,MAAM,SAAS,kBAAkB,KAAK,MAAM;CAC5C,MAAM,QAAQ,iBAAiB,KAAK,MAAM;CAC1C,MAAM,iBAAiB,OAAO,SAAS,KAAK,MAAM,SAAS;CAC3D,MAAM,UAAU,KAAK,QAAQ,KAAK,KAAK,MAAM,CAAC,SAAS;CAEvD,MAAM,gBAAgB,UAAkB;AACvC,mBAAiB,MAAM;AACvB,kBAAgB,KAAK;;AAGtB,QACC,4CACC,oBAACA;EAA4B;aAC1B,EAAE,MAAM,gBAAgB;GAGzB,MAAM,sBAAsB;AAE5B,UACC,oBAAC;IACA,WAAW,GACV,qBACA,uBAAuB,oBACvB,CAAC,uBAAuB,WACxB;cAED,qBAAC;KACA,WAAW,GACV,6CACA,uBAAuB,YACvB;;MAGA,WACA,oBAAC;OACA,WAAW,GACV,4EACA;QACC,qEACC,CAAC;QACF,4CACC;QACD,iBACC,UAAU,uBAAuB,CAAC;QACnC,iBACC,UAAU,CAAC,uBAAuB,CAAC;QACpC,CACD;OACD;OACA,MAAM,KAAK;QACV;MAIF,OAAO,SAAS,KAChB,oBAAC;OACA,WAAW,GACV,wBACA,uBAAuB,cACvB;iBAEA,OAAO,KAAK,OAAO,UACnB,oBAAC;QACA,WAAU;QAEV,eAAe,aAAa,MAAM;QAClC,MAAK;kBAIL,oBAAC;SACA,KAAK,MAAM,YAAY,SAAS,QAAQ;SACxC,WAAU;SACV,SAAQ;SACR,KAAK,MAAM;UACV;UAXG,MAAM,IAYH,CACR;QACG;MAIN,MAAM,SAAS,KACf,oBAAC;OAAI,WAAU;iBACb,MAAM,KAAK,SACX,qBAAC;QACA,WAAW,GACV,0EACA;SACC,gIACC,CAAC;SACF,mEACC;SACD,CACD;QACD,UAAU,KAAK;QACf,MAAM,KAAK;QAEX,KAAI;QACJ,QAAO;;SAEP,oBAACC;UAAK,WAAU;UAAmB,MAAK;WAAS;SACjD,oBAAC;UAAK,WAAU;oBACd,KAAK,YAAY;WACZ;SACN,KAAK,QACL,oBAAC;UAAK,WAAU;oBACd,eAAe,KAAK,KAAK;WACpB;;UAXH,KAAK,IAaP,CACH;QACG;MAGN,UACA,oBAAC;OACA,WAAU;OACC;uBAGV,4CACE,UAAU,mBAAmB,EAAE,EAAE;QACjC,MAAM;QACN,QAAQ;QACR,CAAC,EACD,QACA,IAAI,KAAK,0CAA0C,MAClD;QAEmB;;MAEpB;KACD;;GAGe,EAGvB,OAAO,SAAS,KAChB,oBAAC;EACQ;EACR,cAAc;EACd,QAAQ;EACR,eAAe,gBAAgB,MAAM;GACpC,IAED"}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
import { cn } from "../utils/index.js";
|
|
5
4
|
import { BouncingDots } from "./typing-indicator.js";
|
|
6
5
|
import { SupportTrigger } from "../../primitives/trigger.js";
|
|
6
|
+
import icons_default from "./icons.js";
|
|
7
7
|
import { useNewMessageSound } from "../../hooks/use-new-message-sound.js";
|
|
8
8
|
import { useTypingSound } from "../../hooks/use-typing-sound.js";
|
|
9
|
-
import icons_default from "./icons.js";
|
|
10
9
|
import * as React$1 from "react";
|
|
11
10
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
12
11
|
import { AnimatePresence, motion } from "motion/react";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trigger.js","names":["TriggerContent: React.FC<TriggerContentProps>","React","Icon","DefaultTrigger: React.FC<DefaultTriggerProps>","Primitive.Trigger"],"sources":["../../../src/support/components/trigger.tsx"],"sourcesContent":["\"use client\";\n\nimport { AnimatePresence, motion } from \"motion/react\";\nimport * as React from \"react\";\nimport { useNewMessageSound } from \"../../hooks/use-new-message-sound\";\nimport { useTypingSound } from \"../../hooks/use-typing-sound\";\nimport * as Primitive from \"../../primitives\";\nimport type { TriggerRenderProps } from \"../types\";\nimport { cn } from \"../utils\";\nimport Icon from \"./icons\";\nimport { BouncingDots } from \"./typing-indicator\";\n\ntype TriggerContentProps = {\n\tisOpen: boolean;\n\tunreadCount: number;\n\tisTyping: boolean;\n};\n\nconst TriggerContent: React.FC<TriggerContentProps> = ({\n\tisOpen,\n\tunreadCount,\n\tisTyping,\n}) => {\n\tconst playNewMessageSound = useNewMessageSound({\n\t\tvolume: 0.7,\n\t\tplaybackRate: 1.0,\n\t});\n\tconst previousUnreadCountRef = React.useRef(0);\n\n\tuseTypingSound(!isOpen && isTyping, {\n\t\tvolume: 1,\n\t\tplaybackRate: 1.3,\n\t});\n\n\tReact.useEffect(() => {\n\t\tif (unreadCount > previousUnreadCountRef.current) {\n\t\t\tplayNewMessageSound();\n\t\t}\n\t\tpreviousUnreadCountRef.current = unreadCount;\n\t}, [unreadCount, playNewMessageSound]);\n\n\treturn (\n\t\t<>\n\t\t\t<AnimatePresence mode=\"wait\">\n\t\t\t\t{isOpen ? (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tanimate={{\n\t\t\t\t\t\t\tscale: 1,\n\t\t\t\t\t\t\trotate: 0,\n\t\t\t\t\t\t\topacity: 1,\n\t\t\t\t\t\t\ttransition: { duration: 0.2, ease: \"easeOut\" },\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName=\"flex items-center justify-center\"\n\t\t\t\t\t\texit={{\n\t\t\t\t\t\t\tscale: 0.9,\n\t\t\t\t\t\t\trotate: -45,\n\t\t\t\t\t\t\topacity: 0,\n\t\t\t\t\t\t\ttransition: { duration: 0.1, ease: \"easeIn\" },\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tinitial={{ scale: 0.9, rotate: 45, opacity: 0 }}\n\t\t\t\t\t\tkey=\"chevron\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Icon className=\"size-5\" name=\"chevron-down\" />\n\t\t\t\t\t</motion.div>\n\t\t\t\t) : isTyping ? (\n\t\t\t\t\t<motion.span\n\t\t\t\t\t\tanimate={{\n\t\t\t\t\t\t\topacity: 1,\n\t\t\t\t\t\t\tscale: 1,\n\t\t\t\t\t\t\ttransition: {\n\t\t\t\t\t\t\t\tduration: 0.2,\n\t\t\t\t\t\t\t\tease: \"easeOut\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName=\"pointer-events-none flex items-center rounded-full text-co-primary\"\n\t\t\t\t\t\texit={{\n\t\t\t\t\t\t\topacity: 0,\n\t\t\t\t\t\t\tscale: 0.9,\n\t\t\t\t\t\t\ttransition: {\n\t\t\t\t\t\t\t\tduration: 0.1,\n\t\t\t\t\t\t\t\tease: \"easeIn\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tinitial={{ opacity: 0, scale: 0.9 }}\n\t\t\t\t\t\tkey=\"typing-indicator\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<BouncingDots className=\"bg-co-primary-foreground\" />\n\t\t\t\t\t</motion.span>\n\t\t\t\t) : (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tanimate={{\n\t\t\t\t\t\t\tscale: 1,\n\t\t\t\t\t\t\trotate: 0,\n\t\t\t\t\t\t\topacity: 1,\n\t\t\t\t\t\t\ttransition: { duration: 0.2, ease: \"easeOut\" },\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName=\"flex items-center justify-center\"\n\t\t\t\t\t\texit={{\n\t\t\t\t\t\t\tscale: 0.9,\n\t\t\t\t\t\t\trotate: 45,\n\t\t\t\t\t\t\topacity: 0,\n\t\t\t\t\t\t\ttransition: { duration: 0.1, ease: \"easeIn\" },\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tinitial={{ scale: 0.9, rotate: -45, opacity: 0 }}\n\t\t\t\t\t\tkey=\"chat\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Icon className=\"size-6.5\" name=\"chat\" variant=\"filled\" />\n\t\t\t\t\t</motion.div>\n\t\t\t\t)}\n\t\t\t</AnimatePresence>\n\n\t\t\t{unreadCount > 0 && (\n\t\t\t\t<motion.div\n\t\t\t\t\tanimate={{ scale: 1, opacity: 1 }}\n\t\t\t\t\tclassName=\"absolute top-0.5 right-0.5 flex size-2 items-center justify-center rounded-full bg-co-destructive font-medium text-[10px] text-co-destructive-foreground text-white text-xs\"\n\t\t\t\t\texit={{ scale: 0, opacity: 0 }}\n\t\t\t\t\tinitial={{ scale: 0, opacity: 0 }}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t);\n};\n\nexport type DefaultTriggerProps = {\n\tclassName?: string;\n};\n\n/**\n * Default styled trigger button.\n * Used internally when no custom trigger is provided.\n */\nexport const DefaultTrigger: React.FC<DefaultTriggerProps> = ({\n\tclassName,\n}) => (\n\t<Primitive.Trigger asChild>\n\t\t{({ isOpen, unreadCount, isTyping }: TriggerRenderProps) => (\n\t\t\t<motion.button\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"relative z-[9999] flex size-14 cursor-pointer items-center justify-center rounded-full bg-co-primary text-co-primary-foreground transition-colors hover:bg-co-primary/90 data-[open=true]:bg-co-primary/90\",\n\t\t\t\t\tclassName\n\t\t\t\t)}\n\t\t\t\tdata-open={isOpen}\n\t\t\t\ttransition={{\n\t\t\t\t\ttype: \"spring\",\n\t\t\t\t\tstiffness: 800,\n\t\t\t\t\tdamping: 17,\n\t\t\t\t}}\n\t\t\t\ttype=\"button\"\n\t\t\t\twhileTap={{ scale: 0.95 }}\n\t\t\t>\n\t\t\t\t<TriggerContent\n\t\t\t\t\tisOpen={isOpen}\n\t\t\t\t\tisTyping={isTyping}\n\t\t\t\t\tunreadCount={unreadCount}\n\t\t\t\t/>\n\t\t\t</motion.button>\n\t\t)}\n\t</Primitive.Trigger>\n);\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"trigger.js","names":["TriggerContent: React.FC<TriggerContentProps>","React","Icon","DefaultTrigger: React.FC<DefaultTriggerProps>","Primitive.Trigger"],"sources":["../../../src/support/components/trigger.tsx"],"sourcesContent":["\"use client\";\n\nimport { AnimatePresence, motion } from \"motion/react\";\nimport * as React from \"react\";\nimport { useNewMessageSound } from \"../../hooks/use-new-message-sound\";\nimport { useTypingSound } from \"../../hooks/use-typing-sound\";\nimport * as Primitive from \"../../primitives\";\nimport type { TriggerRenderProps } from \"../types\";\nimport { cn } from \"../utils\";\nimport Icon from \"./icons\";\nimport { BouncingDots } from \"./typing-indicator\";\n\ntype TriggerContentProps = {\n\tisOpen: boolean;\n\tunreadCount: number;\n\tisTyping: boolean;\n};\n\nconst TriggerContent: React.FC<TriggerContentProps> = ({\n\tisOpen,\n\tunreadCount,\n\tisTyping,\n}) => {\n\tconst playNewMessageSound = useNewMessageSound({\n\t\tvolume: 0.7,\n\t\tplaybackRate: 1.0,\n\t});\n\tconst previousUnreadCountRef = React.useRef(0);\n\n\tuseTypingSound(!isOpen && isTyping, {\n\t\tvolume: 1,\n\t\tplaybackRate: 1.3,\n\t});\n\n\tReact.useEffect(() => {\n\t\tif (unreadCount > previousUnreadCountRef.current) {\n\t\t\tplayNewMessageSound();\n\t\t}\n\t\tpreviousUnreadCountRef.current = unreadCount;\n\t}, [unreadCount, playNewMessageSound]);\n\n\treturn (\n\t\t<>\n\t\t\t<AnimatePresence mode=\"wait\">\n\t\t\t\t{isOpen ? (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tanimate={{\n\t\t\t\t\t\t\tscale: 1,\n\t\t\t\t\t\t\trotate: 0,\n\t\t\t\t\t\t\topacity: 1,\n\t\t\t\t\t\t\ttransition: { duration: 0.2, ease: \"easeOut\" },\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName=\"flex items-center justify-center\"\n\t\t\t\t\t\texit={{\n\t\t\t\t\t\t\tscale: 0.9,\n\t\t\t\t\t\t\trotate: -45,\n\t\t\t\t\t\t\topacity: 0,\n\t\t\t\t\t\t\ttransition: { duration: 0.1, ease: \"easeIn\" },\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tinitial={{ scale: 0.9, rotate: 45, opacity: 0 }}\n\t\t\t\t\t\tkey=\"chevron\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Icon className=\"size-5\" name=\"chevron-down\" />\n\t\t\t\t\t</motion.div>\n\t\t\t\t) : isTyping ? (\n\t\t\t\t\t<motion.span\n\t\t\t\t\t\tanimate={{\n\t\t\t\t\t\t\topacity: 1,\n\t\t\t\t\t\t\tscale: 1,\n\t\t\t\t\t\t\ttransition: {\n\t\t\t\t\t\t\t\tduration: 0.2,\n\t\t\t\t\t\t\t\tease: \"easeOut\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName=\"pointer-events-none flex items-center rounded-full text-co-primary\"\n\t\t\t\t\t\texit={{\n\t\t\t\t\t\t\topacity: 0,\n\t\t\t\t\t\t\tscale: 0.9,\n\t\t\t\t\t\t\ttransition: {\n\t\t\t\t\t\t\t\tduration: 0.1,\n\t\t\t\t\t\t\t\tease: \"easeIn\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tinitial={{ opacity: 0, scale: 0.9 }}\n\t\t\t\t\t\tkey=\"typing-indicator\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<BouncingDots className=\"bg-co-primary-foreground\" />\n\t\t\t\t\t</motion.span>\n\t\t\t\t) : (\n\t\t\t\t\t<motion.div\n\t\t\t\t\t\tanimate={{\n\t\t\t\t\t\t\tscale: 1,\n\t\t\t\t\t\t\trotate: 0,\n\t\t\t\t\t\t\topacity: 1,\n\t\t\t\t\t\t\ttransition: { duration: 0.2, ease: \"easeOut\" },\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName=\"flex items-center justify-center\"\n\t\t\t\t\t\texit={{\n\t\t\t\t\t\t\tscale: 0.9,\n\t\t\t\t\t\t\trotate: 45,\n\t\t\t\t\t\t\topacity: 0,\n\t\t\t\t\t\t\ttransition: { duration: 0.1, ease: \"easeIn\" },\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tinitial={{ scale: 0.9, rotate: -45, opacity: 0 }}\n\t\t\t\t\t\tkey=\"chat\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<Icon className=\"size-6.5\" name=\"chat\" variant=\"filled\" />\n\t\t\t\t\t</motion.div>\n\t\t\t\t)}\n\t\t\t</AnimatePresence>\n\n\t\t\t{unreadCount > 0 && (\n\t\t\t\t<motion.div\n\t\t\t\t\tanimate={{ scale: 1, opacity: 1 }}\n\t\t\t\t\tclassName=\"absolute top-0.5 right-0.5 flex size-2 items-center justify-center rounded-full bg-co-destructive font-medium text-[10px] text-co-destructive-foreground text-white text-xs\"\n\t\t\t\t\texit={{ scale: 0, opacity: 0 }}\n\t\t\t\t\tinitial={{ scale: 0, opacity: 0 }}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</>\n\t);\n};\n\nexport type DefaultTriggerProps = {\n\tclassName?: string;\n};\n\n/**\n * Default styled trigger button.\n * Used internally when no custom trigger is provided.\n */\nexport const DefaultTrigger: React.FC<DefaultTriggerProps> = ({\n\tclassName,\n}) => (\n\t<Primitive.Trigger asChild>\n\t\t{({ isOpen, unreadCount, isTyping }: TriggerRenderProps) => (\n\t\t\t<motion.button\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"relative z-[9999] flex size-14 cursor-pointer items-center justify-center rounded-full bg-co-primary text-co-primary-foreground transition-colors hover:bg-co-primary/90 data-[open=true]:bg-co-primary/90\",\n\t\t\t\t\tclassName\n\t\t\t\t)}\n\t\t\t\tdata-open={isOpen}\n\t\t\t\ttransition={{\n\t\t\t\t\ttype: \"spring\",\n\t\t\t\t\tstiffness: 800,\n\t\t\t\t\tdamping: 17,\n\t\t\t\t}}\n\t\t\t\ttype=\"button\"\n\t\t\t\twhileTap={{ scale: 0.95 }}\n\t\t\t>\n\t\t\t\t<TriggerContent\n\t\t\t\t\tisOpen={isOpen}\n\t\t\t\t\tisTyping={isTyping}\n\t\t\t\t\tunreadCount={unreadCount}\n\t\t\t\t/>\n\t\t\t</motion.button>\n\t\t)}\n\t</Primitive.Trigger>\n);\n"],"mappings":";;;;;;;;;;;;;AAkBA,MAAMA,kBAAiD,EACtD,QACA,aACA,eACK;CACL,MAAM,sBAAsB,mBAAmB;EAC9C,QAAQ;EACR,cAAc;EACd,CAAC;CACF,MAAM,yBAAyBC,QAAM,OAAO,EAAE;AAE9C,gBAAe,CAAC,UAAU,UAAU;EACnC,QAAQ;EACR,cAAc;EACd,CAAC;AAEF,SAAM,gBAAgB;AACrB,MAAI,cAAc,uBAAuB,QACxC,sBAAqB;AAEtB,yBAAuB,UAAU;IAC/B,CAAC,aAAa,oBAAoB,CAAC;AAEtC,QACC,4CACC,oBAAC;EAAgB,MAAK;YACpB,SACA,oBAAC,OAAO;GACP,SAAS;IACR,OAAO;IACP,QAAQ;IACR,SAAS;IACT,YAAY;KAAE,UAAU;KAAK,MAAM;KAAW;IAC9C;GACD,WAAU;GACV,MAAM;IACL,OAAO;IACP,QAAQ;IACR,SAAS;IACT,YAAY;KAAE,UAAU;KAAK,MAAM;KAAU;IAC7C;GACD,SAAS;IAAE,OAAO;IAAK,QAAQ;IAAI,SAAS;IAAG;aAG/C,oBAACC;IAAK,WAAU;IAAS,MAAK;KAAiB;KAF3C,UAGQ,GACV,WACH,oBAAC,OAAO;GACP,SAAS;IACR,SAAS;IACT,OAAO;IACP,YAAY;KACX,UAAU;KACV,MAAM;KACN;IACD;GACD,WAAU;GACV,MAAM;IACL,SAAS;IACT,OAAO;IACP,YAAY;KACX,UAAU;KACV,MAAM;KACN;IACD;GACD,SAAS;IAAE,SAAS;IAAG,OAAO;IAAK;aAGnC,oBAAC,gBAAa,WAAU,6BAA6B;KAFjD,mBAGS,GAEd,oBAAC,OAAO;GACP,SAAS;IACR,OAAO;IACP,QAAQ;IACR,SAAS;IACT,YAAY;KAAE,UAAU;KAAK,MAAM;KAAW;IAC9C;GACD,WAAU;GACV,MAAM;IACL,OAAO;IACP,QAAQ;IACR,SAAS;IACT,YAAY;KAAE,UAAU;KAAK,MAAM;KAAU;IAC7C;GACD,SAAS;IAAE,OAAO;IAAK,QAAQ;IAAK,SAAS;IAAG;aAGhD,oBAACA;IAAK,WAAU;IAAW,MAAK;IAAO,SAAQ;KAAW;KAFtD,OAGQ;GAEG,EAEjB,cAAc,KACd,oBAAC,OAAO;EACP,SAAS;GAAE,OAAO;GAAG,SAAS;GAAG;EACjC,WAAU;EACV,MAAM;GAAE,OAAO;GAAG,SAAS;GAAG;EAC9B,SAAS;GAAE,OAAO;GAAG,SAAS;GAAG;GAChC,IAED;;;;;;AAYL,MAAaC,kBAAiD,EAC7D,gBAEA,oBAACC;CAAkB;YAChB,EAAE,QAAQ,aAAa,eACxB,oBAAC,OAAO;EACP,WAAW,GACV,8MACA,UACA;EACD,aAAW;EACX,YAAY;GACX,MAAM;GACN,WAAW;GACX,SAAS;GACT;EACD,MAAK;EACL,UAAU,EAAE,OAAO,KAAM;YAEzB,oBAAC;GACQ;GACE;GACG;IACZ;GACa;EAEE"}
|
|
@@ -12,7 +12,7 @@ const BouncingDots = ({ className }) => /* @__PURE__ */ jsxs("div", {
|
|
|
12
12
|
/* @__PURE__ */ jsx("span", { className: cn("dot-bounce-3 size-1 rounded-full bg-co-primary", className) })
|
|
13
13
|
]
|
|
14
14
|
});
|
|
15
|
-
const TypingIndicator = React$1.forwardRef(({ participants, availableAIAgents = [], availableHumanAgents = [], withAvatars = true, className
|
|
15
|
+
const TypingIndicator = React$1.forwardRef(({ participants, availableAIAgents = [], availableHumanAgents = [], withAvatars = true, className, ...props }, ref) => {
|
|
16
16
|
if (!participants || participants.length === 0) return null;
|
|
17
17
|
const humanParticipantIds = participants.filter((p) => p.type === "team_member").map((p) => p.id);
|
|
18
18
|
const aiParticipantIds = participants.filter((p) => p.type === "ai").map((p) => p.id);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typing-indicator.js","names":["React"],"sources":["../../../src/support/components/typing-indicator.tsx"],"sourcesContent":["import type { AvailableAIAgent, AvailableHumanAgent } from \"@cossistant/types\";\nimport * as React from \"react\";\nimport { cn } from \"../utils\";\nimport { AvatarStack } from \"./avatar-stack\";\n\nexport type TypingParticipantType = \"visitor\" | \"team_member\" | \"ai\";\n\nexport type TypingParticipant = {\n\tid: string;\n\ttype: TypingParticipantType;\n};\n\nexport type TypingIndicatorProps = React.HTMLAttributes<HTMLDivElement> & {\n\tparticipants: TypingParticipant[];\n\tavailableAIAgents?: AvailableAIAgent[];\n\tavailableHumanAgents?: AvailableHumanAgent[];\n\twithAvatars?: boolean;\n};\n\nexport const BouncingDots = ({\n\tclassName,\n}: {\n\tclassName?: string;\n}): React.ReactElement => (\n\t<div className=\"flex gap-1\">\n\t\t<span\n\t\t\tclassName={cn(\n\t\t\t\t\"dot-bounce-1 size-1 rounded-full bg-co-primary\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t/>\n\t\t<span\n\t\t\tclassName={cn(\n\t\t\t\t\"dot-bounce-2 size-1 rounded-full bg-co-primary\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t/>\n\t\t<span\n\t\t\tclassName={cn(\n\t\t\t\t\"dot-bounce-3 size-1 rounded-full bg-co-primary\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t/>\n\t</div>\n);\n\nexport const TypingIndicator = React.forwardRef<\n\tHTMLDivElement,\n\tTypingIndicatorProps\n>(\n\t(\n\t\t{\n\t\t\tparticipants,\n\t\t\tavailableAIAgents = [],\n\t\t\tavailableHumanAgents = [],\n\t\t\twithAvatars = true,\n\t\t\tclassName,\n\t\t\t...props\n\t\t},\n\t\tref\n\t) => {\n\t\tif (!participants || participants.length === 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Separate AI and human participants\n\t\tconst humanParticipantIds = participants\n\t\t\t.filter((p) => p.type === \"team_member\")\n\t\t\t.map((p) => p.id);\n\n\t\tconst aiParticipantIds = participants\n\t\t\t.filter((p) => p.type === \"ai\")\n\t\t\t.map((p) => p.id);\n\n\t\t// Get matching agents\n\t\tconst typingHumanAgents = availableHumanAgents.filter((agent) =>\n\t\t\thumanParticipantIds.includes(agent.id)\n\t\t);\n\n\t\tconst typingAIAgents = availableAIAgents.filter((agent) =>\n\t\t\taiParticipantIds.includes(agent.id)\n\t\t);\n\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName={cn(\"flex items-center gap-6\", className)}\n\t\t\t\tref={ref}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{withAvatars && (\n\t\t\t\t\t<AvatarStack\n\t\t\t\t\t\taiAgents={typingAIAgents}\n\t\t\t\t\t\thideDefaultAIAgent={typingAIAgents.length === 0}\n\t\t\t\t\t\thumanAgents={typingHumanAgents}\n\t\t\t\t\t\tsize={24}\n\t\t\t\t\t\tspacing={16}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t<BouncingDots />\n\t\t\t</div>\n\t\t);\n\t}\n);\n\nTypingIndicator.displayName = \"TypingIndicator\";\n"],"mappings":";;;;;;AAmBA,MAAa,gBAAgB,EAC5B,gBAIA,qBAAC;CAAI,WAAU;;EACd,oBAAC,UACA,WAAW,GACV,kDACA,UACA,GACA;EACF,oBAAC,UACA,WAAW,GACV,kDACA,UACA,GACA;EACF,oBAAC,UACA,WAAW,GACV,kDACA,UACA,GACA;;EACG;AAGP,MAAa,kBAAkBA,QAAM,YAKnC,EACC,cACA,oBAAoB,EAAE,EACtB,uBAAuB,EAAE,EACzB,cAAc,MACd,
|
|
1
|
+
{"version":3,"file":"typing-indicator.js","names":["React"],"sources":["../../../src/support/components/typing-indicator.tsx"],"sourcesContent":["import type { AvailableAIAgent, AvailableHumanAgent } from \"@cossistant/types\";\nimport * as React from \"react\";\nimport { cn } from \"../utils\";\nimport { AvatarStack } from \"./avatar-stack\";\n\nexport type TypingParticipantType = \"visitor\" | \"team_member\" | \"ai\";\n\nexport type TypingParticipant = {\n\tid: string;\n\ttype: TypingParticipantType;\n};\n\nexport type TypingIndicatorProps = React.HTMLAttributes<HTMLDivElement> & {\n\tparticipants: TypingParticipant[];\n\tavailableAIAgents?: AvailableAIAgent[];\n\tavailableHumanAgents?: AvailableHumanAgent[];\n\twithAvatars?: boolean;\n};\n\nexport const BouncingDots = ({\n\tclassName,\n}: {\n\tclassName?: string;\n}): React.ReactElement => (\n\t<div className=\"flex gap-1\">\n\t\t<span\n\t\t\tclassName={cn(\n\t\t\t\t\"dot-bounce-1 size-1 rounded-full bg-co-primary\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t/>\n\t\t<span\n\t\t\tclassName={cn(\n\t\t\t\t\"dot-bounce-2 size-1 rounded-full bg-co-primary\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t/>\n\t\t<span\n\t\t\tclassName={cn(\n\t\t\t\t\"dot-bounce-3 size-1 rounded-full bg-co-primary\",\n\t\t\t\tclassName\n\t\t\t)}\n\t\t/>\n\t</div>\n);\n\nexport const TypingIndicator = React.forwardRef<\n\tHTMLDivElement,\n\tTypingIndicatorProps\n>(\n\t(\n\t\t{\n\t\t\tparticipants,\n\t\t\tavailableAIAgents = [],\n\t\t\tavailableHumanAgents = [],\n\t\t\twithAvatars = true,\n\t\t\tclassName,\n\t\t\t...props\n\t\t},\n\t\tref\n\t) => {\n\t\tif (!participants || participants.length === 0) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Separate AI and human participants\n\t\tconst humanParticipantIds = participants\n\t\t\t.filter((p) => p.type === \"team_member\")\n\t\t\t.map((p) => p.id);\n\n\t\tconst aiParticipantIds = participants\n\t\t\t.filter((p) => p.type === \"ai\")\n\t\t\t.map((p) => p.id);\n\n\t\t// Get matching agents\n\t\tconst typingHumanAgents = availableHumanAgents.filter((agent) =>\n\t\t\thumanParticipantIds.includes(agent.id)\n\t\t);\n\n\t\tconst typingAIAgents = availableAIAgents.filter((agent) =>\n\t\t\taiParticipantIds.includes(agent.id)\n\t\t);\n\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName={cn(\"flex items-center gap-6\", className)}\n\t\t\t\tref={ref}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{withAvatars && (\n\t\t\t\t\t<AvatarStack\n\t\t\t\t\t\taiAgents={typingAIAgents}\n\t\t\t\t\t\thideDefaultAIAgent={typingAIAgents.length === 0}\n\t\t\t\t\t\thumanAgents={typingHumanAgents}\n\t\t\t\t\t\tsize={24}\n\t\t\t\t\t\tspacing={16}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t<BouncingDots />\n\t\t\t</div>\n\t\t);\n\t}\n);\n\nTypingIndicator.displayName = \"TypingIndicator\";\n"],"mappings":";;;;;;AAmBA,MAAa,gBAAgB,EAC5B,gBAIA,qBAAC;CAAI,WAAU;;EACd,oBAAC,UACA,WAAW,GACV,kDACA,UACA,GACA;EACF,oBAAC,UACA,WAAW,GACV,kDACA,UACA,GACA;EACF,oBAAC,UACA,WAAW,GACV,kDACA,UACA,GACA;;EACG;AAGP,MAAa,kBAAkBA,QAAM,YAKnC,EACC,cACA,oBAAoB,EAAE,EACtB,uBAAuB,EAAE,EACzB,cAAc,MACd,WACA,GAAG,SAEJ,QACI;AACJ,KAAI,CAAC,gBAAgB,aAAa,WAAW,EAC5C,QAAO;CAIR,MAAM,sBAAsB,aAC1B,QAAQ,MAAM,EAAE,SAAS,cAAc,CACvC,KAAK,MAAM,EAAE,GAAG;CAElB,MAAM,mBAAmB,aACvB,QAAQ,MAAM,EAAE,SAAS,KAAK,CAC9B,KAAK,MAAM,EAAE,GAAG;CAGlB,MAAM,oBAAoB,qBAAqB,QAAQ,UACtD,oBAAoB,SAAS,MAAM,GAAG,CACtC;CAED,MAAM,iBAAiB,kBAAkB,QAAQ,UAChD,iBAAiB,SAAS,MAAM,GAAG,CACnC;AAED,QACC,qBAAC;EACA,WAAW,GAAG,2BAA2B,UAAU;EAC9C;EACL,GAAI;aAEH,eACA,oBAAC;GACA,UAAU;GACV,oBAAoB,eAAe,WAAW;GAC9C,aAAa;GACb,MAAM;GACN,SAAS;IACR,EAEH,oBAAC,iBAAe;GACX;EAGR;AAED,gBAAgB,cAAc"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controlled-state.js","names":["React","ControlledStateProvider: React.FC<\n\tControlledStateProviderProps\n>"],"sources":["../../../src/support/context/controlled-state.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\n/**\n * Controlled state context for the Support widget.\n * Allows external control of widget open/close state.\n */\nexport type ControlledStateContextValue = {\n\t/**\n\t * Controlled open state (undefined = uncontrolled)\n\t */\n\topen: boolean | undefined;\n\t/**\n\t * Callback when open state should change\n\t */\n\tonOpenChange: ((open: boolean) => void) | undefined;\n\t/**\n\t * Whether the component is in controlled mode\n\t */\n\tisControlled: boolean;\n};\n\nconst ControlledStateContext =\n\tReact.createContext<ControlledStateContextValue | null>(null);\n\nexport type ControlledStateProviderProps = {\n\t/**\n\t * Controlled open state\n\t */\n\topen?: boolean;\n\t/**\n\t * Callback when open state changes\n\t */\n\tonOpenChange?: (open: boolean) => void;\n\tchildren: React.ReactNode;\n};\n\n/**\n * Provider for controlled widget state.\n * Wraps the Support component to enable controlled mode.\n */\nexport const ControlledStateProvider: React.FC<\n\tControlledStateProviderProps\n> = ({ open, onOpenChange, children }) => {\n\tconst value = React.useMemo<ControlledStateContextValue>(\n\t\t() => ({\n\t\t\topen,\n\t\t\tonOpenChange,\n\t\t\tisControlled: open !== undefined,\n\t\t}),\n\t\t[open, onOpenChange]\n\t);\n\n\treturn (\n\t\t<ControlledStateContext.Provider value={value}>\n\t\t\t{children}\n\t\t</ControlledStateContext.Provider>\n\t);\n};\n\n/**\n * Access controlled state context.\n * Returns null if not inside a ControlledStateProvider.\n */\nexport function useControlledState(): ControlledStateContextValue | null {\n\treturn React.useContext(ControlledStateContext);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"controlled-state.js","names":["React","ControlledStateProvider: React.FC<\n\tControlledStateProviderProps\n>"],"sources":["../../../src/support/context/controlled-state.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\n/**\n * Controlled state context for the Support widget.\n * Allows external control of widget open/close state.\n */\nexport type ControlledStateContextValue = {\n\t/**\n\t * Controlled open state (undefined = uncontrolled)\n\t */\n\topen: boolean | undefined;\n\t/**\n\t * Callback when open state should change\n\t */\n\tonOpenChange: ((open: boolean) => void) | undefined;\n\t/**\n\t * Whether the component is in controlled mode\n\t */\n\tisControlled: boolean;\n};\n\nconst ControlledStateContext =\n\tReact.createContext<ControlledStateContextValue | null>(null);\n\nexport type ControlledStateProviderProps = {\n\t/**\n\t * Controlled open state\n\t */\n\topen?: boolean;\n\t/**\n\t * Callback when open state changes\n\t */\n\tonOpenChange?: (open: boolean) => void;\n\tchildren: React.ReactNode;\n};\n\n/**\n * Provider for controlled widget state.\n * Wraps the Support component to enable controlled mode.\n */\nexport const ControlledStateProvider: React.FC<\n\tControlledStateProviderProps\n> = ({ open, onOpenChange, children }) => {\n\tconst value = React.useMemo<ControlledStateContextValue>(\n\t\t() => ({\n\t\t\topen,\n\t\t\tonOpenChange,\n\t\t\tisControlled: open !== undefined,\n\t\t}),\n\t\t[open, onOpenChange]\n\t);\n\n\treturn (\n\t\t<ControlledStateContext.Provider value={value}>\n\t\t\t{children}\n\t\t</ControlledStateContext.Provider>\n\t);\n};\n\n/**\n * Access controlled state context.\n * Returns null if not inside a ControlledStateProvider.\n */\nexport function useControlledState(): ControlledStateContextValue | null {\n\treturn React.useContext(ControlledStateContext);\n}\n"],"mappings":";;;;;;AAuBA,MAAM,yBACLA,QAAM,cAAkD,KAAK;;;;;AAkB9D,MAAaC,2BAER,EAAE,MAAM,cAAc,eAAe;CACzC,MAAM,QAAQD,QAAM,eACZ;EACN;EACA;EACA,cAAc,SAAS;EACvB,GACD,CAAC,MAAM,aAAa,CACpB;AAED,QACC,oBAAC,uBAAuB;EAAgB;EACtC;GACgC;;;;;;AAQpC,SAAgB,qBAAyD;AACxE,QAAOA,QAAM,WAAW,uBAAuB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.js","names":["React","SupportEventsProvider: React.FC<SupportEventsProviderProps>"],"sources":["../../../src/support/context/events.tsx"],"sourcesContent":["\"use client\";\n\nimport type { Conversation } from \"@cossistant/types\";\nimport type { TimelineItem } from \"@cossistant/types/api/timeline-item\";\nimport * as React from \"react\";\n\n// =============================================================================\n// Event Types\n// =============================================================================\n\nexport type SupportEventType =\n\t| \"conversationStart\"\n\t| \"conversationEnd\"\n\t| \"messageSent\"\n\t| \"messageReceived\"\n\t| \"error\";\n\nexport type ConversationStartEvent = {\n\ttype: \"conversationStart\";\n\tconversationId: string;\n\tconversation?: Conversation;\n};\n\nexport type ConversationEndEvent = {\n\ttype: \"conversationEnd\";\n\tconversationId: string;\n\tconversation?: Conversation;\n};\n\nexport type MessageSentEvent = {\n\ttype: \"messageSent\";\n\tconversationId: string;\n\tmessage: TimelineItem;\n};\n\nexport type MessageReceivedEvent = {\n\ttype: \"messageReceived\";\n\tconversationId: string;\n\tmessage: TimelineItem;\n};\n\nexport type ErrorEvent = {\n\ttype: \"error\";\n\terror: Error;\n\tcontext?: string;\n};\n\nexport type SupportEvent =\n\t| ConversationStartEvent\n\t| ConversationEndEvent\n\t| MessageSentEvent\n\t| MessageReceivedEvent\n\t| ErrorEvent;\n\n// =============================================================================\n// Event Callbacks\n// =============================================================================\n\nexport type SupportEventCallbacks = {\n\t/**\n\t * Called when a new conversation is started.\n\t */\n\tonConversationStart?: (event: ConversationStartEvent) => void;\n\t/**\n\t * Called when a conversation ends (resolved, closed, etc.).\n\t */\n\tonConversationEnd?: (event: ConversationEndEvent) => void;\n\t/**\n\t * Called when the visitor sends a message.\n\t */\n\tonMessageSent?: (event: MessageSentEvent) => void;\n\t/**\n\t * Called when a message is received from an agent (human or AI).\n\t */\n\tonMessageReceived?: (event: MessageReceivedEvent) => void;\n\t/**\n\t * Called when an error occurs.\n\t */\n\tonError?: (event: ErrorEvent) => void;\n};\n\n// =============================================================================\n// Context\n// =============================================================================\n\nexport type SupportEventsContextValue = {\n\t/**\n\t * Emit an event to all registered callbacks.\n\t */\n\temit: <T extends SupportEvent>(event: T) => void;\n\t/**\n\t * Subscribe to a specific event type.\n\t * Returns an unsubscribe function.\n\t */\n\tsubscribe: <T extends SupportEventType>(\n\t\ttype: T,\n\t\tcallback: (event: Extract<SupportEvent, { type: T }>) => void\n\t) => () => void;\n};\n\nconst SupportEventsContext =\n\tReact.createContext<SupportEventsContextValue | null>(null);\n\nexport type SupportEventsProviderProps = SupportEventCallbacks & {\n\tchildren: React.ReactNode;\n};\n\n/**\n * Provider for support widget events.\n * Allows listening to lifecycle events like message sent/received,\n * conversation start/end, and errors.\n *\n * @example\n * <Support\n * onMessageSent={({ message }) => console.log(\"Sent:\", message)}\n * onMessageReceived={({ message }) => console.log(\"Received:\", message)}\n * onConversationStart={({ conversationId }) => console.log(\"Started:\", conversationId)}\n * onError={({ error }) => console.error(\"Error:\", error)}\n * />\n */\nexport const SupportEventsProvider: React.FC<SupportEventsProviderProps> = ({\n\tonConversationStart,\n\tonConversationEnd,\n\tonMessageSent,\n\tonMessageReceived,\n\tonError,\n\tchildren,\n}) => {\n\t// Store callbacks in refs to avoid stale closures\n\tconst callbacksRef = React.useRef<SupportEventCallbacks>({\n\t\tonConversationStart,\n\t\tonConversationEnd,\n\t\tonMessageSent,\n\t\tonMessageReceived,\n\t\tonError,\n\t});\n\n\t// Update refs when callbacks change\n\tReact.useEffect(() => {\n\t\tcallbacksRef.current = {\n\t\t\tonConversationStart,\n\t\t\tonConversationEnd,\n\t\t\tonMessageSent,\n\t\t\tonMessageReceived,\n\t\t\tonError,\n\t\t};\n\t}, [\n\t\tonConversationStart,\n\t\tonConversationEnd,\n\t\tonMessageSent,\n\t\tonMessageReceived,\n\t\tonError,\n\t]);\n\n\t// Additional subscribers (for internal use)\n\tconst subscribersRef = React.useRef<\n\t\tMap<SupportEventType, Set<(event: SupportEvent) => void>>\n\t>(new Map());\n\n\tconst emit = React.useCallback(<T extends SupportEvent>(event: T) => {\n\t\t// Call the prop callback\n\t\tswitch (event.type) {\n\t\t\tcase \"conversationStart\":\n\t\t\t\tcallbacksRef.current.onConversationStart?.(event);\n\t\t\t\tbreak;\n\t\t\tcase \"conversationEnd\":\n\t\t\t\tcallbacksRef.current.onConversationEnd?.(event);\n\t\t\t\tbreak;\n\t\t\tcase \"messageSent\":\n\t\t\t\tcallbacksRef.current.onMessageSent?.(event);\n\t\t\t\tbreak;\n\t\t\tcase \"messageReceived\":\n\t\t\t\tcallbacksRef.current.onMessageReceived?.(event);\n\t\t\t\tbreak;\n\t\t\tcase \"error\":\n\t\t\t\tcallbacksRef.current.onError?.(event);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t// Unknown event type - no callback to call\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// Call any additional subscribers\n\t\tconst subscribers = subscribersRef.current.get(event.type);\n\t\tif (subscribers) {\n\t\t\tfor (const callback of subscribers) {\n\t\t\t\tcallback(event);\n\t\t\t}\n\t\t}\n\t}, []);\n\n\tconst subscribe = React.useCallback(\n\t\t<T extends SupportEventType>(\n\t\t\ttype: T,\n\t\t\tcallback: (event: Extract<SupportEvent, { type: T }>) => void\n\t\t) => {\n\t\t\tif (!subscribersRef.current.has(type)) {\n\t\t\t\tsubscribersRef.current.set(type, new Set());\n\t\t\t}\n\t\t\tconst subscribers = subscribersRef.current.get(type);\n\t\t\tsubscribers?.add(callback as (event: SupportEvent) => void);\n\n\t\t\t// Return unsubscribe function\n\t\t\treturn () => {\n\t\t\t\tsubscribers?.delete(callback as (event: SupportEvent) => void);\n\t\t\t};\n\t\t},\n\t\t[]\n\t);\n\n\tconst value = React.useMemo<SupportEventsContextValue>(\n\t\t() => ({ emit, subscribe }),\n\t\t[emit, subscribe]\n\t);\n\n\treturn (\n\t\t<SupportEventsContext.Provider value={value}>\n\t\t\t{children}\n\t\t</SupportEventsContext.Provider>\n\t);\n};\n\n/**\n * Access the events context.\n * Returns null if not inside a SupportEventsProvider.\n */\nexport function useSupportEvents(): SupportEventsContextValue | null {\n\treturn React.useContext(SupportEventsContext);\n}\n\n/**\n * Hook to emit events from within the widget.\n * Safe to use outside of provider (will no-op).\n */\nexport function useSupportEventEmitter() {\n\tconst events = useSupportEvents();\n\n\treturn React.useMemo(\n\t\t() => ({\n\t\t\temitConversationStart: (\n\t\t\t\tconversationId: string,\n\t\t\t\tconversation?: Conversation\n\t\t\t) => {\n\t\t\t\tevents?.emit({\n\t\t\t\t\ttype: \"conversationStart\",\n\t\t\t\t\tconversationId,\n\t\t\t\t\tconversation,\n\t\t\t\t});\n\t\t\t},\n\t\t\temitConversationEnd: (\n\t\t\t\tconversationId: string,\n\t\t\t\tconversation?: Conversation\n\t\t\t) => {\n\t\t\t\tevents?.emit({\n\t\t\t\t\ttype: \"conversationEnd\",\n\t\t\t\t\tconversationId,\n\t\t\t\t\tconversation,\n\t\t\t\t});\n\t\t\t},\n\t\t\temitMessageSent: (conversationId: string, message: TimelineItem) => {\n\t\t\t\tevents?.emit({\n\t\t\t\t\ttype: \"messageSent\",\n\t\t\t\t\tconversationId,\n\t\t\t\t\tmessage,\n\t\t\t\t});\n\t\t\t},\n\t\t\temitMessageReceived: (conversationId: string, message: TimelineItem) => {\n\t\t\t\tevents?.emit({\n\t\t\t\t\ttype: \"messageReceived\",\n\t\t\t\t\tconversationId,\n\t\t\t\t\tmessage,\n\t\t\t\t});\n\t\t\t},\n\t\t\temitError: (error: Error, context?: string) => {\n\t\t\t\tevents?.emit({\n\t\t\t\t\ttype: \"error\",\n\t\t\t\t\terror,\n\t\t\t\t\tcontext,\n\t\t\t\t});\n\t\t\t},\n\t\t}),\n\t\t[events]\n\t);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"events.js","names":["React","SupportEventsProvider: React.FC<SupportEventsProviderProps>"],"sources":["../../../src/support/context/events.tsx"],"sourcesContent":["\"use client\";\n\nimport type { Conversation } from \"@cossistant/types\";\nimport type { TimelineItem } from \"@cossistant/types/api/timeline-item\";\nimport * as React from \"react\";\n\n// =============================================================================\n// Event Types\n// =============================================================================\n\nexport type SupportEventType =\n\t| \"conversationStart\"\n\t| \"conversationEnd\"\n\t| \"messageSent\"\n\t| \"messageReceived\"\n\t| \"error\";\n\nexport type ConversationStartEvent = {\n\ttype: \"conversationStart\";\n\tconversationId: string;\n\tconversation?: Conversation;\n};\n\nexport type ConversationEndEvent = {\n\ttype: \"conversationEnd\";\n\tconversationId: string;\n\tconversation?: Conversation;\n};\n\nexport type MessageSentEvent = {\n\ttype: \"messageSent\";\n\tconversationId: string;\n\tmessage: TimelineItem;\n};\n\nexport type MessageReceivedEvent = {\n\ttype: \"messageReceived\";\n\tconversationId: string;\n\tmessage: TimelineItem;\n};\n\nexport type ErrorEvent = {\n\ttype: \"error\";\n\terror: Error;\n\tcontext?: string;\n};\n\nexport type SupportEvent =\n\t| ConversationStartEvent\n\t| ConversationEndEvent\n\t| MessageSentEvent\n\t| MessageReceivedEvent\n\t| ErrorEvent;\n\n// =============================================================================\n// Event Callbacks\n// =============================================================================\n\nexport type SupportEventCallbacks = {\n\t/**\n\t * Called when a new conversation is started.\n\t */\n\tonConversationStart?: (event: ConversationStartEvent) => void;\n\t/**\n\t * Called when a conversation ends (resolved, closed, etc.).\n\t */\n\tonConversationEnd?: (event: ConversationEndEvent) => void;\n\t/**\n\t * Called when the visitor sends a message.\n\t */\n\tonMessageSent?: (event: MessageSentEvent) => void;\n\t/**\n\t * Called when a message is received from an agent (human or AI).\n\t */\n\tonMessageReceived?: (event: MessageReceivedEvent) => void;\n\t/**\n\t * Called when an error occurs.\n\t */\n\tonError?: (event: ErrorEvent) => void;\n};\n\n// =============================================================================\n// Context\n// =============================================================================\n\nexport type SupportEventsContextValue = {\n\t/**\n\t * Emit an event to all registered callbacks.\n\t */\n\temit: <T extends SupportEvent>(event: T) => void;\n\t/**\n\t * Subscribe to a specific event type.\n\t * Returns an unsubscribe function.\n\t */\n\tsubscribe: <T extends SupportEventType>(\n\t\ttype: T,\n\t\tcallback: (event: Extract<SupportEvent, { type: T }>) => void\n\t) => () => void;\n};\n\nconst SupportEventsContext =\n\tReact.createContext<SupportEventsContextValue | null>(null);\n\nexport type SupportEventsProviderProps = SupportEventCallbacks & {\n\tchildren: React.ReactNode;\n};\n\n/**\n * Provider for support widget events.\n * Allows listening to lifecycle events like message sent/received,\n * conversation start/end, and errors.\n *\n * @example\n * <Support\n * onMessageSent={({ message }) => console.log(\"Sent:\", message)}\n * onMessageReceived={({ message }) => console.log(\"Received:\", message)}\n * onConversationStart={({ conversationId }) => console.log(\"Started:\", conversationId)}\n * onError={({ error }) => console.error(\"Error:\", error)}\n * />\n */\nexport const SupportEventsProvider: React.FC<SupportEventsProviderProps> = ({\n\tonConversationStart,\n\tonConversationEnd,\n\tonMessageSent,\n\tonMessageReceived,\n\tonError,\n\tchildren,\n}) => {\n\t// Store callbacks in refs to avoid stale closures\n\tconst callbacksRef = React.useRef<SupportEventCallbacks>({\n\t\tonConversationStart,\n\t\tonConversationEnd,\n\t\tonMessageSent,\n\t\tonMessageReceived,\n\t\tonError,\n\t});\n\n\t// Update refs when callbacks change\n\tReact.useEffect(() => {\n\t\tcallbacksRef.current = {\n\t\t\tonConversationStart,\n\t\t\tonConversationEnd,\n\t\t\tonMessageSent,\n\t\t\tonMessageReceived,\n\t\t\tonError,\n\t\t};\n\t}, [\n\t\tonConversationStart,\n\t\tonConversationEnd,\n\t\tonMessageSent,\n\t\tonMessageReceived,\n\t\tonError,\n\t]);\n\n\t// Additional subscribers (for internal use)\n\tconst subscribersRef = React.useRef<\n\t\tMap<SupportEventType, Set<(event: SupportEvent) => void>>\n\t>(new Map());\n\n\tconst emit = React.useCallback(<T extends SupportEvent>(event: T) => {\n\t\t// Call the prop callback\n\t\tswitch (event.type) {\n\t\t\tcase \"conversationStart\":\n\t\t\t\tcallbacksRef.current.onConversationStart?.(event);\n\t\t\t\tbreak;\n\t\t\tcase \"conversationEnd\":\n\t\t\t\tcallbacksRef.current.onConversationEnd?.(event);\n\t\t\t\tbreak;\n\t\t\tcase \"messageSent\":\n\t\t\t\tcallbacksRef.current.onMessageSent?.(event);\n\t\t\t\tbreak;\n\t\t\tcase \"messageReceived\":\n\t\t\t\tcallbacksRef.current.onMessageReceived?.(event);\n\t\t\t\tbreak;\n\t\t\tcase \"error\":\n\t\t\t\tcallbacksRef.current.onError?.(event);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t// Unknown event type - no callback to call\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// Call any additional subscribers\n\t\tconst subscribers = subscribersRef.current.get(event.type);\n\t\tif (subscribers) {\n\t\t\tfor (const callback of subscribers) {\n\t\t\t\tcallback(event);\n\t\t\t}\n\t\t}\n\t}, []);\n\n\tconst subscribe = React.useCallback(\n\t\t<T extends SupportEventType>(\n\t\t\ttype: T,\n\t\t\tcallback: (event: Extract<SupportEvent, { type: T }>) => void\n\t\t) => {\n\t\t\tif (!subscribersRef.current.has(type)) {\n\t\t\t\tsubscribersRef.current.set(type, new Set());\n\t\t\t}\n\t\t\tconst subscribers = subscribersRef.current.get(type);\n\t\t\tsubscribers?.add(callback as (event: SupportEvent) => void);\n\n\t\t\t// Return unsubscribe function\n\t\t\treturn () => {\n\t\t\t\tsubscribers?.delete(callback as (event: SupportEvent) => void);\n\t\t\t};\n\t\t},\n\t\t[]\n\t);\n\n\tconst value = React.useMemo<SupportEventsContextValue>(\n\t\t() => ({ emit, subscribe }),\n\t\t[emit, subscribe]\n\t);\n\n\treturn (\n\t\t<SupportEventsContext.Provider value={value}>\n\t\t\t{children}\n\t\t</SupportEventsContext.Provider>\n\t);\n};\n\n/**\n * Access the events context.\n * Returns null if not inside a SupportEventsProvider.\n */\nexport function useSupportEvents(): SupportEventsContextValue | null {\n\treturn React.useContext(SupportEventsContext);\n}\n\n/**\n * Hook to emit events from within the widget.\n * Safe to use outside of provider (will no-op).\n */\nexport function useSupportEventEmitter() {\n\tconst events = useSupportEvents();\n\n\treturn React.useMemo(\n\t\t() => ({\n\t\t\temitConversationStart: (\n\t\t\t\tconversationId: string,\n\t\t\t\tconversation?: Conversation\n\t\t\t) => {\n\t\t\t\tevents?.emit({\n\t\t\t\t\ttype: \"conversationStart\",\n\t\t\t\t\tconversationId,\n\t\t\t\t\tconversation,\n\t\t\t\t});\n\t\t\t},\n\t\t\temitConversationEnd: (\n\t\t\t\tconversationId: string,\n\t\t\t\tconversation?: Conversation\n\t\t\t) => {\n\t\t\t\tevents?.emit({\n\t\t\t\t\ttype: \"conversationEnd\",\n\t\t\t\t\tconversationId,\n\t\t\t\t\tconversation,\n\t\t\t\t});\n\t\t\t},\n\t\t\temitMessageSent: (conversationId: string, message: TimelineItem) => {\n\t\t\t\tevents?.emit({\n\t\t\t\t\ttype: \"messageSent\",\n\t\t\t\t\tconversationId,\n\t\t\t\t\tmessage,\n\t\t\t\t});\n\t\t\t},\n\t\t\temitMessageReceived: (conversationId: string, message: TimelineItem) => {\n\t\t\t\tevents?.emit({\n\t\t\t\t\ttype: \"messageReceived\",\n\t\t\t\t\tconversationId,\n\t\t\t\t\tmessage,\n\t\t\t\t});\n\t\t\t},\n\t\t\temitError: (error: Error, context?: string) => {\n\t\t\t\tevents?.emit({\n\t\t\t\t\ttype: \"error\",\n\t\t\t\t\terror,\n\t\t\t\t\tcontext,\n\t\t\t\t});\n\t\t\t},\n\t\t}),\n\t\t[events]\n\t);\n}\n"],"mappings":";;;;;;AAoGA,MAAM,uBACLA,QAAM,cAAgD,KAAK;;;;;;;;;;;;;;AAmB5D,MAAaC,yBAA+D,EAC3E,qBACA,mBACA,eACA,mBACA,SACA,eACK;CAEL,MAAM,eAAeD,QAAM,OAA8B;EACxD;EACA;EACA;EACA;EACA;EACA,CAAC;AAGF,SAAM,gBAAgB;AACrB,eAAa,UAAU;GACtB;GACA;GACA;GACA;GACA;GACA;IACC;EACF;EACA;EACA;EACA;EACA;EACA,CAAC;CAGF,MAAM,iBAAiBA,QAAM,uBAE3B,IAAI,KAAK,CAAC;CAEZ,MAAM,OAAOA,QAAM,aAAqC,UAAa;AAEpE,UAAQ,MAAM,MAAd;GACC,KAAK;AACJ,iBAAa,QAAQ,sBAAsB,MAAM;AACjD;GACD,KAAK;AACJ,iBAAa,QAAQ,oBAAoB,MAAM;AAC/C;GACD,KAAK;AACJ,iBAAa,QAAQ,gBAAgB,MAAM;AAC3C;GACD,KAAK;AACJ,iBAAa,QAAQ,oBAAoB,MAAM;AAC/C;GACD,KAAK;AACJ,iBAAa,QAAQ,UAAU,MAAM;AACrC;GACD,QAEC;;EAIF,MAAM,cAAc,eAAe,QAAQ,IAAI,MAAM,KAAK;AAC1D,MAAI,YACH,MAAK,MAAM,YAAY,YACtB,UAAS,MAAM;IAGf,EAAE,CAAC;CAEN,MAAM,YAAYA,QAAM,aAEtB,MACA,aACI;AACJ,MAAI,CAAC,eAAe,QAAQ,IAAI,KAAK,CACpC,gBAAe,QAAQ,IAAI,sBAAM,IAAI,KAAK,CAAC;EAE5C,MAAM,cAAc,eAAe,QAAQ,IAAI,KAAK;AACpD,eAAa,IAAI,SAA0C;AAG3D,eAAa;AACZ,gBAAa,OAAO,SAA0C;;IAGhE,EAAE,CACF;CAED,MAAM,QAAQA,QAAM,eACZ;EAAE;EAAM;EAAW,GAC1B,CAAC,MAAM,UAAU,CACjB;AAED,QACC,oBAAC,qBAAqB;EAAgB;EACpC;GAC8B;;;;;;AAQlC,SAAgB,mBAAqD;AACpE,QAAOA,QAAM,WAAW,qBAAqB;;;;;;AAO9C,SAAgB,yBAAyB;CACxC,MAAM,SAAS,kBAAkB;AAEjC,QAAOA,QAAM,eACL;EACN,wBACC,gBACA,iBACI;AACJ,WAAQ,KAAK;IACZ,MAAM;IACN;IACA;IACA,CAAC;;EAEH,sBACC,gBACA,iBACI;AACJ,WAAQ,KAAK;IACZ,MAAM;IACN;IACA;IACA,CAAC;;EAEH,kBAAkB,gBAAwB,YAA0B;AACnE,WAAQ,KAAK;IACZ,MAAM;IACN;IACA;IACA,CAAC;;EAEH,sBAAsB,gBAAwB,YAA0B;AACvE,WAAQ,KAAK;IACZ,MAAM;IACN;IACA;IACA,CAAC;;EAEH,YAAY,OAAc,YAAqB;AAC9C,WAAQ,KAAK;IACZ,MAAM;IACN;IACA;IACA,CAAC;;EAEH,GACD,CAAC,OAAO,CACR"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handle.js","names":["React","SupportHandleProvider: React.FC<SupportHandleProviderProps>"],"sources":["../../../src/support/context/handle.tsx"],"sourcesContent":["\"use client\";\n\nimport type { RouteRegistry } from \"@cossistant/core\";\nimport * as React from \"react\";\nimport { PENDING_CONVERSATION_ID } from \"../../utils/id\";\nimport { useSupportConfig, useSupportNavigation } from \"../store/support-store\";\n\n// =============================================================================\n// Handle Type\n// =============================================================================\n\n/**\n * Imperative handle for programmatic control of the Support widget.\n * Access via ref on the Support component or via useSupportHandle hook.\n *\n * @example\n * const supportRef = useRef<SupportHandle>(null);\n *\n * // Open the widget\n * supportRef.current?.open();\n *\n * // Navigate to a conversation\n * supportRef.current?.openConversation(\"conv_123\");\n *\n * // Start a new conversation with a message\n * supportRef.current?.startConversation(\"I need help with...\");\n *\n * <Support ref={supportRef} />\n */\nexport type SupportHandle = {\n\t/**\n\t * Open the support widget.\n\t */\n\topen: () => void;\n\t/**\n\t * Close the support widget.\n\t */\n\tclose: () => void;\n\t/**\n\t * Toggle the support widget open/closed.\n\t */\n\ttoggle: () => void;\n\t/**\n\t * Navigate to a specific page with optional params.\n\t */\n\tnavigate: <K extends keyof RouteRegistry>(options: {\n\t\tpage: K;\n\t\tparams?: RouteRegistry[K];\n\t}) => void;\n\t/**\n\t * Go back to the previous page.\n\t */\n\tgoBack: () => void;\n\t/**\n\t * Open a specific conversation.\n\t */\n\topenConversation: (conversationId: string) => void;\n\t/**\n\t * Start a new conversation, optionally with an initial message.\n\t */\n\tstartConversation: (initialMessage?: string) => void;\n\t/**\n\t * Navigate to the home page.\n\t */\n\tgoHome: () => void;\n};\n\n// =============================================================================\n// Context\n// =============================================================================\n\nconst SupportHandleContext = React.createContext<SupportHandle | null>(null);\n\nexport type SupportHandleProviderProps = {\n\t/**\n\t * Ref to expose the handle to parent components.\n\t */\n\tforwardedRef?: React.Ref<SupportHandle>;\n\tchildren: React.ReactNode;\n};\n\n/**\n * Provider that creates and exposes the imperative handle.\n */\nexport const SupportHandleProvider: React.FC<SupportHandleProviderProps> = ({\n\tforwardedRef,\n\tchildren,\n}) => {\n\tconst { open, close, toggle } = useSupportConfig();\n\tconst { navigate, goBack } = useSupportNavigation();\n\n\tconst handle = React.useMemo<SupportHandle>(\n\t\t() => ({\n\t\t\topen,\n\t\t\tclose,\n\t\t\ttoggle,\n\t\t\tnavigate: <K extends keyof RouteRegistry>(options: {\n\t\t\t\tpage: K;\n\t\t\t\tparams?: RouteRegistry[K];\n\t\t\t}) => {\n\t\t\t\t// Use type assertion since we know the navigate function accepts these types\n\t\t\t\tnavigate(options as Parameters<typeof navigate>[0]);\n\t\t\t},\n\t\t\tgoBack,\n\t\t\topenConversation: (conversationId: string) => {\n\t\t\t\tnavigate({\n\t\t\t\t\tpage: \"CONVERSATION\",\n\t\t\t\t\tparams: { conversationId },\n\t\t\t\t});\n\t\t\t\t// Also open the widget if closed\n\t\t\t\topen();\n\t\t\t},\n\t\t\tstartConversation: (initialMessage?: string) => {\n\t\t\t\tnavigate({\n\t\t\t\t\tpage: \"CONVERSATION\",\n\t\t\t\t\tparams: {\n\t\t\t\t\t\tconversationId: PENDING_CONVERSATION_ID,\n\t\t\t\t\t\tinitialMessage,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\t// Also open the widget if closed\n\t\t\t\topen();\n\t\t\t},\n\t\t\tgoHome: () => {\n\t\t\t\tnavigate({ page: \"HOME\" });\n\t\t\t},\n\t\t}),\n\t\t[open, close, toggle, navigate, goBack]\n\t);\n\n\t// Expose handle via ref\n\tReact.useImperativeHandle(forwardedRef, () => handle, [handle]);\n\n\treturn (\n\t\t<SupportHandleContext.Provider value={handle}>\n\t\t\t{children}\n\t\t</SupportHandleContext.Provider>\n\t);\n};\n\n// =============================================================================\n// Hook\n// =============================================================================\n\n/**\n * Hook to access the imperative handle from within the widget.\n * Returns null if not inside Support component.\n *\n * @example\n * function MyComponent() {\n * const support = useSupportHandle();\n *\n * return (\n * <button onClick={() => support?.startConversation(\"Hello!\")}>\n * Get Help\n * </button>\n * );\n * }\n */\nexport function useSupportHandle(): SupportHandle | null {\n\treturn React.useContext(SupportHandleContext);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"handle.js","names":["React","SupportHandleProvider: React.FC<SupportHandleProviderProps>"],"sources":["../../../src/support/context/handle.tsx"],"sourcesContent":["\"use client\";\n\nimport type { RouteRegistry } from \"@cossistant/core\";\nimport * as React from \"react\";\nimport { PENDING_CONVERSATION_ID } from \"../../utils/id\";\nimport { useSupportConfig, useSupportNavigation } from \"../store/support-store\";\n\n// =============================================================================\n// Handle Type\n// =============================================================================\n\n/**\n * Imperative handle for programmatic control of the Support widget.\n * Access via ref on the Support component or via useSupportHandle hook.\n *\n * @example\n * const supportRef = useRef<SupportHandle>(null);\n *\n * // Open the widget\n * supportRef.current?.open();\n *\n * // Navigate to a conversation\n * supportRef.current?.openConversation(\"conv_123\");\n *\n * // Start a new conversation with a message\n * supportRef.current?.startConversation(\"I need help with...\");\n *\n * <Support ref={supportRef} />\n */\nexport type SupportHandle = {\n\t/**\n\t * Open the support widget.\n\t */\n\topen: () => void;\n\t/**\n\t * Close the support widget.\n\t */\n\tclose: () => void;\n\t/**\n\t * Toggle the support widget open/closed.\n\t */\n\ttoggle: () => void;\n\t/**\n\t * Navigate to a specific page with optional params.\n\t */\n\tnavigate: <K extends keyof RouteRegistry>(options: {\n\t\tpage: K;\n\t\tparams?: RouteRegistry[K];\n\t}) => void;\n\t/**\n\t * Go back to the previous page.\n\t */\n\tgoBack: () => void;\n\t/**\n\t * Open a specific conversation.\n\t */\n\topenConversation: (conversationId: string) => void;\n\t/**\n\t * Start a new conversation, optionally with an initial message.\n\t */\n\tstartConversation: (initialMessage?: string) => void;\n\t/**\n\t * Navigate to the home page.\n\t */\n\tgoHome: () => void;\n};\n\n// =============================================================================\n// Context\n// =============================================================================\n\nconst SupportHandleContext = React.createContext<SupportHandle | null>(null);\n\nexport type SupportHandleProviderProps = {\n\t/**\n\t * Ref to expose the handle to parent components.\n\t */\n\tforwardedRef?: React.Ref<SupportHandle>;\n\tchildren: React.ReactNode;\n};\n\n/**\n * Provider that creates and exposes the imperative handle.\n */\nexport const SupportHandleProvider: React.FC<SupportHandleProviderProps> = ({\n\tforwardedRef,\n\tchildren,\n}) => {\n\tconst { open, close, toggle } = useSupportConfig();\n\tconst { navigate, goBack } = useSupportNavigation();\n\n\tconst handle = React.useMemo<SupportHandle>(\n\t\t() => ({\n\t\t\topen,\n\t\t\tclose,\n\t\t\ttoggle,\n\t\t\tnavigate: <K extends keyof RouteRegistry>(options: {\n\t\t\t\tpage: K;\n\t\t\t\tparams?: RouteRegistry[K];\n\t\t\t}) => {\n\t\t\t\t// Use type assertion since we know the navigate function accepts these types\n\t\t\t\tnavigate(options as Parameters<typeof navigate>[0]);\n\t\t\t},\n\t\t\tgoBack,\n\t\t\topenConversation: (conversationId: string) => {\n\t\t\t\tnavigate({\n\t\t\t\t\tpage: \"CONVERSATION\",\n\t\t\t\t\tparams: { conversationId },\n\t\t\t\t});\n\t\t\t\t// Also open the widget if closed\n\t\t\t\topen();\n\t\t\t},\n\t\t\tstartConversation: (initialMessage?: string) => {\n\t\t\t\tnavigate({\n\t\t\t\t\tpage: \"CONVERSATION\",\n\t\t\t\t\tparams: {\n\t\t\t\t\t\tconversationId: PENDING_CONVERSATION_ID,\n\t\t\t\t\t\tinitialMessage,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\t// Also open the widget if closed\n\t\t\t\topen();\n\t\t\t},\n\t\t\tgoHome: () => {\n\t\t\t\tnavigate({ page: \"HOME\" });\n\t\t\t},\n\t\t}),\n\t\t[open, close, toggle, navigate, goBack]\n\t);\n\n\t// Expose handle via ref\n\tReact.useImperativeHandle(forwardedRef, () => handle, [handle]);\n\n\treturn (\n\t\t<SupportHandleContext.Provider value={handle}>\n\t\t\t{children}\n\t\t</SupportHandleContext.Provider>\n\t);\n};\n\n// =============================================================================\n// Hook\n// =============================================================================\n\n/**\n * Hook to access the imperative handle from within the widget.\n * Returns null if not inside Support component.\n *\n * @example\n * function MyComponent() {\n * const support = useSupportHandle();\n *\n * return (\n * <button onClick={() => support?.startConversation(\"Hello!\")}>\n * Get Help\n * </button>\n * );\n * }\n */\nexport function useSupportHandle(): SupportHandle | null {\n\treturn React.useContext(SupportHandleContext);\n}\n"],"mappings":";;;;;;;;AAuEA,MAAM,uBAAuBA,QAAM,cAAoC,KAAK;;;;AAa5E,MAAaC,yBAA+D,EAC3E,cACA,eACK;CACL,MAAM,EAAE,MAAM,OAAO,WAAW,kBAAkB;CAClD,MAAM,EAAE,UAAU,WAAW,sBAAsB;CAEnD,MAAM,SAASD,QAAM,eACb;EACN;EACA;EACA;EACA,WAA0C,YAGpC;AAEL,YAAS,QAA0C;;EAEpD;EACA,mBAAmB,mBAA2B;AAC7C,YAAS;IACR,MAAM;IACN,QAAQ,EAAE,gBAAgB;IAC1B,CAAC;AAEF,SAAM;;EAEP,oBAAoB,mBAA4B;AAC/C,YAAS;IACR,MAAM;IACN,QAAQ;KACP,gBAAgB;KAChB;KACA;IACD,CAAC;AAEF,SAAM;;EAEP,cAAc;AACb,YAAS,EAAE,MAAM,QAAQ,CAAC;;EAE3B,GACD;EAAC;EAAM;EAAO;EAAQ;EAAU;EAAO,CACvC;AAGD,SAAM,oBAAoB,oBAAoB,QAAQ,CAAC,OAAO,CAAC;AAE/D,QACC,oBAAC,qBAAqB;EAAS,OAAO;EACpC;GAC8B;;;;;;;;;;;;;;;;;AAuBlC,SAAgB,mBAAyC;AACxD,QAAOA,QAAM,WAAW,qBAAqB"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
2
|
+
|
|
3
|
+
//#region src/support/context/identification.d.ts
|
|
4
|
+
type IdentificationState = {
|
|
5
|
+
/**
|
|
6
|
+
* Whether an identification request is currently in progress.
|
|
7
|
+
* When true, the identification form should not be shown.
|
|
8
|
+
*/
|
|
9
|
+
isIdentifying: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Set the identifying state (used internally by IdentifySupportVisitor).
|
|
12
|
+
*/
|
|
13
|
+
setIsIdentifying: (value: boolean) => void;
|
|
14
|
+
};
|
|
15
|
+
type IdentificationProviderProps = {
|
|
16
|
+
children: React.ReactNode;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Provider for tracking visitor identification state.
|
|
20
|
+
* This is used internally to prevent showing the identification form
|
|
21
|
+
* while an identification request is in progress.
|
|
22
|
+
*/
|
|
23
|
+
declare function IdentificationProvider({
|
|
24
|
+
children
|
|
25
|
+
}: IdentificationProviderProps): react_jsx_runtime0.JSX.Element;
|
|
26
|
+
/**
|
|
27
|
+
* Hook to access the identification state.
|
|
28
|
+
* Returns null if used outside of IdentificationProvider.
|
|
29
|
+
*/
|
|
30
|
+
declare function useIdentificationState(): IdentificationState | null;
|
|
31
|
+
//#endregion
|
|
32
|
+
export { IdentificationProvider, useIdentificationState };
|
|
33
|
+
//# sourceMappingURL=identification.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identification.d.ts","names":[],"sources":["../../../src/support/context/identification.tsx"],"sourcesContent":[],"mappings":";;;KAIK,mBAAA;;;AAyByB;AAzBN;EAuBR,aAAA,EAAA,OAAA;EACf;;;EAC6B,gBAAA,EAAA,CAAA,KAAA,EAAA,OAAA,EAAA,GAAA,IAAA;AAsB9B,CAAA;KAjCK,2BAAA;YACM,KAAA,CAAM;;;;;;;iBAQD,sBAAA;;GAEb,8BAA2B,kBAAA,CAAA,GAAA,CAAA;;;;;iBAsBd,sBAAA,CAAA,GAA0B"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { createContext, useContext, useMemo, useState } from "react";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
|
|
6
|
+
//#region src/support/context/identification.tsx
|
|
7
|
+
const IdentificationContext = createContext(null);
|
|
8
|
+
/**
|
|
9
|
+
* Provider for tracking visitor identification state.
|
|
10
|
+
* This is used internally to prevent showing the identification form
|
|
11
|
+
* while an identification request is in progress.
|
|
12
|
+
*/
|
|
13
|
+
function IdentificationProvider({ children }) {
|
|
14
|
+
const [isIdentifying, setIsIdentifying] = useState(false);
|
|
15
|
+
const value = useMemo(() => ({
|
|
16
|
+
isIdentifying,
|
|
17
|
+
setIsIdentifying
|
|
18
|
+
}), [isIdentifying]);
|
|
19
|
+
return /* @__PURE__ */ jsx(IdentificationContext.Provider, {
|
|
20
|
+
value,
|
|
21
|
+
children
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Hook to access the identification state.
|
|
26
|
+
* Returns null if used outside of IdentificationProvider.
|
|
27
|
+
*/
|
|
28
|
+
function useIdentificationState() {
|
|
29
|
+
return useContext(IdentificationContext);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
//#endregion
|
|
33
|
+
export { IdentificationProvider, useIdentificationState };
|
|
34
|
+
//# sourceMappingURL=identification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identification.js","names":[],"sources":["../../../src/support/context/identification.tsx"],"sourcesContent":["\"use client\";\n\nimport { createContext, useContext, useMemo, useState } from \"react\";\n\ntype IdentificationState = {\n\t/**\n\t * Whether an identification request is currently in progress.\n\t * When true, the identification form should not be shown.\n\t */\n\tisIdentifying: boolean;\n\t/**\n\t * Set the identifying state (used internally by IdentifySupportVisitor).\n\t */\n\tsetIsIdentifying: (value: boolean) => void;\n};\n\nconst IdentificationContext = createContext<IdentificationState | null>(null);\n\ntype IdentificationProviderProps = {\n\tchildren: React.ReactNode;\n};\n\n/**\n * Provider for tracking visitor identification state.\n * This is used internally to prevent showing the identification form\n * while an identification request is in progress.\n */\nexport function IdentificationProvider({\n\tchildren,\n}: IdentificationProviderProps) {\n\tconst [isIdentifying, setIsIdentifying] = useState(false);\n\n\tconst value = useMemo(\n\t\t() => ({\n\t\t\tisIdentifying,\n\t\t\tsetIsIdentifying,\n\t\t}),\n\t\t[isIdentifying]\n\t);\n\n\treturn (\n\t\t<IdentificationContext.Provider value={value}>\n\t\t\t{children}\n\t\t</IdentificationContext.Provider>\n\t);\n}\n\n/**\n * Hook to access the identification state.\n * Returns null if used outside of IdentificationProvider.\n */\nexport function useIdentificationState(): IdentificationState | null {\n\treturn useContext(IdentificationContext);\n}\n"],"mappings":";;;;;;AAgBA,MAAM,wBAAwB,cAA0C,KAAK;;;;;;AAW7E,SAAgB,uBAAuB,EACtC,YAC+B;CAC/B,MAAM,CAAC,eAAe,oBAAoB,SAAS,MAAM;CAEzD,MAAM,QAAQ,eACN;EACN;EACA;EACA,GACD,CAAC,cAAc,CACf;AAED,QACC,oBAAC,sBAAsB;EAAgB;EACrC;GAC+B;;;;;;AAQnC,SAAgB,yBAAqD;AACpE,QAAO,WAAW,sBAAsB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"positioning.js","names":["React","TriggerRefProvider: React.FC<TriggerRefProviderProps>"],"sources":["../../../src/support/context/positioning.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type TriggerRefContextValue = {\n\t/** The trigger element (state-based for reactivity) */\n\ttriggerElement: HTMLElement | null;\n\t/** Set the trigger element - triggers re-render when called */\n\tsetTriggerElement: (element: HTMLElement | null) => void;\n};\n\n// =============================================================================\n// Context\n// =============================================================================\n\nconst TriggerRefContext = React.createContext<TriggerRefContextValue | null>(\n\tnull\n);\n\n// =============================================================================\n// Provider\n// =============================================================================\n\nexport type TriggerRefProviderProps = {\n\tchildren: React.ReactNode;\n};\n\nexport const TriggerRefProvider: React.FC<TriggerRefProviderProps> = ({\n\tchildren,\n}) => {\n\t// Using state instead of ref to trigger re-renders when trigger mounts\n\t// This ensures Floating UI receives the reference element\n\tconst [triggerElement, setTriggerElement] =\n\t\tReact.useState<HTMLElement | null>(null);\n\n\tconst value = React.useMemo<TriggerRefContextValue>(\n\t\t() => ({\n\t\t\ttriggerElement,\n\t\t\tsetTriggerElement,\n\t\t}),\n\t\t[triggerElement]\n\t);\n\n\treturn (\n\t\t<TriggerRefContext.Provider value={value}>\n\t\t\t{children}\n\t\t</TriggerRefContext.Provider>\n\t);\n};\n\n// =============================================================================\n// Hook\n// =============================================================================\n\nexport function useTriggerRef(): TriggerRefContextValue | null {\n\treturn React.useContext(TriggerRefContext);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"positioning.js","names":["React","TriggerRefProvider: React.FC<TriggerRefProviderProps>"],"sources":["../../../src/support/context/positioning.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type TriggerRefContextValue = {\n\t/** The trigger element (state-based for reactivity) */\n\ttriggerElement: HTMLElement | null;\n\t/** Set the trigger element - triggers re-render when called */\n\tsetTriggerElement: (element: HTMLElement | null) => void;\n};\n\n// =============================================================================\n// Context\n// =============================================================================\n\nconst TriggerRefContext = React.createContext<TriggerRefContextValue | null>(\n\tnull\n);\n\n// =============================================================================\n// Provider\n// =============================================================================\n\nexport type TriggerRefProviderProps = {\n\tchildren: React.ReactNode;\n};\n\nexport const TriggerRefProvider: React.FC<TriggerRefProviderProps> = ({\n\tchildren,\n}) => {\n\t// Using state instead of ref to trigger re-renders when trigger mounts\n\t// This ensures Floating UI receives the reference element\n\tconst [triggerElement, setTriggerElement] =\n\t\tReact.useState<HTMLElement | null>(null);\n\n\tconst value = React.useMemo<TriggerRefContextValue>(\n\t\t() => ({\n\t\t\ttriggerElement,\n\t\t\tsetTriggerElement,\n\t\t}),\n\t\t[triggerElement]\n\t);\n\n\treturn (\n\t\t<TriggerRefContext.Provider value={value}>\n\t\t\t{children}\n\t\t</TriggerRefContext.Provider>\n\t);\n};\n\n// =============================================================================\n// Hook\n// =============================================================================\n\nexport function useTriggerRef(): TriggerRefContextValue | null {\n\treturn React.useContext(TriggerRefContext);\n}\n"],"mappings":";;;;;;AAmBA,MAAM,oBAAoBA,QAAM,cAC/B,KACA;AAUD,MAAaC,sBAAyD,EACrE,eACK;CAGL,MAAM,CAAC,gBAAgB,qBACtBD,QAAM,SAA6B,KAAK;CAEzC,MAAM,QAAQA,QAAM,eACZ;EACN;EACA;EACA,GACD,CAAC,eAAe,CAChB;AAED,QACC,oBAAC,kBAAkB;EAAgB;EACjC;GAC2B;;AAQ/B,SAAgB,gBAA+C;AAC9D,QAAOA,QAAM,WAAW,kBAAkB"}
|
package/support/context/slots.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slots.js","names":["React","SlotProvider: React.FC<SlotProviderProps>","HeaderSlot: React.FC<SlotProps>","FooterSlot: React.FC<SlotProps>"],"sources":["../../../src/support/context/slots.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\n// =============================================================================\n// Slot Types\n// =============================================================================\n\nexport type SlotContextValue = {\n\t/**\n\t * Custom header slot content\n\t */\n\theader: React.ReactNode | null;\n\t/**\n\t * Custom footer slot content\n\t */\n\tfooter: React.ReactNode | null;\n\t/**\n\t * Whether to use the custom header\n\t */\n\thasCustomHeader: boolean;\n\t/**\n\t * Whether to use the custom footer\n\t */\n\thasCustomFooter: boolean;\n};\n\ntype SlotRegistration = {\n\tregisterHeader: (content: React.ReactNode) => void;\n\tregisterFooter: (content: React.ReactNode) => void;\n\tunregisterHeader: () => void;\n\tunregisterFooter: () => void;\n};\n\nconst SlotContext = React.createContext<SlotContextValue>({\n\theader: null,\n\tfooter: null,\n\thasCustomHeader: false,\n\thasCustomFooter: false,\n});\n\nconst SlotRegistrationContext = React.createContext<SlotRegistration | null>(\n\tnull\n);\n\n// =============================================================================\n// Provider\n// =============================================================================\n\nexport type SlotProviderProps = {\n\tchildren: React.ReactNode;\n};\n\n/**\n * Provider for slot-based customization.\n * Allows children to register custom header/footer content.\n */\nexport const SlotProvider: React.FC<SlotProviderProps> = ({ children }) => {\n\tconst [header, setHeader] = React.useState<React.ReactNode | null>(null);\n\tconst [footer, setFooter] = React.useState<React.ReactNode | null>(null);\n\n\tconst registration = React.useMemo<SlotRegistration>(\n\t\t() => ({\n\t\t\tregisterHeader: (content) => setHeader(content),\n\t\t\tregisterFooter: (content) => setFooter(content),\n\t\t\tunregisterHeader: () => setHeader(null),\n\t\t\tunregisterFooter: () => setFooter(null),\n\t\t}),\n\t\t[]\n\t);\n\n\tconst value = React.useMemo<SlotContextValue>(\n\t\t() => ({\n\t\t\theader,\n\t\t\tfooter,\n\t\t\thasCustomHeader: header !== null,\n\t\t\thasCustomFooter: footer !== null,\n\t\t}),\n\t\t[header, footer]\n\t);\n\n\treturn (\n\t\t<SlotRegistrationContext.Provider value={registration}>\n\t\t\t<SlotContext.Provider value={value}>{children}</SlotContext.Provider>\n\t\t</SlotRegistrationContext.Provider>\n\t);\n};\n\n// =============================================================================\n// Hooks\n// =============================================================================\n\n/**\n * Access slot values (for content component)\n */\nexport function useSlots(): SlotContextValue {\n\treturn React.useContext(SlotContext);\n}\n\n/**\n * Access slot registration (for slot components)\n */\nfunction useSlotRegistration(): SlotRegistration | null {\n\treturn React.useContext(SlotRegistrationContext);\n}\n\n// =============================================================================\n// Slot Components\n// =============================================================================\n\nexport type SlotProps = {\n\t/**\n\t * Content to render in the slot.\n\t */\n\tchildren: React.ReactNode;\n\t/**\n\t * When true, renders children directly without a wrapper.\n\t * Useful when you want your component to receive all props.\n\t */\n\tasChild?: boolean;\n};\n\n/**\n * Header slot component.\n * Use inside Support.Content to replace the default header.\n *\n * @example\n * <Support.Content>\n * <Support.Header>\n * <MyCustomHeader />\n * </Support.Header>\n * <Support.Router />\n * </Support.Content>\n *\n * @example\n * // With asChild pattern\n * <Support.Header asChild>\n * <MyCustomHeader showBackButton />\n * </Support.Header>\n */\nexport const HeaderSlot: React.FC<SlotProps> = ({ children, asChild }) => {\n\tconst registration = useSlotRegistration();\n\n\tReact.useEffect(() => {\n\t\tif (registration) {\n\t\t\tregistration.registerHeader(children);\n\t\t\treturn () => registration.unregisterHeader();\n\t\t}\n\t}, [registration, children]);\n\n\t// This component doesn't render anything directly\n\t// It registers its children as the header slot\n\treturn null;\n};\n\n(HeaderSlot as React.FC & { displayName?: string }).displayName =\n\t\"Support.Header\";\n\n/**\n * Footer slot component.\n * Use inside Support.Content to replace the default footer.\n *\n * @example\n * <Support.Content>\n * <Support.Router />\n * <Support.Footer>\n * <MyCustomFooter />\n * </Support.Footer>\n * </Support.Content>\n *\n * @example\n * // With asChild pattern\n * <Support.Footer asChild>\n * <MyCustomFooter showBranding={false} />\n * </Support.Footer>\n */\nexport const FooterSlot: React.FC<SlotProps> = ({ children, asChild }) => {\n\tconst registration = useSlotRegistration();\n\n\tReact.useEffect(() => {\n\t\tif (registration) {\n\t\t\tregistration.registerFooter(children);\n\t\t\treturn () => registration.unregisterFooter();\n\t\t}\n\t}, [registration, children]);\n\n\t// This component doesn't render anything directly\n\t// It registers its children as the footer slot\n\treturn null;\n};\n\n(FooterSlot as React.FC & { displayName?: string }).displayName =\n\t\"Support.Footer\";\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"slots.js","names":["React","SlotProvider: React.FC<SlotProviderProps>","HeaderSlot: React.FC<SlotProps>","FooterSlot: React.FC<SlotProps>"],"sources":["../../../src/support/context/slots.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\n// =============================================================================\n// Slot Types\n// =============================================================================\n\nexport type SlotContextValue = {\n\t/**\n\t * Custom header slot content\n\t */\n\theader: React.ReactNode | null;\n\t/**\n\t * Custom footer slot content\n\t */\n\tfooter: React.ReactNode | null;\n\t/**\n\t * Whether to use the custom header\n\t */\n\thasCustomHeader: boolean;\n\t/**\n\t * Whether to use the custom footer\n\t */\n\thasCustomFooter: boolean;\n};\n\ntype SlotRegistration = {\n\tregisterHeader: (content: React.ReactNode) => void;\n\tregisterFooter: (content: React.ReactNode) => void;\n\tunregisterHeader: () => void;\n\tunregisterFooter: () => void;\n};\n\nconst SlotContext = React.createContext<SlotContextValue>({\n\theader: null,\n\tfooter: null,\n\thasCustomHeader: false,\n\thasCustomFooter: false,\n});\n\nconst SlotRegistrationContext = React.createContext<SlotRegistration | null>(\n\tnull\n);\n\n// =============================================================================\n// Provider\n// =============================================================================\n\nexport type SlotProviderProps = {\n\tchildren: React.ReactNode;\n};\n\n/**\n * Provider for slot-based customization.\n * Allows children to register custom header/footer content.\n */\nexport const SlotProvider: React.FC<SlotProviderProps> = ({ children }) => {\n\tconst [header, setHeader] = React.useState<React.ReactNode | null>(null);\n\tconst [footer, setFooter] = React.useState<React.ReactNode | null>(null);\n\n\tconst registration = React.useMemo<SlotRegistration>(\n\t\t() => ({\n\t\t\tregisterHeader: (content) => setHeader(content),\n\t\t\tregisterFooter: (content) => setFooter(content),\n\t\t\tunregisterHeader: () => setHeader(null),\n\t\t\tunregisterFooter: () => setFooter(null),\n\t\t}),\n\t\t[]\n\t);\n\n\tconst value = React.useMemo<SlotContextValue>(\n\t\t() => ({\n\t\t\theader,\n\t\t\tfooter,\n\t\t\thasCustomHeader: header !== null,\n\t\t\thasCustomFooter: footer !== null,\n\t\t}),\n\t\t[header, footer]\n\t);\n\n\treturn (\n\t\t<SlotRegistrationContext.Provider value={registration}>\n\t\t\t<SlotContext.Provider value={value}>{children}</SlotContext.Provider>\n\t\t</SlotRegistrationContext.Provider>\n\t);\n};\n\n// =============================================================================\n// Hooks\n// =============================================================================\n\n/**\n * Access slot values (for content component)\n */\nexport function useSlots(): SlotContextValue {\n\treturn React.useContext(SlotContext);\n}\n\n/**\n * Access slot registration (for slot components)\n */\nfunction useSlotRegistration(): SlotRegistration | null {\n\treturn React.useContext(SlotRegistrationContext);\n}\n\n// =============================================================================\n// Slot Components\n// =============================================================================\n\nexport type SlotProps = {\n\t/**\n\t * Content to render in the slot.\n\t */\n\tchildren: React.ReactNode;\n\t/**\n\t * When true, renders children directly without a wrapper.\n\t * Useful when you want your component to receive all props.\n\t */\n\tasChild?: boolean;\n};\n\n/**\n * Header slot component.\n * Use inside Support.Content to replace the default header.\n *\n * @example\n * <Support.Content>\n * <Support.Header>\n * <MyCustomHeader />\n * </Support.Header>\n * <Support.Router />\n * </Support.Content>\n *\n * @example\n * // With asChild pattern\n * <Support.Header asChild>\n * <MyCustomHeader showBackButton />\n * </Support.Header>\n */\nexport const HeaderSlot: React.FC<SlotProps> = ({ children, asChild }) => {\n\tconst registration = useSlotRegistration();\n\n\tReact.useEffect(() => {\n\t\tif (registration) {\n\t\t\tregistration.registerHeader(children);\n\t\t\treturn () => registration.unregisterHeader();\n\t\t}\n\t}, [registration, children]);\n\n\t// This component doesn't render anything directly\n\t// It registers its children as the header slot\n\treturn null;\n};\n\n(HeaderSlot as React.FC & { displayName?: string }).displayName =\n\t\"Support.Header\";\n\n/**\n * Footer slot component.\n * Use inside Support.Content to replace the default footer.\n *\n * @example\n * <Support.Content>\n * <Support.Router />\n * <Support.Footer>\n * <MyCustomFooter />\n * </Support.Footer>\n * </Support.Content>\n *\n * @example\n * // With asChild pattern\n * <Support.Footer asChild>\n * <MyCustomFooter showBranding={false} />\n * </Support.Footer>\n */\nexport const FooterSlot: React.FC<SlotProps> = ({ children, asChild }) => {\n\tconst registration = useSlotRegistration();\n\n\tReact.useEffect(() => {\n\t\tif (registration) {\n\t\t\tregistration.registerFooter(children);\n\t\t\treturn () => registration.unregisterFooter();\n\t\t}\n\t}, [registration, children]);\n\n\t// This component doesn't render anything directly\n\t// It registers its children as the footer slot\n\treturn null;\n};\n\n(FooterSlot as React.FC & { displayName?: string }).displayName =\n\t\"Support.Footer\";\n"],"mappings":";;;;;;AAkCA,MAAM,cAAcA,QAAM,cAAgC;CACzD,QAAQ;CACR,QAAQ;CACR,iBAAiB;CACjB,iBAAiB;CACjB,CAAC;AAEF,MAAM,0BAA0BA,QAAM,cACrC,KACA;;;;;AAcD,MAAaC,gBAA6C,EAAE,eAAe;CAC1E,MAAM,CAAC,QAAQ,aAAaD,QAAM,SAAiC,KAAK;CACxE,MAAM,CAAC,QAAQ,aAAaA,QAAM,SAAiC,KAAK;CAExE,MAAM,eAAeA,QAAM,eACnB;EACN,iBAAiB,YAAY,UAAU,QAAQ;EAC/C,iBAAiB,YAAY,UAAU,QAAQ;EAC/C,wBAAwB,UAAU,KAAK;EACvC,wBAAwB,UAAU,KAAK;EACvC,GACD,EAAE,CACF;CAED,MAAM,QAAQA,QAAM,eACZ;EACN;EACA;EACA,iBAAiB,WAAW;EAC5B,iBAAiB,WAAW;EAC5B,GACD,CAAC,QAAQ,OAAO,CAChB;AAED,QACC,oBAAC,wBAAwB;EAAS,OAAO;YACxC,oBAAC,YAAY;GAAgB;GAAQ;IAAgC;GACnC;;;;;AAWrC,SAAgB,WAA6B;AAC5C,QAAOA,QAAM,WAAW,YAAY;;;;;AAMrC,SAAS,sBAA+C;AACvD,QAAOA,QAAM,WAAW,wBAAwB;;;;;;;;;;;;;;;;;;;;AAqCjD,MAAaE,cAAmC,EAAE,UAAU,cAAc;CACzE,MAAM,eAAe,qBAAqB;AAE1C,SAAM,gBAAgB;AACrB,MAAI,cAAc;AACjB,gBAAa,eAAe,SAAS;AACrC,gBAAa,aAAa,kBAAkB;;IAE3C,CAAC,cAAc,SAAS,CAAC;AAI5B,QAAO;;AAGR,AAAC,WAAmD,cACnD;;;;;;;;;;;;;;;;;;;AAoBD,MAAaC,cAAmC,EAAE,UAAU,cAAc;CACzE,MAAM,eAAe,qBAAqB;AAE1C,SAAM,gBAAgB;AACrB,MAAI,cAAc;AACjB,gBAAa,eAAe,SAAS;AACrC,gBAAa,aAAa,kBAAkB;;IAE3C,CAAC,cAAc,SAAS,CAAC;AAI5B,QAAO;;AAGR,AAAC,WAAmD,cACnD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket.js","names":["WebSocketBridge: React.FC<WebSocketBridgeProps>","intervalId: number | null","WebSocketProvider: React.FC<WebSocketProviderProps>"],"sources":["../../../src/support/context/websocket.tsx"],"sourcesContent":["\"use client\";\n\nimport { PRESENCE_PING_INTERVAL_MS } from \"@cossistant/types\";\nimport type React from \"react\";\nimport { createContext, useContext, useEffect, useMemo } from \"react\";\nimport {\n\ttype RealtimeAuthConfig,\n\ttype RealtimeContextValue,\n\tRealtimeProvider,\n\tuseRealtimeConnection,\n} from \"../../realtime\";\n\ntype WebSocketContextValue = RealtimeContextValue;\n\ntype WebSocketProviderProps = {\n\tchildren: React.ReactNode;\n\tpublicKey?: string;\n\twebsiteId?: string;\n\tvisitorId?: string;\n\twsUrl?: string;\n\tautoConnect?: boolean;\n\tonConnect?: () => void;\n\tonDisconnect?: () => void;\n\tonError?: (error: Error) => void;\n};\n\nconst WebSocketContext = createContext<WebSocketContextValue | null>(null);\n\nfunction createVisitorAuthConfig({\n\tvisitorId,\n\twebsiteId,\n\tpublicKey,\n}: Pick<\n\tWebSocketProviderProps,\n\t\"visitorId\" | \"websiteId\" | \"publicKey\"\n>): RealtimeAuthConfig | null {\n\tconst normalizedVisitorId = visitorId?.trim();\n\tif (!normalizedVisitorId) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tkind: \"visitor\",\n\t\tvisitorId: normalizedVisitorId,\n\t\twebsiteId: websiteId?.trim() || null,\n\t\tpublicKey: publicKey?.trim() || null,\n\t} satisfies RealtimeAuthConfig;\n}\n\ntype WebSocketBridgeProps = {\n\tchildren: React.ReactNode;\n\tonError?: (error: Error) => void;\n};\n\nconst WebSocketBridge: React.FC<WebSocketBridgeProps> = ({\n\tchildren,\n\tonError,\n}) => {\n\tconst connection = useRealtimeConnection();\n\tconst { visitorId, sendRaw, isConnected } = connection;\n\n\tuseEffect(() => {\n\t\tif (typeof window === \"undefined\" || typeof document === \"undefined\") {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!(visitorId && sendRaw)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst pingMessage = \"presence:ping\";\n\n\t\tconst sendPresencePing = () => {\n\t\t\tif (!isConnected) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tsendRaw(pingMessage);\n\t\t\t} catch (error) {\n\t\t\t\tif (!onError) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst normalizedError =\n\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t? error\n\t\t\t\t\t\t: new Error(\n\t\t\t\t\t\t\t\ttypeof error === \"string\"\n\t\t\t\t\t\t\t\t\t? error\n\t\t\t\t\t\t\t\t\t: \"Unknown presence ping error\"\n\t\t\t\t\t\t\t);\n\n\t\t\t\tif (!normalizedError.message.includes(\"Failed to send presence ping\")) {\n\t\t\t\t\tnormalizedError.message = `Failed to send presence ping: ${normalizedError.message}`;\n\t\t\t\t}\n\n\t\t\t\tonError(normalizedError);\n\t\t\t}\n\t\t};\n\n\t\tlet intervalId: number | null = null;\n\n\t\tconst clearPresenceInterval = () => {\n\t\t\tif (intervalId !== null) {\n\t\t\t\twindow.clearInterval(intervalId);\n\t\t\t\tintervalId = null;\n\t\t\t}\n\t\t};\n\n\t\tconst startPresenceInterval = () => {\n\t\t\tclearPresenceInterval();\n\n\t\t\tif (!isConnected || document.visibilityState === \"hidden\") {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tintervalId = window.setInterval(\n\t\t\t\tsendPresencePing,\n\t\t\t\tPRESENCE_PING_INTERVAL_MS\n\t\t\t);\n\t\t};\n\n\t\tconst handleFocus = () => {\n\t\t\tsendPresencePing();\n\t\t\tstartPresenceInterval();\n\t\t};\n\n\t\tconst handleVisibilityChange = () => {\n\t\t\tif (document.visibilityState === \"hidden\") {\n\t\t\t\tclearPresenceInterval();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsendPresencePing();\n\t\t\tstartPresenceInterval();\n\t\t};\n\n\t\twindow.addEventListener(\"focus\", handleFocus);\n\t\tdocument.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n\t\tif (isConnected && document.visibilityState !== \"hidden\") {\n\t\t\tsendPresencePing();\n\t\t\tstartPresenceInterval();\n\t\t}\n\n\t\treturn () => {\n\t\t\twindow.removeEventListener(\"focus\", handleFocus);\n\t\t\tdocument.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n\t\t\tclearPresenceInterval();\n\t\t};\n\t}, [isConnected, onError, sendRaw, visitorId]);\n\tconst value = useMemo(() => connection, [connection]);\n\treturn (\n\t\t<WebSocketContext.Provider value={value}>\n\t\t\t{children}\n\t\t</WebSocketContext.Provider>\n\t);\n};\n\n/**\n * Support-specific realtime provider that authenticates visitors and keeps the\n * connection alive with presence pings.\n */\nexport const WebSocketProvider: React.FC<WebSocketProviderProps> = ({\n\tchildren,\n\tpublicKey,\n\twebsiteId,\n\tvisitorId,\n\twsUrl,\n\tautoConnect = true,\n\tonConnect,\n\tonDisconnect,\n\tonError,\n}) => {\n\tconst auth = createVisitorAuthConfig({ publicKey, websiteId, visitorId });\n\n\treturn (\n\t\t<RealtimeProvider\n\t\t\tauth={auth}\n\t\t\tautoConnect={autoConnect}\n\t\t\tonConnect={onConnect}\n\t\t\tonDisconnect={onDisconnect}\n\t\t\tonError={onError}\n\t\t\twsUrl={wsUrl}\n\t\t>\n\t\t\t<WebSocketBridge onError={onError}>{children}</WebSocketBridge>\n\t\t</RealtimeProvider>\n\t);\n};\n\n/**\n * Accessor for the support websocket context.\n * Throws if used outside WebSocketProvider.\n */\nexport const useWebSocket = (): WebSocketContextValue => {\n\tconst context = useContext(WebSocketContext);\n\tif (!context) {\n\t\tthrow new Error(\"useWebSocket must be used within WebSocketProvider\");\n\t}\n\treturn context;\n};\n\n/**\n * Safe accessor for the support websocket context.\n * Returns null if used outside WebSocketProvider instead of throwing.\n * Useful for optional WebSocket usage in hooks that may or may not have the provider.\n */\nexport const useWebSocketSafe = (): WebSocketContextValue | null =>\n\tuseContext(WebSocketContext);\n\nexport type { WebSocketContextValue, WebSocketProviderProps };\nexport type { RealtimeEvent } from \"@cossistant/types/realtime-events\";\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"websocket.js","names":["WebSocketBridge: React.FC<WebSocketBridgeProps>","intervalId: number | null","WebSocketProvider: React.FC<WebSocketProviderProps>"],"sources":["../../../src/support/context/websocket.tsx"],"sourcesContent":["\"use client\";\n\nimport { PRESENCE_PING_INTERVAL_MS } from \"@cossistant/types\";\nimport type React from \"react\";\nimport { createContext, useContext, useEffect, useMemo } from \"react\";\nimport {\n\ttype RealtimeAuthConfig,\n\ttype RealtimeContextValue,\n\tRealtimeProvider,\n\tuseRealtimeConnection,\n} from \"../../realtime\";\n\ntype WebSocketContextValue = RealtimeContextValue;\n\ntype WebSocketProviderProps = {\n\tchildren: React.ReactNode;\n\tpublicKey?: string;\n\twebsiteId?: string;\n\tvisitorId?: string;\n\twsUrl?: string;\n\tautoConnect?: boolean;\n\tonConnect?: () => void;\n\tonDisconnect?: () => void;\n\tonError?: (error: Error) => void;\n};\n\nconst WebSocketContext = createContext<WebSocketContextValue | null>(null);\n\nfunction createVisitorAuthConfig({\n\tvisitorId,\n\twebsiteId,\n\tpublicKey,\n}: Pick<\n\tWebSocketProviderProps,\n\t\"visitorId\" | \"websiteId\" | \"publicKey\"\n>): RealtimeAuthConfig | null {\n\tconst normalizedVisitorId = visitorId?.trim();\n\tif (!normalizedVisitorId) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tkind: \"visitor\",\n\t\tvisitorId: normalizedVisitorId,\n\t\twebsiteId: websiteId?.trim() || null,\n\t\tpublicKey: publicKey?.trim() || null,\n\t} satisfies RealtimeAuthConfig;\n}\n\ntype WebSocketBridgeProps = {\n\tchildren: React.ReactNode;\n\tonError?: (error: Error) => void;\n};\n\nconst WebSocketBridge: React.FC<WebSocketBridgeProps> = ({\n\tchildren,\n\tonError,\n}) => {\n\tconst connection = useRealtimeConnection();\n\tconst { visitorId, sendRaw, isConnected } = connection;\n\n\tuseEffect(() => {\n\t\tif (typeof window === \"undefined\" || typeof document === \"undefined\") {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!(visitorId && sendRaw)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst pingMessage = \"presence:ping\";\n\n\t\tconst sendPresencePing = () => {\n\t\t\tif (!isConnected) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tsendRaw(pingMessage);\n\t\t\t} catch (error) {\n\t\t\t\tif (!onError) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst normalizedError =\n\t\t\t\t\terror instanceof Error\n\t\t\t\t\t\t? error\n\t\t\t\t\t\t: new Error(\n\t\t\t\t\t\t\t\ttypeof error === \"string\"\n\t\t\t\t\t\t\t\t\t? error\n\t\t\t\t\t\t\t\t\t: \"Unknown presence ping error\"\n\t\t\t\t\t\t\t);\n\n\t\t\t\tif (!normalizedError.message.includes(\"Failed to send presence ping\")) {\n\t\t\t\t\tnormalizedError.message = `Failed to send presence ping: ${normalizedError.message}`;\n\t\t\t\t}\n\n\t\t\t\tonError(normalizedError);\n\t\t\t}\n\t\t};\n\n\t\tlet intervalId: number | null = null;\n\n\t\tconst clearPresenceInterval = () => {\n\t\t\tif (intervalId !== null) {\n\t\t\t\twindow.clearInterval(intervalId);\n\t\t\t\tintervalId = null;\n\t\t\t}\n\t\t};\n\n\t\tconst startPresenceInterval = () => {\n\t\t\tclearPresenceInterval();\n\n\t\t\tif (!isConnected || document.visibilityState === \"hidden\") {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tintervalId = window.setInterval(\n\t\t\t\tsendPresencePing,\n\t\t\t\tPRESENCE_PING_INTERVAL_MS\n\t\t\t);\n\t\t};\n\n\t\tconst handleFocus = () => {\n\t\t\tsendPresencePing();\n\t\t\tstartPresenceInterval();\n\t\t};\n\n\t\tconst handleVisibilityChange = () => {\n\t\t\tif (document.visibilityState === \"hidden\") {\n\t\t\t\tclearPresenceInterval();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsendPresencePing();\n\t\t\tstartPresenceInterval();\n\t\t};\n\n\t\twindow.addEventListener(\"focus\", handleFocus);\n\t\tdocument.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n\t\tif (isConnected && document.visibilityState !== \"hidden\") {\n\t\t\tsendPresencePing();\n\t\t\tstartPresenceInterval();\n\t\t}\n\n\t\treturn () => {\n\t\t\twindow.removeEventListener(\"focus\", handleFocus);\n\t\t\tdocument.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n\t\t\tclearPresenceInterval();\n\t\t};\n\t}, [isConnected, onError, sendRaw, visitorId]);\n\tconst value = useMemo(() => connection, [connection]);\n\treturn (\n\t\t<WebSocketContext.Provider value={value}>\n\t\t\t{children}\n\t\t</WebSocketContext.Provider>\n\t);\n};\n\n/**\n * Support-specific realtime provider that authenticates visitors and keeps the\n * connection alive with presence pings.\n */\nexport const WebSocketProvider: React.FC<WebSocketProviderProps> = ({\n\tchildren,\n\tpublicKey,\n\twebsiteId,\n\tvisitorId,\n\twsUrl,\n\tautoConnect = true,\n\tonConnect,\n\tonDisconnect,\n\tonError,\n}) => {\n\tconst auth = createVisitorAuthConfig({ publicKey, websiteId, visitorId });\n\n\treturn (\n\t\t<RealtimeProvider\n\t\t\tauth={auth}\n\t\t\tautoConnect={autoConnect}\n\t\t\tonConnect={onConnect}\n\t\t\tonDisconnect={onDisconnect}\n\t\t\tonError={onError}\n\t\t\twsUrl={wsUrl}\n\t\t>\n\t\t\t<WebSocketBridge onError={onError}>{children}</WebSocketBridge>\n\t\t</RealtimeProvider>\n\t);\n};\n\n/**\n * Accessor for the support websocket context.\n * Throws if used outside WebSocketProvider.\n */\nexport const useWebSocket = (): WebSocketContextValue => {\n\tconst context = useContext(WebSocketContext);\n\tif (!context) {\n\t\tthrow new Error(\"useWebSocket must be used within WebSocketProvider\");\n\t}\n\treturn context;\n};\n\n/**\n * Safe accessor for the support websocket context.\n * Returns null if used outside WebSocketProvider instead of throwing.\n * Useful for optional WebSocket usage in hooks that may or may not have the provider.\n */\nexport const useWebSocketSafe = (): WebSocketContextValue | null =>\n\tuseContext(WebSocketContext);\n\nexport type { WebSocketContextValue, WebSocketProviderProps };\nexport type { RealtimeEvent } from \"@cossistant/types/realtime-events\";\n"],"mappings":";;;;;;;;AA0BA,MAAM,mBAAmB,cAA4C,KAAK;AAE1E,SAAS,wBAAwB,EAChC,WACA,WACA,aAI6B;CAC7B,MAAM,sBAAsB,WAAW,MAAM;AAC7C,KAAI,CAAC,oBACJ,QAAO;AAGR,QAAO;EACN,MAAM;EACN,WAAW;EACX,WAAW,WAAW,MAAM,IAAI;EAChC,WAAW,WAAW,MAAM,IAAI;EAChC;;AAQF,MAAMA,mBAAmD,EACxD,UACA,cACK;CACL,MAAM,aAAa,uBAAuB;CAC1C,MAAM,EAAE,WAAW,SAAS,gBAAgB;AAE5C,iBAAgB;AACf,MAAI,OAAO,WAAW,eAAe,OAAO,aAAa,YACxD;AAGD,MAAI,EAAE,aAAa,SAClB;EAGD,MAAM,cAAc;EAEpB,MAAM,yBAAyB;AAC9B,OAAI,CAAC,YACJ;AAGD,OAAI;AACH,YAAQ,YAAY;YACZ,OAAO;AACf,QAAI,CAAC,QACJ;IAGD,MAAM,kBACL,iBAAiB,QACd,QACA,IAAI,MACJ,OAAO,UAAU,WACd,QACA,8BACH;AAEJ,QAAI,CAAC,gBAAgB,QAAQ,SAAS,+BAA+B,CACpE,iBAAgB,UAAU,iCAAiC,gBAAgB;AAG5E,YAAQ,gBAAgB;;;EAI1B,IAAIC,aAA4B;EAEhC,MAAM,8BAA8B;AACnC,OAAI,eAAe,MAAM;AACxB,WAAO,cAAc,WAAW;AAChC,iBAAa;;;EAIf,MAAM,8BAA8B;AACnC,0BAAuB;AAEvB,OAAI,CAAC,eAAe,SAAS,oBAAoB,SAChD;AAGD,gBAAa,OAAO,YACnB,kBACA,0BACA;;EAGF,MAAM,oBAAoB;AACzB,qBAAkB;AAClB,0BAAuB;;EAGxB,MAAM,+BAA+B;AACpC,OAAI,SAAS,oBAAoB,UAAU;AAC1C,2BAAuB;AACvB;;AAGD,qBAAkB;AAClB,0BAAuB;;AAGxB,SAAO,iBAAiB,SAAS,YAAY;AAC7C,WAAS,iBAAiB,oBAAoB,uBAAuB;AAErE,MAAI,eAAe,SAAS,oBAAoB,UAAU;AACzD,qBAAkB;AAClB,0BAAuB;;AAGxB,eAAa;AACZ,UAAO,oBAAoB,SAAS,YAAY;AAChD,YAAS,oBAAoB,oBAAoB,uBAAuB;AACxE,0BAAuB;;IAEtB;EAAC;EAAa;EAAS;EAAS;EAAU,CAAC;CAC9C,MAAM,QAAQ,cAAc,YAAY,CAAC,WAAW,CAAC;AACrD,QACC,oBAAC,iBAAiB;EAAgB;EAChC;GAC0B;;;;;;AAQ9B,MAAaC,qBAAuD,EACnE,UACA,WACA,WACA,WACA,OACA,cAAc,MACd,WACA,cACA,cACK;AAGL,QACC,oBAAC;EACA,MAJW,wBAAwB;GAAE;GAAW;GAAW;GAAW,CAAC;EAK1D;EACF;EACG;EACL;EACF;YAEP,oBAAC;GAAyB;GAAU;IAA2B;GAC7C;;;;;;AAQrB,MAAa,qBAA4C;CACxD,MAAM,UAAU,WAAW,iBAAiB;AAC5C,KAAI,CAAC,QACJ,OAAM,IAAI,MAAM,qDAAqD;AAEtE,QAAO;;;;;;;AAQR,MAAa,yBACZ,WAAW,iBAAiB"}
|
package/support/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/support/index.tsx"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/support/index.tsx"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;KAuCY,qCAAqC;;;;;;;;;SAUzC;EAVI;;;;EAmCQ,KAAA,CAAA,EAnBX,KAmBW;EA+CD;;;;EAeJ,UAAA,CAAA,EAAA,MAAA;EASgB;;;;;EA4BnB,eAAM,CAAA,EAAA,OAAA;EAAS;AAwO3B;;;EAAkC,gBAAA,CAAA,EA3Ud,gBA2Uc;EAQtB;;;EAAiE,UAAA,CAAA,EAAA;IAsCjE,OAAA,CAAA,EAAA,MAAA;IAMJ,OAAA,CAAA,EAAA,MAAA;EAKC,CAAA;EAgBW;;;EA4CR,KAAA,CAAA,EAAA,OAAA,GAAA,MAAkB;EAsClB;;;;;EAMwC,IAAA,CAAA,EAAA,OAAA;EADxC;;AAuBZ;;;;;;EA6CW,YAAM,CAAA,EAAA,CAAA,IAAA,EAAA,OAAA,EAAA,GAAA,IAAA;EAAS;AA+G1B;;;;EA1ViD,WAAA,CAAA,EAAA,OAAA;EAAV;;;;;;;oBArRpB;;;;EAoS2C,MAAM,CAAA,EA/R1D,MA+R0D;;;;YA1RzD,4BAA4B;;;;gBAKxB;;;;gCASgB;;;;8BAKF;;;;0BAKJ;;;;8BAKI;;;;oBAKV;;;;;;;aAQP,OAAA,CAAM;;KAwON,mBAAA,GAAsB,KACjC,OAAA,CAAM,qBAAqB;;;;;aAOhB,OAAA,CAAM,qBAAqB,uBAAuB,OAAA,CAAM;;;;;;;KAsCxD,mBAAA;;;;;;SAMJ;;;;;UAKC;;;;;;;;;;;;;;;;qBAgBW;aACR,OAAA,CAAM;;KA2CN,kBAAA;;;;gBAIG;;;;aAIH,OAAA,CAAM;;KA8BN,iCAAgB,iBAAA,CAEO,sBAAa,iBAAA,CAAoC;QAE7E;aACK,OAAA,CAAM;aADV,iBAAA,CAE8B,aAAA,CAAc;;;KAsBxC,gBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCA4BmB;;;;8BAIF;;;;0BAIJ;;;;8BAII;;;;oBAIV;YACR,OAAA,CAAM;;cA+GJ,mCA5VS,sBAEd,aAAa;QAAkB,OAAA,CAAM,IAAI;MAC5C,OAAA,CAAM;;;;;;;eAcC,OAAA,CAAM,qBAAqB,uBAAuB,OAAA,CAAM"}
|