@connectycube/react-ui-kit 0.0.14 → 0.0.15

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 (63) hide show
  1. package/configs/dependencies.json +1 -3
  2. package/dist/index.cjs +27 -1
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.js +27 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/tsconfig.tsbuildinfo +1 -1
  7. package/dist/types/components/animated-loader.d.ts +10 -0
  8. package/dist/types/components/animated-loader.d.ts.map +1 -0
  9. package/dist/types/components/avatar.d.ts +15 -0
  10. package/dist/types/components/avatar.d.ts.map +1 -0
  11. package/dist/types/components/dismiss-layer.d.ts +10 -0
  12. package/dist/types/components/dismiss-layer.d.ts.map +1 -0
  13. package/dist/types/components/placeholder-text.d.ts +8 -0
  14. package/dist/types/components/placeholder-text.d.ts.map +1 -0
  15. package/dist/types/components/presence.d.ts +17 -0
  16. package/dist/types/components/presence.d.ts.map +1 -0
  17. package/dist/types/components/status-indicator.d.ts +19 -0
  18. package/dist/types/components/status-indicator.d.ts.map +1 -0
  19. package/dist/types/components/stream-view.d.ts +28 -24
  20. package/dist/types/components/stream-view.d.ts.map +1 -1
  21. package/dist/types/components/utils.d.ts +2 -0
  22. package/dist/types/components/utils.d.ts.map +1 -1
  23. package/dist/types/index.d.ts +4 -2
  24. package/dist/types/index.d.ts.map +1 -1
  25. package/gen/components/avatar.jsx +6 -6
  26. package/gen/components/dismiss-layer.jsx +1 -1
  27. package/gen/components/presence.jsx +47 -7
  28. package/gen/components/status-indicator.jsx +12 -19
  29. package/package.json +18 -16
  30. package/src/components/animated-loader.tsx +1 -2
  31. package/src/components/avatar.tsx +10 -14
  32. package/src/components/dismiss-layer.tsx +1 -2
  33. package/src/components/placeholder-text.tsx +0 -1
  34. package/src/components/presence.tsx +48 -10
  35. package/src/components/status-indicator.tsx +19 -35
  36. package/src/components/stream-view.tsx +1 -3
  37. package/dist/types/components/connectycube-ui/stream-view.d.ts +0 -26
  38. package/dist/types/components/connectycube-ui/stream-view.d.ts.map +0 -1
  39. package/dist/types/components/connectycube-ui/utils.d.ts +0 -4
  40. package/dist/types/components/connectycube-ui/utils.d.ts.map +0 -1
  41. package/dist/types/lib/constants.d.ts +0 -5
  42. package/dist/types/lib/constants.d.ts.map +0 -1
  43. package/dist/types/lib/utils.d.ts +0 -4
  44. package/dist/types/lib/utils.d.ts.map +0 -1
  45. package/dist/types/templates/local-stream.d.ts +0 -22
  46. package/dist/types/templates/local-stream.d.ts.map +0 -1
  47. package/dist/types/templates/remote-stream.d.ts +0 -18
  48. package/dist/types/templates/remote-stream.d.ts.map +0 -1
  49. package/src/components/connectycube-ui/animated-loader.jsx +0 -10
  50. package/src/components/connectycube-ui/animated-loader.tsx +0 -15
  51. package/src/components/connectycube-ui/avatar.jsx +0 -34
  52. package/src/components/connectycube-ui/avatar.tsx +0 -45
  53. package/src/components/connectycube-ui/dismiss-layer.jsx +0 -57
  54. package/src/components/connectycube-ui/dismiss-layer.tsx +0 -74
  55. package/src/components/connectycube-ui/placeholder-text.jsx +0 -22
  56. package/src/components/connectycube-ui/placeholder-text.tsx +0 -28
  57. package/src/components/connectycube-ui/presence.jsx +0 -41
  58. package/src/components/connectycube-ui/presence.tsx +0 -55
  59. package/src/components/connectycube-ui/status-indicator.tsx +0 -100
  60. package/src/components/connectycube-ui/stream-view.jsx +0 -201
  61. package/src/components/connectycube-ui/stream-view.tsx +0 -246
  62. package/src/components/connectycube-ui/utils.js +0 -30
  63. package/src/components/connectycube-ui/utils.ts +0 -28
