@orbitconnect/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/CHANGELOG.md +56 -0
- package/LICENSE +21 -0
- package/README.md +374 -0
- package/dist/OrbitContext.d.ts +87 -0
- package/dist/OrbitProvider.d.ts +24 -0
- package/dist/api/client.d.ts +44 -0
- package/dist/api/index.d.ts +2 -0
- package/dist/bg.svg +1 -0
- package/dist/call/CallContext.d.ts +27 -0
- package/dist/call/CallProvider.d.ts +4 -0
- package/dist/components/call/CallControls.d.ts +18 -0
- package/dist/components/call/CallHistory.d.ts +22 -0
- package/dist/components/call/CallScreen.d.ts +11 -0
- package/dist/components/call/InCallChatPanel.d.ts +7 -0
- package/dist/components/call/IncomingCallModal.d.ts +8 -0
- package/dist/components/call/OutgoingCallScreen.d.ts +8 -0
- package/dist/components/call/VideoCallScreen.d.ts +23 -0
- package/dist/components/call/index.d.ts +11 -0
- package/dist/components/chat/AttachmentPicker.d.ts +23 -0
- package/dist/components/chat/AttachmentRenderer.d.ts +15 -0
- package/dist/components/chat/AudioRecorder.d.ts +6 -0
- package/dist/components/chat/BatchToolbar.d.ts +8 -0
- package/dist/components/chat/CallBanner.d.ts +14 -0
- package/dist/components/chat/ChatBox.d.ts +90 -0
- package/dist/components/chat/Composer.d.ts +15 -0
- package/dist/components/chat/ConversationList.d.ts +32 -0
- package/dist/components/chat/ConversationPicker.d.ts +7 -0
- package/dist/components/chat/ConversationProfile.d.ts +13 -0
- package/dist/components/chat/DocumentViewer.d.ts +2 -0
- package/dist/components/chat/EmojiPicker.d.ts +5 -0
- package/dist/components/chat/ImageViewer.d.ts +2 -0
- package/dist/components/chat/LinkPreview.d.ts +7 -0
- package/dist/components/chat/MediaMessage.d.ts +5 -0
- package/dist/components/chat/MediaViewer.d.ts +13 -0
- package/dist/components/chat/MessageActionMenu.d.ts +16 -0
- package/dist/components/chat/MessageBubble.d.ts +61 -0
- package/dist/components/chat/MessageInfoSheet.d.ts +7 -0
- package/dist/components/chat/MessageInput.d.ts +12 -0
- package/dist/components/chat/MessageList.d.ts +7 -0
- package/dist/components/chat/QuickMessages.d.ts +17 -0
- package/dist/components/chat/ReactionDialog.d.ts +6 -0
- package/dist/components/chat/ReplyComposer.d.ts +8 -0
- package/dist/components/chat/StickerPicker.d.ts +21 -0
- package/dist/components/chat/VideoViewer.d.ts +2 -0
- package/dist/components/chat/emojiData.d.ts +9 -0
- package/dist/components/chat/index.d.ts +44 -0
- package/dist/components/chat/mediaViewerRegistry.d.ts +22 -0
- package/dist/components/chat/urlUtils.d.ts +1 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/meeting/MeetingControls.d.ts +15 -0
- package/dist/components/meeting/MeetingRoom.d.ts +27 -0
- package/dist/components/meeting/ParticipantGrid.d.ts +6 -0
- package/dist/components/meeting/ParticipantsPanel.d.ts +8 -0
- package/dist/components/meeting/ReactionBurst.d.ts +9 -0
- package/dist/components/meeting/ScreenShareView.d.ts +5 -0
- package/dist/components/meeting/WaitingRoom.d.ts +7 -0
- package/dist/components/meeting/index.d.ts +8 -0
- package/dist/components/ui/Avatar.d.ts +13 -0
- package/dist/components/ui/BottomNav.d.ts +8 -0
- package/dist/components/ui/EscalationButton.d.ts +12 -0
- package/dist/components/ui/IconBtn.d.ts +8 -0
- package/dist/components/ui/PoweredBy.d.ts +1 -0
- package/dist/components/ui/index.d.ts +5 -0
- package/dist/favicon.svg +1 -0
- package/dist/hooks/index.d.ts +20 -0
- package/dist/hooks/useAppBrand.d.ts +6 -0
- package/dist/hooks/useCall.d.ts +2 -0
- package/dist/hooks/useCallHistory.d.ts +5 -0
- package/dist/hooks/useConversations.d.ts +7 -0
- package/dist/hooks/useMedia.d.ts +19 -0
- package/dist/hooks/useMeeting.d.ts +22 -0
- package/dist/hooks/useMeetingWebRTC.d.ts +28 -0
- package/dist/hooks/useMessages.d.ts +11 -0
- package/dist/hooks/useNotifications.d.ts +19 -0
- package/dist/hooks/usePresence.d.ts +8 -0
- package/dist/hooks/usePushToken.d.ts +11 -0
- package/dist/hooks/useRealtime.d.ts +21 -0
- package/dist/hooks/useRecording.d.ts +16 -0
- package/dist/hooks/useSound.d.ts +9 -0
- package/dist/hooks/useWebRTC.d.ts +12 -0
- package/dist/icons.svg +24 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +12441 -0
- package/dist/meeting/MeetingContext.d.ts +19 -0
- package/dist/meeting/MeetingProvider.d.ts +4 -0
- package/dist/meeting/index.d.ts +3 -0
- package/dist/socket/OrbitListenerProvider.d.ts +14 -0
- package/dist/socket/OrbitSocket.d.ts +97 -0
- package/dist/socket/config.d.ts +10 -0
- package/dist/socket/context.d.ts +10 -0
- package/dist/socket/events.d.ts +283 -0
- package/dist/socket/index.d.ts +8 -0
- package/dist/socket/useOrbitEvent.d.ts +8 -0
- package/dist/theme/ThemeProvider.d.ts +17 -0
- package/dist/theme/defaults.d.ts +3 -0
- package/dist/theme/index.d.ts +3 -0
- package/dist/theme/types.d.ts +85 -0
- package/dist/widgets/Chat.d.ts +13 -0
- package/dist/widgets/MeetingWidget.d.ts +6 -0
- package/dist/widgets/VideoCall.d.ts +1 -0
- package/dist/widgets/index.d.ts +6 -0
- package/package.json +79 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@orbitconnect/react` will be documented here.
|
|
4
|
+
|
|
5
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## [0.1.0] — 2025-04-27
|
|
10
|
+
|
|
11
|
+
Initial public release.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
**Core**
|
|
16
|
+
- `OrbitProvider` — root context provider with WebSocket lifecycle, token refresh (`onTokenExpired`), and theming
|
|
17
|
+
- `useOrbit` — access `apiClient`, `appUserId`, `clientId`, `baseUrl`, `appConfig` from any child
|
|
18
|
+
- `useAppConfig` — resolved feature flags and icon overrides from `AppConfig`
|
|
19
|
+
|
|
20
|
+
**Widgets**
|
|
21
|
+
- `Chat` — full-featured chat UI: conversation list, message bubbles, composer, reactions, reply/quote, file/image/video/audio attachments, voice recording, emoji & sticker picker, message search, pin, batch select/delete/forward, presence, call history
|
|
22
|
+
- `VideoCall` — floating WebRTC call overlay, renders automatically when a call is active
|
|
23
|
+
- `MeetingWidget` — full video-conferencing room with participant grid, screen share, reactions, and hand-raise
|
|
24
|
+
|
|
25
|
+
**Hooks**
|
|
26
|
+
- `useMessages` — real-time messages with typing indicators, pinned messages, read receipts, reactions, recall, edit
|
|
27
|
+
- `useConversations` — conversation list with live presence, typing, and delivery status
|
|
28
|
+
- `useCall` — full call lifecycle: initiate, accept, reject, end, mute, camera toggle
|
|
29
|
+
- `useMeeting` — meeting lifecycle: join, leave, mute, screen share, raise hand, reactions
|
|
30
|
+
- `useMedia` — file upload with `upload()` and `getUrl()`
|
|
31
|
+
- `useNotifications` — in-app notification feed with unread count, mark read, mark all read, clear
|
|
32
|
+
- `usePresence` — real-time presence status per user (`online` / `away` / `offline`)
|
|
33
|
+
- `useCallHistory` — call records with caller/callee info
|
|
34
|
+
- `useRealtime` — session lifecycle with transitions (chat → call → meeting) and custom event emission
|
|
35
|
+
- `useOrbitEvent` — subscribe to any raw WebSocket event
|
|
36
|
+
- `useOrbitListener` — access the raw socket and connection status
|
|
37
|
+
|
|
38
|
+
**Meeting context**
|
|
39
|
+
- `MeetingProvider`, `MeetingContext`, `useMeetingContext` — standalone meeting context for custom meeting UIs
|
|
40
|
+
|
|
41
|
+
**Theme**
|
|
42
|
+
- `ThemeProvider`, `useTheme`, `darkTheme`, `lightTheme`
|
|
43
|
+
- Full CSS variable token set: backgrounds, foregrounds, bubbles, composer, borders, radii, fonts
|
|
44
|
+
- `PartialTheme` type for partial overrides via `OrbitProvider`
|
|
45
|
+
|
|
46
|
+
**Stylesheet**
|
|
47
|
+
- `dist/index.css` — pre-built Tailwind CSS stylesheet, import once via `import '@orbitconnect/react/index.css'`
|
|
48
|
+
|
|
49
|
+
**Build**
|
|
50
|
+
- Vite library build (ESM only) with React Compiler (babel-plugin-react-compiler)
|
|
51
|
+
- TypeScript declarations emitted to `dist/` via `tsc -p tsconfig.build.json`
|
|
52
|
+
- Tailwind CSS minified and bundled to `dist/index.css`
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
[0.1.0]: https://github.com/core-dynamics/orbitconnect-sdk/releases/tag/react-v0.1.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 OrbitConnect
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
# @orbitconnect/react
|
|
2
|
+
|
|
3
|
+
React SDK for OrbitConnect — drop in real-time chat, voice/video calls, and meetings into any React app.
|
|
4
|
+
|
|
5
|
+
> The SDK connects exclusively to `https://orbitxyz.muvle.org/api/v1`. This base URL is fixed and cannot be overridden.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @orbitconnect/react
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Also import the stylesheet once in your entry file:
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import '@orbitconnect/react/index.css'
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick start
|
|
20
|
+
|
|
21
|
+
### 1. Backend — issue a user token
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
// Express / Next.js API route
|
|
25
|
+
import { OrbitServer } from '@orbitconnect/server'
|
|
26
|
+
|
|
27
|
+
const orbit = new OrbitServer({ secretKey: process.env.ORBIT_SECRET_KEY! })
|
|
28
|
+
|
|
29
|
+
app.post('/auth/token', async (req, res) => {
|
|
30
|
+
const user = await orbit.users.create({
|
|
31
|
+
external_id: req.user.id,
|
|
32
|
+
display_name: req.user.name,
|
|
33
|
+
})
|
|
34
|
+
const { token } = await orbit.users.createToken(user.id)
|
|
35
|
+
res.json({ token, userId: user.id, clientId: process.env.ORBIT_CLIENT_ID })
|
|
36
|
+
})
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 2. Frontend — wrap with OrbitProvider
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import { OrbitProvider, Chat } from '@orbitconnect/react'
|
|
43
|
+
import '@orbitconnect/react/index.css'
|
|
44
|
+
|
|
45
|
+
export function App() {
|
|
46
|
+
const [auth, setAuth] = useState(null)
|
|
47
|
+
|
|
48
|
+
async function login() {
|
|
49
|
+
const data = await fetch('/auth/token', { method: 'POST' }).then(r => r.json())
|
|
50
|
+
setAuth(data)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!auth) return <button onClick={login}>Sign in</button>
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<OrbitProvider
|
|
57
|
+
clientId={auth.clientId}
|
|
58
|
+
userToken={auth.token}
|
|
59
|
+
appUserId={auth.userId}
|
|
60
|
+
>
|
|
61
|
+
<Chat />
|
|
62
|
+
</OrbitProvider>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
That's it — you now have a fully functional chat with real-time messaging, presence, reactions, file attachments, and voice/video calls.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## OrbitProvider
|
|
72
|
+
|
|
73
|
+
The root context provider. Wrap your app (or the section that uses OrbitConnect) with it once.
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
<OrbitProvider
|
|
77
|
+
clientId="pk_live_..."
|
|
78
|
+
userToken={token}
|
|
79
|
+
appUserId={userId}
|
|
80
|
+
baseTheme={darkTheme}
|
|
81
|
+
theme={{ primary: '#7c3aed', bubbleSender: '#7c3aed' }}
|
|
82
|
+
appConfig={{ name: 'MyApp', showPoweredBy: false }}
|
|
83
|
+
onTokenExpired={async () => fetchFreshToken()}
|
|
84
|
+
>
|
|
85
|
+
<App />
|
|
86
|
+
</OrbitProvider>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
| Prop | Type | Required | Description |
|
|
90
|
+
| --- | --- | --- | --- |
|
|
91
|
+
| `clientId` | `string` | ✓ | Publishable key (`pk_live_…` or `pk_test_…`) |
|
|
92
|
+
| `userToken` | `string` | ✓ | Short-lived token from `orbit.users.createToken()` |
|
|
93
|
+
| `appUserId` | `string` | ✓ | The authenticated app user ID |
|
|
94
|
+
| `theme` | `PartialTheme` | | CSS variable overrides — see [Theming](#theming) |
|
|
95
|
+
| `baseTheme` | `OrbitTheme` | | Base theme object (default: `darkTheme`) |
|
|
96
|
+
| `appConfig` | `AppConfig` | | Branding, icons, sounds — see [AppConfig](#appconfig) |
|
|
97
|
+
| `onTokenExpired` | `() => Promise<string>` | | Called on WS close 4001 — return a fresh token to reconnect |
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Widgets
|
|
102
|
+
|
|
103
|
+
Drop-in components that work out of the box inside `OrbitProvider`.
|
|
104
|
+
|
|
105
|
+
### Chat
|
|
106
|
+
|
|
107
|
+
Full-featured chat UI — conversation list, message bubbles, composer, reactions, file attachments, voice messages, call buttons, and more.
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
import { Chat } from '@orbitconnect/react'
|
|
111
|
+
|
|
112
|
+
<Chat
|
|
113
|
+
onCallRequest={(userId, type) => initiateCall(userId, type)}
|
|
114
|
+
chatBanner={<div>Support hours: Mon–Fri 9am–5pm</div>}
|
|
115
|
+
defaultQuickMessages={[
|
|
116
|
+
{ id: '1', label: 'Greeting', text: 'Hi! How can I help?' },
|
|
117
|
+
]}
|
|
118
|
+
/>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
| Prop | Type | Description |
|
|
122
|
+
| --- | --- | --- |
|
|
123
|
+
| `conversationId` | `string` | Open directly to a specific conversation |
|
|
124
|
+
| `onCallRequest` | `(userId, type) => void` | Called when the user taps the call/video button |
|
|
125
|
+
| `renderHeader` | `(info: ChatHeaderInfo) => ReactNode` | Replace the default header |
|
|
126
|
+
| `chatBanner` | `ReactNode` | Rendered above the message list |
|
|
127
|
+
| `defaultQuickMessages` | `QuickMessage[]` | Seed the quick-message picker |
|
|
128
|
+
|
|
129
|
+
Included out of the box: real-time messaging, typing indicators, read receipts, reactions, reply/quote, file/image/video/audio attachments, voice recording, sticker & GIF picker, message search, pin messages, batch select/delete/forward, presence, call history.
|
|
130
|
+
|
|
131
|
+
### VideoCall
|
|
132
|
+
|
|
133
|
+
Floating WebRTC call overlay — renders automatically when a call is active.
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
import { VideoCall, useCall } from '@orbitconnect/react'
|
|
137
|
+
|
|
138
|
+
function App() {
|
|
139
|
+
const { initiateCall } = useCall()
|
|
140
|
+
return (
|
|
141
|
+
<>
|
|
142
|
+
<button onClick={() => initiateCall(userId, 'video')}>Start call</button>
|
|
143
|
+
<VideoCall /> {/* place once at the root */}
|
|
144
|
+
</>
|
|
145
|
+
)
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### MeetingWidget
|
|
150
|
+
|
|
151
|
+
Full video-conferencing room with participant grid, screen share, reactions, and hand-raise.
|
|
152
|
+
|
|
153
|
+
```tsx
|
|
154
|
+
import { MeetingWidget } from '@orbitconnect/react'
|
|
155
|
+
|
|
156
|
+
<MeetingWidget
|
|
157
|
+
meetingId={activeMeetingId}
|
|
158
|
+
title="Team Standup"
|
|
159
|
+
onEnd={() => setScreen('lobby')}
|
|
160
|
+
/>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
| Prop | Type | Required | Description |
|
|
164
|
+
| --- | --- | --- | --- |
|
|
165
|
+
| `meetingId` | `string` | ✓ | The meeting ID to join |
|
|
166
|
+
| `title` | `string` | | Display title (default: `"Meeting"`) |
|
|
167
|
+
| `onEnd` | `() => void` | | Called when the meeting ends or the user leaves |
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Hooks
|
|
172
|
+
|
|
173
|
+
All hooks must be used inside `OrbitProvider`.
|
|
174
|
+
|
|
175
|
+
### useMessages(conversationId)
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
const {
|
|
179
|
+
messages, // MessageBubbleProps[]
|
|
180
|
+
loading,
|
|
181
|
+
typingUsers, // string[] — display names of typing users
|
|
182
|
+
pinnedMessages,
|
|
183
|
+
sendMessage, // (text, mediaId?, meta?) => Promise<void>
|
|
184
|
+
sendTyping,
|
|
185
|
+
markRead,
|
|
186
|
+
editMessageLocally,
|
|
187
|
+
} = useMessages(conversationId)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### useConversations()
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
const {
|
|
194
|
+
conversations, // Conversation[]
|
|
195
|
+
loading,
|
|
196
|
+
createDirect, // (participantId: string) => Promise<string>
|
|
197
|
+
refresh,
|
|
198
|
+
} = useConversations()
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### useCall()
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
const {
|
|
205
|
+
call, // ActiveCall | null
|
|
206
|
+
localStream, // MediaStream | null
|
|
207
|
+
remoteStream, // MediaStream | null
|
|
208
|
+
initiateCall, // (userId, type, conversationId?) => void
|
|
209
|
+
acceptCall,
|
|
210
|
+
rejectCall,
|
|
211
|
+
endCall,
|
|
212
|
+
toggleMute, // (muted: boolean) => void
|
|
213
|
+
toggleCamera, // (enabled: boolean) => void
|
|
214
|
+
dismissEnded,
|
|
215
|
+
} = useCall()
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### useNotifications()
|
|
219
|
+
|
|
220
|
+
```ts
|
|
221
|
+
const {
|
|
222
|
+
notifications, // OrbitNotification[]
|
|
223
|
+
unreadCount,
|
|
224
|
+
markRead, // (id: string) => void
|
|
225
|
+
markAllRead,
|
|
226
|
+
clearAll,
|
|
227
|
+
} = useNotifications()
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### usePresence(userId)
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
const status = usePresence(userId) // 'online' | 'away' | 'offline'
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### useMedia()
|
|
237
|
+
|
|
238
|
+
```ts
|
|
239
|
+
const {
|
|
240
|
+
upload, // (file: File) => Promise<MediaObject>
|
|
241
|
+
getUrl, // (mediaId: string) => Promise<string>
|
|
242
|
+
} = useMedia()
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### useRealtime()
|
|
246
|
+
|
|
247
|
+
```ts
|
|
248
|
+
const {
|
|
249
|
+
session,
|
|
250
|
+
createSession, // (input: CreateSessionInput) => Promise<void>
|
|
251
|
+
endSession,
|
|
252
|
+
transition, // (type: TransitionType, contextId?: string) => Promise<void>
|
|
253
|
+
emitEvent, // (eventType: string, payload: object) => Promise<void>
|
|
254
|
+
} = useRealtime()
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### useOrbitEvent(eventType, handler)
|
|
258
|
+
|
|
259
|
+
Subscribe to any raw WebSocket event.
|
|
260
|
+
|
|
261
|
+
```ts
|
|
262
|
+
import { useOrbitEvent } from '@orbitconnect/react'
|
|
263
|
+
|
|
264
|
+
useOrbitEvent('message:new', ({ conversation_id, message }) => {
|
|
265
|
+
console.log('New message:', message)
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
useOrbitEvent('notification:received', ({ payload }) => {
|
|
269
|
+
toast(payload.title as string)
|
|
270
|
+
})
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### useCallHistory()
|
|
274
|
+
|
|
275
|
+
```ts
|
|
276
|
+
const { records } = useCallHistory() // CallRecord[]
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### useOrbit()
|
|
280
|
+
|
|
281
|
+
Access the raw context from any child component.
|
|
282
|
+
|
|
283
|
+
```ts
|
|
284
|
+
const { apiClient, appUserId, clientId, baseUrl, appConfig } = useOrbit()
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Theming
|
|
290
|
+
|
|
291
|
+
Every colour, radius, and font is a CSS variable you can override.
|
|
292
|
+
|
|
293
|
+
```tsx
|
|
294
|
+
import { OrbitProvider, darkTheme, lightTheme } from '@orbitconnect/react'
|
|
295
|
+
import type { PartialTheme } from '@orbitconnect/react'
|
|
296
|
+
|
|
297
|
+
const myTheme: PartialTheme = {
|
|
298
|
+
primary: '#7c3aed',
|
|
299
|
+
bubbleSender: '#7c3aed',
|
|
300
|
+
bubbleSenderForeground: '#fff',
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
<OrbitProvider baseTheme={darkTheme} theme={myTheme} ...>
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Key token groups: `background`, `foreground`, `card`, `border`, `primary`, `bubbleSender`, `bubbleReceiver`, `composerBg`, `radiusSm/Md/Lg/Xl`, `fontBody`.
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## AppConfig
|
|
311
|
+
|
|
312
|
+
White-label every aspect of the UI — name, logo, icons, sounds, and feature flags.
|
|
313
|
+
|
|
314
|
+
```tsx
|
|
315
|
+
<OrbitProvider
|
|
316
|
+
appConfig={{
|
|
317
|
+
name: 'MyApp',
|
|
318
|
+
logo: <MyLogo />,
|
|
319
|
+
showPoweredBy: false,
|
|
320
|
+
|
|
321
|
+
// feature flags
|
|
322
|
+
showAudioIcon: true,
|
|
323
|
+
showVideoIcon: true,
|
|
324
|
+
showSearchIcon: true,
|
|
325
|
+
showAttachMentButton: true,
|
|
326
|
+
showQuickMessageButton: true,
|
|
327
|
+
useRichTextEditor: true,
|
|
328
|
+
enableMeetingUi: true,
|
|
329
|
+
|
|
330
|
+
// icon overrides (any ReactNode)
|
|
331
|
+
sendIcon: <IoPaperPlaneOutline />,
|
|
332
|
+
callIcon: <IoCallOutline />,
|
|
333
|
+
VideoCallIcon: <IoVideocamOutline />,
|
|
334
|
+
|
|
335
|
+
// custom sounds
|
|
336
|
+
sounds: {
|
|
337
|
+
messageSent: '/sounds/sent.mp3',
|
|
338
|
+
messageReceived: '/sounds/received.mp3',
|
|
339
|
+
incomingCall: '/sounds/ring.mp3',
|
|
340
|
+
},
|
|
341
|
+
}}
|
|
342
|
+
>
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Token refresh
|
|
348
|
+
|
|
349
|
+
When the server closes the WebSocket with code `4001` (token expired), the SDK calls `onTokenExpired`. Return a fresh token to reconnect automatically.
|
|
350
|
+
|
|
351
|
+
```tsx
|
|
352
|
+
<OrbitProvider
|
|
353
|
+
onTokenExpired={async () => {
|
|
354
|
+
const res = await fetch('/auth/refresh', { method: 'POST' })
|
|
355
|
+
const data = await res.json()
|
|
356
|
+
return data.token
|
|
357
|
+
}}
|
|
358
|
+
...
|
|
359
|
+
>
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## Build
|
|
365
|
+
|
|
366
|
+
```bash
|
|
367
|
+
npm run build # tsc + vite build + tailwind CSS
|
|
368
|
+
npm run dev # vite dev server (for SDK development)
|
|
369
|
+
npm run lint # eslint
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
## License
|
|
373
|
+
|
|
374
|
+
MIT
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { ApiClient } from './api/client';
|
|
3
|
+
/** Sound asset URLs for SDK events */
|
|
4
|
+
export interface SoundConfig {
|
|
5
|
+
/** Played when the user sends a message */
|
|
6
|
+
messageSent?: string;
|
|
7
|
+
/** Played when a new message is received */
|
|
8
|
+
messageReceived?: string;
|
|
9
|
+
/** Played when the remote user is typing */
|
|
10
|
+
typing?: string;
|
|
11
|
+
/** Played when a reaction is added to a message */
|
|
12
|
+
messageReaction?: string;
|
|
13
|
+
/** Played when an incoming call arrives */
|
|
14
|
+
incomingCall?: string;
|
|
15
|
+
/** Played when a call ends */
|
|
16
|
+
callEnded?: string;
|
|
17
|
+
/** Played when a meeting reaction burst fires */
|
|
18
|
+
meetingReaction?: string;
|
|
19
|
+
}
|
|
20
|
+
/** Branding / white-label config passed to OrbitProvider */
|
|
21
|
+
export interface AppConfig {
|
|
22
|
+
/** Your app name — replaces "OrbitConnect" everywhere */
|
|
23
|
+
name?: string;
|
|
24
|
+
/** A React component rendered as the logo */
|
|
25
|
+
logo?: ReactNode;
|
|
26
|
+
/** Show both name and logo (default when both are provided) */
|
|
27
|
+
showNameAndLogo?: boolean;
|
|
28
|
+
/** Show name only, even if logo is provided */
|
|
29
|
+
showNameOnly?: boolean;
|
|
30
|
+
/** Show logo only, even if name is provided */
|
|
31
|
+
showLogoOnly?: boolean;
|
|
32
|
+
/** Custom sound assets */
|
|
33
|
+
sounds?: SoundConfig;
|
|
34
|
+
/** Show the chat header bar (default: true) */
|
|
35
|
+
showChatHeader?: boolean;
|
|
36
|
+
/** Show the quick-message button in the composer (default: true) */
|
|
37
|
+
showQuickMessageButton?: boolean;
|
|
38
|
+
/** Use the rich-text (contentEditable) editor; false = plain textarea (default: true) */
|
|
39
|
+
useRichTextEditor?: boolean;
|
|
40
|
+
/** Show the attachment button in the composer (default: true) */
|
|
41
|
+
showAttachMentButton?: boolean;
|
|
42
|
+
/** Show the search icon in the chat header (default: true) */
|
|
43
|
+
showSearchIcon?: boolean;
|
|
44
|
+
/** Show the audio-call icon in the chat header (default: true) */
|
|
45
|
+
showAudioIcon?: boolean;
|
|
46
|
+
/** Show the video-call icon in the chat header (default: true) */
|
|
47
|
+
showVideoIcon?: boolean;
|
|
48
|
+
/** Show the meeting tab / meeting UI (default: true) */
|
|
49
|
+
enableMeetingUi?: boolean;
|
|
50
|
+
/** Show "Powered by OrbitConnect" footer in Chat and Meeting widgets (default: true) */
|
|
51
|
+
showPoweredBy?: boolean;
|
|
52
|
+
/** Custom attachment button icon */
|
|
53
|
+
attachmentIcon?: ReactNode;
|
|
54
|
+
/** Custom voice-record button icon */
|
|
55
|
+
recordIcon?: ReactNode;
|
|
56
|
+
/** Custom quick-message button icon */
|
|
57
|
+
QuickmessageIcon?: ReactNode;
|
|
58
|
+
/** Custom emoji button icon */
|
|
59
|
+
emojIcon?: ReactNode;
|
|
60
|
+
/** Custom sticker button icon */
|
|
61
|
+
stickerIcon?: ReactNode;
|
|
62
|
+
/** Custom send button icon */
|
|
63
|
+
sendIcon?: ReactNode;
|
|
64
|
+
/** Custom "delivered" status icon */
|
|
65
|
+
deliveredIcon?: ReactNode;
|
|
66
|
+
/** Custom "sent" status icon */
|
|
67
|
+
sentIcon?: ReactNode;
|
|
68
|
+
/** Custom "read" status icon */
|
|
69
|
+
readIcon?: ReactNode;
|
|
70
|
+
/** Custom audio-call icon (header) */
|
|
71
|
+
callIcon?: ReactNode;
|
|
72
|
+
/** Custom video-call icon (header) */
|
|
73
|
+
VideoCallIcon?: ReactNode;
|
|
74
|
+
}
|
|
75
|
+
export interface OrbitContextValue {
|
|
76
|
+
apiClient: ApiClient;
|
|
77
|
+
/** The authenticated app_user ID */
|
|
78
|
+
appUserId: string;
|
|
79
|
+
clientId: string;
|
|
80
|
+
baseUrl: string;
|
|
81
|
+
/** Optional branding config */
|
|
82
|
+
appConfig?: AppConfig;
|
|
83
|
+
}
|
|
84
|
+
export declare const OrbitContext: import("react").Context<OrbitContextValue | null>;
|
|
85
|
+
export declare function useOrbit(): OrbitContextValue;
|
|
86
|
+
/** Convenience hook — returns appConfig with safe defaults applied */
|
|
87
|
+
export declare function useAppConfig(): Required<Pick<AppConfig, 'showChatHeader' | 'showQuickMessageButton' | 'useRichTextEditor' | 'showAttachMentButton' | 'showSearchIcon' | 'showAudioIcon' | 'showVideoIcon' | 'enableMeetingUi' | 'showPoweredBy'>> & Pick<AppConfig, 'attachmentIcon' | 'recordIcon' | 'QuickmessageIcon' | 'emojIcon' | 'stickerIcon' | 'sendIcon' | 'deliveredIcon' | 'sentIcon' | 'readIcon' | 'callIcon' | 'VideoCallIcon'>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type AppConfig } from './OrbitContext';
|
|
3
|
+
import type { PartialTheme, OrbitTheme } from './theme/types';
|
|
4
|
+
export interface OrbitProviderProps {
|
|
5
|
+
/**
|
|
6
|
+
* Your publishable client ID — safe for the browser.
|
|
7
|
+
* Format: "pk_live_..." or "pk_test_..."
|
|
8
|
+
*/
|
|
9
|
+
clientId: string;
|
|
10
|
+
/** Short-lived user token from orbit.users.createToken() on your backend */
|
|
11
|
+
userToken: string;
|
|
12
|
+
/** The authenticated app_user's ID */
|
|
13
|
+
appUserId: string;
|
|
14
|
+
/** Theme overrides */
|
|
15
|
+
theme?: PartialTheme;
|
|
16
|
+
/** Base theme. Defaults to darkTheme */
|
|
17
|
+
baseTheme?: OrbitTheme;
|
|
18
|
+
/** Called when the WS connection closes with code 4001 (token expired). Should return a fresh token. */
|
|
19
|
+
onTokenExpired?: () => Promise<string>;
|
|
20
|
+
/** Branding / white-label config — replaces "OrbitConnect" with your app name/logo */
|
|
21
|
+
appConfig?: AppConfig;
|
|
22
|
+
children: ReactNode;
|
|
23
|
+
}
|
|
24
|
+
export declare function OrbitProvider({ clientId, userToken, appUserId, theme, baseTheme, onTokenExpired, appConfig, children, }: OrbitProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight fetch client for the client SDK.
|
|
3
|
+
* Uses the user token + client ID — never the secret API key.
|
|
4
|
+
*/
|
|
5
|
+
export interface ApiClientOptions {
|
|
6
|
+
baseUrl: string;
|
|
7
|
+
userToken: string;
|
|
8
|
+
clientId: string;
|
|
9
|
+
/** The authenticated app_user ID — forwarded as X-App-User-Id for per-user rate limiting */
|
|
10
|
+
appUserId: string;
|
|
11
|
+
}
|
|
12
|
+
export declare class ApiClient {
|
|
13
|
+
private readonly opts;
|
|
14
|
+
constructor(opts: ApiClientOptions);
|
|
15
|
+
get baseUrl(): string;
|
|
16
|
+
get userToken(): string;
|
|
17
|
+
get clientId(): string;
|
|
18
|
+
private headers;
|
|
19
|
+
request<T>(method: string, path: string, body?: unknown): Promise<T>;
|
|
20
|
+
get<T>(path: string): Promise<T>;
|
|
21
|
+
post<T>(path: string, body?: unknown): Promise<T>;
|
|
22
|
+
patch<T>(path: string, body?: unknown): Promise<T>;
|
|
23
|
+
delete<T>(path: string): Promise<T>;
|
|
24
|
+
/** Register a device push token so the backend can send FCM/APNs wakeup pushes */
|
|
25
|
+
registerPushToken(token: string, platform: 'android' | 'ios'): Promise<void>;
|
|
26
|
+
/** Send a test notification to yourself (dev/demo use) */
|
|
27
|
+
sendTestNotification(opts?: {
|
|
28
|
+
type?: string;
|
|
29
|
+
title?: string;
|
|
30
|
+
body?: string;
|
|
31
|
+
icon?: string;
|
|
32
|
+
channel?: string;
|
|
33
|
+
actions?: Array<{
|
|
34
|
+
id: string;
|
|
35
|
+
label: string;
|
|
36
|
+
url?: string;
|
|
37
|
+
}>;
|
|
38
|
+
}): Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
export declare class OrbitClientError extends Error {
|
|
41
|
+
readonly status: number;
|
|
42
|
+
readonly code: string | undefined;
|
|
43
|
+
constructor(message: string, status: number, code?: string);
|
|
44
|
+
}
|