@dsh-plugin/dsh-ui-experience 1.0.0-dev.43488936935 → 1.0.0-dev.43491051069

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 (3) hide show
  1. package/README.md +4 -3
  2. package/lib/client.js +28 -21
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -160,12 +160,13 @@ M3 那侧的分离要说明白:Material 3 的 `emphasized` 整体是两段首
160
160
  - `跟随系统`(默认):系统开启「减弱动态效果」时,全部时长压到 1ms、动画只跑一轮。
161
161
  - `始终减弱动效`:无论系统设置,一律压制。
162
162
 
163
- 这一条是整层里唯一使用 `!important` 的地方——它要压掉本层从未写过的声明,逐条改写做不到。压制期间不再改写曲线,因为没有可观察的时长。
163
+ 这一条是整层里唯一使用 `!important` 的地方——它要压掉本层从未写过的声明,逐条改写做不到。进入压制时会先撤掉已改写的曲线并停掉观察者:时长已被压到 1ms,改写既看不见,还会在压制表插入时被自己的观察者重新触发一次扫描。
164
164
 
165
165
  ### 生效范围
166
166
 
167
- - 覆盖页面上的全部样式表,包括其他插件注入的。首次应用时全量扫描,之后用 `MutationObserver` 监视 `head` 与 `body`,新注入的 `<style>` 在下一个微任务内被补上。
168
- - 通过 `document.adoptedStyleSheets` 挂载的构造式样式表不是 DOM 变更,只在首次应用与下一次 `apply` 时被读取。
167
+ - 覆盖页面上的全部样式表,包括其他插件注入的。首次应用时全量扫描,之后用 `MutationObserver` 监视 `head` 与 `body`;只有当新增节点本身是 `<style>` / `<link>`,或子树里含有时才补扫——聊天流式输出每帧都在改 DOM,无条件补扫会把一次性开销变成每帧开销。
168
+ - 通过 `document.adoptedStyleSheets` 挂载的构造式样式表不是 DOM 变更,观察者看不到它,只能在下一次全量扫描(切换曲线族、解除减弱动效、重新应用设置)时被读到。
169
+ - 同理,对已挂载 `<style>` 再改 `textContent`、或在它的 `sheet` 上 `insertRule`/`replaceSync`,都不产生新增节点,也要等下一次全量扫描。DSH 自身与插件加载器都是「建 `<style>` → 设文本 → 挂载」,不受影响。
169
170
  - 跨源样式表读不到 `cssRules`,会在浏览器控制台记录一行并跳过——这类表的规则无法改写,静默跳过会让部分界面停留在原生曲线而无迹可循。(这条诊断走控制台而非 `~/.dsh/ui-experience.log`:后者由宿主半写入,浏览器半够不到文件系统。)
170
171
  - 状态会写在 `<html data-dsh-uix-motion="m3|m3e">` 上,便于区分曲线来源。
171
172
 
package/lib/client.js CHANGED
@@ -195,7 +195,6 @@
195
195
  ];
196
196
  function createMotion() {
197
197
  const patches = /* @__PURE__ */ new Map();
198
- const durationBase = /* @__PURE__ */ new Map();
199
198
  const unreadable = /* @__PURE__ */ new Set();
200
199
  const media = window.matchMedia("(prefers-reduced-motion: reduce)");
201
200
  let settings;
@@ -296,6 +295,7 @@
296
295
  return changed;
297
296
  }
298
297
  function scan() {
298
+ if (wantsReduced()) return;
299
299
  const active = settings;
300
300
  if (active === void 0 || active.mode === "off") return;
301
301
  const sheets = readableSheets();
@@ -318,14 +318,10 @@
318
318
  const root = document.documentElement;
319
319
  const computed = window.getComputedStyle(root);
320
320
  for (const token of DURATION_TOKENS) {
321
- let base = durationBase.get(token);
321
+ const base = parseDurationMs(computed.getPropertyValue(token).trim());
322
322
  if (base === void 0) {
323
- base = parseDurationMs(computed.getPropertyValue(token).trim());
324
- if (base === void 0) {
325
- console.error(`ui-experience: motion cannot read ${token}; durations using it keep their shipped value`);
326
- continue;
327
- }
328
- durationBase.set(token, base);
323
+ console.error(`ui-experience: motion cannot read ${token}; durations using it keep their shipped value`);
324
+ continue;
329
325
  }
330
326
  root.style.setProperty(token, `${Math.round(base * active.durationScale)}ms`);
331
327
  }
@@ -353,13 +349,15 @@
353
349
  function realize() {
354
350
  const active = settings;
355
351
  if (active === void 0 || active.mode === "off") return;
356
- const want = wantsReduced();
357
- setReducedSheet(want);
358
- if (want) {
352
+ if (wantsReduced()) {
353
+ observer?.disconnect();
354
+ observer = void 0;
355
+ setReducedSheet(true);
359
356
  restoreDeclarations();
360
357
  clearDurationTokens();
361
358
  return;
362
359
  }
360
+ setReducedSheet(false);
363
361
  applyDurationTokens();
364
362
  scan();
365
363
  observer ??= observeDocument();
@@ -372,9 +370,22 @@
372
370
  scan();
373
371
  });
374
372
  }
373
+ function bringsStylesheet(node) {
374
+ if (node === void 0) return false;
375
+ const name = node.nodeName?.toUpperCase();
376
+ if (name === "STYLE" || name === "LINK") return true;
377
+ return (node.querySelectorAll?.("style,link")?.length ?? 0) > 0;
378
+ }
375
379
  function observeDocument() {
376
- const instance = new MutationObserver(() => {
377
- refresh();
380
+ const instance = new MutationObserver((records) => {
381
+ for (const record of records) {
382
+ for (let index = 0; index < record.addedNodes.length; index += 1) {
383
+ if (bringsStylesheet(record.addedNodes[index])) {
384
+ refresh();
385
+ return;
386
+ }
387
+ }
388
+ }
378
389
  });
379
390
  instance.observe(document.head, { childList: true, subtree: true });
380
391
  instance.observe(document.body, { childList: true, subtree: true });
@@ -422,11 +433,7 @@
422
433
  document.documentElement.setAttribute(MOTION_ATTRIBUTE, next.mode);
423
434
  realize();
424
435
  },
425
- refresh,
426
- restore,
427
- dispose() {
428
- restore();
429
- }
436
+ restore
430
437
  };
431
438
  }
432
439
 
@@ -540,9 +547,9 @@
540
547
  report(media.matches);
541
548
  };
542
549
  report(media.matches);
543
- media.addEventListener?.("change", listener);
550
+ media.addEventListener("change", listener);
544
551
  return () => {
545
- media.removeEventListener?.("change", listener);
552
+ media.removeEventListener("change", listener);
546
553
  };
547
554
  }
548
555
  var SOURCE = "@dsh-plugin/dsh-ui-experience";
@@ -1233,7 +1240,7 @@
1233
1240
  return () => {
1234
1241
  disposed = true;
1235
1242
  teardown();
1236
- motion.dispose();
1243
+ motion.restore();
1237
1244
  };
1238
1245
  }, "ui-experience: page-level layers");
1239
1246
  void poll();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsh-plugin/dsh-ui-experience",
3
- "version": "1.0.0-dev.43488936935",
3
+ "version": "1.0.0-dev.43491051069",
4
4
  "type": "module",
5
5
  "description": "UI experience enhancements for DeepSeek Harness: follow the system matugen Material You palette as the interface theme, and rewrite interface motion onto Material 3 / Material 3 Expressive curves.",
6
6
  "license": "MIT",