├── packages ├── vue2-renderer │ ├── README.md │ ├── build.json │ ├── build.plugin.js │ ├── tsconfig.json │ ├── src │ │ ├── index.ts │ │ └── create-element │ │ │ ├── Vue2ReactWrapper.tsx │ │ │ ├── vue2-create-element.ts │ │ │ └── adaptive-create-element.ts │ └── package.json ├── vue3-renderer │ ├── README.md │ ├── build.json │ ├── build.plugin.js │ ├── tsconfig.json │ ├── src │ │ ├── index.ts │ │ └── create-element │ │ │ ├── Vue3ReactWrapper.tsx │ │ │ ├── vue3-create-element.ts │ │ │ └── adaptive-create-element.ts │ └── package.json ├── vue-renderer-core │ ├── README.md │ ├── src │ │ ├── utils │ │ │ ├── index.ts │ │ │ ├── is-react.ts │ │ │ └── build-components.ts │ │ ├── types │ │ │ ├── index.ts │ │ │ ├── create-element.ts │ │ │ └── npm.ts │ │ └── index.ts │ ├── tsconfig.json │ ├── build.json │ └── package.json ├── vue2-simulator-renderer │ ├── README.md │ ├── build.json │ ├── build.test.json │ ├── build.plugin.js │ ├── .babelrc │ ├── src │ │ ├── host.ts │ │ ├── utils │ │ │ ├── is-dom-node.ts │ │ │ ├── get-client-rects.ts │ │ │ ├── misc.ts │ │ │ ├── react-find-dom-nodes.ts │ │ │ └── url.ts │ │ ├── index.ts │ │ ├── builtin-components │ │ │ ├── leaf.tsx │ │ │ ├── slot.tsx │ │ │ └── builtin-components.ts │ │ └── renderer.less │ ├── tsconfig.json │ ├── test │ │ ├── utils │ │ │ ├── components.tsx │ │ │ └── host.ts │ │ ├── src │ │ │ └── renderer │ │ │ │ ├── __snapshots__ │ │ │ │ └── demo.test.tsx.snap │ │ │ │ └── demo.test.tsx │ │ └── schema │ │ │ └── basic.ts │ ├── build.umd.json │ ├── jest.config.js │ └── package.json └── vue3-simulator-renderer │ ├── README.md │ ├── build.json │ ├── build.test.json │ ├── build.plugin.js │ ├── .babelrc │ ├── src │ ├── host.ts │ ├── utils │ │ ├── is-dom-node.ts │ │ ├── get-client-rects.ts │ │ ├── misc.ts │ │ ├── react-find-dom-nodes.ts │ │ └── url.ts │ ├── index.ts │ ├── builtin-components │ │ ├── leaf.tsx │ │ ├── slot.tsx │ │ └── builtin-components.ts │ └── renderer.less │ ├── tsconfig.json │ ├── test │ ├── utils │ │ ├── components.tsx │ │ └── host.ts │ ├── src │ │ └── renderer │ │ │ ├── __snapshots__ │ │ │ └── demo.test.tsx.snap │ │ │ └── demo.test.tsx │ └── schema │ │ └── basic.ts │ ├── build.umd.json │ ├── jest.config.js │ └── package.json ├── examples ├── lowcode-vue2-demo │ ├── public │ │ ├── index.html │ │ ├── fixtures │ │ │ └── basic-fusion-with-single-component │ │ │ │ ├── view.css │ │ │ │ ├── view.js │ │ │ │ └── meta.js │ │ ├── mock │ │ │ └── info.json │ │ ├── favicon.png │ │ ├── mock-pages.json │ │ ├── preview.html │ │ ├── simulator │ │ │ └── css │ │ │ │ └── vue2-simulator-renderer.css │ │ └── index.ejs │ ├── .prettierrc.js │ ├── src │ │ ├── sample-plugins │ │ │ ├── logo │ │ │ │ ├── index.scss │ │ │ │ └── index.tsx │ │ │ ├── delete-hidden-transducer │ │ │ │ └── index.ts │ │ │ ├── scenario-switcher │ │ │ │ └── index.tsx │ │ │ └── set-ref-prop │ │ │ │ └── index.tsx │ │ ├── setters │ │ │ ├── custom-setter.tsx │ │ │ └── behavior-setter.tsx │ │ ├── universal │ │ │ ├── scenarios.json │ │ │ ├── global.scss │ │ │ ├── assets.json │ │ │ └── plugin.tsx │ │ ├── scenarios │ │ │ └── index │ │ │ │ └── index.ts │ │ └── preview.tsx │ ├── scripts │ │ └── watchdog.js │ ├── README.md │ ├── LICENSE │ ├── build.json │ ├── .gitignore │ ├── tsconfig.json │ ├── package.json │ └── build.plugin.js └── lowcode-vue3-demo │ ├── public │ ├── index.html │ ├── fixtures │ │ └── basic-fusion-with-single-component │ │ │ ├── view.css │ │ │ ├── view.js │ │ │ └── meta.js │ ├── mock │ │ └── info.json │ ├── favicon.png │ ├── mock-pages.json │ ├── preview.html │ ├── simulator │ │ └── css │ │ │ └── vue3-simulator-renderer.css │ └── index.ejs │ ├── .prettierrc.js │ ├── src │ ├── sample-plugins │ │ ├── logo │ │ │ ├── index.scss │ │ │ └── index.tsx │ │ ├── delete-hidden-transducer │ │ │ └── index.ts │ │ ├── scenario-switcher │ │ │ └── index.tsx │ │ └── set-ref-prop │ │ │ └── index.tsx │ ├── setters │ │ ├── custom-setter.tsx │ │ └── behavior-setter.tsx │ ├── universal │ │ ├── scenarios.json │ │ ├── global.scss │ │ ├── assets.json │ │ └── plugin.tsx │ ├── scenarios │ │ └── index │ │ │ └── index.ts │ └── preview.tsx │ ├── scripts │ └── watchdog.js │ ├── README.md │ ├── LICENSE │ ├── build.json │ ├── .gitignore │ ├── tsconfig.json │ ├── package.json │ └── build.plugin.js ├── .stylelintrc.js ├── .stylelintignore ├── .prettierrc.js ├── .eslintignore ├── pnpm-workspace.yaml ├── .editorconfig ├── scripts └── build.sh ├── README.md ├── package.json ├── LICENSE ├── .eslintrc.js ├── tsconfig.json └── .gitignore /packages/vue2-renderer/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/vue3-renderer/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/vue-renderer-core/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/README.md: -------------------------------------------------------------------------------- 1 | 沙箱环境 2 | -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/README.md: -------------------------------------------------------------------------------- 1 | 沙箱环境 2 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/public/index.html: -------------------------------------------------------------------------------- 1 | 勿删,删了有奇妙的 bug😄~ -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/public/index.html: -------------------------------------------------------------------------------- 1 | 勿删,删了有奇妙的 bug😄~ -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/public/fixtures/basic-fusion-with-single-component/view.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/public/fixtures/basic-fusion-with-single-component/view.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/vue-renderer-core/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './build-components'; 2 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/public/mock/info.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": "Hello AliLowCode!!" 3 | } -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/public/mock/info.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": "Hello AliLowCode!!" 3 | } -------------------------------------------------------------------------------- /packages/vue2-renderer/build.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "build-plugin-component" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /packages/vue3-renderer/build.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "build-plugin-component" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /packages/vue-renderer-core/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './create-element'; 2 | export * from './npm'; 3 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/build.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["build-plugin-component", "./build.plugin.js"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/build.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["build-plugin-component", "./build.plugin.js"] 3 | } 4 | -------------------------------------------------------------------------------- /.stylelintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: 'stylelint-config-ali', 3 | rules: { 4 | "selector-max-id": 2 5 | } 6 | }; 7 | -------------------------------------------------------------------------------- /.stylelintignore: -------------------------------------------------------------------------------- 1 | # 忽略目录 2 | node_modules/ 3 | build/ 4 | dist/ 5 | 6 | # 忽略文件 7 | **/*.min.css 8 | **/*-min.css 9 | **/*.bundle.css 10 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 100, 3 | tabWidth: 2, 4 | semi: true, 5 | singleQuote: true, 6 | trailingComma: 'all', 7 | }; 8 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowcodecloud/lowcode-engine-vue-projects/HEAD/examples/lowcode-vue2-demo/public/favicon.png -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowcodecloud/lowcode-engine-vue-projects/HEAD/examples/lowcode-vue3-demo/public/favicon.png -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/build.test.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "build-plugin-component", 4 | "@alilc/lowcode-test-mate/plugin/index.ts" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/build.test.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "build-plugin-component", 4 | "@alilc/lowcode-test-mate/plugin/index.ts" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /packages/vue-renderer-core/src/types/create-element.ts: -------------------------------------------------------------------------------- 1 | export interface CreateElementAdapter { 2 | createElement(component: any, props: any, ...children: any): any; 3 | } 4 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 100, 3 | tabWidth: 2, 4 | semi: true, 5 | singleQuote: true, 6 | trailingComma: 'all', 7 | }; 8 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 100, 3 | tabWidth: 2, 4 | semi: true, 5 | singleQuote: true, 6 | trailingComma: 'all', 7 | }; 8 | -------------------------------------------------------------------------------- /packages/vue2-renderer/build.plugin.js: -------------------------------------------------------------------------------- 1 | module.exports = ({ onGetWebpackConfig }) => { 2 | onGetWebpackConfig((config) => { 3 | config.performance.hints(false); 4 | }); 5 | }; 6 | -------------------------------------------------------------------------------- /packages/vue3-renderer/build.plugin.js: -------------------------------------------------------------------------------- 1 | module.exports = ({ onGetWebpackConfig }) => { 2 | onGetWebpackConfig((config) => { 3 | config.performance.hints(false); 4 | }); 5 | }; 6 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/build.plugin.js: -------------------------------------------------------------------------------- 1 | module.exports = ({ onGetWebpackConfig }) => { 2 | onGetWebpackConfig((config) => { 3 | config.performance.hints(false); 4 | }); 5 | }; 6 | -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/build.plugin.js: -------------------------------------------------------------------------------- 1 | module.exports = ({ onGetWebpackConfig }) => { 2 | onGetWebpackConfig((config) => { 3 | config.performance.hints(false); 4 | }); 5 | }; 6 | -------------------------------------------------------------------------------- /packages/vue2-renderer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "lib" 5 | }, 6 | "include": [ 7 | "./src/" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /packages/vue3-renderer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "lib" 5 | }, 6 | "include": [ 7 | "./src/" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /packages/vue-renderer-core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "lib" 5 | }, 6 | "include": [ 7 | "./src/" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | ["@babel/plugin-proposal-decorators", { "legacy": true }], 4 | ["@babel/plugin-proposal-class-properties", { "loose": true }] 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | ["@babel/plugin-proposal-decorators", { "legacy": true }], 4 | ["@babel/plugin-proposal-class-properties", { "loose": true }] 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/src/host.ts: -------------------------------------------------------------------------------- 1 | // NOTE: 仅做类型标注,切勿做其它用途 2 | import { BuiltinSimulatorHost } from '@alilc/lowcode-designer'; 3 | 4 | export const host: BuiltinSimulatorHost = (window as any).LCSimulatorHost; 5 | -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/src/host.ts: -------------------------------------------------------------------------------- 1 | // NOTE: 仅做类型标注,切勿做其它用途 2 | import { BuiltinSimulatorHost } from '@alilc/lowcode-designer'; 3 | 4 | export const host: BuiltinSimulatorHost = (window as any).LCSimulatorHost; 5 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # 忽略目录 2 | node_modules 3 | test-cases 4 | test 5 | output 6 | build 7 | dist 8 | demo 9 | es 10 | lib 11 | tests 12 | .* 13 | ~* 14 | 15 | # 忽略文件 16 | **/*.min.js 17 | **/*-min.js 18 | **/*.bundle.js 19 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "lib" 5 | }, 6 | "include": [ 7 | "./src/", "../../index.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "lib" 5 | }, 6 | "include": [ 7 | "./src/", "../../index.ts" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /packages/vue-renderer-core/build.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "build-plugin-component", 4 | "build-plugin-fusion", 5 | ["build-plugin-moment-locales", { 6 | "locales": ["zh-cn"] 7 | }] 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/src/utils/is-dom-node.ts: -------------------------------------------------------------------------------- 1 | export function isDOMNode(node: any): node is Element | Text { 2 | return node.nodeType && (node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.TEXT_NODE); 3 | } 4 | -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/src/utils/is-dom-node.ts: -------------------------------------------------------------------------------- 1 | export function isDOMNode(node: any): node is Element | Text { 2 | return node.nodeType && (node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.TEXT_NODE); 3 | } 4 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | # all packages in subdirs of packages/ and components/ 3 | - 'packages/**' 4 | - 'examples/**' 5 | # exclude packages that are inside test directories 6 | - '!**/test/**' 7 | - '!**/scripts/**' -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/test/utils/components.tsx: -------------------------------------------------------------------------------- 1 | export const Text = ({ 2 | __tag, 3 | content, 4 | ...props 5 | }: any) => (
{content}
); 6 | 7 | export const Page = (props: any) => (
{props.children}
); -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/test/utils/components.tsx: -------------------------------------------------------------------------------- 1 | export const Text = ({ 2 | __tag, 3 | content, 4 | ...props 5 | }: any) => (
{content}
); 6 | 7 | export const Page = (props: any) => (
{props.children}
); -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | quote_type = single 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/src/sample-plugins/logo/index.scss: -------------------------------------------------------------------------------- 1 | .lowcode-plugin-logo { 2 | .logo { 3 | display: block; 4 | width: 139px; 5 | height: 26px; 6 | cursor: pointer; 7 | background-size: contain; 8 | background-position: center; 9 | background-repeat: no-repeat; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/src/sample-plugins/logo/index.scss: -------------------------------------------------------------------------------- 1 | .lowcode-plugin-logo { 2 | .logo { 3 | display: block; 4 | width: 139px; 5 | height: 26px; 6 | cursor: pointer; 7 | background-size: contain; 8 | background-position: center; 9 | background-repeat: no-repeat; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/vue2-renderer/src/index.ts: -------------------------------------------------------------------------------- 1 | import createRendererFactory, { setRuntime, types, buildComponents } from '@lowcodecloud/lowcode-engine-vue-renderer-core'; 2 | 3 | import createElement from './create-element/adaptive-create-element'; 4 | 5 | setRuntime({ 6 | createElement, 7 | }); 8 | 9 | export default createRendererFactory() as types.IRenderComponent; 10 | export { buildComponents, createElement }; 11 | -------------------------------------------------------------------------------- /packages/vue3-renderer/src/index.ts: -------------------------------------------------------------------------------- 1 | import createRendererFactory, { setRuntime, types, buildComponents } from '@lowcodecloud/lowcode-engine-vue-renderer-core'; 2 | 3 | import createElement from './create-element/adaptive-create-element'; 4 | 5 | setRuntime({ 6 | createElement, 7 | }); 8 | 9 | export default createRendererFactory() as types.IRenderComponent; 10 | export { buildComponents, createElement }; 11 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/src/setters/custom-setter.tsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; // import classNames from 'classnames'; 2 | 3 | class CustomSetter extends Component { 4 | render() { 5 | const { defaultValue, value, onChange } = this.props; 6 | const { editor } = this.props.field; 7 | 8 | return
hello world
; 9 | } 10 | } 11 | 12 | export default CustomSetter; 13 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/src/setters/custom-setter.tsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; // import classNames from 'classnames'; 2 | 3 | class CustomSetter extends Component { 4 | render() { 5 | const { defaultValue, value, onChange } = this.props; 6 | const { editor } = this.props.field; 7 | 8 | return
hello world
; 9 | } 10 | } 11 | 12 | export default CustomSetter; 13 | -------------------------------------------------------------------------------- /packages/vue3-renderer/src/create-element/Vue3ReactWrapper.tsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { applyVueInReact } from 'veaury'; 3 | 4 | class Vue3ReactWrapper extends Component { 5 | render() { 6 | const { $vueComponent, __events, ...rest } = this.props; 7 | let VueComponent = applyVueInReact($vueComponent); 8 | return (); 9 | } 10 | } 11 | 12 | export default Vue3ReactWrapper; 13 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/src/utils/get-client-rects.ts: -------------------------------------------------------------------------------- 1 | import { isElement } from '@alilc/lowcode-utils'; 2 | 3 | // a range for test TextNode clientRect 4 | const cycleRange = document.createRange(); 5 | 6 | export function getClientRects(node: Element | Text) { 7 | if (isElement(node)) { 8 | return [node.getBoundingClientRect()]; 9 | } 10 | 11 | cycleRange.selectNode(node); 12 | return Array.from(cycleRange.getClientRects()); 13 | } 14 | -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/src/utils/get-client-rects.ts: -------------------------------------------------------------------------------- 1 | import { isElement } from '@alilc/lowcode-utils'; 2 | 3 | // a range for test TextNode clientRect 4 | const cycleRange = document.createRange(); 5 | 6 | export function getClientRects(node: Element | Text) { 7 | if (isElement(node)) { 8 | return [node.getBoundingClientRect()]; 9 | } 10 | 11 | cycleRange.selectNode(node); 12 | return Array.from(cycleRange.getClientRects()); 13 | } 14 | -------------------------------------------------------------------------------- /packages/vue2-renderer/src/create-element/Vue2ReactWrapper.tsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { applyVueInReact } from 'vuereact-combined'; 3 | 4 | class Vue2ReactWrapper extends Component { 5 | render() { 6 | const { $vueComponent, __events, ...rest } = this.props; 7 | let VueComponent = applyVueInReact($vueComponent); 8 | return (); 9 | } 10 | } 11 | 12 | export default Vue2ReactWrapper; 13 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/public/mock-pages.json: -------------------------------------------------------------------------------- 1 | {"success":true,"content":[{"gmtModified":"2021-03-06 00:40:54","formUuid":"FORM-6X866SC1KM4O4BLF3U7879QB0EMT2Z3TGIWLKW","parentNavUuid":"NAV-SYSTEM-PARENT-UUID","hidden":"n","navUuid":"FORM-6X866SC1KM4O4BLF3U7879QB0EMT2Z3TGIWLKW","navType":"PAGE","isIndex":"n","isNew":"n","gmtCreate":"2021-03-06 00:27:26","title":{"en_US":"页面1","zh_CN":"页面1","type":"i18n"},"relateUuid":"FORM-6X866SC1KM4O4BLF3U7879QB0EMT2Z3TGIWLKW","parentId":0,"listOrder":0,"id":556103}]} -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/public/mock-pages.json: -------------------------------------------------------------------------------- 1 | {"success":true,"content":[{"gmtModified":"2021-03-06 00:40:54","formUuid":"FORM-6X866SC1KM4O4BLF3U7879QB0EMT2Z3TGIWLKW","parentNavUuid":"NAV-SYSTEM-PARENT-UUID","hidden":"n","navUuid":"FORM-6X866SC1KM4O4BLF3U7879QB0EMT2Z3TGIWLKW","navType":"PAGE","isIndex":"n","isNew":"n","gmtCreate":"2021-03-06 00:27:26","title":{"en_US":"页面1","zh_CN":"页面1","type":"i18n"},"relateUuid":"FORM-6X866SC1KM4O4BLF3U7879QB0EMT2Z3TGIWLKW","parentId":0,"listOrder":0,"id":556103}]} -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/scripts/watchdog.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const fs = require('fs'); 3 | const { join } = require('path'); 4 | 5 | const workingDir = process.cwd(); 6 | 7 | const pkg = JSON.parse(fs.readFileSync(join(workingDir, 'package.json'), 'utf-8')); 8 | if (pkg.private) return; 9 | const { files } = pkg; 10 | files.forEach(file => { 11 | const fileDir = join(workingDir, file); 12 | if (!fs.existsSync(fileDir)) { 13 | throw new Error(`${fileDir} does not exist, plz run build`); 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/scripts/watchdog.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const fs = require('fs'); 3 | const { join } = require('path'); 4 | 5 | const workingDir = process.cwd(); 6 | 7 | const pkg = JSON.parse(fs.readFileSync(join(workingDir, 'package.json'), 'utf-8')); 8 | if (pkg.private) return; 9 | const { files } = pkg; 10 | files.forEach(file => { 11 | const fileDir = join(workingDir, file); 12 | if (!fs.existsSync(fileDir)) { 13 | throw new Error(`${fileDir} does not exist, plz run build`); 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/src/index.ts: -------------------------------------------------------------------------------- 1 | import { runInAction } from 'mobx'; 2 | import renderer from './renderer'; 3 | 4 | if (typeof window !== 'undefined') { 5 | (window as any).SimulatorRenderer = renderer; 6 | } 7 | 8 | window.addEventListener('beforeunload', () => { 9 | runInAction(() => { 10 | (window as any).LCSimulatorHost = null; 11 | renderer.dispose?.(); 12 | (window as any).SimulatorRenderer = null; 13 | (window as any).ReactDOM.unmountComponentAtNode(document.getElementById('app')); 14 | }); 15 | }); 16 | 17 | export default renderer; 18 | -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/src/index.ts: -------------------------------------------------------------------------------- 1 | import { runInAction } from 'mobx'; 2 | import renderer from './renderer'; 3 | 4 | if (typeof window !== 'undefined') { 5 | (window as any).SimulatorRenderer = renderer; 6 | } 7 | 8 | window.addEventListener('beforeunload', () => { 9 | runInAction(() => { 10 | (window as any).LCSimulatorHost = null; 11 | renderer.dispose?.(); 12 | (window as any).SimulatorRenderer = null; 13 | (window as any).ReactDOM.unmountComponentAtNode(document.getElementById('app')); 14 | }); 15 | }); 16 | 17 | export default renderer; 18 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/src/sample-plugins/logo/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './index.scss'; 3 | import { PluginProps } from '@alilc/lowcode-types'; 4 | 5 | export interface IProps { 6 | logo?: string; 7 | href?: string; 8 | } 9 | 10 | const Logo: React.FC = (props): React.ReactElement => { 11 | return ( 12 |
13 | 14 |
15 | ); 16 | }; 17 | 18 | export default Logo; 19 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/src/sample-plugins/logo/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './index.scss'; 3 | import { PluginProps } from '@alilc/lowcode-types'; 4 | 5 | export interface IProps { 6 | logo?: string; 7 | href?: string; 8 | } 9 | 10 | const Logo: React.FC = (props): React.ReactElement => { 11 | return ( 12 | 15 | ); 16 | }; 17 | 18 | export default Logo; 19 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/src/builtin-components/leaf.tsx: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | 3 | class Leaf extends Component { 4 | static displayName = 'Leaf'; 5 | 6 | static componentMetadata = { 7 | componentName: 'Leaf', 8 | configure: { 9 | props: [{ 10 | name: 'children', 11 | setter: 'StringSetter', 12 | }], 13 | // events/className/style/general/directives 14 | supports: false, 15 | }, 16 | }; 17 | 18 | render() { 19 | const { children } = this.props; 20 | return children; 21 | } 22 | } 23 | 24 | export default Leaf; 25 | -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/src/builtin-components/leaf.tsx: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | 3 | class Leaf extends Component { 4 | static displayName = 'Leaf'; 5 | 6 | static componentMetadata = { 7 | componentName: 'Leaf', 8 | configure: { 9 | props: [{ 10 | name: 'children', 11 | setter: 'StringSetter', 12 | }], 13 | // events/className/style/general/directives 14 | supports: false, 15 | }, 16 | }; 17 | 18 | render() { 19 | const { children } = this.props; 20 | return children; 21 | } 22 | } 23 | 24 | export default Leaf; 25 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/src/sample-plugins/delete-hidden-transducer/index.ts: -------------------------------------------------------------------------------- 1 | import { ILowCodePluginContext, project } from '@alilc/lowcode-engine'; 2 | import { CompositeObject, TransformStage } from '@alilc/lowcode-types'; 3 | 4 | export const deleteHiddenTransducer = (ctx: ILowCodePluginContext) => { 5 | return { 6 | name: 'deleteHiddenTransducer', 7 | async init() { 8 | project.addPropsTransducer((props: CompositeObject): CompositeObject => { 9 | delete props.hidden; 10 | return props; 11 | }, TransformStage.Save); 12 | }, 13 | }; 14 | } 15 | 16 | deleteHiddenTransducer.pluginName = 'deleteHiddenTransducer'; 17 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/src/sample-plugins/delete-hidden-transducer/index.ts: -------------------------------------------------------------------------------- 1 | import { ILowCodePluginContext, project } from '@alilc/lowcode-engine'; 2 | import { CompositeObject, TransformStage } from '@alilc/lowcode-types'; 3 | 4 | export const deleteHiddenTransducer = (ctx: ILowCodePluginContext) => { 5 | return { 6 | name: 'deleteHiddenTransducer', 7 | async init() { 8 | project.addPropsTransducer((props: CompositeObject): CompositeObject => { 9 | delete props.hidden; 10 | return props; 11 | }, TransformStage.Save); 12 | }, 13 | }; 14 | } 15 | 16 | deleteHiddenTransducer.pluginName = 'deleteHiddenTransducer'; 17 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/src/universal/scenarios.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "index", 4 | "title": "综合场景" 5 | }, 6 | { 7 | "name": "basic-fusion", 8 | "title": "基础 fusion 组件" 9 | }, 10 | { 11 | "name": "basic-fusion-with-single-component", 12 | "title": "基础 fusion 组件 + 单自定义组件" 13 | }, 14 | { 15 | "name": "basic-antd", 16 | "title": "基础 antd 组件" 17 | }, 18 | { 19 | "name": "custom-initialization", 20 | "title": "自定义初始化引擎" 21 | }, 22 | { 23 | "name": "node-extended-actions", 24 | "title": "扩展节点操作项" 25 | }, 26 | { 27 | "name": "next-pro", 28 | "title": "基于next实现的高级表单低代码物料" 29 | } 30 | ] 31 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/src/universal/scenarios.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "index", 4 | "title": "综合场景" 5 | }, 6 | { 7 | "name": "basic-fusion", 8 | "title": "基础 fusion 组件" 9 | }, 10 | { 11 | "name": "basic-fusion-with-single-component", 12 | "title": "基础 fusion 组件 + 单自定义组件" 13 | }, 14 | { 15 | "name": "basic-antd", 16 | "title": "基础 antd 组件" 17 | }, 18 | { 19 | "name": "custom-initialization", 20 | "title": "自定义初始化引擎" 21 | }, 22 | { 23 | "name": "node-extended-actions", 24 | "title": "扩展节点操作项" 25 | }, 26 | { 27 | "name": "next-pro", 28 | "title": "基于next实现的高级表单低代码物料" 29 | } 30 | ] 31 | -------------------------------------------------------------------------------- /packages/vue2-renderer/src/create-element/vue2-create-element.ts: -------------------------------------------------------------------------------- 1 | import { createElement } from 'react'; 2 | import { vueRendererExtTypes } from '@lowcodecloud/lowcode-engine-vue-renderer-core'; 3 | import Vue2ReactWrapper from './Vue2ReactWrapper'; 4 | 5 | class Vue2CreateElement implements vueRendererExtTypes.CreateElementAdapter { 6 | createElement(component: any, props: any, ...children: any): any { 7 | // TODO 处理 reactWrapper 8 | let $vueComponent = component; 9 | let newProps = { $vueComponent, ...props }; 10 | return createElement(Vue2ReactWrapper, newProps, ...children); 11 | } 12 | } 13 | 14 | export default new Vue2CreateElement().createElement; 15 | -------------------------------------------------------------------------------- /packages/vue3-renderer/src/create-element/vue3-create-element.ts: -------------------------------------------------------------------------------- 1 | import { createElement } from 'react'; 2 | import { vueRendererExtTypes } from '@lowcodecloud/lowcode-engine-vue-renderer-core'; 3 | import Vue3ReactWrapper from './Vue3ReactWrapper'; 4 | 5 | class Vue3CreateElement implements vueRendererExtTypes.CreateElementAdapter { 6 | createElement(component: any, props: any, ...children: any): any { 7 | // TODO 处理 reactWrapper 8 | let $vueComponent = component; 9 | let newProps = { $vueComponent, ...props }; 10 | return createElement(Vue3ReactWrapper, newProps, ...children); 11 | } 12 | } 13 | 14 | export default new Vue3CreateElement().createElement; 15 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/src/utils/misc.ts: -------------------------------------------------------------------------------- 1 | interface UtilsMetadata { 2 | name: string; 3 | npm: { 4 | package: string; 5 | version?: string; 6 | exportName: string; 7 | subName?: string; 8 | destructuring?: boolean; 9 | main?: string; 10 | }; 11 | } 12 | 13 | interface LibrayMap { 14 | [key: string]: string; 15 | } 16 | 17 | export function getProjectUtils(librayMap: LibrayMap, utilsMetadata: UtilsMetadata[]) { 18 | const projectUtils: { [packageName: string]: any } = {}; 19 | if (utilsMetadata) { 20 | utilsMetadata.forEach(meta => { 21 | if (librayMap[meta?.npm.package]) { 22 | const lib = window[librayMap[meta?.npm.package]]; 23 | } 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/src/utils/misc.ts: -------------------------------------------------------------------------------- 1 | interface UtilsMetadata { 2 | name: string; 3 | npm: { 4 | package: string; 5 | version?: string; 6 | exportName: string; 7 | subName?: string; 8 | destructuring?: boolean; 9 | main?: string; 10 | }; 11 | } 12 | 13 | interface LibrayMap { 14 | [key: string]: string; 15 | } 16 | 17 | export function getProjectUtils(librayMap: LibrayMap, utilsMetadata: UtilsMetadata[]) { 18 | const projectUtils: { [packageName: string]: any } = {}; 19 | if (utilsMetadata) { 20 | utilsMetadata.forEach(meta => { 21 | if (librayMap[meta?.npm.package]) { 22 | const lib = window[librayMap[meta?.npm.package]]; 23 | } 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/vue-renderer-core/src/utils/is-react.ts: -------------------------------------------------------------------------------- 1 | import { ComponentClass, Component, ComponentType } from 'react'; 2 | 3 | const hasSymbol = typeof Symbol === 'function' && Symbol.for; 4 | const REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0; 5 | 6 | export function isReactClass(obj: any): obj is ComponentClass { 7 | return obj && obj.prototype && (obj.prototype.isReactComponent || obj.prototype instanceof Component); 8 | } 9 | 10 | function isForwardRefType(obj: any): boolean { 11 | return obj?.$$typeof && obj?.$$typeof === REACT_FORWARD_REF_TYPE; 12 | } 13 | 14 | export function isReactComponent(obj: any): obj is ComponentType { 15 | return obj && (isReactClass(obj) || isForwardRefType(obj)); 16 | } 17 | -------------------------------------------------------------------------------- /scripts/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | pnpm --filter=@lowcodecloud/lowcode-engine-vue-renderer-core build 4 | 5 | pnpm --filter=@lowcodecloud/lowcode-engine-vue2-renderer build 6 | 7 | pnpm --filter=@lowcodecloud/lowcode-engine-vue2-simulator-renderer build 8 | pnpm --filter=@lowcodecloud/lowcode-engine-vue2-simulator-renderer build:umd 9 | 10 | cp -r packages/vue2-simulator-renderer/dist/* examples/lowcode-vue2-demo/public/simulator/ 11 | 12 | 13 | pnpm --filter=@lowcodecloud/lowcode-engine-vue3-renderer build 14 | 15 | pnpm --filter=@lowcodecloud/lowcode-engine-vue3-simulator-renderer build 16 | pnpm --filter=@lowcodecloud/lowcode-engine-vue3-simulator-renderer build:umd 17 | 18 | cp -r packages/vue3-simulator-renderer/dist/* examples/lowcode-vue3-demo/public/simulator/ 19 | 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LowCode Engine Vue Projects 2 | 3 | ## 介绍 4 | 5 | 本项目初衷是让 `lowcode-engine` 能够快速接入 `Vue` 生态。 6 | 7 | ## 主要实现 8 | 9 | > vue-renderer 10 | 11 | 复用了`react-renderer` 改造原理比较简单,主要涉及: 12 | - 资产包增加Vue组件识别能力构造具有组件标识的`component` 核心改造 `buildComponents`及资产包描述 13 | - `createElement` 根据组件标识(devStack) 选择 `React` 实现 或 `Vue` 实现 14 | 15 | `createElement` Vue 实现,基于 `vuereact-combined`、`veaury`。 16 | 17 | 由于 `vue2.x`、`vue3.x` 命名空间都是 `Vue` 所以他们不能同时并存。 18 | 19 | > vue-simulator-renderer 20 | 21 | 原理同上 22 | 23 | ## 快速开始 24 | 25 | ### 环境准备 26 | 27 | - nodejs >= 14 28 | - 安装 pnpm (比较快,而且省磁盘🏅) 29 | 30 | ### 安装依赖 31 | 32 | ```bash 33 | pnpm install 34 | ``` 35 | 36 | ### 构建 37 | 38 | ```bash 39 | pnpm build 40 | ``` 41 | 42 | ### 启动 43 | 44 | 默认启动 vue2 demo 45 | 46 | ```bash 47 | pnpm start 48 | ``` 49 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lowcodecloud/lowcode-engine-vue-projects", 3 | "version": "1.0.0", 4 | "description": "lowcode-engine-vue-projects", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "sh ./scripts/build.sh", 8 | "start": "pnpm start:vue3", 9 | "start:vue2": "pnpm --filter=@lowcodecloud/lowcode-vue2-demo start", 10 | "start:vue3": "pnpm --filter=@lowcodecloud/lowcode-vue3-demo start" 11 | }, 12 | "keywords": [ 13 | "lowcode", 14 | "lowcode-engin", 15 | "vue" 16 | ], 17 | "author": "qinning", 18 | "license": "MIT", 19 | "devDependencies": { 20 | "react": "^16", 21 | "react-dom": "^16.7.0", 22 | "vue": "^2.6.14", 23 | "f2elint": "^2.0.1", 24 | "typescript": "^4.5.5" 25 | }, 26 | "engines": { 27 | "node": ">=14.17.0 <16" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/README.md: -------------------------------------------------------------------------------- 1 | ## Low-Code Engine Demo 2 | 3 | 本 demo 是一个组合内核、setter、插件、物料的示范工程,因为未经长期生产环境打磨,可能还会有一些各个模块间结合的 bug,希望大家理解~ 4 | 5 | 场景列表: 6 | 7 | - [index](https://lowcode-engine.cn/demo/index.html) 8 | - [basic-fusion](https://lowcode-engine.cn/demo/basic-fusion.html)(此 fusion 的元数据描述是很老的版本,只为了示意描述结构,请勿用于生产环境) 9 | - [basic-antd](https://lowcode-engine.cn/demo/basic-antd.html) 10 | - [basic-fusion-with-single-component](https://lowcode-engine.cn/demo/basic-fusion-with-single-component.html) 11 | - [custom-initialization](https://lowcode-engine.cn/demo/custom-initialization.html) 12 | - [node-extended-actions](https://lowcode-engine.cn/demo/node-extended-actions.html) 13 | - [next-pro](https://lowcode-engine.cn/demo/next-pro.html) 14 | 15 | 更多参考资料: 16 | 17 | - [马上玩一下](https://lowcode-engine.cn/demo/index.html) 18 | - [低代码引擎官网](http://lowcode-engine.cn) 19 | - [引擎主包](https://github.com/alibaba/lowcode-engine) 20 | 21 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/README.md: -------------------------------------------------------------------------------- 1 | ## Low-Code Engine Demo 2 | 3 | 本 demo 是一个组合内核、setter、插件、物料的示范工程,因为未经长期生产环境打磨,可能还会有一些各个模块间结合的 bug,希望大家理解~ 4 | 5 | 场景列表: 6 | 7 | - [index](https://lowcode-engine.cn/demo/index.html) 8 | - [basic-fusion](https://lowcode-engine.cn/demo/basic-fusion.html)(此 fusion 的元数据描述是很老的版本,只为了示意描述结构,请勿用于生产环境) 9 | - [basic-antd](https://lowcode-engine.cn/demo/basic-antd.html) 10 | - [basic-fusion-with-single-component](https://lowcode-engine.cn/demo/basic-fusion-with-single-component.html) 11 | - [custom-initialization](https://lowcode-engine.cn/demo/custom-initialization.html) 12 | - [node-extended-actions](https://lowcode-engine.cn/demo/node-extended-actions.html) 13 | - [next-pro](https://lowcode-engine.cn/demo/next-pro.html) 14 | 15 | 更多参考资料: 16 | 17 | - [马上玩一下](https://lowcode-engine.cn/demo/index.html) 18 | - [低代码引擎官网](http://lowcode-engine.cn) 19 | - [引擎主包](https://github.com/alibaba/lowcode-engine) 20 | 21 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/test/src/renderer/__snapshots__/demo.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Base should be render NotFoundComponent 1`] = ` 4 |
8 |
11 |
14 | Component Not Found 15 |
16 |
17 |
18 | `; 19 | 20 | exports[`Base should be render Text 1`] = ` 21 |
25 |
28 |
37 | 我是一个简单的测试页面 38 |
39 |
40 |
41 | `; 42 | -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/test/src/renderer/__snapshots__/demo.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Base should be render NotFoundComponent 1`] = ` 4 |
8 |
11 |
14 | Component Not Found 15 |
16 |
17 |
18 | `; 19 | 20 | exports[`Base should be render Text 1`] = ` 21 |
25 |
28 |
37 | 我是一个简单的测试页面 38 |
39 |
40 |
41 | `; 42 | -------------------------------------------------------------------------------- /packages/vue-renderer-core/src/types/npm.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 组件开发技术栈 3 | */ 4 | export enum DevStack { 5 | React = 'react', 6 | Vue = 'vue', 7 | Vue2 = 'vue2', 8 | Vue3 = 'vue3', 9 | Mp = 'mp' 10 | } 11 | 12 | /** 13 | * Library -> Package 关系映射 14 | */ 15 | export interface LibraryPackageMapping { 16 | [key: string]: string; 17 | } 18 | 19 | /** 20 | * npm 源引入完整描述对象 21 | */ 22 | export interface NpmInfo { 23 | /** 24 | * 源码组件名称 25 | */ 26 | componentName?: string; 27 | /** 28 | * 源码组件库名 29 | */ 30 | package: string; 31 | /** 32 | * 源码组件版本号 33 | */ 34 | version?: string; 35 | /** 36 | * 是否解构 37 | */ 38 | destructuring?: boolean; 39 | /** 40 | * 源码组件名称 41 | */ 42 | exportName?: string; 43 | /** 44 | * 子组件名 45 | */ 46 | subName?: string; 47 | /** 48 | * 组件路径 49 | */ 50 | main?: string; 51 | 52 | /** 53 | * 组件技术栈 54 | */ 55 | devStack?: DevStack | string | undefined; 56 | } 57 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/build.umd.json: -------------------------------------------------------------------------------- 1 | { 2 | "entry": { 3 | "vue2-simulator-renderer": "src/index" 4 | }, 5 | "sourceMap": true, 6 | "library": "___Vue2SimulatorRenderer___", 7 | "libraryTarget": "umd", 8 | "externals": { 9 | "react": "var window.React", 10 | "react-dom": "var window.ReactDOM", 11 | "prop-types": "var window.PropTypes", 12 | "@alifd/next": "var Next", 13 | "@alilc/lowcode-engine-ext": "var window.AliLowCodeEngineExt", 14 | "moment": "var moment", 15 | "lodash": "var _", 16 | "vue": "var window.Vue" 17 | }, 18 | "polyfill": false, 19 | "outputDir": "dist", 20 | "vendor": false, 21 | "ignoreHtmlTemplate": true, 22 | "plugins": [ 23 | "build-plugin-react-app", 24 | [ 25 | "build-plugin-fusion", 26 | { 27 | "externalNext": "umd" 28 | } 29 | ], 30 | [ 31 | "build-plugin-moment-locales", 32 | { 33 | "locales": ["zh-cn"] 34 | } 35 | ], 36 | "./build.plugin.js" 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/build.umd.json: -------------------------------------------------------------------------------- 1 | { 2 | "entry": { 3 | "vue3-simulator-renderer": "src/index" 4 | }, 5 | "sourceMap": true, 6 | "library": "___Vue3SimulatorRenderer___", 7 | "libraryTarget": "umd", 8 | "externals": { 9 | "react": "var window.React", 10 | "react-dom": "var window.ReactDOM", 11 | "prop-types": "var window.PropTypes", 12 | "@alifd/next": "var Next", 13 | "@alilc/lowcode-engine-ext": "var window.AliLowCodeEngineExt", 14 | "moment": "var moment", 15 | "lodash": "var _", 16 | "vue": "var window.Vue" 17 | }, 18 | "polyfill": false, 19 | "outputDir": "dist", 20 | "vendor": false, 21 | "ignoreHtmlTemplate": true, 22 | "plugins": [ 23 | "build-plugin-react-app", 24 | [ 25 | "build-plugin-fusion", 26 | { 27 | "externalNext": "umd" 28 | } 29 | ], 30 | [ 31 | "build-plugin-moment-locales", 32 | { 33 | "locales": ["zh-cn"] 34 | } 35 | ], 36 | "./build.plugin.js" 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/test/src/renderer/demo.test.tsx: -------------------------------------------------------------------------------- 1 | import renderer from 'react-test-renderer'; 2 | import rendererContainer from '../../../src/renderer'; 3 | import SimulatorRendererView from '../../../src/renderer-view'; 4 | import { Text } from '../../utils/components'; 5 | 6 | describe('Base', () => { 7 | const component = renderer.create( 8 | 11 | ); 12 | 13 | it('should be render NotFoundComponent', () => { 14 | let tree = component.toJSON(); 15 | expect(tree).toMatchSnapshot(); 16 | }); 17 | 18 | it('should be render Text', () => { 19 | // 更新 _componentsMap 值 20 | (rendererContainer as any)._componentsMap.Text = Text;// = host.designer.componentsMap; 21 | // 更新 components 列表 22 | (rendererContainer as any).buildComponents(); 23 | 24 | expect(!!(rendererContainer.components as any).Text).toBeTruthy(); 25 | 26 | rendererContainer.rerender(); 27 | 28 | let tree = component.toJSON(); 29 | expect(tree).toMatchSnapshot(); 30 | }); 31 | }) -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/test/src/renderer/demo.test.tsx: -------------------------------------------------------------------------------- 1 | import renderer from 'react-test-renderer'; 2 | import rendererContainer from '../../../src/renderer'; 3 | import SimulatorRendererView from '../../../src/renderer-view'; 4 | import { Text } from '../../utils/components'; 5 | 6 | describe('Base', () => { 7 | const component = renderer.create( 8 | 11 | ); 12 | 13 | it('should be render NotFoundComponent', () => { 14 | let tree = component.toJSON(); 15 | expect(tree).toMatchSnapshot(); 16 | }); 17 | 18 | it('should be render Text', () => { 19 | // 更新 _componentsMap 值 20 | (rendererContainer as any)._componentsMap.Text = Text;// = host.designer.componentsMap; 21 | // 更新 components 列表 22 | (rendererContainer as any).buildComponents(); 23 | 24 | expect(!!(rendererContainer.components as any).Text).toBeTruthy(); 25 | 26 | rendererContainer.rerender(); 27 | 28 | let tree = component.toJSON(); 29 | expect(tree).toMatchSnapshot(); 30 | }); 31 | }) -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/src/setters/behavior-setter.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import BehaviorSetter from '@alilc/lowcode-setter-behavior'; 3 | 4 | 5 | const defaultExtraBehaviorActions: any[] = []; 6 | class LocalBehaviorSetter extends React.Component { 7 | render() { 8 | // ignore url && responseFormatter props, use default ones 9 | const { url: propsUrl, responseFormatter: propsFormatter, extraBehaviorActions: propsExtraBehaviorActions = [], ...otherProps } = this.props; 10 | const url = 'https://hn.algolia.com/api/v1/search?query'; 11 | const responseFormatter = (response) => response.hits.map((item) => ({ 12 | label: item.title, 13 | value: item.author 14 | })); 15 | const extraBehaviorActions = propsExtraBehaviorActions.concat(defaultExtraBehaviorActions); 16 | return ( 17 | 23 | ); 24 | } 25 | } 26 | 27 | export default LocalBehaviorSetter; -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/src/setters/behavior-setter.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import BehaviorSetter from '@alilc/lowcode-setter-behavior'; 3 | 4 | 5 | const defaultExtraBehaviorActions: any[] = []; 6 | class LocalBehaviorSetter extends React.Component { 7 | render() { 8 | // ignore url && responseFormatter props, use default ones 9 | const { url: propsUrl, responseFormatter: propsFormatter, extraBehaviorActions: propsExtraBehaviorActions = [], ...otherProps } = this.props; 10 | const url = 'https://hn.algolia.com/api/v1/search?query'; 11 | const responseFormatter = (response) => response.hits.map((item) => ({ 12 | label: item.title, 13 | value: item.author 14 | })); 15 | const extraBehaviorActions = propsExtraBehaviorActions.concat(defaultExtraBehaviorActions); 16 | return ( 17 | 23 | ); 24 | } 25 | } 26 | 27 | export default LocalBehaviorSetter; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 LowCodeCloud 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Alibaba 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Alibaba 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/jest.config.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const { join } = require('path'); 3 | const esModules = ['zen-logger'].join('|'); 4 | const pkgNames = fs.readdirSync(join('..')).filter(pkgName => !pkgName.startsWith('.')); 5 | 6 | const jestConfig = { 7 | // transform: { 8 | // '^.+\\.[jt]sx?$': 'babel-jest', 9 | // // '^.+\\.(ts|tsx)$': 'ts-jest', 10 | // // '^.+\\.(js|jsx)$': 'babel-jest', 11 | // }, 12 | // testMatch: ['**/document/node/node.test.ts'], 13 | // testMatch: ['**/designer/builtin-hotkey.test.ts'], 14 | // testMatch: ['**/plugin/plugin-manager.test.ts'], 15 | // testMatch: ['(/tests?/.*(test))\\.[jt]s$'], 16 | transformIgnorePatterns: [ 17 | `/node_modules/(?!${esModules})/`, 18 | ], 19 | setupFiles: ['./test/utils/host.ts'], 20 | moduleFileExtensions: ['ts', 'tsx', 'js', 'json'], 21 | collectCoverage: true, 22 | collectCoverageFrom: [ 23 | 'src/**/*.ts', 24 | '!src/**/*.d.ts', 25 | '!**/node_modules/**', 26 | ], 27 | }; 28 | 29 | // 只对本仓库内的 pkg 做 mapping 30 | jestConfig.moduleNameMapper = {}; 31 | jestConfig.moduleNameMapper[`^@alilc/lowcode\\-(${pkgNames.join('|')})$`] = '/../$1/src'; 32 | 33 | module.exports = jestConfig; -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/jest.config.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const { join } = require('path'); 3 | const esModules = ['zen-logger'].join('|'); 4 | const pkgNames = fs.readdirSync(join('..')).filter(pkgName => !pkgName.startsWith('.')); 5 | 6 | const jestConfig = { 7 | // transform: { 8 | // '^.+\\.[jt]sx?$': 'babel-jest', 9 | // // '^.+\\.(ts|tsx)$': 'ts-jest', 10 | // // '^.+\\.(js|jsx)$': 'babel-jest', 11 | // }, 12 | // testMatch: ['**/document/node/node.test.ts'], 13 | // testMatch: ['**/designer/builtin-hotkey.test.ts'], 14 | // testMatch: ['**/plugin/plugin-manager.test.ts'], 15 | // testMatch: ['(/tests?/.*(test))\\.[jt]s$'], 16 | transformIgnorePatterns: [ 17 | `/node_modules/(?!${esModules})/`, 18 | ], 19 | setupFiles: ['./test/utils/host.ts'], 20 | moduleFileExtensions: ['ts', 'tsx', 'js', 'json'], 21 | collectCoverage: true, 22 | collectCoverageFrom: [ 23 | 'src/**/*.ts', 24 | '!src/**/*.d.ts', 25 | '!**/node_modules/**', 26 | ], 27 | }; 28 | 29 | // 只对本仓库内的 pkg 做 mapping 30 | jestConfig.moduleNameMapper = {}; 31 | jestConfig.moduleNameMapper[`^@alilc/lowcode\\-(${pkgNames.join('|')})$`] = '/../$1/src'; 32 | 33 | module.exports = jestConfig; -------------------------------------------------------------------------------- /packages/vue-renderer-core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lowcodecloud/lowcode-engine-vue-renderer-core", 3 | "version": "1.0.0", 4 | "description": "lowcode-engine-vue-renderer-core", 5 | "main": "lib/index.js", 6 | "module": "es/index.js", 7 | "files": [ 8 | "lib", 9 | "es", 10 | "dist" 11 | ], 12 | "scripts": { 13 | "build": "build-scripts build --skip-demo" 14 | }, 15 | "keywords": [ 16 | "lowcode", 17 | "engine", 18 | "vue" 19 | ], 20 | "dependencies": { 21 | "@alifd/next": "^1.21.16", 22 | "@alilc/lowcode-renderer-core": "^1.0.9", 23 | "@alilc/lowcode-types": "^1.0.9", 24 | "@alilc/lowcode-utils": "^1.0.9", 25 | "react": "^16" 26 | }, 27 | "devDependencies": { 28 | "@alib/build-scripts": "^0.1.18", 29 | "@types/node": "^13.7.1", 30 | "@types/react": "^16", 31 | "@types/react-dom": "^16", 32 | "@types/react-router": "^5.1.17", 33 | "build-plugin-component": "^0.2.10", 34 | "react-test-renderer": "^16" 35 | }, 36 | "publishConfig": { 37 | "access": "public", 38 | "registry": "https://registry.npmjs.org/" 39 | }, 40 | "repository": { 41 | "type": "http", 42 | "url": "https://github.com/lowcodecloud" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/build.json: -------------------------------------------------------------------------------- 1 | { 2 | "entry": { 3 | "preview": "./src/preview.tsx" 4 | }, 5 | "vendor": false, 6 | "devServer": { 7 | "hot": false 8 | }, 9 | "publicPath": "/", 10 | "externals": { 11 | "react": "var window.React", 12 | "react-dom": "var window.ReactDOM", 13 | "prop-types": "var window.PropTypes", 14 | "@alifd/next": "var window.Next", 15 | "@alilc/lowcode-engine": "var window.AliLowCodeEngine", 16 | "@alilc/lowcode-editor-core": "var window.AliLowCodeEngine.common.editorCabin", 17 | "@alilc/lowcode-editor-skeleton": "var window.AliLowCodeEngine.common.skeletonCabin", 18 | "@alilc/lowcode-designer": "var window.AliLowCodeEngine.common.designerCabin", 19 | "@alilc/lowcode-engine-ext": "var window.AliLowCodeEngineExt", 20 | "@ali/lowcode-engine": "var window.AliLowCodeEngine", 21 | "moment": "var window.moment", 22 | "lodash": "var window._", 23 | "vue": "var window.Vue" 24 | }, 25 | "plugins": [ 26 | [ 27 | "build-plugin-react-app" 28 | ], 29 | [ 30 | "build-plugin-moment-locales", 31 | { 32 | "locales": [ 33 | "zh-cn" 34 | ] 35 | } 36 | ], 37 | "./build.plugin.js" 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/build.json: -------------------------------------------------------------------------------- 1 | { 2 | "entry": { 3 | "preview": "./src/preview.tsx" 4 | }, 5 | "vendor": false, 6 | "devServer": { 7 | "hot": false 8 | }, 9 | "publicPath": "/", 10 | "externals": { 11 | "react": "var window.React", 12 | "react-dom": "var window.ReactDOM", 13 | "prop-types": "var window.PropTypes", 14 | "@alifd/next": "var window.Next", 15 | "@alilc/lowcode-engine": "var window.AliLowCodeEngine", 16 | "@alilc/lowcode-editor-core": "var window.AliLowCodeEngine.common.editorCabin", 17 | "@alilc/lowcode-editor-skeleton": "var window.AliLowCodeEngine.common.skeletonCabin", 18 | "@alilc/lowcode-designer": "var window.AliLowCodeEngine.common.designerCabin", 19 | "@alilc/lowcode-engine-ext": "var window.AliLowCodeEngineExt", 20 | "@ali/lowcode-engine": "var window.AliLowCodeEngine", 21 | "moment": "var window.moment", 22 | "lodash": "var window._", 23 | "vue": "var window.Vue" 24 | }, 25 | "plugins": [ 26 | [ 27 | "build-plugin-react-app" 28 | ], 29 | [ 30 | "build-plugin-moment-locales", 31 | { 32 | "locales": [ 33 | "zh-cn" 34 | ] 35 | } 36 | ], 37 | "./build.plugin.js" 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/src/universal/global.scss: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: PingFangSC-Regular, Roboto, Helvetica Neue, Helvetica, Tahoma, Arial, PingFang SC-Light, Microsoft YaHei; 3 | font-size: 12px; 4 | * { 5 | box-sizing: border-box; 6 | } 7 | } 8 | 9 | body, #lce-container { 10 | position: fixed; 11 | left: 0; 12 | right: 0; 13 | bottom: 0; 14 | top: 0; 15 | box-sizing: border-box; 16 | padding: 0; 17 | margin: 0; 18 | overflow: hidden; 19 | text-rendering: optimizeLegibility; 20 | -webkit-user-select: none; 21 | -webkit-user-drag: none; 22 | -webkit-text-size-adjust: none; 23 | -webkit-touch-callout: none; 24 | -webkit-font-smoothing: antialiased; 25 | #engine { 26 | width: 100%; 27 | height: 100%; 28 | } 29 | } 30 | 31 | html { 32 | min-width: 1024px; 33 | } 34 | 35 | .save-sample { 36 | width: 80px; 37 | height: 30px; 38 | background-color: #5584FF; 39 | border: none; 40 | outline: none; 41 | border-radius: 4px; 42 | color: white; 43 | cursor: pointer; 44 | } 45 | 46 | .load-assets { 47 | width: 100px; 48 | height: 30px; 49 | background-color: #5584FF; 50 | border: none; 51 | outline: none; 52 | border-radius: 4px; 53 | color: white; 54 | cursor: pointer; 55 | } 56 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/src/universal/global.scss: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: PingFangSC-Regular, Roboto, Helvetica Neue, Helvetica, Tahoma, Arial, PingFang SC-Light, Microsoft YaHei; 3 | font-size: 12px; 4 | * { 5 | box-sizing: border-box; 6 | } 7 | } 8 | 9 | body, #lce-container { 10 | position: fixed; 11 | left: 0; 12 | right: 0; 13 | bottom: 0; 14 | top: 0; 15 | box-sizing: border-box; 16 | padding: 0; 17 | margin: 0; 18 | overflow: hidden; 19 | text-rendering: optimizeLegibility; 20 | -webkit-user-select: none; 21 | -webkit-user-drag: none; 22 | -webkit-text-size-adjust: none; 23 | -webkit-touch-callout: none; 24 | -webkit-font-smoothing: antialiased; 25 | #engine { 26 | width: 100%; 27 | height: 100%; 28 | } 29 | } 30 | 31 | html { 32 | min-width: 1024px; 33 | } 34 | 35 | .save-sample { 36 | width: 80px; 37 | height: 30px; 38 | background-color: #5584FF; 39 | border: none; 40 | outline: none; 41 | border-radius: 4px; 42 | color: white; 43 | cursor: pointer; 44 | } 45 | 46 | .load-assets { 47 | width: 100px; 48 | height: 30px; 49 | background-color: #5584FF; 50 | border: none; 51 | outline: none; 52 | border-radius: 4px; 53 | color: white; 54 | cursor: pointer; 55 | } 56 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/src/utils/react-find-dom-nodes.ts: -------------------------------------------------------------------------------- 1 | import { ReactInstance } from 'react'; 2 | import { findDOMNode } from 'react-dom'; 3 | import { isElement } from '@alilc/lowcode-utils'; 4 | import { isDOMNode } from './is-dom-node'; 5 | 6 | export const FIBER_KEY = '_reactInternalFiber'; 7 | 8 | function elementsFromFiber(fiber: any, elements: Array) { 9 | if (fiber) { 10 | if (fiber.stateNode && isDOMNode(fiber.stateNode)) { 11 | elements.push(fiber.stateNode); 12 | } else if (fiber.child) { 13 | // deep fiberNode.child 14 | elementsFromFiber(fiber.child, elements); 15 | } 16 | 17 | if (fiber.sibling) { 18 | elementsFromFiber(fiber.sibling, elements); 19 | } 20 | } 21 | } 22 | 23 | export function reactFindDOMNodes(elem: ReactInstance | null): Array | null { 24 | if (!elem) { 25 | return null; 26 | } 27 | if (isElement(elem)) { 28 | return [elem]; 29 | } 30 | const elements: Array = []; 31 | const fiberNode = (elem as any)[FIBER_KEY]; 32 | elementsFromFiber(fiberNode?.child, elements); 33 | if (elements.length > 0) return elements; 34 | try { 35 | return [findDOMNode(elem)]; 36 | } catch (e) { 37 | return null; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/src/utils/react-find-dom-nodes.ts: -------------------------------------------------------------------------------- 1 | import { ReactInstance } from 'react'; 2 | import { findDOMNode } from 'react-dom'; 3 | import { isElement } from '@alilc/lowcode-utils'; 4 | import { isDOMNode } from './is-dom-node'; 5 | 6 | export const FIBER_KEY = '_reactInternalFiber'; 7 | 8 | function elementsFromFiber(fiber: any, elements: Array) { 9 | if (fiber) { 10 | if (fiber.stateNode && isDOMNode(fiber.stateNode)) { 11 | elements.push(fiber.stateNode); 12 | } else if (fiber.child) { 13 | // deep fiberNode.child 14 | elementsFromFiber(fiber.child, elements); 15 | } 16 | 17 | if (fiber.sibling) { 18 | elementsFromFiber(fiber.sibling, elements); 19 | } 20 | } 21 | } 22 | 23 | export function reactFindDOMNodes(elem: ReactInstance | null): Array | null { 24 | if (!elem) { 25 | return null; 26 | } 27 | if (isElement(elem)) { 28 | return [elem]; 29 | } 30 | const elements: Array = []; 31 | const fiberNode = (elem as any)[FIBER_KEY]; 32 | elementsFromFiber(fiberNode?.child, elements); 33 | if (elements.length > 0) return elements; 34 | try { 35 | return [findDOMNode(elem)]; 36 | } catch (e) { 37 | return null; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/public/preview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 阿里低代码引擎 Demo - 预览页 7 | 8 | 9 | 10 | 11 |
12 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/public/preview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 阿里低代码引擎 Demo - 预览页 7 | 8 | 9 | 10 | 11 |
12 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/src/scenarios/index/index.ts: -------------------------------------------------------------------------------- 1 | import { init, plugins } from '@alilc/lowcode-engine'; 2 | import { createFetchHandler } from '@alilc/lowcode-datasource-fetch-handler'; 3 | import registerPlugins from '../../universal/plugin'; 4 | import { scenarioSwitcher } from '../../sample-plugins/scenario-switcher'; 5 | import '../../universal/global.scss'; 6 | 7 | const preference = new Map(); 8 | preference.set('DataSourcePane', { 9 | importPlugins: [], 10 | dataSourceTypes: [ 11 | { 12 | type: 'fetch', 13 | }, 14 | { 15 | type: 'jsonp', 16 | }, 17 | ], 18 | }); 19 | 20 | (async function main() { 21 | await plugins.register(scenarioSwitcher); 22 | await registerPlugins(); 23 | 24 | init(document.getElementById('lce-container')!, { 25 | // designMode: 'live', 26 | // locale: 'zh-CN', 27 | enableCondition: true, 28 | enableCanvasLock: true, 29 | // 默认绑定变量 30 | supportVariableGlobally: true, 31 | // simulatorUrl 在当 engine-core.js 同一个父路径下时是不需要配置的!!! 32 | // 这里因为用的是 alifd cdn,在不同 npm 包,engine-core.js 和 react-simulator-renderer.js 是不同路径 33 | simulatorUrl: [ 34 | './simulator/css/vue2-simulator-renderer.css', 35 | './simulator/js/vue2-simulator-renderer.js', 36 | ], 37 | requestHandlersMap: { 38 | fetch: createFetchHandler(), 39 | }, 40 | }, preference); 41 | })(); 42 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/src/scenarios/index/index.ts: -------------------------------------------------------------------------------- 1 | import { init, plugins } from '@alilc/lowcode-engine'; 2 | import { createFetchHandler } from '@alilc/lowcode-datasource-fetch-handler'; 3 | import registerPlugins from '../../universal/plugin'; 4 | import { scenarioSwitcher } from '../../sample-plugins/scenario-switcher'; 5 | import '../../universal/global.scss'; 6 | 7 | const preference = new Map(); 8 | preference.set('DataSourcePane', { 9 | importPlugins: [], 10 | dataSourceTypes: [ 11 | { 12 | type: 'fetch', 13 | }, 14 | { 15 | type: 'jsonp', 16 | }, 17 | ], 18 | }); 19 | 20 | (async function main() { 21 | await plugins.register(scenarioSwitcher); 22 | await registerPlugins(); 23 | 24 | init(document.getElementById('lce-container')!, { 25 | // designMode: 'live', 26 | // locale: 'zh-CN', 27 | enableCondition: true, 28 | enableCanvasLock: true, 29 | // 默认绑定变量 30 | supportVariableGlobally: true, 31 | // simulatorUrl 在当 engine-core.js 同一个父路径下时是不需要配置的!!! 32 | // 这里因为用的是 alifd cdn,在不同 npm 包,engine-core.js 和 react-simulator-renderer.js 是不同路径 33 | simulatorUrl: [ 34 | './simulator/css/vue3-simulator-renderer.css', 35 | './simulator/js/vue3-simulator-renderer.js', 36 | ], 37 | requestHandlersMap: { 38 | fetch: createFetchHandler(), 39 | }, 40 | }, preference); 41 | })(); 42 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/src/sample-plugins/scenario-switcher/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | ILowCodePluginContext, 4 | } from '@alilc/lowcode-engine'; 5 | import { Select } from '@alifd/next'; 6 | import scenarios from '../../universal/scenarios.json'; 7 | const { Option } = Select; 8 | 9 | const getCurrentScenarioName = () => { 10 | // return 'index' 11 | const list = location.href.split('/'); 12 | return list[list.length - 1].replace('.html', ''); 13 | } 14 | 15 | function Switcher(props: any) { 16 | return () 26 | } 27 | 28 | export const scenarioSwitcher = (ctx: ILowCodePluginContext) => { 29 | return { 30 | name: 'scenarioSwitcher', 31 | async init() { 32 | const { skeleton } = ctx; 33 | 34 | skeleton.add({ 35 | name: 'scenarioSwitcher', 36 | area: 'topArea', 37 | type: 'Widget', 38 | props: { 39 | align: 'right', 40 | width: 80, 41 | }, 42 | content: Switcher, 43 | }); 44 | }, 45 | }; 46 | }; 47 | scenarioSwitcher.pluginName = 'scenarioSwitcher'; -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/src/sample-plugins/scenario-switcher/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | ILowCodePluginContext, 4 | } from '@alilc/lowcode-engine'; 5 | import { Select } from '@alifd/next'; 6 | import scenarios from '../../universal/scenarios.json'; 7 | const { Option } = Select; 8 | 9 | const getCurrentScenarioName = () => { 10 | // return 'index' 11 | const list = location.href.split('/'); 12 | return list[list.length - 1].replace('.html', ''); 13 | } 14 | 15 | function Switcher(props: any) { 16 | return () 26 | } 27 | 28 | export const scenarioSwitcher = (ctx: ILowCodePluginContext) => { 29 | return { 30 | name: 'scenarioSwitcher', 31 | async init() { 32 | const { skeleton } = ctx; 33 | 34 | skeleton.add({ 35 | name: 'scenarioSwitcher', 36 | area: 'topArea', 37 | type: 'Widget', 38 | props: { 39 | align: 'right', 40 | width: 80, 41 | }, 42 | content: Switcher, 43 | }); 44 | }, 45 | }; 46 | }; 47 | scenarioSwitcher.pluginName = 'scenarioSwitcher'; -------------------------------------------------------------------------------- /packages/vue3-renderer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lowcodecloud/lowcode-engine-vue3-renderer", 3 | "version": "1.0.0", 4 | "description": "lowcode-engine-vue3-renderer", 5 | "main": "lib/index.js", 6 | "module": "es/index.js", 7 | "files": [ 8 | "lib", 9 | "es", 10 | "dist" 11 | ], 12 | "scripts": { 13 | "start": "build-scripts start", 14 | "build": "build-scripts build --skip-demo", 15 | "build:umd": "build-scripts build --config build.umd.json" 16 | }, 17 | "keywords": [ 18 | "lowcode", 19 | "engine", 20 | "vue" 21 | ], 22 | "dependencies": { 23 | "@alifd/next": "^1.19.17", 24 | "@alilc/lowcode-renderer-core": "^1.0.9", 25 | "@alilc/lowcode-types": "^1.0.9", 26 | "@alilc/lowcode-utils": "^1.0.9", 27 | "@lowcodecloud/lowcode-engine-vue-renderer-core": "1.0.0", 28 | "react": "^16", 29 | "react-dom": "^16", 30 | "veaury": "^2.0.1", 31 | "vue": "^3.2.37", 32 | "moment": "^2.24.0" 33 | }, 34 | "devDependencies": { 35 | "@alib/build-scripts": "^0.1.18", 36 | "@babel/runtime": "^7.18.3", 37 | "@types/node": "^13.7.1", 38 | "@types/react": "^16", 39 | "@types/react-dom": "^16", 40 | "build-plugin-component": "^0.2.10", 41 | "build-plugin-fusion": "^0.1.0", 42 | "build-plugin-moment-locales": "^0.1.0", 43 | "react-test-renderer": "^16" 44 | }, 45 | "publishConfig": { 46 | "access": "public", 47 | "registry": "https://registry.npmjs.org/" 48 | }, 49 | "repository": { 50 | "type": "http", 51 | "url": "https://github.com/lowcodecloud" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/test/utils/host.ts: -------------------------------------------------------------------------------- 1 | import { Box, Breadcrumb, Form, Select, Input, Button, Table, Pagination, Dialog } from '@alifd/next'; 2 | import defaultSchema from '../schema/basic'; 3 | import { Page } from './components'; 4 | 5 | class Designer { 6 | componentsMap = { 7 | Box, 8 | Breadcrumb, 9 | 'Breadcrumb.Item': Breadcrumb.Item, 10 | Form, 11 | 'Form.Item': Form.Item, 12 | Select, 13 | Input, 14 | Button, 15 | 'Button.Group': Button.Group, 16 | Table, 17 | Pagination, 18 | Dialog, 19 | Page, 20 | } 21 | } 22 | 23 | class Host { 24 | designer = new Designer(); 25 | 26 | connect = () => {} 27 | 28 | autorun = (fn: Function) => { 29 | fn(); 30 | } 31 | 32 | autoRender = true; 33 | 34 | componentsConsumer = { 35 | consume() {} 36 | } 37 | 38 | schema = defaultSchema; 39 | 40 | project = { 41 | documents: [ 42 | { 43 | id: '1', 44 | path: '/', 45 | fileName: '', 46 | export: () => { 47 | return this.schema; 48 | }, 49 | getNode: () => {}, 50 | } 51 | ], 52 | get: () => ({}), 53 | } 54 | 55 | setInstance() {} 56 | 57 | designMode = 'design' 58 | 59 | get() {} 60 | 61 | injectionConsumer = { 62 | consume() {} 63 | } 64 | 65 | /** 下列的函数或者方法是方便测试用 */ 66 | mockSchema = (schema: any) => { 67 | this.schema = schema; 68 | }; 69 | } 70 | 71 | if (!(window as any).LCSimulatorHost) { 72 | (window as any).LCSimulatorHost = new Host(); 73 | } 74 | 75 | export default (window as any).LCSimulatorHost; -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/test/utils/host.ts: -------------------------------------------------------------------------------- 1 | import { Box, Breadcrumb, Form, Select, Input, Button, Table, Pagination, Dialog } from '@alifd/next'; 2 | import defaultSchema from '../schema/basic'; 3 | import { Page } from './components'; 4 | 5 | class Designer { 6 | componentsMap = { 7 | Box, 8 | Breadcrumb, 9 | 'Breadcrumb.Item': Breadcrumb.Item, 10 | Form, 11 | 'Form.Item': Form.Item, 12 | Select, 13 | Input, 14 | Button, 15 | 'Button.Group': Button.Group, 16 | Table, 17 | Pagination, 18 | Dialog, 19 | Page, 20 | } 21 | } 22 | 23 | class Host { 24 | designer = new Designer(); 25 | 26 | connect = () => {} 27 | 28 | autorun = (fn: Function) => { 29 | fn(); 30 | } 31 | 32 | autoRender = true; 33 | 34 | componentsConsumer = { 35 | consume() {} 36 | } 37 | 38 | schema = defaultSchema; 39 | 40 | project = { 41 | documents: [ 42 | { 43 | id: '1', 44 | path: '/', 45 | fileName: '', 46 | export: () => { 47 | return this.schema; 48 | }, 49 | getNode: () => {}, 50 | } 51 | ], 52 | get: () => ({}), 53 | } 54 | 55 | setInstance() {} 56 | 57 | designMode = 'design' 58 | 59 | get() {} 60 | 61 | injectionConsumer = { 62 | consume() {} 63 | } 64 | 65 | /** 下列的函数或者方法是方便测试用 */ 66 | mockSchema = (schema: any) => { 67 | this.schema = schema; 68 | }; 69 | } 70 | 71 | if (!(window as any).LCSimulatorHost) { 72 | (window as any).LCSimulatorHost = new Host(); 73 | } 74 | 75 | export default (window as any).LCSimulatorHost; -------------------------------------------------------------------------------- /packages/vue2-renderer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lowcodecloud/lowcode-engine-vue2-renderer", 3 | "version": "1.0.0", 4 | "description": "lowcode-engine-vue2-renderer", 5 | "main": "lib/index.js", 6 | "module": "es/index.js", 7 | "files": [ 8 | "lib", 9 | "es", 10 | "dist" 11 | ], 12 | "scripts": { 13 | "start": "build-scripts start", 14 | "build": "build-scripts build --skip-demo", 15 | "build:umd": "build-scripts build --config build.umd.json" 16 | }, 17 | "keywords": [ 18 | "lowcode", 19 | "engine", 20 | "vue" 21 | ], 22 | "dependencies": { 23 | "@alifd/next": "^1.19.17", 24 | "@alilc/lowcode-renderer-core": "^1.0.9", 25 | "@alilc/lowcode-types": "^1.0.9", 26 | "@alilc/lowcode-utils": "^1.0.9", 27 | "@lowcodecloud/lowcode-engine-vue-renderer-core": "1.0.0", 28 | "react": "^16", 29 | "react-dom": "^16", 30 | "vuereact-combined": "^1.2.5", 31 | "moment": "^2.24.0", 32 | "vue": "^2.6.0" 33 | }, 34 | "devDependencies": { 35 | "@alib/build-scripts": "^0.1.18", 36 | "@babel/runtime": "^7.18.3", 37 | "@types/node": "^13.7.1", 38 | "@types/react": "^16", 39 | "@types/react-dom": "^16", 40 | "build-plugin-component": "^0.2.10", 41 | "build-plugin-fusion": "^0.1.0", 42 | "build-plugin-moment-locales": "^0.1.0", 43 | "react-test-renderer": "^16" 44 | }, 45 | "publishConfig": { 46 | "access": "public", 47 | "registry": "https://registry.npmjs.org/" 48 | }, 49 | "repository": { 50 | "type": "http", 51 | "url": "https://github.com/lowcodecloud" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/src/builtin-components/slot.tsx: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | 3 | class Slot extends Component { 4 | static displayName = 'Slot'; 5 | 6 | static componentMetadata = { 7 | componentName: 'Slot', 8 | configure: { 9 | props: [ 10 | { 11 | name: '___title', 12 | title: { 13 | type: 'i18n', 14 | 'en-US': 'Slot Title', 15 | 'zh-CN': '插槽标题', 16 | }, 17 | setter: 'StringSetter', 18 | defaultValue: '插槽容器', 19 | }, 20 | { 21 | name: '___params', 22 | title: { 23 | type: 'i18n', 24 | 'en-US': 'Slot Params', 25 | 'zh-CN': '插槽入参', 26 | }, 27 | setter: { 28 | componentName: 'ArraySetter', 29 | props: { 30 | itemSetter: { 31 | componentName: 'StringSetter', 32 | props: { 33 | placeholder: { 34 | type: 'i18n', 35 | 'zh-CN': '参数名称', 36 | 'en-US': 'Argument Name', 37 | }, 38 | }, 39 | }, 40 | }, 41 | }, 42 | }, 43 | ], 44 | component: { 45 | isContainer: true, 46 | }, 47 | // events/className/style/general/directives 48 | supports: false, 49 | }, 50 | }; 51 | 52 | render() { 53 | const { children } = this.props; 54 | return
{children}
; 55 | } 56 | } 57 | 58 | export default Slot; 59 | -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/src/builtin-components/slot.tsx: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | 3 | class Slot extends Component { 4 | static displayName = 'Slot'; 5 | 6 | static componentMetadata = { 7 | componentName: 'Slot', 8 | configure: { 9 | props: [ 10 | { 11 | name: '___title', 12 | title: { 13 | type: 'i18n', 14 | 'en-US': 'Slot Title', 15 | 'zh-CN': '插槽标题', 16 | }, 17 | setter: 'StringSetter', 18 | defaultValue: '插槽容器', 19 | }, 20 | { 21 | name: '___params', 22 | title: { 23 | type: 'i18n', 24 | 'en-US': 'Slot Params', 25 | 'zh-CN': '插槽入参', 26 | }, 27 | setter: { 28 | componentName: 'ArraySetter', 29 | props: { 30 | itemSetter: { 31 | componentName: 'StringSetter', 32 | props: { 33 | placeholder: { 34 | type: 'i18n', 35 | 'zh-CN': '参数名称', 36 | 'en-US': 'Argument Name', 37 | }, 38 | }, 39 | }, 40 | }, 41 | }, 42 | }, 43 | ], 44 | component: { 45 | isContainer: true, 46 | }, 47 | // events/className/style/general/directives 48 | supports: false, 49 | }, 50 | }; 51 | 52 | render() { 53 | const { children } = this.props; 54 | return
{children}
; 55 | } 56 | } 57 | 58 | export default Slot; 59 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: 'eslint-config-ali/typescript/react', 3 | parserOptions: { 4 | project: [], // for lint performance 5 | createDefaultProgram: false, // for lint performance 6 | }, 7 | rules: { 8 | 'react/no-multi-comp': 0, 9 | 'no-unused-expressions': 0, 10 | 'implicit-arrow-linebreak': 1, 11 | 'no-nested-ternary': 1, 12 | 'no-mixed-operators': 1, 13 | '@typescript-eslint/ban-types': 1, 14 | 'no-shadow': 1, 15 | 'no-prototype-builtins': 1, 16 | 'no-useless-constructor': 1, 17 | 'no-empty-function': 1, 18 | '@typescript-eslint/member-ordering': 0, 19 | 'lines-between-class-members': 0, 20 | 'no-await-in-loop': 0, 21 | 'no-plusplus': 0, 22 | '@typescript-eslint/no-parameter-properties': 0, 23 | '@typescript-eslint/no-unused-vars': 1, 24 | 'no-multi-assign': 1, 25 | 'no-dupe-class-members': 1, 26 | 'react/no-deprecated': 1, 27 | 'no-useless-escape': 1, 28 | 'brace-style': 1, 29 | '@typescript-eslint/no-inferrable-types': 0, 30 | 'no-proto': 0, 31 | 'prefer-const': 0, 32 | 'eol-last': 0, 33 | 'react/no-find-dom-node': 0, 34 | 'no-case-declarations': 0, 35 | '@typescript-eslint/indent': 0, 36 | 'import/no-cycle': 0, 37 | '@typescript-eslint/no-shadow': 0, 38 | "@typescript-eslint/method-signature-style": 0, 39 | "@typescript-eslint/consistent-type-assertions": 0, 40 | "@typescript-eslint/no-useless-constructor": 0, 41 | '@typescript-eslint/dot-notation': 0, // for lint performance 42 | '@typescript-eslint/restrict-plus-operands': 0, // for lint performance 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/.gitignore: -------------------------------------------------------------------------------- 1 | # project custom 2 | build 3 | dist 4 | 5 | 6 | # IDE 7 | .vscode 8 | .idea 9 | 10 | # Logs 11 | logs 12 | *.log 13 | npm-debug.log* 14 | yarn-debug.log* 15 | yarn-error.log* 16 | lerna-debug.log* 17 | 18 | # Runtime data 19 | pids 20 | *.pid 21 | *.seed 22 | *.pid.lock 23 | 24 | 25 | # Directory for instrumented libs generated by jscoverage/JSCover 26 | lib-cov 27 | 28 | # Coverage directory used by tools like istanbul 29 | coverage 30 | 31 | # nyc test coverage 32 | .nyc_output 33 | 34 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 35 | .grunt 36 | 37 | # Bower dependency directory (https://bower.io/) 38 | bower_components 39 | 40 | # node-waf configuration 41 | .lock-wscript 42 | 43 | # Compiled binary addons (https://nodejs.org/api/addons.html) 44 | build/Release 45 | lib 46 | 47 | # Dependency directories 48 | node_modules/ 49 | jspm_packages/ 50 | 51 | # TypeScript v1 declaration files 52 | typings/ 53 | 54 | # Optional npm cache directory 55 | .npm 56 | 57 | # Optional eslint cache 58 | .eslintcache 59 | 60 | # Optional REPL history 61 | .node_repl_history 62 | 63 | # Output of 'npm pack' 64 | *.tgz 65 | 66 | # Yarn Integrity file 67 | .yarn-integrity 68 | 69 | # dotenv environment variables file 70 | .env 71 | .env.test 72 | 73 | # parcel-bundler cache (https://parceljs.org/) 74 | .cache 75 | 76 | # next.js build output 77 | .next 78 | 79 | # nuxt.js build output 80 | .nuxt 81 | 82 | # vuepress build output 83 | .vuepress/dist 84 | 85 | # Serverless directories 86 | .serverless/ 87 | 88 | # FuseBox cache 89 | .fusebox/ 90 | 91 | # DynamoDB Local files 92 | .dynamodb/ 93 | 94 | # mac config files 95 | .DS_Store 96 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/.gitignore: -------------------------------------------------------------------------------- 1 | # project custom 2 | build 3 | dist 4 | 5 | 6 | # IDE 7 | .vscode 8 | .idea 9 | 10 | # Logs 11 | logs 12 | *.log 13 | npm-debug.log* 14 | yarn-debug.log* 15 | yarn-error.log* 16 | lerna-debug.log* 17 | 18 | # Runtime data 19 | pids 20 | *.pid 21 | *.seed 22 | *.pid.lock 23 | 24 | 25 | # Directory for instrumented libs generated by jscoverage/JSCover 26 | lib-cov 27 | 28 | # Coverage directory used by tools like istanbul 29 | coverage 30 | 31 | # nyc test coverage 32 | .nyc_output 33 | 34 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 35 | .grunt 36 | 37 | # Bower dependency directory (https://bower.io/) 38 | bower_components 39 | 40 | # node-waf configuration 41 | .lock-wscript 42 | 43 | # Compiled binary addons (https://nodejs.org/api/addons.html) 44 | build/Release 45 | lib 46 | 47 | # Dependency directories 48 | node_modules/ 49 | jspm_packages/ 50 | 51 | # TypeScript v1 declaration files 52 | typings/ 53 | 54 | # Optional npm cache directory 55 | .npm 56 | 57 | # Optional eslint cache 58 | .eslintcache 59 | 60 | # Optional REPL history 61 | .node_repl_history 62 | 63 | # Output of 'npm pack' 64 | *.tgz 65 | 66 | # Yarn Integrity file 67 | .yarn-integrity 68 | 69 | # dotenv environment variables file 70 | .env 71 | .env.test 72 | 73 | # parcel-bundler cache (https://parceljs.org/) 74 | .cache 75 | 76 | # next.js build output 77 | .next 78 | 79 | # nuxt.js build output 80 | .nuxt 81 | 82 | # vuepress build output 83 | .vuepress/dist 84 | 85 | # Serverless directories 86 | .serverless/ 87 | 88 | # FuseBox cache 89 | .fusebox/ 90 | 91 | # DynamoDB Local files 92 | .dynamodb/ 93 | 94 | # mac config files 95 | .DS_Store 96 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lowcodecloud/lowcode-engine-vue2-simulator-renderer", 3 | "version": "1.0.9", 4 | "description": "lowcode-engine-vue2-simulator-renderer", 5 | "main": "lib/index.js", 6 | "module": "es/index.js", 7 | "license": "MIT", 8 | "files": [ 9 | "es", 10 | "lib", 11 | "dist" 12 | ], 13 | "scripts": { 14 | "test": "build-scripts test --config build.test.json", 15 | "build": "build-scripts build --skip-demo", 16 | "build:umd": "build-scripts build --config build.umd.json" 17 | }, 18 | "dependencies": { 19 | "@alilc/lowcode-designer": "^1.0.9", 20 | "@alilc/lowcode-react-renderer": "^1.0.9", 21 | "@alilc/lowcode-types": "^1.0.9", 22 | "@alilc/lowcode-utils": "^1.0.9", 23 | "@lowcodecloud/lowcode-engine-vue2-renderer": "1.0.0", 24 | "classnames": "^2.2.6", 25 | "history": "^5.3.0", 26 | "lodash": "^4.17.21", 27 | "mobx": "^6.3.0", 28 | "mobx-react": "^7.2.0", 29 | "react": "^16", 30 | "react-dom": "^16.7.0", 31 | "react-router": "^5.2.1", 32 | "tslib": "^2.4.0" 33 | }, 34 | "devDependencies": { 35 | "@alib/build-scripts": "^0.1.18", 36 | "@babel/runtime": "^7.18.3", 37 | "@types/classnames": "^2.2.7", 38 | "@types/lodash": "^4.14.182", 39 | "@types/node": "^13.7.1", 40 | "@types/react": "^16", 41 | "@types/react-dom": "^16", 42 | "@types/react-router": "^5.1.17", 43 | "build-plugin-component": "^0.2.11" 44 | }, 45 | "publishConfig": { 46 | "access": "public", 47 | "registry": "https://registry.npmjs.org/" 48 | }, 49 | "repository": { 50 | "type": "http", 51 | "url": "https://github.com/lowcodecloud" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lowcodecloud/lowcode-engine-vue3-simulator-renderer", 3 | "version": "1.0.9", 4 | "description": "lowcode-engine-vue3-simulator-renderer", 5 | "main": "lib/index.js", 6 | "module": "es/index.js", 7 | "license": "MIT", 8 | "files": [ 9 | "es", 10 | "lib", 11 | "dist" 12 | ], 13 | "scripts": { 14 | "test": "build-scripts test --config build.test.json", 15 | "build": "build-scripts build --skip-demo", 16 | "build:umd": "build-scripts build --config build.umd.json" 17 | }, 18 | "dependencies": { 19 | "@alilc/lowcode-designer": "^1.0.9", 20 | "@alilc/lowcode-react-renderer": "^1.0.9", 21 | "@alilc/lowcode-types": "^1.0.9", 22 | "@alilc/lowcode-utils": "^1.0.9", 23 | "@lowcodecloud/lowcode-engine-vue3-renderer": "1.0.0", 24 | "classnames": "^2.2.6", 25 | "history": "^5.3.0", 26 | "lodash": "^4.17.21", 27 | "mobx": "^6.3.0", 28 | "mobx-react": "^7.2.0", 29 | "react": "^16", 30 | "react-dom": "^16.7.0", 31 | "react-router": "^5.2.1", 32 | "tslib": "^2.4.0" 33 | }, 34 | "devDependencies": { 35 | "@alib/build-scripts": "^0.1.18", 36 | "@babel/runtime": "^7.18.3", 37 | "@types/classnames": "^2.2.7", 38 | "@types/lodash": "^4.14.182", 39 | "@types/node": "^13.7.1", 40 | "@types/react": "^16", 41 | "@types/react-dom": "^16", 42 | "@types/react-router": "^5.1.17", 43 | "build-plugin-component": "^0.2.11" 44 | }, 45 | "publishConfig": { 46 | "access": "public", 47 | "registry": "https://registry.npmjs.org/" 48 | }, 49 | "repository": { 50 | "type": "http", 51 | "url": "https://github.com/lowcodecloud" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packages/vue2-renderer/src/create-element/adaptive-create-element.ts: -------------------------------------------------------------------------------- 1 | import { createElement as reactCreateElement } from 'react'; 2 | 3 | import { vueRendererExtTypes } from '@lowcodecloud/lowcode-engine-vue-renderer-core'; 4 | 5 | import vue2CreateElement from './vue2-create-element'; 6 | 7 | class AdaptiveCreateElementAdapter implements vueRendererExtTypes.CreateElementAdapter { 8 | createElement(component: any, props: any, ...children: any): any { 9 | if (!component) { 10 | return reactCreateElement(component, props, ...children); 11 | } 12 | let { $$devStack } = component; 13 | 14 | if ($$devStack === undefined) { 15 | return reactCreateElement(component, props, ...children); 16 | } 17 | 18 | switch ($$devStack as vueRendererExtTypes.DevStack) { 19 | case vueRendererExtTypes.DevStack.React: 20 | return reactCreateElement(component, props, ...children); 21 | case vueRendererExtTypes.DevStack.Vue: 22 | if (component.render && typeof component.render.toString === 'function' && !component.render.toString().startsWith('function()')) { 23 | return reactCreateElement(component, props, ...children); 24 | } 25 | return vue2CreateElement(component, props, ...children); 26 | case vueRendererExtTypes.DevStack.Vue2: 27 | if (component.render && typeof component.render.toString === 'function' && !component.render.toString().startsWith('function()')) { 28 | return reactCreateElement(component, props, ...children); 29 | } 30 | return vue2CreateElement(component, props, ...children); 31 | default: 32 | return reactCreateElement(component, props, ...children); 33 | } 34 | } 35 | } 36 | 37 | export default new AdaptiveCreateElementAdapter().createElement; 38 | -------------------------------------------------------------------------------- /packages/vue3-renderer/src/create-element/adaptive-create-element.ts: -------------------------------------------------------------------------------- 1 | import { createElement as reactCreateElement } from 'react'; 2 | 3 | import { vueRendererExtTypes } from '@lowcodecloud/lowcode-engine-vue-renderer-core'; 4 | 5 | import vue2CreateElement from './vue3-create-element'; 6 | 7 | class AdaptiveCreateElementAdapter implements vueRendererExtTypes.CreateElementAdapter { 8 | createElement(component: any, props: any, ...children: any): any { 9 | if (!component) { 10 | return reactCreateElement(component, props, ...children); 11 | } 12 | let { $$devStack } = component; 13 | 14 | if ($$devStack === undefined) { 15 | return reactCreateElement(component, props, ...children); 16 | } 17 | 18 | switch ($$devStack as vueRendererExtTypes.DevStack) { 19 | case vueRendererExtTypes.DevStack.React: 20 | return reactCreateElement(component, props, ...children); 21 | case vueRendererExtTypes.DevStack.Vue: 22 | if (component.render && typeof component.render.toString === 'function' && !component.render.toString().startsWith('function()')) { 23 | return reactCreateElement(component, props, ...children); 24 | } 25 | return vue2CreateElement(component, props, ...children); 26 | case vueRendererExtTypes.DevStack.Vue2: 27 | if (component.render && typeof component.render.toString === 'function' && !component.render.toString().startsWith('function()')) { 28 | return reactCreateElement(component, props, ...children); 29 | } 30 | return vue2CreateElement(component, props, ...children); 31 | default: 32 | return reactCreateElement(component, props, ...children); 33 | } 34 | } 35 | } 36 | 37 | export default new AdaptiveCreateElementAdapter().createElement; 38 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "lib": [ 5 | "es2015", 6 | "dom" 7 | ], 8 | // Target latest version of ECMAScript. 9 | "target": "esnext", 10 | // Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. 11 | "module": "esnext", 12 | // Search under node_modules for non-relative imports. 13 | "moduleResolution": "node", 14 | // Enable strictest settings like strictNullChecks & noImplicitAny. 15 | "strict": true, 16 | "strictPropertyInitialization": false, 17 | // Allow default imports from modules with no default export. This does not affect code emit, just typechecking. 18 | "allowSyntheticDefaultImports": true, 19 | // Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. 20 | "esModuleInterop": true, 21 | // Specify JSX code generation: 'preserve', 'react-native', or 'react'. 22 | "jsx": "preserve", 23 | // Import emit helpers (e.g. __extends, __rest, etc..) from tslib 24 | "importHelpers": true, 25 | // Enables experimental support for ES7 decorators. 26 | "experimentalDecorators": true, 27 | "emitDecoratorMetadata": true, 28 | // Generates corresponding .map file. 29 | "sourceMap": true, 30 | // Disallow inconsistently-cased references to the same file. 31 | "forceConsistentCasingInFileNames": true, 32 | // Allow json import 33 | "resolveJsonModule": true, 34 | // skip type checking of declaration files 35 | "skipLibCheck": true, 36 | "useDefineForClassFields": true, 37 | "baseUrl": "./", 38 | "outDir": "lib" 39 | }, 40 | "exclude": [ 41 | "**/dist", 42 | "**/build", 43 | "**/lib", 44 | "**/es", 45 | "node_modules" 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "declaration": true, 5 | "lib": ["es2015", "dom"], 6 | // Target latest version of ECMAScript. 7 | "target": "esnext", 8 | // Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. 9 | "module": "esnext", 10 | // Search under node_modules for non-relative imports. 11 | "moduleResolution": "node", 12 | // Process & infer types from .js files. 13 | "allowJs": true, 14 | // Report errors in .js files. 15 | "checkJs": false, 16 | // Don't emit; allow Babel to transform files. 17 | // "noEmit": true, 18 | // Enable strictest settings like strictNullChecks & noImplicitAny. 19 | "strict": true, 20 | // Allow default imports from modules with no default export. This does not affect code emit, just typechecking. 21 | "allowSyntheticDefaultImports": true, 22 | // Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. 23 | "esModuleInterop": true, 24 | // Specify JSX code generation: 'preserve', 'react-native', or 'react'. 25 | "jsx": "preserve", 26 | // Import emit helpers (e.g. __extends, __rest, etc..) from tslib 27 | "importHelpers": true, 28 | // Enables experimental support for ES7 decorators. 29 | "experimentalDecorators": true, 30 | // Generates corresponding .map file. 31 | "sourceMap": true, 32 | // Disallow inconsistently-cased references to the same file. 33 | "forceConsistentCasingInFileNames": true, 34 | // Allow json import 35 | "resolveJsonModule": true, 36 | // skip type checking of declaration files 37 | "skipLibCheck": true, 38 | "outDir": "lib" 39 | }, 40 | "include": [ 41 | "./src/" 42 | ], 43 | "exclude": ["**/test", "**/lib", "**/es", "node_modules"] 44 | } 45 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "declaration": true, 5 | "lib": ["es2015", "dom"], 6 | // Target latest version of ECMAScript. 7 | "target": "esnext", 8 | // Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. 9 | "module": "esnext", 10 | // Search under node_modules for non-relative imports. 11 | "moduleResolution": "node", 12 | // Process & infer types from .js files. 13 | "allowJs": true, 14 | // Report errors in .js files. 15 | "checkJs": false, 16 | // Don't emit; allow Babel to transform files. 17 | // "noEmit": true, 18 | // Enable strictest settings like strictNullChecks & noImplicitAny. 19 | "strict": true, 20 | // Allow default imports from modules with no default export. This does not affect code emit, just typechecking. 21 | "allowSyntheticDefaultImports": true, 22 | // Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. 23 | "esModuleInterop": true, 24 | // Specify JSX code generation: 'preserve', 'react-native', or 'react'. 25 | "jsx": "preserve", 26 | // Import emit helpers (e.g. __extends, __rest, etc..) from tslib 27 | "importHelpers": true, 28 | // Enables experimental support for ES7 decorators. 29 | "experimentalDecorators": true, 30 | // Generates corresponding .map file. 31 | "sourceMap": true, 32 | // Disallow inconsistently-cased references to the same file. 33 | "forceConsistentCasingInFileNames": true, 34 | // Allow json import 35 | "resolveJsonModule": true, 36 | // skip type checking of declaration files 37 | "skipLibCheck": true, 38 | "outDir": "lib" 39 | }, 40 | "include": [ 41 | "./src/" 42 | ], 43 | "exclude": ["**/test", "**/lib", "**/es", "node_modules"] 44 | } 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # project custom 2 | build 3 | dist 4 | packages/*/lib/ 5 | packages/*/es/ 6 | packages/*/dist/ 7 | packages/*/output/ 8 | packages/demo/ 9 | package-lock.json 10 | yarn.lock 11 | deploy-space/packages 12 | deploy-space/.env 13 | 14 | 15 | # IDE 16 | .vscode 17 | .idea 18 | 19 | # Logs 20 | logs 21 | *.log 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | lerna-debug.log* 26 | 27 | # Runtime data 28 | pids 29 | *.pid 30 | *.seed 31 | *.pid.lock 32 | 33 | 34 | # Directory for instrumented libs generated by jscoverage/JSCover 35 | lib-cov 36 | 37 | # Coverage directory used by tools like istanbul 38 | coverage 39 | 40 | # nyc test coverage 41 | .nyc_output 42 | 43 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 44 | .grunt 45 | 46 | # Bower dependency directory (https://bower.io/) 47 | bower_components 48 | 49 | # node-waf configuration 50 | .lock-wscript 51 | 52 | # Compiled binary addons (https://nodejs.org/api/addons.html) 53 | build/Release 54 | lib 55 | 56 | # Dependency directories 57 | node_modules/ 58 | jspm_packages/ 59 | 60 | # TypeScript v1 declaration files 61 | typings/ 62 | 63 | # Optional npm cache directory 64 | .npm 65 | 66 | # pnpm 67 | pnpm-lock.yaml 68 | 69 | # Optional eslint cache 70 | .eslintcache 71 | 72 | # Optional REPL history 73 | .node_repl_history 74 | 75 | # Output of 'npm pack' 76 | *.tgz 77 | 78 | # Yarn Integrity file 79 | .yarn-integrity 80 | 81 | # dotenv environment variables file 82 | .env 83 | .env.test 84 | 85 | # parcel-bundler cache (https://parceljs.org/) 86 | .cache 87 | 88 | # next.js build output 89 | .next 90 | 91 | # nuxt.js build output 92 | .nuxt 93 | 94 | # vuepress build output 95 | .vuepress/dist 96 | 97 | # Serverless directories 98 | .serverless/ 99 | 100 | # FuseBox cache 101 | .fusebox/ 102 | 103 | # DynamoDB Local files 104 | .dynamodb/ 105 | 106 | # mac config files 107 | .DS_Store 108 | 109 | # codealike 110 | codealike.json 111 | .node 112 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/src/renderer.less: -------------------------------------------------------------------------------- 1 | body, html { 2 | display: block; 3 | background: white; 4 | padding: 0; 5 | margin: 0; 6 | } 7 | 8 | html.engine-design-mode { 9 | padding-bottom: 0; 10 | } 11 | 12 | html.engine-cursor-move, html.engine-cursor-move * { 13 | cursor: grabbing !important; 14 | } 15 | 16 | html.engine-cursor-copy, html.engine-cursor-copy * { 17 | cursor: copy !important; 18 | } 19 | 20 | html.engine-cursor-ew-resize, html.engine-cursor-ew-resize * { 21 | cursor: ew-resize !important; 22 | } 23 | 24 | ::-webkit-scrollbar { 25 | width: 5px; 26 | height: 5px; 27 | } 28 | 29 | ::-webkit-scrollbar-thumb { 30 | background-color: rgba(0, 0, 0, 0.3); 31 | border-radius: 5px; 32 | } 33 | 34 | .lc-container { 35 | &:empty { 36 | background: #f2f3f5; 37 | color: #a7b1bd; 38 | outline: 1px dashed rgba(31, 56, 88, 0.2); 39 | outline-offset: -1px !important; 40 | height: 66px; 41 | max-height: 100%; 42 | min-width: 140px; 43 | text-align: center; 44 | overflow: hidden; 45 | display: flex; 46 | align-items: center; 47 | &:before { 48 | content: '\62D6\62FD\7EC4\4EF6\6216\6A21\677F\5230\8FD9\91CC'; 49 | font-size: 14px; 50 | z-index: 1; 51 | width: 100%; 52 | white-space: nowrap; 53 | } 54 | } 55 | } 56 | 57 | .lc-container-placeholder { 58 | min-height: 60px; 59 | height: 100%; 60 | width: 100%; 61 | background-color: rgb(240, 240, 240); 62 | border: 1px dotted; 63 | color: rgb(167, 177, 189); 64 | display: flex; 65 | align-items: center; 66 | justify-content: center; 67 | font-size: 14px; 68 | 69 | &.lc-container-locked { 70 | background: #eccfcf; 71 | } 72 | } 73 | 74 | body.engine-document { 75 | &:after, &:before { 76 | content: ""; 77 | display: table; 78 | } 79 | &:after { 80 | clear: both; 81 | } 82 | } 83 | 84 | .engine-live-editing { 85 | cursor: text; 86 | outline: none; 87 | box-shadow: 0 0 0 2px rgb(102, 188, 92); 88 | user-select: text; 89 | } 90 | 91 | #app { 92 | height: 100vh; 93 | } 94 | 95 | 96 | -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/src/renderer.less: -------------------------------------------------------------------------------- 1 | body, html { 2 | display: block; 3 | background: white; 4 | padding: 0; 5 | margin: 0; 6 | } 7 | 8 | html.engine-design-mode { 9 | padding-bottom: 0; 10 | } 11 | 12 | html.engine-cursor-move, html.engine-cursor-move * { 13 | cursor: grabbing !important; 14 | } 15 | 16 | html.engine-cursor-copy, html.engine-cursor-copy * { 17 | cursor: copy !important; 18 | } 19 | 20 | html.engine-cursor-ew-resize, html.engine-cursor-ew-resize * { 21 | cursor: ew-resize !important; 22 | } 23 | 24 | ::-webkit-scrollbar { 25 | width: 5px; 26 | height: 5px; 27 | } 28 | 29 | ::-webkit-scrollbar-thumb { 30 | background-color: rgba(0, 0, 0, 0.3); 31 | border-radius: 5px; 32 | } 33 | 34 | .lc-container { 35 | &:empty { 36 | background: #f2f3f5; 37 | color: #a7b1bd; 38 | outline: 1px dashed rgba(31, 56, 88, 0.2); 39 | outline-offset: -1px !important; 40 | height: 66px; 41 | max-height: 100%; 42 | min-width: 140px; 43 | text-align: center; 44 | overflow: hidden; 45 | display: flex; 46 | align-items: center; 47 | &:before { 48 | content: '\62D6\62FD\7EC4\4EF6\6216\6A21\677F\5230\8FD9\91CC'; 49 | font-size: 14px; 50 | z-index: 1; 51 | width: 100%; 52 | white-space: nowrap; 53 | } 54 | } 55 | } 56 | 57 | .lc-container-placeholder { 58 | min-height: 60px; 59 | height: 100%; 60 | width: 100%; 61 | background-color: rgb(240, 240, 240); 62 | border: 1px dotted; 63 | color: rgb(167, 177, 189); 64 | display: flex; 65 | align-items: center; 66 | justify-content: center; 67 | font-size: 14px; 68 | 69 | &.lc-container-locked { 70 | background: #eccfcf; 71 | } 72 | } 73 | 74 | body.engine-document { 75 | &:after, &:before { 76 | content: ""; 77 | display: table; 78 | } 79 | &:after { 80 | clear: both; 81 | } 82 | } 83 | 84 | .engine-live-editing { 85 | cursor: text; 86 | outline: none; 87 | box-shadow: 0 0 0 2px rgb(102, 188, 92); 88 | user-select: text; 89 | } 90 | 91 | #app { 92 | height: 100vh; 93 | } 94 | 95 | 96 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/public/fixtures/basic-fusion-with-single-component/view.js: -------------------------------------------------------------------------------- 1 | !function e(t,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.M220318=n():t.M220318=n()}(window,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function t(){return e.default}:function t(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=345)}({3:function(e,t){e.exports=window.React},345:function(e,t,n){e.exports=n(429)},346:function(e,t,n){},429:function(e,t,n){"use strict";n.r(t),n.d(t,"default",(function(){return l}));var r={};n.r(r),n.d(r,"default",(function(){return l}));var o=n(3),u=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,r=Object.getOwnPropertySymbols(e);o { 20 | const parts = param.replace(/\+/g, ' ').split('='); 21 | let key = parts.shift()!; 22 | let val: any = parts.length > 0 ? parts.join('=') : undefined; 23 | 24 | key = decodeURIComponent(key); 25 | 26 | val = val === undefined ? null : decodeURIComponent(val); 27 | 28 | if (ret[key] === undefined) { 29 | ret[key] = val; 30 | } else if (Array.isArray(ret[key])) { 31 | ret[key].push(val); 32 | } else { 33 | ret[key] = [ret[key], val]; 34 | } 35 | }); 36 | 37 | return ret; 38 | } 39 | 40 | /** 41 | * Stringify object to query parammeters 42 | * @param {Object} obj 43 | * @return {String} 44 | */ 45 | export function stringifyQuery(obj: any): string { 46 | const param: string[] = []; 47 | Object.keys(obj).forEach((key) => { 48 | let value = obj[key]; 49 | if (value && typeof value === 'object') { 50 | value = JSON.stringify(value); 51 | } 52 | param.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`); 53 | }); 54 | return param.join('&'); 55 | } 56 | 57 | export function uriEncode(uri: string) { 58 | return encodeURIComponent(uri); 59 | } 60 | 61 | export function uriDecode(uri: string) { 62 | return decodeURIComponent(uri); 63 | } 64 | 65 | export function withQueryParams(url: string, params?: object) { 66 | const queryStr = params ? stringifyQuery(params) : ''; 67 | if (queryStr === '') { 68 | return url; 69 | } 70 | const urlSplit = url.split('#'); 71 | const hash = urlSplit[1] ? `#${urlSplit[1]}` : ''; 72 | const urlWithoutHash = urlSplit[0]; 73 | return `${urlWithoutHash}${~urlWithoutHash.indexOf('?') ? '&' : '?'}${queryStr}${hash}`; 74 | } 75 | -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/src/utils/url.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Parse queryString 3 | * @param {String} str '?q=query&b=test' 4 | * @return {Object} 5 | */ 6 | export function parseQuery(str: string): object { 7 | const ret: any = {}; 8 | 9 | if (typeof str !== 'string') { 10 | return ret; 11 | } 12 | 13 | const s = str.trim().replace(/^(\?|#|&)/, ''); 14 | 15 | if (!s) { 16 | return ret; 17 | } 18 | 19 | s.split('&').forEach((param) => { 20 | const parts = param.replace(/\+/g, ' ').split('='); 21 | let key = parts.shift()!; 22 | let val: any = parts.length > 0 ? parts.join('=') : undefined; 23 | 24 | key = decodeURIComponent(key); 25 | 26 | val = val === undefined ? null : decodeURIComponent(val); 27 | 28 | if (ret[key] === undefined) { 29 | ret[key] = val; 30 | } else if (Array.isArray(ret[key])) { 31 | ret[key].push(val); 32 | } else { 33 | ret[key] = [ret[key], val]; 34 | } 35 | }); 36 | 37 | return ret; 38 | } 39 | 40 | /** 41 | * Stringify object to query parammeters 42 | * @param {Object} obj 43 | * @return {String} 44 | */ 45 | export function stringifyQuery(obj: any): string { 46 | const param: string[] = []; 47 | Object.keys(obj).forEach((key) => { 48 | let value = obj[key]; 49 | if (value && typeof value === 'object') { 50 | value = JSON.stringify(value); 51 | } 52 | param.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`); 53 | }); 54 | return param.join('&'); 55 | } 56 | 57 | export function uriEncode(uri: string) { 58 | return encodeURIComponent(uri); 59 | } 60 | 61 | export function uriDecode(uri: string) { 62 | return decodeURIComponent(uri); 63 | } 64 | 65 | export function withQueryParams(url: string, params?: object) { 66 | const queryStr = params ? stringifyQuery(params) : ''; 67 | if (queryStr === '') { 68 | return url; 69 | } 70 | const urlSplit = url.split('#'); 71 | const hash = urlSplit[1] ? `#${urlSplit[1]}` : ''; 72 | const urlWithoutHash = urlSplit[0]; 73 | return `${urlWithoutHash}${~urlWithoutHash.indexOf('?') ? '&' : '?'}${queryStr}${hash}`; 74 | } 75 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lowcodecloud/lowcode-vue2-demo", 3 | "version": "1.0.0", 4 | "description": "Low-Code Engine 低代码搭建引擎 Vue2 Demo 项目", 5 | "repository": "git@github.com:alibaba/lowcode-demo.git", 6 | "license": "MIT", 7 | "main": "index.js", 8 | "scripts": { 9 | "start": "build-scripts start --disable-reload --port 5556", 10 | "build": "build-scripts build", 11 | "prepublishOnly": "npm run build", 12 | "pub": "node ./scripts/watchdog.js && npm pub" 13 | }, 14 | "files": [ 15 | "build" 16 | ], 17 | "config": {}, 18 | "dependencies": { 19 | "@alilc/lowcode-utils": "^1.0.9", 20 | "@alilc/lowcode-datasource-fetch-handler": "^1.0.1", 21 | "@alilc/lowcode-plugin-code-editor": "^1.0.2", 22 | "@alilc/lowcode-plugin-code-generator": "^1.0.4", 23 | "@alilc/lowcode-plugin-components-pane": "^1.0.2", 24 | "@alilc/lowcode-plugin-datasource-pane": "^1.0.5", 25 | "@alilc/lowcode-plugin-inject": "^1.0.0", 26 | "@alilc/lowcode-plugin-manual": "^1.0.3", 27 | "@alilc/lowcode-plugin-schema": "^1.0.1", 28 | "@alilc/lowcode-plugin-simulator-select": "^1.0.0", 29 | "@alilc/lowcode-plugin-undo-redo": "^1.0.0", 30 | "@alilc/lowcode-plugin-zh-en": "^1.0.0", 31 | "@alilc/lowcode-react-renderer": "^1.0.0", 32 | "@alilc/lowcode-setter-behavior": "^1.0.0", 33 | "@alilc/lowcode-setter-title": "^1.0.2", 34 | "@lowcodecloud/lowcode-engine-vue2-renderer": "1.0.0", 35 | "regenerator-runtime": "^0.13.9", 36 | "uuid": "^8.3.2" 37 | }, 38 | "devDependencies": { 39 | "@alib/build-scripts": "^0.1.18", 40 | "@alilc/lowcode-engine": "^1.0.0", 41 | "@alilc/lowcode-engine-ext": "^1.0.0", 42 | "@alilc/lowcode-types": "^1.0.0", 43 | "@babel/runtime": "^7.18.3", 44 | "@types/events": "^3.0.0", 45 | "@types/react": "^16.8.3", 46 | "@types/react-dom": "^16.8.2", 47 | "@types/streamsaver": "^2.0.0", 48 | "@types/uuid": "^8.3.4", 49 | "build-plugin-fusion": "^0.1.0", 50 | "build-plugin-moment-locales": "^0.1.0", 51 | "build-plugin-react-app": "^1.1.2", 52 | "fs-extra": "^10.0.1", 53 | "tsconfig-paths-webpack-plugin": "^3.2.0" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lowcodecloud/lowcode-vue3-demo", 3 | "version": "1.0.0", 4 | "description": "Low-Code Engine 低代码搭建引擎 Vue3 Demo 项目", 5 | "repository": "git@github.com:alibaba/lowcode-demo.git", 6 | "license": "MIT", 7 | "main": "index.js", 8 | "scripts": { 9 | "start": "build-scripts start --disable-reload --port 5557", 10 | "build": "build-scripts build", 11 | "prepublishOnly": "npm run build", 12 | "pub": "node ./scripts/watchdog.js && npm pub" 13 | }, 14 | "files": [ 15 | "build" 16 | ], 17 | "config": {}, 18 | "dependencies": { 19 | "@alilc/lowcode-utils": "^1.0.9", 20 | "@alilc/lowcode-datasource-fetch-handler": "^1.0.1", 21 | "@alilc/lowcode-plugin-code-editor": "^1.0.2", 22 | "@alilc/lowcode-plugin-code-generator": "^1.0.4", 23 | "@alilc/lowcode-plugin-components-pane": "^1.0.2", 24 | "@alilc/lowcode-plugin-datasource-pane": "^1.0.5", 25 | "@alilc/lowcode-plugin-inject": "^1.0.0", 26 | "@alilc/lowcode-plugin-manual": "^1.0.3", 27 | "@alilc/lowcode-plugin-schema": "^1.0.1", 28 | "@alilc/lowcode-plugin-simulator-select": "^1.0.0", 29 | "@alilc/lowcode-plugin-undo-redo": "^1.0.0", 30 | "@alilc/lowcode-plugin-zh-en": "^1.0.0", 31 | "@alilc/lowcode-react-renderer": "^1.0.0", 32 | "@alilc/lowcode-setter-behavior": "^1.0.0", 33 | "@alilc/lowcode-setter-title": "^1.0.2", 34 | "@lowcodecloud/lowcode-engine-vue3-renderer": "1.0.0", 35 | "regenerator-runtime": "^0.13.9", 36 | "uuid": "^8.3.2" 37 | }, 38 | "devDependencies": { 39 | "@alib/build-scripts": "^0.1.18", 40 | "@alilc/lowcode-engine": "^1.0.0", 41 | "@alilc/lowcode-engine-ext": "^1.0.0", 42 | "@alilc/lowcode-types": "^1.0.0", 43 | "@babel/runtime": "^7.18.3", 44 | "@types/events": "^3.0.0", 45 | "@types/react": "^16.8.3", 46 | "@types/react-dom": "^16.8.2", 47 | "@types/streamsaver": "^2.0.0", 48 | "@types/uuid": "^8.3.4", 49 | "build-plugin-fusion": "^0.1.0", 50 | "build-plugin-moment-locales": "^0.1.0", 51 | "build-plugin-react-app": "^1.1.2", 52 | "fs-extra": "^10.0.1", 53 | "tsconfig-paths-webpack-plugin": "^3.2.0" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/src/sample-plugins/set-ref-prop/index.tsx: -------------------------------------------------------------------------------- 1 | import { TransformedComponentMetadata, FieldConfig } from '@alilc/lowcode-types'; 2 | import { v4 as uuidv4 } from 'uuid'; 3 | import { material } from '@alilc/lowcode-engine'; 4 | 5 | function addonCombine(metadata: TransformedComponentMetadata) { 6 | const { componentName, configure = {} } = metadata; 7 | 8 | const isRoot: boolean = componentName === 'Page' || componentName === 'Component'; 9 | 10 | if (isRoot) { 11 | return metadata; 12 | } 13 | 14 | let advancedGroup: FieldConfig | undefined; 15 | 16 | const refItem: FieldConfig = { 17 | title: { 18 | label: 'refId', 19 | tip: '用于获取组件实例,调用物料内部方法', 20 | icon: '', 21 | }, 22 | name: "ref", 23 | setter: { 24 | componentName: 'StringSetter', 25 | }, 26 | defaultValue: () => { 27 | const uuid = uuidv4().replace('-', '').substring(0, 8); 28 | return `${componentName.toLowerCase()}-${uuid}`; 29 | }, 30 | extraProps: { 31 | display: 'block', 32 | supportVariable: false, 33 | }, 34 | } 35 | 36 | if (!configure.combined) { 37 | configure.combined = [] 38 | } 39 | 40 | advancedGroup = configure.combined?.filter(d => d.name === '#advanced')[0]; 41 | 42 | if (!advancedGroup) { 43 | advancedGroup = { 44 | name: '#advanced', 45 | title: { type: 'i18n', 'zh-CN': '高级', 'en-US': 'Advanced' }, 46 | items: [ 47 | refItem, 48 | ], 49 | }; 50 | 51 | configure.combined.push(advancedGroup); 52 | } 53 | 54 | if (!advancedGroup.items) { 55 | advancedGroup.items = [refItem]; 56 | } 57 | 58 | const advanceItems: FieldConfig[] = advancedGroup.items || []; 59 | 60 | if (!advanceItems || !advanceItems.length || !advanceItems?.filter(d => d.name === 'ref').length) { 61 | advanceItems.push(refItem); 62 | } 63 | 64 | return { 65 | ...metadata, 66 | configure, 67 | }; 68 | } 69 | 70 | export const registerRefProp = () => { 71 | return { 72 | init() { 73 | material.registerMetadataTransducer(addonCombine, 110, 'register-ref-prop') 74 | } 75 | }; 76 | }; 77 | 78 | registerRefProp.pluginName = 'register-ref-prop'; 79 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/src/sample-plugins/set-ref-prop/index.tsx: -------------------------------------------------------------------------------- 1 | import { TransformedComponentMetadata, FieldConfig } from '@alilc/lowcode-types'; 2 | import { v4 as uuidv4 } from 'uuid'; 3 | import { material } from '@alilc/lowcode-engine'; 4 | 5 | function addonCombine(metadata: TransformedComponentMetadata) { 6 | const { componentName, configure = {} } = metadata; 7 | 8 | const isRoot: boolean = componentName === 'Page' || componentName === 'Component'; 9 | 10 | if (isRoot) { 11 | return metadata; 12 | } 13 | 14 | let advancedGroup: FieldConfig | undefined; 15 | 16 | const refItem: FieldConfig = { 17 | title: { 18 | label: 'refId', 19 | tip: '用于获取组件实例,调用物料内部方法', 20 | icon: '', 21 | }, 22 | name: "ref", 23 | setter: { 24 | componentName: 'StringSetter', 25 | }, 26 | defaultValue: () => { 27 | const uuid = uuidv4().replace('-', '').substring(0, 8); 28 | return `${componentName.toLowerCase()}-${uuid}`; 29 | }, 30 | extraProps: { 31 | display: 'block', 32 | supportVariable: false, 33 | }, 34 | } 35 | 36 | if (!configure.combined) { 37 | configure.combined = [] 38 | } 39 | 40 | advancedGroup = configure.combined?.filter(d => d.name === '#advanced')[0]; 41 | 42 | if (!advancedGroup) { 43 | advancedGroup = { 44 | name: '#advanced', 45 | title: { type: 'i18n', 'zh-CN': '高级', 'en-US': 'Advanced' }, 46 | items: [ 47 | refItem, 48 | ], 49 | }; 50 | 51 | configure.combined.push(advancedGroup); 52 | } 53 | 54 | if (!advancedGroup.items) { 55 | advancedGroup.items = [refItem]; 56 | } 57 | 58 | const advanceItems: FieldConfig[] = advancedGroup.items || []; 59 | 60 | if (!advanceItems || !advanceItems.length || !advanceItems?.filter(d => d.name === 'ref').length) { 61 | advanceItems.push(refItem); 62 | } 63 | 64 | return { 65 | ...metadata, 66 | configure, 67 | }; 68 | } 69 | 70 | export const registerRefProp = () => { 71 | return { 72 | init() { 73 | material.registerMetadataTransducer(addonCombine, 110, 'register-ref-prop') 74 | } 75 | }; 76 | }; 77 | 78 | registerRefProp.pluginName = 'register-ref-prop'; 79 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/build.plugin.js: -------------------------------------------------------------------------------- 1 | const { join } = require('path'); 2 | const fs = require('fs-extra'); 3 | const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); 4 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 5 | 6 | const scenarioNames = fs.readdirSync(join('./src/scenarios')).filter(name => !name.startsWith('.')); 7 | const { version } = JSON.parse(fs.readFileSync('./package.json', 'utf8')); 8 | 9 | module.exports = ({ onGetWebpackConfig }) => { 10 | onGetWebpackConfig((config) => { 11 | config.resolve.plugin('tsconfigpaths').use(TsconfigPathsPlugin, [ 12 | { 13 | configFile: './tsconfig.json', 14 | }, 15 | ]); 16 | 17 | config.merge({ 18 | node: { 19 | fs: 'empty', 20 | }, 21 | }); 22 | 23 | scenarioNames.forEach(name => { 24 | const hasTsx = fs.existsSync(join(`./src/scenarios/${name}/index.tsx`)); 25 | config.merge({ 26 | entry: { 27 | [name]: hasTsx ? require.resolve(`./src/scenarios/${name}/index.tsx`) : require.resolve(`./src/scenarios/${name}/index.ts`), 28 | }, 29 | }); 30 | config 31 | .plugin(name) 32 | .use(HtmlWebpackPlugin, [ 33 | { 34 | inject: false, 35 | minify: false, 36 | templateParameters: { 37 | scenario: name, 38 | version, 39 | }, 40 | template: require.resolve('./public/index.ejs'), 41 | filename: `${name}.html`, 42 | }, 43 | ]); 44 | }) 45 | 46 | config 47 | .plugin('preview') 48 | .use(HtmlWebpackPlugin, [ 49 | { 50 | inject: false, 51 | templateParameters: { 52 | }, 53 | template: require.resolve('./public/preview.html'), 54 | filename: 'preview.html', 55 | }, 56 | ]); 57 | 58 | config.plugins.delete('hot'); 59 | config.devServer.hot(false); 60 | 61 | config.module // fixes https://github.com/graphql/graphql-js/issues/1272 62 | .rule('mjs$') 63 | .test(/\.mjs$/) 64 | .include 65 | .add(/node_modules/) 66 | .end() 67 | .type('javascript/auto'); 68 | }); 69 | }; 70 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/build.plugin.js: -------------------------------------------------------------------------------- 1 | const { join } = require('path'); 2 | const fs = require('fs-extra'); 3 | const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); 4 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 5 | 6 | const scenarioNames = fs.readdirSync(join('./src/scenarios')).filter(name => !name.startsWith('.')); 7 | const { version } = JSON.parse(fs.readFileSync('./package.json', 'utf8')); 8 | 9 | module.exports = ({ onGetWebpackConfig }) => { 10 | onGetWebpackConfig((config) => { 11 | config.resolve.plugin('tsconfigpaths').use(TsconfigPathsPlugin, [ 12 | { 13 | configFile: './tsconfig.json', 14 | }, 15 | ]); 16 | 17 | config.merge({ 18 | node: { 19 | fs: 'empty', 20 | }, 21 | }); 22 | 23 | scenarioNames.forEach(name => { 24 | const hasTsx = fs.existsSync(join(`./src/scenarios/${name}/index.tsx`)); 25 | config.merge({ 26 | entry: { 27 | [name]: hasTsx ? require.resolve(`./src/scenarios/${name}/index.tsx`) : require.resolve(`./src/scenarios/${name}/index.ts`), 28 | }, 29 | }); 30 | config 31 | .plugin(name) 32 | .use(HtmlWebpackPlugin, [ 33 | { 34 | inject: false, 35 | minify: false, 36 | templateParameters: { 37 | scenario: name, 38 | version, 39 | }, 40 | template: require.resolve('./public/index.ejs'), 41 | filename: `${name}.html`, 42 | }, 43 | ]); 44 | }) 45 | 46 | config 47 | .plugin('preview') 48 | .use(HtmlWebpackPlugin, [ 49 | { 50 | inject: false, 51 | templateParameters: { 52 | }, 53 | template: require.resolve('./public/preview.html'), 54 | filename: 'preview.html', 55 | }, 56 | ]); 57 | 58 | config.plugins.delete('hot'); 59 | config.devServer.hot(false); 60 | 61 | config.module // fixes https://github.com/graphql/graphql-js/issues/1272 62 | .rule('mjs$') 63 | .test(/\.mjs$/) 64 | .include 65 | .add(/node_modules/) 66 | .end() 67 | .type('javascript/auto'); 68 | }); 69 | }; 70 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/public/simulator/css/vue2-simulator-renderer.css: -------------------------------------------------------------------------------- 1 | .visual-dom .panel-container{-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid #e9e9e9}.visual-dom .panel-container .title{display:block;font-size:12px;color:#333;background-color:#ebecf0;line-height:28px;padding:0 12px;border-bottom:1px solid #e9e9e9}.visual-dom .panel-container .content{min-height:20px;padding:5px}html.lc-cursor-dragging,html.lc-cursor-dragging *{cursor:move!important}html.lc-cursor-x-resizing,html.lc-cursor-x-resizing *{cursor:col-resize}html.lc-cursor-y-resizing,html.lc-cursor-y-resizing *{cursor:row-resize}html.lc-cursor-copy,html.lc-cursor-copy *{cursor:copy!important}body,html{display:block;background:#fff;padding:0;margin:0}html.engine-design-mode{padding-bottom:0}html.engine-cursor-move,html.engine-cursor-move *{cursor:-webkit-grabbing!important;cursor:grabbing!important}html.engine-cursor-copy,html.engine-cursor-copy *{cursor:copy!important}html.engine-cursor-ew-resize,html.engine-cursor-ew-resize *{cursor:ew-resize!important}::-webkit-scrollbar{width:5px;height:5px}::-webkit-scrollbar-thumb{background-color:rgba(0,0,0,.3);border-radius:5px}.lc-container:empty{background:#f2f3f5;color:#a7b1bd;outline:1px dashed rgba(31,56,88,.2);outline-offset:-1px!important;height:66px;max-height:100%;min-width:140px;text-align:center;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.lc-container:empty:before{content:"\62D6\62FD\7EC4\4EF6\6216\6A21\677F\5230\8FD9\91CC";font-size:14px;z-index:1;width:100%;white-space:nowrap}.lc-container-placeholder{min-height:60px;height:100%;width:100%;background-color:#f0f0f0;border:1px dotted;color:#a7b1bd;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;font-size:14px}.lc-container-placeholder.lc-container-locked{background:#eccfcf}body.engine-document:after,body.engine-document:before{content:"";display:table}body.engine-document:after{clear:both}.engine-live-editing{cursor:text;outline:none;-webkit-box-shadow:0 0 0 2px #66bc5c;box-shadow:0 0 0 2px #66bc5c;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text}#app{height:100vh} -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/public/simulator/css/vue3-simulator-renderer.css: -------------------------------------------------------------------------------- 1 | .visual-dom .panel-container{-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid #e9e9e9}.visual-dom .panel-container .title{display:block;font-size:12px;color:#333;background-color:#ebecf0;line-height:28px;padding:0 12px;border-bottom:1px solid #e9e9e9}.visual-dom .panel-container .content{min-height:20px;padding:5px}html.lc-cursor-dragging,html.lc-cursor-dragging *{cursor:move!important}html.lc-cursor-x-resizing,html.lc-cursor-x-resizing *{cursor:col-resize}html.lc-cursor-y-resizing,html.lc-cursor-y-resizing *{cursor:row-resize}html.lc-cursor-copy,html.lc-cursor-copy *{cursor:copy!important}body,html{display:block;background:#fff;padding:0;margin:0}html.engine-design-mode{padding-bottom:0}html.engine-cursor-move,html.engine-cursor-move *{cursor:-webkit-grabbing!important;cursor:grabbing!important}html.engine-cursor-copy,html.engine-cursor-copy *{cursor:copy!important}html.engine-cursor-ew-resize,html.engine-cursor-ew-resize *{cursor:ew-resize!important}::-webkit-scrollbar{width:5px;height:5px}::-webkit-scrollbar-thumb{background-color:rgba(0,0,0,.3);border-radius:5px}.lc-container:empty{background:#f2f3f5;color:#a7b1bd;outline:1px dashed rgba(31,56,88,.2);outline-offset:-1px!important;height:66px;max-height:100%;min-width:140px;text-align:center;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.lc-container:empty:before{content:"\62D6\62FD\7EC4\4EF6\6216\6A21\677F\5230\8FD9\91CC";font-size:14px;z-index:1;width:100%;white-space:nowrap}.lc-container-placeholder{min-height:60px;height:100%;width:100%;background-color:#f0f0f0;border:1px dotted;color:#a7b1bd;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;font-size:14px}.lc-container-placeholder.lc-container-locked{background:#eccfcf}body.engine-document:after,body.engine-document:before{content:"";display:table}body.engine-document:after{clear:both}.engine-live-editing{cursor:text;outline:none;-webkit-box-shadow:0 0 0 2px #66bc5c;box-shadow:0 0 0 2px #66bc5c;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text}#app{height:100vh} -------------------------------------------------------------------------------- /packages/vue-renderer-core/src/index.ts: -------------------------------------------------------------------------------- 1 | import React, { 2 | Component, 3 | PureComponent, 4 | createElement, 5 | createContext, 6 | forwardRef, 7 | ReactInstance, 8 | ContextType, 9 | } from 'react'; 10 | import ReactDOM from 'react-dom'; 11 | import { 12 | adapter, 13 | pageRendererFactory, 14 | componentRendererFactory, 15 | blockRendererFactory, 16 | addonRendererFactory, 17 | tempRendererFactory, 18 | rendererFactory, 19 | types, 20 | } from '@alilc/lowcode-renderer-core'; 21 | import ConfigProvider from '@alifd/next/lib/config-provider'; 22 | 23 | import { buildComponents } from './utils'; 24 | 25 | import * as vueRendererExtTypes from './types'; 26 | 27 | window.React = React; 28 | (window as any).ReactDom = ReactDOM; 29 | 30 | const defaultRuntime = { 31 | Component, 32 | PureComponent, 33 | createContext, 34 | createElement, 35 | forwardRef, 36 | findDOMNode: ReactDOM.findDOMNode, 37 | }; 38 | adapter.setRuntime(defaultRuntime); 39 | 40 | function setRuntime(runtime: any) { 41 | adapter.setRuntime({ ...defaultRuntime, ...runtime } as types.IRuntime); 42 | } 43 | 44 | const defaultRenderers = { 45 | PageRenderer: pageRendererFactory(), 46 | ComponentRenderer: componentRendererFactory(), 47 | BlockRenderer: blockRendererFactory(), 48 | AddonRenderer: addonRendererFactory(), 49 | TempRenderer: tempRendererFactory(), 50 | DivRenderer: blockRendererFactory(), 51 | }; 52 | adapter.setRenderers(defaultRenderers); 53 | 54 | function setRenderers(renderers: any) { 55 | adapter.setRenderers({ ...defaultRenderers, ...renderers } as types.IRendererModules); 56 | } 57 | 58 | const defaultConfigProvider = ConfigProvider; 59 | adapter.setConfigProvider(defaultConfigProvider); 60 | 61 | function setConfigProvider(configProvide: any) { 62 | adapter.setConfigProvider(configProvide); 63 | } 64 | 65 | function createRendererFactory(): types.IRenderComponent { 66 | const Renderer = rendererFactory(); 67 | return class ReactRenderer extends Renderer implements Component { 68 | readonly props: types.IRendererProps; 69 | 70 | context: ContextType; 71 | 72 | setState: ( 73 | state: types.IRendererState, 74 | callback?: () => void, 75 | ) => void; 76 | 77 | forceUpdate: (callback?: () => void) => void; 78 | 79 | refs: { 80 | [key: string]: ReactInstance; 81 | }; 82 | 83 | constructor(props: types.IRendererProps, context: ContextType) { 84 | super(props, context); 85 | } 86 | 87 | isValidComponent(obj: any) { 88 | return obj?.prototype?.isReactComponent || obj?.prototype instanceof Component; 89 | } 90 | }; 91 | } 92 | 93 | export default createRendererFactory; 94 | 95 | export { setRuntime, setRenderers, setConfigProvider, buildComponents, types, vueRendererExtTypes }; 96 | 97 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/public/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 阿里低代码引擎 Demo 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 42 | 43 | 44 | 45 |
46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/public/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 阿里低代码引擎 Demo 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 42 | 43 | 44 | 45 |
46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/src/preview.tsx: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom'; 2 | import React, { useState } from 'react'; 3 | import { Loading } from '@alifd/next'; 4 | import { assetBundle, AssetLevel, AssetLoader } from '@alilc/lowcode-utils'; 5 | import ReactRenderer, { buildComponents } from '@lowcodecloud/lowcode-engine-vue2-renderer'; 6 | import { injectComponents } from '@alilc/lowcode-plugin-inject'; 7 | import { createFetchHandler } from '@alilc/lowcode-datasource-fetch-handler'; 8 | 9 | import { getProjectSchemaFromLocalStorage, getPackagesFromLocalStorage } from './universal/utils'; 10 | 11 | const getScenarioName = function () { 12 | if (location.search) { 13 | return new URLSearchParams(location.search.slice(1)).get('scenarioName') || 'index'; 14 | } 15 | return 'index'; 16 | }; 17 | 18 | const SamplePreview = () => { 19 | const [data, setData] = useState({}); 20 | 21 | async function init() { 22 | const scenarioName = getScenarioName(); 23 | const packages = getPackagesFromLocalStorage(scenarioName); 24 | const projectSchema = getProjectSchemaFromLocalStorage(scenarioName); 25 | const { componentsMap: componentsMapArray, componentsTree } = projectSchema; 26 | const componentsMap: any = {}; 27 | componentsMapArray.forEach((component: any) => { 28 | componentsMap[component.componentName] = component; 29 | }); 30 | const schema = componentsTree[0]; 31 | 32 | const libraryMap = {}; 33 | const libraryAsset = []; 34 | packages.forEach(({ package: _package, library, urls, renderUrls }) => { 35 | libraryMap[_package] = library; 36 | if (_package === 'vue') { 37 | return; 38 | } 39 | if (renderUrls) { 40 | libraryAsset.push(renderUrls); 41 | } else if (urls) { 42 | libraryAsset.push(urls); 43 | } 44 | }); 45 | 46 | const vendors = [assetBundle(libraryAsset, AssetLevel.Library)]; 47 | 48 | // TODO asset may cause pollution 49 | const assetLoader = new AssetLoader(); 50 | await assetLoader.load(libraryAsset); 51 | const components = await injectComponents(buildComponents(libraryMap, componentsMap)); 52 | 53 | setData({ 54 | schema, 55 | components, 56 | }); 57 | } 58 | 59 | const { schema, components } = data; 60 | 61 | if (!schema || !components) { 62 | init(); 63 | return ; 64 | } 65 | 66 | return ( 67 |
68 | 78 |
79 | ); 80 | }; 81 | 82 | ReactDOM.render(, document.getElementById('ice-container')); 83 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/src/preview.tsx: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom'; 2 | import React, { useState } from 'react'; 3 | import { Loading } from '@alifd/next'; 4 | import { assetBundle, AssetLevel, AssetLoader } from '@alilc/lowcode-utils'; 5 | import ReactRenderer, { buildComponents } from '@lowcodecloud/lowcode-engine-vue3-renderer'; 6 | import { injectComponents } from '@alilc/lowcode-plugin-inject'; 7 | 8 | import { createFetchHandler } from '@alilc/lowcode-datasource-fetch-handler'; 9 | 10 | import { getProjectSchemaFromLocalStorage, getPackagesFromLocalStorage } from './universal/utils'; 11 | 12 | const getScenarioName = function () { 13 | if (location.search) { 14 | return new URLSearchParams(location.search.slice(1)).get('scenarioName') || 'index'; 15 | } 16 | return 'index'; 17 | }; 18 | 19 | const SamplePreview = () => { 20 | const [data, setData] = useState({}); 21 | 22 | async function init() { 23 | const scenarioName = getScenarioName(); 24 | const packages = getPackagesFromLocalStorage(scenarioName); 25 | const projectSchema = getProjectSchemaFromLocalStorage(scenarioName); 26 | const { componentsMap: componentsMapArray, componentsTree } = projectSchema; 27 | const componentsMap: any = {}; 28 | componentsMapArray.forEach((component: any) => { 29 | componentsMap[component.componentName] = component; 30 | }); 31 | const schema = componentsTree[0]; 32 | 33 | const libraryMap = {}; 34 | const libraryAsset = []; 35 | packages.forEach(({ package: _package, library, urls, renderUrls }) => { 36 | libraryMap[_package] = library; 37 | if (_package === 'vue') { 38 | return; 39 | } 40 | if (renderUrls) { 41 | libraryAsset.push(renderUrls); 42 | } else if (urls) { 43 | libraryAsset.push(urls); 44 | } 45 | }); 46 | 47 | const vendors = [assetBundle(libraryAsset, AssetLevel.Library)]; 48 | 49 | // TODO asset may cause pollution 50 | const assetLoader = new AssetLoader(); 51 | await assetLoader.load(libraryAsset); 52 | const components = await injectComponents(buildComponents(libraryMap, componentsMap)); 53 | 54 | setData({ 55 | schema, 56 | components, 57 | }); 58 | } 59 | 60 | const { schema, components } = data; 61 | 62 | if (!schema || !components) { 63 | init(); 64 | return ; 65 | } 66 | 67 | return ( 68 |
69 | 79 |
80 | ); 81 | }; 82 | 83 | ReactDOM.render(, document.getElementById('ice-container')); 84 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/test/schema/basic.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | id: 'node_ockvuu8u911', 3 | css: 'body{background-color:#f2f3f5}', 4 | flows: [], 5 | props: { 6 | className: 'page_kvuu9hym', 7 | pageStyle: { 8 | backgroundColor: '#f2f3f5', 9 | }, 10 | containerStyle: {}, 11 | templateVersion: '1.0.0', 12 | }, 13 | state: {}, 14 | title: '', 15 | methods: { 16 | __initMethods__: { 17 | type: 'JSExpression', 18 | value: "function (exports, module) { \"use strict\";\n\nexports.__esModule = true;\nexports.func1 = func1;\nexports.helloPage = helloPage;\n\nfunction func1() {\n console.info('hello, this is a page function');\n}\n\nfunction helloPage() {\n // 你可以这么调用其他函数\n this.func1(); // 你可以这么调用组件的函数\n // this.$('textField_xxx').getValue();\n // 你可以这么使用「数据源面板」定义的「变量」\n // this.state.xxx\n // 你可以这么发送一个在「数据源面板」定义的「远程 API」\n // this.dataSourceMap['xxx'].load(data)\n // API 详见:https://go.alibaba-inc.com/help3/API\n} \n}", 19 | }, 20 | }, 21 | children: [ 22 | { 23 | id: 'node_ockvuu8u915', 24 | props: { 25 | fieldId: 'div_kvuu9gl1', 26 | behavior: 'NORMAL', 27 | __style__: {}, 28 | customClassName: '', 29 | useFieldIdAsDomId: false, 30 | }, 31 | title: '', 32 | children: [ 33 | { 34 | id: 'node_ockvuu8u916', 35 | props: { 36 | content: { 37 | use: 'zh_CN', 38 | type: 'JSExpression', 39 | en_US: 'Tips content', 40 | value: '"我是一个简单的测试页面"', 41 | zh_CN: '我是一个简单的测试页面', 42 | extType: 'i18n', 43 | }, 44 | fieldId: 'text_kvuu9gl2', 45 | maxLine: 0, 46 | behavior: 'NORMAL', 47 | __style__: {}, 48 | showTitle: false, 49 | }, 50 | title: '', 51 | condition: true, 52 | componentName: 'Text', 53 | }, 54 | ], 55 | condition: true, 56 | componentName: 'Div', 57 | }, 58 | ], 59 | condition: true, 60 | dataSource: { 61 | list: [], 62 | sync: true, 63 | online: [], 64 | offline: [], 65 | globalConfig: { 66 | fit: { 67 | type: 'JSExpression', 68 | value: "function main(){\n 'use strict';\n\nvar __compiledFunc__ = function fit(response) {\n var content = response.content !== undefined ? response.content : response;\n var error = {\n message: response.errorMsg || response.errors && response.errors[0] && response.errors[0].msg || response.content || '远程数据源请求出错,success is false'\n };\n var success = true;\n if (response.success !== undefined) {\n success = response.success;\n } else if (response.hasError !== undefined) {\n success = !response.hasError;\n }\n return {\n content: content,\n success: success,\n error: error\n };\n};\n return __compiledFunc__.apply(this, arguments);\n}", 69 | extType: 'function', 70 | }, 71 | }, 72 | }, 73 | lifeCycles: { 74 | constructor: { 75 | type: 'JSExpression', 76 | value: "function constructor() {\nvar module = { exports: {} };\nvar _this = this;\nthis.__initMethods__(module.exports, module);\nObject.keys(module.exports).forEach(function(item) {\n if(typeof module.exports[item] === 'function'){\n _this[item] = module.exports[item];\n }\n});\n\n}", 77 | extType: 'function', 78 | }, 79 | }, 80 | componentName: 'Page', 81 | }; 82 | -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/test/schema/basic.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | id: 'node_ockvuu8u911', 3 | css: 'body{background-color:#f2f3f5}', 4 | flows: [], 5 | props: { 6 | className: 'page_kvuu9hym', 7 | pageStyle: { 8 | backgroundColor: '#f2f3f5', 9 | }, 10 | containerStyle: {}, 11 | templateVersion: '1.0.0', 12 | }, 13 | state: {}, 14 | title: '', 15 | methods: { 16 | __initMethods__: { 17 | type: 'JSExpression', 18 | value: "function (exports, module) { \"use strict\";\n\nexports.__esModule = true;\nexports.func1 = func1;\nexports.helloPage = helloPage;\n\nfunction func1() {\n console.info('hello, this is a page function');\n}\n\nfunction helloPage() {\n // 你可以这么调用其他函数\n this.func1(); // 你可以这么调用组件的函数\n // this.$('textField_xxx').getValue();\n // 你可以这么使用「数据源面板」定义的「变量」\n // this.state.xxx\n // 你可以这么发送一个在「数据源面板」定义的「远程 API」\n // this.dataSourceMap['xxx'].load(data)\n // API 详见:https://go.alibaba-inc.com/help3/API\n} \n}", 19 | }, 20 | }, 21 | children: [ 22 | { 23 | id: 'node_ockvuu8u915', 24 | props: { 25 | fieldId: 'div_kvuu9gl1', 26 | behavior: 'NORMAL', 27 | __style__: {}, 28 | customClassName: '', 29 | useFieldIdAsDomId: false, 30 | }, 31 | title: '', 32 | children: [ 33 | { 34 | id: 'node_ockvuu8u916', 35 | props: { 36 | content: { 37 | use: 'zh_CN', 38 | type: 'JSExpression', 39 | en_US: 'Tips content', 40 | value: '"我是一个简单的测试页面"', 41 | zh_CN: '我是一个简单的测试页面', 42 | extType: 'i18n', 43 | }, 44 | fieldId: 'text_kvuu9gl2', 45 | maxLine: 0, 46 | behavior: 'NORMAL', 47 | __style__: {}, 48 | showTitle: false, 49 | }, 50 | title: '', 51 | condition: true, 52 | componentName: 'Text', 53 | }, 54 | ], 55 | condition: true, 56 | componentName: 'Div', 57 | }, 58 | ], 59 | condition: true, 60 | dataSource: { 61 | list: [], 62 | sync: true, 63 | online: [], 64 | offline: [], 65 | globalConfig: { 66 | fit: { 67 | type: 'JSExpression', 68 | value: "function main(){\n 'use strict';\n\nvar __compiledFunc__ = function fit(response) {\n var content = response.content !== undefined ? response.content : response;\n var error = {\n message: response.errorMsg || response.errors && response.errors[0] && response.errors[0].msg || response.content || '远程数据源请求出错,success is false'\n };\n var success = true;\n if (response.success !== undefined) {\n success = response.success;\n } else if (response.hasError !== undefined) {\n success = !response.hasError;\n }\n return {\n content: content,\n success: success,\n error: error\n };\n};\n return __compiledFunc__.apply(this, arguments);\n}", 69 | extType: 'function', 70 | }, 71 | }, 72 | }, 73 | lifeCycles: { 74 | constructor: { 75 | type: 'JSExpression', 76 | value: "function constructor() {\nvar module = { exports: {} };\nvar _this = this;\nthis.__initMethods__(module.exports, module);\nObject.keys(module.exports).forEach(function(item) {\n if(typeof module.exports[item] === 'function'){\n _this[item] = module.exports[item];\n }\n});\n\n}", 77 | extType: 'function', 78 | }, 79 | }, 80 | componentName: 'Page', 81 | }; 82 | -------------------------------------------------------------------------------- /packages/vue-renderer-core/src/utils/build-components.ts: -------------------------------------------------------------------------------- 1 | import { ComponentType, FunctionComponent } from 'react'; 2 | import { ComponentSchema } from '@alilc/lowcode-types'; 3 | import { accessLibrary, isESModule, acceptsRef, wrapReactClass } from '@alilc/lowcode-utils'; 4 | import { isReactComponent } from './is-react'; 5 | import { LibraryPackageMapping, NpmInfo, DevStack } from '../types'; 6 | 7 | export type Component = ComponentType | object; 8 | 9 | export function findComponent(libraryMap: LibraryPackageMapping, componentName: string, npm?: NpmInfo) { 10 | if (!npm) { 11 | return accessLibrary(componentName); 12 | } 13 | 14 | // libraryName the key access to global 15 | // export { exportName } from xxx exportName === global.libraryName.exportName 16 | // export exportName from xxx exportName === global.libraryName.default || global.libraryName 17 | // export { exportName as componentName } from package 18 | // if exportName == null exportName === componentName; 19 | // const componentName = exportName.subName, if exportName empty subName donot use 20 | const exportName = npm.exportName || npm.componentName || componentName; 21 | const libraryName = libraryMap[npm.package] || exportName; 22 | const library = accessLibrary(libraryName); 23 | const paths = npm.exportName && npm.subName ? npm.subName.split('.') : []; 24 | if (npm.destructuring) { 25 | paths.unshift(exportName); 26 | } else if (isESModule(library)) { 27 | paths.unshift('default'); 28 | } 29 | let component = getSubComponent(library, paths); 30 | if (component) { 31 | (component as any).$$devStack = npm.devStack; 32 | } 33 | return component; 34 | } 35 | 36 | export function buildComponents(libraryMap: LibraryPackageMapping, 37 | componentsMap: { [componentName: string]: NpmInfo | ComponentType | ComponentSchema }, 38 | createComponent: (schema: ComponentSchema) => Component | null) { 39 | const components: any = {}; 40 | Object.keys(componentsMap).forEach((componentName) => { 41 | let component = componentsMap[componentName]; 42 | let devStack = component ? (component as NpmInfo).devStack : undefined; 43 | if (component && (component as ComponentSchema).componentName === 'Component') { 44 | components[componentName] = createComponent(component as ComponentSchema); 45 | } else if (devStack === 'vue' || devStack === 'vue2' || devStack === 'vue3') { 46 | // @ts-ignore 47 | component = findComponent(libraryMap, componentName, component); 48 | (component as any).$$devStack = DevStack.Vue; 49 | components[componentName] = component; 50 | } else if (devStack === 'react' || isReactComponent(component)) { 51 | if (!acceptsRef(component)) { 52 | component = wrapReactClass(component as FunctionComponent); 53 | } 54 | (component as any).$$devStack = DevStack.React; 55 | components[componentName] = component; 56 | } else { 57 | // @ts-ignore 58 | component = findComponent(libraryMap, componentName, component); 59 | if (component) { 60 | if (!acceptsRef(component)) { 61 | component = wrapReactClass(component as FunctionComponent); 62 | } 63 | components[componentName] = component; 64 | } 65 | } 66 | }); 67 | return components; 68 | } 69 | 70 | export function getSubComponent(library: any, paths: string[]) { 71 | const l = paths.length; 72 | if (l < 1 || !library) { 73 | return library; 74 | } 75 | let originLibrary = library; 76 | let i = 0; 77 | let component: any; 78 | while (i < l) { 79 | const key = paths[i]!; 80 | let ex: any; 81 | try { 82 | component = library[key]; 83 | component.$$devStack = originLibrary.$$devStack; 84 | } catch (e) { 85 | ex = e; 86 | component = null; 87 | } 88 | if (i === 0 && component == null && key === 'default') { 89 | if (ex) { 90 | return l === 1 ? library : null; 91 | } 92 | component = library; 93 | } else if (component == null) { 94 | return null; 95 | } 96 | library = component; 97 | library.$$devStack = originLibrary.$$devStack; 98 | i++; 99 | } 100 | return component; 101 | } 102 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/public/fixtures/basic-fusion-with-single-component/meta.js: -------------------------------------------------------------------------------- 1 | !function e(t,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.M220318Meta=n():t.M220318Meta=n()}(window,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function t(){return e.default}:function t(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){"use strict";n.r(t),n.d(t,"components",(function(){return S})),n.d(t,"componentList",(function(){return O}));var r={componentName:"M220318",title:"M220318",docUrl:"",screenshot:"",devMode:"proCode",npm:{package:"m-220318",version:"0.1.0",exportName:"default",main:"src/index.tsx",destructuring:!1,subName:""},configure:{props:[{title:{label:{type:"i18n","en-US":"title","zh-CN":"title"}},name:"title",setter:{componentName:"StringSetter",isRequired:!0,initialValue:""}},{title:{label:{type:"i18n","en-US":"content","zh-CN":"content"}},name:"content",setter:{componentName:"StringSetter",isRequired:!0,initialValue:""}},{title:{label:{type:"i18n","en-US":"ref","zh-CN":"ref"}},name:"ref",setter:{componentName:"MixedSetter",props:{setters:[{componentName:"FunctionSetter"},{componentName:"ObjectSetter",props:{config:{extraSetter:{componentName:"MixedSetter",isRequired:!1,props:{}}}},isRequired:!1,initialValue:{}}]}}},{title:{label:{type:"i18n","en-US":"key","zh-CN":"key"}},name:"key",setter:{componentName:"MixedSetter",props:{setters:[{componentName:"StringSetter",isRequired:!1,initialValue:""},{componentName:"NumberSetter",isRequired:!1,initialValue:0}]}}}],supports:{style:!0},component:{}}},o=[{title:"M220318",screenshot:"",schema:{componentName:"M220318",props:{}}}],i=Object.assign(Object.assign({},r),{snippets:o});function c(e){return l(e)||p(e)||u(e)||a()}function a(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function u(e,t){if(e){if("string"==typeof e)return s(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?s(e,t):void 0}}function p(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function l(e){if(Array.isArray(e))return s(e)}function s(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n1&&void 0!==arguments[1]?arguments[1]:"m-220318",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"0.1.0",r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{"@alifd/next":"1.25.23","@alifd/meet":"2.6.3",antd:"4.17.3"};if(!e||!n)return e;var o=e.npm;return o?("object"===d(r)&&r[o.package]?e.npm=m(m({},o),{},{version:r[o.package]}):o.package===t&&(e.npm=m(m({},o),{},{version:n})),e):e}["\u57fa\u7840\u5143\u7d20","\u5e03\u5c40\u5bb9\u5668\u7c7b","\u8868\u683c\u7c7b","\u8868\u5355\u8be6\u60c5\u7c7b","\u5e2e\u52a9\u7c7b","\u5bf9\u8bdd\u6846\u7c7b","\u4e1a\u52a1\u7c7b","\u901a\u7528","\u5f15\u5bfc","\u4fe1\u606f\u8f93\u5165","\u4fe1\u606f\u5c55\u793a","\u4fe1\u606f\u53cd\u9988"].reverse().forEach((function(e,t){b[e]=++t}));var v,S=[];[i].forEach((function(e){Array.isArray(e)?S.push.apply(S,c(e.map((function(e){return h(e)})))):e.components?S.push.apply(S,c(e.components.map((function(e){return h(e)})))):S.push(h(e))}));var O=g(S),j=!0}])})); -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/public/fixtures/basic-fusion-with-single-component/meta.js: -------------------------------------------------------------------------------- 1 | !function e(t,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.M220318Meta=n():t.M220318Meta=n()}(window,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function t(){return e.default}:function t(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){"use strict";n.r(t),n.d(t,"components",(function(){return S})),n.d(t,"componentList",(function(){return O}));var r={componentName:"M220318",title:"M220318",docUrl:"",screenshot:"",devMode:"proCode",npm:{package:"m-220318",version:"0.1.0",exportName:"default",main:"src/index.tsx",destructuring:!1,subName:""},configure:{props:[{title:{label:{type:"i18n","en-US":"title","zh-CN":"title"}},name:"title",setter:{componentName:"StringSetter",isRequired:!0,initialValue:""}},{title:{label:{type:"i18n","en-US":"content","zh-CN":"content"}},name:"content",setter:{componentName:"StringSetter",isRequired:!0,initialValue:""}},{title:{label:{type:"i18n","en-US":"ref","zh-CN":"ref"}},name:"ref",setter:{componentName:"MixedSetter",props:{setters:[{componentName:"FunctionSetter"},{componentName:"ObjectSetter",props:{config:{extraSetter:{componentName:"MixedSetter",isRequired:!1,props:{}}}},isRequired:!1,initialValue:{}}]}}},{title:{label:{type:"i18n","en-US":"key","zh-CN":"key"}},name:"key",setter:{componentName:"MixedSetter",props:{setters:[{componentName:"StringSetter",isRequired:!1,initialValue:""},{componentName:"NumberSetter",isRequired:!1,initialValue:0}]}}}],supports:{style:!0},component:{}}},o=[{title:"M220318",screenshot:"",schema:{componentName:"M220318",props:{}}}],i=Object.assign(Object.assign({},r),{snippets:o});function c(e){return l(e)||p(e)||u(e)||a()}function a(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function u(e,t){if(e){if("string"==typeof e)return s(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?s(e,t):void 0}}function p(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function l(e){if(Array.isArray(e))return s(e)}function s(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n1&&void 0!==arguments[1]?arguments[1]:"m-220318",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"0.1.0",r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{"@alifd/next":"1.25.23","@alifd/meet":"2.6.3",antd:"4.17.3"};if(!e||!n)return e;var o=e.npm;return o?("object"===d(r)&&r[o.package]?e.npm=m(m({},o),{},{version:r[o.package]}):o.package===t&&(e.npm=m(m({},o),{},{version:n})),e):e}["\u57fa\u7840\u5143\u7d20","\u5e03\u5c40\u5bb9\u5668\u7c7b","\u8868\u683c\u7c7b","\u8868\u5355\u8be6\u60c5\u7c7b","\u5e2e\u52a9\u7c7b","\u5bf9\u8bdd\u6846\u7c7b","\u4e1a\u52a1\u7c7b","\u901a\u7528","\u5f15\u5bfc","\u4fe1\u606f\u8f93\u5165","\u4fe1\u606f\u5c55\u793a","\u4fe1\u606f\u53cd\u9988"].reverse().forEach((function(e,t){b[e]=++t}));var v,S=[];[i].forEach((function(e){Array.isArray(e)?S.push.apply(S,c(e.map((function(e){return h(e)})))):e.components?S.push.apply(S,c(e.components.map((function(e){return h(e)})))):S.push(h(e))}));var O=g(S),j=!0}])})); -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/src/universal/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | { 4 | "package": "moment", 5 | "version": "2.24.0", 6 | "urls": [ 7 | "https://g.alicdn.com/mylib/moment/2.24.0/min/moment.min.js" 8 | ], 9 | "library": "moment" 10 | }, 11 | { 12 | "package": "lodash", 13 | "library": "_", 14 | "urls": [ 15 | "https://g.alicdn.com/platform/c/lodash/4.6.1/lodash.min.js" 16 | ] 17 | }, 18 | { 19 | "package": "vue", 20 | "library": "Vue", 21 | "urls": [ 22 | "./vue/vue.global.js" 23 | ] 24 | }, 25 | { 26 | "title": "fusion组件库", 27 | "package": "@alifd/next", 28 | "version": "1.24.18", 29 | "urls": [ 30 | "https://g.alicdn.com/code/lib/alifd__next/1.24.18/next.min.css", 31 | "https://g.alicdn.com/code/lib/alifd__next/1.24.18/next-with-locales.min.js" 32 | ], 33 | "library": "Next" 34 | }, 35 | { 36 | "title": "NextTable", 37 | "package": "NextTable", 38 | "version": "1.0.1", 39 | "urls": [ 40 | "https://g.alicdn.com/fusion-platform/pro-table/1.0.1/next-table.js", 41 | "https://g.alicdn.com/fusion-platform/pro-table/1.0.1/next-table.css" 42 | ], 43 | "library": "NextTable" 44 | }, 45 | { 46 | "package": "@alilc/lowcode-materials", 47 | "version": "1.0.2", 48 | "library": "AlilcLowcodeMaterials", 49 | "urls": [ 50 | "https://alifd.alicdn.com/npm/@alilc/lowcode-materials@1.0.2/dist/AlilcLowcodeMaterials.js", 51 | "https://alifd.alicdn.com/npm/@alilc/lowcode-materials@1.0.2/dist/AlilcLowcodeMaterials.css" 52 | ], 53 | "editUrls": [ 54 | "https://alifd.alicdn.com/npm/@alilc/lowcode-materials@1.0.2/build/lowcode/view.js", 55 | "https://alifd.alicdn.com/npm/@alilc/lowcode-materials@1.0.2/build/lowcode/view.css" 56 | ] 57 | }, 58 | { 59 | "package": "@alifd/pro-layout", 60 | "version": "1.0.1-beta.6", 61 | "library": "AlifdProLayout", 62 | "urls": [ 63 | "https://alifd.alicdn.com/npm/@alifd/pro-layout@1.0.1-beta.6/dist/AlifdProLayout.js", 64 | "https://alifd.alicdn.com/npm/@alifd/pro-layout@1.0.1-beta.6/dist/AlifdProLayout.css" 65 | ], 66 | "editUrls": [ 67 | "https://alifd.alicdn.com/npm/@alifd/pro-layout@1.0.1-beta.6/build/lowcode/view.js", 68 | "https://alifd.alicdn.com/npm/@alifd/pro-layout@1.0.1-beta.6/build/lowcode/view.css" 69 | ] 70 | }, 71 | { 72 | "package": "@alifd/fusion-ui", 73 | "version": "1.0.5", 74 | "library": "AlifdFusionUi", 75 | "urls": [ 76 | "https://alifd.alicdn.com/npm/@alifd/fusion-ui@1.0.5/dist/AlifdFusionUi.js", 77 | "https://alifd.alicdn.com/npm/@alifd/fusion-ui@1.0.5/dist/AlifdFusionUi.css" 78 | ], 79 | "editUrls": [ 80 | "https://alifd.alicdn.com/npm/@alifd/fusion-ui@1.0.5/build/lowcode/view.js", 81 | "https://alifd.alicdn.com/npm/@alifd/fusion-ui@1.0.5/build/lowcode/view.css" 82 | ] 83 | }, 84 | { 85 | "package": "tdesign-vue-next", 86 | "version": "0.15.4", 87 | "urls": [ 88 | "./tdesign/tdesign.min.css", 89 | "./tdesign/tdesign.min.js" 90 | ], 91 | "library": "TDesign" 92 | } 93 | ], 94 | "components": [ 95 | { 96 | "exportName": "AlilcLowcodeMaterialsMeta", 97 | "npm": { 98 | "package": "@alilc/lowcode-materials" 99 | }, 100 | "url": "https://alifd.alicdn.com/npm/@alilc/lowcode-materials@1.0.2/build/lowcode/meta.js", 101 | "urls": { 102 | "default": "https://alifd.alicdn.com/npm/@alilc/lowcode-materials@1.0.2/build/lowcode/meta.js", 103 | "design": "https://alifd.alicdn.com/npm/@alilc/lowcode-materials@1.0.2/build/lowcode/meta.design.js" 104 | } 105 | }, 106 | { 107 | "exportName": "AlifdProLayoutMeta", 108 | "npm": { 109 | "package": "@alifd/pro-layout", 110 | "version": "1.0.1-beta.6" 111 | }, 112 | "url": "https://alifd.alicdn.com/npm/@alifd/pro-layout@1.0.1-beta.6/build/lowcode/meta.js", 113 | "urls": { 114 | "default": "https://alifd.alicdn.com/npm/@alifd/pro-layout@1.0.1-beta.6/build/lowcode/meta.js", 115 | "design": "https://alifd.alicdn.com/npm/@alifd/pro-layout@1.0.1-beta.6/build/lowcode/meta.design.js" 116 | } 117 | }, 118 | { 119 | "exportName": "AlifdFusionUiMeta", 120 | "npm": { 121 | "package": "@alifd/fusion-ui" 122 | }, 123 | "url": "https://alifd.alicdn.com/npm/@alifd/fusion-ui@1.0.5/build/lowcode/meta.js", 124 | "urls": { 125 | "default": "https://alifd.alicdn.com/npm/@alifd/fusion-ui@1.0.5/build/lowcode/meta.js", 126 | "design": "https://alifd.alicdn.com/npm/@alifd/fusion-ui@1.0.5/build/lowcode/meta.design.js" 127 | } 128 | }, 129 | { 130 | "componentName": "TButton", 131 | "title": "按钮", 132 | "npm": { 133 | "package": "tdesign-vue-next", 134 | "version": "0.15.4", 135 | "exportName": "Button", 136 | "destructuring": true, 137 | "devStack": "vue3" 138 | }, 139 | "props": [ 140 | { 141 | "name": "theme", 142 | "propType": "string" 143 | } 144 | ], 145 | "configure": { 146 | "component": { 147 | "isContainer": false 148 | }, 149 | "supports": { 150 | "style": true, 151 | "events": [ 152 | { 153 | "name": "onClick", 154 | "template": "onClick(e){\n// click\nconsole.log('click', e);}" 155 | } 156 | ] 157 | }, 158 | "props": { 159 | "isExtends": true, 160 | "override": [ 161 | { 162 | "name": "theme", 163 | "title": "主题", 164 | "setter": { 165 | "componentName": "StringSetter" 166 | } 167 | }, 168 | { 169 | "name": "class", 170 | "setter": { 171 | "componentName": "ClassNameSetter" 172 | } 173 | } 174 | ] 175 | } 176 | }, 177 | "group": "自定义", 178 | "category": "基础元素", 179 | "snippets": [ 180 | { 181 | "title": "按钮", 182 | "screenshot": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_button.png", 183 | "schema": { 184 | "componentName": "TButton", 185 | "props": { 186 | "theme": "success" 187 | }, 188 | "children": [ 189 | { 190 | "componentName": "NextText", 191 | "props": { 192 | "children": "按钮" 193 | } 194 | } 195 | ] 196 | } 197 | } 198 | ] 199 | } 200 | ], 201 | "sort": { 202 | "groupList": [ 203 | "精选组件", 204 | "原子组件" 205 | ], 206 | "categoryList": [ 207 | "基础元素", 208 | "布局容器类", 209 | "表格类", 210 | "表单详情类", 211 | "帮助类", 212 | "对话框类", 213 | "业务类", 214 | "通用", 215 | "引导", 216 | "信息输入", 217 | "信息展示", 218 | "信息反馈" 219 | ] 220 | }, 221 | "groupList": [ 222 | "精选组件", 223 | "原子组件" 224 | ], 225 | "ignoreComponents": {} 226 | } 227 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/src/universal/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | { 4 | "package": "moment", 5 | "version": "2.24.0", 6 | "urls": [ 7 | "https://g.alicdn.com/mylib/moment/2.24.0/min/moment.min.js" 8 | ], 9 | "library": "moment" 10 | }, 11 | { 12 | "package": "lodash", 13 | "library": "_", 14 | "urls": [ 15 | "https://g.alicdn.com/platform/c/lodash/4.6.1/lodash.min.js" 16 | ] 17 | }, 18 | { 19 | "package": "vue", 20 | "library": "Vue", 21 | "urls": [ 22 | "./vue/vue.js" 23 | ] 24 | }, 25 | { 26 | "title": "fusion组件库", 27 | "package": "@alifd/next", 28 | "version": "1.24.18", 29 | "urls": [ 30 | "https://g.alicdn.com/code/lib/alifd__next/1.24.18/next.min.css", 31 | "https://g.alicdn.com/code/lib/alifd__next/1.24.18/next-with-locales.min.js" 32 | ], 33 | "library": "Next" 34 | }, 35 | { 36 | "title": "NextTable", 37 | "package": "NextTable", 38 | "version": "1.0.1", 39 | "urls": [ 40 | "https://g.alicdn.com/fusion-platform/pro-table/1.0.1/next-table.js", 41 | "https://g.alicdn.com/fusion-platform/pro-table/1.0.1/next-table.css" 42 | ], 43 | "library": "NextTable" 44 | }, 45 | { 46 | "package": "@alilc/lowcode-materials", 47 | "version": "1.0.2", 48 | "library": "AlilcLowcodeMaterials", 49 | "urls": [ 50 | "https://alifd.alicdn.com/npm/@alilc/lowcode-materials@1.0.2/dist/AlilcLowcodeMaterials.js", 51 | "https://alifd.alicdn.com/npm/@alilc/lowcode-materials@1.0.2/dist/AlilcLowcodeMaterials.css" 52 | ], 53 | "editUrls": [ 54 | "https://alifd.alicdn.com/npm/@alilc/lowcode-materials@1.0.2/build/lowcode/view.js", 55 | "https://alifd.alicdn.com/npm/@alilc/lowcode-materials@1.0.2/build/lowcode/view.css" 56 | ] 57 | }, 58 | { 59 | "package": "@alifd/pro-layout", 60 | "version": "1.0.1-beta.6", 61 | "library": "AlifdProLayout", 62 | "urls": [ 63 | "https://alifd.alicdn.com/npm/@alifd/pro-layout@1.0.1-beta.6/dist/AlifdProLayout.js", 64 | "https://alifd.alicdn.com/npm/@alifd/pro-layout@1.0.1-beta.6/dist/AlifdProLayout.css" 65 | ], 66 | "editUrls": [ 67 | "https://alifd.alicdn.com/npm/@alifd/pro-layout@1.0.1-beta.6/build/lowcode/view.js", 68 | "https://alifd.alicdn.com/npm/@alifd/pro-layout@1.0.1-beta.6/build/lowcode/view.css" 69 | ] 70 | }, 71 | { 72 | "package": "@alifd/fusion-ui", 73 | "version": "1.0.5", 74 | "library": "AlifdFusionUi", 75 | "urls": [ 76 | "https://alifd.alicdn.com/npm/@alifd/fusion-ui@1.0.5/dist/AlifdFusionUi.js", 77 | "https://alifd.alicdn.com/npm/@alifd/fusion-ui@1.0.5/dist/AlifdFusionUi.css" 78 | ], 79 | "editUrls": [ 80 | "https://alifd.alicdn.com/npm/@alifd/fusion-ui@1.0.5/build/lowcode/view.js", 81 | "https://alifd.alicdn.com/npm/@alifd/fusion-ui@1.0.5/build/lowcode/view.css" 82 | ] 83 | }, 84 | { 85 | "package": "element-ui", 86 | "version": "2.15.9", 87 | "urls": [ 88 | "https://unpkg.com/element-ui/lib/theme-chalk/index.css", 89 | "https://unpkg.com/element-ui/lib/index.js" 90 | ], 91 | "library": "ELEMENT" 92 | } 93 | ], 94 | "components": [ 95 | { 96 | "exportName": "AlilcLowcodeMaterialsMeta", 97 | "npm": { 98 | "package": "@alilc/lowcode-materials" 99 | }, 100 | "url": "https://alifd.alicdn.com/npm/@alilc/lowcode-materials@1.0.2/build/lowcode/meta.js", 101 | "urls": { 102 | "default": "https://alifd.alicdn.com/npm/@alilc/lowcode-materials@1.0.2/build/lowcode/meta.js", 103 | "design": "https://alifd.alicdn.com/npm/@alilc/lowcode-materials@1.0.2/build/lowcode/meta.design.js" 104 | } 105 | }, 106 | { 107 | "exportName": "AlifdProLayoutMeta", 108 | "npm": { 109 | "package": "@alifd/pro-layout", 110 | "version": "1.0.1-beta.6" 111 | }, 112 | "url": "https://alifd.alicdn.com/npm/@alifd/pro-layout@1.0.1-beta.6/build/lowcode/meta.js", 113 | "urls": { 114 | "default": "https://alifd.alicdn.com/npm/@alifd/pro-layout@1.0.1-beta.6/build/lowcode/meta.js", 115 | "design": "https://alifd.alicdn.com/npm/@alifd/pro-layout@1.0.1-beta.6/build/lowcode/meta.design.js" 116 | } 117 | }, 118 | { 119 | "exportName": "AlifdFusionUiMeta", 120 | "npm": { 121 | "package": "@alifd/fusion-ui" 122 | }, 123 | "url": "https://alifd.alicdn.com/npm/@alifd/fusion-ui@1.0.5/build/lowcode/meta.js", 124 | "urls": { 125 | "default": "https://alifd.alicdn.com/npm/@alifd/fusion-ui@1.0.5/build/lowcode/meta.js", 126 | "design": "https://alifd.alicdn.com/npm/@alifd/fusion-ui@1.0.5/build/lowcode/meta.design.js" 127 | } 128 | }, 129 | { 130 | "componentName": "ELButton", 131 | "title": "按钮", 132 | "npm": { 133 | "package": "element-ui", 134 | "version": "2.15.9", 135 | "exportName": "Button", 136 | "destructuring": true, 137 | "devStack": "vue2" 138 | }, 139 | "props": [ 140 | { 141 | "name": "type", 142 | "propType": "string" 143 | } 144 | ], 145 | "configure": { 146 | "component": { 147 | "isContainer": false 148 | }, 149 | "supports": { 150 | "style": true, 151 | "events": [ 152 | { 153 | "name": "onClick", 154 | "template": "onClick(e){\n// click\nconsole.log('click', e);}" 155 | } 156 | ] 157 | }, 158 | "props": { 159 | "isExtends": true, 160 | "override": [ 161 | { 162 | "name": "type", 163 | "title": "类型", 164 | "setter": { 165 | "componentName": "StringSetter" 166 | } 167 | }, 168 | { 169 | "name": "class", 170 | "setter": { 171 | "componentName": "ClassNameSetter" 172 | } 173 | } 174 | ] 175 | } 176 | }, 177 | "group": "自定义", 178 | "category": "基础元素", 179 | "snippets": [ 180 | { 181 | "title": "按钮", 182 | "screenshot": "https://alifd.oss-cn-hangzhou.aliyuncs.com/fusion-cool/icons/icon-light/ic_light_button.png", 183 | "schema": { 184 | "componentName": "ELButton", 185 | "props": { 186 | "type": "danger" 187 | }, 188 | "children": [ 189 | { 190 | "componentName": "NextText", 191 | "props": { 192 | "children": "按钮" 193 | } 194 | } 195 | ] 196 | } 197 | } 198 | ] 199 | } 200 | ], 201 | "sort": { 202 | "groupList": [ 203 | "精选组件", 204 | "原子组件" 205 | ], 206 | "categoryList": [ 207 | "基础元素", 208 | "布局容器类", 209 | "表格类", 210 | "表单详情类", 211 | "帮助类", 212 | "对话框类", 213 | "业务类", 214 | "通用", 215 | "引导", 216 | "信息输入", 217 | "信息展示", 218 | "信息反馈" 219 | ] 220 | }, 221 | "groupList": [ 222 | "精选组件", 223 | "原子组件" 224 | ], 225 | "ignoreComponents": {} 226 | } 227 | -------------------------------------------------------------------------------- /examples/lowcode-vue2-demo/src/universal/plugin.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | ILowCodePluginContext, 4 | plugins, 5 | skeleton, 6 | project, 7 | setters, 8 | } from '@alilc/lowcode-engine'; 9 | import AliLowCodeEngineExt from '@alilc/lowcode-engine-ext'; 10 | import { Button } from '@alifd/next'; 11 | import UndoRedoPlugin from '@alilc/lowcode-plugin-undo-redo'; 12 | import ComponentsPane from '@alilc/lowcode-plugin-components-pane'; 13 | import ZhEnPlugin from '@alilc/lowcode-plugin-zh-en'; 14 | import CodeGenPlugin from '@alilc/lowcode-plugin-code-generator'; 15 | import DataSourcePanePlugin from '@alilc/lowcode-plugin-datasource-pane'; 16 | import SchemaPlugin from '@alilc/lowcode-plugin-schema'; 17 | import CodeEditor from '@alilc/lowcode-plugin-code-editor'; 18 | import ManualPlugin from '@alilc/lowcode-plugin-manual'; 19 | import Inject, { injectAssets } from '@alilc/lowcode-plugin-inject'; 20 | import SimulatorResizer from '@alilc/lowcode-plugin-simulator-select'; 21 | 22 | // 注册到引擎 23 | import TitleSetter from '@alilc/lowcode-setter-title'; 24 | import BehaviorSetter from '../setters/behavior-setter'; 25 | import CustomSetter from '../setters/custom-setter'; 26 | import Logo from '../sample-plugins/logo'; 27 | import { deleteHiddenTransducer } from '../sample-plugins/delete-hidden-transducer'; 28 | 29 | import { 30 | loadIncrementalAssets, 31 | getPageSchema, 32 | saveSchema, 33 | resetSchema, 34 | preview, 35 | } from './utils'; 36 | import assets from './assets.json'; 37 | import { registerRefProp } from 'src/sample-plugins/set-ref-prop'; 38 | 39 | export default async function registerPlugins() { 40 | await plugins.register(ManualPlugin); 41 | 42 | await plugins.register(Inject); 43 | 44 | await plugins.register(registerRefProp); 45 | 46 | await plugins.register(deleteHiddenTransducer); 47 | 48 | // plugin API 见 https://lowcode-engine.cn/docV2/ibh9fh 49 | SchemaPlugin.pluginName = 'SchemaPlugin'; 50 | await plugins.register(SchemaPlugin); 51 | 52 | SimulatorResizer.pluginName = 'SimulatorResizer'; 53 | plugins.register(SimulatorResizer); 54 | 55 | const editorInit = (ctx: ILowCodePluginContext) => { 56 | return { 57 | name: 'editor-init', 58 | async init() { 59 | // 修改面包屑组件的分隔符属性setter 60 | // const assets = await ( 61 | // await fetch( 62 | // `https://alifd.alicdn.com/npm/@alilc/lowcode-materials/build/lowcode/assets-prod.json` 63 | // ) 64 | // ).json(); 65 | // 设置物料描述 66 | const { material, project } = ctx; 67 | 68 | await material.setAssets(await injectAssets(assets)); 69 | 70 | const schema = await getPageSchema(); 71 | 72 | // 加载 schema 73 | project.openDocument(schema); 74 | }, 75 | }; 76 | }; 77 | editorInit.pluginName = 'editorInit'; 78 | await plugins.register(editorInit); 79 | 80 | const builtinPluginRegistry = (ctx: ILowCodePluginContext) => { 81 | return { 82 | name: 'builtin-plugin-registry', 83 | async init() { 84 | const { skeleton } = ctx; 85 | // 注册 logo 面板 86 | skeleton.add({ 87 | area: 'topArea', 88 | type: 'Widget', 89 | name: 'logo', 90 | content: Logo, 91 | contentProps: { 92 | logo: 'https://img.alicdn.com/imgextra/i4/O1CN013w2bmQ25WAIha4Hx9_!!6000000007533-55-tps-137-26.svg', 93 | href: 'https://lowcode-engine.cn', 94 | }, 95 | props: { 96 | align: 'left', 97 | }, 98 | }); 99 | 100 | // 注册组件面板 101 | const componentsPane = skeleton.add({ 102 | area: 'leftArea', 103 | type: 'PanelDock', 104 | name: 'componentsPane', 105 | content: ComponentsPane, 106 | contentProps: {}, 107 | props: { 108 | align: 'top', 109 | icon: 'zujianku', 110 | description: '组件库', 111 | }, 112 | }); 113 | componentsPane?.disable?.(); 114 | project.onSimulatorRendererReady(() => { 115 | componentsPane?.enable?.(); 116 | }); 117 | }, 118 | }; 119 | }; 120 | builtinPluginRegistry.pluginName = 'builtinPluginRegistry'; 121 | await plugins.register(builtinPluginRegistry); 122 | 123 | // 设置内置 setter 和事件绑定、插件绑定面板 124 | const setterRegistry = (ctx: ILowCodePluginContext) => { 125 | const { setterMap, pluginMap } = AliLowCodeEngineExt; 126 | return { 127 | name: 'ext-setters-registry', 128 | async init() { 129 | const { setters, skeleton } = ctx; 130 | // 注册setterMap 131 | setters.registerSetter(setterMap); 132 | // 注册插件 133 | // 注册事件绑定面板 134 | skeleton.add({ 135 | area: 'centerArea', 136 | type: 'Widget', 137 | content: pluginMap.EventBindDialog, 138 | name: 'eventBindDialog', 139 | props: {}, 140 | }); 141 | 142 | // 注册变量绑定面板 143 | skeleton.add({ 144 | area: 'centerArea', 145 | type: 'Widget', 146 | content: pluginMap.VariableBindDialog, 147 | name: 'variableBindDialog', 148 | props: {}, 149 | }); 150 | }, 151 | }; 152 | }; 153 | setterRegistry.pluginName = 'setterRegistry'; 154 | await plugins.register(setterRegistry); 155 | 156 | // 注册回退/前进 157 | await plugins.register(UndoRedoPlugin); 158 | 159 | // 注册中英文切换 160 | await plugins.register(ZhEnPlugin); 161 | 162 | const loadAssetsSample = (ctx: ILowCodePluginContext) => { 163 | return { 164 | name: 'loadAssetsSample', 165 | async init() { 166 | const { skeleton } = ctx; 167 | 168 | skeleton.add({ 169 | name: 'loadAssetsSample', 170 | area: 'topArea', 171 | type: 'Widget', 172 | props: { 173 | align: 'right', 174 | width: 80, 175 | }, 176 | content: ( 177 | 180 | ), 181 | }); 182 | }, 183 | }; 184 | }; 185 | loadAssetsSample.pluginName = 'loadAssetsSample'; 186 | await plugins.register(loadAssetsSample); 187 | 188 | // 注册保存面板 189 | const saveSample = (ctx: ILowCodePluginContext) => { 190 | return { 191 | name: 'saveSample', 192 | async init() { 193 | const { skeleton, hotkey } = ctx; 194 | 195 | skeleton.add({ 196 | name: 'saveSample', 197 | area: 'topArea', 198 | type: 'Widget', 199 | props: { 200 | align: 'right', 201 | }, 202 | content: ( 203 | 206 | ), 207 | }); 208 | skeleton.add({ 209 | name: 'resetSchema', 210 | area: 'topArea', 211 | type: 'Widget', 212 | props: { 213 | align: 'right', 214 | }, 215 | content: ( 216 | 219 | ), 220 | }); 221 | hotkey.bind('command+s', (e) => { 222 | e.preventDefault(); 223 | saveSchema(); 224 | }); 225 | }, 226 | }; 227 | }; 228 | saveSample.pluginName = 'saveSample'; 229 | await plugins.register(saveSample); 230 | 231 | DataSourcePanePlugin.pluginName = 'DataSourcePane'; 232 | await plugins.register(DataSourcePanePlugin); 233 | 234 | CodeEditor.pluginName = 'CodeEditor'; 235 | await plugins.register(CodeEditor); 236 | 237 | // 注册出码插件 238 | CodeGenPlugin.pluginName = 'CodeGenPlugin'; 239 | await plugins.register(CodeGenPlugin); 240 | 241 | const previewSample = (ctx: ILowCodePluginContext) => { 242 | return { 243 | name: 'previewSample', 244 | async init() { 245 | const { skeleton } = ctx; 246 | skeleton.add({ 247 | name: 'previewSample', 248 | area: 'topArea', 249 | type: 'Widget', 250 | props: { 251 | align: 'right', 252 | }, 253 | content: ( 254 | 257 | ), 258 | }); 259 | }, 260 | }; 261 | }; 262 | previewSample.pluginName = 'previewSample'; 263 | await plugins.register(previewSample); 264 | 265 | const customSetter = (ctx: ILowCodePluginContext) => { 266 | return { 267 | name: '___registerCustomSetter___', 268 | async init() { 269 | const { setters } = ctx; 270 | 271 | setters.registerSetter('TitleSetter', TitleSetter); 272 | setters.registerSetter('BehaviorSetter', BehaviorSetter); 273 | setters.registerSetter('CustomSetter', CustomSetter); 274 | }, 275 | }; 276 | }; 277 | customSetter.pluginName = 'customSetter'; 278 | await plugins.register(customSetter); 279 | } 280 | -------------------------------------------------------------------------------- /examples/lowcode-vue3-demo/src/universal/plugin.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | ILowCodePluginContext, 4 | plugins, 5 | skeleton, 6 | project, 7 | setters, 8 | } from '@alilc/lowcode-engine'; 9 | import AliLowCodeEngineExt from '@alilc/lowcode-engine-ext'; 10 | import { Button } from '@alifd/next'; 11 | import UndoRedoPlugin from '@alilc/lowcode-plugin-undo-redo'; 12 | import ComponentsPane from '@alilc/lowcode-plugin-components-pane'; 13 | import ZhEnPlugin from '@alilc/lowcode-plugin-zh-en'; 14 | import CodeGenPlugin from '@alilc/lowcode-plugin-code-generator'; 15 | import DataSourcePanePlugin from '@alilc/lowcode-plugin-datasource-pane'; 16 | import SchemaPlugin from '@alilc/lowcode-plugin-schema'; 17 | import CodeEditor from '@alilc/lowcode-plugin-code-editor'; 18 | import ManualPlugin from '@alilc/lowcode-plugin-manual'; 19 | import Inject, { injectAssets } from '@alilc/lowcode-plugin-inject'; 20 | import SimulatorResizer from '@alilc/lowcode-plugin-simulator-select'; 21 | 22 | // 注册到引擎 23 | import TitleSetter from '@alilc/lowcode-setter-title'; 24 | import BehaviorSetter from '../setters/behavior-setter'; 25 | import CustomSetter from '../setters/custom-setter'; 26 | import Logo from '../sample-plugins/logo'; 27 | import { deleteHiddenTransducer } from '../sample-plugins/delete-hidden-transducer'; 28 | 29 | import { 30 | loadIncrementalAssets, 31 | getPageSchema, 32 | saveSchema, 33 | resetSchema, 34 | preview, 35 | } from './utils'; 36 | import assets from './assets.json'; 37 | import { registerRefProp } from 'src/sample-plugins/set-ref-prop'; 38 | 39 | export default async function registerPlugins() { 40 | await plugins.register(ManualPlugin); 41 | 42 | await plugins.register(Inject); 43 | 44 | await plugins.register(registerRefProp); 45 | 46 | await plugins.register(deleteHiddenTransducer); 47 | 48 | // plugin API 见 https://lowcode-engine.cn/docV2/ibh9fh 49 | SchemaPlugin.pluginName = 'SchemaPlugin'; 50 | await plugins.register(SchemaPlugin); 51 | 52 | SimulatorResizer.pluginName = 'SimulatorResizer'; 53 | plugins.register(SimulatorResizer); 54 | 55 | const editorInit = (ctx: ILowCodePluginContext) => { 56 | return { 57 | name: 'editor-init', 58 | async init() { 59 | // 修改面包屑组件的分隔符属性setter 60 | // const assets = await ( 61 | // await fetch( 62 | // `https://alifd.alicdn.com/npm/@alilc/lowcode-materials/build/lowcode/assets-prod.json` 63 | // ) 64 | // ).json(); 65 | // 设置物料描述 66 | const { material, project } = ctx; 67 | 68 | await material.setAssets(await injectAssets(assets)); 69 | 70 | const schema = await getPageSchema(); 71 | 72 | // 加载 schema 73 | project.openDocument(schema); 74 | }, 75 | }; 76 | }; 77 | editorInit.pluginName = 'editorInit'; 78 | await plugins.register(editorInit); 79 | 80 | const builtinPluginRegistry = (ctx: ILowCodePluginContext) => { 81 | return { 82 | name: 'builtin-plugin-registry', 83 | async init() { 84 | const { skeleton } = ctx; 85 | // 注册 logo 面板 86 | skeleton.add({ 87 | area: 'topArea', 88 | type: 'Widget', 89 | name: 'logo', 90 | content: Logo, 91 | contentProps: { 92 | logo: 'https://img.alicdn.com/imgextra/i4/O1CN013w2bmQ25WAIha4Hx9_!!6000000007533-55-tps-137-26.svg', 93 | href: 'https://lowcode-engine.cn', 94 | }, 95 | props: { 96 | align: 'left', 97 | }, 98 | }); 99 | 100 | // 注册组件面板 101 | const componentsPane = skeleton.add({ 102 | area: 'leftArea', 103 | type: 'PanelDock', 104 | name: 'componentsPane', 105 | content: ComponentsPane, 106 | contentProps: {}, 107 | props: { 108 | align: 'top', 109 | icon: 'zujianku', 110 | description: '组件库', 111 | }, 112 | }); 113 | componentsPane?.disable?.(); 114 | project.onSimulatorRendererReady(() => { 115 | componentsPane?.enable?.(); 116 | }); 117 | }, 118 | }; 119 | }; 120 | builtinPluginRegistry.pluginName = 'builtinPluginRegistry'; 121 | await plugins.register(builtinPluginRegistry); 122 | 123 | // 设置内置 setter 和事件绑定、插件绑定面板 124 | const setterRegistry = (ctx: ILowCodePluginContext) => { 125 | const { setterMap, pluginMap } = AliLowCodeEngineExt; 126 | return { 127 | name: 'ext-setters-registry', 128 | async init() { 129 | const { setters, skeleton } = ctx; 130 | // 注册setterMap 131 | setters.registerSetter(setterMap); 132 | // 注册插件 133 | // 注册事件绑定面板 134 | skeleton.add({ 135 | area: 'centerArea', 136 | type: 'Widget', 137 | content: pluginMap.EventBindDialog, 138 | name: 'eventBindDialog', 139 | props: {}, 140 | }); 141 | 142 | // 注册变量绑定面板 143 | skeleton.add({ 144 | area: 'centerArea', 145 | type: 'Widget', 146 | content: pluginMap.VariableBindDialog, 147 | name: 'variableBindDialog', 148 | props: {}, 149 | }); 150 | }, 151 | }; 152 | }; 153 | setterRegistry.pluginName = 'setterRegistry'; 154 | await plugins.register(setterRegistry); 155 | 156 | // 注册回退/前进 157 | await plugins.register(UndoRedoPlugin); 158 | 159 | // 注册中英文切换 160 | await plugins.register(ZhEnPlugin); 161 | 162 | const loadAssetsSample = (ctx: ILowCodePluginContext) => { 163 | return { 164 | name: 'loadAssetsSample', 165 | async init() { 166 | const { skeleton } = ctx; 167 | 168 | skeleton.add({ 169 | name: 'loadAssetsSample', 170 | area: 'topArea', 171 | type: 'Widget', 172 | props: { 173 | align: 'right', 174 | width: 80, 175 | }, 176 | content: ( 177 | 180 | ), 181 | }); 182 | }, 183 | }; 184 | }; 185 | loadAssetsSample.pluginName = 'loadAssetsSample'; 186 | await plugins.register(loadAssetsSample); 187 | 188 | // 注册保存面板 189 | const saveSample = (ctx: ILowCodePluginContext) => { 190 | return { 191 | name: 'saveSample', 192 | async init() { 193 | const { skeleton, hotkey } = ctx; 194 | 195 | skeleton.add({ 196 | name: 'saveSample', 197 | area: 'topArea', 198 | type: 'Widget', 199 | props: { 200 | align: 'right', 201 | }, 202 | content: ( 203 | 206 | ), 207 | }); 208 | skeleton.add({ 209 | name: 'resetSchema', 210 | area: 'topArea', 211 | type: 'Widget', 212 | props: { 213 | align: 'right', 214 | }, 215 | content: ( 216 | 219 | ), 220 | }); 221 | hotkey.bind('command+s', (e) => { 222 | e.preventDefault(); 223 | saveSchema(); 224 | }); 225 | }, 226 | }; 227 | }; 228 | saveSample.pluginName = 'saveSample'; 229 | await plugins.register(saveSample); 230 | 231 | DataSourcePanePlugin.pluginName = 'DataSourcePane'; 232 | await plugins.register(DataSourcePanePlugin); 233 | 234 | CodeEditor.pluginName = 'CodeEditor'; 235 | await plugins.register(CodeEditor); 236 | 237 | // 注册出码插件 238 | CodeGenPlugin.pluginName = 'CodeGenPlugin'; 239 | await plugins.register(CodeGenPlugin); 240 | 241 | const previewSample = (ctx: ILowCodePluginContext) => { 242 | return { 243 | name: 'previewSample', 244 | async init() { 245 | const { skeleton } = ctx; 246 | skeleton.add({ 247 | name: 'previewSample', 248 | area: 'topArea', 249 | type: 'Widget', 250 | props: { 251 | align: 'right', 252 | }, 253 | content: ( 254 | 257 | ), 258 | }); 259 | }, 260 | }; 261 | }; 262 | previewSample.pluginName = 'previewSample'; 263 | await plugins.register(previewSample); 264 | 265 | const customSetter = (ctx: ILowCodePluginContext) => { 266 | return { 267 | name: '___registerCustomSetter___', 268 | async init() { 269 | const { setters } = ctx; 270 | 271 | setters.registerSetter('TitleSetter', TitleSetter); 272 | setters.registerSetter('BehaviorSetter', BehaviorSetter); 273 | setters.registerSetter('CustomSetter', CustomSetter); 274 | }, 275 | }; 276 | }; 277 | customSetter.pluginName = 'customSetter'; 278 | await plugins.register(customSetter); 279 | } 280 | -------------------------------------------------------------------------------- /packages/vue2-simulator-renderer/src/builtin-components/builtin-components.ts: -------------------------------------------------------------------------------- 1 | import { ReactElement, createElement, ReactType } from 'react'; 2 | import classNames from 'classnames'; 3 | 4 | const supportedEvents = [ 5 | // MouseEvents 6 | { 7 | name: 'onClick', 8 | description: '点击时', 9 | }, 10 | { 11 | name: 'onDoubleClick', 12 | description: '双击时', 13 | }, 14 | { 15 | name: 'onMouseDown', 16 | description: '鼠标按下', 17 | }, 18 | { 19 | name: 'onMouseEnter', 20 | description: '鼠标进入', 21 | }, 22 | { 23 | name: 'onMouseMove', 24 | description: '鼠标移动', 25 | }, 26 | { 27 | name: 'onMouseOut', 28 | description: '鼠标移出', 29 | }, 30 | { 31 | name: 'onMouseOver', 32 | description: '鼠标悬停', 33 | }, 34 | { 35 | name: 'onMouseUp', 36 | description: '鼠标松开', 37 | }, 38 | // Focus Events 39 | { 40 | name: 'onFocus', 41 | description: '获得焦点', 42 | snippet: '', 43 | }, 44 | { 45 | name: 'onBlur', 46 | description: '失去焦点', 47 | snippet: '', 48 | }, 49 | // Form Events 50 | { 51 | name: 'onChange', 52 | description: '值改变时', 53 | snippet: '', 54 | }, 55 | { 56 | name: 'onSelect', 57 | description: '选择', 58 | }, 59 | { 60 | name: 'onInput', 61 | description: '输入', 62 | snippet: '', 63 | }, 64 | { 65 | name: 'onReset', 66 | description: '重置', 67 | snippet: '', 68 | }, 69 | { 70 | name: 'onSubmit', 71 | description: '提交', 72 | snippet: '', 73 | }, 74 | // Clipboard Events 75 | { 76 | name: 'onCopy', 77 | description: '复制', 78 | snippet: '', 79 | }, 80 | { 81 | name: 'onCut', 82 | description: '剪切', 83 | snippet: '', 84 | }, 85 | { 86 | name: 'onPaste', 87 | description: '粘贴', 88 | snippet: '', 89 | }, 90 | 91 | // Keyboard Events 92 | { 93 | name: 'onKeyDown', 94 | description: '键盘按下', 95 | snippet: '', 96 | }, 97 | { 98 | name: 'onKeyPress', 99 | description: '键盘按下并释放', 100 | snippet: '', 101 | }, 102 | { 103 | name: 'onKeyUp', 104 | description: '键盘松开', 105 | snippet: '', 106 | }, 107 | // Touch Events 108 | { 109 | name: 'onTouchCancel', 110 | description: '触摸退出', 111 | snippet: '', 112 | }, 113 | { 114 | name: 'onTouchEnd', 115 | description: '触摸结束', 116 | snippet: '', 117 | }, 118 | { 119 | name: 'onTouchMove', 120 | description: '触摸移动', 121 | snippet: '', 122 | }, 123 | { 124 | name: 'onTouchStart', 125 | description: '触摸开始', 126 | snippet: '', 127 | }, 128 | // UI Events 129 | { 130 | name: 'onScroll', 131 | description: '滚动', 132 | snippet: '', 133 | }, 134 | { 135 | name: 'onLoad', 136 | description: '加载完毕', 137 | snippet: '', 138 | }, 139 | { 140 | name: 'onWheel', 141 | description: '滚轮事件', 142 | snippet: '', 143 | }, 144 | // Animation Events 145 | { 146 | name: 'onAnimationStart', 147 | description: '动画开始', 148 | }, 149 | { 150 | name: 'onAnimationEnd', 151 | description: '动画结束', 152 | }, 153 | ]; 154 | 155 | // eslint-disable-next-line func-call-spacing 156 | const builtinComponents = new Map ReactElement>(); 157 | function getBlockElement(tag: string): (props: any) => ReactElement { 158 | if (builtinComponents.has(tag)) { 159 | return builtinComponents.get(tag)!; 160 | } 161 | const mock = ({ className, children, ...rest }: any = {}) => { 162 | const props = { 163 | ...rest, 164 | className: classNames('lc-block-container', className), 165 | }; 166 | return createElement(tag, props, children); 167 | }; 168 | 169 | mock.metadata = { 170 | componentName: tag, 171 | // selfControlled: true, 172 | configure: { 173 | props: [], 174 | events: { 175 | supportedEvents, 176 | }, 177 | styles: { 178 | supportClassName: true, 179 | supportInlineStyle: true, 180 | }, 181 | component: { 182 | ...metasMap[tag], 183 | }, 184 | }, 185 | }; 186 | 187 | builtinComponents.set(tag, mock); 188 | return mock; 189 | } 190 | 191 | const HTMLBlock = [ 192 | 'div', 193 | 'p', 194 | 'article', 195 | 'h1', 196 | 'h2', 197 | 'h3', 198 | 'h4', 199 | 'h5', 200 | 'h6', 201 | 'aside', 202 | 'blockquote', 203 | 'footer', 204 | 'form', 205 | 'header', 206 | 'table', 207 | 'tbody', 208 | 'section', 209 | 'ul', 210 | 'li', 211 | ]; 212 | 213 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 214 | const HTMLInlineBlock = ['a', 'b', 'span', 'em']; 215 | export function getIntrinsicMock(tag: string): ReactType { 216 | if (HTMLBlock.indexOf(tag) > -1) { 217 | return getBlockElement(tag); 218 | } 219 | 220 | return tag as any; 221 | } 222 | 223 | const metasMap: any = { 224 | div: { 225 | isContainer: true, 226 | nesting: { 227 | ancestorBlacklist: 'p', 228 | }, 229 | }, 230 | ul: { 231 | isContainer: true, 232 | nesting: { 233 | childWhitelist: 'li', 234 | }, 235 | }, 236 | p: { 237 | isContainer: true, 238 | nesting: { 239 | ancestorBlacklist: 'button,p', 240 | }, 241 | }, 242 | li: { 243 | isContainer: true, 244 | nesting: { 245 | parentWhitelist: 'ui,ol', 246 | }, 247 | }, 248 | span: { 249 | isContainer: true, 250 | selfControlled: true, 251 | }, 252 | a: { 253 | isContainer: true, 254 | nesting: { 255 | ancestorBlacklist: 'a', 256 | }, 257 | }, 258 | b: { 259 | isContainer: true, 260 | }, 261 | strong: { 262 | isContainer: true, 263 | }, 264 | em: { 265 | isContainer: true, 266 | }, 267 | i: { 268 | isContainer: true, 269 | }, 270 | form: { 271 | isContainer: true, 272 | nestingRule: { 273 | ancestorBlacklist: 'form,button', 274 | }, 275 | }, 276 | table: { 277 | isContainer: true, 278 | nestingRule: { 279 | ancestorBlacklist: 'button', 280 | }, 281 | }, 282 | caption: { 283 | isContainer: true, 284 | selfControlled: true, 285 | nestingRule: { 286 | ancestorBlacklist: 'button', 287 | }, 288 | }, 289 | select: { 290 | isContainer: true, 291 | selfControlled: true, 292 | nestingRule: { 293 | ancestorBlacklist: 'button', 294 | }, 295 | }, 296 | button: { 297 | isContainer: true, 298 | nestingRule: { 299 | ancestorBlacklist: 'button', 300 | }, 301 | }, 302 | input: { 303 | isContainer: false, 304 | nestingRule: { 305 | ancestorBlacklist: 'button,h1,h2,h3,h4,h5,h6', 306 | }, 307 | }, 308 | textarea: { 309 | isContainer: false, 310 | nestingRule: { 311 | ancestorBlacklist: 'button', 312 | }, 313 | }, 314 | image: { 315 | isContainer: false, 316 | }, 317 | canvas: { 318 | isContainer: false, 319 | }, 320 | br: { 321 | isContainer: false, 322 | }, 323 | h1: { 324 | isContainer: true, 325 | nestingRule: { 326 | ancestorBlacklist: 'p,h1,h2,h3,h4,h5,h6,button', 327 | }, 328 | }, 329 | h2: { 330 | isContainer: true, 331 | nestingRule: { 332 | ancestorBlacklist: 'p,h1,h2,h3,h4,h5,h6,button', 333 | }, 334 | }, 335 | h3: { 336 | isContainer: true, 337 | nestingRule: { 338 | ancestorBlacklist: 'p,h1,h2,h3,h4,h5,h6,button', 339 | }, 340 | }, 341 | h4: { 342 | isContainer: true, 343 | nestingRule: { 344 | ancestorBlacklist: 'p,h1,h2,h3,h4,h5,h6,button', 345 | }, 346 | }, 347 | h5: { 348 | isContainer: true, 349 | nestingRule: { 350 | ancestorBlacklist: 'p,h1,h2,h3,h4,h5,h6,button', 351 | }, 352 | }, 353 | h6: { 354 | isContainer: true, 355 | nestingRule: { 356 | ancestorBlacklist: 'p,h1,h2,h3,h4,h5,h6,button', 357 | }, 358 | }, 359 | article: { 360 | isContainer: true, 361 | nestingRule: { 362 | ancestorBlacklist: 'button', 363 | }, 364 | }, 365 | aside: { 366 | isContainer: true, 367 | nestingRule: { 368 | ancestorBlacklist: 'button', 369 | }, 370 | }, 371 | footer: { 372 | isContainer: true, 373 | nestingRule: { 374 | ancestorBlacklist: 'button', 375 | }, 376 | }, 377 | header: { 378 | isContainer: true, 379 | nestingRule: { 380 | ancestorBlacklist: 'button', 381 | }, 382 | }, 383 | blockquote: { 384 | isContainer: true, 385 | nestingRule: { 386 | ancestorBlacklist: 'button', 387 | }, 388 | }, 389 | address: { 390 | isContainer: true, 391 | nestingRule: { 392 | ancestorBlacklist: 'button', 393 | }, 394 | }, 395 | section: { 396 | isContainer: true, 397 | nestingRule: { 398 | ancestorBlacklist: 'p,h1,h2,h3,h4,h5,h6,button', 399 | }, 400 | }, 401 | summary: { 402 | isContainer: true, 403 | nestingRule: { 404 | ancestorBlacklist: 'button', 405 | }, 406 | }, 407 | nav: { 408 | isContainer: true, 409 | nestingRule: { 410 | ancestorBlacklist: 'button', 411 | }, 412 | }, 413 | }; 414 | -------------------------------------------------------------------------------- /packages/vue3-simulator-renderer/src/builtin-components/builtin-components.ts: -------------------------------------------------------------------------------- 1 | import { ReactElement, createElement, ReactType } from 'react'; 2 | import classNames from 'classnames'; 3 | 4 | const supportedEvents = [ 5 | // MouseEvents 6 | { 7 | name: 'onClick', 8 | description: '点击时', 9 | }, 10 | { 11 | name: 'onDoubleClick', 12 | description: '双击时', 13 | }, 14 | { 15 | name: 'onMouseDown', 16 | description: '鼠标按下', 17 | }, 18 | { 19 | name: 'onMouseEnter', 20 | description: '鼠标进入', 21 | }, 22 | { 23 | name: 'onMouseMove', 24 | description: '鼠标移动', 25 | }, 26 | { 27 | name: 'onMouseOut', 28 | description: '鼠标移出', 29 | }, 30 | { 31 | name: 'onMouseOver', 32 | description: '鼠标悬停', 33 | }, 34 | { 35 | name: 'onMouseUp', 36 | description: '鼠标松开', 37 | }, 38 | // Focus Events 39 | { 40 | name: 'onFocus', 41 | description: '获得焦点', 42 | snippet: '', 43 | }, 44 | { 45 | name: 'onBlur', 46 | description: '失去焦点', 47 | snippet: '', 48 | }, 49 | // Form Events 50 | { 51 | name: 'onChange', 52 | description: '值改变时', 53 | snippet: '', 54 | }, 55 | { 56 | name: 'onSelect', 57 | description: '选择', 58 | }, 59 | { 60 | name: 'onInput', 61 | description: '输入', 62 | snippet: '', 63 | }, 64 | { 65 | name: 'onReset', 66 | description: '重置', 67 | snippet: '', 68 | }, 69 | { 70 | name: 'onSubmit', 71 | description: '提交', 72 | snippet: '', 73 | }, 74 | // Clipboard Events 75 | { 76 | name: 'onCopy', 77 | description: '复制', 78 | snippet: '', 79 | }, 80 | { 81 | name: 'onCut', 82 | description: '剪切', 83 | snippet: '', 84 | }, 85 | { 86 | name: 'onPaste', 87 | description: '粘贴', 88 | snippet: '', 89 | }, 90 | 91 | // Keyboard Events 92 | { 93 | name: 'onKeyDown', 94 | description: '键盘按下', 95 | snippet: '', 96 | }, 97 | { 98 | name: 'onKeyPress', 99 | description: '键盘按下并释放', 100 | snippet: '', 101 | }, 102 | { 103 | name: 'onKeyUp', 104 | description: '键盘松开', 105 | snippet: '', 106 | }, 107 | // Touch Events 108 | { 109 | name: 'onTouchCancel', 110 | description: '触摸退出', 111 | snippet: '', 112 | }, 113 | { 114 | name: 'onTouchEnd', 115 | description: '触摸结束', 116 | snippet: '', 117 | }, 118 | { 119 | name: 'onTouchMove', 120 | description: '触摸移动', 121 | snippet: '', 122 | }, 123 | { 124 | name: 'onTouchStart', 125 | description: '触摸开始', 126 | snippet: '', 127 | }, 128 | // UI Events 129 | { 130 | name: 'onScroll', 131 | description: '滚动', 132 | snippet: '', 133 | }, 134 | { 135 | name: 'onLoad', 136 | description: '加载完毕', 137 | snippet: '', 138 | }, 139 | { 140 | name: 'onWheel', 141 | description: '滚轮事件', 142 | snippet: '', 143 | }, 144 | // Animation Events 145 | { 146 | name: 'onAnimationStart', 147 | description: '动画开始', 148 | }, 149 | { 150 | name: 'onAnimationEnd', 151 | description: '动画结束', 152 | }, 153 | ]; 154 | 155 | // eslint-disable-next-line func-call-spacing 156 | const builtinComponents = new Map ReactElement>(); 157 | function getBlockElement(tag: string): (props: any) => ReactElement { 158 | if (builtinComponents.has(tag)) { 159 | return builtinComponents.get(tag)!; 160 | } 161 | const mock = ({ className, children, ...rest }: any = {}) => { 162 | const props = { 163 | ...rest, 164 | className: classNames('lc-block-container', className), 165 | }; 166 | return createElement(tag, props, children); 167 | }; 168 | 169 | mock.metadata = { 170 | componentName: tag, 171 | // selfControlled: true, 172 | configure: { 173 | props: [], 174 | events: { 175 | supportedEvents, 176 | }, 177 | styles: { 178 | supportClassName: true, 179 | supportInlineStyle: true, 180 | }, 181 | component: { 182 | ...metasMap[tag], 183 | }, 184 | }, 185 | }; 186 | 187 | builtinComponents.set(tag, mock); 188 | return mock; 189 | } 190 | 191 | const HTMLBlock = [ 192 | 'div', 193 | 'p', 194 | 'article', 195 | 'h1', 196 | 'h2', 197 | 'h3', 198 | 'h4', 199 | 'h5', 200 | 'h6', 201 | 'aside', 202 | 'blockquote', 203 | 'footer', 204 | 'form', 205 | 'header', 206 | 'table', 207 | 'tbody', 208 | 'section', 209 | 'ul', 210 | 'li', 211 | ]; 212 | 213 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 214 | const HTMLInlineBlock = ['a', 'b', 'span', 'em']; 215 | export function getIntrinsicMock(tag: string): ReactType { 216 | if (HTMLBlock.indexOf(tag) > -1) { 217 | return getBlockElement(tag); 218 | } 219 | 220 | return tag as any; 221 | } 222 | 223 | const metasMap: any = { 224 | div: { 225 | isContainer: true, 226 | nesting: { 227 | ancestorBlacklist: 'p', 228 | }, 229 | }, 230 | ul: { 231 | isContainer: true, 232 | nesting: { 233 | childWhitelist: 'li', 234 | }, 235 | }, 236 | p: { 237 | isContainer: true, 238 | nesting: { 239 | ancestorBlacklist: 'button,p', 240 | }, 241 | }, 242 | li: { 243 | isContainer: true, 244 | nesting: { 245 | parentWhitelist: 'ui,ol', 246 | }, 247 | }, 248 | span: { 249 | isContainer: true, 250 | selfControlled: true, 251 | }, 252 | a: { 253 | isContainer: true, 254 | nesting: { 255 | ancestorBlacklist: 'a', 256 | }, 257 | }, 258 | b: { 259 | isContainer: true, 260 | }, 261 | strong: { 262 | isContainer: true, 263 | }, 264 | em: { 265 | isContainer: true, 266 | }, 267 | i: { 268 | isContainer: true, 269 | }, 270 | form: { 271 | isContainer: true, 272 | nestingRule: { 273 | ancestorBlacklist: 'form,button', 274 | }, 275 | }, 276 | table: { 277 | isContainer: true, 278 | nestingRule: { 279 | ancestorBlacklist: 'button', 280 | }, 281 | }, 282 | caption: { 283 | isContainer: true, 284 | selfControlled: true, 285 | nestingRule: { 286 | ancestorBlacklist: 'button', 287 | }, 288 | }, 289 | select: { 290 | isContainer: true, 291 | selfControlled: true, 292 | nestingRule: { 293 | ancestorBlacklist: 'button', 294 | }, 295 | }, 296 | button: { 297 | isContainer: true, 298 | nestingRule: { 299 | ancestorBlacklist: 'button', 300 | }, 301 | }, 302 | input: { 303 | isContainer: false, 304 | nestingRule: { 305 | ancestorBlacklist: 'button,h1,h2,h3,h4,h5,h6', 306 | }, 307 | }, 308 | textarea: { 309 | isContainer: false, 310 | nestingRule: { 311 | ancestorBlacklist: 'button', 312 | }, 313 | }, 314 | image: { 315 | isContainer: false, 316 | }, 317 | canvas: { 318 | isContainer: false, 319 | }, 320 | br: { 321 | isContainer: false, 322 | }, 323 | h1: { 324 | isContainer: true, 325 | nestingRule: { 326 | ancestorBlacklist: 'p,h1,h2,h3,h4,h5,h6,button', 327 | }, 328 | }, 329 | h2: { 330 | isContainer: true, 331 | nestingRule: { 332 | ancestorBlacklist: 'p,h1,h2,h3,h4,h5,h6,button', 333 | }, 334 | }, 335 | h3: { 336 | isContainer: true, 337 | nestingRule: { 338 | ancestorBlacklist: 'p,h1,h2,h3,h4,h5,h6,button', 339 | }, 340 | }, 341 | h4: { 342 | isContainer: true, 343 | nestingRule: { 344 | ancestorBlacklist: 'p,h1,h2,h3,h4,h5,h6,button', 345 | }, 346 | }, 347 | h5: { 348 | isContainer: true, 349 | nestingRule: { 350 | ancestorBlacklist: 'p,h1,h2,h3,h4,h5,h6,button', 351 | }, 352 | }, 353 | h6: { 354 | isContainer: true, 355 | nestingRule: { 356 | ancestorBlacklist: 'p,h1,h2,h3,h4,h5,h6,button', 357 | }, 358 | }, 359 | article: { 360 | isContainer: true, 361 | nestingRule: { 362 | ancestorBlacklist: 'button', 363 | }, 364 | }, 365 | aside: { 366 | isContainer: true, 367 | nestingRule: { 368 | ancestorBlacklist: 'button', 369 | }, 370 | }, 371 | footer: { 372 | isContainer: true, 373 | nestingRule: { 374 | ancestorBlacklist: 'button', 375 | }, 376 | }, 377 | header: { 378 | isContainer: true, 379 | nestingRule: { 380 | ancestorBlacklist: 'button', 381 | }, 382 | }, 383 | blockquote: { 384 | isContainer: true, 385 | nestingRule: { 386 | ancestorBlacklist: 'button', 387 | }, 388 | }, 389 | address: { 390 | isContainer: true, 391 | nestingRule: { 392 | ancestorBlacklist: 'button', 393 | }, 394 | }, 395 | section: { 396 | isContainer: true, 397 | nestingRule: { 398 | ancestorBlacklist: 'p,h1,h2,h3,h4,h5,h6,button', 399 | }, 400 | }, 401 | summary: { 402 | isContainer: true, 403 | nestingRule: { 404 | ancestorBlacklist: 'button', 405 | }, 406 | }, 407 | nav: { 408 | isContainer: true, 409 | nestingRule: { 410 | ancestorBlacklist: 'button', 411 | }, 412 | }, 413 | }; 414 | --------------------------------------------------------------------------------