@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.
- 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,96 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/composer.d.ts
|
|
4
|
+
interface ComposerContextValue {
|
|
5
|
+
value: string;
|
|
6
|
+
setValue: (value: string) => void;
|
|
7
|
+
isSending: boolean;
|
|
8
|
+
disabled: boolean;
|
|
9
|
+
/** value.trim() is non-empty && !disabled && !isSending */
|
|
10
|
+
canSend: boolean;
|
|
11
|
+
/** null when no failed send is pending display */
|
|
12
|
+
error: unknown;
|
|
13
|
+
clearError: () => void;
|
|
14
|
+
/** Fire-and-forget; never rejects. See send() algorithm. */
|
|
15
|
+
send: () => void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Everything except the live draft string. Changes only on boundary events
|
|
19
|
+
* (empty <-> non-empty, send lifecycle, errors), so consumers skip the
|
|
20
|
+
* per-keystroke re-render that `useComposer` implies.
|
|
21
|
+
*/
|
|
22
|
+
interface ComposerStateContextValue extends Omit<ComposerContextValue, "value"> {
|
|
23
|
+
/** value.trim() is non-empty. Boundary-stable, unlike `value` itself. */
|
|
24
|
+
hasText: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** The live draft string. Consumers re-render on every keystroke. */
|
|
27
|
+
declare function useComposerValue(): string;
|
|
28
|
+
/**
|
|
29
|
+
* Actions and boundary-stable flags without the live draft. Prefer this in
|
|
30
|
+
* children that don't display the text (send/attach buttons, error slots) so
|
|
31
|
+
* they don't re-render per keystroke.
|
|
32
|
+
*/
|
|
33
|
+
declare function useComposerState(): ComposerStateContextValue;
|
|
34
|
+
/** Full composer context. Subscribes to the draft: re-renders per keystroke. */
|
|
35
|
+
declare function useComposer(): ComposerContextValue;
|
|
36
|
+
interface ComposerProps extends Omit<React.ComponentProps<"div">, "onSubmit" | "onError"> {
|
|
37
|
+
value?: string;
|
|
38
|
+
defaultValue?: string;
|
|
39
|
+
onValueChange?: (value: string) => void;
|
|
40
|
+
/** Required. Throw/reject to signal failure; the draft is preserved. */
|
|
41
|
+
onSubmit: (text: string) => void | Promise<void>;
|
|
42
|
+
onError?: (error: unknown, context: {
|
|
43
|
+
text: string;
|
|
44
|
+
}) => void;
|
|
45
|
+
disabled?: boolean;
|
|
46
|
+
}
|
|
47
|
+
declare function Composer({
|
|
48
|
+
value,
|
|
49
|
+
defaultValue,
|
|
50
|
+
onValueChange,
|
|
51
|
+
onSubmit,
|
|
52
|
+
onError,
|
|
53
|
+
disabled,
|
|
54
|
+
className,
|
|
55
|
+
children,
|
|
56
|
+
...props
|
|
57
|
+
}: ComposerProps): React.JSX.Element;
|
|
58
|
+
interface ComposerTextareaProps extends React.ComponentProps<"textarea"> {
|
|
59
|
+
/** Enter sends (Shift+Enter = newline). Ignores IME composition. @default true */
|
|
60
|
+
submitOnEnter?: boolean;
|
|
61
|
+
}
|
|
62
|
+
declare function ComposerTextarea({
|
|
63
|
+
submitOnEnter,
|
|
64
|
+
className,
|
|
65
|
+
disabled: disabledProp,
|
|
66
|
+
onKeyDown,
|
|
67
|
+
onChange,
|
|
68
|
+
...props
|
|
69
|
+
}: ComposerTextareaProps): React.JSX.Element;
|
|
70
|
+
type ComposerSendProps = React.ComponentProps<"button">;
|
|
71
|
+
declare function ComposerSend({
|
|
72
|
+
className,
|
|
73
|
+
disabled: disabledProp,
|
|
74
|
+
onClick,
|
|
75
|
+
children,
|
|
76
|
+
type,
|
|
77
|
+
...props
|
|
78
|
+
}: ComposerSendProps): React.JSX.Element;
|
|
79
|
+
type ComposerButtonProps = React.ComponentProps<"button">;
|
|
80
|
+
declare function ComposerButton({
|
|
81
|
+
className,
|
|
82
|
+
disabled: disabledProp,
|
|
83
|
+
type,
|
|
84
|
+
...props
|
|
85
|
+
}: ComposerButtonProps): React.JSX.Element;
|
|
86
|
+
interface ComposerErrorProps extends Omit<React.ComponentProps<"div">, "children"> {
|
|
87
|
+
/** Static node, or a function receiving the error. */
|
|
88
|
+
children?: React.ReactNode | ((error: unknown) => React.ReactNode);
|
|
89
|
+
}
|
|
90
|
+
declare function ComposerError({
|
|
91
|
+
children,
|
|
92
|
+
className,
|
|
93
|
+
...props
|
|
94
|
+
}: ComposerErrorProps): React.JSX.Element | null;
|
|
95
|
+
//#endregion
|
|
96
|
+
export { Composer, ComposerButton, ComposerButtonProps, ComposerContextValue, ComposerError, ComposerErrorProps, ComposerProps, ComposerSend, ComposerSendProps, ComposerStateContextValue, ComposerTextarea, ComposerTextareaProps, useComposer, useComposerState, useComposerValue };
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "./utils.mjs";
|
|
3
|
+
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
import { HugeiconsIcon } from "@hugeicons/react";
|
|
6
|
+
import { Sent02Icon } from "@hugeicons/core-free-icons";
|
|
7
|
+
//#region src/composer.tsx
|
|
8
|
+
const ComposerValueContext = createContext(null);
|
|
9
|
+
const ComposerStateContext = createContext(null);
|
|
10
|
+
/** The live draft string. Consumers re-render on every keystroke. */
|
|
11
|
+
function useComposerValue() {
|
|
12
|
+
const value = useContext(ComposerValueContext);
|
|
13
|
+
if (value === null) throw new Error("useComposerValue must be used within <Composer>");
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Actions and boundary-stable flags without the live draft. Prefer this in
|
|
18
|
+
* children that don't display the text (send/attach buttons, error slots) so
|
|
19
|
+
* they don't re-render per keystroke.
|
|
20
|
+
*/
|
|
21
|
+
function useComposerState() {
|
|
22
|
+
const ctx = useContext(ComposerStateContext);
|
|
23
|
+
if (!ctx) throw new Error("useComposerState must be used within <Composer>");
|
|
24
|
+
return ctx;
|
|
25
|
+
}
|
|
26
|
+
/** Full composer context. Subscribes to the draft: re-renders per keystroke. */
|
|
27
|
+
function useComposer() {
|
|
28
|
+
const ctx = useContext(ComposerStateContext);
|
|
29
|
+
const value = useContext(ComposerValueContext);
|
|
30
|
+
if (!ctx || value === null) throw new Error("useComposer must be used within <Composer>");
|
|
31
|
+
const { hasText: _hasText, ...rest } = ctx;
|
|
32
|
+
return {
|
|
33
|
+
...rest,
|
|
34
|
+
value
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const PILL_CLASS = "flex flex-wrap items-center gap-1 px-2 py-1 min-h-[52px] bg-white rounded-[24px] shadow-[0_1px_3px_rgba(11,20,26,0.12)]";
|
|
38
|
+
/**
|
|
39
|
+
* Owns draft/send state below the pill markup, so uncontrolled keystrokes
|
|
40
|
+
* re-render this provider and draft consumers only, never the pill div or
|
|
41
|
+
* children that stick to useComposerState.
|
|
42
|
+
*/
|
|
43
|
+
function ComposerProvider({ value: valueProp, defaultValue, onValueChange, onSubmit, onError, disabled, children }) {
|
|
44
|
+
const isControlled = valueProp !== void 0;
|
|
45
|
+
const [internalValue, setInternalValue] = useState(defaultValue);
|
|
46
|
+
const [isSending, setIsSending] = useState(false);
|
|
47
|
+
const [error, setError] = useState(null);
|
|
48
|
+
const value = isControlled ? valueProp : internalValue;
|
|
49
|
+
const valueRef = useRef(value);
|
|
50
|
+
valueRef.current = value;
|
|
51
|
+
const disabledRef = useRef(disabled);
|
|
52
|
+
disabledRef.current = disabled;
|
|
53
|
+
const isSendingRef = useRef(false);
|
|
54
|
+
const onSubmitRef = useRef(onSubmit);
|
|
55
|
+
onSubmitRef.current = onSubmit;
|
|
56
|
+
const onErrorRef = useRef(onError);
|
|
57
|
+
onErrorRef.current = onError;
|
|
58
|
+
const onValueChangeRef = useRef(onValueChange);
|
|
59
|
+
onValueChangeRef.current = onValueChange;
|
|
60
|
+
const isControlledRef = useRef(isControlled);
|
|
61
|
+
isControlledRef.current = isControlled;
|
|
62
|
+
const setValue = useCallback((next) => {
|
|
63
|
+
if (!isControlledRef.current) setInternalValue(next);
|
|
64
|
+
onValueChangeRef.current?.(next);
|
|
65
|
+
}, []);
|
|
66
|
+
const clearError = useCallback(() => {
|
|
67
|
+
setError(null);
|
|
68
|
+
}, []);
|
|
69
|
+
const send = useCallback(() => {
|
|
70
|
+
(async () => {
|
|
71
|
+
const text = valueRef.current.trim();
|
|
72
|
+
if (!text || disabledRef.current || isSendingRef.current) return;
|
|
73
|
+
setError(null);
|
|
74
|
+
isSendingRef.current = true;
|
|
75
|
+
setIsSending(true);
|
|
76
|
+
try {
|
|
77
|
+
await onSubmitRef.current(text);
|
|
78
|
+
setValue("");
|
|
79
|
+
} catch (err) {
|
|
80
|
+
setError(err);
|
|
81
|
+
onErrorRef.current?.(err, { text });
|
|
82
|
+
} finally {
|
|
83
|
+
isSendingRef.current = false;
|
|
84
|
+
setIsSending(false);
|
|
85
|
+
}
|
|
86
|
+
})();
|
|
87
|
+
}, [setValue]);
|
|
88
|
+
const hasText = value.trim().length > 0;
|
|
89
|
+
const canSend = hasText && !disabled && !isSending;
|
|
90
|
+
const stateValue = useMemo(() => ({
|
|
91
|
+
setValue,
|
|
92
|
+
isSending,
|
|
93
|
+
disabled,
|
|
94
|
+
canSend,
|
|
95
|
+
hasText,
|
|
96
|
+
error,
|
|
97
|
+
clearError,
|
|
98
|
+
send
|
|
99
|
+
}), [
|
|
100
|
+
setValue,
|
|
101
|
+
isSending,
|
|
102
|
+
disabled,
|
|
103
|
+
canSend,
|
|
104
|
+
hasText,
|
|
105
|
+
error,
|
|
106
|
+
clearError,
|
|
107
|
+
send
|
|
108
|
+
]);
|
|
109
|
+
return /* @__PURE__ */ jsx(ComposerStateContext.Provider, {
|
|
110
|
+
value: stateValue,
|
|
111
|
+
children: /* @__PURE__ */ jsx(ComposerValueContext.Provider, {
|
|
112
|
+
value,
|
|
113
|
+
children
|
|
114
|
+
})
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
function Composer({ value, defaultValue = "", onValueChange, onSubmit, onError, disabled = false, className, children, ...props }) {
|
|
118
|
+
return /* @__PURE__ */ jsx("div", {
|
|
119
|
+
className: cn(PILL_CLASS, className),
|
|
120
|
+
...props,
|
|
121
|
+
children: /* @__PURE__ */ jsx(ComposerProvider, {
|
|
122
|
+
value,
|
|
123
|
+
defaultValue,
|
|
124
|
+
onValueChange,
|
|
125
|
+
onSubmit,
|
|
126
|
+
onError,
|
|
127
|
+
disabled,
|
|
128
|
+
children
|
|
129
|
+
})
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
const TEXTAREA_CLASS = "flex-1 bg-transparent border-none text-[15px] leading-[22px] text-[#111b21] resize-none focus:outline-none max-h-[120px] placeholder:text-[#8696a0]";
|
|
133
|
+
function ComposerTextarea({ submitOnEnter = true, className, disabled: disabledProp, onKeyDown, onChange, ...props }) {
|
|
134
|
+
const value = useComposerValue();
|
|
135
|
+
const { setValue, disabled, isSending, send } = useComposerState();
|
|
136
|
+
const textareaRef = useRef(null);
|
|
137
|
+
const isDisabled = disabled || isSending || !!disabledProp;
|
|
138
|
+
useEffect(() => {
|
|
139
|
+
const el = textareaRef.current;
|
|
140
|
+
if (!el) return;
|
|
141
|
+
el.style.height = "auto";
|
|
142
|
+
if (value === "") return;
|
|
143
|
+
el.style.height = `${el.scrollHeight}px`;
|
|
144
|
+
}, [value]);
|
|
145
|
+
const handleKeyDown = (e) => {
|
|
146
|
+
onKeyDown?.(e);
|
|
147
|
+
if (e.defaultPrevented) return;
|
|
148
|
+
if (!submitOnEnter) return;
|
|
149
|
+
if (e.key !== "Enter" || e.shiftKey) return;
|
|
150
|
+
if (e.nativeEvent.isComposing) return;
|
|
151
|
+
e.preventDefault();
|
|
152
|
+
send();
|
|
153
|
+
};
|
|
154
|
+
const handleChange = (e) => {
|
|
155
|
+
setValue(e.target.value);
|
|
156
|
+
onChange?.(e);
|
|
157
|
+
};
|
|
158
|
+
return /* @__PURE__ */ jsx("textarea", {
|
|
159
|
+
ref: textareaRef,
|
|
160
|
+
className: cn(TEXTAREA_CLASS, className),
|
|
161
|
+
name: "message",
|
|
162
|
+
autoComplete: "off",
|
|
163
|
+
rows: 1,
|
|
164
|
+
value,
|
|
165
|
+
onChange: handleChange,
|
|
166
|
+
onKeyDown: handleKeyDown,
|
|
167
|
+
disabled: isDisabled,
|
|
168
|
+
...props
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
function ComposerSend({ className, disabled: disabledProp, onClick, children, type = "button", ...props }) {
|
|
172
|
+
const { canSend, send } = useComposerState();
|
|
173
|
+
const handleClick = (e) => {
|
|
174
|
+
send();
|
|
175
|
+
onClick?.(e);
|
|
176
|
+
};
|
|
177
|
+
return /* @__PURE__ */ jsx("button", {
|
|
178
|
+
type,
|
|
179
|
+
className: cn("flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-[#00a884] text-white transition-colors hover:bg-[#008f72] disabled:opacity-40 disabled:cursor-not-allowed", className),
|
|
180
|
+
disabled: !canSend || !!disabledProp,
|
|
181
|
+
onClick: handleClick,
|
|
182
|
+
...props,
|
|
183
|
+
children: children ?? /* @__PURE__ */ jsx(HugeiconsIcon, {
|
|
184
|
+
icon: Sent02Icon,
|
|
185
|
+
size: 20
|
|
186
|
+
})
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
function ComposerButton({ className, disabled: disabledProp, type = "button", ...props }) {
|
|
190
|
+
const { isSending } = useComposerState();
|
|
191
|
+
const isDisabled = disabledProp !== void 0 ? disabledProp : isSending;
|
|
192
|
+
return /* @__PURE__ */ jsx("button", {
|
|
193
|
+
type,
|
|
194
|
+
className: cn("p-2 rounded-full hover:bg-black/5 transition-colors disabled:opacity-40", className),
|
|
195
|
+
disabled: isDisabled,
|
|
196
|
+
...props
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
function ComposerError({ children, className, ...props }) {
|
|
200
|
+
const { error } = useComposerState();
|
|
201
|
+
if (error == null) return null;
|
|
202
|
+
const content = typeof children === "function" ? children(error) : children;
|
|
203
|
+
return /* @__PURE__ */ jsx("div", {
|
|
204
|
+
role: "alert",
|
|
205
|
+
className: cn("w-full order-last", className),
|
|
206
|
+
...props,
|
|
207
|
+
children: content
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
//#endregion
|
|
211
|
+
export { Composer, ComposerButton, ComposerError, ComposerSend, ComposerTextarea, useComposer, useComposerState, useComposerValue };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
|
+
import { Conversation } from "better-zap";
|
|
4
|
+
|
|
5
|
+
//#region src/conversation-filter-chips.d.ts
|
|
6
|
+
type ConversationFilterValue = "all" | "unread";
|
|
7
|
+
interface ConversationFilterChipsProps {
|
|
8
|
+
value: ConversationFilterValue;
|
|
9
|
+
onValueChange: (value: ConversationFilterValue) => void;
|
|
10
|
+
unreadCount?: number;
|
|
11
|
+
className?: string;
|
|
12
|
+
labels?: {
|
|
13
|
+
all: string;
|
|
14
|
+
unread: string;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Memoized: with stable onValueChange and labels, typing in the search box
|
|
19
|
+
* doesn't re-render the chips.
|
|
20
|
+
*/
|
|
21
|
+
declare const ConversationFilterChips: React.MemoExoticComponent<({
|
|
22
|
+
value,
|
|
23
|
+
onValueChange,
|
|
24
|
+
unreadCount,
|
|
25
|
+
className,
|
|
26
|
+
labels
|
|
27
|
+
}: ConversationFilterChipsProps) => react_jsx_runtime0.JSX.Element>;
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region src/conversation-list.d.ts
|
|
30
|
+
interface ConversationListLabels {
|
|
31
|
+
searchPlaceholder: string;
|
|
32
|
+
searchLabel: string;
|
|
33
|
+
filterAll: string;
|
|
34
|
+
filterUnread: string;
|
|
35
|
+
loading: string;
|
|
36
|
+
error: string;
|
|
37
|
+
empty: string;
|
|
38
|
+
outgoingPrefix: string;
|
|
39
|
+
noPreview: string;
|
|
40
|
+
yesterday: string;
|
|
41
|
+
}
|
|
42
|
+
interface ConversationListProps extends Omit<React.ComponentProps<"div">, "onSelect"> {
|
|
43
|
+
conversations: Conversation[];
|
|
44
|
+
isLoading?: boolean;
|
|
45
|
+
isError?: boolean;
|
|
46
|
+
selectedConversationId?: string | null;
|
|
47
|
+
onSelect?: (id: string) => void;
|
|
48
|
+
search?: string;
|
|
49
|
+
defaultSearch?: string;
|
|
50
|
+
onSearchChange?: (value: string) => void;
|
|
51
|
+
filter?: ConversationFilterValue;
|
|
52
|
+
defaultFilter?: ConversationFilterValue;
|
|
53
|
+
onFilterChange?: (value: ConversationFilterValue) => void;
|
|
54
|
+
renderItem?: (conversation: Conversation, context: {
|
|
55
|
+
isSelected: boolean;
|
|
56
|
+
select: () => void;
|
|
57
|
+
}) => React.ReactNode;
|
|
58
|
+
renderAvatar?: (conversation: Conversation) => React.ReactNode;
|
|
59
|
+
formatTime?: (isoDate: string) => string;
|
|
60
|
+
labels?: Partial<ConversationListLabels>;
|
|
61
|
+
}
|
|
62
|
+
declare function ConversationList({
|
|
63
|
+
conversations,
|
|
64
|
+
isLoading,
|
|
65
|
+
isError,
|
|
66
|
+
selectedConversationId,
|
|
67
|
+
onSelect,
|
|
68
|
+
search: searchProp,
|
|
69
|
+
defaultSearch,
|
|
70
|
+
onSearchChange,
|
|
71
|
+
filter: filterProp,
|
|
72
|
+
defaultFilter,
|
|
73
|
+
onFilterChange,
|
|
74
|
+
renderItem,
|
|
75
|
+
renderAvatar,
|
|
76
|
+
formatTime: formatTimeProp,
|
|
77
|
+
labels: labelsProp,
|
|
78
|
+
className,
|
|
79
|
+
...props
|
|
80
|
+
}: ConversationListProps): react_jsx_runtime0.JSX.Element;
|
|
81
|
+
interface ConversationItemProps extends React.ComponentProps<"button"> {
|
|
82
|
+
conversation: Conversation;
|
|
83
|
+
isSelected?: boolean;
|
|
84
|
+
avatar?: React.ReactNode;
|
|
85
|
+
outgoingPrefix?: string;
|
|
86
|
+
noPreviewLabel?: string;
|
|
87
|
+
formatTime?: (isoDate: string) => string;
|
|
88
|
+
}
|
|
89
|
+
declare function ConversationItem({
|
|
90
|
+
conversation,
|
|
91
|
+
isSelected,
|
|
92
|
+
avatar,
|
|
93
|
+
outgoingPrefix,
|
|
94
|
+
noPreviewLabel,
|
|
95
|
+
formatTime: formatTimeProp,
|
|
96
|
+
className,
|
|
97
|
+
...props
|
|
98
|
+
}: ConversationItemProps): react_jsx_runtime0.JSX.Element;
|
|
99
|
+
//#endregion
|
|
100
|
+
export { ConversationListProps as a, ConversationFilterValue as c, ConversationListLabels as i, ConversationItemProps as n, ConversationFilterChips as o, ConversationList as r, ConversationFilterChipsProps as s, ConversationItem as t };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
|
+
import { Conversation } from "better-zap";
|
|
4
|
+
|
|
5
|
+
//#region src/conversation-filter-chips.d.ts
|
|
6
|
+
type ConversationFilterValue = "all" | "unread";
|
|
7
|
+
interface ConversationFilterChipsProps {
|
|
8
|
+
value: ConversationFilterValue;
|
|
9
|
+
onValueChange: (value: ConversationFilterValue) => void;
|
|
10
|
+
unreadCount?: number;
|
|
11
|
+
className?: string;
|
|
12
|
+
labels?: {
|
|
13
|
+
all: string;
|
|
14
|
+
unread: string;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Memoized: with stable onValueChange and labels, typing in the search box
|
|
19
|
+
* doesn't re-render the chips.
|
|
20
|
+
*/
|
|
21
|
+
declare const ConversationFilterChips: React.MemoExoticComponent<({
|
|
22
|
+
value,
|
|
23
|
+
onValueChange,
|
|
24
|
+
unreadCount,
|
|
25
|
+
className,
|
|
26
|
+
labels
|
|
27
|
+
}: ConversationFilterChipsProps) => react_jsx_runtime0.JSX.Element>;
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region src/conversation-list.d.ts
|
|
30
|
+
interface ConversationListLabels {
|
|
31
|
+
searchPlaceholder: string;
|
|
32
|
+
searchLabel: string;
|
|
33
|
+
filterAll: string;
|
|
34
|
+
filterUnread: string;
|
|
35
|
+
loading: string;
|
|
36
|
+
error: string;
|
|
37
|
+
empty: string;
|
|
38
|
+
outgoingPrefix: string;
|
|
39
|
+
noPreview: string;
|
|
40
|
+
yesterday: string;
|
|
41
|
+
}
|
|
42
|
+
interface ConversationListProps extends Omit<React.ComponentProps<"div">, "onSelect"> {
|
|
43
|
+
conversations: Conversation[];
|
|
44
|
+
isLoading?: boolean;
|
|
45
|
+
isError?: boolean;
|
|
46
|
+
selectedConversationId?: string | null;
|
|
47
|
+
onSelect?: (id: string) => void;
|
|
48
|
+
search?: string;
|
|
49
|
+
defaultSearch?: string;
|
|
50
|
+
onSearchChange?: (value: string) => void;
|
|
51
|
+
filter?: ConversationFilterValue;
|
|
52
|
+
defaultFilter?: ConversationFilterValue;
|
|
53
|
+
onFilterChange?: (value: ConversationFilterValue) => void;
|
|
54
|
+
renderItem?: (conversation: Conversation, context: {
|
|
55
|
+
isSelected: boolean;
|
|
56
|
+
select: () => void;
|
|
57
|
+
}) => React.ReactNode;
|
|
58
|
+
renderAvatar?: (conversation: Conversation) => React.ReactNode;
|
|
59
|
+
formatTime?: (isoDate: string) => string;
|
|
60
|
+
labels?: Partial<ConversationListLabels>;
|
|
61
|
+
}
|
|
62
|
+
declare function ConversationList({
|
|
63
|
+
conversations,
|
|
64
|
+
isLoading,
|
|
65
|
+
isError,
|
|
66
|
+
selectedConversationId,
|
|
67
|
+
onSelect,
|
|
68
|
+
search: searchProp,
|
|
69
|
+
defaultSearch,
|
|
70
|
+
onSearchChange,
|
|
71
|
+
filter: filterProp,
|
|
72
|
+
defaultFilter,
|
|
73
|
+
onFilterChange,
|
|
74
|
+
renderItem,
|
|
75
|
+
renderAvatar,
|
|
76
|
+
formatTime: formatTimeProp,
|
|
77
|
+
labels: labelsProp,
|
|
78
|
+
className,
|
|
79
|
+
...props
|
|
80
|
+
}: ConversationListProps): react_jsx_runtime0.JSX.Element;
|
|
81
|
+
interface ConversationItemProps extends React.ComponentProps<"button"> {
|
|
82
|
+
conversation: Conversation;
|
|
83
|
+
isSelected?: boolean;
|
|
84
|
+
avatar?: React.ReactNode;
|
|
85
|
+
outgoingPrefix?: string;
|
|
86
|
+
noPreviewLabel?: string;
|
|
87
|
+
formatTime?: (isoDate: string) => string;
|
|
88
|
+
}
|
|
89
|
+
declare function ConversationItem({
|
|
90
|
+
conversation,
|
|
91
|
+
isSelected,
|
|
92
|
+
avatar,
|
|
93
|
+
outgoingPrefix,
|
|
94
|
+
noPreviewLabel,
|
|
95
|
+
formatTime: formatTimeProp,
|
|
96
|
+
className,
|
|
97
|
+
...props
|
|
98
|
+
}: ConversationItemProps): react_jsx_runtime0.JSX.Element;
|
|
99
|
+
//#endregion
|
|
100
|
+
export { ConversationListProps as a, ConversationFilterValue as c, ConversationListLabels as i, ConversationItemProps as n, ConversationFilterChips as o, ConversationList as r, ConversationFilterChipsProps as s, ConversationItem as t };
|