+
+ {
+ const newActions = [...this.state.actions];
+ newActions[index] = newAction;
+ this.setState({
+ actions: newActions,
+ });
+ }}
+ />
+
+
+ {renderUIWidget(uiSchemaPrivider.get(action.$kind), {
+ id: `actions[${index}]`,
+ data: action,
+ onEvent: () => null,
+ })}
+
+
+ );
+ }
+
+ renderActionFactory() {
+ return (
+
+
Visual SDK Demo
+
+ {this.renderActionFactory()}
+ {this.state.actions.map((action, index) => this.renderActionPreview(action, index))}
+
+
+ );
+ }
+}
diff --git a/Composer/packages/extensions/visual-designer/demo/src/stories/story.css b/Composer/packages/adaptive-flow/demo/src/stories/story.css
similarity index 100%
rename from Composer/packages/extensions/visual-designer/demo/src/stories/story.css
rename to Composer/packages/adaptive-flow/demo/src/stories/story.css
diff --git a/Composer/packages/extensions/visual-designer/demo/tsconfig.json b/Composer/packages/adaptive-flow/demo/tsconfig.json
similarity index 100%
rename from Composer/packages/extensions/visual-designer/demo/tsconfig.json
rename to Composer/packages/adaptive-flow/demo/tsconfig.json
diff --git a/Composer/packages/adaptive-flow/demo/webpack.config.demo.js b/Composer/packages/adaptive-flow/demo/webpack.config.demo.js
new file mode 100644
index 0000000000..b50e4cb2af
--- /dev/null
+++ b/Composer/packages/adaptive-flow/demo/webpack.config.demo.js
@@ -0,0 +1,110 @@
+/* eslint-disable */
+const path = require('path');
+
+const webpack = require('webpack');
+const autoprefixer = require('autoprefixer');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
+const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
+
+module.exports = {
+ entry: path.resolve(__dirname, 'src/index.js'),
+ mode: 'development',
+ devtool: 'inline-source-map',
+ devServer: {
+ contentBase: path.join(__dirname, 'dist'),
+ port: 3001,
+ stats: 'errors-only',
+ },
+ node: {
+ fs: 'empty',
+ },
+ module: {
+ rules: [
+ {
+ test: /\.(tsx?|jsx?)$/,
+ loader: 'ts-loader',
+ exclude: /node_modules/,
+ options: {
+ transpileOnly: true,
+ experimentalWatchApi: true,
+ },
+ },
+ {
+ test: /\.(gif|png|webp)$/,
+ loader: 'url-loader',
+ options: {
+ limit: 1,
+ name: '[name].[hash:8].[ext]',
+ },
+ },
+ { test: /\.svg$/, loader: 'url-loader', options: { limit: 1, name: '[name].[hash:8].[ext]' } },
+ { test: /\.jpe?g$/, loader: 'url-loader', options: { limit: 1, name: '[name].[hash:8].[ext]' } },
+ {
+ test: /\.(eot|otf|ttf|woff|woff2)$/,
+ loader: 'url-loader',
+ options: { limit: 1, name: '[name].[hash:8].[ext]' },
+ },
+ {
+ test: /\.css$/,
+ use: [
+ {
+ loader: 'style-loader',
+ },
+ { loader: 'css-loader', options: { importLoaders: 1 } },
+ {
+ loader: 'postcss-loader',
+ options: {
+ ident: 'postcss',
+ plugins: [
+ autoprefixer({
+ browsers: ['>1%', 'last 2 versions', 'not ie < 11'],
+ }),
+ ],
+ },
+ },
+ ],
+ },
+ {
+ test: /\.s[ac]ss$/,
+ use: [
+ {
+ loader: 'style-loader',
+ },
+ { loader: 'css-loader', options: { importLoaders: 1 } },
+ {
+ loader: 'postcss-loader',
+ options: {
+ ident: 'postcss',
+ plugins: [
+ autoprefixer({
+ browsers: ['>1%', 'last 2 versions', 'not ie < 11'],
+ }),
+ ],
+ },
+ },
+ ],
+ },
+ ],
+ },
+ resolve: {
+ extensions: ['.tsx', '.ts', '.js'],
+ plugins: [new TsconfigPathsPlugin({ configFile: path.resolve(__dirname, './tsconfig.json') })],
+ },
+
+ output: {
+ filename: '[name].[chunkhash:8].js',
+ chunkFilename: '[name].[chunkhash:8].js',
+ path: path.resolve('./demo/dist'),
+ },
+
+ plugins: [
+ new webpack.DefinePlugin({
+ 'process.env.NODE_ENV': JSON.stringify('development'),
+ }),
+ new HtmlWebpackPlugin({
+ title: 'Visual Designer',
+ chunksSortMode: 'dependency',
+ template: path.join(__dirname, 'index.html'),
+ }),
+ ],
+};
diff --git a/Composer/packages/adaptive-flow/jest.config.js b/Composer/packages/adaptive-flow/jest.config.js
new file mode 100644
index 0000000000..b842fc2841
--- /dev/null
+++ b/Composer/packages/adaptive-flow/jest.config.js
@@ -0,0 +1,3 @@
+const { createConfig } = require('@botframework-composer/test-utils');
+
+module.exports = createConfig('adaptive-form', 'react');
diff --git a/Composer/packages/adaptive-flow/package.json b/Composer/packages/adaptive-flow/package.json
new file mode 100644
index 0000000000..a60b09d6ab
--- /dev/null
+++ b/Composer/packages/adaptive-flow/package.json
@@ -0,0 +1,65 @@
+{
+ "name": "@bfc/adaptive-flow",
+ "version": "1.0.0",
+ "description": "BotFramework Adaptive Form",
+ "main": "lib/index.js",
+ "engines": {
+ "node": ">=12"
+ },
+ "files": [
+ "css",
+ "es",
+ "lib",
+ "umd"
+ ],
+ "scripts": {
+ "build": "yarn clean && yarn build:ts",
+ "build:ts": "tsc --build tsconfig.build.json",
+ "clean": "rimraf lib demo/dist",
+ "prepublishOnly": "npm run build",
+ "start": "webpack-dev-server --config demo/webpack.config.demo.js --port 3002",
+ "test": "jest --no-cache",
+ "lint": "eslint --quiet ./src ./__tests__",
+ "lint:fix": "yarn lint --fix"
+ },
+ "dependencies": {
+ "@bfc/extension-client": "*",
+ "@bfc/shared": "*",
+ "@bfc/ui-shared": "*",
+ "@emotion/core": "^10.0.27",
+ "@emotion/styled": "^10.0.27",
+ "adaptive-expressions": "4.12.0-dev-20210125.e5a4fc60f438",
+ "botbuilder-lg": "4.12.0-dev-20210125.e5a4fc60f438",
+ "create-react-class": "^15.6.3",
+ "d3": "^5.9.1",
+ "dagre": "^0.8.4",
+ "dagre-d3": "^0.6.3",
+ "lodash": "^4.17.19",
+ "office-ui-fabric-react": "^7.88.1",
+ "prop-types": "^15.7.2",
+ "react-measure": "^2.3.0",
+ "source-map-loader": "^0.2.4"
+ },
+ "peerDependencies": {
+ "format-message": "^6.2.3",
+ "react": "16.13.1"
+ },
+ "devDependencies": {
+ "@botframework-composer/test-utils": "*",
+ "@types/lodash": "^4.14.146",
+ "@types/react": "16.9.23",
+ "format-message": "^6.2.3",
+ "json-loader": "^0.5.7",
+ "react": "16.13.1",
+ "react-dom": "16.13.1",
+ "ts-loader": "7.0.4",
+ "tsconfig-paths-webpack-plugin": "^3.2.0"
+ },
+ "author": "",
+ "homepage": "",
+ "license": "MIT",
+ "repository": "",
+ "keywords": [
+ "react-component"
+ ]
+}
diff --git a/Composer/packages/adaptive-flow/src/adaptive-flow-editor/AdaptiveFlowEditor.tsx b/Composer/packages/adaptive-flow/src/adaptive-flow-editor/AdaptiveFlowEditor.tsx
new file mode 100644
index 0000000000..a52d914eb6
--- /dev/null
+++ b/Composer/packages/adaptive-flow/src/adaptive-flow-editor/AdaptiveFlowEditor.tsx
@@ -0,0 +1,201 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+/** @jsx jsx */
+import { jsx, css, CacheProvider } from '@emotion/core';
+import createCache from '@emotion/cache';
+import React, { useRef, useMemo, useEffect } from 'react';
+import isEqual from 'lodash/isEqual';
+import formatMessage from 'format-message';
+import { DialogFactory, MicrosoftIDialog, SchemaDefinitions } from '@bfc/shared';
+import { useShellApi, JSONSchema7, FlowUISchema, FlowWidget } from '@bfc/extension-client';
+import { MarqueeSelection } from 'office-ui-fabric-react/lib/MarqueeSelection';
+
+import { NodeEventTypes } from '../adaptive-flow-renderer/constants/NodeEventTypes';
+import { AdaptiveDialog } from '../adaptive-flow-renderer/adaptive/AdaptiveDialog';
+
+import { NodeRendererContext, NodeRendererContextValue } from './contexts/NodeRendererContext';
+import { SelfHostContext } from './contexts/SelfHostContext';
+import { getCustomSchema } from './utils/getCustomSchema';
+import { SelectionContext } from './contexts/SelectionContext';
+import { enableKeyboardCommandAttributes, KeyboardCommandHandler } from './components/KeyboardZone';
+import { mapKeyboardCommandToEditorEvent } from './utils/mapKeyboardCommandToEditorEvent';
+import { useSelectionEffect } from './hooks/useSelectionEffect';
+import { useEditorEventApi } from './hooks/useEditorEventApi';
+import {
+ VisualEditorNodeMenu,
+ VisualEditorEdgeMenu,
+ VisualEditorNodeWrapper,
+ VisualEditorElementWrapper,
+} from './renderers';
+import { useFlowUIOptions } from './hooks/useFlowUIOptions';
+import { ZoomZone } from './components/ZoomZone';
+
+formatMessage.setup({
+ missingTranslation: 'ignore',
+});
+
+const emotionCache = createCache({
+ // @ts-ignore
+ nonce: window.__nonce__,
+});
+
+const styles = css`
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+
+ border: 1px solid transparent;
+
+ &:focus {
+ outline: none;
+ border-color: black;
+ }
+`;
+
+export interface VisualDesignerProps {
+ onFocus?: (event: React.FocusEvent