dsh-motion-ui 0.8.3 → 0.8.4
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 +21 -0
- package/README.md +4 -0
- package/VERIFICATION.md +8 -0
- package/client.js +28 -11
- package/lib/build-info.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# DSH Motion UI
|
|
2
2
|
|
|
3
|
+
## 0.8.4 — 2026-10-17
|
|
4
|
+
|
|
5
|
+
### 阅读排版与视觉风格
|
|
6
|
+
|
|
7
|
+
- 修复阅读、极简排版被后续风格规则重新加上根节点阴影的问题,解决明亮扁平和柔光渐彩中文字周围露出偏移底块的现象(Issue #2)。
|
|
8
|
+
- 调整样式覆盖顺序,保持这两种排版的根节点透明、无边框和无额外内边距;深色主题及深色预览遵循相同规则。
|
|
9
|
+
- 保留内部卡片和其他排版应有的阴影、配色与组件样式。
|
|
10
|
+
|
|
11
|
+
### 视频位置、成片与页面响应
|
|
12
|
+
|
|
13
|
+
- 历史视频固定在所属回复内,新一轮回复开始后不会继续堆在聊天列表末尾。
|
|
14
|
+
- 修复多轮视频的定位监听器互相触发、持续搬动播放器并可能卡住页面的问题;正常重排保留播放器实例及播放位置。
|
|
15
|
+
- 拼接成片生成成功后,用成片替代其使用的分镜播放器;独立视频继续保留,源文档和工程文件不删除。
|
|
16
|
+
|
|
17
|
+
### 验证
|
|
18
|
+
|
|
19
|
+
- 149 项单元/集成测试,以及构建、浏览器和播放器回归。
|
|
20
|
+
- 新增 432 个风格、排版、主题和宽度组合检查,覆盖阅读外壳、深色预览、内部卡片及正常排版的阴影保留。
|
|
21
|
+
- 覆盖跨轮视频定位、折叠历史、播放与拖动定位、切换页面,以及多播放器定位循环的复现与防回归。
|
|
22
|
+
|
|
23
|
+
|
|
3
24
|
## 0.8.3 — 2026-10-17
|
|
4
25
|
|
|
5
26
|
### 动画预览控件
|
package/README.md
CHANGED
|
@@ -6,6 +6,10 @@ Interactive, declarative tool views for **DeepSeek Harness Web / Desktop 0.2.0-r
|
|
|
6
6
|
|
|
7
7
|
The plugin adds `render_scene` (short flow/comparison/allocation/budget data), `render_text` (quick native typography), `render_ui` (validated components), `render_canvas` (HTML/SVG), `render_mechanism` (compact assembly/kinematics scenes), and `ui_catalog` (protocol + examples). It saves per-document input state on the Host and sends explicit follow-up requests with the current parameter snapshot.
|
|
8
8
|
|
|
9
|
+
### v0.8.4:阅读阴影与跨轮视频修复
|
|
10
|
+
|
|
11
|
+
修复阅读/极简排版露出偏移阴影,保留内部卡片样式。历史视频留在所属回复,拼接成功后只展示成片及独立视频,并修复多轮播放器互相触发定位导致页面卡住的问题。
|
|
12
|
+
|
|
9
13
|
### v0.8.3:控件可读性与阴影卡片排版
|
|
10
14
|
|
|
11
15
|
改善动画控件的主题对比度,修正画布内边距造成的内部滚动。普通文字卡片保留阴影并随内容自动撑高;SVG 与定位布局增加越界诊断。
|
package/VERIFICATION.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# 验证记录
|
|
2
2
|
|
|
3
|
+
## v0.8.4 发布验证(2026-10-17)
|
|
4
|
+
|
|
5
|
+
- 149 项单元/集成测试、27 组构建与浏览器回归、20 项播放器检查及多轮定位循环对照回归。
|
|
6
|
+
- 阅读外壳检查覆盖 432 个组合:6 种风格、8 种排版、3 种主题状态及 3 档宽度(设备缩放 1.5)。阅读/极简根节点保持透明、无阴影,内部卡片及其他排版保留阴影。
|
|
7
|
+
- 多轮历史视频留在所属回复;完成的拼接成片替代其输入分镜,独立影片保留。覆盖历史折叠、展开、后续回复、播放器实例与播放位置保持、进度定位及导航资源释放。
|
|
8
|
+
- Issue #2 根据原作者补充的原生样式复现资料修正 CSS 规则顺序;HTML/SVG 卡片撑高仍保留独立验证。
|
|
9
|
+
|
|
10
|
+
|
|
3
11
|
## v0.8.3 发布验证(2026-10-17)
|
|
4
12
|
|
|
5
13
|
- 148 项单元/集成测试、26 组构建与浏览器回归、18 项播放器检查。
|
package/client.js
CHANGED
|
@@ -4260,7 +4260,7 @@ function Sandbox({ node, document: doc, state: state2, data, derived, disabled,
|
|
|
4260
4260
|
}
|
|
4261
4261
|
|
|
4262
4262
|
// lib/build-info.js
|
|
4263
|
-
var BUILD_INFO = Object.freeze({ "version": "0.8.
|
|
4263
|
+
var BUILD_INFO = Object.freeze({ "version": "0.8.4", "id": "0.8.4+c46ceb568893", "sourceHash": "c46ceb5688935d2508f4929e89c18c1e468f13cf9179f4183ffd910304d8daa0" });
|
|
4264
4264
|
|
|
4265
4265
|
// lib/refinement.js
|
|
4266
4266
|
var AUDIT_MESSAGES = Object.freeze({ overflow: "\u5185\u5BB9\u8D85\u51FA\u89C6\u53E3\u5BBD\u5EA6", smallText: "\u6587\u5B57\u5B9E\u9645\u663E\u793A\u5C3A\u5BF8\u5C0F\u4E8E 12px", contrast: "\u6587\u5B57\u4E0E\u80CC\u666F\u5BF9\u6BD4\u5EA6\u504F\u4F4E", missingLabel: "\u4EA4\u4E92\u63A7\u4EF6\u7F3A\u5C11\u53EF\u8BBF\u95EE\u540D\u79F0", runtimeError: "\u753B\u5E03\u62A5\u544A\u8FD0\u884C\u5F02\u5E38", clippedText: "\u6587\u5B57\u53EF\u80FD\u88AB\u9690\u85CF\u6216\u88C1\u5207", cardTextOverflow: "\u6587\u5B57\u8D85\u51FA\u5361\u7247\u5185\u5BB9\u8FB9\u754C\uFF1B\u8BF7\u4FDD\u7559\u9634\u5F71\u5E76\u8C03\u6574\u5BB9\u5668\u5C3A\u5BF8\u3001\u5185\u8FB9\u8DDD\u6216\u6587\u5B57\u6392\u7248", bottomWhitespace: "\u5185\u5BB9\u4E0B\u65B9\u5B58\u5728\u660E\u663E\u7A7A\u767D" });
|
|
@@ -5914,7 +5914,7 @@ ${root} [data-motion-component=card],${root} [data-motion-component=stat]{border
|
|
|
5914
5914
|
${root} [data-motion-component=stat] [class*="statValue"]{font-size:var(--du-metric-size);font-weight:var(--du-title-weight);line-height:1.15;letter-spacing:-.7px}
|
|
5915
5915
|
${root} [data-motion-component=card] [class*="cardTitle"]{font-size:20px;font-weight:var(--du-title-weight)}
|
|
5916
5916
|
${root} [data-motion-visual] [class*="block"]{--dsl-g-radius-surface:var(--du-radius-inner);--dsl-g-radius-control:var(--du-action-radius);--dsl-g-font-body:16px;--dsl-g-font-title:18px}
|
|
5917
|
-
|
|
5917
|
+
|
|
5918
5918
|
body[data-ds-dark-theme] ${root},${root}[data-preview-theme=dark]{--du-style-color:color-mix(in srgb,var(--du-style-wash) 58%,var(--du-style-base));--du-line:color-mix(in srgb,var(--du-style-color) 24%,var(--du-bg));--du-soft:color-mix(in srgb,var(--du-style-color) 8%,var(--du-bg))}
|
|
5919
5919
|
body[data-ds-dark-theme] ${root}:not([data-accent]),${root}[data-preview-theme=dark]:not([data-accent]){--du-accent:var(--du-style-color)}
|
|
5920
5920
|
` + grammar("editorial", `
|
|
@@ -5988,6 +5988,9 @@ body[data-ds-dark-theme] &,&[data-preview-theme=dark]{background:var(--du-soft);
|
|
|
5988
5988
|
${root} .dgui-card[data-surface=featured]{border-color:var(--du-accent)}${root} .dgui-card[data-surface=soft]{background:var(--du-soft)}${root} .dgui-card[data-tone]>.dgui-section-title{color:var(--du-tone)}
|
|
5989
5989
|
${root} .dgui-steps li[data-step-status=active]{border-color:var(--du-accent)}${root} .dgui-step-dot .dgui-icon{color:inherit}
|
|
5990
5990
|
@media(max-width:600px){${root}{padding:16px}${root}[data-preset=reading],${root}[data-preset=minimal]{padding:0}${root} .dgui-card,${root} .dgui-metric{padding:16px}${root} .dgui-control{padding:10px}${root}[data-visual-style=editorial] .dgui-card{padding:12px 0}${root}[data-visual-style=expressive] .dgui-metric{padding:10px 0}${root} .dgui-row:has(>.dgui-metric){flex-wrap:wrap}}
|
|
5991
|
+
/* Unframed presets win after every style grammar, including dark preview rules. */
|
|
5992
|
+
${root}[data-preset=reading],${root}[data-preset=minimal]{padding:0;border:0;background:transparent;box-shadow:none}
|
|
5993
|
+
body[data-ds-dark-theme] ${root}[data-preset=reading],body[data-ds-dark-theme] ${root}[data-preset=minimal],${root}[data-preview-theme=dark][data-preset=reading],${root}[data-preview-theme=dark][data-preset=minimal]{background:transparent}
|
|
5991
5994
|
@media(forced-colors:active){${root},${root} .dgui-card,${root} .dgui-metric,${root} .dgui-control,${root} .dgui-chart,${root} .motion-copy-block{background:Canvas;color:CanvasText;box-shadow:none;border-color:CanvasText}${root} .dgui-steps li{background:Canvas}}
|
|
5992
5995
|
`;
|
|
5993
5996
|
|
|
@@ -6574,6 +6577,19 @@ var VISUAL_CSS = `
|
|
|
6574
6577
|
// src/media-history.js
|
|
6575
6578
|
var uuid = /^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/;
|
|
6576
6579
|
var allowedFiles = /* @__PURE__ */ new Set(["video.mp4", "poster.jpg", "source.html", "project.zip"]);
|
|
6580
|
+
function inputAssetIds(value) {
|
|
6581
|
+
const clips = value.kind === "process" ? value.clips ?? value.recipe?.clips : null;
|
|
6582
|
+
if (!Array.isArray(clips)) return [];
|
|
6583
|
+
return [...new Set(clips.slice(0, 256).flatMap((clip) => {
|
|
6584
|
+
if (typeof clip?.path !== "string") return [];
|
|
6585
|
+
const parts = clip.path.replaceAll("\\", "/").split("/"), id2 = parts.at(-2);
|
|
6586
|
+
return parts.at(-1) === "video.mp4" && uuid.test(id2) ? [id2] : [];
|
|
6587
|
+
}))];
|
|
6588
|
+
}
|
|
6589
|
+
function visibleMediaRecords(records2) {
|
|
6590
|
+
const consumed = new Set(records2.flatMap((r) => r.inputAssetIds ?? []));
|
|
6591
|
+
return records2.filter((r) => !consumed.has(r.id));
|
|
6592
|
+
}
|
|
6577
6593
|
function mediaRecord(message) {
|
|
6578
6594
|
if (message?.isError) return null;
|
|
6579
6595
|
for (const part of message?.content ?? []) {
|
|
@@ -6584,7 +6600,7 @@ function mediaRecord(message) {
|
|
|
6584
6600
|
const files = (value.files ?? []).map((f) => typeof f === "string" ? f : f?.name).filter((f) => allowedFiles.has(f));
|
|
6585
6601
|
if (!files.includes("video.mp4")) continue;
|
|
6586
6602
|
const output = value.output ?? {}, positive = (n2) => typeof n2 === "number" && Number.isFinite(n2) && n2 > 0 ? n2 : null;
|
|
6587
|
-
return { id: value.id, sessionId: value.sessionId, kind: value.kind, files: [...new Set(files)], documentId: uuid.test(value.documentId) ? value.documentId : null, documentRevision: Number.isSafeInteger(value.documentRevision) && value.documentRevision >= 0 ? value.documentRevision : null, nodeId: typeof value.nodeId === "string" ? value.nodeId : null, duration: positive(output.duration), width: positive(output.width), height: positive(output.height), hasAudio: Array.isArray(output.audio) ? output.audio.length > 0 : null };
|
|
6603
|
+
return { id: value.id, sessionId: value.sessionId, kind: value.kind, inputAssetIds: inputAssetIds(value), files: [...new Set(files)], documentId: uuid.test(value.documentId) ? value.documentId : null, documentRevision: Number.isSafeInteger(value.documentRevision) && value.documentRevision >= 0 ? value.documentRevision : null, nodeId: typeof value.nodeId === "string" ? value.nodeId : null, duration: positive(output.duration), width: positive(output.width), height: positive(output.height), hasAudio: Array.isArray(output.audio) ? output.audio.length > 0 : null };
|
|
6588
6604
|
} catch {
|
|
6589
6605
|
}
|
|
6590
6606
|
}
|
|
@@ -6865,7 +6881,7 @@ function VideoPlayer({ record }) {
|
|
|
6865
6881
|
function MediaRecords({ records: records2, sessionId }) {
|
|
6866
6882
|
const owner = (0, import_react27.useRef)({});
|
|
6867
6883
|
(0, import_react27.useLayoutEffect)(() => presentMedia(owner.current, sessionId, records2), [records2, sessionId]);
|
|
6868
|
-
return h20(import_react27.default.Fragment, null, records2.filter((r) => r.sessionId === sessionId).map((record) => h20(VideoPlayer, { key: record.id, record })));
|
|
6884
|
+
return h20(import_react27.default.Fragment, null, visibleMediaRecords(records2.filter((r) => r.sessionId === sessionId)).map((record) => h20(VideoPlayer, { key: record.id, record })));
|
|
6869
6885
|
}
|
|
6870
6886
|
var mediaRoots = /* @__PURE__ */ new WeakMap();
|
|
6871
6887
|
var allMediaRoots = /* @__PURE__ */ new Set();
|
|
@@ -6881,12 +6897,15 @@ function disposeSurface(entry) {
|
|
|
6881
6897
|
function disposeMediaSurfaces() {
|
|
6882
6898
|
for (const entry of [...allMediaRoots]) disposeSurface(entry);
|
|
6883
6899
|
}
|
|
6900
|
+
function mediaSeat(anchor, scroll) {
|
|
6901
|
+
let seat = anchor.closest("[data-chat-turn]") ?? anchor;
|
|
6902
|
+
for (let el = anchor.parentElement; el && el !== scroll; el = el.parentElement)
|
|
6903
|
+
if (el.getAttribute("hidden") === "until-found") seat = el;
|
|
6904
|
+
return seat;
|
|
6905
|
+
}
|
|
6884
6906
|
function placeOutsideFold(entry) {
|
|
6885
6907
|
if (!entry.anchor?.isConnected) return;
|
|
6886
|
-
|
|
6887
|
-
for (let el = entry.anchor; el && el !== entry.scroll; el = el.parentElement) if (el.getAttribute("hidden") === "until-found") folded = el;
|
|
6888
|
-
if (!folded) return;
|
|
6889
|
-
const seat = folded.parentElement, parent = seat === entry.scroll ? entry.scroll : seat.parentElement, before = seat === entry.scroll ? null : seat.nextSibling;
|
|
6908
|
+
const seat = mediaSeat(entry.anchor, entry.scroll), parent = seat.parentElement, before = seat.nextSibling;
|
|
6890
6909
|
if (before === entry.host || !before && parent.lastChild === entry.host) return;
|
|
6891
6910
|
try {
|
|
6892
6911
|
if (parent.moveBefore) {
|
|
@@ -6926,9 +6945,7 @@ function MediaNodeView({ node, sessionId }) {
|
|
|
6926
6945
|
return;
|
|
6927
6946
|
}
|
|
6928
6947
|
if (!entry) {
|
|
6929
|
-
|
|
6930
|
-
for (let el = anchor.current; el && el !== scroll; el = el.parentElement) if (el.getAttribute("hidden") === "until-found") folded = el;
|
|
6931
|
-
const seat = folded?.parentElement ?? anchor.current.closest("[data-chat-turn]") ?? anchor.current;
|
|
6948
|
+
const seat = mediaSeat(anchor.current, scroll);
|
|
6932
6949
|
const host = document.createElement("div");
|
|
6933
6950
|
host.dataset.motionMediaTurn = String(state2.turn);
|
|
6934
6951
|
if (seat === scroll) scroll.append(host);
|
package/lib/build-info.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by npm run build.
|
|
2
|
-
export const BUILD_INFO = Object.freeze({"version":"0.8.
|
|
2
|
+
export const BUILD_INFO = Object.freeze({"version":"0.8.4","id":"0.8.4+c46ceb568893","sourceHash":"c46ceb5688935d2508f4929e89c18c1e468f13cf9179f4183ffd910304d8daa0"});
|
package/package.json
CHANGED