nitrostack 1.0.71 → 1.0.73

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 (253) hide show
  1. package/dist/auth/api-key.js.map +1 -1
  2. package/dist/auth/client.js.map +1 -1
  3. package/dist/auth/index.d.ts +2 -1
  4. package/dist/auth/index.d.ts.map +1 -1
  5. package/dist/auth/index.js +3 -0
  6. package/dist/auth/index.js.map +1 -1
  7. package/dist/auth/middleware.d.ts +1 -1
  8. package/dist/auth/middleware.d.ts.map +1 -1
  9. package/dist/auth/middleware.js.map +1 -1
  10. package/dist/auth/secure-secret.d.ts +136 -0
  11. package/dist/auth/secure-secret.d.ts.map +1 -0
  12. package/dist/auth/secure-secret.js +182 -0
  13. package/dist/auth/secure-secret.js.map +1 -0
  14. package/dist/auth/server-metadata.d.ts.map +1 -1
  15. package/dist/auth/server-metadata.js.map +1 -1
  16. package/dist/auth/simple-jwt.d.ts +100 -14
  17. package/dist/auth/simple-jwt.d.ts.map +1 -1
  18. package/dist/auth/simple-jwt.js +19 -9
  19. package/dist/auth/simple-jwt.js.map +1 -1
  20. package/dist/auth/token-store.js +1 -1
  21. package/dist/auth/token-store.js.map +1 -1
  22. package/dist/auth/token-validation.js +1 -1
  23. package/dist/auth/token-validation.js.map +1 -1
  24. package/dist/cli/commands/build.js +1 -1
  25. package/dist/cli/commands/build.js.map +1 -1
  26. package/dist/cli/commands/generate-types.js +12 -12
  27. package/dist/cli/commands/generate-types.js.map +1 -1
  28. package/dist/cli/commands/generate.d.ts +8 -1
  29. package/dist/cli/commands/generate.d.ts.map +1 -1
  30. package/dist/cli/commands/generate.js +13 -12
  31. package/dist/cli/commands/generate.js.map +1 -1
  32. package/dist/cli/commands/init.js +1 -1
  33. package/dist/cli/commands/init.js.map +1 -1
  34. package/dist/cli/commands/upgrade.d.ts +10 -0
  35. package/dist/cli/commands/upgrade.d.ts.map +1 -0
  36. package/dist/cli/commands/upgrade.js +221 -0
  37. package/dist/cli/commands/upgrade.js.map +1 -0
  38. package/dist/cli/index.js +7 -0
  39. package/dist/cli/index.js.map +1 -1
  40. package/dist/core/app-decorator.d.ts +4 -3
  41. package/dist/core/app-decorator.d.ts.map +1 -1
  42. package/dist/core/app-decorator.js +67 -28
  43. package/dist/core/app-decorator.js.map +1 -1
  44. package/dist/core/builders.d.ts +19 -7
  45. package/dist/core/builders.d.ts.map +1 -1
  46. package/dist/core/builders.js +15 -8
  47. package/dist/core/builders.js.map +1 -1
  48. package/dist/core/component.d.ts +8 -8
  49. package/dist/core/component.d.ts.map +1 -1
  50. package/dist/core/component.js +3 -2
  51. package/dist/core/component.js.map +1 -1
  52. package/dist/core/config-module.d.ts +11 -4
  53. package/dist/core/config-module.d.ts.map +1 -1
  54. package/dist/core/config-module.js +1 -1
  55. package/dist/core/config-module.js.map +1 -1
  56. package/dist/core/decorators/cache.decorator.d.ts +9 -9
  57. package/dist/core/decorators/cache.decorator.d.ts.map +1 -1
  58. package/dist/core/decorators/cache.decorator.js +3 -3
  59. package/dist/core/decorators/cache.decorator.js.map +1 -1
  60. package/dist/core/decorators/health-check.decorator.d.ts +3 -3
  61. package/dist/core/decorators/health-check.decorator.d.ts.map +1 -1
  62. package/dist/core/decorators/health-check.decorator.js +2 -2
  63. package/dist/core/decorators/health-check.decorator.js.map +1 -1
  64. package/dist/core/decorators/rate-limit.decorator.d.ts +5 -4
  65. package/dist/core/decorators/rate-limit.decorator.d.ts.map +1 -1
  66. package/dist/core/decorators/rate-limit.decorator.js +3 -3
  67. package/dist/core/decorators/rate-limit.decorator.js.map +1 -1
  68. package/dist/core/decorators.d.ts +47 -29
  69. package/dist/core/decorators.d.ts.map +1 -1
  70. package/dist/core/decorators.js +9 -9
  71. package/dist/core/decorators.js.map +1 -1
  72. package/dist/core/di/container.d.ts +21 -4
  73. package/dist/core/di/container.d.ts.map +1 -1
  74. package/dist/core/di/container.js +11 -7
  75. package/dist/core/di/container.js.map +1 -1
  76. package/dist/core/di/injectable.decorator.d.ts +5 -3
  77. package/dist/core/di/injectable.decorator.d.ts.map +1 -1
  78. package/dist/core/di/injectable.decorator.js.map +1 -1
  79. package/dist/core/errors.d.ts +4 -4
  80. package/dist/core/errors.d.ts.map +1 -1
  81. package/dist/core/errors.js.map +1 -1
  82. package/dist/core/events/event-emitter.d.ts +3 -3
  83. package/dist/core/events/event-emitter.d.ts.map +1 -1
  84. package/dist/core/events/event-emitter.js.map +1 -1
  85. package/dist/core/events/event.decorator.d.ts +5 -5
  86. package/dist/core/events/event.decorator.d.ts.map +1 -1
  87. package/dist/core/events/event.decorator.js +10 -6
  88. package/dist/core/events/event.decorator.js.map +1 -1
  89. package/dist/core/events/log-emitter.d.ts +7 -1
  90. package/dist/core/events/log-emitter.d.ts.map +1 -1
  91. package/dist/core/events/log-emitter.js.map +1 -1
  92. package/dist/core/filters/exception-filter.decorator.d.ts +5 -5
  93. package/dist/core/filters/exception-filter.decorator.d.ts.map +1 -1
  94. package/dist/core/filters/exception-filter.decorator.js +3 -3
  95. package/dist/core/filters/exception-filter.decorator.js.map +1 -1
  96. package/dist/core/filters/exception-filter.interface.d.ts +14 -5
  97. package/dist/core/filters/exception-filter.interface.d.ts.map +1 -1
  98. package/dist/core/guards/apikey.guard.d.ts +1 -1
  99. package/dist/core/guards/apikey.guard.d.ts.map +1 -1
  100. package/dist/core/guards/guard.interface.d.ts +1 -1
  101. package/dist/core/guards/guard.interface.d.ts.map +1 -1
  102. package/dist/core/guards/jwt.guard.d.ts +1 -1
  103. package/dist/core/guards/jwt.guard.d.ts.map +1 -1
  104. package/dist/core/guards/oauth.guard.d.ts +1 -1
  105. package/dist/core/guards/oauth.guard.d.ts.map +1 -1
  106. package/dist/core/guards/use-guards.decorator.d.ts +3 -3
  107. package/dist/core/guards/use-guards.decorator.d.ts.map +1 -1
  108. package/dist/core/guards/use-guards.decorator.js +1 -1
  109. package/dist/core/guards/use-guards.decorator.js.map +1 -1
  110. package/dist/core/index.d.ts +2 -2
  111. package/dist/core/index.d.ts.map +1 -1
  112. package/dist/core/index.js.map +1 -1
  113. package/dist/core/interceptors/interceptor.decorator.d.ts +4 -4
  114. package/dist/core/interceptors/interceptor.decorator.d.ts.map +1 -1
  115. package/dist/core/interceptors/interceptor.decorator.js +2 -2
  116. package/dist/core/interceptors/interceptor.decorator.js.map +1 -1
  117. package/dist/core/interceptors/interceptor.interface.d.ts +3 -3
  118. package/dist/core/interceptors/interceptor.interface.d.ts.map +1 -1
  119. package/dist/core/logger.d.ts.map +1 -1
  120. package/dist/core/logger.js.map +1 -1
  121. package/dist/core/middleware/middleware.decorator.d.ts +4 -4
  122. package/dist/core/middleware/middleware.decorator.d.ts.map +1 -1
  123. package/dist/core/middleware/middleware.decorator.js +2 -2
  124. package/dist/core/middleware/middleware.decorator.js.map +1 -1
  125. package/dist/core/middleware/middleware.interface.d.ts +3 -3
  126. package/dist/core/middleware/middleware.interface.d.ts.map +1 -1
  127. package/dist/core/module.d.ts +33 -14
  128. package/dist/core/module.d.ts.map +1 -1
  129. package/dist/core/module.js +11 -6
  130. package/dist/core/module.js.map +1 -1
  131. package/dist/core/oauth-module.d.ts +9 -3
  132. package/dist/core/oauth-module.d.ts.map +1 -1
  133. package/dist/core/oauth-module.js +4 -3
  134. package/dist/core/oauth-module.js.map +1 -1
  135. package/dist/core/pipes/pipe.decorator.d.ts +14 -5
  136. package/dist/core/pipes/pipe.decorator.d.ts.map +1 -1
  137. package/dist/core/pipes/pipe.decorator.js +2 -2
  138. package/dist/core/pipes/pipe.decorator.js.map +1 -1
  139. package/dist/core/pipes/pipe.interface.d.ts +9 -4
  140. package/dist/core/pipes/pipe.interface.d.ts.map +1 -1
  141. package/dist/core/prompt.d.ts +13 -4
  142. package/dist/core/prompt.d.ts.map +1 -1
  143. package/dist/core/prompt.js +2 -2
  144. package/dist/core/prompt.js.map +1 -1
  145. package/dist/core/resource.d.ts +7 -2
  146. package/dist/core/resource.d.ts.map +1 -1
  147. package/dist/core/resource.js +2 -2
  148. package/dist/core/resource.js.map +1 -1
  149. package/dist/core/server.d.ts +49 -3
  150. package/dist/core/server.d.ts.map +1 -1
  151. package/dist/core/server.js +61 -34
  152. package/dist/core/server.js.map +1 -1
  153. package/dist/core/tool.d.ts +44 -16
  154. package/dist/core/tool.d.ts.map +1 -1
  155. package/dist/core/tool.js +19 -6
  156. package/dist/core/tool.js.map +1 -1
  157. package/dist/core/transports/discovery-http-server.d.ts +7 -1
  158. package/dist/core/transports/discovery-http-server.d.ts.map +1 -1
  159. package/dist/core/transports/discovery-http-server.js.map +1 -1
  160. package/dist/core/transports/http-server.d.ts +2 -2
  161. package/dist/core/transports/http-server.d.ts.map +1 -1
  162. package/dist/core/transports/http-server.js +1 -1
  163. package/dist/core/transports/http-server.js.map +1 -1
  164. package/dist/core/transports/streamable-http.d.ts +4 -4
  165. package/dist/core/transports/streamable-http.d.ts.map +1 -1
  166. package/dist/core/transports/streamable-http.js +1 -1
  167. package/dist/core/transports/streamable-http.js.map +1 -1
  168. package/dist/core/types.d.ts +87 -15
  169. package/dist/core/types.d.ts.map +1 -1
  170. package/dist/core/widgets/widget-registry.d.ts +2 -2
  171. package/dist/core/widgets/widget-registry.d.ts.map +1 -1
  172. package/dist/core/widgets/widget-registry.js +1 -1
  173. package/dist/core/widgets/widget-registry.js.map +1 -1
  174. package/dist/testing/index.d.ts +44 -17
  175. package/dist/testing/index.d.ts.map +1 -1
  176. package/dist/testing/index.js +5 -8
  177. package/dist/testing/index.js.map +1 -1
  178. package/dist/ui-next/index.d.ts +1 -1
  179. package/dist/ui-next/index.d.ts.map +1 -1
  180. package/dist/ui-next/index.js.map +1 -1
  181. package/dist/widgets/hooks/useWidgetSDK.d.ts +5 -5
  182. package/dist/widgets/runtime/WidgetLayout.js.map +1 -1
  183. package/dist/widgets/sdk.d.ts +5 -5
  184. package/dist/widgets/sdk.d.ts.map +1 -1
  185. package/dist/widgets/sdk.js.map +1 -1
  186. package/package.json +1 -1
  187. package/src/studio/app/api/auth/fetch-metadata/route.ts +3 -2
  188. package/src/studio/app/api/auth/register-client/route.ts +3 -2
  189. package/src/studio/app/api/chat/route.ts +33 -17
  190. package/src/studio/app/api/health/checks/route.ts +5 -4
  191. package/src/studio/app/api/init/route.ts +3 -2
  192. package/src/studio/app/api/ping/route.ts +3 -2
  193. package/src/studio/app/api/prompts/[name]/route.ts +4 -3
  194. package/src/studio/app/api/prompts/route.ts +3 -2
  195. package/src/studio/app/api/resources/[...uri]/route.ts +3 -2
  196. package/src/studio/app/api/resources/route.ts +3 -2
  197. package/src/studio/app/api/roots/route.ts +3 -2
  198. package/src/studio/app/api/sampling/route.ts +3 -2
  199. package/src/studio/app/api/tools/[name]/call/route.ts +3 -2
  200. package/src/studio/app/api/tools/route.ts +4 -3
  201. package/src/studio/app/api/widget-examples/route.ts +5 -4
  202. package/src/studio/app/auth/callback/page.tsx +9 -8
  203. package/src/studio/app/chat/page.tsx +1535 -468
  204. package/src/studio/app/chat/page.tsx.backup +1046 -187
  205. package/src/studio/app/globals.css +361 -191
  206. package/src/studio/app/health/page.tsx +73 -77
  207. package/src/studio/app/layout.tsx +9 -11
  208. package/src/studio/app/logs/page.tsx +31 -32
  209. package/src/studio/app/page.tsx +136 -232
  210. package/src/studio/app/prompts/page.tsx +115 -97
  211. package/src/studio/app/resources/page.tsx +115 -124
  212. package/src/studio/app/settings/page.tsx +1083 -127
  213. package/src/studio/app/tools/page.tsx +343 -0
  214. package/src/studio/components/EnlargeModal.tsx +76 -65
  215. package/src/studio/components/LogMessage.tsx +6 -6
  216. package/src/studio/components/MarkdownRenderer.tsx +246 -349
  217. package/src/studio/components/Sidebar.tsx +165 -210
  218. package/src/studio/components/SplashScreen.tsx +109 -0
  219. package/src/studio/components/ToolCard.tsx +50 -41
  220. package/src/studio/components/VoiceOrbOverlay.tsx +475 -0
  221. package/src/studio/components/WidgetErrorBoundary.tsx +48 -0
  222. package/src/studio/components/WidgetRenderer.tsx +169 -211
  223. package/src/studio/components/ops/OpsCanvas.tsx +748 -0
  224. package/src/studio/components/ops/OpsNodeDetailPanel.tsx +150 -0
  225. package/src/studio/components/ops/OpsSummaryBar.tsx +90 -0
  226. package/src/studio/components/ops/index.ts +5 -0
  227. package/src/studio/components/ops/nodes/BaseNode.tsx +65 -0
  228. package/src/studio/components/ops/nodes/LLMCallNode.tsx +34 -0
  229. package/src/studio/components/ops/nodes/LLMResponseNode.tsx +33 -0
  230. package/src/studio/components/ops/nodes/ToolCallNode.tsx +30 -0
  231. package/src/studio/components/ops/nodes/ToolResultNode.tsx +43 -0
  232. package/src/studio/components/ops/nodes/UserPromptNode.tsx +34 -0
  233. package/src/studio/components/ops/nodes/WidgetRenderNode.tsx +23 -0
  234. package/src/studio/components/ops/nodes/index.ts +8 -0
  235. package/src/studio/components/tools/ToolsCanvas.tsx +327 -0
  236. package/src/studio/lib/api.ts +61 -42
  237. package/src/studio/lib/http-client-transport.ts +2 -2
  238. package/src/studio/lib/llm-service.ts +126 -47
  239. package/src/studio/lib/mcp-client.ts +9 -6
  240. package/src/studio/lib/ops-store.ts +427 -0
  241. package/src/studio/lib/ops-tracker.ts +416 -0
  242. package/src/studio/lib/ops-types.ts +164 -0
  243. package/src/studio/lib/store.ts +23 -11
  244. package/src/studio/lib/types.ts +228 -38
  245. package/src/studio/lib/widget-loader.ts +2 -2
  246. package/src/studio/package-lock.json +3303 -0
  247. package/src/studio/package.json +3 -1
  248. package/src/studio/public/NitroStudio Isotype Color.png +0 -0
  249. package/src/studio/tailwind.config.ts +63 -17
  250. package/templates/typescript-oauth/src/modules/flights/flights.prompts.ts +19 -22
  251. package/dist/cli/build-widgets.mjs +0 -165
  252. package/src/studio/app/auth/page.tsx +0 -560
  253. package/src/studio/app/ping/page.tsx +0 -209
