@djangocfg/centrifugo 2.1.168 → 2.1.169

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 CHANGED
@@ -877,6 +877,7 @@ Display connection status in various formats.
877
877
  - `badge` - Compact badge with status indicator
878
878
  - `inline` - Inline text with icon
879
879
  - `detailed` - Detailed view with uptime and subscriptions
880
+ - `dot` - Minimal dot indicator with popover on click (ideal for toolbars)
880
881
 
881
882
  ```tsx
882
883
  import { ConnectionStatus } from '@djangocfg/centrifugo';
@@ -884,9 +885,12 @@ import { ConnectionStatus } from '@djangocfg/centrifugo';
884
885
  // Badge variant
885
886
  <ConnectionStatus variant="badge" />
886
887
 
888
+ // Dot variant - minimal indicator with popover (best for headers/toolbars)
889
+ <ConnectionStatus variant="dot" dotSize="md" />
890
+
887
891
  // Detailed variant with uptime and subscriptions
888
- <ConnectionStatus
889
- variant="detailed"
892
+ <ConnectionStatus
893
+ variant="detailed"
890
894
  showUptime={true}
891
895
  showSubscriptions={true}
892
896
  />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djangocfg/centrifugo",
3
- "version": "2.1.168",
3
+ "version": "2.1.169",
4
4
  "description": "Production-ready Centrifugo WebSocket client for React with real-time subscriptions, RPC patterns, and connection state management",
5
5
  "keywords": [
6
6
  "centrifugo",
@@ -63,10 +63,10 @@
63
63
  "centrifuge": "^5.2.2"
64
64
  },
65
65
  "peerDependencies": {
66
- "@djangocfg/api": "^2.1.168",
67
- "@djangocfg/i18n": "^2.1.168",
68
- "@djangocfg/ui-core": "^2.1.168",
69
- "@djangocfg/ui-tools": "^2.1.168",
66
+ "@djangocfg/api": "^2.1.169",
67
+ "@djangocfg/i18n": "^2.1.169",
68
+ "@djangocfg/ui-core": "^2.1.169",
69
+ "@djangocfg/ui-tools": "^2.1.169",
70
70
  "consola": "^3.4.2",
71
71
  "lucide-react": "^0.545.0",
72
72
  "moment": "^2.30.1",
@@ -74,11 +74,11 @@
74
74
  "react-dom": "^19.1.0"
75
75
  },
76
76
  "devDependencies": {
77
- "@djangocfg/api": "^2.1.168",
78
- "@djangocfg/i18n": "^2.1.168",
79
- "@djangocfg/typescript-config": "^2.1.168",
80
- "@djangocfg/ui-core": "^2.1.168",
81
- "@djangocfg/ui-tools": "^2.1.168",
77
+ "@djangocfg/api": "^2.1.169",
78
+ "@djangocfg/i18n": "^2.1.169",
79
+ "@djangocfg/typescript-config": "^2.1.169",
80
+ "@djangocfg/ui-core": "^2.1.169",
81
+ "@djangocfg/ui-tools": "^2.1.169",
82
82
  "@types/node": "^24.7.2",
83
83
  "@types/react": "^19.1.0",
84
84
  "@types/react-dom": "^19.1.0",
@@ -12,7 +12,12 @@ import moment from 'moment';
12
12
  import React, { useEffect, useMemo, useState } from 'react';
13
13
 
14
14
  import { useTypedT, type I18nTranslations } from '@djangocfg/i18n';
15
- import { Badge } from '@djangocfg/ui-core/components';
15
+ import {
16
+ Badge,
17
+ Popover,
18
+ PopoverContent,
19
+ PopoverTrigger,
20
+ } from '@djangocfg/ui-core/components';
16
21
 
17
22
  import { getConsolaLogger } from '../../core/logger/consolaLogger';
18
23
  import { useCentrifugo } from '../../providers/CentrifugoProvider';
@@ -24,10 +29,12 @@ const logger = getConsolaLogger('ConnectionStatus');
24
29
  // ─────────────────────────────────────────────────────────────────────────
25
30
 
26
31
  export interface ConnectionStatusProps {
27
- variant?: 'badge' | 'inline' | 'detailed';
32
+ variant?: 'badge' | 'inline' | 'detailed' | 'dot';
28
33
  showUptime?: boolean;
29
34
  showSubscriptions?: boolean;
30
35
  className?: string;
36
+ /** Size for dot variant */
37
+ dotSize?: 'sm' | 'md' | 'lg';
31
38
  }
32
39
 
33
40
  // ─────────────────────────────────────────────────────────────────────────
@@ -39,6 +46,7 @@ export function ConnectionStatus({
39
46
  showUptime = false,
40
47
  showSubscriptions = false,
41
48
  className = '',
49
+ dotSize = 'md',
42
50
  }: ConnectionStatusProps) {
43
51
  const t = useTypedT<I18nTranslations>();
44
52
  const { isConnected, client } = useCentrifugo();
@@ -116,6 +124,76 @@ export function ConnectionStatus({
116
124
  return () => clearInterval(interval);
117
125
  }, [client, isConnected]);
118
126
 
127
+ // Dot variant with popover
128
+ if (variant === 'dot') {
129
+ const dotSizeClasses = {
130
+ sm: 'h-2 w-2',
131
+ md: 'h-2.5 w-2.5',
132
+ lg: 'h-3 w-3',
133
+ };
134
+
135
+ const dotClass = dotSizeClasses[dotSize];
136
+ const statusColor = isConnected ? 'bg-green-500' : 'bg-red-500';
137
+ const pulseClass = isConnected ? 'animate-pulse' : '';
138
+
139
+ return (
140
+ <Popover>
141
+ <PopoverTrigger asChild>
142
+ <button
143
+ className={`relative flex items-center justify-center p-1.5 rounded-md hover:bg-muted/50 transition-colors ${className}`}
144
+ aria-label={isConnected ? labels.connected : labels.disconnected}
145
+ >
146
+ <span className={`${dotClass} rounded-full ${statusColor} ${pulseClass}`} />
147
+ </button>
148
+ </PopoverTrigger>
149
+ <PopoverContent className="w-48 p-3" align="end">
150
+ <div className="space-y-2">
151
+ {/* Status */}
152
+ <div className="flex items-center gap-2">
153
+ {isConnected ? (
154
+ <Wifi className="h-4 w-4 text-green-600" />
155
+ ) : (
156
+ <WifiOff className="h-4 w-4 text-red-600" />
157
+ )}
158
+ <span className="text-sm font-medium">
159
+ {isConnected ? labels.connected : labels.disconnected}
160
+ </span>
161
+ </div>
162
+
163
+ {/* Uptime */}
164
+ {isConnected && uptime && (
165
+ <div className="flex items-center justify-between text-xs text-muted-foreground">
166
+ <span className="flex items-center gap-1">
167
+ <Clock className="h-3 w-3" />
168
+ {labels.uptime}
169
+ </span>
170
+ <span className="font-mono">{uptime}</span>
171
+ </div>
172
+ )}
173
+
174
+ {/* Subscriptions */}
175
+ {isConnected && (
176
+ <div className="flex items-center justify-between text-xs text-muted-foreground">
177
+ <span className="flex items-center gap-1">
178
+ <Radio className="h-3 w-3" />
179
+ {labels.subscriptions}
180
+ </span>
181
+ <span className="font-mono">{activeSubscriptions}</span>
182
+ </div>
183
+ )}
184
+
185
+ {/* Disconnected message */}
186
+ {!isConnected && (
187
+ <p className="text-xs text-muted-foreground">
188
+ {labels.realtimeUnavailable}
189
+ </p>
190
+ )}
191
+ </div>
192
+ </PopoverContent>
193
+ </Popover>
194
+ );
195
+ }
196
+
119
197
  // Badge variant
120
198
  if (variant === 'badge') {
121
199
  return (