import { IPublicTypeComponentMetadata, IPublicTypeSnippet } from '@alilc/lowcode-types' const CustomDrawerMeta: IPublicTypeComponentMetadata = { group: '低代码组件', componentName: 'CustomDrawer', title: '抽屉', docUrl: '', screenshot: '', devMode: 'proCode', category: '布局容器类', npm: { package: '@dckj-npm/dc-material', version: '0.1.275', exportName: 'CustomDrawer', main: 'src/index.tsx', destructuring: true, subName: '', }, configure: { props: [ { title: '数据源绑定', name: 'dataList', setter: { componentName: 'SetterFormVariable', props: {}, }, }, { title: '是否显示', name: 'visible', setter: { componentName: 'BoolSetter', initialValue: true, }, }, { title: '标题', name: 'title', setter: { componentName: 'StringSetter', isRequired: false, initialValue: '', }, }, { title: '弹出位置', name: 'placement', setter: { componentName: 'RadioGroupSetter', props: { dataSource: [ { label: '上', value: 'top' }, { label: '左', value: 'left' }, { label: '右', value: 'right' }, { label: '下', value: 'bottom' }, ], options: [ { label: '上', value: 'top' }, { label: '左', value: 'left' }, { label: '右', value: 'right' }, { label: '下', value: 'bottom' }, ], }, initialValue: 'left', }, }, { title: '操作项', name: 'actions', setter: { componentName: 'ArraySetter', props: { itemSetter: { componentName: 'ObjectSetter', props: { config: { items: [ { title: '文本', name: 'text', setter: { componentName: 'StringSetter', isRequired: true, initialValue: '', }, }, { title: '操作', name: 'action', setter: { componentName: 'RadioGroupSetter', props: { dataSource: [ { label: '提交', value: 'submit' }, { label: '取消', value: 'cancel' }, ], options: [ { label: '提交', value: 'submit' }, { label: '取消', value: 'cancel' }, ], }, }, }, { title: '样式', name: 'style', setter: { componentName: 'RadioGroupSetter', props: { dataSource: [ { label: '主要', value: 'primary' }, { label: '次要', value: 'secondary' }, { label: '普通', value: 'normal' }, ], options: [ { label: '主要', value: 'primary' }, { label: '次要', value: 'secondary' }, { label: '普通', value: 'normal' }, ], }, }, }, ], }, }, }, }, }, }, ], supports: { style: true, }, component: { isContainer: true, isModal: true, disableBehaviors: ['copy'], rootSelector: '.drawer', nestingRule: { parentWhitelist: (testNode, currentNode) => { return testNode.componentName === 'Page' }, }, }, advanced: { callbacks: { // 与 next-page 的 onNodeAdd 一模一样 onNodeAdd: (dragment, currentNode) => { // 拖入的组件为 P、Block、Slot(把NextPage拖入到面板里时,NextPage的Slot也会触发onNodeAdd事件) 时,不进行包裹 // 拖入的组件 isModal为true时(例如drawer dialog 这类有单独组件树结构的),不进行包裹 if ( !dragment || ['NextP', 'NextBlock', 'Slot'].includes(dragment.componentName) || (dragment.componentMeta.isModal && dragment.componentMeta.isModal()) ) { console.log( `[${dragment.componentName}] doesn\'n need to wrap with NextBlock > NextBlockCell`, ) return } const NextPProps = { wrap: false, type: 'body2', verAlign: 'middle', textSpacing: true, align: 'left', } if ( [ 'Form', 'ResponsiveGrid', 'Box', 'Card', 'List', 'Message', 'Slider', 'NextTable', ].includes(dragment.componentName) || dragment.getPropValue('isFillContainer') ) { NextPProps.full = true } const layoutPSchema = { componentName: 'NextP', title: '段落', props: NextPProps, children: [dragment.exportSchema()], } // 为目标元素包裹一层 Block const layoutBlockNode = (len) => currentNode.document.createNode({ componentName: 'NextBlock', title: '区块', props: { childTotalColumns: len || 12, }, children: [ { componentName: 'NextBlockCell', title: '子区块', props: { isAutoContainer: true, colSpan: 12, rowSpan: 1, }, children: [layoutPSchema], }, ], }) const dropLocation = dragment.document.canvas.dropLocation if (!dropLocation) { // 没有 dropLocation 一般是 slot, slot 元素不用特殊处理 不做任何包裹 return } const dropTarget = dropLocation.target const dropTargetName = dropLocation.target.componentName || '' // 找到要拖入进去的节点 ID const targetId = (dropLocation && dropLocation.target.id) || '' // 找到要拖入进去的节点 let slotTarget = currentNode.slots.length > 0 && currentNode.slots.find((item) => item.id === targetId) const layoutPNode = currentNode.document.createNode(layoutPSchema) // 是否为 aside slot const isAsideSlot = slotTarget && ['aside'].indexOf(slotTarget._slotFor.key) > -1 // 是否为需要被 P 包裹的 Slot const isNeedPSlot = slotTarget && ['header', 'footer', 'nav'].indexOf(slotTarget._slotFor.key) > -1 const wrapWithBlock = (dragment, node, dropTargetName, blockLen) => { setTimeout(() => { console.log( `[${dragment.componentName}] to [${dropTargetName}] need to wrap with NextBlock > NextBlockCell > NextP [from NextPage2]`, ) const newNode = node.document.createNode(layoutBlockNode(blockLen).exportSchema()) node.insertBefore(newNode, dragment, false) dragment.remove(false) newNode.children.get(0).children.get(0).children.get(0).select() }, 1) } const wrapWithP = (dragment, node, dropTargetName) => { setTimeout(() => { // const dragmentTarget = dropTarget; // 要拖入的地方如果是 NextP 那就 不再自动包裹 P了 if (dropTargetName === 'NextP') { console.log( `[${dragment.componentName}] to [${dropTargetName}] does't need to wrap with NextP. [from NextPage3]`, ) return } console.log( `[${dragment.componentName}] to [${dropTargetName}] need to wrap with NextP [from NextPage3]`, ) const newNode = node.document.createNode(Object.assign(layoutPNode.exportSchema())) node.insertBefore(newNode, dragment, false) dragment.remove(false) newNode.children.get(0).select() }, 1) } // 需要包裹 Block BlockCell P 的情况: // 1. 组件拖入到 NextPage,的直接子元素下(不包括slot), 此时Block宽度为12 if (['NextPage'].includes(dropTargetName) && currentNode.children.has(dragment)) { wrapWithBlock(dragment, currentNode, dropTargetName, 12) // 需要包裹 Block BlockCell P 的情况: // 2. 组件拖入到 NextPage 的 aside slot, 的直接子元素下 (不包括slot下的进一步内容),此时Block宽度为1 } else if (isAsideSlot && slotTarget && slotTarget.children.has(dragment)) { wrapWithBlock(dragment, slotTarget, dropTargetName, 1) // 需要包裹 P 的情况: // 1. 如果是处于,开启了自然布局模式的容器组件中 (或者Tab里) // 这里的Tab主要是给纪元epoch使用的,因为他们用到了 @ali/vc-deep 的TabLayout组件,没办法在这个组件上再增加属性 isAutoContainer } else if (dropTarget.getPropValue('isAutoContainer') || dropTargetName === 'Tab.Item') { wrapWithP(dragment, dropTarget, dropTargetName) // 需要包裹 P 的情况: // 2. 如果是处于,Page 的 nav header footer 中 } else if (isNeedPSlot && slotTarget) { wrapWithP(dragment, slotTarget, dropTargetName) } // 其他维持原状,不进行其他设置 }, }, }, }, } const snippets: IPublicTypeSnippet[] = [ { title: '抽屉', screenshot: '', schema: { componentName: 'CustomDrawer', props: { title: '抽屉', placement: 'left', isAutoContainer: true, actions: [ { text: '确定', action: 'submit', style: 'primary', type: 'submit' }, { text: '取消', action: 'submit', style: 'normal', type: 'cancel' }, ], }, }, }, ] export default { ...CustomDrawerMeta, snippets }