@tmagic/editor 1.8.0-manmanyu.9 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/Editor.vue_vue_type_script_setup_true_lang.js +22 -13
- package/dist/es/components/CodeBlockEditor.vue_vue_type_script_setup_true_lang.js +10 -5
- package/dist/es/components/CodeParams.vue_vue_type_script_setup_true_lang.js +7 -6
- package/dist/es/components/CompareForm.vue_vue_type_script_setup_true_lang.js +21 -122
- package/dist/es/components/ContentMenu.vue_vue_type_script_setup_true_lang.js +21 -5
- package/dist/es/components/FloatingBox.vue_vue_type_script_setup_true_lang.js +62 -16
- package/dist/es/components/Icon.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/Resizer.vue_vue_type_script_setup_true_lang.js +3 -2
- package/dist/es/components/ScrollBar.js +0 -1
- package/dist/es/components/ScrollBar.vue_vue_type_script_setup_true_lang.js +5 -4
- package/dist/es/components/ScrollViewer.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/SearchInput.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/SplitView.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/ToolButton.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/Tree.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/TreeNode.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/components/ViewForm.js +5 -0
- package/dist/es/components/ViewForm.vue_vue_type_script_setup_true_lang.js +56 -0
- package/dist/es/editorProps.js +7 -1
- package/dist/es/fields/Code.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/CodeLink.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/CodeSelect.vue_vue_type_script_setup_true_lang.js +30 -113
- package/dist/es/fields/CodeSelectCol.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/es/fields/CondOpSelect.vue_vue_type_script_setup_true_lang.js +7 -19
- package/dist/es/fields/DataSourceFieldSelect/FieldSelect.vue_vue_type_script_setup_true_lang.js +7 -6
- package/dist/es/fields/DataSourceFieldSelect/Index.vue_vue_type_script_setup_true_lang.js +4 -2
- package/dist/es/fields/DataSourceFields.vue_vue_type_script_setup_true_lang.js +12 -4
- package/dist/es/fields/DataSourceInput.vue_vue_type_script_setup_true_lang.js +9 -20
- package/dist/es/fields/DataSourceMethodSelect.vue_vue_type_script_setup_true_name_true_lang.js +2 -2
- package/dist/es/fields/DataSourceMethods.vue_vue_type_script_setup_true_lang.js +5 -3
- package/dist/es/fields/DataSourceMocks.vue_vue_type_script_setup_true_lang.js +9 -4
- package/dist/es/fields/DataSourceSelect.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/es/fields/DisplayConds.vue_vue_type_script_setup_true_lang.js +10 -110
- package/dist/es/fields/EventSelect.vue_vue_type_script_setup_true_lang.js +52 -363
- package/dist/es/fields/KeyValue.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/PageFragmentSelect.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/StyleSetter/Index.vue_vue_type_script_setup_true_lang.js +3 -6
- package/dist/es/fields/StyleSetter/components/BackgroundPosition.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/StyleSetter/components/Border.vue_vue_type_script_setup_true_lang.js +4 -35
- package/dist/es/fields/StyleSetter/components/Box.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/es/fields/StyleSetter/configs.js +663 -0
- package/dist/es/fields/StyleSetter/icons/align-items/Center.js +1 -1
- package/dist/es/fields/StyleSetter/icons/align-items/FlexEnd.js +1 -1
- package/dist/es/fields/StyleSetter/icons/align-items/FlexStart.js +1 -1
- package/dist/es/fields/StyleSetter/icons/align-items/SpaceAround.js +1 -1
- package/dist/es/fields/StyleSetter/icons/align-items/SpaceBetween.js +1 -1
- package/dist/es/fields/StyleSetter/icons/background-repeat/NoRepeat.js +1 -1
- package/dist/es/fields/StyleSetter/icons/background-repeat/Repeat.js +1 -1
- package/dist/es/fields/StyleSetter/icons/background-repeat/RepeatX.js +1 -1
- package/dist/es/fields/StyleSetter/icons/background-repeat/RepeatY.js +1 -1
- package/dist/es/fields/StyleSetter/icons/display/Block.js +1 -1
- package/dist/es/fields/StyleSetter/icons/display/Flex.js +1 -1
- package/dist/es/fields/StyleSetter/icons/display/Inline.js +1 -1
- package/dist/es/fields/StyleSetter/icons/display/InlineBlock.js +1 -1
- package/dist/es/fields/StyleSetter/icons/display/None.js +1 -1
- package/dist/es/fields/StyleSetter/icons/flex-direction/Column.js +1 -1
- package/dist/es/fields/StyleSetter/icons/flex-direction/ColumnReverse.js +1 -1
- package/dist/es/fields/StyleSetter/icons/flex-direction/Row.js +1 -1
- package/dist/es/fields/StyleSetter/icons/flex-direction/RowReverse.js +1 -1
- package/dist/es/fields/StyleSetter/icons/justify-content/Center.js +1 -1
- package/dist/es/fields/StyleSetter/icons/justify-content/FlexEnd.js +1 -1
- package/dist/es/fields/StyleSetter/icons/justify-content/FlexStart.js +1 -1
- package/dist/es/fields/StyleSetter/icons/justify-content/SpaceAround.js +1 -1
- package/dist/es/fields/StyleSetter/icons/justify-content/SpaceBetween.js +1 -1
- package/dist/es/fields/StyleSetter/icons/text-align/Center.js +1 -1
- package/dist/es/fields/StyleSetter/icons/text-align/Left.js +1 -1
- package/dist/es/fields/StyleSetter/icons/text-align/Right.js +1 -1
- package/dist/es/fields/StyleSetter/pro/Background.vue_vue_type_script_setup_true_lang.js +29 -106
- package/dist/es/fields/StyleSetter/pro/Border.vue_vue_type_script_setup_true_lang.js +8 -11
- package/dist/es/fields/StyleSetter/pro/Font.vue_vue_type_script_setup_true_lang.js +30 -89
- package/dist/es/fields/StyleSetter/pro/Layout.vue_vue_type_script_setup_true_lang.js +29 -297
- package/dist/es/fields/StyleSetter/pro/Position.vue_vue_type_script_setup_true_lang.js +29 -82
- package/dist/es/fields/StyleSetter/pro/Transform.vue_vue_type_script_setup_true_lang.js +8 -24
- package/dist/es/fields/UISelect.js +0 -1
- package/dist/es/fields/UISelect.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/configs/codeSelect.js +98 -0
- package/dist/es/fields/configs/displayConds.js +158 -0
- package/dist/es/fields/configs/eventSelect.js +225 -0
- package/dist/es/fields/configs/stickyAddButton.js +21 -0
- package/dist/es/fields/headless-validation.js +139 -0
- package/dist/es/headless.js +2 -0
- package/dist/es/hooks/use-code-block-edit.js +4 -2
- package/dist/es/hooks/use-compare-form.js +101 -0
- package/dist/es/hooks/use-form-context.js +29 -0
- package/dist/es/hooks/use-stage.js +1 -0
- package/dist/es/icons/CenterIcon.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/icons/CodeIcon.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/icons/DatasourceIcon.js +1 -1
- package/dist/es/icons/FolderMinusIcon.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/index.js +16 -8
- package/dist/es/initService.js +52 -16
- package/dist/es/layouts/AddPageBox.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/CodeEditor.vue_vue_type_script_setup_true_lang.js +26 -10
- package/dist/es/layouts/Framework.vue_vue_type_script_setup_true_lang.js +11 -8
- package/dist/es/layouts/NavMenu.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/NavMenuColumn.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/history-list/Bucket.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/history-list/BucketTab.vue_vue_type_script_setup_true_lang.js +8 -5
- package/dist/es/layouts/history-list/GroupRow.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/history-list/HistoryDiffDialog.vue_vue_type_script_setup_true_lang.js +26 -10
- package/dist/es/layouts/history-list/HistoryListPanel.vue_vue_type_script_setup_true_lang.js +11 -13
- package/dist/es/layouts/history-list/InitialRow.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/history-list/PageTab.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/history-list/composables.js +1 -1
- package/dist/es/layouts/history-list/useHistoryRevert.js +38 -33
- package/dist/es/layouts/page-bar/AddButton.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/page-bar/PageBar.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/page-bar/PageBarScrollContainer.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/page-bar/PageList.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/page-bar/Search.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/es/layouts/props-panel/FormPanel.vue_vue_type_script_setup_true_lang.js +50 -20
- package/dist/es/layouts/props-panel/PropsPanel.vue_vue_type_script_setup_true_lang.js +53 -35
- package/dist/es/layouts/props-panel/use-style-panel.js +3 -2
- package/dist/es/layouts/sidebar/ComponentListPanel.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/es/layouts/sidebar/Sidebar.vue_vue_type_script_setup_true_lang.js +21 -36
- package/dist/es/layouts/sidebar/code-block/CodeBlockList.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/sidebar/code-block/CodeBlockListPanel.vue_vue_type_script_setup_true_lang.js +4 -4
- package/dist/es/layouts/sidebar/code-block/useContentMenu.js +19 -4
- package/dist/es/layouts/sidebar/data-source/DataSourceAddButton.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/sidebar/data-source/DataSourceConfigPanel.vue_vue_type_script_setup_true_lang.js +9 -4
- package/dist/es/layouts/sidebar/data-source/DataSourceList.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/sidebar/data-source/DataSourceListPanel.vue_vue_type_script_setup_true_lang.js +4 -4
- package/dist/es/layouts/sidebar/data-source/useContentMenu.js +19 -4
- package/dist/es/layouts/sidebar/layer/LayerMenu.vue_vue_type_script_setup_true_lang.js +3 -3
- package/dist/es/layouts/sidebar/layer/LayerNodeContent.js +5 -0
- package/dist/es/layouts/sidebar/layer/LayerNodeContent.vue_vue_type_script_setup_true_lang.js +46 -0
- package/dist/es/layouts/sidebar/layer/LayerNodeTool.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/sidebar/layer/LayerPanel.vue_vue_type_script_setup_true_lang.js +6 -4
- package/dist/es/layouts/sidebar/layer/use-click.js +3 -3
- package/dist/es/layouts/sidebar/layer/use-drag.js +11 -10
- package/dist/es/layouts/sidebar/layer/use-node-status.js +2 -2
- package/dist/es/layouts/workspace/Breadcrumb.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/workspace/Workspace.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/workspace/viewer/NodeListMenu.vue_vue_type_script_setup_true_lang.js +9 -3
- package/dist/es/layouts/workspace/viewer/Stage.vue_vue_type_script_setup_true_lang.js +55 -9
- package/dist/es/layouts/workspace/viewer/StageOverlay.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/layouts/workspace/viewer/ViewerMenu.vue_vue_type_script_setup_true_lang.js +8 -8
- package/dist/es/plugin.js +35 -23
- package/dist/es/services/codeBlock.js +8 -3
- package/dist/es/services/dataSource.js +3 -0
- package/dist/es/services/dep.js +162 -41
- package/dist/es/services/editor.js +344 -113
- package/dist/es/services/events.js +4 -4
- package/dist/es/services/history.js +17 -1
- package/dist/es/services/keybinding.js +3 -3
- package/dist/es/services/props.js +2 -1
- package/dist/es/services/storage.js +2 -2
- package/dist/es/services/ui.js +7 -2
- package/dist/es/style.css +277 -114
- package/dist/es/utils/code-block.js +14 -7
- package/dist/es/utils/config.js +4 -1
- package/dist/es/utils/const.js +2 -2
- package/dist/es/utils/content-menu.js +2 -2
- package/dist/es/utils/data-source/index.js +34 -12
- package/dist/es/utils/dep/collect-worker-client.js +154 -0
- package/dist/es/utils/dep/idle-task.js +70 -22
- package/dist/es/utils/dep/worker.js +1 -1
- package/dist/es/utils/editor.js +4 -2
- package/dist/es/utils/event.js +135 -0
- package/dist/es/utils/monaco-editor.js +22 -6
- package/dist/es/utils/operator.js +2 -2
- package/dist/es/utils/props.js +50 -106
- package/dist/es/utils/type-match-rules.js +356 -0
- package/dist/style.css +277 -114
- package/dist/themes/magic-admin.css +978 -175
- package/dist/tmagic-editor-headless.umd.cjs +10880 -0
- package/dist/tmagic-editor.umd.cjs +12695 -10896
- package/package.json +18 -13
- package/src/Editor.vue +23 -6
- package/src/components/CodeBlockEditor.vue +3 -0
- package/src/components/CodeParams.vue +10 -4
- package/src/components/CompareForm.vue +20 -190
- package/src/components/ContentMenu.vue +34 -6
- package/src/components/FloatingBox.vue +71 -7
- package/src/components/ScrollBar.vue +0 -67
- package/src/components/ViewForm.vue +54 -0
- package/src/editorProps.ts +23 -10
- package/src/fields/Code.vue +1 -1
- package/src/fields/CodeSelect.vue +20 -113
- package/src/fields/CodeSelectCol.vue +1 -1
- package/src/fields/CondOpSelect.vue +5 -26
- package/src/fields/DataSourceFieldSelect/FieldSelect.vue +2 -2
- package/src/fields/DataSourceFieldSelect/Index.vue +4 -1
- package/src/fields/DataSourceFields.vue +5 -1
- package/src/fields/DataSourceInput.vue +10 -28
- package/src/fields/DataSourceMethodSelect.vue +1 -1
- package/src/fields/DataSourceMethods.vue +6 -2
- package/src/fields/DataSourceMocks.vue +3 -0
- package/src/fields/DataSourceSelect.vue +1 -1
- package/src/fields/DisplayConds.vue +17 -139
- package/src/fields/EventSelect.vue +29 -416
- package/src/fields/KeyValue.vue +1 -1
- package/src/fields/StyleSetter/Index.vue +2 -8
- package/src/fields/StyleSetter/components/Border.vue +4 -38
- package/src/fields/StyleSetter/components/Box.vue +1 -1
- package/src/fields/StyleSetter/components/Position.vue +1 -1
- package/src/fields/StyleSetter/configs.ts +690 -0
- package/src/fields/StyleSetter/pro/Background.vue +9 -64
- package/src/fields/StyleSetter/pro/Border.vue +5 -16
- package/src/fields/StyleSetter/pro/Font.vue +11 -71
- package/src/fields/StyleSetter/pro/Layout.vue +10 -230
- package/src/fields/StyleSetter/pro/Position.vue +11 -82
- package/src/fields/StyleSetter/pro/Transform.vue +6 -34
- package/src/fields/UISelect.vue +0 -12
- package/src/fields/configs/codeSelect.ts +127 -0
- package/src/fields/configs/displayConds.ts +184 -0
- package/src/fields/configs/eventSelect.ts +309 -0
- package/src/fields/configs/stickyAddButton.ts +32 -0
- package/src/fields/headless-validation.ts +177 -0
- package/src/headless.ts +33 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-compare-form.ts +166 -0
- package/src/hooks/use-form-context.ts +56 -0
- package/src/hooks/use-stage.ts +1 -0
- package/src/index.ts +9 -0
- package/src/initService.ts +73 -18
- package/src/layouts/CodeEditor.vue +32 -6
- package/src/layouts/Framework.vue +7 -6
- package/src/layouts/history-list/BucketTab.vue +2 -2
- package/src/layouts/history-list/HistoryDiffDialog.vue +33 -15
- package/src/layouts/history-list/HistoryListPanel.vue +16 -18
- package/src/layouts/history-list/useHistoryRevert.ts +57 -41
- package/src/layouts/props-panel/FormPanel.vue +75 -20
- package/src/layouts/props-panel/PropsPanel.vue +81 -30
- package/src/layouts/props-panel/use-style-panel.ts +4 -3
- package/src/layouts/sidebar/ComponentListPanel.vue +6 -2
- package/src/layouts/sidebar/Sidebar.vue +5 -3
- package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +5 -2
- package/src/layouts/sidebar/code-block/useContentMenu.ts +14 -2
- package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +3 -0
- package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +3 -3
- package/src/layouts/sidebar/data-source/useContentMenu.ts +14 -2
- package/src/layouts/sidebar/layer/LayerMenu.vue +2 -2
- package/src/layouts/sidebar/layer/LayerNodeContent.vue +57 -0
- package/src/layouts/sidebar/layer/LayerPanel.vue +5 -2
- package/src/layouts/sidebar/layer/use-click.ts +3 -3
- package/src/layouts/sidebar/layer/use-node-status.ts +2 -2
- package/src/layouts/workspace/viewer/NodeListMenu.vue +4 -1
- package/src/layouts/workspace/viewer/Stage.vue +80 -10
- package/src/layouts/workspace/viewer/ViewerMenu.vue +7 -7
- package/src/plugin.ts +35 -25
- package/src/services/codeBlock.ts +4 -0
- package/src/services/dataSource.ts +3 -0
- package/src/services/dep.ts +292 -47
- package/src/services/editor.ts +383 -120
- package/src/services/events.ts +8 -7
- package/src/services/history.ts +22 -1
- package/src/services/keybinding.ts +3 -3
- package/src/services/ui.ts +26 -5
- package/src/theme/code-block.scss +0 -37
- package/src/theme/display-conds.scss +4 -0
- package/src/theme/event.scss +25 -33
- package/src/theme/floating-box.scss +9 -1
- package/src/theme/framework.scss +4 -1
- package/src/theme/layer-node-content.scss +14 -0
- package/src/theme/nav-menu.scss +5 -1
- package/src/theme/props-panel.scss +17 -3
- package/src/theme/scroll-bar.scss +64 -0
- package/src/theme/theme.scss +3 -0
- package/src/theme/themes/magic-admin/index.scss +109 -9
- package/src/theme/ui-select.scss +9 -0
- package/src/type.ts +216 -6
- package/src/utils/code-block.ts +1 -0
- package/src/utils/config.ts +9 -1
- package/src/utils/const.ts +3 -3
- package/src/utils/content-menu.ts +2 -2
- package/src/utils/data-source/index.ts +31 -12
- package/src/utils/dep/collect-worker-client.ts +215 -0
- package/src/utils/dep/idle-task.ts +104 -35
- package/src/utils/dep/worker.ts +113 -9
- package/src/utils/event.ts +237 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/monaco-editor.ts +27 -0
- package/src/utils/operator.ts +2 -2
- package/src/utils/props.ts +61 -122
- package/src/utils/type-match-rules.ts +697 -0
- package/types/headless.d.ts +17 -0
- package/types/index.d.ts +1199 -724
- package/src/fields/StyleSetter/icons/align-items/index copy.ts +0 -5
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.8.0
|
|
2
|
+
"version": "1.8.0",
|
|
3
3
|
"name": "@tmagic/editor",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": [
|
|
@@ -17,6 +17,11 @@
|
|
|
17
17
|
"import": "./dist/es/index.js",
|
|
18
18
|
"require": "./dist/tmagic-editor.umd.cjs"
|
|
19
19
|
},
|
|
20
|
+
"./headless": {
|
|
21
|
+
"types": "./types/headless.d.ts",
|
|
22
|
+
"import": "./dist/es/headless.js",
|
|
23
|
+
"require": "./dist/tmagic-editor-headless.umd.cjs"
|
|
24
|
+
},
|
|
20
25
|
"./dist/style.css": {
|
|
21
26
|
"import": "./dist/style.css",
|
|
22
27
|
"require": "./dist/style.css"
|
|
@@ -54,29 +59,29 @@
|
|
|
54
59
|
"events": "^3.3.0",
|
|
55
60
|
"gesto": "^1.19.4",
|
|
56
61
|
"keycon": "^1.4.0",
|
|
57
|
-
"lodash-es": "^4.
|
|
62
|
+
"lodash-es": "^4.18.1",
|
|
58
63
|
"moveable": "^0.53.0",
|
|
59
|
-
"serialize-javascript": "^7.
|
|
60
|
-
"sortablejs": "^1.15.
|
|
61
|
-
"@tmagic/design": "1.8.0
|
|
62
|
-
"@tmagic/
|
|
63
|
-
"@tmagic/
|
|
64
|
-
"@tmagic/
|
|
65
|
-
"@tmagic/
|
|
64
|
+
"serialize-javascript": "^7.1.1",
|
|
65
|
+
"sortablejs": "^1.15.7",
|
|
66
|
+
"@tmagic/design": "1.8.0",
|
|
67
|
+
"@tmagic/form": "1.8.0",
|
|
68
|
+
"@tmagic/stage": "1.8.0",
|
|
69
|
+
"@tmagic/utils": "1.8.0",
|
|
70
|
+
"@tmagic/table": "1.8.0"
|
|
66
71
|
},
|
|
67
72
|
"devDependencies": {
|
|
68
73
|
"@types/events": "^3.0.3",
|
|
69
|
-
"@types/lodash-es": "^4.17.
|
|
74
|
+
"@types/lodash-es": "^4.17.12",
|
|
70
75
|
"@types/serialize-javascript": "^5.0.4",
|
|
71
76
|
"@types/sortablejs": "^1.15.9",
|
|
72
|
-
"@vue/test-utils": "^2.
|
|
77
|
+
"@vue/test-utils": "^2.5.1"
|
|
73
78
|
},
|
|
74
79
|
"peerDependencies": {
|
|
75
80
|
"monaco-editor": "^0.55.1 ",
|
|
76
81
|
"type-fest": "^5.2.0",
|
|
77
82
|
"typescript": "^6.0.3",
|
|
78
|
-
"vue": "^3.5.
|
|
79
|
-
"@tmagic/core": "1.8.0
|
|
83
|
+
"vue": "^3.5.43",
|
|
84
|
+
"@tmagic/core": "1.8.0"
|
|
80
85
|
},
|
|
81
86
|
"peerDependenciesMeta": {
|
|
82
87
|
"typescript": {
|
package/src/Editor.vue
CHANGED
|
@@ -101,7 +101,6 @@
|
|
|
101
101
|
<template #props-panel>
|
|
102
102
|
<slot name="props-panel">
|
|
103
103
|
<PropsPanel
|
|
104
|
-
:extend-state="extendFormState"
|
|
105
104
|
:disabled-show-src="disabledShowSrc"
|
|
106
105
|
@mounted="propsPanelMountedHandler"
|
|
107
106
|
@unmounted="propsPanelUnmountedHandler"
|
|
@@ -140,7 +139,9 @@ import { computed, provide } from 'vue';
|
|
|
140
139
|
|
|
141
140
|
import type { MApp } from '@tmagic/core';
|
|
142
141
|
import { M_THEME_KEY } from '@tmagic/design';
|
|
142
|
+
import { FORM_CONTEXT_KEY } from '@tmagic/form';
|
|
143
143
|
|
|
144
|
+
import { useEditorFormContext } from './hooks/use-form-context';
|
|
144
145
|
import Framework from './layouts/Framework.vue';
|
|
145
146
|
import TMagicNavMenu from './layouts/NavMenu.vue';
|
|
146
147
|
import FormPanel from './layouts/props-panel/FormPanel.vue';
|
|
@@ -160,7 +161,7 @@ import stageOverlayService from './services/stageOverlay';
|
|
|
160
161
|
import storageService from './services/storage';
|
|
161
162
|
import uiService from './services/ui';
|
|
162
163
|
import keybindingConfig from './utils/keybinding-config';
|
|
163
|
-
import { defaultEditorProps, EditorProps } from './editorProps';
|
|
164
|
+
import { defaultEditorProps, EditorProps, ENABLE_PROPS_FORM_VALIDATE } from './editorProps';
|
|
164
165
|
import { initServiceEvents, initServiceState } from './initService';
|
|
165
166
|
import type { TreeNodeData } from './type';
|
|
166
167
|
import type { EditorSlots, EventBus, Services, StageOptions } from './type';
|
|
@@ -218,6 +219,7 @@ const stageOptions: StageOptions = {
|
|
|
218
219
|
containerHighlightClassName: props.containerHighlightClassName,
|
|
219
220
|
containerHighlightDuration: props.containerHighlightDuration,
|
|
220
221
|
containerHighlightType: props.containerHighlightType,
|
|
222
|
+
containerHighlightAddOnly: props.containerHighlightAddOnly,
|
|
221
223
|
disabledDragStart: props.disabledDragStart,
|
|
222
224
|
renderType: props.renderType,
|
|
223
225
|
guidesOptions: props.guidesOptions,
|
|
@@ -233,13 +235,28 @@ provide('services', services);
|
|
|
233
235
|
|
|
234
236
|
provide('codeOptions', props.codeOptions);
|
|
235
237
|
provide('stageOptions', stageOptions);
|
|
238
|
+
/** 是否启用「属性配置表单校验」联动能力,供 PropsPanel / FormPanel 判断校验失败时是否仍更新节点并记录错误 */
|
|
239
|
+
provide(ENABLE_PROPS_FORM_VALIDATE, props.enablePropsFormValidate ?? false);
|
|
236
240
|
/**
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
241
|
+
* 编辑器注入给整棵表单树的业务上下文(`services` / `stage`),属性面板、对比表单、
|
|
242
|
+
* 侧边栏里的嵌套 MForm 都通过 inject 自动继承。
|
|
243
|
+
*
|
|
244
|
+
* 业务方要追加自己的字段,在 `<MEditor>` 外层再 `provide(FORM_CONTEXT_KEY, computed(...))`
|
|
245
|
+
* 即可,配置回调统一通过 `mForm.xxx` 读取。
|
|
240
246
|
*/
|
|
241
|
-
provide(
|
|
247
|
+
provide(
|
|
248
|
+
FORM_CONTEXT_KEY,
|
|
249
|
+
useEditorFormContext(() => services),
|
|
250
|
+
);
|
|
242
251
|
|
|
252
|
+
// 用 computed 包一层再 provide,否则传下去的是 provide 那一刻的值快照,
|
|
253
|
+
// props.isLargeStageContainer 后续变化不会同步到子孙(如 @tmagic/design/ColorPicker)。
|
|
254
|
+
// 子孙侧 `inject<ComputedRef<boolean>>('isLargeStageContainer', computed(() => false))`
|
|
255
|
+
// 用 `.value` 或模板自动解包读取即可拿到最新值。
|
|
256
|
+
provide(
|
|
257
|
+
'isLargeStageContainer',
|
|
258
|
+
computed(() => props.isLargeStageContainer),
|
|
259
|
+
);
|
|
243
260
|
/**
|
|
244
261
|
* 把历史记录面板的自定义扩展 tab 提供给深层的 HistoryListPanel(它挂在 NavMenu 中,
|
|
245
262
|
* 以 markRaw component 形式渲染,无法直接通过 props 透传)。业务方可借此在历史记录
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
v-model:visible="boxVisible"
|
|
5
5
|
v-model:width="width"
|
|
6
6
|
v-model:height="codeBlockEditorHeight"
|
|
7
|
+
:body-style="{ padding: '0 16px' }"
|
|
7
8
|
:title="content.name ? `${disabled ? '查看' : '编辑'}${content.name}` : '新增代码'"
|
|
9
|
+
:framework-width="frameworkWidth"
|
|
8
10
|
:position="boxPosition"
|
|
9
11
|
:before-close="beforeClose"
|
|
10
12
|
>
|
|
@@ -206,6 +208,7 @@ const closedHandler = () => {
|
|
|
206
208
|
|
|
207
209
|
const parentFloating = inject<Ref<HTMLDivElement | null>>('parentFloating', ref(null));
|
|
208
210
|
const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(uiService, parentFloating);
|
|
211
|
+
const frameworkWidth = computed(() => uiService.get('frameworkRect')?.width || 0);
|
|
209
212
|
|
|
210
213
|
watch(boxVisible, (visible) => {
|
|
211
214
|
nextTick(() => {
|
|
@@ -15,7 +15,13 @@
|
|
|
15
15
|
<script lang="ts" setup>
|
|
16
16
|
import { computed, useTemplateRef } from 'vue';
|
|
17
17
|
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
type ContainerChangeEventData,
|
|
20
|
+
defineFormItem,
|
|
21
|
+
type FormItemConfig,
|
|
22
|
+
type FormValue,
|
|
23
|
+
MForm,
|
|
24
|
+
} from '@tmagic/form';
|
|
19
25
|
|
|
20
26
|
import type { CodeParamStatement } from '@editor/type';
|
|
21
27
|
import { error } from '@editor/utils';
|
|
@@ -41,13 +47,13 @@ const emit = defineEmits(['change']);
|
|
|
41
47
|
const formRef = useTemplateRef<InstanceType<typeof MForm>>('form');
|
|
42
48
|
|
|
43
49
|
const getFormConfig = (items: FormItemConfig[] = []) => [
|
|
44
|
-
{
|
|
50
|
+
defineFormItem({
|
|
45
51
|
type: 'fieldset',
|
|
46
52
|
items,
|
|
47
53
|
legend: '参数',
|
|
48
|
-
|
|
54
|
+
labelPosition: 'top',
|
|
49
55
|
name: props.name,
|
|
50
|
-
},
|
|
56
|
+
}),
|
|
51
57
|
];
|
|
52
58
|
|
|
53
59
|
const codeParamsConfig = computed(() =>
|
|
@@ -10,104 +10,45 @@
|
|
|
10
10
|
:is-compare="true"
|
|
11
11
|
:disabled="true"
|
|
12
12
|
:label-width="labelWidth"
|
|
13
|
-
:
|
|
13
|
+
:context="formContext"
|
|
14
14
|
:show-diff="showDiff"
|
|
15
|
+
:self-diff-field-types="selfDiffFieldTypes"
|
|
16
|
+
:size="size"
|
|
15
17
|
></MForm>
|
|
16
18
|
</div>
|
|
17
19
|
</template>
|
|
18
20
|
|
|
19
21
|
<script lang="ts" setup>
|
|
20
|
-
import { computed,
|
|
22
|
+
import { computed, type Ref, type ShallowRef } from 'vue';
|
|
21
23
|
import { isEqual } from 'lodash-es';
|
|
22
24
|
|
|
23
|
-
import { type CodeBlockContent,
|
|
24
|
-
import { type FormConfig, type
|
|
25
|
+
import { type CodeBlockContent, HookType } from '@tmagic/core';
|
|
26
|
+
import { type FormConfig, type FormValue, MForm } from '@tmagic/form';
|
|
25
27
|
|
|
26
|
-
import {
|
|
27
|
-
import type {
|
|
28
|
-
import { getCodeBlockFormConfig } from '@editor/utils/code-block';
|
|
28
|
+
import { useCompareForm } from '@editor/hooks/use-compare-form';
|
|
29
|
+
import type { CompareFormBaseProps } from '@editor/type';
|
|
29
30
|
|
|
30
31
|
defineOptions({
|
|
31
32
|
name: 'MEditorCompareForm',
|
|
32
33
|
});
|
|
33
34
|
|
|
34
35
|
const props = withDefaults(
|
|
35
|
-
defineProps<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
* - `category` 为 `data-source` 时,`type` 为数据源类型,例如 'base'、'http'
|
|
44
|
-
* - `category` 为 `code-block` 时,`type` 可不传
|
|
45
|
-
*/
|
|
46
|
-
type?: string;
|
|
47
|
-
/** 表单配置类别,决定从哪里取 FormConfig */
|
|
48
|
-
category?: CompareCategory;
|
|
49
|
-
/** 数据源代码块场景下的数据源类型(base/http),用于代码块表单中"执行时机"展示 */
|
|
50
|
-
dataSourceType?: string;
|
|
51
|
-
labelWidth?: string;
|
|
52
|
-
/**
|
|
53
|
-
* 外层容器高度。设置后表单内容超出时会在 CompareForm 内部出现滚动条,
|
|
54
|
-
* 避免 dialog / 面板使用方需要自行处理滚动。可传任意 CSS 长度,例如 `60vh` / `400px` / `100%`。
|
|
55
|
-
*/
|
|
56
|
-
height?: string;
|
|
57
|
-
/**
|
|
58
|
-
* 用户自定义注入到 MForm.formState 的扩展字段,与 Editor 顶层的 `extendFormState`、
|
|
59
|
-
* PropsPanel 的 `extend-state` 语义一致。表单 item 的 `display` / `disabled` 等
|
|
60
|
-
* filterFunction 经常依赖这里注入的字段(如 stage、自定义业务上下文等),
|
|
61
|
-
* 因此在差异对比场景下也需要透传,避免出现 `formState.xxx is undefined` 的运行时错误。
|
|
62
|
-
*/
|
|
63
|
-
extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
|
|
64
|
-
/**
|
|
65
|
-
* 自定义 FormConfig 加载逻辑。传入后将接管内置的按 `category`(node/data-source/code-block)
|
|
66
|
-
* 取配置逻辑,调用方可根据业务自行返回(或异步返回)表单配置。可通过
|
|
67
|
-
* `ctx.defaultLoadConfig()` 复用默认结果再做二次加工。返回的 config 直接用于对比展示。
|
|
68
|
-
*/
|
|
69
|
-
loadConfig?: CompareFormLoadConfig;
|
|
70
|
-
/** 编辑器服务集合,由调用方传入(不再通过 inject('services') 获取)。 */
|
|
71
|
-
services: Services;
|
|
72
|
-
}>(),
|
|
36
|
+
defineProps<
|
|
37
|
+
CompareFormBaseProps & {
|
|
38
|
+
/** 用于对比的旧值(修改前的值) */
|
|
39
|
+
lastValue?: CompareFormBaseProps['value'];
|
|
40
|
+
/** 需要走 self diff 的字段类型(例如 mod-cond)。 */
|
|
41
|
+
selfDiffFieldTypes?: string[];
|
|
42
|
+
}
|
|
43
|
+
>(),
|
|
73
44
|
{
|
|
74
45
|
category: 'node',
|
|
75
46
|
labelWidth: '120px',
|
|
76
|
-
services: () => useServices(),
|
|
77
47
|
},
|
|
78
48
|
);
|
|
79
49
|
|
|
80
|
-
const {
|
|
81
|
-
|
|
82
|
-
provide('services', props.services);
|
|
83
|
-
|
|
84
|
-
const config = ref<FormConfig>([]);
|
|
85
|
-
|
|
86
|
-
/** vs-code 编辑器的 monaco 配置项,沿用 Editor 顶层 provide('codeOptions', ...) 的注入。 */
|
|
87
|
-
const codeOptions = inject<Record<string, any>>('codeOptions', {});
|
|
88
|
-
|
|
89
|
-
/** 将代码块的 content 字段统一成字符串,便于在表单/对比中展示 */
|
|
90
|
-
const normalizeCodeBlockValue = (
|
|
91
|
-
v: Partial<CodeBlockContent> | Record<string, any> | undefined,
|
|
92
|
-
): Record<string, any> => {
|
|
93
|
-
if (!v) return {};
|
|
94
|
-
const next: Record<string, any> = { ...v };
|
|
95
|
-
if (next.content && typeof next.content !== 'string') {
|
|
96
|
-
try {
|
|
97
|
-
next.content = next.content.toString();
|
|
98
|
-
} catch {
|
|
99
|
-
next.content = '';
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return next;
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
const currentValues = computed<FormValue>(() => {
|
|
106
|
-
if (props.category === 'code-block') {
|
|
107
|
-
return normalizeCodeBlockValue(props.value as Partial<CodeBlockContent>);
|
|
108
|
-
}
|
|
109
|
-
return (props.value || {}) as FormValue;
|
|
110
|
-
});
|
|
50
|
+
const { config, currentValues, wrapperStyle, formContext, loadConfig, formRef, normalizeCodeBlockValue } =
|
|
51
|
+
useCompareForm(props);
|
|
111
52
|
|
|
112
53
|
const lastValuesProcessed = computed<FormValue>(() => {
|
|
113
54
|
if (props.category === 'code-block') {
|
|
@@ -116,24 +57,11 @@ const lastValuesProcessed = computed<FormValue>(() => {
|
|
|
116
57
|
return (props.lastValue || {}) as FormValue;
|
|
117
58
|
});
|
|
118
59
|
|
|
119
|
-
/**
|
|
120
|
-
* 外层包裹层的样式:当传入 `height` 时启用固定高度 + 内部滚动,
|
|
121
|
-
* 这样滚动条会出现在 CompareForm 内部,避免父容器(如 Dialog)自身也产生滚动。
|
|
122
|
-
*/
|
|
123
|
-
const wrapperStyle = computed(() => {
|
|
124
|
-
if (!props.height) return undefined;
|
|
125
|
-
return {
|
|
126
|
-
height: props.height,
|
|
127
|
-
overflow: 'auto',
|
|
128
|
-
} as Record<string, string>;
|
|
129
|
-
});
|
|
130
|
-
|
|
131
60
|
/**
|
|
132
61
|
* `code-select` 字段在历史数据中存在两种"语义为空"的形态:
|
|
133
62
|
* - 字符串 `''`(旧数据 / 用户从未配置过钩子);
|
|
134
|
-
* - `{ hookType: HookType.CODE, hookData: [] }
|
|
135
|
-
*
|
|
136
|
-
* `props.model[props.name] = { hookType: HookType.CODE, hookData: [] }`)。
|
|
63
|
+
* - `{ hookType: HookType.CODE, hookData: [] }`(`normalizeCodeSelectValue`
|
|
64
|
+
* 写入的默认结构)。
|
|
137
65
|
*
|
|
138
66
|
* 直接 `isEqual` 会把两者判为不等,从而在历史对比里对每个未配置过钩子的组件
|
|
139
67
|
* 都展示一份"差异",体验很糟糕。这里把它们视为相等,跳过对比。
|
|
@@ -156,104 +84,6 @@ const showDiff = ({ curValue, lastValue, config }: { curValue: any; lastValue: a
|
|
|
156
84
|
return !isEqual(curValue, lastValue);
|
|
157
85
|
};
|
|
158
86
|
|
|
159
|
-
const removeStyleDisplayConfig = (formConfig: FormConfig): FormConfig =>
|
|
160
|
-
formConfig.map((item) => {
|
|
161
|
-
if (!('type' in item)) return item;
|
|
162
|
-
if (item?.type !== 'tab' || !Array.isArray(item.items)) return item;
|
|
163
|
-
|
|
164
|
-
return {
|
|
165
|
-
...item,
|
|
166
|
-
items: item.items.map((tabPane) => {
|
|
167
|
-
if (tabPane?.title !== '样式' || !Array.isArray(tabPane.items)) return tabPane;
|
|
168
|
-
|
|
169
|
-
return {
|
|
170
|
-
...tabPane,
|
|
171
|
-
display: true,
|
|
172
|
-
};
|
|
173
|
-
}),
|
|
174
|
-
};
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* 内置的默认 FormConfig 加载逻辑:按 `category` 从对应 service / 工具取配置。
|
|
179
|
-
* 作为 ctx.defaultLoadConfig 透传给自定义 `loadConfig`,方便复用与二次加工。
|
|
180
|
-
*/
|
|
181
|
-
const defaultLoadConfig = async (): Promise<FormConfig> => {
|
|
182
|
-
switch (props.category) {
|
|
183
|
-
case 'node': {
|
|
184
|
-
if (!props.type) {
|
|
185
|
-
return [];
|
|
186
|
-
}
|
|
187
|
-
return removeStyleDisplayConfig(
|
|
188
|
-
await propsService.getPropsConfig(props.type, { node: props.value as unknown as MNode }),
|
|
189
|
-
);
|
|
190
|
-
}
|
|
191
|
-
case 'data-source': {
|
|
192
|
-
const config = dataSourceService.getFormConfig(props.type || 'base');
|
|
193
|
-
// 数据源表单外层 tab 的「数据定义」项 status 为 'fields',tab-pane name 随之为 'fields'。
|
|
194
|
-
// 未显式设置 active 时,Tabs 默认取 '0',与 'fields' 不匹配会导致打开弹窗时无默认激活项,
|
|
195
|
-
// 这里与 DataSourceConfigPanel 保持一致,默认激活「数据定义」tab。
|
|
196
|
-
return config.map((item) => ('type' in item && item.type === 'tab' ? { ...item, active: 'fields' } : item));
|
|
197
|
-
}
|
|
198
|
-
case 'code-block': {
|
|
199
|
-
return getCodeBlockFormConfig({
|
|
200
|
-
paramColConfig: codeBlockService.getParamsColConfig(),
|
|
201
|
-
// 通过传入 dataSourceType 间接表达"是数据源代码块"——在对比场景下 props.dataSourceType
|
|
202
|
-
// 由调用方按 step 上下文显式传入,未传则视为普通代码块,「执行时机」字段隐藏。
|
|
203
|
-
isDataSource: () => Boolean(props.dataSourceType),
|
|
204
|
-
dataSourceType: () => props.dataSourceType,
|
|
205
|
-
codeOptions,
|
|
206
|
-
// 对比模式只读,不需要校验/语法检查
|
|
207
|
-
editable: false,
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
default:
|
|
211
|
-
return [];
|
|
212
|
-
}
|
|
213
|
-
};
|
|
214
|
-
|
|
215
|
-
const loadConfig = async () => {
|
|
216
|
-
if (props.loadConfig) {
|
|
217
|
-
config.value = await props.loadConfig({
|
|
218
|
-
category: props.category,
|
|
219
|
-
type: props.type,
|
|
220
|
-
dataSourceType: props.dataSourceType,
|
|
221
|
-
defaultLoadConfig,
|
|
222
|
-
});
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
config.value = await defaultLoadConfig();
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
watch(
|
|
230
|
-
[() => props.category, () => props.type, () => props.dataSourceType, () => props.loadConfig],
|
|
231
|
-
() => {
|
|
232
|
-
loadConfig();
|
|
233
|
-
},
|
|
234
|
-
{ immediate: true },
|
|
235
|
-
);
|
|
236
|
-
|
|
237
|
-
const formRef = useTemplateRef<InstanceType<typeof MForm>>('form');
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* 把 services / stage 注入 MForm 的 formState,避免 propsService 注入的表单配置中
|
|
241
|
-
* 形如 `display: ({ services }) => services.uiService.get(...)` 的 filterFunction
|
|
242
|
-
* 在执行时拿不到 `formState.services` 而报错。
|
|
243
|
-
*
|
|
244
|
-
* 与 props-panel/FormPanel.vue 中的注入方式保持一致:
|
|
245
|
-
* - services:整个 useServices() 返回的服务集合;
|
|
246
|
-
* - stage:当前 editorService.get('stage') 的最新值。
|
|
247
|
-
*/
|
|
248
|
-
const stage = computed(() => editorService.get('stage'));
|
|
249
|
-
|
|
250
|
-
watchEffect(() => {
|
|
251
|
-
if (formRef.value) {
|
|
252
|
-
formRef.value.formState.stage = stage.value;
|
|
253
|
-
formRef.value.formState.services = props.services;
|
|
254
|
-
}
|
|
255
|
-
});
|
|
256
|
-
|
|
257
87
|
defineExpose<{
|
|
258
88
|
form: ShallowRef<InstanceType<typeof MForm> | null>;
|
|
259
89
|
config: Ref<FormConfig>;
|
|
@@ -128,20 +128,42 @@ const outsideClickHideHandler = (e: MouseEvent) => {
|
|
|
128
128
|
hide();
|
|
129
129
|
};
|
|
130
130
|
|
|
131
|
-
|
|
132
|
-
|
|
131
|
+
// 根据菜单实际尺寸修正位置,避免超出可视范围
|
|
132
|
+
const fixPosition = () => {
|
|
133
|
+
const menu = menuEl.value;
|
|
134
|
+
if (!menu || !visible.value) return;
|
|
135
|
+
|
|
136
|
+
const menuHeight = menu.clientHeight;
|
|
137
|
+
const menuWidth = menu.clientWidth;
|
|
138
|
+
|
|
139
|
+
let { top, left } = menuPosition.value;
|
|
140
|
+
|
|
141
|
+
if (top + menuHeight > document.body.clientHeight) {
|
|
142
|
+
top = Math.max(0, document.body.clientHeight - menuHeight);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (left + menuWidth > document.body.clientWidth) {
|
|
146
|
+
left = Math.max(0, document.body.clientWidth - menuWidth);
|
|
147
|
+
}
|
|
133
148
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
top = document.body.clientHeight - menuHeight;
|
|
149
|
+
if (top !== menuPosition.value.top || left !== menuPosition.value.left) {
|
|
150
|
+
menuPosition.value = { top, left };
|
|
137
151
|
}
|
|
152
|
+
};
|
|
138
153
|
|
|
154
|
+
const setPosition = (e: { clientY: number; clientX: number }) => {
|
|
139
155
|
menuPosition.value = {
|
|
140
|
-
top,
|
|
156
|
+
top: e.clientY,
|
|
141
157
|
left: e.clientX,
|
|
142
158
|
};
|
|
159
|
+
fixPosition();
|
|
143
160
|
};
|
|
144
161
|
|
|
162
|
+
// 菜单大小动态变化(如菜单项更新)后重新修正位置
|
|
163
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
164
|
+
fixPosition();
|
|
165
|
+
});
|
|
166
|
+
|
|
145
167
|
const show = (e?: { clientY: number; clientX: number }) => {
|
|
146
168
|
visible.value = true;
|
|
147
169
|
|
|
@@ -186,12 +208,18 @@ const mouseenterHandler = () => {
|
|
|
186
208
|
};
|
|
187
209
|
|
|
188
210
|
onMounted(() => {
|
|
211
|
+
if (menuEl.value) {
|
|
212
|
+
resizeObserver.observe(menuEl.value);
|
|
213
|
+
}
|
|
214
|
+
|
|
189
215
|
if (props.isSubMenu) return;
|
|
190
216
|
|
|
191
217
|
globalThis.addEventListener('mousedown', outsideClickHideHandler, true);
|
|
192
218
|
});
|
|
193
219
|
|
|
194
220
|
onBeforeUnmount(() => {
|
|
221
|
+
resizeObserver.disconnect();
|
|
222
|
+
|
|
195
223
|
if (props.isSubMenu) return;
|
|
196
224
|
|
|
197
225
|
globalThis.removeEventListener('mousedown', outsideClickHideHandler, true);
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
<div
|
|
4
4
|
ref="target"
|
|
5
5
|
:class="['m-editor-float-box', themeClass]"
|
|
6
|
+
v-bind="$attrs"
|
|
6
7
|
:style="{ ...style, zIndex: curZIndex }"
|
|
7
8
|
@mousedown="nextZIndex"
|
|
8
9
|
>
|
|
@@ -14,7 +15,7 @@
|
|
|
14
15
|
<TMagicButton link size="small" @click="closeHandler"><MIcon :icon="Close"></MIcon></TMagicButton>
|
|
15
16
|
</div>
|
|
16
17
|
</div>
|
|
17
|
-
<div class="m-editor-float-box-body" :style="{ height: `${bodyHeight}px
|
|
18
|
+
<div class="m-editor-float-box-body" :style="{ height: `${bodyHeight}px`, ...bodyStyle }">
|
|
18
19
|
<slot name="body"></slot>
|
|
19
20
|
</div>
|
|
20
21
|
</div>
|
|
@@ -22,14 +23,13 @@
|
|
|
22
23
|
</template>
|
|
23
24
|
|
|
24
25
|
<script setup lang="ts">
|
|
25
|
-
import { computed, nextTick, onBeforeUnmount, provide, ref, useTemplateRef, watch } from 'vue';
|
|
26
|
+
import { computed, type CSSProperties, nextTick, onBeforeUnmount, provide, ref, useTemplateRef, watch } from 'vue';
|
|
26
27
|
import { Close } from '@element-plus/icons-vue';
|
|
27
28
|
import VanillaMoveable from 'moveable';
|
|
28
29
|
|
|
29
30
|
import { TMagicButton, useThemeClass, useZIndex } from '@tmagic/design';
|
|
30
31
|
|
|
31
32
|
import MIcon from '@editor/components/Icon.vue';
|
|
32
|
-
import { useServices } from '@editor/hooks/use-services';
|
|
33
33
|
|
|
34
34
|
interface Position {
|
|
35
35
|
left: number;
|
|
@@ -44,11 +44,18 @@ const props = withDefaults(
|
|
|
44
44
|
defineProps<{
|
|
45
45
|
position?: Position;
|
|
46
46
|
title?: string;
|
|
47
|
+
bodyStyle?: CSSProperties;
|
|
48
|
+
/** 浮窗初始样式,会与内部计算样式合并,外部传入优先 */
|
|
49
|
+
initialStyle?: CSSProperties;
|
|
50
|
+
/** 用于约束浮窗 left 的容器宽度,传入时按宽度收敛 left,避免超出右边界;默认取视窗宽度 */
|
|
51
|
+
frameworkWidth?: number;
|
|
47
52
|
beforeClose?: (_done: (_cancel?: boolean) => void) => void;
|
|
48
53
|
}>(),
|
|
49
54
|
{
|
|
50
55
|
title: '',
|
|
51
56
|
position: () => ({ left: 0, top: 0 }),
|
|
57
|
+
initialStyle: () => ({}),
|
|
58
|
+
frameworkWidth: 0,
|
|
52
59
|
},
|
|
53
60
|
);
|
|
54
61
|
|
|
@@ -77,12 +84,11 @@ const bodyHeight = computed(() => {
|
|
|
77
84
|
return 'auto';
|
|
78
85
|
});
|
|
79
86
|
|
|
80
|
-
const { uiService } = useServices();
|
|
81
|
-
const frameworkWidth = computed(() => uiService.get('frameworkRect').width || 0);
|
|
82
87
|
const style = computed(() => {
|
|
83
88
|
let { left } = props.position;
|
|
84
|
-
|
|
85
|
-
|
|
89
|
+
const frameworkWidth = props.frameworkWidth || globalThis.window?.innerWidth || 0;
|
|
90
|
+
if (width.value && frameworkWidth) {
|
|
91
|
+
left = left + width.value > frameworkWidth ? frameworkWidth - width.value : left;
|
|
86
92
|
}
|
|
87
93
|
|
|
88
94
|
return {
|
|
@@ -90,11 +96,60 @@ const style = computed(() => {
|
|
|
90
96
|
top: `${props.position.top}px`,
|
|
91
97
|
width: width.value ? `${width.value}px` : 'auto',
|
|
92
98
|
height: height.value ? `${height.value}px` : 'auto',
|
|
99
|
+
...props.initialStyle,
|
|
93
100
|
};
|
|
94
101
|
});
|
|
95
102
|
|
|
96
103
|
let moveable: VanillaMoveable | null = null;
|
|
97
104
|
|
|
105
|
+
// 拖拽/缩放时用于覆盖 iframe 的遮罩,防止鼠标进入 iframe 区域后事件被 iframe 吞掉导致拖拽丢失
|
|
106
|
+
let dragMask: HTMLDivElement | null = null;
|
|
107
|
+
let dragMaskVisible = false;
|
|
108
|
+
|
|
109
|
+
// 兜底:正常情况下遮罩由 moveable 的 dragEnd/resizeEnd 移除;但某些极端场景
|
|
110
|
+
// (拖拽中鼠标移出窗口后松开、alt-tab 切走窗口失焦、标签页被隐藏等)结束事件不会触发,
|
|
111
|
+
// 会导致全屏透明遮罩残留、整个编辑器无法点击。这里挂全局 pointerup/blur/visibilitychange 强制收尾。
|
|
112
|
+
const bindDragMaskSafety = () => {
|
|
113
|
+
globalThis.window?.addEventListener('pointerup', hideDragMask, true);
|
|
114
|
+
globalThis.window?.addEventListener('blur', hideDragMask);
|
|
115
|
+
globalThis.document?.addEventListener('visibilitychange', hideDragMask);
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const unbindDragMaskSafety = () => {
|
|
119
|
+
globalThis.window?.removeEventListener('pointerup', hideDragMask, true);
|
|
120
|
+
globalThis.window?.removeEventListener('blur', hideDragMask);
|
|
121
|
+
globalThis.document?.removeEventListener('visibilitychange', hideDragMask);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const showDragMask = () => {
|
|
125
|
+
if (dragMaskVisible) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (!dragMask) {
|
|
129
|
+
dragMask = globalThis.document.createElement('div');
|
|
130
|
+
dragMask.className = 'm-editor-float-box-drag-mask';
|
|
131
|
+
}
|
|
132
|
+
globalThis.document.body.appendChild(dragMask);
|
|
133
|
+
dragMaskVisible = true;
|
|
134
|
+
bindDragMaskSafety();
|
|
135
|
+
|
|
136
|
+
// 拖拽标题时,root 上的 @mousedown="nextZIndex" 会把浮窗 z-index 抬高,
|
|
137
|
+
// 若此时才读取会拿到旧值导致遮罩被浮窗(及其内部 iframe)盖住,故用 nextTick 在 z-index 稳定后再设置到浮窗之上
|
|
138
|
+
const setMaskZIndex = () => {
|
|
139
|
+
if (dragMask) {
|
|
140
|
+
dragMask.style.zIndex = `${curZIndex.value + 1}`;
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
setMaskZIndex();
|
|
144
|
+
nextTick(setMaskZIndex);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const hideDragMask = () => {
|
|
148
|
+
unbindDragMaskSafety();
|
|
149
|
+
dragMask?.parentNode?.removeChild(dragMask);
|
|
150
|
+
dragMaskVisible = false;
|
|
151
|
+
};
|
|
152
|
+
|
|
98
153
|
const initMoveable = () => {
|
|
99
154
|
moveable = new VanillaMoveable(globalThis.document.body, {
|
|
100
155
|
className: 'm-editor-floating-box-moveable',
|
|
@@ -112,6 +167,14 @@ const initMoveable = () => {
|
|
|
112
167
|
bounds: { left: 0, top: 0, right: 0, bottom: 0, position: 'css' },
|
|
113
168
|
});
|
|
114
169
|
|
|
170
|
+
// 仅在真正发生拖拽/缩放位移时插入遮罩:moveable 的 dragStart/resizeStart 在 mousedown 时即触发,
|
|
171
|
+
// 若此时就盖遮罩,会盖住浮窗本身导致 mouseup 落在遮罩上、关闭按钮的 click 无法触发(点击关闭不了)。
|
|
172
|
+
// 改为在 drag/resize(实际位移)时才显示,纯点击不再触发遮罩。
|
|
173
|
+
moveable.on('drag', showDragMask);
|
|
174
|
+
moveable.on('resize', showDragMask);
|
|
175
|
+
moveable.on('dragEnd', hideDragMask);
|
|
176
|
+
moveable.on('resizeEnd', hideDragMask);
|
|
177
|
+
|
|
115
178
|
moveable.on('drag', (e) => {
|
|
116
179
|
e.target.style.transform = e.transform;
|
|
117
180
|
});
|
|
@@ -126,6 +189,7 @@ const initMoveable = () => {
|
|
|
126
189
|
};
|
|
127
190
|
|
|
128
191
|
const destroyMoveable = () => {
|
|
192
|
+
hideDragMask();
|
|
129
193
|
moveable?.destroy();
|
|
130
194
|
moveable = null;
|
|
131
195
|
};
|