@vtbag/utensil-drawer
Version:
Pull out just what you need to craft seamless transitions. The Utensil Drawer holds reusable functions to help you build websites with view transitions. It is a bit sparse right now, but like the one in your kitchen, it is bound to fill up over time.
66 lines (65 loc) • 2.97 kB
JavaScript
import { getCurrentViewTransition } from './may-start-view-transition.js';
import { createPromiseSubstitute } from './switchable-promise.js';
export function createViewTransitionProxy(types) {
let delegate = undefined;
let skipped = false;
const waitForThose = [];
return new Proxy({
updateCallbackDone: createPromiseSubstitute(),
ready: createPromiseSubstitute(),
finished: createPromiseSubstitute(),
skipTransition: () => (delegate ? delegate.skipTransition() : (skipped = true)),
waitUntil: (promise) => waitForThose.push(promise),
types: new Proxy(new Set(types), {
get(target, prop) {
if (prop === 'add') {
return (value) => (delegate ? delegate.types.add(value) : target.add(value));
}
else if (prop === 'delete') {
return (value) => delegate ? delegate.types.delete(value) : target.delete(value);
}
else if (prop === 'clear') {
return () => (delegate ? delegate.types.clear() : target.clear());
}
else if (prop === 'has') {
return (value) => (delegate ? delegate.types.has(value) : target.has(value));
}
else if (prop === 'size') {
return () => (delegate ? delegate.types.size : target.size);
}
else if (prop === 'forEach') {
return (callback, thisArg) => delegate
? delegate.types.forEach(callback, thisArg)
: target.forEach(callback, thisArg);
}
else if (prop === Symbol.iterator) {
return () => delegate ? delegate.types[Symbol.iterator]() : target[Symbol.iterator]();
}
return target[prop];
},
}),
switch() {
const currentViewTransition = getCurrentViewTransition();
if (!currentViewTransition)
throw new Error('No view transition active');
if (delegate)
throw new Error('Already switched to another view transition');
if (skipped) {
currentViewTransition?.skipTransition();
}
if ('waitUntil' in currentViewTransition)
for (const promise of waitForThose) {
currentViewTransition.waitUntil(promise);
}
this.types = currentViewTransition.types ?? this.types;
this.updateCallbackDone.switch(currentViewTransition.updateCallbackDone);
this.ready.switch(currentViewTransition.ready);
this.finished.switch(currentViewTransition.finished);
delegate = currentViewTransition;
},
}, {
get(target, prop) {
return delegate ? delegate[prop] : target[prop];
},
});
}