---
  title: dooringx lib plug-in development
  toc: menu
  order: 3
---
### Plug in import
The dooringx lib plug-in requires an object of type 'partial<initconfig>'.
For multiple plug-ins, you need to use the 'userconfigmerge' exported by dooringx lib to merge.
Not all properties of userconfigmerge will be merged, and some properties will be overwritten.
### Left panel
On the left panel, enter leftrenderlistcategory.
Type is the category. The category displayed by the component on the left is determined by this field.
On the left is the small icon.
When custom is true, you can use customrender to customize the rendering.
### Left side assembly
To be updated
### Plug in import
The left component should be placed in the leftregistmap of the object.
The left component supports synchronous import or asynchronous import.
If you need to import components asynchronously, you need to fill in urlfn and a function that returns promise. Remote loading of components can also be supported, as long as webpack is equipped with it.
If you need to import components synchronously, you need to put the components into the initcomponentcache of the configuration item, so that they will be registered in the componentregister when loaded.
### Component writing
The component needs to export an object generated by componentitemfactory.
```js
const MButton = new ComponentItemFactory(
'button',
'按钮',
{
style: [
createPannelOptions<FormMap, 'input'>('input', {
receive: 'text', 
label: '文字',
}),
],
animate: [createPannelOptions<FormMap, 'animateControl'>('animateControl', {})],
actions: [createPannelOptions<FormMap, 'actionButton'>('actionButton', {})],
},
{
props: {
...
text:'yehuozhili'// input配置项组件接收的初始值
},
},
(data, context, store, config) => {
return <ButtonTemp data={data} store={store} context={context} config={config}></ButtonTemp>;
},
true
);
export default MButton;
```
The first parameter is the component registration name, and the second parameter is used to display the usage.
The third parameter is used to configure the configuration item component of the right panel. The key is the classification of the right panel, and the value is the configuration item component array.
The fourth parameter will configure the initial value of the component. In particular, the manufacturing component must have the initial width and height (not supported by the content), otherwise there will be problems when selecting all during adaptation.
There are many useful properties in this initial value. For example, fixed represents fixed positioning. You can change this value in combination with configuration items to make the component fixed positioning.
And candrag is similar to the lock command. Locked elements cannot be dragged.
The rotate in the initial value needs an object. Value represents the rotation angle and canrotate represents whether the rotation can be operated. (supported from version 0.7.0)
The fifth parameter is a function. You will get the configuration from the receive attribute in the configuration item (the default configuration is receive for the time being). For example, if the received in the above example is text, the field will be received in the data in the function.
Context generally has only preview and edit, which are used to judge the environment.
Config can get all the data for use when making events.
The sixth parameter resize is to judge whether scaling can be performed. When it is false, scaling cannot be performed.
The seventh parameter is needposition. After some components are moved into the canvas, the drop point will be adopted by default. This configuration item is true by default, which is the position to be dragged. When it is false, the top and left positioning of the components will be used to place them.
### Event registration
#### Timing registration
As mentioned earlier, events have timing and functions, so hook can be used to register timing in the component:
```js
useDynamicAddEventCenter(pr, `${pr.data.id}-init`, '初始渲染时机'); //注册名必须带id 约定！
useDynamicAddEventCenter(pr, `${pr.data.id}-click`, '点击执行时机');
```
The first parameter of usedynamicaddevencenter is an object composed of four parameters of render. The second parameter is the registered time name, which must be related to the ID, which is a convention. Otherwise, multiple components may cause name conflicts, and it is convenient to find the time.
After registering the timing, you need to put the timing into the corresponding trigger position. For example, the click execution timing of this button is put into onclick:
```js
<Button
onClick={() => {
eventCenter.runEventQueue(`${pr.data.id}-click`, pr.config);
}}
>
yehuozhili
</Button> 
```
The first parameter is the registered time name, and the second parameter is the last parameter config in the render function
#### Function registration
The function is thrown by the component and can be loaded into the event chain. For example, if I register a function to change the text, I can call the function at the time of any component, so as to trigger the component to change the text.
Function registration needs to be put into useeffect. At present, there is no need to uninstall actively, but when communicating with the function on the pop-up window, you may need to uninstall in the preview environment, otherwise the second execution may not take effect.
Note that the ID should be accompanied by the component ID, because a component can drag n components to generate n functions.
See later function development for parameters and configuration in the function.
### Right side panel
The configuration of the right panel is the same as that of the left panel:
Type will affect the key name of the third parameter of the left component during development. The key name represents the type displayed on the right.
Icon can put text or icons for panel switching.
If custom is true, the display under this panel can be customized through customrender.
### Right side assembly
#### Right side component import
When importing, just match the developed components into an object and put it into initformcomponents.
```js
initFormComponents: Formmodules,
```
#### Right side component development
First, in order to have a good development experience, you need to define a formmap type:
```js
export interface FormBaseType {
receive?: string;
}
export interface FormInputType extends FormBaseType {
label: string;
}
export interface FormActionButtonType {}
export interface FormAnimateControlType {}
export interface FormMap {
input: FormInputType;
actionButton: FormActionButtonType;
animateControl: FormAnimateControlType;
}
```
The key name of formmap is the key name of initformcomponents. The value of formmap corresponds to the value that the component needs to receive.
Take the input component as an example. At this time, forminputtype has two attributes, label and receive.
When developing this component, props will receive:
```js
interface MInputProps {
data: CreateOptionsRes<FormMap, 'input'>;
current: IBlockType;
config: UserConfig;
}
```
That is, where data is of formmap type and current is the currently clicked component, needless to say config.
Remember the third parameter in component development on the left? So it's all related:
```js
style: [
createPannelOptions<FormMap, 'input'>('input', {
receive: 'text',  
label: '文字',
}),
],
```
The generics of the createpaneloptions function are filled with the corresponding components, which will give a good prompt to the received configuration items.
All you need to do in the configuration item component is to receive the configuration item from the component, and then modify the property of current:
```js
function MInput(props: MInputProps) {
const option = useMemo(() => {
return props.data?.option || {};
}, [props.data]);
return (
<Row style={{ padding: '10px 20px' }}>
<Col span={6} style={{ lineHeight: '30px' }}>
{(option as any)?.label || '文字'}：
</Col>
<Col span={18}>
<Input
value={props.current.props[(option as any).receive] || ''}
onChange={(e) => {
const receive = (option as any).receive;
const clonedata = deepCopy(store.getData());
const newblock = clonedata.block.map((v: IBlockType) => {
if (v.id === props.current.id) {
v.props[receive] = e.target.value;
}
return v;
});
store.setData({ ...clonedata, block: [...newblock] });
}}
></Input>
</Col>
</Row>
);
}
```
Because you can easily get the store, you can modify the data anywhere.
Associate the value of the component with the attribute of current, and onchange to modify the store, so as to complete a two-way binding.
Note: if your right component needs attributes other than block, you may need to judge whether it is in pop-up mode.
####Import of commands
The command object can be imported into the initcommandmodule of the plug-in
```js
initCommandModule: commandModules,
```
#### Command development
A commandfactory object needs to be exported.
```js
import { CommanderItemFactory } from 'dooringx-lib';
const undo = new CommanderItemFactory(
'redo',
'Control+Shift+z',
(store) => {
store. redo();
},
'redo '
);
export default undo;
```
The first parameter is the registration name.
The second parameter is the shortcut key name, and the shortcut key mapping is the key value of the keyboard event
The case of 26 English letters is ignored. At present, only one shortcut key can be registered for a command. If you do not need to register shortcut keys, you can fill in the blank string.
Metakey is the same as controlkey. Just write control.
At present, the third parameter can only get store, which needs to be modified later. The second parameter in version 0.2.0 can obtain config. At the same time, the commander does not export from the index. If necessary, it can be obtained from config.
The last parameter is the display name.
### Right click menu
The right-click menu can be customized:
```js
//Custom right click
const contextMenuState = config. getContextMenuState();
const unmountContextMenu = contextMenuState. unmountContextMenu;
const commander = config. getCommanderRegister();
const ContextMenu = () => {
const handleclick = () => {
unmountContextMenu();
};
const forceUpdate = useState(0)[1];
contextMenuState. forceUpdate = () => {
forceUpdate((pre) => pre + 1);
};
return (
<div
style={{
left: contextMenuState. left,
top: contextMenuState. top,
position: 'fixed',
background: 'rgb(24, 23, 23)',
}}
>
<div
style={{ width: '100%' }}
onClick={() => {
Commander exec('redo');
handleclick();
}}
>
< button > Customize < / button >
</div>
</div>
);
};
contextMenuState. contextMenu = <ContextMenu></ContextMenu>;
```
Get the contextmenustate first. There is an unmountcontextmenu on the contextmenustate, which is the method to close the right-click menu.
Therefore, you need to call close after clicking.
At the same time, the left and top above are the right-click positions.
In addition, you also need to add a strong brush assignment to forceupdate in the component to follow when the component moves.
### Function development
#### Function import
Import the function into an object and put it into initfunctionmap
```js
initFunctionMap: functionMap,
```
#### Function development
This section is waiting to be updated
#### Timing and function loading
If necessary, generally use:
```js
eventCenter. manualUpdateMap(cur, displayName, arr);
```
The first one in the manual updatemap is the time name, the second one is the display name, and the third one is user selection.
After updating the event center, you also need to update the store, and the result is subject to the store.