@better-zap/react 0.0.3 → 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 +173 -106
- package/dist/index.d.cts +23 -7
- package/dist/index.d.mts +23 -7
- package/dist/index.mjs +172 -107
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -28,14 +28,30 @@ 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
|
-
//#region src/
|
|
34
|
+
//#region src/utils.ts
|
|
34
35
|
function cn(...inputs) {
|
|
35
36
|
return (0, tailwind_merge.twMerge)((0, clsx.clsx)(inputs));
|
|
36
37
|
}
|
|
38
|
+
function getDisplayDate(dateStr) {
|
|
39
|
+
const dateObj = new Date(dateStr);
|
|
40
|
+
const now = /* @__PURE__ */ new Date();
|
|
41
|
+
const isToday = dateObj.toDateString() === now.toDateString();
|
|
42
|
+
const yesterday = new Date(now);
|
|
43
|
+
yesterday.setDate(yesterday.getDate() - 1);
|
|
44
|
+
const isYesterday = dateObj.toDateString() === yesterday.toDateString();
|
|
45
|
+
if (isToday) return "HOJE";
|
|
46
|
+
else if (isYesterday) return "ONTEM";
|
|
47
|
+
else return dateObj.toLocaleDateString("pt-BR", {
|
|
48
|
+
day: "2-digit",
|
|
49
|
+
month: "2-digit",
|
|
50
|
+
year: "numeric"
|
|
51
|
+
});
|
|
52
|
+
}
|
|
37
53
|
//#endregion
|
|
38
|
-
//#region src/
|
|
54
|
+
//#region src/whatsapp-dashboard.tsx
|
|
39
55
|
const MOBILE_BREAKPOINT = 1024;
|
|
40
56
|
function useIsMobile() {
|
|
41
57
|
const [isMobile, setIsMobile] = (0, react.useState)(false);
|
|
@@ -76,7 +92,7 @@ function WhatsappDashboard({ children, className, defaultMobileView = "list", ..
|
|
|
76
92
|
});
|
|
77
93
|
}
|
|
78
94
|
//#endregion
|
|
79
|
-
//#region src/
|
|
95
|
+
//#region src/message-bubble.tsx
|
|
80
96
|
const bubbleVariants = (0, class_variance_authority.cva)("relative shadow-[0_1px_0.5px_rgba(11,20,26,0.13)] rounded-lg px-3 py-2 max-w-[65%]", { variants: { variant: {
|
|
81
97
|
outgoing: "bg-green-100 text-green-900 rounded-tr-none",
|
|
82
98
|
incoming: "bg-gray-100 text-gray-900 rounded-tl-none",
|
|
@@ -174,24 +190,7 @@ function FormattedMessage({ text }) {
|
|
|
174
190
|
}) });
|
|
175
191
|
}
|
|
176
192
|
//#endregion
|
|
177
|
-
//#region src/
|
|
178
|
-
function getDisplayDate(dateStr) {
|
|
179
|
-
const dateObj = new Date(dateStr);
|
|
180
|
-
const now = /* @__PURE__ */ new Date();
|
|
181
|
-
const isToday = dateObj.toDateString() === now.toDateString();
|
|
182
|
-
const yesterday = new Date(now);
|
|
183
|
-
yesterday.setDate(yesterday.getDate() - 1);
|
|
184
|
-
const isYesterday = dateObj.toDateString() === yesterday.toDateString();
|
|
185
|
-
if (isToday) return "HOJE";
|
|
186
|
-
else if (isYesterday) return "ONTEM";
|
|
187
|
-
else return dateObj.toLocaleDateString("pt-BR", {
|
|
188
|
-
day: "2-digit",
|
|
189
|
-
month: "2-digit",
|
|
190
|
-
year: "numeric"
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
//#endregion
|
|
194
|
-
//#region src/react/message-view.tsx
|
|
193
|
+
//#region src/message-view.tsx
|
|
195
194
|
function MessageView({ children, className, ...props }) {
|
|
196
195
|
const { isMobile, mobileView } = useWhatsappDashboard();
|
|
197
196
|
const hasContent = react.default.Children.count(children) > 0;
|
|
@@ -258,70 +257,80 @@ function MessageViewHeader({ conversation, onBack, onInfoClick, className }) {
|
|
|
258
257
|
})]
|
|
259
258
|
});
|
|
260
259
|
}
|
|
261
|
-
const
|
|
260
|
+
const MessageViewScrollContext = react.default.createContext(null);
|
|
262
261
|
function MessageViewContent({ children, autoScroll = true, onScrollTop, className, ...props }) {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
if (prevScrollHeight > 0 && newScrollHeight > prevScrollHeight) {
|
|
274
|
-
const addedHeight = newScrollHeight - prevScrollHeight;
|
|
275
|
-
if (el.scrollTop < SCROLL_TOP_THRESHOLD + addedHeight) el.scrollTop = addedHeight;
|
|
276
|
-
}
|
|
277
|
-
prevScrollHeightRef.current = newScrollHeight;
|
|
278
|
-
});
|
|
279
|
-
const handleScroll = (0, react.useCallback)(() => {
|
|
280
|
-
const el = scrollRef.current;
|
|
281
|
-
if (!el || !onScrollTop) return;
|
|
282
|
-
if (el.scrollTop <= SCROLL_TOP_THRESHOLD) onScrollTop();
|
|
283
|
-
}, [onScrollTop]);
|
|
284
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
285
|
-
ref: scrollRef,
|
|
286
|
-
className: cn("flex flex-1 flex-col overflow-y-auto p-4 pb-0 chat-scrollbar", className),
|
|
287
|
-
onScroll: handleScroll,
|
|
288
|
-
...props,
|
|
289
|
-
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
|
+
})
|
|
290
272
|
});
|
|
291
273
|
}
|
|
292
274
|
function MessageList({ messages, renderMessageLabel, className }) {
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
|
|
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;
|
|
296
282
|
messages.forEach((msg) => {
|
|
297
283
|
const displayDate = getDisplayDate(msg.sentAt);
|
|
298
|
-
if (
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
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
|
+
});
|
|
304
292
|
}
|
|
305
|
-
|
|
293
|
+
itemsNew.push({
|
|
294
|
+
type: "message",
|
|
295
|
+
id: msg.id,
|
|
296
|
+
message: msg
|
|
297
|
+
});
|
|
306
298
|
});
|
|
307
|
-
return
|
|
299
|
+
return {
|
|
300
|
+
items: itemsNew,
|
|
301
|
+
stickyHeaderIndices: stickyHeaderIndicesNew
|
|
302
|
+
};
|
|
308
303
|
}, [messages]);
|
|
309
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
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
|
+
}
|
|
325
334
|
});
|
|
326
335
|
}
|
|
327
336
|
function DateDivider({ date }) {
|
|
@@ -368,7 +377,7 @@ function MessageViewEmpty({ className, ...props }) {
|
|
|
368
377
|
});
|
|
369
378
|
}
|
|
370
379
|
//#endregion
|
|
371
|
-
//#region src/
|
|
380
|
+
//#region src/conversation-search.tsx
|
|
372
381
|
function ConversationSearch({ value, onChange, className }) {
|
|
373
382
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
374
383
|
className: cn("border-b border-[#e9edef] shrink-0 p-2", className),
|
|
@@ -389,11 +398,46 @@ function ConversationSearch({ value, onChange, className }) {
|
|
|
389
398
|
});
|
|
390
399
|
}
|
|
391
400
|
//#endregion
|
|
392
|
-
//#region src/
|
|
401
|
+
//#region src/conversation-filter-chips.tsx
|
|
402
|
+
const chips = [{
|
|
403
|
+
label: "Tudo",
|
|
404
|
+
value: "all"
|
|
405
|
+
}, {
|
|
406
|
+
label: "Não lidas",
|
|
407
|
+
value: "unread"
|
|
408
|
+
}];
|
|
409
|
+
function ConversationFilterChips({ value, onValueChange, unreadCount = 0, className }) {
|
|
410
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
411
|
+
className: cn("flex items-center gap-2 px-3 py-3", className),
|
|
412
|
+
children: chips.map((chip) => {
|
|
413
|
+
const isActive = chip.value === value;
|
|
414
|
+
const showCount = chip.value === "unread" && unreadCount > 0;
|
|
415
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
416
|
+
type: "button",
|
|
417
|
+
onClick: () => onValueChange(chip.value),
|
|
418
|
+
"aria-pressed": isActive,
|
|
419
|
+
className: cn("inline-flex h-8 items-center rounded-full border px-4 text-[15px] font-medium transition-colors", isActive ? "border-[#b8e6c1] bg-[#e7fce3] text-[#017561]" : "border-[#d1d7db] bg-white text-[#54656f] hover:bg-[#f5f6f6]"),
|
|
420
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: chip.label }), showCount ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
421
|
+
className: "ml-1",
|
|
422
|
+
children: unreadCount
|
|
423
|
+
}) : null]
|
|
424
|
+
}, chip.value);
|
|
425
|
+
})
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
//#endregion
|
|
429
|
+
//#region src/conversation-list.tsx
|
|
393
430
|
function ConversationList({ conversations, isLoading, isError, selectedConversationId, onSelect, className }) {
|
|
394
431
|
const { isMobile, mobileView, setMobileView } = useWhatsappDashboard();
|
|
395
432
|
const [search, setSearch] = (0, react.useState)("");
|
|
396
|
-
const
|
|
433
|
+
const [filter, setFilter] = (0, react.useState)("all");
|
|
434
|
+
const normalizedSearch = search.trim().toLowerCase();
|
|
435
|
+
const unreadConversationsCount = conversations.filter((c) => c.unreadCount > 0).length;
|
|
436
|
+
const filtered = conversations.filter((conversation) => {
|
|
437
|
+
const matchesSearch = normalizedSearch.length === 0 || conversation.phone.toLowerCase().includes(normalizedSearch) || conversation.contactName?.toLowerCase().includes(normalizedSearch);
|
|
438
|
+
const matchesFilter = filter === "all" || conversation.unreadCount > 0;
|
|
439
|
+
return matchesSearch && matchesFilter;
|
|
440
|
+
});
|
|
397
441
|
const handleSelect = (id) => {
|
|
398
442
|
onSelect(id);
|
|
399
443
|
setMobileView("chat");
|
|
@@ -402,32 +446,53 @@ function ConversationList({ conversations, isLoading, isError, selectedConversat
|
|
|
402
446
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
403
447
|
className: cn("flex flex-col h-full bg-white border-r border-[#e9edef]", isMobile ? "w-full" : "min-w-[320px] max-w-105", className),
|
|
404
448
|
style: isVisible ? void 0 : { display: "none" },
|
|
405
|
-
children: [
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
449
|
+
children: [
|
|
450
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConversationSearch, {
|
|
451
|
+
value: search,
|
|
452
|
+
onChange: setSearch
|
|
453
|
+
}),
|
|
454
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConversationFilterChips, {
|
|
455
|
+
value: filter,
|
|
456
|
+
onValueChange: setFilter,
|
|
457
|
+
unreadCount: unreadConversationsCount
|
|
458
|
+
}),
|
|
459
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
460
|
+
className: "min-h-0 flex-1",
|
|
461
|
+
children: isLoading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
462
|
+
className: "flex items-center justify-center h-full text-sm text-[#667781]",
|
|
463
|
+
children: "Carregando..."
|
|
464
|
+
}) : isError ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
465
|
+
className: "flex items-center justify-center h-full text-sm text-red-500",
|
|
466
|
+
children: "Erro ao carregar conversas"
|
|
467
|
+
}) : filtered.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
468
|
+
className: "flex flex-col items-center justify-center h-full gap-2 text-[#667781]",
|
|
469
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_hugeicons_react.HugeiconsIcon, {
|
|
470
|
+
icon: _hugeicons_core_free_icons.Message01Icon,
|
|
471
|
+
size: 32
|
|
472
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
473
|
+
className: "text-sm",
|
|
474
|
+
children: "Nenhuma conversa encontrada"
|
|
475
|
+
})]
|
|
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
|
+
})
|
|
494
|
+
})
|
|
495
|
+
]
|
|
431
496
|
});
|
|
432
497
|
}
|
|
433
498
|
function ConversationItem({ conversation, isSelected, onClick }) {
|
|
@@ -490,7 +555,7 @@ function formatTime(dateStr) {
|
|
|
490
555
|
}
|
|
491
556
|
}
|
|
492
557
|
//#endregion
|
|
493
|
-
//#region src/
|
|
558
|
+
//#region src/message-input.tsx
|
|
494
559
|
function MessageInput({ onSend, conversation, messages, disabled, placeholder = "Digite uma mensagem", className, contextWindowOpen = true }) {
|
|
495
560
|
const [text, setText] = (0, react.useState)("");
|
|
496
561
|
const [isSending, setIsSending] = (0, react.useState)(false);
|
|
@@ -605,6 +670,7 @@ function MessageInput({ onSend, conversation, messages, disabled, placeholder =
|
|
|
605
670
|
});
|
|
606
671
|
}
|
|
607
672
|
//#endregion
|
|
673
|
+
exports.ConversationFilterChips = ConversationFilterChips;
|
|
608
674
|
exports.ConversationItem = ConversationItem;
|
|
609
675
|
exports.ConversationList = ConversationList;
|
|
610
676
|
exports.FormattedMessage = FormattedMessage;
|
|
@@ -617,4 +683,5 @@ exports.MessageViewEmpty = MessageViewEmpty;
|
|
|
617
683
|
exports.MessageViewHeader = MessageViewHeader;
|
|
618
684
|
exports.WhatsappDashboard = WhatsappDashboard;
|
|
619
685
|
exports.cn = cn;
|
|
686
|
+
exports.getDisplayDate = getDisplayDate;
|
|
620
687
|
exports.useWhatsappDashboard = useWhatsappDashboard;
|
package/dist/index.d.cts
CHANGED
|
@@ -3,7 +3,7 @@ import React from "react";
|
|
|
3
3
|
import { Conversation, Conversation as Conversation$1, ConversationRecord, FreeformMessageWindow, UIMessage, UIMessage as UIMessage$1, UIMessageStatus, UIMessageStatus as UIMessageStatus$1 } from "better-zap";
|
|
4
4
|
import { ClassValue } from "clsx";
|
|
5
5
|
|
|
6
|
-
//#region src/
|
|
6
|
+
//#region src/whatsapp-dashboard.d.ts
|
|
7
7
|
type MobileView = "list" | "chat";
|
|
8
8
|
interface WhatsappDashboardContextValue {
|
|
9
9
|
isMobile: boolean;
|
|
@@ -22,7 +22,7 @@ declare function WhatsappDashboard({
|
|
|
22
22
|
...props
|
|
23
23
|
}: WhatsappDashboardProps): react_jsx_runtime0.JSX.Element;
|
|
24
24
|
//#endregion
|
|
25
|
-
//#region src/
|
|
25
|
+
//#region src/message-view.d.ts
|
|
26
26
|
interface MessageViewProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
27
27
|
children?: React.ReactNode;
|
|
28
28
|
}
|
|
@@ -71,7 +71,7 @@ declare function MessageViewEmpty({
|
|
|
71
71
|
...props
|
|
72
72
|
}: React.HTMLAttributes<HTMLDivElement>): react_jsx_runtime0.JSX.Element;
|
|
73
73
|
//#endregion
|
|
74
|
-
//#region src/
|
|
74
|
+
//#region src/message-bubble.d.ts
|
|
75
75
|
interface MessageBubbleProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
76
76
|
content: string;
|
|
77
77
|
sender: "user" | "bot";
|
|
@@ -96,7 +96,7 @@ declare function FormattedMessage({
|
|
|
96
96
|
text: string;
|
|
97
97
|
}): react_jsx_runtime0.JSX.Element | null;
|
|
98
98
|
//#endregion
|
|
99
|
-
//#region src/
|
|
99
|
+
//#region src/conversation-list.d.ts
|
|
100
100
|
interface ConversationListProps {
|
|
101
101
|
conversations: Conversation$1[];
|
|
102
102
|
isLoading: boolean;
|
|
@@ -124,10 +124,26 @@ declare function ConversationItem({
|
|
|
124
124
|
onClick
|
|
125
125
|
}: ConversationItemProps): react_jsx_runtime0.JSX.Element;
|
|
126
126
|
//#endregion
|
|
127
|
-
//#region src/
|
|
127
|
+
//#region src/conversation-filter-chips.d.ts
|
|
128
|
+
type ConversationFilterValue = "all" | "unread";
|
|
129
|
+
interface ConversationFilterChipsProps {
|
|
130
|
+
value: ConversationFilterValue;
|
|
131
|
+
onValueChange: (value: ConversationFilterValue) => void;
|
|
132
|
+
unreadCount?: number;
|
|
133
|
+
className?: string;
|
|
134
|
+
}
|
|
135
|
+
declare function ConversationFilterChips({
|
|
136
|
+
value,
|
|
137
|
+
onValueChange,
|
|
138
|
+
unreadCount,
|
|
139
|
+
className
|
|
140
|
+
}: ConversationFilterChipsProps): react_jsx_runtime0.JSX.Element;
|
|
141
|
+
//#endregion
|
|
142
|
+
//#region src/utils.d.ts
|
|
128
143
|
declare function cn(...inputs: ClassValue[]): string;
|
|
144
|
+
declare function getDisplayDate(dateStr: string): string;
|
|
129
145
|
//#endregion
|
|
130
|
-
//#region src/
|
|
146
|
+
//#region src/message-input.d.ts
|
|
131
147
|
interface MessageInputProps {
|
|
132
148
|
onSend: (text: string) => void | Promise<void>;
|
|
133
149
|
conversation?: Conversation$1 | null;
|
|
@@ -148,4 +164,4 @@ declare function MessageInput({
|
|
|
148
164
|
contextWindowOpen
|
|
149
165
|
}: MessageInputProps): react_jsx_runtime0.JSX.Element;
|
|
150
166
|
//#endregion
|
|
151
|
-
export { type Conversation, ConversationItem, ConversationList, type ConversationRecord, FormattedMessage, type FreeformMessageWindow, MessageBubble, MessageBubbleProps, MessageInput, MessageList, MessageView, MessageViewContent, MessageViewEmpty, MessageViewHeader, type UIMessage, type UIMessageStatus, WhatsappDashboard, cn, useWhatsappDashboard };
|
|
167
|
+
export { type Conversation, ConversationFilterChips, ConversationFilterValue, ConversationItem, ConversationList, type ConversationRecord, FormattedMessage, type FreeformMessageWindow, MessageBubble, MessageBubbleProps, MessageInput, MessageList, MessageView, MessageViewContent, MessageViewEmpty, MessageViewHeader, type UIMessage, type UIMessageStatus, WhatsappDashboard, cn, getDisplayDate, useWhatsappDashboard };
|
package/dist/index.d.mts
CHANGED
|
@@ -3,7 +3,7 @@ import { ClassValue } from "clsx";
|
|
|
3
3
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
4
4
|
import { Conversation, Conversation as Conversation$1, ConversationRecord, FreeformMessageWindow, UIMessage, UIMessage as UIMessage$1, UIMessageStatus, UIMessageStatus as UIMessageStatus$1 } from "better-zap";
|
|
5
5
|
|
|
6
|
-
//#region src/
|
|
6
|
+
//#region src/whatsapp-dashboard.d.ts
|
|
7
7
|
type MobileView = "list" | "chat";
|
|
8
8
|
interface WhatsappDashboardContextValue {
|
|
9
9
|
isMobile: boolean;
|
|
@@ -22,7 +22,7 @@ declare function WhatsappDashboard({
|
|
|
22
22
|
...props
|
|
23
23
|
}: WhatsappDashboardProps): react_jsx_runtime0.JSX.Element;
|
|
24
24
|
//#endregion
|
|
25
|
-
//#region src/
|
|
25
|
+
//#region src/message-view.d.ts
|
|
26
26
|
interface MessageViewProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
27
27
|
children?: React.ReactNode;
|
|
28
28
|
}
|
|
@@ -71,7 +71,7 @@ declare function MessageViewEmpty({
|
|
|
71
71
|
...props
|
|
72
72
|
}: React.HTMLAttributes<HTMLDivElement>): react_jsx_runtime0.JSX.Element;
|
|
73
73
|
//#endregion
|
|
74
|
-
//#region src/
|
|
74
|
+
//#region src/message-bubble.d.ts
|
|
75
75
|
interface MessageBubbleProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
76
76
|
content: string;
|
|
77
77
|
sender: "user" | "bot";
|
|
@@ -96,7 +96,7 @@ declare function FormattedMessage({
|
|
|
96
96
|
text: string;
|
|
97
97
|
}): react_jsx_runtime0.JSX.Element | null;
|
|
98
98
|
//#endregion
|
|
99
|
-
//#region src/
|
|
99
|
+
//#region src/conversation-list.d.ts
|
|
100
100
|
interface ConversationListProps {
|
|
101
101
|
conversations: Conversation$1[];
|
|
102
102
|
isLoading: boolean;
|
|
@@ -124,10 +124,26 @@ declare function ConversationItem({
|
|
|
124
124
|
onClick
|
|
125
125
|
}: ConversationItemProps): react_jsx_runtime0.JSX.Element;
|
|
126
126
|
//#endregion
|
|
127
|
-
//#region src/
|
|
127
|
+
//#region src/conversation-filter-chips.d.ts
|
|
128
|
+
type ConversationFilterValue = "all" | "unread";
|
|
129
|
+
interface ConversationFilterChipsProps {
|
|
130
|
+
value: ConversationFilterValue;
|
|
131
|
+
onValueChange: (value: ConversationFilterValue) => void;
|
|
132
|
+
unreadCount?: number;
|
|
133
|
+
className?: string;
|
|
134
|
+
}
|
|
135
|
+
declare function ConversationFilterChips({
|
|
136
|
+
value,
|
|
137
|
+
onValueChange,
|
|
138
|
+
unreadCount,
|
|
139
|
+
className
|
|
140
|
+
}: ConversationFilterChipsProps): react_jsx_runtime0.JSX.Element;
|
|
141
|
+
//#endregion
|
|
142
|
+
//#region src/utils.d.ts
|
|
128
143
|
declare function cn(...inputs: ClassValue[]): string;
|
|
144
|
+
declare function getDisplayDate(dateStr: string): string;
|
|
129
145
|
//#endregion
|
|
130
|
-
//#region src/
|
|
146
|
+
//#region src/message-input.d.ts
|
|
131
147
|
interface MessageInputProps {
|
|
132
148
|
onSend: (text: string) => void | Promise<void>;
|
|
133
149
|
conversation?: Conversation$1 | null;
|
|
@@ -148,4 +164,4 @@ declare function MessageInput({
|
|
|
148
164
|
contextWindowOpen
|
|
149
165
|
}: MessageInputProps): react_jsx_runtime0.JSX.Element;
|
|
150
166
|
//#endregion
|
|
151
|
-
export { type Conversation, ConversationItem, ConversationList, type ConversationRecord, FormattedMessage, type FreeformMessageWindow, MessageBubble, MessageBubbleProps, MessageInput, MessageList, MessageView, MessageViewContent, MessageViewEmpty, MessageViewHeader, type UIMessage, type UIMessageStatus, WhatsappDashboard, cn, useWhatsappDashboard };
|
|
167
|
+
export { type Conversation, ConversationFilterChips, ConversationFilterValue, ConversationItem, ConversationList, type ConversationRecord, FormattedMessage, type FreeformMessageWindow, MessageBubble, MessageBubbleProps, MessageInput, MessageList, MessageView, MessageViewContent, MessageViewEmpty, MessageViewHeader, type UIMessage, type UIMessageStatus, WhatsappDashboard, cn, getDisplayDate, useWhatsappDashboard };
|
package/dist/index.mjs
CHANGED
|
@@ -4,14 +4,30 @@ 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
|
-
//#region src/
|
|
10
|
+
//#region src/utils.ts
|
|
10
11
|
function cn(...inputs) {
|
|
11
12
|
return twMerge(clsx(inputs));
|
|
12
13
|
}
|
|
14
|
+
function getDisplayDate(dateStr) {
|
|
15
|
+
const dateObj = new Date(dateStr);
|
|
16
|
+
const now = /* @__PURE__ */ new Date();
|
|
17
|
+
const isToday = dateObj.toDateString() === now.toDateString();
|
|
18
|
+
const yesterday = new Date(now);
|
|
19
|
+
yesterday.setDate(yesterday.getDate() - 1);
|
|
20
|
+
const isYesterday = dateObj.toDateString() === yesterday.toDateString();
|
|
21
|
+
if (isToday) return "HOJE";
|
|
22
|
+
else if (isYesterday) return "ONTEM";
|
|
23
|
+
else return dateObj.toLocaleDateString("pt-BR", {
|
|
24
|
+
day: "2-digit",
|
|
25
|
+
month: "2-digit",
|
|
26
|
+
year: "numeric"
|
|
27
|
+
});
|
|
28
|
+
}
|
|
13
29
|
//#endregion
|
|
14
|
-
//#region src/
|
|
30
|
+
//#region src/whatsapp-dashboard.tsx
|
|
15
31
|
const MOBILE_BREAKPOINT = 1024;
|
|
16
32
|
function useIsMobile() {
|
|
17
33
|
const [isMobile, setIsMobile] = useState(false);
|
|
@@ -52,7 +68,7 @@ function WhatsappDashboard({ children, className, defaultMobileView = "list", ..
|
|
|
52
68
|
});
|
|
53
69
|
}
|
|
54
70
|
//#endregion
|
|
55
|
-
//#region src/
|
|
71
|
+
//#region src/message-bubble.tsx
|
|
56
72
|
const bubbleVariants = cva("relative shadow-[0_1px_0.5px_rgba(11,20,26,0.13)] rounded-lg px-3 py-2 max-w-[65%]", { variants: { variant: {
|
|
57
73
|
outgoing: "bg-green-100 text-green-900 rounded-tr-none",
|
|
58
74
|
incoming: "bg-gray-100 text-gray-900 rounded-tl-none",
|
|
@@ -150,24 +166,7 @@ function FormattedMessage({ text }) {
|
|
|
150
166
|
}) });
|
|
151
167
|
}
|
|
152
168
|
//#endregion
|
|
153
|
-
//#region src/
|
|
154
|
-
function getDisplayDate(dateStr) {
|
|
155
|
-
const dateObj = new Date(dateStr);
|
|
156
|
-
const now = /* @__PURE__ */ new Date();
|
|
157
|
-
const isToday = dateObj.toDateString() === now.toDateString();
|
|
158
|
-
const yesterday = new Date(now);
|
|
159
|
-
yesterday.setDate(yesterday.getDate() - 1);
|
|
160
|
-
const isYesterday = dateObj.toDateString() === yesterday.toDateString();
|
|
161
|
-
if (isToday) return "HOJE";
|
|
162
|
-
else if (isYesterday) return "ONTEM";
|
|
163
|
-
else return dateObj.toLocaleDateString("pt-BR", {
|
|
164
|
-
day: "2-digit",
|
|
165
|
-
month: "2-digit",
|
|
166
|
-
year: "numeric"
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
//#endregion
|
|
170
|
-
//#region src/react/message-view.tsx
|
|
169
|
+
//#region src/message-view.tsx
|
|
171
170
|
function MessageView({ children, className, ...props }) {
|
|
172
171
|
const { isMobile, mobileView } = useWhatsappDashboard();
|
|
173
172
|
const hasContent = React.Children.count(children) > 0;
|
|
@@ -234,70 +233,80 @@ function MessageViewHeader({ conversation, onBack, onInfoClick, className }) {
|
|
|
234
233
|
})]
|
|
235
234
|
});
|
|
236
235
|
}
|
|
237
|
-
const
|
|
236
|
+
const MessageViewScrollContext = React.createContext(null);
|
|
238
237
|
function MessageViewContent({ children, autoScroll = true, onScrollTop, className, ...props }) {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
if (prevScrollHeight > 0 && newScrollHeight > prevScrollHeight) {
|
|
250
|
-
const addedHeight = newScrollHeight - prevScrollHeight;
|
|
251
|
-
if (el.scrollTop < SCROLL_TOP_THRESHOLD + addedHeight) el.scrollTop = addedHeight;
|
|
252
|
-
}
|
|
253
|
-
prevScrollHeightRef.current = newScrollHeight;
|
|
254
|
-
});
|
|
255
|
-
const handleScroll = useCallback(() => {
|
|
256
|
-
const el = scrollRef.current;
|
|
257
|
-
if (!el || !onScrollTop) return;
|
|
258
|
-
if (el.scrollTop <= SCROLL_TOP_THRESHOLD) onScrollTop();
|
|
259
|
-
}, [onScrollTop]);
|
|
260
|
-
return /* @__PURE__ */ jsx("div", {
|
|
261
|
-
ref: scrollRef,
|
|
262
|
-
className: cn("flex flex-1 flex-col overflow-y-auto p-4 pb-0 chat-scrollbar", className),
|
|
263
|
-
onScroll: handleScroll,
|
|
264
|
-
...props,
|
|
265
|
-
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
|
+
})
|
|
266
248
|
});
|
|
267
249
|
}
|
|
268
250
|
function MessageList({ messages, renderMessageLabel, className }) {
|
|
269
|
-
const
|
|
270
|
-
|
|
271
|
-
|
|
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;
|
|
272
258
|
messages.forEach((msg) => {
|
|
273
259
|
const displayDate = getDisplayDate(msg.sentAt);
|
|
274
|
-
if (
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
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
|
+
});
|
|
280
268
|
}
|
|
281
|
-
|
|
269
|
+
itemsNew.push({
|
|
270
|
+
type: "message",
|
|
271
|
+
id: msg.id,
|
|
272
|
+
message: msg
|
|
273
|
+
});
|
|
282
274
|
});
|
|
283
|
-
return
|
|
275
|
+
return {
|
|
276
|
+
items: itemsNew,
|
|
277
|
+
stickyHeaderIndices: stickyHeaderIndicesNew
|
|
278
|
+
};
|
|
284
279
|
}, [messages]);
|
|
285
|
-
return /* @__PURE__ */ jsx(
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
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
|
+
}
|
|
301
310
|
});
|
|
302
311
|
}
|
|
303
312
|
function DateDivider({ date }) {
|
|
@@ -344,7 +353,7 @@ function MessageViewEmpty({ className, ...props }) {
|
|
|
344
353
|
});
|
|
345
354
|
}
|
|
346
355
|
//#endregion
|
|
347
|
-
//#region src/
|
|
356
|
+
//#region src/conversation-search.tsx
|
|
348
357
|
function ConversationSearch({ value, onChange, className }) {
|
|
349
358
|
return /* @__PURE__ */ jsx("div", {
|
|
350
359
|
className: cn("border-b border-[#e9edef] shrink-0 p-2", className),
|
|
@@ -365,11 +374,46 @@ function ConversationSearch({ value, onChange, className }) {
|
|
|
365
374
|
});
|
|
366
375
|
}
|
|
367
376
|
//#endregion
|
|
368
|
-
//#region src/
|
|
377
|
+
//#region src/conversation-filter-chips.tsx
|
|
378
|
+
const chips = [{
|
|
379
|
+
label: "Tudo",
|
|
380
|
+
value: "all"
|
|
381
|
+
}, {
|
|
382
|
+
label: "Não lidas",
|
|
383
|
+
value: "unread"
|
|
384
|
+
}];
|
|
385
|
+
function ConversationFilterChips({ value, onValueChange, unreadCount = 0, className }) {
|
|
386
|
+
return /* @__PURE__ */ jsx("div", {
|
|
387
|
+
className: cn("flex items-center gap-2 px-3 py-3", className),
|
|
388
|
+
children: chips.map((chip) => {
|
|
389
|
+
const isActive = chip.value === value;
|
|
390
|
+
const showCount = chip.value === "unread" && unreadCount > 0;
|
|
391
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
392
|
+
type: "button",
|
|
393
|
+
onClick: () => onValueChange(chip.value),
|
|
394
|
+
"aria-pressed": isActive,
|
|
395
|
+
className: cn("inline-flex h-8 items-center rounded-full border px-4 text-[15px] font-medium transition-colors", isActive ? "border-[#b8e6c1] bg-[#e7fce3] text-[#017561]" : "border-[#d1d7db] bg-white text-[#54656f] hover:bg-[#f5f6f6]"),
|
|
396
|
+
children: [/* @__PURE__ */ jsx("span", { children: chip.label }), showCount ? /* @__PURE__ */ jsx("span", {
|
|
397
|
+
className: "ml-1",
|
|
398
|
+
children: unreadCount
|
|
399
|
+
}) : null]
|
|
400
|
+
}, chip.value);
|
|
401
|
+
})
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
//#endregion
|
|
405
|
+
//#region src/conversation-list.tsx
|
|
369
406
|
function ConversationList({ conversations, isLoading, isError, selectedConversationId, onSelect, className }) {
|
|
370
407
|
const { isMobile, mobileView, setMobileView } = useWhatsappDashboard();
|
|
371
408
|
const [search, setSearch] = useState("");
|
|
372
|
-
const
|
|
409
|
+
const [filter, setFilter] = useState("all");
|
|
410
|
+
const normalizedSearch = search.trim().toLowerCase();
|
|
411
|
+
const unreadConversationsCount = conversations.filter((c) => c.unreadCount > 0).length;
|
|
412
|
+
const filtered = conversations.filter((conversation) => {
|
|
413
|
+
const matchesSearch = normalizedSearch.length === 0 || conversation.phone.toLowerCase().includes(normalizedSearch) || conversation.contactName?.toLowerCase().includes(normalizedSearch);
|
|
414
|
+
const matchesFilter = filter === "all" || conversation.unreadCount > 0;
|
|
415
|
+
return matchesSearch && matchesFilter;
|
|
416
|
+
});
|
|
373
417
|
const handleSelect = (id) => {
|
|
374
418
|
onSelect(id);
|
|
375
419
|
setMobileView("chat");
|
|
@@ -378,32 +422,53 @@ function ConversationList({ conversations, isLoading, isError, selectedConversat
|
|
|
378
422
|
return /* @__PURE__ */ jsxs("div", {
|
|
379
423
|
className: cn("flex flex-col h-full bg-white border-r border-[#e9edef]", isMobile ? "w-full" : "min-w-[320px] max-w-105", className),
|
|
380
424
|
style: isVisible ? void 0 : { display: "none" },
|
|
381
|
-
children: [
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
425
|
+
children: [
|
|
426
|
+
/* @__PURE__ */ jsx(ConversationSearch, {
|
|
427
|
+
value: search,
|
|
428
|
+
onChange: setSearch
|
|
429
|
+
}),
|
|
430
|
+
/* @__PURE__ */ jsx(ConversationFilterChips, {
|
|
431
|
+
value: filter,
|
|
432
|
+
onValueChange: setFilter,
|
|
433
|
+
unreadCount: unreadConversationsCount
|
|
434
|
+
}),
|
|
435
|
+
/* @__PURE__ */ jsx("div", {
|
|
436
|
+
className: "min-h-0 flex-1",
|
|
437
|
+
children: isLoading ? /* @__PURE__ */ jsx("div", {
|
|
438
|
+
className: "flex items-center justify-center h-full text-sm text-[#667781]",
|
|
439
|
+
children: "Carregando..."
|
|
440
|
+
}) : isError ? /* @__PURE__ */ jsx("div", {
|
|
441
|
+
className: "flex items-center justify-center h-full text-sm text-red-500",
|
|
442
|
+
children: "Erro ao carregar conversas"
|
|
443
|
+
}) : filtered.length === 0 ? /* @__PURE__ */ jsxs("div", {
|
|
444
|
+
className: "flex flex-col items-center justify-center h-full gap-2 text-[#667781]",
|
|
445
|
+
children: [/* @__PURE__ */ jsx(HugeiconsIcon, {
|
|
446
|
+
icon: Message01Icon,
|
|
447
|
+
size: 32
|
|
448
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
449
|
+
className: "text-sm",
|
|
450
|
+
children: "Nenhuma conversa encontrada"
|
|
451
|
+
})]
|
|
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
|
+
})
|
|
470
|
+
})
|
|
471
|
+
]
|
|
407
472
|
});
|
|
408
473
|
}
|
|
409
474
|
function ConversationItem({ conversation, isSelected, onClick }) {
|
|
@@ -466,7 +531,7 @@ function formatTime(dateStr) {
|
|
|
466
531
|
}
|
|
467
532
|
}
|
|
468
533
|
//#endregion
|
|
469
|
-
//#region src/
|
|
534
|
+
//#region src/message-input.tsx
|
|
470
535
|
function MessageInput({ onSend, conversation, messages, disabled, placeholder = "Digite uma mensagem", className, contextWindowOpen = true }) {
|
|
471
536
|
const [text, setText] = useState("");
|
|
472
537
|
const [isSending, setIsSending] = useState(false);
|
|
@@ -581,4 +646,4 @@ function MessageInput({ onSend, conversation, messages, disabled, placeholder =
|
|
|
581
646
|
});
|
|
582
647
|
}
|
|
583
648
|
//#endregion
|
|
584
|
-
export { ConversationItem, ConversationList, FormattedMessage, MessageBubble, MessageInput, MessageList, MessageView, MessageViewContent, MessageViewEmpty, MessageViewHeader, WhatsappDashboard, cn, useWhatsappDashboard };
|
|
649
|
+
export { ConversationFilterChips, ConversationItem, ConversationList, FormattedMessage, MessageBubble, MessageInput, MessageList, MessageView, MessageViewContent, MessageViewEmpty, MessageViewHeader, WhatsappDashboard, cn, getDisplayDate, useWhatsappDashboard };
|
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",
|