Repository: motion-canvas/motion-canvas
File: packages/2d/src/components/Latex.ts (TypeScript)

Code before:
/**
 * A node for rendering equations with LaTeX.
 *
 * @preview
 * ```tsx editor
 * import {Latex} from '@motion-canvas/2d/lib/components';
 * import {makeScene2D} from '@motion-canvas/2d/lib/scenes';
 * import {waitFor} from '@motion-canvas/core/lib/flow';
 * import {createRef} from '@motion-canvas/core/lib/utils';
 *
 * export default makeScene2D(function* (view) {
 *   const tex = createRef<Latex>();
 *   view.add(
 *     <Latex
 *       ref={tex}
 *       // Note how this uses \color to set the color.
 *       tex="{\color{white} ax^2+bx+c=0 \implies x=\frac{-b \pm \sqrt{b^2-4ac}}{2a}}"
 *       y={0}
 *       width={600} // height and width can calculate based on each other
 *     />,
 *   );
 *
 *   yield* waitFor(2);
 *   yield* tex().opacity(0, 1);
 *   yield* waitFor(2);
 *   yield* tex().opacity(1, 1);
 * });
 * ```
 */
export class Latex extends Img {
  private static svgContentsPool: Record<string, string> = {};

  private readonly imageElement = document.createElement('img');

  @initial({})
  @signal()
  public declare readonly options: SimpleSignal<OptionList, this>;

  @signal()
  public declare readonly tex: SimpleSignal<string, this>;

  public constructor(props: LatexProps) {
    super(props);
  }

  protected override image(): HTMLImageElement {
    // Render props may change the look of the TeX, so we need to cache both
    // source and render props together.
    const src = `${this.tex()}::${JSON.stringify(this.options())}`;
    if (Latex.svgContentsPool[src]) {
      this.imageElement.src = Latex.svgContentsPool[src];

Review comment (suggestion):
I know this has been copied from the latex page but I don't think the animation is necessary in this case, especially since `Latex` doesn't have any special properties to animate.
```suggestion
```

Code after:
/**
 * A node for rendering equations with LaTeX.
 *
 * @preview
 * ```tsx editor
 * import {Latex, makeScene2D} from '@motion-canvas/2d';
 *
 * export default makeScene2D(function* (view) {
 *   view.add(
 *     <Latex
 *       // Note how this uses \color to set the color.
 *       tex="{\color{white} ax^2+bx+c=0 \implies x=\frac{-b \pm \sqrt{b^2-4ac}}{2a}}"
 *       width={600} // height and width can calculate based on each other
 *     />,
 *   );
 * });
 * ```
 */
export class Latex extends Img {
  private static svgContentsPool: Record<string, string> = {};

  private readonly imageElement = document.createElement('img');

  @initial({})
  @signal()
  public declare readonly options: SimpleSignal<OptionList, this>;

  @signal()
  public declare readonly tex: SimpleSignal<string, this>;

  public constructor(props: LatexProps) {
    super(props);
  }

  protected override image(): HTMLImageElement {
    // Render props may change the look of the TeX, so we need to cache both
    // source and render props together.
    const src = `${this.tex()}::${JSON.stringify(this.options())}`;
    if (Latex.svgContentsPool[src]) {
      this.imageElement.src = Latex.svgContentsPool[src];
      if (!this.imageElement.complete) {
        DependencyContext.collectPromise(
          new Promise((resolve, reject) => {
            this.imageElement.addEventListener('load', resolve);
            this.imageElement.addEventListener('error', reject);
          }),
        );
      }
      return this.imageElement;
    }