@lemoncat7/dsh-theme-xiaohei 0.4.6 → 0.5.1

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 (232) hide show
  1. package/README.md +15 -9
  2. package/THIRD_PARTY_NOTICES.md +13 -1
  3. package/docs/dsh-021-compatibility.md +23 -0
  4. package/docs/releases/0.5.0.md +24 -0
  5. package/docs/rift-interaction.md +35 -0
  6. package/docs/rift-preview.md +39 -0
  7. package/lib/client.companion.js +3 -4
  8. package/lib/client.decorations.js +224 -51
  9. package/lib/client.js +534 -2405
  10. package/lib/index.d.ts +1 -2
  11. package/lib/index.js +395 -11
  12. package/lib/rift/boot.d.ts +6 -0
  13. package/package.json +29 -19
  14. package/lib/appearance.d.ts +0 -12
  15. package/lib/appearance.js +0 -42
  16. package/lib/blink.d.ts +0 -4
  17. package/lib/blink.js +0 -110
  18. package/lib/bloub-heixiu/ambient.d.ts +0 -3
  19. package/lib/bloub-heixiu/ambient.js +0 -12
  20. package/lib/bloub-heixiu/character.d.ts +0 -33
  21. package/lib/bloub-heixiu/character.js +0 -124
  22. package/lib/bloub-heixiu/effects.d.ts +0 -4
  23. package/lib/bloub-heixiu/effects.js +0 -91
  24. package/lib/bloub-heixiu/flight.d.ts +0 -15
  25. package/lib/bloub-heixiu/flight.js +0 -66
  26. package/lib/bloub-heixiu/follow.d.ts +0 -13
  27. package/lib/bloub-heixiu/follow.js +0 -23
  28. package/lib/bloub-heixiu/layout.d.ts +0 -34
  29. package/lib/bloub-heixiu/layout.js +0 -26
  30. package/lib/bloub-heixiu/renderer.d.ts +0 -16
  31. package/lib/bloub-heixiu/renderer.js +0 -94
  32. package/lib/bloub-heixiu/runtime.d.ts +0 -6
  33. package/lib/bloub-heixiu/runtime.js +0 -440
  34. package/lib/bloub-heixiu/signals.d.ts +0 -17
  35. package/lib/bloub-heixiu/signals.js +0 -55
  36. package/lib/bloub-heixiu/styles.d.ts +0 -2
  37. package/lib/bloub-heixiu/styles.js +0 -98
  38. package/lib/boot-appearance.d.ts +0 -10
  39. package/lib/boot-appearance.js +0 -47
  40. package/lib/boot-loader.d.ts +0 -5
  41. package/lib/boot-loader.js +0 -158
  42. package/lib/chrome/accessibility.d.ts +0 -3
  43. package/lib/chrome/accessibility.js +0 -69
  44. package/lib/chrome/blink.d.ts +0 -3
  45. package/lib/chrome/blink.js +0 -15
  46. package/lib/chrome/composer-avatar.d.ts +0 -10
  47. package/lib/chrome/composer-avatar.js +0 -599
  48. package/lib/chrome/composer-send-heixiu.d.ts +0 -3
  49. package/lib/chrome/composer-send-heixiu.js +0 -143
  50. package/lib/chrome/composer.d.ts +0 -3
  51. package/lib/chrome/composer.js +0 -135
  52. package/lib/chrome/controls.d.ts +0 -8
  53. package/lib/chrome/controls.js +0 -348
  54. package/lib/chrome/conversation-messages.d.ts +0 -3
  55. package/lib/chrome/conversation-messages.js +0 -329
  56. package/lib/chrome/conversation-submissions.d.ts +0 -3
  57. package/lib/chrome/conversation-submissions.js +0 -68
  58. package/lib/chrome/conversation.d.ts +0 -3
  59. package/lib/chrome/conversation.js +0 -67
  60. package/lib/chrome/frames.d.ts +0 -6
  61. package/lib/chrome/frames.js +0 -134
  62. package/lib/chrome/gaze.d.ts +0 -3
  63. package/lib/chrome/gaze.js +0 -103
  64. package/lib/chrome/identity.d.ts +0 -6
  65. package/lib/chrome/identity.js +0 -47
  66. package/lib/chrome/overlays.d.ts +0 -3
  67. package/lib/chrome/overlays.js +0 -104
  68. package/lib/chrome/portal.d.ts +0 -6
  69. package/lib/chrome/portal.js +0 -169
  70. package/lib/chrome/reactions.d.ts +0 -3
  71. package/lib/chrome/reactions.js +0 -85
  72. package/lib/chrome/sidebar.d.ts +0 -3
  73. package/lib/chrome/sidebar.js +0 -313
  74. package/lib/chrome/tokens.d.ts +0 -3
  75. package/lib/chrome/tokens.js +0 -224
  76. package/lib/chrome/workspace.d.ts +0 -3
  77. package/lib/chrome/workspace.js +0 -94
  78. package/lib/chrome.d.ts +0 -10
  79. package/lib/chrome.js +0 -46
  80. package/lib/client-entry.d.ts +0 -3
  81. package/lib/client-entry.js +0 -3
  82. package/lib/client.d.ts +0 -10
  83. package/lib/client.pose-chin-dark.js +0 -4
  84. package/lib/client.pose-chin-light.js +0 -4
  85. package/lib/client.pose-doze-dark.js +0 -4
  86. package/lib/client.pose-doze-light.js +0 -4
  87. package/lib/client.pose-halfpeek-dark.js +0 -4
  88. package/lib/client.pose-halfpeek-light.js +0 -4
  89. package/lib/client.pose-peek-dark.js +0 -4
  90. package/lib/client.pose-peek-light.js +0 -4
  91. package/lib/client.pose-seated-dark.js +0 -4
  92. package/lib/client.pose-seated-light.js +0 -4
  93. package/lib/client.rig-chin-dark.js +0 -4
  94. package/lib/client.rig-chin-light.js +0 -4
  95. package/lib/client.rig-halfpeek-dark.js +0 -4
  96. package/lib/client.rig-halfpeek-light.js +0 -4
  97. package/lib/client.rig-peek-dark.js +0 -4
  98. package/lib/client.rig-peek-light.js +0 -4
  99. package/lib/client.rig-seated-dark.js +0 -4
  100. package/lib/client.rig-seated-light.js +0 -4
  101. package/lib/companion-entry.d.ts +0 -3
  102. package/lib/companion-entry.js +0 -3
  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-companion.d.ts +0 -5
  114. package/lib/deferred-companion.js +0 -9
  115. package/lib/deferred-decorations.d.ts +0 -3
  116. package/lib/deferred-decorations.js +0 -51
  117. package/lib/gaze.d.ts +0 -4
  118. package/lib/gaze.js +0 -230
  119. package/lib/generated-backgrounds.d.ts +0 -14
  120. package/lib/generated-backgrounds.js +0 -14
  121. package/lib/generated-character-motion.d.ts +0 -4
  122. package/lib/generated-character-motion.js +0 -2
  123. package/lib/generated-identity.d.ts +0 -6
  124. package/lib/generated-identity.js +0 -6
  125. package/lib/generated-keyart.d.ts +0 -34
  126. package/lib/generated-keyart.js +0 -34
  127. package/lib/generated-loading-assets.d.ts +0 -4
  128. package/lib/generated-loading-assets.js +0 -4
  129. package/lib/heixiu-interactions.d.ts +0 -10
  130. package/lib/heixiu-interactions.js +0 -161
  131. package/lib/host-contract.d.ts +0 -9
  132. package/lib/host-contract.js +0 -13
  133. package/lib/host-dom.d.ts +0 -11
  134. package/lib/host-dom.js +0 -72
  135. package/lib/loading-heixiu.d.ts +0 -8
  136. package/lib/loading-heixiu.js +0 -287
  137. package/lib/metallic-brand-mark.d.ts +0 -10
  138. package/lib/metallic-brand-mark.js +0 -296
  139. package/lib/plugin.d.ts +0 -6
  140. package/lib/plugin.js +0 -60
  141. package/lib/portal.d.ts +0 -40
  142. package/lib/portal.js +0 -225
  143. package/lib/reactions.d.ts +0 -20
  144. package/lib/reactions.js +0 -380
  145. package/lib/scene/avatar-model.d.ts +0 -6
  146. package/lib/scene/avatar-model.js +0 -646
  147. package/lib/scene/avatar-motion.d.ts +0 -3
  148. package/lib/scene/avatar-motion.js +0 -799
  149. package/lib/scene/character-assets.d.ts +0 -13
  150. package/lib/scene/character-assets.js +0 -26
  151. package/lib/scene/character-expression.d.ts +0 -4
  152. package/lib/scene/character-expression.js +0 -15
  153. package/lib/scene/character-eye-material.d.ts +0 -13
  154. package/lib/scene/character-eye-material.js +0 -88
  155. package/lib/scene/character-eye-renderer.d.ts +0 -5
  156. package/lib/scene/character-eye-renderer.js +0 -80
  157. package/lib/scene/character-eye-rig.d.ts +0 -20
  158. package/lib/scene/character-eye-rig.js +0 -35
  159. package/lib/scene/character-gaze.d.ts +0 -16
  160. package/lib/scene/character-gaze.js +0 -36
  161. package/lib/scene/character-idle.d.ts +0 -17
  162. package/lib/scene/character-idle.js +0 -65
  163. package/lib/scene/character-layout.d.ts +0 -24
  164. package/lib/scene/character-layout.js +0 -51
  165. package/lib/scene/character-motion-clock.d.ts +0 -18
  166. package/lib/scene/character-motion-clock.js +0 -70
  167. package/lib/scene/character-motion-types.d.ts +0 -12
  168. package/lib/scene/character-motion-types.js +0 -2
  169. package/lib/scene/character-motion.d.ts +0 -6
  170. package/lib/scene/character-motion.js +0 -187
  171. package/lib/scene/character-poses.d.ts +0 -26
  172. package/lib/scene/character-poses.js +0 -11
  173. package/lib/scene/character-rig-renderer.d.ts +0 -5
  174. package/lib/scene/character-rig-renderer.js +0 -95
  175. package/lib/scene/character-rig.d.ts +0 -22
  176. package/lib/scene/character-rig.js +0 -61
  177. package/lib/scene/heixiu-feedback.d.ts +0 -3
  178. package/lib/scene/heixiu-feedback.js +0 -64
  179. package/lib/scene/heixiu-interactions.d.ts +0 -3
  180. package/lib/scene/heixiu-interactions.js +0 -92
  181. package/lib/scene/ids.d.ts +0 -5
  182. package/lib/scene/ids.js +0 -5
  183. package/lib/scene/pointer-bridge.d.ts +0 -21
  184. package/lib/scene/pointer-bridge.js +0 -155
  185. package/lib/scene/runtime.d.ts +0 -12
  186. package/lib/scene/runtime.js +0 -74
  187. package/lib/scene/state-transitions.d.ts +0 -3
  188. package/lib/scene/state-transitions.js +0 -37
  189. package/lib/scene/styles.d.ts +0 -5
  190. package/lib/scene/styles.js +0 -69
  191. package/lib/scene/sylva-performance.d.ts +0 -11
  192. package/lib/scene/sylva-performance.js +0 -58
  193. package/lib/scene/wallpaper-character-styles.d.ts +0 -3
  194. package/lib/scene/wallpaper-character-styles.js +0 -49
  195. package/lib/scene/wallpaper-character.d.ts +0 -5
  196. package/lib/scene/wallpaper-character.js +0 -222
  197. package/lib/scene.d.ts +0 -8
  198. package/lib/scene.js +0 -8
  199. package/lib/sidebar-glass.d.ts +0 -16
  200. package/lib/sidebar-glass.js +0 -168
  201. package/lib/sidebar-heixiu-escape.d.ts +0 -44
  202. package/lib/sidebar-heixiu-escape.js +0 -340
  203. package/lib/sidebar-heixiu-roaming.d.ts +0 -27
  204. package/lib/sidebar-heixiu-roaming.js +0 -310
  205. package/lib/sidebar-reveal.d.ts +0 -8
  206. package/lib/sidebar-reveal.js +0 -59
  207. package/lib/state.d.ts +0 -21
  208. package/lib/state.js +0 -123
  209. package/lib/theme.d.ts +0 -19
  210. package/lib/theme.js +0 -188
  211. package/lib/vendor/bloub/decor.d.ts +0 -114
  212. package/lib/vendor/bloub/decor.js +0 -198
  213. package/lib/vendor/bloub/engine.d.ts +0 -213
  214. package/lib/vendor/bloub/engine.js +0 -452
  215. package/lib/vendor/bloub/expressions.d.ts +0 -35
  216. package/lib/vendor/bloub/expressions.js +0 -143
  217. package/lib/vendor/bloub/eyefit.d.ts +0 -75
  218. package/lib/vendor/bloub/eyefit.js +0 -393
  219. package/lib/vendor/bloub/face.d.ts +0 -63
  220. package/lib/vendor/bloub/face.js +0 -106
  221. package/lib/vendor/bloub/math.d.ts +0 -22
  222. package/lib/vendor/bloub/math.js +0 -36
  223. package/lib/vendor/bloub/profiles.d.ts +0 -8
  224. package/lib/vendor/bloub/profiles.js +0 -20
  225. package/lib/vendor/bloub/repere.d.ts +0 -30
  226. package/lib/vendor/bloub/repere.js +0 -32
  227. package/lib/vendor/bloub/shape.d.ts +0 -80
  228. package/lib/vendor/bloub/shape.js +0 -268
  229. package/lib/vendor/bloub/skins.d.ts +0 -36
  230. package/lib/vendor/bloub/skins.js +0 -74
  231. package/lib/vendor/bloub/states.d.ts +0 -87
  232. 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