@better-zap/react 0.0.4 → 0.1.0
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.cjs +85 -61
- package/dist/index.mjs +85 -61
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -28,6 +28,7 @@ let tailwind_merge = require("tailwind-merge");
|
|
|
28
28
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
29
29
|
let _hugeicons_react = require("@hugeicons/react");
|
|
30
30
|
let _hugeicons_core_free_icons = require("@hugeicons/core-free-icons");
|
|
31
|
+
let _legendapp_list_react = require("@legendapp/list/react");
|
|
31
32
|
let class_variance_authority = require("class-variance-authority");
|
|
32
33
|
let better_zap = require("better-zap");
|
|
33
34
|
//#region src/utils.ts
|
|
@@ -256,70 +257,80 @@ function MessageViewHeader({ conversation, onBack, onInfoClick, className }) {
|
|
|
256
257
|
})]
|
|
257
258
|
});
|
|
258
259
|
}
|
|
259
|
-
const
|
|
260
|
+
const MessageViewScrollContext = react.default.createContext(null);
|
|
260
261
|
function MessageViewContent({ children, autoScroll = true, onScrollTop, className, ...props }) {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
if (prevScrollHeight > 0 && newScrollHeight > prevScrollHeight) {
|
|
272
|
-
const addedHeight = newScrollHeight - prevScrollHeight;
|
|
273
|
-
if (el.scrollTop < SCROLL_TOP_THRESHOLD + addedHeight) el.scrollTop = addedHeight;
|
|
274
|
-
}
|
|
275
|
-
prevScrollHeightRef.current = newScrollHeight;
|
|
276
|
-
});
|
|
277
|
-
const handleScroll = (0, react.useCallback)(() => {
|
|
278
|
-
const el = scrollRef.current;
|
|
279
|
-
if (!el || !onScrollTop) return;
|
|
280
|
-
if (el.scrollTop <= SCROLL_TOP_THRESHOLD) onScrollTop();
|
|
281
|
-
}, [onScrollTop]);
|
|
282
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
283
|
-
ref: scrollRef,
|
|
284
|
-
className: cn("flex flex-1 flex-col overflow-y-auto p-4 pb-0 chat-scrollbar", className),
|
|
285
|
-
onScroll: handleScroll,
|
|
286
|
-
...props,
|
|
287
|
-
children
|
|
262
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MessageViewScrollContext.Provider, {
|
|
263
|
+
value: {
|
|
264
|
+
autoScroll,
|
|
265
|
+
onScrollTop
|
|
266
|
+
},
|
|
267
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
268
|
+
className: cn("flex min-h-0 flex-1 flex-col p-4 pb-0", className),
|
|
269
|
+
...props,
|
|
270
|
+
children
|
|
271
|
+
})
|
|
288
272
|
});
|
|
289
273
|
}
|
|
290
274
|
function MessageList({ messages, renderMessageLabel, className }) {
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
275
|
+
const scrollContext = (0, react.useContext)(MessageViewScrollContext);
|
|
276
|
+
const autoScroll = scrollContext?.autoScroll ?? true;
|
|
277
|
+
const onScrollTop = scrollContext?.onScrollTop;
|
|
278
|
+
const { items, stickyHeaderIndices } = (0, react.useMemo)(() => {
|
|
279
|
+
const itemsNew = [];
|
|
280
|
+
const stickyHeaderIndicesNew = [];
|
|
281
|
+
let currentDate = null;
|
|
294
282
|
messages.forEach((msg) => {
|
|
295
283
|
const displayDate = getDisplayDate(msg.sentAt);
|
|
296
|
-
if (
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
284
|
+
if (currentDate !== displayDate) {
|
|
285
|
+
currentDate = displayDate;
|
|
286
|
+
stickyHeaderIndicesNew.push(itemsNew.length);
|
|
287
|
+
itemsNew.push({
|
|
288
|
+
type: "date",
|
|
289
|
+
id: `date:${displayDate}`,
|
|
290
|
+
date: displayDate
|
|
291
|
+
});
|
|
302
292
|
}
|
|
303
|
-
|
|
293
|
+
itemsNew.push({
|
|
294
|
+
type: "message",
|
|
295
|
+
id: msg.id,
|
|
296
|
+
message: msg
|
|
297
|
+
});
|
|
304
298
|
});
|
|
305
|
-
return
|
|
299
|
+
return {
|
|
300
|
+
items: itemsNew,
|
|
301
|
+
stickyHeaderIndices: stickyHeaderIndicesNew
|
|
302
|
+
};
|
|
306
303
|
}, [messages]);
|
|
307
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
304
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_legendapp_list_react.LegendList, {
|
|
305
|
+
alignItemsAtEnd: true,
|
|
306
|
+
className: cn("chat-scrollbar", className),
|
|
307
|
+
contentContainerStyle: { paddingBottom: 16 },
|
|
308
|
+
data: items,
|
|
309
|
+
estimatedItemSize: 72,
|
|
310
|
+
getItemType: (item) => item.type,
|
|
311
|
+
initialScrollAtEnd: autoScroll,
|
|
312
|
+
keyExtractor: (item) => item.id,
|
|
313
|
+
maintainScrollAtEnd: autoScroll,
|
|
314
|
+
maintainVisibleContentPosition: true,
|
|
315
|
+
onStartReached: onScrollTop ? () => onScrollTop() : void 0,
|
|
316
|
+
onStartReachedThreshold: .1,
|
|
317
|
+
recycleItems: true,
|
|
318
|
+
renderItem: ({ item }) => item.type === "date" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DateDivider, { date: item.date }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MessageBubble, {
|
|
319
|
+
content: item.message.content || "",
|
|
320
|
+
sender: item.message.direction === "incoming" ? "user" : "bot",
|
|
321
|
+
timestamp: new Date(item.message.sentAt).toLocaleTimeString("pt-BR", {
|
|
322
|
+
hour: "2-digit",
|
|
323
|
+
minute: "2-digit"
|
|
324
|
+
}),
|
|
325
|
+
status: item.message.status,
|
|
326
|
+
templateName: item.message.templateName || void 0,
|
|
327
|
+
label: renderMessageLabel?.(item.message)
|
|
328
|
+
}),
|
|
329
|
+
stickyHeaderIndices,
|
|
330
|
+
style: {
|
|
331
|
+
height: "100%",
|
|
332
|
+
minHeight: 0
|
|
333
|
+
}
|
|
323
334
|
});
|
|
324
335
|
}
|
|
325
336
|
function DateDivider({ date }) {
|
|
@@ -446,7 +457,7 @@ function ConversationList({ conversations, isLoading, isError, selectedConversat
|
|
|
446
457
|
unreadCount: unreadConversationsCount
|
|
447
458
|
}),
|
|
448
459
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
449
|
-
className: "
|
|
460
|
+
className: "min-h-0 flex-1",
|
|
450
461
|
children: isLoading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
451
462
|
className: "flex items-center justify-center h-full text-sm text-[#667781]",
|
|
452
463
|
children: "Carregando..."
|
|
@@ -462,11 +473,24 @@ function ConversationList({ conversations, isLoading, isError, selectedConversat
|
|
|
462
473
|
className: "text-sm",
|
|
463
474
|
children: "Nenhuma conversa encontrada"
|
|
464
475
|
})]
|
|
465
|
-
}) :
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
476
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_legendapp_list_react.LegendList, {
|
|
477
|
+
className: "chat-scrollbar",
|
|
478
|
+
data: filtered,
|
|
479
|
+
estimatedItemSize: 72,
|
|
480
|
+
extraData: selectedConversationId,
|
|
481
|
+
getFixedItemSize: () => 72,
|
|
482
|
+
keyExtractor: (conversation) => conversation.id,
|
|
483
|
+
recycleItems: true,
|
|
484
|
+
renderItem: ({ item: conversation }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConversationItem, {
|
|
485
|
+
conversation,
|
|
486
|
+
isSelected: selectedConversationId === conversation.id,
|
|
487
|
+
onClick: () => handleSelect(conversation.id)
|
|
488
|
+
}),
|
|
489
|
+
style: {
|
|
490
|
+
height: "100%",
|
|
491
|
+
overflowX: "hidden"
|
|
492
|
+
}
|
|
493
|
+
})
|
|
470
494
|
})
|
|
471
495
|
]
|
|
472
496
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -4,6 +4,7 @@ import { twMerge } from "tailwind-merge";
|
|
|
4
4
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
import { HugeiconsIcon } from "@hugeicons/react";
|
|
6
6
|
import { Add01Icon, ArrowLeft02Icon, Clock01Icon, InformationCircleIcon, Message01Icon, Mic01Icon, Search01Icon, Sent02Icon, SmileIcon, UserIcon } from "@hugeicons/core-free-icons";
|
|
7
|
+
import { LegendList } from "@legendapp/list/react";
|
|
7
8
|
import { cva } from "class-variance-authority";
|
|
8
9
|
import { resolveConversationFreeformMessageWindow } from "better-zap";
|
|
9
10
|
//#region src/utils.ts
|
|
@@ -232,70 +233,80 @@ function MessageViewHeader({ conversation, onBack, onInfoClick, className }) {
|
|
|
232
233
|
})]
|
|
233
234
|
});
|
|
234
235
|
}
|
|
235
|
-
const
|
|
236
|
+
const MessageViewScrollContext = React.createContext(null);
|
|
236
237
|
function MessageViewContent({ children, autoScroll = true, onScrollTop, className, ...props }) {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
if (prevScrollHeight > 0 && newScrollHeight > prevScrollHeight) {
|
|
248
|
-
const addedHeight = newScrollHeight - prevScrollHeight;
|
|
249
|
-
if (el.scrollTop < SCROLL_TOP_THRESHOLD + addedHeight) el.scrollTop = addedHeight;
|
|
250
|
-
}
|
|
251
|
-
prevScrollHeightRef.current = newScrollHeight;
|
|
252
|
-
});
|
|
253
|
-
const handleScroll = useCallback(() => {
|
|
254
|
-
const el = scrollRef.current;
|
|
255
|
-
if (!el || !onScrollTop) return;
|
|
256
|
-
if (el.scrollTop <= SCROLL_TOP_THRESHOLD) onScrollTop();
|
|
257
|
-
}, [onScrollTop]);
|
|
258
|
-
return /* @__PURE__ */ jsx("div", {
|
|
259
|
-
ref: scrollRef,
|
|
260
|
-
className: cn("flex flex-1 flex-col overflow-y-auto p-4 pb-0 chat-scrollbar", className),
|
|
261
|
-
onScroll: handleScroll,
|
|
262
|
-
...props,
|
|
263
|
-
children
|
|
238
|
+
return /* @__PURE__ */ jsx(MessageViewScrollContext.Provider, {
|
|
239
|
+
value: {
|
|
240
|
+
autoScroll,
|
|
241
|
+
onScrollTop
|
|
242
|
+
},
|
|
243
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
244
|
+
className: cn("flex min-h-0 flex-1 flex-col p-4 pb-0", className),
|
|
245
|
+
...props,
|
|
246
|
+
children
|
|
247
|
+
})
|
|
264
248
|
});
|
|
265
249
|
}
|
|
266
250
|
function MessageList({ messages, renderMessageLabel, className }) {
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
|
|
251
|
+
const scrollContext = useContext(MessageViewScrollContext);
|
|
252
|
+
const autoScroll = scrollContext?.autoScroll ?? true;
|
|
253
|
+
const onScrollTop = scrollContext?.onScrollTop;
|
|
254
|
+
const { items, stickyHeaderIndices } = useMemo(() => {
|
|
255
|
+
const itemsNew = [];
|
|
256
|
+
const stickyHeaderIndicesNew = [];
|
|
257
|
+
let currentDate = null;
|
|
270
258
|
messages.forEach((msg) => {
|
|
271
259
|
const displayDate = getDisplayDate(msg.sentAt);
|
|
272
|
-
if (
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
260
|
+
if (currentDate !== displayDate) {
|
|
261
|
+
currentDate = displayDate;
|
|
262
|
+
stickyHeaderIndicesNew.push(itemsNew.length);
|
|
263
|
+
itemsNew.push({
|
|
264
|
+
type: "date",
|
|
265
|
+
id: `date:${displayDate}`,
|
|
266
|
+
date: displayDate
|
|
267
|
+
});
|
|
278
268
|
}
|
|
279
|
-
|
|
269
|
+
itemsNew.push({
|
|
270
|
+
type: "message",
|
|
271
|
+
id: msg.id,
|
|
272
|
+
message: msg
|
|
273
|
+
});
|
|
280
274
|
});
|
|
281
|
-
return
|
|
275
|
+
return {
|
|
276
|
+
items: itemsNew,
|
|
277
|
+
stickyHeaderIndices: stickyHeaderIndicesNew
|
|
278
|
+
};
|
|
282
279
|
}, [messages]);
|
|
283
|
-
return /* @__PURE__ */ jsx(
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
280
|
+
return /* @__PURE__ */ jsx(LegendList, {
|
|
281
|
+
alignItemsAtEnd: true,
|
|
282
|
+
className: cn("chat-scrollbar", className),
|
|
283
|
+
contentContainerStyle: { paddingBottom: 16 },
|
|
284
|
+
data: items,
|
|
285
|
+
estimatedItemSize: 72,
|
|
286
|
+
getItemType: (item) => item.type,
|
|
287
|
+
initialScrollAtEnd: autoScroll,
|
|
288
|
+
keyExtractor: (item) => item.id,
|
|
289
|
+
maintainScrollAtEnd: autoScroll,
|
|
290
|
+
maintainVisibleContentPosition: true,
|
|
291
|
+
onStartReached: onScrollTop ? () => onScrollTop() : void 0,
|
|
292
|
+
onStartReachedThreshold: .1,
|
|
293
|
+
recycleItems: true,
|
|
294
|
+
renderItem: ({ item }) => item.type === "date" ? /* @__PURE__ */ jsx(DateDivider, { date: item.date }) : /* @__PURE__ */ jsx(MessageBubble, {
|
|
295
|
+
content: item.message.content || "",
|
|
296
|
+
sender: item.message.direction === "incoming" ? "user" : "bot",
|
|
297
|
+
timestamp: new Date(item.message.sentAt).toLocaleTimeString("pt-BR", {
|
|
298
|
+
hour: "2-digit",
|
|
299
|
+
minute: "2-digit"
|
|
300
|
+
}),
|
|
301
|
+
status: item.message.status,
|
|
302
|
+
templateName: item.message.templateName || void 0,
|
|
303
|
+
label: renderMessageLabel?.(item.message)
|
|
304
|
+
}),
|
|
305
|
+
stickyHeaderIndices,
|
|
306
|
+
style: {
|
|
307
|
+
height: "100%",
|
|
308
|
+
minHeight: 0
|
|
309
|
+
}
|
|
299
310
|
});
|
|
300
311
|
}
|
|
301
312
|
function DateDivider({ date }) {
|
|
@@ -422,7 +433,7 @@ function ConversationList({ conversations, isLoading, isError, selectedConversat
|
|
|
422
433
|
unreadCount: unreadConversationsCount
|
|
423
434
|
}),
|
|
424
435
|
/* @__PURE__ */ jsx("div", {
|
|
425
|
-
className: "
|
|
436
|
+
className: "min-h-0 flex-1",
|
|
426
437
|
children: isLoading ? /* @__PURE__ */ jsx("div", {
|
|
427
438
|
className: "flex items-center justify-center h-full text-sm text-[#667781]",
|
|
428
439
|
children: "Carregando..."
|
|
@@ -438,11 +449,24 @@ function ConversationList({ conversations, isLoading, isError, selectedConversat
|
|
|
438
449
|
className: "text-sm",
|
|
439
450
|
children: "Nenhuma conversa encontrada"
|
|
440
451
|
})]
|
|
441
|
-
}) :
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
452
|
+
}) : /* @__PURE__ */ jsx(LegendList, {
|
|
453
|
+
className: "chat-scrollbar",
|
|
454
|
+
data: filtered,
|
|
455
|
+
estimatedItemSize: 72,
|
|
456
|
+
extraData: selectedConversationId,
|
|
457
|
+
getFixedItemSize: () => 72,
|
|
458
|
+
keyExtractor: (conversation) => conversation.id,
|
|
459
|
+
recycleItems: true,
|
|
460
|
+
renderItem: ({ item: conversation }) => /* @__PURE__ */ jsx(ConversationItem, {
|
|
461
|
+
conversation,
|
|
462
|
+
isSelected: selectedConversationId === conversation.id,
|
|
463
|
+
onClick: () => handleSelect(conversation.id)
|
|
464
|
+
}),
|
|
465
|
+
style: {
|
|
466
|
+
height: "100%",
|
|
467
|
+
overflowX: "hidden"
|
|
468
|
+
}
|
|
469
|
+
})
|
|
446
470
|
})
|
|
447
471
|
]
|
|
448
472
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-zap/react",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "React components for Better Zap.",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"type": "module",
|
|
@@ -33,10 +33,11 @@
|
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@hugeicons/core-free-icons": "^3.1.1",
|
|
35
35
|
"@hugeicons/react": "^1.1.4",
|
|
36
|
+
"@legendapp/list": "^3.1.1",
|
|
36
37
|
"class-variance-authority": "^0.7.1",
|
|
37
38
|
"clsx": "^2.1.1",
|
|
38
39
|
"tailwind-merge": "^3.0.0",
|
|
39
|
-
"better-zap": "0.0
|
|
40
|
+
"better-zap": "0.1.0"
|
|
40
41
|
},
|
|
41
42
|
"peerDependencies": {
|
|
42
43
|
"react": "^19.0.0",
|