fix(amis-saas-4371): 合入布局容器相关代码

Change-Id: I32f0e69e3ba397821561f4881ebc131c9112f065
This commit is contained in:
wibetter 2022-11-14 17:03:04 +08:00
commit 56a2480ebf
38 changed files with 2998 additions and 312 deletions

View File

@ -23,14 +23,6 @@
"lib",
"esm"
],
"lint-staged": {
"{src,scss,examples}/**/**/*.{js,jsx,ts,tsx,scss,json}": [
"prettier --write"
],
"{src,scss,examples}/**/**/*.scss": [
"stylelint"
]
},
"dependencies": {
"@webcomponents/webcomponentsjs": "^2.6.0",
"amis-editor-core": "*",

View File

@ -96,6 +96,7 @@ function transpileDynamicImportForCJS(options) {
}
function getPlugins(format = 'esm') {
const typeScriptOptions = {
typescript: require('typescript'),
sourceMap: false,
@ -161,4 +162,3 @@ function onRollupError(callback = () => {}) {
}
};
}

View File

@ -9,6 +9,7 @@ import {registerIcon, Icon} from 'amis-editor-core';
* 4. icon x 23
* 5. icon x 53
* 6. icon x 3
* 7. icon x 12
*/
// 功能类组件 icon x 11
@ -135,6 +136,21 @@ import propertySheet from './other/property-sheet.svg';
import tooltip from './other/tooltip.svg';
import divider from './other/divider.svg';
// 常见布局组件 icon x 12
import layout_absolute from './layout/layout-absolute.svg';
import layout_fixed from './layout/layout-fixed.svg';
import layout_1with2 from './layout/layout-1with2.svg';
import layout_2cols from './layout/layout-2cols.svg';
import layout_2row from './layout/layout-2row.svg';
import layout_2with1 from './layout/layout-2with1.svg';
import layout_3cols from './layout/layout-3cols.svg';
import layout_3row from './layout/layout-3row.svg';
import layout_full from './layout/layout-full.svg';
import layout_1_2 from './layout/layout1-2.svg';
import layout_2_1 from './layout/layout2-1.svg';
import layout_3_1 from './layout/layout3-1.svg';
import layout_3_2 from './layout/layout3-2.svg';
// 功能类组件 icon x 11
registerIcon('audio-plugin', audio);
registerIcon('custom-plugin', custom);
@ -257,4 +273,19 @@ registerIcon('property-sheet-plugin', propertySheet);
registerIcon('tooltip-plugin', tooltip);
registerIcon('divider-plugin', divider);
// 常见布局组件 icon x 13
registerIcon('layout-absolute-plugin', layout_absolute);
registerIcon('layout-fixed-plugin', layout_fixed);
registerIcon('layout-1with2-plugin', layout_1with2);
registerIcon('layout-2cols-plugin', layout_2cols);
registerIcon('layout-2row-plugin', layout_2row);
registerIcon('layout-2with1-plugin', layout_2with1);
registerIcon('layout-3cols-plugin', layout_3cols);
registerIcon('layout-3row-plugin', layout_3row);
registerIcon('layout-full-plugin', layout_full);
registerIcon('layout-1-2-plugin', layout_1_2);
registerIcon('layout-2-1-plugin', layout_2_1);
registerIcon('layout-3-1-plugin', layout_3_1);
registerIcon('layout-3-2-plugin', layout_3_2);
export {Icon};

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16" height="16" viewBox="0 0 34 34" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="常见布局" transform="translate(-403.000000, -159.000000)" fill-rule="nonzero" stroke="currentColor" stroke-width="2">
<g id="layout-1with2" transform="translate(400.000000, 156.000000)">
<g id="分组" transform="translate(3.000000, 3.000000)">
<rect id="矩形" x="1" y="1" width="32" height="32" rx="1"></rect>
<path d="M17,1.5 L17,32.5" id="直线" stroke-dasharray="0" transform="translate(17.000000, 17.000000) rotate(90.000000) translate(-17.000000, -17.000000) "></path>
<path d="M17.5,20 L17.5,33" id="直线" stroke-dasharray="0"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 982 B

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16" height="16" viewBox="0 0 34 34" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="常见布局-两栏" transform="translate(-163.000000, -159.000000)" fill-rule="nonzero" stroke="currentColor" stroke-width="2">
<g id="layout-2cols" transform="translate(160.000000, 156.000000)">
<g id="分组" transform="translate(3.000000, 3.000000)">
<rect id="矩形" x="1" y="1" width="32" height="32" rx="1"></rect>
<path d="M16.5,1.5 L16.5,33.5" id="直线" stroke-dasharray="0"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 806 B

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16" height="16" viewBox="0 0 34 34" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="常见布局-两行" transform="translate(-323.000000, -158.000000)" fill-rule="nonzero" stroke="currentColor" stroke-width="2">
<g id="layout-2row" transform="translate(320.000000, 155.000000)">
<g id="分组" transform="translate(3.000000, 3.000000)">
<rect id="矩形" x="1" y="1" width="32" height="32" rx="1"></rect>
<path d="M17,1.5 L17,32.5" id="直线" stroke-dasharray="0" transform="translate(17.000000, 17.000000) rotate(90.000000) translate(-17.000000, -17.000000) "></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 899 B

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16" height="16" viewBox="0 0 34 34" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="常见布局-2拖1" transform="translate(-483.000000, -159.000000)" fill-rule="nonzero" stroke="currentColor" stroke-width="2">
<g id="layout-2with1" transform="translate(480.000000, 156.000000)">
<g id="分组" transform="translate(20.000000, 20.000000) scale(1, -1) translate(-20.000000, -20.000000) translate(3.000000, 3.000000)">
<rect id="矩形" x="1" y="1" width="32" height="32" rx="1"></rect>
<path d="M17,1.5 L17,32.5" id="直线" stroke-dasharray="0" transform="translate(17.000000, 17.000000) rotate(90.000000) translate(-17.000000, -17.000000) "></path>
<path d="M17.5,20 L17.5,33" id="直线" stroke-dasharray="0"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16" height="16" viewBox="0 0 34 34" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="常见布局-三栏" transform="translate(-243.000000, -159.000000)" fill-rule="nonzero" stroke="currentColor" stroke-width="2">
<g id="layout-3cols" transform="translate(240.000000, 156.000000)">
<g id="分组" transform="translate(3.000000, 3.000000)">
<rect id="矩形" x="1" y="1" width="32" height="32" rx="1"></rect>
<path d="M11.5,1.5 L11.5,33.5" id="直线" stroke-dasharray="0"></path>
<path d="M22.5,1.5 L22.5,33.5" id="直线" stroke-dasharray="0"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 899 B

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16" height="16" viewBox="0 0 34 34" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="常见布局" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="常见布局-上中下" transform="translate(-563.000000, -159.000000)" fill-rule="nonzero" stroke="currentColor" stroke-width="2">
<g id="layout-3row" transform="translate(560.000000, 156.000000)">
<g id="分组" transform="translate(20.000000, 20.000000) rotate(90.000000) translate(-20.000000, -20.000000) translate(3.000000, 3.000000)">
<rect id="矩形" x="1" y="1" width="32" height="32" rx="1"></rect>
<path d="M11.5,1.5 L11.5,33.5" id="直线" stroke-dasharray="0"></path>
<path d="M22.5,1.5 L22.5,33.5" id="直线" stroke-dasharray="0"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 991 B

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg t="1614848638463" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="14680" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16">
<path d="M592 336H176c-52.928 0-96 43.072-96 96v416c0 52.928 43.072 96 96 96h416c52.928 0 96-43.072 96-96V432c0-52.928-43.072-96-96-96z m32 512a32 32 0 0 1-32 32H176c-17.632 0-32-14.336-32-32V432c0-17.632 14.368-32 32-32h416c17.664 0 32 14.368 32 32v416z" fill="#515151" p-id="14681"></path><path d="M720 208H304a32 32 0 0 0 0 64h416c17.664 0 32 14.368 32 32v416a32 32 0 1 0 64 0V304c0-52.928-43.072-96-96-96zM528 752H240a32 32 0 1 0 0 64h288a32 32 0 1 0 0-64z" fill="currentColor" p-id="14682"></path>
<path d="M848 80H432a32 32 0 0 0 0 64h416c17.664 0 32 14.368 32 32v416a32 32 0 1 0 64 0V176c0-52.928-43.072-96-96-96z" fill="currentColor" p-id="14683"></path>
</svg>

After

Width:  |  Height:  |  Size: 897 B

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg t="1614838454815" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12115" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16">
<path d="M904 1024H120c-66.168 0-120-53.832-120-120V120C0 53.832 53.832 0 120 0h784c66.168 0 120 53.832 120 120v784c0 66.168-53.832 120-120 120zM120 4C56.038 4 4 56.038 4 120v784c0 63.962 52.038 116 116 116h784c63.962 0 116-52.038 116-116V120c0-63.962-52.038-116-116-116H120z" fill="currentColor" p-id="12116"></path>
<path d="M402 832h-130c-44.112 0-80-35.888-80-80V272c0-44.112 35.888-80 80-80h130c44.112 0 80 35.888 80 80v480c0 44.112-35.888 80-80 80z m-130-580c-11.028 0-20 8.972-20 20v480c0 11.028 8.972 20 20 20h130c11.028 0 20-8.972 20-20V272c0-11.028-8.972-20-20-20h-130z" fill="currentColor" p-id="12117"></path>
<path d="M752 482h-130c-44.112 0-80-35.888-80-80v-130c0-44.112 35.888-80 80-80h130c44.112 0 80 35.888 80 80v130c0 44.112-35.888 80-80 80z m-130-230c-11.028 0-20 8.972-20 20v130c0 11.028 8.972 20 20 20h130c11.028 0 20-8.972 20-20v-130c0-11.028-8.972-20-20-20h-130z" fill="currentColor" p-id="12118"></path>
<path d="M752 832h-130c-44.112 0-80-35.888-80-80v-130c0-44.112 35.888-80 80-80h130c44.112 0 80 35.888 80 80v130c0 44.112-35.888 80-80 80z m-130-230c-11.028 0-20 8.972-20 20v130c0 11.028 8.972 20 20 20h130c11.028 0 20-8.972 20-20v-130c0-11.028-8.972-20-20-20h-130z" fill="#205dd9" p-id="12119"></path></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16" height="16" viewBox="0 0 34 34" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<polygon id="path-1" points="4.5 4 30.5 4 30.5 30 4.5 30"></polygon>
<mask id="mask-2" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="26" height="26" fill="white">
<use xlink:href="#path-1"></use>
</mask>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="常见布局" transform="translate(-83.000000, -159.000000)" fill-rule="nonzero" stroke="currentColor">
<g id="layout-full" transform="translate(80.000000, 156.000000)">
<g id="分组" transform="translate(3.000000, 3.000000)">
<rect id="矩形" stroke-width="2" x="1" y="1" width="32" height="32" rx="1"></rect>
<use id="矩形" mask="url(#mask-2)" stroke-width="4" stroke-dasharray="2" xlink:href="#path-1"></use>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16" height="16" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="常见布局" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="常见布局-左一右二" transform="translate(-140.000000, -840.000000)" fill-rule="nonzero" stroke="currentColor" stroke-width="2">
<g id="左一右二" transform="translate(140.000000, 840.000000)">
<g id="分组" transform="translate(20.000000, 20.000000) rotate(-90.000000) translate(-20.000000, -20.000000) translate(3.000000, 3.000000)">
<rect id="矩形" x="1" y="1" width="32" height="32" rx="1"></rect>
<line x1="17" y1="1.5" x2="17" y2="32.5" id="直线" stroke-dasharray="0" transform="translate(17.000000, 17.000000) rotate(90.000000) translate(-17.000000, -17.000000) "></line>
<line x1="17.5" y1="20" x2="17.5" y2="33" id="直线" stroke-dasharray="0"></line>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16" height="16" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="常见布局" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="常见布局-左二右一" transform="translate(-220.000000, -840.000000)" fill-rule="nonzero" stroke="currentColor" stroke-width="2">
<g id="左二右一" transform="translate(220.000000, 840.000000)">
<g id="分组" transform="translate(20.000000, 20.000000) scale(-1, 1) rotate(-90.000000) translate(-20.000000, -20.000000) translate(3.000000, 3.000000)">
<rect id="矩形" x="1" y="1" width="32" height="32" rx="1"></rect>
<line x1="17" y1="1.5" x2="17" y2="32.5" id="直线" stroke-dasharray="0" transform="translate(17.000000, 17.000000) rotate(90.000000) translate(-17.000000, -17.000000) "></line>
<line x1="17.5" y1="20" x2="17.5" y2="33" id="直线" stroke-dasharray="0"></line>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16" height="16" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="常见布局" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="常见布局-经典布局" transform="translate(-460.000000, -840.000000)" fill-rule="nonzero" stroke="currentColor" stroke-width="2">
<g id="布局-栏内容器-经典布局" transform="translate(460.000000, 840.000000)">
<g id="分组" transform="translate(3.000000, 3.000000)">
<rect id="矩形" x="1" y="1" width="32" height="32" rx="1"></rect>
<line x1="17" y1="1.5" x2="17" y2="32.5" id="直线" stroke-dasharray="0" transform="translate(17.000000, 17.000000) rotate(90.000000) translate(-17.000000, -17.000000) "></line>
<line x1="11.5" y1="20" x2="11.5" y2="33" id="直线" stroke-dasharray="0"></line>
<line x1="14" y1="25" x2="32" y2="25" id="直线" stroke-dasharray="0"></line>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16" height="16" viewBox="0 0 40 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="常见布局" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="常见布局-经典布局" transform="translate(-540.000000, -840.000000)" fill-rule="nonzero" stroke="currentColor" stroke-width="2">
<g id="布局-栏内容器-经典布局" transform="translate(540.000000, 840.000000)">
<g id="分组" transform="translate(3.000000, 3.000000)">
<rect id="矩形" x="1" y="1" width="32" height="32" rx="1"></rect>
<line x1="5.5" y1="13" x2="5.5" y2="21" id="直线" stroke-dasharray="0" transform="translate(5.500000, 17.000000) rotate(90.000000) translate(-5.500000, -17.000000) "></line>
<line x1="27.5" y1="13" x2="27.5" y2="21" id="直线" stroke-dasharray="0" transform="translate(27.500000, 17.000000) rotate(90.000000) translate(-27.500000, -17.000000) "></line>
<line x1="11.5" y1="1" x2="11.5" y2="33" id="直线" stroke-dasharray="0"></line>
<line x1="23.5" y1="1" x2="23.5" y2="33" id="直线" stroke-dasharray="0"></line>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -138,6 +138,12 @@ import './plugin/CodeView';
import './plugin/WebComponent';
import './plugin/CRUD2';
import './plugin/ColumnToggler';
import './plugin/Layout/Layout_fixed_bottom';
import './plugin/Layout/Layout_fixed_top';
import './plugin/Layout/Layout_fixed';
import './plugin/Layout/Layout_scroll_x';
import './plugin/Layout/Layout_scroll_y';
import './plugin/Layout/Layout1_2_v4';
import {GridPlugin} from './plugin/Grid';
@ -157,6 +163,7 @@ import './renderer/style-control/Border';
import './renderer/style-control/BoxShadow';
import './renderer/style-control/Background';
import './renderer/style-control/Display';
import './renderer/style-control/InsetBoxModel';
import './renderer/RangePartsControl';
import './renderer/DataBindingControl';
import './renderer/DataMappingControl';

View File

@ -3331,5 +3331,115 @@ extendLocale('en-US', {
'951f802ebd0c0d795fbae6767a5ee9b3': 'Initialize interface request succeeded',
'da0126992b4937a5fd847ef5366b02e6':
'Data returned by initialization interface request successfully',
'70b8342d743374233bfee0f56c7f0fc7': 'Node Sample Data'
'70b8342d743374233bfee0f56c7f0fc7': 'Node Sample Data',
'38f85482d657cd4db1280c5efa1950fd': '{{@1}} Alignment',
'0a0574baedb8eb2abf7daf25159d8bb1':
'Set the alignment of sub elements on the spindle',
'5ccc4c05cd41195f202f550a4c307a64':
'Set the alignment of child elements on the cross axis',
'b1b98c19058af70d8bd499e1899e93bc': 'Layout Container',
'03097563d201ad3a29c79165226764e5':
'The layout container is a layout effect based on CSS Flex. It is more controllable than Grid and HBox for the location of child nodes, and easier to use than CSS classes',
'e151c86d57096bb74dcd390ade29362b': 'New column',
'e5f9b3a3655b8daddcee8b97b735887f': 'Insert Layout Container Forward',
'577b33bf128fba16ed8e9bf7c395f455': 'Insert Layout Container Backward',
'31f84d1bc6175fd0828a81b5bfd98736': 'Add column level element',
'cbc1d00cc640b67ee34a29a694ef162a':
'Left (upper) insert column level container',
'bb3cc092e17ff83e943554bde3d5771b':
'Insert column level container on the right (lower) side',
'b19b454fe603e03e98ad9772615c7c32': 'Positioning mode',
'8444f01399c0003fbb68eeff1310566c':
'Specifies the positioning type of the current container element',
'5ddea41072a27a74a1715549dfb79bc2': 'relative',
'e9513a013011450c57cfe3ef51b7d4b0': 'Fixed (relative to window)',
'3059599d8ebfec00a8ab53346d9b4fa3': 'Absolute (relative to parent container)',
'86a6b5a0a45bba5b6187cc2277e3375e': 'Layout Location',
'6e72759ed1cbf9f9e8523197dd93888f':
'Specifies the location of the current container element, which is used to configure top, right, bottom, and left.',
'6896da744f8ae9633263d55af0fceae1': 'Hierarchy',
'6f649980c839dffca1506f20d534fe3d':
'Specifies the stacking order of elements. Elements at higher levels will always be above elements at lower levels.',
'a8489cf57d7f44e889aff79434776f47':
'The default is block level, which can be set to elastic layout mode (flex layout container)',
'4180e30c34190007ffaa654e0959b8a3': 'Intra row flexible layout',
'ebe7bde5c9094813e2924473488d281a': 'In row block level',
'dde193342b8c350ae29795117c0c5b9a': 'Horizontal Alignment',
'5b15af1f73b4f2d5bb152410863602f4': 'Vertical Alignment',
'78d32d2bd35c0262fe77b517c5a4fb62': 'Arrangement direction',
'3fa460b81736c0360f6f7571801935b1':
'If the direction is set to horizontal arrangement, children are placed from left to right; If it is set to the vertical arrangement direction, the sub items will be set from top to bottom',
'fa228d6bec96d052de0ad369407f5241':
'Horizontal (starting point is at the right end)',
'2df3bc66ab3fcb0de1caf11831eff595': 'Vertical (starting point at lower edge)',
'98b2fea2d8f3ceb81e9ce32d66383f05': 'How to wrap lines',
'9af509c2a9636343199b9072e001826c': 'Default (no line breaks)',
'd4054144c4341872496e3550fdb1b826': 'Word wrap (reverse)',
'ee2df1c1a0d99094f641166535948d4b': 'Elastic mode',
'947c03e411c20563c7ac67d0a5ad741b':
'After the elastic mode is set, the current area is automatically adapted',
'f92626f9e56b3e2d0c47495a446acf71': 'Elastic width',
'cf8852316501c22ea19c4e432c59e7d7': 'Default Width',
'9cc69c8469b23b77519065d3df381113':
'Define the main size occupied by the project before allocating extra space',
'0ad8b3b736ae5b9e23cf16ac13e1e283': 'Proportion setting',
'fa6bb048a2f73975a40789b30c5b8a06':
'Defines the magnification of the project, which is 0 by default, that is, if there is any remaining space, it will not be magnified.',
'c19b79073b676b9bade80613aba2dbfa': 'Fixed height',
'd1b91a1a24f0d4935c2dd13e6a22b6d4':
'The maximum width is the maximum horizontal display area of the current element',
'c2ed47a1f0f45cf7e2d22bddffc8a732':
'Scroll mode for setting horizontal direction',
'cbc7af1d6422e88f4b87ade748e0f07d': 'Exceeding the display',
'b48a90c77b5e792260d830c2d68c527e': 'Beyond hiding',
'ddea62517e2bd1007712689746ebfe00': 'Scrolling',
'55becc96b40692cc9cf898b331d16976': 'Automatic adaptation',
'ede82efb4a69c35743185c6c73ab771e':
'The minimum width is the smallest horizontal display area of the current element',
'6f420734edfaff00a8210a4c762a9207':
'The maximum height is the display height with the most current elements',
'411f9d120093314cd38e6dd5cce398c6':
'The minimum width is the smallest vertical display area of the current element',
'b31c6aaa78f8e24df665ce80ab5301e2':
'Scroll mode for setting the vertical direction',
'4fc0e68b093db41b45a4ea706fbe56f3': 'Center Display',
'55efb233147f9539de019d9abc7653f9':
'Center display by setting margin: 0 auto',
'2bf5bcbe21f39b254a601664fb8b264d': 'Default (Wrap)',
'b2d418355cb59a5613ecff7b150c588f': 'nowrap ',
'7d1313925f158b747c094a7f2480e535': 'Reference position',
'41a7494315a528f0f9618646f7e0dddf':
'It can be set as upper left corner, upper right corner, lower right corner and lower left corner. The default is lower right corner',
'845c61ac8f51c6702dd22e5657c07e8d': 'Lower right corner (default)',
'2794fe303cf8ad4395fe93271fae7925':
'Layout containers are mainly used to design container components with complex layouts. The layout effect implemented based on CSS Flex is more controllable than Grid and HBox for the location of child nodes, and easier to use than using CSS classes',
'abbd790f85282349e2004df9fd494e31':
'Main size occupied by default before allocating extra space',
'dbb93e8f413074ead24b6ed822247d98': 'Insert Layout Container Above',
'5b5765b3fd7e72e04a5cd3e2ef6218a4': 'Insert Layout Container Below',
'ee466872b9a43e720e296813dbc5adee': '{{@1}} Insert Column Level Container',
'14c495b1248756310c75396cd41f4fe9': 'upper',
'e33ac3a4c1a95a02a18f1555038804da': 'Below',
'e731c52010266b8ade1e7e78e25cdccc': 'Common layouts',
'f80bd0a5546465336f4f9cafdfa8b67f': 'Default Height',
'ba9ccf1040d7abd0848046330ba3558c': 'Classic layout',
'230d65546ea0d299907943403608233c':
'Common layout: classic layout (layout container based on CSS Flex implementation).',
'9bbb7cfaeb34a2b5c095ac253355f028': 'Levitation vessel',
'a3e91631c1a3a43e09526ea7f6b8595c':
'Common layout: suspended container (layout container based on CSS Flex implementation).',
'd423930b823fc45f08c18922b19e4e9e': 'Bottom suction vessel',
'b8b4eb373d8ba6f98271b681fba2511d':
'Common layout: bottom suction container (a layout container based on CSS Flex implementation).',
'faaa6444a709917ff33e0d58948504dc': 'Ceiling container',
'1facf0bd0f56c66759857345e7434443':
'Common layout: ceiling container (a layout container based on CSS Flex implementation).',
'f416a3a2566dda04bc0ef67027e6f460': 'X axis rolling container',
'e3d9ad8453925764f2918dbfd6ff824e':
'Common layout: x-axis rolling container (based on the layout container implemented by CSS Flex).',
'053e0cbf18c8fe59b928d52fcd556b88': 'Y-axis rolling container',
'c9f089cefc06c217c6dddfe2fc772ea3':
'Common layout: y-axis rolling container (a layout container based on CSS Flex implementation).',
'3587540660a01f8a8aff6a2c0409a404':
'After the elastic mode is turned on, the current area is automatically adapted'
});

View File

@ -2945,5 +2945,103 @@ extendLocale('zh-CN', {
'ecfd82eb65102274188011a502913d3a': '抽屉数据',
'951f802ebd0c0d795fbae6767a5ee9b3': '初始化接口请求成功',
'da0126992b4937a5fd847ef5366b02e6': '初始化接口请求成功返回的数据',
'70b8342d743374233bfee0f56c7f0fc7': '节点示例数据'
'70b8342d743374233bfee0f56c7f0fc7': '节点示例数据',
'38f85482d657cd4db1280c5efa1950fd': '{{@1}}对齐方式',
'0a0574baedb8eb2abf7daf25159d8bb1': '设置子元素在主轴上的对齐方式',
'5ccc4c05cd41195f202f550a4c307a64': '设置子元素在交叉轴上的对齐方式',
'b1b98c19058af70d8bd499e1899e93bc': '布局容器',
'03097563d201ad3a29c79165226764e5':
'布局容器 是基于 CSS Flex 实现的布局效果,它比 Grid 和 HBox 对子节点位置的可控性更强,比用 CSS 类的方式更易用',
'e151c86d57096bb74dcd390ade29362b': '新的一列',
'e5f9b3a3655b8daddcee8b97b735887f': '向前插入布局容器',
'577b33bf128fba16ed8e9bf7c395f455': '向后插入布局容器',
'31f84d1bc6175fd0828a81b5bfd98736': '新增列级元素',
'cbc1d00cc640b67ee34a29a694ef162a': '左侧(上侧)插入列级容器',
'bb3cc092e17ff83e943554bde3d5771b': '右侧(下侧)插入列级容器',
'b19b454fe603e03e98ad9772615c7c32': '定位模式',
'8444f01399c0003fbb68eeff1310566c': '指定当前容器元素的定位类型',
'5ddea41072a27a74a1715549dfb79bc2': '相对',
'e9513a013011450c57cfe3ef51b7d4b0': '固定(相对窗口)',
'3059599d8ebfec00a8ab53346d9b4fa3': '绝对(相对父容器)',
'86a6b5a0a45bba5b6187cc2277e3375e': '布局位置',
'6e72759ed1cbf9f9e8523197dd93888f':
'指定当前容器元素的定位位置,用于配置 top、right、bottom、left。',
'6896da744f8ae9633263d55af0fceae1': '层级',
'6f649980c839dffca1506f20d534fe3d':
'指定元素的堆叠顺序,层级高的元素总是会处于较低层级元素的上面。',
'a8489cf57d7f44e889aff79434776f47':
'默认为块级可设置为弹性布局模式flex布局容器',
'4180e30c34190007ffaa654e0959b8a3': '行内弹性布局',
'ebe7bde5c9094813e2924473488d281a': '行内块级',
'dde193342b8c350ae29795117c0c5b9a': '水平对齐方式',
'5b15af1f73b4f2d5bb152410863602f4': '垂直对齐方式',
'78d32d2bd35c0262fe77b517c5a4fb62': '排列方向',
'3fa460b81736c0360f6f7571801935b1':
'设置成水平排列方向,则从左到右放置子项;设置成垂直排列方向,则从上到下放置子项',
'fa228d6bec96d052de0ad369407f5241': '水平(起点在右端)',
'2df3bc66ab3fcb0de1caf11831eff595': '垂直(起点在下沿)',
'98b2fea2d8f3ceb81e9ce32d66383f05': '如何换行',
'9af509c2a9636343199b9072e001826c': '默认(不换行)',
'd4054144c4341872496e3550fdb1b826': '自动换行(颠倒)',
'ee2df1c1a0d99094f641166535948d4b': '弹性模式',
'947c03e411c20563c7ac67d0a5ad741b': '设置为弹性模式后,自动适配当前所在区域',
'f92626f9e56b3e2d0c47495a446acf71': '弹性宽度',
'cf8852316501c22ea19c4e432c59e7d7': '默认宽度',
'9cc69c8469b23b77519065d3df381113':
'定义在分配多余空间之前项目占据的主轴空间main size',
'0ad8b3b736ae5b9e23cf16ac13e1e283': '占比设置',
'fa6bb048a2f73975a40789b30c5b8a06':
'定义项目的放大比例默认为0即如果存在剩余空间也不放大。',
'c19b79073b676b9bade80613aba2dbfa': '固定高度',
'd1b91a1a24f0d4935c2dd13e6a22b6d4': '最大宽度即当前元素最大的水平展示区域',
'c18457fe4f249f06b48297ccfe6224e8': ' x轴滚动模式',
'c2ed47a1f0f45cf7e2d22bddffc8a732': '用于设置水平方向的滚动模式',
'cbc7af1d6422e88f4b87ade748e0f07d': '超出显示',
'b48a90c77b5e792260d830c2d68c527e': '超出隐藏',
'ddea62517e2bd1007712689746ebfe00': '滚动显示',
'55becc96b40692cc9cf898b331d16976': '自动适配',
'ede82efb4a69c35743185c6c73ab771e': '最小宽度即当前元素最小的水平展示区域',
'6f420734edfaff00a8210a4c762a9207': '最大高度即当前元素最多的展示高度',
'411f9d120093314cd38e6dd5cce398c6': '最小宽度即当前元素最小的垂直展示区域',
'ff9e9329fe186be342ef59ee711b9371': ' y轴滚动模式',
'b31c6aaa78f8e24df665ce80ab5301e2': '用于设置垂直方向的滚动模式',
'4fc0e68b093db41b45a4ea706fbe56f3': '居中显示',
'55efb233147f9539de019d9abc7653f9':
'通过将设置 margin: 0 auto 来达到居中显示',
'2bf5bcbe21f39b254a601664fb8b264d': '默认(自动换行)',
'b2d418355cb59a5613ecff7b150c588f': '不换行',
'7d1313925f158b747c094a7f2480e535': '参考位置',
'41a7494315a528f0f9618646f7e0dddf':
'可设置为左上角、右上角、右下角、左下角,默认为右下角',
'845c61ac8f51c6702dd22e5657c07e8d': '右下角(默认)',
'2794fe303cf8ad4395fe93271fae7925':
'布局容器主要用于设计复杂布局的容器组件,基于 CSS Flex 实现的布局效果,比 Grid 和 HBox 对子节点位置的可控性更强,比用 CSS 类的方式更简单易用',
'abbd790f85282349e2004df9fd494e31':
'在分配多余空间之前其默认占据的主轴空间main size',
'dbb93e8f413074ead24b6ed822247d98': '上方插入布局容器',
'5b5765b3fd7e72e04a5cd3e2ef6218a4': '下方插入布局容器',
'ee466872b9a43e720e296813dbc5adee': '{{@1}}插入列级容器',
'14c495b1248756310c75396cd41f4fe9': '上方',
'e33ac3a4c1a95a02a18f1555038804da': '下方',
'e731c52010266b8ade1e7e78e25cdccc': '常见布局',
'f80bd0a5546465336f4f9cafdfa8b67f': '默认高度',
'ba9ccf1040d7abd0848046330ba3558c': '经典布局',
'230d65546ea0d299907943403608233c':
'常见布局:经典布局(基于 CSS Flex 实现的布局容器)。',
'9bbb7cfaeb34a2b5c095ac253355f028': '悬浮容器',
'a3e91631c1a3a43e09526ea7f6b8595c':
'常见布局:悬浮容器(基于 CSS Flex 实现的布局容器)。',
'd423930b823fc45f08c18922b19e4e9e': '吸底容器',
'b8b4eb373d8ba6f98271b681fba2511d':
'常见布局:吸底容器(基于 CSS Flex 实现的布局容器)。',
'faaa6444a709917ff33e0d58948504dc': '吸顶容器',
'1facf0bd0f56c66759857345e7434443':
'常见布局:吸顶容器(基于 CSS Flex 实现的布局容器)。',
'f416a3a2566dda04bc0ef67027e6f460': 'x轴滚动容器',
'e3d9ad8453925764f2918dbfd6ff824e':
'常见布局x轴滚动容器基于 CSS Flex 实现的布局容器)。',
'053e0cbf18c8fe59b928d52fcd556b88': 'y轴滚动容器',
'c9f089cefc06c217c6dddfe2fc772ea3':
'常见布局y轴滚动容器基于 CSS Flex 实现的布局容器)。',
'3587540660a01f8a8aff6a2c0409a404': '开启弹性模式后,自动适配当前所在区域'
});

View File

@ -1,6 +1,6 @@
import {registerEditorPlugin} from 'amis-editor-core';
import {BaseEventContext, BasePlugin, RegionConfig} from 'amis-editor-core';
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
import {defaultValue, getSchemaTpl, tipedLabel} from 'amis-editor-core';
export class ContainerPlugin extends BasePlugin {
// 关联渲染器名字
@ -17,12 +17,7 @@ export class ContainerPlugin extends BasePlugin {
pluginIcon = 'container-plugin';
scaffold = {
type: 'container',
body: [
{
type: 'tpl',
tpl: '内容'
}
]
body: []
};
previewSchema = {
...this.scaffold
@ -40,6 +35,13 @@ export class ContainerPlugin extends BasePlugin {
panelJustify = true;
panelBodyCreator = (context: BaseEventContext) => {
const curRendererSchema = context?.schema;
const isRowContent =
curRendererSchema?.direction === 'row' ||
curRendererSchema?.direction === 'row-reverse';
const isFlexItem = this.manager?.isFlexItem(context?.id);
const isFlexColumnItem = this.manager?.isFlexColumnItem(context?.id);
return getSchemaTpl('tabs', [
{
title: '属性',
@ -74,6 +76,87 @@ export class ContainerPlugin extends BasePlugin {
}
]
},
{
title: '布局',
body: [
isFlexItem ? getSchemaTpl('layout:flex', {
isFlexColumnItem,
visibleOn: 'data.style && (data.style.position === "static" || data.style.position === "relative")',
}) : null,
isFlexItem ? getSchemaTpl('layout:flex-grow', {
visibleOn: 'data.style && data.style.flex !== "0 0 auto" && (data.style.position === "static" || data.style.position === "relative")',
}) : null,
isFlexItem ? getSchemaTpl('layout:flex-basis', {
visibleOn: 'data.style && (data.style.position === "static" || data.style.position === "relative")',
}) : null,
getSchemaTpl('layout:position'),
getSchemaTpl('layout:originPosition'),
getSchemaTpl('layout:inset', {
mode: 'vertical'
}),
getSchemaTpl('layout:z-index'),
getSchemaTpl('layout:display'),
getSchemaTpl('layout:flexDirection', {
visibleOn: 'data.style && data.style.display === "flex"',
}),
getSchemaTpl('layout:justifyContent', {
label: '水平对齐方式',
visibleOn: 'data.style && data.style.display === "flex" && data.style.flexDirection === "row" || data.style.flexDirection === "row-reverse"'
}),
getSchemaTpl('layout:justifyContent', {
label: '垂直对齐方式',
visibleOn: 'data.style && data.style.display === "flex" && (data.style.flexDirection === "column" || data.style.flexDirection === "column-reverse")'
}),
getSchemaTpl('layout:alignItems', {
label: '水平对齐方式',
visibleOn: 'data.style && data.style.display === "flex" && (data.style.flexDirection === "column" || data.style.flexDirection === "column-reverse")'
}),
getSchemaTpl('layout:alignItems', {
label: '垂直对齐方式',
visibleOn: 'data.style && data.style.display === "flex" && (data.style.flexDirection === "row" || data.style.flexDirection === "row-reverse")'
}),
getSchemaTpl('layout:flex-wrap', {
visibleOn: 'data.style && data.style.display === "flex"',
}),
getSchemaTpl('layout:isFixedHeight', {
visibleOn: `${!isFlexItem || !isFlexColumnItem}`
}),
getSchemaTpl('layout:height', {
visibleOn: `${!isFlexItem || !isFlexColumnItem}`
}),
getSchemaTpl('layout:max-height', {
visibleOn: `${!isFlexItem || !isFlexColumnItem}`
}),
getSchemaTpl('layout:min-height', {
visibleOn: `${!isFlexItem || !isFlexColumnItem}`
}),
getSchemaTpl('layout:overflow-y', {
visibleOn: `${!isFlexItem || !isFlexColumnItem} && (data.isFixedHeight || data.style && data.style.maxHeight) || (${isFlexItem && isFlexColumnItem} && data.style.flex === '0 0 auto')`,
}),
getSchemaTpl('layout:isFixedWidth', {
visibleOn: `${!isFlexItem || isFlexColumnItem}`
}),
getSchemaTpl('layout:width', {
visibleOn: `${!isFlexItem || isFlexColumnItem}`
}),
getSchemaTpl('layout:max-width', {
visibleOn: `${!isFlexItem || isFlexColumnItem}`
}),
getSchemaTpl('layout:min-width', {
visibleOn: `${!isFlexItem || isFlexColumnItem}`
}),
getSchemaTpl('layout:overflow-x', {
visibleOn: `${!isFlexItem || isFlexColumnItem} && (data.isFixedWidth || data.style && data.style.maxWidth) || (${isFlexItem && !isFlexColumnItem} && data.style.flex === '0 0 auto')`,
}),
!isFlexItem ? getSchemaTpl('layout:margin-center') : null,
]
},
getSchemaTpl('status'),
])
},
@ -81,7 +164,7 @@ export class ContainerPlugin extends BasePlugin {
title: '外观',
className: 'p-none',
body: getSchemaTpl('collapseGroup', [
...getSchemaTpl('style:common', [], ['layout']),
...getSchemaTpl('style:common', ['layout']),
getSchemaTpl('style:classNames', {
isFormItem: false,
schema: [
@ -90,8 +173,7 @@ export class ContainerPlugin extends BasePlugin {
label: '内容区'
})
]
}),
...getSchemaTpl('style:common', ['layout']),
})
])
}
]);

