@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
|
@@ -1,340 +0,0 @@
|
|
|
1
|
-
const POINTER_ALERT_RADIUS_PX = 92;
|
|
2
|
-
const ESCAPE_DESTINATION_CANDIDATES = 32;
|
|
3
|
-
const ESCAPE_MIN_POINTER_DISTANCE_PX = 138;
|
|
4
|
-
const ESCAPE_MIN_TRAVEL_PX = 96;
|
|
5
|
-
const ESCAPE_ENTER_MS = 460;
|
|
6
|
-
const ESCAPE_EXIT_MS = 540;
|
|
7
|
-
const ESCAPE_COOLDOWN_MS = 1900;
|
|
8
|
-
const ESCAPE_EDGE_PADDING_PX = 10;
|
|
9
|
-
export const XIAOHEI_SIDEBAR_ESCAPE_CSS = `
|
|
10
|
-
.xiaohei-sidebar-escape-layer {
|
|
11
|
-
position: absolute;
|
|
12
|
-
inset: 0;
|
|
13
|
-
z-index: 5;
|
|
14
|
-
overflow: hidden;
|
|
15
|
-
contain: layout paint style;
|
|
16
|
-
pointer-events: none;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
.xiaohei-sidebar-escape-portal {
|
|
20
|
-
position: absolute;
|
|
21
|
-
left: var(--xiaohei-sidebar-portal-x, 50%);
|
|
22
|
-
top: var(--xiaohei-sidebar-portal-y, 50%);
|
|
23
|
-
display: block;
|
|
24
|
-
width: 2rem;
|
|
25
|
-
height: 2.8rem;
|
|
26
|
-
border-radius: 48% 52% 45% 55% / 54% 46% 55% 45%;
|
|
27
|
-
opacity: 0;
|
|
28
|
-
background:
|
|
29
|
-
radial-gradient(ellipse at 46% 50%, #010304 0%, #020608 57%, #0a2528 70%, rgb(77 194 171 / 40%) 77%, transparent 83%);
|
|
30
|
-
box-shadow:
|
|
31
|
-
inset 0 0 0.55rem rgb(0 0 0 / 94%),
|
|
32
|
-
0 0 0.65rem rgb(76 201 177 / 16%);
|
|
33
|
-
transform: translate3d(-50%, -50%, 0) rotate(var(--xiaohei-sidebar-portal-angle, 0deg)) scale3d(.06, .16, 1);
|
|
34
|
-
transform-origin: center;
|
|
35
|
-
will-change: transform, opacity;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
.xiaohei-sidebar-escape-portal::after {
|
|
39
|
-
position: absolute;
|
|
40
|
-
inset: 14% 19%;
|
|
41
|
-
display: block;
|
|
42
|
-
content: '';
|
|
43
|
-
border-radius: inherit;
|
|
44
|
-
background: #000102;
|
|
45
|
-
box-shadow: inset 0.15rem 0 0.36rem rgb(18 68 67 / 42%);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
.xiaohei-sidebar-escape-layer[data-xiaohei-sidebar-escape-phase='enter']
|
|
49
|
-
.xiaohei-sidebar-escape-portal--entry,
|
|
50
|
-
.xiaohei-sidebar-escape-layer[data-xiaohei-sidebar-escape-phase='exit']
|
|
51
|
-
.xiaohei-sidebar-escape-portal--exit {
|
|
52
|
-
animation: xiaohei-sidebar-escape-portal-open 520ms cubic-bezier(.2, .76, .24, 1) both;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
.xiaohei-scene__heixiu--sidebar[data-xiaohei-sidebar-escape-phase]::before {
|
|
56
|
-
opacity: 0;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
.xiaohei-scene__heixiu--sidebar[data-xiaohei-sidebar-escape-phase]
|
|
60
|
-
.xiaohei-scene__heixiu-body {
|
|
61
|
-
position: absolute;
|
|
62
|
-
inset: 0;
|
|
63
|
-
display: block;
|
|
64
|
-
transition: none;
|
|
65
|
-
transform-origin: center;
|
|
66
|
-
will-change: transform, opacity;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
.xiaohei-scene__heixiu--sidebar[data-xiaohei-sidebar-escape-phase='enter']
|
|
70
|
-
.xiaohei-scene__heixiu-body {
|
|
71
|
-
animation: xiaohei-sidebar-heixiu-enter ${ESCAPE_ENTER_MS}ms cubic-bezier(.42, 0, .72, .38) both;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
.xiaohei-scene__heixiu--sidebar[data-xiaohei-sidebar-escape-phase='exit']
|
|
75
|
-
.xiaohei-scene__heixiu-body {
|
|
76
|
-
animation: xiaohei-sidebar-heixiu-exit ${ESCAPE_EXIT_MS}ms cubic-bezier(.18, .76, .24, 1) both;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
@keyframes xiaohei-sidebar-escape-portal-open {
|
|
80
|
-
0% {
|
|
81
|
-
opacity: 0;
|
|
82
|
-
transform: translate3d(-50%, -50%, 0) rotate(var(--xiaohei-sidebar-portal-angle, 0deg)) scale3d(.06, .16, 1);
|
|
83
|
-
}
|
|
84
|
-
20%, 72% {
|
|
85
|
-
opacity: .94;
|
|
86
|
-
transform: translate3d(-50%, -50%, 0) rotate(var(--xiaohei-sidebar-portal-angle, 0deg)) scale3d(1, 1, 1);
|
|
87
|
-
}
|
|
88
|
-
100% {
|
|
89
|
-
opacity: 0;
|
|
90
|
-
transform: translate3d(-50%, -50%, 0) rotate(var(--xiaohei-sidebar-portal-angle, 0deg)) scale3d(.06, .16, 1);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
@keyframes xiaohei-sidebar-heixiu-enter {
|
|
95
|
-
0%, 15% { transform: translate3d(0, 0, 0) scale(1); opacity: 1; }
|
|
96
|
-
70% { opacity: .82; }
|
|
97
|
-
100% {
|
|
98
|
-
transform: translate3d(var(--xiaohei-sidebar-escape-in-x), var(--xiaohei-sidebar-escape-in-y), 0) scale(.08);
|
|
99
|
-
opacity: 0;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
@keyframes xiaohei-sidebar-heixiu-exit {
|
|
104
|
-
0%, 16% {
|
|
105
|
-
transform: translate3d(var(--xiaohei-sidebar-escape-out-x), var(--xiaohei-sidebar-escape-out-y), 0) scale(.08);
|
|
106
|
-
opacity: 0;
|
|
107
|
-
}
|
|
108
|
-
38% { opacity: .72; }
|
|
109
|
-
100% { transform: translate3d(0, 0, 0) scale(1); opacity: 1; }
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
html[data-xiaohei-appearance='light'] .xiaohei-sidebar-escape-portal {
|
|
113
|
-
background:
|
|
114
|
-
radial-gradient(ellipse at 46% 50%, #010304 0%, #030708 58%, #123231 70%, rgb(46 142 121 / 34%) 77%, transparent 83%);
|
|
115
|
-
box-shadow:
|
|
116
|
-
inset 0 0 0.55rem rgb(0 0 0 / 94%),
|
|
117
|
-
0 0 0.58rem rgb(44 139 118 / 18%);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
@media (prefers-reduced-motion: reduce), (hover: none) and (pointer: coarse), (forced-colors: active) {
|
|
121
|
-
.xiaohei-sidebar-escape-layer { display: none; }
|
|
122
|
-
|
|
123
|
-
.xiaohei-scene__heixiu--sidebar[data-xiaohei-sidebar-escape-phase]
|
|
124
|
-
.xiaohei-scene__heixiu-body {
|
|
125
|
-
animation: none;
|
|
126
|
-
will-change: auto;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
`;
|
|
130
|
-
/** True when the pointer is close enough for the sidebar companion to flee. */
|
|
131
|
-
export function isXiaoheiSidebarPointerNear(pointer, creatureCenter) {
|
|
132
|
-
return Math.hypot(pointer.x - creatureCenter.x, pointer.y - creatureCenter.y) <= POINTER_ALERT_RADIUS_PX;
|
|
133
|
-
}
|
|
134
|
-
/** Choose a low-obstruction endpoint that is meaningfully away from the pointer. */
|
|
135
|
-
export function chooseXiaoheiSidebarEscapeDestination(space, pointer, current, random = Math.random) {
|
|
136
|
-
const minX = ESCAPE_EDGE_PADDING_PX;
|
|
137
|
-
const maxX = Math.max(minX, space.width - space.creatureWidth - ESCAPE_EDGE_PADDING_PX);
|
|
138
|
-
const minY = Math.min(64, Math.max(ESCAPE_EDGE_PADDING_PX, space.height - space.creatureHeight));
|
|
139
|
-
const maxY = Math.max(minY, space.height - space.creatureHeight - 62);
|
|
140
|
-
const candidates = [
|
|
141
|
-
{ x: minX, y: minY },
|
|
142
|
-
{ x: maxX, y: minY },
|
|
143
|
-
{ x: minX, y: maxY },
|
|
144
|
-
{ x: maxX, y: maxY },
|
|
145
|
-
];
|
|
146
|
-
for (let index = 0; index < ESCAPE_DESTINATION_CANDIDATES; index += 1) {
|
|
147
|
-
candidates.push({
|
|
148
|
-
x: minX + random() * (maxX - minX),
|
|
149
|
-
y: minY + random() * (maxY - minY),
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
const centerOffset = { x: space.creatureWidth / 2, y: space.creatureHeight / 2 };
|
|
153
|
-
const score = (candidate) => {
|
|
154
|
-
const pointerDistance = Math.hypot(candidate.x + centerOffset.x - pointer.x, candidate.y + centerOffset.y - pointer.y);
|
|
155
|
-
const travel = Math.hypot(candidate.x - current.x, candidate.y - current.y);
|
|
156
|
-
const obstruction = escapeDestinationObstruction(candidate, space);
|
|
157
|
-
const pointerPenalty = pointerDistance < ESCAPE_MIN_POINTER_DISTANCE_PX
|
|
158
|
-
? (ESCAPE_MIN_POINTER_DISTANCE_PX - pointerDistance) * 7
|
|
159
|
-
: 0;
|
|
160
|
-
const travelPenalty = travel < ESCAPE_MIN_TRAVEL_PX
|
|
161
|
-
? (ESCAPE_MIN_TRAVEL_PX - travel) * 4
|
|
162
|
-
: 0;
|
|
163
|
-
return pointerDistance * 2.7 + travel * .25 - obstruction * .12 - pointerPenalty - travelPenalty;
|
|
164
|
-
};
|
|
165
|
-
return candidates.reduce((best, candidate) => score(candidate) > score(best) ? candidate : best);
|
|
166
|
-
}
|
|
167
|
-
/** Own pointer proximity and the enter/exit portal sequence; roaming owns position. */
|
|
168
|
-
export function createXiaoheiSidebarEscapeController(options) {
|
|
169
|
-
const { doc } = options;
|
|
170
|
-
const win = doc.defaultView;
|
|
171
|
-
if (win === null)
|
|
172
|
-
return { cancel: () => { }, dispose: () => { }, isRunning: () => false };
|
|
173
|
-
let disposed = false;
|
|
174
|
-
let running = false;
|
|
175
|
-
let frameId = 0;
|
|
176
|
-
let phaseTimer = 0;
|
|
177
|
-
let cooldownUntil = 0;
|
|
178
|
-
let pointer;
|
|
179
|
-
let layer;
|
|
180
|
-
let activeCreature;
|
|
181
|
-
let destination;
|
|
182
|
-
const clearPhaseTimer = () => {
|
|
183
|
-
win.clearTimeout(phaseTimer);
|
|
184
|
-
phaseTimer = 0;
|
|
185
|
-
};
|
|
186
|
-
const removeVisuals = () => {
|
|
187
|
-
layer?.remove();
|
|
188
|
-
layer = undefined;
|
|
189
|
-
if (activeCreature !== undefined) {
|
|
190
|
-
activeCreature.removeAttribute('data-xiaohei-sidebar-escape-phase');
|
|
191
|
-
activeCreature.style.removeProperty('--xiaohei-sidebar-escape-in-x');
|
|
192
|
-
activeCreature.style.removeProperty('--xiaohei-sidebar-escape-in-y');
|
|
193
|
-
activeCreature.style.removeProperty('--xiaohei-sidebar-escape-out-x');
|
|
194
|
-
activeCreature.style.removeProperty('--xiaohei-sidebar-escape-out-y');
|
|
195
|
-
}
|
|
196
|
-
activeCreature = undefined;
|
|
197
|
-
};
|
|
198
|
-
const finish = (notify) => {
|
|
199
|
-
clearPhaseTimer();
|
|
200
|
-
const completedDestination = destination;
|
|
201
|
-
destination = undefined;
|
|
202
|
-
running = false;
|
|
203
|
-
removeVisuals();
|
|
204
|
-
if (notify && completedDestination !== undefined)
|
|
205
|
-
options.onComplete(completedDestination);
|
|
206
|
-
};
|
|
207
|
-
const startEscape = (target, point) => {
|
|
208
|
-
const hostRect = target.host.getBoundingClientRect();
|
|
209
|
-
const creatureRect = target.creature.getBoundingClientRect();
|
|
210
|
-
const current = {
|
|
211
|
-
x: creatureRect.left - hostRect.left,
|
|
212
|
-
y: creatureRect.top - hostRect.top,
|
|
213
|
-
};
|
|
214
|
-
const localPointer = { x: point.x - hostRect.left, y: point.y - hostRect.top };
|
|
215
|
-
const nextDestination = chooseXiaoheiSidebarEscapeDestination(target.space, localPointer, current);
|
|
216
|
-
const currentCenter = {
|
|
217
|
-
x: current.x + target.space.creatureWidth / 2,
|
|
218
|
-
y: current.y + target.space.creatureHeight / 2,
|
|
219
|
-
};
|
|
220
|
-
const nextCenter = {
|
|
221
|
-
x: nextDestination.x + target.space.creatureWidth / 2,
|
|
222
|
-
y: nextDestination.y + target.space.creatureHeight / 2,
|
|
223
|
-
};
|
|
224
|
-
const entryDirection = unitVector(currentCenter.x - localPointer.x, currentCenter.y - localPointer.y);
|
|
225
|
-
const exitDirection = unitVector(nextCenter.x - localPointer.x, nextCenter.y - localPointer.y);
|
|
226
|
-
const entryShift = { x: entryDirection.x * 12, y: entryDirection.y * 12 };
|
|
227
|
-
const exitShift = { x: -exitDirection.x * 10, y: -exitDirection.y * 10 };
|
|
228
|
-
running = true;
|
|
229
|
-
cooldownUntil = win.performance.now() + ESCAPE_ENTER_MS + ESCAPE_EXIT_MS + ESCAPE_COOLDOWN_MS;
|
|
230
|
-
destination = nextDestination;
|
|
231
|
-
activeCreature = target.creature;
|
|
232
|
-
options.onFreeze(current);
|
|
233
|
-
layer = createEscapeLayer(doc, {
|
|
234
|
-
entry: {
|
|
235
|
-
x: currentCenter.x + entryShift.x,
|
|
236
|
-
y: currentCenter.y + entryShift.y,
|
|
237
|
-
angle: Math.atan2(entryDirection.y, entryDirection.x) * 180 / Math.PI,
|
|
238
|
-
},
|
|
239
|
-
exit: {
|
|
240
|
-
x: nextCenter.x + exitShift.x,
|
|
241
|
-
y: nextCenter.y + exitShift.y,
|
|
242
|
-
angle: Math.atan2(exitDirection.y, exitDirection.x) * 180 / Math.PI,
|
|
243
|
-
},
|
|
244
|
-
});
|
|
245
|
-
target.host.append(layer);
|
|
246
|
-
target.creature.style.setProperty('--xiaohei-sidebar-escape-in-x', `${entryShift.x.toFixed(2)}px`);
|
|
247
|
-
target.creature.style.setProperty('--xiaohei-sidebar-escape-in-y', `${entryShift.y.toFixed(2)}px`);
|
|
248
|
-
target.creature.style.setProperty('--xiaohei-sidebar-escape-out-x', `${exitShift.x.toFixed(2)}px`);
|
|
249
|
-
target.creature.style.setProperty('--xiaohei-sidebar-escape-out-y', `${exitShift.y.toFixed(2)}px`);
|
|
250
|
-
target.creature.setAttribute('data-xiaohei-sidebar-escape-phase', 'enter');
|
|
251
|
-
layer.setAttribute('data-xiaohei-sidebar-escape-phase', 'enter');
|
|
252
|
-
phaseTimer = win.setTimeout(() => {
|
|
253
|
-
phaseTimer = 0;
|
|
254
|
-
if (disposed || !running || destination === undefined || layer === undefined || activeCreature === undefined)
|
|
255
|
-
return;
|
|
256
|
-
options.onTeleport(destination);
|
|
257
|
-
activeCreature.setAttribute('data-xiaohei-sidebar-escape-phase', 'exit');
|
|
258
|
-
layer.setAttribute('data-xiaohei-sidebar-escape-phase', 'exit');
|
|
259
|
-
phaseTimer = win.setTimeout(() => finish(true), ESCAPE_EXIT_MS);
|
|
260
|
-
}, ESCAPE_ENTER_MS);
|
|
261
|
-
};
|
|
262
|
-
const inspectPointer = () => {
|
|
263
|
-
frameId = 0;
|
|
264
|
-
if (disposed || running || pointer === undefined || options.isDisabled())
|
|
265
|
-
return;
|
|
266
|
-
if (win.performance.now() < cooldownUntil)
|
|
267
|
-
return;
|
|
268
|
-
const target = options.resolveTarget();
|
|
269
|
-
if (target === undefined)
|
|
270
|
-
return;
|
|
271
|
-
const rect = target.creature.getBoundingClientRect();
|
|
272
|
-
if (rect.width <= 0 || rect.height <= 0)
|
|
273
|
-
return;
|
|
274
|
-
const center = { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };
|
|
275
|
-
if (isXiaoheiSidebarPointerNear(pointer, center))
|
|
276
|
-
startEscape(target, pointer);
|
|
277
|
-
};
|
|
278
|
-
const queueInspection = () => {
|
|
279
|
-
if (disposed || frameId !== 0)
|
|
280
|
-
return;
|
|
281
|
-
frameId = win.requestAnimationFrame(inspectPointer);
|
|
282
|
-
};
|
|
283
|
-
const onPointerMove = (event) => {
|
|
284
|
-
pointer = event.pointerType === 'touch' ? undefined : { x: event.clientX, y: event.clientY };
|
|
285
|
-
queueInspection();
|
|
286
|
-
};
|
|
287
|
-
const clearPointer = () => {
|
|
288
|
-
pointer = undefined;
|
|
289
|
-
};
|
|
290
|
-
doc.addEventListener('pointermove', onPointerMove, { passive: true });
|
|
291
|
-
doc.addEventListener('pointerleave', clearPointer);
|
|
292
|
-
win.addEventListener('blur', clearPointer);
|
|
293
|
-
return {
|
|
294
|
-
cancel: () => finish(false),
|
|
295
|
-
dispose: () => {
|
|
296
|
-
disposed = true;
|
|
297
|
-
if (frameId !== 0)
|
|
298
|
-
win.cancelAnimationFrame(frameId);
|
|
299
|
-
doc.removeEventListener('pointermove', onPointerMove);
|
|
300
|
-
doc.removeEventListener('pointerleave', clearPointer);
|
|
301
|
-
win.removeEventListener('blur', clearPointer);
|
|
302
|
-
finish(false);
|
|
303
|
-
},
|
|
304
|
-
isRunning: () => running,
|
|
305
|
-
};
|
|
306
|
-
}
|
|
307
|
-
function createEscapeLayer(doc, portals) {
|
|
308
|
-
const layer = doc.createElement('div');
|
|
309
|
-
layer.className = 'xiaohei-sidebar-escape-layer';
|
|
310
|
-
layer.setAttribute('aria-hidden', 'true');
|
|
311
|
-
layer.append(createPortal(doc, 'entry', portals.entry), createPortal(doc, 'exit', portals.exit));
|
|
312
|
-
return layer;
|
|
313
|
-
}
|
|
314
|
-
function createPortal(doc, kind, point) {
|
|
315
|
-
const portal = doc.createElement('span');
|
|
316
|
-
portal.className = `xiaohei-sidebar-escape-portal xiaohei-sidebar-escape-portal--${kind}`;
|
|
317
|
-
portal.style.setProperty('--xiaohei-sidebar-portal-x', `${point.x.toFixed(1)}px`);
|
|
318
|
-
portal.style.setProperty('--xiaohei-sidebar-portal-y', `${point.y.toFixed(1)}px`);
|
|
319
|
-
portal.style.setProperty('--xiaohei-sidebar-portal-angle', `${point.angle.toFixed(1)}deg`);
|
|
320
|
-
return portal;
|
|
321
|
-
}
|
|
322
|
-
function escapeDestinationObstruction(point, space) {
|
|
323
|
-
const creature = {
|
|
324
|
-
left: point.x,
|
|
325
|
-
top: point.y,
|
|
326
|
-
right: point.x + space.creatureWidth,
|
|
327
|
-
bottom: point.y + space.creatureHeight,
|
|
328
|
-
};
|
|
329
|
-
return space.controls.reduce((total, control) => total + overlapArea(creature, control), 0);
|
|
330
|
-
}
|
|
331
|
-
function overlapArea(left, right) {
|
|
332
|
-
const width = Math.max(0, Math.min(left.right, right.right) - Math.max(left.left, right.left));
|
|
333
|
-
const height = Math.max(0, Math.min(left.bottom, right.bottom) - Math.max(left.top, right.top));
|
|
334
|
-
return width * height;
|
|
335
|
-
}
|
|
336
|
-
function unitVector(x, y) {
|
|
337
|
-
const length = Math.hypot(x, y);
|
|
338
|
-
return length <= .001 ? { x: 1, y: 0 } : { x: x / length, y: y / length };
|
|
339
|
-
}
|
|
340
|
-
//# sourceMappingURL=sidebar-heixiu-escape.js.map
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
export declare const XIAOHEI_SIDEBAR_ROAMING_STYLE_ID = "dsh-theme-xiaohei/sidebar-heixiu-roaming-style";
|
|
2
|
-
interface Point {
|
|
3
|
-
x: number;
|
|
4
|
-
y: number;
|
|
5
|
-
}
|
|
6
|
-
interface Box {
|
|
7
|
-
left: number;
|
|
8
|
-
top: number;
|
|
9
|
-
right: number;
|
|
10
|
-
bottom: number;
|
|
11
|
-
}
|
|
12
|
-
export interface XiaoheiSidebarRoamingSpace {
|
|
13
|
-
width: number;
|
|
14
|
-
height: number;
|
|
15
|
-
creatureWidth: number;
|
|
16
|
-
creatureHeight: number;
|
|
17
|
-
controls: readonly Box[];
|
|
18
|
-
}
|
|
19
|
-
export declare const XIAOHEI_SIDEBAR_ROAMING_CSS = "\n.xiaohei-scene__heixiu--sidebar[data-xiaohei-sidebar-roaming='true'] {\n left: 0;\n right: auto;\n top: 0;\n animation: none;\n transform: translate3d(\n var(--xiaohei-sidebar-heixiu-x, 7.15rem),\n var(--xiaohei-sidebar-heixiu-y, 8.05rem),\n 0\n );\n transition: transform var(--xiaohei-sidebar-heixiu-duration, 0ms) cubic-bezier(0.22, 0.72, 0.24, 1);\n pointer-events: none;\n will-change: transform;\n}\n\n.xiaohei-scene__heixiu--sidebar[data-xiaohei-sidebar-roaming-paused='true'] {\n transition-duration: 0ms;\n will-change: auto;\n}\n\n@media (prefers-reduced-motion: reduce), (hover: none) and (pointer: coarse) {\n .xiaohei-scene__heixiu--sidebar[data-xiaohei-sidebar-roaming='true'] {\n transform: translate3d(7.15rem, 8.05rem, 0);\n transition: none;\n will-change: auto;\n }\n}\n";
|
|
20
|
-
/** Pick a low-obstruction destination while retaining organic variation. */
|
|
21
|
-
export declare function chooseXiaoheiSidebarDestination(space: XiaoheiSidebarRoamingSpace, current: Point | undefined, random?: () => number): Point;
|
|
22
|
-
/** Longer trips get more time so the companion never darts across controls. */
|
|
23
|
-
export declare function resolveXiaoheiSidebarRoamDuration(from: Point, to: Point): number;
|
|
24
|
-
/** Let the sidebar companion wander without owning scene construction. */
|
|
25
|
-
export declare function installXiaoheiSidebarHeixiuRoaming(doc?: Document | undefined): () => void;
|
|
26
|
-
export {};
|
|
27
|
-
//# sourceMappingURL=sidebar-heixiu-roaming.d.ts.map
|
|
@@ -1,310 +0,0 @@
|
|
|
1
|
-
import { createXiaoheiSidebarEscapeController, XIAOHEI_SIDEBAR_ESCAPE_CSS, } from './sidebar-heixiu-escape.js';
|
|
2
|
-
import { subscribeXiaoheiHostDom } from './host-dom.js';
|
|
3
|
-
import { XIAOHEI_HOST_SELECTORS } from './host-contract.js';
|
|
4
|
-
export const XIAOHEI_SIDEBAR_ROAMING_STYLE_ID = 'dsh-theme-xiaohei/sidebar-heixiu-roaming-style';
|
|
5
|
-
const SIDEBAR_HEIXIU_SELECTOR = '.xiaohei-scene__heixiu--sidebar';
|
|
6
|
-
const INTERACTIVE_SELECTOR = [
|
|
7
|
-
'button',
|
|
8
|
-
'a[href]',
|
|
9
|
-
"[role='treeitem']",
|
|
10
|
-
"[role='menuitem']",
|
|
11
|
-
"[tabindex]:not([tabindex='-1'])",
|
|
12
|
-
].join(',');
|
|
13
|
-
const EDGE_PADDING_PX = 10;
|
|
14
|
-
const TOP_RESERVE_PX = 64;
|
|
15
|
-
const BOTTOM_RESERVE_PX = 62;
|
|
16
|
-
const CONTROL_PADDING_PX = 7;
|
|
17
|
-
const DESTINATION_CANDIDATES = 28;
|
|
18
|
-
const MIN_TRAVEL_PX = 42;
|
|
19
|
-
const INITIAL_PAUSE_MS = 1800;
|
|
20
|
-
const MIN_PAUSE_MS = 2600;
|
|
21
|
-
const PAUSE_RANGE_MS = 3800;
|
|
22
|
-
export const XIAOHEI_SIDEBAR_ROAMING_CSS = `
|
|
23
|
-
.xiaohei-scene__heixiu--sidebar[data-xiaohei-sidebar-roaming='true'] {
|
|
24
|
-
left: 0;
|
|
25
|
-
right: auto;
|
|
26
|
-
top: 0;
|
|
27
|
-
animation: none;
|
|
28
|
-
transform: translate3d(
|
|
29
|
-
var(--xiaohei-sidebar-heixiu-x, 7.15rem),
|
|
30
|
-
var(--xiaohei-sidebar-heixiu-y, 8.05rem),
|
|
31
|
-
0
|
|
32
|
-
);
|
|
33
|
-
transition: transform var(--xiaohei-sidebar-heixiu-duration, 0ms) cubic-bezier(0.22, 0.72, 0.24, 1);
|
|
34
|
-
pointer-events: none;
|
|
35
|
-
will-change: transform;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
.xiaohei-scene__heixiu--sidebar[data-xiaohei-sidebar-roaming-paused='true'] {
|
|
39
|
-
transition-duration: 0ms;
|
|
40
|
-
will-change: auto;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
@media (prefers-reduced-motion: reduce), (hover: none) and (pointer: coarse) {
|
|
44
|
-
.xiaohei-scene__heixiu--sidebar[data-xiaohei-sidebar-roaming='true'] {
|
|
45
|
-
transform: translate3d(7.15rem, 8.05rem, 0);
|
|
46
|
-
transition: none;
|
|
47
|
-
will-change: auto;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
`;
|
|
51
|
-
/** Pick a low-obstruction destination while retaining organic variation. */
|
|
52
|
-
export function chooseXiaoheiSidebarDestination(space, current, random = Math.random) {
|
|
53
|
-
const minX = EDGE_PADDING_PX;
|
|
54
|
-
const maxX = Math.max(minX, space.width - space.creatureWidth - EDGE_PADDING_PX);
|
|
55
|
-
const minY = Math.min(TOP_RESERVE_PX, Math.max(EDGE_PADDING_PX, space.height - space.creatureHeight));
|
|
56
|
-
const maxY = Math.max(minY, space.height - space.creatureHeight - BOTTOM_RESERVE_PX);
|
|
57
|
-
const candidates = [];
|
|
58
|
-
for (let index = 0; index < DESTINATION_CANDIDATES; index += 1) {
|
|
59
|
-
const point = {
|
|
60
|
-
x: minX + random() * (maxX - minX),
|
|
61
|
-
y: minY + random() * (maxY - minY),
|
|
62
|
-
};
|
|
63
|
-
const travel = current === undefined ? Number.POSITIVE_INFINITY : Math.hypot(point.x - current.x, point.y - current.y);
|
|
64
|
-
if (travel < MIN_TRAVEL_PX && index < DESTINATION_CANDIDATES - 1)
|
|
65
|
-
continue;
|
|
66
|
-
candidates.push({ point, obstruction: destinationObstruction(point, space) });
|
|
67
|
-
}
|
|
68
|
-
candidates.sort((left, right) => left.obstruction - right.obstruction);
|
|
69
|
-
const bestScore = candidates[0]?.obstruction;
|
|
70
|
-
const best = candidates.filter(candidate => candidate.obstruction === bestScore);
|
|
71
|
-
return best[Math.min(best.length - 1, Math.floor(random() * best.length))]?.point ?? { x: minX, y: minY };
|
|
72
|
-
}
|
|
73
|
-
/** Longer trips get more time so the companion never darts across controls. */
|
|
74
|
-
export function resolveXiaoheiSidebarRoamDuration(from, to) {
|
|
75
|
-
const distance = Math.hypot(to.x - from.x, to.y - from.y);
|
|
76
|
-
return Math.round(Math.min(5200, Math.max(2400, 2100 + distance * 8.5)));
|
|
77
|
-
}
|
|
78
|
-
/** Let the sidebar companion wander without owning scene construction. */
|
|
79
|
-
export function installXiaoheiSidebarHeixiuRoaming(doc = typeof document === 'undefined' ? undefined : document) {
|
|
80
|
-
if (doc?.head === undefined || doc.body === undefined || doc.defaultView === null)
|
|
81
|
-
return () => { };
|
|
82
|
-
const win = doc.defaultView;
|
|
83
|
-
const reducedMotion = win.matchMedia('(prefers-reduced-motion: reduce)');
|
|
84
|
-
const coarsePointer = win.matchMedia('(hover: none) and (pointer: coarse)');
|
|
85
|
-
let disposed = false;
|
|
86
|
-
let creature;
|
|
87
|
-
let host;
|
|
88
|
-
let current;
|
|
89
|
-
let roamTimer = 0;
|
|
90
|
-
let attachQueued = false;
|
|
91
|
-
let observedHost;
|
|
92
|
-
doc.getElementById(XIAOHEI_SIDEBAR_ROAMING_STYLE_ID)?.remove();
|
|
93
|
-
const style = doc.createElement('style');
|
|
94
|
-
style.id = XIAOHEI_SIDEBAR_ROAMING_STYLE_ID;
|
|
95
|
-
style.textContent = `${XIAOHEI_SIDEBAR_ROAMING_CSS}\n${XIAOHEI_SIDEBAR_ESCAPE_CSS}`;
|
|
96
|
-
doc.head.append(style);
|
|
97
|
-
const behaviorDisabled = () => (reducedMotion.matches
|
|
98
|
-
|| coarsePointer.matches
|
|
99
|
-
|| doc.visibilityState === 'hidden'
|
|
100
|
-
|| host === undefined
|
|
101
|
-
|| host.className.includes('_collapsed')
|
|
102
|
-
|| host.getBoundingClientRect().width < 80);
|
|
103
|
-
const clearTimer = () => {
|
|
104
|
-
win.clearTimeout(roamTimer);
|
|
105
|
-
roamTimer = 0;
|
|
106
|
-
};
|
|
107
|
-
const pause = () => {
|
|
108
|
-
clearTimer();
|
|
109
|
-
creature?.setAttribute('data-xiaohei-sidebar-roaming-paused', 'true');
|
|
110
|
-
};
|
|
111
|
-
const measureSpace = () => {
|
|
112
|
-
if (host === undefined || creature === undefined)
|
|
113
|
-
return undefined;
|
|
114
|
-
const hostRect = host.getBoundingClientRect();
|
|
115
|
-
const creatureRect = creature.getBoundingClientRect();
|
|
116
|
-
if (hostRect.width <= 0 || hostRect.height <= 0)
|
|
117
|
-
return undefined;
|
|
118
|
-
const controls = Array.from(host.querySelectorAll(INTERACTIVE_SELECTOR))
|
|
119
|
-
.filter(element => !creature?.contains(element))
|
|
120
|
-
.map(element => element.getBoundingClientRect())
|
|
121
|
-
.filter(rect => rect.width > 0 && rect.height > 0)
|
|
122
|
-
.map(rect => ({
|
|
123
|
-
left: rect.left - hostRect.left - CONTROL_PADDING_PX,
|
|
124
|
-
top: rect.top - hostRect.top - CONTROL_PADDING_PX,
|
|
125
|
-
right: rect.right - hostRect.left + CONTROL_PADDING_PX,
|
|
126
|
-
bottom: rect.bottom - hostRect.top + CONTROL_PADDING_PX,
|
|
127
|
-
}));
|
|
128
|
-
return {
|
|
129
|
-
width: hostRect.width,
|
|
130
|
-
height: hostRect.height,
|
|
131
|
-
creatureWidth: creatureRect.width || 40,
|
|
132
|
-
creatureHeight: creatureRect.height || 40,
|
|
133
|
-
controls,
|
|
134
|
-
};
|
|
135
|
-
};
|
|
136
|
-
const freezeAt = (position) => {
|
|
137
|
-
clearTimer();
|
|
138
|
-
current = position;
|
|
139
|
-
creature?.setAttribute('data-xiaohei-sidebar-roaming-paused', 'true');
|
|
140
|
-
creature?.style.setProperty('--xiaohei-sidebar-heixiu-duration', '0ms');
|
|
141
|
-
creature?.style.setProperty('--xiaohei-sidebar-heixiu-x', `${position.x.toFixed(1)}px`);
|
|
142
|
-
creature?.style.setProperty('--xiaohei-sidebar-heixiu-y', `${position.y.toFixed(1)}px`);
|
|
143
|
-
};
|
|
144
|
-
const teleportTo = (destination) => {
|
|
145
|
-
current = destination;
|
|
146
|
-
creature?.style.setProperty('--xiaohei-sidebar-heixiu-duration', '0ms');
|
|
147
|
-
creature?.style.setProperty('--xiaohei-sidebar-heixiu-x', `${destination.x.toFixed(1)}px`);
|
|
148
|
-
creature?.style.setProperty('--xiaohei-sidebar-heixiu-y', `${destination.y.toFixed(1)}px`);
|
|
149
|
-
};
|
|
150
|
-
const escapeController = createXiaoheiSidebarEscapeController({
|
|
151
|
-
doc,
|
|
152
|
-
isDisabled: behaviorDisabled,
|
|
153
|
-
resolveTarget: () => {
|
|
154
|
-
const space = measureSpace();
|
|
155
|
-
return creature === undefined || host === undefined || space === undefined
|
|
156
|
-
? undefined
|
|
157
|
-
: { creature, host, space };
|
|
158
|
-
},
|
|
159
|
-
onFreeze: freezeAt,
|
|
160
|
-
onTeleport: teleportTo,
|
|
161
|
-
onComplete: () => {
|
|
162
|
-
if (behaviorDisabled())
|
|
163
|
-
pause();
|
|
164
|
-
else {
|
|
165
|
-
creature?.removeAttribute('data-xiaohei-sidebar-roaming-paused');
|
|
166
|
-
scheduleRoam(1400);
|
|
167
|
-
}
|
|
168
|
-
},
|
|
169
|
-
});
|
|
170
|
-
const scheduleRoam = (delay = MIN_PAUSE_MS + Math.round(Math.random() * PAUSE_RANGE_MS)) => {
|
|
171
|
-
clearTimer();
|
|
172
|
-
if (disposed || behaviorDisabled()) {
|
|
173
|
-
pause();
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
creature?.removeAttribute('data-xiaohei-sidebar-roaming-paused');
|
|
177
|
-
roamTimer = win.setTimeout(roam, delay);
|
|
178
|
-
};
|
|
179
|
-
const roam = () => {
|
|
180
|
-
roamTimer = 0;
|
|
181
|
-
if (disposed || behaviorDisabled() || creature === undefined) {
|
|
182
|
-
pause();
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
const space = measureSpace();
|
|
186
|
-
if (space === undefined) {
|
|
187
|
-
scheduleRoam();
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
const destination = chooseXiaoheiSidebarDestination(space, current);
|
|
191
|
-
const start = current ?? destination;
|
|
192
|
-
const duration = current === undefined ? 0 : resolveXiaoheiSidebarRoamDuration(start, destination);
|
|
193
|
-
creature.style.setProperty('--xiaohei-sidebar-heixiu-duration', `${duration}ms`);
|
|
194
|
-
creature.style.setProperty('--xiaohei-sidebar-heixiu-x', `${destination.x.toFixed(1)}px`);
|
|
195
|
-
creature.style.setProperty('--xiaohei-sidebar-heixiu-y', `${destination.y.toFixed(1)}px`);
|
|
196
|
-
current = destination;
|
|
197
|
-
scheduleRoam(duration + MIN_PAUSE_MS + Math.round(Math.random() * PAUSE_RANGE_MS));
|
|
198
|
-
};
|
|
199
|
-
const bind = () => {
|
|
200
|
-
attachQueued = false;
|
|
201
|
-
if (disposed)
|
|
202
|
-
return;
|
|
203
|
-
const nextCreature = doc.querySelector(SIDEBAR_HEIXIU_SELECTOR) ?? undefined;
|
|
204
|
-
const nextHost = doc.querySelector(XIAOHEI_HOST_SELECTORS.sidebar)?.firstElementChild;
|
|
205
|
-
const nextHostElement = nextHost instanceof win.HTMLElement ? nextHost : undefined;
|
|
206
|
-
if (nextCreature === creature && nextHostElement === host)
|
|
207
|
-
return;
|
|
208
|
-
escapeController.cancel();
|
|
209
|
-
if (creature !== undefined) {
|
|
210
|
-
creature.removeAttribute('data-xiaohei-sidebar-roaming');
|
|
211
|
-
creature.removeAttribute('data-xiaohei-sidebar-roaming-paused');
|
|
212
|
-
creature.style.removeProperty('--xiaohei-sidebar-heixiu-duration');
|
|
213
|
-
creature.style.removeProperty('--xiaohei-sidebar-heixiu-x');
|
|
214
|
-
creature.style.removeProperty('--xiaohei-sidebar-heixiu-y');
|
|
215
|
-
}
|
|
216
|
-
clearTimer();
|
|
217
|
-
creature = nextCreature;
|
|
218
|
-
host = nextHostElement;
|
|
219
|
-
current = undefined;
|
|
220
|
-
observeHostState();
|
|
221
|
-
if (creature === undefined || host === undefined)
|
|
222
|
-
return;
|
|
223
|
-
const hostRect = host.getBoundingClientRect();
|
|
224
|
-
const creatureRect = creature.getBoundingClientRect();
|
|
225
|
-
current = {
|
|
226
|
-
x: creatureRect.left - hostRect.left,
|
|
227
|
-
y: creatureRect.top - hostRect.top,
|
|
228
|
-
};
|
|
229
|
-
creature.style.setProperty('--xiaohei-sidebar-heixiu-duration', '0ms');
|
|
230
|
-
creature.style.setProperty('--xiaohei-sidebar-heixiu-x', `${current.x.toFixed(1)}px`);
|
|
231
|
-
creature.style.setProperty('--xiaohei-sidebar-heixiu-y', `${current.y.toFixed(1)}px`);
|
|
232
|
-
creature.setAttribute('data-xiaohei-sidebar-roaming', 'true');
|
|
233
|
-
scheduleRoam(INITIAL_PAUSE_MS);
|
|
234
|
-
};
|
|
235
|
-
const queueBind = () => {
|
|
236
|
-
if (attachQueued || disposed)
|
|
237
|
-
return;
|
|
238
|
-
attachQueued = true;
|
|
239
|
-
queueMicrotask(bind);
|
|
240
|
-
};
|
|
241
|
-
const resumeOrPause = () => {
|
|
242
|
-
if (escapeController.isRunning()) {
|
|
243
|
-
if (behaviorDisabled()) {
|
|
244
|
-
escapeController.cancel();
|
|
245
|
-
pause();
|
|
246
|
-
}
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
if (behaviorDisabled())
|
|
250
|
-
pause();
|
|
251
|
-
else
|
|
252
|
-
scheduleRoam(600);
|
|
253
|
-
};
|
|
254
|
-
const hostStateObserver = new win.MutationObserver(resumeOrPause);
|
|
255
|
-
const hostResizeObserver = typeof win.ResizeObserver === 'function'
|
|
256
|
-
? new win.ResizeObserver(resumeOrPause)
|
|
257
|
-
: undefined;
|
|
258
|
-
const observeHostState = () => {
|
|
259
|
-
if (host === observedHost)
|
|
260
|
-
return;
|
|
261
|
-
hostStateObserver.disconnect();
|
|
262
|
-
hostResizeObserver?.disconnect();
|
|
263
|
-
observedHost = host;
|
|
264
|
-
if (host === undefined)
|
|
265
|
-
return;
|
|
266
|
-
hostStateObserver.observe(host, { attributes: true, attributeFilter: ['class'] });
|
|
267
|
-
hostResizeObserver?.observe(host);
|
|
268
|
-
};
|
|
269
|
-
bind();
|
|
270
|
-
const unsubscribeHostDom = subscribeXiaoheiHostDom(doc, queueBind);
|
|
271
|
-
doc.addEventListener('visibilitychange', resumeOrPause);
|
|
272
|
-
win.addEventListener('resize', resumeOrPause, { passive: true });
|
|
273
|
-
reducedMotion.addEventListener('change', resumeOrPause);
|
|
274
|
-
coarsePointer.addEventListener('change', resumeOrPause);
|
|
275
|
-
return () => {
|
|
276
|
-
disposed = true;
|
|
277
|
-
escapeController.dispose();
|
|
278
|
-
clearTimer();
|
|
279
|
-
unsubscribeHostDom();
|
|
280
|
-
hostStateObserver.disconnect();
|
|
281
|
-
hostResizeObserver?.disconnect();
|
|
282
|
-
doc.removeEventListener('visibilitychange', resumeOrPause);
|
|
283
|
-
win.removeEventListener('resize', resumeOrPause);
|
|
284
|
-
reducedMotion.removeEventListener('change', resumeOrPause);
|
|
285
|
-
coarsePointer.removeEventListener('change', resumeOrPause);
|
|
286
|
-
if (creature !== undefined) {
|
|
287
|
-
creature.removeAttribute('data-xiaohei-sidebar-roaming');
|
|
288
|
-
creature.removeAttribute('data-xiaohei-sidebar-roaming-paused');
|
|
289
|
-
creature.style.removeProperty('--xiaohei-sidebar-heixiu-duration');
|
|
290
|
-
creature.style.removeProperty('--xiaohei-sidebar-heixiu-x');
|
|
291
|
-
creature.style.removeProperty('--xiaohei-sidebar-heixiu-y');
|
|
292
|
-
}
|
|
293
|
-
style.remove();
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
function destinationObstruction(point, space) {
|
|
297
|
-
const creature = {
|
|
298
|
-
left: point.x,
|
|
299
|
-
top: point.y,
|
|
300
|
-
right: point.x + space.creatureWidth,
|
|
301
|
-
bottom: point.y + space.creatureHeight,
|
|
302
|
-
};
|
|
303
|
-
return space.controls.reduce((total, control) => total + overlapArea(creature, control), 0);
|
|
304
|
-
}
|
|
305
|
-
function overlapArea(left, right) {
|
|
306
|
-
const width = Math.max(0, Math.min(left.right, right.right) - Math.max(left.left, right.left));
|
|
307
|
-
const height = Math.max(0, Math.min(left.bottom, right.bottom) - Math.max(left.top, right.top));
|
|
308
|
-
return width * height;
|
|
309
|
-
}
|
|
310
|
-
//# sourceMappingURL=sidebar-heixiu-roaming.js.map
|
package/lib/sidebar-reveal.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/** Synchronize native wide content with the visible column, without changing
|
|
2
|
-
* Host layout/state or adding a competing animation timer. */
|
|
3
|
-
export declare function createSidebarReveal(doc: Document): {
|
|
4
|
-
setColumn(column: HTMLElement | undefined): void;
|
|
5
|
-
resize(nextWidth: number): void;
|
|
6
|
-
dispose(): void;
|
|
7
|
-
};
|
|
8
|
-
//# sourceMappingURL=sidebar-reveal.d.ts.map
|