跳到主要内容

# skeleton - 面板 API

> @types IPublicApiSkeleton
> @since v1.0.0

## 模块简介​

面板 API 提供了面板扩展和管理的能力，如下图蓝色内容都是扩展出来的。

页面上可以扩展的区域共 6 个，具体如下：

### 基本概念​

#### 扩展区域位置 (area)​

##### topArea​

展示在设计器的顶部区域，常见的相关区域的插件主要是：

1. 注册设计器 Logo；
2. 设计器操作回退和撤销按钮；
3. 全局操作按钮，例如：保存、预览等；

##### leftArea​

左侧区域的展示形式大多数是 Icon 和对应的面板，通过点击 Icon 可以展示对应的面板并隐藏其他的面板。

该区域相关插件的主要有：

1. 大纲树展示，展示该设计器设计页面的大纲。
2. 组件库，展示注册到设计器中的组件，点击之后，可以从组件库面板中拖拽到设计器的画布中。
3. 数据源面板
4. JS 等代码面板。

可以发现，这个区域的面板大多数操作时是不需要同时并存的，且交互比较复杂的，需要一个更整块的区域来进行操作。

##### centerArea​

画布区域，由于画布大多数是展示作用，所以一般扩展的种类比较少。常见的扩展有：

1. 画布大小修改
2. 物料选中扩展区域修改

##### rightArea​

右侧区域，常用于组件的配置。常见的扩展有：统一处理组件的配置项，例如统一删除某一个配置项，统一添加某一个配置项的。

##### bottomArea​

底部扩展区域。

##### toolbar​

跟 topArea 类似，按需放置面板插件~

#### 展示类型 (type)​

展示类型用于区分插件在设计器内可操作的几种不同界面类型。主要的几种类型为 PanelDock、Widget、Dock，另有 Panel 类型目前不推荐使用。

##### PanelDock​

PanelDock 是以面板的形式展示在设计器的左侧区域的。其中主要有两个部分组成，一个是图标，一个是面板。当点击图标时可以控制面板的显示和隐藏。

下图是组件库插件的展示效果。

其中右上角可以进行固定，可以对弹出的宽度做设定

接入可以参考代码

    import { skeleton } from "@alilc/lowcode-engine";

    skeleton.add({
      area: "leftArea", // 插件区域
      type: "PanelDock", // 插件类型，弹出面板
      name: "sourceEditor",
      content: SourceEditor, // 插件组件实例
      props: {
        align: "left",
        icon: "wenjian",
        title: '标题', // 图标下方展示的标题
        description: "JS 面板",
      },
      panelProps: {
        floatable: true, // 是否可浮动
        height: 300,
        hideTitleBar: false,
        maxHeight: 800,
        maxWidth: 1200,
        title: "JS 面板",
        width: 600,
      },
    });

##### Widget​

Widget 形式是直接渲染在当前编辑器的对应位置上。如 demo 中在设计器顶部的所有组件都是这种展现形式。

接入可以参考代码：

    import { skeleton } from "@alilc/lowcode-engine";
    // 注册 logo 面板
    skeleton.add({
      area: "topArea",
      type: "Widget",
      name: "logo",
      content: Logo,  // Widget 组件实例
      contentProps: { // Widget 插件 props
        logo:
        "https://img.alicdn.com/tfs/TB1_SocGkT2gK0jSZFkXXcIQFXa-66-66.png",
        href: "/",
      },
      props: {
        align: "left",
        width: 100,
      },
    });

##### Dock​

一个图标的表现形式，可以用于语言切换、跳转到外部链接、打开一个 widget 等场景。

    import { skeleton } from "@alilc/lowcode-engine";

    skeleton.add({
      area: "leftArea",
      type: "Dock",
      name: "opener",
      props: {
        icon: Icon, // Icon 组件实例
        align: "bottom",
        onClick: function () {
          // 打开外部链接
          window.open('https://lowcode-engine.cn');
          // 显示 widget
          skeleton.showWidget('xxx');
        }
      }
    });

## 方法​

### add​

