Initial curated chimera source from a8ae5b1db07fb49926c94585e2718e5130330974
This commit is contained in:
commit
c737a37f71
531 files changed
+119270
No files matched your search
@@ -0,0 +1,203 @@
|
||||
'use strict';
|
||||
|
||||
(function mountPremiumProjectIllustrations() {
|
||||
const targets = Object.freeze({
|
||||
'games-empty': 'library',
|
||||
'backups-empty': 'protection',
|
||||
'transfers-empty': 'transfer',
|
||||
'media-empty': 'media',
|
||||
});
|
||||
const illustrations = Object.freeze({
|
||||
'library': `<div class="premium-project-illustration" data-variant="library" aria-hidden="true">
|
||||
<span class="premium-project-glow"></span>
|
||||
<svg viewBox="0 0 320 180" focusable="false">
|
||||
<path class="premium-project-path path-a" d="M31 124C76 50 122 57 159 88s75 37 130-23"/>
|
||||
<path class="premium-project-path path-b" d="M37 58c42 18 65 4 96 34s70 44 151 27"/>
|
||||
<g class="premium-project-source library-source"><rect x="24" y="82" width="38" height="54" rx="6"/><rect x="31" y="74" width="38" height="54" rx="6"/><path d="M39 91h22M39 100h16"/></g>
|
||||
<g class="premium-project-surface library-index"><rect x="119" y="39" width="83" height="104" rx="11"/><path d="M135 63h51M135 79h34M135 105h18M160 105h26M135 119h18M160 119h26"/></g>
|
||||
<g class="premium-project-node library-art"><rect x="260" y="48" width="38" height="48" rx="7"/><path d="m268 84 8-10 7 7 6-8"/><circle cx="286" cy="60" r="4"/></g>
|
||||
<g class="premium-project-node library-proof"><circle cx="276" cy="126" r="15"/><path d="m269 126 5 5 9-11"/></g>
|
||||
</svg>
|
||||
<span class="premium-project-packet packet-a"></span><span class="premium-project-packet packet-b"></span><span class="premium-project-packet packet-c"></span>
|
||||
</div>`,
|
||||
'protection': `<div class="premium-project-illustration" data-variant="protection" aria-hidden="true">
|
||||
<span class="premium-project-glow"></span>
|
||||
<svg viewBox="0 0 320 180" focusable="false">
|
||||
<path class="premium-project-path path-a" d="M35 95h79c21 0 27-30 49-30h27c24 0 29 31 49 31h47"/>
|
||||
<path class="premium-project-path path-b" d="M65 131h67c18 0 25-21 42-21h35c17 0 23 21 43 21h34"/>
|
||||
<g class="premium-project-source protection-copy"><rect x="27" y="61" width="46" height="68" rx="7"/><path d="M38 80h24M38 94h19M38 108h24"/></g>
|
||||
<g class="premium-project-node protection-hash"><rect x="129" y="49" width="68" height="55" rx="10"/><path d="M142 68h42M142 80h32"/><text x="144" y="94">SHA</text></g>
|
||||
<g class="premium-project-surface protection-vault"><path d="M238 55h55v77h-55z"/><circle cx="265" cy="93" r="14"/><path d="M265 84v18M256 93h18"/></g>
|
||||
<g class="premium-project-shield"><path d="M183 112c0 19-12 28-25 34-13-6-25-15-25-34l25-9z"/><path d="m149 121 7 7 12-16"/></g>
|
||||
</svg>
|
||||
<span class="premium-project-packet packet-a"></span><span class="premium-project-packet packet-b"></span><span class="premium-project-packet packet-c"></span>
|
||||
</div>`,
|
||||
'transfer': `<div class="premium-project-illustration" data-variant="transfer" aria-hidden="true">
|
||||
<span class="premium-project-glow"></span>
|
||||
<svg viewBox="0 0 320 180" focusable="false">
|
||||
<path class="premium-project-path path-a" d="M68 87h67c21 0 26-27 47-27h28c22 0 27 27 47 27h26"/>
|
||||
<path class="premium-project-path path-b" d="M68 119h63c22 0 31 25 53 25h30c21 0 29-25 47-25h22"/>
|
||||
<g class="premium-project-source transfer-console"><path d="M27 61h46l8 65H19z"/><path d="M37 78h27M42 111h17"/><circle cx="50" cy="93" r="5"/></g>
|
||||
<g class="premium-project-surface transfer-router"><rect x="133" y="42" width="69" height="78" rx="11"/><path d="M146 64h43M146 79h43M146 94h31"/><circle cx="186" cy="95" r="3"/></g>
|
||||
<g class="premium-project-node transfer-vault"><rect x="251" y="61" width="48" height="65" rx="7"/><path d="M260 78h30M260 91h30M260 104h21"/></g>
|
||||
<g class="premium-project-progress"><path d="M126 144h82"/><path d="M126 144h55"/></g>
|
||||
</svg>
|
||||
<span class="premium-project-packet packet-a"></span><span class="premium-project-packet packet-b"></span><span class="premium-project-packet packet-c"></span>
|
||||
</div>`,
|
||||
'media': `<div class="premium-project-illustration" data-variant="media" aria-hidden="true">
|
||||
<span class="premium-project-glow"></span>
|
||||
<svg viewBox="0 0 320 180" focusable="false">
|
||||
<path class="premium-project-path path-a" d="M85 90h58c21 0 24-28 46-28h23c21 0 25 28 44 28h35"/>
|
||||
<path class="premium-project-path path-b" d="M84 120h57c22 0 27 22 47 22h26c20 0 25-22 44-22h33"/>
|
||||
<g class="premium-project-source media-console"><rect x="22" y="48" width="70" height="84" rx="9"/><path d="m34 111 15-18 12 12 18-24"/><circle cx="71" cy="66" r="6"/></g>
|
||||
<g class="premium-project-wave"><path d="M119 92h8l5-17 9 35 8-25 8 13 7-6h8"/></g>
|
||||
<g class="premium-project-surface media-gallery"><rect x="225" y="43" width="67" height="47" rx="7"/><rect x="217" y="99" width="75" height="43" rx="7"/><path d="m235 80 10-11 8 8 11-14 17 17M227 132l11-12 9 8 11-13 22 17"/></g>
|
||||
<g class="premium-project-node media-play"><circle cx="184" cy="95" r="19"/><path d="m180 86 12 9-12 9z"/></g>
|
||||
</svg>
|
||||
<span class="premium-project-packet packet-a"></span><span class="premium-project-packet packet-b"></span><span class="premium-project-packet packet-c"></span>
|
||||
</div>`,
|
||||
'trophies': `<div class="premium-project-illustration" data-variant="trophies" aria-hidden="true">
|
||||
<span class="premium-project-glow"></span>
|
||||
<svg viewBox="0 0 320 180" focusable="false">
|
||||
<path class="premium-project-path path-a" d="M48 126c39-72 80-80 119-45s65 40 111-25"/>
|
||||
<path class="premium-project-path path-b" d="M46 66c43 5 66 23 91 59s80 32 139 4"/>
|
||||
<g class="premium-project-source trophy-game"><rect x="27" y="54" width="52" height="75" rx="7"/><path d="M38 75h30M38 88h20M38 108h30"/></g>
|
||||
<g class="premium-project-surface trophy-cup"><path d="M139 49h46v22c0 23-9 36-23 36s-23-13-23-36z"/><path d="M139 58h-14v8c0 13 7 20 19 21M185 58h14v8c0 13-7 20-19 21M162 107v17M145 126h34"/></g>
|
||||
<g class="premium-project-node trophy-locked"><circle cx="257" cy="62" r="19"/><path d="M250 62v-5a7 7 0 0 1 14 0v5M248 62h18v14h-18z"/></g>
|
||||
<g class="premium-project-node trophy-earned"><circle cx="268" cy="127" r="17"/><path d="m259 127 6 6 12-14"/></g>
|
||||
<g class="premium-project-progress trophy-progress"><circle cx="162" cy="84" r="56"/><path d="M162 28a56 56 0 0 1 51 79"/></g>
|
||||
</svg>
|
||||
<span class="premium-project-packet packet-a"></span><span class="premium-project-packet packet-b"></span><span class="premium-project-packet packet-c"></span>
|
||||
</div>`,
|
||||
});
|
||||
const reducedMotion = typeof window.matchMedia === 'function'
|
||||
? window.matchMedia('(prefers-reduced-motion: reduce)')
|
||||
: { matches: false, addListener() {}, removeListener() {} };
|
||||
const mounted = new Set();
|
||||
const visibilityObserver = 'IntersectionObserver' in window ? new IntersectionObserver(entries => {
|
||||
for (const entry of entries) {
|
||||
entry.target.classList.toggle('is-active', entry.isIntersecting);
|
||||
syncMotion(entry.target);
|
||||
}
|
||||
}, { threshold: .16 }) : null;
|
||||
|
||||
function motionPaused() {
|
||||
return reducedMotion.matches || document.visibilityState !== 'visible';
|
||||
}
|
||||
|
||||
function syncMotion(element) {
|
||||
if (!element) return;
|
||||
element.classList.toggle('is-paused', motionPaused());
|
||||
}
|
||||
|
||||
function syncAllMotion() {
|
||||
for (const element of mounted) {
|
||||
if (!element.isConnected) {
|
||||
visibilityObserver?.unobserve(element);
|
||||
mounted.delete(element);
|
||||
continue;
|
||||
}
|
||||
syncMotion(element);
|
||||
}
|
||||
}
|
||||
|
||||
function bind(illustration) {
|
||||
if (!illustration || mounted.has(illustration)) return;
|
||||
syncAllMotion();
|
||||
mounted.add(illustration);
|
||||
visibilityObserver?.observe(illustration);
|
||||
if (!visibilityObserver) illustration.classList.add('is-active');
|
||||
syncMotion(illustration);
|
||||
let pointerFrame = 0;
|
||||
let pointerX = 0;
|
||||
let pointerY = 0;
|
||||
illustration.addEventListener('pointermove', event => {
|
||||
if (motionPaused() || event.pointerType === 'touch') return;
|
||||
pointerX = event.clientX;
|
||||
pointerY = event.clientY;
|
||||
if (pointerFrame) return;
|
||||
pointerFrame = window.requestAnimationFrame(() => {
|
||||
pointerFrame = 0;
|
||||
const rect = illustration.getBoundingClientRect();
|
||||
illustration.style.setProperty('--illustration-x', `${((pointerX - rect.left) / rect.width - .5) * 7}deg`);
|
||||
illustration.style.setProperty('--illustration-y', `${((pointerY - rect.top) / rect.height - .5) * -5}deg`);
|
||||
});
|
||||
}, { passive: true });
|
||||
illustration.addEventListener('pointerleave', () => {
|
||||
if (pointerFrame) window.cancelAnimationFrame(pointerFrame);
|
||||
pointerFrame = 0;
|
||||
illustration.style.removeProperty('--illustration-x');
|
||||
illustration.style.removeProperty('--illustration-y');
|
||||
});
|
||||
}
|
||||
|
||||
function bindHomeTopology() {
|
||||
const home = document.getElementById('chimera-home-command-center');
|
||||
if (!home) return;
|
||||
home.classList.add('premium-topology-motion');
|
||||
bind(home);
|
||||
}
|
||||
|
||||
function dockImportLauncher() {
|
||||
const launcher = document.getElementById('chimera-import-open');
|
||||
const sidebarDonate = document.getElementById('sidebar-donate');
|
||||
if (!launcher || !sidebarDonate) return false;
|
||||
launcher.classList.add('chimera-import-launcher-docked');
|
||||
sidebarDonate.after(launcher);
|
||||
return true;
|
||||
}
|
||||
|
||||
function ensureTrophyIllustration() {
|
||||
const target = document.querySelector('.trophy-library-empty');
|
||||
if (!target) return;
|
||||
let illustration = target.querySelector('.premium-project-illustration');
|
||||
if (!illustration) {
|
||||
target.insertAdjacentHTML('afterbegin', illustrations.trophies);
|
||||
illustration = target.querySelector('.premium-project-illustration');
|
||||
}
|
||||
bind(illustration);
|
||||
}
|
||||
|
||||
for (const [id, variant] of Object.entries(targets)) {
|
||||
const target = document.getElementById(id);
|
||||
if (!target) continue;
|
||||
const ensure = () => {
|
||||
let illustration = target.querySelector('.premium-project-illustration');
|
||||
if (!illustration) {
|
||||
target.insertAdjacentHTML('afterbegin', illustrations[variant]);
|
||||
illustration = target.querySelector('.premium-project-illustration');
|
||||
}
|
||||
bind(illustration);
|
||||
};
|
||||
ensure();
|
||||
new MutationObserver(ensure).observe(target, { childList: true });
|
||||
}
|
||||
|
||||
// Trophy content is rendered by a route module and the page node may be
|
||||
// replaced while the feature is loading. Observe the stable content root so
|
||||
// both a late render and a replacement page receive the illustration.
|
||||
const trophyHost = document.getElementById('content') || document.body;
|
||||
const touchesTrophyLibrary = mutation => {
|
||||
const target = mutation.target?.nodeType === Node.ELEMENT_NODE ? mutation.target : mutation.target?.parentElement;
|
||||
if (target?.matches?.('#page-trophies, #page-trophies *')) return true;
|
||||
return [...mutation.addedNodes].some(node => node.nodeType === Node.ELEMENT_NODE && (
|
||||
node.matches?.('#page-trophies, .trophy-library-empty')
|
||||
|| node.querySelector?.('#page-trophies, .trophy-library-empty')
|
||||
));
|
||||
};
|
||||
ensureTrophyIllustration();
|
||||
new MutationObserver(mutations => {
|
||||
if (mutations.some(touchesTrophyLibrary)) ensureTrophyIllustration();
|
||||
}).observe(trophyHost, { childList: true, subtree: true });
|
||||
bindHomeTopology();
|
||||
if (!dockImportLauncher()) {
|
||||
const importLauncherObserver = new MutationObserver(() => {
|
||||
if (!dockImportLauncher()) return;
|
||||
importLauncherObserver.disconnect();
|
||||
});
|
||||
importLauncherObserver.observe(document.body, { childList: true });
|
||||
}
|
||||
document.addEventListener('visibilitychange', syncAllMotion);
|
||||
if (typeof reducedMotion.addEventListener === 'function') reducedMotion.addEventListener('change', syncAllMotion);
|
||||
else reducedMotion.addListener(syncAllMotion);
|
||||
})();
|
||||
Reference in new issue
Block a user