View File

@ -2,209 +2,13 @@
* @file Flex
*/
import {registerEditorPlugin} from 'amis-editor-core';
import {
BasePlugin,
PluginEvent,
RegionConfig,
RendererJSONSchemaResolveEventContext
} from 'amis-editor-core';
import {getSchemaTpl} from 'amis-editor-core';
import {EditorNodeType} from 'amis-editor-core';
import {FlexPluginBase} from './Layout/FlexPluginBase';
export class FlexPlugin extends BasePlugin {
// 关联渲染器名字
rendererName = 'flex';
$schema = '/schemas/FlexSchema.json';
disabledRendererPlugin = true;
// 组件名称
name = 'Flex 布局';
isBaseComponent = true;
icon = 'fa fa-columns';
pluginIcon = 'flex-plugin';
description = 'flex 布局';
docLink = '/amis/zh-CN/components/flex';
tags = ['容器'];
scaffold = {
type: 'flex',
items: [
{
type: 'wrapper',
body: '第一列'
},
{
type: 'wrapper',
body: '第二列'
},
{
type: 'wrapper',
body: '第三列'
}
]
};
previewSchema = {
...this.scaffold
};
panelTitle = 'Flex';
panelBody = [
getSchemaTpl('tabs', [
{
title: '属性',
className: 'p-none',
body: [
getSchemaTpl('collapseGroup', [
{
title: '布局',
body: [
{
name: 'justify',
type: 'select',
value: 'center',
label: '子节点水平分布方式',
menuTpl:
"<div class='flex justify-between'><span>${label}</span><span class='text-muted text-sm'>${value}</span></div>",
options: [
{
label: '起始端对齐',
value: 'flex-start'
},
{
label: '居中对齐',
value: 'center'
},
{
label: '末尾端对齐',
value: 'flex-end'
},
{
label: '均匀分布(首尾留空)',
value: 'space-around'
},
{
label: '均匀分布(首尾对齐)',
value: 'space-between'
},
{
label: '均匀分布(元素等间距)',
value: 'space-evenly'
},
{
label: '均匀分布(自动拉伸)',
value: 'stretch'
}
]
},
{
name: 'alignItems',
type: 'select',
value: 'center',
label: '子节点垂直方向位置',
menuTpl:
"<div class='flex justify-between'><span>${label}</span><span class='text-muted text-sm'>${value}</span></div>",
options: [
{
label: '起始端对齐',
value: 'flex-start'
},
{
label: '居中对齐',
value: 'center'
},
{
label: '末尾端对齐',
value: 'flex-end'
},
{
label: '基线对齐',
value: 'baseline'
},
{
label: '自动拉伸',
value: 'stretch'
}
]
},
{
name: 'direction',
type: 'button-group-select',
size: 'sm',
label: '布局方向',
value: 'row',
mode: 'row',
options: [
{label: '水平', value: 'row'},
{label: '垂直', value: 'column'}
]
}
]
},
{
title: '子节点管理',
body: [
{
name: 'items',
label: false,
type: 'combo',
scaffold: {
type: 'wrapper',
body: '子节点内容'
},
minLength: 2,
multiple: true,
// draggable: true,
draggableTip: '',
items: [
{
type: 'tpl',
tpl:
'<span class="label label-default">子节点${index | plus}</span>'
}
]
}
]
}
])
]
},
{
title: '外观',
className: 'p-none',
body: getSchemaTpl('collapseGroup', [
...getSchemaTpl('style:common', ['display']),
{
title: 'CSS 类名',
body: [getSchemaTpl('className', {label: '外层CSS类名'})]
}
])
},
{
title: '状态',
body: [getSchemaTpl('visible'), getSchemaTpl('disabled')]
}
])
];
regions: Array<RegionConfig> = [
{
key: 'items',
label: '子节点集合',
// 复写渲染器里面的 render 方法
renderMethod: 'render',
dndMode: 'position-h'
}
];
afterResolveJsonSchema(
event: PluginEvent<RendererJSONSchemaResolveEventContext>
) {
const context = event.context;
const parent = context.node.parent?.host as EditorNodeType;
if (parent?.info?.plugin === this) {
event.setData('/schemas/FlexColumn.json');
}
}
export class FlexPlugin extends FlexPluginBase {
name = '布局容器';
pluginIcon = 'flex-container-plugin';
description =
'布局容器主要用于设计复杂布局的容器组件,基于 CSS Flex 实现的布局效果,比 Grid 和 HBox 对子节点位置的可控性更强,比用 CSS 类的方式更简单易用';
}
registerEditorPlugin(FlexPlugin);

View File

@ -0,0 +1,299 @@
/**
* @file Flex 1:3
*/
import {BasePlugin, PluginEvent} from 'amis-editor-core';
import {getSchemaTpl, tipedLabel} from 'amis-editor-core';
import type {
BaseEventContext,
EditorNodeType,
RegionConfig,
RendererJSONSchemaResolveEventContext,
BasicToolbarItem
} from 'amis-editor-core';
// 默认的列容器Schema
const defaultFlexColumnSchema = (title: string) => {
return {
type: 'wrapper',
body: [],
size: 'xs',
style: {
position: 'static',
display: 'flex',
flex: '1 1 auto',
flexGrow: 1,
flexBasis: 'auto',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'stretch'
},
isFixedHeight: false,
isFixedWidth: false
};
};
// 默认的布局容器Schema
const defaultFlexContainerSchema = {
type: 'flex',
className: 'p-1',
items: [
defaultFlexColumnSchema('第一列'),
defaultFlexColumnSchema('第二列'),
defaultFlexColumnSchema('第三列')
],
justify: "flex-start",
alignItems: "stretch"
};
export class FlexPluginBase extends BasePlugin {
rendererName = 'flex';
$schema = '/schemas/FlexSchema.json';
disabledRendererPlugin = false;
name = '布局容器';
order = -1200;
isBaseComponent = true;
icon = 'fa fa-columns';
pluginIcon = 'flex-container-plugin';
description =
'布局容器 是基于 CSS Flex 实现的布局效果,它比 Grid 和 HBox 对子节点位置的可控性更强,比用 CSS 类的方式更易用';
docLink = '/amis/zh-CN/components/flex';
tags = ['常见布局'];
scaffold: any = defaultFlexContainerSchema;
previewSchema = {
...this.scaffold
};
panelTitle = 'Flex';
panelJustify = true; // 右侧配置项默认左右展示
panelBodyCreator = (context: BaseEventContext) => {
const curRendererSchema = context?.schema;
const isRowContent =
curRendererSchema?.direction === 'row' ||
curRendererSchema?.direction === 'row-reverse';
const isFlexItem = this.manager?.isFlexItem(context?.id);
const isFlexColumnItem = this.manager?.isFlexColumnItem(context?.id);
return [
getSchemaTpl('tabs', [
{
title: '属性',
className: 'p-none',
body: [
getSchemaTpl('collapseGroup', [
{
title: '布局',
body: [
isFlexItem
? getSchemaTpl('layout:flex', {
isFlexColumnItem,
visibleOn:
'data.style && (data.style.position === "static" || data.style.position === "relative")'
})
: null,
isFlexItem
? getSchemaTpl('layout:flex-grow', {
visibleOn:
'data.style && data.style.flex !== "0 0 auto" && (data.style.position === "static" || data.style.position === "relative")'
})
: null,
isFlexItem
? getSchemaTpl('layout:flex-basis', {
label: isFlexColumnItem ? '默认高度' : '默认宽度',
visibleOn:
'data.style && (data.style.position === "static" || data.style.position === "relative")'
})
: null,
getSchemaTpl('layout:position'),
getSchemaTpl('layout:originPosition'),
getSchemaTpl('layout:inset', {
mode: 'vertical'
}),
getSchemaTpl('layout:z-index'),
getSchemaTpl('layout:flexDirection', {
name: 'direction'
}),
getSchemaTpl('layout:justifyContent', {
name: 'justify',
label: '水平对齐方式',
visibleOn: 'data.direction === "row" || data.direction === "row-reverse"'
}),
// 备注: 重复一个是为了能实时联动后续需要amis优化支持label使用公式表达式
getSchemaTpl('layout:justifyContent', {
name: 'justify',
label: '垂直对齐方式',
visibleOn: 'data.direction === "column" || data.direction === "column-reverse"'
}),
getSchemaTpl('layout:alignItems', {
name: 'alignItems',
label: '水平对齐方式',
visibleOn: 'data.direction === "column" || data.direction === "column-reverse"'
}),
getSchemaTpl('layout:alignItems', {
name: 'alignItems',
label: '垂直对齐方式',
visibleOn: 'data.direction === "row" || data.direction === "row-reverse"'
}),
getSchemaTpl('layout:flex-wrap'),
getSchemaTpl('layout:isFixedHeight', {
visibleOn: `${!isFlexItem || !isFlexColumnItem}`
}),
getSchemaTpl('layout:height', {
visibleOn: `${!isFlexItem || !isFlexColumnItem}`
}),
getSchemaTpl('layout:max-height', {
visibleOn: `${!isFlexItem || !isFlexColumnItem}`
}),
getSchemaTpl('layout:min-height', {
visibleOn: `${!isFlexItem || !isFlexColumnItem}`
}),
getSchemaTpl('layout:overflow-y', {
visibleOn: `${!isFlexItem || !isFlexColumnItem} && (data.isFixedHeight || data.style && data.style.maxHeight) || (${isFlexItem && isFlexColumnItem} && data.style.flex === '0 0 auto')`,
}),
getSchemaTpl('layout:isFixedWidth', {
visibleOn: `${!isFlexItem || isFlexColumnItem}`
}),
getSchemaTpl('layout:width', {
visibleOn: `${!isFlexItem || isFlexColumnItem}`
}),
getSchemaTpl('layout:max-width', {
visibleOn: `${!isFlexItem || isFlexColumnItem}`
}),
getSchemaTpl('layout:min-width', {
visibleOn: `${!isFlexItem || isFlexColumnItem}`
}),
getSchemaTpl('layout:overflow-x', {
visibleOn: `${!isFlexItem || isFlexColumnItem} && (data.isFixedWidth || data.style && data.style.maxWidth) || (${isFlexItem && !isFlexColumnItem} && data.style.flex === '0 0 auto')`,
}),
!isFlexItem ? getSchemaTpl('layout:margin-center') : null
]
},
getSchemaTpl('status')
])
]
},
{
title: '外观',
className: 'p-none',
body: getSchemaTpl('collapseGroup', [
...getSchemaTpl('style:common', ['display']),
{
title: 'CSS 类名',
body: [getSchemaTpl('className', {label: '外层CSS类名'})]
}
])
}
])
];
};
regions: Array<RegionConfig> = [
{
key: 'items',
label: '子节点集合'
}
];
buildEditorToolbar(
{id, info, schema}: BaseEventContext,
toolbars: Array<BasicToolbarItem>
) {
const store = this.manager.store;
const parent = store.getSchemaParentById(id);
const draggableContainer = this.manager.draggableContainer(id);
const isFlexItem = this.manager?.isFlexItem(id);
const isFlexColumnItem = this.manager?.isFlexColumnItem(id);
const newColumnSchema = defaultFlexColumnSchema('新的一列');
if (
parent &&
(info.renderer?.name === 'flex' || info.renderer?.name === 'container') &&
!isFlexItem && // 备注:如果是列级元素就不需要显示了
!draggableContainer
) {
// 非特殊布局元素fixed、absolute支持前后插入追加布局元素功能icon
toolbars.push(
{
iconSvg: 'add-btn',
tooltip: '上方插入布局容器',
level: 'special',
placement: 'right',
className: 'ae-InsertBefore is-vertical',
onClick: () =>
this.manager.appendSiblingSchema(
defaultFlexContainerSchema,
true,
true
)
},
{
iconSvg: 'add-btn',
tooltip: '下方插入布局容器',
level: 'special',
placement: 'right',
className: 'ae-InsertAfter is-vertical',
onClick: () =>
this.manager.appendSiblingSchema(
defaultFlexContainerSchema,
false,
true
)
}
);
// 布局容器 右上角插入子元素
if (info.renderer?.name === 'flex') {
toolbars.push(
{
iconSvg: 'add-btn',
tooltip: '新增列级元素',
level: 'special',
placement: 'bottom',
className: 'ae-AppendChild',
onClick: () => this.manager.addElem(newColumnSchema)
}
);
}
}
if (isFlexItem && !draggableContainer) {
// 布局容器的列级元素 增加左右插入icon
toolbars.push(
{
iconSvg: 'add-btn',
tooltip: `${isFlexColumnItem ? '上方' : '左侧'}插入列级容器`,
level: 'special',
placement: 'right',
className: isFlexColumnItem ? 'ae-InsertBefore is-vertical' : 'ae-InsertBefore',
onClick: () =>
this.manager.appendSiblingSchema(newColumnSchema, true, true)
},
{
iconSvg: 'add-btn',
tooltip: `${isFlexColumnItem ? '下方' : '右侧'}插入列级容器`,
level: 'special',
placement: isFlexColumnItem ? 'right' : 'left',
className: isFlexColumnItem ? 'ae-InsertAfter is-vertical' : 'ae-InsertAfter',
onClick: () =>
this.manager.appendSiblingSchema(newColumnSchema, false, true)
}
);
}
}
afterResolveJsonSchema(
event: PluginEvent<RendererJSONSchemaResolveEventContext>
) {
const context = event.context;
const parent = context.node.parent?.host as EditorNodeType;
if (parent?.info?.plugin === this) {
event.setData('/schemas/FlexColumn.json');
}
}
}

View File

@ -0,0 +1,110 @@
import {registerEditorPlugin} from 'amis-editor-core';
import {FlexPluginBase} from './FlexPluginBase';
export default class Layout1_2_v4 extends FlexPluginBase {
name = '经典布局';
isBaseComponent = true;
pluginIcon = 'layout-3-1-plugin';
description = '常见布局:经典布局(基于 CSS Flex 实现的布局容器)。';
tags = ['常见布局'];
order = 307;
scaffold: any = {
type: 'flex',
className: 'p-1',
items: [
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '0 0 auto',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'stretch'
}
},
{
type: 'flex',
items: [
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '0 0 auto',
flexBasis: '250px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'stretch'
}
},
{
type: 'flex',
items: [
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '1 1 auto',
flexBasis: 'auto',
flexGrow: 1,
display: 'block'
}
},
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '1 1 auto',
flexBasis: 'auto',
flexGrow: 1,
display: 'block'
}
}
],
style: {
position: 'static',
overflowX: 'auto',
overflowY: 'auto',
margin: '0',
flex: '1 1 auto',
flexGrow: 1,
flexBasis: 'auto'
},
alignItems: 'stretch',
direction: 'column',
justify: 'center',
isFixedHeight: false,
isFixedWidth: false
}
],
style: {
flex: '1 1 auto',
overflowX: 'auto',
margin: '0',
maxWidth: 'auto',
overflowY: 'auto',
position: 'static',
minWidth: 'auto',
width: 'auto',
maxHeight: 'auto',
minHeight: '300px'
},
direction: 'row',
justify: 'flex-start',
alignItems: 'stretch',
isFixedHeight: false,
isFixedWidth: false
}
],
direction: 'column',
justify: 'center',
alignItems: 'stretch'
};
}
registerEditorPlugin(Layout1_2_v4);

