142 lines
4.6 KiB
JavaScript
142 lines
4.6 KiB
JavaScript
import { createVNode as _createVNode, mergeProps as _mergeProps, resolveDirective as _resolveDirective } from "vue";
|
|
// Utilities
|
|
import { Transition } from 'vue';
|
|
import { acceleratedEasing, animate, deceleratedEasing, genericComponent, nullifyTransforms, propsFactory, standardEasing } from "../../util/index.mjs";
|
|
import { getTargetBox } from "../../util/box.mjs"; // Types
|
|
export const makeVDialogTransitionProps = propsFactory({
|
|
target: [Object, Array]
|
|
}, 'v-dialog-transition');
|
|
export const VDialogTransition = genericComponent()({
|
|
name: 'VDialogTransition',
|
|
props: makeVDialogTransitionProps(),
|
|
setup(props, _ref) {
|
|
let {
|
|
slots
|
|
} = _ref;
|
|
const functions = {
|
|
onBeforeEnter(el) {
|
|
el.style.pointerEvents = 'none';
|
|
el.style.visibility = 'hidden';
|
|
},
|
|
async onEnter(el, done) {
|
|
await new Promise(resolve => requestAnimationFrame(resolve));
|
|
await new Promise(resolve => requestAnimationFrame(resolve));
|
|
el.style.visibility = '';
|
|
const {
|
|
x,
|
|
y,
|
|
sx,
|
|
sy,
|
|
speed
|
|
} = getDimensions(props.target, el);
|
|
const animation = animate(el, [{
|
|
transform: `translate(${x}px, ${y}px) scale(${sx}, ${sy})`,
|
|
opacity: 0
|
|
}, {}], {
|
|
duration: 225 * speed,
|
|
easing: deceleratedEasing
|
|
});
|
|
getChildren(el)?.forEach(el => {
|
|
animate(el, [{
|
|
opacity: 0
|
|
}, {
|
|
opacity: 0,
|
|
offset: 0.33
|
|
}, {}], {
|
|
duration: 225 * 2 * speed,
|
|
easing: standardEasing
|
|
});
|
|
});
|
|
animation.finished.then(() => done());
|
|
},
|
|
onAfterEnter(el) {
|
|
el.style.removeProperty('pointer-events');
|
|
},
|
|
onBeforeLeave(el) {
|
|
el.style.pointerEvents = 'none';
|
|
},
|
|
async onLeave(el, done) {
|
|
await new Promise(resolve => requestAnimationFrame(resolve));
|
|
const {
|
|
x,
|
|
y,
|
|
sx,
|
|
sy,
|
|
speed
|
|
} = getDimensions(props.target, el);
|
|
const animation = animate(el, [{}, {
|
|
transform: `translate(${x}px, ${y}px) scale(${sx}, ${sy})`,
|
|
opacity: 0
|
|
}], {
|
|
duration: 125 * speed,
|
|
easing: acceleratedEasing
|
|
});
|
|
animation.finished.then(() => done());
|
|
getChildren(el)?.forEach(el => {
|
|
animate(el, [{}, {
|
|
opacity: 0,
|
|
offset: 0.2
|
|
}, {
|
|
opacity: 0
|
|
}], {
|
|
duration: 125 * 2 * speed,
|
|
easing: standardEasing
|
|
});
|
|
});
|
|
},
|
|
onAfterLeave(el) {
|
|
el.style.removeProperty('pointer-events');
|
|
}
|
|
};
|
|
return () => {
|
|
return props.target ? _createVNode(Transition, _mergeProps({
|
|
"name": "dialog-transition"
|
|
}, functions, {
|
|
"css": false
|
|
}), slots) : _createVNode(Transition, {
|
|
"name": "dialog-transition"
|
|
}, slots);
|
|
};
|
|
}
|
|
});
|
|
|
|
/** Animatable children (card, sheet, list) */
|
|
function getChildren(el) {
|
|
const els = el.querySelector(':scope > .v-card, :scope > .v-sheet, :scope > .v-list')?.children;
|
|
return els && [...els];
|
|
}
|
|
function getDimensions(target, el) {
|
|
const targetBox = getTargetBox(target);
|
|
const elBox = nullifyTransforms(el);
|
|
const [originX, originY] = getComputedStyle(el).transformOrigin.split(' ').map(v => parseFloat(v));
|
|
const [anchorSide, anchorOffset] = getComputedStyle(el).getPropertyValue('--v-overlay-anchor-origin').split(' ');
|
|
let offsetX = targetBox.left + targetBox.width / 2;
|
|
if (anchorSide === 'left' || anchorOffset === 'left') {
|
|
offsetX -= targetBox.width / 2;
|
|
} else if (anchorSide === 'right' || anchorOffset === 'right') {
|
|
offsetX += targetBox.width / 2;
|
|
}
|
|
let offsetY = targetBox.top + targetBox.height / 2;
|
|
if (anchorSide === 'top' || anchorOffset === 'top') {
|
|
offsetY -= targetBox.height / 2;
|
|
} else if (anchorSide === 'bottom' || anchorOffset === 'bottom') {
|
|
offsetY += targetBox.height / 2;
|
|
}
|
|
const tsx = targetBox.width / elBox.width;
|
|
const tsy = targetBox.height / elBox.height;
|
|
const maxs = Math.max(1, tsx, tsy);
|
|
const sx = tsx / maxs || 0;
|
|
const sy = tsy / maxs || 0;
|
|
|
|
// Animate elements larger than 12% of the screen area up to 1.5x slower
|
|
const asa = elBox.width * elBox.height / (window.innerWidth * window.innerHeight);
|
|
const speed = asa > 0.12 ? Math.min(1.5, (asa - 0.12) * 10 + 1) : 1;
|
|
return {
|
|
x: offsetX - (originX + elBox.left),
|
|
y: offsetY - (originY + elBox.top),
|
|
sx,
|
|
sy,
|
|
speed
|
|
};
|
|
}
|
|
//# sourceMappingURL=dialog-transition.mjs.map
|