/** * Client half of dsh-better-sidebar: mounts the right sidebar portal (inside * an error boundary so a rendering failure shows an error strip instead of a * blank panel) and registers the turn-tail interception. Requires the * runtime's slots and sessions services; the bundle itself is a module-table * consumer only (react + ui-primitives + xterm, all provided or inlined). */ import { Component, createElement, type ErrorInfo, type ReactNode } from 'react' import { createRoot } from 'react-dom/client' import type { Context } from '../context-types.ts' import { Sidebar } from './Sidebar.tsx' import { registerTurnTailInterception } from './intercept.tsx' import { t } from './locales.ts' import css from './sidebar.module.css' /** Services required before mounting (provided by the client runtime). */ export const inject = ['slots', 'sessions'] /** * Error boundary over the sidebar tree: a render error must never blank the * whole panel silently — it shows a dismissible error strip and logs the * stack for diagnosis. */ class SidebarBoundary extends Component<{ children: ReactNode }, { error: string | null }> { state = { error: null as string | null } static getDerivedStateFromError(error: unknown): { error: string } { return { error: error instanceof Error ? error.message : String(error) } } componentDidCatch(error: Error, info: ErrorInfo): void { console.error('[dsh-better-sidebar] render error:', error, info.componentStack) } render(): ReactNode { if (this.state.error !== null) { return (