@lemoncat7/dsh-theme-xiaohei 0.4.5 → 0.5.0

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 (230) hide show
  1. package/README.md +25 -92
  2. package/THIRD_PARTY_NOTICES.md +13 -1
  3. package/docs/dsh-021-compatibility.md +23 -0
  4. package/docs/releases/0.4.6.md +17 -0
  5. package/docs/releases/0.5.0.md +24 -0
  6. package/docs/releases/README.md +14 -0
  7. package/docs/rift-interaction.md +35 -0
  8. package/docs/rift-preview.md +39 -0
  9. package/lib/client.companion.js +99 -0
  10. package/lib/client.decorations.js +224 -51
  11. package/lib/client.js +532 -2501
  12. package/lib/index.d.ts +1 -2
  13. package/lib/index.js +393 -11
  14. package/lib/rift/boot.d.ts +6 -0
  15. package/package.json +30 -19
  16. package/lib/appearance.d.ts +0 -12
  17. package/lib/appearance.js +0 -42
  18. package/lib/blink.d.ts +0 -4
  19. package/lib/blink.js +0 -110
  20. package/lib/bloub-heixiu/ambient.d.ts +0 -3
  21. package/lib/bloub-heixiu/ambient.js +0 -12
  22. package/lib/bloub-heixiu/character.d.ts +0 -33
  23. package/lib/bloub-heixiu/character.js +0 -124
  24. package/lib/bloub-heixiu/effects.d.ts +0 -4
  25. package/lib/bloub-heixiu/effects.js +0 -91
  26. package/lib/bloub-heixiu/flight.d.ts +0 -15
  27. package/lib/bloub-heixiu/flight.js +0 -66
  28. package/lib/bloub-heixiu/follow.d.ts +0 -13
  29. package/lib/bloub-heixiu/follow.js +0 -23
  30. package/lib/bloub-heixiu/layout.d.ts +0 -18
  31. package/lib/bloub-heixiu/layout.js +0 -12
  32. package/lib/bloub-heixiu/renderer.d.ts +0 -16
  33. package/lib/bloub-heixiu/renderer.js +0 -94
  34. package/lib/bloub-heixiu/runtime.d.ts +0 -6
  35. package/lib/bloub-heixiu/runtime.js +0 -409
  36. package/lib/bloub-heixiu/signals.d.ts +0 -17
  37. package/lib/bloub-heixiu/signals.js +0 -55
  38. package/lib/bloub-heixiu/styles.d.ts +0 -2
  39. package/lib/bloub-heixiu/styles.js +0 -98
  40. package/lib/boot-appearance.d.ts +0 -10
  41. package/lib/boot-appearance.js +0 -47
  42. package/lib/boot-loader.d.ts +0 -5
  43. package/lib/boot-loader.js +0 -158
  44. package/lib/chrome/accessibility.d.ts +0 -3
  45. package/lib/chrome/accessibility.js +0 -69
  46. package/lib/chrome/blink.d.ts +0 -3
  47. package/lib/chrome/blink.js +0 -15
  48. package/lib/chrome/composer-avatar.d.ts +0 -10
  49. package/lib/chrome/composer-avatar.js +0 -599
  50. package/lib/chrome/composer-send-heixiu.d.ts +0 -3
  51. package/lib/chrome/composer-send-heixiu.js +0 -143
  52. package/lib/chrome/composer.d.ts +0 -3
  53. package/lib/chrome/composer.js +0 -135
  54. package/lib/chrome/controls.d.ts +0 -8
  55. package/lib/chrome/controls.js +0 -348
  56. package/lib/chrome/conversation-messages.d.ts +0 -3
  57. package/lib/chrome/conversation-messages.js +0 -329
  58. package/lib/chrome/conversation-submissions.d.ts +0 -3
  59. package/lib/chrome/conversation-submissions.js +0 -68
  60. package/lib/chrome/conversation.d.ts +0 -3
  61. package/lib/chrome/conversation.js +0 -67
  62. package/lib/chrome/frames.d.ts +0 -6
  63. package/lib/chrome/frames.js +0 -134
  64. package/lib/chrome/gaze.d.ts +0 -3
  65. package/lib/chrome/gaze.js +0 -103
  66. package/lib/chrome/identity.d.ts +0 -6
  67. package/lib/chrome/identity.js +0 -47
  68. package/lib/chrome/overlays.d.ts +0 -3
  69. package/lib/chrome/overlays.js +0 -104
  70. package/lib/chrome/portal.d.ts +0 -6
  71. package/lib/chrome/portal.js +0 -169
  72. package/lib/chrome/reactions.d.ts +0 -3
  73. package/lib/chrome/reactions.js +0 -85
  74. package/lib/chrome/sidebar.d.ts +0 -3
  75. package/lib/chrome/sidebar.js +0 -313
  76. package/lib/chrome/tokens.d.ts +0 -3
  77. package/lib/chrome/tokens.js +0 -224
  78. package/lib/chrome/workspace.d.ts +0 -3
  79. package/lib/chrome/workspace.js +0 -94
  80. package/lib/chrome.d.ts +0 -10
  81. package/lib/chrome.js +0 -46
  82. package/lib/client-entry.d.ts +0 -3
  83. package/lib/client-entry.js +0 -3
  84. package/lib/client.d.ts +0 -10
  85. package/lib/client.pose-chin-dark.js +0 -4
  86. package/lib/client.pose-chin-light.js +0 -4
  87. package/lib/client.pose-doze-dark.js +0 -4
  88. package/lib/client.pose-doze-light.js +0 -4
  89. package/lib/client.pose-halfpeek-dark.js +0 -4
  90. package/lib/client.pose-halfpeek-light.js +0 -4
  91. package/lib/client.pose-peek-dark.js +0 -4
  92. package/lib/client.pose-peek-light.js +0 -4
  93. package/lib/client.pose-seated-dark.js +0 -4
  94. package/lib/client.pose-seated-light.js +0 -4
  95. package/lib/client.rig-chin-dark.js +0 -4
  96. package/lib/client.rig-chin-light.js +0 -4
  97. package/lib/client.rig-halfpeek-dark.js +0 -4
  98. package/lib/client.rig-halfpeek-light.js +0 -4
  99. package/lib/client.rig-peek-dark.js +0 -4
  100. package/lib/client.rig-peek-light.js +0 -4
  101. package/lib/client.rig-seated-dark.js +0 -4
  102. package/lib/client.rig-seated-light.js +0 -4
  103. package/lib/composer-avatar.d.ts +0 -18
  104. package/lib/composer-avatar.js +0 -441
  105. package/lib/composer-draft-preview.d.ts +0 -4
  106. package/lib/composer-draft-preview.js +0 -8
  107. package/lib/composer-send-heixiu.d.ts +0 -8
  108. package/lib/composer-send-heixiu.js +0 -133
  109. package/lib/current-session.d.ts +0 -6
  110. package/lib/current-session.js +0 -5
  111. package/lib/decorations-entry.d.ts +0 -3
  112. package/lib/decorations-entry.js +0 -18
  113. package/lib/deferred-decorations.d.ts +0 -3
  114. package/lib/deferred-decorations.js +0 -51
  115. package/lib/gaze.d.ts +0 -4
  116. package/lib/gaze.js +0 -230
  117. package/lib/generated-backgrounds.d.ts +0 -14
  118. package/lib/generated-backgrounds.js +0 -14
  119. package/lib/generated-character-motion.d.ts +0 -4
  120. package/lib/generated-character-motion.js +0 -2
  121. package/lib/generated-identity.d.ts +0 -6
  122. package/lib/generated-identity.js +0 -6
  123. package/lib/generated-keyart.d.ts +0 -34
  124. package/lib/generated-keyart.js +0 -34
  125. package/lib/generated-loading-assets.d.ts +0 -4
  126. package/lib/generated-loading-assets.js +0 -4
  127. package/lib/heixiu-interactions.d.ts +0 -10
  128. package/lib/heixiu-interactions.js +0 -161
  129. package/lib/host-contract.d.ts +0 -9
  130. package/lib/host-contract.js +0 -13
  131. package/lib/host-dom.d.ts +0 -11
  132. package/lib/host-dom.js +0 -68
  133. package/lib/loading-heixiu.d.ts +0 -8
  134. package/lib/loading-heixiu.js +0 -287
  135. package/lib/metallic-brand-mark.d.ts +0 -10
  136. package/lib/metallic-brand-mark.js +0 -296
  137. package/lib/plugin.d.ts +0 -6
  138. package/lib/plugin.js +0 -60
  139. package/lib/portal.d.ts +0 -40
  140. package/lib/portal.js +0 -225
  141. package/lib/reactions.d.ts +0 -20
  142. package/lib/reactions.js +0 -380
  143. package/lib/scene/avatar-model.d.ts +0 -6
  144. package/lib/scene/avatar-model.js +0 -646
  145. package/lib/scene/avatar-motion.d.ts +0 -3
  146. package/lib/scene/avatar-motion.js +0 -799
  147. package/lib/scene/character-assets.d.ts +0 -13
  148. package/lib/scene/character-assets.js +0 -26
  149. package/lib/scene/character-expression.d.ts +0 -4
  150. package/lib/scene/character-expression.js +0 -15
  151. package/lib/scene/character-eye-material.d.ts +0 -13
  152. package/lib/scene/character-eye-material.js +0 -88
  153. package/lib/scene/character-eye-renderer.d.ts +0 -5
  154. package/lib/scene/character-eye-renderer.js +0 -80
  155. package/lib/scene/character-eye-rig.d.ts +0 -20
  156. package/lib/scene/character-eye-rig.js +0 -35
  157. package/lib/scene/character-gaze.d.ts +0 -16
  158. package/lib/scene/character-gaze.js +0 -36
  159. package/lib/scene/character-idle.d.ts +0 -17
  160. package/lib/scene/character-idle.js +0 -65
  161. package/lib/scene/character-layout.d.ts +0 -24
  162. package/lib/scene/character-layout.js +0 -51
  163. package/lib/scene/character-motion-clock.d.ts +0 -18
  164. package/lib/scene/character-motion-clock.js +0 -70
  165. package/lib/scene/character-motion-types.d.ts +0 -12
  166. package/lib/scene/character-motion-types.js +0 -2
  167. package/lib/scene/character-motion.d.ts +0 -6
  168. package/lib/scene/character-motion.js +0 -187
  169. package/lib/scene/character-poses.d.ts +0 -26
  170. package/lib/scene/character-poses.js +0 -11
  171. package/lib/scene/character-rig-renderer.d.ts +0 -5
  172. package/lib/scene/character-rig-renderer.js +0 -95
  173. package/lib/scene/character-rig.d.ts +0 -22
  174. package/lib/scene/character-rig.js +0 -61
  175. package/lib/scene/heixiu-feedback.d.ts +0 -3
  176. package/lib/scene/heixiu-feedback.js +0 -64
  177. package/lib/scene/heixiu-interactions.d.ts +0 -3
  178. package/lib/scene/heixiu-interactions.js +0 -92
  179. package/lib/scene/ids.d.ts +0 -5
  180. package/lib/scene/ids.js +0 -5
  181. package/lib/scene/pointer-bridge.d.ts +0 -21
  182. package/lib/scene/pointer-bridge.js +0 -155
  183. package/lib/scene/runtime.d.ts +0 -12
  184. package/lib/scene/runtime.js +0 -74
  185. package/lib/scene/state-transitions.d.ts +0 -3
  186. package/lib/scene/state-transitions.js +0 -37
  187. package/lib/scene/styles.d.ts +0 -5
  188. package/lib/scene/styles.js +0 -69
  189. package/lib/scene/sylva-performance.d.ts +0 -11
  190. package/lib/scene/sylva-performance.js +0 -58
  191. package/lib/scene/wallpaper-character-styles.d.ts +0 -3
  192. package/lib/scene/wallpaper-character-styles.js +0 -49
  193. package/lib/scene/wallpaper-character.d.ts +0 -5
  194. package/lib/scene/wallpaper-character.js +0 -222
  195. package/lib/scene.d.ts +0 -8
  196. package/lib/scene.js +0 -8
  197. package/lib/sidebar-glass.d.ts +0 -16
  198. package/lib/sidebar-glass.js +0 -168
  199. package/lib/sidebar-heixiu-escape.d.ts +0 -44
  200. package/lib/sidebar-heixiu-escape.js +0 -340
  201. package/lib/sidebar-heixiu-roaming.d.ts +0 -27
  202. package/lib/sidebar-heixiu-roaming.js +0 -310
  203. package/lib/sidebar-reveal.d.ts +0 -8
  204. package/lib/sidebar-reveal.js +0 -59
  205. package/lib/state.d.ts +0 -21
  206. package/lib/state.js +0 -123
  207. package/lib/theme.d.ts +0 -19
  208. package/lib/theme.js +0 -188
  209. package/lib/vendor/bloub/decor.d.ts +0 -114
  210. package/lib/vendor/bloub/decor.js +0 -198
  211. package/lib/vendor/bloub/engine.d.ts +0 -213
  212. package/lib/vendor/bloub/engine.js +0 -452
  213. package/lib/vendor/bloub/expressions.d.ts +0 -35
  214. package/lib/vendor/bloub/expressions.js +0 -143
  215. package/lib/vendor/bloub/eyefit.d.ts +0 -75
  216. package/lib/vendor/bloub/eyefit.js +0 -393
  217. package/lib/vendor/bloub/face.d.ts +0 -63
  218. package/lib/vendor/bloub/face.js +0 -106
  219. package/lib/vendor/bloub/math.d.ts +0 -22
  220. package/lib/vendor/bloub/math.js +0 -36
  221. package/lib/vendor/bloub/profiles.d.ts +0 -8
  222. package/lib/vendor/bloub/profiles.js +0 -20
  223. package/lib/vendor/bloub/repere.d.ts +0 -30
  224. package/lib/vendor/bloub/repere.js +0 -32
  225. package/lib/vendor/bloub/shape.d.ts +0 -80
  226. package/lib/vendor/bloub/shape.js +0 -268
  227. package/lib/vendor/bloub/skins.d.ts +0 -36
  228. package/lib/vendor/bloub/skins.js +0 -74
  229. package/lib/vendor/bloub/states.d.ts +0 -87
  230. package/lib/vendor/bloub/states.js +0 -468
