<script>
  /**
   * @type {number}
   */
  export let maxRotation = 1.5;

  /**
   * @type {number}
   */
  export let translateZ = 5;

  /** @type {Element} */
  let element;

  let mouseX = 0;
  let mouseY = 0;

  function updateMousePosition() {
    const rect = element.getBoundingClientRect();

    const y = mouseY - rect.top;
    const x = mouseX - rect.left;

    const mulForX = Math.max(rect.height / rect.width, 1.0);
    const mulForY = Math.max(rect.width / rect.height, 1.0);

    const bound = Math.max(rect.height, rect.width);

    const rotation = maxRotation / bound * 200;

    element.setAttribute('style', `--max-rotation: ${maxRotation}; --translate-z: ${translateZ}px; --cur-x: ${(-x / rect.width + 0.5) * rotation * mulForX}deg; --cur-y: ${(y / rect.height - 0.5) * rotation * mulForY}deg;`)
  }

  function mouseEnterRegion(/** @type {MouseEvent} */ event) {
    element.setAttribute('transform', '');
  }

  function mouseMove(/** @type {MouseEvent} */ event) {
    mouseX = event.clientX;
    mouseY = event.clientY;

    updateMousePosition();
  }

  function mouseLeaveRegion(/** @type {MouseEvent} */ event) {
    element.removeAttribute('transform');
  }
</script>

<style>
  .perspectiveFx {
    position: relative;

    transform: perspective(180px) translateZ(0px);

    transition: 0.2s;
    transition-property: transform;

    & > .subPerspectiveFx {
      transform: perspective(180px) rotateX(0deg) rotateY(0deg);
    }

    &[transform] {
      transform: perspective(180px) translateZ(var(--translate-z));

      & > .subPerspectiveFx {
        transform: perspective(180px) rotateX(var(--cur-y)) rotateY(var(--cur-x));
      }
    }
  }
</style>

<!-- svelte-ignore a11y-no-static-element-interactions -->
<div class="perspectiveFx" bind:this={element} on:mouseenter={mouseEnterRegion} on:mousemove={mouseMove} on:mouseleave={mouseLeaveRegion} {...$$restProps}>
  <div class="subPerspectiveFx">
    <slot />
  </div>
</div>
<svelte:window on:resize={updateMousePosition}></svelte:window>
