@banbox/chat 1.0.9 → 1.0.11

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/index.d.cts CHANGED
@@ -316,8 +316,18 @@ type ChatRootProps = {
316
316
  * <ChatRoot adapter={adapter} theme="admin" />
317
317
  */
318
318
  theme?: ChatTheme;
319
+ /**
320
+ * Keys of footer toolbar actions to hide.
321
+ *
322
+ * Available keys: "attachment" | "emoji" | "businessCard" | "addressCard" | "translate"
323
+ *
324
+ * @example
325
+ * // Hide the Delivery Address button in the seller app:
326
+ * <ChatRoot hiddenActionKeys={["addressCard"]} ... />
327
+ */
328
+ hiddenActionKeys?: string[];
319
329
  };
320
- declare function ChatRoot({ adapter, uiCallbacks, theme }: ChatRootProps): React$1.ReactPortal | null;
330
+ declare function ChatRoot({ adapter, uiCallbacks, theme, hiddenActionKeys }: ChatRootProps): React$1.ReactPortal | null;
321
331
 
322
332
  declare function ChatUIProvider({ children }: {
323
333
  children: React__default.ReactNode;
@@ -471,7 +481,13 @@ type ChatMessageItemProps = {
471
481
  status?: string;
472
482
  className?: string;
473
483
  onReply?: () => void;
474
- onTranslate?: () => void;
484
+ /**
485
+ * Optional async translator. Receives the original text and returns the
486
+ * translated string. When omitted the translate button is still shown but
487
+ * does nothing (good for demo mode).
488
+ * Example: `onTranslate={(t) => googleTranslate(t, "bn")}`
489
+ */
490
+ onTranslate?: (text: string) => string | undefined;
475
491
  initialSrc?: string;
476
492
  };
477
493
  declare const ChatMessageItem: React__default.FC<ChatMessageItemProps>;
package/dist/index.d.ts CHANGED
@@ -316,8 +316,18 @@ type ChatRootProps = {
316
316
  * <ChatRoot adapter={adapter} theme="admin" />
317
317
  */
318
318
  theme?: ChatTheme;
319
+ /**
320
+ * Keys of footer toolbar actions to hide.
321
+ *
322
+ * Available keys: "attachment" | "emoji" | "businessCard" | "addressCard" | "translate"
323
+ *
324
+ * @example
325
+ * // Hide the Delivery Address button in the seller app:
326
+ * <ChatRoot hiddenActionKeys={["addressCard"]} ... />
327
+ */
328
+ hiddenActionKeys?: string[];
319
329
  };
320
- declare function ChatRoot({ adapter, uiCallbacks, theme }: ChatRootProps): React$1.ReactPortal | null;
330
+ declare function ChatRoot({ adapter, uiCallbacks, theme, hiddenActionKeys }: ChatRootProps): React$1.ReactPortal | null;
321
331
 
322
332
  declare function ChatUIProvider({ children }: {
323
333
  children: React__default.ReactNode;
@@ -471,7 +481,13 @@ type ChatMessageItemProps = {
471
481
  status?: string;
472
482
  className?: string;
473
483
  onReply?: () => void;
474
- onTranslate?: () => void;
484
+ /**
485
+ * Optional async translator. Receives the original text and returns the
486
+ * translated string. When omitted the translate button is still shown but
487
+ * does nothing (good for demo mode).
488
+ * Example: `onTranslate={(t) => googleTranslate(t, "bn")}`
489
+ */
490
+ onTranslate?: (text: string) => string | undefined;
475
491
  initialSrc?: string;
476
492
  };
477
493
  declare const ChatMessageItem: React__default.FC<ChatMessageItemProps>;
package/dist/index.js CHANGED
@@ -3243,21 +3243,6 @@ var MessageHoverActions = ({
3243
3243
  ] });
3244
3244
  };
3245
3245
  var MessageHoverActions_default = MessageHoverActions;
3246
- var toBanglaDemo = (s) => {
3247
- const map = {
3248
- Hi: "\u09B9\u09BE\u0987",
3249
- "Do you have a freight forwarder in China?": "\u0986\u09AA\u09A8\u09BE\u09B0 \u0995\u09BF \u099A\u09C0\u09A8\u09C7 \u0995\u09CB\u09A8\u09CB \u09AB\u09CD\u09B0\u09C7\u0987\u099F \u09AB\u09B0\u0993\u09AF\u09BC\u09BE\u09B0\u09CD\u09A1\u09BE\u09B0 \u0986\u099B\u09C7?",
3250
- "This conversation is empty. Say hi \u{1F44B}": "\u098F\u0987 \u0995\u09A5\u09CB\u09AA\u0995\u09A5\u09A8\u099F\u09BF \u0996\u09BE\u09B2\u09BF \u0964 \u09B9\u09BE\u0987 \u09B9\u09BE\u0987 \u09B9\u09BE\u0987 \u09AC\u09B2\u09C1\u09A8 \u{1F44B}",
3251
- "Can we schedule a call for tomorrow?": "\u0986\u09AE\u09B0\u09BE \u0995\u09BF \u0986\u0997\u09BE\u09AE\u09C0\u0995\u09BE\u09B2 \u098F\u0995\u099F\u09BF \u0995\u09B2 \u09A8\u09BF\u09B0\u09CD\u09A7\u09BE\u09B0\u09A3 \u0995\u09B0\u09A4\u09C7 \u09AA\u09BE\u09B0\u09BF?",
3252
- "Sure, what time suits you?": "\u0985\u09AC\u09B6\u09CD\u09AF\u0987, \u0986\u09AA\u09A8\u09BE\u09B0 \u099C\u09A8\u09CD\u09AF \u0995\u09CB\u09A8 \u09B8\u09AE\u09AF\u09BC\u099F\u09BF \u09B8\u09C1\u09AC\u09BF\u09A7\u09BE\u099C\u09A8\u0995?",
3253
- "Welcome to Global Marketplace": "\u0997\u09CD\u09B2\u09CB\u09AC\u09BE\u09B2 \u09AE\u09BE\u09B0\u09CD\u0995\u09C7\u099F\u09AA\u09CD\u09B2\u09C7\u09B8\u09C7 \u0986\u09AA\u09A8\u09BE\u0995\u09C7 \u09B8\u09CD\u09AC\u09BE\u0997\u09A4\u09AE \u{1F389}",
3254
- "Happy to be here!": "\u098F\u0996\u09BE\u09A8\u09C7 \u09A5\u09BE\u0995\u09A4\u09C7 \u09AA\u09C7\u09B0\u09C7 \u0986\u09A8\u09A8\u09CD\u09A6\u09BF\u09A4!"
3255
- };
3256
- if (map[s]) {
3257
- return map[s];
3258
- }
3259
- return `\u09AC\u09BE\u0982\u09B2\u09BE ${s}`;
3260
- };
3261
3246
  var ChatMessageItem = ({
3262
3247
  id,
3263
3248
  mine = false,
@@ -3280,31 +3265,24 @@ var ChatMessageItem = ({
3280
3265
  }) => {
3281
3266
  const originalTextRef = React16.useRef(text ?? "");
3282
3267
  const [translated, setTranslated] = React16.useState(false);
3283
- const displayText = translated ? toBanglaDemo(originalTextRef.current) : originalTextRef.current;
3268
+ const displayText = translated ? onTranslate?.(originalTextRef.current) ?? originalTextRef.current : originalTextRef.current;
3284
3269
  const handleTranslateClick = () => {
3285
3270
  setTranslated((v) => !v);
3286
- onTranslate?.();
3287
3271
  };
3288
3272
  return /* @__PURE__ */ jsx("div", { className: clsx3("mb-4", className), "data-msg-id": id, children: /* @__PURE__ */ jsxs("div", { className: clsx3("flex items-end gap-3", mine && "justify-end"), children: [
3289
- !mine && /* @__PURE__ */ jsx("div", { className: `${showStatus ? "mb-5" : "mb-0"}`, children: initialSrc ? /* @__PURE__ */ jsxs("div", { className: "relative h-10 w-10 shrink-0 rounded-full border border-[#F1F1F1]", children: [
3290
- /* @__PURE__ */ jsx(
3291
- "img",
3292
- {
3293
- src: initialSrc,
3294
- alt: "avatar image",
3295
- className: "h-full w-full rounded-full object-cover"
3296
- }
3297
- ),
3298
- /* @__PURE__ */ jsx("span", { className: "absolute bottom-0 right-0 h-[11.25px] w-[11.25px] rounded-full bg-[#328545] ring-1 ring-white" })
3299
- ] }) : /* @__PURE__ */ jsxs(
3273
+ !mine && /* @__PURE__ */ jsx("div", { className: `${showStatus ? "mb-5" : "mb-0"}`, children: initialSrc ? /* @__PURE__ */ jsx("div", { className: "relative h-10 w-10 shrink-0 rounded-full border border-[#F1F1F1]", children: /* @__PURE__ */ jsx(
3274
+ "img",
3275
+ {
3276
+ src: initialSrc,
3277
+ alt: "avatar image",
3278
+ className: "h-full w-full rounded-full object-cover"
3279
+ }
3280
+ ) }) : /* @__PURE__ */ jsx(
3300
3281
  "div",
3301
3282
  {
3302
3283
  className: "relative grid h-10 w-10 shrink-0 place-items-center rounded-full border border-[#f1f1f1] font-semibold text-[#2c2c2c]",
3303
3284
  style: { backgroundColor: avatarBg },
3304
- children: [
3305
- authorInitial,
3306
- /* @__PURE__ */ jsx("span", { className: "absolute bottom-0 right-0 h-[11.25px] w-[11.25px] rounded-full bg-[#328545] ring-1 ring-white" })
3307
- ]
3285
+ children: authorInitial
3308
3286
  }
3309
3287
  ) }),
3310
3288
  /* @__PURE__ */ jsxs("div", { className: clsx3("flex flex-col gap-1 w-full"), children: [
@@ -3707,6 +3685,22 @@ var ChatImagePreviewModal = ({
3707
3685
  ) }) });
3708
3686
  };
3709
3687
  var ChatImagePreviewModal_default = ChatImagePreviewModal;
3688
+
3689
+ // src/utils/theme.ts
3690
+ var GRADIENT_BORDER = "linear-gradient(236.83deg, rgba(51,201,212,0.3) 0.4%, rgba(39,83,251,0.3) 30.28%, rgba(39,83,251,0.3) 50.2%, rgba(39,83,251,0.3) 65.14%, rgba(235,67,255,0.3) 100%)";
3691
+ function getThemeAttr(theme) {
3692
+ if (!theme || theme === "marketplace") return "marketplace";
3693
+ if (theme === "admin") return "admin";
3694
+ return "custom";
3695
+ }
3696
+ function getThemeVars(theme) {
3697
+ if (!theme || theme === "marketplace" || theme === "admin") return {};
3698
+ const vars = {};
3699
+ if (theme.primary) vars["--color-banbox-primary"] = theme.primary;
3700
+ if (theme.primaryActive) vars["--color-banbox-primary-active"] = theme.primaryActive;
3701
+ if (theme.surfaceLow) vars["--color-banbox-surface-container-low"] = theme.surfaceLow;
3702
+ return vars;
3703
+ }
3710
3704
  var baseItem = "flex w-full items-center gap-3 px-3 py-2 text-sm hover:bg-black/5 cursor-pointer";
3711
3705
  var ChatKebabMenu = ({
3712
3706
  pinned,
@@ -3802,21 +3796,7 @@ var avatarBgByInitial = {
3802
3796
  B: "#F0EDEB",
3803
3797
  b: "#F0EDEB"
3804
3798
  };
3805
- var GRADIENT_BORDER = "linear-gradient(236.83deg, rgba(51,201,212,0.3) 0.4%, rgba(39,83,251,0.3) 30.28%, rgba(39,83,251,0.3) 50.2%, rgba(39,83,251,0.3) 65.14%, rgba(235,67,255,0.3) 100%)";
3806
- function getThemeAttr(theme) {
3807
- if (!theme || theme === "marketplace") return "marketplace";
3808
- if (theme === "admin") return "admin";
3809
- return "custom";
3810
- }
3811
- function getThemeVars(theme) {
3812
- if (!theme || theme === "marketplace" || theme === "admin") return {};
3813
- const vars = {};
3814
- if (theme.primary) vars["--color-banbox-primary"] = theme.primary;
3815
- if (theme.primaryActive) vars["--color-banbox-primary-active"] = theme.primaryActive;
3816
- if (theme.surfaceLow) vars["--color-banbox-surface-container-low"] = theme.surfaceLow;
3817
- return vars;
3818
- }
3819
- var InboxPopup = ({ adapter, uiCallbacks, theme }) => {
3799
+ var InboxPopup = ({ adapter, uiCallbacks, theme, hiddenActionKeys }) => {
3820
3800
  const { close, selectThread, selectedThreadId, reference } = useChatUI();
3821
3801
  const { isOpen: isGalleryOpen, closeGallery } = useGallery();
3822
3802
  const [threads, setThreads] = useState(() => adapter.threads.list(reference));
@@ -3870,6 +3850,9 @@ var InboxPopup = ({ adapter, uiCallbacks, theme }) => {
3870
3850
  if (activeId) adapter.threads.markRead?.(activeId);
3871
3851
  }
3872
3852
  }, [activeId, adapter]);
3853
+ useEffect(() => {
3854
+ if (activeId) adapter.threads.markRead?.(activeId);
3855
+ }, []);
3873
3856
  const toRef2 = (m) => ({
3874
3857
  id: m.id,
3875
3858
  author: typeof m.author === "string" ? m.author : "U",
@@ -4041,6 +4024,7 @@ var InboxPopup = ({ adapter, uiCallbacks, theme }) => {
4041
4024
  replyTo,
4042
4025
  clearReply: () => setReplyTo(void 0),
4043
4026
  onAfterSend: () => setRev((v) => v + 1),
4027
+ hiddenActionKeys,
4044
4028
  onSend: (payload) => {
4045
4029
  if (activeId) adapter.messages.send(activeId, payload);
4046
4030
  }
@@ -4092,13 +4076,10 @@ var InboxPopup = ({ adapter, uiCallbacks, theme }) => {
4092
4076
  ] });
4093
4077
  };
4094
4078
  var InboxPopup_default = InboxPopup;
4095
- var GRADIENT_BORDER2 = "linear-gradient(236.83deg, rgba(51,201,212,0.3) 0.4%, rgba(39,83,251,0.3) 30.28%, rgba(39,83,251,0.3) 50.2%, rgba(39,83,251,0.3) 65.14%, rgba(235,67,255,0.3) 100%)";
4096
4079
  function coalesceThreadId(reference, threads) {
4097
- const referenceId = reference?.id;
4098
- if (reference?.kind === "quotation") {
4099
- return threads.find((t) => t.id === "t4")?.id ?? (threads[0]?.id ?? "");
4100
- }
4101
- return referenceId && (threads.find((t) => t.id === referenceId)?.id || threads.find((t) => t.inquiryId === referenceId)?.id) || (threads.length ? threads[0].id : "");
4080
+ if (!reference?.id) return threads[0]?.id ?? "";
4081
+ const refId = reference.id;
4082
+ return threads.find((t) => t.id === refId)?.id ?? threads.find((t) => t.orderId === refId)?.id ?? threads.find((t) => t.inquiryId === refId)?.id ?? threads[0]?.id ?? "";
4102
4083
  }
4103
4084
  function toRef(m) {
4104
4085
  return {
@@ -4111,25 +4092,19 @@ function toRef(m) {
4111
4092
  audio: m.audio
4112
4093
  };
4113
4094
  }
4114
- function getThemeAttr2(theme) {
4115
- if (!theme || theme === "marketplace") return "marketplace";
4116
- if (theme === "admin") return "admin";
4117
- return "custom";
4118
- }
4119
- function getThemeVars2(theme) {
4120
- if (!theme || theme === "marketplace" || theme === "admin") return {};
4121
- const vars = {};
4122
- if (theme.primary) vars["--color-banbox-primary"] = theme.primary;
4123
- if (theme.primaryActive) vars["--color-banbox-primary-active"] = theme.primaryActive;
4124
- if (theme.surfaceLow) vars["--color-banbox-surface-container-low"] = theme.surfaceLow;
4125
- return vars;
4126
- }
4127
- var SinglePopup = ({ adapter, uiCallbacks, theme }) => {
4095
+ var SinglePopup = ({ adapter, uiCallbacks, theme, hiddenActionKeys }) => {
4128
4096
  const { close, reference } = useChatUI();
4129
4097
  const { isOpen: isGalleryOpen, closeGallery } = useGallery();
4130
- const threads = adapter.threads.list(reference);
4098
+ const [threads, setThreads] = React16.useState(() => adapter.threads.list(reference));
4099
+ React16.useEffect(() => {
4100
+ setThreads(adapter.threads.list(reference));
4101
+ const unsub = adapter.threads.subscribe(() => {
4102
+ setThreads(adapter.threads.list(reference));
4103
+ });
4104
+ return unsub;
4105
+ }, [adapter, reference]);
4131
4106
  const initialThreadId = React16.useMemo(
4132
- () => coalesceThreadId(reference, threads),
4107
+ () => coalesceThreadId(reference, adapter.threads.list(reference)),
4133
4108
  // eslint-disable-next-line react-hooks/exhaustive-deps
4134
4109
  [reference]
4135
4110
  );
@@ -4193,12 +4168,12 @@ var SinglePopup = ({ adapter, uiCallbacks, theme }) => {
4193
4168
  {
4194
4169
  role: "dialog",
4195
4170
  "aria-modal": "true",
4196
- "data-theme": getThemeAttr2(theme),
4171
+ "data-theme": getThemeAttr(theme),
4197
4172
  className: "banbox-chat-root relative h-[650px] w-[450px] rounded-[20px] p-[2px]",
4198
4173
  style: {
4199
4174
  boxShadow: "0px 2px 12px 0px #3B33331A",
4200
- background: GRADIENT_BORDER2,
4201
- ...getThemeVars2(theme)
4175
+ background: GRADIENT_BORDER,
4176
+ ...getThemeVars(theme)
4202
4177
  },
4203
4178
  initial: { x: "110%" },
4204
4179
  animate: { x: 0 },
@@ -4297,6 +4272,7 @@ var SinglePopup = ({ adapter, uiCallbacks, theme }) => {
4297
4272
  replyTo,
4298
4273
  clearReply: () => setReplyTo(void 0),
4299
4274
  onAfterSend: handleAfterSend,
4275
+ hiddenActionKeys,
4300
4276
  onSend: (payload) => {
4301
4277
  if (activeId) adapter.messages.send(activeId, payload);
4302
4278
  }
@@ -4319,7 +4295,7 @@ var SinglePopup = ({ adapter, uiCallbacks, theme }) => {
4319
4295
  ] });
4320
4296
  };
4321
4297
  var SinglePopup_default = SinglePopup;
4322
- function ChatRoot({ adapter, uiCallbacks, theme }) {
4298
+ function ChatRoot({ adapter, uiCallbacks, theme, hiddenActionKeys }) {
4323
4299
  const { isOpen, variant } = useChatUI();
4324
4300
  useDisableBodyScroll(isOpen);
4325
4301
  if (typeof window === "undefined") {
@@ -4332,7 +4308,8 @@ function ChatRoot({ adapter, uiCallbacks, theme }) {
4332
4308
  {
4333
4309
  adapter,
4334
4310
  uiCallbacks,
4335
- theme
4311
+ theme,
4312
+ hiddenActionKeys
4336
4313
  },
4337
4314
  "inbox"
4338
4315
  ) : /* @__PURE__ */ jsx(
@@ -4340,7 +4317,8 @@ function ChatRoot({ adapter, uiCallbacks, theme }) {
4340
4317
  {
4341
4318
  adapter,
4342
4319
  uiCallbacks,
4343
- theme
4320
+ theme,
4321
+ hiddenActionKeys
4344
4322
  },
4345
4323
  "single"
4346
4324
  )) }) }),