@alcheme/game-chat-react 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # @alcheme/game-chat-react
2
+
3
+ HTML diagram: [Open this subproject map](../../docs/architecture/subproject-maps.html#game-chat-react).
4
+
5
+ Optional React components for external app or runtime integrations that want a simple UI on top of the Alcheme headless communication and voice clients.
6
+
7
+ This package is intentionally adapter-based. It does not require API users to use React, and it does not import Plaza, draft, semantic, knowledge, transcript, or recap controls.
8
+
9
+ ## System Position
10
+
11
+ ```mermaid
12
+ flowchart LR
13
+ app["external app UI"] --> package["@alcheme/game-chat-react"]
14
+ package --> chat["ChatPanel"]
15
+ package --> voice["VoiceControls"]
16
+ chat --> adapter["host-supplied GameChatClientAdapter"]
17
+ voice --> voice_adapter["host-supplied VoiceClientAdapter"]
18
+ adapter -. "may wrap" .-> sdk["@alcheme/sdk runtime clients"]
19
+ voice_adapter -. "may wrap" .-> sdk
20
+ sdk --> query["query-api communication / voice routes"]
21
+ ```
22
+
23
+ ## Component Map
24
+
25
+ ```mermaid
26
+ flowchart TB
27
+ index["src/index.ts"] --> chat["ChatPanel"]
28
+ index --> voice["VoiceControls"]
29
+ chat --> list["listRoomMessages"]
30
+ chat --> send["sendRoomMessage"]
31
+ chat --> stream["subscribeRoomMessages"]
32
+ voice --> join["joinVoice"]
33
+ voice --> mute["setMutedBySelf"]
34
+ voice --> leave["leave"]
35
+ ```
36
+
37
+ ## Responsibility
38
+
39
+ - Provides optional React UI for chat messages and voice controls.
40
+ - Depends on adapters supplied by the host application instead of importing Plaza or Alcheme product UI.
41
+ - Keeps external app integrations compatible with headless SDK runtime clients.
42
+ - Leaves authentication, wallet signing, room claims, and provider setup to the host application.
43
+
44
+ ## Build
45
+
46
+ ```bash
47
+ npm --workspace @alcheme/game-chat-react run build
48
+ ```
49
+
50
+ ## Components
51
+
52
+ - `ChatPanel`: message list, composer, send state, and stream reconnect state.
53
+ - `VoiceControls`: join/leave, mute/unmute, and participant list.
54
+
55
+ Pass adapters compatible with the existing headless SDK runtime methods.
56
+
57
+ ## Entry Points
58
+
59
+ | Surface | File |
60
+ | --- | --- |
61
+ | Package exports | `packages/game-chat-react/src/index.ts` |
62
+ | Chat UI | `packages/game-chat-react/src/ChatPanel.tsx` |
63
+ | Voice UI | `packages/game-chat-react/src/VoiceControls.tsx` |
64
+ | Build config | `packages/game-chat-react/tsconfig.json` |
65
+
66
+ ## Blind Spots To Check
67
+
68
+ | Question | Evidence Needed |
69
+ | --- | --- |
70
+ | Which adapter methods should be treated as stable public API? | Compare `ChatPanel.tsx`, `VoiceControls.tsx`, SDK runtime clients, and external example usage. |
71
+ | Which styling contract should host apps expect? | Inspect exported class names and any future CSS package decisions. |
72
+ | Which voice provider states need richer UI? | Compare `VoiceConnectionState` with query-api voice provider capabilities. |
@@ -0,0 +1,51 @@
1
+ import type { ReactNode } from "react";
2
+ export interface GameChatMessage {
3
+ id?: string;
4
+ envelopeId?: string;
5
+ lamport?: number;
6
+ messageKind?: "plain" | "voice_clip" | string;
7
+ senderHandle?: string | null;
8
+ senderPubkey?: string | null;
9
+ text?: string | null;
10
+ payloadText?: string | null;
11
+ storageUri?: string | null;
12
+ durationMs?: number | null;
13
+ createdAt?: string | Date | null;
14
+ metadata?: Record<string, unknown> | null;
15
+ }
16
+ export interface GameChatMessageSubscription {
17
+ close(): void;
18
+ closed?: Promise<void>;
19
+ }
20
+ export interface GameChatClientAdapter {
21
+ listRoomMessages(roomKey: string, input?: {
22
+ limit?: number;
23
+ afterLamport?: number;
24
+ afterMessageId?: string;
25
+ }): Promise<GameChatMessage[]>;
26
+ sendRoomMessage(roomKey: string, input: {
27
+ text: string;
28
+ senderHandle?: string;
29
+ metadata?: Record<string, unknown>;
30
+ }): Promise<GameChatMessage>;
31
+ subscribeRoomMessages?(roomKey: string, onEvent: (event: unknown) => void, input?: {
32
+ afterLamport?: number;
33
+ afterMessageId?: string;
34
+ }): GameChatMessageSubscription;
35
+ }
36
+ export interface ChatPanelProps {
37
+ roomKey: string;
38
+ client: GameChatClientAdapter;
39
+ senderHandle?: string;
40
+ className?: string;
41
+ disabled?: boolean;
42
+ initialMessages?: GameChatMessage[];
43
+ limit?: number;
44
+ placeholder?: string;
45
+ emptyLabel?: string;
46
+ reconnectLabel?: string;
47
+ renderMessage?: (message: GameChatMessage) => ReactNode;
48
+ onError?: (error: Error) => void;
49
+ }
50
+ export declare function ChatPanel({ roomKey, client, senderHandle, className, disabled, initialMessages, limit, placeholder, emptyLabel, reconnectLabel, renderMessage, onError, }: ChatPanelProps): import("react/jsx-runtime").JSX.Element;
51
+ //# sourceMappingURL=ChatPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatPanel.d.ts","sourceRoot":"","sources":["../src/ChatPanel.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAa,SAAS,EAAE,MAAM,OAAO,CAAC;AAElD,MAAM,WAAW,eAAe;IAC9B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,GAAG,YAAY,GAAG,MAAM,CAAC;IAC9C,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC3C;AAED,MAAM,WAAW,2BAA2B;IAC1C,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,CACd,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,GACzE,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IAC9B,eAAe,CACb,OAAO,EAAE,MAAM,EACf,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACpC,GACA,OAAO,CAAC,eAAe,CAAC,CAAC;IAC5B,qBAAqB,CAAC,CACpB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,EACjC,KAAK,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,GACzD,2BAA2B,CAAC;CAChC;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,qBAAqB,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,eAAe,EAAE,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,SAAS,CAAC;IACxD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAID,wBAAgB,SAAS,CAAC,EACxB,OAAO,EACP,MAAM,EACN,YAAY,EACZ,SAAS,EACT,QAAgB,EAChB,eAAgC,EAChC,KAAU,EACV,WAAuB,EACvB,UAA+B,EAC/B,cAA+B,EAC/B,aAAa,EACb,OAAO,GACR,EAAE,cAAc,2CA+HhB"}
@@ -0,0 +1,148 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useMemo, useState } from "react";
3
+ export function ChatPanel({ roomKey, client, senderHandle, className, disabled = false, initialMessages = EMPTY_MESSAGES, limit = 50, placeholder = "Message", emptyLabel = "No messages yet.", reconnectLabel = "Reconnecting", renderMessage, onError, }) {
4
+ const [messages, setMessages] = useState(initialMessages);
5
+ const [draft, setDraft] = useState("");
6
+ const [loading, setLoading] = useState(true);
7
+ const [sending, setSending] = useState(false);
8
+ const [streamState, setStreamState] = useState("idle");
9
+ useEffect(() => {
10
+ let active = true;
11
+ let subscription;
12
+ setLoading(true);
13
+ setStreamState(client.subscribeRoomMessages ? "connecting" : "idle");
14
+ client
15
+ .listRoomMessages(roomKey, { limit })
16
+ .then((nextMessages) => {
17
+ if (!active)
18
+ return;
19
+ setMessages(mergeMessages(initialMessages, nextMessages));
20
+ setLoading(false);
21
+ })
22
+ .catch((error) => {
23
+ if (!active)
24
+ return;
25
+ setLoading(false);
26
+ reportError(error, onError);
27
+ });
28
+ if (client.subscribeRoomMessages) {
29
+ try {
30
+ subscription = client.subscribeRoomMessages(roomKey, (event) => {
31
+ const message = normalizeIncomingMessage(event);
32
+ if (!message)
33
+ return;
34
+ setMessages((current) => mergeMessages(current, [message]));
35
+ setStreamState("connected");
36
+ });
37
+ subscription.closed?.catch((error) => {
38
+ if (!active)
39
+ return;
40
+ setStreamState("reconnecting");
41
+ reportError(error, onError);
42
+ });
43
+ }
44
+ catch (error) {
45
+ setStreamState("reconnecting");
46
+ reportError(error, onError);
47
+ }
48
+ }
49
+ return () => {
50
+ active = false;
51
+ subscription?.close();
52
+ };
53
+ }, [client, initialMessages, limit, onError, roomKey]);
54
+ const canSend = useMemo(() => !disabled && !sending && draft.trim().length > 0, [disabled, draft, sending]);
55
+ const onSubmit = useCallback(async (event) => {
56
+ event.preventDefault();
57
+ const text = draft.trim();
58
+ if (!text || disabled || sending)
59
+ return;
60
+ setSending(true);
61
+ try {
62
+ const message = await client.sendRoomMessage(roomKey, {
63
+ text,
64
+ senderHandle,
65
+ });
66
+ setDraft("");
67
+ setMessages((current) => mergeMessages(current, [message]));
68
+ }
69
+ catch (error) {
70
+ reportError(error, onError);
71
+ }
72
+ finally {
73
+ setSending(false);
74
+ }
75
+ }, [client, disabled, draft, onError, roomKey, senderHandle, sending]);
76
+ return (_jsxs("section", { className: joinClassNames("alcheme-chat-panel", className), children: [_jsx("div", { className: "alcheme-chat-panel__messages", "aria-busy": loading, children: messages.length === 0 ? (_jsx("p", { className: "alcheme-chat-panel__empty", children: emptyLabel })) : (messages.map((message) => (_jsx("article", { className: "alcheme-chat-panel__message", children: renderMessage ? (renderMessage(message)) : (_jsx(DefaultMessage, { message: message })) }, messageKey(message))))) }), streamState === "reconnecting" ? (_jsx("p", { className: "alcheme-chat-panel__status", role: "status", children: reconnectLabel })) : null, _jsxs("form", { className: "alcheme-chat-panel__composer", onSubmit: onSubmit, children: [_jsx("textarea", { "aria-label": placeholder, className: "alcheme-chat-panel__input", disabled: disabled || sending, onChange: (event) => setDraft(event.target.value), placeholder: placeholder, rows: 2, value: draft }), _jsx("button", { className: "alcheme-chat-panel__send", disabled: !canSend, type: "submit", children: sending ? "Sending" : "Send" })] })] }));
77
+ }
78
+ function DefaultMessage({ message }) {
79
+ const body = message.messageKind === "voice_clip"
80
+ ? message.payloadText || "Voice clip"
81
+ : message.text || "";
82
+ return (_jsxs(_Fragment, { children: [_jsxs("header", { className: "alcheme-chat-panel__message-meta", children: [_jsx("span", { children: message.senderHandle || shortenPubkey(message.senderPubkey) }), message.createdAt ? (_jsx("time", { children: formatTimestamp(message.createdAt) })) : null] }), _jsx("p", { className: "alcheme-chat-panel__message-body", children: body })] }));
83
+ }
84
+ function mergeMessages(current, next) {
85
+ const byKey = new Map();
86
+ for (const message of current) {
87
+ byKey.set(messageKey(message), message);
88
+ }
89
+ for (const message of next) {
90
+ byKey.set(messageKey(message), message);
91
+ }
92
+ return Array.from(byKey.values()).sort(compareMessages);
93
+ }
94
+ function compareMessages(left, right) {
95
+ if (typeof left.lamport === "number" && typeof right.lamport === "number") {
96
+ return left.lamport - right.lamport;
97
+ }
98
+ return timestampValue(left.createdAt) - timestampValue(right.createdAt);
99
+ }
100
+ function normalizeIncomingMessage(event) {
101
+ if (!isRecord(event))
102
+ return null;
103
+ const wrapped = event.message;
104
+ if (isRecord(wrapped))
105
+ return wrapped;
106
+ if ("text" in event || "payloadText" in event || "messageKind" in event) {
107
+ return event;
108
+ }
109
+ return null;
110
+ }
111
+ function messageKey(message) {
112
+ return (message.envelopeId ||
113
+ message.id ||
114
+ `${message.senderPubkey || "unknown"}:${message.lamport ?? ""}:${timestampValue(message.createdAt)}:${message.text || message.payloadText || ""}`);
115
+ }
116
+ function timestampValue(value) {
117
+ if (!value)
118
+ return 0;
119
+ if (value instanceof Date)
120
+ return value.getTime();
121
+ const parsed = Date.parse(value);
122
+ return Number.isFinite(parsed) ? parsed : 0;
123
+ }
124
+ function formatTimestamp(value) {
125
+ const date = value instanceof Date ? value : new Date(value);
126
+ if (Number.isNaN(date.getTime()))
127
+ return "";
128
+ return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
129
+ }
130
+ function shortenPubkey(pubkey) {
131
+ if (!pubkey)
132
+ return "Unknown";
133
+ if (pubkey.length <= 10)
134
+ return pubkey;
135
+ return `${pubkey.slice(0, 4)}...${pubkey.slice(-4)}`;
136
+ }
137
+ function reportError(error, onError) {
138
+ const normalized = error instanceof Error ? error : new Error(String(error));
139
+ onError?.(normalized);
140
+ }
141
+ function joinClassNames(...values) {
142
+ return values.filter(Boolean).join(" ");
143
+ }
144
+ function isRecord(value) {
145
+ return typeof value === "object" && value !== null;
146
+ }
147
+ const EMPTY_MESSAGES = [];
148
+ //# sourceMappingURL=ChatPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatPanel.js","sourceRoot":"","sources":["../src/ChatPanel.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import type { ReactNode } from "react";
2
+ export interface VoiceParticipantState {
3
+ walletPubkey: string;
4
+ speaking?: boolean;
5
+ muted?: boolean;
6
+ mutedBySelf?: boolean;
7
+ mutedByModerator?: boolean;
8
+ }
9
+ export interface VoiceConnectionState {
10
+ connected: boolean;
11
+ participants: VoiceParticipantState[];
12
+ mutedBySelf: boolean;
13
+ mutedByModerator: boolean;
14
+ speaking: boolean;
15
+ }
16
+ export interface VoiceConnectionAdapter {
17
+ readonly state: VoiceConnectionState;
18
+ leave(): Promise<void> | void;
19
+ setMutedBySelf?(muted: boolean): Promise<void> | void;
20
+ }
21
+ export interface VoiceClientAdapter {
22
+ joinVoice(roomKey: string, input?: {
23
+ ttlSec?: number;
24
+ communicationSessionToken?: string;
25
+ }): Promise<VoiceConnectionAdapter>;
26
+ }
27
+ export interface VoiceControlsProps {
28
+ roomKey: string;
29
+ voiceClient: VoiceClientAdapter;
30
+ className?: string;
31
+ disabled?: boolean;
32
+ ttlSec?: number;
33
+ communicationSessionToken?: string;
34
+ participantLabel?: (participant: VoiceParticipantState) => ReactNode;
35
+ refreshIntervalMs?: number;
36
+ onError?: (error: Error) => void;
37
+ }
38
+ export declare function VoiceControls({ roomKey, voiceClient, className, disabled, ttlSec, communicationSessionToken, participantLabel, refreshIntervalMs, onError, }: VoiceControlsProps): import("react/jsx-runtime").JSX.Element;
39
+ //# sourceMappingURL=VoiceControls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceControls.d.ts","sourceRoot":"","sources":["../src/VoiceControls.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,qBAAqB,EAAE,CAAC;IACtC,WAAW,EAAE,OAAO,CAAC;IACrB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAC;IACrC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACvD;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,CACP,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,yBAAyB,CAAC,EAAE,MAAM,CAAA;KAAE,GAC9D,OAAO,CAAC,sBAAsB,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,kBAAkB,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,gBAAgB,CAAC,EAAE,CAAC,WAAW,EAAE,qBAAqB,KAAK,SAAS,CAAC;IACrE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,WAAW,EACX,SAAS,EACT,QAAgB,EAChB,MAAM,EACN,yBAAyB,EACzB,gBAAgB,EAChB,iBAAwB,EACxB,OAAO,GACR,EAAE,kBAAkB,2CA+IpB"}
@@ -0,0 +1,101 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useRef, useState } from "react";
3
+ export function VoiceControls({ roomKey, voiceClient, className, disabled = false, ttlSec, communicationSessionToken, participantLabel, refreshIntervalMs = 1000, onError, }) {
4
+ const [connection, setConnection] = useState(null);
5
+ const connectionRef = useRef(null);
6
+ const [snapshot, setSnapshot] = useState(null);
7
+ const [joining, setJoining] = useState(false);
8
+ useEffect(() => {
9
+ connectionRef.current = connection;
10
+ }, [connection]);
11
+ useEffect(() => {
12
+ if (!connection) {
13
+ setSnapshot(null);
14
+ return undefined;
15
+ }
16
+ setSnapshot(connection.state);
17
+ const timer = setInterval(() => {
18
+ setSnapshot(connection.state);
19
+ }, refreshIntervalMs);
20
+ return () => clearInterval(timer);
21
+ }, [connection, refreshIntervalMs]);
22
+ useEffect(() => {
23
+ return () => {
24
+ void connectionRef.current?.leave();
25
+ };
26
+ }, []);
27
+ const join = useCallback(async () => {
28
+ if (disabled || joining || connection?.state.connected)
29
+ return;
30
+ setJoining(true);
31
+ try {
32
+ const nextConnection = await voiceClient.joinVoice(roomKey, {
33
+ ttlSec,
34
+ communicationSessionToken,
35
+ });
36
+ setConnection(nextConnection);
37
+ setSnapshot(nextConnection.state);
38
+ }
39
+ catch (error) {
40
+ reportError(error, onError);
41
+ }
42
+ finally {
43
+ setJoining(false);
44
+ }
45
+ }, [
46
+ communicationSessionToken,
47
+ connection,
48
+ disabled,
49
+ joining,
50
+ onError,
51
+ roomKey,
52
+ ttlSec,
53
+ voiceClient,
54
+ ]);
55
+ const leave = useCallback(async () => {
56
+ const activeConnection = connection;
57
+ if (!activeConnection)
58
+ return;
59
+ try {
60
+ await activeConnection.leave();
61
+ }
62
+ catch (error) {
63
+ reportError(error, onError);
64
+ }
65
+ finally {
66
+ setConnection(null);
67
+ setSnapshot(null);
68
+ }
69
+ }, [connection, onError]);
70
+ const toggleMute = useCallback(async () => {
71
+ if (!connection?.setMutedBySelf || !snapshot)
72
+ return;
73
+ try {
74
+ await connection.setMutedBySelf(!snapshot.mutedBySelf);
75
+ setSnapshot(connection.state);
76
+ }
77
+ catch (error) {
78
+ reportError(error, onError);
79
+ }
80
+ }, [connection, onError, snapshot]);
81
+ const connected = Boolean(snapshot?.connected);
82
+ const mutedByModerator = Boolean(snapshot?.mutedByModerator);
83
+ const participants = snapshot?.participants ?? EMPTY_PARTICIPANTS;
84
+ return (_jsxs("section", { className: joinClassNames("alcheme-voice-controls", className), children: [_jsxs("div", { className: "alcheme-voice-controls__actions", children: [connected ? (_jsx("button", { className: "alcheme-voice-controls__button", onClick: leave, type: "button", children: "Leave" })) : (_jsx("button", { className: "alcheme-voice-controls__button", disabled: disabled || joining, onClick: join, type: "button", children: joining ? "Joining" : "Join" })), _jsx("button", { className: "alcheme-voice-controls__button", disabled: !connected || !connection?.setMutedBySelf || mutedByModerator, onClick: toggleMute, type: "button", children: snapshot?.mutedBySelf ? "Unmute" : "Mute" })] }), mutedByModerator ? (_jsx("p", { className: "alcheme-voice-controls__notice", role: "status", children: "Listen only" })) : null, _jsx("ul", { className: "alcheme-voice-controls__participants", children: participants.map((participant) => (_jsxs("li", { className: "alcheme-voice-controls__participant", children: [_jsx("span", { children: participantLabel
85
+ ? participantLabel(participant)
86
+ : shortenPubkey(participant.walletPubkey) }), participant.speaking ? (_jsx("span", { className: "alcheme-voice-controls__participant-state", children: "Speaking" })) : null] }, participant.walletPubkey))) })] }));
87
+ }
88
+ function reportError(error, onError) {
89
+ const normalized = error instanceof Error ? error : new Error(String(error));
90
+ onError?.(normalized);
91
+ }
92
+ function shortenPubkey(pubkey) {
93
+ if (pubkey.length <= 10)
94
+ return pubkey;
95
+ return `${pubkey.slice(0, 4)}...${pubkey.slice(-4)}`;
96
+ }
97
+ function joinClassNames(...values) {
98
+ return values.filter(Boolean).join(" ");
99
+ }
100
+ const EMPTY_PARTICIPANTS = [];
101
+ //# sourceMappingURL=VoiceControls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceControls.js","sourceRoot":"","sources":["../src/VoiceControls.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { ChatPanel, type ChatPanelProps, type GameChatClientAdapter, type GameChatMessage, type GameChatMessageSubscription, } from "./ChatPanel.js";
2
+ export { VoiceControls, type VoiceClientAdapter, type VoiceConnectionAdapter, type VoiceConnectionState, type VoiceControlsProps, type VoiceParticipantState, } from "./VoiceControls.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACpB,KAAK,2BAA2B,GACjC,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,GAC3B,MAAM,oBAAoB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { ChatPanel, } from "./ChatPanel.js";
2
+ export { VoiceControls, } from "./VoiceControls.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,GAKV,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,aAAa,GAMd,MAAM,oBAAoB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@alcheme/game-chat-react",
3
+ "version": "0.1.0",
4
+ "license": "Apache-2.0",
5
+ "description": "Optional React components for Alcheme external app chat and voice integrations.",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "default": "./dist/index.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsc -p tsconfig.json",
22
+ "typecheck": "tsc -p tsconfig.json --noEmit"
23
+ },
24
+ "peerDependencies": {
25
+ "react": ">=18 <20"
26
+ },
27
+ "devDependencies": {
28
+ "@types/react": "^19.0.0",
29
+ "react": "19.2.3",
30
+ "typescript": "^5.0.0"
31
+ }
32
+ }