@sc4rfurryx/proteusjs
Version:
The Modern Web Development Framework for Accessible, Responsive, and High-Performance Applications. Intelligent container queries, fluid typography, WCAG compliance, and performance optimization.
121 lines (119 loc) • 3.61 kB
JavaScript
/*!
* ProteusJS v2.0.0
* Shape-shifting responsive design that adapts like the sea god himself
* (c) 2025 sc4rfurry
* Released under the MIT License
*/
/**
* @sc4rfurryx/proteusjs/transitions
* View Transitions API wrapper with safe fallbacks
*
* @version 2.0.0
* @author sc4rfurry
* @license MIT
*/
/**
* One API for animating DOM state changes and cross-document navigations
* using the View Transitions API with safe fallbacks.
*/
async function transition(run, opts = {}) {
const { name, duration = 300, onBefore, onAfter, allowInterrupt = true } = opts;
// Check for View Transitions API support
const hasViewTransitions = 'startViewTransition' in document;
if (onBefore) {
onBefore();
}
if (!hasViewTransitions) {
// Fallback: run immediately without transitions
try {
await run();
}
finally {
if (onAfter) {
onAfter();
}
}
return;
}
// Use native View Transitions API
try {
const viewTransition = document.startViewTransition(async () => {
await run();
});
// Add CSS view-transition-name if name provided
if (name) {
const style = document.createElement('style');
style.textContent = `
::view-transition-old(${name}),
::view-transition-new(${name}) {
animation-duration: ${duration}ms;
}
`;
document.head.appendChild(style);
// Clean up style after transition
viewTransition.finished.finally(() => {
style.remove();
});
}
await viewTransition.finished;
}
catch (error) {
console.warn('View transition failed, falling back to immediate execution:', error);
await run();
}
finally {
if (onAfter) {
onAfter();
}
}
}
/**
* MPA-friendly navigation with view transitions when supported
*/
async function navigate(url, opts = {}) {
const { name, prerender = false } = opts;
// Optional prerender hint (basic implementation)
if (prerender && 'speculation' in HTMLScriptElement.prototype) {
const script = document.createElement('script');
script.type = 'speculationrules';
script.textContent = JSON.stringify({
prerender: [{ where: { href_matches: url } }]
});
document.head.appendChild(script);
}
// Check for View Transitions API support
const hasViewTransitions = 'startViewTransition' in document;
if (!hasViewTransitions) {
// Fallback: normal navigation
window.location.href = url;
return;
}
try {
// Use view transitions for navigation
const viewTransition = document.startViewTransition(() => {
window.location.href = url;
});
if (name) {
const style = document.createElement('style');
style.textContent = `
::view-transition-old(${name}),
::view-transition-new(${name}) {
animation-duration: 300ms;
}
`;
document.head.appendChild(style);
}
await viewTransition.finished;
}
catch (error) {
console.warn('View transition navigation failed, falling back to normal navigation:', error);
window.location.href = url;
}
}
// Export default object for convenience
var index = {
transition,
navigate
};
export { index as default, navigate, transition };
//# sourceMappingURL=transitions.esm.js.map