@paramms/chat-widget 1.0.11 → 1.0.12

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 CHANGED
@@ -1,62 +1,63 @@
1
- import { jsxs as R, jsx as c, Fragment as M } from "react/jsx-runtime";
2
- import { useState as W, useRef as m, useEffect as j } from "react";
3
- import { mount as z } from "./index.js";
1
+ import { jsxs as C, jsx as s, Fragment as D } from "react/jsx-runtime";
2
+ import { useState as M, useRef as v, useEffect as S } from "react";
3
+ import { mount as L } from "./index.js";
4
4
  function Y({
5
5
  url: x,
6
6
  profileId: b,
7
- userId: t,
7
+ userId: e,
8
8
  userName: i,
9
9
  userEmail: r,
10
- userAvatar: n,
10
+ userAvatar: o,
11
11
  contextTitle: g,
12
12
  contextSubtitle: y,
13
- contextStatus: e,
14
- subjectId: h,
15
- accent: p,
16
- launcher: o,
17
- position: s,
18
- quickReplies: d,
19
- height: l = "100%",
20
- i18n: f,
21
- translateLang: a
13
+ contextStatus: t,
14
+ subjectId: f,
15
+ accent: h,
16
+ launcher: n,
17
+ position: l,
18
+ quickReplies: c,
19
+ height: d = "100%",
20
+ i18n: p,
21
+ translateLang: u
22
22
  }) {
23
- const w = m(null), u = m(null);
24
- return j(() => {
23
+ const w = v(null), a = v(null);
24
+ return S(() => {
25
+ var m;
25
26
  if (w.current)
26
- return u.current = z({
27
+ return (m = a.current) == null || m.close(), a.current = L({
27
28
  el: w.current,
28
29
  url: x,
29
30
  profileId: b,
30
- ...h ? { subjectId: h } : {},
31
- ...t ? { token: t } : {},
32
- ...t || i || r || n ? {
31
+ ...f ? { subjectId: f } : {},
32
+ ...e ? { token: e } : {},
33
+ ...e || i || r || o ? {
33
34
  user: {
34
35
  ...i ? { name: i } : {},
35
36
  ...r ? { email: r } : {},
36
- ...n ? { avatar: n } : {}
37
+ ...o ? { avatar: o } : {}
37
38
  }
38
39
  } : {},
39
40
  ...g ? {
40
41
  subject: {
41
42
  title: g,
42
43
  ...y ? { subtitle: y } : {},
43
- ...e ? { status: e } : {}
44
+ ...t ? { status: t } : {}
44
45
  }
45
46
  } : {},
46
- ...d ? { quickReplies: d } : {},
47
- ...p ? { accent: p } : {},
48
- ...a ? { translateLang: a } : {},
49
- ...f ? { i18n: f } : {},
50
- ...o ? { launcher: o, position: s ?? "bottom-right" } : {}
47
+ ...c ? { quickReplies: c } : {},
48
+ ...h ? { accent: h } : {},
49
+ ...u ? { translateLang: u } : {},
50
+ ...p ? { i18n: p } : {},
51
+ ...n ? { launcher: n, position: l ?? "bottom-right" } : {}
51
52
  }), () => {
52
- var v;
53
- (v = u.current) == null || v.close(), u.current = null;
53
+ var R;
54
+ (R = a.current) == null || R.close(), a.current = null;
54
55
  };
55
- }, [x, b, h, t]), /* @__PURE__ */ c(
56
+ }, [x, b, f, e, i, r, h, n, l, u]), /* @__PURE__ */ s(
56
57
  "div",
57
58
  {
58
59
  ref: w,
59
- style: o ? { width: 0, height: 0, overflow: "hidden" } : { width: "100%", height: l, minHeight: l === "100%" ? "480px" : void 0 }
60
+ style: n ? { width: 0, height: 0, overflow: "hidden" } : { width: "100%", height: d, minHeight: d === "100%" ? "480px" : void 0 }
60
61
  }
61
62
  );
62
63
  }
@@ -68,209 +69,207 @@ const B = [
68
69
  function A({
69
70
  url: x,
70
71
  profileId: b,
71
- listingId: t,
72
+ listingId: e,
72
73
  listingTitle: i,
73
74
  listingMeta: r,
74
- listingPrice: n,
75
+ listingPrice: o,
75
76
  listingStatus: g,
76
77
  userId: y,
77
- userName: e,
78
- userEmail: h,
79
- userAvatar: p,
80
- accent: o,
81
- launcher: s,
82
- position: d,
83
- quickReplies: l,
84
- height: f = "100%",
85
- i18n: a,
78
+ userName: t,
79
+ userEmail: f,
80
+ userAvatar: h,
81
+ accent: n,
82
+ launcher: l,
83
+ position: c,
84
+ quickReplies: d,
85
+ height: p = "100%",
86
+ i18n: u,
86
87
  translateLang: w
87
88
  }) {
88
- const u = m(null), v = m(null);
89
- return j(() => {
90
- if (u.current)
91
- return v.current = z({
92
- el: u.current,
89
+ const a = v(null), m = v(null);
90
+ return S(() => {
91
+ var R;
92
+ if (a.current)
93
+ return (R = m.current) == null || R.close(), m.current = L({
94
+ el: a.current,
93
95
  url: x,
94
96
  profileId: b,
95
- // ── Listing context ────────────────────────────────────────────────────
96
- // When listingId is present: open that listing's chat directly (no list).
97
- // When listingId is absent: show the thread list (dedicated inbox page).
98
- ...t ? { subjectId: `listing_${t}` } : {},
97
+ ...e ? { subjectId: `listing_${e}` } : {},
99
98
  ...y ? { token: y } : {},
100
- ...y || e || h || p ? {
99
+ ...y || t || f || h ? {
101
100
  user: {
102
- ...e ? { name: e } : {},
103
- ...h ? { email: h } : {},
104
- ...p ? { avatar: p } : {},
105
- ...t ? { meta: { listingId: t } } : {}
101
+ ...t ? { name: t } : {},
102
+ ...f ? { email: f } : {},
103
+ ...h ? { avatar: h } : {},
104
+ ...e ? { meta: { listingId: e } } : {}
106
105
  }
107
106
  } : {},
108
107
  ...i ? {
109
108
  subject: {
110
109
  title: i,
111
110
  ...r ? { subtitle: r } : {},
112
- ...n ? { tags: [`$${n.toLocaleString()}`] } : {},
111
+ ...o ? { tags: [`$${o.toLocaleString()}`] } : {},
113
112
  ...g ? { status: g } : {}
114
113
  }
115
114
  } : {},
116
- quickReplies: l ?? B,
117
- ...o ? { accent: o } : {},
115
+ quickReplies: d ?? B,
116
+ ...n ? { accent: n } : {},
118
117
  ...w ? { translateLang: w } : {},
119
- ...a ? { i18n: a } : {},
120
- ...s ? { launcher: s, position: d ?? "bottom-right" } : {}
118
+ ...u ? { i18n: u } : {},
119
+ ...l ? { launcher: l, position: c ?? "bottom-right" } : {}
121
120
  }), () => {
122
- var S;
123
- (S = v.current) == null || S.close(), v.current = null;
121
+ var W;
122
+ (W = m.current) == null || W.close(), m.current = null;
124
123
  };
125
- }, [x, b, t, y]), /* @__PURE__ */ c(
124
+ }, [x, b, e, y, t, f, n, l, c, w]), /* @__PURE__ */ s(
126
125
  "div",
127
126
  {
128
- ref: u,
129
- style: s ? { width: 0, height: 0, overflow: "hidden" } : { width: "100%", height: f, minHeight: f === "100%" ? "480px" : void 0 }
127
+ ref: a,
128
+ style: l ? { width: 0, height: 0, overflow: "hidden" } : { width: "100%", height: p, minHeight: p === "100%" ? "480px" : void 0 }
130
129
  }
131
130
  );
132
131
  }
133
- function D({
132
+ function $({
134
133
  url: x,
135
134
  profileId: b,
136
- userId: t,
135
+ userId: e,
137
136
  userName: i,
138
137
  userEmail: r,
139
- accent: n,
138
+ accent: o,
140
139
  height: g = "100%",
141
140
  i18n: y
142
141
  }) {
143
- const [e, h] = W(null), p = m(null), o = m(null), s = m(null), d = m(null);
144
- j(() => {
145
- if (p.current)
146
- return import("./chatlist.js").then(({ mountChatList: f }) => {
147
- s.current = f({
148
- el: p.current,
142
+ const [t, f] = M(null), h = v(null), n = v(null), l = v(null), c = v(null);
143
+ S(() => {
144
+ if (h.current)
145
+ return import("./chatlist.js").then(({ mountChatList: p }) => {
146
+ l.current = p({
147
+ el: h.current,
149
148
  url: x,
150
149
  profileId: b,
151
- onSelect: (a) => h(a),
152
- ...t ? { userId: t } : {},
153
- ...n ? { accent: n } : {},
150
+ onSelect: (u) => f(u),
151
+ ...e ? { userId: e } : {},
152
+ ...o ? { accent: o } : {},
154
153
  ...y ? { i18n: y } : {}
155
154
  });
156
155
  }), () => {
157
- var f;
158
- (f = s.current) == null || f.close(), s.current = null;
156
+ var p;
157
+ (p = l.current) == null || p.close(), l.current = null;
159
158
  };
160
- }, [x, b, t]), j(() => {
161
- var f;
162
- if (!(!o.current || !e))
163
- return (f = d.current) == null || f.close(), d.current = z({
164
- el: o.current,
159
+ }, [x, b, e]), S(() => {
160
+ var p;
161
+ if (!(!n.current || !t))
162
+ return (p = c.current) == null || p.close(), c.current = L({
163
+ el: n.current,
165
164
  url: x,
166
165
  profileId: b,
167
- ...e.subjectId ? { subjectId: e.subjectId } : {},
168
- ...t ? { token: t } : {},
169
- ...t || i || r ? {
166
+ ...t.subjectId ? { subjectId: t.subjectId } : {},
167
+ ...e ? { token: e } : {},
168
+ ...e || i || r ? {
170
169
  user: {
171
170
  ...i ? { name: i } : {},
172
171
  ...r ? { email: r } : {}
173
172
  }
174
173
  } : {},
175
- ...e.subjectTitle ? {
174
+ ...t.subjectTitle ? {
176
175
  subject: {
177
- title: e.subjectTitle,
178
- ...e.subjectMeta ? { subtitle: e.subjectMeta } : {}
176
+ title: t.subjectTitle,
177
+ ...t.subjectMeta ? { subtitle: t.subjectMeta } : {}
179
178
  }
180
179
  } : {},
181
- ...n ? { accent: n } : {}
180
+ ...o ? { accent: o } : {}
182
181
  }), () => {
183
- var a;
184
- (a = d.current) == null || a.close(), d.current = null;
182
+ var u;
183
+ (u = c.current) == null || u.close(), c.current = null;
185
184
  };
186
- }, [e == null ? void 0 : e.id]);
187
- const l = typeof window < "u" && window.innerWidth < 768;
188
- return /* @__PURE__ */ R("div", { style: { display: "flex", width: "100%", height: g, minHeight: "400px", overflow: "hidden" }, children: [
189
- /* @__PURE__ */ c("div", { style: {
190
- width: l ? "100%" : "360px",
191
- flex: l && e ? "none" : void 0,
192
- display: l && e ? "none" : "flex",
185
+ }, [t == null ? void 0 : t.id]);
186
+ const d = typeof window < "u" && window.innerWidth < 768;
187
+ return /* @__PURE__ */ C("div", { style: { display: "flex", width: "100%", height: g, minHeight: "400px", overflow: "hidden" }, children: [
188
+ /* @__PURE__ */ s("div", { style: {
189
+ width: d ? "100%" : "360px",
190
+ flex: d && t ? "none" : void 0,
191
+ display: d && t ? "none" : "flex",
193
192
  flexDirection: "column",
194
- borderRight: l ? "none" : "1px solid #e8eaed",
193
+ borderRight: d ? "none" : "1px solid #e8eaed",
195
194
  minWidth: 0
196
- }, children: /* @__PURE__ */ c("div", { ref: p, style: { width: "100%", height: "100%" } }) }),
197
- e ? /* @__PURE__ */ R("div", { style: { flex: 1, display: "flex", flexDirection: "column", minWidth: 0, position: "relative" }, children: [
198
- l && /* @__PURE__ */ c(
195
+ }, children: /* @__PURE__ */ s("div", { ref: h, style: { width: "100%", height: "100%" } }) }),
196
+ t ? /* @__PURE__ */ C("div", { style: { flex: 1, display: "flex", flexDirection: "column", minWidth: 0, position: "relative" }, children: [
197
+ d && /* @__PURE__ */ s(
199
198
  "button",
200
199
  {
201
- onClick: () => h(null),
200
+ onClick: () => f(null),
202
201
  style: { position: "absolute", top: 12, left: 12, zIndex: 10, background: "none", border: "none", fontSize: 22, cursor: "pointer", color: "#1c1b1a" },
203
202
  children: "←"
204
203
  }
205
204
  ),
206
- /* @__PURE__ */ c("div", { ref: o, style: { width: "100%", height: "100%" } })
207
- ] }) : /* @__PURE__ */ c("div", { style: { flex: 1, display: l ? "none" : "flex", alignItems: "center", justifyContent: "center", color: "#9b9690", fontSize: 14 }, children: "Select a conversation" })
205
+ /* @__PURE__ */ s("div", { ref: n, style: { width: "100%", height: "100%" } })
206
+ ] }) : /* @__PURE__ */ s("div", { style: { flex: 1, display: d ? "none" : "flex", alignItems: "center", justifyContent: "center", color: "#9b9690", fontSize: 14 }, children: "Select a conversation" })
208
207
  ] });
209
208
  }
210
- function E({
209
+ function K({
211
210
  url: x,
212
211
  profileId: b,
213
- userId: t,
212
+ userId: e,
214
213
  userName: i,
215
214
  userEmail: r,
216
- accent: n = "#4F63F5",
215
+ accent: o = "#4F63F5",
217
216
  floating: g = !0,
218
217
  position: y = "bottom-right",
219
- label: e,
220
- panelWidth: h,
221
- panelHeight: p = "600px"
218
+ label: t,
219
+ panelWidth: f,
220
+ panelHeight: h = "600px"
222
221
  }) {
223
- const [o, s] = W(!1), d = m(null), l = y === "bottom-right", a = e ?? (g ? "💬" : "Messages");
224
- if (j(() => {
225
- const k = (L) => {
226
- L.key === "Escape" && s(!1);
222
+ const [n, l] = M(!1), c = v(null), d = y === "bottom-right", u = t ?? (g ? "💬" : "Messages");
223
+ if (S(() => {
224
+ const k = (z) => {
225
+ z.key === "Escape" && l(!1);
227
226
  };
228
227
  return document.addEventListener("keydown", k), () => document.removeEventListener("keydown", k);
229
228
  }, []), g) {
230
- const k = typeof window < "u" && window.innerWidth < 480, L = k ? "100vw" : h ?? "420px", H = k ? "100dvh" : p;
231
- return /* @__PURE__ */ R("div", { style: {
229
+ const k = typeof window < "u" && window.innerWidth < 480, z = k ? "100vw" : f ?? "420px", H = k ? "100dvh" : h;
230
+ return /* @__PURE__ */ C("div", { style: {
232
231
  position: "fixed",
233
- [l ? "right" : "left"]: "20px",
232
+ [d ? "right" : "left"]: "20px",
234
233
  bottom: "20px",
235
234
  zIndex: 9999,
236
235
  display: "flex",
237
236
  flexDirection: "column",
238
- alignItems: l ? "flex-end" : "flex-start",
237
+ alignItems: d ? "flex-end" : "flex-start",
239
238
  gap: "12px"
240
239
  }, children: [
241
- /* @__PURE__ */ c("div", { style: {
242
- width: L,
240
+ /* @__PURE__ */ s("div", { style: {
241
+ width: z,
243
242
  height: H,
244
243
  borderRadius: k ? "0" : "16px",
245
244
  overflow: "hidden",
246
245
  boxShadow: "0 8px 40px rgba(0,0,0,.18)",
247
246
  background: "#fff",
248
- display: o ? "flex" : "none",
247
+ display: n ? "flex" : "none",
249
248
  flexDirection: "column",
250
- transformOrigin: `bottom ${l ? "right" : "left"}`,
251
- animation: o ? "ocl-pop-in .18s ease" : "none"
252
- }, children: /* @__PURE__ */ c(
253
- D,
249
+ transformOrigin: `bottom ${d ? "right" : "left"}`,
250
+ animation: n ? "ocl-pop-in .18s ease" : "none"
251
+ }, children: /* @__PURE__ */ s(
252
+ $,
254
253
  {
255
254
  url: x,
256
255
  profileId: b,
257
- ...t ? { userId: t } : {},
256
+ ...e ? { userId: e } : {},
258
257
  ...i ? { userName: i } : {},
259
258
  ...r ? { userEmail: r } : {},
260
- accent: n,
259
+ accent: o,
261
260
  height: "100%"
262
261
  }
263
262
  ) }),
264
- /* @__PURE__ */ c(
263
+ /* @__PURE__ */ s(
265
264
  "button",
266
265
  {
267
- ref: d,
268
- onClick: () => s((C) => !C),
266
+ ref: c,
267
+ onClick: () => l((j) => !j),
269
268
  style: {
270
269
  width: "56px",
271
270
  height: "56px",
272
271
  borderRadius: "50%",
273
- background: n,
272
+ background: o,
274
273
  color: "#fff",
275
274
  border: "none",
276
275
  fontSize: "24px",
@@ -279,36 +278,36 @@ function E({
279
278
  boxShadow: "0 4px 16px rgba(0,0,0,.25)",
280
279
  transition: "transform .15s"
281
280
  },
282
- onMouseEnter: (C) => {
283
- C.target.style.transform = "scale(1.08)";
281
+ onMouseEnter: (j) => {
282
+ j.target.style.transform = "scale(1.08)";
284
283
  },
285
- onMouseLeave: (C) => {
286
- C.target.style.transform = "scale(1)";
284
+ onMouseLeave: (j) => {
285
+ j.target.style.transform = "scale(1)";
287
286
  },
288
- children: o ? "✕" : a
287
+ children: n ? "✕" : u
289
288
  }
290
289
  ),
291
- /* @__PURE__ */ c("style", { children: "@keyframes ocl-pop-in { from { opacity:0; transform:scale(.95) } to { opacity:1; transform:scale(1) } }" })
290
+ /* @__PURE__ */ s("style", { children: "@keyframes ocl-pop-in { from { opacity:0; transform:scale(.95) } to { opacity:1; transform:scale(1) } }" })
292
291
  ] });
293
292
  }
294
- const w = h ?? "420px", [u, v] = W(null), S = () => {
295
- !o && d.current && v(d.current.getBoundingClientRect()), s((k) => !k);
296
- }, $ = u ? u.bottom + 8 : 0, F = u ? window.innerWidth - u.right : 0;
297
- return /* @__PURE__ */ R(M, { children: [
298
- /* @__PURE__ */ R(
293
+ const w = f ?? "420px", [a, m] = M(null), R = () => {
294
+ !n && c.current && m(c.current.getBoundingClientRect()), l((k) => !k);
295
+ }, W = a ? a.bottom + 8 : 0, F = a ? window.innerWidth - a.right : 0;
296
+ return /* @__PURE__ */ C(D, { children: [
297
+ /* @__PURE__ */ C(
299
298
  "button",
300
299
  {
301
- ref: d,
302
- onClick: S,
300
+ ref: c,
301
+ onClick: R,
303
302
  style: {
304
303
  display: "inline-flex",
305
304
  alignItems: "center",
306
305
  gap: "6px",
307
306
  padding: "8px 16px",
308
307
  borderRadius: "8px",
309
- background: o ? n : "transparent",
310
- color: o ? "#fff" : n,
311
- border: `2px solid ${n}`,
308
+ background: n ? o : "transparent",
309
+ color: n ? "#fff" : o,
310
+ border: `2px solid ${o}`,
312
311
  fontSize: "14px",
313
312
  fontWeight: 600,
314
313
  cursor: "pointer",
@@ -316,49 +315,49 @@ function E({
316
315
  },
317
316
  children: [
318
317
  "💬 ",
319
- a
318
+ u
320
319
  ]
321
320
  }
322
321
  ),
323
- o && u && /* @__PURE__ */ R(M, { children: [
324
- /* @__PURE__ */ c(
322
+ n && a && /* @__PURE__ */ C(D, { children: [
323
+ /* @__PURE__ */ s(
325
324
  "div",
326
325
  {
327
- onClick: () => s(!1),
326
+ onClick: () => l(!1),
328
327
  style: { position: "fixed", inset: 0, zIndex: 9998 }
329
328
  }
330
329
  ),
331
- /* @__PURE__ */ c("div", { style: {
330
+ /* @__PURE__ */ s("div", { style: {
332
331
  position: "fixed",
333
- top: $,
332
+ top: W,
334
333
  right: F,
335
334
  width: w,
336
- height: p,
335
+ height: h,
337
336
  borderRadius: "16px",
338
337
  overflow: "hidden",
339
338
  boxShadow: "0 8px 40px rgba(0,0,0,.2)",
340
339
  background: "#fff",
341
340
  zIndex: 9999,
342
341
  animation: "ocl-slide-in .18s ease"
343
- }, children: /* @__PURE__ */ c(
344
- D,
342
+ }, children: /* @__PURE__ */ s(
343
+ $,
345
344
  {
346
345
  url: x,
347
346
  profileId: b,
348
- ...t ? { userId: t } : {},
347
+ ...e ? { userId: e } : {},
349
348
  ...i ? { userName: i } : {},
350
349
  ...r ? { userEmail: r } : {},
351
- accent: n,
350
+ accent: o,
352
351
  height: "100%"
353
352
  }
354
353
  ) }),
355
- /* @__PURE__ */ c("style", { children: "@keyframes ocl-slide-in { from { opacity:0; transform:translateY(-8px) } to { opacity:1; transform:translateY(0) } }" })
354
+ /* @__PURE__ */ s("style", { children: "@keyframes ocl-slide-in { from { opacity:0; transform:translateY(-8px) } to { opacity:1; transform:translateY(0) } }" })
356
355
  ] })
357
356
  ] });
358
357
  }
359
358
  export {
360
- D as ChatApp,
361
- E as ChatAppLauncher,
359
+ $ as ChatApp,
360
+ K as ChatAppLauncher,
362
361
  Y as ChatWidget,
363
362
  A as MarketplaceChat
364
363
  };
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 WebSocket URL — set as NEXT_PUBLIC_RELAY_WS_URL in .env — required */\n url: 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, 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 = mount({\n el: ref.current,\n url,\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, profileId, subjectId, userId])\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, 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 handleRef.current = mount({\n el: ref.current,\n url,\n profileId,\n\n // ── Listing context ────────────────────────────────────────────────────\n // When listingId is present: open that listing's chat directly (no list).\n // When listingId is absent: show the thread list (dedicated inbox page).\n ...(listingId ? { subjectId: `listing_${listingId}` } : {}),\n\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\n ...(listingTitle ? {\n subject: {\n title: listingTitle,\n ...(listingMeta ? { subtitle: listingMeta } : {}),\n ...(listingPrice ? { tags: [`$${listingPrice.toLocaleString()}`] } : {}),\n ...(listingStatus ? { status: listingStatus } : {}),\n },\n } : {}),\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 // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [url, profileId, listingId, userId])\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 /** 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 '#f5713c' */\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, 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 import('./chatlist.js').then(({ mountChatList }) => {\n handleRef.current = mountChatList({\n el: listRef.current!,\n url,\n profileId,\n onSelect: (entry) => setSelected(entry),\n ...(userId ? { userId } : {}),\n ...(accent ? { accent } : {}),\n ...(i18n ? { i18n } : {}),\n })\n })\n return () => { 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 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 /** 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, 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} 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} 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","profileId","userId","userName","userEmail","userAvatar","contextTitle","contextSubtitle","contextStatus","subjectId","accent","launcher","position","quickReplies","height","i18n","translateLang","ref","useRef","handleRef","useEffect","mount","_a","jsx","DEFAULT_MARKETPLACE_REPLIES","MarketplaceChat","listingId","listingTitle","listingMeta","listingPrice","listingStatus","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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"}
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 WebSocket URL — set as NEXT_PUBLIC_RELAY_WS_URL in .env — required */\n url: 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, 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 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, 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, 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 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, 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 /** 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 '#f5713c' */\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, 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 import('./chatlist.js').then(({ mountChatList }) => {\n handleRef.current = mountChatList({\n el: listRef.current!,\n url,\n profileId,\n onSelect: (entry) => setSelected(entry),\n ...(userId ? { userId } : {}),\n ...(accent ? { accent } : {}),\n ...(i18n ? { i18n } : {}),\n })\n })\n return () => { 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 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 /** 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, 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} 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} 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","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","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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paramms/chat-widget",
3
- "version": "1.0.11",
3
+ "version": "1.0.12",
4
4
  "description": "Embeddable real-time chat widget for the Relay platform",
5
5
  "license": "MIT",
6
6
  "repository": {