@linxin666/dsh-client-ui-skin-center 0.4.6 → 0.4.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/README.md CHANGED
@@ -5,7 +5,7 @@ English | [中文](README.zh.md)
5
5
  <p align="center">
6
6
  <img src="https://img.shields.io/npm/v/@linxin666/dsh-client-ui-skin-center?style=flat-square" alt="Version">
7
7
  &nbsp;
8
- <img src="https://img.shields.io/badge/DSH-%3E%3D0.2.0--rc.2-4c6ef5?style=flat-square&amp;labelColor=454a54" alt="DSH">
8
+ <img src="https://img.shields.io/badge/DSH-%3E%3D0.2.1--rc.2-4c6ef5?style=flat-square&amp;labelColor=454a54" alt="DSH">
9
9
  &nbsp;
10
10
  <img src="https://img.shields.io/badge/license-Apache--2.0-blue?style=flat-square" alt="License">
11
11
  </p>
package/README.zh.md CHANGED
@@ -5,7 +5,7 @@
5
5
  <p align="center">
6
6
  <img src="https://img.shields.io/npm/v/@linxin666/dsh-client-ui-skin-center?style=flat-square" alt="Version">
7
7
  &nbsp;
8
- <img src="https://img.shields.io/badge/DSH-%3E%3D0.2.0--rc.2-4c6ef5?style=flat-square&amp;labelColor=454a54" alt="DSH">
8
+ <img src="https://img.shields.io/badge/DSH-%3E%3D0.2.1--rc.2-4c6ef5?style=flat-square&amp;labelColor=454a54" alt="DSH">
9
9
  &nbsp;
10
10
  <img src="https://img.shields.io/badge/license-Apache--2.0-blue?style=flat-square" alt="License">
11
11
  </p>
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "$schema": "https://schemas.linxin666.org/dsh-skin/official-tokens-v1.json",
3
3
  "contractVersion": 1,
4
- "source": "official surfaces: @deepseek-ai/dsh-client-ui-theme@0.1.7-rc.1 lib + @deepseek-ai/dsh-web-frontend@0.1.7-rc.1 dist/assets",
4
+ "source": "official surfaces: @deepseek-ai/dsh-client-ui-theme@0.2.1-rc.2 lib + @deepseek-ai/dsh-web-frontend@0.2.1-rc.2 dist/assets",
5
5
  "excludedPrefix": "--dsw-static-",
