@better-zap/react 0.2.0 → 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.
Files changed (50) hide show
  1. package/dist/bubble.cjs +93 -0
  2. package/dist/bubble.d.cts +61 -0
  3. package/dist/bubble.d.mts +61 -0
  4. package/dist/bubble.mjs +89 -0
  5. package/dist/composer.cjs +220 -0
  6. package/dist/composer.d.cts +96 -0
  7. package/dist/composer.d.mts +96 -0
  8. package/dist/composer.mjs +211 -0
  9. package/dist/conversation-list-BlhJhDsc.d.cts +100 -0
  10. package/dist/conversation-list-BwQ4oK2J.d.mts +100 -0
  11. package/dist/conversation-list-C0EmReS-.mjs +293 -0
  12. package/dist/conversation-list-CVWdddJh.cjs +311 -0
  13. package/dist/conversation-list.cjs +6 -0
  14. package/dist/conversation-list.d.cts +2 -0
  15. package/dist/conversation-list.d.mts +2 -0
  16. package/dist/conversation-list.mjs +5 -0
  17. package/dist/index.cjs +49 -0
  18. package/dist/index.d.cts +19 -0
  19. package/dist/index.d.mts +19 -0
  20. package/dist/index.mjs +11 -0
  21. package/dist/message-bubble.cjs +116 -0
  22. package/dist/message-bubble.d.cts +38 -0
  23. package/dist/message-bubble.d.mts +38 -0
  24. package/dist/message-bubble.mjs +114 -0
  25. package/dist/message-input-CkaL6fb4.mjs +173 -0
  26. package/dist/message-input-DcEzHQ9t.cjs +191 -0
  27. package/dist/message-input.cjs +6 -0
  28. package/dist/message-input.d.cts +51 -0
  29. package/dist/message-input.d.mts +51 -0
  30. package/dist/message-input.mjs +5 -0
  31. package/dist/message-view.cjs +273 -0
  32. package/dist/message-view.d.cts +109 -0
  33. package/dist/message-view.d.mts +109 -0
  34. package/dist/message-view.mjs +266 -0
  35. package/dist/message.cjs +50 -0
  36. package/dist/message.d.cts +40 -0
  37. package/dist/message.d.mts +40 -0
  38. package/dist/message.mjs +43 -0
  39. package/dist/tailwind.css +33 -0
  40. package/dist/utils-Bp9IahGG.cjs +91 -0
  41. package/dist/utils.cjs +5 -0
  42. package/dist/utils.d.cts +20 -0
  43. package/dist/utils.d.mts +20 -0
  44. package/dist/utils.mjs +45 -0
  45. package/dist/whatsapp-dashboard.cjs +64 -0
  46. package/dist/whatsapp-dashboard.d.cts +33 -0
  47. package/dist/whatsapp-dashboard.d.mts +33 -0
  48. package/dist/whatsapp-dashboard.mjs +60 -0
  49. package/dist/wpp-bg.webp +0 -0
  50. 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 };
@@ -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 };
@@ -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
@@ -0,0 +1,5 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_utils = require("./utils-Bp9IahGG.cjs");
3
+ exports.cn = require_utils.cn;
4
+ exports.getDisplayDate = require_utils.getDisplayDate;
5
+ exports.renderSlot = require_utils.renderSlot;