package/lib/reactions.js DELETED
@@ -1,380 +0,0 @@
1
- import { XIAOHEI_IDLE_EAR_LEFT, XIAOHEI_IDLE_EAR_RIGHT, XIAOHEI_IDLE_TAIL, } from './generated-keyart.js';
2
- import { XIAOHEI_REACTION_CSS } from './chrome/reactions.js';
3
- import { subscribeXiaoheiHostDom } from './host-dom.js';
4
- import { XIAOHEI_HEIXIU_GREETING_EVENT, } from './heixiu-interactions.js';
5
- import { XIAOHEI_PORTAL_PROXIMITY_EVENT, } from './portal.js';
6
- export const XIAOHEI_REACTION_STYLE_ID = 'dsh-theme-xiaohei/reaction-style';
7
- const EAR_DELAY_MS = 190;
8
- const HEIXIU_EAR_DELAY_MS = 180;
9
- const HEIXIU_INTERACTION_DURATION_MS = 800;
10
- const EAR_DURATION_MS = 560;
11
- const TAIL_SLOW_DURATION_MS = 1280;
12
- const TAIL_COMPLETE_DURATION_MS = 700;
13
- const IDLE_TAIL_MIN_DELAY_MS = 12_000;
14
- const IDLE_TAIL_DELAY_RANGE_MS = 12_000;
15
- const LEFT_EAR_CENTER_X = 84 / 256;
16
- const LEFT_EAR_CENTER_Y = 62 / 256;
17
- const RIGHT_EAR_CENTER_X = 166 / 256;
18
- const RIGHT_EAR_CENTER_Y = 82 / 256;
19
- const EAR_POINTER_ENTER_RADIUS_X = 34 / 256;
20
- const EAR_POINTER_ENTER_RADIUS_Y = 42 / 256;
21
- const EAR_POINTER_EXIT_RADIUS_X = 40 / 256;
22
- const EAR_POINTER_EXIT_RADIUS_Y = 48 / 256;
23
- /** Resolve a pointer only inside the two local, non-overlapping ear regions. */
24
- export function resolveXiaoheiPointerEar(bounds, target, activeEar) {
25
- if (bounds.width <= 0 || bounds.height <= 0)
26
- return undefined;
27
- const normalizedDistance = (ear, radiusX, radiusY) => {
28
- const centerX = ear === 'ear-left' ? LEFT_EAR_CENTER_X : RIGHT_EAR_CENTER_X;
29
- const centerY = ear === 'ear-left' ? LEFT_EAR_CENTER_Y : RIGHT_EAR_CENTER_Y;
30
- const dx = (target.x - (bounds.left + bounds.width * centerX)) / (bounds.width * radiusX);
31
- const dy = (target.y - (bounds.top + bounds.height * centerY)) / (bounds.height * radiusY);
32
- return Math.hypot(dx, dy);
33
- };
34
- const entering = ['ear-left', 'ear-right']
35
- .map((ear) => ({
36
- ear,
37
- distance: normalizedDistance(ear, EAR_POINTER_ENTER_RADIUS_X, EAR_POINTER_ENTER_RADIUS_Y),
38
- }))
39
- .filter(({ distance }) => distance <= 1)
40
- .sort((left, right) => left.distance - right.distance)[0];
41
- if (entering !== undefined)
42
- return entering.ear;
43
- if (activeEar !== undefined
44
- && normalizedDistance(activeEar, EAR_POINTER_EXIT_RADIUS_X, EAR_POINTER_EXIT_RADIUS_Y) <= 1) {
45
- return activeEar;
46
- }
47
- return undefined;
48
- }
49
- /** Resolve the next sparse tail visit; exported to keep the timing contract testable. */
50
- export function resolveXiaoheiIdleTailDelay(randomValue = Math.random()) {
51
- const normalized = Math.min(1, Math.max(0, randomValue));
52
- return IDLE_TAIL_MIN_DELAY_MS + Math.round(normalized * IDLE_TAIL_DELAY_RANGE_MS);
53
- }
54
- /** Install proximity ear motion and sparse idle tails without a JavaScript frame loop. */
55
- export function installXiaoheiIdleReactions(doc = typeof document === 'undefined' ? undefined : document) {
56
- if (doc?.body === undefined || doc.defaultView === null)
57
- return () => { };
58
- const win = doc.defaultView;
59
- doc.getElementById(XIAOHEI_REACTION_STYLE_ID)?.remove();
60
- const style = doc.createElement('style');
61
- style.id = XIAOHEI_REACTION_STYLE_ID;
62
- style.textContent = XIAOHEI_REACTION_CSS;
63
- doc.head.append(style);
64
- const reducedMotion = win.matchMedia('(prefers-reduced-motion: reduce)');
65
- const coarsePointer = win.matchMedia('(hover: none) and (pointer: coarse)');
66
- const preloads = [XIAOHEI_IDLE_EAR_LEFT, XIAOHEI_IDLE_EAR_RIGHT, XIAOHEI_IDLE_TAIL]
67
- .map((source) => {
68
- const image = new win.Image();
69
- image.decoding = 'async';
70
- image.src = source;
71
- return image;
72
- });
73
- let disposed = false;
74
- let mascot;
75
- let reactionLayer;
76
- let pointer;
77
- let pointerEar;
78
- let previousState = currentState(doc);
79
- let reactionTimer = 0;
80
- let pendingEarTimer = 0;
81
- let heixiuEarTimer = 0;
82
- let heixiuInteractionTimer = 0;
83
- let idleTailTimer = 0;
84
- const behaviorDisabled = () => reducedMotion.matches || coarsePointer.matches;
85
- const isIdle = () => currentState(doc) === 'idle' && doc.visibilityState !== 'hidden';
86
- const clearTimer = (timer) => {
87
- if (timer !== 0)
88
- win.clearTimeout(timer);
89
- };
90
- const clearPendingEar = () => {
91
- clearTimer(pendingEarTimer);
92
- pendingEarTimer = 0;
93
- };
94
- const clearHeixiuEar = () => {
95
- clearTimer(heixiuEarTimer);
96
- heixiuEarTimer = 0;
97
- };
98
- const clearHeixiuInteraction = () => {
99
- clearTimer(heixiuInteractionTimer);
100
- heixiuInteractionTimer = 0;
101
- mascot?.removeAttribute('data-xiaohei-heixiu-interaction');
102
- };
103
- const clearReaction = () => {
104
- clearTimer(reactionTimer);
105
- reactionTimer = 0;
106
- mascot?.removeAttribute('data-xiaohei-reaction');
107
- mascot?.removeAttribute('data-xiaohei-ear-loop');
108
- reactionLayer?.removeAttribute('data-reaction');
109
- };
110
- const sourceFor = (reaction) => {
111
- if (reaction === 'ear-left')
112
- return XIAOHEI_IDLE_EAR_LEFT;
113
- if (reaction === 'ear-right')
114
- return XIAOHEI_IDLE_EAR_RIGHT;
115
- return XIAOHEI_IDLE_TAIL;
116
- };
117
- const play = (reaction, durationMs) => {
118
- if (disposed || behaviorDisabled() || !isIdle() || mascot === undefined || reactionLayer === undefined) {
119
- return false;
120
- }
121
- if (mascot.hasAttribute('data-xiaohei-reaction'))
122
- return false;
123
- reactionLayer.src = sourceFor(reaction);
124
- reactionLayer.dataset.reaction = reaction;
125
- mascot.dataset.xiaoheiReaction = reaction;
126
- reactionTimer = win.setTimeout(() => {
127
- reactionTimer = 0;
128
- mascot?.removeAttribute('data-xiaohei-reaction');
129
- reactionLayer?.removeAttribute('data-reaction');
130
- }, durationMs + 40);
131
- return true;
132
- };
133
- const playEar = (ear) => {
134
- play(ear, EAR_DURATION_MS);
135
- };
136
- const setEarFrame = (ear) => {
137
- if (mascot === undefined || reactionLayer === undefined)
138
- return;
139
- reactionLayer.src = sourceFor(ear);
140
- reactionLayer.dataset.reaction = ear;
141
- mascot.dataset.xiaoheiReaction = ear;
142
- };
143
- const stopPointerEarLoop = () => {
144
- clearPendingEar();
145
- if (mascot?.dataset.xiaoheiEarLoop === 'true')
146
- clearReaction();
147
- };
148
- const attach = () => {
149
- const nextMascot = doc.querySelector('.xiaohei-scene__mascot') ?? undefined;
150
- if (nextMascot === mascot && reactionLayer?.isConnected === true)
151
- return;
152
- clearReaction();
153
- reactionLayer?.remove();
154
- reactionLayer = undefined;
155
- mascot = nextMascot;
156
- const viewport = nextMascot?.querySelector('.xiaohei-scene__mascot-idle-viewport');
157
- if (viewport === null || viewport === undefined)
158
- return;
159
- const layer = doc.createElement('img');
160
- layer.className = 'xiaohei-scene__idle-reaction';
161
- layer.alt = '';
162
- layer.decoding = 'async';
163
- layer.fetchPriority = 'low';
164
- viewport.append(layer);
165
- reactionLayer = layer;
166
- };
167
- const earToward = (target) => {
168
- if (mascot === undefined)
169
- return undefined;
170
- const rect = mascot.getBoundingClientRect();
171
- if (rect.width <= 0 || rect.height <= 0)
172
- return undefined;
173
- const leftEar = {
174
- x: rect.left + rect.width * LEFT_EAR_CENTER_X,
175
- y: rect.top + rect.height * LEFT_EAR_CENTER_Y,
176
- };
177
- const rightEar = {
178
- x: rect.left + rect.width * RIGHT_EAR_CENTER_X,
179
- y: rect.top + rect.height * RIGHT_EAR_CENTER_Y,
180
- };
181
- const leftDistance = Math.hypot(target.x - leftEar.x, target.y - leftEar.y);
182
- const rightDistance = Math.hypot(target.x - rightEar.x, target.y - rightEar.y);
183
- return leftDistance <= rightDistance ? 'ear-left' : 'ear-right';
184
- };
185
- const startPointerEarLoop = () => {
186
- if (pointerEar === undefined || behaviorDisabled() || !isIdle())
187
- return;
188
- clearHeixiuEar();
189
- clearHeixiuInteraction();
190
- clearReaction();
191
- setEarFrame(pointerEar);
192
- if (mascot !== undefined)
193
- mascot.dataset.xiaoheiEarLoop = 'true';
194
- };
195
- const schedulePointerEarLoop = () => {
196
- if (pendingEarTimer !== 0 || mascot?.dataset.xiaoheiEarLoop === 'true')
197
- return;
198
- if (pointerEar === undefined || behaviorDisabled() || !isIdle())
199
- return;
200
- pendingEarTimer = win.setTimeout(() => {
201
- pendingEarTimer = 0;
202
- startPointerEarLoop();
203
- }, EAR_DELAY_MS);
204
- };
205
- const refreshPointerEarDirection = () => {
206
- if (mascot?.dataset.xiaoheiEarLoop !== 'true' || pointerEar === undefined)
207
- return;
208
- if (mascot.dataset.xiaoheiReaction === pointerEar)
209
- return;
210
- setEarFrame(pointerEar);
211
- };
212
- const syncPointerEarLoop = () => {
213
- const rect = mascot?.getBoundingClientRect();
214
- pointerEar = pointer !== undefined && rect !== undefined
215
- ? resolveXiaoheiPointerEar(rect, pointer, pointerEar)
216
- : undefined;
217
- if (pointerEar !== undefined) {
218
- schedulePointerEarLoop();
219
- refreshPointerEarDirection();
220
- }
221
- else {
222
- stopPointerEarLoop();
223
- }
224
- };
225
- const scheduleIdleTail = () => {
226
- clearTimer(idleTailTimer);
227
- idleTailTimer = 0;
228
- if (disposed || behaviorDisabled() || !isIdle())
229
- return;
230
- const delay = resolveXiaoheiIdleTailDelay();
231
- idleTailTimer = win.setTimeout(() => {
232
- idleTailTimer = 0;
233
- play('tail-slow', TAIL_SLOW_DURATION_MS);
234
- scheduleIdleTail();
235
- }, delay);
236
- };
237
- const onPointerMove = (event) => {
238
- if (event.pointerType === 'touch') {
239
- pointer = undefined;
240
- pointerEar = undefined;
241
- stopPointerEarLoop();
242
- return;
243
- }
244
- pointer = { x: event.clientX, y: event.clientY };
245
- syncPointerEarLoop();
246
- };
247
- const clearPointer = () => {
248
- pointer = undefined;
249
- pointerEar = undefined;
250
- stopPointerEarLoop();
251
- };
252
- const onPortalProximity = (event) => {
253
- const detail = event.detail;
254
- const active = Boolean(detail?.active);
255
- if (!active) {
256
- clearHeixiuEar();
257
- clearHeixiuInteraction();
258
- return;
259
- }
260
- if (pointerEar !== undefined || !isIdle() || detail.target === undefined || mascot === undefined)
261
- return;
262
- startHeixiuInteraction(detail.target, false);
263
- };
264
- const startHeixiuInteraction = (target, supersedePointer) => {
265
- if (!isIdle() || behaviorDisabled() || mascot === undefined)
266
- return;
267
- if (pointerEar !== undefined && !supersedePointer)
268
- return;
269
- if (supersedePointer)
270
- stopPointerEarLoop();
271
- clearHeixiuInteraction();
272
- mascot.dataset.xiaoheiHeixiuInteraction = 'true';
273
- heixiuInteractionTimer = win.setTimeout(() => {
274
- heixiuInteractionTimer = 0;
275
- mascot?.removeAttribute('data-xiaohei-heixiu-interaction');
276
- syncPointerEarLoop();
277
- }, HEIXIU_INTERACTION_DURATION_MS);
278
- clearHeixiuEar();
279
- heixiuEarTimer = win.setTimeout(() => {
280
- heixiuEarTimer = 0;
281
- const ear = earToward(target);
282
- if (ear !== undefined)
283
- playEar(ear);
284
- }, HEIXIU_EAR_DELAY_MS);
285
- };
286
- const onHeixiuGreeting = (event) => {
287
- const detail = event.detail;
288
- if (detail?.target === undefined)
289
- return;
290
- startHeixiuInteraction(detail.target, true);
291
- };
292
- const onStateChange = () => {
293
- const nextState = currentState(doc);
294
- if (nextState === previousState)
295
- return;
296
- const cameFromComplete = previousState === 'complete' && nextState === 'idle';
297
- previousState = nextState;
298
- clearPendingEar();
299
- clearHeixiuEar();
300
- clearHeixiuInteraction();
301
- clearTimer(idleTailTimer);
302
- idleTailTimer = 0;
303
- if (nextState !== 'idle') {
304
- clearReaction();
305
- pointerEar = undefined;
306
- return;
307
- }
308
- if (cameFromComplete)
309
- play('tail-complete', TAIL_COMPLETE_DURATION_MS);
310
- scheduleIdleTail();
311
- syncPointerEarLoop();
312
- };
313
- const onVisibilityChange = () => {
314
- clearPendingEar();
315
- clearHeixiuEar();
316
- clearHeixiuInteraction();
317
- clearTimer(idleTailTimer);
318
- idleTailTimer = 0;
319
- if (doc.visibilityState === 'hidden') {
320
- pointerEar = undefined;
321
- clearReaction();
322
- }
323
- else {
324
- scheduleIdleTail();
325
- syncPointerEarLoop();
326
- }
327
- };
328
- const onPreferenceChange = () => {
329
- clearPendingEar();
330
- clearHeixiuEar();
331
- clearHeixiuInteraction();
332
- clearReaction();
333
- scheduleIdleTail();
334
- syncPointerEarLoop();
335
- };
336
- const unsubscribeHostDom = subscribeXiaoheiHostDom(doc, attach);
337
- const stateObserver = new win.MutationObserver(onStateChange);
338
- stateObserver.observe(doc.documentElement, {
339
- attributes: true,
340
- attributeFilter: ['data-xiaohei-state'],
341
- });
342
- doc.addEventListener('pointermove', onPointerMove, { passive: true });
343
- doc.addEventListener('pointerleave', clearPointer);
344
- doc.addEventListener('visibilitychange', onVisibilityChange);
345
- doc.addEventListener(XIAOHEI_PORTAL_PROXIMITY_EVENT, onPortalProximity);
346
- doc.addEventListener(XIAOHEI_HEIXIU_GREETING_EVENT, onHeixiuGreeting);
347
- win.addEventListener('blur', clearPointer);
348
- reducedMotion.addEventListener('change', onPreferenceChange);
349
- coarsePointer.addEventListener('change', onPreferenceChange);
350
- attach();
351
- scheduleIdleTail();
352
- return () => {
353
- disposed = true;
354
- clearPendingEar();
355
- clearHeixiuEar();
356
- clearHeixiuInteraction();
357
- clearTimer(idleTailTimer);
358
- clearReaction();
359
- unsubscribeHostDom();
360
- stateObserver.disconnect();
361
- doc.removeEventListener('pointermove', onPointerMove);
362
- doc.removeEventListener('pointerleave', clearPointer);
363
- doc.removeEventListener('visibilitychange', onVisibilityChange);
364
- doc.removeEventListener(XIAOHEI_PORTAL_PROXIMITY_EVENT, onPortalProximity);
365
- doc.removeEventListener(XIAOHEI_HEIXIU_GREETING_EVENT, onHeixiuGreeting);
366
- win.removeEventListener('blur', clearPointer);
367
- reducedMotion.removeEventListener('change', onPreferenceChange);
368
- coarsePointer.removeEventListener('change', onPreferenceChange);
369
- reactionLayer?.remove();
370
- mascot?.removeAttribute('data-xiaohei-reaction');
371
- mascot?.removeAttribute('data-xiaohei-ear-loop');
372
- mascot?.removeAttribute('data-xiaohei-heixiu-interaction');
373
- preloads.length = 0;
374
- style.remove();
375
- };
376
- }
377
- function currentState(doc) {
378
- return doc.documentElement.getAttribute('data-xiaohei-state') ?? 'idle';
379
- }
380
- //# sourceMappingURL=reactions.js.map
@@ -1,6 +0,0 @@
1
- export declare const XIAOHEI_SYLVA_AVATAR_MARKER = "data-xiaohei-avatar-model";
2
- /** Inject the renderer-sharing 2.5D avatar without editing registered ThreeUI files. */
3
- export declare function injectXiaoheiSylvaAvatarModel(source: string): string;
4
- /** Prepare the detached iframe so the avatar exists on its first WebGL boot. */
5
- export declare function prepareXiaoheiSylvaAvatarFrame(frame: HTMLIFrameElement): boolean;
6
- //# sourceMappingURL=avatar-model.d.ts.map