6
- "count": 299,
6
+ "count": 329,
7
7
  "tokens": [
8
8
  "--dsw-alias-bg-base",
9
9
  "--dsw-alias-bg-document-preview",
10
+ "--dsw-alias-bg-document-selection",
10
11
  "--dsw-alias-bg-layer-1",
11
12
  "--dsw-alias-bg-layer-2",
12
13
  "--dsw-alias-bg-layer-3",
@@ -60,6 +61,8 @@
60
61
  "--dsw-alias-interactive-bg-hover-danger",
61
62
  "--dsw-alias-interactive-bg-hover-solid",
62
63
  "--dsw-alias-label-caption",
64
+ "--dsw-alias-label-deep-diving",
65
+ "--dsw-alias-label-deep-diving-shimmer",
63
66
  "--dsw-alias-label-dimmed",
64
67
  "--dsw-alias-label-document-preview",
65
68
  "--dsw-alias-label-error",
@@ -69,6 +72,7 @@
69
72
  "--dsw-alias-label-primary-foreground",
70
73
  "--dsw-alias-label-primary-inverted",
71
74
  "--dsw-alias-label-secondary",
75
+ "--dsw-alias-label-shimmer",
72
76
  "--dsw-alias-label-tertiary",
73
77
  "--dsw-alias-link",
74
78
  "--dsw-alias-markdown-citation",
@@ -79,10 +83,18 @@
79
83
  "--dsw-alias-markdown-inline-code",
80
84
  "--dsw-alias-markdown-placeholder",
81
85
  "--dsw-alias-markdown-tag",
86
+ "--dsw-alias-menu-group-header-fill",
87
+ "--dsw-alias-menu-icon",
88
+ "--dsw-alias-onboarding-accent",
89
+ "--dsw-alias-onboarding-card-fill",
90
+ "--dsw-alias-onboarding-checkbox-border",
91
+ "--dsw-alias-onboarding-secondary-fill",
82
92
  "--dsw-alias-scrollbar-bg-l1",
83
93
  "--dsw-alias-scrollbar-bg-l2",
84
94
  "--dsw-alias-scrollbar-hover-l1",
85
95
  "--dsw-alias-scrollbar-hover-l2",
96
+ "--dsw-alias-settings-card-fill",
97
+ "--dsw-alias-settings-card-stroke",
86
98
  "--dsw-alias-state-business-primary",
87
99
  "--dsw-alias-state-business-tertiary",
88
100
  "--dsw-alias-state-error-primary",
@@ -95,14 +107,21 @@
95
107
  "--dsw-alias-state-warn-primary",
96
108
  "--dsw-alias-state-warn-secondary",
97
109
  "--dsw-alias-state-warn-tertiary",
110
+ "--dsw-alias-switch-thumb",
98
111
  "--dsw-alias-toast-bg",
112
+ "--dsw-alias-toast-label",
99
113
  "--dsw-alias-tooltip-bg",
114
+ "--dsw-alias-tooltip-key-bg",
115
+ "--dsw-alias-turn-trigger-bg",
116
+ "--dsw-alias-turn-trigger-bg-hover",
100
117
  "--dsw-corner-shape",
101
118
  "--dsw-elevation-panel",
102
119
  "--dsw-elevation-prominent",
103
120
  "--dsw-elevation-soft",
104
121
  "--dsw-elevation-stroke",
105
122
  "--dsw-elevation-stroke-color",
123
+ "--dsw-focus-ring-color",
124
+ "--dsw-focus-ring-width",
106
125
  "--dsw-font-base-16",
107
126
  "--dsw-font-base-16-font-family",
108
127
  "--dsw-font-base-16-font-size",
@@ -116,6 +135,7 @@
116
135
  "--dsw-font-base-strong-16-font-weight",
117
136
  "--dsw-font-base-strong-16-line-height",
118
137
  "--dsw-font-family",
138
+ "--dsw-font-family-brand",
119
139
  "--dsw-font-l-20",
120
140
  "--dsw-font-l-20-font-family",
121
141
  "--dsw-font-l-20-font-size",
@@ -284,11 +304,21 @@
284
304
  "--dsw-font-xxxs-strong-11-font-style",
285
305
  "--dsw-font-xxxs-strong-11-font-weight",
286
306
  "--dsw-font-xxxs-strong-11-line-height",
307
+ "--dsw-gradient-onboarding-blue-stops",
308
+ "--dsw-gradient-onboarding-cyan-stops",
309
+ "--dsw-gradient-onboarding-violet-stops",
287
310
  "--dsw-hovercard-bg",
288
311
  "--dsw-linear-gradient-think",
289
312
  "--dsw-linear-think-select",
290
313
  "--dsw-mask-blur",
291
314
  "--dsw-menu-backdrop-filter",
315
+ "--dsw-menu-surface-fill",
316
+ "--dsw-radius-lg",
317
+ "--dsw-radius-md",
318
+ "--dsw-radius-panel",
319
+ "--dsw-radius-sm",
320
+ "--dsw-radius-xl",
321
+ "--dsw-radius-xs",
292
322
  "--dsw-shadow-lv1",
293
323
  "--dsw-shadow-lv1-blur",
294
324
  "--dsw-shadow-lv2",
@@ -71,7 +71,7 @@
71
71
  皮肤中心不写委托插件的任何属性,委托插件不写 `data-dsh-skin`,双方都无法把
72
72
  对方卡死。委托皮肤的选择会照常持久化、开机采纳与试穿还原;让路暂停的是
73
73
  视觉,不是插件的设置页与偏好。
74
- ## part 组(81 行,含各 owner 行)
74
+ ## part 组(78 行,含各 owner 行)
75
75
 
76
76
  shell 区域(owner: shell):
77
77
 
@@ -154,14 +154,6 @@ family / 插件区域:
154
154
  | `foot-card-main` / `foot-card-toggle` | usage | 速览卡主体按钮(整卡点击打开设置分区)/ 右上角收起-展开切换钮;foot-card 内裸值 button |
155
155
  | `foot-card-strip` | usage | 折叠态单行摘要条(标签 + 头条值);折叠时 foot-card-main 内裸值 span |
156
156
  | `foot-card-usage` / `foot-card-balances` | usage | 展开态的 tokens/调用行 / 余额行;foot-card 内裸值 span |
157
- | `panel` | model-capabilities | 提供方卡片能力扩展区根;`[data-dsh-plugin="model-capabilities"][data-dsh-part="panel"]` |
158
- | `toggle` | model-capabilities | 扩展区折叠头按钮;panel 内 `button[data-dsh-part="toggle"]` |
159
- | `model-row` / `model-toggle` | model-capabilities | 逐模型能力行与其展开按钮;panel 内 `li[data-dsh-part="model-row"]` 及其中 `button[data-dsh-part="model-toggle"]` |
160
- | `image-input` / `efforts-mode` | model-capabilities | 图片输入勾选组 / 推理档位三态组;展开行内字段容器 `[data-dsh-part="image-input"]`、`[data-dsh-part="efforts-mode"]` |
161
- | `wire-input` | model-capabilities | 档位发送值输入行;`[data-dsh-part="wire-input"]` 内含 `input[type="text"]` |
162
- | `save` / `reset` / `disable` / `enable` / `reload` | model-capabilities | 扩展区动作按钮(保存 / 重置 / 禁用此提供方 / 启用 / 重新读取);panel 内裸值按钮 |
163
- | `disabled-state` | model-capabilities | 已禁用提供方的卡片提示区(含启用按钮);panel 内 `[data-dsh-part="disabled-state"]` |
164
- | `disabled-footer` / `disabled-row` | model-capabilities | Models 页底部存档区与其行;`settings.models.footer` 槽内 `section[data-dsh-part="disabled-footer"]` 与其中 `li[data-dsh-part="disabled-row"]` |
165
157
  | `lever` | liangshen | 首页输入框内的梁神模式拨杆根(模型选择器左侧);`[data-dsh-plugin="liangshen"][data-dsh-part="lever"]`,状态由 `data-state`(`on` / `off` / `locked` / `missing`)锚定 |
166
158
  | `lever-track` | liangshen | 拨杆底座槽(臂的转动轨道);lever 内 `[data-dsh-part="lever-track"]` |
167
159
  | `lever-arm` | liangshen | 拨杆臂(拉杆 + 球头,随状态转动);lever 内 `[data-dsh-part="lever-arm"]` |
@@ -199,7 +191,6 @@ shell 的 `[class*="panelGlyph"]` 内)。shell 目前不把 entry id 透传到
199
191
  | `skin-center` | skins/skin-center | 一级设置分区 settings.section id `skin-center`(列已安装皮肤,属内置源时显式标记) |
