Skip to main content

skeleton - Panel API

@types IPublicApiSkeleton
> @since v1.0.0

Module Overview

The panel API provides panel extension and management. The blue areas in the image below are all extensions.

image.png

There are 5 extensible areas on the page: image.png

Core Concepts

Extension area (area)

topArea

Top area of the designer. Common plugins here include:

  1. Designer logo
  2. Undo/redo buttons
  3. Global actions such as save and preview
leftArea

Left area is usually icons with corresponding panels. Clicking an icon shows that panel and hides others.

Common plugins here include:

  1. Outline tree showing the page structure
  2. Component library — drag components from the panel onto the canvas
  3. Data source panel
  4. JS and other code panels

Panels in this area usually do not need to be open at the same time and often need a larger dedicated area for interaction.

centerArea

Canvas area. Extensions here are relatively rare since the canvas is mostly for display. Common extensions include:

  1. Canvas size controls
  2. Material selection extension areas
rightArea

Right area, commonly used for component configuration. Common extensions include uniformly adding or removing configuration items across components.

toolbar

Similar to topArea — place panel plugins as needed.

Display type (type)

Display type distinguishes different UI patterns plugins can use in the designer. Main types are PanelDock, Widget, and Dock. Panel is currently not recommended.

PanelDock

PanelDock appears as a panel in the left area. It consists of an icon and a panel; clicking the icon toggles panel visibility.

Below is the component library plugin display.

Feb-08-2022 19-44-15.gif

The top-right corner supports pinning and setting popup width.

Integration example:

import { skeleton } from '@rchh/lowcode-engine';

skeleton.add({
area: 'leftArea', // Plugin area
type: 'PanelDock', // Plugin type — popup panel
name: 'sourceEditor',
content: SourceEditor, // Plugin component instance
props: {
align: 'left',
icon: 'wenjian',
title: 'Title', // Title shown below the icon
description: 'JS panel',
},
panelProps: {
floatable: true, // Whether the panel can float
height: 300,
hideTitleBar: false,
maxHeight: 800,
maxWidth: 1200,
title: 'JS panel',
width: 600,
},
});
Widget

Widget renders directly at the corresponding position in the editor. In the demo, all components in the top area use this pattern.

image.png

Integration example:

import { skeleton } from '@rchh/lowcode-engine';
// Register logo panel
skeleton.add({
area: 'topArea',
type: 'Widget',
name: 'logo',
content: Logo, // Widget component instance
contentProps: {
// Widget plugin props
logo: 'https://img.alicdn.com/tfs/TB1_SocGkT2gK0jSZFkXXcIQFXa-66-66.png',
href: '/',
},
props: {
align: 'left',
width: 100,
},
});
Dock

An icon-only display suitable for language switching, external links, opening a widget, and similar scenarios.

import { skeleton } from '@rchh/lowcode-engine';

skeleton.add({
area: 'leftArea',
type: 'Dock',
name: 'opener',
props: {
icon: Icon, // Icon component instance
align: 'bottom',
onClick: function () {
// Open external link
window.open('https://lowcode-engine.cn');
// Show widget
skeleton.showWidget('xxx');
},
},
});

Methods

add

Add a panel to a specified extension area

/**
* Add a panel instance
* add a new panel
* @param config
* @param extraConfig
* @returns
*/
add(config: IPublicTypeWidgetBaseConfig, extraConfig?: Record<string, any>): any;

IWidgetBaseConfig definition:

PropertyDescriptionNotes
namePanel name
areaExtension area: 'topArea' | 'leftArea' | 'rightArea' | 'toolbar' | 'bottomArea' | 'mainArea'
typePanel type: 'Widget' | 'PanelDock' | 'Panel' | DockSee Display type above
contentPanel implementation class/node — ReactClass | ReactElement
propsPanel propertiesalign: 'top' | 'bottom' | 'left' | 'center' | 'right'; // Icon position
icon: string | ReactElement; // When icon is a string, ensure the current Fusion theme includes it
description: string;
condition: Function; // Controls panel visibility
contentPropsProps for the panel implementation class/node
panelPropsValid when type is 'Panel' | 'PanelDock'; passed to PanelkeepVisibleWhileDragging: boolean; // Keep panel open while dragging inside it; default false
area: 'leftFloatArea' | 'leftFixedArea' // Float or pinned panel
indexPanel position; defaults to plugin registration order