View File

@ -0,0 +1,30 @@
import {registerEditorPlugin} from 'amis-editor-core';
import {FlexPluginBase} from './FlexPluginBase';
export default class Layout_fixed extends FlexPluginBase {
name = '悬浮容器';
isBaseComponent = true;
pluginIcon = 'layout-fixed-plugin';
description = '常见布局:悬浮容器(基于 CSS Flex 实现的布局容器)。';
tags = ['常见布局'];
order = 503;
scaffold: any = {
type: 'wrapper',
size: 'xs',
body: [],
style: {
position: 'fixed',
inset: 'auto 50px 50px auto',
zIndex: 10,
display: 'flex',
minWidth: '80px',
minHeight: '80px',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'stretch'
},
originPosition: 'right-bottom'
};
}
registerEditorPlugin(Layout_fixed);

View File

@ -0,0 +1,77 @@
import {registerEditorPlugin} from 'amis-editor-core';
import {FlexPluginBase} from './FlexPluginBase';
export default class Layout_fixed_bottom extends FlexPluginBase {
name = '吸底容器';
isBaseComponent = true;
pluginIcon = 'flex-container-plugin';
description = '常见布局:吸底容器(基于 CSS Flex 实现的布局容器)。';
tags = ['常见布局'];
order = 501;
scaffold: any = {
type: 'flex',
className: 'p-1',
items: [
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '1 1 auto',
flexBasis: 'auto',
flexGrow: 1,
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'stretch'
}
},
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '1 1 auto',
flexBasis: 'auto',
flexGrow: 1,
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'stretch'
}
},
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '1 1 auto',
flexBasis: 'auto',
flexGrow: 1,
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'stretch'
}
}
],
style: {
position: 'fixed',
inset: 'auto auto 0 0',
zIndex: 2,
width: '100%',
overflowX: 'auto',
margin: '0',
overflowY: 'auto',
height: 'auto'
},
isFixedWidth: true,
direction: 'row',
justify: 'center',
alignItems: 'stretch',
isFixedHeight: false,
originPosition: 'right-bottom'
};
}
registerEditorPlugin(Layout_fixed_bottom);

