astro-ghostcms/.pnpm-store/v3/files/1d/56d5dde6053945ed772f8fbfebd...

167 lines
5.4 KiB
Plaintext

import { fade, slide } from "../../transitions/index.js";
import { markHTMLString } from "./escape.js";
import cssesc from "cssesc";
const transitionNameMap = /* @__PURE__ */ new WeakMap();
function incrementTransitionNumber(result) {
let num = 1;
if (transitionNameMap.has(result)) {
num = transitionNameMap.get(result) + 1;
}
transitionNameMap.set(result, num);
return num;
}
function createTransitionScope(result, hash) {
const num = incrementTransitionNumber(result);
return `astro-${hash}-${num}`;
}
const getAnimations = (name) => {
if (name === "fade")
return fade();
if (name === "slide")
return slide();
if (typeof name === "object")
return name;
};
const addPairs = (animations, stylesheet) => {
for (const [direction, images] of Object.entries(animations)) {
for (const [image, rules] of Object.entries(images)) {
stylesheet.addAnimationPair(direction, image, rules);
}
}
};
function renderTransition(result, hash, animationName, transitionName) {
if (!animationName)
animationName = "fade";
const scope = createTransitionScope(result, hash);
const name = transitionName ? cssesc(transitionName, { isIdentifier: true }) : scope;
const sheet = new ViewTransitionStyleSheet(scope, name);
const animations = getAnimations(animationName);
if (animations) {
addPairs(animations, sheet);
} else if (animationName === "none") {
sheet.addFallback("old", "animation: none; mix-blend-mode: normal;");
sheet.addModern("old", "animation: none; opacity: 0; mix-blend-mode: normal;");
sheet.addAnimationRaw("new", "animation: none; mix-blend-mode: normal;");
}
result._metadata.extraHead.push(markHTMLString(`<style>${sheet.toString()}</style>`));
return scope;
}
function createAnimationScope(transitionName, animations) {
const hash = Math.random().toString(36).slice(2, 8);
const scope = `astro-${hash}`;
const sheet = new ViewTransitionStyleSheet(scope, transitionName);
addPairs(animations, sheet);
return { scope, styles: sheet.toString().replaceAll('"', "") };
}
class ViewTransitionStyleSheet {
constructor(scope, name) {
this.scope = scope;
this.name = name;
}
modern = [];
fallback = [];
toString() {
const { scope, name } = this;
const [modern, fallback] = [this.modern, this.fallback].map((rules) => rules.join(""));
return [
`[data-astro-transition-scope="${scope}"] { view-transition-name: ${name}; }`,
this.layer(modern),
fallback
].join("");
}
layer(cssText) {
return cssText ? `@layer astro { ${cssText} }` : "";
}
addRule(target, cssText) {
this[target].push(cssText);
}
addAnimationRaw(image, animation) {
this.addModern(image, animation);
this.addFallback(image, animation);
}
addModern(image, animation) {
const { name } = this;
this.addRule("modern", `::view-transition-${image}(${name}) { ${animation} }`);
}
addFallback(image, animation) {
const { scope } = this;
this.addRule(
"fallback",
// Two selectors here, the second in case there is an animation on the root.
`[data-astro-transition-fallback="${image}"] [data-astro-transition-scope="${scope}"],
[data-astro-transition-fallback="${image}"][data-astro-transition-scope="${scope}"] { ${animation} }`
);
}
addAnimationPair(direction, image, rules) {
const { scope, name } = this;
const animation = stringifyAnimation(rules);
const prefix = direction === "backwards" ? `[data-astro-transition=back]` : direction === "forwards" ? "" : `[data-astro-transition=${direction}]`;
this.addRule("modern", `${prefix}::view-transition-${image}(${name}) { ${animation} }`);
this.addRule(
"fallback",
`${prefix}[data-astro-transition-fallback="${image}"] [data-astro-transition-scope="${scope}"],
${prefix}[data-astro-transition-fallback="${image}"][data-astro-transition-scope="${scope}"] { ${animation} }`
);
}
}
function addAnimationProperty(builder, prop, value) {
let arr = builder[prop];
if (Array.isArray(arr)) {
arr.push(value.toString());
} else {
builder[prop] = [value.toString()];
}
}
function animationBuilder() {
return {
toString() {
let out = "";
for (let k in this) {
let value = this[k];
if (Array.isArray(value)) {
out += `
${k}: ${value.join(", ")};`;
}
}
return out;
}
};
}
function stringifyAnimation(anim) {
if (Array.isArray(anim)) {
return stringifyAnimations(anim);
} else {
return stringifyAnimations([anim]);
}
}
function stringifyAnimations(anims) {
const builder = animationBuilder();
for (const anim of anims) {
if (anim.duration) {
addAnimationProperty(builder, "animation-duration", toTimeValue(anim.duration));
}
if (anim.easing) {
addAnimationProperty(builder, "animation-timing-function", anim.easing);
}
if (anim.direction) {
addAnimationProperty(builder, "animation-direction", anim.direction);
}
if (anim.delay) {
addAnimationProperty(builder, "animation-delay", anim.delay);
}
if (anim.fillMode) {
addAnimationProperty(builder, "animation-fill-mode", anim.fillMode);
}
addAnimationProperty(builder, "animation-name", anim.name);
}
return builder.toString();
}
function toTimeValue(num) {
return typeof num === "number" ? num + "ms" : num;
}
export {
createAnimationScope,
createTransitionScope,
renderTransition
};