keystone-design-bootstrap 1.0.84 → 1.0.86
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/dist/design_system/logo/keystone-logo.js +102 -31
- package/dist/design_system/logo/keystone-logo.js.map +1 -1
- package/dist/index.js +156 -37
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
- package/src/design_system/chat/useRealtimeReplyOrchestrator.ts +127 -0
- package/src/design_system/components/ChatWidget.tsx +58 -37
- package/src/design_system/logo/assets/keystone-logo.svg +17 -0
- package/src/design_system/logo/assets/keystone-wordmark.svg +22 -0
- package/src/design_system/logo/keystone-brand-lockup.tsx +25 -0
- package/src/design_system/logo/keystone-logo-minimal.tsx +26 -87
- package/src/design_system/logo/keystone-logo.tsx +3 -9
- package/src/design_system/logo/keystone-wordmark.tsx +49 -0
- package/src/design_system/portal/LoginModalController.tsx +12 -6
- package/src/design_system/portal/MessageComposer.tsx +53 -1
- package/src/design_system/portal/PortalPage.tsx +16 -5
- package/src/next/routes/chat.ts +57 -1
|
@@ -31,42 +31,113 @@ var twMerge = extendTailwindMerge({
|
|
|
31
31
|
var cx = twMerge;
|
|
32
32
|
|
|
33
33
|
// src/design_system/logo/keystone-logo-minimal.tsx
|
|
34
|
-
import { useId } from "react";
|
|
35
34
|
var KeystoneLogoMinimal = (props) => {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
35
|
+
return /* @__PURE__ */ React.createElement(
|
|
36
|
+
"svg",
|
|
37
|
+
__spreadProps(__spreadValues({
|
|
38
|
+
viewBox: "0 0 36 41",
|
|
39
|
+
fill: "none",
|
|
40
|
+
"aria-hidden": "true"
|
|
41
|
+
}, props), {
|
|
42
|
+
className: cx("text-[#6ECC8B]", props.className)
|
|
43
|
+
}),
|
|
44
|
+
/* @__PURE__ */ React.createElement(
|
|
45
|
+
"path",
|
|
46
|
+
{
|
|
47
|
+
d: "M36 13.6677L24.0031 20.4999L36 27.3321V40.9966L11.998 27.3288V13.671L36 0.0032959V13.6677Z",
|
|
48
|
+
fill: "currentColor"
|
|
49
|
+
}
|
|
50
|
+
),
|
|
51
|
+
/* @__PURE__ */ React.createElement(
|
|
52
|
+
"path",
|
|
53
|
+
{
|
|
54
|
+
d: "M11.9971 27.3288V40.9958L0 34.1644V20.4973L11.9971 27.3288Z",
|
|
55
|
+
fill: "currentColor"
|
|
56
|
+
}
|
|
57
|
+
),
|
|
58
|
+
/* @__PURE__ */ React.createElement(
|
|
59
|
+
"path",
|
|
60
|
+
{
|
|
61
|
+
d: "M11.9971 13.671L0.00476074 20.4999L0 20.4973V6.83551L11.9971 0.00402832V13.671Z",
|
|
62
|
+
fill: "currentColor"
|
|
63
|
+
}
|
|
64
|
+
)
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// src/design_system/logo/keystone-wordmark.tsx
|
|
69
|
+
var KeystoneWordmark = (props) => {
|
|
70
|
+
return /* @__PURE__ */ React.createElement(
|
|
71
|
+
"svg",
|
|
72
|
+
__spreadProps(__spreadValues({
|
|
73
|
+
viewBox: "0 0 104 20",
|
|
74
|
+
fill: "none",
|
|
75
|
+
"aria-hidden": "true"
|
|
76
|
+
}, props), {
|
|
77
|
+
className: cx("text-[#6ECC8B]", props.className)
|
|
78
|
+
}),
|
|
79
|
+
/* @__PURE__ */ React.createElement(
|
|
80
|
+
"path",
|
|
81
|
+
{
|
|
82
|
+
d: "M3.14032 0L3.1612 8.23754H3.82871L9.47236 2.94575H13.0328V3.34299L6.45695 9.52024L13.2946 16.1684V16.5656H9.53903L3.8267 11.0811H3.15919V16.5584H0V0H3.14032Z",
|
|
83
|
+
fill: "currentColor"
|
|
84
|
+
}
|
|
85
|
+
),
|
|
86
|
+
/* @__PURE__ */ React.createElement(
|
|
87
|
+
"path",
|
|
88
|
+
{
|
|
89
|
+
d: "M18.4299 2.62219C22.4643 2.62219 24.8242 5.10147 24.8242 9.20756V10.6049H14.6121C14.6635 12.8878 16.0848 14.486 18.4167 14.486C20.7485 14.486 21.6835 13.2718 21.8892 12.243H24.5535V12.6403C24.1957 14.422 22.5534 16.8876 18.4552 16.8876C14.357 16.8876 11.7031 14.4462 11.7031 9.7505C11.7031 5.05478 14.3675 2.62662 18.4295 2.62662L18.4299 2.62219ZM21.9647 8.28025C21.939 6.42119 20.7365 4.9932 18.3914 4.9932C16.0463 4.9932 14.8181 6.45903 14.6506 8.28025H21.9667H21.9647Z",
|
|
90
|
+
fill: "currentColor"
|
|
91
|
+
}
|
|
92
|
+
),
|
|
93
|
+
/* @__PURE__ */ React.createElement(
|
|
94
|
+
"path",
|
|
95
|
+
{
|
|
96
|
+
d: "M27.5146 2.93809L31.2554 12.994H31.459L35.1865 2.93809H38.2369V3.33534L31.565 19.9996H28.5147V19.6024L29.7417 16.5942L24.3848 3.33292V2.93567H27.5142L27.5146 2.93809Z",
|
|
97
|
+
fill: "currentColor"
|
|
98
|
+
}
|
|
99
|
+
),
|
|
100
|
+
/* @__PURE__ */ React.createElement(
|
|
101
|
+
"path",
|
|
102
|
+
{
|
|
103
|
+
d: "M44.1191 2.63538C47.759 2.63538 49.8832 4.19177 50.1017 6.73947V7.13671H47.3345C47.2445 5.53847 45.965 4.98667 44.1319 4.98667C42.2989 4.98667 41.3129 5.54088 41.3129 6.5982C41.3129 7.65551 42.1338 7.9956 43.3002 8.18115L45.8103 8.57839C48.4747 9.0022 50.2796 10.1214 50.2796 12.6027C50.2796 15.084 48.3591 16.8767 44.4898 16.8767C40.6205 16.8767 38.3782 15.082 38.1855 12.6667V12.2695H41.0045C41.133 13.8677 42.5692 14.5258 44.4898 14.5258C46.4104 14.5258 47.3859 13.8391 47.3859 12.7706C47.3859 11.702 46.5521 11.2782 45.1332 11.0552L42.623 10.658C40.1129 10.2607 38.4324 9.12818 38.4324 6.66219C38.4324 4.1962 40.4944 2.6378 44.1215 2.6378H44.1195L44.1191 2.63538Z",
|
|
104
|
+
fill: "currentColor"
|
|
105
|
+
}
|
|
106
|
+
),
|
|
107
|
+
/* @__PURE__ */ React.createElement(
|
|
108
|
+
"path",
|
|
109
|
+
{
|
|
110
|
+
d: "M54.2257 2.93729V0H57.2632V2.93729H62.247V5.35257H57.2632V13.7724L57.4668 13.9821H62.1679V16.5673H57.8765C55.5828 16.5673 54.2237 15.353 54.2237 13.0327V5.35217H50.2773V2.93689L54.2257 2.93729Z",
|
|
111
|
+
fill: "currentColor"
|
|
112
|
+
}
|
|
113
|
+
),
|
|
114
|
+
/* @__PURE__ */ React.createElement(
|
|
115
|
+
"path",
|
|
116
|
+
{
|
|
117
|
+
d: "M69.219 2.62219C73.3325 2.62219 76.2025 5.13004 76.2025 9.74608C76.2025 14.3621 73.3325 16.8832 69.219 16.8832C65.1056 16.8832 62.25 14.3754 62.25 9.74608C62.25 5.11676 65.1052 2.62219 69.219 2.62219ZM69.219 14.4442C71.6003 14.4442 73.1265 12.7687 73.1265 9.74648C73.1265 6.72426 71.6023 5.06202 69.219 5.06202C66.8358 5.06202 65.3241 6.73754 65.3241 9.74648C65.3241 12.7554 66.8482 14.4442 69.219 14.4442Z",
|
|
118
|
+
fill: "currentColor"
|
|
119
|
+
}
|
|
120
|
+
),
|
|
121
|
+
/* @__PURE__ */ React.createElement(
|
|
122
|
+
"path",
|
|
123
|
+
{
|
|
124
|
+
d: "M80.2535 2.94007V4.45661H80.4568C81.3785 3.16304 82.8641 2.64868 84.6606 2.64868C87.7989 2.64868 89.7472 4.29763 89.7472 7.66236V16.5681H86.7097V7.93846C86.7097 6.03755 85.698 5.15451 83.8907 5.15451C81.9315 5.15451 80.3539 6.30238 80.3539 8.95392V16.566H77.3164V2.94007H80.2535Z",
|
|
125
|
+
fill: "currentColor"
|
|
126
|
+
}
|
|
127
|
+
),
|
|
128
|
+
/* @__PURE__ */ React.createElement(
|
|
129
|
+
"path",
|
|
130
|
+
{
|
|
131
|
+
d: "M97.6065 2.62219C101.64 2.62219 104 5.10147 104 9.20756V10.6049H93.7886C93.838 12.8878 95.261 14.486 97.5933 14.486C99.9255 14.486 100.859 13.2718 101.065 12.243H103.729V12.6403C103.371 14.422 101.73 16.8876 97.6314 16.8876C93.5328 16.8876 90.8789 14.4462 90.8789 9.7505C90.8789 5.05478 93.5437 2.62662 97.6057 2.62662L97.6065 2.62219ZM101.141 8.28025C101.115 6.42119 99.9127 4.9932 97.568 4.9932C95.2233 4.9932 93.9943 6.45903 93.8272 8.28025H101.143H101.141Z",
|
|
132
|
+
fill: "currentColor"
|
|
133
|
+
}
|
|
134
|
+
)
|
|
135
|
+
);
|
|
65
136
|
};
|
|
66
137
|
|
|
67
138
|
// src/design_system/logo/keystone-logo.tsx
|
|
68
139
|
var KeystoneLogo = (props) => {
|
|
69
|
-
return /* @__PURE__ */ React.createElement("div", __spreadProps(__spreadValues({}, props), { className: cx("flex h-8 w-max items-
|
|
140
|
+
return /* @__PURE__ */ React.createElement("div", __spreadProps(__spreadValues({}, props), { className: cx("flex h-8 w-max items-stretch justify-start overflow-visible", props.className) }), /* @__PURE__ */ React.createElement(KeystoneLogoMinimal, { className: "aspect-square h-full w-auto shrink-0" }), /* @__PURE__ */ React.createElement("div", { className: "aspect-[0.4] h-full" }), /* @__PURE__ */ React.createElement(KeystoneWordmark, { className: "h-full w-auto shrink-0" }));
|
|
70
141
|
};
|
|
71
142
|
export {
|
|
72
143
|
KeystoneLogo
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/cx.ts","../../../src/design_system/logo/keystone-logo-minimal.tsx","../../../src/design_system/logo/keystone-logo.tsx"],"sourcesContent":["import { extendTailwindMerge } from \"tailwind-merge\";\n\nconst twMerge = extendTailwindMerge({\n extend: {\n theme: {\n text: [\"display-xs\", \"display-sm\", \"display-md\", \"display-lg\", \"display-xl\", \"display-2xl\"],\n },\n },\n});\n\n/**\n * This function is a wrapper around the twMerge function.\n * It is used to merge the classes inside style objects.\n */\nexport const cx = twMerge;\n\n/**\n * This function does nothing besides helping us to be able to\n * sort the classes inside style objects which is not supported\n * by the Tailwind IntelliSense by default.\n */\nexport function sortCx<T extends Record<string, string | number | Record<string, string | number | Record<string, string | number>>>>(classes: T): T {\n return classes;\n}\n\n","\"use client\";\n\nimport type { SVGProps } from \"react\";\nimport { useId } from \"react\";\nimport { cx } from '../../utils/cx';\n\nexport const KeystoneLogoMinimal = (props: SVGProps<SVGSVGElement>) => {\n const id = useId();\n\n return (\n <svg viewBox=\"0 0 38 38\" fill=\"none\" {...props} className={cx(\"size-8 origin-center scale-[1.2]\", props.className)}>\n <g filter={`url(#filter0-${id})`}>\n <g clipPath={`url(#clip0-${id})`}>\n <path\n d=\"M3 14.8C3 10.3196 3 8.07937 3.87195 6.36808C4.63893 4.86278 5.86278 3.63893 7.36808 2.87195C9.07937 2 11.3196 2 15.8 2H22.2C26.6804 2 28.9206 2 30.6319 2.87195C32.1372 3.63893 33.3611 4.86278 34.1281 6.36808C35 8.07937 35 10.3196 35 14.8V21.2C35 25.6804 35 27.9206 34.1281 29.6319C33.3611 31.1372 32.1372 32.3611 30.6319 33.1281C28.9206 34 26.6804 34 22.2 34H15.8C11.3196 34 9.07937 34 7.36808 33.1281C5.86278 32.3611 4.63893 31.1372 3.87195 29.6319C3 27.9206 3 25.6804 3 21.2V14.8Z\"\n fill=\"white\"\n />\n <path\n d=\"M3 14.8C3 10.3196 3 8.07937 3.87195 6.36808C4.63893 4.86278 5.86278 3.63893 7.36808 2.87195C9.07937 2 11.3196 2 15.8 2H22.2C26.6804 2 28.9206 2 30.6319 2.87195C32.1372 3.63893 33.3611 4.86278 34.1281 6.36808C35 8.07937 35 10.3196 35 14.8V21.2C35 25.6804 35 27.9206 34.1281 29.6319C33.3611 31.1372 32.1372 32.3611 30.6319 33.1281C28.9206 34 26.6804 34 22.2 34H15.8C11.3196 34 9.07937 34 7.36808 33.1281C5.86278 32.3611 4.63893 31.1372 3.87195 29.6319C3 27.9206 3 25.6804 3 21.2V14.8Z\"\n fill={`url(#paint0_linear-${id})`}\n fillOpacity=\"0.2\"\n />\n {/* Clean pistachio circle */}\n <circle cx=\"19\" cy=\"19\" r=\"8\" fill={`url(#paint1_linear-${id})`} />\n </g>\n <path\n d=\"M3.1 14.8C3.1 12.5581 3.10008 10.8828 3.20866 9.55376C3.31715 8.22593 3.53345 7.25268 3.96105 6.41348C4.71845 4.92699 5.92699 3.71845 7.41348 2.96105C8.25268 2.53345 9.22593 2.31715 10.5538 2.20866C11.8828 2.10008 13.5581 2.1 15.8 2.1H22.2C24.4419 2.1 26.1172 2.10008 27.4462 2.20866C28.7741 2.31715 29.7473 2.53345 30.5865 2.96105C32.073 3.71845 33.2816 4.92699 34.039 6.41348C34.4665 7.25268 34.6828 8.22593 34.7913 9.55376C34.8999 10.8828 34.9 12.5581 34.9 14.8V21.2C34.9 23.4419 34.8999 25.1172 34.7913 26.4462C34.6828 27.7741 34.4665 28.7473 34.039 29.5865C33.2816 31.073 32.073 32.2816 30.5865 33.039C29.7473 33.4665 28.7741 33.6828 27.4462 33.7913C26.1172 33.8999 24.4419 33.9 22.2 33.9H15.8C13.5581 33.9 11.8828 33.8999 10.5538 33.7913C9.22593 33.6828 8.25268 33.4665 7.41348 33.039C5.92699 32.2816 4.71845 31.073 3.96105 29.5865C3.53345 28.7473 3.31715 27.7741 3.20866 26.4462C3.10008 25.1172 3.1 23.4419 3.1 21.2V14.8Z\"\n stroke=\"#0A0D12\"\n strokeOpacity=\"0.12\"\n strokeWidth=\"0.2\"\n />\n </g>\n\n <defs>\n <filter id={`filter0-${id}`} x=\"0\" y=\"0\" width=\"38\" height=\"38\" filterUnits=\"userSpaceOnUse\" colorInterpolationFilters=\"sRGB\">\n <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\n <feColorMatrix in=\"SourceAlpha\" type=\"matrix\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\" result=\"hardAlpha\" />\n <feOffset dy=\"1\" />\n <feGaussianBlur stdDeviation=\"1\" />\n <feColorMatrix type=\"matrix\" values=\"0 0 0 0 0.0392157 0 0 0 0 0.0509804 0 0 0 0 0.0705882 0 0 0 0.06 0\" />\n <feBlend mode=\"normal\" in2=\"BackgroundImageFix\" result=\"effect1_dropShadow\" />\n <feColorMatrix in=\"SourceAlpha\" type=\"matrix\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\" result=\"hardAlpha\" />\n <feOffset dy=\"1\" />\n <feGaussianBlur stdDeviation=\"1.5\" />\n <feColorMatrix type=\"matrix\" values=\"0 0 0 0 0.0392157 0 0 0 0 0.0509804 0 0 0 0 0.0705882 0 0 0 0.1 0\" />\n <feBlend mode=\"normal\" in2=\"effect2_dropShadow\" result=\"effect2_dropShadow\" />\n <feColorMatrix in=\"SourceAlpha\" type=\"matrix\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\" result=\"hardAlpha\" />\n <feMorphology radius=\"0.5\" operator=\"erode\" in=\"SourceAlpha\" result=\"effect3_dropShadow\" />\n <feOffset dy=\"1\" />\n <feGaussianBlur stdDeviation=\"0.5\" />\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\n <feColorMatrix type=\"matrix\" values=\"0 0 0 0 0.0392157 0 0 0 0 0.0509804 0 0 0 0 0.0705882 0 0 0 0.13 0\" />\n <feBlend mode=\"normal\" in2=\"effect2_dropShadow\" result=\"effect3_dropShadow\" />\n <feBlend mode=\"normal\" in=\"SourceGraphic\" in2=\"effect3_dropShadow\" result=\"shape\" />\n <feColorMatrix in=\"SourceAlpha\" type=\"matrix\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\" result=\"hardAlpha\" />\n <feOffset dy=\"-0.5\" />\n <feGaussianBlur stdDeviation=\"0.25\" />\n <feComposite in2=\"hardAlpha\" operator=\"arithmetic\" k2=\"-1\" k3=\"1\" />\n <feColorMatrix type=\"matrix\" values=\"0 0 0 0 0.0392157 0 0 0 0 0.0509804 0 0 0 0 0.0705882 0 0 0 0.1 0\" />\n <feBlend mode=\"normal\" in2=\"shape\" result=\"effect4_innerShadow\" />\n </filter>\n <filter id={`filter1_dd-${id}`} x=\"8\" y=\"8\" width=\"22\" height=\"22\" filterUnits=\"userSpaceOnUse\" colorInterpolationFilters=\"sRGB\">\n <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\" />\n <feColorMatrix in=\"SourceAlpha\" type=\"matrix\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\" result=\"hardAlpha\" />\n <feOffset dy=\"1\" />\n <feGaussianBlur stdDeviation=\"1\" />\n <feColorMatrix type=\"matrix\" values=\"0 0 0 0 0.0392157 0 0 0 0 0.0509804 0 0 0 0 0.0705882 0 0 0 0.06 0\" />\n <feBlend mode=\"normal\" in2=\"BackgroundImageFix\" result=\"effect1_dropShadow\" />\n <feColorMatrix in=\"SourceAlpha\" type=\"matrix\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\" result=\"hardAlpha\" />\n <feOffset dy=\"1\" />\n <feGaussianBlur stdDeviation=\"1.5\" />\n <feColorMatrix type=\"matrix\" values=\"0 0 0 0 0.0392157 0 0 0 0 0.0509804 0 0 0 0 0.0705882 0 0 0 0.1 0\" />\n <feBlend mode=\"normal\" in2=\"effect1_dropShadow\" result=\"effect2_dropShadow\" />\n <feBlend mode=\"normal\" in=\"SourceGraphic\" in2=\"effect2_dropShadow\" result=\"shape\" />\n </filter>\n <linearGradient id={`paint0_linear-${id}`} x1=\"19\" y1=\"2\" x2=\"19\" y2=\"34\" gradientUnits=\"userSpaceOnUse\">\n <stop stopColor=\"white\" />\n <stop offset=\"1\" stopColor=\"#0A0D12\" />\n </linearGradient>\n <linearGradient id={`paint1_linear-${id}`} x1=\"15\" y1=\"26\" x2=\"23\" y2=\"10\" gradientUnits=\"userSpaceOnUse\">\n <stop stopColor=\"#66D674\" />\n <stop offset=\"1\" stopColor=\"#42D674\" />\n </linearGradient>\n <clipPath id={`clip0-${id}`}>\n <path\n d=\"M3 14.8C3 10.3196 3 8.07937 3.87195 6.36808C4.63893 4.86278 5.86278 3.63893 7.36808 2.87195C9.07937 2 11.3196 2 15.8 2H22.2C26.6804 2 28.9206 2 30.6319 2.87195C32.1372 3.63893 33.3611 4.86278 34.1281 6.36808C35 8.07937 35 10.3196 35 14.8V21.2C35 25.6804 35 27.9206 34.1281 29.6319C33.3611 31.1372 32.1372 32.3611 30.6319 33.1281C28.9206 34 26.6804 34 22.2 34H15.8C11.3196 34 9.07937 34 7.36808 33.1281C5.86278 32.3611 4.63893 31.1372 3.87195 29.6319C3 27.9206 3 25.6804 3 21.2V14.8Z\"\n fill=\"white\"\n />\n </clipPath>\n </defs>\n </svg>\n );\n};\n","\"use client\";\n\nimport type { HTMLAttributes } from \"react\";\nimport { cx } from '../../utils/cx';\nimport { KeystoneLogoMinimal } from \"./keystone-logo-minimal\";\n\nexport const KeystoneLogo = (props: HTMLAttributes<HTMLOrSVGElement>) => {\n return (\n <div {...props} className={cx(\"flex h-8 w-max items-center justify-start overflow-visible\", props.className)}>\n {/* Minimal logo */}\n <KeystoneLogoMinimal className=\"aspect-square h-full w-auto shrink-0\" />\n\n {/* Gap that adjusts to the height of the container */}\n <div className=\"aspect-[0.4] h-full\" />\n\n {/* Clean text logo */}\n <div className=\"flex items-center\">\n <span className=\"text-lg font-semibold text-fg-primary\">Keystone</span>\n </div>\n </div>\n );\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/cx.ts","../../../src/design_system/logo/keystone-logo-minimal.tsx","../../../src/design_system/logo/keystone-wordmark.tsx","../../../src/design_system/logo/keystone-logo.tsx"],"sourcesContent":["import { extendTailwindMerge } from \"tailwind-merge\";\n\nconst twMerge = extendTailwindMerge({\n extend: {\n theme: {\n text: [\"display-xs\", \"display-sm\", \"display-md\", \"display-lg\", \"display-xl\", \"display-2xl\"],\n },\n },\n});\n\n/**\n * This function is a wrapper around the twMerge function.\n * It is used to merge the classes inside style objects.\n */\nexport const cx = twMerge;\n\n/**\n * This function does nothing besides helping us to be able to\n * sort the classes inside style objects which is not supported\n * by the Tailwind IntelliSense by default.\n */\nexport function sortCx<T extends Record<string, string | number | Record<string, string | number | Record<string, string | number>>>>(classes: T): T {\n return classes;\n}\n\n","\"use client\";\n\nimport type { SVGProps } from \"react\";\nimport { cx } from \"../../utils/cx\";\n\nexport const KEYSTONE_BRAND_COLOR = \"#6ECC8B\";\nexport const KEYSTONE_APP_URL = \"https://www.keystone.app\";\n\nexport const KeystoneLogoMinimal = (props: SVGProps<SVGSVGElement>) => {\n return (\n <svg\n viewBox=\"0 0 36 41\"\n fill=\"none\"\n aria-hidden=\"true\"\n {...props}\n className={cx(\"text-[#6ECC8B]\", props.className)}\n >\n <path\n d=\"M36 13.6677L24.0031 20.4999L36 27.3321V40.9966L11.998 27.3288V13.671L36 0.0032959V13.6677Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M11.9971 27.3288V40.9958L0 34.1644V20.4973L11.9971 27.3288Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M11.9971 13.671L0.00476074 20.4999L0 20.4973V6.83551L11.9971 0.00402832V13.671Z\"\n fill=\"currentColor\"\n />\n </svg>\n );\n};\n","\"use client\";\n\nimport type { SVGProps } from \"react\";\nimport { cx } from \"../../utils/cx\";\n\nexport const KeystoneWordmark = (props: SVGProps<SVGSVGElement>) => {\n return (\n <svg\n viewBox=\"0 0 104 20\"\n fill=\"none\"\n aria-hidden=\"true\"\n {...props}\n className={cx(\"text-[#6ECC8B]\", props.className)}\n >\n <path\n d=\"M3.14032 0L3.1612 8.23754H3.82871L9.47236 2.94575H13.0328V3.34299L6.45695 9.52024L13.2946 16.1684V16.5656H9.53903L3.8267 11.0811H3.15919V16.5584H0V0H3.14032Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M18.4299 2.62219C22.4643 2.62219 24.8242 5.10147 24.8242 9.20756V10.6049H14.6121C14.6635 12.8878 16.0848 14.486 18.4167 14.486C20.7485 14.486 21.6835 13.2718 21.8892 12.243H24.5535V12.6403C24.1957 14.422 22.5534 16.8876 18.4552 16.8876C14.357 16.8876 11.7031 14.4462 11.7031 9.7505C11.7031 5.05478 14.3675 2.62662 18.4295 2.62662L18.4299 2.62219ZM21.9647 8.28025C21.939 6.42119 20.7365 4.9932 18.3914 4.9932C16.0463 4.9932 14.8181 6.45903 14.6506 8.28025H21.9667H21.9647Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M27.5146 2.93809L31.2554 12.994H31.459L35.1865 2.93809H38.2369V3.33534L31.565 19.9996H28.5147V19.6024L29.7417 16.5942L24.3848 3.33292V2.93567H27.5142L27.5146 2.93809Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M44.1191 2.63538C47.759 2.63538 49.8832 4.19177 50.1017 6.73947V7.13671H47.3345C47.2445 5.53847 45.965 4.98667 44.1319 4.98667C42.2989 4.98667 41.3129 5.54088 41.3129 6.5982C41.3129 7.65551 42.1338 7.9956 43.3002 8.18115L45.8103 8.57839C48.4747 9.0022 50.2796 10.1214 50.2796 12.6027C50.2796 15.084 48.3591 16.8767 44.4898 16.8767C40.6205 16.8767 38.3782 15.082 38.1855 12.6667V12.2695H41.0045C41.133 13.8677 42.5692 14.5258 44.4898 14.5258C46.4104 14.5258 47.3859 13.8391 47.3859 12.7706C47.3859 11.702 46.5521 11.2782 45.1332 11.0552L42.623 10.658C40.1129 10.2607 38.4324 9.12818 38.4324 6.66219C38.4324 4.1962 40.4944 2.6378 44.1215 2.6378H44.1195L44.1191 2.63538Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M54.2257 2.93729V0H57.2632V2.93729H62.247V5.35257H57.2632V13.7724L57.4668 13.9821H62.1679V16.5673H57.8765C55.5828 16.5673 54.2237 15.353 54.2237 13.0327V5.35217H50.2773V2.93689L54.2257 2.93729Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M69.219 2.62219C73.3325 2.62219 76.2025 5.13004 76.2025 9.74608C76.2025 14.3621 73.3325 16.8832 69.219 16.8832C65.1056 16.8832 62.25 14.3754 62.25 9.74608C62.25 5.11676 65.1052 2.62219 69.219 2.62219ZM69.219 14.4442C71.6003 14.4442 73.1265 12.7687 73.1265 9.74648C73.1265 6.72426 71.6023 5.06202 69.219 5.06202C66.8358 5.06202 65.3241 6.73754 65.3241 9.74648C65.3241 12.7554 66.8482 14.4442 69.219 14.4442Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M80.2535 2.94007V4.45661H80.4568C81.3785 3.16304 82.8641 2.64868 84.6606 2.64868C87.7989 2.64868 89.7472 4.29763 89.7472 7.66236V16.5681H86.7097V7.93846C86.7097 6.03755 85.698 5.15451 83.8907 5.15451C81.9315 5.15451 80.3539 6.30238 80.3539 8.95392V16.566H77.3164V2.94007H80.2535Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M97.6065 2.62219C101.64 2.62219 104 5.10147 104 9.20756V10.6049H93.7886C93.838 12.8878 95.261 14.486 97.5933 14.486C99.9255 14.486 100.859 13.2718 101.065 12.243H103.729V12.6403C103.371 14.422 101.73 16.8876 97.6314 16.8876C93.5328 16.8876 90.8789 14.4462 90.8789 9.7505C90.8789 5.05478 93.5437 2.62662 97.6057 2.62662L97.6065 2.62219ZM101.141 8.28025C101.115 6.42119 99.9127 4.9932 97.568 4.9932C95.2233 4.9932 93.9943 6.45903 93.8272 8.28025H101.143H101.141Z\"\n fill=\"currentColor\"\n />\n </svg>\n );\n};\n","\"use client\";\n\nimport type { HTMLAttributes } from \"react\";\nimport { cx } from '../../utils/cx';\nimport { KeystoneLogoMinimal } from \"./keystone-logo-minimal\";\nimport { KeystoneWordmark } from \"./keystone-wordmark\";\n\nexport const KeystoneLogo = (props: HTMLAttributes<HTMLOrSVGElement>) => {\n return (\n <div {...props} className={cx(\"flex h-8 w-max items-stretch justify-start overflow-visible\", props.className)}>\n <KeystoneLogoMinimal className=\"aspect-square h-full w-auto shrink-0\" />\n <div className=\"aspect-[0.4] h-full\" />\n <KeystoneWordmark className=\"h-full w-auto shrink-0\" />\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,2BAA2B;AAEpC,IAAM,UAAU,oBAAoB;AAAA,EAChC,QAAQ;AAAA,IACJ,OAAO;AAAA,MACH,MAAM,CAAC,cAAc,cAAc,cAAc,cAAc,cAAc,aAAa;AAAA,IAC9F;AAAA,EACJ;AACJ,CAAC;AAMM,IAAM,KAAK;;;ACNX,IAAM,sBAAsB,CAAC,UAAmC;AACrE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,eAAY;AAAA,OACR,QAJL;AAAA,MAKC,WAAW,GAAG,kBAAkB,MAAM,SAAS;AAAA;AAAA,IAE/C;AAAA,MAAC;AAAA;AAAA,QACC,GAAE;AAAA,QACF,MAAK;AAAA;AAAA,IACP;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,GAAE;AAAA,QACF,MAAK;AAAA;AAAA,IACP;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,GAAE;AAAA,QACF,MAAK;AAAA;AAAA,IACP;AAAA,EACF;AAEJ;;;AC1BO,IAAM,mBAAmB,CAAC,UAAmC;AAClE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,eAAY;AAAA,OACR,QAJL;AAAA,MAKC,WAAW,GAAG,kBAAkB,MAAM,SAAS;AAAA;AAAA,IAE/C;AAAA,MAAC;AAAA;AAAA,QACC,GAAE;AAAA,QACF,MAAK;AAAA;AAAA,IACP;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,GAAE;AAAA,QACF,MAAK;AAAA;AAAA,IACP;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,GAAE;AAAA,QACF,MAAK;AAAA;AAAA,IACP;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,GAAE;AAAA,QACF,MAAK;AAAA;AAAA,IACP;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,GAAE;AAAA,QACF,MAAK;AAAA;AAAA,IACP;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,GAAE;AAAA,QACF,MAAK;AAAA;AAAA,IACP;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,GAAE;AAAA,QACF,MAAK;AAAA;AAAA,IACP;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,GAAE;AAAA,QACF,MAAK;AAAA;AAAA,IACP;AAAA,EACF;AAEJ;;;ACzCO,IAAM,eAAe,CAAC,UAA4C;AACrE,SACI,oCAAC,wCAAQ,QAAR,EAAe,WAAW,GAAG,+DAA+D,MAAM,SAAS,MACxG,oCAAC,uBAAoB,WAAU,wCAAuC,GACtE,oCAAC,SAAI,WAAU,uBAAsB,GACrC,oCAAC,oBAAiB,WAAU,0BAAyB,CACzD;AAER;","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -19917,8 +19917,108 @@ async function submitLeadFormAction(formData) {
|
|
|
19917
19917
|
}
|
|
19918
19918
|
|
|
19919
19919
|
// src/design_system/components/ChatWidget.tsx
|
|
19920
|
-
import React63, { useState as useState33, useEffect as
|
|
19920
|
+
import React63, { useState as useState33, useEffect as useEffect14, useRef as useRef20, useCallback as useCallback12 } from "react";
|
|
19921
19921
|
import { X, MessageChatSquare } from "@untitledui/icons";
|
|
19922
|
+
|
|
19923
|
+
// src/design_system/chat/useRealtimeReplyOrchestrator.ts
|
|
19924
|
+
import { useCallback as useCallback11, useEffect as useEffect13, useRef as useRef19 } from "react";
|
|
19925
|
+
import { createConsumer } from "@rails/actioncable";
|
|
19926
|
+
function useRealtimeReplyOrchestrator({
|
|
19927
|
+
debugLabel,
|
|
19928
|
+
fetchRealtimeData,
|
|
19929
|
+
loadLatestHasReply,
|
|
19930
|
+
onReplyResolved,
|
|
19931
|
+
onAgentThinking
|
|
19932
|
+
}) {
|
|
19933
|
+
const cableRef = useRef19(null);
|
|
19934
|
+
const subscriptionRef = useRef19(null);
|
|
19935
|
+
const subscribedContactRef = useRef19(null);
|
|
19936
|
+
const clearRealtime = useCallback11(() => {
|
|
19937
|
+
if (subscriptionRef.current) {
|
|
19938
|
+
subscriptionRef.current.unsubscribe();
|
|
19939
|
+
subscriptionRef.current = null;
|
|
19940
|
+
}
|
|
19941
|
+
if (cableRef.current) {
|
|
19942
|
+
cableRef.current.disconnect();
|
|
19943
|
+
cableRef.current = null;
|
|
19944
|
+
}
|
|
19945
|
+
subscribedContactRef.current = null;
|
|
19946
|
+
}, []);
|
|
19947
|
+
const resolveReply = useCallback11(() => {
|
|
19948
|
+
onReplyResolved();
|
|
19949
|
+
}, [onReplyResolved]);
|
|
19950
|
+
const subscribeRealtime = useCallback11((realtime) => {
|
|
19951
|
+
const token = realtime.token;
|
|
19952
|
+
const contactIdForStream = realtime.contact_id;
|
|
19953
|
+
const cableUrl = realtime.cable_url;
|
|
19954
|
+
if (!token || !contactIdForStream || !cableUrl) return;
|
|
19955
|
+
if (subscribedContactRef.current === contactIdForStream && subscriptionRef.current && cableRef.current) {
|
|
19956
|
+
return;
|
|
19957
|
+
}
|
|
19958
|
+
clearRealtime();
|
|
19959
|
+
const cable = createConsumer(`${cableUrl}?token=${encodeURIComponent(token)}`);
|
|
19960
|
+
cableRef.current = cable;
|
|
19961
|
+
subscribedContactRef.current = contactIdForStream;
|
|
19962
|
+
subscriptionRef.current = cable.subscriptions.create(
|
|
19963
|
+
{ channel: "ContactCommunicationsChannel", contact_id: String(contactIdForStream) },
|
|
19964
|
+
{
|
|
19965
|
+
connected: () => {
|
|
19966
|
+
console.info(`[${debugLabel}] realtime connected contact_id=${contactIdForStream}`);
|
|
19967
|
+
},
|
|
19968
|
+
disconnected: () => {
|
|
19969
|
+
console.warn(`[${debugLabel}] realtime disconnected contact_id=${contactIdForStream}`);
|
|
19970
|
+
},
|
|
19971
|
+
rejected: () => {
|
|
19972
|
+
console.warn(`[${debugLabel}] realtime rejected contact_id=${contactIdForStream}`);
|
|
19973
|
+
},
|
|
19974
|
+
received: async (data) => {
|
|
19975
|
+
var _a;
|
|
19976
|
+
console.info(`[${debugLabel}] realtime received type=${(_a = data == null ? void 0 : data.type) != null ? _a : "unknown"} contact_id=${contactIdForStream}`);
|
|
19977
|
+
if ((data == null ? void 0 : data.type) === "agent_thinking") {
|
|
19978
|
+
onAgentThinking == null ? void 0 : onAgentThinking();
|
|
19979
|
+
return;
|
|
19980
|
+
}
|
|
19981
|
+
if ((data == null ? void 0 : data.type) !== "new_communication") return;
|
|
19982
|
+
try {
|
|
19983
|
+
const hasReply = await loadLatestHasReply();
|
|
19984
|
+
if (hasReply) {
|
|
19985
|
+
resolveReply();
|
|
19986
|
+
}
|
|
19987
|
+
} catch (error) {
|
|
19988
|
+
console.error(`[${debugLabel}] realtime receive handling error`, error);
|
|
19989
|
+
}
|
|
19990
|
+
}
|
|
19991
|
+
}
|
|
19992
|
+
);
|
|
19993
|
+
}, [clearRealtime, debugLabel, loadLatestHasReply, onAgentThinking, resolveReply]);
|
|
19994
|
+
const ensureRealtimeSubscription = useCallback11(async () => {
|
|
19995
|
+
try {
|
|
19996
|
+
const realtime = await fetchRealtimeData();
|
|
19997
|
+
if (!realtime) return;
|
|
19998
|
+
subscribeRealtime(realtime);
|
|
19999
|
+
} catch (e) {
|
|
20000
|
+
}
|
|
20001
|
+
}, [fetchRealtimeData, subscribeRealtime]);
|
|
20002
|
+
const beginReplyWait = useCallback11((options) => {
|
|
20003
|
+
if (options == null ? void 0 : options.realtimeData) {
|
|
20004
|
+
subscribeRealtime(options.realtimeData);
|
|
20005
|
+
} else {
|
|
20006
|
+
void ensureRealtimeSubscription();
|
|
20007
|
+
}
|
|
20008
|
+
}, [ensureRealtimeSubscription, subscribeRealtime]);
|
|
20009
|
+
useEffect13(() => {
|
|
20010
|
+
return () => {
|
|
20011
|
+
clearRealtime();
|
|
20012
|
+
};
|
|
20013
|
+
}, [clearRealtime]);
|
|
20014
|
+
return {
|
|
20015
|
+
ensureRealtimeSubscription,
|
|
20016
|
+
subscribeRealtime,
|
|
20017
|
+
beginReplyWait
|
|
20018
|
+
};
|
|
20019
|
+
}
|
|
20020
|
+
|
|
20021
|
+
// src/design_system/components/ChatWidget.tsx
|
|
19922
20022
|
var formatTime = (isoString) => {
|
|
19923
20023
|
const date = new Date(isoString);
|
|
19924
20024
|
const now2 = /* @__PURE__ */ new Date();
|
|
@@ -19948,8 +20048,8 @@ function ChatWidget({
|
|
|
19948
20048
|
const [isLoading, setIsLoading] = useState33(false);
|
|
19949
20049
|
const [sessionId, setSessionId] = useState33("");
|
|
19950
20050
|
const [waitingForReply, setWaitingForReply] = useState33(false);
|
|
19951
|
-
const messagesEndRef =
|
|
19952
|
-
|
|
20051
|
+
const messagesEndRef = useRef20(null);
|
|
20052
|
+
useEffect14(() => {
|
|
19953
20053
|
if (contactId) return;
|
|
19954
20054
|
if (providedSessionId) {
|
|
19955
20055
|
setSessionId(providedSessionId);
|
|
@@ -19964,7 +20064,7 @@ function ChatWidget({
|
|
|
19964
20064
|
}
|
|
19965
20065
|
}
|
|
19966
20066
|
}, [contactId, providedSessionId]);
|
|
19967
|
-
const loadMessages =
|
|
20067
|
+
const loadMessages = useCallback12(async () => {
|
|
19968
20068
|
if (!contactId && !sessionId) return [];
|
|
19969
20069
|
try {
|
|
19970
20070
|
const query = contactId ? `contact_id=${encodeURIComponent(contactId)}` : `identifier=${encodeURIComponent(sessionId)}`;
|
|
@@ -19980,46 +20080,55 @@ function ChatWidget({
|
|
|
19980
20080
|
}
|
|
19981
20081
|
return [];
|
|
19982
20082
|
}, [contactId, sessionId]);
|
|
19983
|
-
|
|
20083
|
+
useEffect14(() => {
|
|
19984
20084
|
if (isOpen && (contactId || sessionId)) {
|
|
19985
20085
|
loadMessages();
|
|
19986
20086
|
}
|
|
19987
20087
|
}, [isOpen, contactId, sessionId, loadMessages]);
|
|
19988
|
-
|
|
20088
|
+
useEffect14(() => {
|
|
19989
20089
|
var _a;
|
|
19990
20090
|
(_a = messagesEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
|
|
19991
20091
|
}, [messages]);
|
|
19992
|
-
const
|
|
19993
|
-
|
|
19994
|
-
return ()
|
|
19995
|
-
if (pollIntervalRef.current !== null) {
|
|
19996
|
-
clearInterval(pollIntervalRef.current);
|
|
19997
|
-
}
|
|
19998
|
-
};
|
|
20092
|
+
const hasAgentReplyWithBody = useCallback12((list) => {
|
|
20093
|
+
const latest = list[list.length - 1];
|
|
20094
|
+
return (latest == null ? void 0 : latest.sender_type) === "agent" && (latest == null ? void 0 : latest.body) != null && String(latest.body).trim() !== "";
|
|
19999
20095
|
}, []);
|
|
20000
|
-
const
|
|
20001
|
-
setWaitingForReply(true);
|
|
20002
|
-
let attempts = 0;
|
|
20003
|
-
const maxAttempts = 30;
|
|
20004
|
-
pollIntervalRef.current = setInterval(async () => {
|
|
20005
|
-
attempts++;
|
|
20006
|
-
try {
|
|
20007
|
-
const newMessages = await loadMessages();
|
|
20008
|
-
const latest = newMessages[newMessages.length - 1];
|
|
20009
|
-
const hasAgentReplyWithBody = (latest == null ? void 0 : latest.sender_type) === "agent" && (latest == null ? void 0 : latest.body) != null && String(latest.body).trim() !== "";
|
|
20010
|
-
if (hasAgentReplyWithBody || attempts >= maxAttempts) {
|
|
20011
|
-
clearInterval(pollIntervalRef.current);
|
|
20012
|
-
pollIntervalRef.current = null;
|
|
20013
|
-
setWaitingForReply(false);
|
|
20014
|
-
setIsLoading(false);
|
|
20015
|
-
}
|
|
20016
|
-
} catch (error) {
|
|
20017
|
-
console.error("[ChatWidget] Error polling for messages:", error);
|
|
20018
|
-
}
|
|
20019
|
-
}, 1e3);
|
|
20020
|
-
};
|
|
20021
|
-
const sendMessage = async () => {
|
|
20096
|
+
const fetchRealtimeData = useCallback12(async () => {
|
|
20022
20097
|
var _a, _b, _c;
|
|
20098
|
+
if (!contactId && !sessionId) return null;
|
|
20099
|
+
const query = contactId ? `contact_id=${encodeURIComponent(contactId)}` : `identifier=${encodeURIComponent(sessionId)}`;
|
|
20100
|
+
const response = await fetch(`/api/chat/?action=realtime_token&${query}`);
|
|
20101
|
+
if (!response.ok) return null;
|
|
20102
|
+
const result = await response.json();
|
|
20103
|
+
const token = (_a = result == null ? void 0 : result.data) == null ? void 0 : _a.token;
|
|
20104
|
+
const contactIdForStream = (_b = result == null ? void 0 : result.data) == null ? void 0 : _b.contact_id;
|
|
20105
|
+
const cableUrl = (_c = result == null ? void 0 : result.data) == null ? void 0 : _c.cable_url;
|
|
20106
|
+
if (!token || !contactIdForStream || !cableUrl) return null;
|
|
20107
|
+
return { token, contact_id: contactIdForStream, cable_url: cableUrl };
|
|
20108
|
+
}, [contactId, sessionId]);
|
|
20109
|
+
const {
|
|
20110
|
+
beginReplyWait,
|
|
20111
|
+
ensureRealtimeSubscription
|
|
20112
|
+
} = useRealtimeReplyOrchestrator({
|
|
20113
|
+
debugLabel: "ChatWidget",
|
|
20114
|
+
fetchRealtimeData,
|
|
20115
|
+
loadLatestHasReply: async () => hasAgentReplyWithBody(await loadMessages()),
|
|
20116
|
+
onReplyResolved: () => {
|
|
20117
|
+
setWaitingForReply(false);
|
|
20118
|
+
setIsLoading(false);
|
|
20119
|
+
},
|
|
20120
|
+
onAgentThinking: () => {
|
|
20121
|
+
setWaitingForReply(true);
|
|
20122
|
+
}
|
|
20123
|
+
});
|
|
20124
|
+
const hasPersistedMessages = messages.some((message) => !String(message.id).startsWith("temp_"));
|
|
20125
|
+
useEffect14(() => {
|
|
20126
|
+
if (!isOpen || !contactId && !sessionId) return;
|
|
20127
|
+
if (!contactId && !hasPersistedMessages) return;
|
|
20128
|
+
ensureRealtimeSubscription();
|
|
20129
|
+
}, [contactId, ensureRealtimeSubscription, hasPersistedMessages, isOpen, sessionId]);
|
|
20130
|
+
const sendMessage = async () => {
|
|
20131
|
+
var _a, _b, _c, _d, _e, _f;
|
|
20023
20132
|
if (!inputValue.trim() || !contactId && !sessionId) return;
|
|
20024
20133
|
const messageText = inputValue.trim();
|
|
20025
20134
|
setInputValue("");
|
|
@@ -20044,24 +20153,34 @@ function ChatWidget({
|
|
|
20044
20153
|
const result = await response.json();
|
|
20045
20154
|
captureEvent("chat_message_sent", { is_authenticated: Boolean(contactId) });
|
|
20046
20155
|
if ((_a = result.data) == null ? void 0 : _a.job_id) {
|
|
20047
|
-
|
|
20048
|
-
|
|
20156
|
+
setWaitingForReply(true);
|
|
20157
|
+
const realtimeFromSend = ((_b = result.data) == null ? void 0 : _b.realtime_token) && ((_c = result.data) == null ? void 0 : _c.contact_id) && ((_d = result.data) == null ? void 0 : _d.cable_url) ? {
|
|
20158
|
+
token: result.data.realtime_token,
|
|
20159
|
+
contact_id: result.data.contact_id,
|
|
20160
|
+
cable_url: result.data.cable_url
|
|
20161
|
+
} : null;
|
|
20162
|
+
beginReplyWait({ realtimeData: realtimeFromSend });
|
|
20163
|
+
} else if (((_e = result.data) == null ? void 0 : _e.status) === "agent_unavailable" || ((_f = result.data) == null ? void 0 : _f.status) === "no_auto_reply") {
|
|
20049
20164
|
setIsLoading(false);
|
|
20165
|
+
setWaitingForReply(false);
|
|
20050
20166
|
} else {
|
|
20051
20167
|
await loadMessages();
|
|
20052
20168
|
setIsLoading(false);
|
|
20169
|
+
setWaitingForReply(false);
|
|
20053
20170
|
}
|
|
20054
20171
|
} else {
|
|
20055
20172
|
setMessages((prev) => prev.filter((m) => m.id !== tempMessage.id));
|
|
20056
20173
|
captureEvent("chat_message_failed", { error: "send_failed" });
|
|
20057
20174
|
console.error("Failed to send message");
|
|
20058
20175
|
setIsLoading(false);
|
|
20176
|
+
setWaitingForReply(false);
|
|
20059
20177
|
}
|
|
20060
20178
|
} catch (error) {
|
|
20061
20179
|
setMessages((prev) => prev.filter((m) => m.id !== tempMessage.id));
|
|
20062
20180
|
captureEvent("chat_message_failed", { error: "network_error" });
|
|
20063
20181
|
console.error("Failed to send message:", error);
|
|
20064
20182
|
setIsLoading(false);
|
|
20183
|
+
setWaitingForReply(false);
|
|
20065
20184
|
}
|
|
20066
20185
|
};
|
|
20067
20186
|
const handleKeyDown = (e) => {
|