@stream-io/video-react-bindings 0.0.1-alpha.100

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.
Files changed (64) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/LICENSE +219 -0
  3. package/README.md +3 -0
  4. package/dist/index.d.ts +3 -0
  5. package/dist/index.js +4 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/src/contexts/StreamCallContext.d.ts +27 -0
  8. package/dist/src/contexts/StreamCallContext.js +26 -0
  9. package/dist/src/contexts/StreamCallContext.js.map +1 -0
  10. package/dist/src/contexts/StreamI18nContext.d.ts +19 -0
  11. package/dist/src/contexts/StreamI18nContext.js +40 -0
  12. package/dist/src/contexts/StreamI18nContext.js.map +1 -0
  13. package/dist/src/contexts/StreamVideoContext.d.ts +24 -0
  14. package/dist/src/contexts/StreamVideoContext.js +23 -0
  15. package/dist/src/contexts/StreamVideoContext.js.map +1 -0
  16. package/dist/src/contexts/index.d.ts +3 -0
  17. package/dist/src/contexts/index.js +4 -0
  18. package/dist/src/contexts/index.js.map +1 -0
  19. package/dist/src/hooks/call.d.ts +99 -0
  20. package/dist/src/hooks/call.js +144 -0
  21. package/dist/src/hooks/call.js.map +1 -0
  22. package/dist/src/hooks/client.d.ts +33 -0
  23. package/dist/src/hooks/client.js +36 -0
  24. package/dist/src/hooks/client.js.map +1 -0
  25. package/dist/src/hooks/helpers/useObservableValue.d.ts +6 -0
  26. package/dist/src/hooks/helpers/useObservableValue.js +17 -0
  27. package/dist/src/hooks/helpers/useObservableValue.js.map +1 -0
  28. package/dist/src/hooks/index.d.ts +6 -0
  29. package/dist/src/hooks/index.js +7 -0
  30. package/dist/src/hooks/index.js.map +1 -0
  31. package/dist/src/hooks/participants.d.ts +44 -0
  32. package/dist/src/hooks/participants.js +62 -0
  33. package/dist/src/hooks/participants.js.map +1 -0
  34. package/dist/src/hooks/permissions.d.ts +21 -0
  35. package/dist/src/hooks/permissions.js +32 -0
  36. package/dist/src/hooks/permissions.js.map +1 -0
  37. package/dist/src/hooks/store.d.ts +11 -0
  38. package/dist/src/hooks/store.js +30 -0
  39. package/dist/src/hooks/store.js.map +1 -0
  40. package/dist/src/hooks/user.d.ts +7 -0
  41. package/dist/src/hooks/user.js +13 -0
  42. package/dist/src/hooks/user.js.map +1 -0
  43. package/dist/src/wrappers/Restricted.d.ts +19 -0
  44. package/dist/src/wrappers/Restricted.js +14 -0
  45. package/dist/src/wrappers/Restricted.js.map +1 -0
  46. package/dist/src/wrappers/index.d.ts +1 -0
  47. package/dist/src/wrappers/index.js +2 -0
  48. package/dist/src/wrappers/index.js.map +1 -0
  49. package/index.ts +3 -0
  50. package/package.json +43 -0
  51. package/src/contexts/StreamCallContext.tsx +43 -0
  52. package/src/contexts/StreamI18nContext.tsx +70 -0
  53. package/src/contexts/StreamVideoContext.tsx +54 -0
  54. package/src/contexts/index.ts +3 -0
  55. package/src/hooks/call.ts +157 -0
  56. package/src/hooks/client.ts +77 -0
  57. package/src/hooks/helpers/useObservableValue.ts +21 -0
  58. package/src/hooks/index.ts +6 -0
  59. package/src/hooks/participants.ts +79 -0
  60. package/src/hooks/permissions.ts +37 -0
  61. package/src/hooks/store.ts +34 -0
  62. package/src/hooks/user.ts +13 -0
  63. package/src/wrappers/Restricted.tsx +40 -0
  64. package/src/wrappers/index.ts +1 -0