View File

@ -0,0 +1,67 @@
import {registerEditorPlugin} from 'amis-editor-core';
import {FlexPluginBase} from './FlexPluginBase';
export default class Layout_fixed_top extends FlexPluginBase {
name = '吸顶容器';
isBaseComponent = true;
pluginIcon = 'flex-container-plugin';
description = '常见布局:吸顶容器(基于 CSS Flex 实现的布局容器)。';
tags = ['常见布局'];
order = 502;
scaffold: any = {
type: 'flex',
className: 'p-1',
items: [
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '1 1 auto',
flexBasis: 'auto',
flexGrow: 1,
display: 'block'
}
},
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '1 1 auto',
flexBasis: 'auto',
flexGrow: 1,
display: 'block'
}
},
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '1 1 auto',
display: 'block',
flexBasis: 'auto',
flexGrow: 1
}
}
],
style: {
position: 'fixed',
inset: '0 auto auto 0',
zIndex: 10,
width: '100%',
overflowX: 'auto',
margin: '0',
overflowY: 'auto'
},
isFixedWidth: true,
direction: 'row',
justify: 'center',
alignItems: 'stretch',
isFixedHeight: false,
originPosition: 'right-bottom'
};
}
registerEditorPlugin(Layout_fixed_top);

View File

@ -0,0 +1,146 @@
import {registerEditorPlugin} from 'amis-editor-core';
import {FlexPluginBase} from './FlexPluginBase';
export default class Layout_scroll_x extends FlexPluginBase {
name = 'x轴滚动容器';
isBaseComponent = true;
pluginIcon = 'layout-3cols-plugin';
description = '常见布局x轴滚动容器基于 CSS Flex 实现的布局容器)。';
tags = ['常见布局'];
order = 505;
scaffold: any = {
type: 'flex',
className: 'p-1',
items: [
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '0 0 auto',
flexBasis: '200px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'stretch',
position: 'static',
minWidth: 'auto',
minHeight: 'auto'
}
},
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '0 0 auto',
flexBasis: '200px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'stretch',
position: 'static',
minWidth: 'auto',
minHeight: 'auto'
}
},
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '0 0 auto',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'stretch',
position: 'static',
minWidth: 'auto',
minHeight: 'auto',
flexBasis: '200px'
}
},
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '0 0 auto',
flexBasis: '200px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'stretch',
position: 'static',
minWidth: 'auto',
minHeight: 'auto'
}
},
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '0 0 auto',
flexBasis: '200px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'stretch',
position: 'static',
minWidth: 'auto',
minHeight: 'auto'
}
},
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '0 0 auto',
flexBasis: '200px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'stretch',
position: 'static',
minWidth: 'auto',
minHeight: 'auto'
}
},
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '0 0 auto',
flexBasis: '200px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'stretch',
position: 'static',
minWidth: 'auto',
minHeight: 'auto'
}
}
],
direction: 'row',
justify: 'flex-start',
alignItems: 'stretch',
style: {
position: 'static',
minHeight: 'auto',
maxWidth: '1080px',
minWidth: 'auto',
height: '200px',
overflowX: 'scroll',
overflowY: 'scroll',
margin: '0 auto'
},
isFixedHeight: true,
isFixedWidth: false
};
}
registerEditorPlugin(Layout_scroll_x);

