@ttt-productions/chat-react 0.6.0 → 0.6.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/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/realtime/channel-client.d.ts +104 -0
- package/dist/realtime/channel-client.d.ts.map +1 -0
- package/dist/realtime/channel-client.js +356 -0
- package/dist/realtime/channel-client.js.map +1 -0
- package/dist/realtime/inbox-client.d.ts +55 -0
- package/dist/realtime/inbox-client.d.ts.map +1 -0
- package/dist/realtime/inbox-client.js +173 -0
- package/dist/realtime/inbox-client.js.map +1 -0
- package/dist/realtime/index.d.ts +16 -0
- package/dist/realtime/index.d.ts.map +1 -0
- package/dist/realtime/index.js +14 -0
- package/dist/realtime/index.js.map +1 -0
- package/dist/realtime/map.d.ts +31 -0
- package/dist/realtime/map.d.ts.map +1 -0
- package/dist/realtime/map.js +70 -0
- package/dist/realtime/map.js.map +1 -0
- package/dist/realtime/shared.d.ts +24 -0
- package/dist/realtime/shared.d.ts.map +1 -0
- package/dist/realtime/shared.js +19 -0
- package/dist/realtime/shared.js.map +1 -0
- package/dist/realtime/socket.d.ts +33 -0
- package/dist/realtime/socket.d.ts.map +1 -0
- package/dist/realtime/socket.js +43 -0
- package/dist/realtime/socket.js.map +1 -0
- package/dist/realtime/transport.d.ts +48 -0
- package/dist/realtime/transport.d.ts.map +1 -0
- package/dist/realtime/transport.js +47 -0
- package/dist/realtime/transport.js.map +1 -0
- package/dist/realtime/useRealtimeChatMessages.d.ts +23 -0
- package/dist/realtime/useRealtimeChatMessages.d.ts.map +1 -0
- package/dist/realtime/useRealtimeChatMessages.js +71 -0
- package/dist/realtime/useRealtimeChatMessages.js.map +1 -0
- package/dist/realtime/wire.d.ts +135 -0
- package/dist/realtime/wire.d.ts.map +1 -0
- package/dist/realtime/wire.js +71 -0
- package/dist/realtime/wire.js.map +1 -0
- package/dist/types.d.ts +38 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/ChatShell.d.ts +7 -1
- package/dist/ui/ChatShell.d.ts.map +1 -1
- package/dist/ui/ChatShell.js +51 -3
- package/dist/ui/ChatShell.js.map +1 -1
- package/package.json +7 -6
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
// React hook for the REALTIME transport, returning the SAME shape as
|
|
3
|
+
// `useChatMessages` (the firestore path) so `ChatShell` is transport-agnostic.
|
|
4
|
+
// It subscribes to a `RealtimeChatClient`'s observable state, connects on mount,
|
|
5
|
+
// and tears every socket down on unmount OR when the auth user switches
|
|
6
|
+
// (Contract A: auth-user switch tears down every socket before connecting as the
|
|
7
|
+
// new uid). The client instance is owned by the caller (passed via config) so its
|
|
8
|
+
// identity is the teardown key — a new client for a new uid replaces the old one.
|
|
9
|
+
import * as React from "react";
|
|
10
|
+
import { useOptionalChatNameResolver } from "../context/ChatNameResolverContext.js";
|
|
11
|
+
export function useRealtimeChatMessages(client) {
|
|
12
|
+
const [state, setState] = React.useState(() => client.getState());
|
|
13
|
+
// Subscribe + connect; tear down on client identity change (auth-user switch) or unmount.
|
|
14
|
+
React.useEffect(() => {
|
|
15
|
+
const unsub = client.subscribe(setState);
|
|
16
|
+
setState(client.getState());
|
|
17
|
+
void client.connect();
|
|
18
|
+
return () => {
|
|
19
|
+
unsub();
|
|
20
|
+
client.close();
|
|
21
|
+
};
|
|
22
|
+
}, [client]);
|
|
23
|
+
// Pre-warm the name cache for visible senders (parity with the firestore hook).
|
|
24
|
+
const resolverCtx = useOptionalChatNameResolver();
|
|
25
|
+
const senderIds = React.useMemo(() => {
|
|
26
|
+
const set = new Set();
|
|
27
|
+
for (const m of state.messages) {
|
|
28
|
+
set.add(m.senderId);
|
|
29
|
+
if (m.replyTo?.senderId)
|
|
30
|
+
set.add(m.replyTo.senderId);
|
|
31
|
+
}
|
|
32
|
+
return Array.from(set);
|
|
33
|
+
}, [state.messages]);
|
|
34
|
+
React.useEffect(() => {
|
|
35
|
+
if (resolverCtx?.prewarm && senderIds.length > 0)
|
|
36
|
+
resolverCtx.prewarm(senderIds);
|
|
37
|
+
}, [resolverCtx, senderIds]);
|
|
38
|
+
const fetchOlder = React.useCallback(async () => {
|
|
39
|
+
client.channel.fetchOlder();
|
|
40
|
+
}, [client]);
|
|
41
|
+
const send = React.useCallback((text, replyTo) => {
|
|
42
|
+
client.channel.send({ clientMessageId: makeClientMessageId(), text, replyTo: replyTo ?? null });
|
|
43
|
+
}, [client]);
|
|
44
|
+
const readAck = React.useCallback((readSeq, focused) => client.channel.readAck(readSeq, focused), [client]);
|
|
45
|
+
const signalTyping = React.useCallback(() => client.channel.typing(), [client]);
|
|
46
|
+
return {
|
|
47
|
+
// On the realtime transport DATA ACCESS is enforced by the DO grant, so the
|
|
48
|
+
// hook is always "allowed" client-side (the socket simply won't open / will be
|
|
49
|
+
// closed 4403 if the grant is denied) — accessMode is presentation-only here.
|
|
50
|
+
allowed: true,
|
|
51
|
+
isInitialLoading: state.status === "connecting" || state.status === "idle",
|
|
52
|
+
messages: state.messages,
|
|
53
|
+
fetchOlder,
|
|
54
|
+
hasOlder: state.hasOlder,
|
|
55
|
+
isFetchingOlder: state.isFetchingOlder,
|
|
56
|
+
status: state.status,
|
|
57
|
+
typing: state.typing,
|
|
58
|
+
presence: state.presence,
|
|
59
|
+
send,
|
|
60
|
+
readAck,
|
|
61
|
+
signalTyping,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/** A client message id for optimistic-send idempotency (SQLite unique (senderUid, clientMessageId)). */
|
|
65
|
+
function makeClientMessageId() {
|
|
66
|
+
const c = globalThis.crypto;
|
|
67
|
+
if (c?.randomUUID)
|
|
68
|
+
return c.randomUUID();
|
|
69
|
+
return `cmid-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=useRealtimeChatMessages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRealtimeChatMessages.js","sourceRoot":"","sources":["../../src/realtime/useRealtimeChatMessages.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/** The pinned WebSocket subprotocol tag offered alongside the grant token. */
|
|
2
|
+
export declare const CHAT_SUBPROTOCOL: "ttt.chat.v1";
|
|
3
|
+
/** Wire envelope protocol version (the worker emits and accepts `v: 1`). */
|
|
4
|
+
export declare const CHAT_WIRE_VERSION: 1;
|
|
5
|
+
/** Client → DO message `type`s (chat-worker `CLIENT_KINDS`). */
|
|
6
|
+
export declare const CLIENT_FRAME: {
|
|
7
|
+
readonly SEND: "send";
|
|
8
|
+
readonly READ_ACK: "read-ack";
|
|
9
|
+
readonly HISTORY: "history";
|
|
10
|
+
readonly TYPING: "typing";
|
|
11
|
+
readonly PRESENCE_SUBSCRIBE: "presence-subscribe";
|
|
12
|
+
readonly PRESENCE_UNSUBSCRIBE: "presence-unsubscribe";
|
|
13
|
+
readonly HEARTBEAT: "heartbeat";
|
|
14
|
+
readonly RESUME: "resume";
|
|
15
|
+
};
|
|
16
|
+
/** DO → client message `type`s (chat-worker `SERVER_KINDS`). */
|
|
17
|
+
export declare const SERVER_FRAME: {
|
|
18
|
+
readonly MESSAGE: "message";
|
|
19
|
+
readonly ACK: "ack";
|
|
20
|
+
readonly HISTORY_PAGE: "history-page";
|
|
21
|
+
readonly PRESENCE: "presence";
|
|
22
|
+
readonly TYPING: "typing";
|
|
23
|
+
readonly UNREAD: "unread";
|
|
24
|
+
readonly SNAPSHOT: "snapshot";
|
|
25
|
+
readonly ERROR: "error";
|
|
26
|
+
readonly REVISION: "revision";
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* WebSocket close codes (Contract C). 4xxx are app codes; 1013 is the standard
|
|
30
|
+
* "try again later". Mirrors chat-worker `CLOSE_CODES`.
|
|
31
|
+
*/
|
|
32
|
+
export declare const CHAT_CLOSE_CODES: {
|
|
33
|
+
readonly AUTH_EXPIRED: 4401;
|
|
34
|
+
readonly REVOKED: 4403;
|
|
35
|
+
readonly FLOOD: 4408;
|
|
36
|
+
readonly TOO_LARGE: 4413;
|
|
37
|
+
readonly SOCKET_CAP: 4429;
|
|
38
|
+
readonly OVERLOADED: 1013;
|
|
39
|
+
};
|
|
40
|
+
export type ChatCloseCode = (typeof CHAT_CLOSE_CODES)[keyof typeof CHAT_CLOSE_CODES];
|
|
41
|
+
/** A logical chat channel — typed tuple (NEVER a path string). Mirrors the worker's ChannelRefTuple. */
|
|
42
|
+
export type ChannelRefTuple = {
|
|
43
|
+
scope: 'channel';
|
|
44
|
+
workProjectId: string;
|
|
45
|
+
guildChatChannelId: string;
|
|
46
|
+
} | {
|
|
47
|
+
scope: 'invite';
|
|
48
|
+
guildInviteId: string;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* A message row as the Channel DO stores + broadcasts it (chat-worker
|
|
52
|
+
* `MessageRow`). `replyTo`/`attachmentMeta` arrive as JSON STRINGS (or null) —
|
|
53
|
+
* the DO stores them stringified and does not re-parse before broadcast. The
|
|
54
|
+
* adapter mapping in `map.ts` parses them into the UI `ChatMessageV1` shape.
|
|
55
|
+
*/
|
|
56
|
+
export interface WireMessageRow {
|
|
57
|
+
seq: number;
|
|
58
|
+
senderUid: string;
|
|
59
|
+
clientMessageId: string;
|
|
60
|
+
text: string;
|
|
61
|
+
replyTo: string | null;
|
|
62
|
+
attachmentState: string | null;
|
|
63
|
+
attachmentMeta: string | null;
|
|
64
|
+
createdAt: number;
|
|
65
|
+
epoch: number;
|
|
66
|
+
}
|
|
67
|
+
/** The channel resume snapshot the DO returns for a `resume` frame. */
|
|
68
|
+
export interface WireChannelSnapshot {
|
|
69
|
+
lastMessageSeq: number;
|
|
70
|
+
readSeq: number;
|
|
71
|
+
}
|
|
72
|
+
/** A registry entry in the inbox snapshot (chat-worker `RegistryEntry`). */
|
|
73
|
+
export interface WireRegistryEntry {
|
|
74
|
+
channelRef: string;
|
|
75
|
+
kind: string;
|
|
76
|
+
state: 'active' | 'tombstoned';
|
|
77
|
+
registryVersion: number;
|
|
78
|
+
}
|
|
79
|
+
/** The inbox snapshot payload pushed on connect / `resume` / live delta. */
|
|
80
|
+
export interface WireInboxSnapshot {
|
|
81
|
+
registry: WireRegistryEntry[];
|
|
82
|
+
hasUnread: boolean;
|
|
83
|
+
}
|
|
84
|
+
export type ServerFrame = {
|
|
85
|
+
type: 'message';
|
|
86
|
+
payload: {
|
|
87
|
+
message: WireMessageRow;
|
|
88
|
+
};
|
|
89
|
+
} | {
|
|
90
|
+
type: 'ack';
|
|
91
|
+
payload: {
|
|
92
|
+
clientMessageId?: string;
|
|
93
|
+
seq?: number;
|
|
94
|
+
readSeq?: number;
|
|
95
|
+
};
|
|
96
|
+
} | {
|
|
97
|
+
type: 'history-page';
|
|
98
|
+
payload: {
|
|
99
|
+
messages: WireMessageRow[];
|
|
100
|
+
};
|
|
101
|
+
} | {
|
|
102
|
+
type: 'presence';
|
|
103
|
+
payload: {
|
|
104
|
+
online: string[];
|
|
105
|
+
};
|
|
106
|
+
} | {
|
|
107
|
+
type: 'typing';
|
|
108
|
+
payload: {
|
|
109
|
+
uid: string;
|
|
110
|
+
at: number;
|
|
111
|
+
};
|
|
112
|
+
} | {
|
|
113
|
+
type: 'snapshot';
|
|
114
|
+
payload: WireChannelSnapshot | WireInboxSnapshot;
|
|
115
|
+
} | {
|
|
116
|
+
type: 'error';
|
|
117
|
+
payload: {
|
|
118
|
+
code: string;
|
|
119
|
+
retryAfterMs?: number;
|
|
120
|
+
};
|
|
121
|
+
} | {
|
|
122
|
+
type: 'revision';
|
|
123
|
+
payload: Record<string, unknown>;
|
|
124
|
+
};
|
|
125
|
+
/** Build an outbound `{ v, type, payload }` frame (the wire format the DO reads). */
|
|
126
|
+
export declare function buildFrame(type: string, payload: Record<string, unknown>): string;
|
|
127
|
+
/** Parse an inbound frame, tolerating malformed JSON. Returns null on garbage. */
|
|
128
|
+
export declare function parseFrame(raw: string): {
|
|
129
|
+
v?: number;
|
|
130
|
+
type?: string;
|
|
131
|
+
payload?: Record<string, unknown>;
|
|
132
|
+
} | null;
|
|
133
|
+
/** A snapshot with `registry` is an inbox snapshot; one with `lastMessageSeq` is a channel snapshot. */
|
|
134
|
+
export declare function isInboxSnapshot(p: WireChannelSnapshot | WireInboxSnapshot): p is WireInboxSnapshot;
|
|
135
|
+
//# sourceMappingURL=wire.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wire.d.ts","sourceRoot":"","sources":["../../src/realtime/wire.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// Chat realtime WIRE PROTOCOL (Contract C) — the client side of the chat-worker
|
|
2
|
+
// Channel + Inbox Durable Object protocol. These shapes mirror the worker's
|
|
3
|
+
// `ttt-master-app/chat-worker/src` BYTE-FOR-BYTE so the DO and this client agree
|
|
4
|
+
// on the wire without sharing code (the worker stays ttt-core-free; this package
|
|
5
|
+
// stays generic — neither imports the other).
|
|
6
|
+
//
|
|
7
|
+
// Frame shape on the socket is `{ v, type, payload }` (NOT realtime-core's
|
|
8
|
+
// `{ v, kind, payload }`): the chat worker `send`/`broadcast` emit
|
|
9
|
+
// `JSON.stringify({ v: 1, type, payload })` and read `env.type` + `env.payload`.
|
|
10
|
+
// We keep that field name here to match; realtime-core's envelope schema is the
|
|
11
|
+
// generic transport primitive, the chat worker chose `type` for its DO frames.
|
|
12
|
+
/** The pinned WebSocket subprotocol tag offered alongside the grant token. */
|
|
13
|
+
export const CHAT_SUBPROTOCOL = 'ttt.chat.v1';
|
|
14
|
+
/** Wire envelope protocol version (the worker emits and accepts `v: 1`). */
|
|
15
|
+
export const CHAT_WIRE_VERSION = 1;
|
|
16
|
+
/** Client → DO message `type`s (chat-worker `CLIENT_KINDS`). */
|
|
17
|
+
export const CLIENT_FRAME = {
|
|
18
|
+
SEND: 'send',
|
|
19
|
+
READ_ACK: 'read-ack',
|
|
20
|
+
HISTORY: 'history',
|
|
21
|
+
TYPING: 'typing',
|
|
22
|
+
PRESENCE_SUBSCRIBE: 'presence-subscribe',
|
|
23
|
+
PRESENCE_UNSUBSCRIBE: 'presence-unsubscribe',
|
|
24
|
+
HEARTBEAT: 'heartbeat',
|
|
25
|
+
RESUME: 'resume',
|
|
26
|
+
};
|
|
27
|
+
/** DO → client message `type`s (chat-worker `SERVER_KINDS`). */
|
|
28
|
+
export const SERVER_FRAME = {
|
|
29
|
+
MESSAGE: 'message',
|
|
30
|
+
ACK: 'ack',
|
|
31
|
+
HISTORY_PAGE: 'history-page',
|
|
32
|
+
PRESENCE: 'presence',
|
|
33
|
+
TYPING: 'typing',
|
|
34
|
+
UNREAD: 'unread',
|
|
35
|
+
SNAPSHOT: 'snapshot',
|
|
36
|
+
ERROR: 'error',
|
|
37
|
+
REVISION: 'revision',
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* WebSocket close codes (Contract C). 4xxx are app codes; 1013 is the standard
|
|
41
|
+
* "try again later". Mirrors chat-worker `CLOSE_CODES`.
|
|
42
|
+
*/
|
|
43
|
+
export const CHAT_CLOSE_CODES = {
|
|
44
|
+
AUTH_EXPIRED: 4401,
|
|
45
|
+
REVOKED: 4403,
|
|
46
|
+
FLOOD: 4408,
|
|
47
|
+
TOO_LARGE: 4413,
|
|
48
|
+
SOCKET_CAP: 4429,
|
|
49
|
+
OVERLOADED: 1013,
|
|
50
|
+
};
|
|
51
|
+
/** Build an outbound `{ v, type, payload }` frame (the wire format the DO reads). */
|
|
52
|
+
export function buildFrame(type, payload) {
|
|
53
|
+
return JSON.stringify({ v: CHAT_WIRE_VERSION, type, payload });
|
|
54
|
+
}
|
|
55
|
+
/** Parse an inbound frame, tolerating malformed JSON. Returns null on garbage. */
|
|
56
|
+
export function parseFrame(raw) {
|
|
57
|
+
try {
|
|
58
|
+
const parsed = JSON.parse(raw);
|
|
59
|
+
if (!parsed || typeof parsed !== 'object')
|
|
60
|
+
return null;
|
|
61
|
+
return parsed;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/** A snapshot with `registry` is an inbox snapshot; one with `lastMessageSeq` is a channel snapshot. */
|
|
68
|
+
export function isInboxSnapshot(p) {
|
|
69
|
+
return Array.isArray(p.registry);
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=wire.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wire.js","sourceRoot":"","sources":["../../src/realtime/wire.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,4EAA4E;AAC5E,iFAAiF;AACjF,iFAAiF;AACjF,8CAA8C;AAC9C,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,iFAAiF;AACjF,gFAAgF;AAChF,+EAA+E;AAE/E,8EAA8E;AAC9E,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAsB,CAAC;AAEvD,4EAA4E;AAC5E,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAU,CAAC;AAE5C,gEAAgE;AAChE,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAChB,kBAAkB,EAAE,oBAAoB;IACxC,oBAAoB,EAAE,sBAAsB;IAC5C,SAAS,EAAE,WAAW;IACtB,MAAM,EAAE,QAAQ;CACR,CAAC;AAEX,gEAAgE;AAChE,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,OAAO,EAAE,SAAS;IAClB,GAAG,EAAE,KAAK;IACV,YAAY,EAAE,cAAc;IAC5B,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,UAAU;IACpB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;CACZ,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,YAAY,EAAE,IAAI;IAClB,OAAO,EAAE,IAAI;IACb,KAAK,EAAE,IAAI;IACX,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,IAAI;IAChB,UAAU,EAAE,IAAI;CACR,CAAC;AA6DX,qFAAqF;AACrF,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,OAAgC;IACvE,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,iBAAiB,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AACjE,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;QAC1C,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QACvD,OAAO,MAA0E,CAAC;IACpF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,eAAe,CAAC,CAA0C;IACxE,OAAO,KAAK,CAAC,OAAO,CAAE,CAAuB,CAAC,QAAQ,CAAC,CAAC;AAC1D,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -86,6 +86,34 @@ export type ChatMentionConfig = {
|
|
|
86
86
|
*/
|
|
87
87
|
renderMention?: (ref: MentionRef) => ReactNode;
|
|
88
88
|
};
|
|
89
|
+
/**
|
|
90
|
+
* Which transport backs a chat thread.
|
|
91
|
+
* - `firestore` — the current Firestore newest-window + cursor path (default).
|
|
92
|
+
* - `realtime` — the Cloudflare Durable Object socket (chat-edge-rebuild). On
|
|
93
|
+
* this transport DATA ACCESS is enforced by the DO grant, so `accessMode`
|
|
94
|
+
* becomes PRESENTATION-ONLY (UI affordances like read-only), never a
|
|
95
|
+
* data-access gate.
|
|
96
|
+
*/
|
|
97
|
+
export type ChatTransportMode = 'firestore' | 'realtime';
|
|
98
|
+
/**
|
|
99
|
+
* Realtime (Durable Object) transport handle. The concrete socket client is built
|
|
100
|
+
* in this package (`realtime/transport.ts`); chat-react consumes it through this
|
|
101
|
+
* config so the UI stays transport-agnostic. The app builds the `client` via
|
|
102
|
+
* `createRealtimeChatClient({ endpoint, channelRef, grantProvider, ... })` and
|
|
103
|
+
* passes it here. `channelRef`/`client` stay structurally typed (`unknown` at the
|
|
104
|
+
* config seam) so `ChatCoreConfig` does not pull the realtime module's types into
|
|
105
|
+
* every firestore consumer — the realtime hook narrows them at the call site.
|
|
106
|
+
*/
|
|
107
|
+
export interface ChatRealtimeTransportConfig {
|
|
108
|
+
/** Opaque channel reference the socket is scoped to (guild channel / invite thread). */
|
|
109
|
+
channelRef: unknown;
|
|
110
|
+
/**
|
|
111
|
+
* The realtime client handle from `createRealtimeChatClient(...)`. Drives the
|
|
112
|
+
* channel socket (subscribe / send / ack / typing / presence / history). The UI
|
|
113
|
+
* never reaches into the socket directly — it goes through `useRealtimeChatMessages`.
|
|
114
|
+
*/
|
|
115
|
+
client: unknown;
|
|
116
|
+
}
|
|
89
117
|
export type ChatCoreConfig = {
|
|
90
118
|
chatCollectionPath: string | string[];
|
|
91
119
|
messagesSubcollection?: string;
|
|
@@ -94,7 +122,16 @@ export type ChatCoreConfig = {
|
|
|
94
122
|
currentUserDisplayName?: string;
|
|
95
123
|
isAdmin: boolean;
|
|
96
124
|
/**
|
|
97
|
-
*
|
|
125
|
+
* Which transport backs this thread. Defaults to `'firestore'` (the current
|
|
126
|
+
* path) so existing call sites are unchanged. See {@link ChatTransportMode}.
|
|
127
|
+
*/
|
|
128
|
+
transport?: ChatTransportMode;
|
|
129
|
+
/** Required iff `transport === 'realtime'`; ignored on the firestore transport. */
|
|
130
|
+
realtime?: ChatRealtimeTransportConfig;
|
|
131
|
+
/**
|
|
132
|
+
* The Firestore data-access gate (see ChatAccessMode docs in
|
|
133
|
+
* @ttt-productions/chat-core). REQUIRED. On the `realtime` transport this is
|
|
134
|
+
* PRESENTATION-ONLY — the DO grant is the real data-access authority.
|
|
98
135
|
*/
|
|
99
136
|
accessMode: ChatAccessMode;
|
|
100
137
|
/**
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,eAAe,EACf,UAAU,EACV,qBAAqB,EACtB,MAAM,4BAA4B,CAAC;AAMpC,sEAAsE;AACtE,MAAM,MAAM,qBAAqB,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,IAAI,CACjE,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,KACnB,SAAS,CAAC;AAEf;;;;GAIG;AACH,MAAM,MAAM,yBAAyB,CACnC,KAAK,SAAS,MAAM,GAAG,MAAM,EAC7B,QAAQ,GAAG,OAAO,IAChB,eAAe,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG;IACrC;;;OAGG;IACH,YAAY,CAAC,EAAE,qBAAqB,CAAC,KAAK,CAAC,CAAC;CAC7C,CAAC;AAMF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,+EAA+E;IAC/E,QAAQ,EAAE,MAAM,CAAC;IACjB,kFAAkF;IAClF,eAAe,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAC;IAC5E,6FAA6F;IAC7F,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnG,CAAC;AAMF,MAAM,MAAM,oBAAoB,GAAG;IACjC,cAAc,EAAE,eAAe,CAAC;IAChC,OAAO,EAAE,eAAe,CAAC;IACzB,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,aAAa,EAAE,iBAAiB,CAAC;CAClC,CAAC;AAMF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,kCAAkC;IAClC,SAAS,EAAE,yBAAyB,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACxD,6DAA6D;IAC7D,OAAO,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,MAAM,CAAC,EAAE,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACvC,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,SAAS,CAAC;CAChD,CAAC;AAMF,MAAM,MAAM,cAAc,GAAG;IAC3B,kBAAkB,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACtC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/ChatShell.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { ChatCoreConfig, ChatAttachmentConfig, MessageRendererRegistry } fr
|
|
|
4
4
|
export type ChatShellProps = {
|
|
5
5
|
config: ChatCoreConfig;
|
|
6
6
|
header?: React.ReactNode;
|
|
7
|
-
onSend
|
|
7
|
+
onSend?: (text: string, replyTo?: ChatMessageV1["replyTo"]) => Promise<void>;
|
|
8
8
|
renderMessage?: (m: any) => React.ReactNode;
|
|
9
9
|
messageRenderers?: MessageRendererRegistry;
|
|
10
10
|
handlers?: ModerationHandlers;
|
|
@@ -27,5 +27,11 @@ export type ChatShellProps = {
|
|
|
27
27
|
* Usually unnecessary — prefer `fillHeight`. */
|
|
28
28
|
scrollClassName?: string;
|
|
29
29
|
};
|
|
30
|
+
/**
|
|
31
|
+
* ChatShell dispatches on `config.transport`. Hooks must be unconditional, so the
|
|
32
|
+
* two transports live in separate inner components (each calls exactly ONE data
|
|
33
|
+
* hook) and both render the shared presentational `ChatShellView`. The default
|
|
34
|
+
* (undefined / 'firestore') transport is byte-for-byte the previous behavior.
|
|
35
|
+
*/
|
|
30
36
|
export declare function ChatShell(props: ChatShellProps): React.JSX.Element;
|
|
31
37
|
//# sourceMappingURL=ChatShell.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatShell.d.ts","sourceRoot":"","sources":["../../src/ui/ChatShell.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACtG,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACpB,uBAAuB,EACxB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"ChatShell.d.ts","sourceRoot":"","sources":["../../src/ui/ChatShell.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACtG,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACpB,uBAAuB,EACxB,MAAM,aAAa,CAAC;AAUrB,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,cAAc,CAAC;IAGvB,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAKzB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAG7E,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,KAAK,CAAC,SAAS,CAAC;IAC5C,gBAAgB,CAAC,EAAE,uBAAuB,CAAC;IAC3C,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAG9B,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;IACxC,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAClC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;IAGpB,mBAAmB,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IAC5C,mBAAmB,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IAC5C,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IAGrC,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAGhE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;;6FAGyF;IACzF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;qDACiD;IACjD,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAcF;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,qBAK9C"}
|
package/dist/ui/ChatShell.js
CHANGED
|
@@ -4,12 +4,60 @@ import * as React from "react";
|
|
|
4
4
|
import { Card, CardHeader, CardContent, CardFooter, Skeleton } from "@ttt-productions/ui-core/react";
|
|
5
5
|
import { KeyboardAvoidingView } from "@ttt-productions/mobile-core/react";
|
|
6
6
|
import { useChatMessages } from "../hooks/useChatMessages.js";
|
|
7
|
+
import { useRealtimeChatMessages } from "../realtime/useRealtimeChatMessages.js";
|
|
7
8
|
import { MessageList } from "./MessageList.js";
|
|
8
9
|
import { Composer } from "./Composer.js";
|
|
9
10
|
import { ThreadActions } from "./menus.js";
|
|
11
|
+
/**
|
|
12
|
+
* ChatShell dispatches on `config.transport`. Hooks must be unconditional, so the
|
|
13
|
+
* two transports live in separate inner components (each calls exactly ONE data
|
|
14
|
+
* hook) and both render the shared presentational `ChatShellView`. The default
|
|
15
|
+
* (undefined / 'firestore') transport is byte-for-byte the previous behavior.
|
|
16
|
+
*/
|
|
10
17
|
export function ChatShell(props) {
|
|
11
|
-
|
|
12
|
-
|
|
18
|
+
if (props.config.transport === "realtime") {
|
|
19
|
+
return _jsx(RealtimeChatShell, { ...props });
|
|
20
|
+
}
|
|
21
|
+
return _jsx(FirestoreChatShell, { ...props });
|
|
22
|
+
}
|
|
23
|
+
function FirestoreChatShell(props) {
|
|
24
|
+
const { config, onSend } = props;
|
|
25
|
+
const r = useChatMessages(config);
|
|
26
|
+
const send = React.useCallback(async (text, replyTo) => {
|
|
27
|
+
if (onSend)
|
|
28
|
+
await onSend(text, replyTo);
|
|
29
|
+
}, [onSend]);
|
|
30
|
+
return _jsx(ChatShellView, { ...props, resolved: { ...r, send } });
|
|
31
|
+
}
|
|
32
|
+
function RealtimeChatShell(props) {
|
|
33
|
+
const { config, onSend } = props;
|
|
34
|
+
const client = config.realtime?.client;
|
|
35
|
+
if (!client) {
|
|
36
|
+
throw new Error("[ChatShell] transport 'realtime' requires config.realtime.client (createRealtimeChatClient(...))");
|
|
37
|
+
}
|
|
38
|
+
const r = useRealtimeChatMessages(client);
|
|
39
|
+
const send = React.useCallback(async (text, replyTo) => {
|
|
40
|
+
// Map the UI replyTo (messageId-based) to the wire replyTo (seq + preview).
|
|
41
|
+
const wireReply = replyTo && replyTo.messageId
|
|
42
|
+
? { messageSeq: Number(replyTo.messageId), preview: replyTo.messagePreview ?? "" }
|
|
43
|
+
: null;
|
|
44
|
+
r.send(text, Number.isFinite(wireReply?.messageSeq) ? wireReply : null);
|
|
45
|
+
if (onSend)
|
|
46
|
+
await onSend(text, replyTo); // optional mirror
|
|
47
|
+
}, [r, onSend]);
|
|
48
|
+
return (_jsx(ChatShellView, { ...props, resolved: {
|
|
49
|
+
allowed: r.allowed,
|
|
50
|
+
isInitialLoading: r.isInitialLoading,
|
|
51
|
+
messages: r.messages,
|
|
52
|
+
fetchOlder: r.fetchOlder,
|
|
53
|
+
hasOlder: r.hasOlder,
|
|
54
|
+
isFetchingOlder: r.isFetchingOlder,
|
|
55
|
+
send,
|
|
56
|
+
} }));
|
|
57
|
+
}
|
|
58
|
+
function ChatShellView(props) {
|
|
59
|
+
const { config, header, renderMessage, messageRenderers, handlers, attachmentConfig, sendAttachment, composerPlaceholder, autoFocus = false, renderAboveMessages, renderBelowMessages, renderFooter, onSenderClick, composerDisabled, fillHeight = false, scrollClassName, resolved, } = props;
|
|
60
|
+
const { allowed, isInitialLoading, messages, fetchOlder, hasOlder, isFetchingOlder, send } = resolved;
|
|
13
61
|
const [showScrollToBottom, setShowScrollToBottom] = React.useState(false);
|
|
14
62
|
// In fill mode the Card flexes to its parent's height and the message list fills the
|
|
15
63
|
// space between header and composer; otherwise it's the default natural-height card.
|
|
@@ -21,6 +69,6 @@ export function ChatShell(props) {
|
|
|
21
69
|
if (isInitialLoading) {
|
|
22
70
|
return (_jsxs(Card, { className: cardClassName, children: [_jsxs(CardHeader, { className: "space-y-2", children: [_jsx(Skeleton, { className: "h-5 w-40" }), _jsx(Skeleton, { className: "h-3 w-56" })] }), _jsx(CardContent, { children: _jsx(Skeleton, { className: "h-[240px] w-full" }) }), _jsx(CardFooter, { children: _jsx(Skeleton, { className: "h-10 w-full" }) })] }));
|
|
23
71
|
}
|
|
24
|
-
return (_jsxs(Card, { className: cardClassName, children: [(header || handlers) && (_jsxs(CardHeader, { className: "flex flex-row items-start justify-between gap-4 space-y-0", children: [_jsx("div", { children: header }), _jsx("div", { className: "flex flex-col items-end gap-2", children: _jsx(ThreadActions, { threadId: config.threadId, isAdmin: config.isAdmin, handlers: handlers }) })] })), renderAboveMessages && (_jsx("div", { className: "border-b", children: renderAboveMessages() })), _jsx(CardContent, { className: contentClassName, children: _jsx(MessageList, { messages: messages, currentUserId: config.currentUserId, isAdmin: config.isAdmin, isFetchingOlder: isFetchingOlder, hasOlder: hasOlder, onLoadOlder: () => fetchOlder(), renderMessage: renderMessage, messageRenderers: messageRenderers, showScrollToBottom: showScrollToBottom, onScrollToBottom: () => setShowScrollToBottom(false), fillHeight: fillHeight, scrollClassName: scrollClassName, handlers: handlers, onSenderClick: onSenderClick }) }), renderBelowMessages && (_jsx("div", { className: "border-t", children: renderBelowMessages() })), renderFooter ? (_jsx(CardFooter, { className: "border-t", children: renderFooter() })) : (_jsx(CardFooter, { className: "border-t", children: _jsx(KeyboardAvoidingView, { padding: true, offset: 8, className: "w-full", children: _jsx(Composer, { onSend:
|
|
72
|
+
return (_jsxs(Card, { className: cardClassName, children: [(header || handlers) && (_jsxs(CardHeader, { className: "flex flex-row items-start justify-between gap-4 space-y-0", children: [_jsx("div", { children: header }), _jsx("div", { className: "flex flex-col items-end gap-2", children: _jsx(ThreadActions, { threadId: config.threadId, isAdmin: config.isAdmin, handlers: handlers }) })] })), renderAboveMessages && (_jsx("div", { className: "border-b", children: renderAboveMessages() })), _jsx(CardContent, { className: contentClassName, children: _jsx(MessageList, { messages: messages, currentUserId: config.currentUserId, isAdmin: config.isAdmin, isFetchingOlder: isFetchingOlder, hasOlder: hasOlder, onLoadOlder: () => fetchOlder(), renderMessage: renderMessage, messageRenderers: messageRenderers, showScrollToBottom: showScrollToBottom, onScrollToBottom: () => setShowScrollToBottom(false), fillHeight: fillHeight, scrollClassName: scrollClassName, handlers: handlers, onSenderClick: onSenderClick }) }), renderBelowMessages && (_jsx("div", { className: "border-t", children: renderBelowMessages() })), renderFooter ? (_jsx(CardFooter, { className: "border-t", children: renderFooter() })) : (_jsx(CardFooter, { className: "border-t", children: _jsx(KeyboardAvoidingView, { padding: true, offset: 8, className: "w-full", children: _jsx(Composer, { onSend: send, attachmentConfig: attachmentConfig, sendAttachment: sendAttachment, disabled: composerDisabled, autoFocus: autoFocus, placeholder: composerPlaceholder, mentionConfig: config.mentionConfig }) }) }))] }));
|
|
25
73
|
}
|
|
26
74
|
//# sourceMappingURL=ChatShell.js.map
|
package/dist/ui/ChatShell.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatShell.js","sourceRoot":"","sources":["../../src/ui/ChatShell.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AACrG,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"ChatShell.js","sourceRoot":"","sources":["../../src/ui/ChatShell.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttt-productions/chat-react",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "Chat React UI, hooks, and Firebase-client adapter for TTT Productions apps (realtime newest window + infinite older pagination)",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"@tanstack/react-query": ">=5.0.0",
|
|
36
|
-
"@ttt-productions/query-core": "^0.13.
|
|
36
|
+
"@ttt-productions/query-core": "^0.13.2",
|
|
37
37
|
"firebase": ">=12.0.0",
|
|
38
38
|
"lucide-react": ">=0.0.0",
|
|
39
39
|
"react": ">=19.0.0",
|
|
@@ -62,16 +62,17 @@
|
|
|
62
62
|
"dependencies": {
|
|
63
63
|
"@ttt-productions/chat-core": "^0.10.0",
|
|
64
64
|
"@ttt-productions/chat-schemas": "^0.9.0",
|
|
65
|
-
"@ttt-productions/
|
|
65
|
+
"@ttt-productions/realtime-core": "^0.1.1",
|
|
66
|
+
"@ttt-productions/media-schemas": "^0.11.1",
|
|
66
67
|
"@ttt-productions/ui-core": "^0.11.0",
|
|
67
68
|
"@ttt-productions/file-input": "^0.9.0",
|
|
68
|
-
"@ttt-productions/upload-ui": "^0.7.
|
|
69
|
-
"@ttt-productions/media-viewer": "^0.8.
|
|
69
|
+
"@ttt-productions/upload-ui": "^0.7.1",
|
|
70
|
+
"@ttt-productions/media-viewer": "^0.8.1",
|
|
70
71
|
"@ttt-productions/mobile-core": "^0.9.0",
|
|
71
72
|
"@ttt-productions/firebase-helpers": "^0.11.0"
|
|
72
73
|
},
|
|
73
74
|
"devDependencies": {
|
|
74
|
-
"@ttt-productions/query-core": "^0.13.
|
|
75
|
+
"@ttt-productions/query-core": "^0.13.2",
|
|
75
76
|
"@types/react": "^19.0.0",
|
|
76
77
|
"@types/react-dom": "^19.0.0",
|
|
77
78
|
"react": "^19.0.0",
|