@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.
- package/README.md +2 -2
- package/gen/components/alert-dialog.jsx +2 -2
- package/gen/components/attachment.jsx +10 -11
- package/gen/components/avatar.jsx +2 -2
- package/gen/components/badge.jsx +2 -2
- package/gen/components/button.jsx +4 -3
- package/gen/components/chat-bubble.jsx +8 -8
- package/gen/components/chat-input.jsx +10 -10
- package/gen/components/chat-list.jsx +13 -13
- package/gen/components/checkbox.jsx +2 -2
- package/gen/components/dialog-item.jsx +2 -2
- package/gen/components/dialogs-list.jsx +4 -4
- package/gen/components/dismiss-layer.jsx +7 -7
- package/gen/components/file-picker.jsx +4 -4
- package/gen/components/formatted-date.jsx +2 -2
- package/gen/components/input.jsx +2 -2
- package/gen/components/label.jsx +2 -2
- package/gen/components/link-preview.jsx +7 -7
- package/gen/components/linkify-text.jsx +5 -5
- package/gen/components/placeholder-text.jsx +1 -2
- package/gen/components/presence.jsx +1 -0
- package/gen/components/quick-actions.jsx +2 -2
- package/gen/components/search.jsx +3 -3
- package/gen/components/spinner.jsx +3 -2
- package/gen/components/status-call.jsx +1 -0
- package/gen/components/status-indicator.jsx +2 -2
- package/gen/components/status-sent.jsx +1 -0
- package/gen/components/stream-view.jsx +16 -16
- package/package.json +14 -14
- package/src/components/alert-dialog.tsx +2 -3
- package/src/components/attachment.tsx +12 -13
- package/src/components/avatar.tsx +2 -3
- package/src/components/badge.tsx +2 -3
- package/src/components/button.tsx +4 -4
- package/src/components/chat-bubble.tsx +9 -10
- package/src/components/chat-input.tsx +17 -13
- package/src/components/chat-list.tsx +31 -24
- package/src/components/checkbox.tsx +2 -3
- package/src/components/dialog-item.tsx +2 -3
- package/src/components/dialogs-list.tsx +4 -5
- package/src/components/dismiss-layer.tsx +7 -8
- package/src/components/file-picker.tsx +4 -5
- package/src/components/formatted-date.tsx +4 -3
- package/src/components/input.tsx +2 -3
- package/src/components/label.tsx +2 -3
- package/src/components/link-preview.tsx +16 -26
- package/src/components/linkify-text.tsx +5 -6
- package/src/components/placeholder-text.tsx +1 -2
- package/src/components/presence.tsx +1 -1
- package/src/components/quick-actions.tsx +2 -3
- package/src/components/search.tsx +3 -4
- package/src/components/spinner.tsx +3 -2
- package/src/components/status-call.tsx +1 -0
- package/src/components/status-indicator.tsx +2 -3
- package/src/components/status-sent.tsx +1 -0
- package/src/components/stream-view.tsx +18 -17
- package/src/components/connectycube-ui/attachment.tsx +0 -269
- package/src/components/connectycube-ui/avatar.jsx +0 -54
- package/src/components/connectycube-ui/avatar.tsx +0 -77
- package/src/components/connectycube-ui/badge.jsx +0 -45
- package/src/components/connectycube-ui/badge.tsx +0 -42
- package/src/components/connectycube-ui/chat-input.tsx +0 -174
- package/src/components/connectycube-ui/chat-message.tsx +0 -138
- package/src/components/connectycube-ui/dialog-item.jsx +0 -149
- package/src/components/connectycube-ui/dialog-item.tsx +0 -188
- package/src/components/connectycube-ui/file-picker.jsx +0 -200
- package/src/components/connectycube-ui/file-picker.tsx +0 -231
- package/src/components/connectycube-ui/formatted-date.jsx +0 -57
- package/src/components/connectycube-ui/formatted-date.tsx +0 -57
- package/src/components/connectycube-ui/label.jsx +0 -22
- package/src/components/connectycube-ui/label.tsx +0 -23
- package/src/components/connectycube-ui/link-preview.tsx +0 -149
- package/src/components/connectycube-ui/linkify-text.tsx +0 -40
- package/src/components/connectycube-ui/presence.jsx +0 -81
- package/src/components/connectycube-ui/presence.tsx +0 -96
- package/src/components/connectycube-ui/status-sent.jsx +0 -21
- package/src/components/connectycube-ui/status-sent.tsx +0 -25
- package/src/components/connectycube-ui/utils.js +0 -10
- package/src/components/connectycube-ui/utils.ts +0 -10
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as React from 'react';
|
|
2
2
|
import { cn } from './utils';
|
|
3
3
|
import { Input } from './input';
|
|
4
4
|
import { Search as SearchIcon, X as CloseIcon } from 'lucide-react';
|
|
@@ -16,7 +16,7 @@ function SearchBase(
|
|
|
16
16
|
},
|
|
17
17
|
ref
|
|
18
18
|
) {
|
|
19
|
-
const [value, setValue] = useState('');
|
|
19
|
+
const [value, setValue] = React.useState('');
|
|
20
20
|
const handleOnSearch = (e) => {
|
|
21
21
|
const keyword = e.target.value;
|
|
22
22
|
|
|
@@ -68,7 +68,7 @@ function SearchBase(
|
|
|
68
68
|
);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
const Search = forwardRef(SearchBase);
|
|
71
|
+
const Search = React.forwardRef(SearchBase);
|
|
72
72
|
|
|
73
73
|
Search.displayName = 'Search';
|
|
74
74
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
1
2
|
import { Loader, LoaderCircle } from 'lucide-react';
|
|
2
3
|
import { cn } from './utils';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
const Spinner = ({ loading = false, layout = 'flow', type = 'default', ...props }) => {
|
|
5
6
|
const LoaderIcon = type === 'circle' ? LoaderCircle : Loader;
|
|
6
7
|
|
|
7
8
|
if (!loading) {
|
|
@@ -29,7 +30,7 @@ function Spinner({ loading = false, layout = 'flow', type = 'default', ...props
|
|
|
29
30
|
default:
|
|
30
31
|
return spinnerElement;
|
|
31
32
|
}
|
|
32
|
-
}
|
|
33
|
+
};
|
|
33
34
|
|
|
34
35
|
Spinner.displayName = 'Spinner';
|
|
35
36
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as React from 'react';
|
|
2
2
|
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
3
3
|
import { cn } from './utils';
|
|
4
4
|
|
|
@@ -62,7 +62,7 @@ function StatusIndicatorBase(
|
|
|
62
62
|
);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
const StatusIndicator = forwardRef(StatusIndicatorBase);
|
|
65
|
+
const StatusIndicator = React.forwardRef(StatusIndicatorBase);
|
|
66
66
|
|
|
67
67
|
StatusIndicator.displayName = 'StatusIndicator';
|
|
68
68
|
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as React from 'react';
|
|
2
2
|
import { Maximize, Minimize, PictureInPicture2 } from 'lucide-react';
|
|
3
3
|
import { cn, getRandomString } from './utils';
|
|
4
4
|
|
|
5
5
|
function StreamViewBase({ id, stream, mirror, className, muted, ...props }, ref) {
|
|
6
|
-
const innerRef = useRef(null);
|
|
7
|
-
const elementId = useMemo(() => id ?? `stream-${getRandomString()}`, [id]);
|
|
6
|
+
const innerRef = React.useRef(null);
|
|
7
|
+
const elementId = React.useMemo(() => id ?? `stream-${getRandomString()}`, [id]);
|
|
8
8
|
const isMuted = typeof muted === 'boolean' ? muted : false;
|
|
9
9
|
const defaultClassName = 'size-full object-contain';
|
|
10
10
|
const mirrorClassName = mirror ? 'scale-x-[-1]' : '';
|
|
11
11
|
|
|
12
|
-
useImperativeHandle(ref, () => innerRef.current || {}, []);
|
|
12
|
+
React.useImperativeHandle(ref, () => innerRef.current || {}, []);
|
|
13
13
|
|
|
14
|
-
useEffect(() => {
|
|
14
|
+
React.useEffect(() => {
|
|
15
15
|
if (innerRef.current && stream) {
|
|
16
16
|
innerRef.current.srcObject = stream;
|
|
17
17
|
|
|
@@ -44,7 +44,7 @@ function StreamViewBase({ id, stream, mirror, className, muted, ...props }, ref)
|
|
|
44
44
|
);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
const StreamView = forwardRef(StreamViewBase);
|
|
47
|
+
const StreamView = React.forwardRef(StreamViewBase);
|
|
48
48
|
|
|
49
49
|
StreamView.displayName = 'StreamView';
|
|
50
50
|
|
|
@@ -55,7 +55,7 @@ function LocalStreamViewBase({ muted, mirror, ...props }, ref) {
|
|
|
55
55
|
return <StreamView ref={ref} muted={isMuted} mirror={isMirror} {...props} />;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
const LocalStreamView = forwardRef(LocalStreamViewBase);
|
|
58
|
+
const LocalStreamView = React.forwardRef(LocalStreamViewBase);
|
|
59
59
|
|
|
60
60
|
LocalStreamView.displayName = 'LocalStreamView';
|
|
61
61
|
|
|
@@ -66,7 +66,7 @@ function RemoteStreamViewBase({ muted, mirror, ...props }, ref) {
|
|
|
66
66
|
return <StreamView ref={ref} muted={isMuted} mirror={isMirror} {...props} />;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
const RemoteStreamView = forwardRef(RemoteStreamViewBase);
|
|
69
|
+
const RemoteStreamView = React.forwardRef(RemoteStreamViewBase);
|
|
70
70
|
|
|
71
71
|
RemoteStreamView.displayName = 'RemoteStreamView';
|
|
72
72
|
|
|
@@ -86,10 +86,10 @@ function FullscreenStreamViewBase(
|
|
|
86
86
|
},
|
|
87
87
|
ref
|
|
88
88
|
) {
|
|
89
|
-
const innerRef = useRef(null);
|
|
90
|
-
const [isFullscreen, setIsFullscreen] = useState(false);
|
|
91
|
-
const [isPictureInPicture, setIsPictureInPicture] = useState(false);
|
|
92
|
-
const toggleFullscreen = useCallback(async () => {
|
|
89
|
+
const innerRef = React.useRef(null);
|
|
90
|
+
const [isFullscreen, setIsFullscreen] = React.useState(false);
|
|
91
|
+
const [isPictureInPicture, setIsPictureInPicture] = React.useState(false);
|
|
92
|
+
const toggleFullscreen = React.useCallback(async () => {
|
|
93
93
|
const container = innerRef.current;
|
|
94
94
|
|
|
95
95
|
if (!container) return;
|
|
@@ -108,13 +108,13 @@ function FullscreenStreamViewBase(
|
|
|
108
108
|
console.error('Fullscreen error:', err);
|
|
109
109
|
}
|
|
110
110
|
}, []);
|
|
111
|
-
const togglePictureInPicture = useCallback(() => {
|
|
111
|
+
const togglePictureInPicture = React.useCallback(() => {
|
|
112
112
|
if (pipElement) {
|
|
113
113
|
setIsPictureInPicture((prevState) => !prevState);
|
|
114
114
|
}
|
|
115
115
|
}, [pipElement]);
|
|
116
116
|
|
|
117
|
-
useImperativeHandle(
|
|
117
|
+
React.useImperativeHandle(
|
|
118
118
|
ref,
|
|
119
119
|
() => ({
|
|
120
120
|
...(innerRef.current || {}),
|
|
@@ -126,7 +126,7 @@ function FullscreenStreamViewBase(
|
|
|
126
126
|
[isFullscreen, isPictureInPicture, toggleFullscreen, togglePictureInPicture]
|
|
127
127
|
);
|
|
128
128
|
|
|
129
|
-
useEffect(() => {
|
|
129
|
+
React.useEffect(() => {
|
|
130
130
|
const onFullscreenChange = () => {
|
|
131
131
|
setIsFullscreen(!!document.fullscreenElement);
|
|
132
132
|
setIsPictureInPicture(!!document.fullscreenElement);
|
|
@@ -188,7 +188,7 @@ function FullscreenStreamViewBase(
|
|
|
188
188
|
);
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
const FullscreenStreamView = forwardRef(FullscreenStreamViewBase);
|
|
191
|
+
const FullscreenStreamView = React.forwardRef(FullscreenStreamViewBase);
|
|
192
192
|
|
|
193
193
|
FullscreenStreamView.displayName = 'FullscreenStreamView';
|
|
194
194
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@connectycube/react-ui-kit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Simple React UI Kit generator with TSX/JSX",
|
|
5
5
|
"homepage": "https://github.com/ConnectyCube/react-ui-kit#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -72,42 +72,42 @@
|
|
|
72
72
|
"class-variance-authority": "^0.7.1",
|
|
73
73
|
"clsx": "^2.1.1",
|
|
74
74
|
"date-fns": "^4.1.0",
|
|
75
|
+
"execa": "^9.6.1",
|
|
76
|
+
"fast-glob": "^3.3.3",
|
|
77
|
+
"fs-extra": "^11.3.3",
|
|
75
78
|
"linkify-react": "^4.3.2",
|
|
76
79
|
"lucide-react": "^0.562.0",
|
|
80
|
+
"prettier": "^3.8.1",
|
|
81
|
+
"prompts": "^2.4.2",
|
|
77
82
|
"react-intersection-observer": "^10.0.0",
|
|
78
83
|
"react-textarea-autosize": "^8.5.9",
|
|
79
84
|
"tailwind-merge": "^3.4.0",
|
|
80
|
-
"virtua": "^0.48.
|
|
85
|
+
"virtua": "^0.48.3"
|
|
81
86
|
},
|
|
82
87
|
"peerDependencies": {
|
|
83
88
|
"react": ">=18",
|
|
84
89
|
"react-dom": ">=18"
|
|
85
90
|
},
|
|
86
91
|
"devDependencies": {
|
|
87
|
-
"@babel/core": "^7.28.
|
|
92
|
+
"@babel/core": "^7.28.6",
|
|
88
93
|
"@babel/preset-typescript": "^7.28.5",
|
|
89
94
|
"@eslint/js": "^9.39.2",
|
|
90
95
|
"@rollup/plugin-commonjs": "^29.0.0",
|
|
91
96
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
92
97
|
"@rollup/plugin-terser": "^0.4.4",
|
|
93
98
|
"@rollup/plugin-typescript": "^12.3.0",
|
|
94
|
-
"@stylistic/eslint-plugin": "^5.
|
|
95
|
-
"@types/node": "^25.0.
|
|
96
|
-
"@types/react": "^19.2.
|
|
99
|
+
"@stylistic/eslint-plugin": "^5.7.0",
|
|
100
|
+
"@types/node": "^25.0.8",
|
|
101
|
+
"@types/react": "^19.2.8",
|
|
97
102
|
"eslint": "^9.39.2",
|
|
98
103
|
"eslint-plugin-react-hooks": "^7.0.1",
|
|
99
104
|
"eslint-plugin-react-refresh": "^0.4.26",
|
|
100
|
-
"
|
|
101
|
-
"
|
|
102
|
-
"fs-extra": "^11.3.3",
|
|
103
|
-
"globals": "^16.5.0",
|
|
104
|
-
"prettier": "^3.7.4",
|
|
105
|
-
"prompts": "^2.4.2",
|
|
106
|
-
"rollup": "^4.54.0",
|
|
105
|
+
"globals": "^17.0.0",
|
|
106
|
+
"rollup": "^4.55.1",
|
|
107
107
|
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
108
108
|
"tslib": "^2.8.1",
|
|
109
109
|
"typescript": "^5.9.3",
|
|
110
|
-
"typescript-eslint": "^8.
|
|
110
|
+
"typescript-eslint": "^8.53.0"
|
|
111
111
|
},
|
|
112
112
|
"engines": {
|
|
113
113
|
"node": ">=18"
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { forwardRef } from 'react';
|
|
1
|
+
import * as React from 'react';
|
|
3
2
|
import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog';
|
|
4
3
|
import { Button, type ButtonProps } from './button';
|
|
5
4
|
import { cn } from './utils';
|
|
@@ -111,7 +110,7 @@ function AlertDialogBase(
|
|
|
111
110
|
);
|
|
112
111
|
}
|
|
113
112
|
|
|
114
|
-
const AlertDialog = forwardRef<HTMLDivElement, AlertDialogProps>(AlertDialogBase);
|
|
113
|
+
const AlertDialog = React.forwardRef<HTMLDivElement, AlertDialogProps>(AlertDialogBase);
|
|
115
114
|
|
|
116
115
|
AlertDialog.displayName = 'AlertDialog';
|
|
117
116
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { forwardRef, memo, useImperativeHandle, useRef, useState } from 'react';
|
|
1
|
+
import * as React from 'react';
|
|
3
2
|
import { File, FileXCorner, type LucideProps } from 'lucide-react';
|
|
4
3
|
import { Spinner } from './spinner';
|
|
5
4
|
import { cn, getRandomString } from './utils';
|
|
@@ -14,7 +13,8 @@ interface AttachmentProps {
|
|
|
14
13
|
containerProps?: React.ComponentProps<'div'>;
|
|
15
14
|
}
|
|
16
15
|
|
|
17
|
-
interface AttachmentLinkProps
|
|
16
|
+
interface AttachmentLinkProps
|
|
17
|
+
extends React.ComponentProps<'a'>, Omit<AttachmentProps, 'url' & 'containerProps' & 'mimeType'> {}
|
|
18
18
|
|
|
19
19
|
interface AttachmentImageProps
|
|
20
20
|
extends React.ComponentProps<'img'>, Omit<AttachmentProps, 'containerProps' & 'mimeType'> {}
|
|
@@ -36,7 +36,7 @@ interface AttachmentFailedProps extends LucideProps, Omit<AttachmentProps, 'link
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
function AttachmentLinkBase(
|
|
39
|
-
{
|
|
39
|
+
{ pending = false, children, ...props }: AttachmentLinkProps,
|
|
40
40
|
ref: React.ForwardedRef<HTMLAnchorElement>
|
|
41
41
|
) {
|
|
42
42
|
return (
|
|
@@ -45,7 +45,6 @@ function AttachmentLinkBase(
|
|
|
45
45
|
target="_blank"
|
|
46
46
|
rel="noopener noreferrer"
|
|
47
47
|
{...props}
|
|
48
|
-
href={url}
|
|
49
48
|
className={cn(
|
|
50
49
|
'group relative min-h-8 min-w-8 w-full flex items-center justify-center rounded-md overflow-hidden bg-ring/10 hover:bg-ring/20 transition-color duration-300 ease-out cursor-pointer',
|
|
51
50
|
props?.className
|
|
@@ -57,7 +56,7 @@ function AttachmentLinkBase(
|
|
|
57
56
|
);
|
|
58
57
|
}
|
|
59
58
|
|
|
60
|
-
const AttachmentLink = forwardRef<HTMLAnchorElement, AttachmentLinkProps>(AttachmentLinkBase);
|
|
59
|
+
const AttachmentLink = React.forwardRef<HTMLAnchorElement, AttachmentLinkProps>(AttachmentLinkBase);
|
|
61
60
|
|
|
62
61
|
AttachmentLink.displayName = 'AttachmentLink';
|
|
63
62
|
|
|
@@ -78,7 +77,7 @@ function AttachmentAudioBase(
|
|
|
78
77
|
);
|
|
79
78
|
}
|
|
80
79
|
|
|
81
|
-
const AttachmentAudio = forwardRef<HTMLAudioElement, AttachmentAudioProps>(AttachmentAudioBase);
|
|
80
|
+
const AttachmentAudio = React.forwardRef<HTMLAudioElement, AttachmentAudioProps>(AttachmentAudioBase);
|
|
82
81
|
|
|
83
82
|
function AttachmentVideoBase(
|
|
84
83
|
{ uid, url, maxSize = 360, pending = false, onReady = () => {}, containerProps, ...props }: AttachmentVideoProps,
|
|
@@ -86,8 +85,8 @@ function AttachmentVideoBase(
|
|
|
86
85
|
) {
|
|
87
86
|
const videoId = `attachment_video_${uid || getRandomString()}`;
|
|
88
87
|
const videoMaxSize = `${maxSize}px`;
|
|
89
|
-
const playerRef = useRef<HTMLVideoElement>(null);
|
|
90
|
-
const [style, setStyle] = useState<React.CSSProperties>({
|
|
88
|
+
const playerRef = React.useRef<HTMLVideoElement>(null);
|
|
89
|
+
const [style, setStyle] = React.useState<React.CSSProperties>({
|
|
91
90
|
maxHeight: videoMaxSize,
|
|
92
91
|
maxWidth: videoMaxSize,
|
|
93
92
|
});
|
|
@@ -106,7 +105,7 @@ function AttachmentVideoBase(
|
|
|
106
105
|
}
|
|
107
106
|
};
|
|
108
107
|
|
|
109
|
-
useImperativeHandle(ref, () => playerRef.current || ({} as HTMLVideoElement), []);
|
|
108
|
+
React.useImperativeHandle(ref, () => playerRef.current || ({} as HTMLVideoElement), []);
|
|
110
109
|
|
|
111
110
|
return (
|
|
112
111
|
<div
|
|
@@ -129,7 +128,7 @@ function AttachmentVideoBase(
|
|
|
129
128
|
);
|
|
130
129
|
}
|
|
131
130
|
|
|
132
|
-
const AttachmentVideo = forwardRef<HTMLVideoElement, AttachmentVideoProps>(AttachmentVideoBase);
|
|
131
|
+
const AttachmentVideo = React.forwardRef<HTMLVideoElement, AttachmentVideoProps>(AttachmentVideoBase);
|
|
133
132
|
|
|
134
133
|
AttachmentVideo.displayName = 'AttachmentVideo';
|
|
135
134
|
|
|
@@ -161,7 +160,7 @@ function AttachmentImageBase(
|
|
|
161
160
|
);
|
|
162
161
|
}
|
|
163
162
|
|
|
164
|
-
const AttachmentImage = forwardRef<HTMLImageElement, AttachmentImageProps>(AttachmentImageBase);
|
|
163
|
+
const AttachmentImage = React.forwardRef<HTMLImageElement, AttachmentImageProps>(AttachmentImageBase);
|
|
165
164
|
|
|
166
165
|
AttachmentImage.displayName = 'AttachmentImage';
|
|
167
166
|
|
|
@@ -249,7 +248,7 @@ function AttachmentBase({
|
|
|
249
248
|
}
|
|
250
249
|
}
|
|
251
250
|
|
|
252
|
-
const Attachment = memo(AttachmentBase);
|
|
251
|
+
const Attachment = React.memo(AttachmentBase);
|
|
253
252
|
|
|
254
253
|
Attachment.displayName = 'Attachment';
|
|
255
254
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { memo, forwardRef } from 'react';
|
|
1
|
+
import * as React from 'react';
|
|
3
2
|
import * as AvatarPrimitive from '@radix-ui/react-avatar';
|
|
4
3
|
import { PresenceBadge, type PresenceStatus, type PresenceBadgeProps } from './presence';
|
|
5
4
|
import { cn } from './utils';
|
|
@@ -72,7 +71,7 @@ function AvatarBase(
|
|
|
72
71
|
);
|
|
73
72
|
}
|
|
74
73
|
|
|
75
|
-
const Avatar = memo(forwardRef<HTMLDivElement, AvatarProps>(AvatarBase));
|
|
74
|
+
const Avatar = React.memo(React.forwardRef<HTMLDivElement, AvatarProps>(AvatarBase));
|
|
76
75
|
|
|
77
76
|
Avatar.displayName = 'Avatar';
|
|
78
77
|
|
package/src/components/badge.tsx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { forwardRef } from 'react';
|
|
1
|
+
import * as React from 'react';
|
|
3
2
|
import { Slot } from '@radix-ui/react-slot';
|
|
4
3
|
import { cva, type VariantProps } from 'class-variance-authority';
|
|
5
4
|
import { cn } from './utils';
|
|
@@ -35,7 +34,7 @@ function BadgeBase(
|
|
|
35
34
|
return <Comp ref={ref} {...props} className={cn(badgeVariants({ variant }), className)} />;
|
|
36
35
|
}
|
|
37
36
|
|
|
38
|
-
const Badge = forwardRef<HTMLElement, BadgeProps>(BadgeBase);
|
|
37
|
+
const Badge = React.forwardRef<HTMLElement, BadgeProps>(BadgeBase);
|
|
39
38
|
|
|
40
39
|
Badge.displayName = 'Badge';
|
|
41
40
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { forwardRef } from 'react';
|
|
1
|
+
import * as React from 'react';
|
|
3
2
|
import { Slot } from '@radix-ui/react-slot';
|
|
4
3
|
import { cva, type VariantProps } from 'class-variance-authority';
|
|
5
4
|
import { cn } from './utils';
|
|
@@ -51,8 +50,9 @@ function ButtonBase(
|
|
|
51
50
|
);
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
const Button = forwardRef<HTMLButtonElement, ButtonProps>(ButtonBase);
|
|
53
|
+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(ButtonBase);
|
|
55
54
|
|
|
56
55
|
Button.displayName = 'Button';
|
|
57
56
|
|
|
58
|
-
|
|
57
|
+
// eslint-disable-next-line react-refresh/only-export-components
|
|
58
|
+
export { Button, buttonVariants, type ButtonProps };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useRef } from 'react';
|
|
1
|
+
import * as React from 'react';
|
|
3
2
|
import { useInView } from 'react-intersection-observer';
|
|
4
3
|
import { Avatar, type AvatarProps } from './avatar';
|
|
5
4
|
import { FormattedDate, type FormattedDateProps } from './formatted-date';
|
|
@@ -38,8 +37,8 @@ function ChatBubbleBase(
|
|
|
38
37
|
ref: React.ForwardedRef<HTMLDivElement>
|
|
39
38
|
) {
|
|
40
39
|
const [setRef, inView] = useInView();
|
|
41
|
-
const messageRef = useRef<HTMLDivElement>(null);
|
|
42
|
-
const setRefs = useCallback(
|
|
40
|
+
const messageRef = React.useRef<HTMLDivElement>(null);
|
|
41
|
+
const setRefs = React.useCallback(
|
|
43
42
|
(node: HTMLDivElement) => {
|
|
44
43
|
messageRef.current = node;
|
|
45
44
|
setRef(node);
|
|
@@ -47,13 +46,13 @@ function ChatBubbleBase(
|
|
|
47
46
|
[setRef]
|
|
48
47
|
);
|
|
49
48
|
|
|
50
|
-
useEffect(() => {
|
|
49
|
+
React.useEffect(() => {
|
|
51
50
|
if (inView) {
|
|
52
51
|
onView();
|
|
53
52
|
}
|
|
54
53
|
}, [inView, onView]);
|
|
55
54
|
|
|
56
|
-
useImperativeHandle(ref, () => messageRef.current || ({} as HTMLDivElement), []);
|
|
55
|
+
React.useImperativeHandle(ref, () => messageRef.current || ({} as HTMLDivElement), []);
|
|
57
56
|
|
|
58
57
|
return (
|
|
59
58
|
<div ref={setRefs} {...props} className={cn('mt-2', isLast && 'mb-2', inView && 'view', props?.className)}>
|
|
@@ -62,7 +61,7 @@ function ChatBubbleBase(
|
|
|
62
61
|
);
|
|
63
62
|
}
|
|
64
63
|
|
|
65
|
-
const ChatBubble = forwardRef<HTMLDivElement, ChatBubbleProps>(ChatBubbleBase);
|
|
64
|
+
const ChatBubble = React.forwardRef<HTMLDivElement, ChatBubbleProps>(ChatBubbleBase);
|
|
66
65
|
|
|
67
66
|
function ChatBubbleMessageBase(
|
|
68
67
|
{
|
|
@@ -110,7 +109,7 @@ function ChatBubbleMessageBase(
|
|
|
110
109
|
|
|
111
110
|
<div
|
|
112
111
|
className={cn(
|
|
113
|
-
'relative flex flex-col min-w-
|
|
112
|
+
'relative flex flex-col min-w-50 max-w-120 rounded-xl px-2 pt-2 pb-6 shadow-sm',
|
|
114
113
|
fromMe ? 'bg-gray-200' : 'bg-blue-200',
|
|
115
114
|
hasAvatarMargin && 'ml-9',
|
|
116
115
|
bubbleProps?.className
|
|
@@ -138,7 +137,7 @@ function ChatBubbleMessageBase(
|
|
|
138
137
|
);
|
|
139
138
|
}
|
|
140
139
|
|
|
141
|
-
const ChatBubbleMessage = memo(forwardRef<HTMLDivElement, ChatBubbleMessageProps>(ChatBubbleMessageBase));
|
|
140
|
+
const ChatBubbleMessage = React.memo(React.forwardRef<HTMLDivElement, ChatBubbleMessageProps>(ChatBubbleMessageBase));
|
|
142
141
|
|
|
143
142
|
ChatBubbleMessage.displayName = 'ChatBubbleMessage';
|
|
144
143
|
|
|
@@ -169,7 +168,7 @@ function ChatBubbleInfoBase(
|
|
|
169
168
|
);
|
|
170
169
|
}
|
|
171
170
|
|
|
172
|
-
const ChatBubbleInfo = memo(forwardRef<HTMLDivElement, ChatBubbleInfoProps>(ChatBubbleInfoBase));
|
|
171
|
+
const ChatBubbleInfo = React.memo(React.forwardRef<HTMLDivElement, ChatBubbleInfoProps>(ChatBubbleInfoBase));
|
|
173
172
|
|
|
174
173
|
ChatBubbleInfo.displayName = 'ChatBubbleInfo';
|
|
175
174
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { ChangeEvent, forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
|
|
1
|
+
import * as React from 'react';
|
|
3
2
|
import TextareaAutosize, { type TextareaAutosizeProps, type TextareaHeightChangeMeta } from 'react-textarea-autosize';
|
|
4
3
|
import { SendHorizontal, type LucideProps } from 'lucide-react';
|
|
5
4
|
import { Label, type LabelProps } from './label';
|
|
@@ -48,7 +47,7 @@ function ChatInputSendBase(
|
|
|
48
47
|
);
|
|
49
48
|
}
|
|
50
49
|
|
|
51
|
-
const ChatInputSend = forwardRef<HTMLLabelElement, ChatInputSendProps>(ChatInputSendBase);
|
|
50
|
+
const ChatInputSend = React.forwardRef<HTMLLabelElement, ChatInputSendProps>(ChatInputSendBase);
|
|
52
51
|
|
|
53
52
|
ChatInputSend.displayName = 'ChatInputSend';
|
|
54
53
|
|
|
@@ -68,11 +67,11 @@ function ChatInputBase(
|
|
|
68
67
|
}: ChatInputProps,
|
|
69
68
|
ref: React.ForwardedRef<HTMLTextAreaElement>
|
|
70
69
|
) {
|
|
71
|
-
const [value, setValue] = useState<string>();
|
|
72
|
-
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
|
73
|
-
const textareaHeightRef = useRef<number>(0);
|
|
74
|
-
const typingRef = useRef<boolean>(false);
|
|
75
|
-
const typingTimeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
|
|
70
|
+
const [value, setValue] = React.useState<string>();
|
|
71
|
+
const textareaRef = React.useRef<HTMLTextAreaElement>(null);
|
|
72
|
+
const textareaHeightRef = React.useRef<number>(0);
|
|
73
|
+
const typingRef = React.useRef<boolean>(false);
|
|
74
|
+
const typingTimeoutRef = React.useRef<NodeJS.Timeout | undefined>(undefined);
|
|
76
75
|
const handleStopTyping = () => {
|
|
77
76
|
typingRef.current = false;
|
|
78
77
|
onTyping(false);
|
|
@@ -82,7 +81,9 @@ function ChatInputBase(
|
|
|
82
81
|
typingTimeoutRef.current = undefined;
|
|
83
82
|
}
|
|
84
83
|
};
|
|
85
|
-
const handleOnChange = (event: ChangeEvent<HTMLTextAreaElement>) => {
|
|
84
|
+
const handleOnChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
85
|
+
props.onChange?.(event);
|
|
86
|
+
|
|
86
87
|
const { data } = event.nativeEvent as InputEvent;
|
|
87
88
|
|
|
88
89
|
setValue(event.target.value);
|
|
@@ -105,6 +106,8 @@ function ChatInputBase(
|
|
|
105
106
|
}
|
|
106
107
|
};
|
|
107
108
|
const handleOnHeightChange = (height: number, meta: TextareaHeightChangeMeta) => {
|
|
109
|
+
props.onHeightChange?.(height, meta);
|
|
110
|
+
|
|
108
111
|
if (!height && !meta) return;
|
|
109
112
|
|
|
110
113
|
if (height !== textareaHeightRef.current) {
|
|
@@ -116,14 +119,15 @@ function ChatInputBase(
|
|
|
116
119
|
textareaHeightRef.current = height;
|
|
117
120
|
};
|
|
118
121
|
const handleOnKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
|
122
|
+
props.onKeyDown?.(event);
|
|
123
|
+
|
|
119
124
|
if (event.key === 'Enter' && event.shiftKey === false) {
|
|
120
125
|
event.preventDefault();
|
|
121
|
-
props.onKeyDown?.(event);
|
|
122
126
|
handleOnSend();
|
|
123
127
|
}
|
|
124
128
|
};
|
|
125
129
|
|
|
126
|
-
useEffect(() => {
|
|
130
|
+
React.useEffect(() => {
|
|
127
131
|
const textarea = textareaRef.current;
|
|
128
132
|
|
|
129
133
|
handleStopTyping();
|
|
@@ -135,7 +139,7 @@ function ChatInputBase(
|
|
|
135
139
|
};
|
|
136
140
|
}, [props.key]);
|
|
137
141
|
|
|
138
|
-
useImperativeHandle(ref, () => textareaRef.current || ({} as HTMLTextAreaElement), []);
|
|
142
|
+
React.useImperativeHandle(ref, () => textareaRef.current || ({} as HTMLTextAreaElement), []);
|
|
139
143
|
|
|
140
144
|
return (
|
|
141
145
|
<div {...containerProps} className={cn('flex items-end gap-2', containerProps?.className)}>
|
|
@@ -165,7 +169,7 @@ function ChatInputBase(
|
|
|
165
169
|
);
|
|
166
170
|
}
|
|
167
171
|
|
|
168
|
-
const ChatInput = forwardRef<HTMLTextAreaElement, ChatInputProps>(ChatInputBase);
|
|
172
|
+
const ChatInput = React.forwardRef<HTMLTextAreaElement, ChatInputProps>(ChatInputBase);
|
|
169
173
|
|
|
170
174
|
ChatInput.displayName = 'ChatInput';
|
|
171
175
|
|