layplux 2.0.0 → 2.0.1
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/cjs/components/center-view/index.cjs +18 -28
- package/dist/cjs/components/corner-glow/index.cjs +11 -28
- package/dist/cjs/components/dropdown/index.cjs +136 -130
- package/dist/cjs/components/icon/index.cjs +29 -51
- package/dist/cjs/components/index.cjs +24 -25
- package/dist/cjs/components/panel-view/index.cjs +111 -114
- package/dist/cjs/components/popup/index.cjs +166 -151
- package/dist/cjs/components/title/index.cjs +34 -47
- package/dist/cjs/components/tooltip/index.cjs +70 -61
- package/dist/cjs/components/widget/index.cjs +52 -72
- package/dist/cjs/index.cjs +13 -40
- package/dist/cjs/layout/glass-overlay.cjs +15 -28
- package/dist/cjs/layout/layered-manager.cjs +20 -29
- package/dist/cjs/layout/layplux.cjs +19 -32
- package/dist/cjs/layout/root-pane.cjs +20 -38
- package/dist/cjs/layout/skeleton/bottom-area.cjs +26 -43
- package/dist/cjs/layout/skeleton/bottom-left-area.cjs +12 -29
- package/dist/cjs/layout/skeleton/bottom-right-area.cjs +11 -28
- package/dist/cjs/layout/skeleton/center-area.cjs +278 -371
- package/dist/cjs/layout/skeleton/index.cjs +7 -24
- package/dist/cjs/layout/skeleton/left-bottom-area.cjs +12 -29
- package/dist/cjs/layout/skeleton/left-top-area.cjs +12 -29
- package/dist/cjs/layout/skeleton/right-bottom-area.cjs +11 -28
- package/dist/cjs/layout/skeleton/right-top-area.cjs +11 -28
- package/dist/cjs/layout/skeleton/skeleton.cjs +55 -60
- package/dist/cjs/layout/skeleton/top-area.cjs +26 -43
- package/dist/cjs/locales/en-US.cjs +11 -30
- package/dist/cjs/locales/index.cjs +12 -30
- package/dist/cjs/locales/zh-CN.cjs +11 -30
- package/dist/cjs/managers/area.cjs +12 -25
- package/dist/cjs/managers/index.cjs +12 -20
- package/dist/cjs/managers/pane.cjs +12 -26
- package/dist/cjs/managers/skeleton.cjs +112 -124
- package/dist/cjs/managers/theme.cjs +8 -29
- package/dist/cjs/managers/widget-container.cjs +31 -31
- package/dist/cjs/managers/widget.cjs +63 -50
- package/dist/cjs/types/config.cjs +2 -16
- package/dist/cjs/types/index.cjs +2 -18
- package/dist/cjs/types/locale.cjs +2 -16
- package/dist/cjs/utils/event-bus.cjs +53 -49
- package/dist/cjs/utils/focus-tracker.cjs +66 -42
- package/dist/cjs/utils/index.cjs +23 -31
- package/dist/cjs/utils/unique-id.cjs +5 -24
- package/dist/cjs/utils/vue.cjs +20 -30
- package/dist/esm/components/center-view/index.mjs +15 -7
- package/dist/esm/components/corner-glow/index.mjs +8 -7
- package/dist/esm/components/dropdown/index.mjs +117 -101
- package/dist/esm/components/icon/index.mjs +24 -30
- package/dist/esm/components/index.mjs +7 -8
- package/dist/esm/components/panel-view/index.mjs +107 -98
- package/dist/esm/components/popup/index.mjs +155 -130
- package/dist/esm/components/title/index.mjs +29 -24
- package/dist/esm/components/tooltip/index.mjs +67 -40
- package/dist/esm/components/widget/index.mjs +45 -48
- package/dist/esm/index.mjs +4 -10
- package/dist/esm/layout/glass-overlay.mjs +12 -7
- package/dist/esm/layout/layered-manager.mjs +17 -8
- package/dist/esm/layout/layplux.mjs +14 -11
- package/dist/esm/layout/root-pane.mjs +16 -16
- package/dist/esm/layout/skeleton/bottom-area.mjs +23 -22
- package/dist/esm/layout/skeleton/bottom-left-area.mjs +9 -8
- package/dist/esm/layout/skeleton/bottom-right-area.mjs +8 -7
- package/dist/esm/layout/skeleton/center-area.mjs +251 -333
- package/dist/esm/layout/skeleton/index.mjs +1 -4
- package/dist/esm/layout/skeleton/left-bottom-area.mjs +9 -8
- package/dist/esm/layout/skeleton/left-top-area.mjs +9 -8
- package/dist/esm/layout/skeleton/right-bottom-area.mjs +8 -7
- package/dist/esm/layout/skeleton/right-top-area.mjs +8 -7
- package/dist/esm/layout/skeleton/skeleton.mjs +52 -39
- package/dist/esm/layout/skeleton/top-area.mjs +23 -22
- package/dist/esm/locales/en-US.mjs +9 -10
- package/dist/esm/locales/index.mjs +7 -9
- package/dist/esm/locales/zh-CN.mjs +9 -10
- package/dist/esm/managers/area.mjs +10 -5
- package/dist/esm/managers/index.mjs +3 -3
- package/dist/esm/managers/pane.mjs +9 -5
- package/dist/esm/managers/skeleton.mjs +97 -95
- package/dist/esm/managers/theme.mjs +6 -9
- package/dist/esm/managers/widget-container.mjs +28 -10
- package/dist/esm/managers/widget.mjs +55 -25
- package/dist/esm/types/config.mjs +1 -0
- package/dist/esm/types/index.mjs +1 -1
- package/dist/esm/types/locale.mjs +1 -0
- package/dist/esm/utils/event-bus.mjs +46 -17
- package/dist/esm/utils/focus-tracker.mjs +63 -23
- package/dist/esm/utils/index.mjs +7 -10
- package/dist/esm/utils/unique-id.mjs +3 -4
- package/dist/esm/utils/vue.mjs +13 -5
- package/dist/types/managers/skeleton.d.ts.map +1 -1
- package/dist/umd/index.js +0 -2
- package/package.json +11 -8
|
@@ -1,74 +1,82 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var widget_exports = {};
|
|
20
|
-
__export(widget_exports, {
|
|
21
|
-
isWidget: () => isWidget,
|
|
22
|
-
useWidget: () => useWidget
|
|
23
|
-
});
|
|
24
|
-
module.exports = __toCommonJS(widget_exports);
|
|
25
|
-
var import_vue = require("vue");
|
|
26
|
-
var import_utils = require("../utils");
|
|
27
|
-
var import_components = require("../components");
|
|
28
|
-
var import_pane = require("./pane");
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var vue = require('vue');
|
|
4
|
+
var pane = require('./pane.cjs');
|
|
5
|
+
var uniqueId = require('../utils/unique-id.cjs');
|
|
6
|
+
var vue$1 = require('../utils/vue.cjs');
|
|
7
|
+
var index = require('../components/widget/index.cjs');
|
|
8
|
+
|
|
29
9
|
function useWidget(config, container, skeleton) {
|
|
30
|
-
const {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const
|
|
10
|
+
const {
|
|
11
|
+
name,
|
|
12
|
+
props,
|
|
13
|
+
type
|
|
14
|
+
} = config;
|
|
15
|
+
const active = vue.computed(() => container?.activeId.value === name);
|
|
16
|
+
const focused = vue.computed(() => skeleton?.focusedId.value === name);
|
|
17
|
+
const id = uniqueId.uniqueId(type);
|
|
18
|
+
const align = props?.align ?? 'left';
|
|
19
|
+
const pane$1 = pane.usePane();
|
|
20
|
+
|
|
21
|
+
// ─── Focusable 注册 ──────────────────────────────────────────────────────
|
|
22
|
+
// range 初始为 () => false,PanelView 挂载后通过 focusable.setRange(el) 注入真实 DOM
|
|
36
23
|
const focusable = skeleton.focusTracker.create({
|
|
37
|
-
range:
|
|
24
|
+
range: e => {
|
|
38
25
|
const target = e.target;
|
|
39
26
|
if (!target) {
|
|
40
27
|
return false;
|
|
41
28
|
}
|
|
29
|
+
// 当点击的是panel时,激活
|
|
42
30
|
const el = document.getElementById(id);
|
|
43
31
|
if (el?.contains(target)) {
|
|
44
32
|
return true;
|
|
45
33
|
}
|
|
46
|
-
|
|
34
|
+
// 当class中包含layplux-resize-handle则不失去焦点
|
|
35
|
+
if (target.classList.contains('layplux-resize-handle')) {
|
|
47
36
|
return true;
|
|
48
37
|
}
|
|
49
38
|
return false;
|
|
50
39
|
},
|
|
51
40
|
onActive: () => {
|
|
52
41
|
widget.container?.activate(name);
|
|
53
|
-
skeleton.event?.emitGlobal(`widget:${name}:focus`, {
|
|
42
|
+
skeleton.event?.emitGlobal(`widget:${name}:focus`, {
|
|
43
|
+
widget
|
|
44
|
+
});
|
|
54
45
|
},
|
|
55
46
|
onBlur: () => {
|
|
47
|
+
// 焦点离开 → 清除 focusedId
|
|
56
48
|
skeleton.blur();
|
|
57
|
-
skeleton.event?.emitGlobal(`widget:${name}:blur`, {
|
|
58
|
-
|
|
49
|
+
skeleton.event?.emitGlobal(`widget:${name}:blur`, {
|
|
50
|
+
widget
|
|
51
|
+
});
|
|
52
|
+
// DockUnpinned:失焦自动收起
|
|
53
|
+
if (pane$1.viewMode.value === 'DockUnpinned' || pane$1.viewMode.value === 'Undock') {
|
|
59
54
|
container?.deactivate();
|
|
60
55
|
}
|
|
61
56
|
}
|
|
62
57
|
});
|
|
63
58
|
function renderBody() {
|
|
64
|
-
const {
|
|
65
|
-
|
|
59
|
+
const {
|
|
60
|
+
content,
|
|
61
|
+
contentProps
|
|
62
|
+
} = config;
|
|
63
|
+
return vue$1.createContent(content, {
|
|
64
|
+
...contentProps,
|
|
65
|
+
config,
|
|
66
|
+
event: widget.event
|
|
67
|
+
});
|
|
66
68
|
}
|
|
67
69
|
function renderContent() {
|
|
68
|
-
return
|
|
70
|
+
return vue.h(index.WidgetView, {
|
|
71
|
+
key: id,
|
|
72
|
+
widget
|
|
73
|
+
});
|
|
69
74
|
}
|
|
70
75
|
function renderTitle() {
|
|
71
|
-
return
|
|
76
|
+
return vue.h(index.WidgetTitleView, {
|
|
77
|
+
key: id,
|
|
78
|
+
widget
|
|
79
|
+
});
|
|
72
80
|
}
|
|
73
81
|
const widget = {
|
|
74
82
|
id,
|
|
@@ -80,7 +88,7 @@ function useWidget(config, container, skeleton) {
|
|
|
80
88
|
active,
|
|
81
89
|
focused,
|
|
82
90
|
container,
|
|
83
|
-
pane,
|
|
91
|
+
pane: pane$1,
|
|
84
92
|
focusable,
|
|
85
93
|
event: skeleton.event,
|
|
86
94
|
renderBody,
|
|
@@ -88,16 +96,21 @@ function useWidget(config, container, skeleton) {
|
|
|
88
96
|
renderTitle
|
|
89
97
|
};
|
|
90
98
|
props?.onInit?.(widget);
|
|
99
|
+
|
|
100
|
+
// Emit view-mode-changed events
|
|
91
101
|
if (skeleton?.event) {
|
|
92
|
-
(
|
|
93
|
-
(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
);
|
|
102
|
+
vue.watch(() => pane$1.viewMode.value, mode => {
|
|
103
|
+
skeleton.event.emitGlobal(`widget:${name}:view-mode-changed`, {
|
|
104
|
+
widget,
|
|
105
|
+
mode
|
|
106
|
+
});
|
|
107
|
+
});
|
|
98
108
|
}
|
|
99
109
|
return widget;
|
|
100
110
|
}
|
|
101
111
|
function isWidget(obj) {
|
|
102
112
|
return obj && obj.isWidget;
|
|
103
113
|
}
|
|
114
|
+
|
|
115
|
+
exports.isWidget = isWidget;
|
|
116
|
+
exports.useWidget = useWidget;
|
|
@@ -1,16 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __copyProps = (to, from, except, desc) => {
|
|
7
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
-
for (let key of __getOwnPropNames(from))
|
|
9
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
-
}
|
|
12
|
-
return to;
|
|
13
|
-
};
|
|
14
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
-
var config_exports = {};
|
|
16
|
-
module.exports = __toCommonJS(config_exports);
|
|
1
|
+
'use strict';
|
|
2
|
+
|
package/dist/cjs/types/index.cjs
CHANGED
|
@@ -1,18 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __copyProps = (to, from, except, desc) => {
|
|
7
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
-
for (let key of __getOwnPropNames(from))
|
|
9
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
-
}
|
|
12
|
-
return to;
|
|
13
|
-
};
|
|
14
|
-
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
15
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
16
|
-
var types_exports = {};
|
|
17
|
-
module.exports = __toCommonJS(types_exports);
|
|
18
|
-
__reExport(types_exports, require("./config"), module.exports);
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
@@ -1,16 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __copyProps = (to, from, except, desc) => {
|
|
7
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
-
for (let key of __getOwnPropNames(from))
|
|
9
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
-
}
|
|
12
|
-
return to;
|
|
13
|
-
};
|
|
14
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
-
var locale_exports = {};
|
|
16
|
-
module.exports = __toCommonJS(locale_exports);
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
@@ -1,63 +1,59 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
var event_bus_exports = {};
|
|
30
|
-
__export(event_bus_exports, {
|
|
31
|
-
createPluginEventBus: () => createPluginEventBus,
|
|
32
|
-
emitSystemEvent: () => emitSystemEvent,
|
|
33
|
-
getGlobalEmitter: () => getGlobalEmitter,
|
|
34
|
-
onSystemEvent: () => onSystemEvent
|
|
35
|
-
});
|
|
36
|
-
module.exports = __toCommonJS(event_bus_exports);
|
|
37
|
-
var import_eventemitter2 = __toESM(require("eventemitter2"), 1);
|
|
38
|
-
const globalEmitter = new import_eventemitter2.default({
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var EventEmitter2 = require('eventemitter2');
|
|
4
|
+
|
|
5
|
+
// =================================================================
|
|
6
|
+
// event-bus.ts — 基于 EventEmitter2 的插件事件总线
|
|
7
|
+
//
|
|
8
|
+
// 利用 EventEmitter2 的三个核心特性:
|
|
9
|
+
// 1. wildcard: true → 支持 'terminal:*' 订阅整个命名空间
|
|
10
|
+
// 2. delimiter: ':' → 'namespace:event' 格式的原生支持
|
|
11
|
+
// 3. listener.off() → 订阅返回 Listener 对象,无需手动传 handler 引用
|
|
12
|
+
// =================================================================
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
// ── 全局总线单例(所有插件共享,跨插件通信用)──────────────────────
|
|
16
|
+
//
|
|
17
|
+
// wildcard + delimiter 让命名空间隔离变成原生能力:
|
|
18
|
+
// - 插件 A 订阅 'terminal:*' 可以收到所有 terminal 前缀的事件
|
|
19
|
+
// - 全局订阅 '**' 可以监听所有事件(调试用)
|
|
20
|
+
// - maxListeners 设大一点,避免大量插件时出现警告
|
|
21
|
+
|
|
22
|
+
const globalEmitter = new EventEmitter2({
|
|
39
23
|
wildcard: true,
|
|
40
24
|
// 开启通配符
|
|
41
|
-
delimiter:
|
|
25
|
+
delimiter: ':',
|
|
42
26
|
// 命名空间分隔符,与原版 createModuleEventBus 保持一致
|
|
43
27
|
newListener: false,
|
|
44
28
|
// 不触发 newListener 事件,减少不必要开销
|
|
45
29
|
maxListeners: 200,
|
|
46
30
|
// 对标原版 createModuleEventBus(pluginName, 200) 的容量参数
|
|
47
|
-
verboseMemoryLeak: true
|
|
48
|
-
// 超出 maxListeners 时打印详细的内存泄漏警告
|
|
31
|
+
verboseMemoryLeak: true // 超出 maxListeners 时打印详细的内存泄漏警告
|
|
49
32
|
});
|
|
33
|
+
// ── 插件私有事件总线工厂函数 ──────────────────────────────────────
|
|
34
|
+
//
|
|
35
|
+
// 每个插件获得一个独立的 emitter 实例(私有事件不污染全局),
|
|
36
|
+
// 同时持有 globalEmitter 引用用于跨插件通信。
|
|
37
|
+
//
|
|
38
|
+
// 命名规则:
|
|
39
|
+
// ctx.event.emit('data-loaded') → 实际发出 'terminal:data-loaded'(自动加前缀)
|
|
40
|
+
// ctx.event.on('data-loaded', fn) → 订阅 'terminal:data-loaded'
|
|
41
|
+
// ctx.event.onGlobal('layout:*', fn) → 订阅全局总线上所有 layout 事件(wildcard)
|
|
42
|
+
// ctx.event.emitGlobal('layout:ready')→ 向全局总线发出事件,所有插件都能收到
|
|
43
|
+
|
|
50
44
|
function createPluginEventBus(namespace) {
|
|
51
|
-
|
|
45
|
+
// 每个插件自己的私有 emitter(同样开启 wildcard)
|
|
46
|
+
const privateEmitter = new EventEmitter2({
|
|
52
47
|
wildcard: true,
|
|
53
|
-
delimiter:
|
|
48
|
+
delimiter: ':',
|
|
54
49
|
newListener: false,
|
|
55
50
|
maxListeners: 200,
|
|
56
51
|
verboseMemoryLeak: true
|
|
57
52
|
});
|
|
58
|
-
const prefixed =
|
|
53
|
+
const prefixed = event => `${namespace}:${event}`;
|
|
59
54
|
return {
|
|
60
55
|
// ── 私有事件(自动加 namespace 前缀)──────────────────────────
|
|
56
|
+
|
|
61
57
|
emit(event, payload) {
|
|
62
58
|
privateEmitter.emit(prefixed(event), payload);
|
|
63
59
|
},
|
|
@@ -67,11 +63,9 @@ function createPluginEventBus(namespace) {
|
|
|
67
63
|
* 无需调用方保存 handler 引用。
|
|
68
64
|
*/
|
|
69
65
|
on(event, handler) {
|
|
70
|
-
const listener = privateEmitter.on(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
{ objectify: true }
|
|
74
|
-
// 返回 Listener 对象而非 emitter 本身
|
|
66
|
+
const listener = privateEmitter.on(prefixed(event), handler, {
|
|
67
|
+
objectify: true
|
|
68
|
+
} // 返回 Listener 对象而非 emitter 本身
|
|
75
69
|
);
|
|
76
70
|
return () => listener.off();
|
|
77
71
|
},
|
|
@@ -88,6 +82,7 @@ function createPluginEventBus(namespace) {
|
|
|
88
82
|
return () => listener.off();
|
|
89
83
|
},
|
|
90
84
|
// ── 全局事件(跨插件通信,走 globalEmitter)────────────────────
|
|
85
|
+
|
|
91
86
|
emitGlobal(event, payload) {
|
|
92
87
|
globalEmitter.emit(event, payload);
|
|
93
88
|
},
|
|
@@ -131,6 +126,7 @@ function createPluginEventBus(namespace) {
|
|
|
131
126
|
});
|
|
132
127
|
},
|
|
133
128
|
// ── 清理(插件 destroy 时调用)─────────────────────────────────
|
|
129
|
+
|
|
134
130
|
/**
|
|
135
131
|
* 移除该插件私有 emitter 上的所有监听器。
|
|
136
132
|
* 全局监听器需要单独 offGlobal(插件应在 teardown 中手动清理)。
|
|
@@ -140,6 +136,9 @@ function createPluginEventBus(namespace) {
|
|
|
140
136
|
}
|
|
141
137
|
};
|
|
142
138
|
}
|
|
139
|
+
|
|
140
|
+
// ── 系统级全局事件工具函数(PluginManager 使用)────────────────────
|
|
141
|
+
|
|
143
142
|
function emitSystemEvent(event, payload) {
|
|
144
143
|
globalEmitter.emit(event, payload);
|
|
145
144
|
}
|
|
@@ -152,3 +151,8 @@ function onSystemEvent(event, handler) {
|
|
|
152
151
|
function getGlobalEmitter() {
|
|
153
152
|
return globalEmitter;
|
|
154
153
|
}
|
|
154
|
+
|
|
155
|
+
exports.createPluginEventBus = createPluginEventBus;
|
|
156
|
+
exports.emitSystemEvent = emitSystemEvent;
|
|
157
|
+
exports.getGlobalEmitter = getGlobalEmitter;
|
|
158
|
+
exports.onSystemEvent = onSystemEvent;
|
|
@@ -1,81 +1,79 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
var __copyProps = (to, from, except, desc) => {
|
|
12
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
-
for (let key of __getOwnPropNames(from))
|
|
14
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
21
|
-
var focus_tracker_exports = {};
|
|
22
|
-
__export(focus_tracker_exports, {
|
|
23
|
-
FocusTracker: () => FocusTracker,
|
|
24
|
-
Focusable: () => Focusable
|
|
25
|
-
});
|
|
26
|
-
module.exports = __toCommonJS(focus_tracker_exports);
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 焦点追踪器 — 维护一个焦点栈,管理 Popup/Dropdown 等弹出层的点击外部关闭、ESC 关闭等行为。
|
|
5
|
+
*
|
|
6
|
+
* 核心概念:
|
|
7
|
+
* - actives 是一个栈(active/unshift),栈顶(first)是当前聚焦的 Focusable
|
|
8
|
+
* - modal Focusable 打开时会阻止非 modal 的上层焦点失焦
|
|
9
|
+
* - mount() 在 document 上监听 click,点击栈顶 Focusable 范围外时触发 blur
|
|
10
|
+
*/
|
|
27
11
|
class FocusTracker {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
12
|
+
/** 焦点栈,栈顶为当前聚焦项 */
|
|
13
|
+
actives = [];
|
|
14
|
+
|
|
15
|
+
/** modal 弹层注册表,用于检查是否有 modal 正在打开 */
|
|
16
|
+
modals = [];
|
|
17
|
+
|
|
34
18
|
/** 当前焦点栈顶 */
|
|
35
19
|
get first() {
|
|
36
20
|
return this.actives[0];
|
|
37
21
|
}
|
|
22
|
+
|
|
38
23
|
/** 注册一个 modal 弹层,用于 execSave 等时判断是否跳过 */
|
|
39
24
|
addModal(checkDown, checkOpen) {
|
|
40
|
-
this.modals.push({
|
|
25
|
+
this.modals.push({
|
|
26
|
+
checkDown,
|
|
27
|
+
checkOpen
|
|
28
|
+
});
|
|
41
29
|
}
|
|
30
|
+
|
|
42
31
|
/** 是否有 modal 弹层正在打开 */
|
|
43
32
|
checkModalOpen() {
|
|
44
|
-
return this.modals.some(
|
|
33
|
+
return this.modals.some(item => item.checkOpen());
|
|
45
34
|
}
|
|
35
|
+
|
|
46
36
|
/** 触发保存操作,有 modal 时跳过 */
|
|
47
37
|
execSave() {
|
|
48
38
|
if (this.checkModalOpen()) return;
|
|
49
39
|
if (this.first) this.first.internalTriggerSave();
|
|
50
40
|
}
|
|
41
|
+
|
|
51
42
|
/** 触发 ESC — 挂起栈顶并调用其 onEsc */
|
|
52
43
|
execEsc() {
|
|
53
|
-
const {
|
|
44
|
+
const {
|
|
45
|
+
first
|
|
46
|
+
} = this;
|
|
54
47
|
if (first) {
|
|
55
48
|
this.internalSuspenseItem(first);
|
|
56
49
|
first.internalTriggerEsc();
|
|
57
50
|
}
|
|
58
51
|
}
|
|
52
|
+
|
|
59
53
|
/**
|
|
60
54
|
* 挂载全局点击监听
|
|
61
55
|
* 点击 document 时,如果点击目标不在 first 的 range 内,则挂起 first 并触发 blur
|
|
62
56
|
* @returns 卸载函数
|
|
63
57
|
*/
|
|
64
58
|
mount(win) {
|
|
65
|
-
const checkDown =
|
|
66
|
-
const {
|
|
59
|
+
const checkDown = e => {
|
|
60
|
+
const {
|
|
61
|
+
first
|
|
62
|
+
} = this;
|
|
67
63
|
if (first && !first.internalCheckInRange(e)) {
|
|
68
64
|
this.internalSuspenseItem(first);
|
|
69
65
|
first.internalTriggerBlur();
|
|
70
66
|
}
|
|
71
67
|
};
|
|
72
|
-
win.document.addEventListener(
|
|
73
|
-
return () => win.document.removeEventListener(
|
|
68
|
+
win.document.addEventListener('click', checkDown, true);
|
|
69
|
+
return () => win.document.removeEventListener('click', checkDown, true);
|
|
74
70
|
}
|
|
71
|
+
|
|
75
72
|
/** 创建一个 Focusable 实例并绑定到当前 tracker */
|
|
76
73
|
create(config) {
|
|
77
74
|
return new Focusable(this, config);
|
|
78
75
|
}
|
|
76
|
+
|
|
79
77
|
/**
|
|
80
78
|
* 激活一个 Focusable — 将其推到栈顶
|
|
81
79
|
* 如果栈顶已有其他 Focusable 且新项不是 modal,则先触发旧栈顶的 blur
|
|
@@ -89,6 +87,7 @@ class FocusTracker {
|
|
|
89
87
|
if (!item.isModal && first) first.internalTriggerBlur();
|
|
90
88
|
item.internalTriggerActive();
|
|
91
89
|
}
|
|
90
|
+
|
|
92
91
|
/**
|
|
93
92
|
* 挂起一个 Focusable — 将其从栈中移除
|
|
94
93
|
* 移除后如果还有剩余项,激活新的栈顶
|
|
@@ -101,40 +100,60 @@ class FocusTracker {
|
|
|
101
100
|
}
|
|
102
101
|
}
|
|
103
102
|
}
|
|
103
|
+
|
|
104
|
+
/** Focusable 的创建配置 */
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* 可聚焦项 — 代表一个弹出层(Popup/Dropdown 等)的焦点状态
|
|
108
|
+
*
|
|
109
|
+
* 使用方式:
|
|
110
|
+
* 1. tracker.create(config) 创建 Focusable
|
|
111
|
+
* 2. 弹出层打开时调用 focusable.active() 推入栈顶
|
|
112
|
+
* 3. 弹出层关闭时调用 focusable.suspense() 或 purge() 移出栈
|
|
113
|
+
* 4. 需要在组件挂载后调用 setRange() 注入真实 DOM
|
|
114
|
+
*/
|
|
104
115
|
class Focusable {
|
|
105
116
|
constructor(tracker, config) {
|
|
106
117
|
this.tracker = tracker;
|
|
107
118
|
this.config = config;
|
|
108
|
-
__publicField(this, "isModal");
|
|
109
119
|
this.isModal = config.modal ?? false;
|
|
110
120
|
}
|
|
121
|
+
|
|
111
122
|
/** 激活当前 Focusable,推入焦点栈顶 */
|
|
112
123
|
active() {
|
|
113
124
|
this.tracker.internalActiveItem(this);
|
|
114
125
|
}
|
|
126
|
+
|
|
115
127
|
/** 挂起当前 Focusable,从焦点栈移除 */
|
|
116
128
|
suspense() {
|
|
117
129
|
this.tracker.internalSuspenseItem(this);
|
|
118
130
|
}
|
|
131
|
+
|
|
119
132
|
/** 销毁当前 Focusable(同 suspense,语义化别名) */
|
|
120
133
|
purge() {
|
|
121
134
|
this.tracker.internalSuspenseItem(this);
|
|
122
135
|
}
|
|
136
|
+
|
|
123
137
|
/** 挂载后把真实 DOM 注入,使 range 的 contains 判断生效 */
|
|
124
138
|
setRange(range) {
|
|
125
139
|
this.config.range = range;
|
|
126
140
|
}
|
|
141
|
+
|
|
127
142
|
/** 检查点击事件是否在 range 范围内 */
|
|
128
143
|
internalCheckInRange(e) {
|
|
129
|
-
const {
|
|
144
|
+
const {
|
|
145
|
+
range
|
|
146
|
+
} = this.config;
|
|
130
147
|
if (!range) return false;
|
|
131
|
-
if (typeof range ===
|
|
148
|
+
if (typeof range === 'function') return range(e);
|
|
132
149
|
return range.contains(e.target);
|
|
133
150
|
}
|
|
151
|
+
|
|
134
152
|
/** 触发失焦回调 */
|
|
135
153
|
internalTriggerBlur() {
|
|
136
154
|
this.config.onBlur?.();
|
|
137
155
|
}
|
|
156
|
+
|
|
138
157
|
/** 触发保存回调,返回 true 表示已处理 */
|
|
139
158
|
internalTriggerSave() {
|
|
140
159
|
if (this.config.onSave) {
|
|
@@ -143,12 +162,17 @@ class Focusable {
|
|
|
143
162
|
}
|
|
144
163
|
return false;
|
|
145
164
|
}
|
|
165
|
+
|
|
146
166
|
/** 触发 ESC 回调 */
|
|
147
167
|
internalTriggerEsc() {
|
|
148
168
|
this.config.onEsc?.();
|
|
149
169
|
}
|
|
170
|
+
|
|
150
171
|
/** 触发激活回调 */
|
|
151
172
|
internalTriggerActive() {
|
|
152
173
|
this.config.onActive?.();
|
|
153
174
|
}
|
|
154
175
|
}
|
|
176
|
+
|
|
177
|
+
exports.FocusTracker = FocusTracker;
|
|
178
|
+
exports.Focusable = Focusable;
|
package/dist/cjs/utils/index.cjs
CHANGED
|
@@ -1,31 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
zhCN: () => import_locales.zhCN
|
|
25
|
-
});
|
|
26
|
-
module.exports = __toCommonJS(utils_exports);
|
|
27
|
-
__reExport(utils_exports, require("./vue"), module.exports);
|
|
28
|
-
__reExport(utils_exports, require("./unique-id"), module.exports);
|
|
29
|
-
__reExport(utils_exports, require("./focus-tracker"), module.exports);
|
|
30
|
-
__reExport(utils_exports, require("./event-bus"), module.exports);
|
|
31
|
-
var import_locales = require("../locales");
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var vue = require('./vue.cjs');
|
|
4
|
+
var uniqueId = require('./unique-id.cjs');
|
|
5
|
+
var focusTracker = require('./focus-tracker.cjs');
|
|
6
|
+
var eventBus = require('./event-bus.cjs');
|
|
7
|
+
var index = require('../locales/index.cjs');
|
|
8
|
+
var enUS = require('../locales/en-US.cjs');
|
|
9
|
+
var zhCN = require('../locales/zh-CN.cjs');
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
exports.createContent = vue.createContent;
|
|
14
|
+
exports.uniqueId = uniqueId.uniqueId;
|
|
15
|
+
exports.FocusTracker = focusTracker.FocusTracker;
|
|
16
|
+
exports.Focusable = focusTracker.Focusable;
|
|
17
|
+
exports.createPluginEventBus = eventBus.createPluginEventBus;
|
|
18
|
+
exports.emitSystemEvent = eventBus.emitSystemEvent;
|
|
19
|
+
exports.getGlobalEmitter = eventBus.getGlobalEmitter;
|
|
20
|
+
exports.onSystemEvent = eventBus.onSystemEvent;
|
|
21
|
+
exports.getBuiltInLocale = index.getBuiltInLocale;
|
|
22
|
+
exports.enUS = enUS.enUS;
|
|
23
|
+
exports.zhCN = zhCN.zhCN;
|