@connectycube/react-ui-kit 0.1.0 → 0.1.2

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 (79) hide show
  1. package/README.md +2 -2
  2. package/gen/components/alert-dialog.jsx +2 -2
  3. package/gen/components/attachment.jsx +10 -11
  4. package/gen/components/avatar.jsx +2 -2
  5. package/gen/components/badge.jsx +2 -2
  6. package/gen/components/button.jsx +4 -3
  7. package/gen/components/chat-bubble.jsx +8 -8
  8. package/gen/components/chat-input.jsx +10 -10
  9. package/gen/components/chat-list.jsx +13 -13
  10. package/gen/components/checkbox.jsx +2 -2
  11. package/gen/components/dialog-item.jsx +2 -2
  12. package/gen/components/dialogs-list.jsx +4 -4
  13. package/gen/components/dismiss-layer.jsx +7 -7
  14. package/gen/components/file-picker.jsx +4 -4
  15. package/gen/components/formatted-date.jsx +2 -2
  16. package/gen/components/input.jsx +2 -2
  17. package/gen/components/label.jsx +2 -2
  18. package/gen/components/link-preview.jsx +7 -7
  19. package/gen/components/linkify-text.jsx +5 -5
  20. package/gen/components/placeholder-text.jsx +1 -2
  21. package/gen/components/presence.jsx +1 -0
  22. package/gen/components/quick-actions.jsx +2 -2
  23. package/gen/components/search.jsx +3 -3
  24. package/gen/components/spinner.jsx +3 -2
  25. package/gen/components/status-call.jsx +1 -0
  26. package/gen/components/status-indicator.jsx +2 -2
  27. package/gen/components/status-sent.jsx +1 -0
  28. package/gen/components/stream-view.jsx +16 -16
  29. package/package.json +14 -14
  30. package/src/components/alert-dialog.tsx +2 -3
  31. package/src/components/attachment.tsx +12 -13
  32. package/src/components/avatar.tsx +2 -3
  33. package/src/components/badge.tsx +2 -3
  34. package/src/components/button.tsx +4 -4
  35. package/src/components/chat-bubble.tsx +9 -10
  36. package/src/components/chat-input.tsx +17 -13
  37. package/src/components/chat-list.tsx +31 -24
  38. package/src/components/checkbox.tsx +2 -3
  39. package/src/components/dialog-item.tsx +2 -3
  40. package/src/components/dialogs-list.tsx +4 -5
  41. package/src/components/dismiss-layer.tsx +7 -8
  42. package/src/components/file-picker.tsx +4 -5
  43. package/src/components/formatted-date.tsx +4 -3
  44. package/src/components/input.tsx +2 -3
  45. package/src/components/label.tsx +2 -3
  46. package/src/components/link-preview.tsx +16 -26
  47. package/src/components/linkify-text.tsx +5 -6
  48. package/src/components/placeholder-text.tsx +1 -2
  49. package/src/components/presence.tsx +1 -1
  50. package/src/components/quick-actions.tsx +2 -3
  51. package/src/components/search.tsx +3 -4
  52. package/src/components/spinner.tsx +3 -2
  53. package/src/components/status-call.tsx +1 -0
  54. package/src/components/status-indicator.tsx +2 -3
  55. package/src/components/status-sent.tsx +1 -0
  56. package/src/components/stream-view.tsx +18 -17
  57. package/src/components/connectycube-ui/attachment.tsx +0 -269
  58. package/src/components/connectycube-ui/avatar.jsx +0 -54
  59. package/src/components/connectycube-ui/avatar.tsx +0 -77
  60. package/src/components/connectycube-ui/badge.jsx +0 -45
  61. package/src/components/connectycube-ui/badge.tsx +0 -42
  62. package/src/components/connectycube-ui/chat-input.tsx +0 -174
  63. package/src/components/connectycube-ui/chat-message.tsx +0 -138
  64. package/src/components/connectycube-ui/dialog-item.jsx +0 -149
  65. package/src/components/connectycube-ui/dialog-item.tsx +0 -188
  66. package/src/components/connectycube-ui/file-picker.jsx +0 -200
  67. package/src/components/connectycube-ui/file-picker.tsx +0 -231
  68. package/src/components/connectycube-ui/formatted-date.jsx +0 -57
  69. package/src/components/connectycube-ui/formatted-date.tsx +0 -57
  70. package/src/components/connectycube-ui/label.jsx +0 -22
  71. package/src/components/connectycube-ui/label.tsx +0 -23
  72. package/src/components/connectycube-ui/link-preview.tsx +0 -149
  73. package/src/components/connectycube-ui/linkify-text.tsx +0 -40
  74. package/src/components/connectycube-ui/presence.jsx +0 -81
  75. package/src/components/connectycube-ui/presence.tsx +0 -96
  76. package/src/components/connectycube-ui/status-sent.jsx +0 -21
  77. package/src/components/connectycube-ui/status-sent.tsx +0 -25
  78. package/src/components/connectycube-ui/utils.js +0 -10
  79. package/src/components/connectycube-ui/utils.ts +0 -10
