@lemoncat7/dsh-theme-xiaohei 0.3.0-alpha.23 → 0.3.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.
Files changed (222) hide show
  1. package/README.md +39 -17
  2. package/THIRD_PARTY_NOTICES.md +41 -0
  3. package/lib/appearance.js +26 -10
  4. package/lib/blink.js +3 -3
  5. package/lib/bloub-heixiu/ambient.d.ts +3 -0
  6. package/lib/bloub-heixiu/ambient.js +12 -0
  7. package/lib/bloub-heixiu/character.d.ts +33 -0
  8. package/lib/bloub-heixiu/character.js +124 -0
  9. package/lib/bloub-heixiu/effects.d.ts +4 -0
  10. package/lib/bloub-heixiu/effects.js +91 -0
  11. package/lib/bloub-heixiu/flight.d.ts +15 -0
  12. package/lib/bloub-heixiu/flight.js +66 -0
  13. package/lib/bloub-heixiu/follow.d.ts +13 -0
  14. package/lib/bloub-heixiu/follow.js +23 -0
  15. package/lib/bloub-heixiu/layout.d.ts +18 -0
  16. package/lib/bloub-heixiu/layout.js +12 -0
  17. package/lib/bloub-heixiu/renderer.d.ts +16 -0
  18. package/lib/bloub-heixiu/renderer.js +94 -0
  19. package/lib/bloub-heixiu/runtime.d.ts +6 -0
  20. package/lib/bloub-heixiu/runtime.js +395 -0
  21. package/lib/bloub-heixiu/signals.d.ts +17 -0
  22. package/lib/bloub-heixiu/signals.js +53 -0
  23. package/lib/bloub-heixiu/styles.d.ts +2 -0
  24. package/lib/bloub-heixiu/styles.js +98 -0
  25. package/lib/chrome/accessibility.d.ts +1 -1
  26. package/lib/chrome/accessibility.js +5 -13
  27. package/lib/chrome/composer-avatar.d.ts +10 -0
  28. package/lib/chrome/composer-avatar.js +599 -0
  29. package/lib/chrome/composer-send-heixiu.d.ts +3 -0
  30. package/lib/chrome/composer-send-heixiu.js +143 -0
  31. package/lib/chrome/composer.d.ts +2 -2
  32. package/lib/chrome/composer.js +84 -95
  33. package/lib/chrome/controls.d.ts +8 -0
  34. package/lib/chrome/controls.js +348 -0
  35. package/lib/chrome/conversation-messages.d.ts +1 -1
  36. package/lib/chrome/conversation-messages.js +207 -9
  37. package/lib/chrome/conversation.d.ts +1 -1
  38. package/lib/chrome/conversation.js +6 -0
  39. package/lib/chrome/identity.js +4 -18
  40. package/lib/chrome/portal.d.ts +1 -1
  41. package/lib/chrome/portal.js +1 -1
  42. package/lib/chrome/sidebar.d.ts +1 -1
  43. package/lib/chrome/sidebar.js +134 -153
  44. package/lib/chrome/tokens.d.ts +1 -1
  45. package/lib/chrome/tokens.js +121 -68
  46. package/lib/chrome/workspace.d.ts +2 -2
  47. package/lib/chrome/workspace.js +35 -254
  48. package/lib/chrome.js +4 -0
  49. package/lib/client.d.ts +5 -12
  50. package/lib/client.js +6262 -4455
  51. package/lib/composer-avatar.d.ts +18 -0
  52. package/lib/composer-avatar.js +441 -0
  53. package/lib/composer-send-heixiu.d.ts +8 -0
  54. package/lib/composer-send-heixiu.js +133 -0
  55. package/lib/gaze.js +3 -3
  56. package/lib/generated-backgrounds.d.ts +14 -0
  57. package/lib/generated-backgrounds.js +14 -0
  58. package/lib/generated-character-motion.d.ts +4 -0
  59. package/lib/generated-character-motion.js +2 -0
  60. package/lib/generated-identity.d.ts +1 -0
  61. package/lib/generated-identity.js +1 -0
  62. package/lib/generated-keyart.d.ts +18 -3
  63. package/lib/generated-keyart.js +18 -3
  64. package/lib/host-contract.d.ts +9 -0
  65. package/lib/host-contract.js +13 -0
  66. package/lib/host-dom.d.ts +11 -0
  67. package/lib/host-dom.js +60 -0
  68. package/lib/loading-heixiu.js +3 -3
  69. package/lib/metallic-brand-mark.d.ts +10 -0
  70. package/lib/metallic-brand-mark.js +323 -0
  71. package/lib/plugin.d.ts +1 -1
  72. package/lib/plugin.js +31 -16
  73. package/lib/portal.js +11 -10
  74. package/lib/reactions.js +3 -3
  75. package/lib/scene/avatar-model.d.ts +6 -0
  76. package/lib/scene/avatar-model.js +646 -0
  77. package/lib/scene/avatar-motion.d.ts +3 -0
  78. package/lib/scene/avatar-motion.js +799 -0
  79. package/lib/scene/character-idle.d.ts +17 -0
  80. package/lib/scene/character-idle.js +65 -0
  81. package/lib/scene/character-layout.d.ts +24 -0
  82. package/lib/scene/character-layout.js +51 -0
  83. package/lib/scene/character-motion-clock.d.ts +18 -0
  84. package/lib/scene/character-motion-clock.js +57 -0
  85. package/lib/scene/character-motion-types.d.ts +12 -0
  86. package/lib/scene/character-motion-types.js +2 -0
  87. package/lib/scene/character-motion.d.ts +6 -0
  88. package/lib/scene/character-motion.js +126 -0
  89. package/lib/scene/character-poses.d.ts +26 -0
  90. package/lib/scene/character-poses.js +11 -0
  91. package/lib/scene/character-rig-renderer.d.ts +4 -0
  92. package/lib/scene/character-rig-renderer.js +85 -0
  93. package/lib/scene/character-rig.d.ts +20 -0
  94. package/lib/scene/character-rig.js +53 -0
  95. package/lib/scene/heixiu-feedback.d.ts +1 -1
  96. package/lib/scene/heixiu-feedback.js +0 -17
  97. package/lib/scene/pointer-bridge.d.ts +21 -0
  98. package/lib/scene/pointer-bridge.js +155 -0
  99. package/lib/scene/runtime.d.ts +12 -0
  100. package/lib/scene/runtime.js +87 -0
  101. package/lib/scene/styles.d.ts +7 -0
  102. package/lib/scene/styles.js +75 -0
  103. package/lib/scene/sylva-performance.d.ts +11 -0
  104. package/lib/scene/sylva-performance.js +58 -0
  105. package/lib/scene/wallpaper-character-styles.d.ts +3 -0
  106. package/lib/scene/wallpaper-character-styles.js +53 -0
  107. package/lib/scene/wallpaper-character.d.ts +4 -0
  108. package/lib/scene/wallpaper-character.js +213 -0
  109. package/lib/scene.d.ts +7 -13
  110. package/lib/scene.js +7 -1023
  111. package/lib/sidebar-glass.js +99 -36
  112. package/lib/sidebar-heixiu-roaming.js +5 -5
  113. package/lib/sidebar-reveal.d.ts +8 -0
  114. package/lib/sidebar-reveal.js +51 -0
  115. package/lib/state.d.ts +14 -2
  116. package/lib/state.js +12 -4
  117. package/lib/theme.js +2 -2
  118. package/lib/vendor/bloub/decor.d.ts +114 -0
  119. package/lib/vendor/bloub/decor.js +198 -0
  120. package/lib/vendor/bloub/engine.d.ts +213 -0
  121. package/lib/vendor/bloub/engine.js +452 -0
  122. package/lib/vendor/bloub/expressions.d.ts +35 -0
  123. package/lib/vendor/bloub/expressions.js +143 -0
  124. package/lib/vendor/bloub/eyefit.d.ts +75 -0
  125. package/lib/vendor/bloub/eyefit.js +393 -0
  126. package/lib/vendor/bloub/face.d.ts +63 -0
  127. package/lib/vendor/bloub/face.js +106 -0
  128. package/lib/vendor/bloub/math.d.ts +22 -0
  129. package/lib/vendor/bloub/math.js +36 -0
  130. package/lib/vendor/bloub/profiles.d.ts +8 -0
  131. package/lib/vendor/bloub/profiles.js +20 -0
  132. package/lib/vendor/bloub/repere.d.ts +30 -0
  133. package/lib/vendor/bloub/repere.js +32 -0
  134. package/lib/vendor/bloub/shape.d.ts +80 -0
  135. package/lib/vendor/bloub/shape.js +268 -0
  136. package/lib/vendor/bloub/skins.d.ts +36 -0
  137. package/lib/vendor/bloub/skins.js +74 -0
  138. package/lib/vendor/bloub/states.d.ts +87 -0
  139. package/lib/vendor/bloub/states.js +468 -0
  140. package/package.json +23 -6
  141. package/lib/appearance.d.ts.map +0 -1
  142. package/lib/appearance.js.map +0 -1
  143. package/lib/blink.d.ts.map +0 -1
  144. package/lib/blink.js.map +0 -1
  145. package/lib/boot-appearance.d.ts.map +0 -1
  146. package/lib/boot-appearance.js.map +0 -1
  147. package/lib/boot-loader.d.ts.map +0 -1
  148. package/lib/boot-loader.js.map +0 -1
  149. package/lib/chrome/accessibility.d.ts.map +0 -1
  150. package/lib/chrome/accessibility.js.map +0 -1
  151. package/lib/chrome/blink.d.ts.map +0 -1
  152. package/lib/chrome/blink.js.map +0 -1
  153. package/lib/chrome/composer.d.ts.map +0 -1
  154. package/lib/chrome/composer.js.map +0 -1
  155. package/lib/chrome/conversation-messages.d.ts.map +0 -1
  156. package/lib/chrome/conversation-messages.js.map +0 -1
  157. package/lib/chrome/conversation.d.ts.map +0 -1
  158. package/lib/chrome/conversation.js.map +0 -1
  159. package/lib/chrome/frames.d.ts.map +0 -1
  160. package/lib/chrome/frames.js.map +0 -1
  161. package/lib/chrome/gaze.d.ts.map +0 -1
  162. package/lib/chrome/gaze.js.map +0 -1
  163. package/lib/chrome/identity.d.ts.map +0 -1
  164. package/lib/chrome/identity.js.map +0 -1
  165. package/lib/chrome/overlays.d.ts.map +0 -1
  166. package/lib/chrome/overlays.js.map +0 -1
  167. package/lib/chrome/portal.d.ts.map +0 -1
  168. package/lib/chrome/portal.js.map +0 -1
  169. package/lib/chrome/reactions.d.ts.map +0 -1
  170. package/lib/chrome/reactions.js.map +0 -1
  171. package/lib/chrome/sidebar.d.ts.map +0 -1
  172. package/lib/chrome/sidebar.js.map +0 -1
  173. package/lib/chrome/tokens.d.ts.map +0 -1
  174. package/lib/chrome/tokens.js.map +0 -1
  175. package/lib/chrome/workspace.d.ts.map +0 -1
  176. package/lib/chrome/workspace.js.map +0 -1
  177. package/lib/chrome.d.ts.map +0 -1
  178. package/lib/chrome.js.map +0 -1
  179. package/lib/client.d.ts.map +0 -1
  180. package/lib/client.js.map +0 -7
  181. package/lib/gaze.d.ts.map +0 -1
  182. package/lib/gaze.js.map +0 -1
  183. package/lib/generated-identity.d.ts.map +0 -1
  184. package/lib/generated-identity.js.map +0 -1
  185. package/lib/generated-keyart.d.ts.map +0 -1
  186. package/lib/generated-keyart.js.map +0 -1
  187. package/lib/generated-loading-assets.d.ts.map +0 -1
  188. package/lib/generated-loading-assets.js.map +0 -1
  189. package/lib/generated-sidebar-assets.d.ts +0 -4
  190. package/lib/generated-sidebar-assets.d.ts.map +0 -1
  191. package/lib/generated-sidebar-assets.js +0 -4
  192. package/lib/generated-sidebar-assets.js.map +0 -1
  193. package/lib/heixiu-interactions.d.ts.map +0 -1
  194. package/lib/heixiu-interactions.js.map +0 -1
  195. package/lib/index.d.ts.map +0 -1
  196. package/lib/index.js.map +0 -1
  197. package/lib/loading-heixiu.d.ts.map +0 -1
  198. package/lib/loading-heixiu.js.map +0 -1
  199. package/lib/plugin.d.ts.map +0 -1
  200. package/lib/plugin.js.map +0 -1
  201. package/lib/portal.d.ts.map +0 -1
  202. package/lib/portal.js.map +0 -1
  203. package/lib/reactions.d.ts.map +0 -1
  204. package/lib/reactions.js.map +0 -1
  205. package/lib/scene/heixiu-feedback.d.ts.map +0 -1
  206. package/lib/scene/heixiu-feedback.js.map +0 -1
  207. package/lib/scene/heixiu-interactions.d.ts.map +0 -1
  208. package/lib/scene/heixiu-interactions.js.map +0 -1
  209. package/lib/scene/state-transitions.d.ts.map +0 -1
  210. package/lib/scene/state-transitions.js.map +0 -1
  211. package/lib/scene.d.ts.map +0 -1
  212. package/lib/scene.js.map +0 -1
  213. package/lib/sidebar-glass.d.ts.map +0 -1
  214. package/lib/sidebar-glass.js.map +0 -1
  215. package/lib/sidebar-heixiu-escape.d.ts.map +0 -1
  216. package/lib/sidebar-heixiu-escape.js.map +0 -1
  217. package/lib/sidebar-heixiu-roaming.d.ts.map +0 -1
  218. package/lib/sidebar-heixiu-roaming.js.map +0 -1
  219. package/lib/state.d.ts.map +0 -1
  220. package/lib/state.js.map +0 -1
  221. package/lib/theme.d.ts.map +0 -1
  222. package/lib/theme.js.map +0 -1