@@ -1,209 +0,0 @@
1
- 'use client';
2
-
3
- import { useState } from 'react';
4
- import { useStudioStore } from '@/lib/store';
5
- import { api } from '@/lib/api';
6
- import { Wifi, Activity, Clock, TrendingUp, Radio } from 'lucide-react';
7
-
8
- export default function PingPage() {
9
- const { pingHistory, addPingResult } = useStudioStore();
10
- const [pinging, setPinging] = useState(false);
11
- const [lastLatency, setLastLatency] = useState<number | null>(null);
12
-
13
- const handlePing = async () => {
14
- setPinging(true);
15
- const startTime = Date.now();
16
-
17
- try {
18
- await api.ping();
19
- const latency = Date.now() - startTime;
20
- setLastLatency(latency);
21
- addPingResult({ time: new Date(), latency });
22
- } catch (error) {
23
- console.error('Ping failed:', error);
24
- } finally {
25
- setPinging(false);
26
- }
27
- };
28
-
29
- const averageLatency =
30
- pingHistory.length > 0
31
- ? Math.round(pingHistory.reduce((sum, p) => sum + p.latency, 0) / pingHistory.length)
32
- : null;
33
-
34
- const minLatency =
35
- pingHistory.length > 0
36
- ? Math.min(...pingHistory.map((p) => p.latency))
37
- : null;
38
-
39
- const maxLatency =
40
- pingHistory.length > 0
41
- ? Math.max(...pingHistory.map((p) => p.latency))
42
- : null;
43
-
44
- const getLatencyColor = (latency: number) => {
45
- if (latency < 100) return 'text-emerald-500';
46
- if (latency < 500) return 'text-amber-500';
47
- return 'text-rose-500';
48
- };
49
-
50
- const getLatencyBg = (latency: number) => {
51
- if (latency < 100) return 'bg-emerald-500/10 border-emerald-500/20';
52
- if (latency < 500) return 'bg-amber-500/10 border-amber-500/20';
53
- return 'bg-rose-500/10 border-rose-500/20';
54
- };
55
-
56
- const getLatencyDotColor = (latency: number) => {
57
- if (latency < 100) return 'bg-emerald-500';
58
- if (latency < 500) return 'bg-amber-500';
59
- return 'bg-rose-500';
60
- };
61
-
62
- return (
63
- <div className="fixed inset-0 flex flex-col bg-background" style={{ left: 'var(--sidebar-width, 15rem)' }}>
64
- {/* Sticky Header */}
65
- <div className="sticky top-0 z-10 border-b border-border/50 px-6 py-3 flex items-center justify-between bg-card/80 backdrop-blur-md shadow-sm">
66
- <div className="flex items-center gap-3">
67
- <div className="w-8 h-8 rounded-lg bg-gradient-to-br from-cyan-500 to-blue-500 flex items-center justify-center shadow-md">
68
- <Wifi className="w-5 h-5 text-white" strokeWidth={2.5} />
69
- </div>
70
- <div>
71
- <h1 className="text-lg font-bold text-foreground">Ping</h1>
72
- </div>
73
- </div>
74
- </div>
75
-
76
- {/* Content - ONLY this scrolls */}
77
- <div className="flex-1 overflow-y-auto overflow-x-hidden">
78
- <div className="max-w-4xl mx-auto px-6 py-6">
79
-
80
- {/* Main Ping Card */}
81
- <div className="card card-hover p-8 mb-8 text-center bg-gradient-to-br from-card via-card to-muted/20">
82
- <button
83
- onClick={handlePing}
84
- disabled={pinging}
85
- className="btn btn-primary btn-lg mx-auto px-12 py-4 text-lg gap-3 shadow-lg hover:shadow-xl transition-all"
86
- >
87
- {pinging ? (
88
- <>
89
- <Radio className="w-6 h-6 animate-pulse" />
90
- Pinging...
91
- </>
92
- ) : (
93
- <>
94
- <Wifi className="w-6 h-6" />
95
- Send Ping
96
- </>
97
- )}
98
- </button>
99
-
100
- {lastLatency !== null && (
101
- <div className="mt-8 animate-fade-in">
102
- <div className={`inline-block px-8 py-4 rounded-2xl border ${getLatencyBg(lastLatency)}`}>
103
- <div className={`text-6xl font-bold ${getLatencyColor(lastLatency)}`}>
104
- {lastLatency}ms
105
- </div>
106
- <div className="text-muted-foreground mt-2 flex items-center justify-center gap-2">
107
- <Clock className="w-4 h-4" />
108
- Last ping latency
109
- </div>
110
- </div>
111
- </div>
112
- )}
113
- </div>
114
-
115
- {/* Statistics Grid */}
116
- {pingHistory.length > 0 && (
117
- <div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
118
- {/* Average */}
119
- <div className="card card-hover p-6">
120
- <div className="flex items-center gap-3 mb-3">
121
- <div className="w-10 h-10 rounded-lg bg-blue-500/10 flex items-center justify-center">
122
- <TrendingUp className="w-5 h-5 text-blue-500" />
123
- </div>
124
- <h3 className="font-semibold text-foreground">Average</h3>
125
- </div>
126
- <div className="text-3xl font-bold text-foreground">{averageLatency}ms</div>
127
- <p className="text-sm text-muted-foreground mt-1">{pingHistory.length} total pings</p>
128
- </div>
129
-
130
- {/* Min */}
131
- <div className="card card-hover p-6">
132
- <div className="flex items-center gap-3 mb-3">
133
- <div className="w-10 h-10 rounded-lg bg-emerald-500/10 flex items-center justify-center">
134
- <Activity className="w-5 h-5 text-emerald-500" />
135
- </div>
136
- <h3 className="font-semibold text-foreground">Fastest</h3>
137
- </div>
138
- <div className="text-3xl font-bold text-emerald-500">{minLatency}ms</div>
139
- <p className="text-sm text-muted-foreground mt-1">Best response time</p>
140
- </div>
141
-
142
- {/* Max */}
143
- <div className="card card-hover p-6">
144
- <div className="flex items-center gap-3 mb-3">
145
- <div className="w-10 h-10 rounded-lg bg-amber-500/10 flex items-center justify-center">
146
- <Clock className="w-5 h-5 text-amber-500" />
147
- </div>
148
- <h3 className="font-semibold text-foreground">Slowest</h3>
149
- </div>
150
- <div className="text-3xl font-bold text-amber-500">{maxLatency}ms</div>
151
- <p className="text-sm text-muted-foreground mt-1">Worst response time</p>
152
- </div>
153
- </div>
154
- )}
155
-
156
- {/* Ping History */}
157
- {pingHistory.length > 0 && (
158
- <div>
159
- <h2 className="text-2xl font-semibold text-foreground mb-6 flex items-center gap-2">
160
- <Activity className="w-6 h-6 text-primary" />
161
- Recent Pings
162
- </h2>
163
- <div className="space-y-3">
164
- {pingHistory.slice().reverse().map((ping, idx) => (
165
- <div
166
- key={idx}
167
- className="card card-hover p-5 flex items-center justify-between animate-fade-in"
168
- >
169
- <div className="flex items-center gap-3">
170
- <div className={`w-3 h-3 rounded-full ${getLatencyDotColor(ping.latency)} shadow-lg`} />
171
- <span className="text-sm text-muted-foreground font-mono">
172
- {ping.time.toLocaleTimeString()}
173
- </span>
174
- </div>
175
- <div className="flex items-center gap-3">
176
- <span className={`text-lg font-bold ${getLatencyColor(ping.latency)}`}>
177
- {ping.latency}ms
178
- </span>
179
- <span className={`badge ${
180
- ping.latency < 100
181
- ? 'badge-success'
182
- : ping.latency < 500
183
- ? 'badge-warning'
184
- : 'badge-error'
185
- }`}>
186
- {ping.latency < 100 ? 'Excellent' : ping.latency < 500 ? 'Good' : 'Slow'}
187
- </span>
188
- </div>
189
- </div>
190
- ))}
191
- </div>
192
- </div>
193
- )}
194
-
195
- {/* Empty State */}
196
- {pingHistory.length === 0 && !pinging && (
197
- <div className="empty-state">
198
- <Wifi className="empty-state-icon" />
199
- <p className="empty-state-title">No ping history yet</p>
200
- <p className="empty-state-description">
201
- Click the "Send Ping" button above to test your connection
202
- </p>
203
- </div>
204
- )}
205
- </div>
206
- </div>
207
- </div>
208
- );
209
- }