@mzzsfy/dsh-session-manager 0.9.1 → 0.9.2
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/package.json +1 -1
- package/src/client.js +10 -4
- package/test/client-row-actions.test.mjs +46 -0
package/package.json
CHANGED
package/src/client.js
CHANGED
|
@@ -55,8 +55,10 @@ const CSS = [
|
|
|
55
55
|
'.sm-row__path { grid-column:2 / -1; font:12px/16px var(--ds-font-family-code, monospace); color:var(--dsw-alias-label-caption);',
|
|
56
56
|
' white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }',
|
|
57
57
|
'.sm-deleted { display:flex; flex-direction:column; gap:8px; min-width:0; }',
|
|
58
|
-
|
|
59
|
-
'.sm-
|
|
58
|
+
// 归档行:恢复常显;已删除区保持整组操作悬停显现(删除按钮显隐规则在 .sm-btn 块后)
|
|
59
|
+
'.sm-row__actions { display:flex; gap:2px; justify-content:flex-end; }',
|
|
60
|
+
'.sm-deleted .sm-row__actions { opacity:0; transition:opacity 0.12s ease; }',
|
|
61
|
+
'.sm-deleted .sm-row:hover .sm-row__actions, .sm-deleted .sm-row:focus-within .sm-row__actions { opacity:1; }',
|
|
60
62
|
'.sm-btn { border:0; background:transparent; cursor:pointer; padding:2px 8px; border-radius:6px;',
|
|
61
63
|
' font:var(--dsw-font-xxs-strong-12); color:var(--dsw-alias-label-tertiary); }',
|
|
62
64
|
'.sm-btn:hover { background:var(--dsw-alias-interactive-bg-hover); color:var(--dsw-alias-label-primary); }',
|
|
@@ -67,6 +69,10 @@ const CSS = [
|
|
|
67
69
|
'.sm-btn:disabled { opacity:.45; cursor:default; background:transparent; color:var(--dsw-alias-label-tertiary); }',
|
|
68
70
|
'.sm-btn--confirm:disabled { color:var(--dsw-alias-state-error-primary); }',
|
|
69
71
|
'.sm-btn:focus-visible { outline:2px solid var(--dsw-alias-state-business-primary); outline-offset:1px; }',
|
|
72
|
+
// 删除按钮显隐:隐藏规则必须位于 .sm-btn:disabled 之后——同特异度后出者胜,
|
|
73
|
+
// 否则 busy 禁用态被禁用半透明规则压过而幽灵显形;显现规则特异度更高,不受顺序约束
|
|
74
|
+
'.sm-btn--danger, .sm-btn--danger:disabled { opacity:0; transition:opacity 0.12s ease; }',
|
|
75
|
+
'.sm-row:hover .sm-btn--danger, .sm-row:focus-within .sm-btn--danger { opacity:1; }',
|
|
70
76
|
// 删除确认弹窗:遮罩 + 居中卡片;高 z-index 压过设置面板层,点击遮罩不关闭(强制显式选择)
|
|
71
77
|
'.sm-dialog { position:fixed; inset:0; z-index:10000; display:flex; align-items:center; justify-content:center;',
|
|
72
78
|
' background:rgba(0,0,0,.45); }',
|
|
@@ -108,7 +114,7 @@ const CSS = [
|
|
|
108
114
|
'.sm-more:hover { background:var(--dsw-alias-interactive-bg-hover); color:var(--dsw-alias-label-primary); }',
|
|
109
115
|
'.sm-more:focus-visible { outline:2px solid var(--dsw-alias-state-business-primary); outline-offset:-1px; }',
|
|
110
116
|
'@media (prefers-reduced-motion: reduce) { .sm-group__chev { transition:none; } }',
|
|
111
|
-
'@media (prefers-reduced-motion: reduce) { .sm-row__actions { transition:none; } }',
|
|
117
|
+
'@media (prefers-reduced-motion: reduce) { .sm-btn--danger, .sm-deleted .sm-row__actions { transition:none; } }',
|
|
112
118
|
// 自动归档配置行:数值输入内联呈现,窄面板可换行
|
|
113
119
|
'.sm-cfg { display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin-top:10px;',
|
|
114
120
|
' font:var(--dsw-font-xxs-12, 12px/18px sans-serif); color:var(--dsw-alias-label-caption, rgba(127,127,127,.9)); }',
|
|
@@ -340,8 +346,8 @@ function ArchiveRow(props) {
|
|
|
340
346
|
h('button', { key: 'cancel', className: 'sm-btn', disabled: busy, onClick: props.onDisarm }, '取消'),
|
|
341
347
|
]
|
|
342
348
|
: [
|
|
343
|
-
h('button', { key: 'restore', className: 'sm-btn sm-btn--restore', disabled: busy, onClick: props.onUnarchive }, '恢复'),
|
|
344
349
|
h('button', { key: 'delete', className: 'sm-btn sm-btn--danger', disabled: busy, title: DELETE_BUTTON_TITLE, onClick: props.onDelete }, '删除'),
|
|
350
|
+
h('button', { key: 'restore', className: 'sm-btn sm-btn--restore', disabled: busy, onClick: props.onUnarchive }, '恢复'),
|
|
345
351
|
]
|
|
346
352
|
return h('div', {
|
|
347
353
|
className: 'sm-row' + (armed ? ' sm-row--armed' : '') + (busy ? ' sm-row--busy' : ''),
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// 归档行操作按钮显隐与顺序契约:恢复常显,删除跟随行悬停,删除在恢复之前。
|
|
2
|
+
// 文案与行为同源锁定,防重构把恢复键重新藏进行悬停。
|
|
3
|
+
|
|
4
|
+
import { test } from 'node:test'
|
|
5
|
+
import assert from 'node:assert/strict'
|
|
6
|
+
import { readFileSync } from 'node:fs'
|
|
7
|
+
import { fileURLToPath } from 'node:url'
|
|
8
|
+
|
|
9
|
+
const CLIENT_SRC = readFileSync(fileURLToPath(new URL('../src/client.js', import.meta.url)), 'utf8')
|
|
10
|
+
|
|
11
|
+
// Given 非悬停归档行, When 渲染, Then 恢复常显、删除隐藏;行悬停或键盘聚焦时删除显现
|
|
12
|
+
test('源码契约:恢复常显,删除跟随行悬停与聚焦显现', () => {
|
|
13
|
+
// 操作容器基础常显:不带整体 opacity:0(整体隐藏会让子级无法单独显形)
|
|
14
|
+
assert.ok(CLIENT_SRC.includes('.sm-row__actions { display:flex; gap:2px; justify-content:flex-end; }'),
|
|
15
|
+
'操作容器未改为常显基础形态')
|
|
16
|
+
// 删除按钮默认隐藏;隐藏规则须位于 .sm-btn:disabled 之后(同特异度后出者胜),
|
|
17
|
+
// 否则 busy 禁用态被禁用半透明规则压过而幽灵显形
|
|
18
|
+
assert.ok(/\.sm-btn--danger[^{]*\{ opacity:0/.test(CLIENT_SRC), '删除按钮未默认隐藏')
|
|
19
|
+
// 锚点取规则体而非选择器名,对提及选择器的注释文本免疫
|
|
20
|
+
assert.ok(CLIENT_SRC.indexOf('.sm-btn--danger:disabled { opacity:0') > CLIENT_SRC.indexOf('.sm-btn:disabled { opacity'),
|
|
21
|
+
'删除隐藏规则未置于 .sm-btn:disabled 之后,禁用态会被半透明压过')
|
|
22
|
+
// 行悬停与键盘聚焦显现删除按钮
|
|
23
|
+
assert.ok(CLIENT_SRC.includes('.sm-row:hover .sm-btn--danger'), '行悬停未显现删除按钮')
|
|
24
|
+
assert.ok(CLIENT_SRC.includes('.sm-row:focus-within .sm-btn--danger'), '键盘聚焦未显现删除按钮')
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
// Given 归档行动作渲染, When 构建按钮序列, Then 删除在恢复之前(换位后恢复贴最右)
|
|
28
|
+
test('源码契约:删除按钮先于恢复按钮', () => {
|
|
29
|
+
// 断言限定在 ArchiveRow 片段内,避免文件级首次命中漂移到其他行的同名按钮
|
|
30
|
+
const rowSrc = CLIENT_SRC.slice(CLIENT_SRC.indexOf('function ArchiveRow'), CLIENT_SRC.indexOf('function DeleteDialog'))
|
|
31
|
+
const dangerAt = rowSrc.indexOf("className: 'sm-btn sm-btn--danger'")
|
|
32
|
+
const restoreAt = rowSrc.indexOf("className: 'sm-btn sm-btn--restore'")
|
|
33
|
+
assert.ok(dangerAt >= 0 && restoreAt >= 0, '缺删除或恢复按钮')
|
|
34
|
+
assert.ok(dangerAt < restoreAt, '删除按钮未换位到恢复按钮之前')
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
// Given 已删除区与减弱动效环境, When 渲染, Then 已删除行操作保持悬停显现且动效可关
|
|
38
|
+
test('源码契约:已删除区保持悬停显现且减弱动效覆盖新选择器', () => {
|
|
39
|
+
// 已删除区行操作悬停显现(作用域规则,不回归容器整体隐藏)
|
|
40
|
+
assert.ok(CLIENT_SRC.includes('.sm-deleted .sm-row__actions { opacity:0'), '已删除区未保持悬停显现')
|
|
41
|
+
assert.ok(CLIENT_SRC.includes('.sm-deleted .sm-row:hover .sm-row__actions'), '已删除区缺行悬停显现规则')
|
|
42
|
+
assert.ok(CLIENT_SRC.includes('.sm-deleted .sm-row:focus-within .sm-row__actions'), '已删除区缺键盘聚焦显现规则')
|
|
43
|
+
// 减弱动效覆盖删除按钮与已删除区两处过渡
|
|
44
|
+
assert.ok(/prefers-reduced-motion: reduce.*\{ \.sm-btn--danger, \.sm-deleted \.sm-row__actions \{ transition:none/.test(CLIENT_SRC),
|
|
45
|
+
'减弱动效未覆盖删除按钮与已删除区过渡')
|
|
46
|
+
})
|