=== NEW === - studio/ — MCPEngine Studio scaffold (Next.js monorepo, build plan) - docs/FACTORY-V2.md — Factory v2 architecture doc - docs/CALENDLY_MCP_BUILD_SUMMARY.md — Calendly MCP build report === UPDATED SERVERS === - fieldedge: Added jobs-tools, UI build script, main entry update - lightspeed: Updated main + server entry points - squarespace: Added collection-browser + page-manager apps - toast: Added main + server entry points === INFRA === - infra/command-center/state.json — Updated pipeline state - infra/command-center/FACTORY-V2.md — Factory v2 operator playbook
61 lines
1.8 KiB
TypeScript
61 lines
1.8 KiB
TypeScript
'use client';
|
|
import React from 'react';
|
|
import { clsx } from 'clsx';
|
|
import { twMerge } from 'tailwind-merge';
|
|
|
|
export interface InspectorProps {
|
|
open: boolean;
|
|
onClose: () => void;
|
|
title?: string;
|
|
children: React.ReactNode;
|
|
className?: string;
|
|
width?: number;
|
|
}
|
|
|
|
export const Inspector: React.FC<InspectorProps> = ({
|
|
open,
|
|
onClose,
|
|
title = 'Inspector',
|
|
children,
|
|
className,
|
|
width = 320,
|
|
}) => {
|
|
return (
|
|
<aside
|
|
className={twMerge(
|
|
clsx(
|
|
'h-full border-l border-gray-800 bg-gray-950 flex flex-col shrink-0',
|
|
'transition-all duration-300 ease-out overflow-hidden',
|
|
open ? 'opacity-100' : 'opacity-0 pointer-events-none',
|
|
),
|
|
className,
|
|
)}
|
|
style={{
|
|
width: open ? `${width}px` : 0,
|
|
transform: open ? 'translateX(0)' : `translateX(${width}px)`,
|
|
transition: 'width 0.3s ease-out, transform 0.3s ease-out, opacity 0.2s ease-out',
|
|
}}
|
|
aria-hidden={!open}
|
|
>
|
|
{/* Header */}
|
|
<div className="flex items-center justify-between px-4 py-3 border-b border-gray-800 shrink-0">
|
|
<h3 className="text-sm font-semibold text-gray-200">{title}</h3>
|
|
<button
|
|
onClick={onClose}
|
|
className="text-gray-500 hover:text-gray-300 transition-colors rounded-lg p-1 hover:bg-gray-800"
|
|
aria-label="Close inspector"
|
|
>
|
|
<svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor">
|
|
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18 18 6M6 6l12 12" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
{/* Scrollable content */}
|
|
<div className="flex-1 overflow-y-auto px-4 py-3">{children}</div>
|
|
</aside>
|
|
);
|
|
};
|
|
|
|
Inspector.displayName = 'Inspector';
|