@lemoncat7/dsh-theme-xiaohei 0.4.6 → 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 +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 +532 -2405
- package/lib/index.d.ts +1 -2
- package/lib/index.js +393 -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
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const RIFT_BOOT_ID = "dsh-theme-xiaohei/rift-boot";
|
|
2
|
+
/** Read only the official, literal bootstrap preference. Never evaluate page code. */
|
|
3
|
+
export declare function bootPreference(html: string): 'light' | 'dark' | 'system';
|
|
4
|
+
/** Early wallpaper and native loader styling; one bounded read of local presentation preference. */
|
|
5
|
+
export declare function injectRiftBoot(html: string): string;
|
|
6
|
+
//# sourceMappingURL=boot.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lemoncat7/dsh-theme-xiaohei",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "A Luo Xiaohei-inspired animated dark theme for DeepSeek Harness",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|
|
@@ -26,20 +26,28 @@
|
|
|
26
26
|
"./package.json": "./package.json"
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
|
+
"docs/releases/0.5.0.md",
|
|
30
|
+
"docs/rift-interaction.md",
|
|
31
|
+
"docs/rift-preview.md",
|
|
29
32
|
"docs/releases/0.4.6.md",
|
|
30
33
|
"docs/releases/0.4.5.md",
|
|
31
34
|
"docs/startup-audit-20261013.md",
|
|
32
35
|
"docs/releases/0.4.4.md",
|
|
33
36
|
"docs/releases/0.4.3.md",
|
|
34
|
-
"lib
|
|
35
|
-
"lib
|
|
37
|
+
"lib/index.js",
|
|
38
|
+
"lib/index.d.ts",
|
|
39
|
+
"lib/rift/boot.d.ts",
|
|
40
|
+
"lib/client.js",
|
|
41
|
+
"lib/client.decorations.js",
|
|
42
|
+
"lib/client.companion.js",
|
|
36
43
|
"cordis.patch.yml",
|
|
37
44
|
"README.md",
|
|
38
45
|
"docs/releases/0.3.5.md",
|
|
39
46
|
"THIRD_PARTY_NOTICES.md",
|
|
40
47
|
"LICENSE",
|
|
41
48
|
"docs/releases/0.4.2.md",
|
|
42
|
-
"docs/dsh-020-compatibility.md"
|
|
49
|
+
"docs/dsh-020-compatibility.md",
|
|
50
|
+
"docs/dsh-021-compatibility.md"
|
|
43
51
|
],
|
|
44
52
|
"dsh": {
|
|
45
53
|
"bundle": {
|
|
@@ -57,10 +65,11 @@
|
|
|
57
65
|
}
|
|
58
66
|
},
|
|
59
67
|
"engines": {
|
|
60
|
-
"node": "^22.19.0 || >=24.0.0"
|
|
68
|
+
"node": "^22.19.0 || >=24.0.0",
|
|
69
|
+
"dsh": "^0.2.1-rc.2"
|
|
61
70
|
},
|
|
62
71
|
"scripts": {
|
|
63
|
-
"build": "node scripts/
|
|
72
|
+
"build": "node scripts/embed-rift.mjs && node scripts/embed-assets.mjs && tsc -p tsconfig.json && node scripts/build-rift.mjs",
|
|
64
73
|
"clean": "node -e \"require('node:fs').rmSync('lib', { recursive: true, force: true })\"",
|
|
65
74
|
"prepare": "npm run clean && npm run build",
|
|
66
75
|
"test": "npm run build && node --test test/*.test.mjs",
|
|
@@ -68,25 +77,26 @@
|
|
|
68
77
|
"pack:docker": "docker build --output type=local,dest=./dist ."
|
|
69
78
|
},
|
|
70
79
|
"peerDependencies": {
|
|
71
|
-
"@deepseek-ai/cordis": "^4.0.
|
|
72
|
-
"@deepseek-ai/dsh-client-ui-renderer": "^0.2.
|
|
73
|
-
"@deepseek-ai/dsh-client-ui-theme": "^0.2.
|
|
80
|
+
"@deepseek-ai/cordis": "^4.0.5",
|
|
81
|
+
"@deepseek-ai/dsh-client-ui-renderer": "^0.2.1-rc.2",
|
|
82
|
+
"@deepseek-ai/dsh-client-ui-theme": "^0.2.1-rc.2"
|
|
74
83
|
},
|
|
75
84
|
"devDependencies": {
|
|
76
|
-
"@deepseek-ai/cordis": "~4.0.
|
|
77
|
-
"@deepseek-ai/dsh-api-session-controller": "0.2.
|
|
78
|
-
"@deepseek-ai/dsh-client-ui-conversation": "0.2.
|
|
79
|
-
"@deepseek-ai/dsh-client-ui-
|
|
80
|
-
"@deepseek-ai/dsh-client-ui-
|
|
81
|
-
"@deepseek-ai/dsh-client-ui-
|
|
82
|
-
"@deepseek-ai/dsh-client-ui-
|
|
83
|
-
"@deepseek-ai/dsh-
|
|
85
|
+
"@deepseek-ai/cordis": "~4.0.5",
|
|
86
|
+
"@deepseek-ai/dsh-api-session-controller": "0.2.1-rc.2",
|
|
87
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.2.1-rc.2",
|
|
88
|
+
"@deepseek-ai/dsh-client-ui-layout": "0.2.1-rc.2",
|
|
89
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.2.1-rc.2",
|
|
90
|
+
"@deepseek-ai/dsh-client-ui-session": "0.2.1-rc.2",
|
|
91
|
+
"@deepseek-ai/dsh-client-ui-sidebar": "0.2.1-rc.2",
|
|
92
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.2.1-rc.2",
|
|
93
|
+
"@deepseek-ai/dsh-client-ui-theme": "0.2.1-rc.2",
|
|
94
|
+
"@deepseek-ai/dsh-host-webserver": "0.2.1-rc.2",
|
|
84
95
|
"@types/node": "^24.0.0",
|
|
85
96
|
"@types/react": "^18.3.28",
|
|
86
97
|
"esbuild": "^0.25.0",
|
|
87
98
|
"react": "^18.3.1",
|
|
88
|
-
"typescript": "^5.9.3"
|
|
89
|
-
"@deepseek-ai/dsh-client-ui-session": "0.2.0-rc.2"
|
|
99
|
+
"typescript": "^5.9.3"
|
|
90
100
|
},
|
|
91
101
|
"publishConfig": {
|
|
92
102
|
"access": "public"
|
package/lib/appearance.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { ThemeSnapshot } from '@deepseek-ai/dsh-client-ui-theme/client';
|
|
2
|
-
export declare const XIAOHEI_APPEARANCE_ATTRIBUTE = "data-xiaohei-appearance";
|
|
3
|
-
interface XiaoheiAppearanceContext {
|
|
4
|
-
theme: {
|
|
5
|
-
getTheme(): ThemeSnapshot;
|
|
6
|
-
};
|
|
7
|
-
on(event: 'theme/change', listener: (snapshot: ThemeSnapshot) => void): () => void;
|
|
8
|
-
}
|
|
9
|
-
/** Mirror DSH's resolved Light / Dark / System appearance onto the scene. */
|
|
10
|
-
export declare function bindXiaoheiAppearance(ctx: XiaoheiAppearanceContext, doc?: Document | undefined): () => void;
|
|
11
|
-
export {};
|
|
12
|
-
//# sourceMappingURL=appearance.d.ts.map
|
package/lib/appearance.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { releaseXiaoheiBootAppearance, XIAOHEI_BOOT_APPEARANCE_ATTRIBUTE, } from './boot-appearance.js';
|
|
2
|
-
export const XIAOHEI_APPEARANCE_ATTRIBUTE = 'data-xiaohei-appearance';
|
|
3
|
-
/** Mirror DSH's resolved Light / Dark / System appearance onto the scene. */
|
|
4
|
-
export function bindXiaoheiAppearance(ctx, doc = typeof document === 'undefined' ? undefined : document) {
|
|
5
|
-
if (doc === undefined)
|
|
6
|
-
return () => { };
|
|
7
|
-
const win = doc.defaultView;
|
|
8
|
-
let handoff;
|
|
9
|
-
let disposed = false;
|
|
10
|
-
const cancelHandoff = () => {
|
|
11
|
-
if (handoff !== undefined)
|
|
12
|
-
win?.clearTimeout(handoff);
|
|
13
|
-
handoff = undefined;
|
|
14
|
-
};
|
|
15
|
-
const sync = (snapshot) => {
|
|
16
|
-
if (disposed)
|
|
17
|
-
return;
|
|
18
|
-
cancelHandoff();
|
|
19
|
-
doc.documentElement.setAttribute(XIAOHEI_APPEARANCE_ATTRIBUTE, snapshot.active.colorScheme);
|
|
20
|
-
releaseXiaoheiBootAppearance(doc);
|
|
21
|
-
};
|
|
22
|
-
const off = ctx.on('theme/change', sync);
|
|
23
|
-
const initial = ctx.theme.getTheme();
|
|
24
|
-
const boot = doc.documentElement.getAttribute(XIAOHEI_BOOT_APPEARANCE_ATTRIBUTE);
|
|
25
|
-
if ((boot === 'light' || boot === 'dark') && boot !== initial.active.colorScheme) {
|
|
26
|
-
// Preserve the Host's first frame during settings hydration, but never
|
|
27
|
-
// let a stale boot marker veto later theme events or lock a palette.
|
|
28
|
-
doc.documentElement.setAttribute(XIAOHEI_APPEARANCE_ATTRIBUTE, boot);
|
|
29
|
-
if (win)
|
|
30
|
-
handoff = win.setTimeout(() => sync(ctx.theme.getTheme()), 1000);
|
|
31
|
-
}
|
|
32
|
-
else
|
|
33
|
-
sync(initial);
|
|
34
|
-
return () => {
|
|
35
|
-
disposed = true;
|
|
36
|
-
cancelHandoff();
|
|
37
|
-
off();
|
|
38
|
-
releaseXiaoheiBootAppearance(doc);
|
|
39
|
-
doc.documentElement.removeAttribute(XIAOHEI_APPEARANCE_ATTRIBUTE);
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
//# sourceMappingURL=appearance.js.map
|
package/lib/blink.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
export declare const XIAOHEI_BLINK_STYLE_ID = "dsh-theme-xiaohei/blink-style";
|
|
2
|
-
/** Own every blink from one DOM state so pupils and the closed frame change atomically. */
|
|
3
|
-
export declare function installXiaoheiBlink(doc?: Document | undefined): () => void;
|
|
4
|
-
//# sourceMappingURL=blink.d.ts.map
|
package/lib/blink.js
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { XIAOHEI_BLINK_CSS } from './chrome/blink.js';
|
|
2
|
-
import { XIAOHEI_HEIXIU_GREETING_EVENT } from './heixiu-interactions.js';
|
|
3
|
-
import { subscribeXiaoheiHostDom } from './host-dom.js';
|
|
4
|
-
export const XIAOHEI_BLINK_STYLE_ID = 'dsh-theme-xiaohei/blink-style';
|
|
5
|
-
const INITIAL_BLINK_DELAY_MS = 4780;
|
|
6
|
-
const IDLE_BLINK_INTERVAL_MS = 5065;
|
|
7
|
-
const IDLE_BLINK_CLOSED_MS = 135;
|
|
8
|
-
const HEIXIU_GREETING_BLINK_STEPS = [
|
|
9
|
-
{ at: 78, closed: true },
|
|
10
|
-
{ at: 224, closed: false },
|
|
11
|
-
{ at: 348, closed: true },
|
|
12
|
-
{ at: 447, closed: false },
|
|
13
|
-
];
|
|
14
|
-
/** Own every blink from one DOM state so pupils and the closed frame change atomically. */
|
|
15
|
-
export function installXiaoheiBlink(doc = typeof document === 'undefined' ? undefined : document) {
|
|
16
|
-
if (doc?.body === undefined || doc.defaultView === null)
|
|
17
|
-
return () => { };
|
|
18
|
-
const win = doc.defaultView;
|
|
19
|
-
doc.getElementById(XIAOHEI_BLINK_STYLE_ID)?.remove();
|
|
20
|
-
const style = doc.createElement('style');
|
|
21
|
-
style.id = XIAOHEI_BLINK_STYLE_ID;
|
|
22
|
-
style.textContent = XIAOHEI_BLINK_CSS;
|
|
23
|
-
doc.head.append(style);
|
|
24
|
-
const reducedMotion = win.matchMedia('(prefers-reduced-motion: reduce)');
|
|
25
|
-
const timers = new Set();
|
|
26
|
-
let disposed = false;
|
|
27
|
-
let mascot;
|
|
28
|
-
const isIdle = () => (doc.documentElement.getAttribute('data-xiaohei-state') ?? 'idle') === 'idle' && doc.visibilityState !== 'hidden' && !reducedMotion.matches;
|
|
29
|
-
const setClosed = (closed) => {
|
|
30
|
-
if (closed)
|
|
31
|
-
mascot?.setAttribute('data-xiaohei-blink', 'closed');
|
|
32
|
-
else
|
|
33
|
-
mascot?.removeAttribute('data-xiaohei-blink');
|
|
34
|
-
};
|
|
35
|
-
const clearTimers = () => {
|
|
36
|
-
for (const timer of timers)
|
|
37
|
-
win.clearTimeout(timer);
|
|
38
|
-
timers.clear();
|
|
39
|
-
};
|
|
40
|
-
const queue = (delay, callback) => {
|
|
41
|
-
const timer = win.setTimeout(() => {
|
|
42
|
-
timers.delete(timer);
|
|
43
|
-
if (!disposed)
|
|
44
|
-
callback();
|
|
45
|
-
}, delay);
|
|
46
|
-
timers.add(timer);
|
|
47
|
-
};
|
|
48
|
-
const scheduleIdleBlink = (initial = false) => {
|
|
49
|
-
if (!isIdle() || mascot === undefined)
|
|
50
|
-
return;
|
|
51
|
-
queue(initial ? INITIAL_BLINK_DELAY_MS : IDLE_BLINK_INTERVAL_MS, () => {
|
|
52
|
-
if (!isIdle())
|
|
53
|
-
return;
|
|
54
|
-
setClosed(true);
|
|
55
|
-
queue(IDLE_BLINK_CLOSED_MS, () => {
|
|
56
|
-
setClosed(false);
|
|
57
|
-
scheduleIdleBlink();
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
};
|
|
61
|
-
const restartIdleBlink = (initial = false) => {
|
|
62
|
-
clearTimers();
|
|
63
|
-
setClosed(false);
|
|
64
|
-
scheduleIdleBlink(initial);
|
|
65
|
-
};
|
|
66
|
-
const attach = () => {
|
|
67
|
-
const nextMascot = doc.querySelector('.xiaohei-scene__mascot') ?? undefined;
|
|
68
|
-
if (nextMascot === mascot)
|
|
69
|
-
return;
|
|
70
|
-
mascot?.removeAttribute('data-xiaohei-blink');
|
|
71
|
-
mascot = nextMascot;
|
|
72
|
-
restartIdleBlink(true);
|
|
73
|
-
};
|
|
74
|
-
const onHeixiuGreeting = () => {
|
|
75
|
-
if (!isIdle() || mascot === undefined)
|
|
76
|
-
return;
|
|
77
|
-
clearTimers();
|
|
78
|
-
setClosed(false);
|
|
79
|
-
for (const step of HEIXIU_GREETING_BLINK_STEPS) {
|
|
80
|
-
queue(step.at, () => setClosed(step.closed));
|
|
81
|
-
}
|
|
82
|
-
queue(520, () => {
|
|
83
|
-
setClosed(false);
|
|
84
|
-
scheduleIdleBlink();
|
|
85
|
-
});
|
|
86
|
-
};
|
|
87
|
-
const onEnvironmentChange = () => restartIdleBlink();
|
|
88
|
-
const unsubscribeHostDom = subscribeXiaoheiHostDom(doc, attach);
|
|
89
|
-
const stateObserver = new win.MutationObserver(onEnvironmentChange);
|
|
90
|
-
stateObserver.observe(doc.documentElement, {
|
|
91
|
-
attributes: true,
|
|
92
|
-
attributeFilter: ['data-xiaohei-state'],
|
|
93
|
-
});
|
|
94
|
-
doc.addEventListener('visibilitychange', onEnvironmentChange);
|
|
95
|
-
doc.addEventListener(XIAOHEI_HEIXIU_GREETING_EVENT, onHeixiuGreeting);
|
|
96
|
-
reducedMotion.addEventListener('change', onEnvironmentChange);
|
|
97
|
-
attach();
|
|
98
|
-
return () => {
|
|
99
|
-
disposed = true;
|
|
100
|
-
clearTimers();
|
|
101
|
-
unsubscribeHostDom();
|
|
102
|
-
stateObserver.disconnect();
|
|
103
|
-
doc.removeEventListener('visibilitychange', onEnvironmentChange);
|
|
104
|
-
doc.removeEventListener(XIAOHEI_HEIXIU_GREETING_EVENT, onHeixiuGreeting);
|
|
105
|
-
reducedMotion.removeEventListener('change', onEnvironmentChange);
|
|
106
|
-
mascot?.removeAttribute('data-xiaohei-blink');
|
|
107
|
-
style.remove();
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
//# sourceMappingURL=blink.js.map
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
const unit = (n) => Number.isFinite(n) ? Math.max(0, Math.min(.999999, n)) : .5;
|
|
2
|
-
export function heixiuAmbientDelay(random = Math.random) {
|
|
3
|
-
return 20_000 + Math.floor(unit(random()) * 20_000);
|
|
4
|
-
}
|
|
5
|
-
export function heixiuAmbientIndex(count, previous, random = Math.random) {
|
|
6
|
-
if (count <= 1)
|
|
7
|
-
return 0;
|
|
8
|
-
const exclude = previous >= 0 && previous < count;
|
|
9
|
-
const index = Math.floor(unit(random()) * (exclude ? count - 1 : count));
|
|
10
|
-
return exclude && index >= previous ? index + 1 : index;
|
|
11
|
-
}
|
|
12
|
-
//# sourceMappingURL=ambient.js.map
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import type { BotExpression } from '../vendor/bloub/expressions.js';
|
|
2
|
-
export declare const HEIXIU_PROFILE: number[];
|
|
3
|
-
export declare const HEIXIU_FACE: BotExpression;
|
|
4
|
-
export declare const HEIXIU_FOOT: number;
|
|
5
|
-
export interface HeixiuReaction {
|
|
6
|
-
x: number;
|
|
7
|
-
y: number;
|
|
8
|
-
sx: number;
|
|
9
|
-
sy: number;
|
|
10
|
-
roll: number;
|
|
11
|
-
lid: number;
|
|
12
|
-
cheer: number;
|
|
13
|
-
}
|
|
14
|
-
export declare const HEIXIU_REST: HeixiuReaction;
|
|
15
|
-
export declare const HEIXIU_REACTIONS: readonly ["greet", "hop", "wiggle"];
|
|
16
|
-
export type HeixiuReactionId = typeof HEIXIU_REACTIONS[number];
|
|
17
|
-
/** One bounded, interruptible gesture track; never queues clicks or runs timers. */
|
|
18
|
-
export declare class HeixiuReactions {
|
|
19
|
-
private start;
|
|
20
|
-
private keys;
|
|
21
|
-
private hover;
|
|
22
|
-
private hoverAt;
|
|
23
|
-
private hoverFrom;
|
|
24
|
-
private hoverTo;
|
|
25
|
-
get end(): number;
|
|
26
|
-
reset(): void;
|
|
27
|
-
settle(time: number): void;
|
|
28
|
-
aim(direction: number, time: number): void;
|
|
29
|
-
private track;
|
|
30
|
-
play(kind: HeixiuReactionId, time: number, side?: number): void;
|
|
31
|
-
sample(time: number): HeixiuReaction;
|
|
32
|
-
}
|
|
33
|
-
//# sourceMappingURL=character.d.ts.map
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import { superellipseProfile } from '../vendor/bloub/shape.js';
|
|
2
|
-
// Slightly wider than tall: a soft black body, not an upright head or a flat
|
|
3
|
-
// pill. Side tips sit near the equator. Keep bloub's 64 radial samples.
|
|
4
|
-
export const HEIXIU_PROFILE = superellipseProfile(2.2, 1, .89).map((r, i, radii) => {
|
|
5
|
-
const angle = i / radii.length * Math.PI * 2;
|
|
6
|
-
const bump = (center, width, amount) => {
|
|
7
|
-
const d = Math.atan2(Math.sin(angle - center), Math.cos(angle - center));
|
|
8
|
-
return amount * Math.exp(-.5 * (d / width) ** 2);
|
|
9
|
-
};
|
|
10
|
-
return r * (1 + .016 * Math.sin(angle))
|
|
11
|
-
+ bump(6.12, .12, .065) + bump(3.30, .12, .065)
|
|
12
|
-
+ bump(4.04, .10, .025);
|
|
13
|
-
});
|
|
14
|
-
export const HEIXIU_FACE = {
|
|
15
|
-
id: 'neutre', gaze: { yaw: 0, pitch: -7, roll: -2 }, split: 26,
|
|
16
|
-
eyes: [{ w: .355, h: .48, open: 1 }, { w: .34, h: .465, open: 1 }],
|
|
17
|
-
};
|
|
18
|
-
// Derive the squash pivot from the body itself so a proportion adjustment
|
|
19
|
-
// cannot leave the character rotating/compressing around an invisible foot.
|
|
20
|
-
export const HEIXIU_FOOT = Math.max(...HEIXIU_PROFILE.map((r, i) => r * Math.sin(i / HEIXIU_PROFILE.length * Math.PI * 2))) * 100;
|
|
21
|
-
export const HEIXIU_REST = { x: 0, y: 0, sx: 1, sy: 1, roll: 0, lid: 1, cheer: 0 };
|
|
22
|
-
export const HEIXIU_REACTIONS = ['greet', 'hop', 'wiggle'];
|
|
23
|
-
const smooth = (x) => { const k = Math.max(0, Math.min(1, x)); return k * k * (3 - 2 * k); };
|
|
24
|
-
const pose = (over) => ({ ...HEIXIU_REST, ...over });
|
|
25
|
-
const CHANNELS = Object.keys(HEIXIU_REST);
|
|
26
|
-
// Shape-preserving Hermite tangents: a rising/falling arc passes through its
|
|
27
|
-
// intermediate samples without stopping at every key. Extrema still settle,
|
|
28
|
-
// and lids/scales never overshoot their authored bounds.
|
|
29
|
-
function tangent(keys, index, channel) {
|
|
30
|
-
if (index === 0 || index === keys.length - 1)
|
|
31
|
-
return 0;
|
|
32
|
-
const a = keys[index - 1], b = keys[index], c = keys[index + 1];
|
|
33
|
-
const h0 = b.at - a.at, h1 = c.at - b.at;
|
|
34
|
-
const d0 = (b.pose[channel] - a.pose[channel]) / h0, d1 = (c.pose[channel] - b.pose[channel]) / h1;
|
|
35
|
-
if (d0 * d1 <= 0)
|
|
36
|
-
return 0;
|
|
37
|
-
const w0 = 2 * h1 + h0, w1 = h1 + 2 * h0;
|
|
38
|
-
return (w0 + w1) / (w0 / d0 + w1 / d1);
|
|
39
|
-
}
|
|
40
|
-
/** One bounded, interruptible gesture track; never queues clicks or runs timers. */
|
|
41
|
-
export class HeixiuReactions {
|
|
42
|
-
start = 0;
|
|
43
|
-
keys = [];
|
|
44
|
-
hover = 0;
|
|
45
|
-
hoverAt = 0;
|
|
46
|
-
hoverFrom = 0;
|
|
47
|
-
hoverTo = 0;
|
|
48
|
-
get end() { return this.start + (this.keys.at(-1)?.at ?? 0); }
|
|
49
|
-
reset() { this.keys = []; this.hover = this.hoverFrom = this.hoverTo = 0; }
|
|
50
|
-
settle(time) {
|
|
51
|
-
const origin = this.track(time);
|
|
52
|
-
this.start = time;
|
|
53
|
-
this.keys = [{ at: 0, pose: origin }, { at: .22, pose: { ...HEIXIU_REST } }];
|
|
54
|
-
this.aim(0, time);
|
|
55
|
-
}
|
|
56
|
-
aim(direction, time) {
|
|
57
|
-
this.hover = this.hoverFrom + (this.hoverTo - this.hoverFrom) * smooth((time - this.hoverAt) / .28);
|
|
58
|
-
this.hoverFrom = this.hover;
|
|
59
|
-
this.hoverTo = Math.max(-1, Math.min(1, direction));
|
|
60
|
-
this.hoverAt = time;
|
|
61
|
-
}
|
|
62
|
-
track(time) {
|
|
63
|
-
if (!this.keys.length || time >= this.end)
|
|
64
|
-
return { ...HEIXIU_REST };
|
|
65
|
-
const t = Math.max(0, time - this.start);
|
|
66
|
-
let left = this.keys[0];
|
|
67
|
-
for (let i = 1; i < this.keys.length; i++) {
|
|
68
|
-
const right = this.keys[i];
|
|
69
|
-
if (t <= right.at) {
|
|
70
|
-
const span = right.at - left.at, k = (t - left.at) / span;
|
|
71
|
-
const k2 = k * k, k3 = k2 * k;
|
|
72
|
-
const out = { ...left.pose };
|
|
73
|
-
for (const key of CHANNELS) {
|
|
74
|
-
out[key] = (2 * k3 - 3 * k2 + 1) * left.pose[key] + (-2 * k3 + 3 * k2) * right.pose[key]
|
|
75
|
-
+ (k3 - 2 * k2 + k) * span * tangent(this.keys, i - 1, key)
|
|
76
|
-
+ (k3 - k2) * span * tangent(this.keys, i, key);
|
|
77
|
-
}
|
|
78
|
-
return out;
|
|
79
|
-
}
|
|
80
|
-
left = right;
|
|
81
|
-
}
|
|
82
|
-
return { ...HEIXIU_REST };
|
|
83
|
-
}
|
|
84
|
-
play(kind, time, side = 1) {
|
|
85
|
-
const origin = this.track(time), sign = side < 0 ? -1 : 1;
|
|
86
|
-
const keys = [{ at: 0, pose: origin }];
|
|
87
|
-
const add = (at, over) => keys.push({ at, pose: pose(over) });
|
|
88
|
-
if (kind === 'greet') {
|
|
89
|
-
add(.09, { lid: .25, sy: .99, cheer: .35 });
|
|
90
|
-
add(.16, { lid: 0, sy: .985, cheer: .35, roll: -2 * sign });
|
|
91
|
-
add(.26, { y: -2, sy: 1.005, roll: 1 * sign });
|
|
92
|
-
add(.43, { y: -7, sx: .99, sy: 1.015, roll: 3 * sign });
|
|
93
|
-
add(.67, { sx: 1.018, sy: .982, roll: -1 * sign });
|
|
94
|
-
add(.95, {});
|
|
95
|
-
}
|
|
96
|
-
else if (kind === 'hop') {
|
|
97
|
-
add(.12, { sx: 1.065, sy: .94, lid: .85, roll: -2 * sign });
|
|
98
|
-
add(.23, { sx: .97, sy: 1.045, y: -14, roll: 2 * sign });
|
|
99
|
-
add(.40, { sx: .99, sy: 1.02, y: -28, roll: 3 * sign });
|
|
100
|
-
add(.57, { sy: 1.015, y: -14, roll: 1 * sign });
|
|
101
|
-
add(.69, { sx: 1.06, sy: .94, lid: .55, cheer: .3 });
|
|
102
|
-
add(.80, { sx: .985, sy: 1.02 });
|
|
103
|
-
add(1.02, {});
|
|
104
|
-
}
|
|
105
|
-
else {
|
|
106
|
-
add(.18, { x: -2 * sign, roll: -7 * sign });
|
|
107
|
-
add(.38, { x: 2 * sign, roll: 7 * sign });
|
|
108
|
-
add(.55, { x: -1 * sign, roll: -3 * sign, lid: .3, cheer: .2 });
|
|
109
|
-
add(.64, { roll: -1 * sign, lid: 0, cheer: .2 });
|
|
110
|
-
add(.78, {});
|
|
111
|
-
add(.96, {});
|
|
112
|
-
}
|
|
113
|
-
this.start = time;
|
|
114
|
-
this.keys = keys;
|
|
115
|
-
}
|
|
116
|
-
sample(time) {
|
|
117
|
-
const out = this.track(time);
|
|
118
|
-
this.hover = this.hoverFrom + (this.hoverTo - this.hoverFrom) * smooth((time - this.hoverAt) / .28);
|
|
119
|
-
out.roll += this.hover * 5;
|
|
120
|
-
out.x += this.hover * 4;
|
|
121
|
-
return out;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
//# sourceMappingURL=character.js.map
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { BotFrame } from '../vendor/bloub/engine.js';
|
|
2
|
-
/** Allocated once on first explicit special action, never from the frame loop. */
|
|
3
|
-
export declare function createHeixiuEffects(doc: Document, id: string, defs: SVGDefsElement, behind: SVGGElement, front: SVGGElement, body: SVGGElement): (frame: BotFrame) => void;
|
|
4
|
-
//# sourceMappingURL=effects.d.ts.map
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
const NS = 'http://www.w3.org/2000/svg';
|
|
2
|
-
/** Allocated once on first explicit special action, never from the frame loop. */
|
|
3
|
-
export function createHeixiuEffects(doc, id, defs, behind, front, body) {
|
|
4
|
-
const el = (name) => doc.createElementNS(NS, name);
|
|
5
|
-
const attrs = (node, values) => {
|
|
6
|
-
for (const [key, value] of Object.entries(values)) {
|
|
7
|
-
const text = String(value);
|
|
8
|
-
if (node.getAttribute(key) !== text)
|
|
9
|
-
node.setAttribute(key, text);
|
|
10
|
-
}
|
|
11
|
-
};
|
|
12
|
-
const dotsBack = el('g'), dotsFront = el('g');
|
|
13
|
-
behind.append(dotsBack);
|
|
14
|
-
front.append(dotsFront);
|
|
15
|
-
// Real transparent notch, never a wallpaper-coloured disc over the body.
|
|
16
|
-
const mask = el('mask'), surface = el('rect'), notch = el('circle'), badge = el('circle');
|
|
17
|
-
attrs(mask, { id: `${id}-notification`, maskUnits: 'userSpaceOnUse', x: -200, y: -200, width: 400, height: 400, 'mask-type': 'luminance' });
|
|
18
|
-
attrs(surface, { x: -200, y: -200, width: 400, height: 400, fill: 'white' });
|
|
19
|
-
attrs(notch, { fill: 'black', r: 0, 'data-heixiu-notch': '' });
|
|
20
|
-
attrs(badge, { fill: '#dca964', display: 'none', 'data-heixiu-notification': '' });
|
|
21
|
-
mask.append(surface, notch);
|
|
22
|
-
defs.append(mask);
|
|
23
|
-
front.append(badge);
|
|
24
|
-
const dots = Array.from({ length: 12 }, () => {
|
|
25
|
-
const node = el('path');
|
|
26
|
-
attrs(node, { display: 'none', 'data-heixiu-particle': '' });
|
|
27
|
-
dotsFront.append(node);
|
|
28
|
-
return node;
|
|
29
|
-
});
|
|
30
|
-
const arcs = Array.from({ length: 12 }, (_, i) => {
|
|
31
|
-
const gradient = el('linearGradient'), back = el('path'), fore = el('path');
|
|
32
|
-
attrs(gradient, { id: `${id}-arc-${i}`, gradientUnits: 'userSpaceOnUse' });
|
|
33
|
-
const stops = Array.from({ length: 3 }, () => el('stop'));
|
|
34
|
-
gradient.append(...stops);
|
|
35
|
-
defs.append(gradient);
|
|
36
|
-
for (const node of [back, fore])
|
|
37
|
-
attrs(node, {
|
|
38
|
-
fill: 'none', 'stroke-linecap': 'round', stroke: `url(#${id}-arc-${i})`, display: 'none', 'data-heixiu-orbit': '',
|
|
39
|
-
});
|
|
40
|
-
behind.append(back);
|
|
41
|
-
front.append(fore);
|
|
42
|
-
return { gradient, back, fore, stops };
|
|
43
|
-
});
|
|
44
|
-
return (frame) => {
|
|
45
|
-
if (frame.notif && frame.notch) {
|
|
46
|
-
attrs(body, { mask: `url(#${id}-notification)` });
|
|
47
|
-
attrs(notch, { cx: frame.notch.x, cy: frame.notch.y, r: frame.notch.r });
|
|
48
|
-
attrs(badge, { display: 'inline', cx: frame.notif.x, cy: frame.notif.y, r: frame.notif.r });
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
if (body.getAttribute('mask'))
|
|
52
|
-
body.removeAttribute('mask');
|
|
53
|
-
attrs(notch, { r: 0 });
|
|
54
|
-
attrs(badge, { display: 'none' });
|
|
55
|
-
}
|
|
56
|
-
for (const [i, node] of dots.entries()) {
|
|
57
|
-
const dot = frame.dots[i];
|
|
58
|
-
if (!dot) {
|
|
59
|
-
attrs(node, { display: 'none' });
|
|
60
|
-
continue;
|
|
61
|
-
}
|
|
62
|
-
const parent = frame.dotsBehind ? dotsBack : dotsFront;
|
|
63
|
-
if (node.parentNode !== parent)
|
|
64
|
-
parent.append(node);
|
|
65
|
-
const r = dot.r;
|
|
66
|
-
attrs(node, { display: 'inline',
|
|
67
|
-
d: dot.d ?? `M${-r} 0a${r} ${r} 0 1 0 ${r * 2} 0a${r} ${r} 0 1 0 ${-r * 2} 0`,
|
|
68
|
-
transform: `translate(${dot.x} ${dot.y}) rotate(${dot.rot ?? 0}) scale(${dot.d ? 100 : 1})`,
|
|
69
|
-
fill: dot.color ?? 'var(--heixiu-ink)', opacity: dot.opacity * (dot.depth ?? 1),
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
for (const [i, nodes] of arcs.entries()) {
|
|
73
|
-
const arc = frame.arcs[i];
|
|
74
|
-
if (!arc) {
|
|
75
|
-
attrs(nodes.back, { display: 'none' });
|
|
76
|
-
attrs(nodes.fore, { display: 'none' });
|
|
77
|
-
continue;
|
|
78
|
-
}
|
|
79
|
-
attrs(nodes.gradient, { x1: arc.grad.x1, y1: arc.grad.y1, x2: arc.grad.x2, y2: arc.grad.y2 });
|
|
80
|
-
for (const [j, stop] of nodes.stops.entries())
|
|
81
|
-
attrs(stop, {
|
|
82
|
-
offset: j / 2, 'stop-color': arc.grad.stops[Math.min(j, arc.grad.stops.length - 1)] ?? '#ddd',
|
|
83
|
-
});
|
|
84
|
-
for (const [node, d] of [[nodes.back, arc.back], [nodes.fore, arc.front]])
|
|
85
|
-
attrs(node, {
|
|
86
|
-
display: 'inline', d, 'stroke-width': arc.width, opacity: arc.opacity,
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
//# sourceMappingURL=effects.js.map
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export interface HeixiuBox {
|
|
2
|
-
left: number;
|
|
3
|
-
top: number;
|
|
4
|
-
width: number;
|
|
5
|
-
height: number;
|
|
6
|
-
}
|
|
7
|
-
/** FLIP between native docks; the existing SVG and reaction clock stay alive. */
|
|
8
|
-
export declare function createHeixiuFlight(button: HTMLElement): {
|
|
9
|
-
readonly active: boolean;
|
|
10
|
-
capture: (fallback?: HeixiuBox) => HeixiuBox | undefined;
|
|
11
|
-
target(measured: HeixiuBox): HeixiuBox;
|
|
12
|
-
move(from: HeixiuBox | undefined, to: HeixiuBox, reduced: boolean): void;
|
|
13
|
-
cancel: () => void;
|
|
14
|
-
};
|
|
15
|
-
//# sourceMappingURL=flight.d.ts.map
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
const copyBox = (box) => ({ left: box.left, top: box.top, width: box.width, height: box.height });
|
|
2
|
-
/** FLIP between native docks; the existing SVG and reaction clock stay alive. */
|
|
3
|
-
export function createHeixiuFlight(button) {
|
|
4
|
-
let animation;
|
|
5
|
-
let route;
|
|
6
|
-
const active = () => animation?.playState === 'running';
|
|
7
|
-
const progress = () => Math.max(0, Math.min(1, animation?.effect?.getComputedTiming().progress ?? 0));
|
|
8
|
-
// Native borders can settle by half a CSS pixel; this is not a new flight.
|
|
9
|
-
const same = (a, b) => ['left', 'top', 'width', 'height'].every(k => Math.abs(a[k] - b[k]) < 1);
|
|
10
|
-
function position(fallback) {
|
|
11
|
-
if (!active() || !route)
|
|
12
|
-
return fallback;
|
|
13
|
-
const p = progress();
|
|
14
|
-
const lerp = (key) => route.from[key] + (route.to[key] - route.from[key]) * p;
|
|
15
|
-
return { left: lerp('left'), top: lerp('top'), width: lerp('width'), height: lerp('height') };
|
|
16
|
-
}
|
|
17
|
-
function cancel() {
|
|
18
|
-
if (animation) {
|
|
19
|
-
animation.onfinish = null;
|
|
20
|
-
animation.cancel();
|
|
21
|
-
animation = undefined;
|
|
22
|
-
}
|
|
23
|
-
route = undefined;
|
|
24
|
-
button.dataset.flying = 'false';
|
|
25
|
-
}
|
|
26
|
-
return {
|
|
27
|
-
get active() { return active(); },
|
|
28
|
-
// Read the previous viewport trajectory, not a box already displaced by
|
|
29
|
-
// the moving composer. Capturing must not cancel/restart an equal target.
|
|
30
|
-
capture: position,
|
|
31
|
-
target(measured) {
|
|
32
|
-
if (!active() || !route)
|
|
33
|
-
return measured;
|
|
34
|
-
const p = progress(), { from, to } = route;
|
|
35
|
-
const scale = (from.width / to.width) * (1 - p) + p;
|
|
36
|
-
const width = measured.width / scale, height = measured.height / scale;
|
|
37
|
-
const dx = (from.left + from.width / 2 - to.left - to.width / 2) * (1 - p);
|
|
38
|
-
const dy = (from.top + from.height / 2 - to.top - to.height / 2) * (1 - p);
|
|
39
|
-
return { left: measured.left - dx + (measured.width - width) / 2,
|
|
40
|
-
top: measured.top - dy + (measured.height - height) / 2, width, height };
|
|
41
|
-
},
|
|
42
|
-
move(from, to, reduced) {
|
|
43
|
-
if (!reduced && active() && route && same(route.to, to))
|
|
44
|
-
return;
|
|
45
|
-
const duration = active() && route ? Math.max(80, route.duration - Number(animation.currentTime ?? 0)) : 950;
|
|
46
|
-
cancel();
|
|
47
|
-
if (!from || reduced || typeof button.animate !== 'function' || !from.width || !to.width)
|
|
48
|
-
return;
|
|
49
|
-
const dx = from.left + from.width / 2 - to.left - to.width / 2;
|
|
50
|
-
const dy = from.top + from.height / 2 - to.top - to.height / 2;
|
|
51
|
-
if (Math.hypot(dx, dy) < 4 && Math.abs(from.width - to.width) < 1)
|
|
52
|
-
return;
|
|
53
|
-
route = { from: copyBox(from), to: copyBox(to), duration };
|
|
54
|
-
animation = button.animate([
|
|
55
|
-
{ transform: `translate(${dx}px, ${dy}px) scale(${from.width / to.width})` },
|
|
56
|
-
{ transform: 'translate(0px, 0px) scale(1)' },
|
|
57
|
-
], { duration, easing: 'cubic-bezier(.22,.75,.2,1)' });
|
|
58
|
-
button.dataset.flying = 'true';
|
|
59
|
-
const current = animation;
|
|
60
|
-
current.onfinish = () => { if (animation === current)
|
|
61
|
-
cancel(); };
|
|
62
|
-
},
|
|
63
|
-
cancel,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
//# sourceMappingURL=flight.js.map
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/** Attraction measured from the stationary hit area, not the moving artwork. */
|
|
2
|
-
export declare function resolveHeixiuGaze(dx: number, dy: number): {
|
|
3
|
-
yaw: number;
|
|
4
|
-
pitch: number;
|
|
5
|
-
mix: number;
|
|
6
|
-
spin: number;
|
|
7
|
-
wander: number;
|
|
8
|
-
};
|
|
9
|
-
export declare function resolveHeixiuFollow(dx: number, dy: number, compact: boolean): {
|
|
10
|
-
x: number;
|
|
11
|
-
y: number;
|
|
12
|
-
};
|
|
13
|
-
//# sourceMappingURL=follow.d.ts.map
|