Barazo default frontend
barazo.forum
1'use client'
2
3import { Component, type ReactNode, type ComponentType } from 'react'
4import { usePlugins } from '@/hooks/use-plugins'
5import { getPluginComponents, type SlotName } from '@/lib/plugins/registry'
6
7interface PluginSlotProps {
8 name: SlotName
9 context?: Record<string, unknown>
10 fallback?: ReactNode
11}
12
13// Error boundary for individual plugin components
14interface ErrorBoundaryProps {
15 pluginName: string
16 children: ReactNode
17}
18
19interface ErrorBoundaryState {
20 hasError: boolean
21}
22
23class PluginErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
24 constructor(props: ErrorBoundaryProps) {
25 super(props)
26 this.state = { hasError: false }
27 }
28
29 static getDerivedStateFromError(): ErrorBoundaryState {
30 return { hasError: true }
31 }
32
33 render() {
34 if (this.state.hasError) {
35 return (
36 <div className="rounded border border-destructive/20 bg-destructive/5 px-3 py-2 text-xs text-destructive">
37 Plugin “{this.props.pluginName}” encountered an error.
38 </div>
39 )
40 }
41 return this.props.children
42 }
43}
44
45export function PluginSlot({ name, context = {}, fallback }: PluginSlotProps) {
46 const { plugins } = usePlugins()
47
48 const registrations = getPluginComponents(name)
49
50 // Filter to only enabled plugins
51 const activeRegistrations = registrations.filter((reg) =>
52 plugins.some((p) => p.name === reg.pluginName && p.enabled)
53 )
54
55 if (activeRegistrations.length === 0) {
56 return fallback ?? null
57 }
58
59 return (
60 <>
61 {activeRegistrations.map((reg) => {
62 const PluginComponent = reg.component as ComponentType<Record<string, unknown>>
63 return (
64 <PluginErrorBoundary key={reg.pluginName} pluginName={reg.pluginName}>
65 <PluginComponent {...context} />
66 </PluginErrorBoundary>
67 )
68 })}
69 </>
70 )
71}