@wakastellar/ui 2.1.2 → 2.3.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.
Files changed (123) hide show
  1. package/dist/blocks/apm-overview/index.d.ts +58 -0
  2. package/dist/blocks/cicd-builder/index.d.ts +47 -0
  3. package/dist/blocks/cloud-cost-dashboard/index.d.ts +49 -0
  4. package/dist/blocks/container-orchestrator/index.d.ts +63 -0
  5. package/dist/blocks/database-admin/index.d.ts +84 -0
  6. package/dist/blocks/gitops-sync-status/index.d.ts +45 -0
  7. package/dist/blocks/incident-manager/index.d.ts +44 -0
  8. package/dist/blocks/index.d.ts +10 -0
  9. package/dist/blocks/infrastructure-map/index.d.ts +32 -0
  10. package/dist/blocks/on-call-schedule/index.d.ts +43 -0
  11. package/dist/blocks/release-notes/index.d.ts +49 -0
  12. package/dist/components/index.d.ts +34 -0
  13. package/dist/components/waka-ad-banner/index.d.ts +36 -0
  14. package/dist/components/waka-ad-fallback/index.d.ts +33 -0
  15. package/dist/components/waka-ad-inline/index.d.ts +15 -0
  16. package/dist/components/waka-ad-interstitial/index.d.ts +26 -0
  17. package/dist/components/waka-ad-placeholder/index.d.ts +17 -0
  18. package/dist/components/waka-ad-provider/index.d.ts +103 -0
  19. package/dist/components/waka-ad-sidebar/index.d.ts +18 -0
  20. package/dist/components/waka-ad-sticky-footer/index.d.ts +17 -0
  21. package/dist/components/waka-alert-panel/index.d.ts +45 -0
  22. package/dist/components/waka-artifact-list/index.d.ts +32 -0
  23. package/dist/components/waka-build-matrix/index.d.ts +36 -0
  24. package/dist/components/waka-config-comparator/index.d.ts +37 -0
  25. package/dist/components/waka-container-list/index.d.ts +51 -0
  26. package/dist/components/waka-content-recommendation/index.d.ts +23 -0
  27. package/dist/components/waka-database-card/index.d.ts +46 -0
  28. package/dist/components/waka-dependency-tree/index.d.ts +38 -0
  29. package/dist/components/waka-env-var-editor/index.d.ts +30 -0
  30. package/dist/components/waka-feature-flag-row/index.d.ts +45 -0
  31. package/dist/components/waka-kubernetes-overview/index.d.ts +98 -0
  32. package/dist/components/waka-log-viewer/index.d.ts +38 -0
  33. package/dist/components/waka-migration-list/index.d.ts +36 -0
  34. package/dist/components/waka-outstream-video/index.d.ts +24 -0
  35. package/dist/components/waka-pod-card/index.d.ts +73 -0
  36. package/dist/components/waka-query-explain/index.d.ts +48 -0
  37. package/dist/components/waka-secret-card/index.d.ts +43 -0
  38. package/dist/components/waka-security-scan-result/index.d.ts +45 -0
  39. package/dist/components/waka-service-graph/index.d.ts +44 -0
  40. package/dist/components/waka-sponsored-badge/index.d.ts +20 -0
  41. package/dist/components/waka-sponsored-card/index.d.ts +25 -0
  42. package/dist/components/waka-sponsored-feed/index.d.ts +31 -0
  43. package/dist/components/waka-test-report/index.d.ts +60 -0
  44. package/dist/components/waka-trace-viewer/index.d.ts +36 -0
  45. package/dist/components/waka-video-ad/index.d.ts +32 -0
  46. package/dist/components/waka-video-overlay/index.d.ts +26 -0
  47. package/dist/index.cjs.js +251 -200
  48. package/dist/index.d.ts +1 -0
  49. package/dist/index.es.js +47315 -35823
  50. package/dist/utils/security.d.ts +96 -0
  51. package/package.json +4 -4
  52. package/src/blocks/apm-overview/index.tsx +672 -0
  53. package/src/blocks/cicd-builder/index.tsx +738 -0
  54. package/src/blocks/cloud-cost-dashboard/index.tsx +597 -0
  55. package/src/blocks/container-orchestrator/index.tsx +729 -0
  56. package/src/blocks/database-admin/index.tsx +679 -0
  57. package/src/blocks/gitops-sync-status/index.tsx +557 -0
  58. package/src/blocks/incident-manager/index.tsx +586 -0
  59. package/src/blocks/index.ts +119 -0
  60. package/src/blocks/infrastructure-map/index.tsx +638 -0
  61. package/src/blocks/on-call-schedule/index.tsx +615 -0
  62. package/src/blocks/release-notes/index.tsx +643 -0
  63. package/src/blocks/sidebar/index.tsx +6 -6
  64. package/src/components/DataTable/templates/index.tsx +3 -2
  65. package/src/components/index.ts +283 -0
  66. package/src/components/waka-3d-pie-chart/index.tsx +11 -11
  67. package/src/components/waka-achievement-unlock/index.tsx +16 -16
  68. package/src/components/waka-ad-banner/index.tsx +275 -0
  69. package/src/components/waka-ad-fallback/index.tsx +181 -0
  70. package/src/components/waka-ad-inline/index.tsx +103 -0
  71. package/src/components/waka-ad-interstitial/index.tsx +278 -0
  72. package/src/components/waka-ad-placeholder/index.tsx +84 -0
  73. package/src/components/waka-ad-provider/index.tsx +329 -0
  74. package/src/components/waka-ad-sidebar/index.tsx +113 -0
  75. package/src/components/waka-ad-sticky-footer/index.tsx +125 -0
  76. package/src/components/waka-alert-panel/index.tsx +493 -0
  77. package/src/components/waka-artifact-list/index.tsx +416 -0
  78. package/src/components/waka-badge-showcase/index.tsx +12 -11
  79. package/src/components/waka-build-matrix/index.tsx +396 -0
  80. package/src/components/waka-command-bar/index.tsx +2 -1
  81. package/src/components/waka-config-comparator/index.tsx +416 -0
  82. package/src/components/waka-container-list/index.tsx +475 -0
  83. package/src/components/waka-content-recommendation/index.tsx +294 -0
  84. package/src/components/waka-cost-breakdown/index.tsx +10 -10
  85. package/src/components/waka-database-card/index.tsx +473 -0
  86. package/src/components/waka-dependency-tree/index.tsx +542 -0
  87. package/src/components/waka-env-var-editor/index.tsx +417 -0
  88. package/src/components/waka-feature-flag-row/index.tsx +386 -0
  89. package/src/components/waka-funnel-chart/index.tsx +8 -8
  90. package/src/components/waka-health-pulse/index.tsx +6 -6
  91. package/src/components/waka-kubernetes-overview/index.tsx +536 -0
  92. package/src/components/waka-leaderboard/index.tsx +9 -9
  93. package/src/components/waka-log-viewer/index.tsx +386 -0
  94. package/src/components/waka-loot-box/index.tsx +20 -20
  95. package/src/components/waka-migration-list/index.tsx +487 -0
  96. package/src/components/waka-outstream-video/index.tsx +240 -0
  97. package/src/components/waka-player-card/index.tsx +5 -5
  98. package/src/components/waka-pod-card/index.tsx +528 -0
  99. package/src/components/waka-query-explain/index.tsx +657 -0
  100. package/src/components/waka-quota-bar/index.tsx +4 -4
  101. package/src/components/waka-radar-score/index.tsx +10 -10
  102. package/src/components/waka-scratch-card/index.tsx +5 -4
  103. package/src/components/waka-secret-card/index.tsx +371 -0
  104. package/src/components/waka-security-scan-result/index.tsx +473 -0
  105. package/src/components/waka-server-rack/index.tsx +28 -27
  106. package/src/components/waka-service-graph/index.tsx +445 -0
  107. package/src/components/waka-sponsored-badge/index.tsx +97 -0
  108. package/src/components/waka-sponsored-card/index.tsx +275 -0
  109. package/src/components/waka-sponsored-feed/index.tsx +127 -0
  110. package/src/components/waka-spotlight/index.tsx +2 -1
  111. package/src/components/waka-success-explosion/index.tsx +4 -4
  112. package/src/components/waka-test-report/index.tsx +469 -0
  113. package/src/components/waka-trace-viewer/index.tsx +490 -0
  114. package/src/components/waka-video-ad/index.tsx +406 -0
  115. package/src/components/waka-video-overlay/index.tsx +257 -0
  116. package/src/components/waka-xp-bar/index.tsx +13 -13
  117. package/src/styles/base.css +16 -0
  118. package/src/styles/tailwind.preset.js +12 -0
  119. package/src/styles/themes/forest.css +16 -0
  120. package/src/styles/themes/monochrome.css +16 -0
  121. package/src/styles/themes/perpetuity.css +16 -0
  122. package/src/styles/themes/sunset.css +16 -0
  123. package/src/styles/themes/twilight.css +16 -0
