site/src/components/anime.tsx
2025-01-06 16:35:53 -08:00

73 lines
No EOL
2.1 KiB
TypeScript

"use client";
// Utility component for executing animations
import anime, { AnimeParams } from "animejs";
import React from "react";
interface IProps {
params: AnimeParams;
children: React.ReactNode;
}
interface IState {
scopeState: string;
}
export default class Anime extends React.Component<IProps, IState> {
private anime: anime.AnimeInstance | null;
constructor(props: IProps) {
super(props);
this.state = {
scopeState: "",
};
this.anime = null;
}
private applyDescendantSelector(selector: string): string {
console.log("Applying descendant selector to: " + selector);
return selector.split(",").map((s) => {
return "." + this.state.scopeState + ' ' + s;
}).join(", ");
}
componentDidMount(): void {
const scope = "anime-scope-" + Math.random().toString(36).substring(4);
this.setState({
scopeState: scope,
}, () => {
console.log("Anime scope state: " + this.state.scopeState);
const postTargets = '.' + this.state.scopeState;
console.log("Targets: " + postTargets);
// Update all params targets CSS selectors to include a descendant selector
if (this.props.params.targets !== undefined) {
// Identify if is single or is array (type AnimeTarget)
this.props.params.targets = this.applyDescendantSelector(this.props.params.targets?.toString() as string);
console.log("Updated targets: " + this.props.params.targets);
} else {
this.props.params.targets = postTargets;
}
this.anime = anime({
...this.props.params,
});
});
}
render() {
return (
<div>
<style>
{`.${this.state.scopeState} {}`}
</style>
<div className={this.state.scopeState}>
{this.props.children}
</div>
</div>
)
}
}