View File

@ -0,0 +1,130 @@
import {registerEditorPlugin} from 'amis-editor-core';
import {FlexPluginBase} from './FlexPluginBase';
export default class Layout_scroll_y extends FlexPluginBase {
name = 'y轴滚动容器';
isBaseComponent = true;
pluginIcon = 'layout-3row-plugin';
description = '常见布局y轴滚动容器基于 CSS Flex 实现的布局容器)。';
tags = ['常见布局'];
order = 504;
scaffold: any = {
type: 'flex',
className: 'p-1',
items: [
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '0 0 auto',
flexBasis: '60px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'stretch',
minWidth: 'auto',
minHeight: 'auto'
}
},
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '0 0 auto',
flexBasis: '60px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'stretch',
position: 'static',
minWidth: 'auto',
minHeight: 'auto'
}
},
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '0 0 auto',
flexBasis: '60px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'stretch',
position: 'static',
minWidth: 'auto',
minHeight: 'auto'
}
},
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '0 0 auto',
flexBasis: '60px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'stretch',
position: 'static',
minWidth: 'auto',
minHeight: 'auto'
}
},
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '0 0 auto',
flexBasis: '60px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'stretch',
position: 'static',
minWidth: 'auto',
minHeight: 'auto'
}
},
{
type: 'wrapper',
size: 'xs',
body: [],
style: {
flex: '0 0 auto',
flexBasis: '60px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'stretch',
position: 'static',
minWidth: 'auto',
minHeight: 'auto'
}
}
],
direction: 'column',
justify: 'flex-start',
alignItems: 'stretch',
style: {
position: 'static',
minHeight: 'auto',
maxWidth: 'auto',
minWidth: 'auto',
height: '200px',
width: 'auto',
overflowX: 'auto',
overflowY: 'scroll',
margin: '0'
},
isFixedHeight: true,
isFixedWidth: false
};
}
registerEditorPlugin(Layout_scroll_y);

View File

