@better-zap/react 0.2.1 → 0.2.2
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/bubble.cjs +93 -0
- package/dist/bubble.d.cts +61 -0
- package/dist/bubble.d.mts +61 -0
- package/dist/bubble.mjs +89 -0
- package/dist/composer.cjs +220 -0
- package/dist/composer.d.cts +96 -0
- package/dist/composer.d.mts +96 -0
- package/dist/composer.mjs +211 -0
- package/dist/conversation-list-BlhJhDsc.d.cts +100 -0
- package/dist/conversation-list-BwQ4oK2J.d.mts +100 -0
- package/dist/conversation-list-C0EmReS-.mjs +293 -0
- package/dist/conversation-list-CVWdddJh.cjs +311 -0
- package/dist/conversation-list.cjs +6 -0
- package/dist/conversation-list.d.cts +2 -0
- package/dist/conversation-list.d.mts +2 -0
- package/dist/conversation-list.mjs +5 -0
- package/dist/index.cjs +49 -0
- package/dist/index.d.cts +19 -0
- package/dist/index.d.mts +19 -0
- package/dist/index.mjs +11 -0
- package/dist/message-bubble.cjs +116 -0
- package/dist/message-bubble.d.cts +38 -0
- package/dist/message-bubble.d.mts +38 -0
- package/dist/message-bubble.mjs +114 -0
- package/dist/message-input-CkaL6fb4.mjs +173 -0
- package/dist/message-input-DcEzHQ9t.cjs +191 -0
- package/dist/message-input.cjs +6 -0
- package/dist/message-input.d.cts +51 -0
- package/dist/message-input.d.mts +51 -0
- package/dist/message-input.mjs +5 -0
- package/dist/message-view.cjs +273 -0
- package/dist/message-view.d.cts +109 -0
- package/dist/message-view.d.mts +109 -0
- package/dist/message-view.mjs +266 -0
- package/dist/message.cjs +50 -0
- package/dist/message.d.cts +40 -0
- package/dist/message.d.mts +40 -0
- package/dist/message.mjs +43 -0
- package/dist/tailwind.css +33 -0
- package/dist/utils-Bp9IahGG.cjs +91 -0
- package/dist/utils.cjs +5 -0
- package/dist/utils.d.cts +20 -0
- package/dist/utils.d.mts +20 -0
- package/dist/utils.mjs +45 -0
- package/dist/whatsapp-dashboard.cjs +64 -0
- package/dist/whatsapp-dashboard.d.cts +33 -0
- package/dist/whatsapp-dashboard.d.mts +33 -0
- package/dist/whatsapp-dashboard.mjs +60 -0
- package/dist/wpp-bg.webp +0 -0
- package/package.json +1 -1
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
|
+
import { Conversation, UIMessage } from "better-zap";
|
|
4
|
+
|
|
5
|
+
//#region src/message-view.d.ts
|
|
6
|
+
interface MessageViewProps extends React.ComponentProps<"div"> {
|
|
7
|
+
children?: React.ReactNode;
|
|
8
|
+
}
|
|
9
|
+
declare function MessageView({
|
|
10
|
+
children,
|
|
11
|
+
className,
|
|
12
|
+
style,
|
|
13
|
+
...props
|
|
14
|
+
}: MessageViewProps): react_jsx_runtime0.JSX.Element | null;
|
|
15
|
+
interface MessageViewHeaderLabels {
|
|
16
|
+
back: string;
|
|
17
|
+
info: string;
|
|
18
|
+
}
|
|
19
|
+
interface MessageViewHeaderProps extends React.ComponentProps<"div"> {
|
|
20
|
+
conversation?: Conversation;
|
|
21
|
+
onBack?: () => void;
|
|
22
|
+
onInfoClick?: () => void;
|
|
23
|
+
/** Force the back button outside dashboard context. Default: ctx?.isMobile ?? false */
|
|
24
|
+
showBackButton?: boolean;
|
|
25
|
+
/** Replaces the right-side default info button entirely. */
|
|
26
|
+
actions?: React.ReactNode;
|
|
27
|
+
labels?: Partial<MessageViewHeaderLabels>;
|
|
28
|
+
/** children replace the identity block (name + phone) when provided. */
|
|
29
|
+
children?: React.ReactNode;
|
|
30
|
+
}
|
|
31
|
+
declare function MessageViewHeader({
|
|
32
|
+
conversation,
|
|
33
|
+
onBack,
|
|
34
|
+
onInfoClick,
|
|
35
|
+
showBackButton,
|
|
36
|
+
actions,
|
|
37
|
+
labels: labelsProp,
|
|
38
|
+
children,
|
|
39
|
+
className,
|
|
40
|
+
...props
|
|
41
|
+
}: MessageViewHeaderProps): react_jsx_runtime0.JSX.Element;
|
|
42
|
+
interface MessageViewContentProps extends React.ComponentProps<"div"> {
|
|
43
|
+
children?: React.ReactNode;
|
|
44
|
+
autoScroll?: boolean;
|
|
45
|
+
/** Called when the user scrolls to the top of the container. */
|
|
46
|
+
onScrollTop?: () => void;
|
|
47
|
+
}
|
|
48
|
+
declare function MessageViewContent({
|
|
49
|
+
children,
|
|
50
|
+
autoScroll,
|
|
51
|
+
onScrollTop,
|
|
52
|
+
className,
|
|
53
|
+
...props
|
|
54
|
+
}: MessageViewContentProps): react_jsx_runtime0.JSX.Element;
|
|
55
|
+
type MessageGroupPosition = "single" | "first" | "middle" | "last";
|
|
56
|
+
interface MessageRenderContext {
|
|
57
|
+
message: UIMessage;
|
|
58
|
+
/** Stable list identity — always message.id. */
|
|
59
|
+
id: string;
|
|
60
|
+
direction: "incoming" | "outgoing";
|
|
61
|
+
/** Presentation alignment: incoming → "start", outgoing → "end". */
|
|
62
|
+
align: "start" | "end";
|
|
63
|
+
groupPosition: MessageGroupPosition;
|
|
64
|
+
/** Result of renderMessageLabel, when provided. */
|
|
65
|
+
label?: string;
|
|
66
|
+
}
|
|
67
|
+
interface DateDividerRenderContext {
|
|
68
|
+
/** Formatted label (output of formatDate / getDisplayDate). */
|
|
69
|
+
label: string;
|
|
70
|
+
/** sentAt of the first message under this divider (raw ISO string). */
|
|
71
|
+
date: string;
|
|
72
|
+
}
|
|
73
|
+
interface MessageListProps {
|
|
74
|
+
messages: UIMessage[];
|
|
75
|
+
renderMessage?: (context: MessageRenderContext) => React.ReactNode;
|
|
76
|
+
renderDateDivider?: (context: DateDividerRenderContext) => React.ReactNode;
|
|
77
|
+
/** Formats divider labels. Default: getDisplayDate (pt-BR HOJE/ONTEM). */
|
|
78
|
+
formatDate?: (isoDate: string) => string;
|
|
79
|
+
/** Formats the in-bubble timestamp used by the DEFAULT renderer. Default: pt-BR HH:mm. */
|
|
80
|
+
formatTime?: (isoDate: string) => string;
|
|
81
|
+
renderMessageLabel?: (message: UIMessage) => string | undefined;
|
|
82
|
+
/** Direct props — context from MessageViewContent still works; these win over it. */
|
|
83
|
+
autoScroll?: boolean;
|
|
84
|
+
onScrollTop?: () => void;
|
|
85
|
+
className?: string;
|
|
86
|
+
}
|
|
87
|
+
declare function MessageList({
|
|
88
|
+
messages,
|
|
89
|
+
renderMessage,
|
|
90
|
+
renderDateDivider,
|
|
91
|
+
formatDate,
|
|
92
|
+
formatTime,
|
|
93
|
+
renderMessageLabel,
|
|
94
|
+
autoScroll: autoScrollProp,
|
|
95
|
+
onScrollTop: onScrollTopProp,
|
|
96
|
+
className
|
|
97
|
+
}: MessageListProps): react_jsx_runtime0.JSX.Element;
|
|
98
|
+
declare function DateDivider({
|
|
99
|
+
children,
|
|
100
|
+
className,
|
|
101
|
+
...props
|
|
102
|
+
}: React.ComponentProps<"div">): react_jsx_runtime0.JSX.Element;
|
|
103
|
+
declare function MessageViewEmpty({
|
|
104
|
+
className,
|
|
105
|
+
children,
|
|
106
|
+
...props
|
|
107
|
+
}: React.ComponentProps<"div">): react_jsx_runtime0.JSX.Element;
|
|
108
|
+
//#endregion
|
|
109
|
+
export { DateDivider, DateDividerRenderContext, MessageGroupPosition, MessageList, MessageListProps, MessageRenderContext, MessageView, MessageViewContent, MessageViewContentProps, MessageViewEmpty, MessageViewHeader, MessageViewHeaderLabels, MessageViewHeaderProps, MessageViewProps };
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn, getDisplayDate } from "./utils.mjs";
|
|
3
|
+
import { useOptionalWhatsappDashboard } from "./whatsapp-dashboard.mjs";
|
|
4
|
+
import { MessageBubble } from "./message-bubble.mjs";
|
|
5
|
+
import React, { useContext, useMemo } from "react";
|
|
6
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { HugeiconsIcon } from "@hugeicons/react";
|
|
8
|
+
import { ArrowLeft02Icon, InformationCircleIcon, Message01Icon, UserIcon } from "@hugeicons/core-free-icons";
|
|
9
|
+
import { LegendList } from "@legendapp/list/react";
|
|
10
|
+
//#region src/message-view.tsx
|
|
11
|
+
function MessageView({ children, className, style, ...props }) {
|
|
12
|
+
const ctx = useOptionalWhatsappDashboard();
|
|
13
|
+
const isMobile = ctx?.isMobile ?? false;
|
|
14
|
+
const mobileView = ctx?.mobileView ?? "chat";
|
|
15
|
+
const hasContent = React.Children.count(children) > 0;
|
|
16
|
+
const isVisible = !isMobile || mobileView === "chat";
|
|
17
|
+
if (!hasContent) {
|
|
18
|
+
if (isMobile) return null;
|
|
19
|
+
return /* @__PURE__ */ jsx(MessageViewEmpty, {
|
|
20
|
+
className,
|
|
21
|
+
style,
|
|
22
|
+
...props
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
26
|
+
className: cn("relative flex flex-1 flex-col bg-[#efeae2]", className),
|
|
27
|
+
style: {
|
|
28
|
+
...style,
|
|
29
|
+
...isVisible ? null : { display: "none" }
|
|
30
|
+
},
|
|
31
|
+
...props,
|
|
32
|
+
children: [/* @__PURE__ */ jsx("div", { style: {
|
|
33
|
+
position: "absolute",
|
|
34
|
+
backgroundImage: `url(${new URL("./wpp-bg.webp", import.meta.url).href})`,
|
|
35
|
+
backgroundRepeat: "repeat",
|
|
36
|
+
opacity: .15,
|
|
37
|
+
inset: 0
|
|
38
|
+
} }), /* @__PURE__ */ jsx("div", {
|
|
39
|
+
className: "relative flex flex-1 flex-col min-h-0",
|
|
40
|
+
children
|
|
41
|
+
})]
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
const DEFAULT_HEADER_LABELS = {
|
|
45
|
+
back: "Voltar",
|
|
46
|
+
info: "Informações"
|
|
47
|
+
};
|
|
48
|
+
const iconButtonClassName = "inline-flex h-10 w-10 items-center justify-center rounded-full text-[#54656f] hover:bg-black/5 focus-visible:outline-2 focus-visible:outline-offset-2";
|
|
49
|
+
function MessageViewHeader({ conversation, onBack, onInfoClick, showBackButton, actions, labels: labelsProp, children, className, ...props }) {
|
|
50
|
+
const ctx = useOptionalWhatsappDashboard();
|
|
51
|
+
const labels = {
|
|
52
|
+
...DEFAULT_HEADER_LABELS,
|
|
53
|
+
...labelsProp
|
|
54
|
+
};
|
|
55
|
+
const showBack = showBackButton ?? ctx?.isMobile ?? false;
|
|
56
|
+
const handleBack = () => {
|
|
57
|
+
ctx?.setMobileView("list");
|
|
58
|
+
onBack?.();
|
|
59
|
+
};
|
|
60
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
61
|
+
className: cn("flex h-[59px] shrink-0 items-center justify-between bg-[#f0f2f5] px-4 z-20", className),
|
|
62
|
+
...props,
|
|
63
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
64
|
+
className: "flex items-center gap-3",
|
|
65
|
+
children: [showBack && /* @__PURE__ */ jsx("button", {
|
|
66
|
+
type: "button",
|
|
67
|
+
"aria-label": labels.back,
|
|
68
|
+
className: iconButtonClassName,
|
|
69
|
+
onClick: handleBack,
|
|
70
|
+
children: /* @__PURE__ */ jsx(HugeiconsIcon, {
|
|
71
|
+
icon: ArrowLeft02Icon,
|
|
72
|
+
size: 20
|
|
73
|
+
})
|
|
74
|
+
}), children ?? (conversation ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
|
|
75
|
+
className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-[#dfe5e7]",
|
|
76
|
+
children: /* @__PURE__ */ jsx(HugeiconsIcon, {
|
|
77
|
+
icon: UserIcon,
|
|
78
|
+
size: 24,
|
|
79
|
+
className: "text-white"
|
|
80
|
+
})
|
|
81
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
82
|
+
className: "flex flex-col",
|
|
83
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
84
|
+
className: "text-[16px] font-medium text-[#111b21] leading-tight",
|
|
85
|
+
children: conversation.contactName || conversation.phone
|
|
86
|
+
}), conversation.contactName && /* @__PURE__ */ jsx("span", {
|
|
87
|
+
className: "text-[13px] text-[#667781] leading-tight",
|
|
88
|
+
children: conversation.phone
|
|
89
|
+
})]
|
|
90
|
+
})] }) : /* @__PURE__ */ jsx("div", { className: "flex flex-col" }))]
|
|
91
|
+
}), actions ?? (onInfoClick ? /* @__PURE__ */ jsx("button", {
|
|
92
|
+
type: "button",
|
|
93
|
+
"aria-label": labels.info,
|
|
94
|
+
className: iconButtonClassName,
|
|
95
|
+
onClick: onInfoClick,
|
|
96
|
+
children: /* @__PURE__ */ jsx(HugeiconsIcon, {
|
|
97
|
+
icon: InformationCircleIcon,
|
|
98
|
+
size: 20
|
|
99
|
+
})
|
|
100
|
+
}) : null)]
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
const MessageViewScrollContext = React.createContext(null);
|
|
104
|
+
function MessageViewContent({ children, autoScroll = true, onScrollTop, className, ...props }) {
|
|
105
|
+
return /* @__PURE__ */ jsx(MessageViewScrollContext.Provider, {
|
|
106
|
+
value: {
|
|
107
|
+
autoScroll,
|
|
108
|
+
onScrollTop
|
|
109
|
+
},
|
|
110
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
111
|
+
className: cn("flex min-h-0 flex-1 flex-col p-4 pb-0", className),
|
|
112
|
+
...props,
|
|
113
|
+
children
|
|
114
|
+
})
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
const MemoizedMessageBubble = React.memo(MessageBubble);
|
|
118
|
+
const MemoizedDateDivider = React.memo(DateDivider);
|
|
119
|
+
function defaultFormatTime(isoDate) {
|
|
120
|
+
return new Date(isoDate).toLocaleTimeString("pt-BR", {
|
|
121
|
+
hour: "2-digit",
|
|
122
|
+
minute: "2-digit"
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function sameGroup(a, b, resolveFormatDate) {
|
|
126
|
+
return resolveFormatDate(a.sentAt) === resolveFormatDate(b.sentAt) && a.direction === b.direction;
|
|
127
|
+
}
|
|
128
|
+
function getGroupPosition(messages, index, resolveFormatDate) {
|
|
129
|
+
const n = messages.length;
|
|
130
|
+
const prevSame = index > 0 && sameGroup(messages[index - 1], messages[index], resolveFormatDate);
|
|
131
|
+
const nextSame = index < n - 1 && sameGroup(messages[index], messages[index + 1], resolveFormatDate);
|
|
132
|
+
if (!prevSame && !nextSame) return "single";
|
|
133
|
+
if (!prevSame && nextSame) return "first";
|
|
134
|
+
if (prevSame && nextSame) return "middle";
|
|
135
|
+
return "last";
|
|
136
|
+
}
|
|
137
|
+
function MessageList({ messages, renderMessage, renderDateDivider, formatDate, formatTime, renderMessageLabel, autoScroll: autoScrollProp, onScrollTop: onScrollTopProp, className }) {
|
|
138
|
+
const scrollContext = useContext(MessageViewScrollContext);
|
|
139
|
+
const resolvedAutoScroll = autoScrollProp ?? scrollContext?.autoScroll ?? true;
|
|
140
|
+
const resolvedOnScrollTop = onScrollTopProp ?? scrollContext?.onScrollTop;
|
|
141
|
+
const resolveFormatDate = formatDate ?? getDisplayDate;
|
|
142
|
+
const resolveFormatTime = formatTime ?? defaultFormatTime;
|
|
143
|
+
const { items, stickyHeaderIndices } = useMemo(() => {
|
|
144
|
+
const itemsNew = [];
|
|
145
|
+
const stickyHeaderIndicesNew = [];
|
|
146
|
+
let currentLabel = null;
|
|
147
|
+
const labelCounts = /* @__PURE__ */ new Map();
|
|
148
|
+
messages.forEach((msg, index) => {
|
|
149
|
+
const label = resolveFormatDate(msg.sentAt);
|
|
150
|
+
if (currentLabel !== label) {
|
|
151
|
+
currentLabel = label;
|
|
152
|
+
stickyHeaderIndicesNew.push(itemsNew.length);
|
|
153
|
+
const seen = labelCounts.get(label) ?? 0;
|
|
154
|
+
labelCounts.set(label, seen + 1);
|
|
155
|
+
const id = seen === 0 ? `date:${label}` : `date:${label}:${seen}`;
|
|
156
|
+
itemsNew.push({
|
|
157
|
+
type: "date",
|
|
158
|
+
id,
|
|
159
|
+
label,
|
|
160
|
+
date: msg.sentAt
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
itemsNew.push({
|
|
164
|
+
type: "message",
|
|
165
|
+
id: msg.id,
|
|
166
|
+
message: msg,
|
|
167
|
+
groupPosition: getGroupPosition(messages, index, resolveFormatDate)
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
return {
|
|
171
|
+
items: itemsNew,
|
|
172
|
+
stickyHeaderIndices: stickyHeaderIndicesNew
|
|
173
|
+
};
|
|
174
|
+
}, [messages, resolveFormatDate]);
|
|
175
|
+
return /* @__PURE__ */ jsx(LegendList, {
|
|
176
|
+
alignItemsAtEnd: true,
|
|
177
|
+
className: cn("chat-scrollbar", className),
|
|
178
|
+
contentContainerStyle: { paddingBottom: 16 },
|
|
179
|
+
data: items,
|
|
180
|
+
estimatedItemSize: 72,
|
|
181
|
+
getItemType: (item) => item.type,
|
|
182
|
+
initialScrollAtEnd: resolvedAutoScroll,
|
|
183
|
+
keyExtractor: (item) => item.id,
|
|
184
|
+
maintainScrollAtEnd: resolvedAutoScroll,
|
|
185
|
+
maintainVisibleContentPosition: true,
|
|
186
|
+
onStartReached: resolvedOnScrollTop ? () => resolvedOnScrollTop() : void 0,
|
|
187
|
+
onStartReachedThreshold: .1,
|
|
188
|
+
recycleItems: true,
|
|
189
|
+
renderItem: ({ item }) => {
|
|
190
|
+
if (item.type === "date") return renderDateDivider?.({
|
|
191
|
+
label: item.label,
|
|
192
|
+
date: item.date
|
|
193
|
+
}) ?? /* @__PURE__ */ jsx(MemoizedDateDivider, { children: item.label });
|
|
194
|
+
const { message, groupPosition } = item;
|
|
195
|
+
const label = renderMessageLabel?.(message);
|
|
196
|
+
const direction = message.direction;
|
|
197
|
+
const align = direction === "incoming" ? "start" : "end";
|
|
198
|
+
const ctx = {
|
|
199
|
+
message,
|
|
200
|
+
id: message.id,
|
|
201
|
+
direction,
|
|
202
|
+
align,
|
|
203
|
+
groupPosition,
|
|
204
|
+
label
|
|
205
|
+
};
|
|
206
|
+
return renderMessage?.(ctx) ?? /* @__PURE__ */ jsx(MemoizedMessageBubble, {
|
|
207
|
+
content: message.content || "",
|
|
208
|
+
sender: direction === "incoming" ? "user" : "bot",
|
|
209
|
+
timestamp: resolveFormatTime(message.sentAt),
|
|
210
|
+
status: message.status,
|
|
211
|
+
templateName: message.templateName || void 0,
|
|
212
|
+
label,
|
|
213
|
+
groupPosition
|
|
214
|
+
});
|
|
215
|
+
},
|
|
216
|
+
stickyHeaderIndices,
|
|
217
|
+
style: {
|
|
218
|
+
height: "100%",
|
|
219
|
+
minHeight: 0
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
function DateDivider({ children, className, ...props }) {
|
|
224
|
+
return /* @__PURE__ */ jsx("div", {
|
|
225
|
+
className: cn("sticky top-0 z-10 flex justify-center w-full py-2 pointer-events-none", className),
|
|
226
|
+
...props,
|
|
227
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
228
|
+
className: "bg-white shadow-[0_1px_0.5px_rgba(11,20,26,0.13)] text-[#54656f] text-[12.5px] font-medium px-3 py-[5px] rounded-[7.5px] uppercase pointer-events-auto",
|
|
229
|
+
children
|
|
230
|
+
})
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
function MessageViewEmpty({ className, children, ...props }) {
|
|
234
|
+
return /* @__PURE__ */ jsx("div", {
|
|
235
|
+
className: cn("relative flex flex-1 flex-col items-center justify-center bg-[#f0f2f5] text-[#667781] p-6 border-b-[6px] border-[#25d366]", className),
|
|
236
|
+
...props,
|
|
237
|
+
children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
238
|
+
/* @__PURE__ */ jsx(HugeiconsIcon, {
|
|
239
|
+
icon: Message01Icon,
|
|
240
|
+
size: 96,
|
|
241
|
+
strokeWidth: 1,
|
|
242
|
+
className: "mb-6 text-[#c6cdd2]"
|
|
243
|
+
}),
|
|
244
|
+
/* @__PURE__ */ jsx("h1", {
|
|
245
|
+
className: "mb-4 text-[32px] font-light text-[#41525d]",
|
|
246
|
+
children: "Better Zap"
|
|
247
|
+
}),
|
|
248
|
+
/* @__PURE__ */ jsxs("div", {
|
|
249
|
+
className: "max-w-md space-y-3 text-center",
|
|
250
|
+
children: [/* @__PURE__ */ jsxs("p", {
|
|
251
|
+
className: "text-sm leading-[20px]",
|
|
252
|
+
children: [
|
|
253
|
+
"Esta é uma interface dedicada para visualização e monitoramento de mensagens da ",
|
|
254
|
+
/* @__PURE__ */ jsx("strong", { children: "API Oficial do WhatsApp" }),
|
|
255
|
+
"."
|
|
256
|
+
]
|
|
257
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
258
|
+
className: "text-sm leading-[20px] opacity-80",
|
|
259
|
+
children: "Acompanhe o histórico de conversas, verifique o status de entrega e gerencie as interações do Cloud API de forma profissional."
|
|
260
|
+
})]
|
|
261
|
+
})
|
|
262
|
+
] })
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
//#endregion
|
|
266
|
+
export { DateDivider, MessageList, MessageView, MessageViewContent, MessageViewEmpty, MessageViewHeader };
|
package/dist/message.cjs
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_utils = require("./utils-Bp9IahGG.cjs");
|
|
3
|
+
let react = require("react");
|
|
4
|
+
react = require_utils.__toESM(react);
|
|
5
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
6
|
+
//#region src/message.tsx
|
|
7
|
+
function Message({ align = "start", className, ...props }) {
|
|
8
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9
|
+
"data-align": align,
|
|
10
|
+
className: require_utils.cn("group/message flex w-full gap-2", align === "start" ? "justify-start" : "justify-end", className),
|
|
11
|
+
...props
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
function MessageAvatar({ className, ...props }) {
|
|
15
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
16
|
+
className: require_utils.cn("flex size-8 shrink-0 self-end items-center justify-center overflow-hidden rounded-full bg-gray-200", className),
|
|
17
|
+
...props
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function MessageContent({ className, ...props }) {
|
|
21
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
22
|
+
className: require_utils.cn("flex min-w-0 max-w-[65%] flex-col gap-0.5 items-start group-data-[align=end]/message:items-end", className),
|
|
23
|
+
...props
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function MessageHeader({ className, ...props }) {
|
|
27
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
28
|
+
className: require_utils.cn("self-start flex items-center gap-2 px-1 text-xs text-gray-500", className),
|
|
29
|
+
...props
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function MessageFooter({ className, ...props }) {
|
|
33
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
34
|
+
className: require_utils.cn("flex items-center gap-1 px-1 text-[11px] text-gray-500", className),
|
|
35
|
+
...props
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
function MessageGroup({ className, ...props }) {
|
|
39
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
40
|
+
className: require_utils.cn("flex w-full flex-col gap-0.5", className),
|
|
41
|
+
...props
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
exports.Message = Message;
|
|
46
|
+
exports.MessageAvatar = MessageAvatar;
|
|
47
|
+
exports.MessageContent = MessageContent;
|
|
48
|
+
exports.MessageFooter = MessageFooter;
|
|
49
|
+
exports.MessageGroup = MessageGroup;
|
|
50
|
+
exports.MessageHeader = MessageHeader;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/message.d.ts
|
|
4
|
+
type MessageAlign = "start" | "end";
|
|
5
|
+
interface MessageProps extends React.ComponentProps<"div"> {
|
|
6
|
+
/** @default "start" */
|
|
7
|
+
align?: MessageAlign;
|
|
8
|
+
}
|
|
9
|
+
declare function Message({
|
|
10
|
+
align,
|
|
11
|
+
className,
|
|
12
|
+
...props
|
|
13
|
+
}: MessageProps): React.JSX.Element;
|
|
14
|
+
type MessageAvatarProps = React.ComponentProps<"div">;
|
|
15
|
+
declare function MessageAvatar({
|
|
16
|
+
className,
|
|
17
|
+
...props
|
|
18
|
+
}: MessageAvatarProps): React.JSX.Element;
|
|
19
|
+
type MessageContentProps = React.ComponentProps<"div">;
|
|
20
|
+
declare function MessageContent({
|
|
21
|
+
className,
|
|
22
|
+
...props
|
|
23
|
+
}: MessageContentProps): React.JSX.Element;
|
|
24
|
+
type MessageHeaderProps = React.ComponentProps<"div">;
|
|
25
|
+
declare function MessageHeader({
|
|
26
|
+
className,
|
|
27
|
+
...props
|
|
28
|
+
}: MessageHeaderProps): React.JSX.Element;
|
|
29
|
+
type MessageFooterProps = React.ComponentProps<"div">;
|
|
30
|
+
declare function MessageFooter({
|
|
31
|
+
className,
|
|
32
|
+
...props
|
|
33
|
+
}: MessageFooterProps): React.JSX.Element;
|
|
34
|
+
type MessageGroupProps = React.ComponentProps<"div">;
|
|
35
|
+
declare function MessageGroup({
|
|
36
|
+
className,
|
|
37
|
+
...props
|
|
38
|
+
}: MessageGroupProps): React.JSX.Element;
|
|
39
|
+
//#endregion
|
|
40
|
+
export { Message, MessageAlign, MessageAvatar, MessageAvatarProps, MessageContent, MessageContentProps, MessageFooter, MessageFooterProps, MessageGroup, MessageGroupProps, MessageHeader, MessageHeaderProps, MessageProps };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/message.d.ts
|
|
4
|
+
type MessageAlign = "start" | "end";
|
|
5
|
+
interface MessageProps extends React.ComponentProps<"div"> {
|
|
6
|
+
/** @default "start" */
|
|
7
|
+
align?: MessageAlign;
|
|
8
|
+
}
|
|
9
|
+
declare function Message({
|
|
10
|
+
align,
|
|
11
|
+
className,
|
|
12
|
+
...props
|
|
13
|
+
}: MessageProps): React.JSX.Element;
|
|
14
|
+
type MessageAvatarProps = React.ComponentProps<"div">;
|
|
15
|
+
declare function MessageAvatar({
|
|
16
|
+
className,
|
|
17
|
+
...props
|
|
18
|
+
}: MessageAvatarProps): React.JSX.Element;
|
|
19
|
+
type MessageContentProps = React.ComponentProps<"div">;
|
|
20
|
+
declare function MessageContent({
|
|
21
|
+
className,
|
|
22
|
+
...props
|
|
23
|
+
}: MessageContentProps): React.JSX.Element;
|
|
24
|
+
type MessageHeaderProps = React.ComponentProps<"div">;
|
|
25
|
+
declare function MessageHeader({
|
|
26
|
+
className,
|
|
27
|
+
...props
|
|
28
|
+
}: MessageHeaderProps): React.JSX.Element;
|
|
29
|
+
type MessageFooterProps = React.ComponentProps<"div">;
|
|
30
|
+
declare function MessageFooter({
|
|
31
|
+
className,
|
|
32
|
+
...props
|
|
33
|
+
}: MessageFooterProps): React.JSX.Element;
|
|
34
|
+
type MessageGroupProps = React.ComponentProps<"div">;
|
|
35
|
+
declare function MessageGroup({
|
|
36
|
+
className,
|
|
37
|
+
...props
|
|
38
|
+
}: MessageGroupProps): React.JSX.Element;
|
|
39
|
+
//#endregion
|
|
40
|
+
export { Message, MessageAlign, MessageAvatar, MessageAvatarProps, MessageContent, MessageContentProps, MessageFooter, MessageFooterProps, MessageGroup, MessageGroupProps, MessageHeader, MessageHeaderProps, MessageProps };
|
package/dist/message.mjs
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { cn } from "./utils.mjs";
|
|
2
|
+
import "react";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
//#region src/message.tsx
|
|
5
|
+
function Message({ align = "start", className, ...props }) {
|
|
6
|
+
return /* @__PURE__ */ jsx("div", {
|
|
7
|
+
"data-align": align,
|
|
8
|
+
className: cn("group/message flex w-full gap-2", align === "start" ? "justify-start" : "justify-end", className),
|
|
9
|
+
...props
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
function MessageAvatar({ className, ...props }) {
|
|
13
|
+
return /* @__PURE__ */ jsx("div", {
|
|
14
|
+
className: cn("flex size-8 shrink-0 self-end items-center justify-center overflow-hidden rounded-full bg-gray-200", className),
|
|
15
|
+
...props
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
function MessageContent({ className, ...props }) {
|
|
19
|
+
return /* @__PURE__ */ jsx("div", {
|
|
20
|
+
className: cn("flex min-w-0 max-w-[65%] flex-col gap-0.5 items-start group-data-[align=end]/message:items-end", className),
|
|
21
|
+
...props
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function MessageHeader({ className, ...props }) {
|
|
25
|
+
return /* @__PURE__ */ jsx("div", {
|
|
26
|
+
className: cn("self-start flex items-center gap-2 px-1 text-xs text-gray-500", className),
|
|
27
|
+
...props
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function MessageFooter({ className, ...props }) {
|
|
31
|
+
return /* @__PURE__ */ jsx("div", {
|
|
32
|
+
className: cn("flex items-center gap-1 px-1 text-[11px] text-gray-500", className),
|
|
33
|
+
...props
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
function MessageGroup({ className, ...props }) {
|
|
37
|
+
return /* @__PURE__ */ jsx("div", {
|
|
38
|
+
className: cn("flex w-full flex-col gap-0.5", className),
|
|
39
|
+
...props
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { Message, MessageAvatar, MessageContent, MessageFooter, MessageGroup, MessageHeader };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Tailwind CSS source manifest for @better-zap/react components.
|
|
3
|
+
*
|
|
4
|
+
* Consuming apps should import this file (e.g. `@import "@better-zap/react/tailwind.css"`)
|
|
5
|
+
* so that Tailwind's JIT scanner picks up every utility class used by the components.
|
|
6
|
+
*
|
|
7
|
+
* The `@source "."` directive tells Tailwind to scan all recognised file types
|
|
8
|
+
* in this directory, and the path resolves relative to THIS file — so it works
|
|
9
|
+
* regardless of where the consuming app lives in the monorepo.
|
|
10
|
+
*/
|
|
11
|
+
@source ".";
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
* WhatsApp-style thin scrollbar used by ConversationList and MessageList.
|
|
15
|
+
* Plain CSS (not utilities) so it ships even without Tailwind plugins.
|
|
16
|
+
*/
|
|
17
|
+
.chat-scrollbar {
|
|
18
|
+
scrollbar-width: thin;
|
|
19
|
+
scrollbar-color: rgba(11, 20, 26, 0.2) transparent;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.chat-scrollbar::-webkit-scrollbar {
|
|
23
|
+
width: 6px;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.chat-scrollbar::-webkit-scrollbar-track {
|
|
27
|
+
background: transparent;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.chat-scrollbar::-webkit-scrollbar-thumb {
|
|
31
|
+
background: rgba(11, 20, 26, 0.2);
|
|
32
|
+
border-radius: 3px;
|
|
33
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
//#endregion
|
|
23
|
+
let react = require("react");
|
|
24
|
+
react = __toESM(react);
|
|
25
|
+
let clsx = require("clsx");
|
|
26
|
+
let tailwind_merge = require("tailwind-merge");
|
|
27
|
+
//#region src/utils.ts
|
|
28
|
+
function cn(...inputs) {
|
|
29
|
+
return (0, tailwind_merge.twMerge)((0, clsx.clsx)(inputs));
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Base UI-style element polymorphism: merge part props onto a render element.
|
|
33
|
+
* - className: cn(computed, render.props.className)
|
|
34
|
+
* - style: { ...computed.style, ...render.props.style }
|
|
35
|
+
* - other props: render element's own props win
|
|
36
|
+
* - children: part children win unless render element already has children
|
|
37
|
+
*/
|
|
38
|
+
function renderSlot(render, computed) {
|
|
39
|
+
const renderProps = render.props;
|
|
40
|
+
const merged = {
|
|
41
|
+
...computed,
|
|
42
|
+
...renderProps,
|
|
43
|
+
className: cn(computed.className, renderProps.className),
|
|
44
|
+
style: {
|
|
45
|
+
...computed.style ?? {},
|
|
46
|
+
...renderProps.style ?? {}
|
|
47
|
+
},
|
|
48
|
+
children: renderProps.children !== void 0 && renderProps.children !== null ? renderProps.children : computed.children
|
|
49
|
+
};
|
|
50
|
+
return react.default.cloneElement(render, merged);
|
|
51
|
+
}
|
|
52
|
+
function getDisplayDate(dateStr) {
|
|
53
|
+
const dateObj = new Date(dateStr);
|
|
54
|
+
const now = /* @__PURE__ */ new Date();
|
|
55
|
+
const isToday = dateObj.toDateString() === now.toDateString();
|
|
56
|
+
const yesterday = new Date(now);
|
|
57
|
+
yesterday.setDate(yesterday.getDate() - 1);
|
|
58
|
+
const isYesterday = dateObj.toDateString() === yesterday.toDateString();
|
|
59
|
+
if (isToday) return "HOJE";
|
|
60
|
+
else if (isYesterday) return "ONTEM";
|
|
61
|
+
else return dateObj.toLocaleDateString("pt-BR", {
|
|
62
|
+
day: "2-digit",
|
|
63
|
+
month: "2-digit",
|
|
64
|
+
year: "numeric"
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
//#endregion
|
|
68
|
+
Object.defineProperty(exports, "__toESM", {
|
|
69
|
+
enumerable: true,
|
|
70
|
+
get: function() {
|
|
71
|
+
return __toESM;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
Object.defineProperty(exports, "cn", {
|
|
75
|
+
enumerable: true,
|
|
76
|
+
get: function() {
|
|
77
|
+
return cn;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
Object.defineProperty(exports, "getDisplayDate", {
|
|
81
|
+
enumerable: true,
|
|
82
|
+
get: function() {
|
|
83
|
+
return getDisplayDate;
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
Object.defineProperty(exports, "renderSlot", {
|
|
87
|
+
enumerable: true,
|
|
88
|
+
get: function() {
|
|
89
|
+
return renderSlot;
|
|
90
|
+
}
|
|
91
|
+
});
|
package/dist/utils.cjs
ADDED