dsh-m 0.9.54 → 0.9.55

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 CHANGED
@@ -8,6 +8,12 @@ The full release history of dsh-m, maintained bilingually: **Chinese first, Engl
8
8
 
9
9
  ## 中文
10
10
 
11
+ ### 0.9.55 变更:ZoneChips 折叠/展开切换钮内联化(对齐 dsh-market 参考设计)+ overlay 叠涂 scrim 强化对比度
12
+
13
+ - **切换钮内联化(主人提出,dsh-market v1.66.11 参考设计)**:`+N` 从右侧 overlay 组改为**绝对定位内联**——钉在「末可见分类 chip 右侧 +6px」(即末可见行剩余空位),与展开态 `⌃`(列表末尾 in-flow)构成统一位置语义「紧跟当前列表末尾」,只翻方向不挪位;窄宽度放不下时贴内容右缘收口(不侵入筛选槽)。gutter 随 `+N` 移出由 132px 瘦身至 96px(仅承载钉住筛选),同宽度可多显示约 1 颗分类。overlay 组内 `+N` 移除后仅剩钉住筛选,第④类碰撞(R2-N1)自然消解。
14
+ - **overlay 叠涂 scrim(主人提出:浅色主题对比度偏低)**:根因是 `--dsw-alias-bg-base` token 本身 0.55 半透明;overlay 底衬改同 token **三层叠涂**(background-color + 双 linear-gradient 层),有效不透明度 ≈ 1−0.45³ ≈ 91%,深浅主题自适应(深色 rgba(12,26,38,·) / 浅色 rgba(247,250,252,·) 均显著强化),不引入硬编码色值。
15
+ - **测试**:全量 1221 例零失败、typecheck 零错误;无头探针实证:折叠态 `+N` 左缘 = 末可见 chip 右缘 +6px 同行对齐、scrim 双梯度、筛选单钮零碰撞、收起/展开往复位置稳定、Q1 回归(长文案 hidden>0);真机截图见发版记录。
16
+
11
17
  ### 0.9.54 变更:评审修复随版(ZoneChips 重测盲区/⌃ 弹回/overlay 居中)+ dsh-skip-browser-auth 收录文案对账
12
18
 
13
19
  - **ZoneChips 三处评审修复(执行结果评审 R1,`b2aab5f`)**:① 测量 deps 以 `chips` 引用替代 `chips.length` 并叠加 `active`——同长度内容变化(计数刷新/激活加粗变宽)确定性重测,消除 RO 因 max-height 钳制失聪导致的陈旧 geom 盲区(被裁 chip 保持可聚焦/激活分类越界不自动展开的失效窗口,D4 违背态);② `⌃` 手动收起无条件记录 autoRef——手动收起全路径被尊重,消除展开态 geom 陈旧时收起被决策 effect 弹回的边缘漂移;③ overlay 组按 rowHeight 垂直居中(bottom 补偿偏移)。
@@ -406,6 +412,12 @@ The full release history of dsh-m, maintained bilingually: **Chinese first, Engl
406
412
 
407
413
  ## English
408
414
 
415
+ ### Changed in 0.9.55 — ZoneChips expand/collapse toggle inline (aligned with the dsh-market reference design) + overlay stacked scrim for contrast
416
+
417
+ - **Inline toggle (owner-requested, reference: dsh-market v1.66.11)**: `+N` moves out of the right-side overlay group into an **absolutely-positioned inline slot** pinned at "last visible category chip's right edge + 6px" (the leftover of the last visible row), sharing one position semantic with the expanded `⌃` (in-flow at list end): "hug the current end of the list", flipping direction without relocating; when the leftover is too narrow it clamps to the content right edge without entering the filter gutter. The gutter slims from 132px to 96px (hosting only the pinned filter), showing ~1 more category per width. With `+N` removed, the overlay group hosts only the pinned filter and the R2-N1 4th collision class dissolves naturally.
418
+ - **Overlay stacked scrim (owner-requested: low contrast in light theme)**: root cause is that the `--dsw-alias-bg-base` token itself is 0.55-translucent; the overlay scrim now paints the same token in a **three-layer stack** (background-color + two linear-gradient layers), effective opacity ≈ 1−0.45³ ≈ 91%, theme-adaptive (dark rgba(12,26,38,·) / light rgba(247,250,252,·) both significantly strengthened) with zero hard-coded colors.
419
+ - **Tests**: full suite 1221 cases zero failures, typecheck clean; headless probe verified collapsed-state `+N` left edge = last visible chip right edge + 6px on the same row, double scrim gradients, single-button zero-collision filter, stable toggle position across collapse/expand cycles, and the Q1 regression (long labels: hidden > 0); real-panel screenshots in the release record.
420
+
409
421
  ### Changed in 0.9.54 — review fixes ship (ZoneChips stale-geom / ⌃ bounce / overlay centering) + dsh-skip-browser-auth catalog copy reconciliation
