All files / src/features/tilt Tilt.ts

100% Statements 42/42
100% Branches 16/16
100% Functions 8/8
100% Lines 42/42

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75          14x           23x 23x 23x 23x   23x 43x 43x 43x 43x     23x 43x 43x   43x 43x 43x     23x 43x   43x 43x 35x 35x 35x 35x       23x 43x 43x 43x     23x 43x   43x 43x   43x 43x 4x 4x       23x 47x   47x 47x     23x 7x      
import { constrainToRange } from '@/utils/helperFns';
import type { ClientPosition } from '@/utils/types';
 
import type { TiltProps } from './types.public';
 
const TILT_ANGLE_CONSTRAINT = 90;
 
// All props are initialized by default with non-null values
/* eslint-disable @typescript-eslint/no-non-null-assertion */
 
export class Tilt {
  public tiltAngleX = 0;
  public tiltAngleY = 0;
  public tiltAngleXPercentage = 0;
  public tiltAngleYPercentage = 0;
 
  public update = (wrapperElClientPosition: ClientPosition, props: TiltProps): void => {
    this.updateTilt(wrapperElClientPosition, props);
    this.updateTiltManualInput(wrapperElClientPosition, props);
    this.updateTiltReverse(props);
    this.updateTiltLimits(props);
  };
 
  private updateTilt = (wrapperElClientPosition: ClientPosition, props: TiltProps): void => {
    const { xPercentage, yPercentage } = wrapperElClientPosition;
    const { tiltMaxAngleX, tiltMaxAngleY } = props;
 
    const tiltTowardMouse = -1;
    this.tiltAngleX = (xPercentage * tiltMaxAngleX!) / 100;
    this.tiltAngleY = ((yPercentage * tiltMaxAngleY!) / 100) * tiltTowardMouse;
  };
 
  private updateTiltManualInput = (wrapperElClientPosition: ClientPosition, props: TiltProps): void => {
    const { tiltAngleXManual, tiltAngleYManual, tiltMaxAngleX, tiltMaxAngleY } = props;
 
    const isManualInputIgnoreOtherInputs = tiltAngleXManual !== null || tiltAngleYManual !== null;
    if (isManualInputIgnoreOtherInputs) {
      this.tiltAngleX = tiltAngleXManual !== null ? tiltAngleXManual! : 0;
      this.tiltAngleY = tiltAngleYManual !== null ? tiltAngleYManual! : 0;
      wrapperElClientPosition.xPercentage = (100 * this.tiltAngleX) / tiltMaxAngleX!;
      wrapperElClientPosition.yPercentage = (100 * this.tiltAngleY) / tiltMaxAngleY!;
    }
  };
 
  private updateTiltReverse = (props: TiltProps): void => {
    const tiltReverse = props.tiltReverse ? -1 : 1;
    this.tiltAngleX = tiltReverse * this.tiltAngleX;
    this.tiltAngleY = tiltReverse * this.tiltAngleY;
  };
 
  private updateTiltLimits = (props: TiltProps): void => {
    const { tiltAxis } = props;
 
    this.tiltAngleX = constrainToRange(this.tiltAngleX, -TILT_ANGLE_CONSTRAINT, TILT_ANGLE_CONSTRAINT);
    this.tiltAngleY = constrainToRange(this.tiltAngleY, -TILT_ANGLE_CONSTRAINT, TILT_ANGLE_CONSTRAINT);
 
    const isOnlyOneAxisEnabledForTilting = tiltAxis;
    if (isOnlyOneAxisEnabledForTilting) {
      this.tiltAngleX = tiltAxis === 'x' ? this.tiltAngleX : 0;
      this.tiltAngleY = tiltAxis === 'y' ? this.tiltAngleY : 0;
    }
  };
 
  public updateTiltAnglesPercentage = (props: TiltProps): void => {
    const { tiltMaxAngleX, tiltMaxAngleY } = props;
 
    this.tiltAngleXPercentage = (this.tiltAngleX / tiltMaxAngleX!) * 100;
    this.tiltAngleYPercentage = (this.tiltAngleY / tiltMaxAngleY!) * 100;
  };
 
  public render = (element: HTMLDivElement): void => {
    element.style.transform += `rotateX(${this.tiltAngleX}deg) rotateY(${this.tiltAngleY}deg) `;
  };
}