@cossistant/react 0.0.4 → 0.0.5
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/_virtual/rolldown_runtime.js +19 -0
- package/conversation.d.ts +26 -3
- package/conversation.d.ts.map +1 -1
- package/hooks/index.d.ts +5 -3
- package/hooks/index.js +7 -5
- package/hooks/private/store/use-conversations-store.d.ts +8 -0
- package/hooks/private/store/use-conversations-store.d.ts.map +1 -1
- package/hooks/private/store/use-conversations-store.js +8 -0
- package/hooks/private/store/use-conversations-store.js.map +1 -1
- package/hooks/private/store/use-store-selector.d.ts +4 -0
- package/hooks/private/store/use-store-selector.d.ts.map +1 -1
- package/hooks/private/store/use-store-selector.js +5 -2
- package/hooks/private/store/use-store-selector.js.map +1 -1
- package/hooks/private/store/use-website-store.d.ts +4 -0
- package/hooks/private/store/use-website-store.d.ts.map +1 -1
- package/hooks/private/store/use-website-store.js +6 -3
- package/hooks/private/store/use-website-store.js.map +1 -1
- package/hooks/private/typing.d.ts +35 -0
- package/hooks/private/typing.d.ts.map +1 -0
- package/hooks/private/typing.js +49 -0
- package/hooks/private/typing.js.map +1 -0
- package/hooks/private/use-client-query.d.ts +5 -0
- package/hooks/private/use-client-query.d.ts.map +1 -1
- package/hooks/private/use-client-query.js +5 -0
- package/hooks/private/use-client-query.js.map +1 -1
- package/hooks/private/use-grouped-messages.d.ts +10 -4
- package/hooks/private/use-grouped-messages.d.ts.map +1 -1
- package/hooks/private/use-grouped-messages.js +24 -4
- package/hooks/private/use-grouped-messages.js.map +1 -1
- package/hooks/private/use-multimodal-input.d.ts.map +1 -1
- package/hooks/private/use-rest-client.d.ts.map +1 -1
- package/hooks/private/use-visitor-typing-reporter.d.ts +6 -0
- package/hooks/private/use-visitor-typing-reporter.d.ts.map +1 -1
- package/hooks/private/use-visitor-typing-reporter.js +6 -0
- package/hooks/private/use-visitor-typing-reporter.js.map +1 -1
- package/hooks/use-composer-refocus.d.ts.map +1 -1
- package/hooks/use-conversation-auto-seen.d.ts +9 -0
- package/hooks/use-conversation-auto-seen.d.ts.map +1 -1
- package/hooks/use-conversation-auto-seen.js +44 -3
- package/hooks/use-conversation-auto-seen.js.map +1 -1
- package/hooks/use-conversation-history-page.d.ts.map +1 -1
- package/hooks/use-conversation-history-page.js +16 -18
- package/hooks/use-conversation-history-page.js.map +1 -1
- package/hooks/use-conversation-lifecycle.d.ts.map +1 -1
- package/hooks/use-conversation-lifecycle.js +2 -4
- package/hooks/use-conversation-lifecycle.js.map +1 -1
- package/hooks/use-conversation-page.d.ts +6 -0
- package/hooks/use-conversation-page.d.ts.map +1 -1
- package/hooks/use-conversation-page.js +41 -3
- package/hooks/use-conversation-page.js.map +1 -1
- package/hooks/use-conversation-preview.d.ts +61 -0
- package/hooks/use-conversation-preview.d.ts.map +1 -0
- package/hooks/use-conversation-preview.js +173 -0
- package/hooks/use-conversation-preview.js.map +1 -0
- package/hooks/use-conversation-seen.d.ts +4 -0
- package/hooks/use-conversation-seen.d.ts.map +1 -1
- package/hooks/use-conversation-seen.js +4 -0
- package/hooks/use-conversation-seen.js.map +1 -1
- package/hooks/use-conversation-timeline-items.d.ts +4 -0
- package/hooks/use-conversation-timeline-items.d.ts.map +1 -1
- package/hooks/use-conversation-timeline-items.js +4 -0
- package/hooks/use-conversation-timeline-items.js.map +1 -1
- package/hooks/use-conversation-timeline.d.ts +32 -0
- package/hooks/use-conversation-timeline.d.ts.map +1 -0
- package/hooks/use-conversation-timeline.js +41 -0
- package/hooks/use-conversation-timeline.js.map +1 -0
- package/hooks/use-conversation-typing.d.ts +4 -0
- package/hooks/use-conversation-typing.d.ts.map +1 -1
- package/hooks/use-conversation-typing.js +4 -0
- package/hooks/use-conversation-typing.js.map +1 -1
- package/hooks/use-conversation.d.ts +11 -0
- package/hooks/use-conversation.d.ts.map +1 -1
- package/hooks/use-conversation.js +11 -0
- package/hooks/use-conversation.js.map +1 -1
- package/hooks/use-conversations.d.ts +12 -0
- package/hooks/use-conversations.d.ts.map +1 -1
- package/hooks/use-conversations.js +12 -0
- package/hooks/use-conversations.js.map +1 -1
- package/hooks/use-create-conversation.d.ts +5 -0
- package/hooks/use-create-conversation.d.ts.map +1 -1
- package/hooks/use-create-conversation.js +12 -9
- package/hooks/use-create-conversation.js.map +1 -1
- package/hooks/use-home-page.d.ts.map +1 -1
- package/hooks/use-home-page.js +6 -4
- package/hooks/use-home-page.js.map +1 -1
- package/hooks/use-message-composer.d.ts.map +1 -1
- package/hooks/use-realtime-support.d.ts.map +1 -1
- package/hooks/use-send-message.d.ts +9 -0
- package/hooks/use-send-message.d.ts.map +1 -1
- package/hooks/use-send-message.js +15 -13
- package/hooks/use-send-message.js.map +1 -1
- package/hooks/use-visitor.d.ts.map +1 -1
- package/hooks/use-visitor.js +28 -30
- package/hooks/use-visitor.js.map +1 -1
- package/hooks/use-window-visibility-focus.d.ts +4 -0
- package/hooks/use-window-visibility-focus.d.ts.map +1 -1
- package/hooks/use-window-visibility-focus.js +5 -2
- package/hooks/use-window-visibility-focus.js.map +1 -1
- package/identify-visitor.d.ts +12 -3
- package/identify-visitor.d.ts.map +1 -1
- package/identify-visitor.js +58 -9
- package/identify-visitor.js.map +1 -1
- package/index.d.ts +10 -7
- package/index.js +10 -9
- package/package.json +11 -16
- package/primitives/avatar/avatar.d.ts.map +1 -1
- package/primitives/avatar/fallback.d.ts.map +1 -1
- package/primitives/avatar/fallback.js +1 -3
- package/primitives/avatar/fallback.js.map +1 -1
- package/primitives/avatar/image.d.ts.map +1 -1
- package/primitives/avatar/index.d.ts +1 -0
- package/primitives/bubble.d.ts +2 -0
- package/primitives/bubble.d.ts.map +1 -1
- package/primitives/bubble.js +8 -2
- package/primitives/bubble.js.map +1 -1
- package/primitives/button.d.ts.map +1 -1
- package/primitives/conversation-timeline.d.ts.map +1 -1
- package/primitives/conversation-timeline.js +58 -5
- package/primitives/conversation-timeline.js.map +1 -1
- package/primitives/index.d.ts +1 -0
- package/primitives/index.parts.d.ts +1 -0
- package/primitives/multimodal-input.d.ts.map +1 -1
- package/primitives/timeline-item-group.d.ts +7 -7
- package/primitives/timeline-item-group.d.ts.map +1 -1
- 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 +7 -1
- package/primitives/timeline-item.js.map +1 -1
- package/primitives/window.d.ts +1 -1
- package/primitives/window.d.ts.map +1 -1
- package/primitives/window.js +4 -4
- package/primitives/window.js.map +1 -1
- package/provider.d.ts +23 -43
- package/provider.d.ts.map +1 -1
- package/provider.js +152 -49
- package/provider.js.map +1 -1
- package/realtime/event-filter.d.ts +4 -0
- package/realtime/event-filter.d.ts.map +1 -1
- package/realtime/event-filter.js +4 -0
- package/realtime/event-filter.js.map +1 -1
- package/realtime/index.js +1 -1
- package/realtime/provider.d.ts +7 -2
- package/realtime/provider.d.ts.map +1 -1
- package/realtime/provider.js +23 -1
- package/realtime/provider.js.map +1 -1
- package/realtime/seen-store.d.ts +13 -0
- package/realtime/seen-store.d.ts.map +1 -1
- package/realtime/seen-store.js +14 -2
- package/realtime/seen-store.js.map +1 -1
- package/realtime/support-provider.d.ts +1 -2
- package/realtime/support-provider.d.ts.map +1 -1
- package/realtime/support-provider.js +19 -20
- package/realtime/support-provider.js.map +1 -1
- package/realtime/typing-store.d.ts +18 -0
- package/realtime/typing-store.d.ts.map +1 -1
- package/realtime/typing-store.js +19 -2
- package/realtime/typing-store.js.map +1 -1
- package/realtime/use-realtime.d.ts +8 -4
- package/realtime/use-realtime.d.ts.map +1 -1
- package/realtime/use-realtime.js +4 -0
- package/realtime/use-realtime.js.map +1 -1
- package/realtime-events.d.ts +17 -3
- package/realtime-events.d.ts.map +1 -1
- package/schemas.d.ts +7 -1
- package/schemas.d.ts.map +1 -1
- package/support/components/avatar-stack.d.ts +8 -4
- package/support/components/avatar-stack.d.ts.map +1 -1
- package/support/components/avatar-stack.js +4 -0
- package/support/components/avatar-stack.js.map +1 -1
- package/support/components/avatar.d.ts +11 -6
- package/support/components/avatar.d.ts.map +1 -1
- package/support/components/avatar.js +4 -0
- package/support/components/avatar.js.map +1 -1
- package/support/components/bubble.d.ts.map +1 -1
- package/support/components/bubble.js +29 -6
- package/support/components/bubble.js.map +1 -1
- package/support/components/button.d.ts +8 -5
- package/support/components/button.d.ts.map +1 -1
- package/support/components/button.js +5 -1
- package/support/components/button.js.map +1 -1
- package/support/components/container.d.ts +0 -1
- package/support/components/container.d.ts.map +1 -1
- package/support/components/container.js +2 -8
- package/support/components/container.js.map +1 -1
- package/support/components/conversation-button-link.d.ts +8 -21
- package/support/components/conversation-button-link.d.ts.map +1 -1
- package/support/components/conversation-button-link.js +62 -178
- 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 +4 -0
- package/support/components/conversation-event.js.map +1 -1
- package/support/components/conversation-timeline.d.ts +10 -1
- package/support/components/conversation-timeline.d.ts.map +1 -1
- package/support/components/conversation-timeline.js +63 -57
- package/support/components/conversation-timeline.js.map +1 -1
- package/support/components/cossistant-branding.d.ts +5 -2
- package/support/components/cossistant-branding.d.ts.map +1 -1
- package/support/components/cossistant-branding.js +3 -0
- package/support/components/cossistant-branding.js.map +1 -1
- package/support/components/header.d.ts.map +1 -1
- package/support/components/header.js +2 -2
- package/support/components/header.js.map +1 -1
- package/support/components/icons.d.ts.map +1 -1
- package/support/components/multimodal-input.d.ts.map +1 -1
- package/support/components/multimodal-input.js +5 -24
- package/support/components/multimodal-input.js.map +1 -1
- package/support/components/navigation-tab.d.ts +7 -2
- package/support/components/navigation-tab.d.ts.map +1 -1
- package/support/components/navigation-tab.js +4 -0
- package/support/components/navigation-tab.js.map +1 -1
- package/support/components/support-content.d.ts +1 -1
- package/support/components/support-content.d.ts.map +1 -1
- package/support/components/support-content.js +7 -10
- package/support/components/support-content.js.map +1 -1
- package/support/components/text-effect.d.ts +5 -2
- package/support/components/text-effect.d.ts.map +1 -1
- package/support/components/text-effect.js +4 -0
- package/support/components/text-effect.js.map +1 -1
- package/support/components/timeline-identification-tool.d.ts +7 -0
- package/support/components/timeline-identification-tool.d.ts.map +1 -0
- package/support/components/timeline-identification-tool.js +139 -0
- package/support/components/timeline-identification-tool.js.map +1 -0
- package/support/components/timeline-message-group.d.ts +2 -1
- package/support/components/timeline-message-group.d.ts.map +1 -1
- package/support/components/timeline-message-group.js +4 -19
- package/support/components/timeline-message-group.js.map +1 -1
- package/support/components/timeline-message-item.d.ts +6 -2
- package/support/components/timeline-message-item.d.ts.map +1 -1
- package/support/components/timeline-message-item.js +8 -4
- package/support/components/timeline-message-item.js.map +1 -1
- package/support/components/typing-indicator.d.ts +5 -2
- package/support/components/typing-indicator.d.ts.map +1 -1
- package/support/components/typing-indicator.js +4 -4
- package/support/components/typing-indicator.js.map +1 -1
- package/support/components/watermark.d.ts.map +1 -1
- package/support/context/websocket.d.ts +8 -0
- package/support/context/websocket.d.ts.map +1 -1
- package/support/context/websocket.js +12 -6
- package/support/context/websocket.js.map +1 -1
- package/support/index.d.ts +8 -8
- package/support/index.d.ts.map +1 -1
- package/support/index.js +18 -18
- package/support/index.js.map +1 -1
- package/support/pages/conversation-history.js +46 -54
- package/support/pages/conversation-history.js.map +1 -1
- package/support/pages/conversation.d.ts +3 -6
- package/support/pages/conversation.d.ts.map +1 -1
- package/support/pages/conversation.js +19 -9
- package/support/pages/conversation.js.map +1 -1
- package/support/pages/home.d.ts +2 -2
- package/support/pages/home.d.ts.map +1 -1
- package/support/pages/home.js +64 -77
- package/support/pages/home.js.map +1 -1
- package/support/store/support-store.d.ts +18 -2
- package/support/store/support-store.d.ts.map +1 -1
- package/support/store/support-store.js +20 -5
- package/support/store/support-store.js.map +1 -1
- package/support/{support-CMoDLQoC.css → support-Ck4jy29i.css} +1 -2
- package/support/support-Ck4jy29i.css.map +1 -0
- package/support/text/index.d.ts +15 -2
- package/support/text/index.d.ts.map +1 -1
- package/support/text/index.js +15 -2
- package/support/text/index.js.map +1 -1
- package/support/text/locales/en.js +22 -4
- package/support/text/locales/en.js.map +1 -1
- package/support/text/locales/es.js +18 -0
- package/support/text/locales/es.js.map +1 -1
- package/support/text/locales/fr.js +18 -0
- package/support/text/locales/fr.js.map +1 -1
- package/support/text/locales/keys.d.ts +69 -9
- package/support/text/locales/keys.d.ts.map +1 -1
- package/support/text/locales/keys.js +18 -0
- package/support/text/locales/keys.js.map +1 -1
- package/support/text/runtime.d.ts +21 -0
- package/support/text/runtime.d.ts.map +1 -1
- package/support/text/runtime.js +21 -0
- package/support/text/runtime.js.map +1 -1
- package/support/utils/index.d.ts +4 -0
- package/support/utils/index.d.ts.map +1 -1
- package/support/utils/index.js +4 -1
- package/support/utils/index.js.map +1 -1
- package/support/utils/time.d.ts +3 -0
- package/support/utils/time.d.ts.map +1 -1
- package/support/utils/time.js +3 -0
- package/support/utils/time.js.map +1 -1
- package/support-config.d.ts +2 -1
- package/support-config.d.ts.map +1 -1
- package/support-config.js.map +1 -1
- package/support.css +2 -2
- package/timeline-item.d.ts +10 -0
- package/timeline-item.d.ts.map +1 -1
- package/utils/conversation.d.ts +7 -0
- package/utils/conversation.d.ts.map +1 -0
- package/utils/conversation.js +18 -0
- package/utils/conversation.js.map +1 -0
- package/utils/id.d.ts +3 -0
- package/utils/id.d.ts.map +1 -1
- package/utils/id.js +3 -0
- package/utils/id.js.map +1 -1
- package/utils/index.d.ts +2 -1
- package/utils/index.js +2 -1
- package/utils/metadata-hash.d.ts +12 -0
- package/utils/metadata-hash.d.ts.map +1 -0
- package/utils/metadata-hash.js +26 -0
- package/utils/metadata-hash.js.map +1 -0
- package/utils/text.d.ts +3 -0
- package/utils/text.d.ts.map +1 -1
- package/utils/text.js +3 -0
- package/utils/text.js.map +1 -1
- package/utils/use-render-element.d.ts +3 -0
- package/utils/use-render-element.d.ts.map +1 -1
- package/utils/use-render-element.js +3 -0
- package/utils/use-render-element.js.map +1 -1
- package/support/context/config.d.ts +0 -32
- package/support/context/config.d.ts.map +0 -1
- package/support/context/config.js +0 -27
- package/support/context/config.js.map +0 -1
- package/support/support-CMoDLQoC.css.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-window-visibility-focus.js","names":[],"sources":["../../src/hooks/use-window-visibility-focus.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nexport type WindowVisibilityFocusState = {\n
|
|
1
|
+
{"version":3,"file":"use-window-visibility-focus.js","names":[],"sources":["../../src/hooks/use-window-visibility-focus.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nexport type WindowVisibilityFocusState = {\n\tisPageVisible: boolean;\n\thasWindowFocus: boolean;\n};\n\nconst getVisibilityFocusState = (): WindowVisibilityFocusState => {\n\tif (typeof document === \"undefined\") {\n\t\treturn { isPageVisible: true, hasWindowFocus: true };\n\t}\n\n\tconst isPageVisible = !document.hidden;\n\tconst hasWindowFocus =\n\t\tisPageVisible &&\n\t\t(typeof document.hasFocus === \"function\" ? document.hasFocus() : true);\n\n\treturn { isPageVisible, hasWindowFocus };\n};\n\n/**\n * Tracks document visibility and window focus so hooks can defer updates while\n * the user is away from the page.\n */\nexport function useWindowVisibilityFocus(): WindowVisibilityFocusState {\n\tconst [state, setState] = useState<WindowVisibilityFocusState>(() =>\n\t\tgetVisibilityFocusState()\n\t);\n\n\tuseEffect(() => {\n\t\tif (typeof document === \"undefined\") {\n\t\t\treturn;\n\t\t}\n\n\t\tconst handleVisibilityChange = () => {\n\t\t\tsetState(getVisibilityFocusState());\n\t\t};\n\n\t\tdocument.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\t\thandleVisibilityChange();\n\t\treturn () => {\n\t\t\tdocument.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n\t\t};\n\t}, []);\n\n\tuseEffect(() => {\n\t\tif (typeof window === \"undefined\") {\n\t\t\treturn;\n\t\t}\n\n\t\tconst syncVisibilityFocus = () => {\n\t\t\tsetState(getVisibilityFocusState());\n\t\t};\n\n\t\tconst handleFocus = () => {\n\t\t\tsyncVisibilityFocus();\n\t\t};\n\t\tconst handleBlur = () => {\n\t\t\tsyncVisibilityFocus();\n\t\t};\n\n\t\twindow.addEventListener(\"focus\", handleFocus);\n\t\twindow.addEventListener(\"blur\", handleBlur);\n\n\t\tsyncVisibilityFocus();\n\n\t\treturn () => {\n\t\t\twindow.removeEventListener(\"focus\", handleFocus);\n\t\t\twindow.removeEventListener(\"blur\", handleBlur);\n\t\t};\n\t}, []);\n\n\treturn state;\n}\n"],"mappings":";;;AAOA,MAAM,gCAA4D;AACjE,KAAI,OAAO,aAAa,YACvB,QAAO;EAAE,eAAe;EAAM,gBAAgB;EAAM;CAGrD,MAAM,gBAAgB,CAAC,SAAS;AAKhC,QAAO;EAAE;EAAe,gBAHvB,kBACC,OAAO,SAAS,aAAa,aAAa,SAAS,UAAU,GAAG;EAE1B;;;;;;AAOzC,SAAgB,2BAAuD;CACtE,MAAM,CAAC,OAAO,YAAY,eACzB,yBAAyB,CACzB;AAED,iBAAgB;AACf,MAAI,OAAO,aAAa,YACvB;EAGD,MAAM,+BAA+B;AACpC,YAAS,yBAAyB,CAAC;;AAGpC,WAAS,iBAAiB,oBAAoB,uBAAuB;AACrE,0BAAwB;AACxB,eAAa;AACZ,YAAS,oBAAoB,oBAAoB,uBAAuB;;IAEvE,EAAE,CAAC;AAEN,iBAAgB;AACf,MAAI,OAAO,WAAW,YACrB;EAGD,MAAM,4BAA4B;AACjC,YAAS,yBAAyB,CAAC;;EAGpC,MAAM,oBAAoB;AACzB,wBAAqB;;EAEtB,MAAM,mBAAmB;AACxB,wBAAqB;;AAGtB,SAAO,iBAAiB,SAAS,YAAY;AAC7C,SAAO,iBAAiB,QAAQ,WAAW;AAE3C,uBAAqB;AAErB,eAAa;AACZ,UAAO,oBAAoB,SAAS,YAAY;AAChD,UAAO,oBAAoB,QAAQ,WAAW;;IAE7C,EAAE,CAAC;AAEN,QAAO"}
|
package/identify-visitor.d.ts
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
|
+
import { ReactElement } from "react";
|
|
2
|
+
import { VisitorMetadata } from "@cossistant/types";
|
|
3
|
+
|
|
1
4
|
//#region src/identify-visitor.d.ts
|
|
2
5
|
type IdentifySupportVisitorProps = {
|
|
3
6
|
externalId?: string;
|
|
4
7
|
email?: string;
|
|
8
|
+
name?: string | null;
|
|
9
|
+
image?: string | null;
|
|
10
|
+
metadata?: VisitorMetadata | null;
|
|
5
11
|
};
|
|
6
12
|
/**
|
|
7
|
-
* Component exposed by Cossistant allowing you to identify a visitor whenever rendered with either an `externalId` or `email`.
|
|
13
|
+
* Component exposed by Cossistant allowing you to identify a visitor whenever rendered with either an `externalId` or `email`. Once identified, the visitor will be associated with a contact and any subsequent metadata updates will be attached to this contact.
|
|
8
14
|
*/
|
|
9
15
|
declare const IdentifySupportVisitor: {
|
|
10
16
|
({
|
|
11
17
|
externalId,
|
|
12
|
-
email
|
|
13
|
-
|
|
18
|
+
email,
|
|
19
|
+
name,
|
|
20
|
+
image,
|
|
21
|
+
metadata: _newMetadata
|
|
22
|
+
}: IdentifySupportVisitorProps): ReactElement | null;
|
|
14
23
|
displayName: string;
|
|
15
24
|
};
|
|
16
25
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identify-visitor.d.ts","names":[],"sources":["../src/identify-visitor.tsx"],"sourcesContent":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"identify-visitor.d.ts","names":[],"sources":["../src/identify-visitor.tsx"],"sourcesContent":[],"mappings":";;;;KAOY,2BAAA;EAAA,UAAA,CAAA,EAAA,MAAA;EAWC,KAAA,CAAA,EAAA,MAAA;;;aAND;;;;;AAYiC,cANhC,sBAMgC,EAAA;;;;;;;KAA1C,8BAA8B"}
|
package/identify-visitor.js
CHANGED
|
@@ -1,21 +1,70 @@
|
|
|
1
1
|
import { useVisitor } from "./hooks/use-visitor.js";
|
|
2
|
-
import {
|
|
2
|
+
import { computeMetadataHash } from "./utils/metadata-hash.js";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
3
4
|
|
|
4
5
|
//#region src/identify-visitor.tsx
|
|
5
6
|
/**
|
|
6
|
-
* Component exposed by Cossistant allowing you to identify a visitor whenever rendered with either an `externalId` or `email`.
|
|
7
|
+
* Component exposed by Cossistant allowing you to identify a visitor whenever rendered with either an `externalId` or `email`. Once identified, the visitor will be associated with a contact and any subsequent metadata updates will be attached to this contact.
|
|
7
8
|
*/
|
|
8
|
-
const IdentifySupportVisitor = ({ externalId, email }) => {
|
|
9
|
-
const { visitor, identify } = useVisitor();
|
|
9
|
+
const IdentifySupportVisitor = ({ externalId, email, name, image, metadata: _newMetadata }) => {
|
|
10
|
+
const { visitor, identify, setVisitorMetadata } = useVisitor();
|
|
11
|
+
const [hasIdentified, setHasIdentified] = useState(false);
|
|
12
|
+
const [lastMetadataHash, setLastMetadataHash] = useState(null);
|
|
10
13
|
useEffect(() => {
|
|
11
|
-
|
|
12
|
-
externalId
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
const shouldIdentify = async () => {
|
|
15
|
+
if (!Boolean(externalId || email)) return;
|
|
16
|
+
if (!visitor?.contact) {
|
|
17
|
+
if (!hasIdentified) {
|
|
18
|
+
await identify({
|
|
19
|
+
externalId,
|
|
20
|
+
email,
|
|
21
|
+
name: name ?? void 0,
|
|
22
|
+
image: image ?? void 0
|
|
23
|
+
});
|
|
24
|
+
setHasIdentified(true);
|
|
25
|
+
}
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const contact = visitor.contact;
|
|
29
|
+
const nameChanged = name !== void 0 && name !== contact.name;
|
|
30
|
+
const emailChanged = email !== void 0 && email !== contact.email;
|
|
31
|
+
const imageChanged = image !== void 0 && image !== contact.image;
|
|
32
|
+
if (nameChanged || emailChanged || imageChanged) await identify({
|
|
33
|
+
externalId,
|
|
34
|
+
email,
|
|
35
|
+
name: name ?? void 0,
|
|
36
|
+
image: image ?? void 0
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
shouldIdentify();
|
|
15
40
|
}, [
|
|
16
41
|
visitor?.contact,
|
|
17
42
|
externalId,
|
|
18
|
-
email
|
|
43
|
+
email,
|
|
44
|
+
name,
|
|
45
|
+
image,
|
|
46
|
+
identify,
|
|
47
|
+
hasIdentified
|
|
48
|
+
]);
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
const updateMetadata = async () => {
|
|
51
|
+
if (!_newMetadata) return;
|
|
52
|
+
if (!visitor?.contact) return;
|
|
53
|
+
const newMetadataHash = await computeMetadataHash(_newMetadata);
|
|
54
|
+
const hashChanged = newMetadataHash !== (visitor.contact.metadataHash || "");
|
|
55
|
+
const notAlreadyUpdated = newMetadataHash !== lastMetadataHash;
|
|
56
|
+
if (Boolean(newMetadataHash && hashChanged && notAlreadyUpdated)) {
|
|
57
|
+
await setVisitorMetadata(_newMetadata);
|
|
58
|
+
setLastMetadataHash(newMetadataHash);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
updateMetadata();
|
|
62
|
+
}, [
|
|
63
|
+
_newMetadata,
|
|
64
|
+
visitor?.contact?.metadataHash,
|
|
65
|
+
visitor?.contact,
|
|
66
|
+
setVisitorMetadata,
|
|
67
|
+
lastMetadataHash
|
|
19
68
|
]);
|
|
20
69
|
return null;
|
|
21
70
|
};
|
package/identify-visitor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identify-visitor.js","names":[],"sources":["../src/identify-visitor.tsx"],"sourcesContent":["/** biome-ignore-all lint/correctness/useExhaustiveDependencies: wanted here */\nimport { useEffect } from \"react\";\nimport { useVisitor } from \"./hooks\";\n\nexport type IdentifySupportVisitorProps = {\n\texternalId?: string;\n\temail?: string;\n};\n\n/**\n * Component exposed by Cossistant allowing you to identify a visitor whenever rendered with either an `externalId` or `email
|
|
1
|
+
{"version":3,"file":"identify-visitor.js","names":[],"sources":["../src/identify-visitor.tsx"],"sourcesContent":["/** biome-ignore-all lint/correctness/useExhaustiveDependencies: wanted here */\n\nimport type { VisitorMetadata } from \"@cossistant/types\";\nimport { type ReactElement, useEffect, useState } from \"react\";\nimport { useVisitor } from \"./hooks\";\nimport { computeMetadataHash } from \"./utils/metadata-hash\";\n\nexport type IdentifySupportVisitorProps = {\n\texternalId?: string;\n\temail?: string;\n\tname?: string | null;\n\timage?: string | null;\n\tmetadata?: VisitorMetadata | null;\n};\n\n/**\n * Component exposed by Cossistant allowing you to identify a visitor whenever rendered with either an `externalId` or `email`. Once identified, the visitor will be associated with a contact and any subsequent metadata updates will be attached to this contact.\n */\nexport const IdentifySupportVisitor = ({\n\texternalId,\n\temail,\n\tname,\n\timage,\n\tmetadata: _newMetadata,\n}: IdentifySupportVisitorProps): ReactElement | null => {\n\tconst { visitor, identify, setVisitorMetadata } = useVisitor();\n\tconst [hasIdentified, setHasIdentified] = useState(false);\n\tconst [lastMetadataHash, setLastMetadataHash] = useState<string | null>(null);\n\n\t// Only call identify if:\n\t// 1. Visitor hasn't been identified yet (no contact)\n\t// 2. Name, email, or image changed compared to current contact\n\tuseEffect(() => {\n\t\tconst shouldIdentify = async () => {\n\t\t\tconst hasIdentificationData = Boolean(externalId || email);\n\n\t\t\t// Need at least externalId or email to identify\n\t\t\tif (!hasIdentificationData) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Case 1: No contact exists yet\n\t\t\tif (!visitor?.contact) {\n\t\t\t\tif (!hasIdentified) {\n\t\t\t\t\tawait identify({\n\t\t\t\t\t\texternalId,\n\t\t\t\t\t\temail,\n\t\t\t\t\t\tname: name ?? undefined,\n\t\t\t\t\t\timage: image ?? undefined,\n\t\t\t\t\t});\n\t\t\t\t\tsetHasIdentified(true);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Case 2: Contact exists but name/email/image changed\n\t\t\tconst contact = visitor.contact;\n\t\t\tconst nameChanged = name !== undefined && name !== contact.name;\n\t\t\tconst emailChanged = email !== undefined && email !== contact.email;\n\t\t\tconst imageChanged = image !== undefined && image !== contact.image;\n\t\t\tconst hasChanges = nameChanged || emailChanged || imageChanged;\n\n\t\t\tif (hasChanges) {\n\t\t\t\tawait identify({\n\t\t\t\t\texternalId,\n\t\t\t\t\temail,\n\t\t\t\t\tname: name ?? undefined,\n\t\t\t\t\timage: image ?? undefined,\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\tshouldIdentify();\n\t}, [\n\t\tvisitor?.contact,\n\t\texternalId,\n\t\temail,\n\t\tname,\n\t\timage,\n\t\tidentify,\n\t\thasIdentified,\n\t]);\n\n\t// Compute metadata hash, compare to previous hash and only update if it has changed\n\tuseEffect(() => {\n\t\tconst updateMetadata = async () => {\n\t\t\t// Skip if no metadata provided or visitor doesn't have a contact\n\t\t\tif (!_newMetadata) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!visitor?.contact) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Compute new metadata hash\n\t\t\tconst newMetadataHash = await computeMetadataHash(_newMetadata);\n\n\t\t\t// Get the existing hash from the contact\n\t\t\tconst existingHash = visitor.contact.metadataHash || \"\";\n\n\t\t\t// Only update if hashes don't match and we haven't already updated with this hash\n\t\t\tconst hashChanged = newMetadataHash !== existingHash;\n\t\t\tconst notAlreadyUpdated = newMetadataHash !== lastMetadataHash;\n\t\t\tconst shouldUpdate = Boolean(\n\t\t\t\tnewMetadataHash && hashChanged && notAlreadyUpdated\n\t\t\t);\n\n\t\t\tif (shouldUpdate) {\n\t\t\t\tawait setVisitorMetadata(_newMetadata);\n\t\t\t\tsetLastMetadataHash(newMetadataHash);\n\t\t\t}\n\t\t};\n\n\t\tupdateMetadata();\n\t}, [\n\t\t_newMetadata,\n\t\tvisitor?.contact?.metadataHash,\n\t\tvisitor?.contact,\n\t\tsetVisitorMetadata,\n\t\tlastMetadataHash,\n\t]);\n\n\treturn null;\n};\n\nIdentifySupportVisitor.displayName = \"IdentifySupportVisitor\";\n"],"mappings":";;;;;;;;AAkBA,MAAa,0BAA0B,EACtC,YACA,OACA,MACA,OACA,UAAU,mBAC6C;CACvD,MAAM,EAAE,SAAS,UAAU,uBAAuB,YAAY;CAC9D,MAAM,CAAC,eAAe,oBAAoB,SAAS,MAAM;CACzD,MAAM,CAAC,kBAAkB,uBAAuB,SAAwB,KAAK;AAK7E,iBAAgB;EACf,MAAM,iBAAiB,YAAY;AAIlC,OAAI,CAH0B,QAAQ,cAAc,MAAM,CAIzD;AAID,OAAI,CAAC,SAAS,SAAS;AACtB,QAAI,CAAC,eAAe;AACnB,WAAM,SAAS;MACd;MACA;MACA,MAAM,QAAQ;MACd,OAAO,SAAS;MAChB,CAAC;AACF,sBAAiB,KAAK;;AAEvB;;GAID,MAAM,UAAU,QAAQ;GACxB,MAAM,cAAc,SAAS,UAAa,SAAS,QAAQ;GAC3D,MAAM,eAAe,UAAU,UAAa,UAAU,QAAQ;GAC9D,MAAM,eAAe,UAAU,UAAa,UAAU,QAAQ;AAG9D,OAFmB,eAAe,gBAAgB,aAGjD,OAAM,SAAS;IACd;IACA;IACA,MAAM,QAAQ;IACd,OAAO,SAAS;IAChB,CAAC;;AAIJ,kBAAgB;IACd;EACF,SAAS;EACT;EACA;EACA;EACA;EACA;EACA;EACA,CAAC;AAGF,iBAAgB;EACf,MAAM,iBAAiB,YAAY;AAElC,OAAI,CAAC,aACJ;AAGD,OAAI,CAAC,SAAS,QACb;GAID,MAAM,kBAAkB,MAAM,oBAAoB,aAAa;GAM/D,MAAM,cAAc,qBAHC,QAAQ,QAAQ,gBAAgB;GAIrD,MAAM,oBAAoB,oBAAoB;AAK9C,OAJqB,QACpB,mBAAmB,eAAe,kBAClC,EAEiB;AACjB,UAAM,mBAAmB,aAAa;AACtC,wBAAoB,gBAAgB;;;AAItC,kBAAgB;IACd;EACF;EACA,SAAS,SAAS;EAClB,SAAS;EACT;EACA;EACA,CAAC;AAEF,QAAO;;AAGR,uBAAuB,cAAc"}
|
package/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useClientQuery } from "./hooks/private/use-client-query.js";
|
|
2
2
|
import { useDefaultMessages } from "./hooks/private/use-default-messages.js";
|
|
3
|
-
import { ConversationItem, GroupedMessage, TimelineEventItem, UseGroupedMessagesOptions, UseGroupedMessagesProps, useGroupedMessages } from "./hooks/private/use-grouped-messages.js";
|
|
3
|
+
import { ConversationItem, GroupedMessage, TimelineEventItem, TimelineToolItem, UseGroupedMessagesOptions, UseGroupedMessagesProps, useGroupedMessages } from "./hooks/private/use-grouped-messages.js";
|
|
4
4
|
import { UseMultimodalInputOptions, UseMultimodalInputReturn, useMultimodalInput } from "./hooks/private/use-multimodal-input.js";
|
|
5
5
|
import { UseClientResult, useClient } from "./hooks/private/use-rest-client.js";
|
|
6
6
|
import { UseComposerRefocusOptions, UseComposerRefocusReturn, useComposerRefocus } from "./hooks/use-composer-refocus.js";
|
|
@@ -9,9 +9,12 @@ import { CONVERSATION_AUTO_SEEN_DELAY_MS, UseConversationAutoSeenOptions, useCon
|
|
|
9
9
|
import { UseConversationHistoryPageOptions, UseConversationHistoryPageReturn, useConversationHistoryPage } from "./hooks/use-conversation-history-page.js";
|
|
10
10
|
import { ConversationLifecycleState, UseConversationLifecycleOptions, UseConversationLifecycleReturn, useConversationLifecycle } from "./hooks/use-conversation-lifecycle.js";
|
|
11
11
|
import { UseConversationPageOptions, UseConversationPageReturn, useConversationPage } from "./hooks/use-conversation-page.js";
|
|
12
|
-
import {
|
|
12
|
+
import { SupportLocale, SupportTextContentOverrides } from "./support/text/locales/keys.js";
|
|
13
13
|
import { UseConversationTimelineItemsOptions, UseConversationTimelineItemsResult, useConversationTimelineItems } from "./hooks/use-conversation-timeline-items.js";
|
|
14
|
+
import { ConversationPreviewAssignedAgent, ConversationPreviewLastMessage, ConversationPreviewTypingParticipant, ConversationPreviewTypingState, UseConversationPreviewOptions, UseConversationPreviewReturn, useConversationPreview } from "./hooks/use-conversation-preview.js";
|
|
15
|
+
import { useConversationSeen, useDebouncedConversationSeen } from "./hooks/use-conversation-seen.js";
|
|
14
16
|
import { ConversationTypingParticipant, useConversationTyping } from "./hooks/use-conversation-typing.js";
|
|
17
|
+
import { ConversationTimelineTypingParticipant, UseConversationTimelineOptions, UseConversationTimelineReturn, useConversationTimeline } from "./hooks/use-conversation-timeline.js";
|
|
15
18
|
import { UseConversationsOptions, UseConversationsResult, useConversations } from "./hooks/use-conversations.js";
|
|
16
19
|
import { CreateConversationVariables, UseCreateConversationOptions, UseCreateConversationResult, useCreateConversation } from "./hooks/use-create-conversation.js";
|
|
17
20
|
import { UseHomePageOptions, UseHomePageReturn, useHomePage } from "./hooks/use-home-page.js";
|
|
@@ -20,19 +23,19 @@ import { UseRealtimeSupportOptions, UseRealtimeSupportResult, useRealtimeSupport
|
|
|
20
23
|
import { SendMessageOptions, SendMessageResult, UseSendMessageOptions, UseSendMessageResult, useSendMessage } from "./hooks/use-send-message.js";
|
|
21
24
|
import { UseVisitorReturn, useVisitor } from "./hooks/use-visitor.js";
|
|
22
25
|
import { WindowVisibilityFocusState, useWindowVisibilityFocus } from "./hooks/use-window-visibility-focus.js";
|
|
26
|
+
import "./hooks/index.js";
|
|
23
27
|
import { IdentifySupportVisitor, IdentifySupportVisitorProps } from "./identify-visitor.js";
|
|
24
28
|
import { SupportConfig, SupportConfigProps } from "./support-config.js";
|
|
25
29
|
import { index_d_exports } from "./primitives/index.js";
|
|
26
|
-
import { CossistantContextValue, CossistantProviderProps, SupportProvider, SupportProviderProps, useSupport } from "./provider.js";
|
|
30
|
+
import { CossistantContextValue, CossistantProviderProps, SupportContext, SupportProvider, SupportProviderProps, UseSupportValue, useSupport } from "./provider.js";
|
|
27
31
|
import { RealtimeAuthConfig, RealtimeContextValue, RealtimeProvider, RealtimeProviderProps, useRealtimeConnection } from "./realtime/provider.js";
|
|
28
32
|
import { applyConversationSeenEvent, hydrateConversationSeen, upsertConversationSeen } from "./realtime/seen-store.js";
|
|
29
33
|
import { SupportRealtimeProvider } from "./realtime/support-provider.js";
|
|
30
34
|
import { applyConversationTypingEvent, clearTypingFromTimelineItem, clearTypingState, setTypingState } from "./realtime/typing-store.js";
|
|
31
35
|
import { RealtimeEventHandler, RealtimeEventHandlerEntry, RealtimeEventHandlersMap, RealtimeEventMeta, useRealtime } from "./realtime/use-realtime.js";
|
|
32
|
-
import
|
|
36
|
+
import "./realtime/index.js";
|
|
33
37
|
import { Text, useSupportText } from "./support/text/index.js";
|
|
34
|
-
import { useSupportConfig } from "./support/context/config.js";
|
|
35
38
|
import { WebSocketContextValue, WebSocketProvider, useWebSocket } from "./support/context/websocket.js";
|
|
36
|
-
import { useSupportStore } from "./support/store/support-store.js";
|
|
39
|
+
import { useSupportConfig, useSupportNavigation, useSupportStore } from "./support/store/support-store.js";
|
|
37
40
|
import { Support, SupportProps } from "./support/index.js";
|
|
38
|
-
export { CONVERSATION_AUTO_SEEN_DELAY_MS, ConversationItem, ConversationLifecycleState, ConversationTypingParticipant, CossistantContextValue, CossistantProviderProps, CreateConversationVariables, GroupedMessage, IdentifySupportVisitor, IdentifySupportVisitorProps, index_d_exports as Primitives, RealtimeAuthConfig, RealtimeContextValue, RealtimeEventHandler, RealtimeEventHandlerEntry, RealtimeEventHandlersMap, RealtimeEventMeta, RealtimeProvider, RealtimeProviderProps, SendMessageOptions, SendMessageResult, Support, SupportConfig, SupportConfigProps, SupportLocale, SupportProps, SupportProvider, SupportProviderProps, SupportRealtimeProvider, SupportTextContentOverrides, Text, TimelineEventItem, UseClientResult, UseComposerRefocusOptions, UseComposerRefocusReturn, UseConversationAutoSeenOptions, UseConversationHistoryPageOptions, UseConversationHistoryPageReturn, UseConversationLifecycleOptions, UseConversationLifecycleReturn, UseConversationOptions, UseConversationPageOptions, UseConversationPageReturn, UseConversationResult, UseConversationTimelineItemsOptions, UseConversationTimelineItemsResult, UseConversationsOptions, UseConversationsResult, UseCreateConversationOptions, UseCreateConversationResult, UseGroupedMessagesOptions, UseGroupedMessagesProps, UseHomePageOptions, UseHomePageReturn, UseMessageComposerOptions, UseMessageComposerReturn, UseMultimodalInputOptions, UseMultimodalInputReturn, UseRealtimeSupportOptions, UseRealtimeSupportResult, UseSendMessageOptions, UseSendMessageResult, UseVisitorReturn, WebSocketContextValue, WebSocketProvider, WindowVisibilityFocusState, applyConversationSeenEvent, applyConversationTypingEvent, clearTypingFromTimelineItem, clearTypingState, hydrateConversationSeen, setTypingState, upsertConversationSeen, useClient, useClientQuery, useComposerRefocus, useConversation, useConversationAutoSeen, useConversationHistoryPage, useConversationLifecycle, useConversationPage, useConversationSeen, useConversationTimelineItems, useConversationTyping, useConversations, useCreateConversation, useDebouncedConversationSeen, useDefaultMessages, useGroupedMessages, useHomePage, useMessageComposer, useMultimodalInput, useRealtime, useRealtimeConnection, useRealtimeSupport, useSendMessage, useSupport, useSupportConfig, useSupportStore, useSupportText, useVisitor, useWebSocket, useWindowVisibilityFocus };
|
|
41
|
+
export { CONVERSATION_AUTO_SEEN_DELAY_MS, ConversationItem, ConversationLifecycleState, ConversationPreviewAssignedAgent, ConversationPreviewLastMessage, ConversationPreviewTypingParticipant, ConversationPreviewTypingState, ConversationTimelineTypingParticipant, ConversationTypingParticipant, CossistantContextValue, CossistantProviderProps, CreateConversationVariables, GroupedMessage, IdentifySupportVisitor, IdentifySupportVisitorProps, index_d_exports as Primitives, RealtimeAuthConfig, RealtimeContextValue, RealtimeEventHandler, RealtimeEventHandlerEntry, RealtimeEventHandlersMap, RealtimeEventMeta, RealtimeProvider, RealtimeProviderProps, SendMessageOptions, SendMessageResult, Support, SupportConfig, SupportConfigProps, SupportContext, SupportLocale, SupportProps, SupportProvider, SupportProviderProps, SupportRealtimeProvider, SupportTextContentOverrides, Text, TimelineEventItem, TimelineToolItem, UseClientResult, UseComposerRefocusOptions, UseComposerRefocusReturn, UseConversationAutoSeenOptions, UseConversationHistoryPageOptions, UseConversationHistoryPageReturn, UseConversationLifecycleOptions, UseConversationLifecycleReturn, UseConversationOptions, UseConversationPageOptions, UseConversationPageReturn, UseConversationPreviewOptions, UseConversationPreviewReturn, UseConversationResult, UseConversationTimelineItemsOptions, UseConversationTimelineItemsResult, UseConversationTimelineOptions, UseConversationTimelineReturn, UseConversationsOptions, UseConversationsResult, UseCreateConversationOptions, UseCreateConversationResult, UseGroupedMessagesOptions, UseGroupedMessagesProps, UseHomePageOptions, UseHomePageReturn, UseMessageComposerOptions, UseMessageComposerReturn, UseMultimodalInputOptions, UseMultimodalInputReturn, UseRealtimeSupportOptions, UseRealtimeSupportResult, UseSendMessageOptions, UseSendMessageResult, UseSupportValue, UseVisitorReturn, WebSocketContextValue, WebSocketProvider, WindowVisibilityFocusState, applyConversationSeenEvent, applyConversationTypingEvent, clearTypingFromTimelineItem, clearTypingState, hydrateConversationSeen, setTypingState, upsertConversationSeen, useClient, useClientQuery, useComposerRefocus, useConversation, useConversationAutoSeen, useConversationHistoryPage, useConversationLifecycle, useConversationPage, useConversationPreview, useConversationSeen, useConversationTimeline, useConversationTimelineItems, useConversationTyping, useConversations, useCreateConversation, useDebouncedConversationSeen, useDefaultMessages, useGroupedMessages, useHomePage, useMessageComposer, useMultimodalInput, useRealtime, useRealtimeConnection, useRealtimeSupport, useSendMessage, useSupport, useSupportConfig, useSupportNavigation, useSupportStore, useSupportText, useVisitor, useWebSocket, useWindowVisibilityFocus };
|
package/index.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { useClientQuery } from "./hooks/private/use-client-query.js";
|
|
2
2
|
import { useClient } from "./hooks/private/use-rest-client.js";
|
|
3
|
-
import { RealtimeProvider, useRealtimeConnection } from "./realtime/provider.js";
|
|
4
3
|
import { applyConversationSeenEvent, hydrateConversationSeen, upsertConversationSeen } from "./realtime/seen-store.js";
|
|
4
|
+
import { RealtimeProvider, useRealtimeConnection } from "./realtime/provider.js";
|
|
5
5
|
import { applyConversationTypingEvent, clearTypingFromTimelineItem, clearTypingState, setTypingState } from "./realtime/typing-store.js";
|
|
6
6
|
import { useRealtime } from "./realtime/use-realtime.js";
|
|
7
7
|
import { SupportRealtimeProvider } from "./realtime/support-provider.js";
|
|
8
8
|
import { SupportConfig } from "./support-config.js";
|
|
9
|
-
import { useSupportStore } from "./support/store/support-store.js";
|
|
10
|
-
import { useSupportConfig } from "./support/context/config.js";
|
|
9
|
+
import { useSupportConfig, useSupportNavigation, useSupportStore } from "./support/store/support-store.js";
|
|
11
10
|
import { primitives_exports } from "./primitives/index.js";
|
|
12
11
|
import { Text, useSupportText } from "./support/text/index.js";
|
|
12
|
+
import { useConversation } from "./hooks/use-conversation.js";
|
|
13
13
|
import { useWindowVisibilityFocus } from "./hooks/use-window-visibility-focus.js";
|
|
14
14
|
import { CONVERSATION_AUTO_SEEN_DELAY_MS, useConversationAutoSeen } from "./hooks/use-conversation-auto-seen.js";
|
|
15
15
|
import { useConversationLifecycle } from "./hooks/use-conversation-lifecycle.js";
|
|
@@ -19,20 +19,21 @@ import { useSendMessage } from "./hooks/use-send-message.js";
|
|
|
19
19
|
import { useMessageComposer } from "./hooks/use-message-composer.js";
|
|
20
20
|
import { useConversationPage } from "./hooks/use-conversation-page.js";
|
|
21
21
|
import { useGroupedMessages } from "./hooks/private/use-grouped-messages.js";
|
|
22
|
+
import { useConversationSeen, useDebouncedConversationSeen } from "./hooks/use-conversation-seen.js";
|
|
23
|
+
import { useConversationTyping } from "./hooks/use-conversation-typing.js";
|
|
24
|
+
import { useConversationTimeline } from "./hooks/use-conversation-timeline.js";
|
|
22
25
|
import { useComposerRefocus } from "./hooks/use-composer-refocus.js";
|
|
26
|
+
import { useVisitor } from "./hooks/use-visitor.js";
|
|
23
27
|
import { useConversations } from "./hooks/use-conversations.js";
|
|
24
28
|
import { useConversationHistoryPage } from "./hooks/use-conversation-history-page.js";
|
|
29
|
+
import { useConversationPreview } from "./hooks/use-conversation-preview.js";
|
|
25
30
|
import { useHomePage } from "./hooks/use-home-page.js";
|
|
26
31
|
import { WebSocketProvider, useWebSocket } from "./support/context/websocket.js";
|
|
27
32
|
import { Support } from "./support/index.js";
|
|
28
|
-
import { SupportProvider, useSupport } from "./provider.js";
|
|
33
|
+
import { SupportContext, SupportProvider, useSupport } from "./provider.js";
|
|
29
34
|
import { useDefaultMessages } from "./hooks/private/use-default-messages.js";
|
|
30
|
-
import { useConversation } from "./hooks/use-conversation.js";
|
|
31
|
-
import { useConversationSeen, useDebouncedConversationSeen } from "./hooks/use-conversation-seen.js";
|
|
32
|
-
import { useConversationTyping } from "./hooks/use-conversation-typing.js";
|
|
33
35
|
import { useCreateConversation } from "./hooks/use-create-conversation.js";
|
|
34
36
|
import { useRealtimeSupport } from "./hooks/use-realtime-support.js";
|
|
35
|
-
import { useVisitor } from "./hooks/use-visitor.js";
|
|
36
37
|
import { IdentifySupportVisitor } from "./identify-visitor.js";
|
|
37
38
|
|
|
38
|
-
export { CONVERSATION_AUTO_SEEN_DELAY_MS, IdentifySupportVisitor, primitives_exports as Primitives, RealtimeProvider, Support, SupportConfig, SupportProvider, SupportRealtimeProvider, Text, WebSocketProvider, applyConversationSeenEvent, applyConversationTypingEvent, clearTypingFromTimelineItem, clearTypingState, hydrateConversationSeen, setTypingState, upsertConversationSeen, useClient, useClientQuery, useComposerRefocus, useConversation, useConversationAutoSeen, useConversationHistoryPage, useConversationLifecycle, useConversationPage, useConversationSeen, useConversationTimelineItems, useConversationTyping, useConversations, useCreateConversation, useDebouncedConversationSeen, useDefaultMessages, useGroupedMessages, useHomePage, useMessageComposer, useMultimodalInput, useRealtime, useRealtimeConnection, useRealtimeSupport, useSendMessage, useSupport, useSupportConfig, useSupportStore, useSupportText, useVisitor, useWebSocket, useWindowVisibilityFocus };
|
|
39
|
+
export { CONVERSATION_AUTO_SEEN_DELAY_MS, IdentifySupportVisitor, primitives_exports as Primitives, RealtimeProvider, Support, SupportConfig, SupportContext, SupportProvider, SupportRealtimeProvider, Text, WebSocketProvider, applyConversationSeenEvent, applyConversationTypingEvent, clearTypingFromTimelineItem, clearTypingState, hydrateConversationSeen, setTypingState, upsertConversationSeen, useClient, useClientQuery, useComposerRefocus, useConversation, useConversationAutoSeen, useConversationHistoryPage, useConversationLifecycle, useConversationPage, useConversationPreview, useConversationSeen, useConversationTimeline, useConversationTimelineItems, useConversationTyping, useConversations, useCreateConversation, useDebouncedConversationSeen, useDefaultMessages, useGroupedMessages, useHomePage, useMessageComposer, useMultimodalInput, useRealtime, useRealtimeConnection, useRealtimeSupport, useSendMessage, useSupport, useSupportConfig, useSupportNavigation, useSupportStore, useSupportText, useVisitor, useWebSocket, useWindowVisibilityFocus };
|
package/package.json
CHANGED
|
@@ -1,27 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cossistant/react",
|
|
3
|
-
"
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.5",
|
|
4
5
|
"private": false,
|
|
5
6
|
"author": "Cossistant team",
|
|
6
7
|
"description": "Headless React SDK for building AI-powered support/chat widgets. Hooks + primitives, WS-driven, TypeScript-first. Next.js-ready, Tailwind optional.",
|
|
7
8
|
"keywords": [
|
|
8
9
|
"react",
|
|
9
|
-
"headless",
|
|
10
10
|
"headless-ui",
|
|
11
|
-
"support",
|
|
12
|
-
"
|
|
11
|
+
"support-widget",
|
|
12
|
+
"chat-widget",
|
|
13
|
+
"customer-support",
|
|
13
14
|
"helpdesk",
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"ai",
|
|
18
|
-
"ai support",
|
|
19
|
-
"ai-agent",
|
|
20
|
-
"support agent",
|
|
15
|
+
"live-chat",
|
|
16
|
+
"ai-support",
|
|
17
|
+
"websocket",
|
|
21
18
|
"typescript",
|
|
22
|
-
"nextjs",
|
|
23
19
|
"tailwind",
|
|
24
|
-
"shadcn",
|
|
25
20
|
"accessibility"
|
|
26
21
|
],
|
|
27
22
|
"bugs": {
|
|
@@ -56,10 +51,10 @@
|
|
|
56
51
|
"import": "./hooks/index.js"
|
|
57
52
|
},
|
|
58
53
|
"./hooks/*": {
|
|
59
|
-
"types": "./hooks
|
|
60
|
-
"import": "./hooks
|
|
54
|
+
"types": "./hooks/*.d.ts",
|
|
55
|
+
"import": "./hooks/*.js"
|
|
61
56
|
},
|
|
62
|
-
"./support.css": "./support
|
|
57
|
+
"./support.css": "./support.css",
|
|
63
58
|
"./realtime": {
|
|
64
59
|
"types": "./realtime/index.d.ts",
|
|
65
60
|
"import": "./realtime/index.js"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"avatar.d.ts","names":[],"sources":["../../../src/primitives/avatar/avatar.tsx"],"sourcesContent":[],"mappings":";;;KAGK,WAAA;;AAH0B,CAAA;AAOnB,KAAA,WAAA,GAAc,IAAH,CACtB,OAAA,CAAM,cADgB,CACD,eADC,CAAA,EAAA,UAAA,CAAA,GAAA;
|
|
1
|
+
{"version":3,"file":"avatar.d.ts","names":[],"sources":["../../../src/primitives/avatar/avatar.tsx"],"sourcesContent":[],"mappings":";;;KAGK,WAAA;;AAH0B,CAAA;AAOnB,KAAA,WAAA,GAAc,IAAH,CACtB,OAAA,CAAM,cADgB,CACD,eADC,CAAA,EAAA,UAAA,CAAA,GAAA;EACD,QAAA,CAAA,EAGV,OAAA,CAAM,SAHI;EAArB,OAAM,CAAA,EAAA,OAAA;EADmB,SAAA,CAAA,EAAA,MAAA;CAId;AAAe,UAKV,kBAAA,SAA2B,WALjB,CAAA;EAKV,0BAAmB,EAAA,CAAA,MAE1B,EAAA,WAFkC,CAAA,oBAAW,CAAA,EAAA,GAAA,IAAA;AAYvD;AAcA;;;;AA/BY,cAiBC,gBAjBK,EAAA,GAAA,GAiBW,kBAjBX;;;;;cA+BL,QAAM,OAAA,CAAA,0BAAA,KAAA,OAAA,CAAA,eAAA;aA/BP,OAAA,CAAM"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fallback.d.ts","names":[],"sources":["../../../src/primitives/avatar/fallback.tsx"],"sourcesContent":[],"mappings":";;;KASY,mBAAA,GAAsB,KACjC,OAAA,CAAM,eAAe;aAGV,OAAA,CAAM;EAJN,IAAA,CAAA,EAAA,MAAA;
|
|
1
|
+
{"version":3,"file":"fallback.d.ts","names":[],"sources":["../../../src/primitives/avatar/fallback.tsx"],"sourcesContent":[],"mappings":";;;KASY,mBAAA,GAAsB,KACjC,OAAA,CAAM,eAAe;aAGV,OAAA,CAAM;EAJN,IAAA,CAAA,EAAA,MAAA;EACU,OAAA,CAAA,EAAA,MAAA;EAArB,OAAM,CAAA,EAAA,OAAA;EAD2B,SAAA,CAAA,EAAA,MAAA;CAItB;;AA4BZ;;;AAA2B,cAAd,cAAc,EAAA,OAAA,CAAA,yBAAA,CAAA,IAAA,CAAA,OAAA,CAAA,cAAA,CAAA,eAAA,CAAA,EAAA,UAAA,CAAA,GAAA;EA5Bf,QAAM,CAAA,EAAN,OAAA,CAAM,SAAA;;;EA4BS,OAAA,CAAA,EAAA,OAAA;EAAA,SAAA,CAAA,EAAA,MAAA"}
|
|
@@ -7,9 +7,7 @@ const getInitials = (name) => {
|
|
|
7
7
|
const names = name.trim().split(" ");
|
|
8
8
|
if (names.length === 0) return "";
|
|
9
9
|
if (names.length === 1) return names[0]?.charAt(0).toUpperCase() || "";
|
|
10
|
-
|
|
11
|
-
const lastInitial = names[names.length - 1]?.charAt(0) || "";
|
|
12
|
-
return (firstInitial + lastInitial).toUpperCase();
|
|
10
|
+
return ((names[0]?.charAt(0) || "") + (names[names.length - 1]?.charAt(0) || "")).toUpperCase();
|
|
13
11
|
};
|
|
14
12
|
/**
|
|
15
13
|
* Displays initials or custom content while the avatar image loads or fails.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fallback.js","names":["React","state: FallbackState"],"sources":["../../../src/primitives/avatar/fallback.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { useRenderElement } from \"../../utils/use-render-element\";\nimport { useAvatarContext } from \"./avatar\";\n\ntype FallbackState = {\n\timageLoadingStatus: \"idle\" | \"loading\" | \"loaded\" | \"error\";\n\tinitials?: string;\n};\n\nexport type AvatarFallbackProps = Omit<\n\tReact.HTMLAttributes<HTMLSpanElement>,\n\t\"children\"\n> & {\n\tchildren?: React.ReactNode;\n\tname?: string;\n\tdelayMs?: number;\n\tasChild?: boolean;\n\tclassName?: string;\n};\n\nconst getInitials = (name: string): string => {\n\tconst names = name.trim().split(\" \");\n\tif (names.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tif (names.length === 1) {\n\t\treturn names[0]?.charAt(0).toUpperCase() || \"\";\n\t}\n\n\tconst firstInitial = names[0]?.charAt(0) || \"\";\n\t// biome-ignore lint/style/useAtIndex: ok here\n\tconst lastInitial = names[names.length - 1]?.charAt(0) || \"\";\n\n\treturn (firstInitial + lastInitial).toUpperCase();\n};\n\n/**\n * Displays initials or custom content while the avatar image loads or fails.\n * Optional delay avoids flashes when images load instantly.\n */\nexport const AvatarFallback = (() => {\n\tconst Component = React.forwardRef<HTMLSpanElement, AvatarFallbackProps>(\n\t\t(\n\t\t\t{\n\t\t\t\tchildren,\n\t\t\t\tname = \"\",\n\t\t\t\tdelayMs = 0,\n\t\t\t\tclassName,\n\t\t\t\tasChild = false,\n\t\t\t\t...props\n\t\t\t},\n\t\t\tref\n\t\t) => {\n\t\t\tconst { imageLoadingStatus } = useAvatarContext();\n\t\t\tconst [canRender, setCanRender] = React.useState(delayMs === 0);\n\n\t\t\tReact.useEffect(() => {\n\t\t\t\tif (delayMs > 0) {\n\t\t\t\t\tconst timerId = window.setTimeout(() => setCanRender(true), delayMs);\n\t\t\t\t\treturn () => window.clearTimeout(timerId);\n\t\t\t\t}\n\t\t\t}, [delayMs]);\n\n\t\t\tconst initials = React.useMemo(() => {\n\t\t\t\tif (name) {\n\t\t\t\t\treturn getInitials(name);\n\t\t\t\t}\n\t\t\t\treturn \"\";\n\t\t\t}, [name]);\n\n\t\t\tconst state: FallbackState = {\n\t\t\t\timageLoadingStatus,\n\t\t\t\tinitials,\n\t\t\t};\n\n\t\t\tconst shouldRender =\n\t\t\t\tcanRender &&\n\t\t\t\timageLoadingStatus !== \"loaded\" &&\n\t\t\t\timageLoadingStatus !== \"loading\";\n\n\t\t\tconst content = children || initials;\n\n\t\t\treturn useRenderElement(\n\t\t\t\t\"span\",\n\t\t\t\t{\n\t\t\t\t\tasChild,\n\t\t\t\t\tclassName,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tref,\n\t\t\t\t\tstate,\n\t\t\t\t\tenabled: shouldRender,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tchildren: content,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n\n\tComponent.displayName = \"AvatarFallback\";\n\treturn Component;\n})();\n"],"mappings":";;;;;AAoBA,MAAM,eAAe,SAAyB;CAC7C,MAAM,QAAQ,KAAK,MAAM,CAAC,MAAM,IAAI;AACpC,KAAI,MAAM,WAAW,EACpB,QAAO;AAGR,KAAI,MAAM,WAAW,EACpB,QAAO,MAAM,IAAI,OAAO,EAAE,CAAC,aAAa,IAAI;
|
|
1
|
+
{"version":3,"file":"fallback.js","names":["React","state: FallbackState"],"sources":["../../../src/primitives/avatar/fallback.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { useRenderElement } from \"../../utils/use-render-element\";\nimport { useAvatarContext } from \"./avatar\";\n\ntype FallbackState = {\n\timageLoadingStatus: \"idle\" | \"loading\" | \"loaded\" | \"error\";\n\tinitials?: string;\n};\n\nexport type AvatarFallbackProps = Omit<\n\tReact.HTMLAttributes<HTMLSpanElement>,\n\t\"children\"\n> & {\n\tchildren?: React.ReactNode;\n\tname?: string;\n\tdelayMs?: number;\n\tasChild?: boolean;\n\tclassName?: string;\n};\n\nconst getInitials = (name: string): string => {\n\tconst names = name.trim().split(\" \");\n\tif (names.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tif (names.length === 1) {\n\t\treturn names[0]?.charAt(0).toUpperCase() || \"\";\n\t}\n\n\tconst firstInitial = names[0]?.charAt(0) || \"\";\n\t// biome-ignore lint/style/useAtIndex: ok here\n\tconst lastInitial = names[names.length - 1]?.charAt(0) || \"\";\n\n\treturn (firstInitial + lastInitial).toUpperCase();\n};\n\n/**\n * Displays initials or custom content while the avatar image loads or fails.\n * Optional delay avoids flashes when images load instantly.\n */\nexport const AvatarFallback = (() => {\n\tconst Component = React.forwardRef<HTMLSpanElement, AvatarFallbackProps>(\n\t\t(\n\t\t\t{\n\t\t\t\tchildren,\n\t\t\t\tname = \"\",\n\t\t\t\tdelayMs = 0,\n\t\t\t\tclassName,\n\t\t\t\tasChild = false,\n\t\t\t\t...props\n\t\t\t},\n\t\t\tref\n\t\t) => {\n\t\t\tconst { imageLoadingStatus } = useAvatarContext();\n\t\t\tconst [canRender, setCanRender] = React.useState(delayMs === 0);\n\n\t\t\tReact.useEffect(() => {\n\t\t\t\tif (delayMs > 0) {\n\t\t\t\t\tconst timerId = window.setTimeout(() => setCanRender(true), delayMs);\n\t\t\t\t\treturn () => window.clearTimeout(timerId);\n\t\t\t\t}\n\t\t\t}, [delayMs]);\n\n\t\t\tconst initials = React.useMemo(() => {\n\t\t\t\tif (name) {\n\t\t\t\t\treturn getInitials(name);\n\t\t\t\t}\n\t\t\t\treturn \"\";\n\t\t\t}, [name]);\n\n\t\t\tconst state: FallbackState = {\n\t\t\t\timageLoadingStatus,\n\t\t\t\tinitials,\n\t\t\t};\n\n\t\t\tconst shouldRender =\n\t\t\t\tcanRender &&\n\t\t\t\timageLoadingStatus !== \"loaded\" &&\n\t\t\t\timageLoadingStatus !== \"loading\";\n\n\t\t\tconst content = children || initials;\n\n\t\t\treturn useRenderElement(\n\t\t\t\t\"span\",\n\t\t\t\t{\n\t\t\t\t\tasChild,\n\t\t\t\t\tclassName,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tref,\n\t\t\t\t\tstate,\n\t\t\t\t\tenabled: shouldRender,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tchildren: content,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n\n\tComponent.displayName = \"AvatarFallback\";\n\treturn Component;\n})();\n"],"mappings":";;;;;AAoBA,MAAM,eAAe,SAAyB;CAC7C,MAAM,QAAQ,KAAK,MAAM,CAAC,MAAM,IAAI;AACpC,KAAI,MAAM,WAAW,EACpB,QAAO;AAGR,KAAI,MAAM,WAAW,EACpB,QAAO,MAAM,IAAI,OAAO,EAAE,CAAC,aAAa,IAAI;AAO7C,UAJqB,MAAM,IAAI,OAAO,EAAE,IAAI,OAExB,MAAM,MAAM,SAAS,IAAI,OAAO,EAAE,IAAI,KAEtB,aAAa;;;;;;AAOlD,MAAa,wBAAwB;CACpC,MAAM,YAAYA,QAAM,YAEtB,EACC,UACA,OAAO,IACP,UAAU,GACV,WACA,UAAU,MACV,GAAG,SAEJ,QACI;EACJ,MAAM,EAAE,uBAAuB,kBAAkB;EACjD,MAAM,CAAC,WAAW,gBAAgBA,QAAM,SAAS,YAAY,EAAE;AAE/D,UAAM,gBAAgB;AACrB,OAAI,UAAU,GAAG;IAChB,MAAM,UAAU,OAAO,iBAAiB,aAAa,KAAK,EAAE,QAAQ;AACpE,iBAAa,OAAO,aAAa,QAAQ;;KAExC,CAAC,QAAQ,CAAC;EAEb,MAAM,WAAWA,QAAM,cAAc;AACpC,OAAI,KACH,QAAO,YAAY,KAAK;AAEzB,UAAO;KACL,CAAC,KAAK,CAAC;EAEV,MAAMC,QAAuB;GAC5B;GACA;GACA;EAED,MAAM,eACL,aACA,uBAAuB,YACvB,uBAAuB;EAExB,MAAM,UAAU,YAAY;AAE5B,SAAO,iBACN,QACA;GACC;GACA;GACA,EACD;GACC;GACA;GACA,SAAS;GACT,OAAO;IACN,GAAG;IACH,UAAU;IACV;GACD,CACD;GAEF;AAED,WAAU,cAAc;AACxB,QAAO;IACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.d.ts","names":[],"sources":["../../../src/primitives/avatar/image.tsx"],"sourcesContent":[],"mappings":";;;KAIK,UAAA;;AAJ0B,CAAA;AAQnB,KAAA,gBAAA,GAAmB,IAAH,CAC3B,OAAA,CAAM,iBADqB,CACH,gBADG,CAAA,EAAA,KAAA,GAAA,KAAA,CAAA,GAAA;
|
|
1
|
+
{"version":3,"file":"image.d.ts","names":[],"sources":["../../../src/primitives/avatar/image.tsx"],"sourcesContent":[],"mappings":";;;KAIK,UAAA;;AAJ0B,CAAA;AAQnB,KAAA,gBAAA,GAAmB,IAAH,CAC3B,OAAA,CAAM,iBADqB,CACH,gBADG,CAAA,EAAA,KAAA,GAAA,KAAA,CAAA,GAAA;EACH,GAAA,EAAA,MAAA;EAAxB,GAAA,CAAA,EAAM,MAAA;EADwB,OAAA,CAAA,EAAA,OAAA;EAQG,SAAA,CAAA,EAAA,MAAA;EAAU,qBAAA,CAAA,EAAA,CAAA,MAAA,EAAV,UAAU,CAAA,oBAAA,CAAA,EAAA,GAAA,IAAA;AAO5C,CAAA;;;;;cAAa,aAAW,OAAA,CAAA,0BAAA,KAAA,OAAA,CAAA,kBAAA;;EAAA,GAAA,CAAA,EAAA,MAAA;EAAA,OAAA,CAAA,EAAA,OAAA;;mCAPU"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Avatar, AvatarProps } from "./avatar.js";
|
|
2
2
|
import { AvatarFallback, AvatarFallbackProps } from "./fallback.js";
|
|
3
3
|
import { AvatarImage, AvatarImageProps } from "./image.js";
|
|
4
|
+
import "./index.parts.js";
|
|
4
5
|
export { Avatar, AvatarFallback, AvatarFallbackProps, AvatarImage, AvatarImageProps, AvatarProps };
|
package/primitives/bubble.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ type SupportBubbleProps = Omit<React$1.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
|
5
5
|
children?: React$1.ReactNode | ((props: {
|
|
6
6
|
isOpen: boolean;
|
|
7
7
|
unreadCount: number;
|
|
8
|
+
isTyping: boolean;
|
|
8
9
|
toggle: () => void;
|
|
9
10
|
}) => React$1.ReactNode);
|
|
10
11
|
asChild?: boolean;
|
|
@@ -18,6 +19,7 @@ declare const SupportBubble: React$1.ForwardRefExoticComponent<Omit<React$1.Butt
|
|
|
18
19
|
children?: React$1.ReactNode | ((props: {
|
|
19
20
|
isOpen: boolean;
|
|
20
21
|
unreadCount: number;
|
|
22
|
+
isTyping: boolean;
|
|
21
23
|
toggle: () => void;
|
|
22
24
|
}) => React$1.ReactNode);
|
|
23
25
|
asChild?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bubble.d.ts","names":[],"sources":["../../src/primitives/bubble.tsx"],"sourcesContent":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"bubble.d.ts","names":[],"sources":["../../src/primitives/bubble.tsx"],"sourcesContent":[],"mappings":";;;KAMY,kBAAA,GAAqB,KAChC,OAAA,CAAM,qBAAqB;aAIxB,OAAA,CAAM;IALE,MAAA,EAAA,OAAA;IACgB,WAAA,EAAA,MAAA;IAA3B,QAAM,EAAA,OAAA;IAD0B,MAAA,EAAA,GAAA,GAAA,IAAA;EAK7B,CAAA,EAAA,GAMM,OAAA,CAAM,SANN,CAAA;EAMA,OAAM,CAAA,EAAA,OAAA;EAAS,SAAA,CAAA,EAAA,MAAA;AASzB,CAAA;;;;;AATU,cASG,aATG,EASU,OAAA,CAAA,yBATV,CASU,IATV,CASU,OAAA,CAAA,oBATV,CASU,iBATV,CAAA,EAAA,UAAA,CAAA,GAAA;aANZ,OAAA,CAAM;;IAegB,WAAA,EAAA,MAAA;IAAA,QAAA,EAAA,OAAA;;QAThB,OAAA,CAAM"}
|
package/primitives/bubble.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { useTypingStore } from "../realtime/typing-store.js";
|
|
1
2
|
import { useRenderElement } from "../utils/use-render-element.js";
|
|
2
|
-
import { useSupportConfig } from "../support/
|
|
3
|
+
import { useSupportConfig } from "../support/store/support-store.js";
|
|
3
4
|
import { useSupport } from "../provider.js";
|
|
4
5
|
import * as React$1 from "react";
|
|
5
6
|
|
|
@@ -11,10 +12,15 @@ import * as React$1 from "react";
|
|
|
11
12
|
const SupportBubble = (() => {
|
|
12
13
|
const Component = React$1.forwardRef(({ children, className, asChild = false,...props }, ref) => {
|
|
13
14
|
const { isOpen, toggle } = useSupportConfig();
|
|
14
|
-
const { unreadCount } = useSupport();
|
|
15
|
+
const { unreadCount, visitor } = useSupport();
|
|
16
|
+
const visitorId = visitor?.id ?? null;
|
|
15
17
|
const renderProps = {
|
|
16
18
|
isOpen,
|
|
17
19
|
unreadCount,
|
|
20
|
+
isTyping: useTypingStore(React$1.useCallback((state) => Object.values(state.conversations).some((entries) => Object.values(entries).some((entry) => {
|
|
21
|
+
if (visitorId && entry.actorType === "visitor" && entry.actorId === visitorId) return false;
|
|
22
|
+
return true;
|
|
23
|
+
})), [visitorId])),
|
|
18
24
|
toggle
|
|
19
25
|
};
|
|
20
26
|
const content = typeof children === "function" ? children(renderProps) : children;
|
package/primitives/bubble.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bubble.js","names":["React"],"sources":["../../src/primitives/bubble.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { useSupport } from \"../provider\";\nimport { useSupportConfig } from \"../support\";\nimport { useRenderElement } from \"../utils/use-render-element\";\n\nexport type SupportBubbleProps = Omit<\n\tReact.ButtonHTMLAttributes<HTMLButtonElement>,\n\t\"children\"\n> & {\n\tchildren?:\n\t\t| React.ReactNode\n\t\t| ((props: {\n\t\t\t\tisOpen: boolean;\n\t\t\t\tunreadCount: number;\n\t\t\t\ttoggle: () => void;\n\t\t }) => React.ReactNode);\n\tasChild?: boolean;\n\tclassName?: string;\n};\n\n/**\n * Floating action button that toggles the support window. Exposes widget state\n * and unread counts to render-prop children for fully custom UI shells.\n */\nexport const SupportBubble = (() => {\n\tconst Component = React.forwardRef<HTMLButtonElement, SupportBubbleProps>(\n\t\t({ children, className, asChild = false, ...props }, ref) => {\n\t\t\tconst { isOpen, toggle } = useSupportConfig();\n\t\t\tconst { unreadCount } = useSupport();\n\n\t\t\tconst
|
|
1
|
+
{"version":3,"file":"bubble.js","names":["React"],"sources":["../../src/primitives/bubble.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { useSupport } from \"../provider\";\nimport { useTypingStore } from \"../realtime/typing-store\";\nimport { useSupportConfig } from \"../support\";\nimport { useRenderElement } from \"../utils/use-render-element\";\n\nexport type SupportBubbleProps = Omit<\n\tReact.ButtonHTMLAttributes<HTMLButtonElement>,\n\t\"children\"\n> & {\n\tchildren?:\n\t\t| React.ReactNode\n\t\t| ((props: {\n\t\t\t\tisOpen: boolean;\n\t\t\t\tunreadCount: number;\n\t\t\t\tisTyping: boolean;\n\t\t\t\ttoggle: () => void;\n\t\t }) => React.ReactNode);\n\tasChild?: boolean;\n\tclassName?: string;\n};\n\n/**\n * Floating action button that toggles the support window. Exposes widget state\n * and unread counts to render-prop children for fully custom UI shells.\n */\nexport const SupportBubble = (() => {\n\tconst Component = React.forwardRef<HTMLButtonElement, SupportBubbleProps>(\n\t\t({ children, className, asChild = false, ...props }, ref) => {\n\t\t\tconst { isOpen, toggle } = useSupportConfig();\n\t\t\tconst { unreadCount, visitor } = useSupport();\n\t\t\tconst visitorId = visitor?.id ?? null;\n\n\t\t\tconst hasTyping = useTypingStore(\n\t\t\t\tReact.useCallback(\n\t\t\t\t\t(state) =>\n\t\t\t\t\t\tObject.values(state.conversations).some((entries) =>\n\t\t\t\t\t\t\tObject.values(entries).some((entry) => {\n\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\tvisitorId &&\n\t\t\t\t\t\t\t\t\tentry.actorType === \"visitor\" &&\n\t\t\t\t\t\t\t\t\tentry.actorId === visitorId\n\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t),\n\t\t\t\t\t[visitorId]\n\t\t\t\t)\n\t\t\t);\n\n\t\t\tconst renderProps = {\n\t\t\t\tisOpen,\n\t\t\t\tunreadCount,\n\t\t\t\tisTyping: hasTyping,\n\t\t\t\ttoggle,\n\t\t\t};\n\n\t\t\tconst content =\n\t\t\t\ttypeof children === \"function\" ? children(renderProps) : children;\n\n\t\t\treturn useRenderElement(\n\t\t\t\t\"button\",\n\t\t\t\t{\n\t\t\t\t\tasChild,\n\t\t\t\t\tclassName,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tref,\n\t\t\t\t\tstate: renderProps,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\ttype: \"button\",\n\t\t\t\t\t\t\"aria-haspopup\": \"dialog\",\n\t\t\t\t\t\t\"aria-expanded\": isOpen,\n\t\t\t\t\t\tonClick: toggle,\n\t\t\t\t\t\t...props,\n\t\t\t\t\t\tchildren: content,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t);\n\n\tComponent.displayName = \"SupportBubble\";\n\treturn Component;\n})();\n"],"mappings":";;;;;;;;;;;AA0BA,MAAa,uBAAuB;CACnC,MAAM,YAAYA,QAAM,YACtB,EAAE,UAAU,WAAW,UAAU,MAAO,GAAG,SAAS,QAAQ;EAC5D,MAAM,EAAE,QAAQ,WAAW,kBAAkB;EAC7C,MAAM,EAAE,aAAa,YAAY,YAAY;EAC7C,MAAM,YAAY,SAAS,MAAM;EAsBjC,MAAM,cAAc;GACnB;GACA;GACA,UAvBiB,eACjBA,QAAM,aACJ,UACA,OAAO,OAAO,MAAM,cAAc,CAAC,MAAM,YACxC,OAAO,OAAO,QAAQ,CAAC,MAAM,UAAU;AACtC,QACC,aACA,MAAM,cAAc,aACpB,MAAM,YAAY,UAElB,QAAO;AAGR,WAAO;KACN,CACF,EACF,CAAC,UAAU,CACX,CACD;GAMA;GACA;EAED,MAAM,UACL,OAAO,aAAa,aAAa,SAAS,YAAY,GAAG;AAE1D,SAAO,iBACN,UACA;GACC;GACA;GACA,EACD;GACC;GACA,OAAO;GACP,OAAO;IACN,MAAM;IACN,iBAAiB;IACjB,iBAAiB;IACjB,SAAS;IACT,GAAG;IACH,UAAU;IACV;GACD,CACD;GAEF;AAED,WAAU,cAAc;AACxB,QAAO;IACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"button.d.ts","names":[],"sources":["../../src/primitives/button.tsx"],"sourcesContent":[],"mappings":";;;KAGY,WAAA,GAAc,OAAA,CAAM,qBAAqB;;EAAzC,SAAA,CAAA,EAAA,MAAW;CAAA
|
|
1
|
+
{"version":3,"file":"button.d.ts","names":[],"sources":["../../src/primitives/button.tsx"],"sourcesContent":[],"mappings":";;;KAGY,WAAA,GAAc,OAAA,CAAM,qBAAqB;;EAAzC,SAAA,CAAA,EAAA,MAAW;AAUvB,CAAA;;;;;;AAAmB,cAAN,MAAM,EAAA,OAAA,CAAA,yBAAA,CAAA,OAAA,CAAA,oBAAA,CAAA,iBAAA,CAAA,GAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-timeline.d.ts","names":[],"sources":["../../src/primitives/conversation-timeline.tsx"],"sourcesContent":[],"mappings":";;;;;;;AAQA;AAOA;
|
|
1
|
+
{"version":3,"file":"conversation-timeline.d.ts","names":[],"sources":["../../src/primitives/conversation-timeline.tsx"],"sourcesContent":[],"mappings":";;;;;;;AAQA;AAOA;AACsB,KARV,+BAAA,GAQU;EAArB,SAAM,EAAA,MAAA;EADiC,SAAA,CAAA,EAAA,OAAA;EAKpC,OAAM,CAAA,EAAA,OAAA;EACG,OAAA,EAAA,OAAA;CAAoC;AAGxC,KATG,yBAAA,GAA4B,IAS/B,CARR,OAAA,CAAM,cAQE,CARa,cAQb,CAAA,EAAA,UAAA,CAAA,GAAA;EAAgB,QAAA,CAAA,EAJrB,OAAA,CAAM,SAIe,GAAA,CAAA,CAAA,KAAA,EAHZ,+BAGY,EAAA,GAHwB,OAAA,CAAM,SAG9B,CAAA;EA6BZ,OAAA,CAAA,EAAA,OAAA;EAAoB,SAAA,CAAA,EAAA,MAAA;EAAA,KAAA,CAAA,EA7BxB,YA6BwB,EAAA;EAAA,SAAA,CAAA,EAAA,OAAA;EAjC7B,OAAM,CAAA,EAAA,OAAA;EACG,UAAA,CAAA,EAAA,OAAA;EAAoC,WAAM,CAAA,EAAA,GAAA,GAAA,IAAA;EAG9C,aAAA,CAAA,EAAA,GAAA,GAAA,IAAA;;;;;AA+LT;AACsB,cAnKT,oBAmKS,EAnKW,OAAA,CAAA,yBAmKX,CAnKW,IAmKX,CAnKW,OAAA,CAAA,cAmKX,CAnKW,cAmKX,CAAA,EAAA,UAAA,CAAA,GAAA;EAArB,QAAM,CAAA,EApMH,OAAA,CAAM,SAoMH,GAAA,CAAA,CAAA,KAAA,EAnMM,+BAmMN,EAAA,GAnM0C,OAAA,CAAM,SAmMhD,CAAA;EAD0C,OAAA,CAAA,EAAA,OAAA;EAIrC,SAAM,CAAA,EAAA,MAAA;EAAS,KAAA,CAAA,EAnMlB,YAmMkB,EAAA;EASd,SAAA,CAAA,EAAA,OAAA;EAA6B,OAAA,CAAA,EAAA,OAAA;EAAA,UAAA,CAAA,EAAA,OAAA;EAAA,WAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EAT9B,aAAM,CAAA,EAAA,GAAA,GAAA,IAAA;;KAJN,kCAAA,GAAqC,KAChD,OAAA,CAAM,eAAe;EAYoB,QAAA,CAAA,EAT9B,OAAA,CAAM,SASwB;EAAA,OAAA,CAAA,EAAA,OAAA;EAyB9B,SAAA,CAAA,EAAA,MAAA;CACU;;;;;AAYT,cAtCA,6BA+DT,EA/DsC,OAAA,CAAA,yBA+DtC,CA/DsC,IA+DtC,CA/DsC,OAAA,CAAA,cA+DtC,CA/DsC,cA+DtC,CAAA,EAAA,UAAA,CAAA,GAAA;EAzBoC,QAAA,CAAA,EA/C5B,OAAA,CAAM,SA+CsB;EAAA,OAAA,CAAA,EAAA,OAAA;EAAA,SAAA,CAAA,EAAA,MAAA;CAT5B,wBAAM,eAAA,CAAA,CAAA;KAJN,gCAAA,GAAmC,KAC9C,OAAA,CAAM,eAAe;aAGV,OAAA,CAAM;EASsB,OAAA,CAAA,EAAA,OAAA;EAAA,SAAA,CAAA,EAAA,MAAA;AA2BxC,CAAA;;;;;AAI2B,cA/Bd,2BA+Bc,EA/Ba,OAAA,CAAA,yBA+Bb,CA/Ba,IA+Bb,CA/Ba,OAAA,CAAA,cA+Bb,CA/Ba,cA+Bb,CAAA,EAAA,UAAA,CAAA,GAAA;EASd,QAAA,CAAA,EAjDD,OAAA,CAAM,SAiDL;EAAyB,OAAA,CAAA,EAAA,OAAA;EAAA,SAAA,CAAA,EAAA,MAAA;CAAA,wBAAA,eAAA,CAAA,CAAA;AAT1B,KAJA,8BAAA,GAAiC,IAI3B,CAHjB,OAAA,CAAM,cAGW,CAHI,cAGJ,CAAA,EAAA,UAAA,CAAA,GAAA;aAAN,OAAA,CAAM;;EASoB,SAAA,CAAA,EAAA,MAAA;CAAA;;;;;cAAzB,2BAAyB,OAAA,CAAA,0BAAA,KAAA,OAAA,CAAA,eAAA;aAT1B,OAAA,CAAM"}
|
|
@@ -2,6 +2,14 @@ import { useRenderElement } from "../utils/use-render-element.js";
|
|
|
2
2
|
import * as React$1 from "react";
|
|
3
3
|
|
|
4
4
|
//#region src/primitives/conversation-timeline.tsx
|
|
5
|
+
const BOTTOM_THRESHOLD_PX = 12;
|
|
6
|
+
const TOP_THRESHOLD_PX = 2;
|
|
7
|
+
function getLastItemKey(items) {
|
|
8
|
+
if (items.length === 0) return null;
|
|
9
|
+
const lastItem = items.at(-1);
|
|
10
|
+
if (lastItem?.id) return lastItem.id;
|
|
11
|
+
return lastItem?.createdAt ?? null;
|
|
12
|
+
}
|
|
5
13
|
/**
|
|
6
14
|
* Scrollable conversation timeline that wires auto-scroll behaviour, live-region semantics and
|
|
7
15
|
* pagination callbacks for displaying timeline items (messages, events, etc.).
|
|
@@ -16,6 +24,9 @@ const ConversationTimeline = (() => {
|
|
|
16
24
|
}, [ref]);
|
|
17
25
|
const isInitialRender = React$1.useRef(true);
|
|
18
26
|
const previousItemCount = React$1.useRef(items.length);
|
|
27
|
+
const previousLastItemKey = React$1.useRef(getLastItemKey(items));
|
|
28
|
+
const isPinnedToBottom = React$1.useRef(true);
|
|
29
|
+
const isAtTop = React$1.useRef(true);
|
|
19
30
|
const renderProps = {
|
|
20
31
|
itemCount: items.length,
|
|
21
32
|
isLoading,
|
|
@@ -23,18 +34,59 @@ const ConversationTimeline = (() => {
|
|
|
23
34
|
isEmpty: items.length === 0
|
|
24
35
|
};
|
|
25
36
|
const content = typeof children === "function" ? children(renderProps) : children;
|
|
37
|
+
const lastItemKey = getLastItemKey(items);
|
|
26
38
|
React$1.useEffect(() => {
|
|
27
|
-
|
|
28
|
-
|
|
39
|
+
const element = internalRef.current;
|
|
40
|
+
if (!(element && autoScroll)) {
|
|
29
41
|
previousItemCount.current = items.length;
|
|
42
|
+
previousLastItemKey.current = lastItemKey;
|
|
30
43
|
isInitialRender.current = false;
|
|
44
|
+
return;
|
|
31
45
|
}
|
|
32
|
-
|
|
46
|
+
const hasNewItems = items.length > previousItemCount.current;
|
|
47
|
+
const itemsRemoved = items.length < previousItemCount.current;
|
|
48
|
+
const appendedNewItem = hasNewItems && lastItemKey !== null && lastItemKey !== previousLastItemKey.current;
|
|
49
|
+
const replacedLastItem = !hasNewItems && lastItemKey !== null && lastItemKey !== previousLastItemKey.current;
|
|
50
|
+
if (isInitialRender.current || itemsRemoved && isPinnedToBottom.current || appendedNewItem && isPinnedToBottom.current || replacedLastItem && isPinnedToBottom.current) {
|
|
51
|
+
element.scrollTop = element.scrollHeight;
|
|
52
|
+
isPinnedToBottom.current = true;
|
|
53
|
+
isAtTop.current = false;
|
|
54
|
+
}
|
|
55
|
+
previousItemCount.current = items.length;
|
|
56
|
+
previousLastItemKey.current = lastItemKey;
|
|
57
|
+
isInitialRender.current = false;
|
|
58
|
+
}, [
|
|
59
|
+
autoScroll,
|
|
60
|
+
items.length,
|
|
61
|
+
lastItemKey
|
|
62
|
+
]);
|
|
33
63
|
const handleScroll = React$1.useCallback((e) => {
|
|
34
64
|
const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
|
|
35
|
-
|
|
36
|
-
if (
|
|
65
|
+
const pinnedNow = scrollHeight - scrollTop - clientHeight <= BOTTOM_THRESHOLD_PX;
|
|
66
|
+
if (pinnedNow && !isPinnedToBottom.current) onScrollEnd?.();
|
|
67
|
+
isPinnedToBottom.current = pinnedNow;
|
|
68
|
+
const atTop = scrollTop <= TOP_THRESHOLD_PX;
|
|
69
|
+
if (atTop && !isAtTop.current) onScrollStart?.();
|
|
70
|
+
isAtTop.current = atTop;
|
|
37
71
|
}, [onScrollStart, onScrollEnd]);
|
|
72
|
+
const fadeStyle = React$1.useMemo(() => {
|
|
73
|
+
const maskHeight = "90px";
|
|
74
|
+
const scrollbarWidth = "8px";
|
|
75
|
+
const maskImage = `linear-gradient(to bottom, transparent, black ${maskHeight}, black calc(100% - ${maskHeight}), transparent), linear-gradient(black, black)`;
|
|
76
|
+
const maskSize = `calc(100% - ${scrollbarWidth}) 100%, ${scrollbarWidth} 100%`;
|
|
77
|
+
const maskPosition = "0 0, 100% 0";
|
|
78
|
+
const maskRepeat = "no-repeat, no-repeat";
|
|
79
|
+
return {
|
|
80
|
+
maskImage,
|
|
81
|
+
maskSize,
|
|
82
|
+
maskPosition,
|
|
83
|
+
maskRepeat,
|
|
84
|
+
WebkitMaskImage: maskImage,
|
|
85
|
+
WebkitMaskSize: maskSize,
|
|
86
|
+
WebkitMaskPosition: maskPosition,
|
|
87
|
+
WebkitMaskRepeat: maskRepeat
|
|
88
|
+
};
|
|
89
|
+
}, []);
|
|
38
90
|
return useRenderElement("div", {
|
|
39
91
|
className,
|
|
40
92
|
asChild
|
|
@@ -47,6 +99,7 @@ const ConversationTimeline = (() => {
|
|
|
47
99
|
"aria-live": "polite",
|
|
48
100
|
"aria-relevant": "additions",
|
|
49
101
|
onScroll: handleScroll,
|
|
102
|
+
style: fadeStyle,
|
|
50
103
|
...props,
|
|
51
104
|
children: content
|
|
52
105
|
}
|