import { ReactNode } from 'react'; import { Model, IJsonModel } from 'flexlayout-react'; import { IMenuItemConfig } from '../../core/registry/MenuRegistry'; import { ISlashCommandConfig } from '../../core/services/ChatService'; import { IPanel } from '../../core/services/PaneService'; import { IStatusBarWidgetConfig } from '../../core/services/StatusBarService'; export interface ShellLayoutProps { /** * Panels to register, for every edge. * * Each panel's `side` decides where it docks — `"left"`, `"right"` or * `"bottom"`, defaulting to left — and each edge keeps its own open panel, so * a file tree, an inspector and a terminal can all be showing at once. A rail * appears only once its edge has a panel. * * Placement is data on the panel rather than a separate prop per side, so * moving something is a one-word change. */ panels?: IPanel[]; /** Slash commands available in the chat pane. */ slashCommands?: ISlashCommandConfig[]; /** Menu structure, keyed by top-level menu name. Items dispatch by `commandId`. */ menuConfig?: Record; /** Items for the status bar, grouped by their `alignment`. */ statusBarConfig?: IStatusBarWidgetConfig[]; /** Branding shown at the far left of the menu bar. */ title?: ReactNode; /** Slot at the far right of the menu bar, for actions or a theme switcher. */ rightMenuBarContent?: ReactNode; /** Widget rendered between the menus and the right slot, sized for search. */ centerMenuBarContent?: ReactNode; /** * Take control of the docking layout. When provided, the shell renders this * model and stops writing changes to `useLayoutStore` — useful for tests and * stories. Omit it to use the store's persisted model. */ layoutModel?: Model; /** * Starting workspace, as a `flexlayout-react` JSON model. Applied once on * mount and only when nothing has been restored from storage, so it seeds a * first run without overwriting a layout the user has since arranged. * * Ignored when `layoutModel` is provided, which takes control outright. */ initialLayoutJson?: IJsonModel; /** * Stop persisting the layout to `localStorage`. The workspace then resets to * `initialLayoutJson` on every load — useful for embedded or multi-tenant * shells where a per-browser layout would be wrong. Defaults to `false`. */ disableLocalStorage?: boolean; /** * Called with the serialised model whenever the user moves, splits, opens or * closes a tab. Use it to persist the layout somewhere of your own — a user * profile on the server, say — instead of, or alongside, `localStorage`. */ onLayoutChange?: (layout: IJsonModel) => void; } /** * The complete application shell: menu bar, a docked pane and rail on each * edge, a `flexlayout-react` docking workspace, and a status bar. * * **This is where an application starts.** Call {@link initializeShell} once to * register your commands, menus and panels, render this component, and add * features by registering them rather than by restructuring the layout. Tab * contents resolve through the {@link componentRegistry}, so a new view is a * registration and a menu entry — the shell never needs to import it. * * Configuration can arrive either way. Props are convenient for values that * change with your app's state; {@link initializeShell} is better for the fixed * set, since it runs once and works outside React. Props passed here are * written into the same stores on mount, so the two are interchangeable. * * Internally this composes the `Connected*` component variants, which read from * the shell stores. Those components — and the pure ones beneath them — are * exported too, for the cases where you need to rearrange the frame itself. * * Closing a tab marked dirty via `useLayoutStore().setTabDirty` prompts for * confirmation before the tab is removed. * * @example * ```tsx * // main.tsx — a complete application * import { initializeShell, ShellLayout, componentRegistry, AppTitle } from 'nexus-shell'; * import 'nexus-shell/style.css'; * * componentRegistry.register('editor', Editor); * * initializeShell({ * panels: [ * { id: 'files', label: 'Explorer', icon: Files, component: FileTree }, * chatPanel({ side: 'right' }), * terminalPanel({ side: 'bottom' }), * ], * commands: [{ id: 'file.save', label: 'File: Save', keybinding: 'Control+s', execute: save }], * menus: { File: [{ id: 'save', label: 'Save', commandId: 'file.save' }] }, * statusBar: [{ id: 'branch', label: 'main', alignment: 'left' }], * }); * * createRoot(document.getElementById('root')!).render( * } />} />, * ); * ``` */ export declare const ShellLayout: ({ panels, slashCommands, menuConfig, statusBarConfig, title, rightMenuBarContent, centerMenuBarContent, layoutModel, initialLayoutJson, disableLocalStorage, onLayoutChange, }: ShellLayoutProps) => import("react/jsx-runtime").JSX.Element;