@@ -0,0 +1,43 @@
1
+ import { createContext, PropsWithChildren, useContext } from 'react';
2
+ import { Call } from '@stream-io/video-client';
3
+
4
+ const StreamCallContext = createContext<Call | undefined>(undefined);
5
+
6
+ /**
7
+ *
8
+ * We don't expose types in our docs site but we should still add doc comments
9
+ * @internal
10
+ */
11
+ export interface StreamCallProviderProps {
12
+ call?: Call;
13
+ }
14
+
15
+ /**
16
+ *
17
+ * @param props
18
+ * @returns
19
+ *
20
+ * @category Call State
21
+ *
22
+ * @react If you're using the React SDK we recommend using the `StreamCall` component that wraps the `StreamCallProvider`. You only need to use the `StreamCallProvider` for advanced use-cases.
23
+ */
24
+ export const StreamCallProvider = (
25
+ props: PropsWithChildren<StreamCallProviderProps>,
26
+ ) => {
27
+ const { call, children } = props;
28
+ return (
29
+ <StreamCallContext.Provider value={call}>
30
+ {children}
31
+ </StreamCallContext.Provider>
32
+ );
33
+ };
34
+
35
+ /**
36
+ *
37
+ * @returns
38
+ *
39
+ * @category Call State
40
+ */
41
+ export const useCall = () => {
42
+ return useContext(StreamCallContext);
43
+ };
@@ -0,0 +1,70 @@
1
+ import {
2
+ createContext,
3
+ PropsWithChildren,
4
+ useContext,
5
+ useEffect,
6
+ useState,
7
+ } from 'react';
8
+ import {
9
+ defaultTranslationFunction,
10
+ StreamI18n,
11
+ TranslationsMap,
12
+ } from '@stream-io/i18n';
13
+
14
+ type StreamI18nContextValue = {
15
+ t: StreamI18n['t'];
16
+ i18n?: StreamI18n;
17
+ };
18
+
19
+ const StreamI18nContext = createContext<StreamI18nContextValue>({
20
+ t: defaultTranslationFunction,
21
+ });
22
+
23
+ export type StreamI18nProviderProps = CreateI18nParams;
24
+
25
+ export const StreamI18nProvider = ({
26
+ children,
27
+ ...createI18nParams
28
+ }: PropsWithChildren<StreamI18nProviderProps>) => {
29
+ const { i18n, t } = useCreateI18n(createI18nParams);
30
+
31
+ return (
32
+ <StreamI18nContext.Provider value={{ t, i18n }}>
33
+ {children}
34
+ </StreamI18nContext.Provider>
35
+ );
36
+ };
37
+
38
+ type CreateI18nParams = {
39
+ i18nInstance?: StreamI18n;
40
+ language?: string;
41
+ translationsOverrides?: TranslationsMap;
42
+ };
43
+
44
+ export const useCreateI18n = ({
45
+ i18nInstance,
46
+ language,
47
+ translationsOverrides,
48
+ }: CreateI18nParams) => {
49
+ const [i18n] = useState<StreamI18n>(
50
+ () =>
51
+ i18nInstance ||
52
+ new StreamI18n({ currentLanguage: language, translationsOverrides }),
53
+ );
54
+ const [t, setTranslationFn] = useState<StreamI18n['t']>(
55
+ () => defaultTranslationFunction,
56
+ );
57
+
58
+ useEffect(() => {
59
+ if (i18n.isInitialized && language && i18n?.currentLanguage !== language) {
60
+ i18n.changeLanguage(language);
61
+ } else if (!i18n.isInitialized) {
62
+ if (!language) i18n.changeLanguage();
63
+ i18n.init().then((_i18n) => setTranslationFn(() => _i18n.i18nInstance.t));
64
+ }
65
+ }, [i18n, i18nInstance, language, translationsOverrides]);
66
+
67
+ return { i18n, t };
68
+ };
69
+
70
+ export const useI18n = () => useContext(StreamI18nContext);
@@ -0,0 +1,54 @@
1
+ import { createContext, PropsWithChildren, useContext } from 'react';
2
+ import { StreamVideoClient } from '@stream-io/video-client';
3
+ import {
4
+ StreamI18nProvider,
5
+ StreamI18nProviderProps,
6
+ } from './StreamI18nContext';
7
+
8
+ const StreamVideoContext = createContext<StreamVideoClient | undefined>(
9
+ undefined,
10
+ );
11
+
12
+ /**
13
+ * Exclude types from documentaiton site, but we should still add doc comments
14
+ * @internal
15
+ */
16
+ export type StreamVideoProps = StreamI18nProviderProps & {
17
+ client: StreamVideoClient;
18
+ };
19
+
20
+ /**
21
+ * StreamVideo is a provider component which should be used to wrap the entire application.
22
+ * It provides the client object to all children components and initializes the i18n instance.
23
+ * @param PropsWithChildren<StreamVideoProps>
24
+ * @category Client State
25
+ */
26
+ export const StreamVideo = ({
27
+ children,
28
+ client,
29
+ i18nInstance,
30
+ language,
31
+ translationsOverrides,
32
+ }: PropsWithChildren<StreamVideoProps>) => {
33
+ return (
34
+ <StreamVideoContext.Provider value={client}>
35
+ <StreamI18nProvider
36
+ i18nInstance={i18nInstance}
37
+ language={language}
38
+ translationsOverrides={translationsOverrides}
39
+ >
40
+ {children}
41
+ </StreamI18nProvider>
42
+ </StreamVideoContext.Provider>
43
+ );
44
+ };
45
+
46
+ /**
47
+ *
48
+ * @returns
49
+ *
50
+ * @category Client State
51
+ */
52
+ export const useStreamVideoClient = () => {
53
+ return useContext(StreamVideoContext);
54
+ };
@@ -0,0 +1,3 @@
1
+ export * from './StreamCallContext';
2
+ export * from './StreamI18nContext';
3
+ export * from './StreamVideoContext';
@@ -0,0 +1,157 @@
1
+ import { useObservableValue } from './helpers/useObservableValue';
2
+ import { useCallState, useStore } from './store';
3
+
4
+ /**
5
+ * Utility hook which provides information whether the current call is being recorded.
6
+ *
7
+ * @category Call State
8
+ */
9
+ export const useIsCallRecordingInProgress = () => {
10
+ const metadata = useCallMetadata();
11
+ return !!metadata?.recording;
12
+ };
13
+
14
+ /**
15
+ * Utility hook which provides information whether the current call is broadcasting.
16
+ *
17
+ * @category Call State
18
+ */
19
+ export const useIsCallBroadcastingInProgress = () => {
20
+ const metadata = useCallMetadata();
21
+ return !!metadata?.broadcasting;
22
+ };
23
+
24
+ /**
25
+ * Utility hook which provides information whether the current call is live.
26
+ *
27
+ * @category Call State
28
+ */
29
+ export const useIsCallLive = () => {
30
+ const metadata = useCallMetadata();
31
+ return !metadata?.backstage;
32
+ };
33
+
34
+ /**
35
+ * Utility hook which provides a boolean indicating whether there is
36
+ * a participant in the current call which shares their screen.
37
+ *
38
+ * @category Call State
39
+ */
40
+ export const useHasOngoingScreenShare = () => {
41
+ const { hasOngoingScreenShare$ } = useCallState();
42
+ return useObservableValue(hasOngoingScreenShare$);
43
+ };
44
+
45
+ /**
46
+ * Utility hook which provides the latest stats report of the current call.
47
+ *
48
+ * The latest stats report of the current call.
49
+ * When stats gathering is enabled, this observable will emit a new value
50
+ * at a regular (configurable) interval.
51
+ *
52
+ * Consumers of this observable can implement their own batching logic
53
+ * in case they want to show historical stats data.
54
+ *
55
+ * @category Call State
56
+ */
57
+ export const useCallStatsReport = () => {
58
+ const { callStatsReport$ } = useCallState();
59
+ return useObservableValue(callStatsReport$);
60
+ };
61
+
62
+ /**
63
+ * Utility hook which provides the dominant speaker of the current call.
64
+ *
65
+ * @category Call State
66
+ */
67
+ export const useDominantSpeaker = () => {
68
+ const { dominantSpeaker$ } = useCallState();
69
+ return useObservableValue(dominantSpeaker$);
70
+ };
71
+
72
+ /**
73
+ * Utility hook which provides a list of all notifications about created calls.
74
+ * In the ring call settings, these calls can be outgoing (I have called somebody)
75
+ * or incoming (somebody has called me).
76
+ *
77
+ * @category Client State
78
+ */
79
+ export const useCalls = () => {
80
+ const { calls$ } = useStore();
81
+ return useObservableValue(calls$);
82
+ };
83
+
84
+ /**
85
+ * Utility hook which provides a list of all incoming ring calls (somebody calls me).
86
+ *
87
+ * @deprecated derive from useCalls()/useCall() instead.
88
+ * @internal
89
+ * @category Client State
90
+ */
91
+ export const useIncomingCalls = () => {
92
+ const { incomingCalls$ } = useStore();
93
+ return useObservableValue(incomingCalls$);
94
+ };
95
+
96
+ /**
97
+ * Utility hook which provides a list of all outgoing ring calls (I call somebody).
98
+ *
99
+ * @deprecated derive from useCalls()/useCall() instead.
100
+ * @internal
101
+ * @category Client State
102
+ */
103
+ export const useOutgoingCalls = () => {
104
+ const { outgoingCalls$ } = useStore();
105
+ return useObservableValue(outgoingCalls$);
106
+ };
107
+
108
+ /**
109
+ * Utility hook which provides call metadata (such as blocked users and own capabilities).
110
+ *
111
+ * @category Call State
112
+ */
113
+ export const useCallMetadata = () => {
114
+ const { metadata$ } = useCallState();
115
+ return useObservableValue(metadata$);
116
+ };
117
+
118
+ /**
119
+ * Utility hook which provides a list of call members.
120
+ *
121
+ * @category Call State
122
+ */
123
+ export const useCallMembers = () => {
124
+ const { members$ } = useCallState();
125
+ return useObservableValue(members$);
126
+ };
127
+
128
+ /**
129
+ * Utility hook providing the latest list of recordings performed during the active call
130
+ *
131
+ * @category Call State
132
+ */
133
+ export const useCallRecordings = () => {
134
+ const { callRecordingList$ } = useCallState();
135
+ return useObservableValue(callRecordingList$);
136
+ };
137
+
138
+ /**
139
+ * Utility hook providing the current calling state of the call.
140
+ *
141
+ * @category Call State
142
+ */
143
+ export const useCallCallingState = () => {
144
+ const { callingState$ } = useCallState();
145
+ return useObservableValue(callingState$);
146
+ };
147
+
148
+ /**
149
+ * Utility hook providing the actual start time of the call.
150
+ * Useful for calculating the call duration.
151
+ *
152
+ * @category Call State
153
+ */
154
+ export const useCallStartedAt = () => {
155
+ const { startedAt$ } = useCallState();
156
+ return useObservableValue(startedAt$);
157
+ };
@@ -0,0 +1,77 @@
1
+ import {
2
+ StreamClientOptions,
3
+ StreamVideoClient,
4
+ TokenOrProvider,
5
+ User,
6
+ } from '@stream-io/video-client';
7
+ import { useEffect, useRef, useState } from 'react';
8
+
9
+ /**
10
+ * Exclude types from documentation site, but we should still add doc comments
11
+ * @internal
12
+ */
13
+ export type StreamVideoClientInit = {
14
+ /**
15
+ * The Stream API key.
16
+ */
17
+ apiKey: string;
18
+ /**
19
+ * The token or token provider.
20
+ */
21
+ tokenOrProvider: TokenOrProvider;
22
+ /**
23
+ * The client options.
24
+ */
25
+ options?: StreamClientOptions;
26
+ /**
27
+ * The user to connect.
28
+ */
29
+ user: User;
30
+ /**
31
+ * Whether the user is anonymous. Defaults to `false`.
32
+ */
33
+ isAnonymous?: boolean;
34
+ };
35
+
36
+ /**
37
+ * Creates a new `StreamVideoClient` instance and connects the given user.
38
+ *
39
+ * @category Client State
40
+ */
41
+ export const useCreateStreamVideoClient = ({
42
+ apiKey,
43
+ tokenOrProvider,
44
+ user,
45
+ options,
46
+ isAnonymous = false,
47
+ }: StreamVideoClientInit) => {
48
+ const [client] = useState(() => new StreamVideoClient(apiKey, options));
49
+
50
+ const disconnectRef = useRef(Promise.resolve());
51
+ useEffect(() => {
52
+ const connectionPromise = disconnectRef.current.then(() => {
53
+ if (isAnonymous) {
54
+ return client
55
+ .connectAnonymousUser(user, tokenOrProvider)
56
+ .catch((err) => {
57
+ console.error(`Failed to establish connection`, err);
58
+ });
59
+ }
60
+ return client.connectUser(user, tokenOrProvider).catch((err) => {
61
+ console.error(`Failed to establish connection`, err);
62
+ });
63
+ });
64
+
65
+ return () => {
66
+ disconnectRef.current = connectionPromise
67
+ .then(() => client.disconnectUser())
68
+ .catch((err) => {
69
+ console.error(`Failed to disconnect`, err);
70
+ });
71
+ };
72
+ // we want to re-run this effect only in some special cases
73
+ // eslint-disable-next-line react-hooks/exhaustive-deps
74
+ }, [apiKey, tokenOrProvider, client, isAnonymous, user?.id]);
75
+
76
+ return client;
77
+ };
@@ -0,0 +1,21 @@
1
+ import type { Observable } from 'rxjs';
2
+ import { useEffect, useState } from 'react';
3
+ import { RxUtils } from '@stream-io/video-client';
4
+
5
+ /**
6
+ *
7
+ * @internal
8
+ */
9
+ export const useObservableValue = <T>(observable$: Observable<T>) => {
10
+ const [value, setValue] = useState<T>(() =>
11
+ RxUtils.getCurrentValue(observable$),
12
+ );
13
+ useEffect(() => {
14
+ const subscription = observable$.subscribe(setValue);
15
+ return () => {
16
+ subscription.unsubscribe();
17
+ };
18
+ }, [observable$]);
19
+
20
+ return value;
21
+ };
@@ -0,0 +1,6 @@
1
+ export * from './call';
2
+ export * from './client';
3
+ export * from './participants';
4
+ export * from './permissions';
5
+ export * from './store';
6
+ export * from './user';
@@ -0,0 +1,79 @@
1
+ import { useObservableValue } from './helpers/useObservableValue';
2
+ import { useCallState } from './store';
3
+ import type {
4
+ Comparator,
5
+ StreamVideoParticipant,
6
+ } from '@stream-io/video-client';
7
+ import { useMemo } from 'react';
8
+
9
+ /**
10
+ * A hook which provides a list of all participants that have joined an active call.
11
+ *
12
+ * @category Call State
13
+ *
14
+ * @param options.sortBy - A comparator function to sort the participants by.
15
+ * Make sure to memoize output of the `combineComparators` function
16
+ * (or keep it out of component's scope if possible) before passing it down to this property.
17
+ */
18
+ export const useParticipants = ({
19
+ sortBy,
20
+ }: {
21
+ /**
22
+ * Make sure to memoize output of the `combineComparators` function
23
+ * (or keep it out of component's scope if possible) before passing it down to this property.
24
+ */
25
+ sortBy?: Comparator<StreamVideoParticipant>;
26
+ } = {}) => {
27
+ const { participants$ } = useCallState();
28
+ const participants = useObservableValue(participants$);
29
+
30
+ return useMemo(() => {
31
+ if (sortBy) {
32
+ return [...participants].sort(sortBy);
33
+ }
34
+ return participants;
35
+ }, [participants, sortBy]);
36
+ };
37
+
38
+ /**
39
+ * A hook which provides a StreamVideoLocalParticipant object.
40
+ * It signals that I have joined a call.
41
+ *
42
+ * @category Call State
43
+ */
44
+ export const useLocalParticipant = () => {
45
+ const { localParticipant$ } = useCallState();
46
+ return useObservableValue(localParticipant$);
47
+ };
48
+
49
+ /**
50
+ * A hook which provides a list of all other participants than me that have joined an active call.
51
+ *
52
+ * @category Call State
53
+ */
54
+ export const useRemoteParticipants = () => {
55
+ const { remoteParticipants$ } = useCallState();
56
+ return useObservableValue(remoteParticipants$);
57
+ };
58
+
59
+ /**
60
+ * Returns the approximate participant count of the active call.
61
+ * This includes the anonymous users as well, and it is computed on the server.
62
+ *
63
+ * @category Call State
64
+ */
65
+ export const useParticipantCount = () => {
66
+ const { participantCount$ } = useCallState();
67
+ return useObservableValue(participantCount$);
68
+ };
69
+
70
+ /**
71
+ * Returns the approximate anonymous participant count of the active call.
72
+ * The regular participants are not included in this count. It is computed on the server.
73
+ *
74
+ * @category Call State
75
+ */
76
+ export const useAnonymousParticipantCount = () => {
77
+ const { anonymousParticipantCount$ } = useCallState();
78
+ return useObservableValue(anonymousParticipantCount$);
79
+ };
@@ -0,0 +1,37 @@
1
+ import { OwnCapability, PermissionRequestEvent } from '@stream-io/video-client';
2
+ import { useCallState } from './store';
3
+ import { useObservableValue } from './helpers/useObservableValue';
4
+
5
+ /**
6
+ * Hook that returns true if the current user has all the given permissions.
7
+ *
8
+ * @param permissions the permissions to check.
9
+ *
10
+ * @category Call State
11
+ */
12
+ export const useHasPermissions = (...permissions: OwnCapability[]): boolean => {
13
+ const capabilities = useOwnCapabilities();
14
+ return permissions.every((permission) => capabilities.includes(permission));
15
+ };
16
+
17
+ /**
18
+ * A hook which returns the current user's own capabilities.
19
+ *
20
+ * @category Call State
21
+ */
22
+ export const useOwnCapabilities = (): OwnCapability[] => {
23
+ const { ownCapabilities$ } = useCallState();
24
+ return useObservableValue(ownCapabilities$);
25
+ };
26
+
27
+ /**
28
+ * A hook which returns the latest call permission request.
29
+ *
30
+ * @category Call State
31
+ */
32
+ export const useCallPermissionRequest = ():
33
+ | PermissionRequestEvent
34
+ | undefined => {
35
+ const { callPermissionRequest$ } = useCallState();
36
+ return useObservableValue(callPermissionRequest$);
37
+ };
@@ -0,0 +1,34 @@
1
+ import { CallState } from '@stream-io/video-client';
2
+ import { useCall, useStreamVideoClient } from '../contexts';
3
+
4
+ /**
5
+ * Utility hook which provides access to client's state store.
6
+ */
7
+ export const useStore = () => {
8
+ const client = useStreamVideoClient();
9
+ if (!client) {
10
+ throw new Error(
11
+ `StreamVideoClient isn't initialized or this hook is called outside of <StreamVideo> context.`,
12
+ );
13
+ }
14
+ return client.readOnlyStateStore;
15
+ };
16
+
17
+ /**
18
+ * Utility hook which provides the current call's state.
19
+ *
20
+ * @category Call State
21
+ */
22
+ export const useCallState = () => {
23
+ const call = useCall();
24
+ // return an empty and unlinked CallState object if there is no call in the provider
25
+ // this ensures that the hooks always return a value and many null checks can be avoided
26
+ if (!call) {
27
+ const message =
28
+ 'You are using useCallState() outside a Call context. ' +
29
+ 'Please wrap your component in <StreamCallProvider /> and provide a non-null "call" instance.';
30
+ console.warn(message);
31
+ return new CallState();
32
+ }
33
+ return call.state;
34
+ };
@@ -0,0 +1,13 @@
1
+ import { useStore } from './store';
2
+ import { useObservableValue } from './helpers/useObservableValue';
3
+
4
+ /**
5
+ *
6
+ * @returns
7
+ *
8
+ * @category Client State
9
+ */
10
+ export const useConnectedUser = () => {
11
+ const { connectedUser$ } = useStore();
12
+ return useObservableValue(connectedUser$);
13
+ };
@@ -0,0 +1,40 @@
1
+ import { OwnCapability } from '@stream-io/video-client';
2
+
3
+ import { PropsWithChildren } from 'react';
4
+ import { useCall } from '../contexts';
5
+ import { useOwnCapabilities } from '../hooks';
6
+
7
+ type RestrictedProps = PropsWithChildren<{
8
+ /**
9
+ * OwnCapabilities of the participant - grants they have available
10
+ */
11
+ availableGrants?: OwnCapability[];
12
+ /**
13
+ * Required grants for the component to be able to render supplied children elements
14
+ */
15
+ requiredGrants: OwnCapability[];
16
+ /**
17
+ * Require all grants specified in `requiredGrants` to be available in the `availableGrants`,
18
+ * component by default requires only one grant to appear in both arrays to render its children
19
+ */
20
+ requireAll?: boolean;
21
+ }>;
22
+
23
+ export const Restricted = ({
24
+ availableGrants: availableGrantsFromProps,
25
+ requiredGrants,
26
+ requireAll = true,
27
+ children,
28
+ }: RestrictedProps) => {
29
+ const call = useCall();
30
+ const ownCapabilities = useOwnCapabilities();
31
+ const availableGrants = availableGrantsFromProps ?? ownCapabilities;
32
+ const hasPermissions = requiredGrants[requireAll ? 'every' : 'some'](
33
+ (capability) => availableGrants.includes(capability),
34
+ );
35
+ const canRequest = requiredGrants.some(
36
+ (capability) => !!call && call.permissionsContext.canRequest(capability),
37
+ );
38
+ if (hasPermissions || canRequest) return <>{children}</>;
39
+ return null;
40
+ };
@@ -0,0 +1 @@
1
+ export * from './Restricted';