@@ -0,0 +1,396 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { cn } from "../../utils/cn"
5
+ import { Badge } from "../badge"
6
+ import { Button } from "../button"
7
+ import { ScrollArea } from "../scroll-area"
8
+ import {
9
+ Tooltip,
10
+ TooltipContent,
11
+ TooltipProvider,
12
+ TooltipTrigger,
13
+ } from "../tooltip"
14
+ import {
15
+ CheckCircle2,
16
+ XCircle,
17
+ Loader2,
18
+ Clock,
19
+ SkipForward,
20
+ RefreshCw,
21
+ Grid3X3,
22
+ ChevronDown,
23
+ ChevronRight,
24
+ ExternalLink,
25
+ } from "lucide-react"
26
+
27
+ export type BuildStatus = "success" | "failed" | "running" | "pending" | "skipped" | "cancelled"
28
+
29
+ export interface BuildCell {
30
+ id: string
31
+ status: BuildStatus
32
+ duration?: number // in seconds
33
+ startedAt?: Date
34
+ finishedAt?: Date
35
+ url?: string
36
+ logs?: string
37
+ }
38
+
39
+ export interface BuildMatrixRow {
40
+ label: string
41
+ description?: string
42
+ cells: BuildCell[]
43
+ }
44
+
45
+ export interface WakaBuildMatrixProps {
46
+ /** Column headers (e.g., OS names or versions) */
47
+ columns: string[]
48
+ /** Row data with cells */
49
+ rows: BuildMatrixRow[]
50
+ /** Callback when clicking on a cell */
51
+ onCellClick?: (rowIndex: number, colIndex: number, cell: BuildCell) => void
52
+ /** Callback when retrying a build */
53
+ onRetry?: (rowIndex: number, colIndex: number) => void
54
+ /** Callback when viewing logs */
55
+ onViewLogs?: (cell: BuildCell) => void
56
+ /** Title of the matrix */
57
+ title?: string
58
+ /** Show duration in cells */
59
+ showDuration?: boolean
60
+ /** Custom class name */
61
+ className?: string
62
+ }
63
+
64
+ const statusConfig: Record<BuildStatus, { icon: React.ElementType; color: string; bgColor: string; label: string }> = {
65
+ success: { icon: CheckCircle2, color: "text-green-500", bgColor: "bg-green-500", label: "Success" },
66
+ failed: { icon: XCircle, color: "text-red-500", bgColor: "bg-red-500", label: "Failed" },
67
+ running: { icon: Loader2, color: "text-blue-500", bgColor: "bg-blue-500", label: "Running" },
68
+ pending: { icon: Clock, color: "text-gray-400", bgColor: "bg-gray-400", label: "Pending" },
69
+ skipped: { icon: SkipForward, color: "text-gray-500", bgColor: "bg-gray-500", label: "Skipped" },
70
+ cancelled: { icon: XCircle, color: "text-orange-500", bgColor: "bg-orange-500", label: "Cancelled" },
71
+ }
72
+
73
+ function formatDuration(seconds: number): string {
74
+ if (seconds < 60) return `${seconds}s`
75
+ const minutes = Math.floor(seconds / 60)
76
+ const secs = seconds % 60
77
+ if (minutes < 60) return `${minutes}m ${secs}s`
78
+ const hours = Math.floor(minutes / 60)
79
+ return `${hours}h ${minutes % 60}m`
80
+ }
81
+
82
+ function BuildCellComponent({
83
+ cell,
84
+ onClick,
85
+ showDuration,
86
+ }: {
87
+ cell: BuildCell
88
+ onClick?: () => void
89
+ showDuration: boolean
90
+ }) {
91
+ const config = statusConfig[cell.status]
92
+ const Icon = config.icon
93
+
94
+ return (
95
+ <TooltipProvider>
96
+ <Tooltip>
97
+ <TooltipTrigger asChild>
98
+ <button
99
+ className={cn(
100
+ "w-12 h-12 rounded-lg flex flex-col items-center justify-center gap-0.5 transition-all",
101
+ "hover:scale-105 hover:shadow-md cursor-pointer",
102
+ "border border-transparent",
103
+ cell.status === "success" && "bg-green-500/10 hover:border-green-500/50",
104
+ cell.status === "failed" && "bg-red-500/10 hover:border-red-500/50",
105
+ cell.status === "running" && "bg-blue-500/10 hover:border-blue-500/50",
106
+ cell.status === "pending" && "bg-gray-500/10 hover:border-gray-500/50",
107
+ cell.status === "skipped" && "bg-gray-500/5 hover:border-gray-500/30",
108
+ cell.status === "cancelled" && "bg-orange-500/10 hover:border-orange-500/50"
109
+ )}
110
+ onClick={onClick}
111
+ >
112
+ <Icon
113
+ className={cn(
114
+ "h-5 w-5",
115
+ config.color,
116
+ cell.status === "running" && "animate-spin"
117
+ )}
118
+ />
119
+ {showDuration && cell.duration && (
120
+ <span className="text-[10px] text-muted-foreground">
121
+ {formatDuration(cell.duration)}
122
+ </span>
123
+ )}
124
+ </button>
125
+ </TooltipTrigger>
126
+ <TooltipContent>
127
+ <div className="space-y-1">
128
+ <div className="font-medium">{config.label}</div>
129
+ {cell.duration && <div className="text-xs">Duration: {formatDuration(cell.duration)}</div>}
130
+ {cell.startedAt && (
131
+ <div className="text-xs">Started: {cell.startedAt.toLocaleString()}</div>
132
+ )}
133
+ </div>
134
+ </TooltipContent>
135
+ </Tooltip>
136
+ </TooltipProvider>
137
+ )
138
+ }
139
+
140
+ export function WakaBuildMatrix({
141
+ columns,
142
+ rows,
143
+ onCellClick,
144
+ onRetry,
145
+ onViewLogs,
146
+ title = "Build Matrix",
147
+ showDuration = true,
148
+ className,
149
+ }: WakaBuildMatrixProps) {
150
+ const [expandedRows, setExpandedRows] = React.useState<Set<number>>(new Set())
151
+
152
+ const toggleRow = (index: number) => {
153
+ setExpandedRows((prev) => {
154
+ const next = new Set(prev)
155
+ if (next.has(index)) {
156
+ next.delete(index)
157
+ } else {
158
+ next.add(index)
159
+ }
160
+ return next
161
+ })
162
+ }
163
+
164
+ // Calculate summary stats
165
+ const stats = React.useMemo(() => {
166
+ let total = 0
167
+ let success = 0
168
+ let failed = 0
169
+ let running = 0
170
+
171
+ rows.forEach((row) => {
172
+ row.cells.forEach((cell) => {
173
+ total++
174
+ if (cell.status === "success") success++
175
+ if (cell.status === "failed") failed++
176
+ if (cell.status === "running") running++
177
+ })
178
+ })
179
+
180
+ return { total, success, failed, running, passRate: total > 0 ? (success / total) * 100 : 0 }
181
+ }, [rows])
182
+
183
+ return (
184
+ <div className={cn("border rounded-lg bg-background", className)}>
185
+ {/* Header */}
186
+ <div className="flex items-center justify-between gap-4 p-3 border-b">
187
+ <div className="flex items-center gap-3">
188
+ <Grid3X3 className="h-5 w-5" />
189
+ <h3 className="font-semibold">{title}</h3>
190
+ </div>
191
+
192
+ <div className="flex items-center gap-2">
193
+ <Badge variant="secondary" className="text-xs">
194
+ {stats.total} jobs
195
+ </Badge>
196
+ {stats.success > 0 && (
197
+ <Badge className="bg-green-500 text-xs">{stats.success} passed</Badge>
198
+ )}
199
+ {stats.failed > 0 && (
200
+ <Badge className="bg-red-500 text-xs">{stats.failed} failed</Badge>
201
+ )}
202
+ {stats.running > 0 && (
203
+ <Badge className="bg-blue-500 text-xs">{stats.running} running</Badge>
204
+ )}
205
+ </div>
206
+ </div>
207
+
208
+ {/* Legend */}
209
+ <div className="flex items-center gap-4 px-3 py-2 border-b bg-muted/30 text-xs flex-wrap">
210
+ {Object.entries(statusConfig).map(([status, config]) => {
211
+ const Icon = config.icon
212
+ return (
213
+ <div key={status} className="flex items-center gap-1.5">
214
+ <Icon className={cn("h-3 w-3", config.color)} />
215
+ <span>{config.label}</span>
216
+ </div>
217
+ )
218
+ })}
219
+ </div>
220
+
221
+ {/* Matrix */}
222
+ <ScrollArea className="max-h-[500px]">
223
+ <div className="p-3">
224
+ <table className="w-full">
225
+ <thead>
226
+ <tr>
227
+ <th className="text-left p-2 text-sm font-medium text-muted-foreground w-48">
228
+ Configuration
229
+ </th>
230
+ {columns.map((col, i) => (
231
+ <th key={i} className="p-2 text-center text-sm font-medium text-muted-foreground">
232
+ {col}
233
+ </th>
234
+ ))}
235
+ </tr>
236
+ </thead>
237
+ <tbody>
238
+ {rows.map((row, rowIndex) => {
239
+ const isExpanded = expandedRows.has(rowIndex)
240
+ const rowStats = {
241
+ success: row.cells.filter((c) => c.status === "success").length,
242
+ failed: row.cells.filter((c) => c.status === "failed").length,
243
+ total: row.cells.length,
244
+ }
245
+
246
+ return (
247
+ <React.Fragment key={rowIndex}>
248
+ <tr className="border-t hover:bg-muted/30">
249
+ <td className="p-2">
250
+ <button
251
+ className="flex items-center gap-2 text-left w-full"
252
+ onClick={() => toggleRow(rowIndex)}
253
+ >
254
+ {isExpanded ? (
255
+ <ChevronDown className="h-4 w-4 text-muted-foreground" />
256
+ ) : (
257
+ <ChevronRight className="h-4 w-4 text-muted-foreground" />
258
+ )}
259
+ <div>
260
+ <div className="font-medium text-sm">{row.label}</div>
261
+ {row.description && (
262
+ <div className="text-xs text-muted-foreground">{row.description}</div>
263
+ )}
264
+ </div>
265
+ </button>
266
+ </td>
267
+ {row.cells.map((cell, colIndex) => (
268
+ <td key={colIndex} className="p-2">
269
+ <div className="flex justify-center">
270
+ <BuildCellComponent
271
+ cell={cell}
272
+ onClick={() => onCellClick?.(rowIndex, colIndex, cell)}
273
+ showDuration={showDuration}
274
+ />
275
+ </div>
276
+ </td>
277
+ ))}
278
+ </tr>
279
+
280
+ {/* Expanded row details */}
281
+ {isExpanded && (
282
+ <tr className="bg-muted/20">
283
+ <td colSpan={columns.length + 1} className="p-4">
284
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
285
+ {row.cells.map((cell, colIndex) => {
286
+ const config = statusConfig[cell.status]
287
+ const Icon = config.icon
288
+ return (
289
+ <div
290
+ key={colIndex}
291
+ className="border rounded-lg p-3 bg-background"
292
+ >
293
+ <div className="flex items-center justify-between mb-2">
294
+ <div className="flex items-center gap-2">
295
+ <Icon className={cn("h-4 w-4", config.color)} />
296
+ <span className="font-medium text-sm">{columns[colIndex]}</span>
297
+ </div>
298
+ <Badge variant="outline" className={config.color}>
299
+ {config.label}
300
+ </Badge>
301
+ </div>
302
+ <div className="text-xs text-muted-foreground space-y-1">
303
+ {cell.duration && (
304
+ <div>Duration: {formatDuration(cell.duration)}</div>
305
+ )}
306
+ {cell.startedAt && (
307
+ <div>Started: {cell.startedAt.toLocaleTimeString()}</div>
308
+ )}
309
+ </div>
310
+ <div className="flex items-center gap-2 mt-3">
311
+ {cell.url && (
312
+ <Button
313
+ variant="outline"
314
+ size="sm"
315
+ className="h-7 text-xs"
316
+ onClick={() => window.open(cell.url, "_blank")}
317
+ >
318
+ <ExternalLink className="h-3 w-3 mr-1" />
319
+ View
320
+ </Button>
321
+ )}
322
+ {cell.status === "failed" && onRetry && (
323
+ <Button
324
+ variant="outline"
325
+ size="sm"
326
+ className="h-7 text-xs"
327
+ onClick={() => onRetry(rowIndex, colIndex)}
328
+ >
329
+ <RefreshCw className="h-3 w-3 mr-1" />
330
+ Retry
331
+ </Button>
332
+ )}
333
+ </div>
334
+ </div>
335
+ )
336
+ })}
337
+ </div>
338
+ </td>
339
+ </tr>
340
+ )}
341
+ </React.Fragment>
342
+ )
343
+ })}
344
+ </tbody>
345
+ </table>
346
+ </div>
347
+ </ScrollArea>
348
+
349
+ {/* Footer with pass rate */}
350
+ <div className="flex items-center justify-between px-3 py-2 border-t bg-muted/30 text-sm">
351
+ <span className="text-muted-foreground">
352
+ Pass Rate: <span className="font-medium text-foreground">{stats.passRate.toFixed(1)}%</span>
353
+ </span>
354
+ <span className="text-muted-foreground">
355
+ {stats.success}/{stats.total} jobs passed
356
+ </span>
357
+ </div>
358
+ </div>
359
+ )
360
+ }
361
+
362
+ // Default sample data for demo
363
+ export const defaultBuildMatrixColumns = ["Ubuntu 22.04", "Ubuntu 20.04", "macOS 13", "Windows 2022"]
364
+
365
+ export const defaultBuildMatrixRows: BuildMatrixRow[] = [
366
+ {
367
+ label: "Node.js 20",
368
+ description: "LTS version",
369
+ cells: [
370
+ { id: "1", status: "success", duration: 125 },
371
+ { id: "2", status: "success", duration: 142 },
372
+ { id: "3", status: "success", duration: 98 },
373
+ { id: "4", status: "success", duration: 156 },
374
+ ],
375
+ },
376
+ {
377
+ label: "Node.js 18",
378
+ description: "Previous LTS",
379
+ cells: [
380
+ { id: "5", status: "success", duration: 118 },
381
+ { id: "6", status: "success", duration: 135 },
382
+ { id: "7", status: "failed", duration: 45 },
383
+ { id: "8", status: "success", duration: 162 },
384
+ ],
385
+ },
386
+ {
387
+ label: "Node.js 21",
388
+ description: "Current",
389
+ cells: [
390
+ { id: "9", status: "running", startedAt: new Date() },
391
+ { id: "10", status: "pending" },
392
+ { id: "11", status: "pending" },
393
+ { id: "12", status: "pending" },
394
+ ],
395
+ },
396
+ ]
@@ -2,6 +2,7 @@
2
2
 
3
3
  import * as React from "react"
4
4
  import { cn } from "../../utils/cn"
5
+ import { safeNavigate } from "../../utils/security"
5
6
  import { Command, Search, ArrowRight, CornerDownLeft, Hash, Settings, User, FileText, Zap } from "lucide-react"
6
7
 
7
8
  // ============================================================================
@@ -214,7 +215,7 @@ export function WakaCommandBar({
214
215
  onSelect?.(item)
215
216
  item.action?.()
216
217
  if (item.href) {
217
- window.location.href = item.href
218
+ safeNavigate(item.href)
218
219
  }
219
220
  onOpenChange(false)
220
221
  }