remove

Remove a panel instance

/**
* Remove a panel instance
* remove a panel
* @param config
* @returns
*/
remove(config: IPublicTypeWidgetBaseConfig): number | undefined;

getPanel

Get a panel instance

/**
* Get a panel instance
* @param name Panel name
*/
getPanel(name: string): IPublicModelSkeletonItem | undefined;

Related type: IPublicModelSkeletonItem

@since v1.1.10

showPanel

Show a panel instance by name

/**
* Show a panel instance by name
* show panel by name
* @param name
*/
showPanel(name: string): void;

hidePanel

Hide a panel

/**
* Hide a panel
* hide panel by name
* @param name
*/
hidePanel(name: string): void;

showWidget

Show a widget instance by name

/**
* Show a widget instance by name
* show widget by name
* @param name
*/
showWidget(name: string): void;

enableWidget

Enable a widget.

/**
* Enable a widget
* enable widget
* @param name
*/
enableWidget(name: string): void;

hideWidget

Hide a widget instance by name.

/**
* Hide a widget instance by name
* hide widget by name
* @param name
*/
hideWidget(name: string): void;

disableWidget

Disable a widget; all mouse events are blocked.

Use case: disable the panel during initialization to prevent user clicks from causing errors, then re-enable when ready.

/**
* Disable a widget; all mouse events are blocked.
* disable widget,and make it not responding any click event.
* @param name
*/
disableWidget(name: string): void;

showArea

Show an area

/**
* Show an area
* show area
* @param areaName name of area
*/
showArea(areaName: string): void;

hideArea

Hide an area

/**
* Hide an area
* hide area
* @param areaName name of area
*/
hideArea(areaName: string): void;

getAreaItems

Get all panel instances in an area

/**
* Get all panel instances in an area
* @param areaName IPublicTypeWidgetConfigArea
*/
getAreaItems(areaName: IPublicTypeWidgetConfigArea): IPublicModelSkeletonItem[] | undefined;

Related type: IPublicModelSkeletonItem

registerConfigTransducer

Register a panel configuration transducer.

/**
* Register a panel configuration transducer.
* Registers a configuration transducer for a panel.
* @param {IPublicTypeConfigTransducer} transducer
* - Transducer function to register. Accepts a configuration object (IPublicTypeSkeletonConfig) and returns the modified configuration.
* - The transducer function to be registered. This function takes a configuration object
*
* @param {number} level
* - Transducer priority. Higher priority transducers run first.
* - The priority level of the transducer. Transducers with higher priority levels are executed first.
*
* @param {string} [id]
* - (Optional) Unique transducer identifier for referencing or manipulating a specific transducer.
* - (Optional) A unique identifier for the transducer. Used for referencing or manipulating a specific transducer when needed.
*/
registerConfigTransducer(transducer: IPublicTypeConfigTransducer, level: number, id?: string): void;

Usage example

import { IPublicModelPluginContext, IPublicTypeSkeletonConfig } from '@rchh/lowcode-types';

function updatePanelWidth(config: IPublicTypeSkeletonConfig) {
if (config.type === 'PanelDock') {
return {
...config,
panelProps: {
...(config.panelProps || {}),
width: 240,
},
};
}

return config;
}

const controlPanelWidthPlugin = (ctx: IPublicModelPluginContext) => {
const { skeleton } = ctx;
(skeleton as any).registerConfigTransducer?.(updatePanelWidth, 1, 'update-panel-width');

return {
init() {},
};
};

controlPanelWidthPlugin.pluginName = 'controlPanelWidthPlugin';
controlPanelWidthPlugin.meta = {
dependencies: [],
engines: {
lowcodeEngine: '^1.2.3', // Plugin requires engine ^1.0.0
},
};

