@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
@@ -366,3 +366,286 @@ export {
366
366
  type UseTooltipTourOptions,
367
367
  type UseTooltipTourReturn,
368
368
  } from './waka-tooltip-tour'
369
+
370
+ // DevOps - Monitoring & Logs Components
371
+ export {
372
+ WakaLogViewer,
373
+ defaultLogs,
374
+ type LogEntry,
375
+ type LogLevel as WakaLogLevel,
376
+ type WakaLogViewerProps,
377
+ } from './waka-log-viewer'
378
+
379
+ export {
380
+ WakaTraceViewer,
381
+ defaultTraceSpans,
382
+ type TraceSpan,
383
+ type SpanStatus,
384
+ type WakaTraceViewerProps,
385
+ } from './waka-trace-viewer'
386
+
387
+ export {
388
+ WakaAlertPanel,
389
+ defaultAlerts as defaultPanelAlerts,
390
+ type Alert as WakaPanelAlert,
391
+ type AlertSeverity as WakaPanelAlertSeverity,
392
+ type AlertStatus as WakaPanelAlertStatus,
393
+ type WakaAlertPanelProps,
394
+ } from './waka-alert-panel'
395
+
396
+ // DevOps - Containers & Kubernetes Components
397
+ export {
398
+ WakaContainerList,
399
+ defaultContainers,
400
+ type Container,
401
+ type ContainerStatus as WakaContainerStatus,
402
+ type ContainerResource,
403
+ type WakaContainerListProps,
404
+ } from './waka-container-list'
405
+
406
+ export {
407
+ WakaKubernetesOverview,
408
+ defaultK8sNodes,
409
+ defaultK8sPods,
410
+ defaultK8sDeployments,
411
+ defaultK8sServices,
412
+ defaultK8sNamespaces,
413
+ type K8sNode,
414
+ type K8sPod,
415
+ type K8sDeployment,
416
+ type K8sService,
417
+ type K8sNamespace,
418
+ type NodeStatus as K8sNodeStatus,
419
+ type PodPhase as K8sPodPhase,
420
+ type DeploymentStatus as K8sDeploymentStatus,
421
+ type WakaKubernetesOverviewProps,
422
+ } from './waka-kubernetes-overview'
423
+
424
+ export {
425
+ WakaPodCard,
426
+ defaultPodDetails,
427
+ type PodDetails,
428
+ type PodContainer,
429
+ type PodEvent,
430
+ type PodPhase,
431
+ type ContainerState,
432
+ type WakaPodCardProps,
433
+ } from './waka-pod-card'
434
+
435
+ export {
436
+ WakaServiceGraph,
437
+ defaultServices,
438
+ defaultConnections,
439
+ type ServiceNode,
440
+ type ServiceConnection,
441
+ type ServiceHealth,
442
+ type ServiceType,
443
+ type WakaServiceGraphProps,
444
+ } from './waka-service-graph'
445
+
446
+ // DevOps - CI/CD Components
447
+ export {
448
+ WakaBuildMatrix,
449
+ defaultBuildMatrixColumns,
450
+ defaultBuildMatrixRows,
451
+ type BuildMatrixRow,
452
+ type BuildCell,
453
+ type BuildStatus as WakaBuildStatus,
454
+ type WakaBuildMatrixProps,
455
+ } from './waka-build-matrix'
456
+
457
+ export {
458
+ WakaTestReport,
459
+ defaultTestSuites,
460
+ defaultCoverage,
461
+ type TestSuite,
462
+ type TestCase,
463
+ type CoverageReport,
464
+ type TestStatus,
465
+ type WakaTestReportProps,
466
+ } from './waka-test-report'
467
+
468
+ export {
469
+ WakaArtifactList,
470
+ defaultArtifacts,
471
+ type Artifact,
472
+ type WakaArtifactListProps,
473
+ } from './waka-artifact-list'
474
+
475
+ export {
476
+ WakaSecurityScanResult,
477
+ defaultVulnerabilities,
478
+ type Vulnerability,
479
+ type VulnerabilitySeverity,
480
+ type ScanType,
481
+ type ScanSummary,
482
+ type WakaSecurityScanResultProps,
483
+ } from './waka-security-scan-result'
484
+
485
+ export {
486
+ WakaDependencyTree,
487
+ defaultDependencies,
488
+ type Dependency,
489
+ type DependencyType,
490
+ type VulnSeverity as DependencyVulnSeverity,
491
+ type WakaDependencyTreeProps,
492
+ } from './waka-dependency-tree'
493
+
494
+ // DevOps - Configuration Components
495
+ export {
496
+ WakaEnvVarEditor,
497
+ defaultEnvVariables,
498
+ type EnvVariable,
499
+ type WakaEnvVarEditorProps,
500
+ } from './waka-env-var-editor'
501
+
502
+ export {
503
+ WakaSecretCard,
504
+ defaultSecret,
505
+ type Secret,
506
+ type SecretAccess,
507
+ type WakaSecretCardProps,
508
+ } from './waka-secret-card'
509
+
510
+ export {
511
+ WakaConfigComparator,
512
+ defaultConfigEnvironments,
513
+ type ConfigEnvironment,
514
+ type ConfigValue,
515
+ type ConfigDiff,
516
+ type DiffType,
517
+ type WakaConfigComparatorProps,
518
+ } from './waka-config-comparator'
519
+
520
+ export {
521
+ WakaFeatureFlagRow,
522
+ defaultFeatureFlags,
523
+ type FeatureFlag,
524
+ type FeatureFlagStatus,
525
+ type FeatureFlagSegment,
526
+ type WakaFeatureFlagRowProps,
527
+ } from './waka-feature-flag-row'
528
+
529
+ // DevOps - Database Components
530
+ export {
531
+ WakaDatabaseCard,
532
+ defaultDatabase,
533
+ defaultDatabases,
534
+ type DatabaseInfo,
535
+ type DatabaseMetrics,
536
+ type DatabaseType as WakaDatabaseType,
537
+ type DatabaseStatus as WakaDatabaseStatus,
538
+ type ReplicationRole,
539
+ type WakaDatabaseCardProps,
540
+ } from './waka-database-card'
541
+
542
+ export {
543
+ WakaMigrationList,
544
+ defaultMigrations,
545
+ type Migration,
546
+ type MigrationStatus,
547
+ type WakaMigrationListProps,
548
+ } from './waka-migration-list'
549
+
550
+ export {
551
+ WakaQueryExplain,
552
+ defaultQueryPlan,
553
+ type QueryPlan,
554
+ type ExplainNode,
555
+ type NodeType,
556
+ type WakaQueryExplainProps,
557
+ } from './waka-query-explain'
558
+
559
+ // Advertising Components
560
+ export {
561
+ WakaAdProvider,
562
+ useAdContext,
563
+ useAdVisibility,
564
+ useAdConsent,
565
+ useAdSlot,
566
+ AD_SIZES,
567
+ type AdNetwork,
568
+ type AdSize,
569
+ type AdPosition,
570
+ type AdSlot,
571
+ type AdConfig,
572
+ type AdEvent,
573
+ type CustomAd,
574
+ } from './waka-ad-provider'
575
+
576
+ export {
577
+ WakaAdBanner,
578
+ type WakaAdBannerProps,
579
+ } from './waka-ad-banner'
580
+
581
+ export {
582
+ WakaAdPlaceholder,
583
+ type WakaAdPlaceholderProps,
584
+ } from './waka-ad-placeholder'
585
+
586
+ export {
587
+ WakaAdFallback,
588
+ type WakaAdFallbackProps,
589
+ type AdFallbackVariant,
590
+ } from './waka-ad-fallback'
591
+
592
+ export {
593
+ WakaSponsoredBadge,
594
+ type WakaSponsoredBadgeProps,
595
+ type SponsoredBadgeVariant,
596
+ type SponsoredBadgeSize,
597
+ } from './waka-sponsored-badge'
598
+
599
+ export {
600
+ WakaAdSidebar,
601
+ type WakaAdSidebarProps,
602
+ } from './waka-ad-sidebar'
603
+
604
+ export {
605
+ WakaAdInline,
606
+ type WakaAdInlineProps,
607
+ } from './waka-ad-inline'
608
+
609
+ export {
610
+ WakaAdInterstitial,
611
+ type WakaAdInterstitialProps,
612
+ } from './waka-ad-interstitial'
613
+
614
+ export {
615
+ WakaAdStickyFooter,
616
+ type WakaAdStickyFooterProps,
617
+ } from './waka-ad-sticky-footer'
618
+
619
+ export {
620
+ WakaSponsoredCard,
621
+ type WakaSponsoredCardProps,
622
+ type SponsoredCardVariant,
623
+ } from './waka-sponsored-card'
624
+
625
+ export {
626
+ WakaSponsoredFeed,
627
+ type WakaSponsoredFeedProps,
628
+ } from './waka-sponsored-feed'
629
+
630
+ export {
631
+ WakaContentRecommendation,
632
+ type WakaContentRecommendationProps,
633
+ type RecommendationLayout,
634
+ } from './waka-content-recommendation'
635
+
636
+ export {
637
+ WakaVideoAd,
638
+ type WakaVideoAdProps,
639
+ } from './waka-video-ad'
640
+
641
+ export {
642
+ WakaOutstreamVideo,
643
+ type WakaOutstreamVideoProps,
644
+ } from './waka-outstream-video'
645
+
646
+ export {
647
+ WakaVideoOverlay,
648
+ type WakaVideoOverlayProps,
649
+ type OverlayPosition,
650
+ type OverlayTrigger,
651
+ } from './waka-video-overlay'
@@ -127,18 +127,18 @@ export function Waka3DPieChart({
127
127
  })