往指定扩展区加入一块面板

    /**
     * 增加一个面板实例
     * add a new panel
     * @param config
     * @param extraConfig
     * @returns
     */
    add(config: IPublicTypeWidgetBaseConfig, extraConfig?: Record<string, any>): any;

IWidgetBaseConfig 定义如下：

属性名 | 含义 | 备注
--- | --- | ---
name | 面板名称 |
area | 扩展区位置，可选值：'topArea' | 'leftArea' | 'rightArea' | 'toolbar' | 'bottomArea' | 'mainArea' |
type | 面板类型，可选值：'Widget' | 'PanelDock' | 'Panel' | Dock | 详见前文中对展示类型的描述
content | 面板的实现类/节点，类型是 ReactClass | ReactElement |
props | 面板属性 | align: 'top' | 'bottom' | 'left' | 'center' | 'right'; // 指定面板 icon 位置区域 icon: string | ReactElement; // icon 为字符串时，请确定当前 fusion 主题包中包含该 icon description: string; condition: Function; // 指定当前面板的显影状态
contentProps | 面板的实现类/节点的参数 |
panelProps | 假如 type: 'Panel' | 'PanelDock' 时有效，传给 Panel 类的参数 | keepVisibleWhileDragging: boolean; // 当有元素在当前 panel 拖拽时，是否保持 panel 为展开状态，默认值：false area: 'leftFloatArea' | 'leftFixedArea' // 指定 panel 位于浮动面板还是钉住面板
index | 面板的位置，不传默认按插件注册顺序 |

### remove​

移除一个面板实例

    /**
     * 移除一个面板实例
     * remove a panel
     * @param config
     * @returns
     */
    remove(config: IPublicTypeWidgetBaseConfig): number | undefined;

### getPanel​

获取面板实例

    /**
     * 获取面板实例
     * @param name 面板名称
     */
    getPanel(name: string): IPublicModelSkeletonItem | undefined;

相关类型：IPublicModelSkeletonItem

@since v1.1.10

### showPanel​

展示指定 Panel 实例

    /**
     * 展示指定 Panel 实例
     * show panel by name
     * @param name
     */
    showPanel(name: string): void;

### hidePanel​

隐藏面板

    /**
     * 隐藏面板
     * hide panel by name
     * @param name
     */
    hidePanel(name: string): void;

### showWidget​

展示指定 Widget 实例

    /**
     * 展示指定 Widget 实例
     * show widget by name
     * @param name
     */
    showWidget(name: string): void;

### enableWidget​

将 widget 启用。

    /**
     * 将 widget 启用
     * enable widget
     * @param name
     */
    enableWidget(name: string): void;

### hideWidget​

隐藏指定 widget 实例。

    /**
     * 隐藏指定 widget 实例
     * hide widget by name
     * @param name
     */
    hideWidget(name: string): void;

### disableWidget​

将 widget 禁用掉，禁用后，所有鼠标事件都会被禁止掉。

适用场景：在该面板还在进行初始化构造时，可以先禁止掉，防止用户点击报错，待初始化完成，重新启用。

    /**
     * 将 widget 禁用掉，禁用后，所有鼠标事件都会被禁止掉。
     * disable widget，and make it not responding any click event.
     * @param name
     */
    disableWidget(name: string): void;

### showArea​

显示某个 Area

    /**
     * 显示某个 Area
     * show area
     * @param areaName name of area
     */
    showArea(areaName: string): void;

### hideArea​

隐藏某个 Area

    /**
     * 隐藏某个 Area
     * hide area
     * @param areaName name of area
     */
    hideArea(areaName: string): void;

### getAreaItems​

获取某个区域下的所有面板实例

    /**
      * 获取某个区域下的所有面板实例
      * @param areaName IPublicTypeWidgetConfigArea
      */
    getAreaItems(areaName: IPublicTypeWidgetConfigArea): IPublicModelSkeletonItem[] | undefined;

相关类型：IPublicModelSkeletonItem

### registerConfigTransducer​

