flikkui 0.2.0-beta.1 → 0.2.0-beta.4

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 (215) hide show
  1. package/README.md +12 -539
  2. package/dist/components/ai/PromptInput/PromptInput.js +94 -4
  3. package/dist/components/ai/PromptSuggestions/PromptSuggestion.d.ts +27 -0
  4. package/dist/components/ai/PromptSuggestions/PromptSuggestion.js +62 -0
  5. package/dist/components/ai/PromptSuggestions/PromptSuggestion.theme.d.ts +10 -0
  6. package/dist/components/ai/PromptSuggestions/PromptSuggestion.theme.js +12 -0
  7. package/dist/components/ai/PromptSuggestions/PromptSuggestion.types.d.ts +53 -0
  8. package/dist/components/ai/PromptSuggestions/index.d.ts +4 -2
  9. package/dist/components/ai/index.d.ts +2 -12
  10. package/dist/components/charts/ActivityRings/ActivityRings.js +70 -58
  11. package/dist/components/charts/ActivityRings/ActivityRings.theme.js +0 -1
  12. package/dist/components/charts/ActivityRings/ActivityRings.types.d.ts +17 -0
  13. package/dist/components/charts/BarChart/BarChart.js +8 -4
  14. package/dist/components/charts/BarChart/BarChart.types.d.ts +14 -0
  15. package/dist/components/charts/DonutChart/DonutChart.js +11 -8
  16. package/dist/components/charts/DonutChart/DonutChart.theme.d.ts +3 -0
  17. package/dist/components/charts/DonutChart/DonutChart.theme.js +5 -4
  18. package/dist/components/charts/DonutChart/donut-utils.d.ts +5 -0
  19. package/dist/components/charts/DonutChart/donut-utils.js +26 -1
  20. package/dist/components/charts/Heatmap/Heatmap.theme.js +2 -2
  21. package/dist/components/charts/shared/ChartAxis/XAxis.d.ts +2 -2
  22. package/dist/components/charts/shared/ChartAxis/XAxis.js +4 -4
  23. package/dist/components/charts/shared/ChartAxis/YAxis.d.ts +2 -2
  24. package/dist/components/charts/shared/ChartAxis/YAxis.js +8 -7
  25. package/dist/components/charts/shared/ChartGrid/HorizontalGrid.d.ts +1 -1
  26. package/dist/components/charts/shared/ChartGrid/HorizontalGrid.js +2 -2
  27. package/dist/components/charts/theme/chart.theme.d.ts +1 -1
  28. package/dist/components/charts/theme/chart.theme.js +39 -39
  29. package/dist/components/core/Accordion/Accordion.d.ts +1 -1
  30. package/dist/components/core/Accordion/Accordion.js +2 -2
  31. package/dist/components/core/Accordion/Accordion.types.d.ts +8 -0
  32. package/dist/components/core/Badge/Badge.js +11 -15
  33. package/dist/components/core/Badge/Badge.theme.js +7 -21
  34. package/dist/components/core/Badge/Badge.types.d.ts +9 -1
  35. package/dist/components/core/Button/Button.js +2 -2
  36. package/dist/components/core/Button/Button.theme.js +1 -1
  37. package/dist/components/core/Button/Button.types.d.ts +8 -0
  38. package/dist/components/core/Card/Card.js +8 -2
  39. package/dist/components/core/Card/Card.theme.js +1 -1
  40. package/dist/components/core/Card/Card.types.d.ts +24 -1
  41. package/dist/components/core/Drawer/Drawer.d.ts +1 -1
  42. package/dist/components/core/Drawer/Drawer.js +10 -40
  43. package/dist/components/core/Drawer/Drawer.theme.js +2 -1
  44. package/dist/components/core/Drawer/Drawer.types.d.ts +8 -0
  45. package/dist/components/core/Dropdown/Dropdown.d.ts +1 -1
  46. package/dist/components/core/Dropdown/Dropdown.js +2 -2
  47. package/dist/components/core/Dropdown/Dropdown.types.d.ts +8 -0
  48. package/dist/components/core/Metric/Metric.d.ts +1 -1
  49. package/dist/components/core/Metric/Metric.js +9 -5
  50. package/dist/components/core/Metric/Metric.theme.d.ts +1 -1
  51. package/dist/components/core/Metric/Metric.theme.js +38 -28
  52. package/dist/components/core/Metric/Metric.types.d.ts +27 -8
  53. package/dist/components/core/Modal/Modal.d.ts +1 -1
  54. package/dist/components/core/Modal/Modal.js +17 -40
  55. package/dist/components/core/Modal/Modal.theme.js +8 -3
  56. package/dist/components/core/Modal/Modal.types.d.ts +18 -0
  57. package/dist/components/core/Modal/index.d.ts +1 -1
  58. package/dist/components/core/Notification/Notification.js +67 -0
  59. package/dist/components/core/Pill/Pill.d.ts +6 -11
  60. package/dist/components/core/Pill/Pill.theme.d.ts +2 -2
  61. package/dist/components/core/Pill/Pill.types.d.ts +9 -22
  62. package/dist/components/core/Pill/index.d.ts +1 -1
  63. package/dist/components/core/Popover/Popover.d.ts +1 -1
  64. package/dist/components/core/Popover/Popover.js +2 -2
  65. package/dist/components/core/Popover/Popover.types.d.ts +8 -0
  66. package/dist/components/core/Progress/Progress.d.ts +28 -0
  67. package/dist/components/core/Progress/Progress.js +114 -0
  68. package/dist/components/core/Progress/Progress.theme.d.ts +5 -0
  69. package/dist/components/core/Progress/Progress.theme.js +33 -0
  70. package/dist/components/core/Progress/Progress.types.d.ts +92 -0
  71. package/dist/components/core/Progress/index.d.ts +2 -0
  72. package/dist/components/core/Tabs/Tabs.js +2 -2
  73. package/dist/components/core/Tabs/Tabs.types.d.ts +8 -0
  74. package/dist/components/core/Tag/Tag.animations.d.ts +3 -0
  75. package/dist/components/core/Tag/Tag.animations.js +31 -0
  76. package/dist/components/core/Tag/Tag.d.ts +14 -0
  77. package/dist/components/core/Tag/Tag.js +45 -0
  78. package/dist/components/core/Tag/Tag.theme.d.ts +2 -0
  79. package/dist/components/core/Tag/Tag.theme.js +21 -0
  80. package/dist/components/core/Tag/Tag.types.d.ts +40 -0
  81. package/dist/components/core/Tag/index.d.ts +3 -0
  82. package/dist/components/core/Tooltip/Tooltip.d.ts +1 -1
  83. package/dist/components/core/Tooltip/Tooltip.js +3 -3
  84. package/dist/components/core/Tooltip/Tooltip.theme.js +1 -1
  85. package/dist/components/core/Tooltip/Tooltip.types.d.ts +17 -0
  86. package/dist/components/core/index.d.ts +2 -1
  87. package/dist/components/core/index.js +3 -2
  88. package/dist/components/effects/CustomCursor/CustomCursor.d.ts +0 -13
  89. package/dist/components/effects/CustomCursor/CustomCursor.js +26 -2
  90. package/dist/components/effects/CustomCursor/CustomCursor.theme.js +12 -1
  91. package/dist/components/effects/CustomCursor/CustomCursor.types.d.ts +14 -1
  92. package/dist/components/forms/Combobox/Combobox.d.ts +25 -0
  93. package/dist/components/forms/Combobox/Combobox.js +412 -0
  94. package/dist/components/forms/Combobox/Combobox.theme.d.ts +6 -0
  95. package/dist/components/forms/Combobox/Combobox.theme.js +60 -0
  96. package/dist/components/forms/Combobox/Combobox.types.d.ts +111 -0
  97. package/dist/components/forms/Combobox/index.d.ts +3 -0
  98. package/dist/components/forms/FileUpload/FileUpload.js +68 -0
  99. package/dist/components/forms/Input/Input.js +25 -28
  100. package/dist/components/forms/Input/inputMasks.d.ts +15 -0
  101. package/dist/components/forms/Input/inputMasks.js +72 -1
  102. package/dist/components/forms/InputTag/InputTag.d.ts +40 -0
  103. package/dist/components/forms/InputTag/InputTag.js +491 -0
  104. package/dist/components/forms/InputTag/InputTag.theme.d.ts +2 -0
  105. package/dist/components/forms/InputTag/InputTag.theme.js +16 -0
  106. package/dist/components/forms/InputTag/InputTag.types.d.ts +107 -0
  107. package/dist/components/forms/InputTag/index.d.ts +3 -0
  108. package/dist/components/forms/Select/Select.d.ts +101 -2
  109. package/dist/components/forms/Select/Select.js +128 -132
  110. package/dist/components/forms/Select/Select.theme.js +10 -14
  111. package/dist/components/forms/Select/Select.types.d.ts +6 -2
  112. package/dist/components/forms/Select/index.d.ts +7 -4
  113. package/dist/components/forms/Select/useSelectState.d.ts +66 -0
  114. package/dist/components/forms/Select/useSelectState.js +134 -0
  115. package/dist/components/forms/SelectExpand/SelectExpand.animations.d.ts +20 -0
  116. package/dist/components/forms/SelectExpand/SelectExpand.animations.js +74 -0
  117. package/dist/components/forms/SelectExpand/SelectExpand.d.ts +9 -0
  118. package/dist/components/forms/SelectExpand/SelectExpand.js +223 -0
  119. package/dist/components/forms/SelectExpand/SelectExpand.theme.d.ts +5 -0
  120. package/dist/components/forms/SelectExpand/SelectExpand.theme.js +74 -0
  121. package/dist/components/forms/SelectExpand/SelectExpand.types.d.ts +126 -0
  122. package/dist/components/forms/SelectExpand/index.d.ts +4 -0
  123. package/dist/components/forms/Switch/Switch.js +3 -3
  124. package/dist/components/forms/Switch/Switch.theme.d.ts +1 -1
  125. package/dist/components/forms/Switch/Switch.theme.js +2 -2
  126. package/dist/components/forms/TimePicker/TimePicker.animations.d.ts +0 -46
  127. package/dist/components/forms/TimePicker/TimePicker.d.ts +15 -6
  128. package/dist/components/forms/TimePicker/TimePicker.js +285 -124
  129. package/dist/components/forms/TimePicker/TimePicker.theme.d.ts +1 -1
  130. package/dist/components/forms/TimePicker/TimePicker.theme.js +39 -22
  131. package/dist/components/forms/TimePicker/TimePicker.types.d.ts +88 -34
  132. package/dist/components/forms/TimePicker/TimePickerContent.d.ts +7 -10
  133. package/dist/components/forms/TimePicker/TimePickerContent.js +149 -16
  134. package/dist/components/forms/TimePicker/TimePickerTrigger.d.ts +3 -3
  135. package/dist/components/forms/TimePicker/TimePickerTrigger.js +22 -19
  136. package/dist/components/forms/TimePicker/WheelColumn.d.ts +14 -0
  137. package/dist/components/forms/TimePicker/WheelColumn.js +90 -0
  138. package/dist/components/forms/TimePicker/index.d.ts +4 -1
  139. package/dist/components/forms/TimePicker/useWheelPicker.d.ts +37 -0
  140. package/dist/components/forms/TimePicker/useWheelPicker.js +138 -0
  141. package/dist/components/forms/forms.theme.d.ts +14 -0
  142. package/dist/components/forms/forms.theme.js +31 -0
  143. package/dist/components/forms/index.d.ts +9 -3
  144. package/dist/components/forms/index.js +73 -2
  145. package/dist/hooks/index.d.ts +0 -4
  146. package/dist/icons/Icon.d.ts +7 -0
  147. package/dist/icons/Icon.js +6 -2
  148. package/dist/index.js +62 -63
  149. package/dist/styles.css +1 -1
  150. package/dist/utils/index.d.ts +0 -1
  151. package/dist/utils/optimisticErrors.js +1 -70
  152. package/package.json +1 -1
  153. package/dist/components/ai/EditingIndicator/EditingIndicator.animations.d.ts +0 -31
  154. package/dist/components/ai/EditingIndicator/EditingIndicator.animations.js +0 -115
  155. package/dist/components/ai/EditingIndicator/EditingIndicator.d.ts +0 -35
  156. package/dist/components/ai/EditingIndicator/EditingIndicator.js +0 -94
  157. package/dist/components/ai/EditingIndicator/EditingIndicator.theme.d.ts +0 -2
  158. package/dist/components/ai/EditingIndicator/EditingIndicator.theme.js +0 -13
  159. package/dist/components/ai/EditingIndicator/EditingIndicator.types.d.ts +0 -54
  160. package/dist/components/ai/EditingIndicator/index.d.ts +0 -9
  161. package/dist/components/ai/GenerativeRenderer/GenerativeRenderer.d.ts +0 -3
  162. package/dist/components/ai/GenerativeRenderer/GenerativeRenderer.js +0 -126
  163. package/dist/components/ai/GenerativeRenderer/GenerativeRenderer.theme.d.ts +0 -2
  164. package/dist/components/ai/GenerativeRenderer/GenerativeRenderer.theme.js +0 -8
  165. package/dist/components/ai/GenerativeRenderer/GenerativeRenderer.types.d.ts +0 -45
  166. package/dist/components/ai/GenerativeRenderer/index.d.ts +0 -3
  167. package/dist/components/ai/PresenceIndicator/PresenceIndicator.animations.d.ts +0 -17
  168. package/dist/components/ai/PresenceIndicator/PresenceIndicator.animations.js +0 -56
  169. package/dist/components/ai/PresenceIndicator/PresenceIndicator.d.ts +0 -38
  170. package/dist/components/ai/PresenceIndicator/PresenceIndicator.js +0 -110
  171. package/dist/components/ai/PresenceIndicator/PresenceIndicator.theme.d.ts +0 -2
  172. package/dist/components/ai/PresenceIndicator/PresenceIndicator.theme.js +0 -13
  173. package/dist/components/ai/PresenceIndicator/PresenceIndicator.types.d.ts +0 -53
  174. package/dist/components/ai/PresenceIndicator/index.d.ts +0 -8
  175. package/dist/components/ai/PresenceProvider/PresenceContext.d.ts +0 -24
  176. package/dist/components/ai/PresenceProvider/PresenceContext.js +0 -34
  177. package/dist/components/ai/PresenceProvider/PresenceProvider.d.ts +0 -32
  178. package/dist/components/ai/PresenceProvider/PresenceProvider.js +0 -321
  179. package/dist/components/ai/PresenceProvider/PresenceProvider.types.d.ts +0 -140
  180. package/dist/components/ai/PresenceProvider/adapters/MockAdapter.d.ts +0 -102
  181. package/dist/components/ai/PresenceProvider/adapters/MockAdapter.js +0 -331
  182. package/dist/components/ai/PresenceProvider/adapters/PresenceAdapter.d.ts +0 -93
  183. package/dist/components/ai/PresenceProvider/adapters/SupabaseAdapter.d.ts +0 -134
  184. package/dist/components/ai/PresenceProvider/adapters/WebSocketAdapter.d.ts +0 -149
  185. package/dist/components/ai/PresenceProvider/adapters/index.d.ts +0 -11
  186. package/dist/components/ai/PresenceProvider/index.d.ts +0 -10
  187. package/dist/components/ai/PromptSuggestions/PromptSuggestions.d.ts +0 -27
  188. package/dist/components/ai/PromptSuggestions/PromptSuggestions.js +0 -61
  189. package/dist/components/ai/PromptSuggestions/PromptSuggestions.types.d.ts +0 -65
  190. package/dist/components/ai/VersionSlider/VersionSlider.d.ts +0 -3
  191. package/dist/components/ai/VersionSlider/VersionSlider.js +0 -97
  192. package/dist/components/ai/VersionSlider/VersionSlider.theme.d.ts +0 -2
  193. package/dist/components/ai/VersionSlider/VersionSlider.theme.js +0 -18
  194. package/dist/components/ai/VersionSlider/VersionSlider.types.d.ts +0 -77
  195. package/dist/components/ai/VersionSlider/index.d.ts +0 -3
  196. package/dist/components/core/Pill/Pill.animations.js +0 -25
  197. package/dist/components/core/Pill/Pill.js +0 -145
  198. package/dist/components/core/Pill/Pill.theme.js +0 -65
  199. package/dist/components/core/RetryBoundary/RetryBoundary.d.ts +0 -35
  200. package/dist/components/core/RetryBoundary/RetryBoundary.js +0 -154
  201. package/dist/components/core/RetryBoundary/RetryBoundary.theme.d.ts +0 -2
  202. package/dist/components/core/RetryBoundary/RetryBoundary.theme.js +0 -7
  203. package/dist/components/core/RetryBoundary/RetryBoundary.types.d.ts +0 -51
  204. package/dist/components/core/RetryBoundary/index.d.ts +0 -3
  205. package/dist/components/forms/OptimisticForm/OptimisticForm.d.ts +0 -33
  206. package/dist/components/forms/OptimisticForm/OptimisticForm.js +0 -87
  207. package/dist/components/forms/OptimisticForm/OptimisticForm.theme.d.ts +0 -2
  208. package/dist/components/forms/OptimisticForm/OptimisticForm.theme.js +0 -8
  209. package/dist/components/forms/OptimisticForm/OptimisticForm.types.d.ts +0 -74
  210. package/dist/components/forms/OptimisticForm/index.d.ts +0 -3
  211. package/dist/hooks/useOptimisticMutation.d.ts +0 -109
  212. package/dist/hooks/useOptimisticMutation.js +0 -171
  213. package/dist/hooks/usePresence.d.ts +0 -88
  214. package/dist/utils/presenceUtils.d.ts +0 -66
  215. package/dist/utils/presenceUtils.js +0 -107
