@rencar-dev/feature-modules-public 0.0.7

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.
@@ -0,0 +1,231 @@
1
+ import { Socket } from 'socket.io-client';
2
+
3
+ /**
4
+ * Presence User Type
5
+ */
6
+ type PresenceUser = {
7
+ userId: string;
8
+ name: string;
9
+ [key: string]: unknown;
10
+ };
11
+ /**
12
+ * Socket configuration
13
+ */
14
+ type PresenceConfig = {
15
+ url: string;
16
+ transports?: ("websocket" | "polling")[];
17
+ };
18
+ /**
19
+ * usePresence hook options
20
+ */
21
+ type UsePresenceOptions = {
22
+ /** Room identifier to join */
23
+ roomId: string;
24
+ /** Current user info to broadcast */
25
+ currentUser: PresenceUser;
26
+ /** Enable/disable the hook (default: true) */
27
+ enabled?: boolean;
28
+ /** Heartbeat interval in ms (default: 10 minutes) */
29
+ heartbeatInterval?: number;
30
+ };
31
+ /**
32
+ * usePresenceWatch hook options
33
+ */
34
+ type UsePresenceWatchOptions = {
35
+ /** Room IDs to watch */
36
+ roomIds: string[];
37
+ /** Enable/disable the hook (default: true) */
38
+ enabled?: boolean;
39
+ };
40
+ /**
41
+ * usePresenceAvatarsState hook options
42
+ */
43
+ type UsePresenceAvatarsStateOptions = {
44
+ /** List of presence users */
45
+ users: PresenceUser[];
46
+ /** Maximum visible avatars (default: 3) */
47
+ maxVisible?: number;
48
+ };
49
+ /**
50
+ * usePresenceAvatarsState return type
51
+ */
52
+ type UsePresenceAvatarsStateReturn = {
53
+ visibleUsers: PresenceUser[];
54
+ moreCount: number;
55
+ hoveredUser: PresenceUser | null;
56
+ hoveredIndex: number | null;
57
+ setHoveredIndex: (index: number | null) => void;
58
+ getInitial: (user: PresenceUser) => string;
59
+ getZIndex: (index: number, isHovered: boolean) => number;
60
+ };
61
+ /**
62
+ * usePresenceFloatingState hook options
63
+ */
64
+ type UsePresenceFloatingStateOptions = {
65
+ /** List of presence users */
66
+ users: PresenceUser[];
67
+ /** Maximum visible avatars (default: 8) */
68
+ maxVisible?: number;
69
+ /** Initial position */
70
+ initialPosition?: {
71
+ top: number;
72
+ };
73
+ };
74
+ /**
75
+ * usePresenceFloatingState return type
76
+ */
77
+ type UsePresenceFloatingStateReturn = {
78
+ containerRef: React.RefObject<HTMLDivElement | null>;
79
+ position: {
80
+ top: number;
81
+ left: number;
82
+ };
83
+ isDragging: boolean;
84
+ hasDragged: boolean;
85
+ inlineStyle: React.CSSProperties;
86
+ visibleUsers: PresenceUser[];
87
+ moreCount: number;
88
+ hoveredUser: PresenceUser | null;
89
+ tooltipTop: number;
90
+ onMouseDownHeader: (e: React.MouseEvent) => void;
91
+ onTouchStartHeader: (e: React.TouchEvent) => void;
92
+ onAvatarEnter: (e: React.MouseEvent, user: PresenceUser) => void;
93
+ onAvatarLeave: () => void;
94
+ };
95
+
96
+ /**
97
+ * Initialize the presence socket with configuration
98
+ * Must be called before using any presence hooks
99
+ */
100
+ declare function initPresenceSocket(presenceConfig: PresenceConfig): void;
101
+ /**
102
+ * Get the shared socket instance
103
+ * @throws Error if socket is not initialized
104
+ */
105
+ declare function getPresenceSocket(): Socket;
106
+ /**
107
+ * Disconnect and cleanup the socket connection
108
+ */
109
+ declare function disconnectPresenceSocket(): void;
110
+ /**
111
+ * Check if socket is initialized
112
+ */
113
+ declare function isPresenceSocketInitialized(): boolean;
114
+
115
+ /**
116
+ * Hook to join a presence room and track users in that room
117
+ *
118
+ * @param options - Configuration options
119
+ * @returns Array of users currently in the room
120
+ *
121
+ * @example
122
+ * ```tsx
123
+ * const users = usePresence({
124
+ * roomId: 'my-app:page-123',
125
+ * currentUser: { userId: '1', name: 'John' },
126
+ * });
127
+ * ```
128
+ */
129
+ declare function usePresence(options: UsePresenceOptions): PresenceUser[];
130
+
131
+ /**
132
+ * Hook to watch multiple rooms without joining them
133
+ * (read-only observation, current user is not added to the rooms)
134
+ *
135
+ * @param options - Configuration options
136
+ * @returns Map of roomId to array of users in that room
137
+ *
138
+ * @example
139
+ * ```tsx
140
+ * const roomsUsers = usePresenceWatch({
141
+ * roomIds: ['room-1', 'room-2', 'room-3'],
142
+ * });
143
+ * // roomsUsers = { 'room-1': [...], 'room-2': [...], ... }
144
+ * ```
145
+ */
146
+ declare function usePresenceWatch(options: UsePresenceWatchOptions): Record<string, PresenceUser[]>;
147
+
148
+ /**
149
+ * Headless hook for presence avatars UI state management
150
+ *
151
+ * This hook provides all the state and logic needed to build
152
+ * a presence avatars component without any styling.
153
+ *
154
+ * @param options - Configuration options
155
+ * @returns State and handlers for building presence avatars UI
156
+ *
157
+ * @example
158
+ * ```tsx
159
+ * const {
160
+ * visibleUsers,
161
+ * moreCount,
162
+ * hoveredUser,
163
+ * setHoveredIndex,
164
+ * getInitial,
165
+ * getZIndex,
166
+ * } = usePresenceAvatarsState({ users, maxVisible: 3 });
167
+ *
168
+ * return (
169
+ * <div>
170
+ * {visibleUsers.map((user, idx) => (
171
+ * <span
172
+ * key={user.userId}
173
+ * style={{ zIndex: getZIndex(idx, hoveredUser?.userId === user.userId) }}
174
+ * onMouseEnter={() => setHoveredIndex(idx)}
175
+ * onMouseLeave={() => setHoveredIndex(null)}
176
+ * >
177
+ * {getInitial(user)}
178
+ * </span>
179
+ * ))}
180
+ * {moreCount > 0 && <span>+{moreCount}</span>}
181
+ * </div>
182
+ * );
183
+ * ```
184
+ */
185
+ declare function usePresenceAvatarsState(options: UsePresenceAvatarsStateOptions): UsePresenceAvatarsStateReturn;
186
+
187
+ /**
188
+ * Headless hook for presence floating UI state management
189
+ *
190
+ * This hook provides all the state and logic needed to build
191
+ * a draggable floating presence panel without any styling.
192
+ *
193
+ * @param options - Configuration options
194
+ * @returns State and handlers for building floating presence UI
195
+ *
196
+ * @example
197
+ * ```tsx
198
+ * const {
199
+ * containerRef,
200
+ * inlineStyle,
201
+ * isDragging,
202
+ * visibleUsers,
203
+ * moreCount,
204
+ * hoveredUser,
205
+ * tooltipTop,
206
+ * onMouseDownHeader,
207
+ * onAvatarEnter,
208
+ * onAvatarLeave,
209
+ * } = usePresenceFloatingState({ users, maxVisible: 8 });
210
+ *
211
+ * return (
212
+ * <div ref={containerRef} style={inlineStyle} onMouseDown={onMouseDownHeader}>
213
+ * <div className="header">열람중 {users.length}</div>
214
+ * <div className="body">
215
+ * {visibleUsers.map((user) => (
216
+ * <span
217
+ * key={user.userId}
218
+ * onMouseEnter={(e) => onAvatarEnter(e, user)}
219
+ * onMouseLeave={onAvatarLeave}
220
+ * >
221
+ * {user.name}
222
+ * </span>
223
+ * ))}
224
+ * </div>
225
+ * </div>
226
+ * );
227
+ * ```
228
+ */
229
+ declare function usePresenceFloatingState(options: UsePresenceFloatingStateOptions): UsePresenceFloatingStateReturn;
230
+
231
+ export { type PresenceConfig, type PresenceUser, type UsePresenceAvatarsStateOptions, type UsePresenceAvatarsStateReturn, type UsePresenceFloatingStateOptions, type UsePresenceFloatingStateReturn, type UsePresenceOptions, type UsePresenceWatchOptions, disconnectPresenceSocket, getPresenceSocket, initPresenceSocket, isPresenceSocketInitialized, usePresence, usePresenceAvatarsState, usePresenceFloatingState, usePresenceWatch };
@@ -0,0 +1,231 @@
1
+ import { Socket } from 'socket.io-client';
2
+
3
+ /**
4
+ * Presence User Type
5
+ */
6
+ type PresenceUser = {
7
+ userId: string;
8
+ name: string;
9
+ [key: string]: unknown;
10
+ };
11
+ /**
12
+ * Socket configuration
13
+ */
14
+ type PresenceConfig = {
15
+ url: string;
16
+ transports?: ("websocket" | "polling")[];
17
+ };
18
+ /**
19
+ * usePresence hook options
20
+ */
21
+ type UsePresenceOptions = {
22
+ /** Room identifier to join */
23
+ roomId: string;
24
+ /** Current user info to broadcast */
25
+ currentUser: PresenceUser;
26
+ /** Enable/disable the hook (default: true) */
27
+ enabled?: boolean;
28
+ /** Heartbeat interval in ms (default: 10 minutes) */
29
+ heartbeatInterval?: number;
30
+ };
31
+ /**
32
+ * usePresenceWatch hook options
33
+ */
34
+ type UsePresenceWatchOptions = {
35
+ /** Room IDs to watch */
36
+ roomIds: string[];
37
+ /** Enable/disable the hook (default: true) */
38
+ enabled?: boolean;
39
+ };
40
+ /**
41
+ * usePresenceAvatarsState hook options
42
+ */
43
+ type UsePresenceAvatarsStateOptions = {
44
+ /** List of presence users */
45
+ users: PresenceUser[];
46
+ /** Maximum visible avatars (default: 3) */
47
+ maxVisible?: number;
48
+ };
49
+ /**
50
+ * usePresenceAvatarsState return type
51
+ */
52
+ type UsePresenceAvatarsStateReturn = {
53
+ visibleUsers: PresenceUser[];
54
+ moreCount: number;
55
+ hoveredUser: PresenceUser | null;
56
+ hoveredIndex: number | null;
57
+ setHoveredIndex: (index: number | null) => void;
58
+ getInitial: (user: PresenceUser) => string;
59
+ getZIndex: (index: number, isHovered: boolean) => number;
60
+ };
61
+ /**
62
+ * usePresenceFloatingState hook options
63
+ */
64
+ type UsePresenceFloatingStateOptions = {
65
+ /** List of presence users */
66
+ users: PresenceUser[];
67
+ /** Maximum visible avatars (default: 8) */
68
+ maxVisible?: number;
69
+ /** Initial position */
70
+ initialPosition?: {
71
+ top: number;
72
+ };
73
+ };
74
+ /**
75
+ * usePresenceFloatingState return type
76
+ */
77
+ type UsePresenceFloatingStateReturn = {
78
+ containerRef: React.RefObject<HTMLDivElement | null>;
79
+ position: {
80
+ top: number;
81
+ left: number;
82
+ };
83
+ isDragging: boolean;
84
+ hasDragged: boolean;
85
+ inlineStyle: React.CSSProperties;
86
+ visibleUsers: PresenceUser[];
87
+ moreCount: number;
88
+ hoveredUser: PresenceUser | null;
89
+ tooltipTop: number;
90
+ onMouseDownHeader: (e: React.MouseEvent) => void;
91
+ onTouchStartHeader: (e: React.TouchEvent) => void;
92
+ onAvatarEnter: (e: React.MouseEvent, user: PresenceUser) => void;
93
+ onAvatarLeave: () => void;
94
+ };
95
+
96
+ /**
97
+ * Initialize the presence socket with configuration
98
+ * Must be called before using any presence hooks
99
+ */
100
+ declare function initPresenceSocket(presenceConfig: PresenceConfig): void;
101
+ /**
102
+ * Get the shared socket instance
103
+ * @throws Error if socket is not initialized
104
+ */
105
+ declare function getPresenceSocket(): Socket;
106
+ /**
107
+ * Disconnect and cleanup the socket connection
108
+ */
109
+ declare function disconnectPresenceSocket(): void;
110
+ /**
111
+ * Check if socket is initialized
112
+ */
113
+ declare function isPresenceSocketInitialized(): boolean;
114
+
115
+ /**
116
+ * Hook to join a presence room and track users in that room
117
+ *
118
+ * @param options - Configuration options
119
+ * @returns Array of users currently in the room
120
+ *
121
+ * @example
122
+ * ```tsx
123
+ * const users = usePresence({
124
+ * roomId: 'my-app:page-123',
125
+ * currentUser: { userId: '1', name: 'John' },
126
+ * });
127
+ * ```
128
+ */
129
+ declare function usePresence(options: UsePresenceOptions): PresenceUser[];
130
+
131
+ /**
132
+ * Hook to watch multiple rooms without joining them
133
+ * (read-only observation, current user is not added to the rooms)
134
+ *
135
+ * @param options - Configuration options
136
+ * @returns Map of roomId to array of users in that room
137
+ *
138
+ * @example
139
+ * ```tsx
140
+ * const roomsUsers = usePresenceWatch({
141
+ * roomIds: ['room-1', 'room-2', 'room-3'],
142
+ * });
143
+ * // roomsUsers = { 'room-1': [...], 'room-2': [...], ... }
144
+ * ```
145
+ */
146
+ declare function usePresenceWatch(options: UsePresenceWatchOptions): Record<string, PresenceUser[]>;
147
+
148
+ /**
149
+ * Headless hook for presence avatars UI state management
150
+ *
151
+ * This hook provides all the state and logic needed to build
152
+ * a presence avatars component without any styling.
153
+ *
154
+ * @param options - Configuration options
155
+ * @returns State and handlers for building presence avatars UI
156
+ *
157
+ * @example
158
+ * ```tsx
159
+ * const {
160
+ * visibleUsers,
161
+ * moreCount,
162
+ * hoveredUser,
163
+ * setHoveredIndex,
164
+ * getInitial,
165
+ * getZIndex,
166
+ * } = usePresenceAvatarsState({ users, maxVisible: 3 });
167
+ *
168
+ * return (
169
+ * <div>
170
+ * {visibleUsers.map((user, idx) => (
171
+ * <span
172
+ * key={user.userId}
173
+ * style={{ zIndex: getZIndex(idx, hoveredUser?.userId === user.userId) }}
174
+ * onMouseEnter={() => setHoveredIndex(idx)}
175
+ * onMouseLeave={() => setHoveredIndex(null)}
176
+ * >
177
+ * {getInitial(user)}
178
+ * </span>
179
+ * ))}
180
+ * {moreCount > 0 && <span>+{moreCount}</span>}
181
+ * </div>
182
+ * );
183
+ * ```
184
+ */
185
+ declare function usePresenceAvatarsState(options: UsePresenceAvatarsStateOptions): UsePresenceAvatarsStateReturn;
186
+
187
+ /**
188
+ * Headless hook for presence floating UI state management
189
+ *
190
+ * This hook provides all the state and logic needed to build
191
+ * a draggable floating presence panel without any styling.
192
+ *
193
+ * @param options - Configuration options
194
+ * @returns State and handlers for building floating presence UI
195
+ *
196
+ * @example
197
+ * ```tsx
198
+ * const {
199
+ * containerRef,
200
+ * inlineStyle,
201
+ * isDragging,
202
+ * visibleUsers,
203
+ * moreCount,
204
+ * hoveredUser,
205
+ * tooltipTop,
206
+ * onMouseDownHeader,
207
+ * onAvatarEnter,
208
+ * onAvatarLeave,
209
+ * } = usePresenceFloatingState({ users, maxVisible: 8 });
210
+ *
211
+ * return (
212
+ * <div ref={containerRef} style={inlineStyle} onMouseDown={onMouseDownHeader}>
213
+ * <div className="header">열람중 {users.length}</div>
214
+ * <div className="body">
215
+ * {visibleUsers.map((user) => (
216
+ * <span
217
+ * key={user.userId}
218
+ * onMouseEnter={(e) => onAvatarEnter(e, user)}
219
+ * onMouseLeave={onAvatarLeave}
220
+ * >
221
+ * {user.name}
222
+ * </span>
223
+ * ))}
224
+ * </div>
225
+ * </div>
226
+ * );
227
+ * ```
228
+ */
229
+ declare function usePresenceFloatingState(options: UsePresenceFloatingStateOptions): UsePresenceFloatingStateReturn;
230
+
231
+ export { type PresenceConfig, type PresenceUser, type UsePresenceAvatarsStateOptions, type UsePresenceAvatarsStateReturn, type UsePresenceFloatingStateOptions, type UsePresenceFloatingStateReturn, type UsePresenceOptions, type UsePresenceWatchOptions, disconnectPresenceSocket, getPresenceSocket, initPresenceSocket, isPresenceSocketInitialized, usePresence, usePresenceAvatarsState, usePresenceFloatingState, usePresenceWatch };