@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.
- package/README.md +25 -92
- package/THIRD_PARTY_NOTICES.md +13 -1
- package/docs/dsh-021-compatibility.md +23 -0
- package/docs/releases/0.4.6.md +17 -0
- package/docs/releases/0.5.0.md +24 -0
- package/docs/releases/README.md +14 -0
- package/docs/rift-interaction.md +35 -0
- package/docs/rift-preview.md +39 -0
- package/lib/client.companion.js +99 -0
- package/lib/client.decorations.js +224 -51
- package/lib/client.js +532 -2501
- package/lib/index.d.ts +1 -2
- package/lib/index.js +393 -11
- package/lib/rift/boot.d.ts +6 -0
- package/package.json +30 -19
- package/lib/appearance.d.ts +0 -12
- package/lib/appearance.js +0 -42
- package/lib/blink.d.ts +0 -4
- package/lib/blink.js +0 -110
- package/lib/bloub-heixiu/ambient.d.ts +0 -3
- package/lib/bloub-heixiu/ambient.js +0 -12
- package/lib/bloub-heixiu/character.d.ts +0 -33
- package/lib/bloub-heixiu/character.js +0 -124
- package/lib/bloub-heixiu/effects.d.ts +0 -4
- package/lib/bloub-heixiu/effects.js +0 -91
- package/lib/bloub-heixiu/flight.d.ts +0 -15
- package/lib/bloub-heixiu/flight.js +0 -66
- package/lib/bloub-heixiu/follow.d.ts +0 -13
- package/lib/bloub-heixiu/follow.js +0 -23
- package/lib/bloub-heixiu/layout.d.ts +0 -18
- package/lib/bloub-heixiu/layout.js +0 -12
- package/lib/bloub-heixiu/renderer.d.ts +0 -16
- package/lib/bloub-heixiu/renderer.js +0 -94
- package/lib/bloub-heixiu/runtime.d.ts +0 -6
- package/lib/bloub-heixiu/runtime.js +0 -409
- package/lib/bloub-heixiu/signals.d.ts +0 -17
- package/lib/bloub-heixiu/signals.js +0 -55
- package/lib/bloub-heixiu/styles.d.ts +0 -2
- package/lib/bloub-heixiu/styles.js +0 -98
- package/lib/boot-appearance.d.ts +0 -10
- package/lib/boot-appearance.js +0 -47
- package/lib/boot-loader.d.ts +0 -5
- package/lib/boot-loader.js +0 -158
- package/lib/chrome/accessibility.d.ts +0 -3
- package/lib/chrome/accessibility.js +0 -69
- package/lib/chrome/blink.d.ts +0 -3
- package/lib/chrome/blink.js +0 -15
- package/lib/chrome/composer-avatar.d.ts +0 -10
- package/lib/chrome/composer-avatar.js +0 -599
- package/lib/chrome/composer-send-heixiu.d.ts +0 -3
- package/lib/chrome/composer-send-heixiu.js +0 -143
- package/lib/chrome/composer.d.ts +0 -3
- package/lib/chrome/composer.js +0 -135
- package/lib/chrome/controls.d.ts +0 -8
- package/lib/chrome/controls.js +0 -348
- package/lib/chrome/conversation-messages.d.ts +0 -3
- package/lib/chrome/conversation-messages.js +0 -329
- package/lib/chrome/conversation-submissions.d.ts +0 -3
- package/lib/chrome/conversation-submissions.js +0 -68
- package/lib/chrome/conversation.d.ts +0 -3
- package/lib/chrome/conversation.js +0 -67
- package/lib/chrome/frames.d.ts +0 -6
- package/lib/chrome/frames.js +0 -134
- package/lib/chrome/gaze.d.ts +0 -3
- package/lib/chrome/gaze.js +0 -103
- package/lib/chrome/identity.d.ts +0 -6
- package/lib/chrome/identity.js +0 -47
- package/lib/chrome/overlays.d.ts +0 -3
- package/lib/chrome/overlays.js +0 -104
- package/lib/chrome/portal.d.ts +0 -6
- package/lib/chrome/portal.js +0 -169
- package/lib/chrome/reactions.d.ts +0 -3
- package/lib/chrome/reactions.js +0 -85
- package/lib/chrome/sidebar.d.ts +0 -3
- package/lib/chrome/sidebar.js +0 -313
- package/lib/chrome/tokens.d.ts +0 -3
- package/lib/chrome/tokens.js +0 -224
- package/lib/chrome/workspace.d.ts +0 -3
- package/lib/chrome/workspace.js +0 -94
- package/lib/chrome.d.ts +0 -10
- package/lib/chrome.js +0 -46
- package/lib/client-entry.d.ts +0 -3
- package/lib/client-entry.js +0 -3
- package/lib/client.d.ts +0 -10
- package/lib/client.pose-chin-dark.js +0 -4
- package/lib/client.pose-chin-light.js +0 -4
- package/lib/client.pose-doze-dark.js +0 -4
- package/lib/client.pose-doze-light.js +0 -4
- package/lib/client.pose-halfpeek-dark.js +0 -4
- package/lib/client.pose-halfpeek-light.js +0 -4
- package/lib/client.pose-peek-dark.js +0 -4
- package/lib/client.pose-peek-light.js +0 -4
- package/lib/client.pose-seated-dark.js +0 -4
- package/lib/client.pose-seated-light.js +0 -4
- package/lib/client.rig-chin-dark.js +0 -4
- package/lib/client.rig-chin-light.js +0 -4
- package/lib/client.rig-halfpeek-dark.js +0 -4
- package/lib/client.rig-halfpeek-light.js +0 -4
- package/lib/client.rig-peek-dark.js +0 -4
- package/lib/client.rig-peek-light.js +0 -4
- package/lib/client.rig-seated-dark.js +0 -4
- package/lib/client.rig-seated-light.js +0 -4
- package/lib/composer-avatar.d.ts +0 -18
- package/lib/composer-avatar.js +0 -441
- package/lib/composer-draft-preview.d.ts +0 -4
- package/lib/composer-draft-preview.js +0 -8
- package/lib/composer-send-heixiu.d.ts +0 -8
- package/lib/composer-send-heixiu.js +0 -133
- package/lib/current-session.d.ts +0 -6
- package/lib/current-session.js +0 -5
- package/lib/decorations-entry.d.ts +0 -3
- package/lib/decorations-entry.js +0 -18
- package/lib/deferred-decorations.d.ts +0 -3
- package/lib/deferred-decorations.js +0 -51
- package/lib/gaze.d.ts +0 -4
- package/lib/gaze.js +0 -230
- package/lib/generated-backgrounds.d.ts +0 -14
- package/lib/generated-backgrounds.js +0 -14
- package/lib/generated-character-motion.d.ts +0 -4
- package/lib/generated-character-motion.js +0 -2
- package/lib/generated-identity.d.ts +0 -6
- package/lib/generated-identity.js +0 -6
- package/lib/generated-keyart.d.ts +0 -34
- package/lib/generated-keyart.js +0 -34
- package/lib/generated-loading-assets.d.ts +0 -4
- package/lib/generated-loading-assets.js +0 -4
- package/lib/heixiu-interactions.d.ts +0 -10
- package/lib/heixiu-interactions.js +0 -161
- package/lib/host-contract.d.ts +0 -9
- package/lib/host-contract.js +0 -13
- package/lib/host-dom.d.ts +0 -11
- package/lib/host-dom.js +0 -68
- package/lib/loading-heixiu.d.ts +0 -8
- package/lib/loading-heixiu.js +0 -287
- package/lib/metallic-brand-mark.d.ts +0 -10
- package/lib/metallic-brand-mark.js +0 -296
- package/lib/plugin.d.ts +0 -6
- package/lib/plugin.js +0 -60
- package/lib/portal.d.ts +0 -40
- package/lib/portal.js +0 -225
- package/lib/reactions.d.ts +0 -20
- package/lib/reactions.js +0 -380
- package/lib/scene/avatar-model.d.ts +0 -6
- package/lib/scene/avatar-model.js +0 -646
- package/lib/scene/avatar-motion.d.ts +0 -3
- package/lib/scene/avatar-motion.js +0 -799
- package/lib/scene/character-assets.d.ts +0 -13
- package/lib/scene/character-assets.js +0 -26
- package/lib/scene/character-expression.d.ts +0 -4
- package/lib/scene/character-expression.js +0 -15
- package/lib/scene/character-eye-material.d.ts +0 -13
- package/lib/scene/character-eye-material.js +0 -88
- package/lib/scene/character-eye-renderer.d.ts +0 -5
- package/lib/scene/character-eye-renderer.js +0 -80
- package/lib/scene/character-eye-rig.d.ts +0 -20
- package/lib/scene/character-eye-rig.js +0 -35
- package/lib/scene/character-gaze.d.ts +0 -16
- package/lib/scene/character-gaze.js +0 -36
- package/lib/scene/character-idle.d.ts +0 -17
- package/lib/scene/character-idle.js +0 -65
- package/lib/scene/character-layout.d.ts +0 -24
- package/lib/scene/character-layout.js +0 -51
- package/lib/scene/character-motion-clock.d.ts +0 -18
- package/lib/scene/character-motion-clock.js +0 -70
- package/lib/scene/character-motion-types.d.ts +0 -12
- package/lib/scene/character-motion-types.js +0 -2
- package/lib/scene/character-motion.d.ts +0 -6
- package/lib/scene/character-motion.js +0 -187
- package/lib/scene/character-poses.d.ts +0 -26
- package/lib/scene/character-poses.js +0 -11
- package/lib/scene/character-rig-renderer.d.ts +0 -5
- package/lib/scene/character-rig-renderer.js +0 -95
- package/lib/scene/character-rig.d.ts +0 -22
- package/lib/scene/character-rig.js +0 -61
- package/lib/scene/heixiu-feedback.d.ts +0 -3
- package/lib/scene/heixiu-feedback.js +0 -64
- package/lib/scene/heixiu-interactions.d.ts +0 -3
- package/lib/scene/heixiu-interactions.js +0 -92
- package/lib/scene/ids.d.ts +0 -5
- package/lib/scene/ids.js +0 -5
- package/lib/scene/pointer-bridge.d.ts +0 -21
- package/lib/scene/pointer-bridge.js +0 -155
- package/lib/scene/runtime.d.ts +0 -12
- package/lib/scene/runtime.js +0 -74
- package/lib/scene/state-transitions.d.ts +0 -3
- package/lib/scene/state-transitions.js +0 -37
- package/lib/scene/styles.d.ts +0 -5
- package/lib/scene/styles.js +0 -69
- package/lib/scene/sylva-performance.d.ts +0 -11
- package/lib/scene/sylva-performance.js +0 -58
- package/lib/scene/wallpaper-character-styles.d.ts +0 -3
- package/lib/scene/wallpaper-character-styles.js +0 -49
- package/lib/scene/wallpaper-character.d.ts +0 -5
- package/lib/scene/wallpaper-character.js +0 -222
- package/lib/scene.d.ts +0 -8
- package/lib/scene.js +0 -8
- package/lib/sidebar-glass.d.ts +0 -16
- package/lib/sidebar-glass.js +0 -168
- package/lib/sidebar-heixiu-escape.d.ts +0 -44
- package/lib/sidebar-heixiu-escape.js +0 -340
- package/lib/sidebar-heixiu-roaming.d.ts +0 -27
- package/lib/sidebar-heixiu-roaming.js +0 -310
- package/lib/sidebar-reveal.d.ts +0 -8
- package/lib/sidebar-reveal.js +0 -59
- package/lib/state.d.ts +0 -21
- package/lib/state.js +0 -123
- package/lib/theme.d.ts +0 -19
- package/lib/theme.js +0 -188
- package/lib/vendor/bloub/decor.d.ts +0 -114
- package/lib/vendor/bloub/decor.js +0 -198
- package/lib/vendor/bloub/engine.d.ts +0 -213
- package/lib/vendor/bloub/engine.js +0 -452
- package/lib/vendor/bloub/expressions.d.ts +0 -35
- package/lib/vendor/bloub/expressions.js +0 -143
- package/lib/vendor/bloub/eyefit.d.ts +0 -75
- package/lib/vendor/bloub/eyefit.js +0 -393
- package/lib/vendor/bloub/face.d.ts +0 -63
- package/lib/vendor/bloub/face.js +0 -106
- package/lib/vendor/bloub/math.d.ts +0 -22
- package/lib/vendor/bloub/math.js +0 -36
- package/lib/vendor/bloub/profiles.d.ts +0 -8
- package/lib/vendor/bloub/profiles.js +0 -20
- package/lib/vendor/bloub/repere.d.ts +0 -30
- package/lib/vendor/bloub/repere.js +0 -32
- package/lib/vendor/bloub/shape.d.ts +0 -80
- package/lib/vendor/bloub/shape.js +0 -268
- package/lib/vendor/bloub/skins.d.ts +0 -36
- package/lib/vendor/bloub/skins.js +0 -74
- package/lib/vendor/bloub/states.d.ts +0 -87
- package/lib/vendor/bloub/states.js +0 -468
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
import { characterAssets } from './character-assets.js';
|
|
2
|
-
import { createCharacterMotionClock } from './character-motion-clock.js';
|
|
3
|
-
import { createRigRenderer } from './character-rig-renderer.js';
|
|
4
|
-
import { EYE_RIGS } from './character-eye-rig.js';
|
|
5
|
-
import { createCharacterGaze } from './character-gaze.js';
|
|
6
|
-
/** Owns loading and lifecycle only. Rig math and painting stay independent. */
|
|
7
|
-
export function createCharacterMotion(doc) {
|
|
8
|
-
const win = doc.defaultView, reduced = win.matchMedia('(prefers-reduced-motion: reduce)');
|
|
9
|
-
const images = new Map(), loading = new Map();
|
|
10
|
-
let disposed = false, part, rig;
|
|
11
|
-
let canvas, render;
|
|
12
|
-
let pose = '', appearance = '', revision = 0, nearby = false, lastPointer = 0;
|
|
13
|
-
let selection = '';
|
|
14
|
-
let attentionTimer, lastAttention = -Infinity;
|
|
15
|
-
let gazePoint = [0, 0], activeAction, activeProgress = 0;
|
|
16
|
-
let bounds;
|
|
17
|
-
const paint = () => { if (render && part) {
|
|
18
|
-
render(activeAction, activeProgress, gazePoint);
|
|
19
|
-
part.dataset.motion = activeAction ?? 'rig-rest';
|
|
20
|
-
} };
|
|
21
|
-
const gaze = createCharacterGaze(win, point => { gazePoint = point; paint(); });
|
|
22
|
-
const cancelAttention = () => { if (attentionTimer !== undefined)
|
|
23
|
-
win.clearTimeout(attentionTimer); attentionTimer = undefined; };
|
|
24
|
-
function decode(src) {
|
|
25
|
-
if (loading.has(src))
|
|
26
|
-
return loading.get(src);
|
|
27
|
-
if (images.has(src))
|
|
28
|
-
return Promise.resolve();
|
|
29
|
-
const image = new win.Image();
|
|
30
|
-
image.src = src;
|
|
31
|
-
const pending = image.decode().then(() => { if (!disposed)
|
|
32
|
-
images.set(src, image); }, () => { })
|
|
33
|
-
.finally(() => loading.delete(src));
|
|
34
|
-
loading.set(src, pending);
|
|
35
|
-
return pending;
|
|
36
|
-
}
|
|
37
|
-
const clock = createCharacterMotionClock(win, (action, progress) => {
|
|
38
|
-
if (!canvas || !part || !render)
|
|
39
|
-
return;
|
|
40
|
-
// Keep the same layered rest drawing after an action: no plate swap/pop.
|
|
41
|
-
activeAction = action;
|
|
42
|
-
activeProgress = progress;
|
|
43
|
-
paint();
|
|
44
|
-
});
|
|
45
|
-
function update() {
|
|
46
|
-
if (disposed)
|
|
47
|
-
return;
|
|
48
|
-
const mode = doc.documentElement.dataset.xiaoheiAppearance === 'light' ? 'light' : 'dark';
|
|
49
|
-
const moving = doc.documentElement.hasAttribute('data-xiaohei-sidebar-resizing');
|
|
50
|
-
const key = !doc.hidden && !reduced.matches && !moving && part ? `${pose}-${mode}` : '';
|
|
51
|
-
if (key === selection && appearance === mode)
|
|
52
|
-
return;
|
|
53
|
-
selection = key;
|
|
54
|
-
cancelAttention();
|
|
55
|
-
render = undefined;
|
|
56
|
-
clock.setClips(undefined);
|
|
57
|
-
gaze.reset();
|
|
58
|
-
bounds = undefined;
|
|
59
|
-
activeAction = undefined;
|
|
60
|
-
activeProgress = 0;
|
|
61
|
-
const current = ++revision;
|
|
62
|
-
canvas?.remove();
|
|
63
|
-
canvas = undefined;
|
|
64
|
-
if (part)
|
|
65
|
-
part.dataset.motion = 'rest';
|
|
66
|
-
rig = undefined;
|
|
67
|
-
appearance = mode;
|
|
68
|
-
nearby = false;
|
|
69
|
-
if (!key || !part)
|
|
70
|
-
return;
|
|
71
|
-
const currentPart = part;
|
|
72
|
-
void characterAssets.rig(pose, mode).then(async (next) => {
|
|
73
|
-
if (!next || disposed || current !== revision)
|
|
74
|
-
return;
|
|
75
|
-
await Promise.all(Object.values(next.layers).map(layer => decode(layer.src)));
|
|
76
|
-
if (disposed || current !== revision || Object.values(next.layers).some(layer => !images.get(layer.src)))
|
|
77
|
-
return;
|
|
78
|
-
rig = next;
|
|
79
|
-
canvas = doc.createElement('canvas');
|
|
80
|
-
canvas.className = 'xiaohei-character-motion';
|
|
81
|
-
canvas.width = next.size[0];
|
|
82
|
-
canvas.height = next.size[1];
|
|
83
|
-
const ctx = canvas.getContext('2d');
|
|
84
|
-
if (!ctx) {
|
|
85
|
-
canvas = undefined;
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
currentPart.append(canvas);
|
|
89
|
-
render = createRigRenderer(ctx, next, images, EYE_RIGS[pose]);
|
|
90
|
-
clock.setClips({
|
|
91
|
-
blink: { duration: 280 },
|
|
92
|
-
...Object.fromEntries(next.ears.map((_, i) => ['ear' + i, { duration: 1050 }])),
|
|
93
|
-
...(next.layers.tail ? { tail: { duration: 2400 } } : {}),
|
|
94
|
-
attention: { duration: 2400 },
|
|
95
|
-
});
|
|
96
|
-
}).catch(() => { });
|
|
97
|
-
}
|
|
98
|
-
const pointer = (event) => {
|
|
99
|
-
if (!part || !render || event.pointerType !== 'mouse')
|
|
100
|
-
return;
|
|
101
|
-
const now = win.performance.now();
|
|
102
|
-
if (!bounds || now - lastPointer >= 100) {
|
|
103
|
-
bounds = part.getBoundingClientRect();
|
|
104
|
-
lastPointer = now;
|
|
105
|
-
}
|
|
106
|
-
const rect = bounds, eyes = EYE_RIGS[pose];
|
|
107
|
-
if (rig && eyes?.length) {
|
|
108
|
-
const scale = Math.min(rect.width / rig.size[0], rect.height / rig.size[1]);
|
|
109
|
-
const eyeX = eyes.reduce((sum, eye) => sum + eye.iris[0], 0) / eyes.length / 2;
|
|
110
|
-
const eyeY = eyes.reduce((sum, eye) => sum + eye.iris[1], 0) / eyes.length / 2;
|
|
111
|
-
const cx = rect.left + eyeX * scale;
|
|
112
|
-
const cy = rect.top + (rect.height - rig.size[1] * scale) / 2 + eyeY * scale;
|
|
113
|
-
gaze.target((event.clientX - cx) / Math.max(220, win.innerWidth * .32), (event.clientY - cy) / Math.max(180, win.innerHeight * .32));
|
|
114
|
-
}
|
|
115
|
-
const near = event.clientX >= rect.left - 70 && event.clientX <= rect.right + 70
|
|
116
|
-
&& event.clientY >= rect.top - 50 && event.clientY <= rect.bottom + 50;
|
|
117
|
-
if (!near)
|
|
118
|
-
cancelAttention();
|
|
119
|
-
if (near && !nearby && now - lastAttention > 6000) {
|
|
120
|
-
const current = revision;
|
|
121
|
-
// A passing pointer should not trigger a performance. Brief dwell gives
|
|
122
|
-
// an intentional approach one quiet, coordinated response.
|
|
123
|
-
attentionTimer = win.setTimeout(() => {
|
|
124
|
-
attentionTimer = undefined;
|
|
125
|
-
if (!disposed && nearby && current === revision) {
|
|
126
|
-
lastAttention = win.performance.now();
|
|
127
|
-
clock.attention();
|
|
128
|
-
}
|
|
129
|
-
}, 180);
|
|
130
|
-
}
|
|
131
|
-
nearby = near;
|
|
132
|
-
};
|
|
133
|
-
reduced.addEventListener('change', update);
|
|
134
|
-
const neutral = () => { gaze.target(0, 0); nearby = false; cancelAttention(); };
|
|
135
|
-
const leave = (event) => { if (!event.relatedTarget)
|
|
136
|
-
neutral(); };
|
|
137
|
-
const resize = () => { bounds = undefined; };
|
|
138
|
-
doc.addEventListener('pointerout', leave);
|
|
139
|
-
win.addEventListener('blur', neutral);
|
|
140
|
-
win.addEventListener('resize', resize);
|
|
141
|
-
doc.addEventListener('visibilitychange', update);
|
|
142
|
-
doc.addEventListener('pointermove', pointer, { passive: true });
|
|
143
|
-
const observer = new win.MutationObserver(update);
|
|
144
|
-
observer.observe(doc.documentElement, { attributes: true, attributeFilter: ['data-xiaohei-appearance', 'data-xiaohei-sidebar-resizing'] });
|
|
145
|
-
return {
|
|
146
|
-
setPose(nextPart, nextPose) {
|
|
147
|
-
if (nextPart !== part || pose !== nextPose) {
|
|
148
|
-
cancelAttention();
|
|
149
|
-
revision++;
|
|
150
|
-
selection = '';
|
|
151
|
-
render = undefined;
|
|
152
|
-
clock.setClips(undefined);
|
|
153
|
-
gaze.reset();
|
|
154
|
-
bounds = undefined;
|
|
155
|
-
canvas?.remove();
|
|
156
|
-
canvas = undefined;
|
|
157
|
-
rig = undefined;
|
|
158
|
-
if (part)
|
|
159
|
-
part.dataset.motion = 'rest';
|
|
160
|
-
}
|
|
161
|
-
part = nextPart;
|
|
162
|
-
pose = nextPose;
|
|
163
|
-
update();
|
|
164
|
-
},
|
|
165
|
-
dispose() {
|
|
166
|
-
disposed = true;
|
|
167
|
-
cancelAttention();
|
|
168
|
-
revision++;
|
|
169
|
-
clock.dispose();
|
|
170
|
-
gaze.dispose();
|
|
171
|
-
canvas?.remove();
|
|
172
|
-
render = undefined;
|
|
173
|
-
images.clear();
|
|
174
|
-
loading.clear();
|
|
175
|
-
if (part)
|
|
176
|
-
part.dataset.motion = 'rest';
|
|
177
|
-
reduced.removeEventListener('change', update);
|
|
178
|
-
observer.disconnect();
|
|
179
|
-
doc.removeEventListener('visibilitychange', update);
|
|
180
|
-
doc.removeEventListener('pointermove', pointer);
|
|
181
|
-
doc.removeEventListener('pointerout', leave);
|
|
182
|
-
win.removeEventListener('blur', neutral);
|
|
183
|
-
win.removeEventListener('resize', resize);
|
|
184
|
-
},
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
//# sourceMappingURL=character-motion.js.map
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/** Shared catalog: runtime preloading and CSS must always use the same assets. */
|
|
2
|
-
export declare const CHARACTER_POSES: {
|
|
3
|
-
readonly seated: {
|
|
4
|
-
readonly light: string;
|
|
5
|
-
readonly dark: string;
|
|
6
|
-
};
|
|
7
|
-
readonly chin: {
|
|
8
|
-
readonly light: string;
|
|
9
|
-
readonly dark: string;
|
|
10
|
-
};
|
|
11
|
-
readonly doze: {
|
|
12
|
-
readonly light: string;
|
|
13
|
-
readonly dark: string;
|
|
14
|
-
};
|
|
15
|
-
readonly peek: {
|
|
16
|
-
readonly light: string;
|
|
17
|
-
readonly dark: string;
|
|
18
|
-
};
|
|
19
|
-
readonly halfpeek: {
|
|
20
|
-
readonly light: string;
|
|
21
|
-
readonly dark: string;
|
|
22
|
-
};
|
|
23
|
-
};
|
|
24
|
-
export type CharacterPose = keyof typeof CHARACTER_POSES;
|
|
25
|
-
export declare const CHARACTER_POSE_NAMES: CharacterPose[];
|
|
26
|
-
//# sourceMappingURL=character-poses.d.ts.map
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { XIAOHEI_SEATED_LIGHT, XIAOHEI_SEATED_DARK, XIAOHEI_PEEK_LIGHT, XIAOHEI_PEEK_DARK, XIAOHEI_CHIN_LIGHT, XIAOHEI_CHIN_DARK, XIAOHEI_DOZE_LIGHT, XIAOHEI_DOZE_DARK, XIAOHEI_HALFPEEK_LIGHT, XIAOHEI_HALFPEEK_DARK, } from '../generated-backgrounds.js';
|
|
2
|
-
/** Shared catalog: runtime preloading and CSS must always use the same assets. */
|
|
3
|
-
export const CHARACTER_POSES = {
|
|
4
|
-
seated: { light: XIAOHEI_SEATED_LIGHT, dark: XIAOHEI_SEATED_DARK },
|
|
5
|
-
chin: { light: XIAOHEI_CHIN_LIGHT, dark: XIAOHEI_CHIN_DARK },
|
|
6
|
-
doze: { light: XIAOHEI_DOZE_LIGHT, dark: XIAOHEI_DOZE_DARK },
|
|
7
|
-
peek: { light: XIAOHEI_PEEK_LIGHT, dark: XIAOHEI_PEEK_DARK },
|
|
8
|
-
halfpeek: { light: XIAOHEI_HALFPEEK_LIGHT, dark: XIAOHEI_HALFPEEK_DARK },
|
|
9
|
-
};
|
|
10
|
-
export const CHARACTER_POSE_NAMES = Object.keys(CHARACTER_POSES);
|
|
11
|
-
//# sourceMappingURL=character-poses.js.map
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { CharacterRig, Point } from './character-motion-types.js';
|
|
2
|
-
import type { EyeRig } from './character-eye-rig.js';
|
|
3
|
-
/** Small CPU-skinned tail only; body and ears use normal image draws. */
|
|
4
|
-
export declare function createRigRenderer(ctx: CanvasRenderingContext2D, rig: CharacterRig, images: ReadonlyMap<string, HTMLImageElement | null>, eyes?: readonly EyeRig[]): (action: string | undefined, progress: number, gaze?: Point) => void;
|
|
5
|
-
//# sourceMappingURL=character-rig-renderer.d.ts.map
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { attentionBlink, blinkClosure } from './character-expression.js';
|
|
2
|
-
import { createEyeRenderer } from './character-eye-renderer.js';
|
|
3
|
-
import { bindVertex, earOffset, rigAngles, skinVertex, solveBones, TAIL_JOINTS } from './character-rig.js';
|
|
4
|
-
/** Small CPU-skinned tail only; body and ears use normal image draws. */
|
|
5
|
-
export function createRigRenderer(ctx, rig, images, eyes = []) {
|
|
6
|
-
const body = images.get(rig.layers.body.src);
|
|
7
|
-
const drawEyes = body ? createEyeRenderer(ctx, body, eyes) : undefined;
|
|
8
|
-
const tail = rig.layers.tail;
|
|
9
|
-
const vertices = [], triangles = [];
|
|
10
|
-
if (tail) {
|
|
11
|
-
const [x, y, r, b] = tail.box, cols = Math.ceil((r - x) / 10), rows = Math.ceil((b - y) / 10);
|
|
12
|
-
for (let row = 0; row <= rows; row++)
|
|
13
|
-
for (let col = 0; col <= cols; col++)
|
|
14
|
-
vertices.push(bindVertex(x + (r - x) * col / cols, y + (b - y) * row / rows));
|
|
15
|
-
for (let row = 0; row < rows; row++)
|
|
16
|
-
for (let col = 0; col < cols; col++) {
|
|
17
|
-
const i = row * (cols + 1) + col;
|
|
18
|
-
triangles.push([i, i + 1, i + cols + 1], [i + 1, i + cols + 2, i + cols + 1]);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
function layer(name) {
|
|
22
|
-
const layer = rig.layers[name], image = layer && images.get(layer.src);
|
|
23
|
-
if (layer && image) {
|
|
24
|
-
const [x, y, r, b] = layer.box;
|
|
25
|
-
ctx.drawImage(image, x, y, r - x, b - y);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
function drawTail(progress) {
|
|
29
|
-
if (!tail)
|
|
30
|
-
return;
|
|
31
|
-
const image = images.get(tail.src);
|
|
32
|
-
if (!image)
|
|
33
|
-
return;
|
|
34
|
-
if (progress <= 0 || progress >= 1) {
|
|
35
|
-
layer('tail');
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
const joints = solveBones(TAIL_JOINTS, rigAngles(progress, TAIL_JOINTS.length, true));
|
|
39
|
-
const posed = vertices.map(v => skinVertex(v, joints));
|
|
40
|
-
const [left, top] = tail.box;
|
|
41
|
-
for (const indices of triangles) {
|
|
42
|
-
const [ia, ib, ic] = indices;
|
|
43
|
-
const a = vertices[ia], b = vertices[ib], c = vertices[ic];
|
|
44
|
-
const p = posed[ia], q = posed[ib], r = posed[ic];
|
|
45
|
-
const ux = b.x - a.x, uy = b.y - a.y, vx = c.x - a.x, vy = c.y - a.y, det = ux * vy - uy * vx;
|
|
46
|
-
const aa = ((q[0] - p[0]) * vy - (r[0] - p[0]) * uy) / det;
|
|
47
|
-
const bb = ((q[1] - p[1]) * vy - (r[1] - p[1]) * uy) / det;
|
|
48
|
-
const cc = ((r[0] - p[0]) * ux - (q[0] - p[0]) * vx) / det;
|
|
49
|
-
const dd = ((r[1] - p[1]) * ux - (q[1] - p[1]) * vx) / det;
|
|
50
|
-
ctx.save();
|
|
51
|
-
ctx.beginPath();
|
|
52
|
-
// Slightly overlap the interior triangles to avoid antialias hairlines.
|
|
53
|
-
const cx = (p[0] + q[0] + r[0]) / 3, cy = (p[1] + q[1] + r[1]) / 3;
|
|
54
|
-
[p, q, r].forEach((v, i) => {
|
|
55
|
-
const dx = v[0] - cx, dy = v[1] - cy, scale = 1 + 1.2 / Math.max(1, Math.hypot(dx, dy));
|
|
56
|
-
if (i)
|
|
57
|
-
ctx.lineTo(cx + dx * scale, cy + dy * scale);
|
|
58
|
-
else
|
|
59
|
-
ctx.moveTo(cx + dx * scale, cy + dy * scale);
|
|
60
|
-
});
|
|
61
|
-
ctx.closePath();
|
|
62
|
-
ctx.clip();
|
|
63
|
-
ctx.transform(aa, bb, cc, dd, p[0] - aa * (a.x - left) - cc * (a.y - top), p[1] - bb * (a.x - left) - dd * (a.y - top));
|
|
64
|
-
ctx.drawImage(image, 0, 0);
|
|
65
|
-
ctx.restore();
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return (action, progress, gaze = [0, 0]) => {
|
|
69
|
-
ctx.clearRect(0, 0, rig.size[0], rig.size[1]);
|
|
70
|
-
const earProgress = action === 'attention' ? Math.max(0, Math.min(1, (progress - .03) / .65)) : progress;
|
|
71
|
-
const ears = rigAngles(earProgress, rig.ears.length, false);
|
|
72
|
-
rig.ears.forEach(([, root], i) => {
|
|
73
|
-
const part = rig.layers['ear' + i], image = part && images.get(part.src);
|
|
74
|
-
if (!part || !image)
|
|
75
|
-
return;
|
|
76
|
-
const angle = action === 'attention' || action === 'ear' + i ? ears[i] : 0;
|
|
77
|
-
if (Math.abs(angle) < 1e-8) {
|
|
78
|
-
layer('ear' + i);
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
const [x, top, right, bottom] = part.box;
|
|
82
|
-
// Non-overlapping source rows preserve alpha and never rotate a rectangle
|
|
83
|
-
// of hair out from behind the head. The lower attachment stays identical.
|
|
84
|
-
for (let row = 0; row < image.height; row++) {
|
|
85
|
-
const y = top + row * (bottom - top) / image.height;
|
|
86
|
-
ctx.drawImage(image, 0, row, image.width, 1, x + earOffset(y, top, root, angle), y, right - x, (bottom - top) / image.height);
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
layer('body');
|
|
90
|
-
drawTail(action === 'attention' ? Math.max(0, Math.min(1, (progress - .22) / .78)) : action === 'tail' ? progress : 0);
|
|
91
|
-
const closure = action === 'blink' ? blinkClosure(progress) : action === 'attention' ? attentionBlink(progress) : 0;
|
|
92
|
-
drawEyes?.(gaze, closure);
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
//# sourceMappingURL=character-rig-renderer.js.map
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { Point } from './character-motion-types.js';
|
|
2
|
-
/** Bind-space joint positions. Each child inherits its parent's rotation. */
|
|
3
|
-
export declare const TAIL_JOINTS: readonly Point[];
|
|
4
|
-
export interface Joint {
|
|
5
|
-
x: number;
|
|
6
|
-
y: number;
|
|
7
|
-
angle: number;
|
|
8
|
-
}
|
|
9
|
-
export interface Vertex {
|
|
10
|
-
x: number;
|
|
11
|
-
y: number;
|
|
12
|
-
bone: number;
|
|
13
|
-
weight: number;
|
|
14
|
-
}
|
|
15
|
-
/** Keep the ear root (and any hair below it) fixed; only flex the upper tip. */
|
|
16
|
-
export declare function earOffset(y: number, top: number, root: number, angle: number): number;
|
|
17
|
-
export declare function solveBones(rest: readonly Point[], angles: readonly number[]): Joint[];
|
|
18
|
-
export declare function bindVertex(x: number, y: number, rest?: readonly Point[]): Vertex;
|
|
19
|
-
/** Linear blend skinning, inverse bind translation followed by posed rotation. */
|
|
20
|
-
export declare function skinVertex(v: Vertex, joints: readonly Joint[], rest?: readonly Point[]): Point;
|
|
21
|
-
export declare function rigAngles(progress: number, count: number, tail: boolean): number[];
|
|
22
|
-
//# sourceMappingURL=character-rig.d.ts.map
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/** Bind-space joint positions. Each child inherits its parent's rotation. */
|
|
2
|
-
export const TAIL_JOINTS = [
|
|
3
|
-
[284, 328], [310, 347], [324, 373], [319, 398],
|
|
4
|
-
[307, 423], [307, 448], [319, 464],
|
|
5
|
-
];
|
|
6
|
-
/** Keep the ear root (and any hair below it) fixed; only flex the upper tip. */
|
|
7
|
-
export function earOffset(y, top, root, angle) {
|
|
8
|
-
const span = Math.max(1, root - top);
|
|
9
|
-
const weight = Math.max(0, Math.min(1, (root - y) / span));
|
|
10
|
-
if (weight === 0)
|
|
11
|
-
return 0;
|
|
12
|
-
return Math.sin(angle) * Math.min(20, span * .55) * weight * weight;
|
|
13
|
-
}
|
|
14
|
-
export function solveBones(rest, angles) {
|
|
15
|
-
return rest.reduce((out, p, i) => {
|
|
16
|
-
const parent = out[i - 1];
|
|
17
|
-
const angle = (parent?.angle ?? 0) + (angles[i] ?? 0);
|
|
18
|
-
if (!parent)
|
|
19
|
-
out.push({ x: p[0], y: p[1], angle });
|
|
20
|
-
else {
|
|
21
|
-
const prev = rest[i - 1], dx = p[0] - prev[0], dy = p[1] - prev[1];
|
|
22
|
-
const c = Math.cos(parent.angle), s = Math.sin(parent.angle);
|
|
23
|
-
out.push({ x: parent.x + dx * c - dy * s, y: parent.y + dx * s + dy * c, angle });
|
|
24
|
-
}
|
|
25
|
-
return out;
|
|
26
|
-
}, []);
|
|
27
|
-
}
|
|
28
|
-
export function bindVertex(x, y, rest = TAIL_JOINTS) {
|
|
29
|
-
let distance = Infinity, bone = 0, weight = 0;
|
|
30
|
-
for (let i = 0; i < rest.length - 1; i++) {
|
|
31
|
-
const a = rest[i], b = rest[i + 1], dx = b[0] - a[0], dy = b[1] - a[1];
|
|
32
|
-
const t = Math.max(0, Math.min(1, ((x - a[0]) * dx + (y - a[1]) * dy) / (dx * dx + dy * dy)));
|
|
33
|
-
const d = (x - a[0] - dx * t) ** 2 + (y - a[1] - dy * t) ** 2;
|
|
34
|
-
if (d < distance) {
|
|
35
|
-
distance = d;
|
|
36
|
-
bone = i;
|
|
37
|
-
weight = t;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
return { x, y, bone, weight };
|
|
41
|
-
}
|
|
42
|
-
/** Linear blend skinning, inverse bind translation followed by posed rotation. */
|
|
43
|
-
export function skinVertex(v, joints, rest = TAIL_JOINTS) {
|
|
44
|
-
let x = 0, y = 0;
|
|
45
|
-
for (let k = 0; k < 2; k++) {
|
|
46
|
-
const i = v.bone + k, p = rest[i], j = joints[i], w = k ? v.weight : 1 - v.weight;
|
|
47
|
-
const dx = v.x - p[0], dy = v.y - p[1], c = Math.cos(j.angle), s = Math.sin(j.angle);
|
|
48
|
-
x += w * (j.x + dx * c - dy * s);
|
|
49
|
-
y += w * (j.y + dx * s + dy * c);
|
|
50
|
-
}
|
|
51
|
-
return [x, y];
|
|
52
|
-
}
|
|
53
|
-
export function rigAngles(progress, count, tail) {
|
|
54
|
-
const t = Math.max(0, Math.min(1, progress));
|
|
55
|
-
const envelope = Math.sin(Math.PI * t) ** 2;
|
|
56
|
-
// Delayed distal joints create follow-through, with zero displacement/velocity
|
|
57
|
-
// at both ends; no discrete frame lookup and no idle simulation.
|
|
58
|
-
return Array.from({ length: count }, (_, i) => envelope * (tail ? (i ? .12 : 0) : .32)
|
|
59
|
-
* Math.sin(t * Math.PI * (tail ? 3 : 4) - i * (tail ? .65 : 1.1)));
|
|
60
|
-
}
|
|
61
|
-
//# sourceMappingURL=character-rig.js.map
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
/** Session feedback runs on an inner plane so ambient drifting stays untouched. */
|
|
2
|
-
export declare const XIAOHEI_HEIXIU_FEEDBACK_CSS = "\n.xiaohei-scene__heixiu-body {\n position: absolute;\n inset: 0;\n display: block;\n transform: translate3d(0, 0, 0);\n opacity: 1;\n}\n\nhtml[data-xiaohei-state='complete'] .xiaohei-scene__heixiu--mascot .xiaohei-scene__heixiu-body,\nhtml[data-xiaohei-state='complete'] .xiaohei-scene__heixiu--sidebar .xiaohei-scene__heixiu-body {\n animation: xiaohei-heixiu-feedback-complete 760ms cubic-bezier(0.16, 1, 0.3, 1) both;\n}\n\nhtml[data-xiaohei-state='complete'] .xiaohei-scene__heixiu--sidebar .xiaohei-scene__heixiu-body {\n animation-delay: 140ms;\n}\n\nhtml[data-xiaohei-state='error'] .xiaohei-scene__heixiu .xiaohei-scene__heixiu-body {\n animation: xiaohei-heixiu-feedback-error 880ms cubic-bezier(0.22, 0.72, 0.24, 1) both;\n}\n\nhtml[data-xiaohei-state='complete'] .xiaohei-scene__heixiu .xiaohei-scene__heixiu-open,\nhtml[data-xiaohei-state='error'] .xiaohei-scene__heixiu .xiaohei-scene__heixiu-open {\n animation: xiaohei-heixiu-feedback-eyes-open 620ms step-end both;\n}\n\nhtml[data-xiaohei-state='complete'] .xiaohei-scene__heixiu .xiaohei-scene__heixiu-blink,\nhtml[data-xiaohei-state='error'] .xiaohei-scene__heixiu .xiaohei-scene__heixiu-blink {\n animation: xiaohei-heixiu-feedback-eyes-blink 620ms step-end both;\n}\n\n@keyframes xiaohei-heixiu-feedback-complete {\n 0%, 100% { transform: translate3d(0, 0, 0); opacity: 1; }\n 38% { transform: translate3d(0, -0.42rem, 0); opacity: 1; }\n 68% { transform: translate3d(0, -0.12rem, 0); opacity: 0.96; }\n}\n\n@keyframes xiaohei-heixiu-feedback-error {\n 0%, 100% { transform: translate3d(0, 0, 0); opacity: 1; }\n 30% { transform: translate3d(0, 0.2rem, 0); opacity: 0.52; }\n 62% { transform: translate3d(0, 0.08rem, 0); opacity: 0.72; }\n}\n\n@keyframes xiaohei-heixiu-feedback-eyes-open {\n 0%, 24%, 48%, 100% { opacity: 1; }\n 25%, 47% { opacity: 0; }\n}\n\n@keyframes xiaohei-heixiu-feedback-eyes-blink {\n 0%, 24%, 48%, 100% { opacity: 0; }\n 25%, 47% { opacity: 1; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n html[data-xiaohei-state] .xiaohei-scene__heixiu .xiaohei-scene__heixiu-body,\n html[data-xiaohei-state] .xiaohei-scene__heixiu .xiaohei-scene__heixiu-open,\n html[data-xiaohei-state] .xiaohei-scene__heixiu .xiaohei-scene__heixiu-blink {\n animation: none;\n }\n}\n";
|
|
3
|
-
//# sourceMappingURL=heixiu-feedback.d.ts.map
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/** Session feedback runs on an inner plane so ambient drifting stays untouched. */
|
|
2
|
-
export const XIAOHEI_HEIXIU_FEEDBACK_CSS = `
|
|
3
|
-
.xiaohei-scene__heixiu-body {
|
|
4
|
-
position: absolute;
|
|
5
|
-
inset: 0;
|
|
6
|
-
display: block;
|
|
7
|
-
transform: translate3d(0, 0, 0);
|
|
8
|
-
opacity: 1;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
html[data-xiaohei-state='complete'] .xiaohei-scene__heixiu--mascot .xiaohei-scene__heixiu-body,
|
|
12
|
-
html[data-xiaohei-state='complete'] .xiaohei-scene__heixiu--sidebar .xiaohei-scene__heixiu-body {
|
|
13
|
-
animation: xiaohei-heixiu-feedback-complete 760ms cubic-bezier(0.16, 1, 0.3, 1) both;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
html[data-xiaohei-state='complete'] .xiaohei-scene__heixiu--sidebar .xiaohei-scene__heixiu-body {
|
|
17
|
-
animation-delay: 140ms;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
html[data-xiaohei-state='error'] .xiaohei-scene__heixiu .xiaohei-scene__heixiu-body {
|
|
21
|
-
animation: xiaohei-heixiu-feedback-error 880ms cubic-bezier(0.22, 0.72, 0.24, 1) both;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
html[data-xiaohei-state='complete'] .xiaohei-scene__heixiu .xiaohei-scene__heixiu-open,
|
|
25
|
-
html[data-xiaohei-state='error'] .xiaohei-scene__heixiu .xiaohei-scene__heixiu-open {
|
|
26
|
-
animation: xiaohei-heixiu-feedback-eyes-open 620ms step-end both;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
html[data-xiaohei-state='complete'] .xiaohei-scene__heixiu .xiaohei-scene__heixiu-blink,
|
|
30
|
-
html[data-xiaohei-state='error'] .xiaohei-scene__heixiu .xiaohei-scene__heixiu-blink {
|
|
31
|
-
animation: xiaohei-heixiu-feedback-eyes-blink 620ms step-end both;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
@keyframes xiaohei-heixiu-feedback-complete {
|
|
35
|
-
0%, 100% { transform: translate3d(0, 0, 0); opacity: 1; }
|
|
36
|
-
38% { transform: translate3d(0, -0.42rem, 0); opacity: 1; }
|
|
37
|
-
68% { transform: translate3d(0, -0.12rem, 0); opacity: 0.96; }
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
@keyframes xiaohei-heixiu-feedback-error {
|
|
41
|
-
0%, 100% { transform: translate3d(0, 0, 0); opacity: 1; }
|
|
42
|
-
30% { transform: translate3d(0, 0.2rem, 0); opacity: 0.52; }
|
|
43
|
-
62% { transform: translate3d(0, 0.08rem, 0); opacity: 0.72; }
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
@keyframes xiaohei-heixiu-feedback-eyes-open {
|
|
47
|
-
0%, 24%, 48%, 100% { opacity: 1; }
|
|
48
|
-
25%, 47% { opacity: 0; }
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
@keyframes xiaohei-heixiu-feedback-eyes-blink {
|
|
52
|
-
0%, 24%, 48%, 100% { opacity: 0; }
|
|
53
|
-
25%, 47% { opacity: 1; }
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
@media (prefers-reduced-motion: reduce) {
|
|
57
|
-
html[data-xiaohei-state] .xiaohei-scene__heixiu .xiaohei-scene__heixiu-body,
|
|
58
|
-
html[data-xiaohei-state] .xiaohei-scene__heixiu .xiaohei-scene__heixiu-open,
|
|
59
|
-
html[data-xiaohei-state] .xiaohei-scene__heixiu .xiaohei-scene__heixiu-blink {
|
|
60
|
-
animation: none;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
`;
|
|
64
|
-
//# sourceMappingURL=heixiu-feedback.js.map
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
/** Direct pointer attention and synchronized Heixiu-to-Xiaohei greetings. */
|
|
2
|
-
export declare const XIAOHEI_HEIXIU_INTERACTION_CSS = "\n.xiaohei-scene__heixiu-body {\n transition: transform 150ms ease-out, opacity 150ms ease-out;\n}\n\n.xiaohei-scene__heixiu-body::after {\n content: '';\n position: absolute;\n inset: 8%;\n border-radius: 50%;\n pointer-events: none;\n background: radial-gradient(circle, rgb(126 239 219 / 20%), transparent 68%);\n opacity: 0;\n transition: opacity 150ms ease-out;\n}\n\n.xiaohei-scene__heixiu[data-xiaohei-heixiu-attention='true'] {\n opacity: 0.92;\n filter:\n drop-shadow(0 0.32rem 0.68rem rgb(109 233 211 / 32%))\n drop-shadow(0 0.68rem 1.15rem rgb(1 9 10 / 20%));\n}\n\n.xiaohei-scene__heixiu[data-xiaohei-heixiu-attention='true'] .xiaohei-scene__heixiu-body {\n transform: translate3d(\n var(--xiaohei-heixiu-attention-x, 0px),\n var(--xiaohei-heixiu-attention-y, 0px),\n 0\n );\n}\n\n.xiaohei-scene__heixiu[data-xiaohei-heixiu-attention='true'] .xiaohei-scene__heixiu-body::after {\n opacity: 1;\n}\n\n.xiaohei-scene__heixiu[data-xiaohei-heixiu-greeting='true'] .xiaohei-scene__heixiu-body {\n animation: xiaohei-heixiu-greet-xiaohei 760ms cubic-bezier(0.2, 0.72, 0.24, 1) both;\n}\n\n.xiaohei-scene__heixiu[data-xiaohei-heixiu-greeting='true'] .xiaohei-scene__heixiu-open {\n animation: xiaohei-heixiu-greeting-open 760ms step-end both;\n}\n\n.xiaohei-scene__heixiu[data-xiaohei-heixiu-greeting='true'] .xiaohei-scene__heixiu-blink {\n animation: xiaohei-heixiu-greeting-blink 760ms step-end both;\n}\n\nhtml[data-xiaohei-appearance='light'] .xiaohei-scene__heixiu-body::after {\n background: radial-gradient(circle, rgb(44 135 113 / 14%), transparent 68%);\n}\n\nhtml[data-xiaohei-appearance='light'] .xiaohei-scene__heixiu[data-xiaohei-heixiu-attention='true'] {\n filter:\n drop-shadow(0 0.3rem 0.62rem rgb(47 133 118 / 22%))\n drop-shadow(0 0.62rem 1rem rgb(45 64 56 / 10%));\n}\n\n@keyframes xiaohei-heixiu-greet-xiaohei {\n 0%, 100% { transform: translate3d(0, 0, 0); }\n 30% { transform: translate3d(0.42rem, -0.28rem, 0); }\n 62% { transform: translate3d(0.16rem, -0.08rem, 0); }\n}\n\n@keyframes xiaohei-heixiu-greeting-open {\n 0%, 20%, 40%, 62%, 80%, 100% { opacity: 1; }\n 21%, 39%, 63%, 79% { opacity: 0; }\n}\n\n@keyframes xiaohei-heixiu-greeting-blink {\n 0%, 20%, 40%, 62%, 80%, 100% { opacity: 0; }\n 21%, 39%, 63%, 79% { opacity: 1; }\n}\n\n@media (prefers-reduced-motion: reduce), (hover: none) and (pointer: coarse) {\n .xiaohei-scene__heixiu-body,\n .xiaohei-scene__heixiu-body::after {\n transition: none;\n }\n\n .xiaohei-scene__heixiu[data-xiaohei-heixiu-greeting='true'] .xiaohei-scene__heixiu-body,\n .xiaohei-scene__heixiu[data-xiaohei-heixiu-greeting='true'] .xiaohei-scene__heixiu-open,\n .xiaohei-scene__heixiu[data-xiaohei-heixiu-greeting='true'] .xiaohei-scene__heixiu-blink {\n animation: none;\n }\n}\n\n@media (forced-colors: active) {\n .xiaohei-scene__heixiu-body::after { display: none; }\n}\n";
|
|
3
|
-
//# sourceMappingURL=heixiu-interactions.d.ts.map
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
/** Direct pointer attention and synchronized Heixiu-to-Xiaohei greetings. */
|
|
2
|
-
export const XIAOHEI_HEIXIU_INTERACTION_CSS = `
|
|
3
|
-
.xiaohei-scene__heixiu-body {
|
|
4
|
-
transition: transform 150ms ease-out, opacity 150ms ease-out;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
.xiaohei-scene__heixiu-body::after {
|
|
8
|
-
content: '';
|
|
9
|
-
position: absolute;
|
|
10
|
-
inset: 8%;
|
|
11
|
-
border-radius: 50%;
|
|
12
|
-
pointer-events: none;
|
|
13
|
-
background: radial-gradient(circle, rgb(126 239 219 / 20%), transparent 68%);
|
|
14
|
-
opacity: 0;
|
|
15
|
-
transition: opacity 150ms ease-out;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
.xiaohei-scene__heixiu[data-xiaohei-heixiu-attention='true'] {
|
|
19
|
-
opacity: 0.92;
|
|
20
|
-
filter:
|
|
21
|
-
drop-shadow(0 0.32rem 0.68rem rgb(109 233 211 / 32%))
|
|
22
|
-
drop-shadow(0 0.68rem 1.15rem rgb(1 9 10 / 20%));
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
.xiaohei-scene__heixiu[data-xiaohei-heixiu-attention='true'] .xiaohei-scene__heixiu-body {
|
|
26
|
-
transform: translate3d(
|
|
27
|
-
var(--xiaohei-heixiu-attention-x, 0px),
|
|
28
|
-
var(--xiaohei-heixiu-attention-y, 0px),
|
|
29
|
-
0
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
.xiaohei-scene__heixiu[data-xiaohei-heixiu-attention='true'] .xiaohei-scene__heixiu-body::after {
|
|
34
|
-
opacity: 1;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
.xiaohei-scene__heixiu[data-xiaohei-heixiu-greeting='true'] .xiaohei-scene__heixiu-body {
|
|
38
|
-
animation: xiaohei-heixiu-greet-xiaohei 760ms cubic-bezier(0.2, 0.72, 0.24, 1) both;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
.xiaohei-scene__heixiu[data-xiaohei-heixiu-greeting='true'] .xiaohei-scene__heixiu-open {
|
|
42
|
-
animation: xiaohei-heixiu-greeting-open 760ms step-end both;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
.xiaohei-scene__heixiu[data-xiaohei-heixiu-greeting='true'] .xiaohei-scene__heixiu-blink {
|
|
46
|
-
animation: xiaohei-heixiu-greeting-blink 760ms step-end both;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
html[data-xiaohei-appearance='light'] .xiaohei-scene__heixiu-body::after {
|
|
50
|
-
background: radial-gradient(circle, rgb(44 135 113 / 14%), transparent 68%);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
html[data-xiaohei-appearance='light'] .xiaohei-scene__heixiu[data-xiaohei-heixiu-attention='true'] {
|
|
54
|
-
filter:
|
|
55
|
-
drop-shadow(0 0.3rem 0.62rem rgb(47 133 118 / 22%))
|
|
56
|
-
drop-shadow(0 0.62rem 1rem rgb(45 64 56 / 10%));
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
@keyframes xiaohei-heixiu-greet-xiaohei {
|
|
60
|
-
0%, 100% { transform: translate3d(0, 0, 0); }
|
|
61
|
-
30% { transform: translate3d(0.42rem, -0.28rem, 0); }
|
|
62
|
-
62% { transform: translate3d(0.16rem, -0.08rem, 0); }
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
@keyframes xiaohei-heixiu-greeting-open {
|
|
66
|
-
0%, 20%, 40%, 62%, 80%, 100% { opacity: 1; }
|
|
67
|
-
21%, 39%, 63%, 79% { opacity: 0; }
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
@keyframes xiaohei-heixiu-greeting-blink {
|
|
71
|
-
0%, 20%, 40%, 62%, 80%, 100% { opacity: 0; }
|
|
72
|
-
21%, 39%, 63%, 79% { opacity: 1; }
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
@media (prefers-reduced-motion: reduce), (hover: none) and (pointer: coarse) {
|
|
76
|
-
.xiaohei-scene__heixiu-body,
|
|
77
|
-
.xiaohei-scene__heixiu-body::after {
|
|
78
|
-
transition: none;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
.xiaohei-scene__heixiu[data-xiaohei-heixiu-greeting='true'] .xiaohei-scene__heixiu-body,
|
|
82
|
-
.xiaohei-scene__heixiu[data-xiaohei-heixiu-greeting='true'] .xiaohei-scene__heixiu-open,
|
|
83
|
-
.xiaohei-scene__heixiu[data-xiaohei-heixiu-greeting='true'] .xiaohei-scene__heixiu-blink {
|
|
84
|
-
animation: none;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
@media (forced-colors: active) {
|
|
89
|
-
.xiaohei-scene__heixiu-body::after { display: none; }
|
|
90
|
-
}
|
|
91
|
-
`;
|
|
92
|
-
//# sourceMappingURL=heixiu-interactions.js.map
|
package/lib/scene/ids.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
/** Asset-free identifiers shared by the startup shell and deferred scenery. */
|
|
2
|
-
export declare const XIAOHEI_SCENE_STYLE_ID = "dsh-theme-xiaohei/scene-style";
|
|
3
|
-
export declare const XIAOHEI_SCENE_LAYER_ID = "dsh-theme-xiaohei/scene-layer";
|
|
4
|
-
export declare const XIAOHEI_SCENE_WORLD_CLASS = "xiaohei-scene__world";
|
|
5
|
-
//# sourceMappingURL=ids.d.ts.map
|
package/lib/scene/ids.js
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
/** Asset-free identifiers shared by the startup shell and deferred scenery. */
|
|
2
|
-
export const XIAOHEI_SCENE_STYLE_ID = 'dsh-theme-xiaohei/scene-style';
|
|
3
|
-
export const XIAOHEI_SCENE_LAYER_ID = 'dsh-theme-xiaohei/scene-layer';
|
|
4
|
-
export const XIAOHEI_SCENE_WORLD_CLASS = 'xiaohei-scene__world';
|
|
5
|
-
//# sourceMappingURL=ids.js.map
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export declare const XIAOHEI_SYLVA_POINTER_CHANNEL = "dsh-theme-xiaohei/sylva-pointer-v1";
|
|
2
|
-
export declare const XIAOHEI_SYLVA_POINTER_ACK_CHANNEL = "dsh-theme-xiaohei/sylva-pointer-ack-v1";
|
|
3
|
-
export declare const XIAOHEI_SYLVA_POINTER_MARKER = "data-xiaohei-pointer-bridge";
|
|
4
|
-
export type XiaoheiSylvaPointerMessage = {
|
|
5
|
-
channel: typeof XIAOHEI_SYLVA_POINTER_CHANNEL;
|
|
6
|
-
event: 'move' | 'leave';
|
|
7
|
-
x?: number;
|
|
8
|
-
y?: number;
|
|
9
|
-
pointerType?: string;
|
|
10
|
-
};
|
|
11
|
-
type FrameBounds = Pick<DOMRectReadOnly, 'left' | 'top' | 'width' | 'height'>;
|
|
12
|
-
/** Translate a host-page pointer into the isolated scene viewport. */
|
|
13
|
-
export declare function resolveXiaoheiSylvaPointer(clientX: number, clientY: number, bounds: FrameBounds): Pick<XiaoheiSylvaPointerMessage, 'event' | 'x' | 'y'>;
|
|
14
|
-
/** Add the receiver to a derived srcDoc without changing the registered ThreeUI source. */
|
|
15
|
-
export declare function injectXiaoheiSylvaPointerBridge(source: string): string;
|
|
16
|
-
/** Prepare a frame before it is connected, so WebGL boots exactly once. */
|
|
17
|
-
export declare function prepareXiaoheiSylvaPointerFrame(frame: HTMLIFrameElement): boolean;
|
|
18
|
-
/** Install a movement-only bridge. It never forwards clicks or presses. */
|
|
19
|
-
export declare function installXiaoheiSylvaPointerBridge(host: HTMLElement, prepareSceneFrame?: (frame: HTMLIFrameElement) => void): () => void;
|
|
20
|
-
export {};
|
|
21
|
-
//# sourceMappingURL=pointer-bridge.d.ts.map
|