@@ -1,246 +0,0 @@
1
- import type React from 'react';
2
- import type { LucideProps } from 'lucide-react';
3
- import { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
4
- import { Maximize, Minimize, PictureInPicture2 } from 'lucide-react';
5
- import { cn, getRandomString } from './utils';
6
-
7
- interface StreamViewProps extends React.ComponentProps<'video'> {
8
- stream?: MediaStream | null;
9
- mirror?: boolean;
10
- }
11
-
12
- function StreamViewBase(
13
- { id, stream, mirror, className, muted, ...props }: StreamViewProps,
14
- ref: React.Ref<HTMLVideoElement>
15
- ) {
16
- const innerRef = useRef<HTMLVideoElement>(null);
17
- const elementId = useMemo(() => id ?? `stream-${getRandomString()}`, [id]);
18
- const isMuted = typeof muted === 'boolean' ? muted : false;
19
- const defaultClassName = 'size-full object-contain';
20
- const mirrorClassName = mirror ? 'scale-x-[-1]' : '';
21
-
22
- useImperativeHandle(ref, () => innerRef.current!);
23
-
24
- useEffect(() => {
25
- if (innerRef.current && stream) {
26
- innerRef.current.srcObject = stream;
27
-
28
- const playVideo = () => {
29
- try {
30
- innerRef.current?.play();
31
- } catch (error) {
32
- console.error('Error playing video:', error);
33
- }
34
- };
35
-
36
- innerRef.current.onloadedmetadata = () => {
37
- queueMicrotask(playVideo);
38
- };
39
- }
40
- }, [stream]);
41
-
42
- if (!stream) return null;
43
-
44
- return (
45
- <video
46
- ref={innerRef}
47
- id={elementId}
48
- autoPlay
49
- playsInline
50
- muted={isMuted}
51
- className={cn(defaultClassName, mirrorClassName, className)}
52
- {...props}
53
- />
54
- );
55
- }
56
-
57
- const StreamView = forwardRef<HTMLVideoElement, StreamViewProps>(StreamViewBase);
58
-
59
- StreamView.displayName = 'StreamView';
60
-
61
- function LocalStreamViewBase({ muted, mirror, ...props }: StreamViewProps, ref: React.Ref<HTMLVideoElement>) {
62
- const isMuted = typeof muted === 'boolean' ? muted : true;
63
- const isMirror = typeof mirror === 'boolean' ? mirror : true;
64
-
65
- return <StreamView ref={ref} muted={isMuted} mirror={isMirror} {...props} />;
66
- }
67
-
68
- const LocalStreamView = forwardRef<HTMLVideoElement, StreamViewProps>(LocalStreamViewBase);
69
-
70
- LocalStreamView.displayName = 'LocalStreamView';
71
-
72
- function RemoteStreamViewBase({ muted, mirror, ...props }: StreamViewProps, ref: React.Ref<HTMLVideoElement>) {
73
- const isMuted = typeof muted === 'boolean' ? muted : false;
74
- const isMirror = typeof mirror === 'boolean' ? mirror : false;
75
-
76
- return <StreamView ref={ref} muted={isMuted} mirror={isMirror} {...props} />;
77
- }
78
-
79
- const RemoteStreamView = forwardRef<HTMLVideoElement, StreamViewProps>(RemoteStreamViewBase);
80
-
81
- RemoteStreamView.displayName = 'RemoteStreamView';
82
-
83
- interface FullscreenStreamViewProps extends React.ComponentProps<'div'> {
84
- element: React.ReactElement<StreamViewProps>;
85
- pipElement?: React.ReactElement<StreamViewProps>;
86
- navElement?: React.ReactElement<HTMLElement>;
87
- hideIconElement?: React.ReactElement;
88
- showIconElement?: React.ReactElement;
89
- containerClassName?: string;
90
- fullscreenButtonClassName?: string;
91
- fullscreenButtonIconClassName?: string;
92
- pipContainerClassName?: string;
93
- pipButtonClassName?: string;
94
- pipButtonIconClassName?: string;
95
- containerProps?: React.ComponentProps<'div'>;
96
- fullscreenButtonProps?: React.ComponentProps<'button'>;
97
- fullscreenButtonIconProps?: LucideProps;
98
- pipContainerProps?: React.ComponentProps<'div'>;
99
- pipButtonProps?: React.ComponentProps<'button'>;
100
- pipButtonIconProps?: LucideProps;
101
- }
102
-
103
- interface FullscreenStreamViewRef extends React.ComponentRef<'div'> {
104
- isFullscreen: boolean;
105
- isPictureInPicture: boolean;
106
- toggleFullscreen: () => Promise<void>;
107
- togglePictureInPicture: () => void;
108
- }
109
-
110
- function FullscreenStreamViewBase(
111
- {
112
- element,
113
- pipElement,
114
- navElement,
115
- hideIconElement,
116
- showIconElement,
117
- containerClassName,
118
- fullscreenButtonClassName,
119
- fullscreenButtonIconClassName,
120
- pipContainerClassName,
121
- pipButtonClassName,
122
- pipButtonIconClassName,
123
- containerProps,
124
- fullscreenButtonProps,
125
- fullscreenButtonIconProps,
126
- pipContainerProps,
127
- pipButtonProps,
128
- pipButtonIconProps,
129
- }: FullscreenStreamViewProps,
130
- ref: React.Ref<FullscreenStreamViewRef>
131
- ) {
132
- const innerRef = useRef<HTMLDivElement>(null);
133
- const [isFullscreen, setIsFullscreen] = useState<boolean>(false);
134
- const [isPictureInPicture, setIsPictureInPicture] = useState<boolean>(false);
135
- const toggleFullscreen = useCallback(async () => {
136
- const container = innerRef.current;
137
-
138
- if (!container) return;
139
-
140
- try {
141
- if (!document.fullscreenElement) {
142
- await container.requestFullscreen();
143
- setIsFullscreen(true);
144
- setIsPictureInPicture(true);
145
- } else {
146
- await document.exitFullscreen();
147
- setIsFullscreen(false);
148
- setIsPictureInPicture(false);
149
- }
150
- } catch (err) {
151
- console.error('Fullscreen error:', err);
152
- }
153
- }, []);
154
- const togglePictureInPicture = useCallback(() => {
155
- if (pipElement) {
156
- setIsPictureInPicture((prevState) => !prevState);
157
- }
158
- }, [pipElement]);
159
-
160
- useImperativeHandle(
161
- ref,
162
- () =>
163
- Object.assign(innerRef.current!, {
164
- isFullscreen,
165
- isPictureInPicture,
166
- toggleFullscreen,
167
- togglePictureInPicture,
168
- }),
169
- [isFullscreen, isPictureInPicture, toggleFullscreen, togglePictureInPicture]
170
- );
171
-
172
- useEffect(() => {
173
- const onFullscreenChange = () => {
174
- setIsFullscreen(!!document.fullscreenElement);
175
- setIsPictureInPicture(!!document.fullscreenElement);
176
- };
177
-
178
- document.addEventListener('fullscreenchange', onFullscreenChange);
179
-
180
- return () => document.removeEventListener('fullscreenchange', onFullscreenChange);
181
- }, []);
182
-
183
- return (
184
- <div
185
- ref={innerRef}
186
- className={cn('relative flex items-center justify-center size-full', containerClassName)}
187
- {...containerProps}
188
- >
189
- {element}
190
- <button
191
- onClick={toggleFullscreen}
192
- className={cn(
193
- 'absolute top-2 right-2 p-1 rounded-md bg-black/50 text-white hover:bg-black/80 z-10 shadow-xs shadow-white/25',
194
- fullscreenButtonClassName
195
- )}
196
- {...fullscreenButtonProps}
197
- >
198
- {isFullscreen
199
- ? hideIconElement || <Minimize className={fullscreenButtonIconClassName} {...fullscreenButtonIconProps} />
200
- : showIconElement || <Maximize className={fullscreenButtonIconClassName} {...fullscreenButtonIconProps} />}
201
- </button>
202
- <div className="absolute size-full p-2 flex flex-col justify-end items-center">
203
- {isFullscreen && pipElement && (
204
- <div className="relative size-full flex items-end justify-end">
205
- {isPictureInPicture && (
206
- <div
207
- className={cn(
208
- 'max-w-1/4 max-h-1/4 aspect-4/3 overflow-hidden rounded-md shadow-md shadow-white/25',
209
- pipContainerClassName
210
- )}
211
- {...pipContainerProps}
212
- >
213
- {pipElement}
214
- </div>
215
- )}
216
- <button
217
- onClick={togglePictureInPicture}
218
- className={cn(
219
- 'absolute bottom-2 right-2 p-1 rounded-md bg-black/50 text-white hover:bg-black/80 z-10 shadow-xs shadow-white/25',
220
- pipButtonClassName
221
- )}
222
- {...pipButtonProps}
223
- >
224
- <PictureInPicture2 className={pipButtonIconClassName} {...pipButtonIconProps} />
225
- </button>
226
- </div>
227
- )}
228
- {isFullscreen && navElement}
229
- </div>
230
- </div>
231
- );
232
- }
233
-
234
- const FullscreenStreamView = forwardRef<FullscreenStreamViewRef, FullscreenStreamViewProps>(FullscreenStreamViewBase);
235
-
236
- FullscreenStreamView.displayName = 'FullscreenStreamView';
237
-
238
- export {
239
- StreamView,
240
- LocalStreamView,
241
- RemoteStreamView,
242
- FullscreenStreamView,
243
- type StreamViewProps,
244
- type FullscreenStreamViewProps,
245
- type FullscreenStreamViewRef,
246
- };
@@ -1,30 +0,0 @@
1
- import { clsx } from 'clsx';
2
- import { twMerge } from 'tailwind-merge';
3
-
4
- export function cn(...inputs) {
5
- return twMerge(clsx(inputs));
6
- }
7
-
8
- export function getRandomString(length = 8) {
9
- return (Date.now() / Math.random()).toString(36).replace('.', '').slice(0, length);
10
- }
11
-
12
- export function getInitialsFromName(name) {
13
- const words = name?.trim().split(/\s+/).filter(Boolean) ?? [];
14
- const result = words.length > 1 ? `${words[0]?.[0]}${words[1]?.[0]}` : (words[0]?.slice(0, 2) ?? 'NA');
15
-
16
- return result.toUpperCase();
17
- }
18
-
19
- export function capitalize(str) {
20
- return typeof str === 'string' && str.length > 0 ? `${str[0]?.toUpperCase()}${str.slice(1)}` : '';
21
- }
22
-
23
- export let UserPresence = /*#__PURE__*/ (function (UserPresence) {
24
- UserPresence['AVAILABLE'] = 'available';
25
- UserPresence['BUSY'] = 'busy';
26
- UserPresence['AWAY'] = 'away';
27
- UserPresence['UNKNOWN'] = 'unknown';
28
-
29
- return UserPresence;
30
- })({});
@@ -1,28 +0,0 @@
1
- import { clsx, type ClassValue } from 'clsx';
2
- import { twMerge } from 'tailwind-merge';
3
-
4
- export function cn(...inputs: ClassValue[]) {
5
- return twMerge(clsx(inputs));
6
- }
7
-
8
- export function getRandomString(length = 8): string {
9
- return (Date.now() / Math.random()).toString(36).replace('.', '').slice(0, length);
10
- }
11
-
12
- export function getInitialsFromName(name?: string): string {
13
- const words = name?.trim().split(/\s+/).filter(Boolean) ?? [];
14
- const result = words.length > 1 ? `${words[0]?.[0]}${words[1]?.[0]}` : (words[0]?.slice(0, 2) ?? 'NA');
15
-
16
- return result.toUpperCase();
17
- }
18
-
19
- export function capitalize(str?: string): string {
20
- return typeof str === 'string' && str.length > 0 ? `${str[0]?.toUpperCase()}${str.slice(1)}` : '';
21
- }
22
-
23
- export enum UserPresence {
24
- AVAILABLE = 'available',
25
- BUSY = 'busy',
26
- AWAY = 'away',
27
- UNKNOWN = 'unknown',
28
- }