@ikonai/sdk-react-ui 1.4.0 → 1.6.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/app/connection-recovery.d.ts +27 -0
- package/app/index.d.ts +1 -0
- package/app/use-ikon-app.d.ts +24 -1
- package/auth/auth-context.spec.d.ts +1 -0
- package/auth/storage.d.ts +16 -0
- package/base/focus-hint-scroll.spec.d.ts +1 -0
- package/index.d.ts +4 -1
- package/index.js +1155 -930
- package/media/use-media-capture.d.ts +21 -0
- package/media/use-media-capture.spec.d.ts +1 -0
- package/media/use-sibling-client.d.ts +21 -0
- package/media/use-sibling-client.spec.d.ts +1 -0
- package/media/video-stream-view.d.ts +40 -0
- package/media/video-stream-view.spec.d.ts +1 -0
- package/package.json +1 -1
- package/theme/ikon-app.css +38 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { IkonAudioCaptureRequest, IkonClient, IkonVideoCaptureRequest } from '../../sdk/sdk/src/index.ts';
|
|
2
|
+
export interface UseMediaCaptureResult {
|
|
3
|
+
/** The start failure, if the last capture start failed (e.g. permission denied). */
|
|
4
|
+
error: Error | null;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Streams the microphone up the given connection while `active` is true. The request
|
|
8
|
+
* is applied when capture (re)starts; changing it alone does not restart capture.
|
|
9
|
+
* Pair with a mute flag: `useMicrophoneCapture(client, !muted)`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function useMicrophoneCapture(client: IkonClient | null | undefined, active: boolean, request?: IkonAudioCaptureRequest): UseMediaCaptureResult;
|
|
12
|
+
/**
|
|
13
|
+
* Streams the camera up the given connection while `active` is true. The request is
|
|
14
|
+
* applied when capture (re)starts; changing it alone does not restart capture.
|
|
15
|
+
*/
|
|
16
|
+
export declare function useCameraCapture(client: IkonClient | null | undefined, active: boolean, request?: Omit<IkonVideoCaptureRequest, 'sourceType'>): UseMediaCaptureResult;
|
|
17
|
+
/**
|
|
18
|
+
* Streams a screenshare up the given connection while `active` is true. The request is
|
|
19
|
+
* applied when capture (re)starts; changing it alone does not restart capture.
|
|
20
|
+
*/
|
|
21
|
+
export declare function useScreenCapture(client: IkonClient | null | undefined, active: boolean, request?: Omit<IkonVideoCaptureRequest, 'sourceType'>): UseMediaCaptureResult;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { IkonClient, IkonClientConfig } from '../../sdk/sdk/src/index.ts';
|
|
2
|
+
export interface UseSiblingClientResult {
|
|
3
|
+
/** The connected sibling client, or null while connecting / when inputs are null. */
|
|
4
|
+
client: IkonClient | null;
|
|
5
|
+
/** The connect failure, if the last connection attempt failed. */
|
|
6
|
+
error: Error | null;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Opens a sibling connection next to an existing one — same deployment, auth and
|
|
10
|
+
* transport, with the given connection parameters replacing the owner's. This is how
|
|
11
|
+
* a page opens a media leg to a cell room (`ikon-cell-type` + the cell's identity
|
|
12
|
+
* fields) while keeping its normal app connection. The sibling connects while the
|
|
13
|
+
* inputs are non-null and disconnects on unmount or when they change — so a huddle's
|
|
14
|
+
* media leg tears down (and the room sees the participant leave) simply by the
|
|
15
|
+
* component unmounting or `parameters` becoming null.
|
|
16
|
+
*
|
|
17
|
+
* Reconnection is keyed on the CONTENT of `parameters` (order-insensitive), so an
|
|
18
|
+
* object literal recreated every render is fine. `overrides` is applied when a
|
|
19
|
+
* connection starts; changing it alone does not reconnect.
|
|
20
|
+
*/
|
|
21
|
+
export declare function useSiblingClient(client: IkonClient | null | undefined, parameters: Record<string, string> | null | undefined, overrides?: Partial<IkonClientConfig>): UseSiblingClientResult;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
import { IkonClient } from '../../sdk/sdk/src/index.ts';
|
|
3
|
+
export declare const ATTACH_CANVAS_RETRY_MS = 100;
|
|
4
|
+
export declare const ATTACH_CANVAS_MAX_ATTEMPTS = 50;
|
|
5
|
+
/**
|
|
6
|
+
* The slice of the custom (non-WebRTC) video playback pipeline this view needs.
|
|
7
|
+
* Structurally satisfied by `IkonVideoPlayback` from `@ikonai/sdk`.
|
|
8
|
+
*/
|
|
9
|
+
export interface VideoStreamPlayback {
|
|
10
|
+
attachCanvas(streamId: string, canvas: HTMLCanvasElement): Promise<unknown>;
|
|
11
|
+
detachCanvas(streamId: string): void;
|
|
12
|
+
}
|
|
13
|
+
export interface VideoStreamViewProps {
|
|
14
|
+
/** The connection the stream arrives on — an app connection or a sibling media connection. */
|
|
15
|
+
client: IkonClient | null | undefined;
|
|
16
|
+
/** App-level stream id, as published by the server (e.g. from a `Video.SendFrameAsync` relay). */
|
|
17
|
+
streamId: string | null | undefined;
|
|
18
|
+
className?: string;
|
|
19
|
+
style?: CSSProperties;
|
|
20
|
+
width?: number;
|
|
21
|
+
height?: number;
|
|
22
|
+
/** Extra attributes for the rendered element (e.g. `data-*` markers). */
|
|
23
|
+
attributes?: Record<string, string>;
|
|
24
|
+
/**
|
|
25
|
+
* Renderer hook: where to take the custom playback pipeline from. Defaults to
|
|
26
|
+
* `client.media?.video`, which is right for standalone use — the UI-node renderer
|
|
27
|
+
* passes its own source so a context-level override keeps working.
|
|
28
|
+
*/
|
|
29
|
+
getPlayback?: () => VideoStreamPlayback | null | undefined;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Renders one incoming video stream (camera or screenshare), handling both media
|
|
33
|
+
* transports: when WebRTC carries the video the stream is a `MediaStream` rendered
|
|
34
|
+
* through a `<video>` element, and on the protocol-channel fallback the frames are
|
|
35
|
+
* decoded into a `<canvas>` attached to the custom playback pipeline. Which transport
|
|
36
|
+
* is active is per connection and can only be known at runtime, so a component that
|
|
37
|
+
* implements just one of the two renders a permanently black tile on the other — use
|
|
38
|
+
* this view instead of calling `attachCanvas` directly.
|
|
39
|
+
*/
|
|
40
|
+
export declare const VideoStreamView: import('react').MemoExoticComponent<({ client, streamId, className, style, width, height, attributes, getPlayback, }: VideoStreamViewProps) => import("react").JSX.Element>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
package/theme/ikon-app.css
CHANGED
|
@@ -158,6 +158,44 @@
|
|
|
158
158
|
word-break: break-word;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
/* An installed PWA has no reload control the user can reach, so this button is the only way back
|
|
162
|
+
into the app — sized for a thumb rather than as a secondary affordance. */
|
|
163
|
+
.ikon-offline-action {
|
|
164
|
+
display: flex;
|
|
165
|
+
align-items: center;
|
|
166
|
+
justify-content: center;
|
|
167
|
+
min-width: 160px;
|
|
168
|
+
min-height: 44px;
|
|
169
|
+
margin-top: 12px;
|
|
170
|
+
padding: 0 20px;
|
|
171
|
+
background: var(--ikon-bg-solid);
|
|
172
|
+
border: 1px solid transparent;
|
|
173
|
+
border-radius: var(--ikon-radius-md);
|
|
174
|
+
font-family: inherit;
|
|
175
|
+
font-size: 15px;
|
|
176
|
+
font-weight: 500;
|
|
177
|
+
line-height: 1;
|
|
178
|
+
cursor: pointer;
|
|
179
|
+
transition: background-color 0.15s ease;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/* Crosswind's preflight resets `button { color: inherit }` unlayered, and an unlayered rule beats
|
|
183
|
+
a layered one whatever its specificity — so colouring the button itself loses the contrast and
|
|
184
|
+
paints the label in the chip's text colour on the solid fill. The span is not something the
|
|
185
|
+
reset targets, which keeps this a normal cascade an app can still override without !important. */
|
|
186
|
+
.ikon-offline-action-label {
|
|
187
|
+
color: var(--ikon-text-on-solid);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.ikon-offline-action:hover {
|
|
191
|
+
background: var(--ikon-bg-solid-hover);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.ikon-offline-action:focus-visible {
|
|
195
|
+
outline: 2px solid var(--ikon-focus-ring);
|
|
196
|
+
outline-offset: 2px;
|
|
197
|
+
}
|
|
198
|
+
|
|
161
199
|
@keyframes ikon-fade-in {
|
|
162
200
|
from { opacity: 0; }
|
|
163
201
|
to { opacity: 1; }
|