410
422
 
411
423
  - **ZoneChips review fixes (execution-review R1, `b2aab5f`)**: ① measure deps use the `chips` reference instead of `chips.length` plus `active` — same-length content changes (count refresh / active bold reflow) now deterministically re-measure, closing the stale-geom blind window where RO is deafened by the max-height clamp (clipped-but-focusable chips / missed auto-expand, a D4 violation); ② manual `⌃` collapse unconditionally records autoRef — manual collapse is respected on every path, removing the edge drift where a stale-geom decision effect bounced the collapse back; ③ the overlay group is vertically centered per measured row-height (compensated bottom offset).
package/lib/client.js CHANGED
@@ -2188,8 +2188,9 @@ var CSS = `
2188
2188
  .dshm-input:focus{border-color:var(--dsw-alias-interactive-bg-selected,#4f46e5)}
2189
2189
  .dshm-chips{display:flex;flex-wrap:wrap;gap:6px;position:relative}
2190
2190
  .dshm-chips-clip{overflow:hidden}
2191
- .dshm-chips-gutter{padding-right:var(--dshm-clip-gutter,132px)}
2192
- .dsvm-chipmore{position:absolute;right:8px;bottom:8px;display:flex;align-items:center;gap:8px;min-height:28px;background:var(--dsw-alias-bg-base,#fff);border:1px solid var(--dsw-alias-border-l1,rgba(127,127,127,.18));border-radius:999px;padding:2px 8px;box-sizing:border-box}
2191
+ .dshm-chips-gutter{padding-right:var(--dshm-clip-gutter,96px)}
2192
+ .dsvm-chipmore{position:absolute;right:8px;display:flex;align-items:center;gap:8px;min-height:28px;background-color:var(--dsw-alias-bg-base,#fff);background-image:linear-gradient(var(--dsw-alias-bg-base,#fff),var(--dsw-alias-bg-base,#fff)),linear-gradient(var(--dsw-alias-bg-base,#fff),var(--dsw-alias-bg-base,#fff));border:1px solid var(--dsw-alias-border-l1,rgba(127,127,127,.18));border-radius:999px;padding:2px 8px;box-sizing:border-box}
2193
+ .dsvm-chipmore-plus{position:absolute;z-index:2;background-color:var(--dsw-alias-bg-base,#fff);background-image:linear-gradient(var(--dsw-alias-bg-base,#fff),var(--dsw-alias-bg-base,#fff)),linear-gradient(var(--dsw-alias-bg-base,#fff),var(--dsw-alias-bg-base,#fff))}
2193
2194
  .dsvm-searchrow{display:flex;align-items:center;gap:8px}
2194
2195
  .dsvm-searchrow .dshm-search{flex:1;display:flex}
2195
2196
  .dshm-search{position:relative}
@@ -2731,8 +2732,30 @@ function ZoneChips({ zone, counts, labels, active, onPick, trailing, wrapTitle }
2731
2732
  if (!rh && k.offsetHeight) rh = k.offsetHeight;
2732
2733
  }
2733
2734
  if (!tops.length) return;
2734
- const next = { tops, clipTop: clipTopOf2(tops, maxRows), hiddenCount: countBeyondRows2(tops.slice(1), maxRows) };
2735
- setGeom((prev) => prev && prev.tops.length === next.tops.length && prev.clipTop === next.clipTop && prev.hiddenCount === next.hiddenCount ? prev : next);
2735
+ const clipTop2 = clipTopOf2(tops, maxRows);
2736
+ let lastVisRight = 0;
2737
+ let lastVisTop = 0;
2738
+ let idx = -1;
2739
+ for (const k of el.children) {
2740
+ if (!(k instanceof HTMLElement) || k.getAttribute("data-chip") !== "1") continue;
2741
+ idx += 1;
2742
+ if (idx === 0) continue;
2743
+ if (k.offsetTop < clipTop2) {
2744
+ lastVisRight = k.offsetLeft + k.offsetWidth;
2745
+ lastVisTop = k.offsetTop;
2746
+ }
2747
+ }
2748
+ const cs = getComputedStyle(el);
2749
+ const contentW = el.clientWidth - (parseFloat(cs.paddingRight) || 0);
2750
+ const plusLeft = Math.max(0, Math.min(lastVisRight + 6, contentW - 48));
2751
+ const next = {
2752
+ tops,
2753
+ clipTop: clipTop2,
2754
+ hiddenCount: countBeyondRows2(tops.slice(1), maxRows),
2755
+ plusLeft,
2756
+ plusTop: lastVisTop
2757
+ };
2758
+ setGeom((prev) => prev && prev.tops.length === next.tops.length && prev.clipTop === next.clipTop && prev.hiddenCount === next.hiddenCount && prev.plusLeft === next.plusLeft && prev.plusTop === next.plusTop ? prev : next);
2736
2759
  setRowHeight((prev) => Math.abs(prev - rh) <= 0.5 ? prev : rh);
2737
2760
  }, [expanded, maxRows]);
2738
2761
  useEffect(() => {
@@ -2783,7 +2806,7 @@ function ZoneChips({ zone, counts, labels, active, onPick, trailing, wrapTitle }
2783
2806
  return () => io.disconnect();
2784
2807
  }, []);
2785
2808
  const clip = !expanded;
2786
- const overlay = clip && (trailing != null || geom && geom.hiddenCount > 0);
2809
+ const filterPinned = clip && trailing != null;
2787
2810
  const clipTop = geom ? geom.clipTop : Infinity;
2788
2811
  const hiddenCount = geom ? geom.hiddenCount : 0;
2789
2812
  const btn = (c, i) => {
@@ -2818,12 +2841,21 @@ function ZoneChips({ zone, counts, labels, active, onPick, trailing, wrapTitle }
2818
2841
  "div",
2819
2842
  {
2820
2843
  ref: wrapRef,
2821
- className: `dshm-chips${clip ? " dshm-chips-clip" : ""}${clip && overlay ? " dshm-chips-gutter" : ""}`,
2844
+ className: `dshm-chips${clip ? " dshm-chips-clip" : ""}${filterPinned ? " dshm-chips-gutter" : ""}`,
2822
2845
  title: wrapTitle || void 0,
2823
2846
  style: { maxHeight: clip ? `${maxH}px` : "none" }
2824
2847
  },
2825
2848
  h("button", { "data-chip": "1", className: `dshm-chip${active == null ? " on" : ""}`, onClick: () => onPick(null) }, lookup("cat.all")),
2826
2849
  ...chips.map((c, i) => btn(c, i)),
2850
+ // 折叠态 +N(0.9.55 对齐 dsh-market 参考设计):绝对定位内联钉在「末可见分类 chip 右侧 +6px」,
2851
+ // 与展开态 ⌃(列表末尾 in-flow)构成同一位置语义——「紧跟当前列表末尾」,只翻方向不挪位。
2852
+ // 不带 data-chip(不参与行分组测量);位于可见行区内,不受 overflow 裁剪。
2853
+ clip && geom && hiddenCount > 0 ? h("button", {
2854
+ key: "more",
2855
+ className: "dshm-chip dsvm-chipmore-plus",
2856
+ style: { left: `${geom.plusLeft}px`, top: `${geom.plusTop}px` },
2857
+ onClick: () => setExpanded(true)
2858
+ }, `+${hiddenCount}`) : null,
2827
2859
  expanded ? [
2828
2860
  h("button", {
2829
2861
  key: "collapse",
@@ -2839,18 +2871,14 @@ function ZoneChips({ zone, counts, labels, active, onPick, trailing, wrapTitle }
2839
2871
  trailing || null
2840
2872
  ] : null
2841
2873
  ),
2842
- // 折叠态右侧 overlay 组(D5/D6):[筛选][+N] 水平并排、钉末可见行右端;gutter 保证与 chip 零相交。
2843
- // 吸顶单行态末可见行=第 1 行,两按钮仍同行并排(第④类碰撞结构性消除,R2-N1)。
2844
- // ⚠️ 展开态不用 overlay(⌃/筛选 in-flow,与现状一致);弹层锚点 .dsvm-filterwrap 随组定位。
2845
- clip && overlay ? h(
2874
+ // 折叠态钉住的筛选触发器(gutter 几何保证与 chip 零相交;叠涂 scrim 强化浅色对比度,评审 R1 后主人优化②)
2875
+ filterPinned ? h(
2846
2876
  "div",
2847
2877
  {
2848
2878
  className: "dsvm-chipmore",
2849
- // 评审 R1-Q4:按行高垂直居中于末可见行(28px 组盒在 22px 行高上居中 → bottom 补偿 -3px)
2850
2879
  style: { bottom: `${8 + ((rowHeight || 22) - 28) / 2}px` }
2851
2880
  },
2852
- trailing || null,
2853
- hiddenCount > 0 ? h("button", { className: "dshm-chip", onClick: () => setExpanded(true) }, `+${hiddenCount}`) : null
2881
+ trailing || null
2854
2882
  ) : null
2855
2883
  )
2856
2884
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-m",
3
- "version": "0.9.54",
3
+ "version": "0.9.55",
4
4
  "description": "可自定义收录清单的 DSH 插件市场:收录、安装、卸载、升级一站完成,附 agent 工具与 dshm CLI。",
5
5
  "license": "MIT",
6
6
  "type": "module",