@@ -1,321 +0,0 @@
1
- import React__default, { useState, useRef, useCallback, useMemo, useEffect } from 'react';
2
- import { PresenceContext } from './PresenceContext.js';
3
- import { useNetworkStatus } from '../../../hooks/useNetworkStatus.js';
4
- import { debounce } from '../../../utils/debounce.js';
5
-
6
- /**
7
- * Presence Provider Component
8
- *
9
- * Root provider that manages real-time presence state via adapter pattern.
10
- * Provides presence context to child components.
11
- *
12
- * Features:
13
- * - Backend-agnostic adapter pattern
14
- * - Network-aware reconnection
15
- * - Typing state management with debouncing
16
- * - Auto-cleanup on unmount
17
- */
18
- /**
19
- * PresenceProvider - Real-time collaboration provider
20
- *
21
- * @example
22
- * ```tsx
23
- * const adapter = new MockPresenceAdapter();
24
- * const currentUser = { id: '1', name: 'John Doe', status: 'online' };
25
- *
26
- * <PresenceProvider channel="chat-room-123" currentUser={currentUser} adapter={adapter}>
27
- * <PresenceIndicator />
28
- * <ChatInterface>
29
- * <MessageHistory />
30
- * <EditingIndicator />
31
- * </ChatInterface>
32
- * </PresenceProvider>
33
- * ```
34
- */
35
- const PresenceProvider = React__default.forwardRef(({ channel, currentUser, adapter, autoConnect = true, typingDebounce = 300, typingTimeout = 3000, autoReconnect = true, onPresenceChange, onConnectionChange, onError, children, className, ...props }, ref) => {
36
- // ===== State =====
37
- const [users, setUsers] = useState([]);
38
- const [typingUsers, setTypingUsers] = useState([]);
39
- const [connectionStatus, setConnectionStatus] = useState('disconnected');
40
- const [error, setError] = useState(null);
41
- // ===== Refs =====
42
- const typingTimeoutRef = useRef(undefined);
43
- const isConnectingRef = useRef(false);
44
- const hasConnectedOnceRef = useRef(false);
45
- // ===== Network status =====
46
- const { isOnline, wasOffline } = useNetworkStatus();
47
- // ===== Derived state =====
48
- const isConnected = connectionStatus === 'connected';
49
- const isConnecting = connectionStatus === 'connecting';
50
- // ===== Connection management =====
51
- /**
52
- * Connect to presence channel
53
- */
54
- const connect = useCallback(async () => {
55
- // Use ref to check if already connecting to avoid dependency on connectionStatus
56
- if (isConnectingRef.current) {
57
- return;
58
- }
59
- isConnectingRef.current = true;
60
- setConnectionStatus('connecting');
61
- setError(null);
62
- try {
63
- await adapter.connect({
64
- channel,
65
- currentUser,
66
- typingDebounce,
67
- typingTimeout,
68
- });
69
- hasConnectedOnceRef.current = true;
70
- setConnectionStatus('connected');
71
- if (process.env.NODE_ENV !== 'production') {
72
- console.log('[PresenceProvider]: Connected to channel:', channel);
73
- }
74
- }
75
- catch (err) {
76
- const error = err instanceof Error ? err : new Error('Connection failed');
77
- setError(error);
78
- setConnectionStatus('disconnected');
79
- onError === null || onError === void 0 ? void 0 : onError(error);
80
- if (process.env.NODE_ENV !== 'production') {
81
- console.error('[PresenceProvider]: Connection error:', error);
82
- }
83
- // Attempt reconnection if enabled
84
- if (autoReconnect && hasConnectedOnceRef.current) {
85
- if (process.env.NODE_ENV !== 'production') {
86
- console.log('[PresenceProvider]: Scheduling reconnection...');
87
- }
88
- setTimeout(() => {
89
- if (isOnline) {
90
- connect();
91
- }
92
- }, 3000);
93
- }
94
- }
95
- finally {
96
- isConnectingRef.current = false;
97
- }
98
- }, [
99
- adapter,
100
- channel,
101
- currentUser,
102
- typingDebounce,
103
- typingTimeout,
104
- autoReconnect,
105
- isOnline,
106
- onError,
107
- ]);
108
- /**
109
- * Disconnect from channel
110
- */
111
- const disconnect = useCallback(async () => {
112
- try {
113
- await adapter.disconnect();
114
- setConnectionStatus('disconnected');
115
- setUsers([]);
116
- setTypingUsers([]);
117
- setError(null);
118
- if (process.env.NODE_ENV !== 'production') {
119
- console.log('[PresenceProvider]: Disconnected from channel');
120
- }
121
- }
122
- catch (err) {
123
- if (process.env.NODE_ENV !== 'production') {
124
- console.error('[PresenceProvider]: Disconnect error:', err);
125
- }
126
- }
127
- }, [adapter]);
128
- // ===== Typing management =====
129
- /**
130
- * Start typing indicator (not debounced - debouncing is handled internally)
131
- */
132
- const startTypingInternal = useCallback(() => {
133
- if (connectionStatus !== 'connected')
134
- return;
135
- adapter.sendTypingStart();
136
- // Clear existing timeout
137
- if (typingTimeoutRef.current) {
138
- clearTimeout(typingTimeoutRef.current);
139
- }
140
- // Auto-stop after timeout
141
- typingTimeoutRef.current = setTimeout(() => {
142
- stopTyping();
143
- }, typingTimeout);
144
- }, [adapter, connectionStatus, typingTimeout]);
145
- /**
146
- * Start typing indicator (debounced)
147
- */
148
- const startTyping = useMemo(() => debounce(startTypingInternal, typingDebounce), [startTypingInternal, typingDebounce]);
149
- /**
150
- * Stop typing indicator
151
- */
152
- const stopTyping = useCallback(() => {
153
- if (connectionStatus !== 'connected')
154
- return;
155
- adapter.sendTypingStop();
156
- // Clear timeout
157
- if (typingTimeoutRef.current) {
158
- clearTimeout(typingTimeoutRef.current);
159
- }
160
- }, [adapter, connectionStatus]);
161
- /**
162
- * Update current user metadata
163
- */
164
- const updateUser = useCallback((updates) => {
165
- if (connectionStatus !== 'connected')
166
- return;
167
- adapter.updateUserMetadata(updates);
168
- }, [adapter, connectionStatus]);
169
- /**
170
- * Send custom event
171
- */
172
- const sendEvent = useCallback((event, data) => {
173
- if (connectionStatus !== 'connected')
174
- return;
175
- adapter.sendCustomEvent(event, data);
176
- }, [adapter, connectionStatus]);
177
- // ===== Effects =====
178
- /**
179
- * Subscribe to adapter events
180
- */
181
- useEffect(() => {
182
- // Subscribe to presence changes
183
- const unsubscribePresence = adapter.onPresenceChange((newUsers) => {
184
- setUsers(newUsers);
185
- // Notify callback
186
- if (onPresenceChange && newUsers.length > users.length) {
187
- // User joined
188
- const newUser = newUsers.find(u => !users.find(existing => existing.id === u.id));
189
- if (newUser) {
190
- const event = { type: 'user-joined', user: newUser };
191
- onPresenceChange(event);
192
- }
193
- }
194
- else if (onPresenceChange && newUsers.length < users.length) {
195
- // User left
196
- const leftUser = users.find(u => !newUsers.find(existing => existing.id === u.id));
197
- if (leftUser) {
198
- const event = { type: 'user-left', userId: leftUser.id };
199
- onPresenceChange(event);
200
- }
201
- }
202
- });
203
- // Subscribe to typing changes
204
- const unsubscribeTyping = adapter.onTypingChange((newTypingUsers) => {
205
- setTypingUsers(newTypingUsers);
206
- // Notify callback
207
- if (onPresenceChange) {
208
- const startedTyping = newTypingUsers.find(u => !typingUsers.find(existing => existing.id === u.id));
209
- const stoppedTyping = typingUsers.find(u => !newTypingUsers.find(existing => existing.id === u.id));
210
- if (startedTyping) {
211
- const event = {
212
- type: 'typing-started',
213
- userId: startedTyping.id,
214
- userName: startedTyping.name,
215
- };
216
- onPresenceChange(event);
217
- }
218
- if (stoppedTyping) {
219
- const event = {
220
- type: 'typing-stopped',
221
- userId: stoppedTyping.id,
222
- };
223
- onPresenceChange(event);
224
- }
225
- }
226
- });
227
- // Subscribe to connection changes
228
- const unsubscribeConnection = adapter.onConnectionChange((status) => {
229
- setConnectionStatus(status);
230
- onConnectionChange === null || onConnectionChange === void 0 ? void 0 : onConnectionChange(status);
231
- if (status === 'connected' && onPresenceChange) {
232
- const event = { type: 'reconnected' };
233
- onPresenceChange(event);
234
- }
235
- else if (status === 'connecting' && onPresenceChange) {
236
- const event = { type: 'reconnecting' };
237
- onPresenceChange(event);
238
- }
239
- });
240
- // Subscribe to errors
241
- const unsubscribeError = adapter.onError((err) => {
242
- setError(err);
243
- onError === null || onError === void 0 ? void 0 : onError(err);
244
- if (onPresenceChange) {
245
- const event = { type: 'connection-error', error: err };
246
- onPresenceChange(event);
247
- }
248
- });
249
- // Cleanup
250
- return () => {
251
- unsubscribePresence();
252
- unsubscribeTyping();
253
- unsubscribeConnection();
254
- unsubscribeError();
255
- };
256
- }, [adapter, users, typingUsers, onPresenceChange, onConnectionChange, onError]);
257
- /**
258
- * Auto-connect on mount
259
- */
260
- useEffect(() => {
261
- if (autoConnect) {
262
- connect();
263
- }
264
- // Cleanup on unmount
265
- return () => {
266
- disconnect();
267
- // Clear typing timeout
268
- if (typingTimeoutRef.current) {
269
- clearTimeout(typingTimeoutRef.current);
270
- }
271
- };
272
- }, [autoConnect, connect, disconnect]);
273
- /**
274
- * Handle network recovery
275
- */
276
- useEffect(() => {
277
- if (wasOffline && isOnline && autoReconnect && hasConnectedOnceRef.current) {
278
- if (process.env.NODE_ENV !== 'production') {
279
- console.log('[PresenceProvider]: Network recovered, reconnecting...');
280
- }
281
- connect();
282
- }
283
- }, [wasOffline, isOnline, autoReconnect, connect]);
284
- // ===== Context value =====
285
- const contextValue = useMemo(() => ({
286
- users,
287
- typingUsers,
288
- currentUser,
289
- connectionStatus,
290
- isConnected,
291
- isConnecting,
292
- error,
293
- connect,
294
- disconnect,
295
- startTyping,
296
- stopTyping,
297
- updateUser,
298
- sendEvent,
299
- }), [
300
- users,
301
- typingUsers,
302
- currentUser,
303
- connectionStatus,
304
- isConnected,
305
- isConnecting,
306
- error,
307
- connect,
308
- disconnect,
309
- startTyping,
310
- stopTyping,
311
- updateUser,
312
- sendEvent,
313
- ]);
314
- // ===== Render =====
315
- return (React__default.createElement(PresenceContext.Provider, { value: contextValue },
316
- React__default.createElement("div", { ref: ref, className: className, "data-channel": channel, "data-connected": isConnected, "data-user-count": users.length, "data-typing-count": typingUsers.length, ...props }, children)));
317
- });
318
- // Set display name for dev tools
319
- PresenceProvider.displayName = 'PresenceProvider';
320
-
321
- export { PresenceProvider };
@@ -1,140 +0,0 @@
1
- /**
2
- * Real-Time Collaboration - Core Type Definitions
3
- *
4
- * Defines the foundational types for the presence system including
5
- * users, typing states, events, and provider configuration.
6
- */
7
- import React from 'react';
8
- import { PresenceAdapter } from './adapters/PresenceAdapter';
9
- /**
10
- * User presence data structure
11
- * Represents a user's current state in the collaboration channel
12
- */
13
- export interface PresenceUser {
14
- /** Unique user identifier */
15
- id: string;
16
- /** Display name */
17
- name: string;
18
- /** Avatar image URL (optional) */
19
- avatar?: string;
20
- /** User status indicator */
21
- status?: 'online' | 'offline' | 'busy' | 'away';
22
- /** Custom metadata (JSON serializable) */
23
- metadata?: Record<string, unknown>;
24
- /** Timestamp when user joined the channel */
25
- joinedAt?: Date;
26
- /** Last activity timestamp */
27
- lastSeenAt?: Date;
28
- }
29
- /**
30
- * Typing state for a user
31
- * Tracks when a user is actively typing
32
- */
33
- export interface TypingUser {
34
- /** User ID */
35
- id: string;
36
- /** User name for display */
37
- name: string;
38
- /** Avatar URL (optional) */
39
- avatar?: string;
40
- /** Timestamp when typing started */
41
- startedAt: Date;
42
- }
43
- /**
44
- * Connection status states
45
- */
46
- export type ConnectionStatus = 'connected' | 'disconnected' | 'connecting';
47
- /**
48
- * Presence event types
49
- * Union type representing all possible presence-related events
50
- */
51
- export type PresenceEvent = {
52
- type: 'user-joined';
53
- user: PresenceUser;
54
- } | {
55
- type: 'user-left';
56
- userId: string;
57
- } | {
58
- type: 'user-updated';
59
- user: PresenceUser;
60
- } | {
61
- type: 'typing-started';
62
- userId: string;
63
- userName: string;
64
- } | {
65
- type: 'typing-stopped';
66
- userId: string;
67
- } | {
68
- type: 'connection-error';
69
- error: Error;
70
- } | {
71
- type: 'reconnecting';
72
- } | {
73
- type: 'reconnected';
74
- };
75
- /**
76
- * Context value provided to child components
77
- * Shared state accessible via usePresenceContext hook
78
- */
79
- export interface PresenceContextValue {
80
- /** All users currently in the channel */
81
- users: PresenceUser[];
82
- /** Users currently typing */
83
- typingUsers: TypingUser[];
84
- /** Current user data */
85
- currentUser: PresenceUser;
86
- /** Current connection status */
87
- connectionStatus: ConnectionStatus;
88
- /** Is actively connected */
89
- isConnected: boolean;
90
- /** Is connecting or reconnecting */
91
- isConnecting: boolean;
92
- /** Connection error (if any) */
93
- error: Error | null;
94
- /** Manually connect to channel */
95
- connect: () => Promise<void>;
96
- /** Manually disconnect from channel */
97
- disconnect: () => Promise<void>;
98
- /** Start typing indicator */
99
- startTyping: () => void;
100
- /** Stop typing indicator */
101
- stopTyping: () => void;
102
- /** Update current user metadata */
103
- updateUser: (updates: Partial<PresenceUser>) => void;
104
- /** Send custom presence event */
105
- sendEvent: (event: string, data?: unknown) => void;
106
- }
107
- /**
108
- * PresenceProvider component props
109
- */
110
- export interface PresenceProviderProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onError'> {
111
- /** Unique channel/room identifier */
112
- channel: string;
113
- /** Current user data */
114
- currentUser: PresenceUser;
115
- /** Backend adapter instance */
116
- adapter: PresenceAdapter;
117
- /** Auto-connect on mount (default: true) */
118
- autoConnect?: boolean;
119
- /** Debounce delay for typing events in milliseconds (default: 300) */
120
- typingDebounce?: number;
121
- /** Auto stop typing after inactivity in milliseconds (default: 3000) */
122
- typingTimeout?: number;
123
- /** Enable automatic reconnection (default: true) */
124
- autoReconnect?: boolean;
125
- /** Callback when presence event occurs */
126
- onPresenceChange?: (event: PresenceEvent) => void;
127
- /** Callback when connection status changes */
128
- onConnectionChange?: (status: ConnectionStatus) => void;
129
- /** Callback when error occurs */
130
- onError?: (error: Error) => void;
131
- /** Children components */
132
- children?: React.ReactNode;
133
- }
134
- /**
135
- * Theme overrides for PresenceProvider
136
- * Currently unused but kept for future styling needs
137
- */
138
- export interface PresenceProviderTheme {
139
- baseStyle?: string;
140
- }
@@ -1,102 +0,0 @@
1
- /**
2
- * Mock Presence Adapter
3
- *
4
- * Simulates real-time presence behavior for development and Storybook demos.
5
- * No external dependencies - pure client-side simulation.
6
- *
7
- * Features:
8
- * - Simulates 4-5 users joining at staggered intervals
9
- * - Random typing events every 5 seconds
10
- * - Auto-stop typing after 2-5 seconds
11
- * - Connection status simulation
12
- */
13
- import { PresenceAdapter, PresenceAdapterConfig } from './PresenceAdapter';
14
- import { PresenceUser, TypingUser, ConnectionStatus } from '../PresenceProvider.types';
15
- /**
16
- * Mock adapter implementation
17
- * Simulates presence behavior without backend
18
- */
19
- export declare class MockPresenceAdapter implements PresenceAdapter {
20
- private config;
21
- private connectionStatus;
22
- private users;
23
- private typingUsers;
24
- private intervals;
25
- private timeouts;
26
- private presenceCallbacks;
27
- private typingCallbacks;
28
- private connectionCallbacks;
29
- private errorCallbacks;
30
- /**
31
- * Connect to mock presence channel
32
- */
33
- connect(config: PresenceAdapterConfig): Promise<void>;
34
- /**
35
- * Disconnect from mock channel
36
- */
37
- disconnect(): Promise<void>;
38
- /**
39
- * Subscribe to presence changes
40
- */
41
- onPresenceChange(callback: (users: PresenceUser[]) => void): () => void;
42
- /**
43
- * Subscribe to typing changes
44
- */
45
- onTypingChange(callback: (users: TypingUser[]) => void): () => void;
46
- /**
47
- * Subscribe to connection changes
48
- */
49
- onConnectionChange(callback: (status: ConnectionStatus) => void): () => void;
50
- /**
51
- * Subscribe to errors
52
- */
53
- onError(callback: (error: Error) => void): () => void;
54
- /**
55
- * Send typing start (current user)
56
- */
57
- sendTypingStart(): void;
58
- /**
59
- * Send typing stop (current user)
60
- */
61
- sendTypingStop(): void;
62
- /**
63
- * Update current user metadata
64
- */
65
- updateUserMetadata(metadata: Partial<PresenceUser>): void;
66
- /**
67
- * Send custom event (mock implementation)
68
- */
69
- sendCustomEvent(event: string, data?: unknown): void;
70
- /**
71
- * Get current connection status
72
- */
73
- getConnectionStatus(): ConnectionStatus;
74
- /**
75
- * Get current user
76
- */
77
- getCurrentUser(): PresenceUser;
78
- /**
79
- * Simulate realistic user activity
80
- */
81
- private simulateUserActivity;
82
- /**
83
- * Simulate typing start for a user
84
- */
85
- private simulateTypingStart;
86
- /**
87
- * Simulate typing stop for a user
88
- */
89
- private simulateTypingStop;
90
- /**
91
- * Notify all presence callbacks
92
- */
93
- private notifyPresenceChange;
94
- /**
95
- * Notify all typing callbacks
96
- */
97
- private notifyTypingChange;
98
- /**
99
- * Notify all connection callbacks
100
- */
101
- private notifyConnectionChange;
102
- }