128
128
  }, [data, total])
129
129
 
130
- // Default colors
130
+ // Default colors - using CSS variables for theme support
131
131
  const defaultColors = [
132
- "#3b82f6", // blue
133
- "#ef4444", // red
134
- "#22c55e", // green
135
- "#f59e0b", // amber
136
- "#8b5cf6", // violet
137
- "#ec4899", // pink
138
- "#14b8a6", // teal
139
- "#f97316", // orange
140
- "#6366f1", // indigo
141
- "#84cc16", // lime
132
+ "hsl(var(--chart-1))",
133
+ "hsl(var(--chart-2))",
134
+ "hsl(var(--chart-3))",
135
+ "hsl(var(--chart-4))",
136
+ "hsl(var(--chart-5))",
137
+ "hsl(var(--primary))",
138
+ "hsl(var(--info))",
139
+ "hsl(var(--warning))",
140
+ "hsl(var(--success))",
141
+ "hsl(var(--destructive))",
142
142
  ]
143
143
 
144
144
  const getSliceColor = (index: number, slice: PieSlice) => {
@@ -73,41 +73,41 @@ const rarityConfig = {
73
73
  common: {
74
74
  gradient: "from-slate-400 to-slate-600",
75
75
  glow: "shadow-slate-400/50",
76
- glowColor: "#94a3b8",
76
+ glowColor: "hsl(var(--muted-foreground))",
77
77
  borderColor: "border-slate-400",
78
- bgColor: "bg-slate-100",
79
- textColor: "text-slate-600",
80
- particleColors: ["#94a3b8", "#cbd5e1", "#64748b"],
78
+ bgColor: "bg-slate-100 dark:bg-slate-900",
79
+ textColor: "text-slate-600 dark:text-slate-400",
80
+ particleColors: ["hsl(var(--muted-foreground))", "hsl(var(--muted))", "hsl(var(--border))"],
81
81
  label: "Common",
82
82
  },
83
83
  rare: {
84
84
  gradient: "from-blue-400 to-blue-600",
85
85
  glow: "shadow-blue-400/50",
86
- glowColor: "#60a5fa",
86
+ glowColor: "hsl(var(--info))",
87
87
  borderColor: "border-blue-400",
88
- bgColor: "bg-blue-100",
89
- textColor: "text-blue-600",
90
- particleColors: ["#60a5fa", "#93c5fd", "#3b82f6"],
88
+ bgColor: "bg-blue-100 dark:bg-blue-950",
89
+ textColor: "text-blue-600 dark:text-blue-400",
90
+ particleColors: ["hsl(var(--info))", "hsl(var(--chart-1))", "hsl(var(--primary))"],
91
91
  label: "Rare",
92
92
  },
93
93
  epic: {
94
94
  gradient: "from-purple-400 to-purple-600",
95
95
  glow: "shadow-purple-400/50",
96
- glowColor: "#a855f7",
96
+ glowColor: "hsl(var(--chart-2))",
97
97
  borderColor: "border-purple-400",
98
- bgColor: "bg-purple-100",
99
- textColor: "text-purple-600",
100
- particleColors: ["#a855f7", "#c084fc", "#9333ea"],
98
+ bgColor: "bg-purple-100 dark:bg-purple-950",
99
+ textColor: "text-purple-600 dark:text-purple-400",
100
+ particleColors: ["hsl(var(--chart-2))", "hsl(var(--chart-3))", "hsl(var(--primary))"],
101
101
  label: "Epic",
102
102
  },
103
103
  legendary: {
104
104
  gradient: "from-amber-400 via-orange-500 to-red-500",
105
105
  glow: "shadow-amber-400/50",
106
- glowColor: "#fbbf24",
106
+ glowColor: "hsl(var(--warning))",
107
107
  borderColor: "border-amber-400",
108
- bgColor: "bg-amber-100",
109
- textColor: "text-amber-600",
110
- particleColors: ["#fbbf24", "#f59e0b", "#ef4444", "#fcd34d"],
108
+ bgColor: "bg-amber-100 dark:bg-amber-950",
109
+ textColor: "text-amber-600 dark:text-amber-400",
110
+ particleColors: ["hsl(var(--warning))", "hsl(var(--chart-4))", "hsl(var(--destructive))", "hsl(var(--chart-5))"],
111
111
  label: "Legendary",
112
112
  },
113
113
  }
@@ -0,0 +1,275 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { useRef, useEffect, useState, useCallback } from "react"
5
+ import { cn } from "../../utils/cn"
6
+ import { useAdContext, useAdVisibility, AD_SIZES, type AdSize, type AdSlot, type CustomAd } from "../waka-ad-provider"
7
+ import { WakaAdPlaceholder } from "../waka-ad-placeholder"
8
+ import { WakaAdFallback } from "../waka-ad-fallback"
9
+ import { WakaSponsoredBadge } from "../waka-sponsored-badge"
10
+
11
+ export interface WakaAdBannerProps {
12
+ /** Unique slot ID */
13
+ slotId: string
14
+ /** Ad size preset */
15
+ size?: AdSize
16
+ /** Custom width (when size is "custom") */
17
+ customWidth?: number
18
+ /** Custom height (when size is "custom") */
19
+ customHeight?: number
20
+ /** GPT ad unit path (for GPT network) */
21
+ adUnitPath?: string
22
+ /** Targeting parameters */
23
+ targeting?: Record<string, string | string[]>
24
+ /** Auto-refresh interval in seconds (0 = disabled) */
25
+ refreshInterval?: number
26
+ /** Enable lazy loading */
27
+ lazyLoad?: boolean
28
+ /** Fallback content when no ad available */
29
+ fallback?: React.ReactNode
30
+ /** Show sponsored badge */
31
+ showBadge?: boolean
32
+ /** Badge position */
33
+ badgePosition?: "top-left" | "top-right" | "bottom-left" | "bottom-right"
34
+ /** Custom class name */
35
+ className?: string
36
+ /** Callback when ad loads */
37
+ onLoad?: () => void
38
+ /** Callback when ad fails */
39
+ onError?: (error: Error) => void
40
+ /** Callback when ad is clicked */
41
+ onClick?: () => void
42
+ }
43
+
44
+ export function WakaAdBanner({
45
+ slotId,
46
+ size = "rectangle",
47
+ customWidth,
48
+ customHeight,
49
+ adUnitPath,
50
+ targeting,
51
+ refreshInterval = 0,
52
+ lazyLoad = true,
53
+ fallback,
54
+ showBadge = true,
55
+ badgePosition = "top-right",
56
+ className,
57
+ onLoad,
58
+ onError,
59
+ onClick,
60
+ }: WakaAdBannerProps) {
61
+ const containerRef = useRef<HTMLDivElement>(null)
62
+ const { config, isReady, hasConsent, registerSlot, unregisterSlot, getCustomAd, trackEvent } = useAdContext()
63
+ const { isVisible } = useAdVisibility(containerRef)
64
+
65
+ const [status, setStatus] = useState<"loading" | "loaded" | "error" | "empty">("loading")
66
+ const [customAd, setCustomAd] = useState<CustomAd | null>(null)
67
+
68
+ const dimensions = size === "custom"
69
+ ? { width: customWidth || 300, height: customHeight || 250 }
70
+ : AD_SIZES[size]
71
+
72
+ // Register slot
73
+ useEffect(() => {
74
+ const slot: AdSlot = {
75
+ id: slotId,
76
+ network: config.network,
77
+ size,
78
+ position: "inline",
79
+ targeting,
80
+ refreshInterval,
81
+ lazyLoad,
82
+ customWidth,
83
+ customHeight,
84
+ }
85
+ registerSlot(slot)
86
+ return () => unregisterSlot(slotId)
87
+ }, [slotId, config.network, size, targeting, refreshInterval, lazyLoad, customWidth, customHeight, registerSlot, unregisterSlot])
88
+
89
+ // Load ad based on network type
90
+ const loadAd = useCallback(async () => {
91
+ if (!isReady || hasConsent === false) return
92
+
93
+ setStatus("loading")
94
+
95
+ try {
96
+ if (config.network === "gpt" && window.googletag && adUnitPath) {
97
+ // GPT implementation
98
+ window.googletag.cmd.push(() => {
99
+ const slot = window.googletag.defineSlot(
100
+ adUnitPath,
101
+ [dimensions.width, dimensions.height],
102
+ slotId
103
+ )
104
+
105
+ if (slot && targeting) {
106
+ Object.entries(targeting).forEach(([key, value]) => {
107
+ window.googletag.pubads().setTargeting(key, value)
108
+ })
109
+ }
110
+
111
+ window.googletag.enableServices()
112
+ window.googletag.display(slotId)
113
+ })
114
+
115
+ setStatus("loaded")
116
+ trackEvent({ type: "loaded", slotId, timestamp: new Date() })
117
+ onLoad?.()
118
+ } else if (config.network === "custom") {
119
+ // Custom ad server
120
+ const ad = await getCustomAd(slotId)
121
+ if (ad) {
122
+ setCustomAd(ad)
123
+ setStatus("loaded")
124
+ trackEvent({ type: "loaded", slotId, timestamp: new Date() })
125
+ onLoad?.()
126
+
127
+ // Fire impression tracking
128
+ if (ad.impressionUrl) {
129
+ fetch(ad.impressionUrl, { mode: "no-cors" }).catch(() => {})
130
+ }
131
+ ad.trackingPixels?.forEach((url) => {
132
+ const img = new Image()
133
+ img.src = url
134
+ })
135
+ } else {
136
+ setStatus("empty")
137
+ trackEvent({ type: "empty", slotId, timestamp: new Date() })
138
+ }
139
+ }
140
+ } catch (error) {
141
+ setStatus("error")
142
+ trackEvent({ type: "error", slotId, timestamp: new Date(), data: { error } })
143
+ onError?.(error as Error)
144
+ }
145
+ }, [isReady, hasConsent, config.network, adUnitPath, dimensions, slotId, targeting, getCustomAd, trackEvent, onLoad, onError])
146
+
147
+ // Initial load (with lazy loading support)
148
+ useEffect(() => {
149
+ if (lazyLoad) {
150
+ if (isVisible) {
151
+ loadAd()
152
+ }
153
+ } else {
154
+ loadAd()
155
+ }
156
+ }, [lazyLoad, isVisible, loadAd])
157
+
158
+ // Auto-refresh
159
+ useEffect(() => {
160
+ if (refreshInterval > 0 && status === "loaded" && isVisible) {
161
+ const interval = setInterval(() => {
162
+ loadAd()
163
+ }, refreshInterval * 1000)
164
+ return () => clearInterval(interval)
165
+ }
166
+ }, [refreshInterval, status, isVisible, loadAd])
167
+
168
+ // Track viewability
169
+ useEffect(() => {
170
+ if (isVisible && status === "loaded") {
171
+ trackEvent({ type: "viewable", slotId, timestamp: new Date() })
172
+ }
173
+ }, [isVisible, status, slotId, trackEvent])
174
+
175
+ const handleClick = () => {
176
+ trackEvent({ type: "click", slotId, timestamp: new Date() })
177
+ onClick?.()
178
+
179
+ if (customAd?.clickUrl) {
180
+ fetch(customAd.clickUrl, { mode: "no-cors" }).catch(() => {})
181
+ }
182
+ if (customAd?.targetUrl) {
183
+ window.open(customAd.targetUrl, "_blank", "noopener,noreferrer")
184
+ }
185
+ }
186
+
187
+ // Render based on status
188
+ const renderContent = () => {
189
+ if (hasConsent === false) {
190
+ return fallback || <WakaAdFallback width={dimensions.width} height={dimensions.height} />
191
+ }
192
+
193
+ if (status === "loading") {
194
+ return <WakaAdPlaceholder width={dimensions.width} height={dimensions.height} />
195
+ }
196
+
197
+ if (status === "error" || status === "empty") {
198
+ return fallback || <WakaAdFallback width={dimensions.width} height={dimensions.height} />
199
+ }
200
+
201
+ // GPT renders into the div directly
202
+ if (config.network === "gpt") {
203
+ return null
204
+ }
205
+
206
+ // Custom ad rendering
207
+ if (customAd) {
208
+ return (
209
+ <button
210
+ onClick={handleClick}
211
+ className="relative w-full h-full cursor-pointer focus:outline-none focus:ring-2 focus:ring-primary"
212
+ >
213
+ {customAd.imageUrl && (
214
+ <img
215
+ src={customAd.imageUrl}
216
+ alt={customAd.title || "Advertisement"}
217
+ className="w-full h-full object-cover"
218
+ />
219
+ )}
220
+ {customAd.title && !customAd.imageUrl && (
221
+ <div className="flex flex-col items-center justify-center h-full p-4 bg-muted">
222
+ <p className="font-semibold text-center">{customAd.title}</p>
223
+ {customAd.description && (
224
+ <p className="text-sm text-muted-foreground text-center mt-1">{customAd.description}</p>
225
+ )}
226
+ {customAd.cta && (
227
+ <span className="mt-2 px-4 py-1 bg-primary text-primary-foreground rounded text-sm">
228
+ {customAd.cta}
229
+ </span>
230
+ )}
231
+ </div>
232
+ )}
233
+ </button>
234
+ )
235
+ }
236
+
237
+ return null
238
+ }
239
+
240
+ const badgePositionClasses = {
241
+ "top-left": "top-1 left-1",
242
+ "top-right": "top-1 right-1",
243
+ "bottom-left": "bottom-1 left-1",
244
+ "bottom-right": "bottom-1 right-1",
245
+ }
246
+
247
+ return (
248
+ <div
249
+ ref={containerRef}
250
+ id={slotId}
251
+ className={cn(
252
+ "relative overflow-hidden bg-muted/20 border border-border/50 rounded-md",
253
+ className
254
+ )}
255
+ style={{
256
+ width: dimensions.width,
257
+ height: dimensions.height,
258
+ maxWidth: "100%",
259
+ }}
260
+ data-ad-slot={slotId}
261
+ data-ad-size={size}
262
+ data-ad-status={status}
263
+ >
264
+ {renderContent()}
265
+
266
+ {showBadge && status === "loaded" && (
267
+ <div className={cn("absolute z-10", badgePositionClasses[badgePosition])}>
268
+ <WakaSponsoredBadge sponsor={customAd?.sponsor} />
269
+ </div>
270
+ )}
271
+ </div>
272
+ )
273
+ }
274
+
275
+ export default WakaAdBanner