@@ -1,11 +1,13 @@
1
- import { XIAOHEI_SCENE_LAYER_ID } from './scene.js';
2
- import { XIAOHEI_SIDEBAR_ATMOSPHERE } from './generated-sidebar-assets.js';
1
+ import { XIAOHEI_SCENE_LAYER_ID, XIAOHEI_SCENE_WORLD_CLASS } from './scene.js';
2
+ import { subscribeXiaoheiHostDom } from './host-dom.js';
3
+ import { XIAOHEI_HOST_SELECTORS } from './host-contract.js';
4
+ import { createSidebarReveal } from './sidebar-reveal.js';
3
5
  /** Stable id for the paint-only glass surface behind DSH's native sidebar. */
4
6
  export const XIAOHEI_SIDEBAR_GLASS_ID = 'dsh-theme-xiaohei/sidebar-glass';
5
- const SIDEBAR_SHELL_SELECTOR = "#root [data-slot='sidebar'] > div";
6
7
  const HORIZONTAL_INSET_START = 7;
7
8
  const HORIZONTAL_INSET_END = 7;
8
9
  const VERTICAL_INSET = 8;
10
+ const RESIZE_SETTLE_MS = 120;
9
11
  /** Keep the visual surface inside the native sidebar without changing layout. */
10
12
  export function resolveXiaoheiSidebarGlassBounds(rect) {
11
13
  return {
@@ -28,52 +30,109 @@ export function installXiaoheiSidebarGlass(doc = typeof document === 'undefined'
28
30
  const win = browserWindow;
29
31
  let disposed = false;
30
32
  let glass;
31
- let sidebarShell;
33
+ let sidebarColumn;
32
34
  let animationFrame;
35
+ let resizeSettleTimer;
36
+ let resizing = false;
37
+ let appliedBounds;
38
+ let geometryDirty = true;
39
+ const reveal = createSidebarReveal(doc);
40
+ const clearResizeState = () => {
41
+ if (resizeSettleTimer !== undefined)
42
+ win.clearTimeout(resizeSettleTimer);
43
+ resizeSettleTimer = undefined;
44
+ resizing = false;
45
+ doc.documentElement.removeAttribute('data-xiaohei-sidebar-resizing');
46
+ };
47
+ const markResizeActivity = () => {
48
+ if (glass === undefined)
49
+ return;
50
+ if (!resizing) {
51
+ resizing = true;
52
+ doc.documentElement.setAttribute('data-xiaohei-sidebar-resizing', '');
53
+ }
54
+ if (resizeSettleTimer !== undefined)
55
+ win.clearTimeout(resizeSettleTimer);
56
+ resizeSettleTimer = win.setTimeout(() => {
57
+ resizeSettleTimer = undefined;
58
+ resizing = false;
59
+ doc.documentElement.removeAttribute('data-xiaohei-sidebar-resizing');
60
+ }, RESIZE_SETTLE_MS);
61
+ };
33
62
  const resizeObserver = typeof win.ResizeObserver === 'function'
34
- ? new win.ResizeObserver(() => scheduleReconcile())
63
+ ? new win.ResizeObserver(() => {
64
+ if (disposed)
65
+ return;
66
+ // RO runs after host layout and before paint. Update the independent
67
+ // paint layer now, not in next frame's RAF (which visibly trails).
68
+ const changed = applyBounds();
69
+ geometryDirty = false;
70
+ if (changed)
71
+ markResizeActivity();
72
+ })
35
73
  : undefined;
36
74
  const applyBounds = () => {
37
- if (glass === undefined || sidebarShell === undefined)
38
- return;
39
- const bounds = resolveXiaoheiSidebarGlassBounds(sidebarShell.getBoundingClientRect());
40
- glass.style.setProperty('--xiaohei-sidebar-glass-left', `${bounds.left}px`);
41
- glass.style.setProperty('--xiaohei-sidebar-glass-top', `${bounds.top}px`);
42
- glass.style.setProperty('--xiaohei-sidebar-glass-width', `${bounds.width}px`);
43
- glass.style.setProperty('--xiaohei-sidebar-glass-height', `${bounds.height}px`);
75
+ if (glass === undefined || sidebarColumn === undefined)
76
+ return false;
77
+ const bounds = resolveXiaoheiSidebarGlassBounds(sidebarColumn.getBoundingClientRect());
78
+ reveal.resize(bounds.width + HORIZONTAL_INSET_START + HORIZONTAL_INSET_END);
79
+ const changed = appliedBounds !== undefined && (bounds.left !== appliedBounds.left || bounds.top !== appliedBounds.top ||
80
+ bounds.width !== appliedBounds.width || bounds.height !== appliedBounds.height);
81
+ if (bounds.left !== appliedBounds?.left) {
82
+ glass.style.setProperty('--xiaohei-sidebar-glass-left', `${bounds.left}px`);
83
+ }
84
+ if (bounds.top !== appliedBounds?.top) {
85
+ glass.style.setProperty('--xiaohei-sidebar-glass-top', `${bounds.top}px`);
86
+ }
87
+ if (bounds.width !== appliedBounds?.width) {
88
+ glass.style.setProperty('--xiaohei-sidebar-glass-width', `${bounds.width}px`);
89
+ }
90
+ if (bounds.height !== appliedBounds?.height) {
91
+ glass.style.setProperty('--xiaohei-sidebar-glass-height', `${bounds.height}px`);
92
+ }
93
+ appliedBounds = bounds;
94
+ return changed;
44
95
  };
45
96
  const reconcile = () => {
46
97
  if (disposed)
47
98
  return;
48
99
  const sceneLayer = doc.getElementById(XIAOHEI_SCENE_LAYER_ID);
49
- const nextSidebarShell = doc.querySelector(SIDEBAR_SHELL_SELECTOR) ?? undefined;
50
- if (nextSidebarShell !== sidebarShell) {
100
+ const nextSidebarColumn = doc.querySelector(XIAOHEI_HOST_SELECTORS.sidebarColumn) ?? undefined;
101
+ if (nextSidebarColumn !== sidebarColumn) {
51
102
  resizeObserver?.disconnect();
52
- sidebarShell = nextSidebarShell;
53
- if (sidebarShell !== undefined)
54
- resizeObserver?.observe(sidebarShell);
103
+ sidebarColumn = nextSidebarColumn;
104
+ geometryDirty = true;
105
+ if (sidebarColumn !== undefined)
106
+ resizeObserver?.observe(sidebarColumn);
55
107
  }
56
- if (sceneLayer === null || sidebarShell === undefined) {
108
+ if (sceneLayer === null || sidebarColumn === undefined) {
109
+ reveal.setColumn(undefined);
110
+ clearResizeState();
57
111
  glass?.remove();
58
112
  glass = undefined;
113
+ appliedBounds = undefined;
114
+ geometryDirty = true;
59
115
  return;
60
116
  }
117
+ reveal.setColumn(sidebarColumn);
61
118
  if (glass === undefined || glass.parentElement !== sceneLayer) {
62
119
  doc.getElementById(XIAOHEI_SIDEBAR_GLASS_ID)?.remove();
63
120
  glass = doc.createElement('div');
64
121
  glass.id = XIAOHEI_SIDEBAR_GLASS_ID;
65
122
  glass.setAttribute('aria-hidden', 'true');
66
- const atmosphere = doc.createElement('img');
67
- atmosphere.className = 'xiaohei-sidebar-atmosphere';
68
- atmosphere.alt = '';
69
- atmosphere.decoding = 'async';
70
- atmosphere.fetchPriority = 'low';
71
- atmosphere.src = XIAOHEI_SIDEBAR_ATMOSPHERE;
72
- glass.append(atmosphere);
73
- const veil = sceneLayer.querySelector('.xiaohei-scene__veil');
74
- sceneLayer.insertBefore(glass, veil?.nextSibling ?? sceneLayer.firstChild);
123
+ appliedBounds = undefined;
124
+ geometryDirty = true;
125
+ const world = sceneLayer.querySelector(`.${XIAOHEI_SCENE_WORLD_CLASS}`);
126
+ // null is meaningful here: insertBefore(node, null) appends after a
127
+ // last-child wallpaper. Falling back to firstChild hides glass UNDER it.
128
+ sceneLayer.insertBefore(glass, world !== null ? world.nextSibling : sceneLayer.firstChild);
129
+ }
130
+ // Streamed text mutates the host tree frequently. Recheck slot identity,
131
+ // but do not force layout unless sidebar geometry actually changed.
132
+ if (geometryDirty) {
133
+ applyBounds();
134
+ geometryDirty = false;
75
135
  }
76
- applyBounds();
77
136
  };
78
137
  function scheduleReconcile() {
79
138
  if (disposed || animationFrame !== undefined)
@@ -83,23 +142,27 @@ export function installXiaoheiSidebarGlass(doc = typeof document === 'undefined'
83
142
  reconcile();
84
143
  });
85
144
  }
86
- const mutationObserver = typeof win.MutationObserver === 'function'
87
- ? new win.MutationObserver(scheduleReconcile)
88
- : undefined;
89
- mutationObserver?.observe(doc.body, { childList: true, subtree: true });
90
- win.addEventListener('resize', scheduleReconcile, { passive: true });
145
+ const unsubscribeHostDom = subscribeXiaoheiHostDom(doc, scheduleReconcile);
146
+ const onViewportResize = () => {
147
+ geometryDirty = true;
148
+ scheduleReconcile();
149
+ };
150
+ win.addEventListener('resize', onViewportResize, { passive: true });
91
151
  scheduleReconcile();
92
152
  return () => {
93
153
  disposed = true;
94
154
  if (animationFrame !== undefined)
95
155
  win.cancelAnimationFrame(animationFrame);
96
156
  animationFrame = undefined;
97
- mutationObserver?.disconnect();
157
+ unsubscribeHostDom();
98
158
  resizeObserver?.disconnect();
99
- win.removeEventListener('resize', scheduleReconcile);
159
+ reveal.dispose();
160
+ win.removeEventListener('resize', onViewportResize);
161
+ clearResizeState();
100
162
  glass?.remove();
101
163
  glass = undefined;
102
- sidebarShell = undefined;
164
+ sidebarColumn = undefined;
165
+ appliedBounds = undefined;
103
166
  };
104
167
  }
105
168
  //# sourceMappingURL=sidebar-glass.js.map
@@ -1,7 +1,8 @@
1
1
  import { createXiaoheiSidebarEscapeController, XIAOHEI_SIDEBAR_ESCAPE_CSS, } from './sidebar-heixiu-escape.js';
2
+ import { subscribeXiaoheiHostDom } from './host-dom.js';
3
+ import { XIAOHEI_HOST_SELECTORS } from './host-contract.js';
2
4
  export const XIAOHEI_SIDEBAR_ROAMING_STYLE_ID = 'dsh-theme-xiaohei/sidebar-heixiu-roaming-style';
3
5
  const SIDEBAR_HEIXIU_SELECTOR = '.xiaohei-scene__heixiu--sidebar';
4
- const SIDEBAR_SELECTOR = "[data-slot='sidebar']";
5
6
  const INTERACTIVE_SELECTOR = [
6
7
  'button',
7
8
  'a[href]',
@@ -200,7 +201,7 @@ export function installXiaoheiSidebarHeixiuRoaming(doc = typeof document === 'un
200
201
  if (disposed)
201
202
  return;
202
203
  const nextCreature = doc.querySelector(SIDEBAR_HEIXIU_SELECTOR) ?? undefined;
203
- const nextHost = doc.querySelector(SIDEBAR_SELECTOR)?.firstElementChild;
204
+ const nextHost = doc.querySelector(XIAOHEI_HOST_SELECTORS.sidebar)?.firstElementChild;
204
205
  const nextHostElement = nextHost instanceof win.HTMLElement ? nextHost : undefined;
205
206
  if (nextCreature === creature && nextHostElement === host)
206
207
  return;
@@ -266,8 +267,7 @@ export function installXiaoheiSidebarHeixiuRoaming(doc = typeof document === 'un
266
267
  hostResizeObserver?.observe(host);
267
268
  };
268
269
  bind();
269
- const observer = new win.MutationObserver(queueBind);
270
- observer.observe(doc.body, { childList: true, subtree: true });
270
+ const unsubscribeHostDom = subscribeXiaoheiHostDom(doc, queueBind);
271
271
  doc.addEventListener('visibilitychange', resumeOrPause);
272
272
  win.addEventListener('resize', resumeOrPause, { passive: true });
273
273
  reducedMotion.addEventListener('change', resumeOrPause);
@@ -276,7 +276,7 @@ export function installXiaoheiSidebarHeixiuRoaming(doc = typeof document === 'un
276
276
  disposed = true;
277
277
  escapeController.dispose();
278
278
  clearTimer();
279
- observer.disconnect();
279
+ unsubscribeHostDom();
280
280
  hostStateObserver.disconnect();
281
281
  hostResizeObserver?.disconnect();
282
282
  doc.removeEventListener('visibilitychange', resumeOrPause);
@@ -0,0 +1,8 @@
1
+ /** Synchronize native wide content with the visible column, without changing
2
+ * Host layout/state or adding a competing animation timer. */
3
+ export declare function createSidebarReveal(doc: Document): {
4
+ setColumn(column: HTMLElement | undefined): void;
5
+ resize(nextWidth: number): void;
6
+ dispose(): void;
7
+ };
8
+ //# sourceMappingURL=sidebar-reveal.d.ts.map
@@ -0,0 +1,51 @@
1
+ /** Synchronize native wide content with the visible column, without changing
2
+ * Host layout/state or adding a competing animation timer. */
3
+ export function createSidebarReveal(doc) {
4
+ let shell;
5
+ let observer;
6
+ let phase = '', width = 0, waiting = false;
7
+ const attribute = 'data-xiaohei-sidebar-reveal';
8
+ const readPhase = () => shell?.className.includes('_collapsed') ? 'rail'
9
+ : shell?.className.includes('_fading') ? 'closing' : 'wide';
10
+ const apply = () => {
11
+ if (!shell)
12
+ return;
13
+ // The Host freezes its shell at the requested width during grid motion.
14
+ // Reading the inline target does not force a layout.
15
+ const target = Number.parseFloat(shell.style.width);
16
+ if (waiting && phase === 'wide' && (!Number.isFinite(target) || width >= target - 2))
17
+ waiting = false;
18
+ const value = waiting ? 'waiting' : 'ready';
19
+ if (shell.getAttribute(attribute) !== value)
20
+ shell.setAttribute(attribute, value);
21
+ };
22
+ const changed = () => {
23
+ const next = readPhase();
24
+ if (next === 'wide' && phase !== 'wide')
25
+ waiting = true;
26
+ if (next === 'rail')
27
+ waiting = false;
28
+ phase = next;
29
+ apply();
30
+ };
31
+ return {
32
+ setColumn(column) {
33
+ const next = column?.querySelector?.("[data-slot='sidebar'] > div") ?? undefined;
34
+ if (next === shell)
35
+ return;
36
+ observer?.disconnect();
37
+ shell?.removeAttribute(attribute);
38
+ shell = next;
39
+ waiting = false;
40
+ phase = readPhase();
41
+ if (!shell)
42
+ return;
43
+ observer = new doc.defaultView.MutationObserver(changed);
44
+ observer.observe(shell, { attributes: true, attributeFilter: ['class', 'style'] });
45
+ apply();
46
+ },
47
+ resize(nextWidth) { width = nextWidth; apply(); },
48
+ dispose() { observer?.disconnect(); shell?.removeAttribute(attribute); shell = undefined; },
49
+ };
50
+ }
51
+ //# sourceMappingURL=sidebar-reveal.js.map
package/lib/state.d.ts CHANGED
@@ -1,9 +1,21 @@
1
- import type { ConversationSnapshot, ISessions, SessionSummary } from '@deepseek-ai/dsh-client-runtime/client';
1
+ import type { ISessions, SessionSnapshot, SessionSummary } from '@deepseek-ai/dsh-api-session-controller/client';
2
2
  export declare const XIAOHEI_STATE_ATTRIBUTE = "data-xiaohei-state";
3
3
  export declare const XIAOHEI_COMPLETE_DURATION_MS = 1600;
4
4
  export type XiaoheiState = 'idle' | 'thinking' | 'streaming' | 'tool' | 'waiting' | 'complete' | 'error';
5
5
  /** Resolve one official DSH snapshot using the theme's visible-state priority. */
6
- export declare function resolveXiaoheiState(snapshot: ConversationSnapshot | undefined, summary: SessionSummary | undefined): Exclude<XiaoheiState, 'complete'>;
6
+ export declare function resolveXiaoheiState(snapshot: SessionSnapshot | LegacySessionActivity | undefined, summary: SessionSummary | undefined): Exclude<XiaoheiState, 'complete'>;
7
+ interface LegacySessionActivity {
8
+ removed: boolean;
9
+ openState: 'cold' | 'loading' | 'open' | 'error';
10
+ openError: unknown | null;
11
+ promptError: unknown | null;
12
+ lastAgentError: unknown | null;
13
+ pending: readonly unknown[];
14
+ runningCalls: readonly unknown[];
15
+ partial: unknown | null;
16
+ running: boolean;
17
+ }
7
18
  /** Mirror the selected Session's official detailed state onto the theme root. */
8
19
  export declare function bindXiaoheiSessionState(sessions: Pick<ISessions, 'list' | 'binding'>, doc?: Document | undefined, completeDurationMs?: number): () => void;
20
+ export {};
9
21
  //# sourceMappingURL=state.d.ts.map
package/lib/state.js CHANGED
@@ -9,20 +9,28 @@ export function resolveXiaoheiState(snapshot, summary) {
9
9
  || snapshot.promptError !== null
10
10
  || snapshot.lastAgentError !== null)
11
11
  return 'error';
12
- if (snapshot.pending.length > 0 || summary?.pendingInteraction !== undefined)
12
+ const pending = 'pending' in snapshot
13
+ ? snapshot.pending
14
+ : [...snapshot.queue, ...snapshot.pendingSubmissions];
15
+ const runningCalls = 'runningCalls' in snapshot ? snapshot.runningCalls : [];
16
+ const partial = 'partial' in snapshot ? snapshot.partial : null;
17
+ if (pending.length > 0 || legacyPendingInteraction(summary) !== undefined)
13
18
  return 'waiting';
14
- if (snapshot.runningCalls.length > 0)
19
+ if (runningCalls.length > 0)
15
20
  return 'tool';
16
- if (snapshot.running && snapshot.partial !== null)
21
+ if (snapshot.running && partial !== null)
17
22
  return 'streaming';
18
23
  if (snapshot.running)
19
24
  return 'thinking';
20
25
  return 'idle';
21
26
  }
22
- if (summary?.pendingInteraction !== undefined)
27
+ if (legacyPendingInteraction(summary) !== undefined)
23
28
  return 'waiting';
24
29
  return summary?.running === true ? 'thinking' : 'idle';
25
30
  }
31
+ function legacyPendingInteraction(summary) {
32
+ return summary?.pendingInteraction;
33
+ }
26
34
  /** Mirror the selected Session's official detailed state onto the theme root. */
27
35
  export function bindXiaoheiSessionState(sessions, doc = typeof document === 'undefined' ? undefined : document, completeDurationMs = XIAOHEI_COMPLETE_DURATION_MS) {
28
36
  if (doc === undefined)
package/lib/theme.js CHANGED
@@ -2,7 +2,7 @@
2
2
  export const XIAOHEI_DAWN_THEME_ID = 'xiaohei-dawn';
3
3
  export const XIAOHEI_NIGHT_THEME_ID = 'xiaohei-night';
4
4
  const DAWN_TOKENS = {
5
- '--dsw-alias-bg-base': 'rgb(218 225 232 / 24%)',
5
+ '--dsw-alias-bg-base': 'transparent',
6
6
  '--dsw-alias-bg-layer-1': 'rgb(232 237 243 / 82%)',
7
7
  '--dsw-alias-bg-layer-2': 'rgb(238 242 247 / 90%)',
8
8
  '--dsw-alias-bg-layer-3': 'rgb(244 247 250 / 96%)',
@@ -84,7 +84,7 @@ const DAWN_TOKENS = {
84
84
  '--dsw-specific-tip': '#E3EBEA',
85
85
  };
86
86
  const NIGHT_TOKENS = {
87
- '--dsw-alias-bg-base': 'rgb(12 17 19 / 18%)',
87
+ '--dsw-alias-bg-base': 'transparent',
88
88
  '--dsw-alias-bg-layer-1': 'rgb(20 27 29 / 74%)',
89
89
  '--dsw-alias-bg-layer-2': 'rgb(25 33 35 / 86%)',
90
90
  '--dsw-alias-bg-layer-3': 'rgb(31 40 42 / 94%)',
@@ -0,0 +1,114 @@
1
+ export interface DotRender {
2
+ x: number;
3
+ y: number;
4
+ r: number;
5
+ opacity: number;
6
+ /** couleur explicite ; par defaut le rendu prend celle du corps */
7
+ color?: string;
8
+ /**
9
+ * Brume de profondeur : 0 = fondu dans le fond, 1 = couleur du corps pleine.
10
+ * Le melange se fait au rendu, qui seul connait la couleur choisie.
11
+ */
12
+ depth?: number;
13
+ /**
14
+ * Forme non circulaire, en unites de rayon de boule et centree sur l'origine
15
+ * (le point du "!" penche est une goutte, pas un disque). Quand elle est
16
+ * fournie, `r` n'est plus utilise pour le trace.
17
+ */
18
+ d?: string;
19
+ /** rotation appliquee a `d`, en degres */
20
+ rot?: number;
21
+ }
22
+ /**
23
+ * Ce qu'un etat declare : la geometrie de l'arc reste en unites de rayon de
24
+ * boule, c'est le moteur (seul a connaitre l'echelle du viewBox) qui la
25
+ * rasterise. Sans ca les etats devraient connaitre le viewBox.
26
+ */
27
+ export interface ArcSpec {
28
+ id: string;
29
+ seed: ArcSeed;
30
+ t: number;
31
+ opacity: number;
32
+ }
33
+ export interface ArcRender {
34
+ id: string;
35
+ /** portion devant le corps */
36
+ front: string;
37
+ /** portion derriere le corps (dessinee avant, donc masquee par la silhouette) */
38
+ back: string;
39
+ width: number;
40
+ opacity: number;
41
+ /** degrade de teinte le long du trace */
42
+ grad: {
43
+ x1: number;
44
+ y1: number;
45
+ x2: number;
46
+ y2: number;
47
+ stops: string[];
48
+ };
49
+ }
50
+ export interface ArcSeed {
51
+ /** demi-grand axe, en unites de rayon de boule */
52
+ a: number;
53
+ /** aplatissement b/a : mesure <= 0.45, les plans d'orbite sont vus par la tranche */
54
+ k: number;
55
+ /** inclinaison du grand axe a l'ecran, radians */
56
+ tilt: number;
57
+ /** tours par seconde */
58
+ speed: number;
59
+ phase: number;
60
+ /** fraction du tour reellement tracee */
61
+ sweep: number;
62
+ hue: number;
63
+ hueSpan: number;
64
+ width: number;
65
+ cx: number;
66
+ cy: number;
67
+ }
68
+ /**
69
+ * Projette un cercle 3D incline en orthographique.
70
+ *
71
+ * Le cercle vit dans le plan engendre par u (dans l'ecran) et v (qui plonge
72
+ * dans la profondeur). La composante z sert a couper l'arc en deux : la moitie
73
+ * arriere est dessinee avant le corps, donc occultee par lui. C'est ce vrai tri
74
+ * en profondeur qui fait lire les anneaux comme des orbites et pas comme un
75
+ * dessin plat.
76
+ */
77
+ export declare function arcRender(seed: ArcSeed, t: number, scale: number, id: string, opacity?: number): ArcRender;
78
+ /**
79
+ * 6 anneaux, demi-grand axe 1.30-1.40 (donc nettement plus grands que la
80
+ * boule), aplatissement toujours <= 0.45, epaisseur 0.055, ~3.3 tours/s.
81
+ */
82
+ export declare const RINGS: ArcSeed[];
83
+ /**
84
+ * Bouquet d'arcs emboites qui balaie le triangle juste avant les orbites.
85
+ * Vus quasiment par la tranche (d'ou la forme en epingle a cheveux), rmax 1.37.
86
+ */
87
+ export declare const SWOOSH: ArcSeed[];
88
+ /** x mesures : -0.557 / -0.013 / +0.532, y = 0. */
89
+ export declare const DOT_X: readonly [-0.557, -0.013, 0.532];
90
+ export declare const DOT_R = 0.165;
91
+ export declare const DOT_PEAK = 1.25;
92
+ /**
93
+ * Les particules ne partent pas en ligne droite : elles spiralent vers le
94
+ * centre (rayon x0.75 par frame, angle +100 deg/s) en grossissant, et passent
95
+ * derriere le noyau ou elles sont avalees.
96
+ */
97
+ export declare function particles(t: number, scale: number): DotRender[];
98
+ export declare const COMET_RIBBONS: ArcSeed[];
99
+ /** Rayon du point de la comete, mesure a 0.129. */
100
+ export declare const COMET_DOT = 0.129;
101
+ /** Bleu releve au pixel. */
102
+ export declare const NOTIF_BLUE = "#2496e8";
103
+ /** La pastille est posee exactement sur la circonference, a -42deg. */
104
+ export declare const NOTIF_ANGLE = -42;
105
+ export declare const NOTIF_DIST = 1.003;
106
+ /** Rayon au repos ; le pop culmine 14 % au-dessus. */
107
+ export declare const NOTIF_R = 0.15;
108
+ export declare const NOTIF_POP = 1.14;
109
+ /**
110
+ * L'encoche est un disque concentrique a la pastille, soustrait du corps.
111
+ * La marge est constante (0.054 R) et suit l'echelle du corps.
112
+ */
113
+ export declare const NOTIF_MARGIN = 0.054;
114
+ //# sourceMappingURL=decor.d.ts.map