Skip to content

Panel Registry ​

The panel registry maps string component keys (used in openPanel() and serialized layouts) to React component constructors. There are two ways to populate it.

Pass a panels map to createWorkspace(). It fills the workspace's own registry, workspace.registry:

ts
const workspace = createWorkspace({
  panels: {
    map:    { component: MapPanel,    defaultOptions: { title: 'Map', canClose: false } },
    editor: { component: EditorPanel, defaultOptions: { title: 'Editor' } },
    logs:   { component: LogsPanel },
  },
});

Each key is the componentKey argument to openPanel(id, componentKey). Keys must be stable — they are persisted inside saveLayout() JSON.

PanelDefinition ​

ts
interface PanelDefinition {
  // The library injects `panelId` as a prop automatically.
  // Components that don't declare it in their props can read `usePanel().id` instead.
  component: ComponentType<any>;
  defaultOptions?: PanelRegistryEntry['defaultOptions'];
}

defaultOptions ​

The type is PanelRegistryEntry['defaultOptions'] (PanelRegistryEntry is exported). All fields are optional. They set the per-panel defaults; most can be overridden per-instance in openPanel.

OptionTypeDefaultDescription
titlestring | MessageDescriptor | (() => string)—Tab and window title. A function is called each time the title renders; it's also the title a restored panel takes, since a function title isn't saved in a layout.
iconReactNode—Icon shown in the tab, the floating title bar and the taskbar. A single instance can change it at runtime with usePanel().setIcon() or workspace.setPanelIcon().
initialTarget'floating' | 'docked' | 'tabbed''docked'Initial placement when the panel is first opened.
favoritePosition{ x, y, width, height }{ x: 300, y: 150, width: 450, height: 350 }Default floating bounds (position + size) when the panel is first floated. All four values accept numbers (px) or CSS strings ('50%').
canClosebooleantrueShow or hide the × close button.
canMinimizebooleantrueShow or hide the minimize button.
canDragbooleantrueAllow the tab to be dragged to a different leaf or position. When false, the panel cannot be floated via drag.
defaultAnchorFloatAnchor ('top-left' | 'top-right' | 'bottom-left' | 'bottom-right')— (unanchored)Every instance of this component opens pre-anchored to the given workspace corner when floated — see the anchor option in Workspace, which this is the per-component default for.
disableLivePreviewbooleanfalseShow a placeholder instead of a live thumbnail in the preview that pops up when the pointer is over this panel's taskbar button (while it is minimized). A canvas-rendered view (a WebGL map) that blurs in the scaled-down preview can instead be marked with data-rdd-preview-unscale on its container, which renders it at full resolution there.
renderHeaderActions(panelId: string) => ReactNode—Inject React nodes into the panel tab header (e.g. export buttons).

Locked / pinned panel pattern ​

Set canDrag, canClose, and canMinimize all to false to create a panel the user cannot move, close, or hide — useful for a primary map or content area:

ts
const workspace = createWorkspace({
  panels: {
    mainMap: {
      component: MapPanel,
      defaultOptions: {
        title:       'Map',
        canDrag:     false,
        canClose:    false,
        canMinimize: false,
      },
    },
  },
});

A panel locked this way has no tab context menu (every built-in item is off), so custom items it adds with usePanelContextMenu don't appear on its tab.

Imperative registration (advanced) ​

For dynamic panel types registered after the workspace is created, use workspace.registry.register() — or, inside React, useWorkspace().registry.register():

ts
workspace.registry.register('live-chart', LiveChartComponent, {
  title: 'Live Chart',
  canClose: true,
});

Look entries up with get() and list them with getRegisteredIds():

ts
workspace.registry.get('live-chart');        // → { Component, defaultOptions } | undefined
workspace.registry.getRegisteredIds();       // → ['live-chart', …]

There is no global registry: each workspace has its own, so several workspaces on one page never share panel keys.

Unregistered key warning ​

If openPanel('id', 'unknown-key') is called and 'unknown-key' is not in the registry, the panel renders a visual warning placeholder and emits a console.warn naming the panel and the missing key. Add the key to the panels config of createWorkspace(), or register it with workspace.registry.register().

Released under the MIT License.