export default controlPanelWidthPlugin;

Events

onShowPanel

Listen for panel show events

/**
* Listen for panel show events
* set callback for panel shown event
* @param listener
* @returns
*/
onShowPanel(listener: (paneName?: string, panel?: IPublicModelSkeletonItem) => void): IPublicTypeDisposable;

Related type: IPublicTypeDisposable

onHidePanel

Listen for panel hide events

/**
* Listen for panel hide events
* set callback for panel hidden event
* @param listener
* @returns
*/
onHidePanel(listener: (paneName?: string, panel?: IPublicModelSkeletonItem) => void): IPublicTypeDisposable;

Related type: IPublicTypeDisposable

onDisableWidget

Listen for widget disable events

/**
* Listen for widget disable events
* @param listener
*/
onDisableWidget(listener: (paneName?: string, panel?: IPublicModelSkeletonItem) => void): IPublicTypeDisposable;

Related type: IPublicTypeDisposable

onEnableWidget

Listen for widget enable events

/**
* Listen for widget enable events
* @param listener
*/
onEnableWidget(listener: (paneName?: string, panel?: IPublicModelSkeletonItem) => void): IPublicTypeDisposable;

Related type: IPublicTypeDisposable

onShowWidget

Listen for widget show events

/**
* Listen for widget show events
* set callback for widget shown event
* @param listener
* @returns
*/
onShowWidget(listener: (paneName?: string, panel?: IPublicModelSkeletonItem) => void): IPublicTypeDisposable;

Related type: IPublicTypeDisposable

onHideWidget

Listen for widget hide events

/**
* Listen for widget hide events
* set callback for widget hidden event
* @param listener
* @returns
*/
onHideWidget(listener: (paneName?: string, panel?: IPublicModelSkeletonItem) => void): IPublicTypeDisposable;

Related type: IPublicTypeDisposable

Usage Examples

import { skeleton } from '@rchh/lowcode-engine';

skeleton.add({
name: 'logo',
area: 'topArea',
type: 'Widget',
contentProps: {},
content: LogoContent,
});

skeleton.add({
name: 'sourceEditor',
type: 'PanelDock',
area: 'leftArea',
props: {
align: 'top',
icon: 'wenjian',
description: 'JS panel',
},
panelProps: {
floatable: true,
height: 300,
help: undefined,
hideTitleBar: false,
maxHeight: 800,
maxWidth: 1200,
title: 'JS panel',
width: 600,
},
content: SourceEditor,
});

// Show/hide panel
skeleton.showPanel('sourceEditor');
skeleton.hidePanel('sourceEditor');

// Create a floating widget
skeleton.add({
name: 'floatingWidget',
type: 'Widget',
area: 'mainArea',
props: {},
content: React.createElement('div', {}, 'haha'),
contentProps: {
style: {
position: 'fixed',
top: '200px',
bottom: 0,
width: 'calc(100% - 46px)',
'background-color': 'lightblue',
},
},
});

// Show/hide widget
skeleton.showWidget('floatingWidget');
skeleton.hideWidget('floatingWidget');

// Control widget clickability
skeleton.enableWidget('sourceEditor');
skeleton.disableWidget('sourceEditor');

bottomArea example

import { skeleton } from '@rchh/lowcode-engine';

skeleton.add({
name: 'bottomAreaPanelName',
area: 'bottomArea',
type: 'Panel',
content: () => 'demoText',
});

skeleton.showPanel('bottomAreaPanelName');

widget example

// Register logo panel
skeleton.add({
area: 'topArea',
type: 'Widget',
name: 'logo',
content: Logo,
contentProps: {
logo: 'https://img.alicdn.com/imgextra/i4/O1CN013w2bmQ25WAIha4Hx9_!!6000000007533-55-tps-137-26.svg',
href: 'https://lowcode-engine.cn',
},
props: {
align: 'left',
},
});