From 40abbc217495cc226e313adef34312ceebc74963 Mon Sep 17 00:00:00 2001
From: coder-byte <308929264@qq.com>
Date: Wed, 19 Jan 2022 14:44:26 +0800
Subject: [PATCH] fix(core/react): some bug fix about viewport (#198)
---
examples/multi-workspace/.npmignore | 4 +
examples/multi-workspace/LICENSE.md | 20 +
examples/multi-workspace/README.md | 1 +
examples/multi-workspace/config/template.ejs | 15 +
.../multi-workspace/config/webpack.base.ts | 102 +++++
.../multi-workspace/config/webpack.dev.ts | 52 +++
.../multi-workspace/config/webpack.prod.ts | 36 ++
examples/multi-workspace/package.json | 41 ++
examples/multi-workspace/src/content.tsx | 47 ++
examples/multi-workspace/src/main.tsx | 407 +++++++++++++++++
examples/multi-workspace/tsconfig.build.json | 10 +
examples/multi-workspace/tsconfig.json | 5 +
examples/sandbox-multi-workspace/.npmignore | 4 +
examples/sandbox-multi-workspace/LICENSE.md | 20 +
examples/sandbox-multi-workspace/README.md | 1 +
.../config/template.ejs | 15 +
.../config/webpack.base.ts | 103 +++++
.../config/webpack.dev.ts | 52 +++
.../config/webpack.prod.ts | 36 ++
examples/sandbox-multi-workspace/package.json | 41 ++
.../sandbox-multi-workspace/src/content.tsx | 47 ++
examples/sandbox-multi-workspace/src/main.tsx | 430 ++++++++++++++++++
.../sandbox-multi-workspace/src/sandbox.tsx | 7 +
.../tsconfig.build.json | 10 +
.../sandbox-multi-workspace/tsconfig.json | 5 +
package.json | 2 +
.../core/src/effects/useSelectionEffect.ts | 2 +-
packages/core/src/models/Viewport.ts | 6 +-
packages/react/src/containers/Viewport.tsx | 4 +-
.../react/src/hooks/useValidNodeOffsetRect.ts | 2 +-
packages/shared/src/event.ts | 2 +-
31 files changed, 1522 insertions(+), 7 deletions(-)
create mode 100644 examples/multi-workspace/.npmignore
create mode 100644 examples/multi-workspace/LICENSE.md
create mode 100644 examples/multi-workspace/README.md
create mode 100644 examples/multi-workspace/config/template.ejs
create mode 100644 examples/multi-workspace/config/webpack.base.ts
create mode 100644 examples/multi-workspace/config/webpack.dev.ts
create mode 100644 examples/multi-workspace/config/webpack.prod.ts
create mode 100644 examples/multi-workspace/package.json
create mode 100644 examples/multi-workspace/src/content.tsx
create mode 100644 examples/multi-workspace/src/main.tsx
create mode 100644 examples/multi-workspace/tsconfig.build.json
create mode 100644 examples/multi-workspace/tsconfig.json
create mode 100644 examples/sandbox-multi-workspace/.npmignore
create mode 100644 examples/sandbox-multi-workspace/LICENSE.md
create mode 100644 examples/sandbox-multi-workspace/README.md
create mode 100644 examples/sandbox-multi-workspace/config/template.ejs
create mode 100644 examples/sandbox-multi-workspace/config/webpack.base.ts
create mode 100644 examples/sandbox-multi-workspace/config/webpack.dev.ts
create mode 100644 examples/sandbox-multi-workspace/config/webpack.prod.ts
create mode 100644 examples/sandbox-multi-workspace/package.json
create mode 100644 examples/sandbox-multi-workspace/src/content.tsx
create mode 100644 examples/sandbox-multi-workspace/src/main.tsx
create mode 100644 examples/sandbox-multi-workspace/src/sandbox.tsx
create mode 100644 examples/sandbox-multi-workspace/tsconfig.build.json
create mode 100644 examples/sandbox-multi-workspace/tsconfig.json
diff --git a/examples/multi-workspace/.npmignore b/examples/multi-workspace/.npmignore
new file mode 100644
index 000000000..cc5cbf1a4
--- /dev/null
+++ b/examples/multi-workspace/.npmignore
@@ -0,0 +1,4 @@
+node_modules
+*.log
+build
+__tests__
\ No newline at end of file
diff --git a/examples/multi-workspace/LICENSE.md b/examples/multi-workspace/LICENSE.md
new file mode 100644
index 000000000..509632e8e
--- /dev/null
+++ b/examples/multi-workspace/LICENSE.md
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-present, Alibaba Group Holding Limited. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/examples/multi-workspace/README.md b/examples/multi-workspace/README.md
new file mode 100644
index 000000000..7490a9317
--- /dev/null
+++ b/examples/multi-workspace/README.md
@@ -0,0 +1 @@
+# @designable/playground
diff --git a/examples/multi-workspace/config/template.ejs b/examples/multi-workspace/config/template.ejs
new file mode 100644
index 000000000..02784b41e
--- /dev/null
+++ b/examples/multi-workspace/config/template.ejs
@@ -0,0 +1,15 @@
+
+
+
+ Designable Playground
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/multi-workspace/config/webpack.base.ts b/examples/multi-workspace/config/webpack.base.ts
new file mode 100644
index 000000000..dbe282aee
--- /dev/null
+++ b/examples/multi-workspace/config/webpack.base.ts
@@ -0,0 +1,102 @@
+import path from 'path'
+import fs from 'fs-extra'
+import MiniCssExtractPlugin from 'mini-css-extract-plugin'
+//import { getThemeVariables } from 'antd/dist/theme'
+
+const getAlias = () => {
+ const packagesDir = path.resolve(__dirname, '../../../packages')
+ const packages = fs.readdirSync(packagesDir)
+ const pkg = fs.readJSONSync(path.resolve(__dirname, '../package.json'))
+ const deps = Object.entries(pkg.dependencies).reduce((deps, [key]) => {
+ if (key.includes('@designable/')) {
+ return deps
+ } else if (key.includes('react')) {
+ deps[key] = require.resolve(key)
+ return deps
+ }
+ deps[key] = key
+ return deps
+ }, {})
+ const alias = packages
+ .map((v) => path.join(packagesDir, v))
+ .filter((v) => {
+ return !fs.statSync(v).isFile()
+ })
+ .reduce((buf, _path) => {
+ const name = path.basename(_path)
+ return {
+ ...buf,
+ [`@designable/${name}$`]: `${_path}/src`,
+ }
+ }, deps)
+ return alias
+}
+export default {
+ mode: 'development',
+ devtool: 'inline-source-map', // 嵌入到源文件中
+ stats: {
+ entrypoints: false,
+ children: false,
+ },
+ entry: {
+ playground: path.resolve(__dirname, '../src/main'),
+ },
+ output: {
+ path: path.resolve(__dirname, '../dist'),
+ filename: '[name].[hash].bundle.js',
+ },
+ resolve: {
+ modules: ['node_modules'],
+ extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
+ alias: getAlias(),
+ },
+ externals: {
+ // '@formily/reactive': 'Formily.Reactive',
+ react: 'React',
+ 'react-dom': 'ReactDOM',
+ moment: 'moment',
+ antd: 'antd',
+ },
+ module: {
+ rules: [
+ {
+ test: /\.tsx?$/,
+ use: [
+ {
+ loader: require.resolve('ts-loader'),
+ options: {
+ transpileOnly: true,
+ },
+ },
+ ],
+ },
+ {
+ test: /\.css$/,
+ use: [MiniCssExtractPlugin.loader, require.resolve('css-loader')],
+ },
+ {
+ test: /\.less$/,
+ use: [
+ MiniCssExtractPlugin.loader,
+ { loader: 'css-loader' },
+ {
+ loader: 'less-loader',
+ options: {
+ // modifyVars: getThemeVariables({
+ // dark: true // 开启暗黑模式
+ // }),
+ javascriptEnabled: true,
+ },
+ },
+ ],
+ },
+ {
+ test: /\.html?$/,
+ loader: require.resolve('file-loader'),
+ options: {
+ name: '[name].[ext]',
+ },
+ },
+ ],
+ },
+}
diff --git a/examples/multi-workspace/config/webpack.dev.ts b/examples/multi-workspace/config/webpack.dev.ts
new file mode 100644
index 000000000..e39bec5bf
--- /dev/null
+++ b/examples/multi-workspace/config/webpack.dev.ts
@@ -0,0 +1,52 @@
+import baseConfig from './webpack.base'
+import HtmlWebpackPlugin from 'html-webpack-plugin'
+import MiniCssExtractPlugin from 'mini-css-extract-plugin'
+//import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'
+import webpack from 'webpack'
+import path from 'path'
+
+const PORT = 3000
+
+const createPages = (pages) => {
+ return pages.map(({ filename, template, chunk }) => {
+ return new HtmlWebpackPlugin({
+ filename,
+ template,
+ inject: 'body',
+ chunks: chunk,
+ })
+ })
+}
+
+for (let key in baseConfig.entry) {
+ if (Array.isArray(baseConfig.entry[key])) {
+ baseConfig.entry[key].push(
+ require.resolve('webpack/hot/dev-server'),
+ `${require.resolve('webpack-dev-server/client')}?http://localhost:${PORT}`
+ )
+ }
+}
+
+export default {
+ ...baseConfig,
+ plugins: [
+ new MiniCssExtractPlugin({
+ filename: '[name].[hash].css',
+ chunkFilename: '[id].[hash].css',
+ }),
+ ...createPages([
+ {
+ filename: 'index.html',
+ template: path.resolve(__dirname, './template.ejs'),
+ chunk: ['playground'],
+ },
+ ]),
+ new webpack.HotModuleReplacementPlugin(),
+ // new BundleAnalyzerPlugin()
+ ],
+ devServer: {
+ host: '127.0.0.1',
+ open: true,
+ port: PORT,
+ },
+}
diff --git a/examples/multi-workspace/config/webpack.prod.ts b/examples/multi-workspace/config/webpack.prod.ts
new file mode 100644
index 000000000..f031583d7
--- /dev/null
+++ b/examples/multi-workspace/config/webpack.prod.ts
@@ -0,0 +1,36 @@
+import baseConfig from './webpack.base'
+import HtmlWebpackPlugin from 'html-webpack-plugin'
+import MiniCssExtractPlugin from 'mini-css-extract-plugin'
+import path from 'path'
+
+const createPages = (pages) => {
+ return pages.map(({ filename, template, chunk }) => {
+ return new HtmlWebpackPlugin({
+ filename,
+ template,
+ inject: 'body',
+ chunks: chunk,
+ })
+ })
+}
+
+export default {
+ ...baseConfig,
+ mode: 'production',
+ plugins: [
+ new MiniCssExtractPlugin({
+ filename: '[name].[hash].css',
+ chunkFilename: '[id].[hash].css',
+ }),
+ ...createPages([
+ {
+ filename: 'index.html',
+ template: path.resolve(__dirname, './template.ejs'),
+ chunk: ['playground'],
+ },
+ ]),
+ ],
+ optimization: {
+ minimize: true,
+ },
+}
diff --git a/examples/multi-workspace/package.json b/examples/multi-workspace/package.json
new file mode 100644
index 000000000..c05ae70ce
--- /dev/null
+++ b/examples/multi-workspace/package.json
@@ -0,0 +1,41 @@
+{
+ "name": "@designable/multi-workspace-example",
+ "version": "1.0.0-beta.43",
+ "license": "MIT",
+ "private": true,
+ "engines": {
+ "npm": ">=3.0.0"
+ },
+ "scripts": {
+ "build": "rimraf dist && webpack-cli --config config/webpack.prod.ts",
+ "start": "webpack-dev-server --config config/webpack.dev.ts"
+ },
+ "devDependencies": {
+ "file-loader": "^5.0.2",
+ "fs-extra": "^8.1.0",
+ "html-webpack-plugin": "^3.2.0",
+ "mini-css-extract-plugin": "^1.6.0",
+ "raw-loader": "^4.0.0",
+ "style-loader": "^1.1.3",
+ "ts-loader": "^7.0.4",
+ "typescript": "4.1.5",
+ "webpack": "^4.41.5",
+ "webpack-bundle-analyzer": "^3.9.0",
+ "webpack-cli": "^3.3.10",
+ "webpack-dev-server": "^3.10.1"
+ },
+ "dependencies": {
+ "@designable/core": "1.0.0-beta.43",
+ "@designable/react": "1.0.0-beta.43",
+ "@designable/react-sandbox": "1.0.0-beta.43",
+ "@designable/react-settings-form": "1.0.0-beta.43",
+ "@designable/shared": "1.0.0-beta.43",
+ "@formily/reactive": "^2.0.2",
+ "@formily/reactive-react": "^2.0.2",
+ "antd": "^4.15.2",
+ "react": "^16.8.x",
+ "react-dom": "^16.8.x",
+ "react-jss": "^10.4.0"
+ },
+ "gitHead": "820790a9ae32c2348bb36b3de7ca5f1051ed392c"
+}
diff --git a/examples/multi-workspace/src/content.tsx b/examples/multi-workspace/src/content.tsx
new file mode 100644
index 000000000..d432dcbe5
--- /dev/null
+++ b/examples/multi-workspace/src/content.tsx
@@ -0,0 +1,47 @@
+import React from 'react'
+import { ComponentTreeWidget, useTreeNode } from '@designable/react'
+import { observer } from '@formily/reactive-react'
+import 'antd/dist/antd.css'
+
+export const Content = () => (
+ {
+ const node = useTreeNode()
+ return (
+
+ {node.props.title}
+ {props.children}
+
+ )
+ }),
+ Card: (props) => {
+ return (
+
+ {props.children ? props.children : 拖拽字段进入该区域 }
+
+ )
+ },
+ }}
+ />
+)
diff --git a/examples/multi-workspace/src/main.tsx b/examples/multi-workspace/src/main.tsx
new file mode 100644
index 000000000..fd53baa36
--- /dev/null
+++ b/examples/multi-workspace/src/main.tsx
@@ -0,0 +1,407 @@
+import React from 'react'
+import ReactDOM from 'react-dom'
+import {
+ Designer,
+ IconWidget,
+ Workbench,
+ Workspace,
+ ViewPanel,
+ DesignerToolsWidget,
+ ViewToolsWidget,
+ OutlineTreeWidget,
+ ResourceWidget,
+ StudioPanel,
+ CompositePanel,
+ WorkspacePanel,
+ ToolbarPanel,
+ ViewportPanel,
+ SettingsPanel,
+ HistoryWidget,
+} from '@designable/react'
+import { SettingsForm, MonacoInput } from '@designable/react-settings-form'
+import { observer } from '@formily/react'
+import {
+ createDesigner,
+ createResource,
+ createBehavior,
+ GlobalRegistry,
+} from '@designable/core'
+import { Content } from './content'
+import { Space, Button, Radio } from 'antd'
+import { GithubOutlined } from '@ant-design/icons'
+import 'antd/dist/antd.less'
+
+const RootBehavior = createBehavior({
+ name: 'Root',
+ selector: 'Root',
+ designerProps: {
+ droppable: true,
+ },
+ designerLocales: {
+ 'zh-CN': {
+ title: '根组件',
+ },
+ 'en-US': {
+ title: 'Root',
+ },
+ 'ko-KR': {
+ title: '루트',
+ },
+ },
+})
+
+const InputBehavior = createBehavior({
+ name: 'Input',
+ selector: (node) =>
+ node.componentName === 'Field' && node.props['x-component'] === 'Input',
+ designerProps: {
+ propsSchema: {
+ type: 'object',
+ $namespace: 'Field',
+ properties: {
+ 'field-properties': {
+ type: 'void',
+ 'x-component': 'CollapseItem',
+ title: '字段属性',
+ properties: {
+ title: {
+ type: 'string',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ },
+
+ hidden: {
+ type: 'string',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Switch',
+ },
+ default: {
+ 'x-decorator': 'FormItem',
+ 'x-component': 'ValueInput',
+ },
+ test: {
+ type: 'void',
+ title: '测试',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'DrawerSetter',
+ 'x-component-props': {
+ text: '打开抽屉',
+ },
+ properties: {
+ test: {
+ type: 'string',
+ title: '测试输入',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ },
+ },
+ },
+ },
+ },
+
+ 'component-styles': {
+ type: 'void',
+ title: '样式',
+ 'x-component': 'CollapseItem',
+ properties: {
+ 'style.width': {
+ type: 'string',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'SizeInput',
+ },
+ 'style.height': {
+ type: 'string',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'SizeInput',
+ },
+ 'style.display': {
+ 'x-component': 'DisplayStyleSetter',
+ },
+ 'style.background': {
+ 'x-component': 'BackgroundStyleSetter',
+ },
+ 'style.boxShadow': {
+ 'x-component': 'BoxShadowStyleSetter',
+ },
+ 'style.font': {
+ 'x-component': 'FontStyleSetter',
+ },
+ 'style.margin': {
+ 'x-component': 'BoxStyleSetter',
+ },
+ 'style.padding': {
+ 'x-component': 'BoxStyleSetter',
+ },
+ 'style.borderRadius': {
+ 'x-component': 'BorderRadiusStyleSetter',
+ },
+ 'style.border': {
+ 'x-component': 'BorderStyleSetter',
+ },
+ },
+ },
+ },
+ },
+ },
+ designerLocales: {
+ 'zh-CN': {
+ title: '输入框',
+ settings: {
+ title: '标题',
+ hidden: '是否隐藏',
+ default: '默认值',
+ style: {
+ width: '宽度',
+ height: '高度',
+ display: '展示',
+ background: '背景',
+ boxShadow: '阴影',
+ font: '字体',
+ margin: '外边距',
+ padding: '内边距',
+ borderRadius: '圆角',
+ border: '边框',
+ },
+ },
+ },
+ 'en-US': {
+ title: 'Input',
+ settings: {
+ title: 'Title',
+ hidden: 'Hidden',
+ default: 'Default Value',
+ style: {
+ width: 'Width',
+ height: 'Height',
+ display: 'Display',
+ background: 'Background',
+ boxShadow: 'Box Shadow',
+ font: 'Font',
+ margin: 'Margin',
+ padding: 'Padding',
+ borderRadius: 'Border Radius',
+ border: 'Border',
+ },
+ },
+ },
+ 'ko-KR': {
+ title: '입력',
+ settings: {
+ title: '텍스트',
+ hidden: '숨김 여부',
+ default: '기본 설정 값',
+ style: {
+ width: '너비',
+ height: '높이',
+ display: '디스플레이',
+ background: '배경',
+ boxShadow: '그림자 박스',
+ font: '폰트',
+ margin: '마진',
+ padding: '패딩',
+ borderRadius: '테두리 굴곡',
+ border: '테두리',
+ },
+ },
+ },
+ },
+})
+
+const CardBehavior = createBehavior({
+ name: 'Card',
+ selector: 'Card',
+ designerProps: {
+ droppable: true,
+ },
+ designerLocales: {
+ 'zh-CN': {
+ title: '卡片',
+ },
+ 'en-US': {
+ title: 'Card',
+ },
+ 'ko-KR': {
+ title: '카드',
+ },
+ },
+})
+
+GlobalRegistry.setDesignerBehaviors([RootBehavior, InputBehavior, CardBehavior])
+
+const Input = createResource({
+ title: {
+ 'zh-CN': '输入框',
+ 'en-US': 'Input',
+ 'ko-KR': '입력 상자',
+ },
+ icon: 'InputSource',
+ elements: [
+ {
+ componentName: 'Field',
+ props: {
+ title: '输入框',
+ type: 'string',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ },
+ },
+ ],
+})
+
+const Card = createResource({
+ title: {
+ 'zh-CN': '卡片',
+ 'en-US': 'Card',
+ 'ko-KR': '카드 상자',
+ },
+ icon: 'CardSource',
+ elements: [
+ {
+ componentName: 'Card',
+ props: {
+ title: '卡片',
+ },
+ },
+ ],
+})
+
+GlobalRegistry.registerDesignerLocales({
+ 'zh-CN': {
+ sources: {
+ Inputs: '输入控件',
+ Displays: '展示控件',
+ Feedbacks: '反馈控件',
+ },
+ },
+ 'en-US': {
+ sources: {
+ Inputs: 'Inputs',
+ Displays: 'Displays',
+ Feedbacks: 'Feedbacks',
+ },
+ },
+ 'ko-KR': {
+ sources: {
+ Inputs: '입력',
+ Displays: '디스플레이',
+ Feedbacks: '피드백',
+ },
+ },
+})
+
+const Logo: React.FC = () => (
+
+
+
+)
+
+const Actions = observer(() => (
+
+ {
+ GlobalRegistry.setDesignerLanguage(e.target.value)
+ }}
+ />
+
+
+ Github
+
+ 保存
+ 发布
+
+))
+
+const engine = createDesigner()
+window.engine = engine
+const App = () => {
+ return (
+
+
+ } actions={ }>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {' '}
+
+
+ {() => }
+
+ {() => {
+ return (
+ `}
+ />
+
+ )
+ }}
+
+
+
+
+
+
+
+
+ {' '}
+
+
+ {() => }
+
+ {() => {
+ return (
+ `}
+ />
+
+ )
+ }}
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+ReactDOM.render( , document.getElementById('root'))
diff --git a/examples/multi-workspace/tsconfig.build.json b/examples/multi-workspace/tsconfig.build.json
new file mode 100644
index 000000000..8f2e5f5a9
--- /dev/null
+++ b/examples/multi-workspace/tsconfig.build.json
@@ -0,0 +1,10 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "./lib",
+ "paths": {
+ "@designable/*": ["../*"]
+ },
+ "declaration": true
+ }
+}
diff --git a/examples/multi-workspace/tsconfig.json b/examples/multi-workspace/tsconfig.json
new file mode 100644
index 000000000..c6865c25a
--- /dev/null
+++ b/examples/multi-workspace/tsconfig.json
@@ -0,0 +1,5 @@
+{
+ "extends": "../../tsconfig.json",
+ "include": ["./src/**/*.ts", "./src/**/*.tsx"],
+ "exclude": ["./src/__tests__/*", "./esm/*", "./lib/*"]
+}
diff --git a/examples/sandbox-multi-workspace/.npmignore b/examples/sandbox-multi-workspace/.npmignore
new file mode 100644
index 000000000..cc5cbf1a4
--- /dev/null
+++ b/examples/sandbox-multi-workspace/.npmignore
@@ -0,0 +1,4 @@
+node_modules
+*.log
+build
+__tests__
\ No newline at end of file
diff --git a/examples/sandbox-multi-workspace/LICENSE.md b/examples/sandbox-multi-workspace/LICENSE.md
new file mode 100644
index 000000000..509632e8e
--- /dev/null
+++ b/examples/sandbox-multi-workspace/LICENSE.md
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-present, Alibaba Group Holding Limited. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/examples/sandbox-multi-workspace/README.md b/examples/sandbox-multi-workspace/README.md
new file mode 100644
index 000000000..7490a9317
--- /dev/null
+++ b/examples/sandbox-multi-workspace/README.md
@@ -0,0 +1 @@
+# @designable/playground
diff --git a/examples/sandbox-multi-workspace/config/template.ejs b/examples/sandbox-multi-workspace/config/template.ejs
new file mode 100644
index 000000000..39cd66619
--- /dev/null
+++ b/examples/sandbox-multi-workspace/config/template.ejs
@@ -0,0 +1,15 @@
+
+
+
+ Designable Playground
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/sandbox-multi-workspace/config/webpack.base.ts b/examples/sandbox-multi-workspace/config/webpack.base.ts
new file mode 100644
index 000000000..5c193d880
--- /dev/null
+++ b/examples/sandbox-multi-workspace/config/webpack.base.ts
@@ -0,0 +1,103 @@
+import path from 'path'
+import fs from 'fs-extra'
+import MiniCssExtractPlugin from 'mini-css-extract-plugin'
+//import { getThemeVariables } from 'antd/dist/theme'
+
+const getAlias = () => {
+ const packagesDir = path.resolve(__dirname, '../../../packages')
+ const packages = fs.readdirSync(packagesDir)
+ const pkg = fs.readJSONSync(path.resolve(__dirname, '../package.json'))
+ const deps = Object.entries(pkg.dependencies).reduce((deps, [key]) => {
+ if (key.includes('@designable/')) {
+ return deps
+ } else if (key.includes('react')) {
+ deps[key] = require.resolve(key)
+ return deps
+ }
+ deps[key] = key
+ return deps
+ }, {})
+ const alias = packages
+ .map((v) => path.join(packagesDir, v))
+ .filter((v) => {
+ return !fs.statSync(v).isFile()
+ })
+ .reduce((buf, _path) => {
+ const name = path.basename(_path)
+ return {
+ ...buf,
+ [`@designable/${name}$`]: `${_path}/src`,
+ }
+ }, deps)
+ return alias
+}
+export default {
+ mode: 'development',
+ devtool: 'inline-source-map', // 嵌入到源文件中
+ stats: {
+ entrypoints: false,
+ children: false,
+ },
+ entry: {
+ playground: path.resolve(__dirname, '../src/main'),
+ sandbox: path.resolve(__dirname, '../src/sandbox'),
+ },
+ output: {
+ path: path.resolve(__dirname, '../dist'),
+ filename: '[name].bundle.js',
+ },
+ resolve: {
+ modules: ['node_modules'],
+ extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
+ alias: getAlias(),
+ },
+ externals: {
+ '@formily/reactive': 'Formily.Reactive',
+ react: 'React',
+ 'react-dom': 'ReactDOM',
+ moment: 'moment',
+ antd: 'antd',
+ },
+ module: {
+ rules: [
+ {
+ test: /\.tsx?$/,
+ use: [
+ {
+ loader: require.resolve('ts-loader'),
+ options: {
+ transpileOnly: true,
+ },
+ },
+ ],
+ },
+ {
+ test: /\.css$/,
+ use: [MiniCssExtractPlugin.loader, require.resolve('css-loader')],
+ },
+ {
+ test: /\.less$/,
+ use: [
+ MiniCssExtractPlugin.loader,
+ { loader: 'css-loader' },
+ {
+ loader: 'less-loader',
+ options: {
+ // modifyVars: getThemeVariables({
+ // dark: true // 开启暗黑模式
+ // }),
+ javascriptEnabled: true,
+ },
+ },
+ ],
+ },
+ {
+ test: /\.html?$/,
+ loader: require.resolve('file-loader'),
+ options: {
+ name: '[name].[ext]',
+ },
+ },
+ ],
+ },
+}
diff --git a/examples/sandbox-multi-workspace/config/webpack.dev.ts b/examples/sandbox-multi-workspace/config/webpack.dev.ts
new file mode 100644
index 000000000..e39bec5bf
--- /dev/null
+++ b/examples/sandbox-multi-workspace/config/webpack.dev.ts
@@ -0,0 +1,52 @@
+import baseConfig from './webpack.base'
+import HtmlWebpackPlugin from 'html-webpack-plugin'
+import MiniCssExtractPlugin from 'mini-css-extract-plugin'
+//import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'
+import webpack from 'webpack'
+import path from 'path'
+
+const PORT = 3000
+
+const createPages = (pages) => {
+ return pages.map(({ filename, template, chunk }) => {
+ return new HtmlWebpackPlugin({
+ filename,
+ template,
+ inject: 'body',
+ chunks: chunk,
+ })
+ })
+}
+
+for (let key in baseConfig.entry) {
+ if (Array.isArray(baseConfig.entry[key])) {
+ baseConfig.entry[key].push(
+ require.resolve('webpack/hot/dev-server'),
+ `${require.resolve('webpack-dev-server/client')}?http://localhost:${PORT}`
+ )
+ }
+}
+
+export default {
+ ...baseConfig,
+ plugins: [
+ new MiniCssExtractPlugin({
+ filename: '[name].[hash].css',
+ chunkFilename: '[id].[hash].css',
+ }),
+ ...createPages([
+ {
+ filename: 'index.html',
+ template: path.resolve(__dirname, './template.ejs'),
+ chunk: ['playground'],
+ },
+ ]),
+ new webpack.HotModuleReplacementPlugin(),
+ // new BundleAnalyzerPlugin()
+ ],
+ devServer: {
+ host: '127.0.0.1',
+ open: true,
+ port: PORT,
+ },
+}
diff --git a/examples/sandbox-multi-workspace/config/webpack.prod.ts b/examples/sandbox-multi-workspace/config/webpack.prod.ts
new file mode 100644
index 000000000..f031583d7
--- /dev/null
+++ b/examples/sandbox-multi-workspace/config/webpack.prod.ts
@@ -0,0 +1,36 @@
+import baseConfig from './webpack.base'
+import HtmlWebpackPlugin from 'html-webpack-plugin'
+import MiniCssExtractPlugin from 'mini-css-extract-plugin'
+import path from 'path'
+
+const createPages = (pages) => {
+ return pages.map(({ filename, template, chunk }) => {
+ return new HtmlWebpackPlugin({
+ filename,
+ template,
+ inject: 'body',
+ chunks: chunk,
+ })
+ })
+}
+
+export default {
+ ...baseConfig,
+ mode: 'production',
+ plugins: [
+ new MiniCssExtractPlugin({
+ filename: '[name].[hash].css',
+ chunkFilename: '[id].[hash].css',
+ }),
+ ...createPages([
+ {
+ filename: 'index.html',
+ template: path.resolve(__dirname, './template.ejs'),
+ chunk: ['playground'],
+ },
+ ]),
+ ],
+ optimization: {
+ minimize: true,
+ },
+}
diff --git a/examples/sandbox-multi-workspace/package.json b/examples/sandbox-multi-workspace/package.json
new file mode 100644
index 000000000..ec02629de
--- /dev/null
+++ b/examples/sandbox-multi-workspace/package.json
@@ -0,0 +1,41 @@
+{
+ "name": "@designable/sandbox-multi-workspace-example",
+ "version": "1.0.0-beta.43",
+ "license": "MIT",
+ "private": true,
+ "engines": {
+ "npm": ">=3.0.0"
+ },
+ "scripts": {
+ "build": "rimraf dist && webpack-cli --config config/webpack.prod.ts",
+ "start": "webpack-dev-server --config config/webpack.dev.ts"
+ },
+ "devDependencies": {
+ "file-loader": "^5.0.2",
+ "fs-extra": "^8.1.0",
+ "html-webpack-plugin": "^3.2.0",
+ "mini-css-extract-plugin": "^1.6.0",
+ "raw-loader": "^4.0.0",
+ "style-loader": "^1.1.3",
+ "ts-loader": "^7.0.4",
+ "typescript": "4.1.5",
+ "webpack": "^4.41.5",
+ "webpack-bundle-analyzer": "^3.9.0",
+ "webpack-cli": "^3.3.10",
+ "webpack-dev-server": "^3.10.1"
+ },
+ "dependencies": {
+ "@designable/core": "1.0.0-beta.43",
+ "@designable/react": "1.0.0-beta.43",
+ "@designable/react-sandbox": "1.0.0-beta.43",
+ "@designable/react-settings-form": "1.0.0-beta.43",
+ "@designable/shared": "1.0.0-beta.43",
+ "@formily/reactive": "^2.0.2",
+ "@formily/reactive-react": "^2.0.2",
+ "antd": "^4.15.2",
+ "react": "^16.8.x",
+ "react-dom": "^16.8.x",
+ "react-jss": "^10.4.0"
+ },
+ "gitHead": "820790a9ae32c2348bb36b3de7ca5f1051ed392c"
+}
diff --git a/examples/sandbox-multi-workspace/src/content.tsx b/examples/sandbox-multi-workspace/src/content.tsx
new file mode 100644
index 000000000..d432dcbe5
--- /dev/null
+++ b/examples/sandbox-multi-workspace/src/content.tsx
@@ -0,0 +1,47 @@
+import React from 'react'
+import { ComponentTreeWidget, useTreeNode } from '@designable/react'
+import { observer } from '@formily/reactive-react'
+import 'antd/dist/antd.css'
+
+export const Content = () => (
+ {
+ const node = useTreeNode()
+ return (
+
+ {node.props.title}
+ {props.children}
+
+ )
+ }),
+ Card: (props) => {
+ return (
+
+ {props.children ? props.children : 拖拽字段进入该区域 }
+
+ )
+ },
+ }}
+ />
+)
diff --git a/examples/sandbox-multi-workspace/src/main.tsx b/examples/sandbox-multi-workspace/src/main.tsx
new file mode 100644
index 000000000..d9b092663
--- /dev/null
+++ b/examples/sandbox-multi-workspace/src/main.tsx
@@ -0,0 +1,430 @@
+import React from 'react'
+import ReactDOM from 'react-dom'
+import {
+ Designer,
+ IconWidget,
+ Workbench,
+ Workspace,
+ ViewPanel,
+ DesignerToolsWidget,
+ ViewToolsWidget,
+ OutlineTreeWidget,
+ ResourceWidget,
+ StudioPanel,
+ CompositePanel,
+ WorkspacePanel,
+ ToolbarPanel,
+ ViewportPanel,
+ SettingsPanel,
+ HistoryWidget,
+} from '@designable/react'
+import { SettingsForm, MonacoInput } from '@designable/react-settings-form'
+import { observer } from '@formily/react'
+import {
+ createDesigner,
+ createResource,
+ createBehavior,
+ GlobalRegistry,
+} from '@designable/core'
+import { Space, Button, Radio } from 'antd'
+import { GithubOutlined } from '@ant-design/icons'
+import { Sandbox } from '@designable/react-sandbox'
+import 'antd/dist/antd.less'
+
+const RootBehavior = createBehavior({
+ name: 'Root',
+ selector: 'Root',
+ designerProps: {
+ droppable: true,
+ },
+ designerLocales: {
+ 'zh-CN': {
+ title: '根组件',
+ },
+ 'en-US': {
+ title: 'Root',
+ },
+ 'ko-KR': {
+ title: '루트',
+ },
+ },
+})
+
+const InputBehavior = createBehavior({
+ name: 'Input',
+ selector: (node) =>
+ node.componentName === 'Field' && node.props['x-component'] === 'Input',
+ designerProps: {
+ propsSchema: {
+ type: 'object',
+ $namespace: 'Field',
+ properties: {
+ 'field-properties': {
+ type: 'void',
+ 'x-component': 'CollapseItem',
+ title: '字段属性',
+ properties: {
+ title: {
+ type: 'string',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ },
+
+ hidden: {
+ type: 'string',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Switch',
+ },
+ default: {
+ 'x-decorator': 'FormItem',
+ 'x-component': 'ValueInput',
+ },
+ test: {
+ type: 'void',
+ title: '测试',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'DrawerSetter',
+ 'x-component-props': {
+ text: '打开抽屉',
+ },
+ properties: {
+ test: {
+ type: 'string',
+ title: '测试输入',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ },
+ },
+ },
+ },
+ },
+
+ 'component-styles': {
+ type: 'void',
+ title: '样式',
+ 'x-component': 'CollapseItem',
+ properties: {
+ 'style.width': {
+ type: 'string',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'SizeInput',
+ },
+ 'style.height': {
+ type: 'string',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'SizeInput',
+ },
+ 'style.display': {
+ 'x-component': 'DisplayStyleSetter',
+ },
+ 'style.background': {
+ 'x-component': 'BackgroundStyleSetter',
+ },
+ 'style.boxShadow': {
+ 'x-component': 'BoxShadowStyleSetter',
+ },
+ 'style.font': {
+ 'x-component': 'FontStyleSetter',
+ },
+ 'style.margin': {
+ 'x-component': 'BoxStyleSetter',
+ },
+ 'style.padding': {
+ 'x-component': 'BoxStyleSetter',
+ },
+ 'style.borderRadius': {
+ 'x-component': 'BorderRadiusStyleSetter',
+ },
+ 'style.border': {
+ 'x-component': 'BorderStyleSetter',
+ },
+ },
+ },
+ },
+ },
+ },
+ designerLocales: {
+ 'zh-CN': {
+ title: '输入框',
+ settings: {
+ title: '标题',
+ hidden: '是否隐藏',
+ default: '默认值',
+ style: {
+ width: '宽度',
+ height: '高度',
+ display: '展示',
+ background: '背景',
+ boxShadow: '阴影',
+ font: '字体',
+ margin: '外边距',
+ padding: '内边距',
+ borderRadius: '圆角',
+ border: '边框',
+ },
+ },
+ },
+ 'en-US': {
+ title: 'Input',
+ settings: {
+ title: 'Title',
+ hidden: 'Hidden',
+ default: 'Default Value',
+ style: {
+ width: 'Width',
+ height: 'Height',
+ display: 'Display',
+ background: 'Background',
+ boxShadow: 'Box Shadow',
+ font: 'Font',
+ margin: 'Margin',
+ padding: 'Padding',
+ borderRadius: 'Border Radius',
+ border: 'Border',
+ },
+ },
+ },
+ 'ko-KR': {
+ title: '입력',
+ settings: {
+ title: '텍스트',
+ hidden: '숨김 여부',
+ default: '기본 설정 값',
+ style: {
+ width: '너비',
+ height: '높이',
+ display: '디스플레이',
+ background: '배경',
+ boxShadow: '그림자 박스',
+ font: '폰트',
+ margin: '마진',
+ padding: '패딩',
+ borderRadius: '테두리 굴곡',
+ border: '테두리',
+ },
+ },
+ },
+ },
+})
+
+const CardBehavior = createBehavior({
+ name: 'Card',
+ selector: 'Card',
+ designerProps: {
+ droppable: true,
+ },
+ designerLocales: {
+ 'zh-CN': {
+ title: '卡片',
+ },
+ 'en-US': {
+ title: 'Card',
+ },
+ 'ko-KR': {
+ title: '카드',
+ },
+ },
+})
+
+GlobalRegistry.setDesignerBehaviors([RootBehavior, InputBehavior, CardBehavior])
+
+const Input = createResource({
+ title: {
+ 'zh-CN': '输入框',
+ 'en-US': 'Input',
+ 'ko-KR': '입력 상자',
+ },
+ icon: 'InputSource',
+ elements: [
+ {
+ componentName: 'Field',
+ props: {
+ title: '输入框',
+ type: 'string',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ },
+ },
+ ],
+})
+
+const Card = createResource({
+ title: {
+ 'zh-CN': '卡片',
+ 'en-US': 'Card',
+ 'ko-KR': '카드 상자',
+ },
+ icon: 'CardSource',
+ elements: [
+ {
+ componentName: 'Card',
+ props: {
+ title: '卡片',
+ },
+ },
+ ],
+})
+
+GlobalRegistry.registerDesignerLocales({
+ 'zh-CN': {
+ sources: {
+ Inputs: '输入控件',
+ Displays: '展示控件',
+ Feedbacks: '反馈控件',
+ },
+ },
+ 'en-US': {
+ sources: {
+ Inputs: 'Inputs',
+ Displays: 'Displays',
+ Feedbacks: 'Feedbacks',
+ },
+ },
+ 'ko-KR': {
+ sources: {
+ Inputs: '입력',
+ Displays: '디스플레이',
+ Feedbacks: '피드백',
+ },
+ },
+})
+
+const Logo: React.FC = () => (
+
+
+
+)
+
+const Actions = observer(() => (
+
+ {
+ GlobalRegistry.setDesignerLanguage(e.target.value)
+ }}
+ />
+
+
+ Github
+
+ 保存
+ 发布
+
+))
+
+const engine = createDesigner()
+const App = () => {
+ return (
+
+
+ } actions={ }>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {' '}
+
+
+
+ {() => (
+
+ )}
+
+
+ {() => {
+ return (
+ `}
+ />
+
+ )
+ }}
+
+
+
+
+
+
+
+
+ {' '}
+
+
+
+ {() => (
+
+ )}
+
+
+ {() => {
+ return (
+ `}
+ />
+
+ )
+ }}
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+ReactDOM.render( , document.getElementById('root'))
diff --git a/examples/sandbox-multi-workspace/src/sandbox.tsx b/examples/sandbox-multi-workspace/src/sandbox.tsx
new file mode 100644
index 000000000..2959d652c
--- /dev/null
+++ b/examples/sandbox-multi-workspace/src/sandbox.tsx
@@ -0,0 +1,7 @@
+import React from 'react'
+import { Content } from './content'
+import { renderSandboxContent } from '@designable/react-sandbox'
+
+renderSandboxContent(() => {
+ return
+})
diff --git a/examples/sandbox-multi-workspace/tsconfig.build.json b/examples/sandbox-multi-workspace/tsconfig.build.json
new file mode 100644
index 000000000..8f2e5f5a9
--- /dev/null
+++ b/examples/sandbox-multi-workspace/tsconfig.build.json
@@ -0,0 +1,10 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "./lib",
+ "paths": {
+ "@designable/*": ["../*"]
+ },
+ "declaration": true
+ }
+}
diff --git a/examples/sandbox-multi-workspace/tsconfig.json b/examples/sandbox-multi-workspace/tsconfig.json
new file mode 100644
index 000000000..c6865c25a
--- /dev/null
+++ b/examples/sandbox-multi-workspace/tsconfig.json
@@ -0,0 +1,5 @@
+{
+ "extends": "../../tsconfig.json",
+ "include": ["./src/**/*.ts", "./src/**/*.tsx"],
+ "exclude": ["./src/__tests__/*", "./esm/*", "./lib/*"]
+}
diff --git a/package.json b/package.json
index fec7ab5aa..1c2069b59 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,8 @@
"start:playground": "npm run start:basic",
"start:basic": "yarn workspace @designable/basic-example start",
"start:sandbox": "yarn workspace @designable/sandbox-example start",
+ "start:multi-workspace": "yarn workspace @designable/multi-workspace-example start",
+ "start:sandbox-multi-workspace": "yarn workspace @designable/sandbox-multi-workspace-example start",
"test": "jest --coverage",
"test:watch": "jest --watch",
"test:prod": "jest --coverage --silent",
diff --git a/packages/core/src/effects/useSelectionEffect.ts b/packages/core/src/effects/useSelectionEffect.ts
index 1fdf01849..a29e79eff 100644
--- a/packages/core/src/effects/useSelectionEffect.ts
+++ b/packages/core/src/effects/useSelectionEffect.ts
@@ -14,7 +14,7 @@ export const useSelectionEffect = (engine: Engine) => {
`*[${engine.props.nodeSelectionIdAttrName}]`
)
const currentWorkspace =
- event.context.workspace ?? engine.workbench.activeWorkspace
+ event.context?.workspace ?? engine.workbench.activeWorkspace
if (!currentWorkspace) return
if (!el?.getAttribute) {
const point = new Point(event.data.topClientX, event.data.topClientY)
diff --git a/packages/core/src/models/Viewport.ts b/packages/core/src/models/Viewport.ts
index b589fe6c4..b9903fb05 100644
--- a/packages/core/src/models/Viewport.ts
+++ b/packages/core/src/models/Viewport.ts
@@ -191,6 +191,8 @@ export class Viewport {
if (this.isIframe) {
this.workspace.detachEvents(this.contentWindow)
this.workspace.detachEvents(this.viewportElement)
+ } else if (this.viewportElement) {
+ this.workspace.detachEvents(this.viewportElement)
}
}
@@ -403,8 +405,8 @@ export class Viewport {
if (!node) return
const rect = this.getElementRectById(node.id)
if (node && node === node.root) {
- if (!rect) return this.innerRect
- return calcBoundingRect([this.innerRect, rect])
+ if (!rect) return this.rect
+ return calcBoundingRect([this.rect, rect])
}
if (rect) {
diff --git a/packages/react/src/containers/Viewport.tsx b/packages/react/src/containers/Viewport.tsx
index ddcc52492..ea7b2458a 100644
--- a/packages/react/src/containers/Viewport.tsx
+++ b/packages/react/src/containers/Viewport.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useRef, useState } from 'react'
+import React, { useLayoutEffect, useRef, useState } from 'react'
import { usePrefix, useViewport } from '../hooks'
import { AuxToolWidget, EmptyWidget } from '../widgets'
import { Viewport as ViewportType } from '@designable/core'
@@ -21,7 +21,7 @@ export const Viewport: React.FC = ({
const ref = useRef()
const viewportRef = useRef()
const isFrameRef = useRef(false)
- useEffect(() => {
+ useLayoutEffect(() => {
const frameElement = ref.current.querySelector('iframe')
if (!viewport) return
if (viewportRef.current && viewportRef.current !== viewport) {
diff --git a/packages/react/src/hooks/useValidNodeOffsetRect.ts b/packages/react/src/hooks/useValidNodeOffsetRect.ts
index d04324fc3..f8f7d1483 100644
--- a/packages/react/src/hooks/useValidNodeOffsetRect.ts
+++ b/packages/react/src/hooks/useValidNodeOffsetRect.ts
@@ -32,7 +32,7 @@ export const useValidNodeOffsetRect = (node: TreeNode) => {
}, [viewport, node])
useEffect(() => {
- if (!element) return
+ if (!element || !element.isConnected) return
if (observerRef.current) {
observerRef.current.disconnect()
}
diff --git a/packages/shared/src/event.ts b/packages/shared/src/event.ts
index 55ba76098..140a54a7d 100644
--- a/packages/shared/src/event.ts
+++ b/packages/shared/src/event.ts
@@ -351,7 +351,7 @@ export class Event extends Subscribable> {
})
return
}
- if (container instanceof Window) {
+ if (isWindow(container)) {
return this.detachEvents(container.document)
}
if (!container[ATTACHED_SYMBOL]) return