@cossistant/react 0.0.20 → 0.0.23
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/conversation.d.ts +28 -0
- package/conversation.d.ts.map +1 -1
- package/hooks/index.d.ts +4 -1
- package/hooks/index.js +4 -1
- package/hooks/private/use-grouped-messages.d.ts.map +1 -1
- package/hooks/private/use-grouped-messages.js +3 -17
- 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-multimodal-input.js +16 -3
- package/hooks/private/use-multimodal-input.js.map +1 -1
- package/hooks/use-composer-refocus.js +1 -1
- package/hooks/use-composer-refocus.js.map +1 -1
- package/hooks/use-conversation-auto-seen.d.ts +1 -1
- package/hooks/use-conversation-auto-seen.js +30 -46
- package/hooks/use-conversation-auto-seen.js.map +1 -1
- package/hooks/use-conversation-seen.d.ts.map +1 -1
- package/hooks/use-conversation-seen.js +7 -3
- package/hooks/use-conversation-seen.js.map +1 -1
- package/hooks/use-new-message-sound.d.ts +23 -0
- package/hooks/use-new-message-sound.d.ts.map +1 -0
- package/hooks/use-new-message-sound.js +34 -0
- package/hooks/use-new-message-sound.js.map +1 -0
- package/hooks/use-sound-effect.d.ts +30 -0
- package/hooks/use-sound-effect.d.ts.map +1 -0
- package/hooks/use-sound-effect.js +104 -0
- package/hooks/use-sound-effect.js.map +1 -0
- package/hooks/use-typing-sound.d.ts +18 -0
- package/hooks/use-typing-sound.d.ts.map +1 -0
- package/hooks/use-typing-sound.js +38 -0
- package/hooks/use-typing-sound.js.map +1 -0
- package/index.d.ts +5 -2
- package/index.js +8 -6
- package/package.json +3 -3
- package/primitives/avatar/image.d.ts +1 -1
- package/primitives/bubble.js +1 -1
- package/primitives/index.d.ts +3 -5
- package/primitives/index.js +3 -9
- package/primitives/index.parts.d.ts +2 -4
- package/primitives/index.parts.js +2 -4
- package/primitives/router.d.ts +19 -20
- package/primitives/router.d.ts.map +1 -1
- package/primitives/router.js +17 -11
- package/primitives/router.js.map +1 -1
- package/realtime/index.js +1 -1
- package/realtime/provider.js +1 -1
- package/realtime-events.d.ts +83 -0
- package/realtime-events.d.ts.map +1 -1
- package/schemas3.d.ts +7 -0
- package/schemas3.d.ts.map +1 -1
- package/support/components/bubble.d.ts.map +1 -1
- package/support/components/bubble.js +27 -4
- package/support/components/bubble.js.map +1 -1
- package/support/components/button.d.ts +1 -1
- package/support/components/conversation-event.js +1 -1
- package/support/components/conversation-event.js.map +1 -1
- package/support/components/conversation-timeline.d.ts.map +1 -1
- package/support/components/conversation-timeline.js +5 -0
- package/support/components/conversation-timeline.js.map +1 -1
- package/support/components/multimodal-input.d.ts.map +1 -1
- package/support/components/multimodal-input.js +6 -2
- package/support/components/multimodal-input.js.map +1 -1
- package/support/components/support-content.d.ts +2 -0
- package/support/components/support-content.d.ts.map +1 -1
- package/support/components/support-content.js +5 -2
- package/support/components/support-content.js.map +1 -1
- package/support/components/timeline-message-group.js +2 -2
- package/support/components/timeline-message-group.js.map +1 -1
- package/support/components/timeline-message-item.js +2 -2
- package/support/components/timeline-message-item.js.map +1 -1
- package/support/index.d.ts +12 -7
- package/support/index.d.ts.map +1 -1
- package/support/index.js +28 -29
- package/support/index.js.map +1 -1
- package/support/pages/conversation.d.ts.map +1 -1
- package/support/pages/conversation.js +19 -1
- package/support/pages/conversation.js.map +1 -1
- package/support/router.d.ts +19 -9
- package/support/router.d.ts.map +1 -1
- package/support/router.js +31 -30
- package/support/router.js.map +1 -1
- package/timeline-item.d.ts +14 -0
- package/timeline-item.d.ts.map +1 -1
- package/utils/use-render-element.d.ts.map +1 -1
- package/primitives/page-registry.d.ts +0 -30
- package/primitives/page-registry.d.ts.map +0 -1
- package/primitives/page-registry.js +0 -45
- package/primitives/page-registry.js.map +0 -1
- package/primitives/page.d.ts +0 -21
- package/primitives/page.d.ts.map +0 -1
- package/primitives/page.js +0 -18
- package/primitives/page.js.map +0 -1
package/support/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { SupportLocale, SupportTextContentOverrides } from "./text/locales/keys.js";
|
|
2
|
-
import {
|
|
3
|
-
import "../primitives/index.js";
|
|
2
|
+
import { CustomPage } from "./router.js";
|
|
4
3
|
import { Text, useSupportText } from "./text/index.js";
|
|
5
4
|
import { BubbleSlotProps, ContainerSlotProps, RouterSlotProps } from "./types.js";
|
|
6
5
|
import { CoButton } from "./components/button.js";
|
|
@@ -34,6 +33,7 @@ type SupportProps<Locale extends string = SupportLocale> = {
|
|
|
34
33
|
bubble?: string;
|
|
35
34
|
container?: string;
|
|
36
35
|
};
|
|
36
|
+
customPages?: CustomPage[];
|
|
37
37
|
children?: React.ReactNode;
|
|
38
38
|
};
|
|
39
39
|
/**
|
|
@@ -44,10 +44,14 @@ type SupportProps<Locale extends string = SupportLocale> = {
|
|
|
44
44
|
* <Support />
|
|
45
45
|
*
|
|
46
46
|
* @example
|
|
47
|
-
* // With customization
|
|
48
|
-
* <Support
|
|
49
|
-
*
|
|
50
|
-
*
|
|
47
|
+
* // With customization and custom pages
|
|
48
|
+
* <Support
|
|
49
|
+
* theme="dark"
|
|
50
|
+
* classNames={{ bubble: "bg-purple-600" }}
|
|
51
|
+
* customPages={[
|
|
52
|
+
* { name: "FAQ", component: FAQPage }
|
|
53
|
+
* ]}
|
|
54
|
+
* />
|
|
51
55
|
*/
|
|
52
56
|
declare function Support<Locale extends string = SupportLocale>({
|
|
53
57
|
className,
|
|
@@ -62,8 +66,9 @@ declare function Support<Locale extends string = SupportLocale>({
|
|
|
62
66
|
theme,
|
|
63
67
|
slots,
|
|
64
68
|
classNames,
|
|
69
|
+
customPages,
|
|
65
70
|
children
|
|
66
71
|
}: SupportProps<Locale>): ReactElement | null;
|
|
67
72
|
//#endregion
|
|
68
|
-
export { type BubbleSlotProps, CoButton as Button, type ContainerSlotProps, type
|
|
73
|
+
export { type BubbleSlotProps, CoButton as Button, type ContainerSlotProps, type CustomPage, type DefaultRoutes, Header, type NavigationState, type RouteRegistry, type RouterSlotProps, Support, Support as default, type SupportLocale, type SupportPage, SupportProps, type SupportTextContentOverrides, Text, type WebSocketContextValue, WebSocketProvider, useSupportConfig, useSupportNavigation, useSupportStore, useSupportText, useWebSocket };
|
|
69
74
|
//# sourceMappingURL=index.d.ts.map
|
package/support/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/support/index.tsx"],"sourcesContent":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/support/index.tsx"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;KAmBY,qCAAqC;;;;;;oBAO9B;;EAPP,MAAA,CAAA,EASF,MATc;EAAyB,OAAA,CAAA,EAUtC,2BAVsC,CAUV,MAVU,CAAA;EAO9B,KAAA,CAAA,EAAA,OAAA,GAAA,MAAA;EAET,KAAA,CAAA,EAAA;IAC6B,MAAA,CAAA,EAO5B,KAAA,CAAM,aAPsB,CAOR,eAPQ,CAAA;IAA5B,SAAA,CAAA,EAQG,KAAA,CAAM,aART,CAQuB,kBARvB,CAAA;IAOoB,MAAA,CAAA,EAEpB,KAAA,CAAM,aAFc,CAEA,eAFA,CAAA;EAApB,CAAA;EACuB,UAAA,CAAA,EAAA;IAAd,IAAA,CAAA,EAAA,MAAA;IACW,MAAA,CAAA,EAAA,MAAA;IAAd,SAAA,CAAA,EAAA,MAAA;EAWF,CAAA;EAEH,WAAM,CAAA,EAFH,UAEG,EAAA;EAAS,QAAA,CAAA,EAAf,KAAA,CAAM,SAAS;AAoB3B,CAAA;;;;;;;;;;;;;;;;;;AAe0B,iBAfV,OAeU,CAAA,eAAA,MAAA,GAfsB,aAetB,CAAA,CAAA;EAAA,SAAA;EAAA,QAAA;EAAA,KAAA;EAAA,WAAA;EAAA,YAAA;EAAA,eAAA;EAAA,WAAA;EAAA,MAAA;EAAA,OAAA;EAAA,KAAA;EAAA,KAAA;EAAA,UAAA;EAAA,WAAA;EAAA;AAAA,CAAA,EAAvB,YAAuB,CAAV,MAAU,CAAA,CAAA,EAAA,YAAA,GAAA,IAAA"}
|
package/support/index.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import "./support.js";
|
|
2
|
+
import { SupportRealtimeProvider } from "../realtime/support-provider.js";
|
|
2
3
|
import { SupportConfig } from "../support-config.js";
|
|
3
|
-
import { PageRegistryProvider } from "../primitives/page-registry.js";
|
|
4
|
-
import { Page } from "../primitives/page.js";
|
|
5
4
|
import { initializeSupportStore, useSupportConfig, useSupportNavigation, useSupportStore } from "./store/support-store.js";
|
|
6
|
-
import { SupportRealtimeProvider } from "../realtime/support-provider.js";
|
|
7
5
|
import { CoButton } from "./components/button.js";
|
|
8
6
|
import { Header } from "./components/header.js";
|
|
9
7
|
import { SupportTextProvider, Text, useSupportText } from "./text/index.js";
|
|
@@ -23,44 +21,45 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
23
21
|
* <Support />
|
|
24
22
|
*
|
|
25
23
|
* @example
|
|
26
|
-
* // With customization
|
|
27
|
-
* <Support
|
|
28
|
-
*
|
|
29
|
-
*
|
|
24
|
+
* // With customization and custom pages
|
|
25
|
+
* <Support
|
|
26
|
+
* theme="dark"
|
|
27
|
+
* classNames={{ bubble: "bg-purple-600" }}
|
|
28
|
+
* customPages={[
|
|
29
|
+
* { name: "FAQ", component: FAQPage }
|
|
30
|
+
* ]}
|
|
31
|
+
* />
|
|
30
32
|
*/
|
|
31
|
-
function Support({ className, position = "bottom", align = "right", positioning = "fixed", quickOptions, defaultMessages, defaultOpen, locale, content, theme, slots, classNames, children }) {
|
|
33
|
+
function Support({ className, position = "bottom", align = "right", positioning = "fixed", quickOptions, defaultMessages, defaultOpen, locale, content, theme, slots, classNames, customPages, children }) {
|
|
32
34
|
const { website } = useSupport();
|
|
33
35
|
const isVisitorBlocked = website?.visitor?.isBlocked ?? false;
|
|
34
36
|
React.useEffect(() => {
|
|
35
37
|
if (defaultOpen !== void 0) initializeSupportStore({ defaultOpen });
|
|
36
38
|
}, [defaultOpen]);
|
|
37
39
|
if (!website || isVisitorBlocked) return null;
|
|
38
|
-
return /* @__PURE__ */
|
|
40
|
+
return /* @__PURE__ */ jsxs(ThemeWrapper, {
|
|
39
41
|
theme,
|
|
40
|
-
children: /* @__PURE__ */
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
children
|
|
53
|
-
})
|
|
54
|
-
}) }),
|
|
55
|
-
/* @__PURE__ */ jsx(SupportConfig, {
|
|
56
|
-
defaultMessages,
|
|
57
|
-
quickOptions
|
|
42
|
+
children: [/* @__PURE__ */ jsx(SupportRealtimeProvider, { children: /* @__PURE__ */ jsx(SupportTextProvider, {
|
|
43
|
+
content,
|
|
44
|
+
locale,
|
|
45
|
+
children: /* @__PURE__ */ jsx(SupportContent, {
|
|
46
|
+
align,
|
|
47
|
+
className,
|
|
48
|
+
classNames,
|
|
49
|
+
customPages,
|
|
50
|
+
position,
|
|
51
|
+
positioning,
|
|
52
|
+
slots,
|
|
53
|
+
children
|
|
58
54
|
})
|
|
59
|
-
|
|
55
|
+
}) }), /* @__PURE__ */ jsx(SupportConfig, {
|
|
56
|
+
defaultMessages,
|
|
57
|
+
quickOptions
|
|
58
|
+
})]
|
|
60
59
|
});
|
|
61
60
|
}
|
|
62
61
|
var support_default = Support;
|
|
63
62
|
|
|
64
63
|
//#endregion
|
|
65
|
-
export { CoButton as Button, Header,
|
|
64
|
+
export { CoButton as Button, Header, Support, Text, WebSocketProvider, support_default as default, useSupportConfig, useSupportNavigation, useSupportStore, useSupportText, useWebSocket };
|
|
66
65
|
//# sourceMappingURL=index.js.map
|
package/support/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/support/index.tsx"],"sourcesContent":["import \"./support.css\";\n\nimport type { DefaultMessage } from \"@cossistant/types\";\nimport React, { type ReactElement } from \"react\";\nimport {
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/support/index.tsx"],"sourcesContent":["import \"./support.css\";\n\nimport type { DefaultMessage } from \"@cossistant/types\";\nimport React, { type ReactElement } from \"react\";\nimport { useSupport } from \"../provider\";\nimport { SupportRealtimeProvider } from \"../realtime\";\nimport { SupportConfig } from \"../support-config\";\nimport { SupportContent } from \"./components/support-content\";\nimport { ThemeWrapper } from \"./components/theme-wrapper\";\nimport type { CustomPage } from \"./router\";\nimport { initializeSupportStore } from \"./store/support-store\";\nimport type { SupportLocale, SupportTextContentOverrides } from \"./text\";\nimport { SupportTextProvider } from \"./text\";\nimport type {\n\tBubbleSlotProps,\n\tContainerSlotProps,\n\tRouterSlotProps,\n} from \"./types\";\n\nexport type SupportProps<Locale extends string = SupportLocale> = {\n\t// Existing props\n\tclassName?: string;\n\tposition?: \"top\" | \"bottom\";\n\talign?: \"right\" | \"left\";\n\tpositioning?: \"fixed\" | \"absolute\";\n\tquickOptions?: string[];\n\tdefaultMessages?: DefaultMessage[];\n\tdefaultOpen?: boolean;\n\tlocale?: Locale;\n\tcontent?: SupportTextContentOverrides<Locale>;\n\n\t// NEW: Theme control\n\ttheme?: \"light\" | \"dark\";\n\n\t// NEW: Slot customization\n\tslots?: {\n\t\tbubble?: React.ComponentType<BubbleSlotProps>;\n\t\tcontainer?: React.ComponentType<ContainerSlotProps>;\n\t\trouter?: React.ComponentType<RouterSlotProps>;\n\t};\n\n\t// NEW: Granular className overrides\n\tclassNames?: {\n\t\troot?: string;\n\t\tbubble?: string;\n\t\tcontainer?: string;\n\t};\n\n\t// NEW: Type-safe custom pages\n\tcustomPages?: CustomPage[];\n\n\tchildren?: React.ReactNode;\n};\n\n/**\n * Complete support widget with chat, routing, and real-time features.\n *\n * @example\n * // Zero config\n * <Support />\n *\n * @example\n * // With customization and custom pages\n * <Support\n * theme=\"dark\"\n * classNames={{ bubble: \"bg-purple-600\" }}\n * customPages={[\n * { name: \"FAQ\", component: FAQPage }\n * ]}\n * />\n */\nexport function Support<Locale extends string = SupportLocale>({\n\tclassName,\n\tposition = \"bottom\",\n\talign = \"right\",\n\tpositioning = \"fixed\",\n\tquickOptions,\n\tdefaultMessages,\n\tdefaultOpen,\n\tlocale,\n\tcontent,\n\ttheme,\n\tslots,\n\tclassNames,\n\tcustomPages,\n\tchildren,\n}: SupportProps<Locale>): ReactElement | null {\n\tconst { website } = useSupport();\n\tconst isVisitorBlocked = website?.visitor?.isBlocked ?? false;\n\n\t// Initialize support store with defaultOpen when component mounts or prop changes\n\tReact.useEffect(() => {\n\t\tif (defaultOpen !== undefined) {\n\t\t\tinitializeSupportStore({ defaultOpen });\n\t\t}\n\t}, [defaultOpen]);\n\n\tif (!website || isVisitorBlocked) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<ThemeWrapper theme={theme}>\n\t\t\t<SupportRealtimeProvider>\n\t\t\t\t<SupportTextProvider content={content} locale={locale}>\n\t\t\t\t\t<SupportContent\n\t\t\t\t\t\talign={align}\n\t\t\t\t\t\tclassName={className}\n\t\t\t\t\t\tclassNames={classNames}\n\t\t\t\t\t\tcustomPages={customPages}\n\t\t\t\t\t\tposition={position}\n\t\t\t\t\t\tpositioning={positioning}\n\t\t\t\t\t\tslots={slots}\n\t\t\t\t\t>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</SupportContent>\n\t\t\t\t</SupportTextProvider>\n\t\t\t</SupportRealtimeProvider>\n\t\t\t<SupportConfig\n\t\t\t\tdefaultMessages={defaultMessages}\n\t\t\t\tquickOptions={quickOptions}\n\t\t\t/>\n\t\t</ThemeWrapper>\n\t);\n}\n\nexport default Support;\n\n// Type exports from core\nexport type {\n\tDefaultRoutes,\n\tNavigationState,\n\tRouteRegistry,\n\tSupportPage,\n} from \"@cossistant/core\";\nexport { CoButton as Button } from \"./components/button\";\n// UI components for building custom pages\nexport { Header } from \"./components/header\";\n// WebSocket context\nexport type { WebSocketContextValue } from \"./context/websocket\";\nexport { useWebSocket, WebSocketProvider } from \"./context/websocket\";\n// Custom page type for type-safe routing\nexport type { CustomPage } from \"./router\";\n// Navigation hooks and store\nexport {\n\tuseSupportConfig,\n\tuseSupportNavigation,\n\tuseSupportStore,\n} from \"./store\";\n// Text and localization\nexport type { SupportLocale, SupportTextContentOverrides } from \"./text\";\nexport { Text, useSupportText } from \"./text\";\n\n// Slot prop types\nexport type {\n\tBubbleSlotProps,\n\tContainerSlotProps,\n\tRouterSlotProps,\n} from \"./types\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuEA,SAAgB,QAA+C,EAC9D,WACA,WAAW,UACX,QAAQ,SACR,cAAc,SACd,cACA,iBACA,aACA,QACA,SACA,OACA,OACA,YACA,aACA,YAC6C;CAC7C,MAAM,EAAE,YAAY,YAAY;CAChC,MAAM,mBAAmB,SAAS,SAAS,aAAa;AAGxD,OAAM,gBAAgB;AACrB,MAAI,gBAAgB,OACnB,wBAAuB,EAAE,aAAa,CAAC;IAEtC,CAAC,YAAY,CAAC;AAEjB,KAAI,CAAC,WAAW,iBACf,QAAO;AAGR,QACC,qBAAC;EAAoB;aACpB,oBAAC,qCACA,oBAAC;GAA6B;GAAiB;aAC9C,oBAAC;IACO;IACI;IACC;IACC;IACH;IACG;IACN;IAEN;KACe;IACI,GACG,EAC1B,oBAAC;GACiB;GACH;IACb;GACY;;AAIjB,sBAAe"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation.d.ts","names":[],"sources":["../../../src/support/pages/conversation.tsx"],"sourcesContent":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"conversation.d.ts","names":[],"sources":["../../../src/support/pages/conversation.tsx"],"sourcesContent":[],"mappings":";;;;KAeK,qBAAA;;AAbiE;AAqCjD;EAQR,MAAA,CAAA,EAAA;;;;;;;;;;;;YAdH;;;;UAMD;;;;;KAMJ,yBAAA,WAAoC,0BAA0B;cAEtD,kBAAkB"}
|
|
@@ -4,11 +4,12 @@ import { Header } from "../components/header.js";
|
|
|
4
4
|
import { Text, useSupportText } from "../text/index.js";
|
|
5
5
|
import { useConversation } from "../../hooks/use-conversation.js";
|
|
6
6
|
import { useConversationPage } from "../../hooks/use-conversation-page.js";
|
|
7
|
+
import { useNewMessageSound } from "../../hooks/use-new-message-sound.js";
|
|
7
8
|
import { ConversationTimelineList } from "../components/conversation-timeline.js";
|
|
8
9
|
import { MultimodalInput } from "../components/multimodal-input.js";
|
|
9
10
|
import { IdentificationTimelineTool } from "../components/timeline-identification-tool.js";
|
|
10
11
|
import { useSupport } from "../../provider.js";
|
|
11
|
-
import { useMemo } from "react";
|
|
12
|
+
import { useEffect, useMemo, useRef } from "react";
|
|
12
13
|
import { ConversationStatus } from "@cossistant/types";
|
|
13
14
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
14
15
|
|
|
@@ -21,6 +22,11 @@ const ConversationPage = ({ params, conversationId: legacyConversationId, initia
|
|
|
21
22
|
const { navigate, replace, goBack, canGoBack } = useSupportNavigation();
|
|
22
23
|
const { isOpen } = useSupportConfig();
|
|
23
24
|
const text = useSupportText();
|
|
25
|
+
const playNewMessageSound = useNewMessageSound({
|
|
26
|
+
volume: .7,
|
|
27
|
+
playbackRate: 1
|
|
28
|
+
});
|
|
29
|
+
const previousItemsRef = useRef([]);
|
|
24
30
|
const timelineTools = useMemo(() => ({ identification: { component: IdentificationTimelineTool } }), []);
|
|
25
31
|
const conversation = useConversationPage({
|
|
26
32
|
conversationId: initialConversationId,
|
|
@@ -40,6 +46,18 @@ const ConversationPage = ({ params, conversationId: legacyConversationId, initia
|
|
|
40
46
|
if (canGoBack) goBack();
|
|
41
47
|
else navigate({ page: "HOME" });
|
|
42
48
|
};
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
const currentItems = conversation.items;
|
|
51
|
+
const previousItems = previousItemsRef.current;
|
|
52
|
+
if (currentItems.length > previousItems.length) {
|
|
53
|
+
const newItems = currentItems.slice(previousItems.length);
|
|
54
|
+
for (const item of newItems) if (item.type === "message" && !item.visitorId) {
|
|
55
|
+
playNewMessageSound();
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
previousItemsRef.current = currentItems;
|
|
60
|
+
}, [conversation.items, playNewMessageSound]);
|
|
43
61
|
return /* @__PURE__ */ jsxs("div", {
|
|
44
62
|
className: "flex h-full flex-col gap-0 overflow-hidden",
|
|
45
63
|
children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation.js","names":["ConversationPage: ConversationPageComponent"],"sources":["../../../src/support/pages/conversation.tsx"],"sourcesContent":["import { ConversationStatus } from \"@cossistant/types\";\nimport type { TimelineItem } from \"@cossistant/types/api/timeline-item\";\nimport { type ReactElement, useMemo } from \"react\";\nimport { useConversation } from \"../../hooks/use-conversation\";\nimport { useConversationPage } from \"../../hooks/use-conversation-page\";\nimport { useSupport } from \"../../provider\";\nimport { AvatarStack } from \"../components/avatar-stack\";\nimport { ConversationTimelineList } from \"../components/conversation-timeline\";\nimport { Header } from \"../components/header\";\nimport { MultimodalInput } from \"../components/multimodal-input\";\nimport { IdentificationTimelineTool } from \"../components/timeline-identification-tool\";\nimport { useSupportConfig, useSupportNavigation } from \"../store\";\nimport { Text, useSupportText } from \"../text\";\n\ntype ConversationPageProps = {\n\t/**\n\t * Page params object (for compatibility with Page component)\n\t */\n\tparams?: {\n\t\t/**\n\t\t * The conversation ID to display (can be PENDING_CONVERSATION_ID or a real ID).\n\t\t */\n\t\tconversationId: string;\n\n\t\t/**\n\t\t * Optional initial message to send when opening the conversation.\n\t\t */\n\t\tinitialMessage?: string;\n\n\t\t/**\n\t\t * Optional timeline items to display (for optimistic updates or initial state).\n\t\t */\n\t\titems?: TimelineItem[];\n\t};\n\n\t// Legacy direct props support (deprecated but maintained for backward compatibility)\n\tconversationId?: string;\n\tinitialMessage?: string;\n\titems?: TimelineItem[];\n};\n\n/**\n * Conversation page with message timeline and input composer.\n */\ntype ConversationPageComponent = (props: ConversationPageProps) => ReactElement;\n\nexport const ConversationPage: ConversationPageComponent = ({\n\tparams,\n\tconversationId: legacyConversationId,\n\tinitialMessage: legacyInitialMessage,\n\titems: legacyItems,\n}: ConversationPageProps) => {\n\t// Support both params object (new) and direct props (legacy)\n\tconst initialConversationId =\n\t\tparams?.conversationId ?? legacyConversationId ?? \"\";\n\tconst initialMessage = params?.initialMessage ?? legacyInitialMessage;\n\tconst passedItems = params?.items ?? legacyItems ?? [];\n\tconst { website, availableAIAgents, availableHumanAgents, visitor } =\n\t\tuseSupport();\n\tconst { navigate, replace, goBack, canGoBack } = useSupportNavigation();\n\tconst { isOpen } = useSupportConfig();\n\tconst text = useSupportText();\n\n\tconst timelineTools = useMemo(\n\t\t() => ({\n\t\t\tidentification: { component: IdentificationTimelineTool },\n\t\t}),\n\t\t[]\n\t);\n\n\t// Main conversation hook - handles all logic\n\tconst conversation = useConversationPage({\n\t\tconversationId: initialConversationId,\n\t\titems: passedItems,\n\t\tinitialMessage,\n\t\tautoSeenEnabled: isOpen,\n\t\tonConversationIdChange: (newConversationId) => {\n\t\t\t// Update navigation when conversation is created\n\t\t\treplace({\n\t\t\t\tpage: \"CONVERSATION\",\n\t\t\t\tparams: { conversationId: newConversationId },\n\t\t\t});\n\t\t},\n\t});\n\n\tconst { conversation: activeConversation } = useConversation(\n\t\tconversation.isPending ? null : conversation.conversationId,\n\t\t{ enabled: !conversation.isPending }\n\t);\n\n\tconst isConversationClosed = Boolean(\n\t\tactiveConversation &&\n\t\t\t(activeConversation.status === ConversationStatus.RESOLVED ||\n\t\t\t\tactiveConversation.status === ConversationStatus.SPAM ||\n\t\t\t\tactiveConversation.deletedAt)\n\t);\n\n\tconst handleGoBack = () => {\n\t\tif (canGoBack) {\n\t\t\tgoBack();\n\t\t} else {\n\t\t\tnavigate({ page: \"HOME\" });\n\t\t}\n\t};\n\n\treturn (\n\t\t<div className=\"flex h-full flex-col gap-0 overflow-hidden\">\n\t\t\t<Header onGoBack={handleGoBack}>\n\t\t\t\t<div className=\"flex w-full items-center justify-between gap-2 py-3\">\n\t\t\t\t\t<div className=\"flex flex-col\">\n\t\t\t\t\t\t<p className=\"font-medium text-co-primary text-sm\">\n\t\t\t\t\t\t\t{website?.name}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\tas=\"p\"\n\t\t\t\t\t\t\tclassName=\"text-co-muted-foreground text-sm\"\n\t\t\t\t\t\t\ttextKey=\"common.labels.supportOnline\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t\t<AvatarStack\n\t\t\t\t\t\taiAgents={availableAIAgents}\n\t\t\t\t\t\tgapWidth={2}\n\t\t\t\t\t\thumanAgents={availableHumanAgents}\n\t\t\t\t\t\tsize={32}\n\t\t\t\t\t\tspacing={28}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t</Header>\n\n\t\t\t<ConversationTimelineList\n\t\t\t\tavailableAIAgents={availableAIAgents}\n\t\t\t\tavailableHumanAgents={availableHumanAgents}\n\t\t\t\tclassName=\"min-h-0 flex-1 px-4\"\n\t\t\t\tconversationId={conversation.conversationId}\n\t\t\t\tcurrentVisitorId={visitor?.id}\n\t\t\t\titems={conversation.items}\n\t\t\t\ttools={timelineTools}\n\t\t\t/>\n\n\t\t\t{isConversationClosed ? (\n\t\t\t\t<div className=\"m-4 flex items-center justify-center text-balance px-4 pb-6 text-center font-medium text-co-muted-foreground text-sm\">\n\t\t\t\t\t<Text as=\"p\" textKey=\"component.conversationPage.closedMessage\" />\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<div className=\"flex-shrink-0 p-1\">\n\t\t\t\t\t<MultimodalInput\n\t\t\t\t\t\tdisabled={conversation.composer.isSubmitting}\n\t\t\t\t\t\terror={conversation.error}\n\t\t\t\t\t\tfiles={conversation.composer.files}\n\t\t\t\t\t\tisSubmitting={conversation.composer.isSubmitting}\n\t\t\t\t\t\tonChange={conversation.composer.setMessage}\n\t\t\t\t\t\tonFileSelect={conversation.composer.addFiles}\n\t\t\t\t\t\tonRemoveFile={conversation.composer.removeFile}\n\t\t\t\t\t\tonSubmit={conversation.composer.submit}\n\t\t\t\t\t\tplaceholder={text(\"component.multimodalInput.placeholder\")}\n\t\t\t\t\t\tvalue={conversation.composer.message}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"conversation.js","names":["ConversationPage: ConversationPageComponent"],"sources":["../../../src/support/pages/conversation.tsx"],"sourcesContent":["import { ConversationStatus } from \"@cossistant/types\";\nimport type { TimelineItem } from \"@cossistant/types/api/timeline-item\";\nimport { type ReactElement, useEffect, useMemo, useRef } from \"react\";\nimport { useConversation } from \"../../hooks/use-conversation\";\nimport { useConversationPage } from \"../../hooks/use-conversation-page\";\nimport { useNewMessageSound } from \"../../hooks/use-new-message-sound\";\nimport { useSupport } from \"../../provider\";\nimport { AvatarStack } from \"../components/avatar-stack\";\nimport { ConversationTimelineList } from \"../components/conversation-timeline\";\nimport { Header } from \"../components/header\";\nimport { MultimodalInput } from \"../components/multimodal-input\";\nimport { IdentificationTimelineTool } from \"../components/timeline-identification-tool\";\nimport { useSupportConfig, useSupportNavigation } from \"../store\";\nimport { Text, useSupportText } from \"../text\";\n\ntype ConversationPageProps = {\n\t/**\n\t * Page params object (for compatibility with Page component)\n\t */\n\tparams?: {\n\t\t/**\n\t\t * The conversation ID to display (can be PENDING_CONVERSATION_ID or a real ID).\n\t\t */\n\t\tconversationId: string;\n\n\t\t/**\n\t\t * Optional initial message to send when opening the conversation.\n\t\t */\n\t\tinitialMessage?: string;\n\n\t\t/**\n\t\t * Optional timeline items to display (for optimistic updates or initial state).\n\t\t */\n\t\titems?: TimelineItem[];\n\t};\n\n\t// Legacy direct props support (deprecated but maintained for backward compatibility)\n\tconversationId?: string;\n\tinitialMessage?: string;\n\titems?: TimelineItem[];\n};\n\n/**\n * Conversation page with message timeline and input composer.\n */\ntype ConversationPageComponent = (props: ConversationPageProps) => ReactElement;\n\nexport const ConversationPage: ConversationPageComponent = ({\n\tparams,\n\tconversationId: legacyConversationId,\n\tinitialMessage: legacyInitialMessage,\n\titems: legacyItems,\n}: ConversationPageProps) => {\n\t// Support both params object (new) and direct props (legacy)\n\tconst initialConversationId =\n\t\tparams?.conversationId ?? legacyConversationId ?? \"\";\n\tconst initialMessage = params?.initialMessage ?? legacyInitialMessage;\n\tconst passedItems = params?.items ?? legacyItems ?? [];\n\tconst { website, availableAIAgents, availableHumanAgents, visitor } =\n\t\tuseSupport();\n\tconst { navigate, replace, goBack, canGoBack } = useSupportNavigation();\n\tconst { isOpen } = useSupportConfig();\n\tconst text = useSupportText();\n\tconst playNewMessageSound = useNewMessageSound({\n\t\tvolume: 0.7,\n\t\tplaybackRate: 1.0,\n\t});\n\tconst previousItemsRef = useRef<TimelineItem[]>([]);\n\n\tconst timelineTools = useMemo(\n\t\t() => ({\n\t\t\tidentification: { component: IdentificationTimelineTool },\n\t\t}),\n\t\t[]\n\t);\n\n\t// Main conversation hook - handles all logic\n\tconst conversation = useConversationPage({\n\t\tconversationId: initialConversationId,\n\t\titems: passedItems,\n\t\tinitialMessage,\n\t\tautoSeenEnabled: isOpen,\n\t\tonConversationIdChange: (newConversationId) => {\n\t\t\t// Update navigation when conversation is created\n\t\t\treplace({\n\t\t\t\tpage: \"CONVERSATION\",\n\t\t\t\tparams: { conversationId: newConversationId },\n\t\t\t});\n\t\t},\n\t});\n\n\tconst { conversation: activeConversation } = useConversation(\n\t\tconversation.isPending ? null : conversation.conversationId,\n\t\t{ enabled: !conversation.isPending }\n\t);\n\n\tconst isConversationClosed = Boolean(\n\t\tactiveConversation &&\n\t\t\t(activeConversation.status === ConversationStatus.RESOLVED ||\n\t\t\t\tactiveConversation.status === ConversationStatus.SPAM ||\n\t\t\t\tactiveConversation.deletedAt)\n\t);\n\n\tconst handleGoBack = () => {\n\t\tif (canGoBack) {\n\t\t\tgoBack();\n\t\t} else {\n\t\t\tnavigate({ page: \"HOME\" });\n\t\t}\n\t};\n\n\t// Play sound when new messages arrive from agents (not visitor)\n\tuseEffect(() => {\n\t\tconst currentItems = conversation.items;\n\t\tconst previousItems = previousItemsRef.current;\n\n\t\t// Check if there are new items\n\t\tif (currentItems.length > previousItems.length) {\n\t\t\t// Find the new items\n\t\t\tconst newItems = currentItems.slice(previousItems.length);\n\n\t\t\t// Play sound only if new message is from agent (not visitor)\n\t\t\tfor (const item of newItems) {\n\t\t\t\tif (item.type === \"message\" && !item.visitorId) {\n\t\t\t\t\tplayNewMessageSound();\n\t\t\t\t\tbreak; // Only play once per batch\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Update the ref\n\t\tpreviousItemsRef.current = currentItems;\n\t}, [conversation.items, playNewMessageSound]);\n\n\treturn (\n\t\t<div className=\"flex h-full flex-col gap-0 overflow-hidden\">\n\t\t\t<Header onGoBack={handleGoBack}>\n\t\t\t\t<div className=\"flex w-full items-center justify-between gap-2 py-3\">\n\t\t\t\t\t<div className=\"flex flex-col\">\n\t\t\t\t\t\t<p className=\"font-medium text-co-primary text-sm\">\n\t\t\t\t\t\t\t{website?.name}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\tas=\"p\"\n\t\t\t\t\t\t\tclassName=\"text-co-muted-foreground text-sm\"\n\t\t\t\t\t\t\ttextKey=\"common.labels.supportOnline\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t\t<AvatarStack\n\t\t\t\t\t\taiAgents={availableAIAgents}\n\t\t\t\t\t\tgapWidth={2}\n\t\t\t\t\t\thumanAgents={availableHumanAgents}\n\t\t\t\t\t\tsize={32}\n\t\t\t\t\t\tspacing={28}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t</Header>\n\n\t\t\t<ConversationTimelineList\n\t\t\t\tavailableAIAgents={availableAIAgents}\n\t\t\t\tavailableHumanAgents={availableHumanAgents}\n\t\t\t\tclassName=\"min-h-0 flex-1 px-4\"\n\t\t\t\tconversationId={conversation.conversationId}\n\t\t\t\tcurrentVisitorId={visitor?.id}\n\t\t\t\titems={conversation.items}\n\t\t\t\ttools={timelineTools}\n\t\t\t/>\n\n\t\t\t{isConversationClosed ? (\n\t\t\t\t<div className=\"m-4 flex items-center justify-center text-balance px-4 pb-6 text-center font-medium text-co-muted-foreground text-sm\">\n\t\t\t\t\t<Text as=\"p\" textKey=\"component.conversationPage.closedMessage\" />\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<div className=\"flex-shrink-0 p-1\">\n\t\t\t\t\t<MultimodalInput\n\t\t\t\t\t\tdisabled={conversation.composer.isSubmitting}\n\t\t\t\t\t\terror={conversation.error}\n\t\t\t\t\t\tfiles={conversation.composer.files}\n\t\t\t\t\t\tisSubmitting={conversation.composer.isSubmitting}\n\t\t\t\t\t\tonChange={conversation.composer.setMessage}\n\t\t\t\t\t\tonFileSelect={conversation.composer.addFiles}\n\t\t\t\t\t\tonRemoveFile={conversation.composer.removeFile}\n\t\t\t\t\t\tonSubmit={conversation.composer.submit}\n\t\t\t\t\t\tplaceholder={text(\"component.multimodalInput.placeholder\")}\n\t\t\t\t\t\tvalue={conversation.composer.message}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n};\n"],"mappings":";;;;;;;;;;;;;;;;AA+CA,MAAaA,oBAA+C,EAC3D,QACA,gBAAgB,sBAChB,gBAAgB,sBAChB,OAAO,kBACqB;CAE5B,MAAM,wBACL,QAAQ,kBAAkB,wBAAwB;CACnD,MAAM,iBAAiB,QAAQ,kBAAkB;CACjD,MAAM,cAAc,QAAQ,SAAS,eAAe,EAAE;CACtD,MAAM,EAAE,SAAS,mBAAmB,sBAAsB,YACzD,YAAY;CACb,MAAM,EAAE,UAAU,SAAS,QAAQ,cAAc,sBAAsB;CACvE,MAAM,EAAE,WAAW,kBAAkB;CACrC,MAAM,OAAO,gBAAgB;CAC7B,MAAM,sBAAsB,mBAAmB;EAC9C,QAAQ;EACR,cAAc;EACd,CAAC;CACF,MAAM,mBAAmB,OAAuB,EAAE,CAAC;CAEnD,MAAM,gBAAgB,eACd,EACN,gBAAgB,EAAE,WAAW,4BAA4B,EACzD,GACD,EAAE,CACF;CAGD,MAAM,eAAe,oBAAoB;EACxC,gBAAgB;EAChB,OAAO;EACP;EACA,iBAAiB;EACjB,yBAAyB,sBAAsB;AAE9C,WAAQ;IACP,MAAM;IACN,QAAQ,EAAE,gBAAgB,mBAAmB;IAC7C,CAAC;;EAEH,CAAC;CAEF,MAAM,EAAE,cAAc,uBAAuB,gBAC5C,aAAa,YAAY,OAAO,aAAa,gBAC7C,EAAE,SAAS,CAAC,aAAa,WAAW,CACpC;CAED,MAAM,uBAAuB,QAC5B,uBACE,mBAAmB,WAAW,mBAAmB,YACjD,mBAAmB,WAAW,mBAAmB,QACjD,mBAAmB,WACrB;CAED,MAAM,qBAAqB;AAC1B,MAAI,UACH,SAAQ;MAER,UAAS,EAAE,MAAM,QAAQ,CAAC;;AAK5B,iBAAgB;EACf,MAAM,eAAe,aAAa;EAClC,MAAM,gBAAgB,iBAAiB;AAGvC,MAAI,aAAa,SAAS,cAAc,QAAQ;GAE/C,MAAM,WAAW,aAAa,MAAM,cAAc,OAAO;AAGzD,QAAK,MAAM,QAAQ,SAClB,KAAI,KAAK,SAAS,aAAa,CAAC,KAAK,WAAW;AAC/C,yBAAqB;AACrB;;;AAMH,mBAAiB,UAAU;IACzB,CAAC,aAAa,OAAO,oBAAoB,CAAC;AAE7C,QACC,qBAAC;EAAI,WAAU;;GACd,oBAAC;IAAO,UAAU;cACjB,qBAAC;KAAI,WAAU;gBACd,qBAAC;MAAI,WAAU;iBACd,oBAAC;OAAE,WAAU;iBACX,SAAS;QACP,EACJ,oBAAC;OACA,IAAG;OACH,WAAU;OACV,SAAQ;QACP;OACG,EACN,oBAAC;MACA,UAAU;MACV,UAAU;MACV,aAAa;MACb,MAAM;MACN,SAAS;OACR;MACG;KACE;GAET,oBAAC;IACmB;IACG;IACtB,WAAU;IACV,gBAAgB,aAAa;IAC7B,kBAAkB,SAAS;IAC3B,OAAO,aAAa;IACpB,OAAO;KACN;GAED,uBACA,oBAAC;IAAI,WAAU;cACd,oBAAC;KAAK,IAAG;KAAI,SAAQ;MAA6C;KAC7D,GAEN,oBAAC;IAAI,WAAU;cACd,oBAAC;KACA,UAAU,aAAa,SAAS;KAChC,OAAO,aAAa;KACpB,OAAO,aAAa,SAAS;KAC7B,cAAc,aAAa,SAAS;KACpC,UAAU,aAAa,SAAS;KAChC,cAAc,aAAa,SAAS;KACpC,cAAc,aAAa,SAAS;KACpC,UAAU,aAAa,SAAS;KAChC,aAAa,KAAK,wCAAwC;KAC1D,OAAO,aAAa,SAAS;MAC5B;KACG;;GAEF"}
|
package/support/router.d.ts
CHANGED
|
@@ -1,19 +1,29 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { RouteRegistry } from "@cossistant/core";
|
|
2
3
|
|
|
3
4
|
//#region src/support/router.d.ts
|
|
4
|
-
|
|
5
|
+
type CustomPage<K extends keyof RouteRegistry = keyof RouteRegistry> = {
|
|
6
|
+
name: K;
|
|
7
|
+
component: React.ComponentType<{
|
|
8
|
+
params?: RouteRegistry[K];
|
|
9
|
+
}>;
|
|
10
|
+
};
|
|
11
|
+
type SupportRouterProps = {
|
|
12
|
+
customPages?: CustomPage[];
|
|
13
|
+
children?: React.ReactNode;
|
|
14
|
+
};
|
|
5
15
|
/**
|
|
6
16
|
* Router with default support pages (HOME, ARTICLES, CONVERSATION, CONVERSATION_HISTORY).
|
|
7
|
-
* Add custom pages
|
|
17
|
+
* Add custom pages via customPages prop.
|
|
8
18
|
*
|
|
9
19
|
* @example
|
|
10
|
-
* <SupportRouter
|
|
11
|
-
*
|
|
12
|
-
*
|
|
20
|
+
* <SupportRouter
|
|
21
|
+
* customPages={[
|
|
22
|
+
* { name: "SETTINGS", component: SettingsPage }
|
|
23
|
+
* ]}
|
|
24
|
+
* />
|
|
13
25
|
*/
|
|
14
|
-
declare const SupportRouter: React.FC<
|
|
15
|
-
children?: React.ReactNode;
|
|
16
|
-
}>;
|
|
26
|
+
declare const SupportRouter: React.FC<SupportRouterProps>;
|
|
17
27
|
//#endregion
|
|
18
|
-
export { SupportRouter };
|
|
28
|
+
export { CustomPage, SupportRouter, SupportRouterProps };
|
|
19
29
|
//# sourceMappingURL=router.d.ts.map
|
package/support/router.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","names":[],"sources":["../../src/support/router.tsx"],"sourcesContent":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"router.d.ts","names":[],"sources":["../../src/support/router.tsx"],"sourcesContent":[],"mappings":";;;;KAWY,2BAA2B,sBAAsB;QACtD;EADK,SAAA,EAEA,KAAA,CAAM,aAFI,CAAA;IAAiB,MAAA,CAAA,EAEI,aAFJ,CAEkB,CAFlB,CAAA;EAAsB,CAAA,CAAA;CACtD;AACoC,KAG/B,kBAAA,GAH+B;EAAc,WAAA,CAAA,EAI1C,UAJ0C,EAAA;EAA7C,QAAM,CAAA,EAKN,KAAA,CAAM,SALA;CAAa;AAG/B;AAgBA;;;;;;;;;;cAAa,eAAe,KAAA,CAAM,GAAG"}
|
package/support/router.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Page } from "../primitives/page.js";
|
|
2
1
|
import { Router } from "../primitives/router.js";
|
|
3
2
|
import { useSupportNavigation } from "./store/support-store.js";
|
|
4
3
|
import { ArticlesPage } from "./pages/articles.js";
|
|
@@ -10,39 +9,41 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
10
9
|
//#region src/support/router.tsx
|
|
11
10
|
/**
|
|
12
11
|
* Router with default support pages (HOME, ARTICLES, CONVERSATION, CONVERSATION_HISTORY).
|
|
13
|
-
* Add custom pages
|
|
12
|
+
* Add custom pages via customPages prop.
|
|
14
13
|
*
|
|
15
14
|
* @example
|
|
16
|
-
* <SupportRouter
|
|
17
|
-
*
|
|
18
|
-
*
|
|
15
|
+
* <SupportRouter
|
|
16
|
+
* customPages={[
|
|
17
|
+
* { name: "SETTINGS", component: SettingsPage }
|
|
18
|
+
* ]}
|
|
19
|
+
* />
|
|
19
20
|
*/
|
|
20
|
-
const SupportRouter = ({ children }) => {
|
|
21
|
+
const SupportRouter = ({ customPages = [], children }) => {
|
|
21
22
|
const { current } = useSupportNavigation();
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
] });
|
|
23
|
+
const allPages = [...[
|
|
24
|
+
{
|
|
25
|
+
name: "HOME",
|
|
26
|
+
component: HomePage
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: "ARTICLES",
|
|
30
|
+
component: ArticlesPage
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: "CONVERSATION",
|
|
34
|
+
component: ConversationPage
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: "CONVERSATION_HISTORY",
|
|
38
|
+
component: ConversationHistoryPage
|
|
39
|
+
}
|
|
40
|
+
], ...customPages];
|
|
41
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [children, /* @__PURE__ */ jsx(Router, {
|
|
42
|
+
fallback: HomePage,
|
|
43
|
+
page: current.page,
|
|
44
|
+
pages: allPages,
|
|
45
|
+
params: current.params
|
|
46
|
+
})] });
|
|
46
47
|
};
|
|
47
48
|
|
|
48
49
|
//#endregion
|
package/support/router.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","names":["SupportRouter: React.FC<
|
|
1
|
+
{"version":3,"file":"router.js","names":["SupportRouter: React.FC<SupportRouterProps>","Primitive.Router"],"sources":["../../src/support/router.tsx"],"sourcesContent":["import type { RouteRegistry } from \"@cossistant/core\";\nimport type React from \"react\";\nimport type { PageDefinition } from \"../primitives\";\nimport * as Primitive from \"../primitives\";\nimport { ArticlesPage } from \"./pages/articles\";\nimport { ConversationPage } from \"./pages/conversation\";\nimport { ConversationHistoryPage } from \"./pages/conversation-history\";\nimport { HomePage } from \"./pages/home\";\nimport { useSupportNavigation } from \"./store/support-store\";\n\n// Type for custom pages that ensures they match RouteRegistry\nexport type CustomPage<K extends keyof RouteRegistry = keyof RouteRegistry> = {\n\tname: K;\n\tcomponent: React.ComponentType<{ params?: RouteRegistry[K] }>;\n};\n\nexport type SupportRouterProps = {\n\tcustomPages?: CustomPage[];\n\tchildren?: React.ReactNode;\n};\n\n/**\n * Router with default support pages (HOME, ARTICLES, CONVERSATION, CONVERSATION_HISTORY).\n * Add custom pages via customPages prop.\n *\n * @example\n * <SupportRouter\n * customPages={[\n * { name: \"SETTINGS\", component: SettingsPage }\n * ]}\n * />\n */\nexport const SupportRouter: React.FC<SupportRouterProps> = ({\n\tcustomPages = [],\n\tchildren,\n}) => {\n\tconst { current } = useSupportNavigation();\n\n\t// Define all pages with proper typing\n\tconst builtInPages = [\n\t\t{\n\t\t\tname: \"HOME\",\n\t\t\tcomponent: HomePage,\n\t\t},\n\t\t{\n\t\t\tname: \"ARTICLES\",\n\t\t\tcomponent: ArticlesPage,\n\t\t},\n\t\t{\n\t\t\tname: \"CONVERSATION\",\n\t\t\tcomponent: ConversationPage,\n\t\t},\n\t\t{\n\t\t\tname: \"CONVERSATION_HISTORY\",\n\t\t\tcomponent: ConversationHistoryPage,\n\t\t},\n\t] as PageDefinition<keyof RouteRegistry>[];\n\n\t// Combine built-in and custom pages\n\tconst allPages = [...builtInPages, ...customPages] as PageDefinition<\n\t\tkeyof RouteRegistry\n\t>[];\n\n\treturn (\n\t\t<>\n\t\t\t{children}\n\t\t\t<Primitive.Router\n\t\t\t\tfallback={HomePage as React.ComponentType<{ params?: unknown }>}\n\t\t\t\tpage={current.page}\n\t\t\t\tpages={allPages}\n\t\t\t\tparams={current.params}\n\t\t\t/>\n\t\t</>\n\t);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAgCA,MAAaA,iBAA+C,EAC3D,cAAc,EAAE,EAChB,eACK;CACL,MAAM,EAAE,YAAY,sBAAsB;CAuB1C,MAAM,WAAW,CAAC,GApBG;EACpB;GACC,MAAM;GACN,WAAW;GACX;EACD;GACC,MAAM;GACN,WAAW;GACX;EACD;GACC,MAAM;GACN,WAAW;GACX;EACD;GACC,MAAM;GACN,WAAW;GACX;EACD,EAGkC,GAAG,YAAY;AAIlD,QACC,4CACE,UACD,oBAACC;EACA,UAAU;EACV,MAAM,QAAQ;EACd,OAAO;EACP,QAAQ,QAAQ;GACf,IACA"}
|
package/timeline-item.d.ts
CHANGED
|
@@ -61,6 +61,13 @@ declare const timelineItemSchema: ZodObject<{
|
|
|
61
61
|
mediaType: ZodString;
|
|
62
62
|
fileName: ZodOptional<ZodString>;
|
|
63
63
|
size: ZodOptional<ZodNumber>;
|
|
64
|
+
}, $strip>, ZodObject<{
|
|
65
|
+
type: ZodLiteral<"metadata">;
|
|
66
|
+
source: ZodEnum<{
|
|
67
|
+
email: "email";
|
|
68
|
+
widget: "widget";
|
|
69
|
+
api: "api";
|
|
70
|
+
}>;
|
|
64
71
|
}, $strip>]>>;
|
|
65
72
|
userId: ZodNullable<ZodString>;
|
|
66
73
|
aiAgentId: ZodNullable<ZodString>;
|
|
@@ -131,6 +138,13 @@ declare const getConversationTimelineItemsResponseSchema: ZodObject<{
|
|
|
131
138
|
mediaType: ZodString;
|
|
132
139
|
fileName: ZodOptional<ZodString>;
|
|
133
140
|
size: ZodOptional<ZodNumber>;
|
|
141
|
+
}, $strip>, ZodObject<{
|
|
142
|
+
type: ZodLiteral<"metadata">;
|
|
143
|
+
source: ZodEnum<{
|
|
144
|
+
email: "email";
|
|
145
|
+
widget: "widget";
|
|
146
|
+
api: "api";
|
|
147
|
+
}>;
|
|
134
148
|
}, $strip>]>>;
|
|
135
149
|
userId: ZodNullable<ZodString>;
|
|
136
150
|
aiAgentId: ZodNullable<ZodString>;
|
package/timeline-item.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeline-item.d.ts","names":[],"sources":["../../types/src/api/timeline-item.ts"],"sourcesContent":[],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"timeline-item.d.ts","names":[],"sources":["../../types/src/api/timeline-item.ts"],"sourcesContent":[],"mappings":";;;;;;;;cA4Ha,oBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmFwB,SAAA,WAAA;EAAA,SAAA,aAAA,YAAA,UAAA,CAAA,CAAA;AAiBvD,CAAA,QAAY,CAAA;KAhDA,kBAAA,GAAqB,cAAe;KAEpC,YAAA,GAAe,cAAe;cAU7B,2CAAyC;;;;KAe1C,mCAAA,GAAsC,cAC1C;cAGK,4CAA0C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAiB3C,oCAAA,GAAuC,cAC3C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-render-element.d.ts","names":[],"sources":["../../src/utils/use-render-element.tsx"],"sourcesContent":[],"mappings":";;;;AAI+B,KAE1B,YAAA,GAAY,MAAS,GAAA,CAAI,iBAAA;AAAiB,KAE1C,SAAA,CAAA,KAAS,CAAA,GAAA,MAAA,
|
|
1
|
+
{"version":3,"file":"use-render-element.d.ts","names":[],"sources":["../../src/utils/use-render-element.tsx"],"sourcesContent":[],"mappings":";;;;AAI+B,KAE1B,YAAA,GAAY,MAAS,GAAA,CAAI,iBAAA;AAAiB,KAE1C,SAAA,CAAA,KAAS,CAAA,GAAA,MAAA,GAAA,CAA4B,CAAA,KAAK,EAAL,KAAK,EAAA,GAAA,MAAA,CAAA;AAAA,KAE1C,QAAA,CAAA,KAAQ,EAAA,KAAA,CAAA,GAAA,CAAA,KAAA,EACL,KADK,EAAA,KAAA,EAEL,KAFK,EAAA,GAGR,OAAA,CAAM,YAHE;KAKR,WAJG,CAAA,KAAA,EAAA,YAI4B,YAJ5B,CAAA,GAAA;EACA,MAAA,CAAA,EAIE,OAAA,CAAM,YAJR,GAIuB,QAJvB,CAIgC,GAAA,CAAI,iBAJpC,CAIsD,GAJtD,CAAA,EAI4D,KAJ5D,CAAA;EACH,SAAM,CAAA,EAIE,SAJF,CAIY,KAJZ,CAAA;EAAY,OAAA,CAAA,EAAA,OAAA;AAAA,CAAA;KAQlB,YAN+B,CAAA,KAAA,EAAA,YAMC,YAND,CAAA,GAAA;EAC1B,KAAM,CAAA,EAMP,KANO;EAAwB,GAAI,CAAA,EAOrC,OAAA,CAAM,GAP+B,CAAA,GAAA,CAAA;EAAkB,KAAA,CAAA,EAQrD,OARqD,CAQ7C,GAAA,CAAI,iBARyC,CAQvB,GARuB,CAAA,CAAA;EAAM,OAAA,CAAA,EAAA,OAAA;CAArC;;;;AAK1B,iBAyBW,gBAzBC,CAAA,cA0BF,MA1BE,CAAA,MAAA,EAAA,GAAA,CAAA,EAAA,YA2BJ,YA3BI,CAAA,CAAA,GAAA,EA6BX,GA7BW,EAAA,cAAA,EA8BA,WA9BA,CA8BY,KA9BZ,EA8BmB,GA9BnB,CAAA,EAAA,MAAA,CAAA,EA+BP,YA/BO,CA+BM,KA/BN,EA+Ba,GA/Bb,CAAA,CAAA,EAgCd,OAAA,CAAM,YAhCQ,GAAA,IAAA"}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
|
-
//#region src/primitives/page-registry.d.ts
|
|
4
|
-
type PageComponent<P = unknown> = React.ComponentType<{
|
|
5
|
-
params?: P;
|
|
6
|
-
}>;
|
|
7
|
-
type PageRegistry = Map<string, PageComponent>;
|
|
8
|
-
/**
|
|
9
|
-
* Context provider for declarative page registration.
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* <PageRegistryProvider>
|
|
13
|
-
* <Page name="HOME" component={HomePage} />
|
|
14
|
-
* <Router page={currentPage} />
|
|
15
|
-
* </PageRegistryProvider>
|
|
16
|
-
*/
|
|
17
|
-
declare const PageRegistryProvider: React.FC<{
|
|
18
|
-
children: React.ReactNode;
|
|
19
|
-
}>;
|
|
20
|
-
/**
|
|
21
|
-
* Access the page registry (used internally by Router and Page).
|
|
22
|
-
*/
|
|
23
|
-
declare const usePageRegistry: () => PageRegistry;
|
|
24
|
-
/**
|
|
25
|
-
* Register a page in the registry (used internally by Page component).
|
|
26
|
-
*/
|
|
27
|
-
declare const useRegisterPage: (name: string, component: PageComponent) => void;
|
|
28
|
-
//#endregion
|
|
29
|
-
export { PageRegistryProvider, usePageRegistry, useRegisterPage };
|
|
30
|
-
//# sourceMappingURL=page-registry.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"page-registry.d.ts","names":[],"sources":["../../src/primitives/page-registry.tsx"],"sourcesContent":[],"mappings":";;;KAEK,6BAA6B,KAAA,CAAM;WAAyB;AAFC,CAAA,CAAA;AAEb,KAEhD,YAAA,GAAe,GAAH,CAAA,MAAA,EAAe,aAAA,CAAZ;AAapB;AAeA;AAKA;;;;;;;cApBa,sBAAsB,KAAA,CAAM;YAAe,KAAA,CAAM;;;;;cAejD,uBAAe;;;;cAKf,2CAA4C"}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import React, { createContext, useContext, useMemo } from "react";
|
|
2
|
-
import { jsx } from "react/jsx-runtime";
|
|
3
|
-
|
|
4
|
-
//#region src/primitives/page-registry.tsx
|
|
5
|
-
const PageRegistryContext = createContext(/* @__PURE__ */ new Map());
|
|
6
|
-
/**
|
|
7
|
-
* Context provider for declarative page registration.
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* <PageRegistryProvider>
|
|
11
|
-
* <Page name="HOME" component={HomePage} />
|
|
12
|
-
* <Router page={currentPage} />
|
|
13
|
-
* </PageRegistryProvider>
|
|
14
|
-
*/
|
|
15
|
-
const PageRegistryProvider = ({ children }) => {
|
|
16
|
-
const registry = useMemo(() => /* @__PURE__ */ new Map(), []);
|
|
17
|
-
return /* @__PURE__ */ jsx(PageRegistryContext.Provider, {
|
|
18
|
-
value: registry,
|
|
19
|
-
children
|
|
20
|
-
});
|
|
21
|
-
};
|
|
22
|
-
/**
|
|
23
|
-
* Access the page registry (used internally by Router and Page).
|
|
24
|
-
*/
|
|
25
|
-
const usePageRegistry = () => useContext(PageRegistryContext);
|
|
26
|
-
/**
|
|
27
|
-
* Register a page in the registry (used internally by Page component).
|
|
28
|
-
*/
|
|
29
|
-
const useRegisterPage = (name, component) => {
|
|
30
|
-
const registry = usePageRegistry();
|
|
31
|
-
React.useEffect(() => {
|
|
32
|
-
registry.set(name, component);
|
|
33
|
-
return () => {
|
|
34
|
-
registry.delete(name);
|
|
35
|
-
};
|
|
36
|
-
}, [
|
|
37
|
-
name,
|
|
38
|
-
component,
|
|
39
|
-
registry
|
|
40
|
-
]);
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
//#endregion
|
|
44
|
-
export { PageRegistryProvider, usePageRegistry, useRegisterPage };
|
|
45
|
-
//# sourceMappingURL=page-registry.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"page-registry.js","names":["PageRegistryProvider: React.FC<{ children: React.ReactNode }>"],"sources":["../../src/primitives/page-registry.tsx"],"sourcesContent":["import React, { createContext, useContext, useMemo } from \"react\";\n\ntype PageComponent<P = unknown> = React.ComponentType<{ params?: P }>;\n\ntype PageRegistry = Map<string, PageComponent>;\n\nconst PageRegistryContext = createContext<PageRegistry>(new Map());\n\n/**\n * Context provider for declarative page registration.\n *\n * @example\n * <PageRegistryProvider>\n * <Page name=\"HOME\" component={HomePage} />\n * <Router page={currentPage} />\n * </PageRegistryProvider>\n */\nexport const PageRegistryProvider: React.FC<{ children: React.ReactNode }> = ({\n\tchildren,\n}) => {\n\tconst registry = useMemo(() => new Map<string, PageComponent>(), []);\n\n\treturn (\n\t\t<PageRegistryContext.Provider value={registry}>\n\t\t\t{children}\n\t\t</PageRegistryContext.Provider>\n\t);\n};\n\n/**\n * Access the page registry (used internally by Router and Page).\n */\nexport const usePageRegistry = () => useContext(PageRegistryContext);\n\n/**\n * Register a page in the registry (used internally by Page component).\n */\nexport const useRegisterPage = (name: string, component: PageComponent) => {\n\tconst registry = usePageRegistry();\n\n\tReact.useEffect(() => {\n\t\tregistry.set(name, component);\n\t\treturn () => {\n\t\t\tregistry.delete(name);\n\t\t};\n\t}, [name, component, registry]);\n};\n"],"mappings":";;;;AAMA,MAAM,sBAAsB,8BAA4B,IAAI,KAAK,CAAC;;;;;;;;;;AAWlE,MAAaA,wBAAiE,EAC7E,eACK;CACL,MAAM,WAAW,8BAAc,IAAI,KAA4B,EAAE,EAAE,CAAC;AAEpE,QACC,oBAAC,oBAAoB;EAAS,OAAO;EACnC;GAC6B;;;;;AAOjC,MAAa,wBAAwB,WAAW,oBAAoB;;;;AAKpE,MAAa,mBAAmB,MAAc,cAA6B;CAC1E,MAAM,WAAW,iBAAiB;AAElC,OAAM,gBAAgB;AACrB,WAAS,IAAI,MAAM,UAAU;AAC7B,eAAa;AACZ,YAAS,OAAO,KAAK;;IAEpB;EAAC;EAAM;EAAW;EAAS,CAAC"}
|
package/primitives/page.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
//#region src/primitives/page.d.ts
|
|
2
|
-
type PageProps<Params = unknown> = {
|
|
3
|
-
name: string;
|
|
4
|
-
component: React.ComponentType<{
|
|
5
|
-
params?: Params;
|
|
6
|
-
}>;
|
|
7
|
-
};
|
|
8
|
-
/**
|
|
9
|
-
* Declaratively register a page component.
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* <Page name="HOME" component={HomePage} />
|
|
13
|
-
* <Page name="SETTINGS" component={SettingsPage} />
|
|
14
|
-
*/
|
|
15
|
-
declare function Page<Params = unknown>({
|
|
16
|
-
name,
|
|
17
|
-
component
|
|
18
|
-
}: PageProps<Params>): null;
|
|
19
|
-
//#endregion
|
|
20
|
-
export { Page, PageProps };
|
|
21
|
-
//# sourceMappingURL=page.d.ts.map
|
package/primitives/page.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"page.d.ts","names":[],"sources":["../../src/primitives/page.tsx"],"sourcesContent":[],"mappings":";KAEY;EAAA,IAAA,EAAA,MAAS;EAYL,SAAI,EAVR,KAAA,CAAM,aAUE,CAAA;IACnB,MAAA,CAAA,EAX0C,MAW1C;EACA,CAAA,CAAA;CACY;;;;;;;;iBAHG;;;GAGb,UAAU"}
|
package/primitives/page.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { useRegisterPage } from "./page-registry.js";
|
|
2
|
-
|
|
3
|
-
//#region src/primitives/page.tsx
|
|
4
|
-
/**
|
|
5
|
-
* Declaratively register a page component.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* <Page name="HOME" component={HomePage} />
|
|
9
|
-
* <Page name="SETTINGS" component={SettingsPage} />
|
|
10
|
-
*/
|
|
11
|
-
function Page({ name, component }) {
|
|
12
|
-
useRegisterPage(name, component);
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
//#endregion
|
|
17
|
-
export { Page };
|
|
18
|
-
//# sourceMappingURL=page.js.map
|
package/primitives/page.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"page.js","names":[],"sources":["../../src/primitives/page.tsx"],"sourcesContent":["import { useRegisterPage } from \"./page-registry\";\n\nexport type PageProps<Params = unknown> = {\n\tname: string;\n\tcomponent: React.ComponentType<{ params?: Params }>;\n};\n\n/**\n * Declaratively register a page component.\n *\n * @example\n * <Page name=\"HOME\" component={HomePage} />\n * <Page name=\"SETTINGS\" component={SettingsPage} />\n */\nexport function Page<Params = unknown>({\n\tname,\n\tcomponent,\n}: PageProps<Params>): null {\n\tuseRegisterPage(name, component as React.ComponentType<{ params?: unknown }>);\n\treturn null;\n}\n"],"mappings":";;;;;;;;;;AAcA,SAAgB,KAAuB,EACtC,MACA,aAC2B;AAC3B,iBAAgB,MAAM,UAAuD;AAC7E,QAAO"}
|