@@ -1,4 +1,4 @@
1
- import React, { useRef, useEffect, useState, useImperativeHandle, forwardRef, useCallback } from 'react';
1
+ import * as React from 'react';
2
2
  import { Virtualizer, VirtualizerProps, type VirtualizerHandle } from 'virtua';
3
3
  import { FilePickerDropzone, type FilePickerDropzoneProps } from './file-picker';
4
4
  import { QuickActions, type QuickActionsProps } from './quick-actions';
@@ -25,6 +25,7 @@ interface ChatListProps extends VirtualizerProps {
25
25
 
26
26
  interface ChatListHandle extends VirtualizerHandle {
27
27
  scrollToBottom: (force?: boolean) => void;
28
+ setShift: (shift: boolean) => void;
28
29
  }
29
30
 
30
31
  function DefaultChatListWrapper({ children, ...props }: React.ComponentProps<'div'>) {
@@ -53,6 +54,7 @@ function ChatListBase(
53
54
  children,
54
55
  quickActionsVisible,
55
56
  minItemsCount = 1,
57
+ shift = false,
56
58
  ...props
57
59
  }: ChatListProps,
58
60
  ref: React.ForwardedRef<ChatListHandle>
@@ -60,11 +62,11 @@ function ChatListBase(
60
62
  const ChatListWrapper = enableFilePickerDropzone ? FilePickerDropzone : DefaultChatListWrapper;
61
63
  const chatListWrapperProps = enableFilePickerDropzone ? filePickerDropzoneProps : containerProps;
62
64
  const itemsCount = Array.isArray(children) ? children.length : Array.isArray(props.data) ? props.data.length : 0;
63
- const itemsCountRef = useRef<number>(0);
64
- const keyRef = useRef<string | undefined>(undefined);
65
- const [shouldPrependMessages, setShouldPrependMessages] = useState<boolean>(false);
66
- const [isPreparing, setIsPreparing] = useState<boolean>(false);
67
- const virtuaRef = useRef<VirtualizerHandle>(null);
65
+ const itemsCountRef = React.useRef<number>(0);
66
+ const keyRef = React.useRef<string | undefined>(undefined);
67
+ const [isPreparing, setIsPreparing] = React.useState<boolean>(false);
68
+ const [_shift, setShift] = React.useState<boolean>(shift);
69
+ const virtuaRef = React.useRef<VirtualizerHandle>(null);
68
70
  const prepareNextVirtualizer = () => {
69
71
  queueMicrotask(() => {
70
72
  setIsPreparing(true);
@@ -77,7 +79,6 @@ function ChatListBase(
77
79
  if (!virtuaRef.current) return;
78
80
 
79
81
  if (typeof onScrollStartReached === 'function' && offset < offsetToReach) {
80
- setShouldPrependMessages(true);
81
82
  onScrollStartReached();
82
83
  }
83
84
 
@@ -88,18 +89,20 @@ function ChatListBase(
88
89
  onScrollEndReached();
89
90
  }
90
91
  };
91
- const scrollToBottom = useCallback(
92
+ const scrollToBottom = React.useCallback(
92
93
  (force: boolean = false) => {
93
- if (!virtuaRef.current) return;
94
+ if (!virtuaRef.current || itemsCount === 0) return;
94
95
 
95
96
  if (force || virtuaRef.current.scrollSize - virtuaRef.current.scrollOffset < virtuaRef.current.viewportSize * 2) {
96
- queueMicrotask(() => virtuaRef.current?.scrollToIndex(itemsCount - 1, { align: 'start' }));
97
+ requestAnimationFrame(() => {
98
+ virtuaRef.current?.scrollToIndex(itemsCount - 1, { align: 'start' });
99
+ });
97
100
  }
98
101
  },
99
102
  [itemsCount]
100
103
  );
101
104
 
102
- useEffect(() => {
105
+ React.useEffect(() => {
103
106
  if (key !== keyRef.current) {
104
107
  prepareNextVirtualizer();
105
108
  onListReset?.(keyRef.current, key);
@@ -108,7 +111,7 @@ function ChatListBase(
108
111
  }
109
112
  }, [key, onListReset]);
110
113
 
111
- useEffect(() => {
114
+ React.useEffect(() => {
112
115
  if (itemsCountRef.current === 0 && itemsCount > 0) {
113
116
  prepareNextVirtualizer();
114
117
  onListCreate?.();
@@ -117,30 +120,34 @@ function ChatListBase(
117
120
  }
118
121
 
119
122
  if (itemsCount > itemsCountRef.current) {
123
+ const isPrepend = _shift;
124
+
120
125
  onListGrow?.();
121
126
  itemsCountRef.current = itemsCount;
122
127
 
123
- if (shouldPrependMessages) {
124
- queueMicrotask(() => setShouldPrependMessages(false));
128
+ if (isPrepend) {
129
+ queueMicrotask(() => setShift(false));
130
+ } else {
131
+ scrollToBottom();
125
132
  }
126
-
127
- scrollToBottom();
128
133
  }
129
- }, [itemsCount, shouldPrependMessages, onListCreate, onListGrow, scrollToBottom]);
134
+ }, [itemsCount, _shift, onListCreate, onListGrow, scrollToBottom]);
130
135
 
131
- useEffect(() => {
136
+ React.useEffect(() => {
132
137
  virtuaRef.current?.scrollBy(textareaMeasurement.shift);
133
138
  }, [textareaMeasurement]);
134
139
 
135
- useImperativeHandle(ref, () => ({ ...(virtuaRef.current || ({} as VirtualizerHandle)), scrollToBottom }), [
136
- scrollToBottom,
137
- ]);
140
+ React.useImperativeHandle(
141
+ ref,
142
+ () => ({ ...(virtuaRef.current || ({} as VirtualizerHandle)), scrollToBottom, setShift }),
143
+ [scrollToBottom]
144
+ );
138
145
 
139
146
  if (isPreparing) {
140
147
  return null;
141
148
  }
142
149
 
143
- if (minItemsCount >= itemsCount) {
150
+ if (minItemsCount > itemsCount) {
144
151
  return quickActionsVisible ? <QuickActions {...quickActionsProps} /> : <Spinner loading layout="centered" />;
145
152
  }
146
153
 
@@ -149,7 +156,7 @@ function ChatListBase(
149
156
  <Spinner loading={loading} className="my-5" />
150
157
  <div className="flex flex-col h-full overflow-y-auto px-2">
151
158
  <div className="grow" />
152
- <Virtualizer ref={virtuaRef} onScroll={handleOnScroll} shift={shouldPrependMessages} {...props}>
159
+ <Virtualizer ref={virtuaRef} onScroll={handleOnScroll} shift={_shift} {...props}>
153
160
  {children}
154
161
  </Virtualizer>
155
162
  </div>
@@ -157,7 +164,7 @@ function ChatListBase(
157
164
  );
158
165
  }
159
166
 
160
- const ChatList = forwardRef<ChatListHandle, ChatListProps>(ChatListBase);
167
+ const ChatList = React.forwardRef<ChatListHandle, ChatListProps>(ChatListBase);
161
168
 
162
169
  ChatList.displayName = 'ChatList';
163
170
 
@@ -1,5 +1,4 @@
1
- import type React from 'react';
2
- import { forwardRef } from 'react';
1
+ import * as React from 'react';
3
2
  import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
4
3
  import { CheckIcon, type LucideProps } from 'lucide-react';
5
4
  import { cn } from './utils';
@@ -33,7 +32,7 @@ function CheckboxBase(
33
32
  );
34
33
  }
35
34
 
36
- const Checkbox = forwardRef<HTMLButtonElement, CheckboxProps>(CheckboxBase);
35
+ const Checkbox = React.forwardRef<HTMLButtonElement, CheckboxProps>(CheckboxBase);
37
36
 
38
37
  Checkbox.displayName = 'Checkbox';
39
38
 
@@ -1,7 +1,6 @@
1
- import type React from 'react';
1
+ import * as React from 'react';
2
2
  import { Avatar, type AvatarProps } from './avatar';
3
3
  import { Users, type LucideProps } from 'lucide-react';
4
- import { forwardRef, memo } from 'react';
5
4
  import { FormattedDate, type FormattedDateProps } from './formatted-date';
6
5
  import { StatusSent, type StatusSentProps } from './status-sent';
7
6
  import { type PresenceStatus } from './presence';
@@ -184,7 +183,7 @@ function DialogItemBase(
184
183
  );
185
184
  }
186
185
 
187
- const DialogItem = memo(forwardRef<HTMLDivElement, DialogItemProps>(DialogItemBase));
186
+ const DialogItem = React.memo(React.forwardRef<HTMLDivElement, DialogItemProps>(DialogItemBase));
188
187
 
189
188
  DialogItem.displayName = 'DialogItem';
190
189
 
@@ -1,5 +1,4 @@
1
- import type React from 'react';
2
- import { forwardRef, useImperativeHandle, useRef } from 'react';
1
+ import * as React from 'react';
3
2
  import { VList, type VListHandle, type VListProps } from 'virtua';
4
3
  import { PlaceholderText } from './placeholder-text';
5
4
 
@@ -43,7 +42,7 @@ function DialogsListBase(
43
42
  }: DialogsListProps,
44
43
  ref: React.ForwardedRef<VListHandle>
45
44
  ) {
46
- const vListRef = useRef<VListHandle>(null);
45
+ const vListRef = React.useRef<VListHandle>(null);
47
46
  const skeletonList = Array.from({ length: pendingListLength }).map((_, i) => (
48
47
  <PendingItem key={`pending_dialog_item_${i}`} />
49
48
  ));
@@ -64,7 +63,7 @@ function DialogsListBase(
64
63
  }
65
64
  };
66
65
 
67
- useImperativeHandle(ref, () => vListRef.current || ({} as VListHandle), []);
66
+ React.useImperativeHandle(ref, () => vListRef.current || ({} as VListHandle), []);
68
67
 
69
68
  if (placeholderVisible) {
70
69
  return <PlaceholderText titles={placeholderTitles} className="text-base text-muted" />;
@@ -77,7 +76,7 @@ function DialogsListBase(
77
76
  );
78
77
  }
79
78
 
80
- const DialogsList = forwardRef<VListHandle, DialogsListProps>(DialogsListBase);
79
+ const DialogsList = React.forwardRef<VListHandle, DialogsListProps>(DialogsListBase);
81
80
 
82
81
  DialogsList.displayName = 'DialogsList';
83
82
 
@@ -1,5 +1,4 @@
1
- import type React from 'react';
2
- import { useCallback, useEffect, useRef, useImperativeHandle, forwardRef } from 'react';
1
+ import * as React from 'react';
3
2
  import { cn } from './utils';
4
3
 
5
4
  interface DismissLayerProps extends React.ComponentProps<'div'> {
@@ -14,11 +13,11 @@ function DismissLayerBase(
14
13
  { active, onDismiss, disableClickOutside = false, disableEscKeyPress = false, disabled, ...props }: DismissLayerProps,
15
14
  ref: React.ForwardedRef<HTMLDivElement>
16
15
  ) {
17
- const innerRef = useRef<HTMLDivElement>(null);
16
+ const innerRef = React.useRef<HTMLDivElement>(null);
18
17
 
19
- useImperativeHandle(ref, () => innerRef.current || ({} as HTMLDivElement), []);
18
+ React.useImperativeHandle(ref, () => innerRef.current || ({} as HTMLDivElement), []);
20
19
 
21
- const handleClickOrTouch = useCallback(
20
+ const handleClickOrTouch = React.useCallback(
22
21
  (e: React.MouseEvent | React.TouchEvent) => {
23
22
  if (!disableClickOutside && active && e.target === innerRef.current) {
24
23
  onDismiss();
@@ -26,7 +25,7 @@ function DismissLayerBase(
26
25
  },
27
26
  [disableClickOutside, active, onDismiss]
28
27
  );
29
- const handleKeyEvent = useCallback(
28
+ const handleKeyEvent = React.useCallback(
30
29
  (ev: KeyboardEvent) => {
31
30
  if (!disableEscKeyPress && active && ev.key === 'Escape') {
32
31
  onDismiss();
@@ -35,7 +34,7 @@ function DismissLayerBase(
35
34
  [disableEscKeyPress, active, onDismiss]
36
35
  );
37
36
 
38
- useEffect(() => {
37
+ React.useEffect(() => {
39
38
  if (!disableEscKeyPress && active) {
40
39
  document.addEventListener('keydown', handleKeyEvent);
41
40
 
@@ -59,7 +58,7 @@ function DismissLayerBase(
59
58
  );
60
59
  }
61
60
 
62
- const DismissLayer = forwardRef<HTMLDivElement, DismissLayerProps>(DismissLayerBase);
61
+ const DismissLayer = React.forwardRef<HTMLDivElement, DismissLayerProps>(DismissLayerBase);
63
62
 
64
63
  DismissLayer.displayName = 'DismissLayer';
65
64
 
@@ -1,5 +1,4 @@
1
- import type React from 'react';
2
- import { forwardRef, useState } from 'react';
1
+ import * as React from 'react';
3
2
  import { FilePlusCorner, LucideProps, Paperclip } from 'lucide-react';
4
3
  import { Label, type LabelProps } from './label';
5
4
  import { cn } from './utils';
@@ -124,7 +123,7 @@ function FilePickerInputBase(
124
123
  );
125
124
  }
126
125
 
127
- const FilePickerInput = forwardRef<HTMLInputElement, FilePickerInputProps>(FilePickerInputBase);
126
+ const FilePickerInput = React.forwardRef<HTMLInputElement, FilePickerInputProps>(FilePickerInputBase);
128
127
 
129
128
  FilePickerInput.displayName = 'FilePickerInput';
130
129
 
@@ -145,7 +144,7 @@ function FilePickerDropzoneBase(
145
144
  }: FilePickerDropzoneProps,
146
145
  ref: React.ForwardedRef<HTMLDivElement>
147
146
  ) {
148
- const [isDragging, setIsDragging] = useState(false);
147
+ const [isDragging, setIsDragging] = React.useState(false);
149
148
  const handleDragEvent = (event: React.DragEvent<HTMLDivElement>) => {
150
149
  event.preventDefault();
151
150
  event.stopPropagation();
@@ -217,7 +216,7 @@ function FilePickerDropzoneBase(
217
216
  );
218
217
  }
219
218
 
220
- const FilePickerDropzone = forwardRef<HTMLDivElement, FilePickerDropzoneProps>(FilePickerDropzoneBase);
219
+ const FilePickerDropzone = React.forwardRef<HTMLDivElement, FilePickerDropzoneProps>(FilePickerDropzoneBase);
221
220
 
222
221
  FilePickerDropzone.displayName = 'FilePickerDropzone';
223
222
 
@@ -1,6 +1,6 @@
1
- import { forwardRef, memo } from 'react';
1
+ import * as React from 'react';
2
2
  import { differenceInCalendarDays, format, formatDistanceToNow, isToday } from 'date-fns';
3
- import { el, enUS, uk, type Locale } from 'date-fns/locale';
3
+ import { el, enUS, uk, es, type Locale } from 'date-fns/locale';
4
4
  import { cn } from './utils';
5
5
 
6
6
  interface FormattedDateProps extends React.ComponentProps<'span'> {
@@ -13,6 +13,7 @@ const locales: Record<string, Locale> = {
13
13
  en: enUS,
14
14
  el: el,
15
15
  ua: uk,
16
+ es: es,
16
17
  };
17
18
 
18
19
  function formatDate(date: string | number | Date, language: string = 'en', distanceToNow = false): string {
@@ -50,7 +51,7 @@ function FormattedDateBase(
50
51
  );
51
52
  }
52
53
 
53
- const FormattedDate = memo(forwardRef<HTMLSpanElement, FormattedDateProps>(FormattedDateBase));
54
+ const FormattedDate = React.memo(React.forwardRef<HTMLSpanElement, FormattedDateProps>(FormattedDateBase));
54
55
 
55
56
  FormattedDate.displayName = 'FormattedDate';
56
57
 
@@ -1,5 +1,4 @@
1
- import type React from 'react';
2
- import { forwardRef } from 'react';
1
+ import * as React from 'react';
3
2
  import { cn } from './utils';
4
3
 
5
4
  type InputProps = React.ComponentProps<'input'>;
@@ -19,7 +18,7 @@ function InputBase(props: InputProps, ref?: React.ForwardedRef<HTMLInputElement>
19
18
  );
20
19
  }
21
20
 
22
- const Input = forwardRef<HTMLInputElement, InputProps>(InputBase);
21
+ const Input = React.forwardRef<HTMLInputElement, InputProps>(InputBase);
23
22
 
24
23
  Input.displayName = 'Input';
25
24
 
@@ -1,5 +1,4 @@
1
- import type React from 'react';
2
- import { forwardRef } from 'react';
1
+ import * as React from 'react';
3
2
  import { Root as LabelRoot, type LabelProps } from '@radix-ui/react-label';
4
3
  import { cn } from './utils';
5
4
 
@@ -16,7 +15,7 @@ function LabelBase({ ...props }: LabelProps, ref: React.ForwardedRef<HTMLLabelEl
16
15
  );
17
16
  }
18
17
 
19
- const Label = forwardRef<HTMLLabelElement, LabelProps>(LabelBase);
18
+ const Label = React.forwardRef<HTMLLabelElement, LabelProps>(LabelBase);
20
19
 
21
20
  Label.displayName = 'Label';
22
21
 
@@ -1,5 +1,4 @@
1
- import type React from 'react';
2
- import { forwardRef, memo, useCallback, useState } from 'react';
1
+ import * as React from 'react';
3
2
  import { Globe, type LucideProps } from 'lucide-react';
4
3
  import { cn } from './utils';
5
4
 
@@ -52,29 +51,20 @@ function LinkPreviewBase(
52
51
  }: LinkPreviewProps,
53
52
  ref: React.ForwardedRef<HTMLAnchorElement>
54
53
  ) {
55
- const [iconSrc, setIconSrc] = useState<React.ComponentProps<'img'>['src']>(icon);
56
- const [imageSrc, setImageSrc] = useState<React.ComponentProps<'img'>['src']>(image);
57
- const handleOnLoad = useCallback(
58
- (event: React.SyntheticEvent<HTMLImageElement, Event>) => {
59
- imageProps?.onLoad?.(event);
60
- onReady();
61
- },
62
- [onReady, imageProps]
63
- );
64
- const handleIconOnError = useCallback(
65
- (event: React.SyntheticEvent<HTMLImageElement, Event>) => {
66
- iconProps?.onError?.(event);
67
- setIconSrc(undefined);
68
- },
69
- [iconProps]
70
- );
71
- const handleImageOnError = useCallback(
72
- (event: React.SyntheticEvent<HTMLImageElement, Event>) => {
73
- imageProps?.onError?.(event);
74
- setImageSrc(undefined);
75
- },
76
- [imageProps]
77
- );
54
+ const [iconSrc, setIconSrc] = React.useState<React.ComponentProps<'img'>['src']>(icon);
55
+ const [imageSrc, setImageSrc] = React.useState<React.ComponentProps<'img'>['src']>(image);
56
+ const handleOnLoad = (event: React.SyntheticEvent<HTMLImageElement, Event>) => {
57
+ imageProps?.onLoad?.(event);
58
+ onReady();
59
+ };
60
+ const handleIconOnError = (event: React.SyntheticEvent<HTMLImageElement, Event>) => {
61
+ iconProps?.onError?.(event);
62
+ setIconSrc(undefined);
63
+ };
64
+ const handleImageOnError = (event: React.SyntheticEvent<HTMLImageElement, Event>) => {
65
+ imageProps?.onError?.(event);
66
+ setImageSrc(undefined);
67
+ };
78
68
 
79
69
  return (
80
70
  <a
@@ -142,7 +132,7 @@ function LinkPreviewBase(
142
132
  );
143
133
  }
144
134
 
145
- const LinkPreview = memo(forwardRef<HTMLAnchorElement, LinkPreviewProps>(LinkPreviewBase));
135
+ const LinkPreview = React.memo(React.forwardRef<HTMLAnchorElement, LinkPreviewProps>(LinkPreviewBase));
146
136
 
147
137
  LinkPreview.displayName = 'LinkPreview';
148
138
 
@@ -1,6 +1,5 @@
1
- import type React from 'react';
1
+ import * as React from 'react';
2
2
  import type { Opts } from 'linkifyjs';
3
- import { forwardRef, memo, useEffect, useMemo, useRef } from 'react';
4
3
  import Linkify from 'linkify-react';
5
4
  import { cn } from './utils';
6
5
 
@@ -33,8 +32,8 @@ function LinkifyTextBase(
33
32
  }: LinkifyTextProps,
34
33
  ref: React.ForwardedRef<HTMLParagraphElement>
35
34
  ) {
36
- const pendingRef = useRef(pending);
37
- const options = useMemo(
35
+ const pendingRef = React.useRef(pending);
36
+ const options = React.useMemo(
38
37
  () => ({
39
38
  ...DEFAULT_LINKIFY_OPTIONS,
40
39
  ...linkifyProps,
@@ -43,7 +42,7 @@ function LinkifyTextBase(
43
42
  [linkifyProps]
44
43
  );
45
44
 
46
- useEffect(() => {
45
+ React.useEffect(() => {
47
46
  if (pendingRef.current && !pending) {
48
47
  onReady();
49
48
  }
@@ -75,7 +74,7 @@ function LinkifyTextBase(
75
74
  );
76
75
  }
77
76
 
78
- const LinkifyText = memo(forwardRef<HTMLParagraphElement, LinkifyTextProps>(LinkifyTextBase));
77
+ const LinkifyText = React.memo(React.forwardRef<HTMLParagraphElement, LinkifyTextProps>(LinkifyTextBase));
79
78
 
80
79
  LinkifyText.displayName = 'LinkifyText';
81
80
 
@@ -1,5 +1,4 @@
1
1
  import * as React from 'react';
2
- import { forwardRef } from 'react';
3
2
  import { cn } from './utils';
4
3
 
5
4
  interface PlaceholderTextProps extends React.ComponentProps<'div'> {
@@ -33,7 +32,7 @@ function PlaceholderTextBase(
33
32
  );
34
33
  }
35
34
 
36
- const PlaceholderText = forwardRef(PlaceholderTextBase);
35
+ const PlaceholderText = React.forwardRef(PlaceholderTextBase);
37
36
 
38
37
  PlaceholderText.displayName = 'PlaceholderText';
39
38
 
@@ -1,4 +1,4 @@
1
- import type React from 'react';
1
+ import * as React from 'react';
2
2
  import { capitalize, cn } from './utils';
3
3
 
4
4
  type PresenceStatus = 'available' | 'busy' | 'away' | 'unknown' | undefined;
@@ -1,5 +1,4 @@
1
- import type React from 'react';
2
- import { forwardRef } from 'react';
1
+ import * as React from 'react';
3
2
  import { cn } from './utils';
4
3
 
5
4
  interface QuickActionsProps extends React.HTMLAttributes<HTMLDivElement> {
@@ -67,7 +66,7 @@ function QuickActionsBase(
67
66
  );
68
67
  }
69
68
 
70
- const QuickActions = forwardRef<HTMLDivElement, QuickActionsProps>(QuickActionsBase);
69
+ const QuickActions = React.forwardRef<HTMLDivElement, QuickActionsProps>(QuickActionsBase);
71
70
 
72
71
  QuickActions.displayName = 'QuickActions';
73
72
 
@@ -1,5 +1,4 @@
1
- import type React from 'react';
2
- import { forwardRef, useState } from 'react';
1
+ import * as React from 'react';
3
2
  import { cn } from './utils';
4
3
  import { Input, type InputProps } from './input';
5
4
  import { Search as SearchIcon, X as CloseIcon, type LucideProps } from 'lucide-react';
@@ -27,7 +26,7 @@ function SearchBase(
27
26
  }: SearchProps,
28
27
  ref?: React.ForwardedRef<HTMLInputElement>
29
28
  ) {
30
- const [value, setValue] = useState<string>('');
29
+ const [value, setValue] = React.useState<string>('');
31
30
  const handleOnSearch = (e: React.ChangeEvent<HTMLInputElement>): void => {
32
31
  const keyword = e.target.value;
33
32
 
@@ -79,7 +78,7 @@ function SearchBase(
79
78
  );
80
79
  }
81
80
 
82
- const Search = forwardRef<HTMLInputElement, SearchProps>(SearchBase);
81
+ const Search = React.forwardRef<HTMLInputElement, SearchProps>(SearchBase);
83
82
 
84
83
  Search.displayName = 'Search';
85
84
 
@@ -1,3 +1,4 @@
1
+ import * as React from 'react';
1
2
  import { Loader, LoaderCircle, type LucideProps } from 'lucide-react';
2
3
  import { cn } from './utils';
3
4
 
@@ -7,7 +8,7 @@ interface SpinnerProps extends LucideProps {
7
8
  layout?: 'absolute' | 'centered' | 'overlay' | 'flow';
8
9
  }
9
10
 
10
- function Spinner({ loading = false, layout = 'flow', type = 'default', ...props }: SpinnerProps) {
11
+ const Spinner: React.FC<SpinnerProps> = ({ loading = false, layout = 'flow', type = 'default', ...props }) => {
11
12
  const LoaderIcon = type === 'circle' ? LoaderCircle : Loader;
12
13
 
13
14
  if (!loading) {
@@ -35,7 +36,7 @@ function Spinner({ loading = false, layout = 'flow', type = 'default', ...props
35
36
  default:
36
37
  return spinnerElement;
37
38
  }
38
- }
39
+ };
39
40
 
40
41
  Spinner.displayName = 'Spinner';
41
42
 
@@ -1,3 +1,4 @@
1
+ import * as React from 'react';
1
2
  import { Phone, PhoneIncoming, PhoneMissed, PhoneOutgoing, type LucideProps } from 'lucide-react';
2
3
  import { cn } from './utils';
3
4
 
@@ -1,5 +1,4 @@
1
- import type React from 'react';
2
- import { forwardRef } from 'react';
1
+ import * as React from 'react';
3
2
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
4
3
  import { cn } from './utils';
5
4
 
@@ -78,7 +77,7 @@ function StatusIndicatorBase(
78
77
  );
79
78
  }
80
79
 
81
- const StatusIndicator = forwardRef(StatusIndicatorBase);
80
+ const StatusIndicator = React.forwardRef(StatusIndicatorBase);
82
81
 
83
82
  StatusIndicator.displayName = 'StatusIndicator';
84
83
 
@@ -1,3 +1,4 @@
1
+ import * as React from 'react';
1
2
  import { Ban, Check, CheckCheck, Clock, type LucideProps } from 'lucide-react';
2
3
  import { cn } from './utils';
3
4
 
@@ -1,5 +1,4 @@
1
- import type React from 'react';
2
- import { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
1
+ import * as React from 'react';
3
2
  import { Maximize, Minimize, PictureInPicture2, type LucideProps } from 'lucide-react';
4
3
  import { cn, getRandomString } from './utils';
5
4
 
@@ -12,15 +11,15 @@ function StreamViewBase(
12
11
  { id, stream, mirror, className, muted, ...props }: StreamViewProps,
13
12
  ref: React.ForwardedRef<HTMLVideoElement>
14
13
  ) {
15
- const innerRef = useRef<HTMLVideoElement>(null);
16
- const elementId = useMemo(() => id ?? `stream-${getRandomString()}`, [id]);
14
+ const innerRef = React.useRef<HTMLVideoElement>(null);
15
+ const elementId = React.useMemo(() => id ?? `stream-${getRandomString()}`, [id]);
17
16
  const isMuted = typeof muted === 'boolean' ? muted : false;
18
17
  const defaultClassName = 'size-full object-contain';
19
18
  const mirrorClassName = mirror ? 'scale-x-[-1]' : '';
20
19
 
21
- useImperativeHandle(ref, () => innerRef.current || ({} as HTMLVideoElement), []);
20
+ React.useImperativeHandle(ref, () => innerRef.current || ({} as HTMLVideoElement), []);
22
21
 
23
- useEffect(() => {
22
+ React.useEffect(() => {
24
23
  if (innerRef.current && stream) {
25
24
  innerRef.current.srcObject = stream;
26
25
 
@@ -53,7 +52,7 @@ function StreamViewBase(
53
52
  );
54
53
  }
55
54
 
56
- const StreamView = forwardRef<HTMLVideoElement, StreamViewProps>(StreamViewBase);
55
+ const StreamView = React.forwardRef<HTMLVideoElement, StreamViewProps>(StreamViewBase);
57
56
 
58
57
  StreamView.displayName = 'StreamView';
59
58
 
@@ -64,7 +63,7 @@ function LocalStreamViewBase({ muted, mirror, ...props }: StreamViewProps, ref:
64
63
  return <StreamView ref={ref} muted={isMuted} mirror={isMirror} {...props} />;
65
64
  }
66
65
 
67
- const LocalStreamView = forwardRef<HTMLVideoElement, StreamViewProps>(LocalStreamViewBase);
66
+ const LocalStreamView = React.forwardRef<HTMLVideoElement, StreamViewProps>(LocalStreamViewBase);
68
67
 
69
68
  LocalStreamView.displayName = 'LocalStreamView';
70
69
 
@@ -75,7 +74,7 @@ function RemoteStreamViewBase({ muted, mirror, ...props }: StreamViewProps, ref:
75
74
  return <StreamView ref={ref} muted={isMuted} mirror={isMirror} {...props} />;
76
75
  }
77
76
 
78
- const RemoteStreamView = forwardRef<HTMLVideoElement, StreamViewProps>(RemoteStreamViewBase);
77
+ const RemoteStreamView = React.forwardRef<HTMLVideoElement, StreamViewProps>(RemoteStreamViewBase);
79
78
 
80
79
  RemoteStreamView.displayName = 'RemoteStreamView';
81
80
 
@@ -116,10 +115,10 @@ function FullscreenStreamViewBase(
116
115
  }: FullscreenStreamViewProps,
117
116
  ref: React.ForwardedRef<FullscreenStreamViewRef>
118
117
  ) {
119
- const innerRef = useRef<HTMLDivElement>(null);
120
- const [isFullscreen, setIsFullscreen] = useState<boolean>(false);
121
- const [isPictureInPicture, setIsPictureInPicture] = useState<boolean>(false);
122
- const toggleFullscreen = useCallback(async () => {
118
+ const innerRef = React.useRef<HTMLDivElement>(null);
119
+ const [isFullscreen, setIsFullscreen] = React.useState<boolean>(false);
120
+ const [isPictureInPicture, setIsPictureInPicture] = React.useState<boolean>(false);
121
+ const toggleFullscreen = React.useCallback(async () => {
123
122
  const container = innerRef.current;
124
123
 
125
124
  if (!container) return;
@@ -138,13 +137,13 @@ function FullscreenStreamViewBase(
138
137
  console.error('Fullscreen error:', err);
139
138
  }
140
139
  }, []);
141
- const togglePictureInPicture = useCallback(() => {
140
+ const togglePictureInPicture = React.useCallback(() => {
142
141
  if (pipElement) {
143
142
  setIsPictureInPicture((prevState) => !prevState);
144
143
  }
145
144
  }, [pipElement]);
146
145
 
147
- useImperativeHandle(
146
+ React.useImperativeHandle(
148
147
  ref,
149
148
  () => ({
150
149
  ...(innerRef.current || ({} as HTMLDivElement)),
@@ -156,7 +155,7 @@ function FullscreenStreamViewBase(
156
155
  [isFullscreen, isPictureInPicture, toggleFullscreen, togglePictureInPicture]
157
156
  );
158
157
 
159
- useEffect(() => {
158
+ React.useEffect(() => {
160
159
  const onFullscreenChange = () => {
161
160
  setIsFullscreen(!!document.fullscreenElement);
162
161
  setIsPictureInPicture(!!document.fullscreenElement);
@@ -218,7 +217,9 @@ function FullscreenStreamViewBase(
218
217
  );
219
218
  }
220
219
 
221
- const FullscreenStreamView = forwardRef<FullscreenStreamViewRef, FullscreenStreamViewProps>(FullscreenStreamViewBase);
220
+ const FullscreenStreamView = React.forwardRef<FullscreenStreamViewRef, FullscreenStreamViewProps>(
221
+ FullscreenStreamViewBase
222
+ );
222
223
 
223
224
  FullscreenStreamView.displayName = 'FullscreenStreamView';
224
225