layplux 1.0.1 → 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.
Files changed (91) hide show
  1. package/dist/cjs/components/center-view/index.cjs +18 -28
  2. package/dist/cjs/components/corner-glow/index.cjs +11 -28
  3. package/dist/cjs/components/dropdown/index.cjs +136 -130
  4. package/dist/cjs/components/icon/index.cjs +29 -51
  5. package/dist/cjs/components/index.cjs +24 -25
  6. package/dist/cjs/components/panel-view/index.cjs +111 -114
  7. package/dist/cjs/components/popup/index.cjs +166 -151
  8. package/dist/cjs/components/title/index.cjs +34 -47
  9. package/dist/cjs/components/tooltip/index.cjs +70 -61
  10. package/dist/cjs/components/widget/index.cjs +52 -72
  11. package/dist/cjs/index.cjs +13 -40
  12. package/dist/cjs/layout/glass-overlay.cjs +15 -28
  13. package/dist/cjs/layout/layered-manager.cjs +20 -29
  14. package/dist/cjs/layout/layplux.cjs +19 -32
  15. package/dist/cjs/layout/root-pane.cjs +20 -38
  16. package/dist/cjs/layout/skeleton/bottom-area.cjs +26 -43
  17. package/dist/cjs/layout/skeleton/bottom-left-area.cjs +12 -29
  18. package/dist/cjs/layout/skeleton/bottom-right-area.cjs +11 -28
  19. package/dist/cjs/layout/skeleton/center-area.cjs +278 -371
  20. package/dist/cjs/layout/skeleton/index.cjs +7 -24
  21. package/dist/cjs/layout/skeleton/left-bottom-area.cjs +12 -29
  22. package/dist/cjs/layout/skeleton/left-top-area.cjs +12 -29
  23. package/dist/cjs/layout/skeleton/right-bottom-area.cjs +11 -28
  24. package/dist/cjs/layout/skeleton/right-top-area.cjs +11 -28
  25. package/dist/cjs/layout/skeleton/skeleton.cjs +55 -60
  26. package/dist/cjs/layout/skeleton/top-area.cjs +26 -43
  27. package/dist/cjs/locales/en-US.cjs +11 -30
  28. package/dist/cjs/locales/index.cjs +12 -30
  29. package/dist/cjs/locales/zh-CN.cjs +11 -30
  30. package/dist/cjs/managers/area.cjs +12 -25
  31. package/dist/cjs/managers/index.cjs +12 -20
  32. package/dist/cjs/managers/pane.cjs +12 -26
  33. package/dist/cjs/managers/skeleton.cjs +112 -124
  34. package/dist/cjs/managers/theme.cjs +8 -29
  35. package/dist/cjs/managers/widget-container.cjs +31 -31
  36. package/dist/cjs/managers/widget.cjs +63 -50
  37. package/dist/cjs/types/config.cjs +2 -16
  38. package/dist/cjs/types/index.cjs +2 -18
  39. package/dist/cjs/types/locale.cjs +2 -16
  40. package/dist/cjs/utils/event-bus.cjs +53 -49
  41. package/dist/cjs/utils/focus-tracker.cjs +66 -42
  42. package/dist/cjs/utils/index.cjs +23 -31
  43. package/dist/cjs/utils/unique-id.cjs +5 -24
  44. package/dist/cjs/utils/vue.cjs +20 -30
  45. package/dist/esm/components/center-view/index.mjs +15 -7
  46. package/dist/esm/components/corner-glow/index.mjs +8 -7
  47. package/dist/esm/components/dropdown/index.mjs +117 -101
  48. package/dist/esm/components/icon/index.mjs +24 -30
  49. package/dist/esm/components/index.mjs +7 -8
  50. package/dist/esm/components/panel-view/index.mjs +107 -98
  51. package/dist/esm/components/popup/index.mjs +155 -130
  52. package/dist/esm/components/title/index.mjs +29 -24
  53. package/dist/esm/components/tooltip/index.mjs +67 -40
  54. package/dist/esm/components/widget/index.mjs +45 -48
  55. package/dist/esm/index.mjs +4 -10
  56. package/dist/esm/layout/glass-overlay.mjs +12 -7
  57. package/dist/esm/layout/layered-manager.mjs +17 -8
  58. package/dist/esm/layout/layplux.mjs +14 -11
  59. package/dist/esm/layout/root-pane.mjs +16 -16
  60. package/dist/esm/layout/skeleton/bottom-area.mjs +23 -22
  61. package/dist/esm/layout/skeleton/bottom-left-area.mjs +9 -8
  62. package/dist/esm/layout/skeleton/bottom-right-area.mjs +8 -7
  63. package/dist/esm/layout/skeleton/center-area.mjs +251 -333
  64. package/dist/esm/layout/skeleton/index.mjs +1 -4
  65. package/dist/esm/layout/skeleton/left-bottom-area.mjs +9 -8
  66. package/dist/esm/layout/skeleton/left-top-area.mjs +9 -8
  67. package/dist/esm/layout/skeleton/right-bottom-area.mjs +8 -7
  68. package/dist/esm/layout/skeleton/right-top-area.mjs +8 -7
  69. package/dist/esm/layout/skeleton/skeleton.mjs +52 -39
  70. package/dist/esm/layout/skeleton/top-area.mjs +23 -22
  71. package/dist/esm/locales/en-US.mjs +9 -10
  72. package/dist/esm/locales/index.mjs +7 -9
  73. package/dist/esm/locales/zh-CN.mjs +9 -10
  74. package/dist/esm/managers/area.mjs +10 -5
  75. package/dist/esm/managers/index.mjs +3 -3
  76. package/dist/esm/managers/pane.mjs +9 -5
  77. package/dist/esm/managers/skeleton.mjs +97 -95
  78. package/dist/esm/managers/theme.mjs +6 -9
  79. package/dist/esm/managers/widget-container.mjs +28 -10
  80. package/dist/esm/managers/widget.mjs +55 -25
  81. package/dist/esm/types/config.mjs +1 -0
  82. package/dist/esm/types/index.mjs +1 -1
  83. package/dist/esm/types/locale.mjs +1 -0
  84. package/dist/esm/utils/event-bus.mjs +46 -17
  85. package/dist/esm/utils/focus-tracker.mjs +63 -23
  86. package/dist/esm/utils/index.mjs +7 -10
  87. package/dist/esm/utils/unique-id.mjs +3 -4
  88. package/dist/esm/utils/vue.mjs +13 -5
  89. package/dist/types/managers/skeleton.d.ts.map +1 -1
  90. package/dist/umd/index.js +2 -30
  91. package/package.json +18 -14
