@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
package/lib/scene.js CHANGED
@@ -1,1024 +1,8 @@
1
- import { XIAOHEI_COMPLETE, XIAOHEI_DAWN_KEY_ART, XIAOHEI_THINKING, XIAOHEI_ERROR, XIAOHEI_HEIXIU_BLINK, XIAOHEI_HEIXIU_OPEN, XIAOHEI_IDLE_BLINK, XIAOHEI_IDLE_SHEET, XIAOHEI_NIGHT_KEY_ART, XIAOHEI_STREAMING, XIAOHEI_TOOL, XIAOHEI_WAITING, } from './generated-keyart.js';
2
- import { XIAOHEI_HEIXIU_FEEDBACK_CSS } from './scene/heixiu-feedback.js';
3
- import { XIAOHEI_HEIXIU_INTERACTION_CSS } from './scene/heixiu-interactions.js';
4
- import { XIAOHEI_STATE_TRANSITION_CSS } from './scene/state-transitions.js';
5
- /** DOM ids are exported so lifecycle and browser tests can detect leaks. */
6
- export const XIAOHEI_SCENE_STYLE_ID = 'dsh-theme-xiaohei/scene-style';
7
- export const XIAOHEI_SCENE_LAYER_ID = 'dsh-theme-xiaohei/scene-layer';
8
- /**
9
- * The generated key art is a real raster asset. CSS supplies only atmosphere
10
- * and motion, never a shape-built substitute for the character.
11
- */
12
- const XIAOHEI_SCENE_BASE_CSS = `
13
- body {
14
- background: #151C1E;
15
- }
16
-
17
- html[data-xiaohei-appearance='light'] body {
18
- background: #E5EBF1;
19
- }
20
-
21
- #root {
22
- position: relative;
23
- z-index: 1;
24
- }
25
-
26
- #${cssEscape(XIAOHEI_SCENE_LAYER_ID)} {
27
- position: fixed;
28
- inset: 0;
29
- z-index: 0;
30
- overflow: hidden;
31
- contain: strict;
32
- isolation: isolate;
33
- pointer-events: none;
34
- user-select: none;
35
- background: #151C1E;
36
- }
37
-
38
- html[data-xiaohei-appearance='light'] #${cssEscape(XIAOHEI_SCENE_LAYER_ID)} {
39
- background:
40
- radial-gradient(80% 64% at 16% 8%, rgb(248 250 252 / 82%), transparent 72%),
41
- radial-gradient(70% 58% at 86% 88%, rgb(207 220 230 / 48%), transparent 76%),
42
- #E5EBF1;
43
- }
44
-
45
- #${cssEscape(XIAOHEI_SCENE_LAYER_ID)} > * {
46
- position: absolute;
47
- display: block;
48
- pointer-events: none;
49
- }
50
-
51
- .xiaohei-scene__keyart {
52
- inset: 0;
53
- width: 100%;
54
- height: 100%;
55
- max-width: none;
56
- object-fit: cover;
57
- object-position: center bottom;
58
- transform: scale(1.002);
59
- filter: blur(0.55px) saturate(96%) contrast(98%);
60
- transition: opacity 320ms ease-out;
61
- }
62
-
63
- .xiaohei-scene__keyart--night {
64
- opacity: 0.98;
65
- }
66
-
67
- .xiaohei-scene__keyart--dawn {
68
- opacity: 0;
69
- }
70
-
71
- @media (max-aspect-ratio: 4 / 3) {
72
- .xiaohei-scene__keyart {
73
- object-position: 66% bottom;
74
- }
75
- }
76
-
77
- html[data-xiaohei-appearance='light'] .xiaohei-scene__keyart--night {
78
- opacity: 0;
79
- }
80
-
81
- html[data-xiaohei-appearance='light'] .xiaohei-scene__keyart--dawn {
82
- opacity: 0.98;
83
- }
84
-
85
- .xiaohei-scene__veil {
86
- inset: 0;
87
- background:
88
- linear-gradient(90deg, rgb(8 13 15 / 4%) 0%, transparent 48%, rgb(8 13 15 / 4%) 100%),
89
- linear-gradient(180deg, rgb(8 13 15 / 2%) 0%, transparent 58%, rgb(8 13 15 / 4%) 100%);
90
- }
91
-
92
- html[data-xiaohei-appearance='light'] .xiaohei-scene__veil {
93
- background:
94
- linear-gradient(90deg, rgb(58 74 88 / 3%) 0%, transparent 48%, rgb(58 74 88 / 4%) 100%),
95
- linear-gradient(180deg, rgb(255 255 255 / 10%) 0%, transparent 54%, rgb(74 91 105 / 5%) 100%);
96
- }
97
-
98
- .xiaohei-scene__spirit {
99
- width: 0.58rem;
100
- aspect-ratio: 1;
101
- border-radius: 50%;
102
- background: #8BE5D5;
103
- box-shadow: 0 0 0.7rem rgb(117 228 208 / 88%), 0 0 1.8rem rgb(101 209 190 / 56%);
104
- mix-blend-mode: screen;
105
- opacity: 0.18;
106
- will-change: transform, opacity;
107
- }
108
-
109
- html[data-xiaohei-appearance='light'] .xiaohei-scene__spirit {
110
- background: #4D927C;
111
- box-shadow: 0 0 0.45rem rgb(67 133 111 / 54%), 0 0 1.4rem rgb(106 151 132 / 28%);
112
- mix-blend-mode: multiply;
113
- }
114
-
115
- .xiaohei-scene__spirit--one {
116
- right: 22%;
117
- bottom: 20%;
118
- animation: xiaohei-spirit-one 6.8s cubic-bezier(0.37, 0, 0.63, 1) infinite;
119
- }
120
-
121
- .xiaohei-scene__spirit--two {
122
- right: 34%;
123
- bottom: 30%;
124
- animation: xiaohei-spirit-two 8.4s cubic-bezier(0.37, 0, 0.63, 1) -2.2s infinite;
125
- }
126
-
127
- .xiaohei-scene__spirit--three {
128
- right: 13%;
129
- bottom: 45%;
130
- animation: xiaohei-spirit-three 7.7s cubic-bezier(0.37, 0, 0.63, 1) -4.1s infinite;
131
- }
132
-
133
- .xiaohei-scene__mascot {
134
- right: clamp(4.5rem, 8vw, 9rem);
135
- bottom: clamp(5rem, 10vh, 7rem);
136
- width: clamp(11.5rem, 19vw, 19rem);
137
- aspect-ratio: 1;
138
- overflow: visible;
139
- isolation: isolate;
140
- filter:
141
- drop-shadow(0 0.6rem 1.45rem rgb(83 218 193 / 35%))
142
- drop-shadow(0 1.25rem 2.6rem rgb(1 9 10 / 30%));
143
- }
144
-
145
- .xiaohei-scene__mascot-idle-viewport {
146
- position: absolute;
147
- inset: 0;
148
- z-index: 1;
149
- overflow: hidden;
150
- pointer-events: none;
151
- }
152
-
153
- .xiaohei-scene__mascot::before {
154
- content: '';
155
- position: absolute;
156
- z-index: 0;
157
- inset: 4%;
158
- border-radius: 50%;
159
- background: radial-gradient(
160
- circle at 50% 55%,
161
- rgb(190 255 242 / 68%) 0%,
162
- rgb(90 228 202 / 48%) 38%,
163
- rgb(34 144 132 / 18%) 58%,
164
- transparent 74%
165
- );
166
- opacity: 0.66;
167
- }
168
-
169
- html[data-xiaohei-appearance='light'] .xiaohei-scene__mascot {
170
- filter:
171
- drop-shadow(0 0.55rem 0.9rem rgb(40 58 51 / 22%))
172
- drop-shadow(0 1.15rem 2.2rem rgb(45 64 56 / 14%));
173
- }
174
-
175
- html[data-xiaohei-appearance='light'] .xiaohei-scene__mascot::before {
176
- background: radial-gradient(
177
- circle at 50% 58%,
178
- rgb(236 242 230 / 72%) 0%,
179
- rgb(198 219 202 / 34%) 40%,
180
- transparent 72%
181
- );
182
- opacity: 0.42;
183
- }
184
-
185
- .xiaohei-scene__heixiu-field {
186
- inset: 0;
187
- overflow: hidden;
188
- }
189
-
190
- .xiaohei-scene__heixiu {
191
- position: absolute;
192
- display: block;
193
- aspect-ratio: 1;
194
- opacity: var(--heixiu-opacity, 0.58);
195
- filter:
196
- drop-shadow(0 0.32rem 0.58rem rgb(109 233 211 / 18%))
197
- drop-shadow(0 0.68rem 1.15rem rgb(1 9 10 / 20%));
198
- will-change: transform;
199
- }
200
-
201
- #root [data-slot='sidebar'] > div,
202
- #root [data-slot='conversation.composer.bar'] > div {
203
- position: relative !important;
204
- }
205
-
206
- .xiaohei-scene__heixiu-body > img {
207
- position: absolute;
208
- display: block;
209
- inset: 0;
210
- width: 100%;
211
- height: 100%;
212
- max-width: none;
213
- max-height: none;
214
- object-fit: contain;
215
- filter: brightness(1.12) contrast(1.04) saturate(0.82);
216
- }
217
-
218
- .xiaohei-scene__heixiu-open {
219
- opacity: 1;
220
- will-change: opacity;
221
- animation: xiaohei-heixiu-open var(--heixiu-blink-duration, 7.6s) step-end var(--heixiu-blink-delay, 0s) infinite;
222
- }
223
-
224
- .xiaohei-scene__heixiu-blink {
225
- opacity: 0;
226
- will-change: opacity;
227
- animation: xiaohei-heixiu-blink var(--heixiu-blink-duration, 7.6s) step-end var(--heixiu-blink-delay, 0s) infinite;
228
- }
229
-
230
- .xiaohei-scene__heixiu--mascot {
231
- right: clamp(19rem, 25vw, 30rem);
232
- bottom: clamp(9.5rem, 16vh, 13rem);
233
- width: clamp(4.2rem, 5.4vw, 5.5rem);
234
- --heixiu-opacity: 0.72;
235
- --heixiu-blink-duration: 7.2s;
236
- --heixiu-blink-delay: -1.1s;
237
- animation: xiaohei-heixiu-drift-one 13.6s cubic-bezier(0.37, 0, 0.63, 1) infinite;
238
- }
239
-
240
- .xiaohei-scene__heixiu--sidebar {
241
- z-index: 6;
242
- left: 7.15rem;
243
- right: auto;
244
- top: 8.05rem;
245
- width: 2.5rem;
246
- --heixiu-opacity: 0.76;
247
- --heixiu-blink-duration: 8.9s;
248
- --heixiu-blink-delay: -4.7s;
249
- animation: xiaohei-heixiu-drift-two 16.2s cubic-bezier(0.37, 0, 0.63, 1) -5.2s infinite;
250
- }
251
-
252
- .xiaohei-scene__heixiu--sidebar .xiaohei-scene__heixiu-body > img {
253
- filter: brightness(1.18) contrast(1.09) saturate(0.86);
254
- }
255
-
256
- .xiaohei-scene__heixiu--composer {
257
- z-index: 3;
258
- left: 54%;
259
- right: auto;
260
- top: -1.7rem;
261
- width: 3.45rem;
262
- --heixiu-opacity: 0.6;
263
- --heixiu-blink-duration: 9.4s;
264
- --heixiu-blink-delay: -6.2s;
265
- animation: xiaohei-heixiu-drift-three 17.2s cubic-bezier(0.37, 0, 0.63, 1) -8.1s infinite;
266
- }
267
-
268
- .xiaohei-scene__heixiu--sidebar::before,
269
- .xiaohei-scene__heixiu--composer::before {
270
- content: '';
271
- position: absolute;
272
- z-index: -1;
273
- left: 50%;
274
- top: -0.72rem;
275
- width: 1px;
276
- height: 0.85rem;
277
- background: linear-gradient(180deg, transparent, var(--xiaohei-frame-line-strong));
278
- box-shadow: 0 0 0.35rem var(--xiaohei-focus-shadow);
279
- transform: translateX(-50%);
280
- }
281
-
282
- #root [data-slot='sidebar'] > div[class*='_collapsed'] .xiaohei-scene__heixiu--sidebar {
283
- display: none;
284
- }
285
-
286
- html[data-xiaohei-appearance='light'] .xiaohei-scene__heixiu {
287
- filter:
288
- drop-shadow(0 0.28rem 0.5rem rgb(52 83 71 / 13%))
289
- drop-shadow(0 0.62rem 1rem rgb(45 64 56 / 10%));
290
- }
291
-
292
- html[data-xiaohei-appearance='light'] .xiaohei-scene__heixiu-body > img {
293
- filter: brightness(1.02) contrast(1.05) saturate(0.74);
294
- }
295
-
296
- html[data-xiaohei-appearance='light'] .xiaohei-scene__heixiu--sidebar .xiaohei-scene__heixiu-body > img {
297
- filter: brightness(1.03) contrast(1.1) saturate(0.78);
298
- }
299
-
300
- .xiaohei-scene__mascot-sheet {
301
- position: absolute;
302
- display: block;
303
- inset: 0 auto auto 0;
304
- width: 400%;
305
- height: 200%;
306
- max-width: none;
307
- max-height: none;
308
- object-fit: fill;
309
- transform: translate3d(0, 0, 0);
310
- opacity: 0;
311
- z-index: 1;
312
- filter: brightness(1.32) contrast(1.02) saturate(1.04);
313
- }
314
-
315
- .xiaohei-scene__mascot-sheet--open {
316
- opacity: 1;
317
- transition: opacity 120ms ease-out;
318
- }
319
-
320
- .xiaohei-scene__mascot-blink {
321
- position: absolute;
322
- display: block;
323
- inset: 0;
324
- width: 100%;
325
- height: 100%;
326
- max-width: none;
327
- max-height: none;
328
- object-fit: contain;
329
- opacity: 0;
330
- z-index: 3;
331
- filter: brightness(1.32) contrast(1.02) saturate(1.04);
332
- will-change: opacity;
333
- }
334
-
335
- .xiaohei-scene__mascot-state {
336
- position: absolute;
337
- display: block;
338
- left: 50%;
339
- bottom: 0;
340
- width: 100%;
341
- height: auto;
342
- max-width: none;
343
- max-height: none;
344
- object-fit: contain;
345
- opacity: 0;
346
- z-index: 1;
347
- filter: brightness(1.32) contrast(1.02) saturate(1.04);
348
- transform: translateX(-50%);
349
- transform-origin: 50% 100%;
350
- transition: opacity 120ms ease-out;
351
- }
352
-
353
- .xiaohei-scene__mascot-state--thinking {
354
- filter: brightness(1.34) contrast(1.02) saturate(1.03);
355
- }
356
-
357
- html[data-xiaohei-appearance='light'] .xiaohei-scene__mascot-sheet,
358
- html[data-xiaohei-appearance='light'] .xiaohei-scene__mascot-blink,
359
- html[data-xiaohei-appearance='light'] .xiaohei-scene__mascot-state {
360
- filter: brightness(1.02) contrast(1.07) saturate(0.9);
361
- }
362
-
363
- html[data-xiaohei-appearance='light'] .xiaohei-scene__mascot-state--thinking {
364
- filter: brightness(1.04) contrast(1.06) saturate(0.91);
365
- }
366
-
367
- html:not([data-xiaohei-state='idle']) .xiaohei-scene__mascot-sheet--open {
368
- opacity: 0;
369
- }
370
-
371
- html:not([data-xiaohei-state='idle']) .xiaohei-scene__mascot-blink {
372
- opacity: 0;
373
- animation: none;
374
- }
375
-
376
- html[data-xiaohei-state='thinking'] .xiaohei-scene__mascot-state--thinking,
377
- html[data-xiaohei-state='streaming'] .xiaohei-scene__mascot-state--streaming,
378
- html[data-xiaohei-state='tool'] .xiaohei-scene__mascot-state--tool,
379
- html[data-xiaohei-state='waiting'] .xiaohei-scene__mascot-state--waiting,
380
- html[data-xiaohei-state='complete'] .xiaohei-scene__mascot-state--complete,
381
- html[data-xiaohei-state='error'] .xiaohei-scene__mascot-state--error {
382
- opacity: 1;
383
- }
384
-
385
- .xiaohei-scene__thinking-fx,
386
- .xiaohei-scene__thinking-bubble,
387
- .xiaohei-scene__thinking-dot {
388
- position: absolute;
389
- display: block;
390
- pointer-events: none;
391
- }
392
-
393
- .xiaohei-scene__thinking-fx {
394
- inset: 0;
395
- z-index: 3;
396
- opacity: 0;
397
- transition: opacity 160ms ease-out;
398
- }
399
-
400
- .xiaohei-scene__thinking-bubble {
401
- left: 56%;
402
- top: -4%;
403
- width: 36%;
404
- height: 18%;
405
- border: 1px solid rgb(210 242 235 / 44%);
406
- border-radius: 999px;
407
- background: rgb(226 242 238 / 88%);
408
- box-shadow:
409
- 0 0.45rem 1.15rem rgb(1 9 10 / 18%),
410
- inset 0 1px rgb(255 255 255 / 68%);
411
- }
412
-
413
- .xiaohei-scene__thinking-bubble::before,
414
- .xiaohei-scene__thinking-bubble::after {
415
- position: absolute;
416
- display: block;
417
- content: '';
418
- aspect-ratio: 1;
419
- border-radius: 50%;
420
- background: inherit;
421
- box-shadow: inherit;
422
- }
423
-
424
- .xiaohei-scene__thinking-bubble::before {
425
- left: 12%;
426
- bottom: -31%;
427
- width: 15%;
428
- }
429
-
430
- .xiaohei-scene__thinking-bubble::after {
431
- left: 2%;
432
- bottom: -51%;
433
- width: 8%;
434
- }
435
-
436
- .xiaohei-scene__thinking-dot {
437
- top: 50%;
438
- width: 9%;
439
- aspect-ratio: 1;
440
- border-radius: 50%;
441
- background: #526B66;
442
- opacity: 0.28;
443
- transform: translateY(-50%);
444
- }
445
-
446
- .xiaohei-scene__thinking-dot--one { left: 25%; }
447
- .xiaohei-scene__thinking-dot--two { left: 46%; }
448
- .xiaohei-scene__thinking-dot--three { left: 67%; }
449
-
450
- html[data-xiaohei-state='thinking'] .xiaohei-scene__thinking-fx {
451
- opacity: 1;
452
- }
453
-
454
- html[data-xiaohei-state='thinking'] .xiaohei-scene__thinking-dot--one {
455
- animation: xiaohei-thinking-dot 1.8s ease-in-out infinite;
456
- }
457
-
458
- html[data-xiaohei-state='thinking'] .xiaohei-scene__thinking-dot--two {
459
- animation: xiaohei-thinking-dot 1.8s ease-in-out 0.3s infinite;
460
- }
461
-
462
- html[data-xiaohei-state='thinking'] .xiaohei-scene__thinking-dot--three {
463
- animation: xiaohei-thinking-dot 1.8s ease-in-out 0.6s infinite;
464
- }
465
-
466
- html[data-xiaohei-appearance='light'] .xiaohei-scene__thinking-bubble {
467
- border-color: rgb(46 94 83 / 20%);
468
- background: rgb(247 250 247 / 92%);
469
- box-shadow:
470
- 0 0.45rem 1.1rem rgb(44 73 60 / 12%),
471
- inset 0 1px rgb(255 255 255 / 86%);
472
- }
473
-
474
- html[data-xiaohei-appearance='light'] .xiaohei-scene__thinking-dot {
475
- background: #45635C;
476
- }
477
-
478
- .xiaohei-scene__state-fx,
479
- .xiaohei-scene__state-fx > span {
480
- position: absolute;
481
- display: block;
482
- pointer-events: none;
483
- }
484
-
485
- .xiaohei-scene__state-fx {
486
- inset: 0;
487
- z-index: 2;
488
- opacity: 0;
489
- transition: opacity 120ms ease-out;
490
- }
491
-
492
- .xiaohei-scene__state-fx > span {
493
- border-radius: 50%;
494
- opacity: 0;
495
- will-change: transform, opacity;
496
- }
497
-
498
- html[data-xiaohei-state='streaming'] .xiaohei-scene__state-fx--streaming,
499
- html[data-xiaohei-state='tool'] .xiaohei-scene__state-fx--tool,
500
- html[data-xiaohei-state='waiting'] .xiaohei-scene__state-fx--waiting,
501
- html[data-xiaohei-state='complete'] .xiaohei-scene__state-fx--complete,
502
- html[data-xiaohei-state='error'] .xiaohei-scene__state-fx--error {
503
- opacity: 1;
504
- }
505
-
506
- .xiaohei-scene__tail-write {
507
- left: var(--tail-write-left);
508
- top: var(--tail-write-top);
509
- width: var(--tail-write-width);
510
- height: 7%;
511
- border-top: 2px solid #A8FFEB;
512
- border-radius: 50%;
513
- filter: drop-shadow(0 0 0.34rem rgb(91 255 219 / 78%));
514
- transform: rotate(var(--tail-write-angle)) scaleX(0.08);
515
- transform-origin: 100% 50%;
516
- }
517
-
518
- .xiaohei-scene__tail-write--one {
519
- --tail-write-left: 67%;
520
- --tail-write-top: 34%;
521
- --tail-write-width: 16%;
522
- --tail-write-angle: -18deg;
523
- }
524
-
525
- .xiaohei-scene__tail-write--two {
526
- --tail-write-left: 59%;
527
- --tail-write-top: 27%;
528
- --tail-write-width: 19%;
529
- --tail-write-angle: -12deg;
530
- }
531
-
532
- .xiaohei-scene__tail-write--three {
533
- --tail-write-left: 50%;
534
- --tail-write-top: 21%;
535
- --tail-write-width: 21%;
536
- --tail-write-angle: -6deg;
537
- }
538
-
539
- html[data-xiaohei-appearance='light'] .xiaohei-scene__tail-write {
540
- border-top-color: #2F8576;
541
- filter: drop-shadow(0 0 0.28rem rgb(47 133 118 / 34%));
542
- }
543
-
544
- html[data-xiaohei-state='streaming'] .xiaohei-scene__tail-write--one {
545
- animation: xiaohei-tail-write 1.9s ease-in-out infinite;
546
- }
547
-
548
- html[data-xiaohei-state='streaming'] .xiaohei-scene__tail-write--two {
549
- animation: xiaohei-tail-write 1.9s ease-in-out 0.3s infinite;
550
- }
551
-
552
- html[data-xiaohei-state='streaming'] .xiaohei-scene__tail-write--three {
553
- animation: xiaohei-tail-write 1.9s ease-in-out 0.6s infinite;
554
- }
555
-
556
- .xiaohei-scene__tool-key {
557
- top: 84%;
558
- width: 0.3rem;
559
- aspect-ratio: 0.7;
560
- background: #70F2D9;
561
- box-shadow: 0 0 0.7rem rgb(72 238 208 / 90%);
562
- }
563
-
564
- .xiaohei-scene__tool-key--one { left: 29%; }
565
- .xiaohei-scene__tool-key--two { left: 38%; }
566
- .xiaohei-scene__tool-key--three { left: 47%; }
567
-
568
- html[data-xiaohei-state='tool'] .xiaohei-scene__tool-key--one {
569
- animation: xiaohei-tool-key 0.9s ease-in-out infinite;
570
- }
571
-
572
- html[data-xiaohei-state='tool'] .xiaohei-scene__tool-key--two {
573
- animation: xiaohei-tool-key 0.9s ease-in-out -0.3s infinite;
574
- }
575
-
576
- html[data-xiaohei-state='tool'] .xiaohei-scene__tool-key--three {
577
- animation: xiaohei-tool-key 0.9s ease-in-out -0.6s infinite;
578
- }
579
-
580
- .xiaohei-scene__waiting-ring {
581
- left: 61%;
582
- top: 34%;
583
- width: 13%;
584
- aspect-ratio: 1;
585
- border: 1px solid rgb(255 207 126 / 88%);
586
- box-shadow: 0 0 0.8rem rgb(255 188 93 / 42%);
587
- }
588
-
589
- html[data-xiaohei-state='waiting'] .xiaohei-scene__waiting-ring {
590
- animation: xiaohei-waiting-ring 1.8s ease-out infinite;
591
- }
592
-
593
- .xiaohei-scene__complete-spark {
594
- width: 0.35rem;
595
- aspect-ratio: 1;
596
- background: #B6FFED;
597
- box-shadow: 0 0 0.8rem rgb(91 255 219 / 92%);
598
- }
599
-
600
- .xiaohei-scene__complete-spark--one { left: 36%; top: 70%; }
601
- .xiaohei-scene__complete-spark--two { left: 62%; top: 67%; }
602
-
603
- html[data-xiaohei-state='complete'] .xiaohei-scene__complete-spark--one {
604
- animation: xiaohei-complete-spark-one 0.8s ease-out infinite;
605
- }
606
-
607
- html[data-xiaohei-state='complete'] .xiaohei-scene__complete-spark--two {
608
- animation: xiaohei-complete-spark-two 0.8s ease-out -0.4s infinite;
609
- }
610
-
611
- .xiaohei-scene__error-glow {
612
- left: 41%;
613
- top: 82%;
614
- width: 7%;
615
- aspect-ratio: 1;
616
- background: radial-gradient(circle, rgb(255 112 82 / 90%) 0%, rgb(224 58 46 / 28%) 48%, transparent 72%);
617
- mix-blend-mode: screen;
618
- }
619
-
620
- html[data-xiaohei-state='error'] .xiaohei-scene__error-glow {
621
- animation: xiaohei-error-glow 2.2s ease-in-out infinite;
622
- }
623
-
624
- @keyframes xiaohei-heixiu-blink {
625
- 0%, 87.9% { opacity: 0; }
626
- 88%, 90.4% { opacity: 1; }
627
- 90.5%, 100% { opacity: 0; }
628
- }
629
-
630
- @keyframes xiaohei-heixiu-open {
631
- 0%, 87.9% { opacity: 1; }
632
- 88%, 90.4% { opacity: 0; }
633
- 90.5%, 100% { opacity: 1; }
634
- }
635
-
636
- @keyframes xiaohei-heixiu-drift-one {
637
- 0%, 100% { transform: translate3d(0, 0.4rem, 0); }
638
- 28% { transform: translate3d(0.7rem, -0.2rem, 0); }
639
- 61% { transform: translate3d(-0.45rem, -0.9rem, 0); }
640
- 82% { transform: translate3d(0.28rem, -0.48rem, 0); }
641
- }
642
-
643
- @keyframes xiaohei-heixiu-drift-two {
644
- 0%, 100% { transform: translate3d(-0.35rem, 0.25rem, 0); }
645
- 34% { transform: translate3d(0.5rem, -0.72rem, 0); }
646
- 68% { transform: translate3d(-0.6rem, -1.15rem, 0); }
647
- }
648
-
649
- @keyframes xiaohei-heixiu-drift-three {
650
- 0%, 100% { transform: translate3d(0.25rem, 0.15rem, 0); }
651
- 37% { transform: translate3d(-0.65rem, 0.72rem, 0); }
652
- 72% { transform: translate3d(0.48rem, -0.55rem, 0); }
653
- }
654
-
655
- @keyframes xiaohei-spirit-one {
656
- 0%, 100% { transform: translate3d(0, 0.5rem, 0) scale(0.72); opacity: 0.12; }
657
- 48% { transform: translate3d(-0.7rem, -1.6rem, 0) scale(1); opacity: 0.82; }
658
- }
659
-
660
- @keyframes xiaohei-spirit-two {
661
- 0%, 100% { transform: translate3d(0.6rem, 0.4rem, 0) scale(0.68); opacity: 0.08; }
662
- 52% { transform: translate3d(-0.35rem, -1.35rem, 0) scale(0.92); opacity: 0.66; }
663
- }
664
-
665
- @keyframes xiaohei-spirit-three {
666
- 0%, 100% { transform: translate3d(-0.4rem, 0.8rem, 0) scale(0.7); opacity: 0.1; }
667
- 44% { transform: translate3d(0.45rem, -1.2rem, 0) scale(0.96); opacity: 0.7; }
668
- }
669
-
670
- @keyframes xiaohei-thinking-dot {
671
- 0%, 18%, 100% { opacity: 0.28; }
672
- 42%, 62% { opacity: 0.96; }
673
- }
674
-
675
- @keyframes xiaohei-tail-write {
676
- 0%, 12% { transform: rotate(var(--tail-write-angle)) scaleX(0.08); opacity: 0; }
677
- 38%, 68% { transform: rotate(var(--tail-write-angle)) scaleX(1); opacity: 0.94; }
678
- 88%, 100% { transform: rotate(var(--tail-write-angle)) scaleX(1); opacity: 0; }
679
- }
680
-
681
- @keyframes xiaohei-tool-key {
682
- 0%, 100% { transform: translate3d(0, 0, 0) scale(0.7); opacity: 0.18; }
683
- 45% { transform: translate3d(0, -0.15rem, 0) scale(1); opacity: 1; }
684
- }
685
-
686
- @keyframes xiaohei-waiting-ring {
687
- from { transform: translate3d(-50%, -50%, 0) scale(0.55); opacity: 0.72; }
688
- to { transform: translate3d(-50%, -50%, 0) scale(1.45); opacity: 0; }
689
- }
690
-
691
- @keyframes xiaohei-complete-spark-one {
692
- from { transform: translate3d(-0.4rem, 0.4rem, 0) scale(0.45); opacity: 0; }
693
- 35% { opacity: 1; }
694
- to { transform: translate3d(-2.5rem, -2rem, 0) scale(1.15); opacity: 0; }
695
- }
696
-
697
- @keyframes xiaohei-complete-spark-two {
698
- from { transform: translate3d(0.4rem, 0.3rem, 0) scale(0.45); opacity: 0; }
699
- 35% { opacity: 0.95; }
700
- to { transform: translate3d(2.5rem, -1.75rem, 0) scale(1.1); opacity: 0; }
701
- }
702
-
703
- @keyframes xiaohei-error-glow {
704
- 0%, 100% { transform: translate3d(-50%, -50%, 0) scale(0.78); opacity: 0.34; }
705
- 50% { transform: translate3d(-50%, -50%, 0) scale(1.12); opacity: 0.9; }
706
- }
707
-
708
- @media (max-width: 768px) {
709
- .xiaohei-scene__keyart {
710
- object-position: 62% bottom;
711
- }
712
-
713
- .xiaohei-scene__keyart--night { opacity: 0.9; }
714
- .xiaohei-scene__keyart--dawn { opacity: 0; }
715
-
716
- html[data-xiaohei-appearance='light'] .xiaohei-scene__keyart--night { opacity: 0; }
717
-
718
- html[data-xiaohei-appearance='light'] .xiaohei-scene__keyart--dawn {
719
- opacity: 0.94;
720
- }
721
-
722
- .xiaohei-scene__veil {
723
- background: linear-gradient(180deg, rgb(8 13 15 / 3%), rgb(8 13 15 / 8%));
724
- }
725
-
726
- .xiaohei-scene__mascot {
727
- right: -1.5rem;
728
- bottom: 5rem;
729
- width: clamp(10rem, 42vw, 14rem);
730
- }
731
-
732
- .xiaohei-scene__heixiu--mascot {
733
- right: 8.5rem;
734
- bottom: 7.5rem;
735
- width: 3.8rem;
736
- }
737
-
738
- .xiaohei-scene__heixiu--sidebar { display: none; }
739
-
740
- .xiaohei-scene__heixiu--composer {
741
- left: 52%;
742
- right: auto;
743
- top: -1.45rem;
744
- width: 2.8rem;
745
- }
746
-
747
- }
748
-
749
- @media (prefers-reduced-motion: reduce) {
750
- .xiaohei-scene__spirit,
751
- .xiaohei-scene__heixiu,
752
- .xiaohei-scene__heixiu-open,
753
- .xiaohei-scene__heixiu-blink,
754
- .xiaohei-scene__thinking-dot,
755
- .xiaohei-scene__state-fx > span {
756
- animation: none;
757
- will-change: auto;
758
- }
759
-
760
- .xiaohei-scene__spirit { display: none; }
761
- .xiaohei-scene__state-fx { display: none; }
762
-
763
- html[data-xiaohei-state='thinking'] .xiaohei-scene__thinking-dot {
764
- animation: none;
765
- will-change: auto;
766
- opacity: 0.72;
767
- }
768
- }
769
-
770
- @media (prefers-contrast: more) {
771
- .xiaohei-scene__keyart--night { opacity: 0.48; }
772
- .xiaohei-scene__keyart--dawn { opacity: 0; }
773
- html[data-xiaohei-appearance='light'] .xiaohei-scene__keyart--night { opacity: 0; }
774
- html[data-xiaohei-appearance='light'] .xiaohei-scene__keyart--dawn { opacity: 0.5; }
775
- .xiaohei-scene__veil { background: rgb(5 12 15 / 48%); }
776
- html[data-xiaohei-appearance='light'] .xiaohei-scene__veil { background: rgb(235 240 235 / 58%); }
777
- .xiaohei-scene__spirit,
778
- .xiaohei-scene__heixiu-field,
779
- .xiaohei-scene__heixiu--sidebar,
780
- .xiaohei-scene__heixiu--composer { display: none; }
781
- }
782
-
783
- @media (forced-colors: active), print {
784
- #${cssEscape(XIAOHEI_SCENE_LAYER_ID)},
785
- .xiaohei-scene__heixiu--sidebar,
786
- .xiaohei-scene__heixiu--composer { display: none; }
787
- }
788
- `;
789
- export const XIAOHEI_SCENE_CSS = [
790
- XIAOHEI_SCENE_BASE_CSS,
791
- XIAOHEI_STATE_TRANSITION_CSS,
792
- XIAOHEI_HEIXIU_FEEDBACK_CSS,
793
- XIAOHEI_HEIXIU_INTERACTION_CSS,
794
- ].join('\n');
795
- const PARTS = [
796
- 'xiaohei-scene__keyart xiaohei-scene__keyart--night',
797
- 'xiaohei-scene__keyart xiaohei-scene__keyart--dawn',
798
- 'xiaohei-scene__veil',
799
- 'xiaohei-scene__spirit xiaohei-scene__spirit--one',
800
- 'xiaohei-scene__spirit xiaohei-scene__spirit--two',
801
- 'xiaohei-scene__spirit xiaohei-scene__spirit--three',
802
- 'xiaohei-scene__mascot',
803
- 'xiaohei-scene__heixiu-field',
804
- ];
805
- /** Number of top-level decorative parts installed into the ambient layer. */
806
- export const XIAOHEI_SCENE_PART_COUNT = PARTS.length;
807
- /** Skip host lookups while every companion remains attached to the document. */
808
- export function shouldRestoreXiaoheiHeixiuCompanions(creatures) {
809
- return creatures.some(creature => !creature.isConnected);
810
- }
811
- /**
812
- * Install the generated scene after plugin boot becomes idle. The theme tokens
813
- * apply immediately, while image decoding never extends DSH's loading screen.
814
- */
815
- export function installXiaoheiScene(doc = typeof document === 'undefined' ? undefined : document) {
816
- if (doc === undefined)
817
- return () => { };
818
- let disposed = false;
819
- let removeMountedScene = () => { };
820
- let removeHeixiuCompanions = () => { };
821
- const mount = () => {
822
- if (disposed)
823
- return;
824
- doc.getElementById(XIAOHEI_SCENE_STYLE_ID)?.remove();
825
- doc.getElementById(XIAOHEI_SCENE_LAYER_ID)?.remove();
826
- const style = doc.createElement('style');
827
- style.id = XIAOHEI_SCENE_STYLE_ID;
828
- style.textContent = XIAOHEI_SCENE_CSS;
829
- doc.head.append(style);
830
- const layer = doc.createElement('div');
831
- layer.id = XIAOHEI_SCENE_LAYER_ID;
832
- layer.setAttribute('aria-hidden', 'true');
833
- layer.setAttribute('data-xiaohei-scene', '');
834
- const keyArtSources = [XIAOHEI_NIGHT_KEY_ART, XIAOHEI_DAWN_KEY_ART];
835
- for (const [index, source] of keyArtSources.entries()) {
836
- const keyArt = doc.createElement('img');
837
- keyArt.className = PARTS[index];
838
- keyArt.alt = '';
839
- keyArt.decoding = 'async';
840
- keyArt.fetchPriority = 'low';
841
- keyArt.src = source;
842
- layer.append(keyArt);
843
- }
844
- for (const className of PARTS.slice(keyArtSources.length)) {
845
- if (className === 'xiaohei-scene__mascot') {
846
- const mascot = doc.createElement('div');
847
- mascot.className = className;
848
- const idleViewport = doc.createElement('span');
849
- idleViewport.className = 'xiaohei-scene__mascot-idle-viewport';
850
- idleViewport.append(createIdleSheet(doc, 7, 'xiaohei-scene__mascot-sheet--open'), createIdleBlink(doc));
851
- mascot.append(idleViewport, createStateImage(doc, 'thinking', XIAOHEI_THINKING), createStateImage(doc, 'streaming', XIAOHEI_STREAMING), createStateImage(doc, 'tool', XIAOHEI_TOOL), createStateImage(doc, 'waiting', XIAOHEI_WAITING), createStateImage(doc, 'complete', XIAOHEI_COMPLETE), createStateImage(doc, 'error', XIAOHEI_ERROR), createThinkingEffects(doc), createStateEffects(doc, 'streaming', [
852
- 'xiaohei-scene__tail-write xiaohei-scene__tail-write--one',
853
- 'xiaohei-scene__tail-write xiaohei-scene__tail-write--two',
854
- 'xiaohei-scene__tail-write xiaohei-scene__tail-write--three',
855
- ]), createStateEffects(doc, 'tool', [
856
- 'xiaohei-scene__tool-key xiaohei-scene__tool-key--one',
857
- 'xiaohei-scene__tool-key xiaohei-scene__tool-key--two',
858
- 'xiaohei-scene__tool-key xiaohei-scene__tool-key--three',
859
- ]), createStateEffects(doc, 'waiting', ['xiaohei-scene__waiting-ring']), createStateEffects(doc, 'complete', [
860
- 'xiaohei-scene__complete-spark xiaohei-scene__complete-spark--one',
861
- 'xiaohei-scene__complete-spark xiaohei-scene__complete-spark--two',
862
- ]), createStateEffects(doc, 'error', ['xiaohei-scene__error-glow']));
863
- layer.append(mascot);
864
- continue;
865
- }
866
- if (className === 'xiaohei-scene__heixiu-field') {
867
- layer.append(createHeixiuField(doc));
868
- continue;
869
- }
870
- const part = doc.createElement('span');
871
- part.className = className;
872
- layer.append(part);
873
- }
874
- doc.body.prepend(layer);
875
- removeHeixiuCompanions();
876
- removeHeixiuCompanions = installHeixiuCompanions(doc, layer);
877
- removeMountedScene = () => {
878
- removeHeixiuCompanions();
879
- removeHeixiuCompanions = () => { };
880
- layer.remove();
881
- style.remove();
882
- };
883
- };
884
- const win = doc.defaultView;
885
- let cancelSchedule = () => { };
886
- if (win !== null && typeof win.requestIdleCallback === 'function') {
887
- const idleId = win.requestIdleCallback(mount, { timeout: 800 });
888
- cancelSchedule = () => win.cancelIdleCallback(idleId);
889
- }
890
- else if (win !== null) {
891
- const timeoutId = win.setTimeout(mount, 0);
892
- cancelSchedule = () => win.clearTimeout(timeoutId);
893
- }
894
- else {
895
- mount();
896
- }
897
- return () => {
898
- disposed = true;
899
- cancelSchedule();
900
- removeMountedScene();
901
- };
902
- }
903
- /** CSS id escaping for the slash in stable plugin-owned DOM ids. */
904
- function cssEscape(value) {
905
- return value.replaceAll('/', '\\/');
906
- }
907
- function createIdleSheet(doc, frame, modifier) {
908
- const sheet = doc.createElement('img');
909
- sheet.className = `xiaohei-scene__mascot-sheet ${modifier}`;
910
- sheet.alt = '';
911
- sheet.decoding = 'async';
912
- sheet.fetchPriority = 'low';
913
- sheet.src = XIAOHEI_IDLE_SHEET;
914
- setIdleFrame(sheet, frame);
915
- return sheet;
916
- }
917
- function createIdleBlink(doc) {
918
- const image = doc.createElement('img');
919
- image.className = 'xiaohei-scene__mascot-blink';
920
- image.alt = '';
921
- image.decoding = 'async';
922
- image.fetchPriority = 'low';
923
- image.src = XIAOHEI_IDLE_BLINK;
924
- return image;
925
- }
926
- function setIdleFrame(sheet, frame) {
927
- const column = frame % 4;
928
- const row = Math.floor(frame / 4);
929
- sheet.style.transform = `translate3d(${-column * 25}%, ${-row * 50}%, 0)`;
930
- }
931
- function createStateImage(doc, state, source) {
932
- const image = doc.createElement('img');
933
- image.className = `xiaohei-scene__mascot-state xiaohei-scene__mascot-state--${state}`;
934
- image.alt = '';
935
- image.decoding = 'async';
936
- image.fetchPriority = 'low';
937
- image.src = source;
938
- return image;
939
- }
940
- function createHeixiuField(doc) {
941
- const field = doc.createElement('div');
942
- field.className = 'xiaohei-scene__heixiu-field';
943
- field.append(createHeixiuCreature(doc, 'mascot'));
944
- return field;
945
- }
946
- function createHeixiuCreature(doc, name) {
947
- const creature = doc.createElement('span');
948
- creature.className = `xiaohei-scene__heixiu xiaohei-scene__heixiu--${name}`;
949
- creature.setAttribute('aria-hidden', 'true');
950
- const body = doc.createElement('span');
951
- body.className = 'xiaohei-scene__heixiu-body';
952
- body.append(createHeixiuImage(doc, XIAOHEI_HEIXIU_OPEN, 'xiaohei-scene__heixiu-open'), createHeixiuImage(doc, XIAOHEI_HEIXIU_BLINK, 'xiaohei-scene__heixiu-blink'));
953
- creature.append(body);
954
- return creature;
955
- }
956
- function installHeixiuCompanions(doc, layer) {
957
- const companions = [
958
- { slot: 'sidebar', creature: createHeixiuCreature(doc, 'sidebar') },
959
- { slot: 'conversation.composer.bar', creature: createHeixiuCreature(doc, 'composer') },
960
- ];
961
- const companionCreatures = companions.map(({ creature }) => creature);
962
- let attachQueued = false;
963
- const attach = () => {
964
- attachQueued = false;
965
- for (const { slot, creature } of companions) {
966
- const host = doc.querySelector(`[data-slot='${slot}']`)?.firstElementChild;
967
- if (host !== null && host !== undefined && creature.parentElement !== host)
968
- host.append(creature);
969
- }
970
- };
971
- const queueAttach = () => {
972
- if (attachQueued)
973
- return;
974
- attachQueued = true;
975
- queueMicrotask(attach);
976
- };
977
- const restoreDetachedCompanions = () => {
978
- if (!shouldRestoreXiaoheiHeixiuCompanions(companionCreatures))
979
- return;
980
- queueAttach();
981
- };
982
- attach();
983
- const Observer = doc.defaultView?.MutationObserver;
984
- const observer = Observer === undefined ? undefined : new Observer(restoreDetachedCompanions);
985
- observer?.observe(doc.body, { childList: true, subtree: true });
986
- return () => {
987
- observer?.disconnect();
988
- for (const { creature } of companions)
989
- creature.remove();
990
- };
991
- }
992
- function createHeixiuImage(doc, source, className) {
993
- const image = doc.createElement('img');
994
- image.className = className;
995
- image.alt = '';
996
- image.decoding = 'async';
997
- image.fetchPriority = 'low';
998
- image.src = source;
999
- return image;
1000
- }
1001
- function createThinkingEffects(doc) {
1002
- const effects = doc.createElement('span');
1003
- effects.className = 'xiaohei-scene__thinking-fx';
1004
- const bubble = doc.createElement('span');
1005
- bubble.className = 'xiaohei-scene__thinking-bubble';
1006
- for (const suffix of ['one', 'two', 'three']) {
1007
- const dot = doc.createElement('span');
1008
- dot.className = `xiaohei-scene__thinking-dot xiaohei-scene__thinking-dot--${suffix}`;
1009
- bubble.append(dot);
1010
- }
1011
- effects.append(bubble);
1012
- return effects;
1013
- }
1014
- function createStateEffects(doc, state, classNames) {
1015
- const effects = doc.createElement('span');
1016
- effects.className = `xiaohei-scene__state-fx xiaohei-scene__state-fx--${state}`;
1017
- for (const className of classNames) {
1018
- const part = doc.createElement('span');
1019
- part.className = className;
1020
- effects.append(part);
1021
- }
1022
- return effects;
1023
- }
1
+ /** Public scene facade. Runtime structure and visual styling evolve independently. */
2
+ export { XIAOHEI_SCENE_CSS, XIAOHEI_SCENE_LAYER_ID, XIAOHEI_SCENE_STYLE_ID, XIAOHEI_SCENE_WORLD_CLASS, } from './scene/styles.js';
3
+ export { configureXiaoheiWorldRenderer, installXiaoheiScene, XIAOHEI_SCENE_PART_COUNT, } from './scene/runtime.js';
4
+ export { injectXiaoheiSylvaAvatarModel, prepareXiaoheiSylvaAvatarFrame, XIAOHEI_SYLVA_AVATAR_MARKER, } from './scene/avatar-model.js';
5
+ export { XIAOHEI_AVATAR_MOTION_RUNTIME } from './scene/avatar-motion.js';
6
+ export { injectXiaoheiSylvaPerformanceProfile, XIAOHEI_SYLVA_PERFORMANCE_MARKER, } from './scene/sylva-performance.js';
7
+ export { injectXiaoheiSylvaPointerBridge, prepareXiaoheiSylvaPointerFrame, resolveXiaoheiSylvaPointer, XIAOHEI_SYLVA_POINTER_CHANNEL, XIAOHEI_SYLVA_POINTER_MARKER, } from './scene/pointer-bridge.js';
1024
8
  //# sourceMappingURL=scene.js.map