@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.
- package/README.md +15 -9
- package/THIRD_PARTY_NOTICES.md +13 -1
- package/docs/dsh-021-compatibility.md +23 -0
- package/docs/releases/0.5.0.md +24 -0
- package/docs/rift-interaction.md +35 -0
- package/docs/rift-preview.md +39 -0
- package/lib/client.companion.js +3 -4
- package/lib/client.decorations.js +224 -51
- package/lib/client.js +534 -2405
- package/lib/index.d.ts +1 -2
- package/lib/index.js +395 -11
- package/lib/rift/boot.d.ts +6 -0
- package/package.json +29 -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 -34
- package/lib/bloub-heixiu/layout.js +0 -26
- 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 -440
- 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/companion-entry.d.ts +0 -3
- package/lib/companion-entry.js +0 -3
- 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-companion.d.ts +0 -5
- package/lib/deferred-companion.js +0 -9
- 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 -72
- 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,296 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useRef, useState } from 'react';
|
|
3
|
-
import { XIAOHEI_BRAND_AVATAR } from './generated-identity.js';
|
|
4
|
-
// Native wide/rail switches remount this slot. A tiny navigation mark does not
|
|
5
|
-
// need a fresh GPU context and shader compilation on every toggle.
|
|
6
|
-
const metallicSnapshots = new Map();
|
|
7
|
-
const VERTEX_SHADER = `#version 300 es
|
|
8
|
-
precision highp float;
|
|
9
|
-
in vec2 a_position;
|
|
10
|
-
out vec2 vP;
|
|
11
|
-
void main(){vP=a_position*.5+.5;gl_Position=vec4(a_position,0.,1.);}`;
|
|
12
|
-
/* Adapted from React Bits MetallicPaint. The source avatar is already a
|
|
13
|
-
* transparent tonal map, so the expensive browser-side depth solve is not
|
|
14
|
-
* needed for this compact brand mark. */
|
|
15
|
-
const FRAGMENT_SHADER = `#version 300 es
|
|
16
|
-
precision highp float;
|
|
17
|
-
in vec2 vP;
|
|
18
|
-
out vec4 oC;
|
|
19
|
-
uniform sampler2D u_tex;
|
|
20
|
-
uniform float u_time,u_ratio,u_imgRatio,u_seed,u_scale,u_refract,u_blur,u_liquid;
|
|
21
|
-
uniform float u_bright,u_contrast,u_angle,u_fresnel,u_sharp,u_wave,u_noise,u_chroma;
|
|
22
|
-
uniform float u_distort,u_contour;
|
|
23
|
-
uniform vec3 u_lightColor,u_darkColor,u_tint;
|
|
24
|
-
|
|
25
|
-
vec3 sC,sM;
|
|
26
|
-
|
|
27
|
-
vec3 pW(vec3 v){
|
|
28
|
-
vec3 i=floor(v),f=fract(v),s=sign(fract(v*.5)-.5),h=fract(sM*i+i.yzx),c=f*(f-1.);
|
|
29
|
-
return s*c*((h*16.-4.)*c-1.);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
vec3 aF(vec3 b,vec3 c){return pW(b+c.zxy-pW(b.zxy+c.yzx)+pW(b.yzx+c.xyz));}
|
|
33
|
-
vec3 lM(vec3 s,vec3 p){return(p+aF(s,p))*.5;}
|
|
34
|
-
|
|
35
|
-
vec2 fA(){
|
|
36
|
-
vec2 c=vP-.5;
|
|
37
|
-
c.x*=u_ratio>u_imgRatio?u_ratio/u_imgRatio:1.;
|
|
38
|
-
c.y*=u_ratio>u_imgRatio?1.:u_imgRatio/u_ratio;
|
|
39
|
-
return vec2(c.x+.5,.5-c.y);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
vec2 rot(vec2 p,float r){float c=cos(r),s=sin(r);return vec2(p.x*c+p.y*s,p.y*c-p.x*s);}
|
|
43
|
-
|
|
44
|
-
float bM(vec2 c,float t){
|
|
45
|
-
vec2 l=smoothstep(vec2(0.),vec2(t),c),u=smoothstep(vec2(0.),vec2(t),1.-c);
|
|
46
|
-
return l.x*l.y*u.x*u.y;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
float mG(float hi,float lo,float t,float sh,float cv){
|
|
50
|
-
sh*=(2.-u_sharp);
|
|
51
|
-
float ci=smoothstep(.15,.85,cv),r=lo;
|
|
52
|
-
float e1=.08/u_scale;
|
|
53
|
-
r=mix(r,hi,smoothstep(0.,sh*1.5,t));
|
|
54
|
-
r=mix(r,lo,smoothstep(e1-sh,e1+sh,t));
|
|
55
|
-
float e2=e1+.05/u_scale*(1.-ci*.35);
|
|
56
|
-
r=mix(r,hi,smoothstep(e2-sh,e2+sh,t));
|
|
57
|
-
float e3=e2+.025/u_scale*(1.-ci*.45);
|
|
58
|
-
r=mix(r,lo,smoothstep(e3-sh,e3+sh,t));
|
|
59
|
-
float e4=e1+.1/u_scale;
|
|
60
|
-
r=mix(r,hi,smoothstep(e4-sh,e4+sh,t));
|
|
61
|
-
float rm=1.-e4,gT=clamp((t-e4)/rm,0.,1.);
|
|
62
|
-
r=mix(r,mix(hi,lo,smoothstep(0.,1.,gT)),smoothstep(e4-sh*.5,e4+sh*.5,t));
|
|
63
|
-
return r;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
void main(){
|
|
67
|
-
sC=fract(vec3(.7548,.5698,.4154)*(u_seed+17.31))+.5;
|
|
68
|
-
sM=fract(sC.zxy-sC.yzx*1.618);
|
|
69
|
-
vec2 sc=vec2(vP.x*u_ratio,1.-vP.y);
|
|
70
|
-
float angleRad=u_angle*3.14159/180.;
|
|
71
|
-
sc=rot(sc-.5,angleRad)+.5;
|
|
72
|
-
sc=clamp(sc,0.,1.);
|
|
73
|
-
float sl=sc.x-sc.y,an=u_time*.001;
|
|
74
|
-
vec2 iC=fA();
|
|
75
|
-
vec4 texSample=texture(u_tex,iC);
|
|
76
|
-
float dp=texSample.r;
|
|
77
|
-
float shapeMask=texSample.a;
|
|
78
|
-
vec3 hi=u_lightColor*u_bright;
|
|
79
|
-
vec3 lo=u_darkColor*(2.-u_bright);
|
|
80
|
-
lo.b+=smoothstep(.6,1.4,sc.x+sc.y)*.08;
|
|
81
|
-
vec2 fC=sc-.5;
|
|
82
|
-
float rd=length(fC+vec2(0.,sl*.15));
|
|
83
|
-
vec2 ag=rot(fC,(.22-sl*.18)*3.14159);
|
|
84
|
-
float cv=1.-pow(rd*1.65,1.15);
|
|
85
|
-
cv*=pow(sc.y,.35);
|
|
86
|
-
float vs=shapeMask;
|
|
87
|
-
vs*=bM(iC,.01);
|
|
88
|
-
float fr=pow(1.-cv,u_fresnel)*.3;
|
|
89
|
-
vs=min(vs+fr*vs,1.);
|
|
90
|
-
float mT=an*.0625;
|
|
91
|
-
vec3 wO=vec3(-1.05,1.35,1.55);
|
|
92
|
-
vec3 wA=aF(vec3(31.,73.,56.),mT+wO)*.22*u_wave;
|
|
93
|
-
vec3 wB=aF(vec3(24.,64.,42.),mT-wO.yzx)*.22*u_wave;
|
|
94
|
-
vec2 nC=sc*45.*u_noise;
|
|
95
|
-
nC+=aF(sC.zxy,an*.17*sC.yzx-sc.yxy*.35).xy*18.*u_wave;
|
|
96
|
-
vec3 tC=vec3(.00041,.00053,.00076)*mT+wB*nC.x+wA*nC.y;
|
|
97
|
-
tC=lM(sC,tC);
|
|
98
|
-
tC=lM(sC+1.618,tC);
|
|
99
|
-
float tb=sin(tC.x*3.14159)*.5+.5;
|
|
100
|
-
tb=tb*2.-1.;
|
|
101
|
-
float noiseVal=pW(vec3(sc*8.+an,an*.5)).x;
|
|
102
|
-
float edgeFactor=smoothstep(0.,.5,dp)*smoothstep(1.,.5,dp);
|
|
103
|
-
float lD=dp+(1.-dp)*u_liquid*tb;
|
|
104
|
-
lD+=noiseVal*u_distort*.15*edgeFactor;
|
|
105
|
-
float rB=clamp(1.-cv,0.,1.);
|
|
106
|
-
float fl=ag.x+sl;
|
|
107
|
-
fl+=noiseVal*sl*u_distort*edgeFactor;
|
|
108
|
-
fl*=mix(1.,1.-dp*.5,u_contour);
|
|
109
|
-
fl-=dp*u_contour*.8;
|
|
110
|
-
float eI=smoothstep(0.,1.,lD)*smoothstep(1.,0.,lD);
|
|
111
|
-
fl-=tb*sl*1.8*eI;
|
|
112
|
-
float cA=cv*clamp(pow(sc.y,.12),.25,1.);
|
|
113
|
-
fl*=.12+(1.05-lD)*cA;
|
|
114
|
-
fl*=smoothstep(1.,.65,lD);
|
|
115
|
-
float vA1=smoothstep(.08,.18,sc.y)*smoothstep(.38,.18,sc.y);
|
|
116
|
-
float vA2=smoothstep(.08,.18,1.-sc.y)*smoothstep(.38,.18,1.-sc.y);
|
|
117
|
-
fl+=vA1*.16+vA2*.025;
|
|
118
|
-
fl*=.45+pow(sc.y,2.)*.55;
|
|
119
|
-
fl*=u_scale;
|
|
120
|
-
fl-=an;
|
|
121
|
-
float rO=rB+cv*tb*.025;
|
|
122
|
-
float vM1=smoothstep(-.12,.18,sc.y)*smoothstep(.48,.08,sc.y);
|
|
123
|
-
float cM1=smoothstep(.35,.55,cv)*smoothstep(.95,.35,cv);
|
|
124
|
-
rO+=vM1*cM1*4.5;
|
|
125
|
-
rO-=sl;
|
|
126
|
-
float bO=rB*1.25;
|
|
127
|
-
float vM2=smoothstep(-.02,.35,sc.y)*smoothstep(.75,.08,sc.y);
|
|
128
|
-
float cM2=smoothstep(.35,.55,cv)*smoothstep(.75,.35,cv);
|
|
129
|
-
bO+=vM2*cM2*.9;
|
|
130
|
-
bO-=lD*.18;
|
|
131
|
-
rO*=u_refract*u_chroma;
|
|
132
|
-
bO*=u_refract*u_chroma;
|
|
133
|
-
float sf=u_blur;
|
|
134
|
-
float rP=fract(fl+rO);
|
|
135
|
-
float rC=mG(hi.r,lo.r,rP,sf+.018+u_refract*cv*.025,cv);
|
|
136
|
-
float gP=fract(fl);
|
|
137
|
-
float gC=mG(hi.g,lo.g,gP,sf+.008/max(.01,1.-sl),cv);
|
|
138
|
-
float bP=fract(fl-bO);
|
|
139
|
-
float bC=mG(hi.b,lo.b,bP,sf+.008,cv);
|
|
140
|
-
vec3 col=vec3(rC,gC,bC);
|
|
141
|
-
col=(col-.5)*u_contrast+.5;
|
|
142
|
-
col=clamp(col,0.,1.);
|
|
143
|
-
col=mix(col,1.-min(vec3(1.),(1.-col)/max(u_tint,vec3(.001))),length(u_tint-1.)*.5);
|
|
144
|
-
col=clamp(col,0.,1.);
|
|
145
|
-
oC=vec4(col*vs,vs);
|
|
146
|
-
}`;
|
|
147
|
-
const UNIFORM_NAMES = [
|
|
148
|
-
'u_tex', 'u_time', 'u_ratio', 'u_imgRatio', 'u_seed', 'u_scale', 'u_refract',
|
|
149
|
-
'u_blur', 'u_liquid', 'u_bright', 'u_contrast', 'u_angle', 'u_fresnel',
|
|
150
|
-
'u_sharp', 'u_wave', 'u_noise', 'u_chroma', 'u_distort', 'u_contour',
|
|
151
|
-
'u_lightColor', 'u_darkColor', 'u_tint',
|
|
152
|
-
];
|
|
153
|
-
function compileShader(gl, type, source) {
|
|
154
|
-
const shader = gl.createShader(type);
|
|
155
|
-
if (shader === null)
|
|
156
|
-
return undefined;
|
|
157
|
-
gl.shaderSource(shader, source);
|
|
158
|
-
gl.compileShader(shader);
|
|
159
|
-
if (gl.getShaderParameter(shader, gl.COMPILE_STATUS) === true)
|
|
160
|
-
return shader;
|
|
161
|
-
gl.deleteShader(shader);
|
|
162
|
-
return undefined;
|
|
163
|
-
}
|
|
164
|
-
function setRgb(gl, location, color) {
|
|
165
|
-
gl.uniform3f(location, color[0], color[1], color[2]);
|
|
166
|
-
}
|
|
167
|
-
/** Official sidebar brand occupant with a compact, lifecycle-safe metallic shader. */
|
|
168
|
-
export function XiaoheiMetallicBrandMark({ size, className }) {
|
|
169
|
-
const canvasRef = useRef(null);
|
|
170
|
-
const [ready, setReady] = useState(false);
|
|
171
|
-
const visualSize = Math.max(24, size + 4);
|
|
172
|
-
const context = size >= 32 ? 'hero' : 'sidebar';
|
|
173
|
-
const [snapshot, setSnapshot] = useState(metallicSnapshots.get(visualSize));
|
|
174
|
-
useEffect(() => {
|
|
175
|
-
if (snapshot !== undefined)
|
|
176
|
-
return;
|
|
177
|
-
const canvas = canvasRef.current;
|
|
178
|
-
if (canvas === null)
|
|
179
|
-
return;
|
|
180
|
-
const gl = canvas.getContext('webgl2', {
|
|
181
|
-
alpha: true,
|
|
182
|
-
antialias: false,
|
|
183
|
-
powerPreference: 'low-power',
|
|
184
|
-
premultipliedAlpha: true,
|
|
185
|
-
});
|
|
186
|
-
if (gl === null)
|
|
187
|
-
return;
|
|
188
|
-
const vertex = compileShader(gl, gl.VERTEX_SHADER, VERTEX_SHADER);
|
|
189
|
-
const fragment = compileShader(gl, gl.FRAGMENT_SHADER, FRAGMENT_SHADER);
|
|
190
|
-
if (vertex === undefined || fragment === undefined) {
|
|
191
|
-
if (vertex !== undefined)
|
|
192
|
-
gl.deleteShader(vertex);
|
|
193
|
-
if (fragment !== undefined)
|
|
194
|
-
gl.deleteShader(fragment);
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
const program = gl.createProgram();
|
|
198
|
-
const buffer = gl.createBuffer();
|
|
199
|
-
if (program === null || buffer === null) {
|
|
200
|
-
gl.deleteShader(vertex);
|
|
201
|
-
gl.deleteShader(fragment);
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
gl.attachShader(program, vertex);
|
|
205
|
-
gl.attachShader(program, fragment);
|
|
206
|
-
gl.linkProgram(program);
|
|
207
|
-
gl.deleteShader(vertex);
|
|
208
|
-
gl.deleteShader(fragment);
|
|
209
|
-
if (gl.getProgramParameter(program, gl.LINK_STATUS) !== true) {
|
|
210
|
-
gl.deleteBuffer(buffer);
|
|
211
|
-
gl.deleteProgram(program);
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
const uniforms = Object.fromEntries(UNIFORM_NAMES.map(name => [name, gl.getUniformLocation(program, name)]));
|
|
215
|
-
const pixelRatio = Math.min(window.devicePixelRatio || 1, 2);
|
|
216
|
-
const renderSize = Math.max(64, Math.ceil(visualSize * pixelRatio));
|
|
217
|
-
canvas.width = renderSize;
|
|
218
|
-
canvas.height = renderSize;
|
|
219
|
-
gl.viewport(0, 0, renderSize, renderSize);
|
|
220
|
-
gl.useProgram(program);
|
|
221
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
222
|
-
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
|
|
223
|
-
const position = gl.getAttribLocation(program, 'a_position');
|
|
224
|
-
gl.enableVertexAttribArray(position);
|
|
225
|
-
gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0);
|
|
226
|
-
gl.uniform1f(uniforms.u_ratio, 1);
|
|
227
|
-
gl.uniform1f(uniforms.u_imgRatio, 1);
|
|
228
|
-
gl.uniform1f(uniforms.u_seed, 42);
|
|
229
|
-
gl.uniform1f(uniforms.u_scale, 3.2);
|
|
230
|
-
gl.uniform1f(uniforms.u_refract, 0.012);
|
|
231
|
-
gl.uniform1f(uniforms.u_blur, 0.018);
|
|
232
|
-
gl.uniform1f(uniforms.u_liquid, 0.58);
|
|
233
|
-
gl.uniform1f(uniforms.u_bright, 1.35);
|
|
234
|
-
gl.uniform1f(uniforms.u_contrast, 1.08);
|
|
235
|
-
gl.uniform1f(uniforms.u_angle, -12);
|
|
236
|
-
gl.uniform1f(uniforms.u_fresnel, 0.8);
|
|
237
|
-
gl.uniform1f(uniforms.u_sharp, 1.15);
|
|
238
|
-
gl.uniform1f(uniforms.u_wave, 0.65);
|
|
239
|
-
gl.uniform1f(uniforms.u_noise, 0.45);
|
|
240
|
-
gl.uniform1f(uniforms.u_chroma, 0.7);
|
|
241
|
-
gl.uniform1f(uniforms.u_distort, 0.35);
|
|
242
|
-
gl.uniform1f(uniforms.u_contour, 0.38);
|
|
243
|
-
setRgb(gl, uniforms.u_lightColor, [0.96, 0.97, 0.95]);
|
|
244
|
-
setRgb(gl, uniforms.u_darkColor, [0.025, 0.04, 0.045]);
|
|
245
|
-
setRgb(gl, uniforms.u_tint, [0.84, 0.92, 0.89]);
|
|
246
|
-
let disposed = false;
|
|
247
|
-
const metallicTime = 1450;
|
|
248
|
-
const texture = gl.createTexture();
|
|
249
|
-
const image = new Image();
|
|
250
|
-
const draw = () => {
|
|
251
|
-
gl.uniform1f(uniforms.u_time, metallicTime);
|
|
252
|
-
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
253
|
-
};
|
|
254
|
-
image.onload = () => {
|
|
255
|
-
if (disposed || texture === null)
|
|
256
|
-
return;
|
|
257
|
-
gl.activeTexture(gl.TEXTURE0);
|
|
258
|
-
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
259
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
260
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
261
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
262
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
263
|
-
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
|
264
|
-
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
|
|
265
|
-
gl.uniform1i(uniforms.u_tex, 0);
|
|
266
|
-
draw();
|
|
267
|
-
// Preserve the metallic appearance without a permanent GPU animation.
|
|
268
|
-
// Updating snapshot unmounts the canvas and runs the resource cleanup.
|
|
269
|
-
const result = canvas.toDataURL();
|
|
270
|
-
metallicSnapshots.set(visualSize, result);
|
|
271
|
-
setSnapshot(result);
|
|
272
|
-
setReady(true);
|
|
273
|
-
};
|
|
274
|
-
image.src = XIAOHEI_BRAND_AVATAR;
|
|
275
|
-
return () => {
|
|
276
|
-
disposed = true;
|
|
277
|
-
image.onload = null;
|
|
278
|
-
if (texture !== null)
|
|
279
|
-
gl.deleteTexture(texture);
|
|
280
|
-
gl.deleteBuffer(buffer);
|
|
281
|
-
gl.deleteProgram(program);
|
|
282
|
-
gl.getExtension('WEBGL_lose_context')?.loseContext();
|
|
283
|
-
};
|
|
284
|
-
}, [visualSize, context, snapshot]);
|
|
285
|
-
const geometry = {
|
|
286
|
-
'--xiaohei-brand-mark-size': `${visualSize}px`,
|
|
287
|
-
};
|
|
288
|
-
return (_jsxs("span", { className: className === undefined ? 'xiaohei-brand-mark' : `${className} xiaohei-brand-mark`, "data-brand-context": context, "data-xiaohei-sidebar-brand": context === 'sidebar' ? '' : undefined, "data-metallic-ready": ready || snapshot !== undefined ? 'true' : 'false', style: geometry, "aria-hidden": "true", children: [_jsx("img", { className: "xiaohei-brand-mark__fallback", src: XIAOHEI_BRAND_AVATAR, alt: "" }), snapshot !== undefined
|
|
289
|
-
? _jsx("img", { className: "xiaohei-brand-mark__metal", src: snapshot, alt: "" })
|
|
290
|
-
: _jsx("canvas", { className: "xiaohei-brand-mark__metal", ref: canvasRef })] }));
|
|
291
|
-
}
|
|
292
|
-
/** Official sidebar brand-name occupant paired with the Xiaohei mark. */
|
|
293
|
-
export function XiaoheiBrandName() {
|
|
294
|
-
return _jsx("span", { className: "xiaohei-brand-name", "data-xiaohei-sidebar-brand": "", children: "\u7F57\u5C0F\u9ED1 \u00B7 \u5996\u7075\u4F1A\u9986" });
|
|
295
|
-
}
|
|
296
|
-
//# sourceMappingURL=metallic-brand-mark.js.map
|
package/lib/plugin.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
2
|
-
/** Boot decoration has no service dependency; the full theme waits below. */
|
|
3
|
-
export declare const inject: string[];
|
|
4
|
-
/** Shade DSH's native appearance modes without replacing its preference UI. */
|
|
5
|
-
export declare function apply(ctx: ClientContext): void;
|
|
6
|
-
//# sourceMappingURL=plugin.d.ts.map
|
package/lib/plugin.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { bindXiaoheiAppearance } from './appearance.js';
|
|
2
|
-
import { installXiaoheiChrome } from './chrome.js';
|
|
3
|
-
import { installXiaoheiComposerSendHeixiu } from './composer-send-heixiu.js';
|
|
4
|
-
import { XiaoheiDraftPreview } from './composer-draft-preview.js';
|
|
5
|
-
import { installXiaoheiPluginLoading } from './loading-heixiu.js';
|
|
6
|
-
import { installDeferredDecorations } from './deferred-decorations.js';
|
|
7
|
-
import { installXiaoheiScene } from './scene/runtime.js';
|
|
8
|
-
import { installXiaoheiSidebarGlass } from './sidebar-glass.js';
|
|
9
|
-
import { installDeferredCompanion } from './deferred-companion.js';
|
|
10
|
-
import { bindHeixiuSessions, createHeixiuSignals } from './bloub-heixiu/signals.js';
|
|
11
|
-
import { XIAOHEI_THEME_TOKEN_OVERRIDES } from './theme.js';
|
|
12
|
-
import { XiaoheiBrandName, XiaoheiMetallicBrandMark } from './metallic-brand-mark.js';
|
|
13
|
-
/** Boot decoration has no service dependency; the full theme waits below. */
|
|
14
|
-
export const inject = [];
|
|
15
|
-
/** Shade DSH's native appearance modes without replacing its preference UI. */
|
|
16
|
-
export function apply(ctx) {
|
|
17
|
-
ctx.effect(installXiaoheiPluginLoading, 'xiaohei-theme: replace plugin spinner with hopping Heixiu');
|
|
18
|
-
ctx.inject(['slots'], readyCtx => {
|
|
19
|
-
const disposeDraftPreview = readyCtx.slots.inject('conversation.input.dock', () => readyCtx.slots.register({
|
|
20
|
-
name: 'conversation.input.dock',
|
|
21
|
-
id: 'xiaohei-draft-preview',
|
|
22
|
-
order: 100,
|
|
23
|
-
}, XiaoheiDraftPreview));
|
|
24
|
-
const disposeSidebarMark = readyCtx.slots.inject('sidebar.brand.mark', () => readyCtx.slots.register({
|
|
25
|
-
name: 'sidebar.brand.mark',
|
|
26
|
-
priority: -20,
|
|
27
|
-
}, XiaoheiMetallicBrandMark));
|
|
28
|
-
const disposeSidebarName = readyCtx.slots.inject('sidebar.brand.name', () => readyCtx.slots.register({
|
|
29
|
-
name: 'sidebar.brand.name',
|
|
30
|
-
priority: -20,
|
|
31
|
-
}, XiaoheiBrandName));
|
|
32
|
-
const disposeHeroMark = readyCtx.slots.inject('conversation.hero.brand.mark', () => readyCtx.slots.register({
|
|
33
|
-
name: 'conversation.hero.brand.mark',
|
|
34
|
-
priority: -20,
|
|
35
|
-
}, XiaoheiMetallicBrandMark));
|
|
36
|
-
return () => {
|
|
37
|
-
disposeDraftPreview();
|
|
38
|
-
disposeHeroMark();
|
|
39
|
-
disposeSidebarName();
|
|
40
|
-
disposeSidebarMark();
|
|
41
|
-
};
|
|
42
|
-
});
|
|
43
|
-
ctx.inject(['theme'], (readyCtx) => installXiaoheiTheme(readyCtx));
|
|
44
|
-
}
|
|
45
|
-
/** Mount the complete theme only after its runtime services become available. */
|
|
46
|
-
function installXiaoheiTheme(ctx) {
|
|
47
|
-
ctx.effect(() => {
|
|
48
|
-
return ctx.theme.overrideTokens('@lemoncat7/dsh-theme-xiaohei', XIAOHEI_THEME_TOKEN_OVERRIDES);
|
|
49
|
-
}, 'xiaohei-theme: shade native Light / Dark / System palettes');
|
|
50
|
-
ctx.effect(() => bindXiaoheiAppearance(ctx), 'xiaohei-theme: follow resolved appearance');
|
|
51
|
-
ctx.effect(installXiaoheiChrome, 'xiaohei-theme: install spirit control skin');
|
|
52
|
-
ctx.effect(installXiaoheiScene, 'xiaohei-theme: paint wallpaper immediately');
|
|
53
|
-
ctx.effect(installXiaoheiComposerSendHeixiu, 'xiaohei-theme: turn the native send action into blinking Heixiu');
|
|
54
|
-
ctx.effect(installDeferredDecorations, 'xiaohei-theme: load decorations after first paint');
|
|
55
|
-
ctx.effect(installXiaoheiSidebarGlass, 'xiaohei-theme: install isolated sidebar glass');
|
|
56
|
-
const heixiuSignals = createHeixiuSignals();
|
|
57
|
-
ctx.effect(() => installDeferredCompanion(heixiuSignals), 'xiaohei-theme: mount Heixiu after conversation paint');
|
|
58
|
-
ctx.inject(['sessions'], ready => bindHeixiuSessions(ready.sessions, heixiuSignals));
|
|
59
|
-
}
|
|
60
|
-
//# sourceMappingURL=plugin.js.map
|
package/lib/portal.d.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
export declare const XIAOHEI_PORTAL_STYLE_ID = "dsh-theme-xiaohei/portal-style";
|
|
2
|
-
export declare const XIAOHEI_PORTAL_LAYER_ID = "dsh-theme-xiaohei/portal-layer";
|
|
3
|
-
export declare const XIAOHEI_PORTAL_DURATION_MS = 2600;
|
|
4
|
-
export declare const XIAOHEI_PORTAL_ACTIVITY_EVENT = "dsh-theme-xiaohei:portal-activity";
|
|
5
|
-
export declare const XIAOHEI_PORTAL_PROXIMITY_EVENT = "dsh-theme-xiaohei:portal-proximity";
|
|
6
|
-
export interface XiaoheiPortalActivityDetail {
|
|
7
|
-
active: boolean;
|
|
8
|
-
}
|
|
9
|
-
export interface XiaoheiPortalProximityDetail {
|
|
10
|
-
active: boolean;
|
|
11
|
-
target?: {
|
|
12
|
-
x: number;
|
|
13
|
-
y: number;
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
interface PortalPoint {
|
|
17
|
-
x: number;
|
|
18
|
-
y: number;
|
|
19
|
-
angle: number;
|
|
20
|
-
}
|
|
21
|
-
interface PortalInteraction {
|
|
22
|
-
phase: 'entry' | 'exit';
|
|
23
|
-
target: {
|
|
24
|
-
x: number;
|
|
25
|
-
y: number;
|
|
26
|
-
};
|
|
27
|
-
delayMs: number;
|
|
28
|
-
}
|
|
29
|
-
interface RectLike {
|
|
30
|
-
left: number;
|
|
31
|
-
top: number;
|
|
32
|
-
width: number;
|
|
33
|
-
height: number;
|
|
34
|
-
}
|
|
35
|
-
/** Resolve the closest visible portal phase without overlapping distant visits. */
|
|
36
|
-
export declare function resolveXiaoheiPortalInteraction(start: PortalPoint, finish: PortalPoint, mascotRect: RectLike): PortalInteraction | undefined;
|
|
37
|
-
/** Install ambient random visits without coupling them to conversation state. */
|
|
38
|
-
export declare function installXiaoheiPortalTransit(doc?: Document | undefined): () => void;
|
|
39
|
-
export {};
|
|
40
|
-
//# sourceMappingURL=portal.d.ts.map
|
package/lib/portal.js
DELETED
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
import { XIAOHEI_HEIXIU_BLINK, XIAOHEI_HEIXIU_OPEN } from './generated-keyart.js';
|
|
2
|
-
import { XIAOHEI_PORTAL_CSS } from './chrome/portal.js';
|
|
3
|
-
import { subscribeXiaoheiHostDom } from './host-dom.js';
|
|
4
|
-
import { XIAOHEI_HOST_SELECTORS } from './host-contract.js';
|
|
5
|
-
import { XIAOHEI_SCENE_LAYER_ID, XIAOHEI_SCENE_WORLD_CLASS } from './scene/ids.js';
|
|
6
|
-
export const XIAOHEI_PORTAL_STYLE_ID = 'dsh-theme-xiaohei/portal-style';
|
|
7
|
-
export const XIAOHEI_PORTAL_LAYER_ID = 'dsh-theme-xiaohei/portal-layer';
|
|
8
|
-
export const XIAOHEI_PORTAL_DURATION_MS = 2600;
|
|
9
|
-
export const XIAOHEI_PORTAL_ACTIVITY_EVENT = 'dsh-theme-xiaohei:portal-activity';
|
|
10
|
-
export const XIAOHEI_PORTAL_PROXIMITY_EVENT = 'dsh-theme-xiaohei:portal-proximity';
|
|
11
|
-
const INITIAL_VISIT_DELAY_MS = 1800;
|
|
12
|
-
const VISIT_MIN_DELAY_MS = 12_000;
|
|
13
|
-
const VISIT_DELAY_RANGE_MS = 9000;
|
|
14
|
-
const INTERACTION_RADIUS_PX = 420;
|
|
15
|
-
const INTERACTION_DURATION_MS = 520;
|
|
16
|
-
const ENTRY_INTERACTION_DELAY_MS = Math.round(XIAOHEI_PORTAL_DURATION_MS * 0.22);
|
|
17
|
-
const EXIT_INTERACTION_DELAY_MS = Math.round(XIAOHEI_PORTAL_DURATION_MS * 0.76);
|
|
18
|
-
/** Resolve the closest visible portal phase without overlapping distant visits. */
|
|
19
|
-
export function resolveXiaoheiPortalInteraction(start, finish, mascotRect) {
|
|
20
|
-
const head = {
|
|
21
|
-
x: mascotRect.left + mascotRect.width * 0.35,
|
|
22
|
-
y: mascotRect.top + mascotRect.height * 0.42,
|
|
23
|
-
};
|
|
24
|
-
const candidates = [
|
|
25
|
-
{ phase: 'entry', target: { x: start.x, y: start.y }, delayMs: ENTRY_INTERACTION_DELAY_MS },
|
|
26
|
-
{ phase: 'exit', target: { x: finish.x, y: finish.y }, delayMs: EXIT_INTERACTION_DELAY_MS },
|
|
27
|
-
];
|
|
28
|
-
const distance = (candidate) => Math.hypot(candidate.target.x - head.x, candidate.target.y - head.y);
|
|
29
|
-
const nearest = distance(candidates[0]) <= distance(candidates[1])
|
|
30
|
-
? candidates[0]
|
|
31
|
-
: candidates[1];
|
|
32
|
-
return distance(nearest) <= INTERACTION_RADIUS_PX ? nearest : undefined;
|
|
33
|
-
}
|
|
34
|
-
/** Install ambient random visits without coupling them to conversation state. */
|
|
35
|
-
export function installXiaoheiPortalTransit(doc = typeof document === 'undefined' ? undefined : document) {
|
|
36
|
-
if (doc?.body === undefined || doc.defaultView === null)
|
|
37
|
-
return () => { };
|
|
38
|
-
doc.getElementById(XIAOHEI_PORTAL_STYLE_ID)?.remove();
|
|
39
|
-
doc.getElementById(XIAOHEI_PORTAL_LAYER_ID)?.remove();
|
|
40
|
-
const style = doc.createElement('style');
|
|
41
|
-
style.id = XIAOHEI_PORTAL_STYLE_ID;
|
|
42
|
-
style.textContent = XIAOHEI_PORTAL_CSS;
|
|
43
|
-
doc.head.append(style);
|
|
44
|
-
const layer = doc.createElement('div');
|
|
45
|
-
layer.id = XIAOHEI_PORTAL_LAYER_ID;
|
|
46
|
-
layer.setAttribute('aria-hidden', 'true');
|
|
47
|
-
layer.dataset.running = 'false';
|
|
48
|
-
const entry = doc.createElement('span');
|
|
49
|
-
entry.className = 'xiaohei-portal__void xiaohei-portal__void--entry';
|
|
50
|
-
const exit = doc.createElement('span');
|
|
51
|
-
exit.className = 'xiaohei-portal__void xiaohei-portal__void--exit';
|
|
52
|
-
const traveler = doc.createElement('span');
|
|
53
|
-
traveler.className = 'xiaohei-portal__traveler';
|
|
54
|
-
traveler.append(createTravelerImage(doc, XIAOHEI_HEIXIU_OPEN, 'xiaohei-portal__traveler-open'), createTravelerImage(doc, XIAOHEI_HEIXIU_BLINK, 'xiaohei-portal__traveler-blink'));
|
|
55
|
-
layer.append(entry, exit, traveler);
|
|
56
|
-
const win = doc.defaultView;
|
|
57
|
-
let disposed = false;
|
|
58
|
-
let animationTimer = 0;
|
|
59
|
-
let visitTimer = 0;
|
|
60
|
-
let interactionStartTimer = 0;
|
|
61
|
-
let interactionEndTimer = 0;
|
|
62
|
-
let interactionActive = false;
|
|
63
|
-
let visitsStarted = false;
|
|
64
|
-
const mount = () => {
|
|
65
|
-
const scene = doc.getElementById(XIAOHEI_SCENE_LAYER_ID);
|
|
66
|
-
if (scene === null)
|
|
67
|
-
return false;
|
|
68
|
-
if (layer.parentElement !== scene) {
|
|
69
|
-
const world = scene.querySelector(`.${XIAOHEI_SCENE_WORLD_CLASS}`);
|
|
70
|
-
scene.insertBefore(layer, world?.nextSibling ?? scene.firstChild);
|
|
71
|
-
}
|
|
72
|
-
return true;
|
|
73
|
-
};
|
|
74
|
-
const clearTimer = (timer) => {
|
|
75
|
-
if (timer !== 0)
|
|
76
|
-
win.clearTimeout(timer);
|
|
77
|
-
};
|
|
78
|
-
const endInteraction = () => {
|
|
79
|
-
clearTimer(interactionStartTimer);
|
|
80
|
-
clearTimer(interactionEndTimer);
|
|
81
|
-
interactionStartTimer = 0;
|
|
82
|
-
interactionEndTimer = 0;
|
|
83
|
-
if (!interactionActive)
|
|
84
|
-
return;
|
|
85
|
-
interactionActive = false;
|
|
86
|
-
dispatchPortalProximity(doc, false);
|
|
87
|
-
};
|
|
88
|
-
const scheduleVisit = (initial = false) => {
|
|
89
|
-
clearTimer(visitTimer);
|
|
90
|
-
if (disposed)
|
|
91
|
-
return;
|
|
92
|
-
const delay = initial
|
|
93
|
-
? INITIAL_VISIT_DELAY_MS
|
|
94
|
-
: VISIT_MIN_DELAY_MS + Math.round(Math.random() * VISIT_DELAY_RANGE_MS);
|
|
95
|
-
visitTimer = win.setTimeout(play, delay);
|
|
96
|
-
};
|
|
97
|
-
const play = () => {
|
|
98
|
-
if (disposed || layer.dataset.running === 'true' || !mount())
|
|
99
|
-
return;
|
|
100
|
-
endInteraction();
|
|
101
|
-
const [start, finish] = choosePortalPoints(doc);
|
|
102
|
-
const styleMap = layer.style;
|
|
103
|
-
styleMap.setProperty('--portal-entry-x', `${start.x}px`);
|
|
104
|
-
styleMap.setProperty('--portal-entry-y', `${start.y}px`);
|
|
105
|
-
styleMap.setProperty('--portal-exit-x', `${finish.x}px`);
|
|
106
|
-
styleMap.setProperty('--portal-exit-y', `${finish.y}px`);
|
|
107
|
-
styleMap.setProperty('--portal-entry-angle', `${start.angle}deg`);
|
|
108
|
-
styleMap.setProperty('--portal-exit-angle', `${finish.angle}deg`);
|
|
109
|
-
styleMap.setProperty('--portal-travel-x', `${finish.x - start.x}px`);
|
|
110
|
-
styleMap.setProperty('--portal-travel-y', `${finish.y - start.y}px`);
|
|
111
|
-
const emergeDirection = finish.x < win.innerWidth / 2 ? -1 : 1;
|
|
112
|
-
styleMap.setProperty('--portal-emerge-near', `${emergeDirection * 20}px`);
|
|
113
|
-
styleMap.setProperty('--portal-emerge-far', `${emergeDirection * 69}px`);
|
|
114
|
-
styleMap.setProperty('--portal-emerge-end', `${emergeDirection * 86}px`);
|
|
115
|
-
layer.dataset.running = 'false';
|
|
116
|
-
void layer.offsetWidth;
|
|
117
|
-
layer.dataset.running = 'true';
|
|
118
|
-
dispatchPortalActivity(doc, true);
|
|
119
|
-
const mascotRect = doc.querySelector('.xiaohei-scene__mascot')?.getBoundingClientRect();
|
|
120
|
-
const interaction = mascotRect === undefined
|
|
121
|
-
? undefined
|
|
122
|
-
: resolveXiaoheiPortalInteraction(start, finish, mascotRect);
|
|
123
|
-
layer.dataset.interaction = interaction?.phase ?? 'none';
|
|
124
|
-
if (interaction !== undefined) {
|
|
125
|
-
interactionStartTimer = win.setTimeout(() => {
|
|
126
|
-
interactionStartTimer = 0;
|
|
127
|
-
if (disposed || layer.dataset.running !== 'true')
|
|
128
|
-
return;
|
|
129
|
-
interactionActive = true;
|
|
130
|
-
dispatchPortalProximity(doc, true, interaction.target);
|
|
131
|
-
interactionEndTimer = win.setTimeout(endInteraction, INTERACTION_DURATION_MS);
|
|
132
|
-
}, interaction.delayMs);
|
|
133
|
-
}
|
|
134
|
-
clearTimer(animationTimer);
|
|
135
|
-
animationTimer = win.setTimeout(() => {
|
|
136
|
-
animationTimer = 0;
|
|
137
|
-
if (disposed)
|
|
138
|
-
return;
|
|
139
|
-
endInteraction();
|
|
140
|
-
layer.dataset.running = 'false';
|
|
141
|
-
dispatchPortalActivity(doc, false);
|
|
142
|
-
scheduleVisit();
|
|
143
|
-
}, XIAOHEI_PORTAL_DURATION_MS);
|
|
144
|
-
};
|
|
145
|
-
const startVisits = () => {
|
|
146
|
-
if (visitsStarted || disposed)
|
|
147
|
-
return;
|
|
148
|
-
visitsStarted = true;
|
|
149
|
-
scheduleVisit(true);
|
|
150
|
-
};
|
|
151
|
-
let unsubscribeHostDom = () => { };
|
|
152
|
-
if (mount()) {
|
|
153
|
-
startVisits();
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
156
|
-
unsubscribeHostDom = subscribeXiaoheiHostDom(doc, () => {
|
|
157
|
-
if (!mount())
|
|
158
|
-
return;
|
|
159
|
-
unsubscribeHostDom();
|
|
160
|
-
startVisits();
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
return () => {
|
|
164
|
-
disposed = true;
|
|
165
|
-
clearTimer(animationTimer);
|
|
166
|
-
clearTimer(visitTimer);
|
|
167
|
-
endInteraction();
|
|
168
|
-
unsubscribeHostDom();
|
|
169
|
-
if (layer.dataset.running === 'true')
|
|
170
|
-
dispatchPortalActivity(doc, false);
|
|
171
|
-
layer.remove();
|
|
172
|
-
style.remove();
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
function dispatchPortalProximity(doc, active, target) {
|
|
176
|
-
const EventConstructor = doc.defaultView?.CustomEvent;
|
|
177
|
-
if (EventConstructor === undefined)
|
|
178
|
-
return;
|
|
179
|
-
doc.dispatchEvent(new EventConstructor(XIAOHEI_PORTAL_PROXIMITY_EVENT, {
|
|
180
|
-
detail: target === undefined ? { active } : { active, target },
|
|
181
|
-
}));
|
|
182
|
-
}
|
|
183
|
-
function dispatchPortalActivity(doc, active) {
|
|
184
|
-
const EventConstructor = doc.defaultView?.CustomEvent;
|
|
185
|
-
if (EventConstructor === undefined)
|
|
186
|
-
return;
|
|
187
|
-
doc.dispatchEvent(new EventConstructor(XIAOHEI_PORTAL_ACTIVITY_EVENT, {
|
|
188
|
-
detail: { active },
|
|
189
|
-
}));
|
|
190
|
-
}
|
|
191
|
-
function createTravelerImage(doc, source, className) {
|
|
192
|
-
const image = doc.createElement('img');
|
|
193
|
-
image.className = className;
|
|
194
|
-
image.alt = '';
|
|
195
|
-
image.decoding = 'async';
|
|
196
|
-
image.fetchPriority = 'low';
|
|
197
|
-
image.src = source;
|
|
198
|
-
return image;
|
|
199
|
-
}
|
|
200
|
-
/** Pick separated positions from background-biased zones, away from key UI. */
|
|
201
|
-
function choosePortalPoints(doc) {
|
|
202
|
-
const win = doc.defaultView;
|
|
203
|
-
const width = Math.max(640, win?.innerWidth ?? 1280);
|
|
204
|
-
const height = Math.max(480, win?.innerHeight ?? 720);
|
|
205
|
-
const sidebarRight = doc.querySelector(XIAOHEI_HOST_SELECTORS.sidebar)?.getBoundingClientRect().right ?? 0;
|
|
206
|
-
const composerRect = doc.querySelector(XIAOHEI_HOST_SELECTORS.composerCard)?.getBoundingClientRect();
|
|
207
|
-
const contentLeft = composerRect?.left ?? width * 0.37;
|
|
208
|
-
const contentRight = composerRect?.right ?? width * 0.77;
|
|
209
|
-
const leftMin = Math.max(sidebarRight + 80, 90);
|
|
210
|
-
const leftMax = Math.max(leftMin + 60, contentLeft - 90);
|
|
211
|
-
const rightMin = Math.min(width - 150, contentRight + 90);
|
|
212
|
-
const rightMax = width - 90;
|
|
213
|
-
const minY = 100;
|
|
214
|
-
const maxY = height - 130;
|
|
215
|
-
const point = (side) => {
|
|
216
|
-
const start = side === 'left' ? leftMin : rightMin;
|
|
217
|
-
const end = side === 'left' ? leftMax : rightMax;
|
|
218
|
-
const x = start + Math.random() * Math.max(40, end - start);
|
|
219
|
-
const y = minY + Math.random() * Math.max(120, maxY - minY);
|
|
220
|
-
return { x, y, angle: -8 + Math.round(Math.random() * 16) };
|
|
221
|
-
};
|
|
222
|
-
const leftFirst = Math.random() > 0.5;
|
|
223
|
-
return leftFirst ? [point('left'), point('right')] : [point('right'), point('left')];
|
|
224
|
-
}
|
|
225
|
-
//# sourceMappingURL=portal.js.map
|
package/lib/reactions.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export declare const XIAOHEI_REACTION_STYLE_ID = "dsh-theme-xiaohei/reaction-style";
|
|
2
|
-
export type EarReaction = 'ear-left' | 'ear-right';
|
|
3
|
-
interface Point {
|
|
4
|
-
x: number;
|
|
5
|
-
y: number;
|
|
6
|
-
}
|
|
7
|
-
interface MascotBounds {
|
|
8
|
-
left: number;
|
|
9
|
-
top: number;
|
|
10
|
-
width: number;
|
|
11
|
-
height: number;
|
|
12
|
-
}
|
|
13
|
-
/** Resolve a pointer only inside the two local, non-overlapping ear regions. */
|
|
14
|
-
export declare function resolveXiaoheiPointerEar(bounds: MascotBounds, target: Point, activeEar?: EarReaction): EarReaction | undefined;
|
|
15
|
-
/** Resolve the next sparse tail visit; exported to keep the timing contract testable. */
|
|
16
|
-
export declare function resolveXiaoheiIdleTailDelay(randomValue?: number): number;
|
|
17
|
-
/** Install proximity ear motion and sparse idle tails without a JavaScript frame loop. */
|
|
18
|
-
export declare function installXiaoheiIdleReactions(doc?: Document | undefined): () => void;
|
|
19
|
-
export {};
|
|
20
|
-
//# sourceMappingURL=reactions.d.ts.map
|