@@ -1,467 +1,374 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
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 center_area_exports = {};
20
- __export(center_area_exports, {
21
- CenterArea: () => CenterArea
22
- });
23
- module.exports = __toCommonJS(center_area_exports);
24
- var import_jsx_runtime = require("vue/jsx-runtime");
25
- var import_vue = require("vue");
26
- var import_components = require("../../components");
27
- const CenterArea = (0, import_vue.defineComponent)({
28
- name: "CenterArea",
1
+ 'use strict';
2
+
3
+ var vue = require('vue');
4
+ var index = require('../../components/panel-view/index.cjs');
5
+
6
+ function _isSlot(s) {
7
+ return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !vue.isVNode(s);
8
+ }
9
+ const CenterArea = vue.defineComponent({
10
+ name: 'CenterArea',
29
11
  props: {
30
12
  skeleton: Object,
31
13
  centerArea: Object
32
14
  },
33
15
  setup(props) {
16
+ // ─── FocusTracker 全局挂载 ────────────────────────────────────────────
17
+ // 监听 document click,点击面板外自动触发 onBlur(DockUnpinned 自动收起)
34
18
  let unmountFocusTracker = null;
35
- (0, import_vue.onMounted)(() => {
19
+ vue.onMounted(() => {
36
20
  unmountFocusTracker = props.skeleton?.focusTracker.mount(window) ?? null;
37
21
  });
38
- (0, import_vue.onUnmounted)(() => {
22
+ vue.onUnmounted(() => {
39
23
  unmountFocusTracker?.();
40
24
  });
41
- const leftWidth = (0, import_vue.ref)(340);
42
- const rightWidth = (0, import_vue.ref)(340);
43
- const bottomHeight = (0, import_vue.ref)(300);
44
- const leftSplitRatio = (0, import_vue.ref)(0.5);
45
- const rightSplitRatio = (0, import_vue.ref)(0.5);
46
- const bottomSplitRatio = (0, import_vue.ref)(0.5);
25
+
26
+ // ─── 面板尺寸状态 ─────────────────────────────────────────────────────
27
+ const leftWidth = vue.ref(340);
28
+ const rightWidth = vue.ref(340);
29
+ const bottomHeight = vue.ref(300);
30
+
31
+ // 上下 / 左右内部分割比例 (0~1)
32
+ const leftSplitRatio = vue.ref(0.5);
33
+ const rightSplitRatio = vue.ref(0.5);
34
+ const bottomSplitRatio = vue.ref(0.5);
35
+
36
+ // ─── 通用拖拽 ─────────────────────────────────────────────────────────
47
37
  function startDrag(e, axis, onMove) {
48
38
  e.preventDefault();
49
- const startPos = axis === "x" ? e.clientX : e.clientY;
50
- const onMouseMove = (ev) => onMove((axis === "x" ? ev.clientX : ev.clientY) - startPos);
39
+ const startPos = axis === 'x' ? e.clientX : e.clientY;
40
+ const onMouseMove = ev => onMove((axis === 'x' ? ev.clientX : ev.clientY) - startPos);
51
41
  const onMouseUp = () => {
52
- window.removeEventListener("mousemove", onMouseMove);
53
- window.removeEventListener("mouseup", onMouseUp);
42
+ window.removeEventListener('mousemove', onMouseMove);
43
+ window.removeEventListener('mouseup', onMouseUp);
54
44
  };
55
- window.addEventListener("mousemove", onMouseMove);
56
- window.addEventListener("mouseup", onMouseUp);
45
+ window.addEventListener('mousemove', onMouseMove);
46
+ window.addEventListener('mouseup', onMouseUp);
57
47
  }
48
+
49
+ // 左侧整体宽度
58
50
  function dragLeftWidth(e) {
59
51
  const base = leftWidth.value;
60
- startDrag(e, "x", (d) => {
52
+ startDrag(e, 'x', d => {
61
53
  leftWidth.value = Math.max(160, Math.min(600, base + d));
62
54
  });
63
55
  }
56
+ // 右侧整体宽度(向左拖拽变宽,delta 取反)
64
57
  function dragRightWidth(e) {
65
58
  const base = rightWidth.value;
66
- startDrag(e, "x", (d) => {
59
+ startDrag(e, 'x', d => {
67
60
  rightWidth.value = Math.max(160, Math.min(600, base - d));
68
61
  });
69
62
  }
63
+ // 底部整体高度(向上拖拽变高,delta 取反)
70
64
  function dragBottomHeight(e) {
71
65
  const base = bottomHeight.value;
72
- startDrag(e, "y", (d) => {
66
+ startDrag(e, 'y', d => {
73
67
  bottomHeight.value = Math.max(80, Math.min(600, base - d));
74
68
  });
75
69
  }
70
+ // 左侧内部上下分割
76
71
  function dragLeftSplit(e, totalHeight) {
77
72
  const base = leftSplitRatio.value;
78
- startDrag(e, "y", (d) => {
73
+ startDrag(e, 'y', d => {
79
74
  leftSplitRatio.value = Math.max(0.15, Math.min(0.85, base + d / totalHeight));
80
75
  });
81
76
  }
77
+ // 右侧内部上下分割
82
78
  function dragRightSplit(e, totalHeight) {
83
79
  const base = rightSplitRatio.value;
84
- startDrag(e, "y", (d) => {
80
+ startDrag(e, 'y', d => {
85
81
  rightSplitRatio.value = Math.max(0.15, Math.min(0.85, base + d / totalHeight));
86
82
  });
87
83
  }
84
+ // 底部内部左右分割
88
85
  function dragBottomSplit(e, totalWidth) {
89
86
  const base = bottomSplitRatio.value;
90
- startDrag(e, "x", (d) => {
87
+ startDrag(e, 'x', d => {
91
88
  bottomSplitRatio.value = Math.max(0.15, Math.min(0.85, base + d / totalWidth));
92
89
  });
93
90
  }
91
+
92
+ // ─── 辅助 ─────────────────────────────────────────────────────────────
94
93
  function getActiveWidget(activeId) {
95
94
  if (!activeId) return null;
96
- return props.skeleton?.widgets.find((w) => w.name === activeId) ?? null;
95
+ return props.skeleton?.widgets.find(w => w.name === activeId) ?? null;
97
96
  }
98
97
  function isDocked(activeId) {
99
98
  const mode = getActiveWidget(activeId)?.pane.viewMode.value;
100
- return mode === "DockPinned" || mode === "DockUnpinned";
99
+ return mode === 'DockPinned' || mode === 'DockUnpinned';
101
100
  }
102
- const leftTopWidget = (0, import_vue.computed)(
103
- () => getActiveWidget(props.skeleton?.leftTopArea.container.activeId.value ?? null)
104
- );
105
- const leftBottomWidget = (0, import_vue.computed)(
106
- () => getActiveWidget(props.skeleton?.leftBottomArea.container.activeId.value ?? null)
107
- );
108
- const rightTopWidget = (0, import_vue.computed)(
109
- () => getActiveWidget(props.skeleton?.rightTopArea.container.activeId.value ?? null)
110
- );
111
- const rightBottomWidget = (0, import_vue.computed)(
112
- () => getActiveWidget(props.skeleton?.rightBottomArea.container.activeId.value ?? null)
113
- );
114
- const bottomLeftWidget = (0, import_vue.computed)(
115
- () => getActiveWidget(props.skeleton?.bottomLeftArea.container.activeId.value ?? null)
116
- );
117
- const bottomRightWidget = (0, import_vue.computed)(
118
- () => getActiveWidget(props.skeleton?.bottomRightArea.container.activeId.value ?? null)
119
- );
120
- const isLeftTopVisible = (0, import_vue.computed)(
121
- () => isDocked(props.skeleton?.leftTopArea.container.activeId.value ?? null)
122
- );
123
- const isLeftBottomVisible = (0, import_vue.computed)(
124
- () => isDocked(props.skeleton?.leftBottomArea.container.activeId.value ?? null)
125
- );
126
- const isRightTopVisible = (0, import_vue.computed)(
127
- () => isDocked(props.skeleton?.rightTopArea.container.activeId.value ?? null)
128
- );
129
- const isRightBottomVisible = (0, import_vue.computed)(
130
- () => isDocked(props.skeleton?.rightBottomArea.container.activeId.value ?? null)
131
- );
132
- const isBottomLeftVisible = (0, import_vue.computed)(
133
- () => isDocked(props.skeleton?.bottomLeftArea.container.activeId.value ?? null)
134
- );
135
- const isBottomRightVisible = (0, import_vue.computed)(
136
- () => isDocked(props.skeleton?.bottomRightArea.container.activeId.value ?? null)
137
- );
138
- const isLeftVisible = (0, import_vue.computed)(() => isLeftTopVisible.value || isLeftBottomVisible.value);
139
- const isRightVisible = (0, import_vue.computed)(() => isRightTopVisible.value || isRightBottomVisible.value);
140
- const isBottomVisible = (0, import_vue.computed)(() => isBottomLeftVisible.value || isBottomRightVisible.value);
101
+
102
+ // ─── 各侧 active widget ───────────────────────────────────────────────
103
+ const leftTopWidget = vue.computed(() => getActiveWidget(props.skeleton?.leftTopArea.container.activeId.value ?? null));
104
+ const leftBottomWidget = vue.computed(() => getActiveWidget(props.skeleton?.leftBottomArea.container.activeId.value ?? null));
105
+ const rightTopWidget = vue.computed(() => getActiveWidget(props.skeleton?.rightTopArea.container.activeId.value ?? null));
106
+ const rightBottomWidget = vue.computed(() => getActiveWidget(props.skeleton?.rightBottomArea.container.activeId.value ?? null));
107
+ const bottomLeftWidget = vue.computed(() => getActiveWidget(props.skeleton?.bottomLeftArea.container.activeId.value ?? null));
108
+ const bottomRightWidget = vue.computed(() => getActiveWidget(props.skeleton?.bottomRightArea.container.activeId.value ?? null));
109
+
110
+ // ─── 各面板 docked 可见性 ─────────────────────────────────────────────
111
+ const isLeftTopVisible = vue.computed(() => isDocked(props.skeleton?.leftTopArea.container.activeId.value ?? null));
112
+ const isLeftBottomVisible = vue.computed(() => isDocked(props.skeleton?.leftBottomArea.container.activeId.value ?? null));
113
+ const isRightTopVisible = vue.computed(() => isDocked(props.skeleton?.rightTopArea.container.activeId.value ?? null));
114
+ const isRightBottomVisible = vue.computed(() => isDocked(props.skeleton?.rightBottomArea.container.activeId.value ?? null));
115
+ const isBottomLeftVisible = vue.computed(() => isDocked(props.skeleton?.bottomLeftArea.container.activeId.value ?? null));
116
+ const isBottomRightVisible = vue.computed(() => isDocked(props.skeleton?.bottomRightArea.container.activeId.value ?? null));
117
+
118
+ // 整侧可见(有任意一个 docked 就显示侧栏容器)
119
+ const isLeftVisible = vue.computed(() => isLeftTopVisible.value || isLeftBottomVisible.value);
120
+ const isRightVisible = vue.computed(() => isRightTopVisible.value || isRightBottomVisible.value);
121
+ const isBottomVisible = vue.computed(() => isBottomLeftVisible.value || isBottomRightVisible.value);
122
+
123
+ // ─── Undocked widget(每侧独立,从 focusedId 里找) ───────────────────
141
124
  function makeUndockedWidget(side) {
142
- return (0, import_vue.computed)(() => {
125
+ return vue.computed(() => {
143
126
  const sk = props.skeleton;
144
127
  const w = getActiveWidget(sk?.focusedId.value ?? null);
145
- if (!w || w.pane.viewMode.value !== "Undock") return null;
128
+ if (!w || w.pane.viewMode.value !== 'Undock') return null;
146
129
  const areaMap = {
147
130
  left: [sk?.leftTopArea, sk?.leftBottomArea],
148
131
  right: [sk?.rightTopArea, sk?.rightBottomArea],
149
132
  bottom: [sk?.bottomLeftArea, sk?.bottomRightArea]
150
133
  };
151
- const belongs = areaMap[side].some(
152
- (a) => a?.container.items.value.some((i) => i.name === w.name)
153
- );
134
+ const belongs = areaMap[side].some(a => a?.container.items.value.some(i => i.name === w.name));
154
135
  return belongs ? w : null;
155
136
  });
156
137
  }
157
- const leftUndockedWidget = makeUndockedWidget("left");
158
- const rightUndockedWidget = makeUndockedWidget("right");
159
- const bottomUndockedWidget = makeUndockedWidget("bottom");
160
- const isLeftUndockedVisible = (0, import_vue.computed)(() => leftUndockedWidget.value !== null);
161
- const isRightUndockedVisible = (0, import_vue.computed)(() => rightUndockedWidget.value !== null);
162
- const isBottomUndockedVisible = (0, import_vue.computed)(() => bottomUndockedWidget.value !== null);
163
- const teleportTargets = (0, import_vue.computed)(() => {
138
+ const leftUndockedWidget = makeUndockedWidget('left');
139
+ const rightUndockedWidget = makeUndockedWidget('right');
140
+ const bottomUndockedWidget = makeUndockedWidget('bottom');
141
+ const isLeftUndockedVisible = vue.computed(() => leftUndockedWidget.value !== null);
142
+ const isRightUndockedVisible = vue.computed(() => rightUndockedWidget.value !== null);
143
+ const isBottomUndockedVisible = vue.computed(() => bottomUndockedWidget.value !== null);
144
+
145
+ // ─── Teleport 目标 map ────────────────────────────────────────────────
146
+ const teleportTargets = vue.computed(() => {
164
147
  const sk = props.skeleton;
165
148
  const map = {};
166
149
  if (!sk) return map;
167
- const sideIndex = /* @__PURE__ */ new Map();
168
- sk.leftTopArea.container.items.value.forEach(
169
- (w) => sideIndex.set(w.name, "#left-undocked-area")
170
- );
171
- sk.leftBottomArea.container.items.value.forEach(
172
- (w) => sideIndex.set(w.name, "#left-undocked-area")
173
- );
174
- sk.rightTopArea.container.items.value.forEach(
175
- (w) => sideIndex.set(w.name, "#right-undocked-area")
176
- );
177
- sk.rightBottomArea.container.items.value.forEach(
178
- (w) => sideIndex.set(w.name, "#right-undocked-area")
179
- );
180
- sk.bottomLeftArea.container.items.value.forEach(
181
- (w) => sideIndex.set(w.name, "#bottom-undocked-area")
182
- );
183
- sk.bottomRightArea.container.items.value.forEach(
184
- (w) => sideIndex.set(w.name, "#bottom-undocked-area")
185
- );
150
+
151
+ // widgetName -> 所属侧的 undocked 锚点(仅表达归属,不代表一定能传送过去)
152
+ const sideIndex = new Map();
153
+ sk.leftTopArea.container.items.value.forEach(w => sideIndex.set(w.name, '#left-undocked-area'));
154
+ sk.leftBottomArea.container.items.value.forEach(w => sideIndex.set(w.name, '#left-undocked-area'));
155
+ sk.rightTopArea.container.items.value.forEach(w => sideIndex.set(w.name, '#right-undocked-area'));
156
+ sk.rightBottomArea.container.items.value.forEach(w => sideIndex.set(w.name, '#right-undocked-area'));
157
+ sk.bottomLeftArea.container.items.value.forEach(w => sideIndex.set(w.name, '#bottom-undocked-area'));
158
+ sk.bottomRightArea.container.items.value.forEach(w => sideIndex.set(w.name, '#bottom-undocked-area'));
159
+
160
+ // 每个 undocked 锚点当前唯一获得传送权的 widgetName
161
+ // 规则:focusedId 优先;若 focusedId 不属于该侧则该侧无 undocked 显示
186
162
  const focusedName = sk.focusedId.value;
187
163
  const undockWinner = {
188
- "#left-undocked-area": null,
189
- "#right-undocked-area": null,
190
- "#bottom-undocked-area": null
164
+ '#left-undocked-area': null,
165
+ '#right-undocked-area': null,
166
+ '#bottom-undocked-area': null
191
167
  };
192
168
  if (focusedName) {
193
- const focusedWidget = sk.widgets.find((w) => w.name === focusedName);
194
- if (focusedWidget?.pane.viewMode.value === "Undock") {
169
+ const focusedWidget = sk.widgets.find(w => w.name === focusedName);
170
+ if (focusedWidget?.pane.viewMode.value === 'Undock') {
195
171
  const anchor = sideIndex.get(focusedName);
196
172
  if (anchor) undockWinner[anchor] = focusedName;
197
173
  }
198
174
  }
175
+
176
+ // activeId -> docked 锚点
199
177
  const dockTargets = {
200
- [sk.leftTopArea.container.activeId.value ?? ""]: "#left-top-area",
201
- [sk.leftBottomArea.container.activeId.value ?? ""]: "#left-bottom-area",
202
- [sk.rightTopArea.container.activeId.value ?? ""]: "#right-top-area",
203
- [sk.rightBottomArea.container.activeId.value ?? ""]: "#right-bottom-area",
204
- [sk.bottomLeftArea.container.activeId.value ?? ""]: "#bottom-left-area",
205
- [sk.bottomRightArea.container.activeId.value ?? ""]: "#bottom-right-area"
178
+ [sk.leftTopArea.container.activeId.value ?? '']: '#left-top-area',
179
+ [sk.leftBottomArea.container.activeId.value ?? '']: '#left-bottom-area',
180
+ [sk.rightTopArea.container.activeId.value ?? '']: '#right-top-area',
181
+ [sk.rightBottomArea.container.activeId.value ?? '']: '#right-bottom-area',
182
+ [sk.bottomLeftArea.container.activeId.value ?? '']: '#bottom-left-area',
183
+ [sk.bottomRightArea.container.activeId.value ?? '']: '#bottom-right-area'
206
184
  };
207
- delete dockTargets[""];
208
- sk.widgets.filter((w) => w.type === "panel").forEach((w) => {
209
- if (w.pane.viewMode.value === "Undock") {
210
- const anchor = sideIndex.get(w.name) ?? "#widget-offscreen";
211
- map[w.name] = undockWinner[anchor] === w.name ? anchor : "#widget-offscreen";
185
+ delete dockTargets[''];
186
+ sk.widgets.filter(w => w.type === 'panel').forEach(w => {
187
+ if (w.pane.viewMode.value === 'Undock') {
188
+ const anchor = sideIndex.get(w.name) ?? '#widget-offscreen';
189
+ // 只有赢得该锚点的 widget 才能传送过去,其余保活在 offscreen
190
+ map[w.name] = undockWinner[anchor] === w.name ? anchor : '#widget-offscreen';
212
191
  } else {
213
- map[w.name] = dockTargets[w.name] ?? "#widget-offscreen";
192
+ map[w.name] = dockTargets[w.name] ?? '#widget-offscreen';
214
193
  }
215
194
  });
216
195
  return map;
217
196
  });
218
- const centerWidgetNames = (0, import_vue.computed)(() => {
219
- const names = /* @__PURE__ */ new Set();
220
- props.centerArea?.container.items.value.forEach((w) => names.add(w.name));
197
+
198
+ // ─── Center widget Teleport 目标 ──────────────────────────────────────
199
+ const centerWidgetNames = vue.computed(() => {
200
+ const names = new Set();
201
+ props.centerArea?.container.items.value.forEach(w => names.add(w.name));
221
202
  return names;
222
203
  });
223
- const centerTargets = (0, import_vue.computed)(() => {
204
+ const centerTargets = vue.computed(() => {
224
205
  const activeId = props.centerArea?.container.activeId.value ?? null;
225
206
  const map = {};
226
- props.centerArea?.container.items.value.forEach((w) => {
227
- map[w.name] = w.name === activeId ? "#center-area" : "#center-offscreen";
207
+ props.centerArea?.container.items.value.forEach(w => {
208
+ map[w.name] = w.name === activeId ? '#center-area' : '#center-offscreen';
228
209
  });
229
210
  return map;
230
211
  });
231
- const leftTopHeight = (0, import_vue.computed)(() => `calc((100% - 4px) * ${leftSplitRatio.value})`);
232
- const leftBottomHeight = (0, import_vue.computed)(() => `calc((100% - 4px) * ${1 - leftSplitRatio.value})`);
233
- const rightTopHeight = (0, import_vue.computed)(() => `calc((100% - 4px) * ${rightSplitRatio.value})`);
234
- const rightBottomHeight = (0, import_vue.computed)(() => `calc((100% - 4px) * ${1 - rightSplitRatio.value})`);
235
- const bottomLeftWidth = (0, import_vue.computed)(() => `calc((100% - 4px) * ${bottomSplitRatio.value})`);
236
- const bottomRightWidth = (0, import_vue.computed)(() => `calc((100% - 4px) * ${1 - bottomSplitRatio.value})`);
212
+
213
+ // ─── 内部分割高度 / 宽度(CSS calc 字符串) ───────────────────────────
214
+ const leftTopHeight = vue.computed(() => `calc((100% - 4px) * ${leftSplitRatio.value})`);
215
+ const leftBottomHeight = vue.computed(() => `calc((100% - 4px) * ${1 - leftSplitRatio.value})`);
216
+ const rightTopHeight = vue.computed(() => `calc((100% - 4px) * ${rightSplitRatio.value})`);
217
+ const rightBottomHeight = vue.computed(() => `calc((100% - 4px) * ${1 - rightSplitRatio.value})`);
218
+ const bottomLeftWidth = vue.computed(() => `calc((100% - 4px) * ${bottomSplitRatio.value})`);
219
+ const bottomRightWidth = vue.computed(() => `calc((100% - 4px) * ${1 - bottomSplitRatio.value})`);
237
220
  return () => {
238
221
  if (!props.skeleton) return null;
239
222
  const sk = props.skeleton;
240
223
  const leftBoth = isLeftTopVisible.value && isLeftBottomVisible.value;
241
224
  const rightBoth = isRightTopVisible.value && isRightBottomVisible.value;
242
225
  const bottomBoth = isBottomLeftVisible.value && isBottomRightVisible.value;
243
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "layplux-center-area", children: [
244
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { id: "widget-offscreen", style: "display:none;" }),
245
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { id: "center-offscreen", style: "display:none;" }),
246
- sk.widgets.filter((w) => w.type === "panel" && !centerWidgetNames.value.has(w.name)).map((w) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
247
- import_vue.Teleport,
248
- {
249
- defer: true,
250
- to: teleportTargets.value[w.name] ?? "#widget-offscreen",
251
- children: w.renderContent()
252
- },
253
- w.name
254
- )),
255
- props.centerArea?.container.items.value.map((w) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_vue.Teleport, { defer: true, to: centerTargets.value[w.name] ?? "#center-offscreen", children: w.renderContent() }, w.name)),
256
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
257
- "div",
258
- {
259
- class: "layplux-panel--undocked layplux-panel--undocked-left",
260
- "v-show": isLeftUndockedVisible.value,
261
- style: { width: `${leftWidth.value}px` },
262
- children: [
263
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.PanelView, { anchor: "left-undocked-area", widget: leftUndockedWidget.value ?? void 0 }),
264
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
265
- "div",
266
- {
267
- class: "layplux-resize-handle layplux-resize-handle--x layplux-resize-handle--edge-right",
268
- onMousedown: dragLeftWidth
269
- }
270
- )
271
- ]
272
- }
273
- ),
274
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
275
- "div",
276
- {
277
- class: "layplux-panel--undocked layplux-panel--undocked-right",
278
- "v-show": isRightUndockedVisible.value,
279
- style: { width: `${rightWidth.value}px` },
280
- children: [
281
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
282
- "div",
283
- {
284
- class: "layplux-resize-handle layplux-resize-handle--x layplux-resize-handle--edge-left",
285
- onMousedown: dragRightWidth
286
- }
287
- ),
288
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
289
- import_components.PanelView,
290
- {
291
- anchor: "right-undocked-area",
292
- widget: rightUndockedWidget.value ?? void 0
293
- }
294
- )
295
- ]
296
- }
297
- ),
298
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
299
- "div",
300
- {
301
- class: "layplux-panel--undocked layplux-panel--undocked-bottom",
302
- "v-show": isBottomUndockedVisible.value,
303
- style: { height: `${bottomHeight.value}px` },
304
- children: [
305
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
306
- "div",
307
- {
308
- class: "layplux-resize-handle layplux-resize-handle--y layplux-resize-handle--edge-top",
309
- onMousedown: dragBottomHeight
310
- }
311
- ),
312
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
313
- import_components.PanelView,
314
- {
315
- anchor: "bottom-undocked-area",
316
- widget: bottomUndockedWidget.value ?? void 0
317
- }
318
- )
319
- ]
320
- }
321
- ),
322
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "layplux-center-area__main", children: [
323
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
324
- "div",
325
- {
326
- class: "layplux-center-area__left",
327
- "v-show": isLeftVisible.value,
328
- style: { width: `${leftWidth.value}px` },
329
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "layplux-center-area__docked-panels", children: [
330
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
331
- import_components.PanelView,
332
- {
333
- anchor: "left-top-area",
334
- widget: leftTopWidget.value ?? void 0,
335
- "v-show": isLeftTopVisible.value,
336
- style: leftBoth ? { height: leftTopHeight.value, flex: "none" } : {}
337
- }
338
- ),
339
- leftBoth && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
340
- "div",
341
- {
342
- class: "layplux-resize-handle layplux-resize-handle--y",
343
- onMousedown: (e) => dragLeftSplit(
344
- e,
345
- e.currentTarget.closest(
346
- ".layplux-center-area__docked-panels"
347
- ).clientHeight
348
- )
349
- }
350
- ),
351
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
352
- import_components.PanelView,
353
- {
354
- anchor: "left-bottom-area",
355
- widget: leftBottomWidget.value ?? void 0,
356
- "v-show": isLeftBottomVisible.value,
357
- style: leftBoth ? { height: leftBottomHeight.value, flex: "none" } : {}
358
- }
359
- )
360
- ] })
361
- }
362
- ),
363
- isLeftVisible.value && !isLeftUndockedVisible.value && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
364
- "div",
365
- {
366
- class: "layplux-resize-handle layplux-resize-handle--x",
367
- onMousedown: dragLeftWidth
368
- }
369
- ),
370
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { id: "center-area", class: "layplux-center-area__editor" }),
371
- isRightVisible.value && !isRightUndockedVisible.value && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
372
- "div",
373
- {
374
- class: "layplux-resize-handle layplux-resize-handle--x",
375
- onMousedown: dragRightWidth
376
- }
377
- ),
378
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
379
- "div",
380
- {
381
- class: "layplux-center-area__right",
382
- "v-show": isRightVisible.value,
383
- style: { width: `${rightWidth.value}px` },
384
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "layplux-center-area__docked-panels", children: [
385
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
386
- import_components.PanelView,
387
- {
388
- anchor: "right-top-area",
389
- widget: rightTopWidget.value ?? void 0,
390
- "v-show": isRightTopVisible.value,
391
- style: rightBoth ? { height: rightTopHeight.value, flex: "none" } : {}
392
- }
393
- ),
394
- rightBoth && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
395
- "div",
396
- {
397
- class: "layplux-resize-handle layplux-resize-handle--y",
398
- onMousedown: (e) => dragRightSplit(
399
- e,
400
- e.currentTarget.closest(
401
- ".layplux-center-area__docked-panels"
402
- ).clientHeight
403
- )
404
- }
405
- ),
406
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
407
- import_components.PanelView,
408
- {
409
- anchor: "right-bottom-area",
410
- widget: rightBottomWidget.value ?? void 0,
411
- "v-show": isRightBottomVisible.value,
412
- style: rightBoth ? { height: rightBottomHeight.value, flex: "none" } : {}
413
- }
414
- )
415
- ] })
416
- }
417
- )
418
- ] }),
419
- isBottomVisible.value && !isBottomUndockedVisible.value && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
420
- "div",
421
- {
422
- class: "layplux-resize-handle layplux-resize-handle--y layplux-resize-handle--bottom-edge",
423
- onMousedown: dragBottomHeight
424
- }
425
- ),
426
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
427
- "div",
428
- {
429
- class: "layplux-center-area__bottom",
430
- "v-show": isBottomVisible.value,
431
- style: { height: `${bottomHeight.value}px` },
432
- children: [
433
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
434
- import_components.PanelView,
435
- {
436
- anchor: "bottom-left-area",
437
- widget: bottomLeftWidget.value ?? void 0,
438
- "v-show": isBottomLeftVisible.value,
439
- style: bottomBoth ? { width: bottomLeftWidth.value, flex: "none" } : {}
440
- }
441
- ),
442
- bottomBoth && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
443
- "div",
444
- {
445
- class: "layplux-resize-handle layplux-resize-handle--x",
446
- onMousedown: (e) => dragBottomSplit(
447
- e,
448
- e.currentTarget.closest(".layplux-center-area__bottom").clientWidth
449
- )
450
- }
451
- ),
452
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
453
- import_components.PanelView,
454
- {
455
- anchor: "bottom-right-area",
456
- widget: bottomRightWidget.value ?? void 0,
457
- "v-show": isBottomRightVisible.value,
458
- style: bottomBoth ? { width: bottomRightWidth.value, flex: "none" } : {}
459
- }
460
- )
461
- ]
462
- }
463
- )
464
- ] });
226
+ return vue.createVNode("div", {
227
+ "class": "layplux-center-area"
228
+ }, [vue.createVNode("div", {
229
+ "id": "widget-offscreen",
230
+ "style": "display:none;"
231
+ }, null), vue.createVNode("div", {
232
+ "id": "center-offscreen",
233
+ "style": "display:none;"
234
+ }, null), sk.widgets.filter(w => w.type === 'panel' && !centerWidgetNames.value.has(w.name)).map(w => {
235
+ let _slot;
236
+ return vue.createVNode(vue.Teleport, {
237
+ "defer": true,
238
+ "key": w.name,
239
+ "to": teleportTargets.value[w.name] ?? '#widget-offscreen'
240
+ }, _isSlot(_slot = w.renderContent()) ? _slot : {
241
+ default: () => [_slot]
242
+ });
243
+ }), props.centerArea?.container.items.value.map(w => {
244
+ let _slot2;
245
+ return vue.createVNode(vue.Teleport, {
246
+ "defer": true,
247
+ "key": w.name,
248
+ "to": centerTargets.value[w.name] ?? '#center-offscreen'
249
+ }, _isSlot(_slot2 = w.renderContent()) ? _slot2 : {
250
+ default: () => [_slot2]
251
+ });
252
+ }), vue.withDirectives(vue.createVNode("div", {
253
+ "class": "layplux-panel--undocked layplux-panel--undocked-left",
254
+ "style": {
255
+ width: `${leftWidth.value}px`
256
+ }
257
+ }, [vue.createVNode(index.PanelView, {
258
+ "anchor": "left-undocked-area",
259
+ "widget": leftUndockedWidget.value ?? undefined
260
+ }, null), vue.createVNode("div", {
261
+ "class": "layplux-resize-handle layplux-resize-handle--x layplux-resize-handle--edge-right",
262
+ "onMousedown": dragLeftWidth
263
+ }, null)]), [[vue.vShow, isLeftUndockedVisible.value]]), vue.withDirectives(vue.createVNode("div", {
264
+ "class": "layplux-panel--undocked layplux-panel--undocked-right",
265
+ "style": {
266
+ width: `${rightWidth.value}px`
267
+ }
268
+ }, [vue.createVNode("div", {
269
+ "class": "layplux-resize-handle layplux-resize-handle--x layplux-resize-handle--edge-left",
270
+ "onMousedown": dragRightWidth
271
+ }, null), vue.createVNode(index.PanelView, {
272
+ "anchor": "right-undocked-area",
273
+ "widget": rightUndockedWidget.value ?? undefined
274
+ }, null)]), [[vue.vShow, isRightUndockedVisible.value]]), vue.withDirectives(vue.createVNode("div", {
275
+ "class": "layplux-panel--undocked layplux-panel--undocked-bottom",
276
+ "style": {
277
+ height: `${bottomHeight.value}px`
278
+ }
279
+ }, [vue.createVNode("div", {
280
+ "class": "layplux-resize-handle layplux-resize-handle--y layplux-resize-handle--edge-top",
281
+ "onMousedown": dragBottomHeight
282
+ }, null), vue.createVNode(index.PanelView, {
283
+ "anchor": "bottom-undocked-area",
284
+ "widget": bottomUndockedWidget.value ?? undefined
285
+ }, null)]), [[vue.vShow, isBottomUndockedVisible.value]]), vue.createVNode("div", {
286
+ "class": "layplux-center-area__main"
287
+ }, [vue.withDirectives(vue.createVNode("div", {
288
+ "class": "layplux-center-area__left",
289
+ "style": {
290
+ width: `${leftWidth.value}px`
291
+ }
292
+ }, [vue.createVNode("div", {
293
+ "class": "layplux-center-area__docked-panels"
294
+ }, [vue.withDirectives(vue.createVNode(index.PanelView, {
295
+ "anchor": "left-top-area",
296
+ "widget": leftTopWidget.value ?? undefined,
297
+ "style": leftBoth ? {
298
+ height: leftTopHeight.value,
299
+ flex: 'none'
300
+ } : {}
301
+ }, null), [[vue.vShow, isLeftTopVisible.value]]), leftBoth && vue.createVNode("div", {
302
+ "class": "layplux-resize-handle layplux-resize-handle--y",
303
+ "onMousedown": e => dragLeftSplit(e, e.currentTarget.closest('.layplux-center-area__docked-panels').clientHeight)
304
+ }, null), vue.withDirectives(vue.createVNode(index.PanelView, {
305
+ "anchor": "left-bottom-area",
306
+ "widget": leftBottomWidget.value ?? undefined,
307
+ "style": leftBoth ? {
308
+ height: leftBottomHeight.value,
309
+ flex: 'none'
310
+ } : {}
311
+ }, null), [[vue.vShow, isLeftBottomVisible.value]])])]), [[vue.vShow, isLeftVisible.value]]), isLeftVisible.value && !isLeftUndockedVisible.value && vue.createVNode("div", {
312
+ "class": "layplux-resize-handle layplux-resize-handle--x",
313
+ "onMousedown": dragLeftWidth
314
+ }, null), vue.createVNode("div", {
315
+ "id": "center-area",
316
+ "class": "layplux-center-area__editor"
317
+ }, null), isRightVisible.value && !isRightUndockedVisible.value && vue.createVNode("div", {
318
+ "class": "layplux-resize-handle layplux-resize-handle--x",
319
+ "onMousedown": dragRightWidth
320
+ }, null), vue.withDirectives(vue.createVNode("div", {
321
+ "class": "layplux-center-area__right",
322
+ "style": {
323
+ width: `${rightWidth.value}px`
324
+ }
325
+ }, [vue.createVNode("div", {
326
+ "class": "layplux-center-area__docked-panels"
327
+ }, [vue.withDirectives(vue.createVNode(index.PanelView, {
328
+ "anchor": "right-top-area",
329
+ "widget": rightTopWidget.value ?? undefined,
330
+ "style": rightBoth ? {
331
+ height: rightTopHeight.value,
332
+ flex: 'none'
333
+ } : {}
334
+ }, null), [[vue.vShow, isRightTopVisible.value]]), rightBoth && vue.createVNode("div", {
335
+ "class": "layplux-resize-handle layplux-resize-handle--y",
336
+ "onMousedown": e => dragRightSplit(e, e.currentTarget.closest('.layplux-center-area__docked-panels').clientHeight)
337
+ }, null), vue.withDirectives(vue.createVNode(index.PanelView, {
338
+ "anchor": "right-bottom-area",
339
+ "widget": rightBottomWidget.value ?? undefined,
340
+ "style": rightBoth ? {
341
+ height: rightBottomHeight.value,
342
+ flex: 'none'
343
+ } : {}
344
+ }, null), [[vue.vShow, isRightBottomVisible.value]])])]), [[vue.vShow, isRightVisible.value]])]), isBottomVisible.value && !isBottomUndockedVisible.value && vue.createVNode("div", {
345
+ "class": "layplux-resize-handle layplux-resize-handle--y layplux-resize-handle--bottom-edge",
346
+ "onMousedown": dragBottomHeight
347
+ }, null), vue.withDirectives(vue.createVNode("div", {
348
+ "class": "layplux-center-area__bottom",
349
+ "style": {
350
+ height: `${bottomHeight.value}px`
351
+ }
352
+ }, [vue.withDirectives(vue.createVNode(index.PanelView, {
353
+ "anchor": "bottom-left-area",
354
+ "widget": bottomLeftWidget.value ?? undefined,
355
+ "style": bottomBoth ? {
356
+ width: bottomLeftWidth.value,
357
+ flex: 'none'
358
+ } : {}
359
+ }, null), [[vue.vShow, isBottomLeftVisible.value]]), bottomBoth && vue.createVNode("div", {
360
+ "class": "layplux-resize-handle layplux-resize-handle--x",
361
+ "onMousedown": e => dragBottomSplit(e, e.currentTarget.closest('.layplux-center-area__bottom').clientWidth)
362
+ }, null), vue.withDirectives(vue.createVNode(index.PanelView, {
363
+ "anchor": "bottom-right-area",
364
+ "widget": bottomRightWidget.value ?? undefined,
365
+ "style": bottomBoth ? {
366
+ width: bottomRightWidth.value,
367
+ flex: 'none'
368
+ } : {}
369
+ }, null), [[vue.vShow, isBottomRightVisible.value]])]), [[vue.vShow, isBottomVisible.value]])]);
465
370
  };
466
371
  }
467
372
  });
373
+
374
+ exports.CenterArea = CenterArea;