200
192
  | `session-id` | dsh-session-id | footer action slot entry id `session-id`;`[data-dsh-plugin="session-id"]`(面板 overlay 根 + 入口触发器) |
201
193
  | `usage` | dsh-usage | 一级设置分区 settings.section id `dsh-usage`(创意工坊下方);`[data-dsh-plugin="usage"]`;侧栏底部速览卡容器 `[data-dsh-usage-foot-card]` |
202
- | `model-capabilities` | dsh-model-capabilities | Models 页 `settings.models.provider-card` keyed 槽 key `llm-pi-ai`(提供方卡片扩展区)+ `settings.models.footer` 槽 entry id `ui-model-capabilities`(存档区);`[data-dsh-plugin="model-capabilities"]` |
203
194
  | `preset-center` | dsh-preset-center | 创意工坊卡片的「预设」标签页面板(`dsh-workshop.panel` keyed 槽 key `preset`);`[data-dsh-plugin="preset-center"]` |
204
195
  | `liangshen` | dsh-liangshen | 首页输入框内的梁神模式拨杆;`[data-dsh-plugin="liangshen"][data-dsh-part="lever"]`,slot entry id `liangshen-lever` |
205
196
 
package/lib/client.js CHANGED
@@ -237,6 +237,40 @@ window.__ModuleLoader__.load({
237
237
  "data-phase"
238
238
  ];
239
239
  /**
240
+ * Selector shapes whose verdict depends on the element's DESCENDANTS or on
241
+ * its position among its siblings, rather than on the element alone.
242
+ *
243
+ * Everything outside this list is "self-only": inserting a descendant cannot
244
+ * change whether the element itself matches. Splitting the table on that
245
+ * boundary is what keeps the ancestor walk cheap without weakening what the
246
+ * walk is FOR (issue #1732) — re-anchoring an ANCESTOR when a late descendant
247
+ * turns out to be the anchor that ancestor keys on.
248
+ */
249
+ const DESCENDANT_SENSITIVE_PSEUDO = /:has\(|:empty|:first-child|:last-child|:only-child|:first-of-type|:last-of-type|:only-of-type|:nth-/;
250
+ /**
251
+ * Attribute names a selector references. Deliberately a plain scan of the
252
+ * bracket contents rather than a parsed selector: it also finds a reference
253
+ * nested INSIDE a functional pseudo-class, which is what lets
254
+ * `[role="dialog"]:has([data-slot="settings.section"])` answer to a late
255
+ * data-slot flip on an element inside the dialog.
256
+ */
257
+ const SELECTOR_ATTRIBUTE = /\[([A-Za-z0-9_-]+)/g;
258
+ const attributeReferences = (selector) => {
259
+ const names = /* @__PURE__ */ new Set();
260
+ for (const found of selector.matchAll(SELECTOR_ATTRIBUTE)) names.add(found[1]);
261
+ return names;
262
+ };
263
+ /**
264
+ * Rule traits derived from the selector text ONCE, at module load, never per
265
+ * element. The classification is what every batching decision below reads;
266
+ * re-deriving it inside the walk would reintroduce exactly the per-node work
267
+ * this change removes (issue #1870).
268
+ */
269
+ const RULE_TRAITS = SEMANTIC_RULES_V1.map((rule) => ({
270
+ descendantSensitive: DESCENDANT_SENSITIVE_PSEUDO.test(rule.selector),
271
+ attributes: attributeReferences(rule.selector)
272
+ }));
273
+ /**
240
274
  * Safety bound of the ancestor walk, NOT a depth ceiling.
241
275
  *
242
276
  * The walk's normal terminator is the observed root: every node the observer
@@ -251,14 +285,31 @@ window.__ModuleLoader__.load({
251
285
  * a deeper row unanchored — which is the very defect this walk exists to fix
252
286
  * (issue #1732). A measured sweep anchors through 23 wrapper levels and misses
253
287
  * from 24, i.e. only past the point where the tree is pathological.
288
+ *
289
+ * Narrowing WHICH rules a hop applies does not make the hop count safe to drop
290
+ * (issue #1870): a childList record only ever flips a descendant-sensitive
291
+ * rule, and an attributes record only the rules naming the attribute that
292
+ * actually changed, so a hop now costs one matches() call per APPLICABLE rule
293
+ * instead of one per rule in the table. The bound stays as the backstop it has
294
+ * always been.
254
295
  */
255
296
  const ANCESTOR_HOPS = 24;
256
297
  function createSemanticAdapter(doc) {
257
- const rules = SEMANTIC_RULES_V1.map((rule) => ({
298
+ const rules = SEMANTIC_RULES_V1.map((rule, index) => ({
258
299
  rule,
259
300
  usable: true,
260
- matchedInPass: 0
301
+ matchedInPass: 0,
302
+ descendantSensitive: RULE_TRAITS[index].descendantSensitive,
303
+ attributes: RULE_TRAITS[index].attributes
261
304
  }));
305
+ /**
306
+ * The subset a childList delivery may walk: inserting a descendant can flip
307
+ * a descendant-sensitive rule on an ancestor and nothing else. A self-only
308
+ * ancestor was already rule-checked when it was added (or by fullPass), and
309
+ * its verdict cannot change because something inside it grew, so
310
+ * re-evaluating it is the cost, not the correctness, of the walk.
311
+ */
312
+ const descendantSensitiveRules = rules.filter((live) => live.descendantSensitive);
262
313
  let observer = null;
263
314
  let stamped = 0;
264
315
  let running = false;
@@ -297,24 +348,55 @@ window.__ModuleLoader__.load({
297
348
  if (doc.documentElement) applyToTree(doc.documentElement);
298
349
  };
299
350
  /**
300
- * Re-anchor one changed node and its ancestor chain.
351
+ * Re-anchor one changed node's ancestor chain with the rules that change
352
+ * could actually have flipped.
301
353
  *
302
354
  * applyToTree only walks DOWNWARD: a rule whose selector matches an ancestor
303
355
  * of the changed node (the panel-list row is recognised by the glyph INSIDE
304
356
  * it) is never re-evaluated when that descendant arrives. React mounts the
305
357
  * row first and the registering plugin's glyph a tick later, so without this
306
358
  * the row keeps no anchor at all until something forces a full pass
307
- * (issue #1732). The walk is bounded and stops at the document root.
359
+ * (issue #1732). The walk is bounded, stops at the document root, and
360
+ * carries only the rules the reported change can flip: the caller's batch has
361
+ * already deduplicated the hops it shares with sibling records, so a hop
362
+ * costs one matches() call per applicable rule, not one per rule in the table
363
+ * (issue #1870).
308
364
  */
309
- const reanchorAround = (node) => {
365
+ const reanchorAncestors = (node, subset) => {
366
+ if (subset.length === 0) return;
310
367
  const root = doc.body ?? doc.documentElement;
311
368
  let current = node;
312
369
  for (let hop = 0; current !== null && hop <= ANCESTOR_HOPS; hop += 1) {
313
- for (const live of rules) if (live.usable) applyRule(live, current);
370
+ for (const live of subset) if (live.usable) applyRule(live, current);
314
371
  if (current === root || current === doc.documentElement) return;
315
372
  current = current.parentElement;
316
373
  }
317
374
  };
375
+ /**
376
+ * Drop added roots that another root of the same delivery already contains:
377
+ * applyToTree on the containing root scans the nested one as part of its own
378
+ * subtree, and the containing root's own ancestor walk covers the nested
379
+ * root's ancestors, so re-scanning it is pure duplicate work. Membership is a
380
+ * Set probe per ancestor hop — no selector-engine call — which keeps a
381
+ * delivery that mounts a whole subtree at once linear in that subtree.
382
+ */
383
+ const topmostRoots = (roots) => {
384
+ const kept = [];
385
+ for (const candidate of roots) {
386
+ let parent = candidate.parentElement;
387
+ let nested = false;
388
+ while (parent !== null) {
389
+ if (roots.has(parent)) {
390
+ nested = true;
391
+ break;
392
+ }
393
+ if (parent === doc.documentElement) break;
394
+ parent = parent.parentElement;
395
+ }
396
+ if (!nested) kept.push(candidate);
397
+ }
398
+ return kept;
399
+ };
318
400
  return {
319
401
  get running() {
320
402
  return running;
@@ -325,15 +407,41 @@ window.__ModuleLoader__.load({
325
407
  fullPass();
326
408
  observer = new doc.defaultView.MutationObserver((records) => {
327
409
  try {
410
+ const roots = /* @__PURE__ */ new Set();
411
+ const byAttribute = /* @__PURE__ */ new Map();
328
412
  for (const record of records) {
413
+ if (record.type === "attributes") {
414
+ const target = record.target.nodeType === 1 ? record.target : null;
415
+ const name = record.attributeName;
416
+ if (target === null || name === null) continue;
417
+ const seen = byAttribute.get(name);
418
+ if (seen === void 0) byAttribute.set(name, /* @__PURE__ */ new Set([target]));
419
+ else seen.add(target);
420
+ continue;
421
+ }
422
+ if (record.type !== "childList") continue;
329
423
  for (const node of Array.from(record.addedNodes)) {
330
424
  if (node.nodeType !== 1) continue;
331
- const el = node;
332
- applyToTree(el);
333
- reanchorAround(el.parentElement ?? el);
425
+ roots.add(node);
426
+ }
427
+ }
428
+ for (const root of topmostRoots(roots)) {
429
+ applyToTree(root);
430
+ reanchorAncestors(root.parentElement ?? root, descendantSensitiveRules);
431
+ }
432
+ for (const [name, targets] of byAttribute) {
433
+ const onTarget = [];
434
+ const onAncestors = [];
435
+ for (const live of rules) {
436
+ if (!live.attributes.has(name)) continue;
437
+ onTarget.push(live);
438
+ if (live.descendantSensitive) onAncestors.push(live);
439
+ }
440
+ if (onTarget.length === 0) continue;
441
+ for (const target of targets) {
442
+ for (const live of onTarget) applyRule(live, target);
443
+ reanchorAncestors(target.parentElement ?? target, onAncestors);
334
444
  }
335
- const target = record.target.nodeType === 1 ? record.target : null;
336
- if (target !== null && record.type === "attributes") reanchorAround(target);
337
445
  }
338
446
  } catch {}
339
447
  });
@@ -5188,7 +5296,7 @@ window.__ModuleLoader__.load({
5188
5296
  sectionState() {
5189
5297
  const snapshot = this.scope.getSnapshot();
5190
5298
  const revision = snapshot.revision === void 0 ? "none" : String(snapshot.revision);
5191
- return `${SKIN_CUSTOM_THEME_NS}: status ${snapshot.status}, writable ${String(snapshot.writable)}, mode ${snapshot.mode}, revision ${revision}`;
5299
+ return `${SKIN_CUSTOM_THEME_NS}: status ${snapshot.status}, writable ${String(snapshot.writable)}, revision ${revision}`;
5192
5300
  }
5193
5301
  queueWrite(field, value) {
5194
5302
  this.pendingWrites += 1;
@@ -5261,8 +5369,7 @@ window.__ModuleLoader__.load({
5261
5369
  base: layerOf(snapshot.base, key),
5262
5370
  user: layerOf(snapshot.user, key),
5263
5371
  revision: snapshot.revision,
5264
- writable: snapshot.writable,
5265
- mode: snapshot.mode
5372
+ writable: snapshot.writable
5266
5373
  };
5267
5374
  return projected;
5268
5375
  };
@@ -5329,8 +5436,7 @@ window.__ModuleLoader__.load({
5329
5436
  base: void 0,
5330
5437
  user: void 0,
5331
5438
  revision: void 0,
5332
- writable: false,
5333
- mode: "host"
5439
+ writable: false
5334
5440
  };
5335
5441
  }
5336
5442
  /**
@@ -5439,7 +5545,7 @@ window.__ModuleLoader__.load({
5439
5545
  /** The building package's version, when the bundle carries it. */
5440
5546
  function bakedVersion() {
5441
5547
  try {
5442
- return "0.4.6";
5548
+ return "0.4.7";
5443
5549
  } catch {
5444
5550
  return;
5445
5551
  }