# 可视化编辑支持第三方组件库展示能力
> 对于已有的小程序组件库，工具可视化新增展示能力。只需该组件库包处于  miniprogram_npm 目录下，且在组件库根目录下配置相应的配置文件接口
工具可视化即可解析和添加该组件库组件信息，使其可以拖拽到相应页面 wxml 和 json 中。

## 运行环境
[1.05.2206242](log#rc) 或以上版本的开发者工具

## 新建操作流程
工具可视化的第三方组件库接入，需要新增配置一份 json 来进行管理
## 1. 新建配置
- 在组件库的根目录中新建一个 `.wechatide.ib.json`，需要打包后的 miniprogram_root

## 2. 配置组成说明
### 2.1 主要结构 components 和 menu
2. `.wechatide-ib.json` 内部是一个  json 对象，包含以下 `key`
```typescript
export interface IIBComponentLibConfig {
  key: string // 组件库标识，如 tdesign
  label: string // 可读名称，如 "Tdesign 组件"

  // 组件列表说明配置
  components: {
    [propName: string]: IIBComponentLibConfigComponent
  };

  // 菜单相关
  menu: IIBComponentLibConfigMenu[], // 组件面板菜单情况
  common: IIBComponentLibConfigCommon // @TODO 通用属性和配置
}
```

### 2.2 组件定义 IIBComponentLibConfigComponent
工具会通过 components 的内容获取定义组件的基本信息
```typescript

export interface IIBComponentLibConfigComponent {
  key?: string; // 组件标签名称, 如 "t-button", 应该和组件列表的 key 是一样的，工具会默认补齐，可不配置
  label: string; // 组件可读名称，如 "按钮"
  icon: string; // 组件 icon 示意图、本地或者网络地址，建议尺寸为 200 * 100， 如 "../../xxx.png" 或者 “https://xxxx/xx.png”
  topIcon?: string // 组件如果需要放在头部，本地或者网络地址，建议尺寸 44 * 44, 内边距为 10, 如 "../../xxx.png" 或者 “https://xxxx/xx.png”
  events?: IIBComponentLibConfigEvent[]; // 事件列表
  properties?: IIBComponentLibConfigProperty[]; // 属性列表
  tpl?: string; // 自定义组件模块代码，为空则用 key 作为标签名生成默认 tpl `<$key></$key>`
  path?: string, // 原子组件的相对 npm 根目录的位置
  require?: {
	[propName: string]: string	
  } // 组件依赖的其他组件,填写的是依赖的组件的 key，通常是组合组件tpl 才会需要填写
  externalClasses?: string[] // 外部样式类
}
```

组件 icon ，如下所示

组件 topIcon, 如下所示

例如最简单的一个组件 button，虽然没什么用
```json
{
  "button": {
    "key": "td-button",
    "icon": "",
    "label": "按钮"
 }
```

### 2.2.1 组件自定义模板 tpl
tpl 表示使用组件会生成的节点结构内容，如果为空则相当默认使用组件 key 来拼一个空的标签 `<td-button />`
```json
{
  "key": "td-button",
  "icon": "",
  "label": "按钮",
  "tpl": "<td-button />"
}
```
如果需要自定义的話，则会输出对应的 tpl `<td-button type="warn">按钮</td-view>`
```json
{
  "key": "td-button",
  "icon": "",
  "label": "按钮",
  "tpl": "<td-button type=\"warn\">按钮</td-button>"
}
```

### 2.2.2 组件依赖路径 path
组件如果是自定义组件的内容，是需要去依赖加载的，path 表示该组件的组件定路径，相对组件库根目录

```json
{
  "key": "td-button",
  "icon": "",
  "label": "按钮",
  "tpl": "<td-button type=\"warn\">按钮</td-button>",
  "path": "./dist/components/button/index" 
}
```

### 2.2.3 组合组件依赖说明 require
如果 tpl 配置的是组合多个自定义组件的话，且不是一个自定义组件的话，可以通过配置 require 来有多个依赖的话
```json
{
  "key": "td-button-group",
  "icon": "",
  "label": "按钮",
  "tpl": "<view><td-button type=\"warn\">按钮</td-button> <t-icon></t-icon><view>",
  "require": {
     "td-icon": "./dist/components/icon/index",
     "td-button": "./dist/components/button/index"
  }
}
```

### 2.2.4 组件事件 IComponentEvent
组件事件 IComponentEvent 解释自定义组件能够配置的事件
```typescript
interface IIBComponentLibConfigEvent {
  key: string; // 事件名称，如"onChange"
  label: string; // 事件展示可读名称
  desc: string; // 事件展示的描述
  references?: IIBComponentLibConfigPropertyReferences // 组件属性说明文档
}

// 事件说明文档地址
interface IIBComponentLibConfigPropertyReferences {
  desc: string,
  url: string
}
```
示例，如下自定义了一个 onClick 的事件属性
```json
{
  "key": "td-button-group",
  "icon": "",
  "label": "按钮",
  "tpl": "<td-button type=\"warn\">按钮</td-button>",
  "path": "./dist/components/button/index",
  "events": [
    {
    "key": "onClick",
    "label": "点击处理",
    "desc": "点击按钮后触发绑定"
    }
  ]
}
```

### 2.2.5 组件属性 IComponentProperty
组件属性 IComponentProperty 解释组件能够配置的属性
```typescript

type ComponentPropertyType = 'Boolean' | 'String' | 'Color' | 'Image' | 'Enum' | 'Number' | 'Object' | 'Array'
export interface IIBComponentLibConfigProperty {
  key: string; // 属性名称, 如 "value"
  label: string; // 属性展示可读名称
  desc: string; // 属性展示的描述
  type: ComponentPropertyType[]; // 属性值类型（多种）
  defaultValue?: any // @TODO
  enum?: any[] // @TODO 枚举，对应下拉选择
  references?: IIBComponentLibConfigPropertyReferences // @TODO 组件属性说明文档
}
```

如下面定义了一个button 的 type 属性，其值类型为字符串，默认值为 ”normal"
```json
{
  "key": "td-button-group",
  "icon": "",
  "label": "按钮",
  "tpl": "<td-button type=\"warn\">按钮</td-button>",
  "path": "./dist/components/button/index",
  "properties": [
  {
        "key": "text",
        "label": "文本",
        "desc": "按钮文本",
        "type": "String",
        "defaultValue": "normal"
      },
  {
        "key": "type",
        "label": "类型",
        "desc": "按钮类型",
        "type": "Enum",
        "defaultValue": "a",
        "details": [
        "a", "b", "c"
        ]
      }
  ]
}
```

### 2.2.6 复用公共的 properties 和 event(暂不支持)
可在 common 定义公共的 property 和 event ，然后组件使用的时候只需要写对应的 key 值即可
```json
{
  "common": {
    "properties": {
      "commonText": {
        "key": "text",
        "label": "文本",
        "desc": "按钮文本",
        "type": "String",
        "defaultValue": "normal"
      }
    }
  },
  "components": [
    {
      "key": "td-button-group",
      "icon": "",
      "label": "按钮",
  	  "tpl": "<td-button type=\"warn\">按钮</td-button>",
  	  "path": "./dist/components/button/index",
      "properties": [
        "commonText",
        {
          "key": "type",
          "label": "类型",
          "desc": "按钮类型",
          "type": "Enum",
          "defaultValue": "a",
          "details": ["a", "b", "c"]
        }
      ]
    }
  ]
}

```

### 2.3 组件定义菜单
菜单定义的是展示组件的层级结构，目前只支持总共三级的结构
- 组件类型
- 组件二级类型
- 具体组件

```typescript
// 一级菜单
// 一级菜单
export interface IIBComponentLibConfigMenu {
  key: string; // 菜单唯一标识
  label: string; // 菜单可读名称
  icon?: string // 菜单 menu 图标 20*20
  submenu: IIBComponentLibConfigSubMenu[];
}
// 二级菜单
export interface IIBComponentLibConfigSubMenu {
  key: string; // 二级菜单唯一标识
  label: string; // 二级菜单可读名称
  components: string[]; // 对应的组件 key
}

```
示例如下

```json
{
  "menu": [
    {
      "key": "form",
      "label": "表单组件",
      "icon": "",
      "submenu": [
        {
          "label": "按钮",
          "key": "button",
          "compnents": ["button", "button-group"]
        }
      ]
    }
  ]
}
```

### 完整的描述

```typescript
/**
 * 可视化组件库配置规范
 */

export interface IIBComponentLibConfig {
  key: string // 组件库标识
  label: string // 可读名称

  // 组件列表说明配置
  components: {
    [propName: string]: IIBComponentLibConfigComponent
  };

  // 菜单相关
  topList?: string[], // 组件面板顶部通用组件列表 max 5个，配置的内容是 components 中组件的 key
  menu: IIBComponentLibConfigMenu[], // 组件面板菜单情况

  // @TODO: 其他配置
  remote?: string // @TODO 远程配置地址，后续读取配置进行更新
  common: IIBComponentLibConfigCommon // @TODO
}

// 通用 properties 和 events
export interface IIBComponentLibConfigCommon {
  properties?: {
    [proName: string]: IIBComponentLibConfigProperty;
  }, // 通用属性
  events?: {
    [proName: string]: IIBComponentLibConfigEvent;
  }, // 通用事件
}

export interface IIBComponentLibConfigComponent {
  key?: string; // 组件标签名称, 应该和组件列表的 key 是一样的，工具会默认补齐
  label: string; // 组件可读名称
  icon: string; // 组件 icon 示意图、本地或者网络地址，建议尺寸为 200 * 100
  topIcon?: string // 组件如果需要放在头部，本地或者网络地址，建议尺寸 44 * 44, 内边距为 10
  events?: IIBComponentLibConfigEvent[]; // 事件列表
  properties?: IIBComponentLibConfigProperty[]; // 属性列表
  tpl?: string; // 自定义组件模块代码，为空则用 key 作为标签名生成默认 tpl `<$key></$key>`
  path?: string, // 原子组件的相对 npm 根目录的位置
  require?: string[] // 组件依赖的其他组件,填写的是依赖的组件的 key，通常是组合组件tpl 才会需要填写
}

interface IIBComponentLibConfigEvent {
  key: string; // 事件名称，如"onChange"
  label: string; // 事件展示可读名称
  desc: string; // 事件展示的描述
  references?: IIBComponentLibConfigPropertyReferences // 组件属性说明文档
}

type ComponentPropertyType = 'Boolean' | 'String' | 'Color' | 'Image' | 'Enum' | 'Number' | 'Object' | 'Array'
export interface IIBComponentLibConfigProperty {
  key: string; // 属性名称, 如 "value"
  label: string; // 属性展示可读名称
  desc: string; // 属性展示的描述
  type: ComponentPropertyType[]; // 属性值类型（多种）
  defaultValue?: any // @TODO
  enum?: any[] // @TODO 枚举，对应下拉选择
  references?: IIBComponentLibConfigPropertyReferences // @TODO 组件属性说明文档
}

// 对应文档地址
export interface IIBComponentLibConfigPropertyReferences {
  desc: string,
  url: string
}

// 一级菜单
export interface IIBComponentLibConfigMenu {
  key: string; // 菜单唯一标识
  label: string; // 菜单可读名称
  icon?: string // 菜单 menu 图标 20*20
  submenu: IIBComponentLibConfigSubMenu[];
}
// 二级菜单
export interface IIBComponentLibConfigSubMenu {
  key: string; // 二级菜单唯一标识
  label: string; // 二级菜单可读名称
  components: string[]; // 对应的组件 key
}

```