@ -1,5 +1,5 @@
import {registerEditorPlugin} from 'amis-editor-core';
import {BasePlugin, RegionConfig, RendererInfo} from 'amis-editor-core';
import {BasePlugin, RegionConfig, BaseEventContext} from 'amis-editor-core';
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
export class WrapperPlugin extends BasePlugin {
@ -31,7 +31,15 @@ export class WrapperPlugin extends BasePlugin {
];
panelTitle = '包裹';
panelBody = [
panelJustify = true;
panelBodyCreator = (context: BaseEventContext) => {
const curRendererSchema = context?.schema;
const isFlexItem = this.manager?.isFlexItem(context?.id);
const isFlexColumnItem = this.manager?.isFlexColumnItem(context?.id);
return [
getSchemaTpl('tabs', [
{
title: '属性',
@ -39,7 +47,88 @@ export class WrapperPlugin extends BasePlugin {
body: [
getSchemaTpl('collapseGroup', [
{
title: '基本',
title: '布局',
body: [
isFlexItem ? getSchemaTpl('layout:flex', {
isFlexColumnItem,
visibleOn: 'data.style && (data.style.position === "static" || data.style.position === "relative")',
}) : null,
isFlexItem ? getSchemaTpl('layout:flex-grow', {
visibleOn: 'data.style && data.style.flex !== "0 0 auto" && (data.style.position === "static" || data.style.position === "relative")',
}) : null,
isFlexItem ? getSchemaTpl('layout:flex-basis', {
label: isFlexColumnItem ? '默认高度' : '默认宽度',
visibleOn: 'data.style && (data.style.position === "static" || data.style.position === "relative")',
}) : null,
getSchemaTpl('layout:position'),
getSchemaTpl('layout:originPosition'),
getSchemaTpl('layout:inset', {
mode: 'vertical'
}),
getSchemaTpl('layout:z-index'),
getSchemaTpl('layout:display'),
getSchemaTpl('layout:flexDirection', {
visibleOn: 'data.style && data.style.display === "flex"',
}),
getSchemaTpl('layout:justifyContent', {
label: '水平对齐方式',
visibleOn: 'data.style && data.style.display === "flex" && data.style.flexDirection === "row" || data.style.flexDirection === "row-reverse"'
}),
getSchemaTpl('layout:justifyContent', {
label: '垂直对齐方式',
visibleOn: 'data.style && data.style.display === "flex" && (data.style.flexDirection === "column" || data.style.flexDirection === "column-reverse")'
}),
getSchemaTpl('layout:alignItems', {
label: '水平对齐方式',
visibleOn: 'data.style && data.style.display === "flex" && (data.style.flexDirection === "column" || data.style.flexDirection === "column-reverse")'
}),
getSchemaTpl('layout:alignItems', {
label: '垂直对齐方式',
visibleOn: 'data.style && data.style.display === "flex" && (data.style.flexDirection === "row" || data.style.flexDirection === "row-reverse")'
}),
getSchemaTpl('layout:flex-wrap', {
visibleOn: 'data.style && data.style.display === "flex"',
}),
getSchemaTpl('layout:isFixedHeight', {
visibleOn: `${!isFlexItem || !isFlexColumnItem}`
}),
getSchemaTpl('layout:height', {
visibleOn: `${!isFlexItem || !isFlexColumnItem}`
}),
getSchemaTpl('layout:max-height', {
visibleOn: `${!isFlexItem || !isFlexColumnItem}`
}),
getSchemaTpl('layout:min-height', {
visibleOn: `${!isFlexItem || !isFlexColumnItem}`
}),
getSchemaTpl('layout:overflow-y', {
visibleOn: `${!isFlexItem || !isFlexColumnItem} && (data.isFixedHeight || data.style && data.style.maxHeight) || (${isFlexItem && isFlexColumnItem} && data.style.flex === '0 0 auto')`,
}),
getSchemaTpl('layout:isFixedWidth', {
visibleOn: `${!isFlexItem || isFlexColumnItem}`
}),
getSchemaTpl('layout:width', {
visibleOn: `${!isFlexItem || isFlexColumnItem}`
}),
getSchemaTpl('layout:max-width', {
visibleOn: `${!isFlexItem || isFlexColumnItem}`
}),
getSchemaTpl('layout:min-width', {
visibleOn: `${!isFlexItem || isFlexColumnItem}`
}),
getSchemaTpl('layout:overflow-x', {
visibleOn: `${!isFlexItem || isFlexColumnItem} && (data.isFixedWidth || data.style && data.style.maxWidth) || (${isFlexItem && !isFlexColumnItem} && data.style.flex === '0 0 auto')`,
}),
!isFlexItem ? getSchemaTpl('layout:margin-center') : null,
]
},
{
title: '常用',
body: [
{
label: '内间距',
@ -78,29 +167,7 @@ export class WrapperPlugin extends BasePlugin {
}
]
},
{
title: '子节点管理',
body: [
{
name: 'body',
label: false,
type: 'combo',
scaffold: {
type: 'tpl',
tpl: '子节点',
inline: false
},
multiple: true,
draggableTip: '',
items: [
{
type: 'tpl',
tpl: '<span class="label label-default">子节点${index | plus}</span>'
}
]
}
]
}
getSchemaTpl('status')
])
]
},
@ -108,7 +175,7 @@ export class WrapperPlugin extends BasePlugin {
title: '外观',
className: 'p-none',
body: getSchemaTpl('collapseGroup', [
...getSchemaTpl('style:common'),
...getSchemaTpl('style:common', ['layout']),
{
title: 'CSS 类名',
body: [
@ -123,5 +190,6 @@ export class WrapperPlugin extends BasePlugin {
])
];
}
}
registerEditorPlugin(WrapperPlugin);

View File

@ -45,7 +45,7 @@ interface EventControlProps extends FormControlProps {
) => void;
addBroadcast?: (event: RendererPluginEvent) => void;
removeBroadcast?: (eventName: string) => void;
getComponents: (action: RendererPluginAction) => ComponentInfo[]; // 当前页面组件树
getComponents: (action: any) => ComponentInfo[]; // 当前页面组件树
getContextSchemas?: (id?: string, withoutSuper?: boolean) => DataSchema; // 获取上下文
actionConfigInitFormatter?: (
actionConfig: ActionConfig,

View File

@ -10,6 +10,7 @@ import camelCase from 'lodash/camelCase';
import {FormItem} from 'amis';
import {isNumeric} from 'amis-editor-core';
import {isAuto} from '../../util';
import type {FormControlProps} from 'amis-core';
import type {PlainObject} from './types';
@ -37,6 +38,7 @@ function BoxModel({
// 数字类型或带有合法单位的字符串都支持
if (
isNumeric(inputValue) ||
isAuto(inputValue) ||
/^(-?(\d*\.)?\d+)((px)|(em)|(%)|(ex)|(ch)|(rem)|(vw)|(vh)|(vmin)|(vmax)|(cm)|(mm)|(in)|(pt)|(pc))$/.test(
inputValue
)

View File

@ -0,0 +1,92 @@
/**
* @file InsetBoxModel
* @description toprightbottomleft
*/
import cx from 'classnames';
import React from 'react';
import {observer} from 'mobx-react';
import camelCase from 'lodash/camelCase';
import {FormItem} from 'amis';
import {isNumeric} from 'amis-editor-core';
import type {FormControlProps} from 'amis-core';
import {isAuto} from '../../util';
import type {PlainObject} from './types';
export type Direction = 'left' | 'right' | 'top' | 'bottom';
function InsetBoxModel({
value,
onChange
}: {
value?: PlainObject;
onChange: (value: PlainObject) => void;
}) {
const directions: Direction[] = ['left', 'right', 'top', 'bottom'];
function handleChange(styleName: string) {
return (e: React.ChangeEvent<HTMLInputElement>) => {
let inputValue = e.target.value;
if (!inputValue) {
onChange({...value, [styleName]: ''});
return;
}
// 数字类型或带有合法单位的字符串都支持
if (
isNumeric(inputValue) ||
isAuto(inputValue) ||
/^(-?(\d*\.)?\d+)((px)|(em)|(%)|(ex)|(ch)|(rem)|(vw)|(vh)|(vmin)|(vmax)|(cm)|(mm)|(in)|(pt)|(pc))$/.test(
inputValue
)
) {
onChange({
...value,
[styleName]: inputValue
});
}
};
}
function renderBoxItem(item: string) {
return (
<>
{directions.map((direction: Direction) => {
const propsName = camelCase(`${item}-${direction}`);
return (
<input
key={propsName}
placeholder="0"
className={`ae-BoxModel-input ${direction}`}
type="text"
onChange={handleChange(propsName)}
value={value?.[propsName] || ''}
/>
);
})}
<div className="ae-BoxModel-title">{item.toUpperCase()}</div>
{['lt', 'lb', 'rt', 'rb'].map(position => (
<div key={position} className={cx('ae-BoxModel-line', position)} />
))}
</>
);
}
return (
<div className="mx-2 ae-BoxModel">
<div className="ae-BoxModel-inner"></div>
{renderBoxItem('inset')}
</div>
);
}
export default observer(InsetBoxModel);
@FormItem({type: 'inset-box-model'})
export class BoxModelRenderer extends React.Component<FormControlProps> {
render() {
return <InsetBoxModel {...this.props} />;
}
}

View File

@ -380,6 +380,7 @@ setSchemaTpl(
rendererWrapper: config?.rendererWrapper,
needDeleteValue: config?.needDeleteValue,
valueType: config?.valueType,
visibleOn: config?.visibleOn,
evalMode: config?.evalMode ?? false // 默认需要${}包裹变量
}
]

View File

@ -5,5 +5,6 @@ import './api';
import './options';
import './validations';
import './style';
import './layout';
export * from './style';

View File

@ -0,0 +1,985 @@
import {setSchemaTpl, getSchemaTpl, defaultValue, tipedLabel} from 'amis-editor-core';
import isNumber from 'lodash/isNumber';
import isString from 'lodash/isString';
/**
*
* 备注: 当前合计新增22个布局相关配置项
* fixed
* 1. inset toprightbottomleft
* 2. wrappercontainer
* 3.
* 4. flex布局
* 5. z-index
* flexcontainer wrapper Flex
*
* flexcontainer
* 1. y轴滚动
* 2. x轴滚动
* 3.
* 4.
* 5.
*/
// 默认支持的单位
const LayoutUnitOptions = [
"px",
"%",
"em",
"vh",
"vw"
];
// 定位模式
setSchemaTpl(
'layout:position',
(config?: {
mode?: string;
label?: string;
name?: string;
value?: string,
visibleOn?: string; // 用于控制显示的表达式
pipeIn?: (value: any, data: any) => void;
pipeOut?: (value: any, data: any) => void;
}) => {
const configSchema = {
type: 'select',
label: config?.label || tipedLabel('定位模式', '指定当前容器元素的定位类型'),
name: config?.name || 'style.position',
value: config?.value || 'static',
visibleOn: config?.visibleOn,
pipeIn: config?.pipeIn,
pipeOut: config?.pipeOut,
onChange: (value: string, oldValue: string, model: any, form: any) => {
if (value === 'static') {
form.setValueByName('style.inset', undefined);
form.setValueByName('style.zIndex', undefined);
} else if (value === 'fixed' || value === 'absolute') {
// 默认使用右下角进行相对定位
form.setValueByName('style.inset', 'auto 50px 50px auto');
}
},
options: [
{
label: '默认',
value: 'static'
},
{
label: '相对',
value: 'relative'
},
{
label: '固定(相对窗口)',
value: 'fixed'
},
{
label: '绝对(相对父容器)',
value: 'absolute'
},
]
}
if (config?.mode === 'vertical') {
// 上下展示,可避免 自定义渲染器 出现挤压
return {
type: 'group',
mode: 'vertical',
visibleOn: config?.visibleOn,
body: [
{
...configSchema
}
]
};
} else {
// 默认左右展示
return configSchema;
}
});
// inset 配置:
setSchemaTpl(
'layout:inset',
(config?: {
mode?: string;
label?: string;
name?: string;
value?: string,
visibleOn?: string;
}) => {
const configSchema = {
type: 'inset-box-model',
label: config?.label || tipedLabel('布局位置', '指定当前容器元素的定位位置,用于配置 top、right、bottom、left。'),
name: config?.name || 'style.inset',
value: config?.value || 'auto',
visibleOn: config?.visibleOn ?? 'data.style && data.style.position && data.style.position !== "static"',
pipeIn: (value: any) => {
let curValue = value || 'auto';
if (isNumber(curValue)) {
curValue = curValue.toString();
} if (!isString(curValue)) {
curValue = '0';
}
const inset = curValue.split(' ');
return {
insetTop: inset[0] || 'auto',
insetRight: inset[1] || 'auto',
insetBottom: inset[2] || inset[0] || 'auto',
insetLeft: inset[3] || inset[1] || 'auto',
};
},
pipeOut: (value: any) => {
console.log('pipeOut:', value);
return `${value.insetTop ?? 'auto'} ${value.insetRight ?? 'auto'} ${value.insetBottom ?? 'auto'} ${value.insetLeft ?? 'auto'}`;
}
}
if (config?.mode === 'vertical') {
// 上下展示,可避免 自定义渲染器 出现挤压
return {
type: 'group',
mode: 'vertical',
visibleOn: config?.visibleOn,
body: [
{
...configSchema
}
]
};
} else {
// 默认左右展示
return configSchema;
}
});
// z-index 配置:
setSchemaTpl(
'layout:z-index',
(config?: {
mode?: string;
label?: string;
name?: string;
value?: string,
visibleOn?: string;
pipeIn?: (value: any, data: any) => void;
pipeOut?: (value: any, data: any) => void;
}) => {
const configSchema = {
type: 'input-number',
label: config?.label || tipedLabel('层级', '指定元素的堆叠顺序,层级高的元素总是会处于较低层级元素的上面。'),
name: config?.name || 'style.zIndex',
value: config?.value || '0',
visibleOn: config?.visibleOn ?? 'data.style && data.style.position && data.style.position !== "static"',
pipeIn: config?.pipeIn,
pipeOut: config?.pipeOut,
}
if (config?.mode === 'vertical') {
// 上下展示,可避免 自定义渲染器 出现挤压
return {
type: 'group',
mode: 'vertical',
visibleOn: config?.visibleOn,
body: [
{
...configSchema
}
]
};
} else {
// 默认左右展示
return configSchema;
}
});
// 显示类型
setSchemaTpl(
'layout:display',
(config?: {
mode?: string;
label?: string;
name?: string;
value?: string,
visibleOn?: string;
pipeIn?: (value: any, data: any) => void;
pipeOut?: (value: any, data: any) => void;
}) => {
const configSchema = {
type: 'select',
label: config?.label || tipedLabel('显示类型', '默认为块级可设置为弹性布局模式flex布局容器'),
name: config?.name || 'style.display',
value: config?.value || 'block',
visibleOn: config?.visibleOn,
pipeIn: config?.pipeIn,
pipeOut: config?.pipeOut,
onChange: (value: string, oldValue: string, model: any, form: any) => {
if (value !== 'flex' && value !== 'inline-flex') {
form.setValueByName('style.flexDirection', undefined);
form.setValueByName('style.justifyContent', undefined);
form.setValueByName('style.alignItems', undefined);
}
},
options: [
{
label: '默认',
value: 'block'
},
{
label: '弹性布局',
value: 'flex'
},
{
label: '行内弹性布局',
value: 'inline-flex'
},
{
label: '行内块级',
value: 'inline-block'
},
{
label: '行内元素',
value: 'inline'
},
]
}
if (config?.mode === 'vertical') {
// 上下展示,可避免 自定义渲染器 出现挤压
return {
type: 'group',
mode: 'vertical',
visibleOn: config?.visibleOn,
body: [
{
...configSchema
}
]
};
} else {
// 默认左右展示
return configSchema;
}
});
// 主轴排列方向
setSchemaTpl(
'layout:justifyContent',
(config?: {
mode?: string; // 自定义展示默认值,上下展示: vertical, 左右展示: horizontal
label?: string; // 表单项 label
name?: string; // 表单项 name
value?: string,
visibleOn?: string; // 用于控制显示的表达式
pipeIn?: (value: any, data: any) => void;
pipeOut?: (value: any, data: any) => void;
}) => {
const configSchema = {
type: 'select',
label: config?.label || tipedLabel(`水平对齐方式`, '设置子元素在主轴上的对齐方式'),
name: config?.name || 'style.justifyContent',
value: config?.value || 'flex-start',
visibleOn: config?.visibleOn,
pipeIn: config?.pipeIn,
pipeOut: config?.pipeOut,
options: [
{
label: '起始端对齐',
value: 'flex-start'
},
{
label: '居中对齐',
value: 'center'
},
{
label: '末尾端对齐',
value: 'flex-end'
},
{
label: '均匀分布(首尾留空)',
value: 'space-around'
},
{
label: '均匀分布(首尾对齐)',
value: 'space-between'
},
{
label: '均匀分布(元素等间距)',
value: 'space-evenly'
},
{
label: '均匀分布(自动拉伸)',
value: 'stretch'
}
]
}
if (config?.mode === 'vertical') {
// 上下展示,可避免 自定义渲染器 出现挤压
return {
type: 'group',
mode: 'vertical',
visibleOn: config?.visibleOn,
body: [
{
...configSchema
}
]
};
} else {
// 默认左右展示
return configSchema;
}
});
// 交叉轴排列方向
setSchemaTpl(
'layout:alignItems',
(config?: {
mode?: string;
label?: string;
name?: string;
value?: string,
visibleOn?: string;
pipeIn?: (value: any, data: any) => void;
pipeOut?: (value: any, data: any) => void;
}) => {
const configSchema = {
type: 'select',
label: config?.label || tipedLabel(`垂直对齐方式`, '设置子元素在交叉轴上的对齐方式'),
name: config?.name || 'style.alignItems',
value: config?.value || 'stretch', // 如果项目未设置高度或设为auto将占满整个容器的高度。
visibleOn: config?.visibleOn,
pipeIn: config?.pipeIn,
pipeOut: config?.pipeOut,
options: [
{
label: '起始端对齐',
value: 'flex-start'
},
{
label: '居中对齐',
value: 'center'
},
{
label: '末尾端对齐',
value: 'flex-end'
},
{
label: '基线对齐',
value: 'baseline'
},
{
label: '自动拉伸',
value: 'stretch'
}
]
}
if (config?.mode === 'vertical') {
return {
type: 'group',
mode: 'vertical',
visibleOn: config?.visibleOn,
body: [
{
...configSchema
}
]
};
} else {
return configSchema;
}
});
// 排列方向
setSchemaTpl(
'layout:flexDirection',
(config?: {
mode?: string;
label?: string;
name?: string;
value?: string,
visibleOn?: string;
pipeIn?: (value: any, data: any) => void;
pipeOut?: (value: any, data: any) => void;
}) => {
const configSchema = {
type: 'select',
label: config?.label || tipedLabel('排列方向', '设置成水平排列方向,则从左到右放置子项;设置成垂直排列方向,则从上到下放置子项'),
name: config?.name || 'style.flexDirection',
value: config?.value || 'row',
visibleOn: config?.visibleOn,
pipeIn: config?.pipeIn,
pipeOut: config?.pipeOut,
options: [
{
label: '水平',
value: 'row'
},
{
label: '水平(起点在右端)',
value: 'row-reverse'
},
{
label: '垂直',
value: 'column'
},
{
label: '垂直(起点在下沿)',
value: 'column-reverse'
},
]
}
if (config?.mode === 'vertical') {
// 上下展示,可避免 自定义渲染器 出现挤压
return {
type: 'group',
mode: 'vertical',
visibleOn: config?.visibleOn,
body: [
{
...configSchema
}
]
};
} else {
// 默认左右展示
return configSchema;
}
});
// 如何换行
setSchemaTpl(
'layout:flex-wrap',
(config?: {
label?: string;
name?: string;
value?: string,
visibleOn?: string;
pipeIn?: (value: any, data: any) => void;
pipeOut?: (value: any, data: any) => void;
}) => {
return {
type: 'select',
label: config?.label || '如何换行',
name: config?.name || 'style.flexWrap',
value: config?.value || 'nowrap',
visibleOn: config?.visibleOn,
pipeIn: config?.pipeIn,
pipeOut: config?.pipeOut,
options: [
{
label: '默认(不换行)',
value: 'nowrap'
},
{
label: '自动换行',
value: 'wrap'
},
{
label: '自动换行(颠倒)',
value: 'wrap-reverse'
},
]
};
});
// 弹性模式
setSchemaTpl(
'layout:flex',
(config?: {
label?: string;
name?: string;
value?: string,
visibleOn?: string;
isFlexColumnItem?: boolean;
}) => {
return {
type: 'switch',
label: config?.label || tipedLabel('弹性模式', '开启弹性模式后,自动适配当前所在区域'),
name: config?.name || 'style.flex',
value: config?.value || '0 0 auto',
trueValue: '1 1 auto',
falseValue: '0 0 auto',
onText: "开启",
offText: "关闭",
inputClassName: 'inline-flex justify-between',
visibleOn: config?.visibleOn,
onChange: (value: any, oldValue: boolean, model: any, form: any) => {
if (!value || value === '0 0 auto') {
// 固定宽度模式下,剔除占比设置
form.setValueByName('style.flexGrow', undefined);
}
if (config?.isFlexColumnItem) {
form.setValueByName('style.overflowY', 'auto');
form.setValueByName('style.height', undefined);
} else {
form.setValueByName('style.overflowX', 'auto');
form.setValueByName('style.width', undefined);
}
},
};
});
// flex-basis设置
setSchemaTpl(
'layout:flex-basis',
(config?: {
label?: string;
name?: string;
value?: string,
visibleOn?: string;
unitOptions?: Array<string>;
pipeIn?: (value: any, data: any) => void;
pipeOut?: (value: any, data: any) => void;
}) => {
return {
type: 'input-number',
label: tipedLabel(config?.label || '默认宽度', '在分配多余空间之前其默认占据的主轴空间main size'),
name: config?.name || 'style.flexBasis',
value: config?.value || 'auto',
visibleOn: config?.visibleOn,
clearable: true,
unitOptions: config?.unitOptions ?? LayoutUnitOptions,
pipeIn: config?.pipeIn,
pipeOut: config?.pipeOut,
};
});
// flex-grow 占比设置
setSchemaTpl(
'layout:flex-grow',
(config?: {
label?: string;
name?: string;
value?: string,
visibleOn?: string;
pipeIn?: (value: any, data: any) => void;
pipeOut?: (value: any, data: any) => void;
}) => {
return {
type: 'input-range',
max: 12,
step: 1,
label: config?.label || tipedLabel('占比设置', '定义项目的放大比例默认为0即如果存在剩余空间也不放大。'),
name: config?.name || 'style.flexGrow',
value: config?.value || 1,
visibleOn: config?.visibleOn || 'data.style && data.style.flex !== "0 0 auto"',
pipeIn: config?.pipeIn,
pipeOut: config?.pipeOut,
};
});
// 是否固定宽度: isFixedWidth 配置:
setSchemaTpl(
'layout:isFixedWidth',
(config?: {
label?: string;
name?: string;
value?: string,
visibleOn?: string;
pipeIn?: (value: any, data: any) => void;
pipeOut?: (value: any, data: any) => void;
}) => {
return {
type: 'switch',
label: config?.label || '固定宽度',
name: config?.name || 'isFixedWidth',
value: config?.value || false,
visibleOn: config?.visibleOn,
inputClassName: 'inline-flex justify-between',
pipeIn: config?.pipeIn,
pipeOut: config?.pipeOut,
onChange: (value: boolean, oldValue: boolean, model: any, form: any) => {
if (value) {
// 固定宽度时,剔除最大宽度、最小宽度
form.setValueByName('style.maxWidth', undefined);
form.setValueByName('style.minWidth', undefined);
} else {
// 非固定宽度时,剔除宽度数值
form.setValueByName('style.width', undefined);
}
},
};
});
// 宽度设置
setSchemaTpl(
'layout:width',
(config?: {
label?: string;
name?: string;
value?: string,
visibleOn?: string;
unitOptions?: Array<string>;
pipeIn?: (value: any, data: any) => void;
pipeOut?: (value: any, data: any) => void;
}) => {
return {
type: 'input-number',
label: config?.label || '宽度',
name: config?.name || 'style.width',
value: config?.value || '300px',
visibleOn: config?.visibleOn ? `${config?.visibleOn} && data.isFixedWidth` : 'data.isFixedWidth',
clearable: true,
unitOptions: config?.unitOptions ?? LayoutUnitOptions,
pipeIn: config?.pipeIn,
pipeOut: config?.pipeOut,
};
});
// 最大宽度设置
setSchemaTpl(
'layout:max-width',
(config?: {
label?: string;
name?: string;
value?: string,
visibleOn?: string;
unitOptions?: Array<string>;
pipeIn?: (value: any, data: any) => void;
pipeOut?: (value: any, data: any) => void;
}) => {
return {
type: 'input-number',
label: config?.label || tipedLabel('最大宽度', '最大宽度即当前元素最大的水平展示区域'),
name: config?.name || 'style.maxWidth',
value: config?.value,
min: '${style.minWidth | toInt}',
visibleOn: config?.visibleOn ? `${config?.visibleOn} && !data.isFixedWidth` : '!data.isFixedWidth',
clearable: true,
unitOptions: config?.unitOptions ?? LayoutUnitOptions,
pipeIn: config?.pipeIn,
pipeOut: config?.pipeOut,
};
});
// 最小宽度设置
setSchemaTpl(
'layout:min-width',
(config?: {
label?: string;
name?: string;
value?: string,
visibleOn?: string;
unitOptions?: Array<string>;
pipeIn?: (value: any, data: any) => void;
pipeOut?: (value: any, data: any) => void;
}) => {
return {
type: 'input-number',
label: config?.label || tipedLabel('最小宽度', '最小宽度即当前元素最小的水平展示区域'),
name: config?.name || 'style.minWidth',
value: config?.value,
max: '${style.maxWidth | toInt}',
visibleOn: config?.visibleOn ? `${config?.visibleOn} && !data.isFixedWidth` : '!data.isFixedWidth',
clearable: true,
unitOptions: config?.unitOptions ?? LayoutUnitOptions,
pipeIn: config?.pipeIn,
pipeOut: config?.pipeOut,
};
});
// x轴水平轴滚动模式
setSchemaTpl(
'layout:overflow-x',
(config?: {
label?: string;
name?: string;
value?: string,
visibleOn?: string;
pipeIn?: (value: any, data: any) => void;
pipeOut?: (value: any, data: any) => void;
}) => {
return {
type: 'select',
label: config?.label || tipedLabel(' x轴滚动模式', '用于设置水平方向的滚动模式'),
name: config?.name || 'style.overflowX',
value: config?.value || 'auto',
visibleOn: config?.visibleOn,
pipeIn: config?.pipeIn,
pipeOut: config?.pipeOut,
options: [
{
label: '超出显示',
value: 'visible'
},
{
label: '超出隐藏',
value: 'hidden'
},
{
label: '滚动显示',
value: 'scroll'
},
{
label: '自动适配',
value: 'auto'
},
]
};
});
// 是否固定高度: isFixedHeight 配置:
setSchemaTpl(
'layout:isFixedHeight',
(config?: {
label?: string;
name?: string;
value?: string,
visibleOn?: string;
pipeIn?: (value: any, data: any) => void;
pipeOut?: (value: any, data: any) => void;
}) => {
return {
type: 'switch',
label: config?.label || '固定高度',
name: config?.name || 'isFixedHeight',
value: config?.value || false,
visibleOn: config?.visibleOn,
inputClassName: 'inline-flex justify-between',
pipeIn: config?.pipeIn,
pipeOut: config?.pipeOut,
onChange: (value: boolean, oldValue: boolean, model: any, form: any) => {
if (value) {
// 固定高度时,剔除最大高度、最小高度
form.setValueByName('style.maxHeight', undefined);
form.setValueByName('style.minHeight', undefined);
} else {
// 非固定高度时,剔除高度数值
form.setValueByName('style.height', undefined);
}
},
};
});
// 高度设置
setSchemaTpl(
'layout:height',
(config?: {
label?: string;
name?: string;
value?: string,
visibleOn?: string;
unitOptions?: Array<string>;
pipeIn?: (value: any, data: any) => void;
pipeOut?: (value: any, data: any) => void;
}) => {
return {
type: 'input-number',
label: config?.label || '高度',
name: config?.name || 'style.height',
value: config?.value || '300px',
visibleOn: config?.visibleOn ? `${config?.visibleOn} && data.isFixedHeight` : 'data.isFixedHeight',
clearable: true,
unitOptions: config?.unitOptions ?? LayoutUnitOptions,
pipeIn: config?.pipeIn,
pipeOut: config?.pipeOut,
};
});
// 最大高度设置
setSchemaTpl(
'layout:max-height',
(config?: {
label?: string;
name?: string;
value?: string,
visibleOn?: string;
unitOptions?: Array<string>;
pipeIn?: (value: any, data: any) => void;
pipeOut?: (value: any, data: any) => void;
}) => {
return {
type: 'input-number',
label: config?.label || tipedLabel('最大高度', '最大高度即当前元素最多的展示高度'),
name: config?.name || 'style.maxHeight',
value: config?.value,
min: '${style.minHeight | toInt}',
visibleOn: config?.visibleOn ? `${config?.visibleOn} && !data.isFixedHeight` : '!data.isFixedHeight',
clearable: true,
unitOptions: config?.unitOptions ?? LayoutUnitOptions,
pipeIn: config?.pipeIn,
pipeOut: config?.pipeOut,
};
});
// 最小高度设置
setSchemaTpl(
'layout:min-height',
(config?: {
label?: string;
name?: string;
value?: string,
visibleOn?: string;
unitOptions?: Array<string>;
pipeIn?: (value: any, data: any) => void;
pipeOut?: (value: any, data: any) => void;
}) => {
return {
type: 'input-number',
label: config?.label || tipedLabel('最小高度', '最小宽度即当前元素最小的垂直展示区域'),
name: config?.name || 'style.minHeight',
value: config?.value,
max: '${style.maxHeight | toInt}',
visibleOn: config?.visibleOn ? `${config?.visibleOn} && !data.isFixedHeight` : '!data.isFixedHeight',
clearable: true,
unitOptions: config?.unitOptions ?? LayoutUnitOptions,
pipeIn: config?.pipeIn,
pipeOut: config?.pipeOut,
};
});
// y轴交叉轴滚动模式
setSchemaTpl(
'layout:overflow-y',
(config?: {
label?: string;
name?: string;
value?: string,
visibleOn?: string;
pipeIn?: (value: any, data: any) => void;
pipeOut?: (value: any, data: any) => void;
}) => {
return {
type: 'select',
label: config?.label || tipedLabel(' y轴滚动模式', '用于设置垂直方向的滚动模式'),
name: config?.name || 'style.overflowY',
value: config?.value || 'auto',
visibleOn: config?.visibleOn,
pipeIn: config?.pipeIn,
pipeOut: config?.pipeOut,
options: [
{
label: '超出显示',
value: 'visible'
},
{
label: '超出隐藏',
value: 'hidden'
},
{
label: '滚动显示',
value: 'scroll'
},
{
label: '自动适配',
value: 'auto'
},
]
};
});
// 居中显示
setSchemaTpl(
'layout:margin-center',
(config?: {
label?: string;
name?: string;
value?: string;
visibleOn?: string;
pipeIn?: (value: any, data: any) => void;
pipeOut?: (value: any, data: any) => void;
}) => {
return {
type: 'switch',
label: config?.label || tipedLabel('居中显示', '通过将设置 margin: 0 auto 来达到居中显示'),
name: config?.name || 'style.margin',
value: config?.value || '0',
inputClassName: 'inline-flex justify-between',
visibleOn: config?.visibleOn ?? 'data.isFixedWidth || data.style && data.style.maxWidth',
pipeIn: (value: any) => {
let curValue = value || '0';
if (isNumber(curValue)) {
curValue = curValue.toString();
} if (!isString(curValue)) {
curValue = '0';
}
const margin = value.split(' ');
const curMargin = {
top: margin[0] || '0',
right: margin[1] || '0',
bottom: margin[2] || margin[0] || '0',
left: margin[3] || margin[1] || '0',
}
// 当左右margin数值相同时则可认为是居中模式
return curMargin.left !== '0' && curMargin.left === curMargin.right ? true : false;
},
pipeOut: (value: boolean) => {
return value ? '0 auto' : '0';
}
};
});
//「参考位置」可设置为左上角、右上角、右下角、左下角,默认为“右下角”。
setSchemaTpl(
'layout:originPosition',
(config?: {
mode?: string;
label?: string;
name?: string;
value?: string,
visibleOn?: string;
pipeIn?: (value: any, data: any) => void;
pipeOut?: (value: any, data: any) => void;
}) => {
const configSchema = {
type: 'select',
label: config?.label || tipedLabel('参考位置', '可设置为左上角、右上角、右下角、左下角,默认为右下角'),
name: config?.name || 'originPosition',
value: config?.value || 'right-bottom',
visibleOn: config?.visibleOn ?? 'data.style && data.style.position && (data.style.position === "fixed" || data.style.position === "absolute")',
pipeIn: config?.pipeIn,
pipeOut: config?.pipeOut,
options: [
{
label: '左上角',
value: 'left-top'
},
{
label: '右上角',
value: 'right-top'
},
{
label: '右下角(默认)',
value: 'right-bottom'
},
{
label: '左下角',
value: 'left-bottom'
},
],
onChange: (value: string, oldValue: string, model: any, form: any) => {
if (value === 'right-bottom') {
// 右下角
form.setValueByName('style.inset', 'auto 50px 50px auto');
} else if (value === 'left-top') {
// 左上角
form.setValueByName('style.inset', '50px auto auto 50px');
} else if (value === 'right-top') {
// 右上角
form.setValueByName('style.inset', '50px 50px auto auto');
} else if (value === 'left-bottom') {
// 左下角
form.setValueByName('style.inset', 'auto auto 50px 50px');
}
},
}
if (config?.mode === 'vertical') {
return {
type: 'group',
mode: 'vertical',
visibleOn: config?.visibleOn,
body: [
{
...configSchema
}
]
};
} else {
return configSchema;
}
});

View File

@ -0,0 +1,282 @@
import {
BaseEventContext,
EditorManager,
RendererPluginAction
} from 'amis-editor-core';
import {filterTree, mapTree} from 'amis';
import ACTION_TYPE_TREE from './renderer/event-control/actions';
import {ActionConfig, ComponentInfo} from './renderer/event-control/types';
import {
COMMON_ACTION_SCHEMA_MAP,
findActionNode,
findSubActionNode,
FORMITEM_CMPTS,
getActionType,
getPropOfAcion,
hasActionType
} from './renderer/event-control/helper';
import isString from 'lodash/isString';
/**
*
*/
export const getEventControlConfig = (
manager: EditorManager,
context: BaseEventContext
) => {
// 通用动作配置
const commonActions =
manager?.config.actionOptions?.customActionGetter?.(manager);
// 动作树
const actionTree = manager?.config.actionOptions?.actionTreeGetter
? manager?.config.actionOptions?.actionTreeGetter(ACTION_TYPE_TREE(manager))
: ACTION_TYPE_TREE(manager);
const commonActionConfig = {
...COMMON_ACTION_SCHEMA_MAP,
...commonActions
};
return {
showOldEntry:
manager?.config.actionOptions?.showOldEntry !== false &&
(!!context.schema.actionType ||
['submit', 'reset'].includes(context.schema.type)),
actions: manager?.pluginActions,
events: manager?.pluginEvents,
actionTree,
commonActions,
owner: '',
addBroadcast: manager?.addBroadcast,
removeBroadcast: manager?.removeBroadcast,
getContextSchemas: async (id?: string, withoutSuper?: boolean) => {
const dataSchema = await manager.getContextSchemas(
id ?? context!.id,
withoutSuper
);
// 存在指定id时只需要当前层上下文
if (id) {
return dataSchema;
}
return manager.dataSchema;
},
getComponents: (action: RendererPluginAction) => {
const actionType = action.actionType!;
const components = filterTree(
mapTree(
manager?.store?.outline ?? [],
(item: any) => {
const schema = manager?.store?.getSchema(item.id);
return {
id: item.id,
label: item.label,
value: schema?.id ?? item.id,
type: schema?.type ?? item.type,
schema,
disabled: !!item.region,
children: item?.children
};
},
1,
true
),
node => {
const actions = manager?.pluginActions[node.type];
let isSupport = false;
if (typeof action.supportComponents === 'string') {
isSupport =
action.supportComponents === '*' ||
action.supportComponents === node.type;
} else if (Array.isArray(action.supportComponents)) {
isSupport = action.supportComponents.includes(node.type);
}
if (['reload', 'setValue'].includes(actionType)) {
isSupport = hasActionType(actionType, actions);
}
if (actionType === 'component' && !actions?.length) {
node.disabled = true;
}
if (isSupport) {
return true;
} else if (!isSupport && !!node.children?.length) {
node.disabled = true;
return true;
}
return false;
},
1,
true
);
return components;
},
actionConfigInitFormatter: (action: ActionConfig) => {
let config = {...action};
if (
['setValue', 'url', 'link'].includes(action.actionType) &&
action.args
) {
const prop = action.actionType === 'setValue' ? 'value' : 'params';
!config.args && (config.args = {});
if (Array.isArray(action.args[prop])) {
config.args[prop] = action.args[prop].reduce(
(arr: any, valueItem: any, index: number) => {
if (!arr[index]) {
arr[index] = {};
}
arr[index].item = Object.entries(valueItem).map(([key, val]) => ({
key,
val
}));
return arr;
},
[]
);
} else if (typeof action.args[prop] === 'object') {
config.args[prop] = Object.keys(action.args[prop]).map(key => ({
key,
val: action.args?.[prop][key]
}));
} else if (
action.actionType === 'setValue' &&
typeof action.args[prop] === 'string'
) {
config.args['valueInput'] = config.args['value'];
delete config.args?.value;
}
}
// 获取动作专有配置参数
const innerArgs: any = getPropOfAcion(
action,
'innerArgs',
actionTree,
manager.pluginActions,
commonActions
);
// 还原args为可视化配置结构(args + addOnArgs)
if (config.args) {
if (innerArgs) {
let tmpArgs = {};
config.addOnArgs = [];
Object.keys(config.args).forEach(key => {
// 筛选出附加配置参数
if (!innerArgs.includes(key)) {
config.addOnArgs = [
...config.addOnArgs,
{
key: key,
val: config.args?.[key]
}
];
} else {
tmpArgs = {
...tmpArgs,
[key]: config.args?.[key]
};
}
});
config.args = tmpArgs;
}
}
// 获取左侧命中的动作节点
const hasSubActionNode = findSubActionNode(actionTree, action.actionType);
return {
...config,
actionType: getActionType(action, hasSubActionNode)
};
},
actionConfigSubmitFormatter: (config: ActionConfig) => {
let action = {...config};
action.__title = findActionNode(
actionTree,
config.actionType
)?.actionLabel;
// 修正动作名称
if (config.actionType === 'component') {
// 标记一下组件特性动作
action.__isCmptAction = true;
action.actionType = config.__cmptActionType;
}
const hasSubActionNode = findSubActionNode(
actionTree,
config.__cmptActionType
);
if (hasSubActionNode) {
// 修正动作
action.actionType = config.__cmptActionType;
}
// 合并附加的动作参数
if (config.addOnArgs) {
config.addOnArgs.forEach((args: any) => {
action.args = action.args ?? {};
action.args = {
...action.args,
[args.key]: args.val
};
});
delete action.addOnArgs;
}
// 转换下格式
if (['setValue', 'url', 'link'].includes(action.actionType)) {
const propName = action.actionType === 'setValue' ? 'value' : 'params';
if (Array.isArray(config.args?.[propName])) {
action.args = action.args ?? {};
if (action.__rendererName === 'combo') {
// combo特殊处理
let tempArr: any = [];
config.args?.[propName].forEach((valueItem: any, index: number) => {
valueItem.item.forEach((item: any) => {
if (!tempArr[index]) {
tempArr[index] = {};
}
tempArr[index][item.key] = item.val;
});
});
action.args = {
...action.args,
[propName]: tempArr
};
} else {
let tmpObj: any = {};
config.args?.[propName].forEach((item: any) => {
tmpObj[item.key] = item.val;
});
action.args = {
...action.args,
[propName]: tmpObj
};
}
} else if (action.actionType === 'setValue') {
// 处理变量赋值非数组的情况
action.args = {
...action.args,
value: config.args?.['valueInput']
};
}
}
delete action.config;
return action;
}
};
};
/**
*
*/
export const isAuto = (value: any) => {
if (value && isString(value)
&& /^((a)|(au)|(aut)|(auto))$/.test(value)) {
return true;
}
return false;
}

View File

@ -49,7 +49,7 @@ export interface Validator {
/**
*
*/
schema?: SchemaObject[];
schema?: any[];
/**
* true则表示是默认

View File

@ -0,0 +1,101 @@
/**
* @file webpack 配置文件
*/
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const nodeExternals = require('webpack-node-externals');
const path = require('path');
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
mode: 'production', // development production
entry: {
index: ['./src/index.tsx'],
},
output: {
path: path.join(__dirname, 'lib'),
filename: '[name].min.js',
libraryTarget: 'commonjs'
},
resolve: {
extensions: ['.ts', '.tsx', '.js']
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
options: {
compilerOptions: {
declaration: true,
outDir: './lib'
}
}
},
{
test: /\.scss$/i,
use: [
MiniCssExtractPlugin.loader,
// Creates `style` nodes from JS strings
// 'style-loader',
// Translates CSS into CommonJS
'css-loader',
// Compiles Sass to CSS
{
loader: 'sass-loader',
options: {
implementation: require('sass'), // `dart-sass` 是首选
// webpackImporter: true, // 开启 / 关闭默认的 Webpack importer。默认为true所以不需要额外配置这个
sassOptions: {
// 正常情况下不需要这个配置项但有些情况下需要比如导入的sass文件包含 media queries等
includePaths: ['node_modules', '../../node_modules'],
},
},
}
]
},
{
test: /\.css$/i,
use: [
MiniCssExtractPlugin.loader,
// Creates `style` nodes from JS strings
// 'style-loader',
// Translates CSS into CommonJS
'css-loader'
]
},
{
test: /\.svg$/,
issuer: /\.[jt]sx?$/,
use: ['@svgr/webpack']
}
]
},
plugins: [
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: '[name].css',
chunkFilename: '[id].css'
}),
// new BundleAnalyzerPlugin(),
{
apply(compiler) {
compiler.hooks.shouldEmit.tap(
'Remove styles from output',
compilation => {
delete compilation.assets['style.min.js']; // Remove asset. Name of file depends of your entries and
return true;
}
);
}
}
],
externals: [
nodeExternals({
importType: 'commonjs',
allowlist: [/^amis\/schemas/],
additionalModuleDirs: [path.resolve(__dirname, '../../node_modules')]
})
]
};