@theoremjs/react 0.3.4-next.831.g934609e → 0.3.4-next.841.g5f7aa38
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 +11 -1
- package/components/live/use-live-call.d.ts +1 -0
- package/components/live/use-live-call.js +11 -2
- package/live.d.ts +1 -0
- package/live.js +1 -0
- package/package.json +3 -3
- package/ui/LiveCallTile.d.ts +24 -0
- package/ui/LiveCallTile.js +49 -0
- package/ui/LiveRunner.js +2 -31
- package/ui/LiveVideoPreview.d.ts +10 -0
- package/ui/LiveVideoPreview.js +33 -0
- package/ui/labels.d.ts +4 -0
- package/ui/labels.js +4 -0
package/README.md
CHANGED
|
@@ -147,7 +147,7 @@ The profile, the keys, and the system prompt stay on the server. The browser rec
|
|
|
147
147
|
| --- | --- |
|
|
148
148
|
| `@theoremjs/react` | Hooks, transports, and client logic |
|
|
149
149
|
| `@theoremjs/react/ui` | `TheoremChat`, `TheoremHost`, `TheoremDecision`, `TheoremEmbedding`, and their parts |
|
|
150
|
-
| `@theoremjs/react/live` | `useLiveCall` and `
|
|
150
|
+
| `@theoremjs/react/live` | `useLiveCall`, `LiveRunner` and `LiveCallTile`, the voice and video call and its UI |
|
|
151
151
|
| `@theoremjs/react/server` | `@theoremjs/web/server`: the handlers and the stores they use |
|
|
152
152
|
| `@theoremjs/react/ui/theme` | `theoremTheme`, the base for your own Astryx theme |
|
|
153
153
|
| `@theoremjs/react/ui/icons` | The icon set of the theme |
|
|
@@ -367,6 +367,16 @@ The call lasts as long as the component that calls `useLiveCall`. Call it above
|
|
|
367
367
|
|
|
368
368
|
Give `LiveRunner` an `onMinimize` to show a minimize control in the call. Theorem calls it and does not navigate: your code decides where to go, and the call goes on.
|
|
369
369
|
|
|
370
|
+
`LiveCallTile` draws the same call small: the camera preview, or the ink waveform when the camera is off, then the call time, mute, end, and expand. It fills the box you give it, so your code places it and sizes it. A press on the tile or its expand control calls `onExpand`.
|
|
371
|
+
|
|
372
|
+
```tsx
|
|
373
|
+
import { LiveCallTile } from '@theoremjs/react/live';
|
|
374
|
+
|
|
375
|
+
<LiveCallTile call={call} onExpand={() => navigate('/call')} />
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
Show `LiveRunner` or `LiveCallTile` for a call, not both: the camera preview is one element, and it shows in the one that mounted last.
|
|
379
|
+
|
|
370
380
|
### The page's part in a call
|
|
371
381
|
|
|
372
382
|
Three more values for `useLiveCall` come from the page. The profile declares each one; the page only supplies the value.
|
|
@@ -22,6 +22,7 @@ export declare function useLiveCall({ iface, connection, ...options }: LiveCallI
|
|
|
22
22
|
handle: string;
|
|
23
23
|
traces: import("@theoremjs/web/client").TraceFeed;
|
|
24
24
|
callStarted: boolean;
|
|
25
|
+
connectedAt: number | null;
|
|
25
26
|
pastCalls: LiveCaptionTurn[][];
|
|
26
27
|
captions: LiveCaptionState;
|
|
27
28
|
failure: import("@theoremjs/web/client").ClientFailure | null;
|
|
@@ -14,6 +14,8 @@ import { useLiveSessionClient } from "./use-live-session-client.js";
|
|
|
14
14
|
function useLiveCallLifecycle(controls, captionsRef, sessionActive, videoAvailable) {
|
|
15
15
|
const [callStarted, setCallStarted] = useState(false);
|
|
16
16
|
const [ended, setEnded] = useState(false);
|
|
17
|
+
/** When this call first connected; a reconnect keeps it, a new call clears it. */
|
|
18
|
+
const [connectedAt, setConnectedAt] = useState(null);
|
|
17
19
|
const videoOnConnectRef = useRef(false);
|
|
18
20
|
const startCall = useCallback((options) => {
|
|
19
21
|
videoOnConnectRef.current = options.video && videoAvailable;
|
|
@@ -21,6 +23,10 @@ function useLiveCallLifecycle(controls, captionsRef, sessionActive, videoAvailab
|
|
|
21
23
|
setEnded(false);
|
|
22
24
|
void controls.startSession();
|
|
23
25
|
}, [controls, videoAvailable]);
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (sessionActive)
|
|
28
|
+
setConnectedAt((at) => at ?? Date.now());
|
|
29
|
+
}, [sessionActive]);
|
|
24
30
|
// why: Camera capture needs a live session, so a video call turns it on once connected.
|
|
25
31
|
useEffect(() => {
|
|
26
32
|
if (!sessionActive || !videoOnConnectRef.current)
|
|
@@ -32,12 +38,14 @@ function useLiveCallLifecycle(controls, captionsRef, sessionActive, videoAvailab
|
|
|
32
38
|
videoOnConnectRef.current = false;
|
|
33
39
|
controls.teardownSession();
|
|
34
40
|
setEnded(true);
|
|
41
|
+
setConnectedAt(null);
|
|
35
42
|
}, [controls]);
|
|
36
43
|
const [pastCalls, setPastCalls] = useState([]);
|
|
37
44
|
const handleRestart = useCallback(async () => {
|
|
38
45
|
const previous = captionsRef.current.turns;
|
|
39
46
|
setPastCalls((calls) => stashLiveCaptionCall(calls, previous));
|
|
40
47
|
setEnded(false);
|
|
48
|
+
setConnectedAt(null);
|
|
41
49
|
await controls.handleRestart();
|
|
42
50
|
}, [controls, captionsRef]);
|
|
43
51
|
const teardownSessionRef = useRef(controls.teardownSession);
|
|
@@ -47,7 +55,7 @@ function useLiveCallLifecycle(controls, captionsRef, sessionActive, videoAvailab
|
|
|
47
55
|
teardownSessionRef.current();
|
|
48
56
|
};
|
|
49
57
|
}, []);
|
|
50
|
-
return { callStarted, ended, pastCalls, startCall, handleEnd, handleRestart };
|
|
58
|
+
return { callStarted, connectedAt, ended, pastCalls, startCall, handleEnd, handleRestart };
|
|
51
59
|
}
|
|
52
60
|
/**
|
|
53
61
|
* Owns a live call: its session client, state, and controls. The call lasts as
|
|
@@ -139,7 +147,7 @@ export function useLiveCall({ iface, connection, ...options }) {
|
|
|
139
147
|
setVideoFacingMode: ui.setVideoFacingMode,
|
|
140
148
|
setIsVideoOn: ui.setIsVideoOn,
|
|
141
149
|
});
|
|
142
|
-
const { callStarted, ended, pastCalls, startCall, handleEnd, handleRestart } = useLiveCallLifecycle(controls, ui.captionsRef, ui.sessionActive, videoAvailable);
|
|
150
|
+
const { callStarted, connectedAt, ended, pastCalls, startCall, handleEnd, handleRestart } = useLiveCallLifecycle(controls, ui.captionsRef, ui.sessionActive, videoAvailable);
|
|
143
151
|
// why: The page's context is compared by value, so a host may build it inline on each render.
|
|
144
152
|
const contextJson = JSON.stringify(options.context);
|
|
145
153
|
useEffect(() => {
|
|
@@ -161,6 +169,7 @@ export function useLiveCall({ iface, connection, ...options }) {
|
|
|
161
169
|
handle: iface.identity.handle,
|
|
162
170
|
traces,
|
|
163
171
|
callStarted,
|
|
172
|
+
connectedAt,
|
|
164
173
|
pastCalls,
|
|
165
174
|
captions: ui.captions,
|
|
166
175
|
failure: ui.failure,
|
package/live.d.ts
CHANGED
|
@@ -5,5 +5,6 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export type { LiveCallOptions, LiveConnection, PageTool, PageToolAnswer, PageTools, } from '@theoremjs/web/client';
|
|
7
7
|
export { type LiveCall, type LiveCallInput, useLiveCall, } from './components/live/use-live-call.ts';
|
|
8
|
+
export { LiveCallTile, type LiveCallTileProps } from './ui/LiveCallTile.tsx';
|
|
8
9
|
export type { LiveRunnerProps } from './ui/LiveRunner.tsx';
|
|
9
10
|
export { LiveRunner } from './ui/LiveRunner.tsx';
|
package/live.js
CHANGED
|
@@ -8,4 +8,5 @@ import '@astryxdesign/core/reset.css';
|
|
|
8
8
|
import '@astryxdesign/core/astryx.css';
|
|
9
9
|
import './ui/built/theme.css';
|
|
10
10
|
export { useLiveCall, } from "./components/live/use-live-call.js";
|
|
11
|
+
export { LiveCallTile } from "./ui/LiveCallTile.js";
|
|
11
12
|
export { LiveRunner } from "./ui/LiveRunner.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theoremjs/react",
|
|
3
|
-
"version": "0.3.4-next.
|
|
3
|
+
"version": "0.3.4-next.841.g5f7aa38",
|
|
4
4
|
"description": "React bindings for Theorem: headless hooks + transport, an Astryx chat UI, and a Web-standard server handler.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -60,8 +60,8 @@
|
|
|
60
60
|
"@stylexjs/stylex": "0.19.0",
|
|
61
61
|
"react": "^19.0.0",
|
|
62
62
|
"react-dom": "^19.0.0",
|
|
63
|
-
"@theoremjs/agents": "^0.3.4-next.
|
|
64
|
-
"@theoremjs/web": "^0.3.4-next.
|
|
63
|
+
"@theoremjs/agents": "^0.3.4-next.841.g5f7aa38",
|
|
64
|
+
"@theoremjs/web": "^0.3.4-next.841.g5f7aa38"
|
|
65
65
|
},
|
|
66
66
|
"peerDependenciesMeta": {
|
|
67
67
|
"@astryxdesign/core": {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { DefinedTheme } from '@astryxdesign/core/theme';
|
|
2
|
+
import type { LiveCall } from '../components/live/use-live-call.ts';
|
|
3
|
+
import { type TheoremLabels } from './labels.ts';
|
|
4
|
+
export type LiveCallTileProps = {
|
|
5
|
+
/** The call to draw, from `useLiveCall`: the same call `LiveRunner` draws. */
|
|
6
|
+
call: LiveCall;
|
|
7
|
+
/**
|
|
8
|
+
* Called when the person asks to open the call full size, from the tile or
|
|
9
|
+
* its expand control. The host decides what that means, such as going back
|
|
10
|
+
* to the call's page.
|
|
11
|
+
*/
|
|
12
|
+
onExpand: () => void;
|
|
13
|
+
/** Astryx theme, as on `LiveRunner`. */
|
|
14
|
+
theme?: DefinedTheme;
|
|
15
|
+
mode?: 'system' | 'light' | 'dark';
|
|
16
|
+
/** Replacement lines by locale, as on `LiveRunner`. */
|
|
17
|
+
labels?: TheoremLabels;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* A small view of a running call: the camera preview, or the ink waveform
|
|
21
|
+
* when the camera is off, then the call time, mute, end, and expand. It fills
|
|
22
|
+
* the box the host gives it; the host places it.
|
|
23
|
+
*/
|
|
24
|
+
export declare function LiveCallTile({ theme, mode, labels, ...props }: LiveCallTileProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { AspectRatio } from '@astryxdesign/core/AspectRatio';
|
|
3
|
+
import { ClickableCard } from '@astryxdesign/core/ClickableCard';
|
|
4
|
+
import { HStack } from '@astryxdesign/core/HStack';
|
|
5
|
+
import { Icon } from '@astryxdesign/core/Icon';
|
|
6
|
+
import { IconButton } from '@astryxdesign/core/IconButton';
|
|
7
|
+
import { StackItem } from '@astryxdesign/core/Stack';
|
|
8
|
+
import { Text } from '@astryxdesign/core/Text';
|
|
9
|
+
import { ToggleButton } from '@astryxdesign/core/ToggleButton';
|
|
10
|
+
import { VStack } from '@astryxdesign/core/VStack';
|
|
11
|
+
import { IconArrowsDiagonal, IconMicrophone, IconMicrophoneOff, IconPhoneOff, } from '@tabler/icons-react';
|
|
12
|
+
import { InkWaveform } from "../components/InkWaveform.js";
|
|
13
|
+
import { useSecondTicker } from "../hooks/use-second-ticker.js";
|
|
14
|
+
import { LiveVideoPreview } from "./LiveVideoPreview.js";
|
|
15
|
+
import { liveDuration, liveStateLabel } from "./labels.js";
|
|
16
|
+
import { TheoremLabelsProvider, useLabels } from "./labels-provider.js";
|
|
17
|
+
import { TheoremThemeProvider } from "./theme.js";
|
|
18
|
+
/**
|
|
19
|
+
* A small view of a running call: the camera preview, or the ink waveform
|
|
20
|
+
* when the camera is off, then the call time, mute, end, and expand. It fills
|
|
21
|
+
* the box the host gives it; the host places it.
|
|
22
|
+
*/
|
|
23
|
+
export function LiveCallTile({ theme, mode, labels, ...props }) {
|
|
24
|
+
return (_jsx(TheoremThemeProvider, { theme: theme, mode: mode, children: _jsx(TheoremLabelsProvider, { labels: labels, children: _jsx(LiveCallTileBody, { ...props }) }) }));
|
|
25
|
+
}
|
|
26
|
+
function LiveCallTileBody({ call, onExpand, }) {
|
|
27
|
+
const t = useLabels();
|
|
28
|
+
return (_jsx(ClickableCard, { label: t('@theorem.live.expand'), onClick: onExpand, padding: 0, elevation: "high", width: "100%", children: _jsxs(VStack, { children: [_jsx(TileMedia, { call: call }), _jsxs(HStack, { gap: 1, vAlign: "center", padding: 2, children: [_jsx(StackItem, { size: "fill", children: _jsx(TileTime, { call: call }) }), _jsx(TileControls, { call: call, onExpand: onExpand })] })] }) }));
|
|
29
|
+
}
|
|
30
|
+
/** The camera preview while the camera is on; otherwise the ink waveform. */
|
|
31
|
+
function TileMedia({ call }) {
|
|
32
|
+
if (call.isVideoOn && call.videoPreview) {
|
|
33
|
+
return _jsx(LiveVideoPreview, { video: call.videoPreview, facingMode: call.videoFacingMode });
|
|
34
|
+
}
|
|
35
|
+
return (_jsx(AspectRatio, { ratio: 4 / 3, children: _jsx(VStack, { height: "100%", vAlign: "center", padding: 4, "aria-hidden": "true", children: _jsx(InkWaveform, { status: call.status, levelsRef: call.levelsRef, toolActive: call.toolActive, variant: "pill" }) }) }));
|
|
36
|
+
}
|
|
37
|
+
/** How long the call has run, or its state before it connects and after it ends. */
|
|
38
|
+
function TileTime({ call }) {
|
|
39
|
+
const t = useLabels();
|
|
40
|
+
const since = call.sessionActive ? call.connectedAt : null;
|
|
41
|
+
const now = useSecondTicker(since !== null);
|
|
42
|
+
return (_jsx(Text, { type: "supporting", hasTabularNumbers: true, maxLines: 1, children: since === null
|
|
43
|
+
? liveStateLabel(t, call.liveState, call.activeTool)
|
|
44
|
+
: liveDuration(t, now - since) }));
|
|
45
|
+
}
|
|
46
|
+
function TileControls({ call, onExpand }) {
|
|
47
|
+
const t = useLabels();
|
|
48
|
+
return (_jsxs(_Fragment, { children: [call.voiceAvailable ? (_jsx(ToggleButton, { label: t('@theorem.live.microphone'), tooltip: t(call.isMuted ? '@theorem.live.unmute' : '@theorem.live.mute'), isIconOnly: true, size: "sm", isPressed: !call.isMuted, isDisabled: !call.sessionActive, icon: _jsx(Icon, { icon: IconMicrophone }), pressedIcon: _jsx(Icon, { icon: IconMicrophoneOff }), onPressedChange: call.handleToggleMic })) : null, _jsx(IconButton, { label: t('@theorem.live.end_call'), tooltip: t('@theorem.live.end_call'), variant: "destructive", size: "sm", isDisabled: !call.sessionActive, icon: _jsx(Icon, { icon: IconPhoneOff }), onClick: call.handleEnd }), _jsx(IconButton, { label: t('@theorem.live.expand'), tooltip: t('@theorem.live.expand'), variant: "ghost", size: "sm", icon: _jsx(Icon, { icon: IconArrowsDiagonal }), onClick: onExpand })] }));
|
|
49
|
+
}
|
package/ui/LiveRunner.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { AspectRatio } from '@astryxdesign/core/AspectRatio';
|
|
3
2
|
import { Banner } from '@astryxdesign/core/Banner';
|
|
4
3
|
import { Button } from '@astryxdesign/core/Button';
|
|
5
4
|
import { Center } from '@astryxdesign/core/Center';
|
|
@@ -14,9 +13,10 @@ import { ToggleButton } from '@astryxdesign/core/ToggleButton';
|
|
|
14
13
|
import { Toolbar } from '@astryxdesign/core/Toolbar';
|
|
15
14
|
import { VStack } from '@astryxdesign/core/VStack';
|
|
16
15
|
import { IconArrowsDiagonalMinimize2, IconCameraRotate, IconMessage, IconMicrophone, IconMicrophoneOff, IconPhone, IconPhoneOff, IconVideo, IconVideoOff, } from '@tabler/icons-react';
|
|
17
|
-
import { Fragment,
|
|
16
|
+
import { Fragment, useLayoutEffect, useRef } from 'react';
|
|
18
17
|
import { InkWaveform } from "../components/InkWaveform.js";
|
|
19
18
|
import { LiveCaptionsPanel } from "./LiveCaptionsPanel.js";
|
|
19
|
+
import { LiveVideoPreview } from "./LiveVideoPreview.js";
|
|
20
20
|
import { liveStateLabel } from "./labels.js";
|
|
21
21
|
import { TheoremLabelsProvider, useLabels } from "./labels-provider.js";
|
|
22
22
|
import { PANEL_EDGE, SidePanel, SidePanelHeader, SidePanelToggle, useSidePanel, } from "./SidePanel.js";
|
|
@@ -134,35 +134,6 @@ function LiveCallButton({ call }) {
|
|
|
134
134
|
function LiveCaptions({ call }) {
|
|
135
135
|
return (_jsx(LiveCaptionsPanel, { handle: call.handle, captions: call.captions, pastCalls: call.pastCalls, draftText: call.textDraft, onDraftTextChange: call.setTextDraft, onSubmit: call.handleSendText, isDisabled: !call.sessionActive, showComposer: call.textAvailable, leading: call.videoPreview ? (_jsx(LiveVideoPreview, { video: call.videoPreview, facingMode: call.videoFacingMode })) : null }));
|
|
136
136
|
}
|
|
137
|
-
/**
|
|
138
|
-
* The camera preview, at the top of the captions panel. The capture element comes
|
|
139
|
-
* from the session client, so it is mounted imperatively; it sits one level
|
|
140
|
-
* below AspectRatio, so it carries its own fill and mirror styles.
|
|
141
|
-
*/
|
|
142
|
-
function LiveVideoPreview({ video, facingMode, }) {
|
|
143
|
-
const t = useLabels();
|
|
144
|
-
const hostRef = useRef(null);
|
|
145
|
-
useEffect(() => {
|
|
146
|
-
const host = hostRef.current;
|
|
147
|
-
if (!host)
|
|
148
|
-
return;
|
|
149
|
-
Object.assign(video.style, {
|
|
150
|
-
width: '100%',
|
|
151
|
-
height: '100%',
|
|
152
|
-
objectFit: 'cover',
|
|
153
|
-
display: 'block',
|
|
154
|
-
});
|
|
155
|
-
host.replaceChildren(video);
|
|
156
|
-
return () => {
|
|
157
|
-
if (video.parentElement === host)
|
|
158
|
-
host.removeChild(video);
|
|
159
|
-
};
|
|
160
|
-
}, [video]);
|
|
161
|
-
useEffect(() => {
|
|
162
|
-
video.style.transform = facingMode === 'user' ? 'scaleX(-1)' : '';
|
|
163
|
-
}, [video, facingMode]);
|
|
164
|
-
return (_jsx(AspectRatio, { ratio: 4 / 3, fit: "cover", children: _jsx("div", { ref: hostRef, "aria-label": t('@theorem.live.camera_preview'), role: "img" }) }));
|
|
165
|
-
}
|
|
166
137
|
/** Room around the gate card for its shadow. */
|
|
167
138
|
const GATE_DIALOG_PADDING = 4;
|
|
168
139
|
const GATE_DIALOG_WIDTH = GATE_CARD_WIDTH + 2 * GATE_DIALOG_PADDING * 4;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { LiveFacingMode } from '../client/live/live-video.ts';
|
|
2
|
+
/**
|
|
3
|
+
* The camera preview: atop the call's captions, or in its tile. The capture element comes
|
|
4
|
+
* from the session client, so it is mounted imperatively; it sits one level
|
|
5
|
+
* below AspectRatio, so it carries its own fill and mirror styles.
|
|
6
|
+
*/
|
|
7
|
+
export declare function LiveVideoPreview({ video, facingMode, }: {
|
|
8
|
+
video: HTMLVideoElement;
|
|
9
|
+
facingMode: LiveFacingMode;
|
|
10
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { AspectRatio } from '@astryxdesign/core/AspectRatio';
|
|
3
|
+
import { useEffect, useRef } from 'react';
|
|
4
|
+
import { useLabels } from "./labels-provider.js";
|
|
5
|
+
/**
|
|
6
|
+
* The camera preview: atop the call's captions, or in its tile. The capture element comes
|
|
7
|
+
* from the session client, so it is mounted imperatively; it sits one level
|
|
8
|
+
* below AspectRatio, so it carries its own fill and mirror styles.
|
|
9
|
+
*/
|
|
10
|
+
export function LiveVideoPreview({ video, facingMode, }) {
|
|
11
|
+
const t = useLabels();
|
|
12
|
+
const hostRef = useRef(null);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
const host = hostRef.current;
|
|
15
|
+
if (!host)
|
|
16
|
+
return;
|
|
17
|
+
Object.assign(video.style, {
|
|
18
|
+
width: '100%',
|
|
19
|
+
height: '100%',
|
|
20
|
+
objectFit: 'cover',
|
|
21
|
+
display: 'block',
|
|
22
|
+
});
|
|
23
|
+
host.replaceChildren(video);
|
|
24
|
+
return () => {
|
|
25
|
+
if (video.parentElement === host)
|
|
26
|
+
host.removeChild(video);
|
|
27
|
+
};
|
|
28
|
+
}, [video]);
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
video.style.transform = facingMode === 'user' ? 'scaleX(-1)' : '';
|
|
31
|
+
}, [video, facingMode]);
|
|
32
|
+
return (_jsx(AspectRatio, { ratio: 4 / 3, fit: "cover", children: _jsx("div", { ref: hostRef, "aria-label": t('@theorem.live.camera_preview'), role: "img" }) }));
|
|
33
|
+
}
|
package/ui/labels.d.ts
CHANGED
|
@@ -1364,6 +1364,10 @@ export declare const THEOREM_UI_CATALOG: {
|
|
|
1364
1364
|
readonly defaultMessage: "End call";
|
|
1365
1365
|
readonly description: "Hangs up.";
|
|
1366
1366
|
};
|
|
1367
|
+
readonly '@theorem.live.expand': {
|
|
1368
|
+
readonly defaultMessage: "Open call";
|
|
1369
|
+
readonly description: "Asks the host to show a minimized call full size.";
|
|
1370
|
+
};
|
|
1367
1371
|
readonly '@theorem.live.minimize': {
|
|
1368
1372
|
readonly defaultMessage: "Minimize call";
|
|
1369
1373
|
readonly description: "Asks the host to show the call small; the call goes on.";
|
package/ui/labels.js
CHANGED
|
@@ -1291,6 +1291,10 @@ export const THEOREM_UI_CATALOG = {
|
|
|
1291
1291
|
description: 'Switches front and back camera.',
|
|
1292
1292
|
},
|
|
1293
1293
|
'@theorem.live.end_call': { defaultMessage: 'End call', description: 'Hangs up.' },
|
|
1294
|
+
'@theorem.live.expand': {
|
|
1295
|
+
defaultMessage: 'Open call',
|
|
1296
|
+
description: 'Asks the host to show a minimized call full size.',
|
|
1297
|
+
},
|
|
1294
1298
|
'@theorem.live.minimize': {
|
|
1295
1299
|
defaultMessage: 'Minimize call',
|
|
1296
1300
|
description: 'Asks the host to show the call small; the call goes on.',
|