@paramms/chat-widget 1.0.22 → 1.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/dist/react.js +151 -147
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
package/dist/react.js
CHANGED
|
@@ -1,111 +1,113 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { useState as
|
|
3
|
-
import { mount as
|
|
1
|
+
import { jsxs as S, jsx as p, Fragment as $ } from "react/jsx-runtime";
|
|
2
|
+
import { useState as D, useRef as k, useEffect as z } from "react";
|
|
3
|
+
import { mount as T } from "./index.js";
|
|
4
4
|
function A({
|
|
5
|
-
url:
|
|
5
|
+
url: x,
|
|
6
6
|
apiUrl: i,
|
|
7
|
-
profileId:
|
|
8
|
-
userId:
|
|
7
|
+
profileId: b,
|
|
8
|
+
userId: t,
|
|
9
9
|
userName: l,
|
|
10
10
|
userEmail: c,
|
|
11
11
|
userAvatar: o,
|
|
12
|
-
contextTitle:
|
|
12
|
+
contextTitle: w,
|
|
13
13
|
contextSubtitle: y,
|
|
14
|
-
contextStatus:
|
|
15
|
-
subjectId:
|
|
16
|
-
accent:
|
|
14
|
+
contextStatus: e,
|
|
15
|
+
subjectId: a,
|
|
16
|
+
accent: d,
|
|
17
17
|
launcher: n,
|
|
18
|
-
position:
|
|
18
|
+
position: s,
|
|
19
19
|
quickReplies: f,
|
|
20
20
|
height: h = "100%",
|
|
21
21
|
i18n: g,
|
|
22
22
|
translateLang: r
|
|
23
23
|
}) {
|
|
24
|
-
const
|
|
25
|
-
return
|
|
24
|
+
const m = k(null), u = k(null);
|
|
25
|
+
return z(() => {
|
|
26
26
|
var v;
|
|
27
|
-
if (
|
|
28
|
-
return (v =
|
|
29
|
-
el:
|
|
30
|
-
url:
|
|
27
|
+
if (m.current)
|
|
28
|
+
return (v = u.current) == null || v.close(), u.current = T({
|
|
29
|
+
el: m.current,
|
|
30
|
+
url: x,
|
|
31
31
|
...i ? { apiUrl: i } : {},
|
|
32
|
-
profileId:
|
|
33
|
-
...
|
|
34
|
-
...
|
|
35
|
-
...
|
|
32
|
+
profileId: b,
|
|
33
|
+
...a ? { subjectId: a } : {},
|
|
34
|
+
...t ? { userId: t } : {},
|
|
35
|
+
...t || l || c || o ? {
|
|
36
36
|
user: {
|
|
37
37
|
...l ? { name: l } : {},
|
|
38
38
|
...c ? { email: c } : {},
|
|
39
39
|
...o ? { avatar: o } : {}
|
|
40
40
|
}
|
|
41
41
|
} : {},
|
|
42
|
-
...
|
|
42
|
+
...w ? {
|
|
43
43
|
subject: {
|
|
44
|
-
title:
|
|
44
|
+
title: w,
|
|
45
45
|
...y ? { subtitle: y } : {},
|
|
46
|
-
...
|
|
46
|
+
...e ? { status: e } : {}
|
|
47
47
|
}
|
|
48
48
|
} : {},
|
|
49
49
|
...f ? { quickReplies: f } : {},
|
|
50
|
-
...
|
|
50
|
+
...d ? { accent: d } : {},
|
|
51
51
|
...r ? { translateLang: r } : {},
|
|
52
52
|
...g ? { i18n: g } : {},
|
|
53
|
-
...n ? { launcher: n, position:
|
|
53
|
+
...n ? { launcher: n, position: s ?? "bottom-right" } : {}
|
|
54
54
|
}), () => {
|
|
55
55
|
var C;
|
|
56
|
-
(C =
|
|
56
|
+
(C = u.current) == null || C.close(), u.current = null;
|
|
57
57
|
};
|
|
58
|
-
}, [
|
|
58
|
+
}, [x, i, b, a, t, l, c, d, n, s, r]), /* @__PURE__ */ p(
|
|
59
59
|
"div",
|
|
60
60
|
{
|
|
61
|
-
ref:
|
|
61
|
+
ref: m,
|
|
62
62
|
style: n ? { width: 0, height: 0, overflow: "hidden" } : { width: "100%", height: h, minHeight: h === "100%" ? "480px" : void 0 }
|
|
63
63
|
}
|
|
64
64
|
);
|
|
65
65
|
}
|
|
66
|
-
const
|
|
66
|
+
const B = [
|
|
67
67
|
"Is this still available?",
|
|
68
68
|
"Can I schedule a viewing?",
|
|
69
69
|
"What is your best price?"
|
|
70
70
|
];
|
|
71
71
|
function K({
|
|
72
|
-
url:
|
|
72
|
+
url: x,
|
|
73
73
|
apiUrl: i,
|
|
74
|
-
profileId:
|
|
75
|
-
listingId:
|
|
74
|
+
profileId: b,
|
|
75
|
+
listingId: t,
|
|
76
76
|
listingTitle: l,
|
|
77
77
|
listingMeta: c,
|
|
78
78
|
listingPrice: o,
|
|
79
|
-
listingStatus:
|
|
79
|
+
listingStatus: w,
|
|
80
80
|
userId: y,
|
|
81
|
-
userName:
|
|
82
|
-
userEmail:
|
|
83
|
-
userAvatar:
|
|
81
|
+
userName: e,
|
|
82
|
+
userEmail: a,
|
|
83
|
+
userAvatar: d,
|
|
84
84
|
accent: n,
|
|
85
|
-
launcher:
|
|
85
|
+
launcher: s,
|
|
86
86
|
position: f,
|
|
87
87
|
quickReplies: h,
|
|
88
88
|
height: g = "100%",
|
|
89
89
|
i18n: r,
|
|
90
|
-
translateLang:
|
|
90
|
+
translateLang: m
|
|
91
91
|
}) {
|
|
92
|
-
const
|
|
93
|
-
return
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
92
|
+
const u = k(null), v = k(null);
|
|
93
|
+
return z(() => {
|
|
94
|
+
if (!u.current) return;
|
|
95
|
+
let C = !1;
|
|
96
|
+
const M = setTimeout(() => {
|
|
97
|
+
var j;
|
|
98
|
+
C || !u.current || ((j = v.current) == null || j.close(), v.current = T({
|
|
99
|
+
el: u.current,
|
|
100
|
+
url: x,
|
|
99
101
|
...i ? { apiUrl: i } : {},
|
|
100
|
-
profileId:
|
|
101
|
-
...
|
|
102
|
-
...y ? {
|
|
103
|
-
...y ||
|
|
102
|
+
profileId: b,
|
|
103
|
+
...t ? { subjectId: `listing_${t}` } : {},
|
|
104
|
+
...y ? { userId: y } : {},
|
|
105
|
+
...y || e || a || d ? {
|
|
104
106
|
user: {
|
|
105
|
-
...
|
|
106
|
-
...
|
|
107
|
-
...
|
|
108
|
-
...
|
|
107
|
+
...e ? { name: e } : {},
|
|
108
|
+
...a ? { email: a } : {},
|
|
109
|
+
...d ? { avatar: d } : {},
|
|
110
|
+
...t ? { meta: { listingId: t } } : {}
|
|
109
111
|
}
|
|
110
112
|
} : {},
|
|
111
113
|
...l ? {
|
|
@@ -113,76 +115,78 @@ function K({
|
|
|
113
115
|
title: l,
|
|
114
116
|
...c ? { subtitle: c } : {},
|
|
115
117
|
...o ? { tags: [`$${o.toLocaleString()}`] } : {},
|
|
116
|
-
...
|
|
118
|
+
...w ? { status: w } : {}
|
|
117
119
|
}
|
|
118
120
|
} : {},
|
|
119
|
-
quickReplies: h ??
|
|
121
|
+
quickReplies: h ?? B,
|
|
120
122
|
...n ? { accent: n } : {},
|
|
121
|
-
...
|
|
123
|
+
...m ? { translateLang: m } : {},
|
|
122
124
|
...r ? { i18n: r } : {},
|
|
123
|
-
...
|
|
124
|
-
})
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
125
|
+
...s ? { launcher: s, position: f ?? "bottom-right" } : {}
|
|
126
|
+
}));
|
|
127
|
+
}, 0);
|
|
128
|
+
return () => {
|
|
129
|
+
var j;
|
|
130
|
+
C = !0, clearTimeout(M), (j = v.current) == null || j.close(), v.current = null;
|
|
131
|
+
};
|
|
132
|
+
}, [x, i, b, t, y, n, s, f, m]), /* @__PURE__ */ p(
|
|
129
133
|
"div",
|
|
130
134
|
{
|
|
131
|
-
ref:
|
|
132
|
-
style:
|
|
135
|
+
ref: u,
|
|
136
|
+
style: s ? { width: 0, height: 0, overflow: "hidden" } : { width: "100%", height: g, minHeight: g === "100%" ? "480px" : void 0 }
|
|
133
137
|
}
|
|
134
138
|
);
|
|
135
139
|
}
|
|
136
140
|
function F({
|
|
137
|
-
url:
|
|
141
|
+
url: x,
|
|
138
142
|
apiUrl: i,
|
|
139
|
-
profileId:
|
|
140
|
-
userId:
|
|
143
|
+
profileId: b,
|
|
144
|
+
userId: t,
|
|
141
145
|
userName: l,
|
|
142
146
|
userEmail: c,
|
|
143
147
|
accent: o,
|
|
144
|
-
height:
|
|
148
|
+
height: w = "100%",
|
|
145
149
|
i18n: y
|
|
146
150
|
}) {
|
|
147
|
-
const [
|
|
148
|
-
|
|
149
|
-
if (!
|
|
151
|
+
const [e, a] = D(null), d = k(null), n = k(null), s = k(null), f = k(null);
|
|
152
|
+
z(() => {
|
|
153
|
+
if (!d.current) return;
|
|
150
154
|
let g = !1;
|
|
151
155
|
return import("./chatlist.js").then(({ mountChatList: r }) => {
|
|
152
|
-
g || !
|
|
153
|
-
el:
|
|
154
|
-
url:
|
|
156
|
+
g || !d.current || (s.current = r({
|
|
157
|
+
el: d.current,
|
|
158
|
+
url: x,
|
|
155
159
|
...i ? { apiUrl: i } : {},
|
|
156
|
-
profileId:
|
|
157
|
-
onSelect: (
|
|
158
|
-
...
|
|
160
|
+
profileId: b,
|
|
161
|
+
onSelect: (m) => a(m),
|
|
162
|
+
...t ? { userId: t } : {},
|
|
159
163
|
...o ? { accent: o } : {},
|
|
160
164
|
...y ? { i18n: y } : {}
|
|
161
165
|
}));
|
|
162
166
|
}), () => {
|
|
163
167
|
var r;
|
|
164
|
-
g = !0, (r =
|
|
168
|
+
g = !0, (r = s.current) == null || r.close(), s.current = null;
|
|
165
169
|
};
|
|
166
|
-
}, [
|
|
170
|
+
}, [x, b, t]), z(() => {
|
|
167
171
|
var g;
|
|
168
|
-
if (!(!n.current || !
|
|
169
|
-
return (g = f.current) == null || g.close(), f.current =
|
|
172
|
+
if (!(!n.current || !e))
|
|
173
|
+
return (g = f.current) == null || g.close(), f.current = T({
|
|
170
174
|
el: n.current,
|
|
171
|
-
url:
|
|
175
|
+
url: x,
|
|
172
176
|
...i ? { apiUrl: i } : {},
|
|
173
|
-
profileId:
|
|
174
|
-
...
|
|
175
|
-
...
|
|
176
|
-
...
|
|
177
|
+
profileId: b,
|
|
178
|
+
...e.subjectId ? { subjectId: e.subjectId } : {},
|
|
179
|
+
...t ? { token: t } : {},
|
|
180
|
+
...t || l || c ? {
|
|
177
181
|
user: {
|
|
178
182
|
...l ? { name: l } : {},
|
|
179
183
|
...c ? { email: c } : {}
|
|
180
184
|
}
|
|
181
185
|
} : {},
|
|
182
|
-
...
|
|
186
|
+
...e.subjectTitle ? {
|
|
183
187
|
subject: {
|
|
184
|
-
title:
|
|
185
|
-
...
|
|
188
|
+
title: e.subjectTitle,
|
|
189
|
+
...e.subjectMeta ? { subtitle: e.subjectMeta } : {}
|
|
186
190
|
}
|
|
187
191
|
} : {},
|
|
188
192
|
...o ? { accent: o } : {}
|
|
@@ -190,53 +194,53 @@ function F({
|
|
|
190
194
|
var r;
|
|
191
195
|
(r = f.current) == null || r.close(), f.current = null;
|
|
192
196
|
};
|
|
193
|
-
}, [
|
|
197
|
+
}, [e == null ? void 0 : e.id]);
|
|
194
198
|
const h = typeof window < "u" && window.innerWidth < 768;
|
|
195
|
-
return /* @__PURE__ */
|
|
196
|
-
/* @__PURE__ */
|
|
199
|
+
return /* @__PURE__ */ S("div", { style: { display: "flex", width: "100%", height: w, minHeight: "400px", overflow: "hidden" }, children: [
|
|
200
|
+
/* @__PURE__ */ p("div", { style: {
|
|
197
201
|
width: h ? "100%" : "360px",
|
|
198
|
-
flex: h &&
|
|
199
|
-
display: h &&
|
|
202
|
+
flex: h && e ? "none" : void 0,
|
|
203
|
+
display: h && e ? "none" : "flex",
|
|
200
204
|
flexDirection: "column",
|
|
201
205
|
borderRight: h ? "none" : "1px solid #e8eaed",
|
|
202
206
|
minWidth: 0
|
|
203
|
-
}, children: /* @__PURE__ */
|
|
204
|
-
|
|
205
|
-
h && /* @__PURE__ */
|
|
207
|
+
}, children: /* @__PURE__ */ p("div", { ref: d, style: { width: "100%", height: "100%" } }) }),
|
|
208
|
+
e ? /* @__PURE__ */ S("div", { style: { flex: 1, display: "flex", flexDirection: "column", minWidth: 0, position: "relative" }, children: [
|
|
209
|
+
h && /* @__PURE__ */ p(
|
|
206
210
|
"button",
|
|
207
211
|
{
|
|
208
|
-
onClick: () =>
|
|
212
|
+
onClick: () => a(null),
|
|
209
213
|
style: { position: "absolute", top: 12, left: 12, zIndex: 10, background: "none", border: "none", fontSize: 22, cursor: "pointer", color: "#1c1b1a" },
|
|
210
214
|
children: "←"
|
|
211
215
|
}
|
|
212
216
|
),
|
|
213
|
-
/* @__PURE__ */
|
|
214
|
-
] }) : /* @__PURE__ */
|
|
217
|
+
/* @__PURE__ */ p("div", { ref: n, style: { width: "100%", height: "100%" } })
|
|
218
|
+
] }) : /* @__PURE__ */ p("div", { style: { flex: 1, display: h ? "none" : "flex", alignItems: "center", justifyContent: "center", color: "#9b9690", fontSize: 14 }, children: "Select a conversation" })
|
|
215
219
|
] });
|
|
216
220
|
}
|
|
217
221
|
function P({
|
|
218
|
-
url:
|
|
222
|
+
url: x,
|
|
219
223
|
apiUrl: i,
|
|
220
|
-
profileId:
|
|
221
|
-
userId:
|
|
224
|
+
profileId: b,
|
|
225
|
+
userId: t,
|
|
222
226
|
userName: l,
|
|
223
227
|
userEmail: c,
|
|
224
228
|
accent: o = "#4F63F5",
|
|
225
|
-
floating:
|
|
229
|
+
floating: w = !0,
|
|
226
230
|
position: y = "bottom-right",
|
|
227
|
-
label:
|
|
228
|
-
panelWidth:
|
|
229
|
-
panelHeight:
|
|
231
|
+
label: e,
|
|
232
|
+
panelWidth: a,
|
|
233
|
+
panelHeight: d = "600px"
|
|
230
234
|
}) {
|
|
231
|
-
const [n,
|
|
232
|
-
if (
|
|
233
|
-
const R = (
|
|
234
|
-
|
|
235
|
+
const [n, s] = D(!1), f = k(null), h = y === "bottom-right", r = e ?? (w ? "💬" : "Messages");
|
|
236
|
+
if (z(() => {
|
|
237
|
+
const R = (L) => {
|
|
238
|
+
L.key === "Escape" && s(!1);
|
|
235
239
|
};
|
|
236
240
|
return document.addEventListener("keydown", R), () => document.removeEventListener("keydown", R);
|
|
237
|
-
}, []),
|
|
238
|
-
const R = typeof window < "u" && window.innerWidth < 480,
|
|
239
|
-
return /* @__PURE__ */
|
|
241
|
+
}, []), w) {
|
|
242
|
+
const R = typeof window < "u" && window.innerWidth < 480, L = R ? "100vw" : a ?? "420px", H = R ? "100dvh" : d;
|
|
243
|
+
return /* @__PURE__ */ S("div", { style: {
|
|
240
244
|
position: "fixed",
|
|
241
245
|
[h ? "right" : "left"]: "20px",
|
|
242
246
|
bottom: "20px",
|
|
@@ -246,9 +250,9 @@ function P({
|
|
|
246
250
|
alignItems: h ? "flex-end" : "flex-start",
|
|
247
251
|
gap: "12px"
|
|
248
252
|
}, children: [
|
|
249
|
-
/* @__PURE__ */
|
|
250
|
-
width:
|
|
251
|
-
height:
|
|
253
|
+
/* @__PURE__ */ p("div", { style: {
|
|
254
|
+
width: L,
|
|
255
|
+
height: H,
|
|
252
256
|
borderRadius: R ? "0" : "16px",
|
|
253
257
|
overflow: "hidden",
|
|
254
258
|
boxShadow: "0 8px 40px rgba(0,0,0,.18)",
|
|
@@ -257,24 +261,24 @@ function P({
|
|
|
257
261
|
flexDirection: "column",
|
|
258
262
|
transformOrigin: `bottom ${h ? "right" : "left"}`,
|
|
259
263
|
animation: n ? "ocl-pop-in .18s ease" : "none"
|
|
260
|
-
}, children: /* @__PURE__ */
|
|
264
|
+
}, children: /* @__PURE__ */ p(
|
|
261
265
|
F,
|
|
262
266
|
{
|
|
263
|
-
url:
|
|
267
|
+
url: x,
|
|
264
268
|
...i ? { apiUrl: i } : {},
|
|
265
|
-
profileId:
|
|
266
|
-
...
|
|
269
|
+
profileId: b,
|
|
270
|
+
...t ? { userId: t } : {},
|
|
267
271
|
...l ? { userName: l } : {},
|
|
268
272
|
...c ? { userEmail: c } : {},
|
|
269
273
|
accent: o,
|
|
270
274
|
height: "100%"
|
|
271
275
|
}
|
|
272
276
|
) }),
|
|
273
|
-
/* @__PURE__ */
|
|
277
|
+
/* @__PURE__ */ p(
|
|
274
278
|
"button",
|
|
275
279
|
{
|
|
276
280
|
ref: f,
|
|
277
|
-
onClick: () =>
|
|
281
|
+
onClick: () => s((W) => !W),
|
|
278
282
|
style: {
|
|
279
283
|
width: "56px",
|
|
280
284
|
height: "56px",
|
|
@@ -288,23 +292,23 @@ function P({
|
|
|
288
292
|
boxShadow: "0 4px 16px rgba(0,0,0,.25)",
|
|
289
293
|
transition: "transform .15s"
|
|
290
294
|
},
|
|
291
|
-
onMouseEnter: (
|
|
292
|
-
|
|
295
|
+
onMouseEnter: (W) => {
|
|
296
|
+
W.target.style.transform = "scale(1.08)";
|
|
293
297
|
},
|
|
294
|
-
onMouseLeave: (
|
|
295
|
-
|
|
298
|
+
onMouseLeave: (W) => {
|
|
299
|
+
W.target.style.transform = "scale(1)";
|
|
296
300
|
},
|
|
297
301
|
children: n ? "✕" : r
|
|
298
302
|
}
|
|
299
303
|
),
|
|
300
|
-
/* @__PURE__ */
|
|
304
|
+
/* @__PURE__ */ p("style", { children: "@keyframes ocl-pop-in { from { opacity:0; transform:scale(.95) } to { opacity:1; transform:scale(1) } }" })
|
|
301
305
|
] });
|
|
302
306
|
}
|
|
303
|
-
const
|
|
304
|
-
!n && f.current && v(f.current.getBoundingClientRect()),
|
|
305
|
-
},
|
|
306
|
-
return /* @__PURE__ */
|
|
307
|
-
/* @__PURE__ */
|
|
307
|
+
const m = a ?? "420px", [u, v] = D(null), C = () => {
|
|
308
|
+
!n && f.current && v(f.current.getBoundingClientRect()), s((R) => !R);
|
|
309
|
+
}, M = u ? u.bottom + 8 : 0, j = u ? window.innerWidth - u.right : 0;
|
|
310
|
+
return /* @__PURE__ */ S($, { children: [
|
|
311
|
+
/* @__PURE__ */ S(
|
|
308
312
|
"button",
|
|
309
313
|
{
|
|
310
314
|
ref: f,
|
|
@@ -329,40 +333,40 @@ function P({
|
|
|
329
333
|
]
|
|
330
334
|
}
|
|
331
335
|
),
|
|
332
|
-
n &&
|
|
333
|
-
/* @__PURE__ */
|
|
336
|
+
n && u && /* @__PURE__ */ S($, { children: [
|
|
337
|
+
/* @__PURE__ */ p(
|
|
334
338
|
"div",
|
|
335
339
|
{
|
|
336
|
-
onClick: () =>
|
|
340
|
+
onClick: () => s(!1),
|
|
337
341
|
style: { position: "fixed", inset: 0, zIndex: 9998 }
|
|
338
342
|
}
|
|
339
343
|
),
|
|
340
|
-
/* @__PURE__ */
|
|
344
|
+
/* @__PURE__ */ p("div", { style: {
|
|
341
345
|
position: "fixed",
|
|
342
|
-
top:
|
|
343
|
-
right:
|
|
344
|
-
width:
|
|
345
|
-
height:
|
|
346
|
+
top: M,
|
|
347
|
+
right: j,
|
|
348
|
+
width: m,
|
|
349
|
+
height: d,
|
|
346
350
|
borderRadius: "16px",
|
|
347
351
|
overflow: "hidden",
|
|
348
352
|
boxShadow: "0 8px 40px rgba(0,0,0,.2)",
|
|
349
353
|
background: "#fff",
|
|
350
354
|
zIndex: 9999,
|
|
351
355
|
animation: "ocl-slide-in .18s ease"
|
|
352
|
-
}, children: /* @__PURE__ */
|
|
356
|
+
}, children: /* @__PURE__ */ p(
|
|
353
357
|
F,
|
|
354
358
|
{
|
|
355
|
-
url:
|
|
359
|
+
url: x,
|
|
356
360
|
...i ? { apiUrl: i } : {},
|
|
357
|
-
profileId:
|
|
358
|
-
...
|
|
361
|
+
profileId: b,
|
|
362
|
+
...t ? { userId: t } : {},
|
|
359
363
|
...l ? { userName: l } : {},
|
|
360
364
|
...c ? { userEmail: c } : {},
|
|
361
365
|
accent: o,
|
|
362
366
|
height: "100%"
|
|
363
367
|
}
|
|
364
368
|
) }),
|
|
365
|
-
/* @__PURE__ */
|
|
369
|
+
/* @__PURE__ */ p("style", { children: "@keyframes ocl-slide-in { from { opacity:0; transform:translateY(-8px) } to { opacity:1; transform:translateY(0) } }" })
|
|
366
370
|
] })
|
|
367
371
|
] });
|
|
368
372
|
}
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.js","sources":["../src/react.tsx"],"sourcesContent":["// react.tsx — React wrapper around mount().\n//\n// Next.js App Router: add 'use client' to whichever file imports these.\n// The widget needs WebSocket + DOM — it cannot render on the server.\n//\n// Import path: '@paramms/chat-widget/react'\n//\n// Two components:\n// ChatWidget — general support chat (hotel, SaaS, helpdesk, etc.)\n// MarketplaceChat — one thread per listing (used cars, rentals, etc.)\n//\n// Both: only url + profileId are required. userId is always optional —\n// anonymous guests are handled automatically via localStorage.\n\nimport { useEffect, useRef, useState } from 'react'\nimport { mount, type MountOptions, type WidgetHandle } from './index.js'\n\n// ── Shared base props ─────────────────────────────────────────────────────────\n\ninterface BaseProps {\n /** Relay URL — set as NEXT_PUBLIC_RELAY_URL in .env. Any scheme works:\n * `https://api.example.com` is fine. The WebSocket URL and REST base are\n * derived automatically — you do NOT need to pass `wss://` or `/ws`. */\n url: string\n /** HTTP(S) base for REST calls — only when the REST API is on a different\n * origin than the socket. Normally omit. */\n apiUrl?: string\n /** Your Relay profile ID — set as NEXT_PUBLIC_RELAY_PROFILE_ID in .env — required */\n profileId: string\n\n /** Your logged-in user's stable ID. When omitted the widget automatically\n * assigns a persistent anonymous ID from localStorage — no login required. */\n userId?: string\n /** Shown to agents instead of the raw user ID */\n userName?: string\n /** Shown to agents so they can follow up by email */\n userEmail?: string\n /** Avatar URL shown in the widget header and dashboard */\n userAvatar?: string\n\n /** Brand colour hex, e.g. \"#1a56db\". Defaults to the profile theme colour. */\n accent?: string\n /** Render as a floating launcher button instead of inline */\n launcher?: boolean\n /** Launcher position — default 'bottom-right' */\n position?: 'bottom-right' | 'bottom-left'\n /** Pre-set reply chips shown above the input */\n quickReplies?: string[]\n /** Container height when rendered inline. Default: '100%' */\n height?: string\n /** i18n string overrides for non-English sites */\n i18n?: MountOptions['i18n']\n /** ISO language code for auto-translating incoming messages */\n translateLang?: string\n}\n\n// ── ChatWidget ────────────────────────────────────────────────────────────────\n\nexport interface ChatWidgetProps extends BaseProps {\n /** Optional context card shown at the top of the chat\n * (e.g. the support ticket, booking, or order being discussed) */\n contextTitle?: string\n contextSubtitle?: string\n contextStatus?: string\n\n /** Stable item ID — pins this conversation to a specific item/thread. */\n subjectId?: string\n}\n\n/**\n * General-purpose support chat widget. Only `url` and `profileId` are required.\n * All other props are optional — anonymous guests work without any configuration.\n *\n * @example Basic support chat\n * ```tsx\n * <ChatWidget\n * url={process.env.NEXT_PUBLIC_RELAY_WS_URL}\n * profileId={process.env.NEXT_PUBLIC_RELAY_PROFILE_ID}\n * userId={session?.user.id}\n * userName={session?.user.name}\n * userEmail={session?.user.email}\n * />\n * ```\n *\n * @example Multi-thread (tickets, bookings, orders)\n * ```tsx\n * <ChatWidget\n * url={...} profileId={...}\n * showChatList\n * subjectId={`ticket_${ticket.id}`}\n * contextTitle={ticket.title}\n * contextStatus={ticket.status}\n * userId={session?.user.id}\n * />\n * ```\n */\nexport function ChatWidget({\n url, apiUrl, profileId,\n userId, userName, userEmail, userAvatar,\n contextTitle, contextSubtitle, contextStatus,\n subjectId,\n accent, launcher, position, quickReplies, height = '100%',\n i18n, translateLang,\n}: ChatWidgetProps): JSX.Element {\n const ref = useRef<HTMLDivElement>(null)\n const handleRef = useRef<WidgetHandle | null>(null)\n\n useEffect(() => {\n if (!ref.current) return\n handleRef.current?.close()\n handleRef.current = mount({\n el: ref.current,\n url,\n ...(apiUrl ? { apiUrl } : {}),\n profileId,\n ...(subjectId ? { subjectId } : {}),\n ...(userId ? { token: userId } : {}),\n ...(userId || userName || userEmail || userAvatar ? {\n user: {\n ...(userName ? { name: userName } : {}),\n ...(userEmail ? { email: userEmail } : {}),\n ...(userAvatar ? { avatar: userAvatar } : {}),\n },\n } : {}),\n ...(contextTitle ? {\n subject: {\n title: contextTitle,\n ...(contextSubtitle ? { subtitle: contextSubtitle } : {}),\n ...(contextStatus ? { status: contextStatus } : {}),\n },\n } : {}),\n ...(quickReplies ? { quickReplies } : {}),\n ...(accent ? { accent } : {}),\n ...(translateLang ? { translateLang } : {}),\n ...(i18n ? { i18n } : {}),\n ...(launcher ? { launcher, position: position ?? 'bottom-right' } : {}),\n })\n return () => { handleRef.current?.close(); handleRef.current = null }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [url, apiUrl, profileId, subjectId, userId, userName, userEmail, accent, launcher, position, translateLang])\n\n // When launcher=true, still render the div — mount() moves it inside the\n // fixed panel above the bubble. Zero size so it doesn't affect page layout.\n return (\n <div\n ref={ref}\n style={launcher ? { width: 0, height: 0, overflow: 'hidden' } : { width: '100%', height, minHeight: height === '100%' ? '480px' : undefined }}\n />\n )\n}\n\n// ── MarketplaceChat ───────────────────────────────────────────────────────────\n\nexport interface MarketplaceChatProps extends BaseProps {\n /** Unique ID for this listing — each listing gets its own thread.\n * Omit for a general (non-item-specific) conversation. */\n listingId?: string\n /** Shown at the top of the chat — e.g. \"2019 Toyota Camry SE\" */\n listingTitle?: string\n /** One-line detail — e.g. \"45,000 km · Automatic\" */\n listingMeta?: string\n /** Price shown as a tag — e.g. 12500 → \"$12,500\" */\n listingPrice?: number\n /** Status badge — e.g. \"Available\", \"Sold\", \"Pending\" */\n listingStatus?: string\n}\n\nconst DEFAULT_MARKETPLACE_REPLIES = [\n 'Is this still available?',\n 'Can I schedule a viewing?',\n 'What is your best price?',\n]\n\n/**\n * Marketplace chat widget. Two modes depending on whether `listingId` is provided:\n *\n * **With `listingId` (listing page)** — opens that listing's chat immediately.\n * No list screen. The buyer is already looking at the item so context is clear.\n * ```tsx\n * // On your listing detail page:\n * <MarketplaceChat\n * url={process.env.NEXT_PUBLIC_RELAY_WS_URL}\n * profileId={process.env.NEXT_PUBLIC_RELAY_PROFILE_ID}\n * listingId={car.id}\n * listingTitle={car.title}\n * listingPrice={car.price}\n * listingMeta={`${car.mileage.toLocaleString()} km · ${car.gearbox}`}\n * listingStatus=\"Available\"\n * userId={session?.user.id}\n * userName={session?.user.name}\n * userEmail={session?.user.email}\n * />\n * ```\n *\n * **Without `listingId` (My Messages / inbox page)** — shows the WhatsApp-style\n * thread list as the home screen. No conversation is opened until the user taps one.\n * Use this on a dedicated `/messages` or `/inbox` page.\n * ```tsx\n * // On your /messages page:\n * <MarketplaceChat\n * url={process.env.NEXT_PUBLIC_RELAY_WS_URL}\n * profileId={process.env.NEXT_PUBLIC_RELAY_PROFILE_ID}\n * userId={session?.user.id}\n * userName={session?.user.name}\n * />\n * ```\n *\n * Only `url` and `profileId` are required. All other props are optional.\n */\nexport function MarketplaceChat({\n url, apiUrl, profileId,\n listingId, listingTitle, listingMeta, listingPrice, listingStatus,\n userId, userName, userEmail, userAvatar,\n accent, launcher, position, quickReplies, height = '100%',\n i18n, translateLang,\n}: MarketplaceChatProps): JSX.Element {\n const ref = useRef<HTMLDivElement>(null)\n const handleRef = useRef<WidgetHandle | null>(null)\n\n useEffect(() => {\n if (!ref.current) return\n // Close any previous instance on this element before mounting.\n // Required because React StrictMode double-invokes effects, and because\n // launcher=true moves the div out of the React tree — a re-render can\n // cause React to insert a fresh div at the original position, which then\n // gets mounted a second time if the effect fires again.\n handleRef.current?.close()\n handleRef.current = mount({\n el: ref.current,\n url,\n ...(apiUrl ? { apiUrl } : {}),\n profileId,\n ...(listingId ? { subjectId: `listing_${listingId}` } : {}),\n ...(userId ? { token: userId } : {}),\n ...(userId || userName || userEmail || userAvatar ? {\n user: {\n ...(userName ? { name: userName } : {}),\n ...(userEmail ? { email: userEmail } : {}),\n ...(userAvatar ? { avatar: userAvatar } : {}),\n ...(listingId ? { meta: { listingId } } : {}),\n },\n } : {}),\n ...(listingTitle ? {\n subject: {\n title: listingTitle,\n ...(listingMeta ? { subtitle: listingMeta } : {}),\n ...(listingPrice ? { tags: [`$${listingPrice.toLocaleString()}`] } : {}),\n ...(listingStatus ? { status: listingStatus } : {}),\n },\n } : {}),\n quickReplies: quickReplies ?? DEFAULT_MARKETPLACE_REPLIES,\n ...(accent ? { accent } : {}),\n ...(translateLang ? { translateLang } : {}),\n ...(i18n ? { i18n } : {}),\n ...(launcher ? { launcher, position: position ?? 'bottom-right' } : {}),\n })\n return () => { handleRef.current?.close(); handleRef.current = null }\n // Include all props that affect the mounted widget so stale closures\n // never leave a phantom widget behind when the listing changes.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [url, apiUrl, profileId, listingId, userId, userName, userEmail, accent, launcher, position, translateLang])\n\n // When launcher=true, still render the div — mount() moves it inside the\n // fixed panel above the bubble. Zero size so it doesn't affect page layout.\n return (\n <div\n ref={ref}\n style={launcher ? { width: 0, height: 0, overflow: 'hidden' } : { width: '100%', height, minHeight: height === '100%' ? '480px' : undefined }}\n />\n )\n}\n\n// ── ChatList ──────────────────────────────────────────────────────────────────\n\nexport interface ChatAppProps {\n /** Relay WebSocket URL — required */\n url: string\n /** HTTP(S) base for REST calls. Defaults to the WS origin. */\n apiUrl?: string\n /** Your Relay profile ID — required */\n profileId: string\n /** Your logged-in user's stable ID. Omit for anonymous (uses localStorage UID) */\n userId?: string\n /** Optional: shown to agents in the dashboard */\n userName?: string\n /** Optional: shown to agents in the dashboard */\n userEmail?: string\n /** Brand colour hex — default '#4F63F5' */\n accent?: string\n /** Container height. Default: '100%' */\n height?: string\n /** i18n overrides */\n i18n?: import('./chatlist.js').ChatListOptions['i18n']\n}\n\n/**\n * Full chat-app component: conversation list on the left (or full screen on\n * mobile), chat room on the right when a thread is selected.\n *\n * Works like a standalone messaging app — tapping a thread opens the chat\n * inline without navigating away from the page.\n *\n * @example\n * ```tsx\n * 'use client'\n * import { ChatList } from '@paramms/chat-widget/react'\n *\n * export default function MessagesPage({ session }) {\n * return (\n * <div style={{ height: '100vh' }}>\n * <ChatList\n * url={process.env.NEXT_PUBLIC_RELAY_WS_URL}\n * profileId={process.env.NEXT_PUBLIC_RELAY_PROFILE_ID}\n * userId={session?.user.id}\n * userName={session?.user.name}\n * userEmail={session?.user.email}\n * />\n * </div>\n * )\n * }\n * ```\n */\nexport function ChatApp({\n url, apiUrl, profileId, userId, userName, userEmail, accent, height = '100%', i18n,\n}: ChatAppProps): JSX.Element {\n type Entry = import('./chatlist.js').ChatListEntry\n const [selected, setSelected] = useState<Entry | null>(null)\n const listRef = useRef<HTMLDivElement>(null)\n const chatRef = useRef<HTMLDivElement>(null)\n const handleRef = useRef<import('./chatlist.js').ChatListHandle | null>(null)\n const chatHandle = useRef<WidgetHandle | null>(null)\n\n // Build the chat list\n useEffect(() => {\n if (!listRef.current) return\n let cancelled = false\n import('./chatlist.js').then(({ mountChatList }) => {\n // The dynamic import is async: if the effect was cleaned up (unmount,\n // dep change, or StrictMode's double-invoke) before it resolved, or the\n // ref is gone, don't mount a phantom list that never gets closed.\n if (cancelled || !listRef.current) return\n handleRef.current = mountChatList({\n el: listRef.current,\n url,\n ...(apiUrl ? { apiUrl } : {}),\n profileId,\n onSelect: (entry) => setSelected(entry),\n ...(userId ? { userId } : {}),\n ...(accent ? { accent } : {}),\n ...(i18n ? { i18n } : {}),\n })\n })\n return () => { cancelled = true; handleRef.current?.close(); handleRef.current = null }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [url, profileId, userId])\n\n // Open a ChatWidget when a thread is selected\n useEffect(() => {\n if (!chatRef.current || !selected) return\n chatHandle.current?.close()\n chatHandle.current = mount({\n el: chatRef.current,\n url,\n ...(apiUrl ? { apiUrl } : {}),\n profileId,\n ...(selected.subjectId ? { subjectId: selected.subjectId } : {}),\n ...(userId ? { token: userId } : {}),\n ...(userId || userName || userEmail ? {\n user: {\n ...(userName ? { name: userName } : {}),\n ...(userEmail ? { email: userEmail } : {}),\n },\n } : {}),\n ...(selected.subjectTitle ? {\n subject: {\n title: selected.subjectTitle,\n ...(selected.subjectMeta ? { subtitle: selected.subjectMeta } : {}),\n },\n } : {}),\n ...(accent ? { accent } : {}),\n })\n return () => { chatHandle.current?.close(); chatHandle.current = null }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [selected?.id])\n\n const isMobile = typeof window !== 'undefined' && window.innerWidth < 768\n\n return (\n <div style={{ display: 'flex', width: '100%', height, minHeight: '400px', overflow: 'hidden' }}>\n {/* List panel — hidden on mobile when a chat is open */}\n <div style={{\n width: isMobile ? '100%' : '360px',\n flex: isMobile && selected ? 'none' : undefined,\n display: isMobile && selected ? 'none' : 'flex',\n flexDirection: 'column',\n borderRight: isMobile ? 'none' : '1px solid #e8eaed',\n minWidth: 0,\n }}>\n <div ref={listRef} style={{ width: '100%', height: '100%' }} />\n </div>\n\n {/* Chat panel — shows when a thread is selected */}\n {selected ? (\n <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minWidth: 0, position: 'relative' }}>\n {/* Back button on mobile */}\n {isMobile && (\n <button\n onClick={() => setSelected(null)}\n style={{ position: 'absolute', top: 12, left: 12, zIndex: 10, background: 'none', border: 'none', fontSize: 22, cursor: 'pointer', color: '#1c1b1a' }}\n >\n ←\n </button>\n )}\n <div ref={chatRef} style={{ width: '100%', height: '100%' }} />\n </div>\n ) : (\n <div style={{ flex: 1, display: isMobile ? 'none' : 'flex', alignItems: 'center', justifyContent: 'center', color: '#9b9690', fontSize: 14 }}>\n Select a conversation\n </div>\n )}\n </div>\n )\n}\n\n// ── ChatAppLauncher ───────────────────────────────────────────────────────────\n\nexport interface ChatAppLauncherProps {\n /** Relay WebSocket URL — required */\n url: string\n /** HTTP(S) base for REST calls. Defaults to the WS origin. */\n apiUrl?: string\n /** Your Relay profile ID — required */\n profileId: string\n /** Your logged-in user's stable ID */\n userId?: string\n userName?: string\n userEmail?: string\n /** Brand colour hex — default '#4F63F5' */\n accent?: string\n\n /** true → floating bubble fixed to the corner of the screen (like Intercom)\n * false → an inline \"Messages\" button that expands a panel below it\n * Default: true */\n floating?: boolean\n /** Only used when floating=true. Default: 'bottom-right' */\n position?: 'bottom-right' | 'bottom-left'\n /** Label shown on the button. Default: '💬' for floating, 'Messages' for inline */\n label?: string\n /** Width of the chat panel. Default: '420px' (floating) or '100%' (inline) */\n panelWidth?: string\n /** Height of the chat panel. Default: '600px' */\n panelHeight?: string\n}\n\n/**\n * A button that opens the full ChatApp (list → chat) in a panel.\n *\n * floating=true → fixed bubble in the corner of the screen, like WhatsApp Web's\n * chat button or Intercom.\n * floating=false → an inline button (e.g. in your nav bar) that expands a panel\n * below it.\n *\n * @example Floating bubble (bottom-right)\n * ```tsx\n * <ChatAppLauncher\n * url={process.env.NEXT_PUBLIC_RELAY_WS_URL}\n * profileId={process.env.NEXT_PUBLIC_RELAY_PROFILE_ID}\n * userId={session?.user.id}\n * floating\n * position=\"bottom-right\"\n * />\n * ```\n *\n * @example Inline nav button\n * ```tsx\n * <ChatAppLauncher\n * url={process.env.NEXT_PUBLIC_RELAY_WS_URL}\n * profileId={process.env.NEXT_PUBLIC_RELAY_PROFILE_ID}\n * userId={session?.user.id}\n * floating={false}\n * label=\"Messages\"\n * />\n * ```\n */\nexport function ChatAppLauncher({\n url, apiUrl, profileId, userId, userName, userEmail,\n accent = '#4F63F5',\n floating = true,\n position = 'bottom-right',\n label,\n panelWidth,\n panelHeight = '600px',\n}: ChatAppLauncherProps): JSX.Element {\n const [open, setOpen] = useState(false)\n const btnRef = useRef<HTMLButtonElement>(null)\n\n const isRight = position === 'bottom-right'\n const defaultLabel = floating ? '💬' : 'Messages'\n const btnLabel = label ?? defaultLabel\n\n // Close on Escape\n useEffect(() => {\n const handler = (e: KeyboardEvent) => { if (e.key === 'Escape') setOpen(false) }\n document.addEventListener('keydown', handler)\n return () => document.removeEventListener('keydown', handler)\n }, [])\n\n // ── Floating mode ──────────────────────────────────────────────────────────\n if (floating) {\n const isMobile = typeof window !== 'undefined' && window.innerWidth < 480\n const pWidth = isMobile ? '100vw' : (panelWidth ?? '420px')\n const pHeight = isMobile ? '100dvh' : panelHeight\n\n return (\n <div style={{\n position: 'fixed',\n [isRight ? 'right' : 'left']: '20px',\n bottom: '20px',\n zIndex: 9999,\n display: 'flex',\n flexDirection: 'column',\n alignItems: isRight ? 'flex-end' : 'flex-start',\n gap: '12px',\n }}>\n {/* Panel */}\n <div style={{\n width: pWidth,\n height: pHeight,\n borderRadius: isMobile ? '0' : '16px',\n overflow: 'hidden',\n boxShadow: '0 8px 40px rgba(0,0,0,.18)',\n background: '#fff',\n display: open ? 'flex' : 'none',\n flexDirection: 'column',\n transformOrigin: `bottom ${isRight ? 'right' : 'left'}`,\n animation: open ? 'ocl-pop-in .18s ease' : 'none',\n }}>\n <ChatApp\n url={url} {...(apiUrl ? { apiUrl } : {})} profileId={profileId}\n {...(userId ? { userId } : {})}\n {...(userName ? { userName } : {})}\n {...(userEmail ? { userEmail } : {})}\n accent={accent} height=\"100%\"\n />\n </div>\n\n {/* Bubble button */}\n <button\n ref={btnRef}\n onClick={() => setOpen(o => !o)}\n style={{\n width: '56px', height: '56px', borderRadius: '50%',\n background: accent, color: '#fff', border: 'none',\n fontSize: '24px', cursor: 'pointer', flexShrink: 0,\n boxShadow: '0 4px 16px rgba(0,0,0,.25)',\n transition: 'transform .15s',\n }}\n onMouseEnter={e => { (e.target as HTMLElement).style.transform = 'scale(1.08)' }}\n onMouseLeave={e => { (e.target as HTMLElement).style.transform = 'scale(1)' }}\n >\n {open ? '✕' : btnLabel}\n </button>\n\n <style>{`@keyframes ocl-pop-in { from { opacity:0; transform:scale(.95) } to { opacity:1; transform:scale(1) } }`}</style>\n </div>\n )\n }\n\n // ── Inline mode ────────────────────────────────────────────────────────────\n // The panel is rendered via a fixed overlay anchored to the button position.\n // This prevents clipping from parent overflow:hidden containers (e.g. nav bars).\n const pWidth = panelWidth ?? '420px'\n\n // Track button position for panel anchor\n const [btnRect, setBtnRect] = useState<DOMRect | null>(null)\n\n const handleBtnClick = () => {\n if (!open && btnRef.current) setBtnRect(btnRef.current.getBoundingClientRect())\n setOpen(o => !o)\n }\n\n const panelTop = btnRect ? btnRect.bottom + 8 : 0\n const panelRight = btnRect ? window.innerWidth - btnRect.right : 0\n\n return (\n <>\n {/* Trigger button */}\n <button\n ref={btnRef}\n onClick={handleBtnClick}\n style={{\n display: 'inline-flex', alignItems: 'center', gap: '6px',\n padding: '8px 16px', borderRadius: '8px',\n background: open ? accent : 'transparent',\n color: open ? '#fff' : accent,\n border: `2px solid ${accent}`,\n fontSize: '14px', fontWeight: 600, cursor: 'pointer',\n transition: 'background .15s, color .15s',\n }}\n >\n 💬 {btnLabel}\n </button>\n\n {/* Fixed panel — rendered at document root level via CSS fixed positioning */}\n {open && btnRect && (\n <>\n {/* Backdrop */}\n <div\n onClick={() => setOpen(false)}\n style={{ position: 'fixed', inset: 0, zIndex: 9998 }}\n />\n <div style={{\n position: 'fixed',\n top: panelTop,\n right: panelRight,\n width: pWidth,\n height: panelHeight,\n borderRadius: '16px',\n overflow: 'hidden',\n boxShadow: '0 8px 40px rgba(0,0,0,.2)',\n background: '#fff',\n zIndex: 9999,\n animation: 'ocl-slide-in .18s ease',\n }}>\n <ChatApp\n url={url} {...(apiUrl ? { apiUrl } : {})} profileId={profileId}\n {...(userId ? { userId } : {})}\n {...(userName ? { userName } : {})}\n {...(userEmail ? { userEmail } : {})}\n accent={accent} height=\"100%\"\n />\n </div>\n <style>{`@keyframes ocl-slide-in { from { opacity:0; transform:translateY(-8px) } to { opacity:1; transform:translateY(0) } }`}</style>\n </>\n )}\n </>\n )\n}\n"],"names":["ChatWidget","url","apiUrl","profileId","userId","userName","userEmail","userAvatar","contextTitle","contextSubtitle","contextStatus","subjectId","accent","launcher","position","quickReplies","height","i18n","translateLang","ref","useRef","handleRef","useEffect","_a","mount","jsx","DEFAULT_MARKETPLACE_REPLIES","MarketplaceChat","listingId","listingTitle","listingMeta","listingPrice","listingStatus","ChatApp","selected","setSelected","useState","listRef","chatRef","chatHandle","cancelled","mountChatList","entry","isMobile","jsxs","ChatAppLauncher","floating","label","panelWidth","panelHeight","open","setOpen","btnRef","isRight","btnLabel","handler","e","pWidth","pHeight","o","btnRect","setBtnRect","handleBtnClick","panelTop","panelRight","Fragment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"react.js","sources":["../src/react.tsx"],"sourcesContent":["// react.tsx — React wrapper around mount().\n//\n// Next.js App Router: add 'use client' to whichever file imports these.\n// The widget needs WebSocket + DOM — it cannot render on the server.\n//\n// Import path: '@paramms/chat-widget/react'\n//\n// Two components:\n// ChatWidget — general support chat (hotel, SaaS, helpdesk, etc.)\n// MarketplaceChat — one thread per listing (used cars, rentals, etc.)\n//\n// Both: only url + profileId are required. userId is always optional —\n// anonymous guests are handled automatically via localStorage.\n\nimport { useEffect, useRef, useState } from 'react'\nimport { mount, type MountOptions, type WidgetHandle } from './index.js'\n\n// ── Shared base props ─────────────────────────────────────────────────────────\n\ninterface BaseProps {\n /** Relay URL — set as NEXT_PUBLIC_RELAY_URL in .env. Any scheme works:\n * `https://api.example.com` is fine. The WebSocket URL and REST base are\n * derived automatically — you do NOT need to pass `wss://` or `/ws`. */\n url: string\n /** HTTP(S) base for REST calls — only when the REST API is on a different\n * origin than the socket. Normally omit. */\n apiUrl?: string\n /** Your Relay profile ID — set as NEXT_PUBLIC_RELAY_PROFILE_ID in .env — required */\n profileId: string\n\n /** Your logged-in user's stable ID. When omitted the widget automatically\n * assigns a persistent anonymous ID from localStorage — no login required. */\n userId?: string\n /** Shown to agents instead of the raw user ID */\n userName?: string\n /** Shown to agents so they can follow up by email */\n userEmail?: string\n /** Avatar URL shown in the widget header and dashboard */\n userAvatar?: string\n\n /** Brand colour hex, e.g. \"#1a56db\". Defaults to the profile theme colour. */\n accent?: string\n /** Render as a floating launcher button instead of inline */\n launcher?: boolean\n /** Launcher position — default 'bottom-right' */\n position?: 'bottom-right' | 'bottom-left'\n /** Pre-set reply chips shown above the input */\n quickReplies?: string[]\n /** Container height when rendered inline. Default: '100%' */\n height?: string\n /** i18n string overrides for non-English sites */\n i18n?: MountOptions['i18n']\n /** ISO language code for auto-translating incoming messages */\n translateLang?: string\n}\n\n// ── ChatWidget ────────────────────────────────────────────────────────────────\n\nexport interface ChatWidgetProps extends BaseProps {\n /** Optional context card shown at the top of the chat\n * (e.g. the support ticket, booking, or order being discussed) */\n contextTitle?: string\n contextSubtitle?: string\n contextStatus?: string\n\n /** Stable item ID — pins this conversation to a specific item/thread. */\n subjectId?: string\n}\n\n/**\n * General-purpose support chat widget. Only `url` and `profileId` are required.\n * All other props are optional — anonymous guests work without any configuration.\n *\n * @example Basic support chat\n * ```tsx\n * <ChatWidget\n * url={process.env.NEXT_PUBLIC_RELAY_WS_URL}\n * profileId={process.env.NEXT_PUBLIC_RELAY_PROFILE_ID}\n * userId={session?.user.id}\n * userName={session?.user.name}\n * userEmail={session?.user.email}\n * />\n * ```\n *\n * @example Multi-thread (tickets, bookings, orders)\n * ```tsx\n * <ChatWidget\n * url={...} profileId={...}\n * showChatList\n * subjectId={`ticket_${ticket.id}`}\n * contextTitle={ticket.title}\n * contextStatus={ticket.status}\n * userId={session?.user.id}\n * />\n * ```\n */\nexport function ChatWidget({\n url, apiUrl, profileId,\n userId, userName, userEmail, userAvatar,\n contextTitle, contextSubtitle, contextStatus,\n subjectId,\n accent, launcher, position, quickReplies, height = '100%',\n i18n, translateLang,\n}: ChatWidgetProps): JSX.Element {\n const ref = useRef<HTMLDivElement>(null)\n const handleRef = useRef<WidgetHandle | null>(null)\n\n useEffect(() => {\n if (!ref.current) return\n handleRef.current?.close()\n handleRef.current = mount({\n el: ref.current,\n url,\n ...(apiUrl ? { apiUrl } : {}),\n profileId,\n ...(subjectId ? { subjectId } : {}),\n ...(userId ? { userId } : {}),\n ...(userId || userName || userEmail || userAvatar ? {\n user: {\n ...(userName ? { name: userName } : {}),\n ...(userEmail ? { email: userEmail } : {}),\n ...(userAvatar ? { avatar: userAvatar } : {}),\n },\n } : {}),\n ...(contextTitle ? {\n subject: {\n title: contextTitle,\n ...(contextSubtitle ? { subtitle: contextSubtitle } : {}),\n ...(contextStatus ? { status: contextStatus } : {}),\n },\n } : {}),\n ...(quickReplies ? { quickReplies } : {}),\n ...(accent ? { accent } : {}),\n ...(translateLang ? { translateLang } : {}),\n ...(i18n ? { i18n } : {}),\n ...(launcher ? { launcher, position: position ?? 'bottom-right' } : {}),\n })\n return () => { handleRef.current?.close(); handleRef.current = null }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [url, apiUrl, profileId, subjectId, userId, userName, userEmail, accent, launcher, position, translateLang])\n\n // When launcher=true, still render the div — mount() moves it inside the\n // fixed panel above the bubble. Zero size so it doesn't affect page layout.\n return (\n <div\n ref={ref}\n style={launcher ? { width: 0, height: 0, overflow: 'hidden' } : { width: '100%', height, minHeight: height === '100%' ? '480px' : undefined }}\n />\n )\n}\n\n// ── MarketplaceChat ───────────────────────────────────────────────────────────\n\nexport interface MarketplaceChatProps extends BaseProps {\n /** Unique ID for this listing — each listing gets its own thread.\n * Omit for a general (non-item-specific) conversation. */\n listingId?: string\n /** Shown at the top of the chat — e.g. \"2019 Toyota Camry SE\" */\n listingTitle?: string\n /** One-line detail — e.g. \"45,000 km · Automatic\" */\n listingMeta?: string\n /** Price shown as a tag — e.g. 12500 → \"$12,500\" */\n listingPrice?: number\n /** Status badge — e.g. \"Available\", \"Sold\", \"Pending\" */\n listingStatus?: string\n}\n\nconst DEFAULT_MARKETPLACE_REPLIES = [\n 'Is this still available?',\n 'Can I schedule a viewing?',\n 'What is your best price?',\n]\n\n/**\n * Marketplace chat widget. Two modes depending on whether `listingId` is provided:\n *\n * **With `listingId` (listing page)** — opens that listing's chat immediately.\n * No list screen. The buyer is already looking at the item so context is clear.\n * ```tsx\n * // On your listing detail page:\n * <MarketplaceChat\n * url={process.env.NEXT_PUBLIC_RELAY_WS_URL}\n * profileId={process.env.NEXT_PUBLIC_RELAY_PROFILE_ID}\n * listingId={car.id}\n * listingTitle={car.title}\n * listingPrice={car.price}\n * listingMeta={`${car.mileage.toLocaleString()} km · ${car.gearbox}`}\n * listingStatus=\"Available\"\n * userId={session?.user.id}\n * userName={session?.user.name}\n * userEmail={session?.user.email}\n * />\n * ```\n *\n * **Without `listingId` (My Messages / inbox page)** — shows the WhatsApp-style\n * thread list as the home screen. No conversation is opened until the user taps one.\n * Use this on a dedicated `/messages` or `/inbox` page.\n * ```tsx\n * // On your /messages page:\n * <MarketplaceChat\n * url={process.env.NEXT_PUBLIC_RELAY_WS_URL}\n * profileId={process.env.NEXT_PUBLIC_RELAY_PROFILE_ID}\n * userId={session?.user.id}\n * userName={session?.user.name}\n * />\n * ```\n *\n * Only `url` and `profileId` are required. All other props are optional.\n */\nexport function MarketplaceChat({\n url, apiUrl, profileId,\n listingId, listingTitle, listingMeta, listingPrice, listingStatus,\n userId, userName, userEmail, userAvatar,\n accent, launcher, position, quickReplies, height = '100%',\n i18n, translateLang,\n}: MarketplaceChatProps): JSX.Element {\n const ref = useRef<HTMLDivElement>(null)\n const handleRef = useRef<WidgetHandle | null>(null)\n\n useEffect(() => {\n if (!ref.current) return\n // Coalesce rapid identity changes into a SINGLE mount. NextAuth's\n // `session?.user.id` is undefined on first render and resolves a tick later,\n // which would otherwise open an anonymous conversation and immediately\n // orphan it when the real id arrives — surfacing as \"a new chat every time\".\n // Deferring the mount lets a same-tick id change settle first. For a slower\n // (network) session fetch, gate rendering on the session status host-side\n // (e.g. NextAuth: don't render until `status !== 'loading'`).\n let cancelled = false\n const timer = setTimeout(() => {\n if (cancelled || !ref.current) return\n handleRef.current?.close()\n handleRef.current = mount({\n el: ref.current,\n url,\n ...(apiUrl ? { apiUrl } : {}),\n profileId,\n ...(listingId ? { subjectId: `listing_${listingId}` } : {}),\n ...(userId ? { userId } : {}),\n ...(userId || userName || userEmail || userAvatar ? {\n user: {\n ...(userName ? { name: userName } : {}),\n ...(userEmail ? { email: userEmail } : {}),\n ...(userAvatar ? { avatar: userAvatar } : {}),\n ...(listingId ? { meta: { listingId } } : {}),\n },\n } : {}),\n ...(listingTitle ? {\n subject: {\n title: listingTitle,\n ...(listingMeta ? { subtitle: listingMeta } : {}),\n ...(listingPrice ? { tags: [`$${listingPrice.toLocaleString()}`] } : {}),\n ...(listingStatus ? { status: listingStatus } : {}),\n },\n } : {}),\n quickReplies: quickReplies ?? DEFAULT_MARKETPLACE_REPLIES,\n ...(accent ? { accent } : {}),\n ...(translateLang ? { translateLang } : {}),\n ...(i18n ? { i18n } : {}),\n ...(launcher ? { launcher, position: position ?? 'bottom-right' } : {}),\n })\n }, 0)\n return () => { cancelled = true; clearTimeout(timer); handleRef.current?.close(); handleRef.current = null }\n // Only identity/target-affecting props trigger a remount — metadata like\n // userName/userEmail is sent once at mount and must NOT churn the connection.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [url, apiUrl, profileId, listingId, userId, accent, launcher, position, translateLang])\n\n // When launcher=true, still render the div — mount() moves it inside the\n // fixed panel above the bubble. Zero size so it doesn't affect page layout.\n return (\n <div\n ref={ref}\n style={launcher ? { width: 0, height: 0, overflow: 'hidden' } : { width: '100%', height, minHeight: height === '100%' ? '480px' : undefined }}\n />\n )\n}\n\n// ── ChatList ──────────────────────────────────────────────────────────────────\n\nexport interface ChatAppProps {\n /** Relay WebSocket URL — required */\n url: string\n /** HTTP(S) base for REST calls. Defaults to the WS origin. */\n apiUrl?: string\n /** Your Relay profile ID — required */\n profileId: string\n /** Your logged-in user's stable ID. Omit for anonymous (uses localStorage UID) */\n userId?: string\n /** Optional: shown to agents in the dashboard */\n userName?: string\n /** Optional: shown to agents in the dashboard */\n userEmail?: string\n /** Brand colour hex — default '#4F63F5' */\n accent?: string\n /** Container height. Default: '100%' */\n height?: string\n /** i18n overrides */\n i18n?: import('./chatlist.js').ChatListOptions['i18n']\n}\n\n/**\n * Full chat-app component: conversation list on the left (or full screen on\n * mobile), chat room on the right when a thread is selected.\n *\n * Works like a standalone messaging app — tapping a thread opens the chat\n * inline without navigating away from the page.\n *\n * @example\n * ```tsx\n * 'use client'\n * import { ChatList } from '@paramms/chat-widget/react'\n *\n * export default function MessagesPage({ session }) {\n * return (\n * <div style={{ height: '100vh' }}>\n * <ChatList\n * url={process.env.NEXT_PUBLIC_RELAY_WS_URL}\n * profileId={process.env.NEXT_PUBLIC_RELAY_PROFILE_ID}\n * userId={session?.user.id}\n * userName={session?.user.name}\n * userEmail={session?.user.email}\n * />\n * </div>\n * )\n * }\n * ```\n */\nexport function ChatApp({\n url, apiUrl, profileId, userId, userName, userEmail, accent, height = '100%', i18n,\n}: ChatAppProps): JSX.Element {\n type Entry = import('./chatlist.js').ChatListEntry\n const [selected, setSelected] = useState<Entry | null>(null)\n const listRef = useRef<HTMLDivElement>(null)\n const chatRef = useRef<HTMLDivElement>(null)\n const handleRef = useRef<import('./chatlist.js').ChatListHandle | null>(null)\n const chatHandle = useRef<WidgetHandle | null>(null)\n\n // Build the chat list\n useEffect(() => {\n if (!listRef.current) return\n let cancelled = false\n import('./chatlist.js').then(({ mountChatList }) => {\n // The dynamic import is async: if the effect was cleaned up (unmount,\n // dep change, or StrictMode's double-invoke) before it resolved, or the\n // ref is gone, don't mount a phantom list that never gets closed.\n if (cancelled || !listRef.current) return\n handleRef.current = mountChatList({\n el: listRef.current,\n url,\n ...(apiUrl ? { apiUrl } : {}),\n profileId,\n onSelect: (entry) => setSelected(entry),\n ...(userId ? { userId } : {}),\n ...(accent ? { accent } : {}),\n ...(i18n ? { i18n } : {}),\n })\n })\n return () => { cancelled = true; handleRef.current?.close(); handleRef.current = null }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [url, profileId, userId])\n\n // Open a ChatWidget when a thread is selected\n useEffect(() => {\n if (!chatRef.current || !selected) return\n chatHandle.current?.close()\n chatHandle.current = mount({\n el: chatRef.current,\n url,\n ...(apiUrl ? { apiUrl } : {}),\n profileId,\n ...(selected.subjectId ? { subjectId: selected.subjectId } : {}),\n ...(userId ? { token: userId } : {}),\n ...(userId || userName || userEmail ? {\n user: {\n ...(userName ? { name: userName } : {}),\n ...(userEmail ? { email: userEmail } : {}),\n },\n } : {}),\n ...(selected.subjectTitle ? {\n subject: {\n title: selected.subjectTitle,\n ...(selected.subjectMeta ? { subtitle: selected.subjectMeta } : {}),\n },\n } : {}),\n ...(accent ? { accent } : {}),\n })\n return () => { chatHandle.current?.close(); chatHandle.current = null }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [selected?.id])\n\n const isMobile = typeof window !== 'undefined' && window.innerWidth < 768\n\n return (\n <div style={{ display: 'flex', width: '100%', height, minHeight: '400px', overflow: 'hidden' }}>\n {/* List panel — hidden on mobile when a chat is open */}\n <div style={{\n width: isMobile ? '100%' : '360px',\n flex: isMobile && selected ? 'none' : undefined,\n display: isMobile && selected ? 'none' : 'flex',\n flexDirection: 'column',\n borderRight: isMobile ? 'none' : '1px solid #e8eaed',\n minWidth: 0,\n }}>\n <div ref={listRef} style={{ width: '100%', height: '100%' }} />\n </div>\n\n {/* Chat panel — shows when a thread is selected */}\n {selected ? (\n <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minWidth: 0, position: 'relative' }}>\n {/* Back button on mobile */}\n {isMobile && (\n <button\n onClick={() => setSelected(null)}\n style={{ position: 'absolute', top: 12, left: 12, zIndex: 10, background: 'none', border: 'none', fontSize: 22, cursor: 'pointer', color: '#1c1b1a' }}\n >\n ←\n </button>\n )}\n <div ref={chatRef} style={{ width: '100%', height: '100%' }} />\n </div>\n ) : (\n <div style={{ flex: 1, display: isMobile ? 'none' : 'flex', alignItems: 'center', justifyContent: 'center', color: '#9b9690', fontSize: 14 }}>\n Select a conversation\n </div>\n )}\n </div>\n )\n}\n\n// ── ChatAppLauncher ───────────────────────────────────────────────────────────\n\nexport interface ChatAppLauncherProps {\n /** Relay WebSocket URL — required */\n url: string\n /** HTTP(S) base for REST calls. Defaults to the WS origin. */\n apiUrl?: string\n /** Your Relay profile ID — required */\n profileId: string\n /** Your logged-in user's stable ID */\n userId?: string\n userName?: string\n userEmail?: string\n /** Brand colour hex — default '#4F63F5' */\n accent?: string\n\n /** true → floating bubble fixed to the corner of the screen (like Intercom)\n * false → an inline \"Messages\" button that expands a panel below it\n * Default: true */\n floating?: boolean\n /** Only used when floating=true. Default: 'bottom-right' */\n position?: 'bottom-right' | 'bottom-left'\n /** Label shown on the button. Default: '💬' for floating, 'Messages' for inline */\n label?: string\n /** Width of the chat panel. Default: '420px' (floating) or '100%' (inline) */\n panelWidth?: string\n /** Height of the chat panel. Default: '600px' */\n panelHeight?: string\n}\n\n/**\n * A button that opens the full ChatApp (list → chat) in a panel.\n *\n * floating=true → fixed bubble in the corner of the screen, like WhatsApp Web's\n * chat button or Intercom.\n * floating=false → an inline button (e.g. in your nav bar) that expands a panel\n * below it.\n *\n * @example Floating bubble (bottom-right)\n * ```tsx\n * <ChatAppLauncher\n * url={process.env.NEXT_PUBLIC_RELAY_WS_URL}\n * profileId={process.env.NEXT_PUBLIC_RELAY_PROFILE_ID}\n * userId={session?.user.id}\n * floating\n * position=\"bottom-right\"\n * />\n * ```\n *\n * @example Inline nav button\n * ```tsx\n * <ChatAppLauncher\n * url={process.env.NEXT_PUBLIC_RELAY_WS_URL}\n * profileId={process.env.NEXT_PUBLIC_RELAY_PROFILE_ID}\n * userId={session?.user.id}\n * floating={false}\n * label=\"Messages\"\n * />\n * ```\n */\nexport function ChatAppLauncher({\n url, apiUrl, profileId, userId, userName, userEmail,\n accent = '#4F63F5',\n floating = true,\n position = 'bottom-right',\n label,\n panelWidth,\n panelHeight = '600px',\n}: ChatAppLauncherProps): JSX.Element {\n const [open, setOpen] = useState(false)\n const btnRef = useRef<HTMLButtonElement>(null)\n\n const isRight = position === 'bottom-right'\n const defaultLabel = floating ? '💬' : 'Messages'\n const btnLabel = label ?? defaultLabel\n\n // Close on Escape\n useEffect(() => {\n const handler = (e: KeyboardEvent) => { if (e.key === 'Escape') setOpen(false) }\n document.addEventListener('keydown', handler)\n return () => document.removeEventListener('keydown', handler)\n }, [])\n\n // ── Floating mode ──────────────────────────────────────────────────────────\n if (floating) {\n const isMobile = typeof window !== 'undefined' && window.innerWidth < 480\n const pWidth = isMobile ? '100vw' : (panelWidth ?? '420px')\n const pHeight = isMobile ? '100dvh' : panelHeight\n\n return (\n <div style={{\n position: 'fixed',\n [isRight ? 'right' : 'left']: '20px',\n bottom: '20px',\n zIndex: 9999,\n display: 'flex',\n flexDirection: 'column',\n alignItems: isRight ? 'flex-end' : 'flex-start',\n gap: '12px',\n }}>\n {/* Panel */}\n <div style={{\n width: pWidth,\n height: pHeight,\n borderRadius: isMobile ? '0' : '16px',\n overflow: 'hidden',\n boxShadow: '0 8px 40px rgba(0,0,0,.18)',\n background: '#fff',\n display: open ? 'flex' : 'none',\n flexDirection: 'column',\n transformOrigin: `bottom ${isRight ? 'right' : 'left'}`,\n animation: open ? 'ocl-pop-in .18s ease' : 'none',\n }}>\n <ChatApp\n url={url} {...(apiUrl ? { apiUrl } : {})} profileId={profileId}\n {...(userId ? { userId } : {})}\n {...(userName ? { userName } : {})}\n {...(userEmail ? { userEmail } : {})}\n accent={accent} height=\"100%\"\n />\n </div>\n\n {/* Bubble button */}\n <button\n ref={btnRef}\n onClick={() => setOpen(o => !o)}\n style={{\n width: '56px', height: '56px', borderRadius: '50%',\n background: accent, color: '#fff', border: 'none',\n fontSize: '24px', cursor: 'pointer', flexShrink: 0,\n boxShadow: '0 4px 16px rgba(0,0,0,.25)',\n transition: 'transform .15s',\n }}\n onMouseEnter={e => { (e.target as HTMLElement).style.transform = 'scale(1.08)' }}\n onMouseLeave={e => { (e.target as HTMLElement).style.transform = 'scale(1)' }}\n >\n {open ? '✕' : btnLabel}\n </button>\n\n <style>{`@keyframes ocl-pop-in { from { opacity:0; transform:scale(.95) } to { opacity:1; transform:scale(1) } }`}</style>\n </div>\n )\n }\n\n // ── Inline mode ────────────────────────────────────────────────────────────\n // The panel is rendered via a fixed overlay anchored to the button position.\n // This prevents clipping from parent overflow:hidden containers (e.g. nav bars).\n const pWidth = panelWidth ?? '420px'\n\n // Track button position for panel anchor\n const [btnRect, setBtnRect] = useState<DOMRect | null>(null)\n\n const handleBtnClick = () => {\n if (!open && btnRef.current) setBtnRect(btnRef.current.getBoundingClientRect())\n setOpen(o => !o)\n }\n\n const panelTop = btnRect ? btnRect.bottom + 8 : 0\n const panelRight = btnRect ? window.innerWidth - btnRect.right : 0\n\n return (\n <>\n {/* Trigger button */}\n <button\n ref={btnRef}\n onClick={handleBtnClick}\n style={{\n display: 'inline-flex', alignItems: 'center', gap: '6px',\n padding: '8px 16px', borderRadius: '8px',\n background: open ? accent : 'transparent',\n color: open ? '#fff' : accent,\n border: `2px solid ${accent}`,\n fontSize: '14px', fontWeight: 600, cursor: 'pointer',\n transition: 'background .15s, color .15s',\n }}\n >\n 💬 {btnLabel}\n </button>\n\n {/* Fixed panel — rendered at document root level via CSS fixed positioning */}\n {open && btnRect && (\n <>\n {/* Backdrop */}\n <div\n onClick={() => setOpen(false)}\n style={{ position: 'fixed', inset: 0, zIndex: 9998 }}\n />\n <div style={{\n position: 'fixed',\n top: panelTop,\n right: panelRight,\n width: pWidth,\n height: panelHeight,\n borderRadius: '16px',\n overflow: 'hidden',\n boxShadow: '0 8px 40px rgba(0,0,0,.2)',\n background: '#fff',\n zIndex: 9999,\n animation: 'ocl-slide-in .18s ease',\n }}>\n <ChatApp\n url={url} {...(apiUrl ? { apiUrl } : {})} profileId={profileId}\n {...(userId ? { userId } : {})}\n {...(userName ? { userName } : {})}\n {...(userEmail ? { userEmail } : {})}\n accent={accent} height=\"100%\"\n />\n </div>\n <style>{`@keyframes ocl-slide-in { from { opacity:0; transform:translateY(-8px) } to { opacity:1; transform:translateY(0) } }`}</style>\n </>\n )}\n </>\n )\n}\n"],"names":["ChatWidget","url","apiUrl","profileId","userId","userName","userEmail","userAvatar","contextTitle","contextSubtitle","contextStatus","subjectId","accent","launcher","position","quickReplies","height","i18n","translateLang","ref","useRef","handleRef","useEffect","_a","mount","jsx","DEFAULT_MARKETPLACE_REPLIES","MarketplaceChat","listingId","listingTitle","listingMeta","listingPrice","listingStatus","cancelled","timer","ChatApp","selected","setSelected","useState","listRef","chatRef","chatHandle","mountChatList","entry","isMobile","jsxs","ChatAppLauncher","floating","label","panelWidth","panelHeight","open","setOpen","btnRef","isRight","btnLabel","handler","e","pWidth","pHeight","o","btnRect","setBtnRect","handleBtnClick","panelTop","panelRight","Fragment"],"mappings":"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"}
|