@modernman00/shared-js-lib 1.2.89 → 1.6.2
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/AddressAutocomplete.js +164 -15
- package/AiBillSplitter.js +230 -0
- package/AiEntertainmentPrompt.js +130 -0
- package/AiFlyerStudio.js +215 -0
- package/AiMediaGuard.js +95 -0
- package/AiPrivacyGuard.js +63 -0
- package/AiSemanticSearch.js +107 -0
- package/AiVoiceRecorder.js +196 -0
- package/CanvasPhysicsEngine.js +568 -0
- package/FileUpload.js +182 -1
- package/HyperReality3DEngine.js +404 -0
- package/Loader.js +6 -2
- package/PwaInstall.js +20 -2
- package/README.md +78 -0
- package/SovereignBroadcasterClient.js +325 -0
- package/VisualSupremacyRuntime.js +312 -0
- package/WebAuthnClient.js +470 -0
- package/WebPushClient.js +308 -0
- package/axiosWrapper.js +1 -0
- package/config/version.php +1 -1
- package/index.js +13 -1
- package/package.json +14 -1
- package/release-history.md +6 -0
- package/templates/sw.template.js +105 -57
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vse-canvas.js
|
|
3
|
+
*
|
|
4
|
+
* Next-Gen Visual Supremacy Engine (VSE) Client Runtime
|
|
5
|
+
*
|
|
6
|
+
* Features:
|
|
7
|
+
* - Dynamic P3 wide colour gamut and HDR capability detection
|
|
8
|
+
* - 2.5D tactile gyroscopic micro-parallax with spring damping
|
|
9
|
+
* - Dr. Viktor Kovács & Marcus security killswitch (suspends sensors on input focus)
|
|
10
|
+
* - Accessibility & reduced-motion invariant compliance
|
|
11
|
+
* - 120Hz ProMotion frame pacing via requestAnimationFrame
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
'use strict';
|
|
15
|
+
|
|
16
|
+
class VisualSupremacyRuntime {
|
|
17
|
+
constructor() {
|
|
18
|
+
this.isP3 = false;
|
|
19
|
+
this.isHDR = false;
|
|
20
|
+
this.reducedMotion = false;
|
|
21
|
+
this.isLowPowerMode = false;
|
|
22
|
+
this.isSensorActive = false;
|
|
23
|
+
this.isInputFocused = false;
|
|
24
|
+
this.orientation = { gamma: 0, beta: 0 };
|
|
25
|
+
this.targetOrientation = { gamma: 0, beta: 0 };
|
|
26
|
+
this.rafId = null;
|
|
27
|
+
this.activeCards = new Set();
|
|
28
|
+
this.intersectionObserver = null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
init() {
|
|
32
|
+
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 1. Telemetry: Wide Colour Gamut & Dynamic Range Detection
|
|
37
|
+
try {
|
|
38
|
+
this.isP3 = window.matchMedia && window.matchMedia('(color-gamut: p3)').matches;
|
|
39
|
+
this.isHDR = window.matchMedia && window.matchMedia('(dynamic-range: high)').matches;
|
|
40
|
+
this.reducedMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
41
|
+
|
|
42
|
+
const root = document.documentElement;
|
|
43
|
+
if (this.isP3) {
|
|
44
|
+
root.classList.add('vse-p3-capable');
|
|
45
|
+
}
|
|
46
|
+
if (this.isHDR) {
|
|
47
|
+
root.classList.add('vse-hdr-capable');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Watch for live reduced motion preference changes
|
|
51
|
+
if (window.matchMedia) {
|
|
52
|
+
window.matchMedia('(prefers-reduced-motion: reduce)').addEventListener('change', (e) => {
|
|
53
|
+
this.reducedMotion = e.matches;
|
|
54
|
+
if (this.reducedMotion) {
|
|
55
|
+
this.resetTransforms();
|
|
56
|
+
this.stopSensors();
|
|
57
|
+
} else if (!this.isLowPowerMode) {
|
|
58
|
+
this.startSensors();
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
} catch (_) {}
|
|
63
|
+
|
|
64
|
+
if (this.reducedMotion) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 2. Segun & Victor PWA Battery-Saver & Low-Memory Killswitch
|
|
69
|
+
this.setupBatteryAndMemoryGuard();
|
|
70
|
+
|
|
71
|
+
// 3. Observe media cards using IntersectionObserver to only animate visible elements
|
|
72
|
+
this.setupCardObserver();
|
|
73
|
+
|
|
74
|
+
// 4. Mandatory Adversarial Security Gate (Dr. Viktor Kovács & Marcus): Input Focus Guard
|
|
75
|
+
this.setupSecurityGuard();
|
|
76
|
+
|
|
77
|
+
// 5. Desktop Pointer Parallax Fallback
|
|
78
|
+
this.setupDesktopPointerParallax();
|
|
79
|
+
|
|
80
|
+
// 6. Initialize Sensor Pipeline
|
|
81
|
+
this.startSensors();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
setupBatteryAndMemoryGuard() {
|
|
85
|
+
try {
|
|
86
|
+
// Low-end Android / memory-constrained device guard (< 2GB RAM)
|
|
87
|
+
if (typeof navigator !== 'undefined' && navigator.deviceMemory && navigator.deviceMemory < 2) {
|
|
88
|
+
this.isLowPowerMode = true;
|
|
89
|
+
this.stopSensors();
|
|
90
|
+
this.resetTransforms();
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Battery Status API guard: Disable 2.5D sensors if battery <= 20% and not charging
|
|
95
|
+
if (typeof navigator !== 'undefined' && typeof navigator.getBattery === 'function') {
|
|
96
|
+
navigator.getBattery().then((battery) => {
|
|
97
|
+
const checkBattery = () => {
|
|
98
|
+
const low = !battery.charging && battery.level <= 0.20;
|
|
99
|
+
this.isLowPowerMode = low;
|
|
100
|
+
if (low) {
|
|
101
|
+
this.stopSensors();
|
|
102
|
+
this.resetTransforms();
|
|
103
|
+
} else if (!this.reducedMotion && !this.isInputFocused && !document.hidden) {
|
|
104
|
+
this.startSensors();
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
checkBattery();
|
|
108
|
+
battery.addEventListener('levelchange', checkBattery);
|
|
109
|
+
battery.addEventListener('chargingchange', checkBattery);
|
|
110
|
+
}).catch(() => {});
|
|
111
|
+
}
|
|
112
|
+
} catch (_) {}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
setupCardObserver() {
|
|
116
|
+
if (!('IntersectionObserver' in window)) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
this.intersectionObserver = new IntersectionObserver((entries) => {
|
|
121
|
+
entries.forEach((entry) => {
|
|
122
|
+
if (entry.isIntersecting) {
|
|
123
|
+
this.activeCards.add(entry.target);
|
|
124
|
+
} else {
|
|
125
|
+
this.activeCards.delete(entry.target);
|
|
126
|
+
// Reset transform when scrolling out of viewport to save GPU compositing
|
|
127
|
+
this.resetCardTransform(entry.target);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}, { threshold: 0.1 });
|
|
131
|
+
|
|
132
|
+
// Auto-observe post-media-stage containers
|
|
133
|
+
this.refreshObservedCards();
|
|
134
|
+
|
|
135
|
+
// Re-check for dynamically inserted posts (e.g. infinite scroll, new post submission)
|
|
136
|
+
const observer = new MutationObserver(() => this.refreshObservedCards());
|
|
137
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
refreshObservedCards() {
|
|
141
|
+
if (!this.intersectionObserver) return;
|
|
142
|
+
const stages = document.querySelectorAll('.post-media-stage:not([data-vse-observed])');
|
|
143
|
+
stages.forEach((el) => {
|
|
144
|
+
el.setAttribute('data-vse-observed', 'true');
|
|
145
|
+
this.intersectionObserver.observe(el);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
setupSecurityGuard() {
|
|
150
|
+
// Gyroscopic Timing Side-Channel Defense: Immediately detach listeners on active input
|
|
151
|
+
const pauseEvents = ['focusin', 'focus'];
|
|
152
|
+
const resumeEvents = ['focusout', 'blur'];
|
|
153
|
+
|
|
154
|
+
pauseEvents.forEach((ev) => {
|
|
155
|
+
document.addEventListener(ev, (e) => {
|
|
156
|
+
const tag = e.target && e.target.tagName ? e.target.tagName.toLowerCase() : '';
|
|
157
|
+
const isEditable = e.target && (e.target.isContentEditable || tag === 'input' || tag === 'textarea' || tag === 'select');
|
|
158
|
+
if (isEditable) {
|
|
159
|
+
this.isInputFocused = true;
|
|
160
|
+
this.stopSensors();
|
|
161
|
+
this.resetTransforms();
|
|
162
|
+
}
|
|
163
|
+
}, true);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
resumeEvents.forEach((ev) => {
|
|
167
|
+
document.addEventListener(ev, () => {
|
|
168
|
+
this.isInputFocused = false;
|
|
169
|
+
if (!document.hidden && !this.reducedMotion) {
|
|
170
|
+
this.startSensors();
|
|
171
|
+
}
|
|
172
|
+
}, true);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// Tab Visibility Guard
|
|
176
|
+
document.addEventListener('visibilitychange', () => {
|
|
177
|
+
if (document.hidden) {
|
|
178
|
+
this.stopSensors();
|
|
179
|
+
this.resetTransforms();
|
|
180
|
+
} else if (!this.isInputFocused && !this.reducedMotion) {
|
|
181
|
+
this.startSensors();
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
startSensors() {
|
|
187
|
+
if (this.isSensorActive || this.reducedMotion || this.isInputFocused || this.isLowPowerMode) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (typeof window.DeviceOrientationEvent !== 'undefined') {
|
|
192
|
+
this.orientationHandler = (e) => this.handleDeviceOrientation(e);
|
|
193
|
+
window.addEventListener('deviceorientation', this.orientationHandler, { passive: true });
|
|
194
|
+
this.isSensorActive = true;
|
|
195
|
+
this.scheduleRenderLoop();
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
stopSensors() {
|
|
200
|
+
if (!this.isSensorActive) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (this.orientationHandler) {
|
|
205
|
+
window.removeEventListener('deviceorientation', this.orientationHandler);
|
|
206
|
+
this.orientationHandler = null;
|
|
207
|
+
}
|
|
208
|
+
if (this.rafId) {
|
|
209
|
+
cancelAnimationFrame(this.rafId);
|
|
210
|
+
this.rafId = null;
|
|
211
|
+
}
|
|
212
|
+
this.isSensorActive = false;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
handleDeviceOrientation(event) {
|
|
216
|
+
if (this.isInputFocused || this.reducedMotion || this.isLowPowerMode) return;
|
|
217
|
+
|
|
218
|
+
// Gamma: Left to Right (-90 to 90), Beta: Front to Back (-180 to 180)
|
|
219
|
+
let g = event.gamma || 0;
|
|
220
|
+
let b = event.beta || 0;
|
|
221
|
+
|
|
222
|
+
// Normalise resting hand angle: smartphones are typically held tilted forward by ~45 degrees
|
|
223
|
+
b = b - 45;
|
|
224
|
+
|
|
225
|
+
// Clamp to safe, subtle displacement (±15 degrees input, mapping to ±3.5 degrees visual rotation)
|
|
226
|
+
const clamp = (val, max) => Math.max(-max, Math.min(max, val));
|
|
227
|
+
this.targetOrientation.gamma = clamp(g, 15);
|
|
228
|
+
this.targetOrientation.beta = clamp(b, 15);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
setupDesktopPointerParallax() {
|
|
232
|
+
// For non-touch/pointer devices, provide a subtle interactive hover depth response
|
|
233
|
+
if (window.matchMedia && window.matchMedia('(hover: hover)').matches) {
|
|
234
|
+
document.addEventListener('mousemove', (e) => {
|
|
235
|
+
if (this.isInputFocused || this.reducedMotion || this.activeCards.size === 0) return;
|
|
236
|
+
|
|
237
|
+
this.activeCards.forEach((card) => {
|
|
238
|
+
const rect = card.getBoundingClientRect();
|
|
239
|
+
if (e.clientX >= rect.left && e.clientX <= rect.right && e.clientY >= rect.top && e.clientY <= rect.bottom) {
|
|
240
|
+
const relX = ((e.clientX - rect.left) / rect.width) * 2 - 1; // -1 to 1
|
|
241
|
+
const relY = ((e.clientY - rect.top) / rect.height) * 2 - 1; // -1 to 1
|
|
242
|
+
|
|
243
|
+
const rotX = -relY * 3.5;
|
|
244
|
+
const rotY = relX * 3.5;
|
|
245
|
+
const transX = relX * 4;
|
|
246
|
+
const transY = relY * 4;
|
|
247
|
+
|
|
248
|
+
const img = card.querySelector('.post-media-first-img');
|
|
249
|
+
if (img) {
|
|
250
|
+
img.style.transform = `perspective(800px) rotateX(${rotX.toFixed(2)}deg) rotateY(${rotY.toFixed(2)}deg) translate3d(${transX.toFixed(1)}px, ${transY.toFixed(1)}px, 6px) scale(1.02)`;
|
|
251
|
+
img.style.transition = 'transform 0.12s cubic-bezier(0.2, 0, 0, 1)';
|
|
252
|
+
}
|
|
253
|
+
} else {
|
|
254
|
+
this.resetCardTransform(card);
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
}, { passive: true });
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
scheduleRenderLoop() {
|
|
262
|
+
if (this.rafId) return;
|
|
263
|
+
|
|
264
|
+
const render = () => {
|
|
265
|
+
// Spring damping / low-pass filter for silky 120fps motion without jitter
|
|
266
|
+
const ease = 0.08;
|
|
267
|
+
this.orientation.gamma += (this.targetOrientation.gamma - this.orientation.gamma) * ease;
|
|
268
|
+
this.orientation.beta += (this.targetOrientation.beta - this.orientation.beta) * ease;
|
|
269
|
+
|
|
270
|
+
const rotY = (this.orientation.gamma / 15) * 3.2; // Max 3.2deg
|
|
271
|
+
const rotX = (-this.orientation.beta / 15) * 3.2; // Max 3.2deg
|
|
272
|
+
const transX = (this.orientation.gamma / 15) * 4.5; // Max 4.5px
|
|
273
|
+
const transY = (this.orientation.beta / 15) * 4.5; // Max 4.5px
|
|
274
|
+
|
|
275
|
+
if (this.activeCards.size > 0 && (Math.abs(rotY) > 0.05 || Math.abs(rotX) > 0.05)) {
|
|
276
|
+
this.activeCards.forEach((card) => {
|
|
277
|
+
const img = card.querySelector('.post-media-first-img');
|
|
278
|
+
if (img) {
|
|
279
|
+
img.style.transform = `perspective(800px) rotateX(${rotX.toFixed(2)}deg) rotateY(${rotY.toFixed(2)}deg) translate3d(${transX.toFixed(1)}px, ${transY.toFixed(1)}px, 5px) scale(1.015)`;
|
|
280
|
+
img.style.transformOrigin = 'center center';
|
|
281
|
+
img.style.willChange = 'transform';
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
this.rafId = requestAnimationFrame(render);
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
this.rafId = requestAnimationFrame(render);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
resetCardTransform(card) {
|
|
293
|
+
if (!card) return;
|
|
294
|
+
const img = card.querySelector('.post-media-first-img');
|
|
295
|
+
if (img) {
|
|
296
|
+
img.style.transform = '';
|
|
297
|
+
img.style.willChange = 'auto';
|
|
298
|
+
img.style.transition = 'transform 0.3s ease-out';
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
resetTransforms() {
|
|
303
|
+
this.activeCards.forEach((card) => this.resetCardTransform(card));
|
|
304
|
+
this.targetOrientation = { gamma: 0, beta: 0 };
|
|
305
|
+
this.orientation = { gamma: 0, beta: 0 };
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export const vseRuntime = new VisualSupremacyRuntime();
|
|
310
|
+
export function initVisualSupremacy() {
|
|
311
|
+
vseRuntime.init();
|
|
312
|
+
}
|