注册一个面板的配置转换器（transducer）。

    /**
     * 注册一个面板的配置转换器（transducer）。
     * Registers a configuration transducer for a panel.
     * @param {IPublicTypeConfigTransducer} transducer
     *   - 要注册的转换器函数。该函数接受一个配置对象（类型为 IPublicTypeSkeletonConfig）作为输入，并返回修改后的配置对象。
     *   - The transducer function to be registered. This function takes a configuration object
     *
     * @param {number} level
     *   - 转换器的优先级。优先级较高的转换器会先执行。
     *   - The priority level of the transducer. Transducers with higher priority levels are executed first.
     *
     * @param {string} [id]
     *   - （可选）转换器的唯一标识符。用于在需要时引用或操作特定的转换器。
     *   - (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;

使用示例

    import { IPublicModelPluginContext, IPublicTypeSkeletonConfig } from '@alilc/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', // 插件需要配合 ^1.0.0 的引擎才可运行
      },
    };

    export default controlPanelWidthPlugin;

## 事件​

### onShowPanel​

监听 Panel 实例显示事件

    /**
     * 监听 panel 显示事件
     * set callback for panel shown event
     * @param listener
     * @returns
     */
    onShowPanel(listener: (paneName?: string, panel?: IPublicModelSkeletonItem) => void): IPublicTypeDisposable;

相关类型：IPublicTypeDisposable

### onHidePanel​

监听 Panel 实例隐藏事件

    /**
     * 监听 Panel 实例隐藏事件
     * set callback for panel hidden event
     * @param listener
     * @returns
     */
    onHidePanel(listener: (paneName?: string, panel?: IPublicModelSkeletonItem) => void): IPublicTypeDisposable;

相关类型：IPublicTypeDisposable

### onDisableWidget​

监听 Widget 实例 Disable 事件

    /**
     * 监听 Widget 实例 Disable 事件
     * @param listener
     */
    onDisableWidget(listener: (paneName?: string, panel?: IPublicModelSkeletonItem) => void): IPublicTypeDisposable;

相关类型：IPublicTypeDisposable

### onEnableWidget​

监听 Widget 实例 Enable 事件

    /**
     * 监听 Widget 实例 Enable 事件
     * @param listener
     */
    onEnableWidget(listener: (paneName?: string, panel?: IPublicModelSkeletonItem) => void): IPublicTypeDisposable;

相关类型：IPublicTypeDisposable

### onShowWidget​

监听 Widget 实例显示事件

    /**
     * 监听 Widget 显示事件
     * set callback for widget shown event
     * @param listener
     * @returns
     */
    onShowWidget(listener: (paneName?: string, panel?: IPublicModelSkeletonItem) => void): IPublicTypeDisposable;

相关类型：IPublicTypeDisposable

### onHideWidget​

监听 Widget 实例隐藏事件

    /**
     * 监听 Widget 隐藏事件
     * set callback for widget hidden event
     * @param listener
     * @returns
     */
    onHideWidget(listener: (paneName?: string, panel?: IPublicModelSkeletonItem) => void): IPublicTypeDisposable;

相关类型：IPublicTypeDisposable

## 使用示例​

    import { skeleton } from '@alilc/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 面板',
      },
      panelProps: {
        floatable: true,
        height: 300,
        help: undefined,
        hideTitleBar: false,
        maxHeight: 800,
        maxWidth: 1200,
        title: 'JS 面板',
        width: 600,
      },
      content: SourceEditor,
    });

    // 显隐 panel
    skeleton.showPanel('sourceEditor');
    skeleton.hidePanel('sourceEditor');

    // 创建一个浮动的 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'
        }
      }
    });

    // 显隐 widget
    skeleton.showWidget('floatingWidget');
    skeleton.hideWidget('floatingWidget');

    // 控制 widget 的可点击态
    skeleton.enableWidget('sourceEditor');
    skeleton.disableWidget('sourceEditor');

### bottomArea 示例​

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

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

    skeleton.showPanel('bottomAreaPanelName');

### widget 示例​

    // 注册 logo 面板
    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',
      },
    });