@stream-io/video-react-sdk 0.4.7 → 0.4.9
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 +18 -0
- package/dist/css/styles.css +16 -69
- package/dist/css/styles.css.map +1 -1
- package/dist/index.cjs.js +15 -131
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.es.js +14 -133
- package/dist/index.es.js.map +1 -1
- package/dist/src/components/index.d.ts +1 -0
- package/dist/src/hooks/useFloatingUIPreset.d.ts +11 -5
- package/dist/src/translations/index.d.ts +2 -0
- package/index.ts +0 -1
- package/package.json +5 -5
- package/src/components/Permissions/PermissionRequests.tsx +3 -3
- package/src/components/index.ts +1 -0
- package/src/core/components/ParticipantView/DefaultParticipantViewUI.tsx +5 -25
- package/src/hooks/useFloatingUIPreset.ts +5 -5
- package/src/translations/en.json +3 -0
- package/dist/src/components/Debug/DebugParticipantPublishQuality.d.ts +0 -5
- package/dist/src/components/Debug/DebugStatsView.d.ts +0 -7
- package/dist/src/components/Debug/useIsDebugMode.d.ts +0 -5
- package/dist/src/types/components.d.ts +0 -7
- package/dist/src/types/index.d.ts +0 -1
- package/src/components/Debug/DebugParticipantPublishQuality.tsx +0 -62
- package/src/components/Debug/DebugStatsView.tsx +0 -126
- package/src/components/Debug/useIsDebugMode.ts +0 -24
- package/src/types/components.ts +0 -7
- package/src/types/index.ts +0 -1
|
@@ -4,6 +4,7 @@ export * from './CallControls';
|
|
|
4
4
|
export * from './CallParticipantsList';
|
|
5
5
|
export * from './CallPreview';
|
|
6
6
|
export * from './CallRecordingList';
|
|
7
|
+
export * from './CallStats';
|
|
7
8
|
export * from './DeviceSettings';
|
|
8
9
|
export * from './Icon';
|
|
9
10
|
export * from './LoadingIndicator';
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { UseFloatingData } from '@floating-ui/react';
|
|
3
|
+
export declare const useFloatingUIPreset: ({ placement, strategy, }: Pick<UseFloatingData, 'placement' | 'strategy'>) => {
|
|
4
|
+
refs: {
|
|
5
|
+
reference: import("react").MutableRefObject<import("@floating-ui/react-dom").ReferenceType | null>;
|
|
6
|
+
floating: import("react").MutableRefObject<HTMLElement | null>;
|
|
7
|
+
setReference: (node: import("@floating-ui/react-dom").ReferenceType | null) => void;
|
|
8
|
+
setFloating: (node: HTMLElement | null) => void;
|
|
9
|
+
} & import("@floating-ui/react").ExtendedRefs<import("@floating-ui/react").ReferenceType>;
|
|
10
|
+
x: number;
|
|
11
|
+
y: number;
|
|
6
12
|
domReference: Element | null;
|
|
7
13
|
floating: HTMLElement | null;
|
|
8
14
|
strategy: import("@floating-ui/utils").Strategy;
|
|
@@ -67,6 +67,8 @@ export declare const translations: {
|
|
|
67
67
|
Leave: string;
|
|
68
68
|
"{{ direction }} fullscreen": string;
|
|
69
69
|
"{{ direction }} picture-in-picture": string;
|
|
70
|
+
"Dominant Speaker": string;
|
|
71
|
+
"Poor connection quality": string;
|
|
70
72
|
Participants: string;
|
|
71
73
|
Anonymous: string;
|
|
72
74
|
"No participants found": string;
|
package/index.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stream-io/video-react-sdk",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.9",
|
|
4
4
|
"packageManager": "yarn@3.2.4",
|
|
5
5
|
"main": "./dist/index.cjs.js",
|
|
6
6
|
"module": "./dist/index.es.js",
|
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
"CHANGELOG.md"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@floating-ui/react": "^0.
|
|
31
|
+
"@floating-ui/react": "^0.26.1",
|
|
32
32
|
"@nivo/core": "^0.80.0",
|
|
33
33
|
"@nivo/line": "^0.80.0",
|
|
34
|
-
"@stream-io/video-client": "^0.4.
|
|
35
|
-
"@stream-io/video-react-bindings": "^0.3.
|
|
34
|
+
"@stream-io/video-client": "^0.4.6",
|
|
35
|
+
"@stream-io/video-react-bindings": "^0.3.6",
|
|
36
36
|
"clsx": "^2.0.0",
|
|
37
37
|
"prop-types": "^15.8.1"
|
|
38
38
|
},
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@rollup/plugin-json": "^6.0.1",
|
|
45
45
|
"@rollup/plugin-replace": "^5.0.4",
|
|
46
46
|
"@rollup/plugin-typescript": "^11.1.5",
|
|
47
|
-
"@stream-io/video-styling": "^0.1.
|
|
47
|
+
"@stream-io/video-styling": "^0.1.14",
|
|
48
48
|
"@types/prop-types": "^15.7.8",
|
|
49
49
|
"react": "^18.2.0",
|
|
50
50
|
"react-dom": "^18.2.0",
|
|
@@ -49,6 +49,7 @@ export const PermissionRequests = () => {
|
|
|
49
49
|
OwnCapability.UPDATE_CALL_PERMISSIONS,
|
|
50
50
|
);
|
|
51
51
|
|
|
52
|
+
const localUserId = localParticipant?.userId;
|
|
52
53
|
useEffect(() => {
|
|
53
54
|
if (!call || !canUpdateCallPermissions) return;
|
|
54
55
|
|
|
@@ -56,8 +57,7 @@ export const PermissionRequests = () => {
|
|
|
56
57
|
'call.permission_request',
|
|
57
58
|
(event: StreamVideoEvent) => {
|
|
58
59
|
if (event.type !== 'call.permission_request') return;
|
|
59
|
-
|
|
60
|
-
if (event.user.id !== localParticipant?.userId) {
|
|
60
|
+
if (event.user.id !== localUserId) {
|
|
61
61
|
setPermissionRequests((requests) =>
|
|
62
62
|
[...requests, event as PermissionRequestEvent].sort((a, b) =>
|
|
63
63
|
byNameOrId(a.user, b.user),
|
|
@@ -69,7 +69,7 @@ export const PermissionRequests = () => {
|
|
|
69
69
|
return () => {
|
|
70
70
|
unsubscribe();
|
|
71
71
|
};
|
|
72
|
-
}, [call, canUpdateCallPermissions,
|
|
72
|
+
}, [call, canUpdateCallPermissions, localUserId]);
|
|
73
73
|
|
|
74
74
|
const handleUpdatePermission: HandleUpdatePermission = (request, type) => {
|
|
75
75
|
return async () => {
|
package/src/components/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ export * from './CallControls';
|
|
|
4
4
|
export * from './CallParticipantsList';
|
|
5
5
|
export * from './CallPreview';
|
|
6
6
|
export * from './CallRecordingList';
|
|
7
|
+
export * from './CallStats';
|
|
7
8
|
export * from './DeviceSettings';
|
|
8
9
|
export * from './Icon';
|
|
9
10
|
export * from './LoadingIndicator';
|
|
@@ -13,10 +13,6 @@ import {
|
|
|
13
13
|
ToggleMenuButtonProps,
|
|
14
14
|
} from '../../../components';
|
|
15
15
|
import { Reaction } from '../../../components/Reaction';
|
|
16
|
-
|
|
17
|
-
import { DebugParticipantPublishQuality } from '../../../components/Debug/DebugParticipantPublishQuality';
|
|
18
|
-
import { DebugStatsView } from '../../../components/Debug/DebugStatsView';
|
|
19
|
-
import { useIsDebugMode } from '../../../components/Debug/useIsDebugMode';
|
|
20
16
|
import { useParticipantViewContext } from './ParticipantViewContext';
|
|
21
17
|
|
|
22
18
|
export type DefaultParticipantViewUIProps = {
|
|
@@ -124,10 +120,10 @@ export const ParticipantDetails = ({
|
|
|
124
120
|
sessionId,
|
|
125
121
|
name,
|
|
126
122
|
userId,
|
|
127
|
-
videoStream,
|
|
128
123
|
} = participant;
|
|
129
|
-
const call = useCall()
|
|
124
|
+
const call = useCall();
|
|
130
125
|
|
|
126
|
+
const { t } = useI18n();
|
|
131
127
|
const connectionQualityAsString =
|
|
132
128
|
!!connectionQuality &&
|
|
133
129
|
SfuModels.ConnectionQuality[connectionQuality].toLowerCase();
|
|
@@ -136,8 +132,6 @@ export const ParticipantDetails = ({
|
|
|
136
132
|
const hasVideo = publishedTracks.includes(SfuModels.TrackType.VIDEO);
|
|
137
133
|
const canUnpin = !!pin && pin.isLocalPin;
|
|
138
134
|
|
|
139
|
-
const isDebugMode = useIsDebugMode();
|
|
140
|
-
|
|
141
135
|
return (
|
|
142
136
|
<div className="str-video__participant-details">
|
|
143
137
|
<span className="str-video__participant-details__name">
|
|
@@ -145,7 +139,7 @@ export const ParticipantDetails = ({
|
|
|
145
139
|
{indicatorsVisible && isDominantSpeaker && (
|
|
146
140
|
<span
|
|
147
141
|
className="str-video__participant-details__name--dominant_speaker"
|
|
148
|
-
title=
|
|
142
|
+
title={t('Dominant speaker')}
|
|
149
143
|
/>
|
|
150
144
|
)}
|
|
151
145
|
{indicatorsVisible && (
|
|
@@ -154,7 +148,7 @@ export const ParticipantDetails = ({
|
|
|
154
148
|
isLocalParticipant &&
|
|
155
149
|
connectionQuality === SfuModels.ConnectionQuality.POOR
|
|
156
150
|
}
|
|
157
|
-
message=
|
|
151
|
+
message={t('Poor connection quality')}
|
|
158
152
|
>
|
|
159
153
|
{connectionQualityAsString && (
|
|
160
154
|
<span
|
|
@@ -176,27 +170,13 @@ export const ParticipantDetails = ({
|
|
|
176
170
|
{indicatorsVisible && canUnpin && (
|
|
177
171
|
// TODO: remove this monstrosity once we have a proper design
|
|
178
172
|
<span
|
|
179
|
-
title=
|
|
173
|
+
title={t('Unpin')}
|
|
180
174
|
onClick={() => call?.unpin(sessionId)}
|
|
181
175
|
style={{ cursor: 'pointer' }}
|
|
182
176
|
className="str-video__participant-details__name--pinned"
|
|
183
177
|
/>
|
|
184
178
|
)}
|
|
185
179
|
</span>
|
|
186
|
-
{isDebugMode && (
|
|
187
|
-
<>
|
|
188
|
-
<DebugParticipantPublishQuality
|
|
189
|
-
participant={participant}
|
|
190
|
-
call={call}
|
|
191
|
-
/>
|
|
192
|
-
<DebugStatsView
|
|
193
|
-
call={call}
|
|
194
|
-
sessionId={sessionId}
|
|
195
|
-
userId={userId}
|
|
196
|
-
mediaStream={videoStream}
|
|
197
|
-
/>
|
|
198
|
-
</>
|
|
199
|
-
)}
|
|
200
180
|
</div>
|
|
201
181
|
);
|
|
202
182
|
};
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { useEffect } from 'react';
|
|
2
|
+
import type { UseFloatingData } from '@floating-ui/react';
|
|
2
3
|
import {
|
|
3
|
-
offset,
|
|
4
4
|
autoUpdate,
|
|
5
|
+
flip,
|
|
6
|
+
offset,
|
|
7
|
+
shift,
|
|
5
8
|
size,
|
|
6
9
|
useFloating,
|
|
7
|
-
shift,
|
|
8
|
-
flip,
|
|
9
10
|
} from '@floating-ui/react';
|
|
10
|
-
import type { UseFloatingProps } from '@floating-ui/react';
|
|
11
11
|
|
|
12
12
|
export const useFloatingUIPreset = ({
|
|
13
13
|
placement,
|
|
14
14
|
strategy,
|
|
15
|
-
}: Pick<
|
|
15
|
+
}: Pick<UseFloatingData, 'placement' | 'strategy'>) => {
|
|
16
16
|
const {
|
|
17
17
|
refs,
|
|
18
18
|
x,
|
package/src/translations/en.json
CHANGED
|
@@ -72,6 +72,9 @@
|
|
|
72
72
|
"{{ direction }} fullscreen": "{{ direction }} fullscreen",
|
|
73
73
|
"{{ direction }} picture-in-picture": "{{ direction }} picture-in-picture",
|
|
74
74
|
|
|
75
|
+
"Dominant Speaker": "Dominant Speaker",
|
|
76
|
+
"Poor connection quality": "Poor connection quality. Please check your internet connection.",
|
|
77
|
+
|
|
75
78
|
"Participants": "Participants",
|
|
76
79
|
"Anonymous": ", and ({{ count }}) anonymous",
|
|
77
80
|
"No participants found": "No participants found",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './components';
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react';
|
|
2
|
-
import { Call, StreamVideoParticipant } from '@stream-io/video-client';
|
|
3
|
-
|
|
4
|
-
export const DebugParticipantPublishQuality = (props: {
|
|
5
|
-
participant: StreamVideoParticipant;
|
|
6
|
-
call: Call;
|
|
7
|
-
}) => {
|
|
8
|
-
const { call, participant } = props;
|
|
9
|
-
const [quality, setQuality] = useState<string>();
|
|
10
|
-
const [publishStats, setPublishStats] = useState(() => ({
|
|
11
|
-
f: true,
|
|
12
|
-
h: true,
|
|
13
|
-
q: true,
|
|
14
|
-
}));
|
|
15
|
-
|
|
16
|
-
useEffect(() => {
|
|
17
|
-
return call.on('changePublishQuality', (event) => {
|
|
18
|
-
if (event.eventPayload.oneofKind !== 'changePublishQuality') return;
|
|
19
|
-
const { videoSenders } = event.eventPayload.changePublishQuality;
|
|
20
|
-
// FIXME OL: support additional layers (like screenshare)
|
|
21
|
-
const [videoLayer] = videoSenders.map(({ layers }) => {
|
|
22
|
-
return layers.map((l) => ({ [l.name]: l.active }));
|
|
23
|
-
});
|
|
24
|
-
setPublishStats((s) => ({
|
|
25
|
-
...s,
|
|
26
|
-
...videoLayer,
|
|
27
|
-
}));
|
|
28
|
-
});
|
|
29
|
-
}, [call]);
|
|
30
|
-
|
|
31
|
-
return (
|
|
32
|
-
<select
|
|
33
|
-
title={`Published tracks: ${JSON.stringify(publishStats)}`}
|
|
34
|
-
value={quality}
|
|
35
|
-
onChange={(e) => {
|
|
36
|
-
const value = e.target.value;
|
|
37
|
-
setQuality(value);
|
|
38
|
-
let w = 960;
|
|
39
|
-
let h = 540;
|
|
40
|
-
if (value === 'h') {
|
|
41
|
-
w = w / 2; // 480
|
|
42
|
-
h = h / 2; // 270
|
|
43
|
-
} else if (value === 'q') {
|
|
44
|
-
w = w / 4; // 240
|
|
45
|
-
h = h / 4; // 135
|
|
46
|
-
}
|
|
47
|
-
call.updateSubscriptionsPartial('video', {
|
|
48
|
-
[participant.sessionId]: {
|
|
49
|
-
dimension: {
|
|
50
|
-
width: w,
|
|
51
|
-
height: h,
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
});
|
|
55
|
-
}}
|
|
56
|
-
>
|
|
57
|
-
<option value="f">High (f)</option>
|
|
58
|
-
<option value="h">Medium (h)</option>
|
|
59
|
-
<option value="q">Low (q)</option>
|
|
60
|
-
</select>
|
|
61
|
-
);
|
|
62
|
-
};
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import { useEffect, useRef, useState } from 'react';
|
|
2
|
-
import { Call } from '@stream-io/video-client';
|
|
3
|
-
import { useFloatingUIPreset } from '../../hooks';
|
|
4
|
-
import { StatCard } from '../CallStats';
|
|
5
|
-
import { useCallStateHooks } from '@stream-io/video-react-bindings';
|
|
6
|
-
|
|
7
|
-
export const DebugStatsView = (props: {
|
|
8
|
-
call: Call;
|
|
9
|
-
mediaStream?: MediaStream;
|
|
10
|
-
sessionId: string;
|
|
11
|
-
userId: string;
|
|
12
|
-
}) => {
|
|
13
|
-
const { call, mediaStream, sessionId, userId } = props;
|
|
14
|
-
const { useCallStatsReport } = useCallStateHooks();
|
|
15
|
-
const callStatsReport = useCallStatsReport();
|
|
16
|
-
|
|
17
|
-
useEffect(() => {
|
|
18
|
-
call.startReportingStatsFor(sessionId);
|
|
19
|
-
return () => {
|
|
20
|
-
call.stopReportingStatsFor(sessionId);
|
|
21
|
-
};
|
|
22
|
-
}, [call, sessionId]);
|
|
23
|
-
|
|
24
|
-
const reportForTracks = callStatsReport?.participants[sessionId];
|
|
25
|
-
const trackStats = reportForTracks?.flatMap((report) => report.streams);
|
|
26
|
-
|
|
27
|
-
const previousWidth = useRef<Record<string, number>>({ f: 0, h: 0, q: 0 });
|
|
28
|
-
const previousHeight = useRef<Record<string, number>>({ f: 0, h: 0, q: 0 });
|
|
29
|
-
trackStats?.forEach((track) => {
|
|
30
|
-
if (track.kind !== 'video') return;
|
|
31
|
-
const { frameWidth = 0, frameHeight = 0, rid = '' } = track;
|
|
32
|
-
if (
|
|
33
|
-
frameWidth !== previousWidth.current[rid] ||
|
|
34
|
-
frameHeight !== previousHeight.current[rid]
|
|
35
|
-
) {
|
|
36
|
-
const trackSize = `${frameWidth}x${frameHeight}`;
|
|
37
|
-
console.log(`Track stats (${userId}/${sessionId}): ${rid}(${trackSize})`);
|
|
38
|
-
previousWidth.current[rid] = frameWidth;
|
|
39
|
-
previousHeight.current[rid] = frameHeight;
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
const { refs, strategy, y, x } = useFloatingUIPreset({
|
|
44
|
-
placement: 'top',
|
|
45
|
-
strategy: 'absolute',
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
const [isPopperOpen, setIsPopperOpen] = useState(false);
|
|
49
|
-
|
|
50
|
-
const [videoTrack] = mediaStream?.getVideoTracks() ?? [];
|
|
51
|
-
const settings = videoTrack?.getSettings();
|
|
52
|
-
return (
|
|
53
|
-
<>
|
|
54
|
-
<span
|
|
55
|
-
className="str-video__debug__track-stats-icon"
|
|
56
|
-
tabIndex={0}
|
|
57
|
-
ref={refs.setReference}
|
|
58
|
-
title={
|
|
59
|
-
settings &&
|
|
60
|
-
`${settings.width}x${settings.height}@${Math.round(
|
|
61
|
-
settings.frameRate || 0,
|
|
62
|
-
)}`
|
|
63
|
-
}
|
|
64
|
-
onClick={() => {
|
|
65
|
-
setIsPopperOpen((v) => !v);
|
|
66
|
-
}}
|
|
67
|
-
/>
|
|
68
|
-
{isPopperOpen && (
|
|
69
|
-
<div
|
|
70
|
-
className="str-video__debug__track-stats str-video__call-stats"
|
|
71
|
-
ref={refs.setFloating}
|
|
72
|
-
style={{
|
|
73
|
-
position: strategy,
|
|
74
|
-
top: y ?? 0,
|
|
75
|
-
left: x ?? 0,
|
|
76
|
-
overflowY: 'auto',
|
|
77
|
-
}}
|
|
78
|
-
>
|
|
79
|
-
<h3>Participant stats</h3>
|
|
80
|
-
<div className="str-video__call-stats__card-container">
|
|
81
|
-
{trackStats
|
|
82
|
-
?.map((track) => {
|
|
83
|
-
if (track.kind === 'video') {
|
|
84
|
-
return (
|
|
85
|
-
<StatCard
|
|
86
|
-
key={`${track.rid}/${track.ssrc}/${track.codec}/${track.kind}`}
|
|
87
|
-
label={
|
|
88
|
-
`${track.kind}: ${track.codec} ` +
|
|
89
|
-
(track.rid ? ` (${track.rid})` : '')
|
|
90
|
-
}
|
|
91
|
-
value={`${track.frameWidth || 0}x${
|
|
92
|
-
track.frameHeight || 0
|
|
93
|
-
}@${track.framesPerSecond || 0}fps`}
|
|
94
|
-
/>
|
|
95
|
-
);
|
|
96
|
-
} else if (track.kind === 'audio') {
|
|
97
|
-
return (
|
|
98
|
-
<StatCard
|
|
99
|
-
key={`${track.ssrc}/${track.codec}/${track.kind}`}
|
|
100
|
-
label={track.codec || 'N/A'}
|
|
101
|
-
value={`Jitter: ${track.jitter || 0}ms`}
|
|
102
|
-
/>
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
return null;
|
|
106
|
-
})
|
|
107
|
-
.filter(Boolean)}
|
|
108
|
-
</div>
|
|
109
|
-
{reportForTracks?.map((report, index) => (
|
|
110
|
-
<pre key={index}>
|
|
111
|
-
{JSON.stringify(unwrapStats(report.rawStats), null, 2)}
|
|
112
|
-
</pre>
|
|
113
|
-
))}
|
|
114
|
-
</div>
|
|
115
|
-
)}
|
|
116
|
-
</>
|
|
117
|
-
);
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
const unwrapStats = (rawStats?: RTCStatsReport) => {
|
|
121
|
-
const decodedStats: Record<string, string> = {};
|
|
122
|
-
rawStats?.forEach((s) => {
|
|
123
|
-
decodedStats[s.id] = s;
|
|
124
|
-
});
|
|
125
|
-
return decodedStats;
|
|
126
|
-
};
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
|
-
|
|
3
|
-
const useQueryParams = () => {
|
|
4
|
-
return useMemo(
|
|
5
|
-
() =>
|
|
6
|
-
typeof window === 'undefined'
|
|
7
|
-
? null
|
|
8
|
-
: new URLSearchParams(window.location.search),
|
|
9
|
-
[],
|
|
10
|
-
);
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Internal purpose hook. Enables certain development mode tools.
|
|
15
|
-
*/
|
|
16
|
-
export const useIsDebugMode = () => {
|
|
17
|
-
const params = useQueryParams();
|
|
18
|
-
return !!params?.get('debug');
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const useDebugPreferredVideoCodec = () => {
|
|
22
|
-
const params = useQueryParams();
|
|
23
|
-
return params?.get('video_codec');
|
|
24
|
-
};
|
package/src/types/components.ts
DELETED
package/src/types/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './components';
|