niuma-ui 2.1.5 → 2.1.7
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/CHANGELOG.md +13 -0
- package/dist/components/context-menu/src/RsContextMenu.impl.js +4 -0
- package/dist/components/terminal/src/RsTerminal.css +29 -29
- package/dist/components/terminal/src/RsTerminal.impl.js +28 -3
- package/dist/components/terminal/src/RsTerminal.js +1 -1
- package/dist/components/terminal/src/terminal-utils.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,19 @@
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
|
|
10
|
+
## [2.1.7] - 2026-10-08
|
|
11
|
+
|
|
12
|
+
### 修复
|
|
13
|
+
|
|
14
|
+
- `RsTerminal`:页签被 keep-alive 收起后,页面上其它组件写入 `data-rs-theme` 仍会让已摘掉的终端重读 `--rs-terminal-*`。节点不在文档里时这些变量继承不到,前景落成黑色,`minimumContrastRatio` 再把正文抬成灰色。现在宿主不在文档里不写调色板;回到页签时,只有收起期间确实要重读才再采一次。采到的颜色与当前相同则不赋 `options.theme`,避免清对比度缓存并重画视口。
|
|
15
|
+
|
|
16
|
+
## [2.1.6] - 2026-10-08
|
|
17
|
+
|
|
18
|
+
### 修复
|
|
19
|
+
|
|
20
|
+
- `RsContextMenu`:页面上任意元素滚动都会关掉已打开的菜单。旁边面板(例如流式输出把消息列表往下滚)会把另一侧的右键清掉。现在只在触发器自己的滚动链上关闭:滚动的节点包含触发器,或触发器包含该节点。菜单内部滚动仍不关闭;点菜单外空白处仍关闭。
|
|
21
|
+
|
|
9
22
|
## [2.1.5] - 2026-09-28
|
|
10
23
|
|
|
11
24
|
### 变更
|
|
@@ -522,6 +522,10 @@ var RsContextMenu_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
|
|
|
522
522
|
if (!open.value) return;
|
|
523
523
|
const target = event.target;
|
|
524
524
|
if (target instanceof Node && isInsideMenu(target)) return;
|
|
525
|
+
const trigger = triggerEl.value;
|
|
526
|
+
if (trigger && target instanceof Node) {
|
|
527
|
+
if (!(target.contains(trigger) || trigger.contains(target))) return;
|
|
528
|
+
}
|
|
525
529
|
restoreOnClose = false;
|
|
526
530
|
setOpen(false);
|
|
527
531
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
.rs-terminal[data-v-
|
|
2
|
+
.rs-terminal[data-v-06f53055] {
|
|
3
3
|
position: relative;
|
|
4
4
|
height: 100%;
|
|
5
5
|
min-height: 0;
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
box-shadow: var(--rs-shadow-sm);
|
|
14
14
|
overflow: hidden;
|
|
15
15
|
}
|
|
16
|
-
.rs-terminal__host[data-v-
|
|
16
|
+
.rs-terminal__host[data-v-06f53055] {
|
|
17
17
|
position: relative;
|
|
18
18
|
width: 100%;
|
|
19
19
|
height: 100%;
|
|
@@ -21,15 +21,15 @@
|
|
|
21
21
|
/* FitAddon 取整余量露底时,与单元格同色(勿用 shell 灰底) */
|
|
22
22
|
background: var(--rs-terminal-bg);
|
|
23
23
|
}
|
|
24
|
-
.rs-terminal__loading[data-v-
|
|
25
|
-
.rs-terminal__overlay[data-v-
|
|
24
|
+
.rs-terminal__loading[data-v-06f53055],
|
|
25
|
+
.rs-terminal__overlay[data-v-06f53055] {
|
|
26
26
|
position: absolute;
|
|
27
27
|
inset: 0;
|
|
28
28
|
display: flex;
|
|
29
29
|
align-items: center;
|
|
30
30
|
justify-content: center;
|
|
31
31
|
}
|
|
32
|
-
.rs-terminal__overlay[data-v-
|
|
32
|
+
.rs-terminal__overlay[data-v-06f53055] {
|
|
33
33
|
flex-direction: column;
|
|
34
34
|
gap: var(--rs-space-sm);
|
|
35
35
|
padding: var(--rs-space-lg);
|
|
@@ -42,13 +42,13 @@
|
|
|
42
42
|
font-weight: var(--rs-font-weight-regular);
|
|
43
43
|
line-height: var(--rs-line-height-normal);
|
|
44
44
|
}
|
|
45
|
-
.rs-terminal__overlay--interactive[data-v-
|
|
45
|
+
.rs-terminal__overlay--interactive[data-v-06f53055] {
|
|
46
46
|
pointer-events: auto;
|
|
47
47
|
}
|
|
48
|
-
.rs-terminal__overlay-action[data-v-
|
|
48
|
+
.rs-terminal__overlay-action[data-v-06f53055] {
|
|
49
49
|
pointer-events: auto;
|
|
50
50
|
}
|
|
51
|
-
.rs-terminal__search[data-v-
|
|
51
|
+
.rs-terminal__search[data-v-06f53055] {
|
|
52
52
|
position: absolute;
|
|
53
53
|
inset-block-start: var(--rs-space-xs);
|
|
54
54
|
inset-inline-end: var(--rs-space-xs);
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
border-radius: var(--rs-radius-sm);
|
|
64
64
|
background: color-mix(in srgb, var(--rs-terminal-bg) 92%, transparent);
|
|
65
65
|
}
|
|
66
|
-
.rs-terminal__search-input[data-v-
|
|
66
|
+
.rs-terminal__search-input[data-v-06f53055] {
|
|
67
67
|
inline-size: 12rem;
|
|
68
68
|
max-inline-size: 100%;
|
|
69
69
|
padding-block: var(--rs-space-xs);
|
|
@@ -76,12 +76,12 @@
|
|
|
76
76
|
font-size: var(--rs-font-size-xs);
|
|
77
77
|
outline: none;
|
|
78
78
|
}
|
|
79
|
-
.rs-terminal__search-input[data-v-
|
|
80
|
-
.rs-terminal__search-btn[data-v-
|
|
79
|
+
.rs-terminal__search-input[data-v-06f53055]:focus-visible,
|
|
80
|
+
.rs-terminal__search-btn[data-v-06f53055]:focus-visible {
|
|
81
81
|
outline: var(--rs-focus-ring-width, 2px) solid var(--rs-focus-border);
|
|
82
82
|
outline-offset: 1px;
|
|
83
83
|
}
|
|
84
|
-
.rs-terminal__search-btn[data-v-
|
|
84
|
+
.rs-terminal__search-btn[data-v-06f53055] {
|
|
85
85
|
padding-block: var(--rs-space-xs);
|
|
86
86
|
padding-inline: var(--rs-space-xs);
|
|
87
87
|
border: 1px solid var(--rs-terminal-border);
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
font-size: var(--rs-font-size-xs);
|
|
92
92
|
cursor: pointer;
|
|
93
93
|
}
|
|
94
|
-
.rs-terminal__search-status[data-v-
|
|
94
|
+
.rs-terminal__search-status[data-v-06f53055] {
|
|
95
95
|
margin: 0;
|
|
96
96
|
color: var(--rs-text-secondary);
|
|
97
97
|
font-size: var(--rs-font-size-xs);
|
|
@@ -104,7 +104,7 @@
|
|
|
104
104
|
* DOM 渲染器于是按 `cellWidth - 测量值` 给每个字符补正字距,行盒却仍是 cols × cellWidth,
|
|
105
105
|
* 逐列累积后整行溢出十几到几十像素,被行盒的 overflow:hidden 切掉行尾几个字符。
|
|
106
106
|
*/
|
|
107
|
-
.rs-terminal[data-v-
|
|
107
|
+
.rs-terminal[data-v-06f53055] .xterm {
|
|
108
108
|
width: 100%;
|
|
109
109
|
height: 100%;
|
|
110
110
|
line-height: normal;
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
* xterm 6 官方仍给空的 .xterm-viewport 写 overflow-y:scroll + 背景 #000。
|
|
116
116
|
* 真正滚动的是 .xterm-scrollable-element;空层滚动条会挡住最后一列。
|
|
117
117
|
*/
|
|
118
|
-
.rs-terminal[data-v-
|
|
118
|
+
.rs-terminal[data-v-06f53055] .xterm .xterm-viewport {
|
|
119
119
|
overflow: hidden;
|
|
120
120
|
background-color: transparent;
|
|
121
121
|
}
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
* 的圆角胶囊不一致。轨道宽度由 overviewRuler.width 决定,改它会给每个终端实例多建一块
|
|
126
126
|
* overview ruler 画布,因此只重绘滑块:热区仍是 14px,靠透明边框内缩出 10px 可见胶囊。
|
|
127
127
|
*/
|
|
128
|
-
.rs-terminal[data-v-
|
|
128
|
+
.rs-terminal[data-v-06f53055] .xterm-scrollable-element > .scrollbar > .slider {
|
|
129
129
|
box-sizing: border-box;
|
|
130
130
|
border: var(--rs-scrollbar-padding, 2px) solid transparent;
|
|
131
131
|
border-radius: var(--rs-radius-full);
|
|
@@ -134,34 +134,34 @@
|
|
|
134
134
|
transition: background-color var(--rs-transition-fast);
|
|
135
135
|
}
|
|
136
136
|
@media (prefers-reduced-motion: reduce) {
|
|
137
|
-
.rs-terminal[data-v-
|
|
137
|
+
.rs-terminal[data-v-06f53055] .xterm-scrollable-element > .scrollbar > .slider {
|
|
138
138
|
transition: none;
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
141
|
@media (forced-colors: active) {
|
|
142
|
-
.rs-terminal[data-v-
|
|
142
|
+
.rs-terminal[data-v-06f53055] {
|
|
143
143
|
background: Canvas;
|
|
144
144
|
color: CanvasText;
|
|
145
145
|
border-color: ButtonText;
|
|
146
146
|
box-shadow: none;
|
|
147
147
|
}
|
|
148
|
-
.rs-terminal__search-input[data-v-
|
|
149
|
-
.rs-terminal__search-btn[data-v-
|
|
148
|
+
.rs-terminal__search-input[data-v-06f53055]:focus-visible,
|
|
149
|
+
.rs-terminal__search-btn[data-v-06f53055]:focus-visible {
|
|
150
150
|
outline: var(--rs-focus-ring-width, 2px) solid Highlight;
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
|
-
.rs-terminal[data-v-
|
|
153
|
+
.rs-terminal[data-v-06f53055] .xterm-scrollable-element > .scrollbar > .slider:hover {
|
|
154
154
|
background-color: color-mix(in srgb, var(--rs-primary) 40%, var(--rs-muted));
|
|
155
155
|
}
|
|
156
|
-
.rs-terminal[data-v-
|
|
156
|
+
.rs-terminal[data-v-06f53055] .xterm-scrollable-element > .scrollbar > .slider.active {
|
|
157
157
|
background-color: color-mix(in srgb, var(--rs-primary) 55%, var(--rs-muted));
|
|
158
158
|
}
|
|
159
|
-
.rs-terminal--zebra[data-v-
|
|
160
|
-
.rs-terminal--zebra[data-v-
|
|
161
|
-
.rs-terminal--zebra[data-v-
|
|
159
|
+
.rs-terminal--zebra[data-v-06f53055] .xterm-rows,
|
|
160
|
+
.rs-terminal--zebra[data-v-06f53055] .xterm-rows > div,
|
|
161
|
+
.rs-terminal--zebra[data-v-06f53055] .xterm-row {
|
|
162
162
|
background-color: transparent !important;
|
|
163
163
|
}
|
|
164
|
-
.rs-terminal--zebra[data-v-
|
|
164
|
+
.rs-terminal--zebra[data-v-06f53055] .xterm-scrollable-element {
|
|
165
165
|
background-color: transparent !important;
|
|
166
166
|
background-image: repeating-linear-gradient(
|
|
167
167
|
to bottom,
|
|
@@ -172,12 +172,12 @@
|
|
|
172
172
|
);
|
|
173
173
|
background-attachment: local;
|
|
174
174
|
}
|
|
175
|
-
.rs-terminal--zebra[data-v-
|
|
175
|
+
.rs-terminal--zebra[data-v-06f53055] .xterm-screen {
|
|
176
176
|
background-color: transparent !important;
|
|
177
177
|
}
|
|
178
|
-
.rs-terminal[data-v-
|
|
178
|
+
.rs-terminal[data-v-06f53055] .xterm-fg-257 {
|
|
179
179
|
color: var(--rs-terminal-bg) !important;
|
|
180
180
|
}
|
|
181
|
-
.rs-terminal[data-v-
|
|
181
|
+
.rs-terminal[data-v-06f53055] .xterm-bg-257 {
|
|
182
182
|
background-color: var(--rs-terminal-fg) !important;
|
|
183
183
|
}
|
|
@@ -5,7 +5,7 @@ import { beginClipboardPrefetch, copyTextToClipboard, readClipboardText } from "
|
|
|
5
5
|
import { readTerminalFontFamily, readTerminalFontSizePx, readTerminalFontWeight, readTerminalFontWeightBold } from "../../../theme/css-token.js";
|
|
6
6
|
import { findTerminalHttpLinks, isSafeTerminalLink, mergeTerminalTheme, needsPtyWriteViewportPrep, prepareTerminalForPtyWrite, proposeTerminalGeometry, readXtermCssCellSize, resolveTerminalTheme, subscribeTerminalTheme, terminalLinkCellRange, terminalShortcutLabel } from "./terminal-utils.js";
|
|
7
7
|
import { attachWheelScrollGuard, isAlternateTerminalBuffer } from "./terminal-wheel.js";
|
|
8
|
-
import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, defineComponent, mergeProps, nextTick, normalizeClass, onBeforeUnmount, onMounted, openBlock, ref, renderSlot, toDisplayString, unref, useId, vModelText, watch, withCtx, withDirectives, withModifiers } from "vue";
|
|
8
|
+
import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, defineComponent, mergeProps, nextTick, normalizeClass, onActivated, onBeforeUnmount, onMounted, openBlock, ref, renderSlot, toDisplayString, unref, useId, vModelText, watch, withCtx, withDirectives, withModifiers } from "vue";
|
|
9
9
|
import { FitAddon } from "@xterm/addon-fit";
|
|
10
10
|
import { SearchAddon } from "@xterm/addon-search";
|
|
11
11
|
import { Terminal } from "@xterm/xterm";
|
|
@@ -282,9 +282,19 @@ var RsTerminal_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defin
|
|
|
282
282
|
const textarea = hostEl.value?.querySelector("textarea");
|
|
283
283
|
if (textarea instanceof HTMLTextAreaElement) textarea.setAttribute("aria-label", regionLabel.value);
|
|
284
284
|
}
|
|
285
|
+
function terminalThemesEqual(current, next) {
|
|
286
|
+
const prev = current ?? {};
|
|
287
|
+
const prevKeys = Object.keys(prev);
|
|
288
|
+
const nextKeys = Object.keys(next);
|
|
289
|
+
if (prevKeys.length !== nextKeys.length) return false;
|
|
290
|
+
for (const key of nextKeys) if (prev[key] !== next[key]) return false;
|
|
291
|
+
return true;
|
|
292
|
+
}
|
|
285
293
|
function applyThemeToTerminal() {
|
|
286
294
|
if (!terminal) return;
|
|
287
|
-
|
|
295
|
+
const next = buildXtermTheme();
|
|
296
|
+
if (terminalThemesEqual(terminal.options.theme, next)) return;
|
|
297
|
+
terminal.options.theme = next;
|
|
288
298
|
}
|
|
289
299
|
function syncZebraRowStepFromDom() {
|
|
290
300
|
zebraRowStepPx.value = null;
|
|
@@ -305,8 +315,16 @@ var RsTerminal_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defin
|
|
|
305
315
|
}
|
|
306
316
|
});
|
|
307
317
|
}
|
|
318
|
+
/** 收起期间有人要求重读调色板。回到文档后再采,避免每次激活都重画。 */
|
|
319
|
+
let themeRefreshPending = false;
|
|
308
320
|
function refreshResolvedTheme() {
|
|
309
|
-
|
|
321
|
+
const host = hostEl.value;
|
|
322
|
+
if (host && !host.isConnected) {
|
|
323
|
+
themeRefreshPending = true;
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
themeRefreshPending = false;
|
|
327
|
+
resolvedThemeMode.value = resolveTerminalTheme(props.themeMode, host);
|
|
310
328
|
applyThemeToTerminal();
|
|
311
329
|
}
|
|
312
330
|
function currentGeometry() {
|
|
@@ -772,6 +790,13 @@ var RsTerminal_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defin
|
|
|
772
790
|
if (alive && props.themeMode === "auto") refreshResolvedTheme();
|
|
773
791
|
});
|
|
774
792
|
});
|
|
793
|
+
onActivated(() => {
|
|
794
|
+
if (!alive || !themeRefreshPending) return;
|
|
795
|
+
nextTick(() => {
|
|
796
|
+
if (!alive || !themeRefreshPending) return;
|
|
797
|
+
refreshResolvedTheme();
|
|
798
|
+
});
|
|
799
|
+
});
|
|
775
800
|
onBeforeUnmount(() => {
|
|
776
801
|
alive = false;
|
|
777
802
|
unsubscribeTheme?.();
|
|
@@ -3,6 +3,6 @@ import _plugin_vue_export_helper_default from "../../../_virtual/_plugin-vue_exp
|
|
|
3
3
|
import RsTerminal_vue_vue_type_script_setup_true_lang_default from "./RsTerminal.impl.js";
|
|
4
4
|
|
|
5
5
|
//#region src/components/terminal/src/RsTerminal.vue
|
|
6
|
-
var RsTerminal_default = /*#__PURE__*/ _plugin_vue_export_helper_default(RsTerminal_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-
|
|
6
|
+
var RsTerminal_default = /*#__PURE__*/ _plugin_vue_export_helper_default(RsTerminal_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-06f53055"]]);
|
|
7
7
|
//#endregion
|
|
8
8
|
export { RsTerminal_default as default };
|
|
@@ -123,7 +123,7 @@ function resolveTerminalTheme(mode = "auto", el) {
|
|
|
123
123
|
return (node instanceof HTMLElement ? node.dataset.rsTheme : null) === "dark" ? "dark" : "light";
|
|
124
124
|
}
|
|
125
125
|
function pickThemeSource(mode, el) {
|
|
126
|
-
if (el && resolveTerminalTheme("auto", el) === mode) return el;
|
|
126
|
+
if (el?.isConnected && resolveTerminalTheme("auto", el) === mode) return el;
|
|
127
127
|
return themeSourceElement(mode);
|
|
128
128
|
}
|
|
129
129
|
/** 从 `--rs-terminal-*` 构建 xterm 调色板。传入宿主时读继承到的 token。 */
|