@tmagic/editor 1.8.0-beta.2 → 1.8.0-beta.21
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 +43 -9
- package/dist/es/components/CodeBlockEditor.vue_vue_type_script_setup_true_lang.js +8 -4
- package/dist/es/components/CodeParams.vue_vue_type_script_setup_true_lang.js +3 -2
- package/dist/es/components/CompareForm.vue_vue_type_script_setup_true_lang.js +22 -98
- package/dist/es/components/ContentMenu.vue_vue_type_script_setup_true_lang.js +32 -9
- package/dist/es/components/FloatingBox.vue_vue_type_script_setup_true_lang.js +68 -17
- 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 +1 -1
- package/dist/es/components/ScrollBar.js +0 -1
- package/dist/es/components/ScrollBar.vue_vue_type_script_setup_true_lang.js +1 -1
- 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 +7 -7
- 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 +58 -0
- package/dist/es/editorProps.js +9 -1
- package/dist/es/fields/Code.vue_vue_type_script_setup_true_lang.js +16 -5
- package/dist/es/fields/CodeLink.vue_vue_type_script_setup_true_lang.js +7 -7
- package/dist/es/fields/CodeSelect.vue_vue_type_script_setup_true_lang.js +81 -44
- package/dist/es/fields/CodeSelectCol.vue_vue_type_script_setup_true_lang.js +10 -3
- 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 +13 -6
- package/dist/es/fields/DataSourceFieldSelect/Index.vue_vue_type_script_setup_true_lang.js +11 -8
- package/dist/es/fields/DataSourceFields.vue_vue_type_script_setup_true_lang.js +39 -12
- package/dist/es/fields/DataSourceInput.vue_vue_type_script_setup_true_lang.js +11 -20
- package/dist/es/fields/DataSourceMethodSelect.vue_vue_type_script_setup_true_name_true_lang.js +11 -6
- package/dist/es/fields/DataSourceMethods.vue_vue_type_script_setup_true_lang.js +30 -14
- package/dist/es/fields/DataSourceMocks.vue_vue_type_script_setup_true_lang.js +11 -4
- package/dist/es/fields/DataSourceSelect.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/DisplayConds.vue_vue_type_script_setup_true_lang.js +38 -6
- package/dist/es/fields/EventSelect.vue_vue_type_script_setup_true_lang.js +156 -155
- package/dist/es/fields/KeyValue.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/PageFragmentSelect.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/StyleSetter/Index.vue_vue_type_script_setup_true_lang.js +8 -10
- package/dist/es/fields/StyleSetter/components/BackgroundPosition.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/fields/StyleSetter/components/Border.vue_vue_type_script_setup_true_lang.js +28 -6
- package/dist/es/fields/StyleSetter/components/Box.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/fields/StyleSetter/icons/align-items/Center.js +31 -0
- package/dist/es/fields/StyleSetter/icons/align-items/FlexEnd.js +31 -0
- package/dist/es/fields/StyleSetter/icons/align-items/FlexStart.js +31 -0
- package/dist/es/fields/StyleSetter/icons/align-items/SpaceAround.js +50 -0
- package/dist/es/fields/StyleSetter/icons/align-items/SpaceBetween.js +50 -0
- package/dist/es/fields/StyleSetter/icons/background-repeat/NoRepeat.js +7 -7
- package/dist/es/fields/StyleSetter/icons/background-repeat/Repeat.js +6 -3
- package/dist/es/fields/StyleSetter/icons/background-repeat/RepeatX.js +29 -6
- package/dist/es/fields/StyleSetter/icons/background-repeat/RepeatY.js +32 -6
- 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 +11 -3
- package/dist/es/fields/StyleSetter/icons/flex-direction/ColumnReverse.js +11 -3
- package/dist/es/fields/StyleSetter/icons/flex-direction/Row.js +11 -3
- package/dist/es/fields/StyleSetter/icons/flex-direction/RowReverse.js +11 -3
- package/dist/es/fields/StyleSetter/icons/justify-content/Center.js +17 -3
- package/dist/es/fields/StyleSetter/icons/justify-content/FlexEnd.js +19 -3
- package/dist/es/fields/StyleSetter/icons/justify-content/FlexStart.js +19 -3
- package/dist/es/fields/StyleSetter/icons/justify-content/SpaceAround.js +37 -3
- package/dist/es/fields/StyleSetter/icons/justify-content/SpaceBetween.js +33 -3
- 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 +56 -30
- package/dist/es/fields/StyleSetter/pro/Border.vue_vue_type_script_setup_true_lang.js +7 -4
- package/dist/es/fields/StyleSetter/pro/Font.vue_vue_type_script_setup_true_lang.js +35 -26
- package/dist/es/fields/StyleSetter/pro/Layout.vue_vue_type_script_setup_true_lang.js +76 -48
- package/dist/es/fields/StyleSetter/pro/Position.vue_vue_type_script_setup_true_lang.js +29 -23
- package/dist/es/fields/StyleSetter/pro/Transform.vue_vue_type_script_setup_true_lang.js +7 -4
- package/dist/es/fields/UISelect.js +0 -1
- package/dist/es/fields/UISelect.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/es/hooks/use-code-block-edit.js +6 -3
- package/dist/es/hooks/use-compare-form.js +119 -0
- package/dist/es/hooks/use-data-source-edit.js +5 -2
- package/dist/es/hooks/use-stage.js +9 -4
- 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 +17 -0
- package/dist/es/icons/FolderMinusIcon.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/es/index.js +24 -10
- package/dist/es/initService.js +19 -13
- 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 +24 -12
- package/dist/es/layouts/Framework.vue_vue_type_script_setup_true_lang.js +25 -18
- package/dist/es/layouts/NavMenu.vue_vue_type_script_setup_true_lang.js +4 -4
- 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 +25 -38
- package/dist/es/layouts/history-list/BucketTab.js +5 -0
- package/dist/es/layouts/history-list/BucketTab.vue_vue_type_script_setup_true_lang.js +62 -0
- package/dist/es/layouts/history-list/GroupRow.vue_vue_type_script_setup_true_lang.js +177 -88
- package/dist/es/layouts/history-list/HistoryDiffDialog.vue_vue_type_script_setup_true_lang.js +139 -37
- package/dist/es/layouts/history-list/HistoryListPanel.vue_vue_type_script_setup_true_lang.js +164 -107
- package/dist/es/layouts/history-list/InitialRow.vue_vue_type_script_setup_true_lang.js +44 -9
- package/dist/es/layouts/history-list/PageTab.vue_vue_type_script_setup_true_lang.js +49 -53
- package/dist/es/layouts/history-list/composables.js +138 -108
- package/dist/es/layouts/history-list/useHistoryList.js +56 -0
- package/dist/es/layouts/history-list/useHistoryRevert.js +317 -0
- 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 +5 -3
- 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 -7
- package/dist/es/layouts/props-panel/PropsPanel.vue_vue_type_script_setup_true_lang.js +33 -13
- 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 +26 -38
- package/dist/es/layouts/sidebar/code-block/CodeBlockList.vue_vue_type_script_setup_true_lang.js +4 -4
- 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 +23 -6
- 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 +27 -5
- 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 +8 -8
- 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 +2 -2
- package/dist/es/layouts/sidebar/layer/LayerPanel.vue_vue_type_script_setup_true_lang.js +3 -2
- package/dist/es/layouts/sidebar/layer/use-click.js +3 -3
- 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 +2 -2
- 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 +16 -16
- package/dist/es/plugin.js +5 -2
- package/dist/es/services/codeBlock.js +137 -56
- package/dist/es/services/dataSource.js +122 -52
- package/dist/es/services/dep.js +162 -41
- package/dist/es/services/editor.js +613 -179
- package/dist/es/services/events.js +2 -2
- package/dist/es/services/history.js +350 -386
- package/dist/es/services/keybinding.js +6 -6
- package/dist/es/services/props.js +3 -2
- package/dist/es/services/storage.js +2 -2
- package/dist/es/services/ui.js +10 -2
- package/dist/es/style.css +549 -113
- package/dist/es/utils/config.js +4 -1
- package/dist/es/utils/const.js +2 -2
- package/dist/es/utils/content-menu.js +19 -11
- package/dist/es/utils/data-source/index.js +34 -11
- package/dist/es/utils/dep/collect-worker-client.js +114 -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 +103 -49
- package/dist/es/utils/event.js +135 -0
- package/dist/es/utils/history.js +220 -0
- package/dist/es/utils/indexed-db.js +86 -0
- package/dist/es/utils/monaco-editor.js +22 -6
- package/dist/es/utils/operator.js +2 -2
- package/dist/es/utils/props.js +114 -33
- package/dist/es/utils/type-match-rules.js +367 -0
- package/dist/es/utils/undo-redo.js +60 -1
- package/dist/style.css +549 -113
- package/dist/themes/magic-admin.css +3028 -0
- package/dist/tmagic-editor.umd.cjs +14403 -10121
- package/package.json +8 -8
- package/src/Editor.vue +43 -2
- package/src/components/CodeBlockEditor.vue +3 -0
- package/src/components/CompareForm.vue +18 -146
- package/src/components/ContentMenu.vue +44 -8
- package/src/components/FloatingBox.vue +84 -9
- package/src/components/ScrollBar.vue +0 -67
- package/src/components/ToolButton.vue +2 -2
- package/src/components/ViewForm.vue +55 -0
- package/src/editorProps.ts +30 -0
- package/src/fields/Code.vue +10 -2
- package/src/fields/CodeLink.vue +2 -5
- package/src/fields/CodeSelect.vue +54 -40
- package/src/fields/CodeSelectCol.vue +8 -1
- package/src/fields/CondOpSelect.vue +2 -24
- package/src/fields/DataSourceFieldSelect/FieldSelect.vue +16 -2
- package/src/fields/DataSourceFieldSelect/Index.vue +14 -5
- package/src/fields/DataSourceFields.vue +42 -8
- package/src/fields/DataSourceInput.vue +10 -28
- package/src/fields/DataSourceMethodSelect.vue +9 -4
- package/src/fields/DataSourceMethods.vue +42 -21
- package/src/fields/DataSourceMocks.vue +3 -0
- package/src/fields/DisplayConds.vue +18 -1
- package/src/fields/EventSelect.vue +152 -166
- package/src/fields/StyleSetter/Index.vue +3 -12
- package/src/fields/StyleSetter/components/Border.vue +15 -6
- package/src/fields/StyleSetter/icons/align-items/Center.vue +19 -0
- package/src/fields/StyleSetter/icons/align-items/FlexEnd.vue +19 -0
- package/src/fields/StyleSetter/icons/align-items/FlexStart.vue +19 -0
- package/src/fields/StyleSetter/icons/align-items/SpaceAround.vue +34 -0
- package/src/fields/StyleSetter/icons/align-items/SpaceBetween.vue +34 -0
- package/src/fields/StyleSetter/icons/align-items/index.ts +5 -0
- package/src/fields/StyleSetter/icons/background-repeat/NoRepeat.vue +20 -4
- package/src/fields/StyleSetter/icons/background-repeat/Repeat.vue +10 -28
- package/src/fields/StyleSetter/icons/background-repeat/RepeatX.vue +4 -5
- package/src/fields/StyleSetter/icons/background-repeat/RepeatY.vue +4 -5
- package/src/fields/StyleSetter/icons/flex-direction/Column.vue +4 -3
- package/src/fields/StyleSetter/icons/flex-direction/ColumnReverse.vue +4 -3
- package/src/fields/StyleSetter/icons/flex-direction/Row.vue +4 -3
- package/src/fields/StyleSetter/icons/flex-direction/RowReverse.vue +4 -3
- package/src/fields/StyleSetter/icons/justify-content/Center.vue +5 -2
- package/src/fields/StyleSetter/icons/justify-content/FlexEnd.vue +15 -2
- package/src/fields/StyleSetter/icons/justify-content/FlexStart.vue +15 -2
- package/src/fields/StyleSetter/icons/justify-content/SpaceAround.vue +28 -3
- package/src/fields/StyleSetter/icons/justify-content/SpaceBetween.vue +28 -2
- package/src/fields/StyleSetter/pro/Background.vue +99 -55
- package/src/fields/StyleSetter/pro/Border.vue +9 -11
- package/src/fields/StyleSetter/pro/Font.vue +66 -64
- package/src/fields/StyleSetter/pro/Layout.vue +211 -139
- package/src/fields/StyleSetter/pro/Position.vue +69 -67
- package/src/fields/StyleSetter/pro/Transform.vue +23 -25
- package/src/fields/UISelect.vue +0 -12
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-code-block-edit.ts +4 -3
- package/src/hooks/use-compare-form.ts +187 -0
- package/src/hooks/use-data-source-edit.ts +2 -2
- package/src/hooks/use-stage.ts +5 -3
- package/src/icons/DatasourceIcon.vue +7 -0
- package/src/index.ts +12 -0
- package/src/initService.ts +26 -16
- package/src/layouts/CodeEditor.vue +34 -11
- package/src/layouts/Framework.vue +15 -8
- package/src/layouts/NavMenu.vue +3 -3
- package/src/layouts/history-list/Bucket.vue +33 -41
- package/src/layouts/history-list/BucketTab.vue +72 -0
- package/src/layouts/history-list/GroupRow.vue +190 -93
- package/src/layouts/history-list/HistoryDiffDialog.vue +169 -90
- package/src/layouts/history-list/HistoryListPanel.vue +191 -95
- package/src/layouts/history-list/InitialRow.vue +38 -8
- package/src/layouts/history-list/PageTab.vue +67 -43
- package/src/layouts/history-list/composables.ts +239 -125
- package/src/layouts/history-list/useHistoryList.ts +60 -0
- package/src/layouts/history-list/useHistoryRevert.ts +425 -0
- package/src/layouts/page-bar/PageBar.vue +4 -2
- package/src/layouts/props-panel/FormPanel.vue +72 -6
- package/src/layouts/props-panel/PropsPanel.vue +62 -18
- package/src/layouts/props-panel/use-style-panel.ts +4 -3
- package/src/layouts/sidebar/ComponentListPanel.vue +10 -6
- package/src/layouts/sidebar/Sidebar.vue +13 -6
- package/src/layouts/sidebar/code-block/CodeBlockList.vue +5 -5
- 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 +34 -2
- package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +29 -4
- package/src/layouts/sidebar/data-source/useContentMenu.ts +14 -2
- package/src/layouts/sidebar/layer/LayerMenu.vue +21 -13
- package/src/layouts/sidebar/layer/LayerNodeContent.vue +57 -0
- package/src/layouts/sidebar/layer/LayerNodeTool.vue +7 -4
- package/src/layouts/sidebar/layer/LayerPanel.vue +4 -1
- 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 +1 -1
- package/src/layouts/workspace/viewer/ViewerMenu.vue +15 -15
- package/src/plugin.ts +6 -3
- package/src/services/codeBlock.ts +152 -47
- package/src/services/dataSource.ts +120 -41
- package/src/services/dep.ts +292 -47
- package/src/services/editor.ts +820 -224
- package/src/services/events.ts +3 -3
- package/src/services/history.ts +449 -412
- package/src/services/keybinding.ts +6 -6
- package/src/services/ui.ts +33 -5
- package/src/theme/code-block.scss +37 -0
- package/src/theme/common/var.scss +1 -1
- package/src/theme/component-list-panel.scss +2 -2
- package/src/theme/data-source-field.scss +4 -0
- package/src/theme/display-conds.scss +11 -0
- package/src/theme/event.scss +70 -1
- package/src/theme/floating-box.scss +9 -1
- package/src/theme/framework.scss +4 -1
- package/src/theme/history-list-panel.scss +157 -23
- package/src/theme/layer-node-content.scss +14 -0
- package/src/theme/nav-menu.scss +5 -1
- package/src/theme/page-bar.scss +0 -4
- package/src/theme/props-panel.scss +5 -4
- package/src/theme/scroll-bar.scss +64 -0
- package/src/theme/style-setter/border.scss +17 -5
- package/src/theme/theme.scss +4 -0
- package/src/theme/themes/magic-admin/index.scss +214 -0
- package/src/theme/ui-select.scss +9 -0
- package/src/type.ts +668 -124
- package/src/utils/config.ts +9 -1
- package/src/utils/const.ts +3 -2
- package/src/utils/content-menu.ts +20 -11
- package/src/utils/data-source/index.ts +32 -12
- package/src/utils/dep/collect-worker-client.ts +149 -0
- package/src/utils/dep/idle-task.ts +104 -35
- package/src/utils/dep/worker.ts +113 -9
- package/src/utils/editor.ts +166 -60
- package/src/utils/event.ts +237 -0
- package/src/utils/history.ts +286 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/indexed-db.ts +122 -0
- package/src/utils/monaco-editor.ts +27 -0
- package/src/utils/operator.ts +2 -2
- package/src/utils/props.ts +114 -11
- package/src/utils/type-match-rules.ts +684 -0
- package/src/utils/undo-redo.ts +88 -0
- package/types/index.d.ts +1990 -517
- package/dist/es/layouts/history-list/CodeBlockTab.js +0 -5
- package/dist/es/layouts/history-list/CodeBlockTab.vue_vue_type_script_setup_true_lang.js +0 -62
- package/dist/es/layouts/history-list/DataSourceTab.js +0 -5
- package/dist/es/layouts/history-list/DataSourceTab.vue_vue_type_script_setup_true_lang.js +0 -62
- package/src/layouts/history-list/CodeBlockTab.vue +0 -61
- package/src/layouts/history-list/DataSourceTab.vue +0 -61
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.8.0-beta.
|
|
2
|
+
"version": "1.8.0-beta.21",
|
|
3
3
|
"name": "@tmagic/editor",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": [
|
|
@@ -58,11 +58,11 @@
|
|
|
58
58
|
"moveable": "^0.53.0",
|
|
59
59
|
"serialize-javascript": "^7.0.0",
|
|
60
60
|
"sortablejs": "^1.15.6",
|
|
61
|
-
"@tmagic/design": "1.8.0-beta.
|
|
62
|
-
"@tmagic/
|
|
63
|
-
"@tmagic/
|
|
64
|
-
"@tmagic/
|
|
65
|
-
"@tmagic/
|
|
61
|
+
"@tmagic/design": "1.8.0-beta.21",
|
|
62
|
+
"@tmagic/form": "1.8.0-beta.21",
|
|
63
|
+
"@tmagic/stage": "1.8.0-beta.21",
|
|
64
|
+
"@tmagic/table": "1.8.0-beta.21",
|
|
65
|
+
"@tmagic/utils": "1.8.0-beta.21"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"@types/events": "^3.0.3",
|
|
@@ -75,8 +75,8 @@
|
|
|
75
75
|
"monaco-editor": "^0.55.1 ",
|
|
76
76
|
"type-fest": "^5.2.0",
|
|
77
77
|
"typescript": "^6.0.3",
|
|
78
|
-
"vue": "^3.5.
|
|
79
|
-
"@tmagic/core": "1.8.0-beta.
|
|
78
|
+
"vue": "^3.5.40",
|
|
79
|
+
"@tmagic/core": "1.8.0-beta.21"
|
|
80
80
|
},
|
|
81
81
|
"peerDependenciesMeta": {
|
|
82
82
|
"typescript": {
|
package/src/Editor.vue
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
:page-bar-sort-options="pageBarSortOptions"
|
|
5
5
|
:page-filter-function="pageFilterFunction"
|
|
6
6
|
:hide-sidebar="hideSidebar"
|
|
7
|
+
:theme="theme"
|
|
7
8
|
>
|
|
8
9
|
<template #header>
|
|
9
10
|
<slot name="header"></slot>
|
|
@@ -135,9 +136,10 @@
|
|
|
135
136
|
<script lang="ts" setup>
|
|
136
137
|
import { EventEmitter } from 'events';
|
|
137
138
|
|
|
138
|
-
import { provide } from 'vue';
|
|
139
|
+
import { computed, provide, ref } from 'vue';
|
|
139
140
|
|
|
140
141
|
import type { MApp } from '@tmagic/core';
|
|
142
|
+
import { M_THEME_KEY } from '@tmagic/design';
|
|
141
143
|
|
|
142
144
|
import Framework from './layouts/Framework.vue';
|
|
143
145
|
import TMagicNavMenu from './layouts/NavMenu.vue';
|
|
@@ -158,7 +160,7 @@ import stageOverlayService from './services/stageOverlay';
|
|
|
158
160
|
import storageService from './services/storage';
|
|
159
161
|
import uiService from './services/ui';
|
|
160
162
|
import keybindingConfig from './utils/keybinding-config';
|
|
161
|
-
import { defaultEditorProps, EditorProps } from './editorProps';
|
|
163
|
+
import { defaultEditorProps, EditorProps, ENABLE_PROPS_FORM_VALIDATE } from './editorProps';
|
|
162
164
|
import { initServiceEvents, initServiceState } from './initService';
|
|
163
165
|
import type { TreeNodeData } from './type';
|
|
164
166
|
import type { EditorSlots, EventBus, Services, StageOptions } from './type';
|
|
@@ -216,20 +218,26 @@ const stageOptions: StageOptions = {
|
|
|
216
218
|
containerHighlightClassName: props.containerHighlightClassName,
|
|
217
219
|
containerHighlightDuration: props.containerHighlightDuration,
|
|
218
220
|
containerHighlightType: props.containerHighlightType,
|
|
221
|
+
containerHighlightAddOnly: props.containerHighlightAddOnly,
|
|
219
222
|
disabledDragStart: props.disabledDragStart,
|
|
220
223
|
renderType: props.renderType,
|
|
221
224
|
guidesOptions: props.guidesOptions,
|
|
222
225
|
disabledMultiSelect: props.disabledMultiSelect,
|
|
223
226
|
alwaysMultiSelect: props.alwaysMultiSelect,
|
|
227
|
+
disabledFlashTip: props.disabledFlashTip,
|
|
224
228
|
beforeDblclick: props.beforeDblclick,
|
|
225
229
|
};
|
|
226
230
|
|
|
227
231
|
stageOverlayService.set('stageOptions', stageOptions);
|
|
228
232
|
|
|
233
|
+
const propsPanelRef = ref<InstanceType<typeof FormPanel> | null>(null);
|
|
234
|
+
|
|
229
235
|
provide('services', services);
|
|
230
236
|
|
|
231
237
|
provide('codeOptions', props.codeOptions);
|
|
232
238
|
provide('stageOptions', stageOptions);
|
|
239
|
+
/** 是否启用「属性配置表单校验」联动能力,供 PropsPanel / FormPanel 判断校验失败时是否仍更新节点并记录错误 */
|
|
240
|
+
provide(ENABLE_PROPS_FORM_VALIDATE, props.enablePropsFormValidate ?? false);
|
|
233
241
|
/**
|
|
234
242
|
* 把顶层 `extendFormState` 提供给非 PropsPanel 链路上的组件使用(例如历史差异对话框 HistoryDiffDialog
|
|
235
243
|
* 内部的 CompareForm)。这样所有依赖业务上下文的表单 filterFunction 都能拿到一致的扩展状态,
|
|
@@ -237,12 +245,45 @@ provide('stageOptions', stageOptions);
|
|
|
237
245
|
*/
|
|
238
246
|
provide('extendFormState', props.extendFormState);
|
|
239
247
|
|
|
248
|
+
// 用 computed 包一层再 provide,否则传下去的是 provide 那一刻的值快照,
|
|
249
|
+
// props.isLargeStageContainer 后续变化不会同步到子孙(如 @tmagic/design/ColorPicker)。
|
|
250
|
+
// 子孙侧 `inject<ComputedRef<boolean>>('isLargeStageContainer', computed(() => false))`
|
|
251
|
+
// 用 `.value` 或模板自动解包读取即可拿到最新值。
|
|
252
|
+
provide(
|
|
253
|
+
'isLargeStageContainer',
|
|
254
|
+
computed(() => props.isLargeStageContainer),
|
|
255
|
+
);
|
|
256
|
+
/**
|
|
257
|
+
* 提供 PropsPanel 主属性表单的 formState getter,供历史差异弹窗复用,
|
|
258
|
+
* 让 CompareForm 与 PropsPanel 的 filterFunction 上下文保持一致。
|
|
259
|
+
*/
|
|
260
|
+
provide('getPropsPanelFormState', () => propsPanelRef.value?.configForm?.formState);
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* 把历史记录面板的自定义扩展 tab 提供给深层的 HistoryListPanel(它挂在 NavMenu 中,
|
|
264
|
+
* 以 markRaw component 形式渲染,无法直接通过 props 透传)。业务方可借此在历史记录
|
|
265
|
+
* 面板内追加自定义模块的历史 tab。
|
|
266
|
+
*/
|
|
267
|
+
provide('historyListExtraTabs', props.historyListExtraTabs);
|
|
268
|
+
|
|
240
269
|
provide<EventBus>('eventBus', new EventEmitter());
|
|
241
270
|
|
|
271
|
+
/**
|
|
272
|
+
* 把当前主题以响应式 ref 形式 provide 给后代,供包含 `Teleport` 的组件
|
|
273
|
+
* (如 `TMagicPopover` / `FloatingBox` / `ContentMenu`)在传送目标上挂 `m-theme--<theme>`
|
|
274
|
+
* 类,让主题级 CSS 变量在 portal 节点上也能命中。详见 `@tmagic/design/theme.ts`。
|
|
275
|
+
*/
|
|
276
|
+
provide(
|
|
277
|
+
M_THEME_KEY,
|
|
278
|
+
computed(() => props.theme ?? ''),
|
|
279
|
+
);
|
|
280
|
+
|
|
242
281
|
const propsPanelMountedHandler = (e: InstanceType<typeof FormPanel>) => {
|
|
282
|
+
propsPanelRef.value = e;
|
|
243
283
|
emit('props-panel-mounted', e);
|
|
244
284
|
};
|
|
245
285
|
const propsPanelUnmountedHandler = () => {
|
|
286
|
+
propsPanelRef.value = null;
|
|
246
287
|
emit('props-panel-unmounted');
|
|
247
288
|
};
|
|
248
289
|
|
|
@@ -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(() => {
|
|
@@ -10,101 +10,45 @@
|
|
|
10
10
|
:is-compare="true"
|
|
11
11
|
:disabled="true"
|
|
12
12
|
:label-width="labelWidth"
|
|
13
|
-
:extend-state="
|
|
13
|
+
:extend-state="mergedExtendState"
|
|
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 {
|
|
28
|
+
import { useCompareForm } from '@editor/hooks/use-compare-form';
|
|
29
|
+
import type { CompareFormBaseProps } from '@editor/type';
|
|
28
30
|
|
|
29
31
|
defineOptions({
|
|
30
32
|
name: 'MEditorCompareForm',
|
|
31
33
|
});
|
|
32
34
|
|
|
33
|
-
/**
|
|
34
|
-
* 对比类型:
|
|
35
|
-
* - node: 节点组件,按 `type` 从 propsService 获取属性表单配置
|
|
36
|
-
* - data-source: 数据源,按 `type`(base/http/...) 从 dataSourceService 获取数据源表单配置
|
|
37
|
-
* - code-block: 数据源代码块,使用内置的代码块表单配置
|
|
38
|
-
*/
|
|
39
|
-
export type CompareCategory = 'node' | 'data-source' | 'code-block';
|
|
40
|
-
|
|
41
35
|
const props = withDefaults(
|
|
42
|
-
defineProps<
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
* - `category` 为 `data-source` 时,`type` 为数据源类型,例如 'base'、'http'
|
|
51
|
-
* - `category` 为 `code-block` 时,`type` 可不传
|
|
52
|
-
*/
|
|
53
|
-
type?: string;
|
|
54
|
-
/** 表单配置类别,决定从哪里取 FormConfig */
|
|
55
|
-
category?: CompareCategory;
|
|
56
|
-
/** 数据源代码块场景下的数据源类型(base/http),用于代码块表单中"执行时机"展示 */
|
|
57
|
-
dataSourceType?: string;
|
|
58
|
-
labelWidth?: string;
|
|
59
|
-
/**
|
|
60
|
-
* 外层容器高度。设置后表单内容超出时会在 CompareForm 内部出现滚动条,
|
|
61
|
-
* 避免 dialog / 面板使用方需要自行处理滚动。可传任意 CSS 长度,例如 `60vh` / `400px` / `100%`。
|
|
62
|
-
*/
|
|
63
|
-
height?: string;
|
|
64
|
-
/**
|
|
65
|
-
* 用户自定义注入到 MForm.formState 的扩展字段,与 Editor 顶层的 `extendFormState`、
|
|
66
|
-
* PropsPanel 的 `extend-state` 语义一致。表单 item 的 `display` / `disabled` 等
|
|
67
|
-
* filterFunction 经常依赖这里注入的字段(如 stage、自定义业务上下文等),
|
|
68
|
-
* 因此在差异对比场景下也需要透传,避免出现 `formState.xxx is undefined` 的运行时错误。
|
|
69
|
-
*/
|
|
70
|
-
extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
|
|
71
|
-
}>(),
|
|
36
|
+
defineProps<
|
|
37
|
+
CompareFormBaseProps & {
|
|
38
|
+
/** 用于对比的旧值(修改前的值) */
|
|
39
|
+
lastValue?: CompareFormBaseProps['value'];
|
|
40
|
+
/** 需要走 self diff 的字段类型(例如 mod-cond)。 */
|
|
41
|
+
selfDiffFieldTypes?: string[];
|
|
42
|
+
}
|
|
43
|
+
>(),
|
|
72
44
|
{
|
|
73
45
|
category: 'node',
|
|
74
46
|
labelWidth: '120px',
|
|
75
47
|
},
|
|
76
48
|
);
|
|
77
49
|
|
|
78
|
-
const {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const config = ref<FormConfig>([]);
|
|
82
|
-
|
|
83
|
-
/** vs-code 编辑器的 monaco 配置项,沿用 Editor 顶层 provide('codeOptions', ...) 的注入。 */
|
|
84
|
-
const codeOptions = inject<Record<string, any>>('codeOptions', {});
|
|
85
|
-
|
|
86
|
-
/** 将代码块的 content 字段统一成字符串,便于在表单/对比中展示 */
|
|
87
|
-
const normalizeCodeBlockValue = (
|
|
88
|
-
v: Partial<CodeBlockContent> | Record<string, any> | undefined,
|
|
89
|
-
): Record<string, any> => {
|
|
90
|
-
if (!v) return {};
|
|
91
|
-
const next: Record<string, any> = { ...v };
|
|
92
|
-
if (next.content && typeof next.content !== 'string') {
|
|
93
|
-
try {
|
|
94
|
-
next.content = next.content.toString();
|
|
95
|
-
} catch {
|
|
96
|
-
next.content = '';
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
return next;
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
const currentValues = computed<FormValue>(() => {
|
|
103
|
-
if (props.category === 'code-block') {
|
|
104
|
-
return normalizeCodeBlockValue(props.value as Partial<CodeBlockContent>);
|
|
105
|
-
}
|
|
106
|
-
return (props.value || {}) as FormValue;
|
|
107
|
-
});
|
|
50
|
+
const { config, currentValues, wrapperStyle, mergedExtendState, loadConfig, formRef, normalizeCodeBlockValue } =
|
|
51
|
+
useCompareForm(props);
|
|
108
52
|
|
|
109
53
|
const lastValuesProcessed = computed<FormValue>(() => {
|
|
110
54
|
if (props.category === 'code-block') {
|
|
@@ -113,18 +57,6 @@ const lastValuesProcessed = computed<FormValue>(() => {
|
|
|
113
57
|
return (props.lastValue || {}) as FormValue;
|
|
114
58
|
});
|
|
115
59
|
|
|
116
|
-
/**
|
|
117
|
-
* 外层包裹层的样式:当传入 `height` 时启用固定高度 + 内部滚动,
|
|
118
|
-
* 这样滚动条会出现在 CompareForm 内部,避免父容器(如 Dialog)自身也产生滚动。
|
|
119
|
-
*/
|
|
120
|
-
const wrapperStyle = computed(() => {
|
|
121
|
-
if (!props.height) return undefined;
|
|
122
|
-
return {
|
|
123
|
-
height: props.height,
|
|
124
|
-
overflow: 'auto',
|
|
125
|
-
} as Record<string, string>;
|
|
126
|
-
});
|
|
127
|
-
|
|
128
60
|
/**
|
|
129
61
|
* `code-select` 字段在历史数据中存在两种"语义为空"的形态:
|
|
130
62
|
* - 字符串 `''`(旧数据 / 用户从未配置过钩子);
|
|
@@ -153,66 +85,6 @@ const showDiff = ({ curValue, lastValue, config }: { curValue: any; lastValue: a
|
|
|
153
85
|
return !isEqual(curValue, lastValue);
|
|
154
86
|
};
|
|
155
87
|
|
|
156
|
-
const loadConfig = async () => {
|
|
157
|
-
switch (props.category) {
|
|
158
|
-
case 'node': {
|
|
159
|
-
if (!props.type) {
|
|
160
|
-
config.value = [];
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
config.value = await propsService.getPropsConfig(props.type);
|
|
164
|
-
break;
|
|
165
|
-
}
|
|
166
|
-
case 'data-source': {
|
|
167
|
-
config.value = dataSourceService.getFormConfig(props.type || 'base');
|
|
168
|
-
break;
|
|
169
|
-
}
|
|
170
|
-
case 'code-block': {
|
|
171
|
-
config.value = getCodeBlockFormConfig({
|
|
172
|
-
paramColConfig: codeBlockService.getParamsColConfig(),
|
|
173
|
-
// 通过传入 dataSourceType 间接表达"是数据源代码块"——在对比场景下 props.dataSourceType
|
|
174
|
-
// 由调用方按 step 上下文显式传入,未传则视为普通代码块,「执行时机」字段隐藏。
|
|
175
|
-
isDataSource: () => Boolean(props.dataSourceType),
|
|
176
|
-
dataSourceType: () => props.dataSourceType,
|
|
177
|
-
codeOptions,
|
|
178
|
-
// 对比模式只读,不需要校验/语法检查
|
|
179
|
-
editable: false,
|
|
180
|
-
});
|
|
181
|
-
break;
|
|
182
|
-
}
|
|
183
|
-
default:
|
|
184
|
-
config.value = [];
|
|
185
|
-
}
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
watch(
|
|
189
|
-
[() => props.category, () => props.type, () => props.dataSourceType],
|
|
190
|
-
() => {
|
|
191
|
-
loadConfig();
|
|
192
|
-
},
|
|
193
|
-
{ immediate: true },
|
|
194
|
-
);
|
|
195
|
-
|
|
196
|
-
const formRef = useTemplateRef<InstanceType<typeof MForm>>('form');
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* 把 services / stage 注入 MForm 的 formState,避免 propsService 注入的表单配置中
|
|
200
|
-
* 形如 `display: ({ services }) => services.uiService.get(...)` 的 filterFunction
|
|
201
|
-
* 在执行时拿不到 `formState.services` 而报错。
|
|
202
|
-
*
|
|
203
|
-
* 与 props-panel/FormPanel.vue 中的注入方式保持一致:
|
|
204
|
-
* - services:整个 useServices() 返回的服务集合;
|
|
205
|
-
* - stage:当前 editorService.get('stage') 的最新值。
|
|
206
|
-
*/
|
|
207
|
-
const stage = computed(() => editorService.get('stage'));
|
|
208
|
-
|
|
209
|
-
watchEffect(() => {
|
|
210
|
-
if (formRef.value) {
|
|
211
|
-
formRef.value.formState.stage = stage.value;
|
|
212
|
-
formRef.value.formState.services = services;
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
|
|
216
88
|
defineExpose<{
|
|
217
89
|
form: ShallowRef<InstanceType<typeof MForm> | null>;
|
|
218
90
|
config: Ref<FormConfig>;
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
<transition name="fade">
|
|
3
3
|
<div
|
|
4
4
|
v-show="visible"
|
|
5
|
-
class="magic-editor-content-menu"
|
|
6
5
|
ref="menu"
|
|
6
|
+
:class="['magic-editor-content-menu', themeClass]"
|
|
7
7
|
:style="menuStyle"
|
|
8
8
|
@mouseenter="mouseenterHandler()"
|
|
9
9
|
@contextmenu.prevent
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
<script lang="ts" setup>
|
|
40
40
|
import { computed, nextTick, onBeforeUnmount, onMounted, type Ref, ref, useTemplateRef } from 'vue';
|
|
41
41
|
|
|
42
|
-
import { useZIndex } from '@tmagic/design';
|
|
42
|
+
import { useThemeClass, useZIndex } from '@tmagic/design';
|
|
43
43
|
|
|
44
44
|
import { MenuButton, MenuComponent } from '@editor/type';
|
|
45
45
|
|
|
@@ -73,6 +73,14 @@ const menuEl = useTemplateRef<HTMLDivElement>('menu');
|
|
|
73
73
|
const buttonRefs = useTemplateRef<InstanceType<typeof ToolButton>[]>('buttons');
|
|
74
74
|
const subMenuRef = useTemplateRef<any>('subMenu');
|
|
75
75
|
const visible = ref(false);
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* 主题修饰类(来自最近的 `<MEditor>` / `<MForm>` 祖先 provide)。
|
|
79
|
+
* - 顶层 `ContentMenu` 渲染在编辑器子树中,加上去是冗余但无害;
|
|
80
|
+
* - 子菜单(递归 `<content-menu :is-sub-menu="true">` 被 `<teleport to="body">` 送到 body)
|
|
81
|
+
* 不在编辑器子树中,必须显式挂上主题类,主题级 CSS 变量才能命中。
|
|
82
|
+
*/
|
|
83
|
+
const themeClass = useThemeClass();
|
|
76
84
|
const subMenuData: Ref<(MenuButton | MenuComponent)[]> = ref<(MenuButton | MenuComponent)[]>([]);
|
|
77
85
|
const zIndex = useZIndex();
|
|
78
86
|
const curZIndex = ref<number>(0);
|
|
@@ -120,20 +128,42 @@ const outsideClickHideHandler = (e: MouseEvent) => {
|
|
|
120
128
|
hide();
|
|
121
129
|
};
|
|
122
130
|
|
|
123
|
-
|
|
124
|
-
|
|
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;
|
|
125
140
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
top = document.body.clientHeight - menuHeight;
|
|
141
|
+
if (top + menuHeight > document.body.clientHeight) {
|
|
142
|
+
top = Math.max(0, document.body.clientHeight - menuHeight);
|
|
129
143
|
}
|
|
130
144
|
|
|
145
|
+
if (left + menuWidth > document.body.clientWidth) {
|
|
146
|
+
left = Math.max(0, document.body.clientWidth - menuWidth);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (top !== menuPosition.value.top || left !== menuPosition.value.left) {
|
|
150
|
+
menuPosition.value = { top, left };
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const setPosition = (e: { clientY: number; clientX: number }) => {
|
|
131
155
|
menuPosition.value = {
|
|
132
|
-
top,
|
|
156
|
+
top: e.clientY,
|
|
133
157
|
left: e.clientX,
|
|
134
158
|
};
|
|
159
|
+
fixPosition();
|
|
135
160
|
};
|
|
136
161
|
|
|
162
|
+
// 菜单大小动态变化(如菜单项更新)后重新修正位置
|
|
163
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
164
|
+
fixPosition();
|
|
165
|
+
});
|
|
166
|
+
|
|
137
167
|
const show = (e?: { clientY: number; clientX: number }) => {
|
|
138
168
|
visible.value = true;
|
|
139
169
|
|
|
@@ -178,12 +208,18 @@ const mouseenterHandler = () => {
|
|
|
178
208
|
};
|
|
179
209
|
|
|
180
210
|
onMounted(() => {
|
|
211
|
+
if (menuEl.value) {
|
|
212
|
+
resizeObserver.observe(menuEl.value);
|
|
213
|
+
}
|
|
214
|
+
|
|
181
215
|
if (props.isSubMenu) return;
|
|
182
216
|
|
|
183
217
|
globalThis.addEventListener('mousedown', outsideClickHideHandler, true);
|
|
184
218
|
});
|
|
185
219
|
|
|
186
220
|
onBeforeUnmount(() => {
|
|
221
|
+
resizeObserver.disconnect();
|
|
222
|
+
|
|
187
223
|
if (props.isSubMenu) return;
|
|
188
224
|
|
|
189
225
|
globalThis.removeEventListener('mousedown', outsideClickHideHandler, true);
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<Teleport to="body" v-if="visible">
|
|
3
|
-
<div
|
|
3
|
+
<div
|
|
4
|
+
ref="target"
|
|
5
|
+
:class="['m-editor-float-box', themeClass]"
|
|
6
|
+
v-bind="$attrs"
|
|
7
|
+
:style="{ ...style, zIndex: curZIndex }"
|
|
8
|
+
@mousedown="nextZIndex"
|
|
9
|
+
>
|
|
4
10
|
<div ref="title" class="m-editor-float-box-title">
|
|
5
11
|
<slot name="title">
|
|
6
12
|
<span>{{ title }}</span>
|
|
@@ -9,7 +15,7 @@
|
|
|
9
15
|
<TMagicButton link size="small" @click="closeHandler"><MIcon :icon="Close"></MIcon></TMagicButton>
|
|
10
16
|
</div>
|
|
11
17
|
</div>
|
|
12
|
-
<div class="m-editor-float-box-body" :style="{ height: `${bodyHeight}px
|
|
18
|
+
<div class="m-editor-float-box-body" :style="{ height: `${bodyHeight}px`, ...bodyStyle }">
|
|
13
19
|
<slot name="body"></slot>
|
|
14
20
|
</div>
|
|
15
21
|
</div>
|
|
@@ -17,14 +23,13 @@
|
|
|
17
23
|
</template>
|
|
18
24
|
|
|
19
25
|
<script setup lang="ts">
|
|
20
|
-
import { computed, nextTick, onBeforeUnmount, provide, ref, useTemplateRef, watch } from 'vue';
|
|
26
|
+
import { computed, type CSSProperties, nextTick, onBeforeUnmount, provide, ref, useTemplateRef, watch } from 'vue';
|
|
21
27
|
import { Close } from '@element-plus/icons-vue';
|
|
22
28
|
import VanillaMoveable from 'moveable';
|
|
23
29
|
|
|
24
|
-
import { TMagicButton, useZIndex } from '@tmagic/design';
|
|
30
|
+
import { TMagicButton, useThemeClass, useZIndex } from '@tmagic/design';
|
|
25
31
|
|
|
26
32
|
import MIcon from '@editor/components/Icon.vue';
|
|
27
|
-
import { useServices } from '@editor/hooks/use-services';
|
|
28
33
|
|
|
29
34
|
interface Position {
|
|
30
35
|
left: number;
|
|
@@ -39,17 +44,30 @@ const props = withDefaults(
|
|
|
39
44
|
defineProps<{
|
|
40
45
|
position?: Position;
|
|
41
46
|
title?: string;
|
|
47
|
+
bodyStyle?: CSSProperties;
|
|
48
|
+
/** 浮窗初始样式,会与内部计算样式合并,外部传入优先 */
|
|
49
|
+
initialStyle?: CSSProperties;
|
|
50
|
+
/** 用于约束浮窗 left 的容器宽度,传入时按宽度收敛 left,避免超出右边界;默认取视窗宽度 */
|
|
51
|
+
frameworkWidth?: number;
|
|
42
52
|
beforeClose?: (_done: (_cancel?: boolean) => void) => void;
|
|
43
53
|
}>(),
|
|
44
54
|
{
|
|
45
55
|
title: '',
|
|
46
56
|
position: () => ({ left: 0, top: 0 }),
|
|
57
|
+
initialStyle: () => ({}),
|
|
58
|
+
frameworkWidth: 0,
|
|
47
59
|
},
|
|
48
60
|
);
|
|
49
61
|
|
|
50
62
|
const targetEl = useTemplateRef<HTMLDivElement>('target');
|
|
51
63
|
const titleEl = useTemplateRef<HTMLDivElement>('title');
|
|
52
64
|
|
|
65
|
+
/**
|
|
66
|
+
* 主题修饰类(来自最近的 `<MEditor>` / `<MForm>` 祖先 provide)。
|
|
67
|
+
* 挂在 `Teleport` 出去的浮动面板根节点上,让主题级 CSS 变量在 portal 节点上也能命中。
|
|
68
|
+
*/
|
|
69
|
+
const themeClass = useThemeClass();
|
|
70
|
+
|
|
53
71
|
const zIndex = useZIndex();
|
|
54
72
|
const curZIndex = ref<number>(0);
|
|
55
73
|
|
|
@@ -66,12 +84,11 @@ const bodyHeight = computed(() => {
|
|
|
66
84
|
return 'auto';
|
|
67
85
|
});
|
|
68
86
|
|
|
69
|
-
const { uiService } = useServices();
|
|
70
|
-
const frameworkWidth = computed(() => uiService.get('frameworkRect').width || 0);
|
|
71
87
|
const style = computed(() => {
|
|
72
88
|
let { left } = props.position;
|
|
73
|
-
|
|
74
|
-
|
|
89
|
+
const frameworkWidth = props.frameworkWidth || globalThis.window?.innerWidth || 0;
|
|
90
|
+
if (width.value && frameworkWidth) {
|
|
91
|
+
left = left + width.value > frameworkWidth ? frameworkWidth - width.value : left;
|
|
75
92
|
}
|
|
76
93
|
|
|
77
94
|
return {
|
|
@@ -79,11 +96,60 @@ const style = computed(() => {
|
|
|
79
96
|
top: `${props.position.top}px`,
|
|
80
97
|
width: width.value ? `${width.value}px` : 'auto',
|
|
81
98
|
height: height.value ? `${height.value}px` : 'auto',
|
|
99
|
+
...props.initialStyle,
|
|
82
100
|
};
|
|
83
101
|
});
|
|
84
102
|
|
|
85
103
|
let moveable: VanillaMoveable | null = null;
|
|
86
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
|
+
|
|
87
153
|
const initMoveable = () => {
|
|
88
154
|
moveable = new VanillaMoveable(globalThis.document.body, {
|
|
89
155
|
className: 'm-editor-floating-box-moveable',
|
|
@@ -101,6 +167,14 @@ const initMoveable = () => {
|
|
|
101
167
|
bounds: { left: 0, top: 0, right: 0, bottom: 0, position: 'css' },
|
|
102
168
|
});
|
|
103
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
|
+
|
|
104
178
|
moveable.on('drag', (e) => {
|
|
105
179
|
e.target.style.transform = e.transform;
|
|
106
180
|
});
|
|
@@ -115,6 +189,7 @@ const initMoveable = () => {
|
|
|
115
189
|
};
|
|
116
190
|
|
|
117
191
|
const destroyMoveable = () => {
|
|
192
|
+
hideDragMask();
|
|
118
193
|
moveable?.destroy();
|
|
119
194
|
moveable = null;
|
|
120
195
|
};
|