@better-zap/react 0.0.3 → 0.0.4
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 +94 -51
- package/dist/index.d.cts +23 -7
- package/dist/index.d.mts +23 -7
- package/dist/index.mjs +93 -52
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -30,12 +30,27 @@ let _hugeicons_react = require("@hugeicons/react");
|
|
|
30
30
|
let _hugeicons_core_free_icons = require("@hugeicons/core-free-icons");
|
|
31
31
|
let class_variance_authority = require("class-variance-authority");
|
|
32
32
|
let better_zap = require("better-zap");
|
|
33
|
-
//#region src/
|
|
33
|
+
//#region src/utils.ts
|
|
34
34
|
function cn(...inputs) {
|
|
35
35
|
return (0, tailwind_merge.twMerge)((0, clsx.clsx)(inputs));
|
|
36
36
|
}
|
|
37
|
+
function getDisplayDate(dateStr) {
|
|
38
|
+
const dateObj = new Date(dateStr);
|
|
39
|
+
const now = /* @__PURE__ */ new Date();
|
|
40
|
+
const isToday = dateObj.toDateString() === now.toDateString();
|
|
41
|
+
const yesterday = new Date(now);
|
|
42
|
+
yesterday.setDate(yesterday.getDate() - 1);
|
|
43
|
+
const isYesterday = dateObj.toDateString() === yesterday.toDateString();
|
|
44
|
+
if (isToday) return "HOJE";
|
|
45
|
+
else if (isYesterday) return "ONTEM";
|
|
46
|
+
else return dateObj.toLocaleDateString("pt-BR", {
|
|
47
|
+
day: "2-digit",
|
|
48
|
+
month: "2-digit",
|
|
49
|
+
year: "numeric"
|
|
50
|
+
});
|
|
51
|
+
}
|
|
37
52
|
//#endregion
|
|
38
|
-
//#region src/
|
|
53
|
+
//#region src/whatsapp-dashboard.tsx
|
|
39
54
|
const MOBILE_BREAKPOINT = 1024;
|
|
40
55
|
function useIsMobile() {
|
|
41
56
|
const [isMobile, setIsMobile] = (0, react.useState)(false);
|
|
@@ -76,7 +91,7 @@ function WhatsappDashboard({ children, className, defaultMobileView = "list", ..
|
|
|
76
91
|
});
|
|
77
92
|
}
|
|
78
93
|
//#endregion
|
|
79
|
-
//#region src/
|
|
94
|
+
//#region src/message-bubble.tsx
|
|
80
95
|
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
96
|
outgoing: "bg-green-100 text-green-900 rounded-tr-none",
|
|
82
97
|
incoming: "bg-gray-100 text-gray-900 rounded-tl-none",
|
|
@@ -174,24 +189,7 @@ function FormattedMessage({ text }) {
|
|
|
174
189
|
}) });
|
|
175
190
|
}
|
|
176
191
|
//#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
|
|
192
|
+
//#region src/message-view.tsx
|
|
195
193
|
function MessageView({ children, className, ...props }) {
|
|
196
194
|
const { isMobile, mobileView } = useWhatsappDashboard();
|
|
197
195
|
const hasContent = react.default.Children.count(children) > 0;
|
|
@@ -368,7 +366,7 @@ function MessageViewEmpty({ className, ...props }) {
|
|
|
368
366
|
});
|
|
369
367
|
}
|
|
370
368
|
//#endregion
|
|
371
|
-
//#region src/
|
|
369
|
+
//#region src/conversation-search.tsx
|
|
372
370
|
function ConversationSearch({ value, onChange, className }) {
|
|
373
371
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
374
372
|
className: cn("border-b border-[#e9edef] shrink-0 p-2", className),
|
|
@@ -389,11 +387,46 @@ function ConversationSearch({ value, onChange, className }) {
|
|
|
389
387
|
});
|
|
390
388
|
}
|
|
391
389
|
//#endregion
|
|
392
|
-
//#region src/
|
|
390
|
+
//#region src/conversation-filter-chips.tsx
|
|
391
|
+
const chips = [{
|
|
392
|
+
label: "Tudo",
|
|
393
|
+
value: "all"
|
|
394
|
+
}, {
|
|
395
|
+
label: "Não lidas",
|
|
396
|
+
value: "unread"
|
|
397
|
+
}];
|
|
398
|
+
function ConversationFilterChips({ value, onValueChange, unreadCount = 0, className }) {
|
|
399
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
400
|
+
className: cn("flex items-center gap-2 px-3 py-3", className),
|
|
401
|
+
children: chips.map((chip) => {
|
|
402
|
+
const isActive = chip.value === value;
|
|
403
|
+
const showCount = chip.value === "unread" && unreadCount > 0;
|
|
404
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
405
|
+
type: "button",
|
|
406
|
+
onClick: () => onValueChange(chip.value),
|
|
407
|
+
"aria-pressed": isActive,
|
|
408
|
+
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]"),
|
|
409
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: chip.label }), showCount ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
410
|
+
className: "ml-1",
|
|
411
|
+
children: unreadCount
|
|
412
|
+
}) : null]
|
|
413
|
+
}, chip.value);
|
|
414
|
+
})
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
//#endregion
|
|
418
|
+
//#region src/conversation-list.tsx
|
|
393
419
|
function ConversationList({ conversations, isLoading, isError, selectedConversationId, onSelect, className }) {
|
|
394
420
|
const { isMobile, mobileView, setMobileView } = useWhatsappDashboard();
|
|
395
421
|
const [search, setSearch] = (0, react.useState)("");
|
|
396
|
-
const
|
|
422
|
+
const [filter, setFilter] = (0, react.useState)("all");
|
|
423
|
+
const normalizedSearch = search.trim().toLowerCase();
|
|
424
|
+
const unreadConversationsCount = conversations.filter((c) => c.unreadCount > 0).length;
|
|
425
|
+
const filtered = conversations.filter((conversation) => {
|
|
426
|
+
const matchesSearch = normalizedSearch.length === 0 || conversation.phone.toLowerCase().includes(normalizedSearch) || conversation.contactName?.toLowerCase().includes(normalizedSearch);
|
|
427
|
+
const matchesFilter = filter === "all" || conversation.unreadCount > 0;
|
|
428
|
+
return matchesSearch && matchesFilter;
|
|
429
|
+
});
|
|
397
430
|
const handleSelect = (id) => {
|
|
398
431
|
onSelect(id);
|
|
399
432
|
setMobileView("chat");
|
|
@@ -402,32 +435,40 @@ function ConversationList({ conversations, isLoading, isError, selectedConversat
|
|
|
402
435
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
403
436
|
className: cn("flex flex-col h-full bg-white border-r border-[#e9edef]", isMobile ? "w-full" : "min-w-[320px] max-w-105", className),
|
|
404
437
|
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
|
-
|
|
438
|
+
children: [
|
|
439
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConversationSearch, {
|
|
440
|
+
value: search,
|
|
441
|
+
onChange: setSearch
|
|
442
|
+
}),
|
|
443
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConversationFilterChips, {
|
|
444
|
+
value: filter,
|
|
445
|
+
onValueChange: setFilter,
|
|
446
|
+
unreadCount: unreadConversationsCount
|
|
447
|
+
}),
|
|
448
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
449
|
+
className: "flex-1 overflow-y-auto overflow-x-hidden chat-scrollbar",
|
|
450
|
+
children: isLoading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
451
|
+
className: "flex items-center justify-center h-full text-sm text-[#667781]",
|
|
452
|
+
children: "Carregando..."
|
|
453
|
+
}) : isError ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
454
|
+
className: "flex items-center justify-center h-full text-sm text-red-500",
|
|
455
|
+
children: "Erro ao carregar conversas"
|
|
456
|
+
}) : filtered.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
457
|
+
className: "flex flex-col items-center justify-center h-full gap-2 text-[#667781]",
|
|
458
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_hugeicons_react.HugeiconsIcon, {
|
|
459
|
+
icon: _hugeicons_core_free_icons.Message01Icon,
|
|
460
|
+
size: 32
|
|
461
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
462
|
+
className: "text-sm",
|
|
463
|
+
children: "Nenhuma conversa encontrada"
|
|
464
|
+
})]
|
|
465
|
+
}) : filtered.map((conversation) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConversationItem, {
|
|
466
|
+
conversation,
|
|
467
|
+
isSelected: selectedConversationId === conversation.id,
|
|
468
|
+
onClick: () => handleSelect(conversation.id)
|
|
469
|
+
}, conversation.id))
|
|
470
|
+
})
|
|
471
|
+
]
|
|
431
472
|
});
|
|
432
473
|
}
|
|
433
474
|
function ConversationItem({ conversation, isSelected, onClick }) {
|
|
@@ -490,7 +531,7 @@ function formatTime(dateStr) {
|
|
|
490
531
|
}
|
|
491
532
|
}
|
|
492
533
|
//#endregion
|
|
493
|
-
//#region src/
|
|
534
|
+
//#region src/message-input.tsx
|
|
494
535
|
function MessageInput({ onSend, conversation, messages, disabled, placeholder = "Digite uma mensagem", className, contextWindowOpen = true }) {
|
|
495
536
|
const [text, setText] = (0, react.useState)("");
|
|
496
537
|
const [isSending, setIsSending] = (0, react.useState)(false);
|
|
@@ -605,6 +646,7 @@ function MessageInput({ onSend, conversation, messages, disabled, placeholder =
|
|
|
605
646
|
});
|
|
606
647
|
}
|
|
607
648
|
//#endregion
|
|
649
|
+
exports.ConversationFilterChips = ConversationFilterChips;
|
|
608
650
|
exports.ConversationItem = ConversationItem;
|
|
609
651
|
exports.ConversationList = ConversationList;
|
|
610
652
|
exports.FormattedMessage = FormattedMessage;
|
|
@@ -617,4 +659,5 @@ exports.MessageViewEmpty = MessageViewEmpty;
|
|
|
617
659
|
exports.MessageViewHeader = MessageViewHeader;
|
|
618
660
|
exports.WhatsappDashboard = WhatsappDashboard;
|
|
619
661
|
exports.cn = cn;
|
|
662
|
+
exports.getDisplayDate = getDisplayDate;
|
|
620
663
|
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
|
@@ -6,12 +6,27 @@ import { HugeiconsIcon } from "@hugeicons/react";
|
|
|
6
6
|
import { Add01Icon, ArrowLeft02Icon, Clock01Icon, InformationCircleIcon, Message01Icon, Mic01Icon, Search01Icon, Sent02Icon, SmileIcon, UserIcon } from "@hugeicons/core-free-icons";
|
|
7
7
|
import { cva } from "class-variance-authority";
|
|
8
8
|
import { resolveConversationFreeformMessageWindow } from "better-zap";
|
|
9
|
-
//#region src/
|
|
9
|
+
//#region src/utils.ts
|
|
10
10
|
function cn(...inputs) {
|
|
11
11
|
return twMerge(clsx(inputs));
|
|
12
12
|
}
|
|
13
|
+
function getDisplayDate(dateStr) {
|
|
14
|
+
const dateObj = new Date(dateStr);
|
|
15
|
+
const now = /* @__PURE__ */ new Date();
|
|
16
|
+
const isToday = dateObj.toDateString() === now.toDateString();
|
|
17
|
+
const yesterday = new Date(now);
|
|
18
|
+
yesterday.setDate(yesterday.getDate() - 1);
|
|
19
|
+
const isYesterday = dateObj.toDateString() === yesterday.toDateString();
|
|
20
|
+
if (isToday) return "HOJE";
|
|
21
|
+
else if (isYesterday) return "ONTEM";
|
|
22
|
+
else return dateObj.toLocaleDateString("pt-BR", {
|
|
23
|
+
day: "2-digit",
|
|
24
|
+
month: "2-digit",
|
|
25
|
+
year: "numeric"
|
|
26
|
+
});
|
|
27
|
+
}
|
|
13
28
|
//#endregion
|
|
14
|
-
//#region src/
|
|
29
|
+
//#region src/whatsapp-dashboard.tsx
|
|
15
30
|
const MOBILE_BREAKPOINT = 1024;
|
|
16
31
|
function useIsMobile() {
|
|
17
32
|
const [isMobile, setIsMobile] = useState(false);
|
|
@@ -52,7 +67,7 @@ function WhatsappDashboard({ children, className, defaultMobileView = "list", ..
|
|
|
52
67
|
});
|
|
53
68
|
}
|
|
54
69
|
//#endregion
|
|
55
|
-
//#region src/
|
|
70
|
+
//#region src/message-bubble.tsx
|
|
56
71
|
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
72
|
outgoing: "bg-green-100 text-green-900 rounded-tr-none",
|
|
58
73
|
incoming: "bg-gray-100 text-gray-900 rounded-tl-none",
|
|
@@ -150,24 +165,7 @@ function FormattedMessage({ text }) {
|
|
|
150
165
|
}) });
|
|
151
166
|
}
|
|
152
167
|
//#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
|
|
168
|
+
//#region src/message-view.tsx
|
|
171
169
|
function MessageView({ children, className, ...props }) {
|
|
172
170
|
const { isMobile, mobileView } = useWhatsappDashboard();
|
|
173
171
|
const hasContent = React.Children.count(children) > 0;
|
|
@@ -344,7 +342,7 @@ function MessageViewEmpty({ className, ...props }) {
|
|
|
344
342
|
});
|
|
345
343
|
}
|
|
346
344
|
//#endregion
|
|
347
|
-
//#region src/
|
|
345
|
+
//#region src/conversation-search.tsx
|
|
348
346
|
function ConversationSearch({ value, onChange, className }) {
|
|
349
347
|
return /* @__PURE__ */ jsx("div", {
|
|
350
348
|
className: cn("border-b border-[#e9edef] shrink-0 p-2", className),
|
|
@@ -365,11 +363,46 @@ function ConversationSearch({ value, onChange, className }) {
|
|
|
365
363
|
});
|
|
366
364
|
}
|
|
367
365
|
//#endregion
|
|
368
|
-
//#region src/
|
|
366
|
+
//#region src/conversation-filter-chips.tsx
|
|
367
|
+
const chips = [{
|
|
368
|
+
label: "Tudo",
|
|
369
|
+
value: "all"
|
|
370
|
+
}, {
|
|
371
|
+
label: "Não lidas",
|
|
372
|
+
value: "unread"
|
|
373
|
+
}];
|
|
374
|
+
function ConversationFilterChips({ value, onValueChange, unreadCount = 0, className }) {
|
|
375
|
+
return /* @__PURE__ */ jsx("div", {
|
|
376
|
+
className: cn("flex items-center gap-2 px-3 py-3", className),
|
|
377
|
+
children: chips.map((chip) => {
|
|
378
|
+
const isActive = chip.value === value;
|
|
379
|
+
const showCount = chip.value === "unread" && unreadCount > 0;
|
|
380
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
381
|
+
type: "button",
|
|
382
|
+
onClick: () => onValueChange(chip.value),
|
|
383
|
+
"aria-pressed": isActive,
|
|
384
|
+
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]"),
|
|
385
|
+
children: [/* @__PURE__ */ jsx("span", { children: chip.label }), showCount ? /* @__PURE__ */ jsx("span", {
|
|
386
|
+
className: "ml-1",
|
|
387
|
+
children: unreadCount
|
|
388
|
+
}) : null]
|
|
389
|
+
}, chip.value);
|
|
390
|
+
})
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
//#endregion
|
|
394
|
+
//#region src/conversation-list.tsx
|
|
369
395
|
function ConversationList({ conversations, isLoading, isError, selectedConversationId, onSelect, className }) {
|
|
370
396
|
const { isMobile, mobileView, setMobileView } = useWhatsappDashboard();
|
|
371
397
|
const [search, setSearch] = useState("");
|
|
372
|
-
const
|
|
398
|
+
const [filter, setFilter] = useState("all");
|
|
399
|
+
const normalizedSearch = search.trim().toLowerCase();
|
|
400
|
+
const unreadConversationsCount = conversations.filter((c) => c.unreadCount > 0).length;
|
|
401
|
+
const filtered = conversations.filter((conversation) => {
|
|
402
|
+
const matchesSearch = normalizedSearch.length === 0 || conversation.phone.toLowerCase().includes(normalizedSearch) || conversation.contactName?.toLowerCase().includes(normalizedSearch);
|
|
403
|
+
const matchesFilter = filter === "all" || conversation.unreadCount > 0;
|
|
404
|
+
return matchesSearch && matchesFilter;
|
|
405
|
+
});
|
|
373
406
|
const handleSelect = (id) => {
|
|
374
407
|
onSelect(id);
|
|
375
408
|
setMobileView("chat");
|
|
@@ -378,32 +411,40 @@ function ConversationList({ conversations, isLoading, isError, selectedConversat
|
|
|
378
411
|
return /* @__PURE__ */ jsxs("div", {
|
|
379
412
|
className: cn("flex flex-col h-full bg-white border-r border-[#e9edef]", isMobile ? "w-full" : "min-w-[320px] max-w-105", className),
|
|
380
413
|
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
|
-
|
|
414
|
+
children: [
|
|
415
|
+
/* @__PURE__ */ jsx(ConversationSearch, {
|
|
416
|
+
value: search,
|
|
417
|
+
onChange: setSearch
|
|
418
|
+
}),
|
|
419
|
+
/* @__PURE__ */ jsx(ConversationFilterChips, {
|
|
420
|
+
value: filter,
|
|
421
|
+
onValueChange: setFilter,
|
|
422
|
+
unreadCount: unreadConversationsCount
|
|
423
|
+
}),
|
|
424
|
+
/* @__PURE__ */ jsx("div", {
|
|
425
|
+
className: "flex-1 overflow-y-auto overflow-x-hidden chat-scrollbar",
|
|
426
|
+
children: isLoading ? /* @__PURE__ */ jsx("div", {
|
|
427
|
+
className: "flex items-center justify-center h-full text-sm text-[#667781]",
|
|
428
|
+
children: "Carregando..."
|
|
429
|
+
}) : isError ? /* @__PURE__ */ jsx("div", {
|
|
430
|
+
className: "flex items-center justify-center h-full text-sm text-red-500",
|
|
431
|
+
children: "Erro ao carregar conversas"
|
|
432
|
+
}) : filtered.length === 0 ? /* @__PURE__ */ jsxs("div", {
|
|
433
|
+
className: "flex flex-col items-center justify-center h-full gap-2 text-[#667781]",
|
|
434
|
+
children: [/* @__PURE__ */ jsx(HugeiconsIcon, {
|
|
435
|
+
icon: Message01Icon,
|
|
436
|
+
size: 32
|
|
437
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
438
|
+
className: "text-sm",
|
|
439
|
+
children: "Nenhuma conversa encontrada"
|
|
440
|
+
})]
|
|
441
|
+
}) : filtered.map((conversation) => /* @__PURE__ */ jsx(ConversationItem, {
|
|
442
|
+
conversation,
|
|
443
|
+
isSelected: selectedConversationId === conversation.id,
|
|
444
|
+
onClick: () => handleSelect(conversation.id)
|
|
445
|
+
}, conversation.id))
|
|
446
|
+
})
|
|
447
|
+
]
|
|
407
448
|
});
|
|
408
449
|
}
|
|
409
450
|
function ConversationItem({ conversation, isSelected, onClick }) {
|
|
@@ -466,7 +507,7 @@ function formatTime(dateStr) {
|
|
|
466
507
|
}
|
|
467
508
|
}
|
|
468
509
|
//#endregion
|
|
469
|
-
//#region src/
|
|
510
|
+
//#region src/message-input.tsx
|
|
470
511
|
function MessageInput({ onSend, conversation, messages, disabled, placeholder = "Digite uma mensagem", className, contextWindowOpen = true }) {
|
|
471
512
|
const [text, setText] = useState("");
|
|
472
513
|
const [isSending, setIsSending] = useState(false);
|
|
@@ -581,4 +622,4 @@ function MessageInput({ onSend, conversation, messages, disabled, placeholder =
|
|
|
581
622
|
});
|
|
582
623
|
}
|
|
583
624
|
//#endregion
|
|
584
|
-
export { ConversationItem, ConversationList, FormattedMessage, MessageBubble, MessageInput, MessageList, MessageView, MessageViewContent, MessageViewEmpty, MessageViewHeader, WhatsappDashboard, cn, useWhatsappDashboard };
|
|
625
|
+
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.0.4",
|
|
4
4
|
"description": "React components for Better Zap.",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"type": "module",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"class-variance-authority": "^0.7.1",
|
|
37
37
|
"clsx": "^2.1.1",
|
|
38
38
|
"tailwind-merge": "^3.0.0",
|
|
39
|
-
"better-zap": "0.0.
|
|
39
|
+
"better-zap": "0.0.4"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"react": "^19.0.0",
|