npm ERR! ERESOLVE could not resolve (dependency conflicts)

I am using AWS (Amazon Web Services) specifically Amplify. I added the template that is provided by Amplify to GitHub and cloned it to my local machine and deployed it to Amplify that worked fine. I then modified the code locally and pushed the changes to GitHub which in turn attempted to deploy to Amplify, which then failed. I then read up online about this issue and have tried several methods to try and resolve the issue but nothing has worked so far. I have tried the following;

  1. Updating package-lock.json file 4 times
  2. npm audit fix --force
  3. deleting the package-lock.json file and npm install to create new one (I saved a copy of the original package-lock.json file)

After doing the above I am left with this output from the Amplify deployment.

Amplify output of why the deployment failed

This is my package.json file:

{
  "name": "amplify-vite-react-template",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview"
  },
  "dependencies": {
    "@aws-amplify/ui-react": "^6.9.4",
    "aws-amplify": "^6.13.6",
    "react": "^19.0.0",
    "react-dom": "^19.0.0"
  },
  "devDependencies": {
    "@aws-amplify/backend": "^1.14.3",
    "@aws-amplify/backend-cli": "^1.5.0",
    "@types/react": "^19.0.12",
    "@types/react-dom": "^19.0.4",
    "@typescript-eslint/eslint-plugin": "^8.28.0",
    "@typescript-eslint/parser": "^8.28.0",
    "@vitejs/plugin-react": "^4.3.4",
    "aws-cdk": "^2.1005.0",
    "aws-cdk-lib": "^2.185.0",
    "constructs": "^10.4.2",
    "esbuild": "^0.25.1",
    "eslint": "^9.23.0",
    "eslint-plugin-react-hooks": "^5.2.0",
    "eslint-plugin-react-refresh": "^0.4.19",
    "tsx": "^4.19.3",
    "typescript": "^5.8.2",
    "vite": "^6.2.3"
  }
}

What do I need to do to rectify the errors?

Asynchronously looping a map (or array) in sequential order without await to avoid blocking UI updates [closed]

I have a map that must be looped through in sequential order, as i relies on i - 1 being finished. await is an obvious solution, however it is blocking the UI updates for the app aka the UI freezes. This loop takes several seconds to complete, and it’s critical that other code runs while this loop is running.

// Mocks
const functionThatReturnsMap = () => new Map([
  ['foo', 'FOO'],
  ['bar', 'BAR'],
  ['baz', 'BAZ'],
]);
const foo = async (i, m) => {
  console.log('Calling foo for iteration:', i);
  // do something async like an HTTP call
  await fetch(`https://echo.zuplo.io/${i}`);
  console.log(`foo[${i}] completed`);
};

async function bar() {
  let ref = functionThatReturnsMap();

  for (let i = 0; i < ref.size; i++) {
    await foo(i, ref);
  }
}

async function bat() {
  bar();
}

bat();
console.log('OMG, other code!');
.as-console-wrapper { max-height: 100% !important; }

For clarity, ref is a map that is being modified by foo by reference.

In a non-UI-updates-blocking way, how do I loop through my map ref asynchronously while ensuring that i - 1 is finished before i runs?

its possible combines “a fixed tooltip” (bindTooltip) when i using leaflet markers group?

When I am creating markers on the map, individually, I am using the “bindTooltip” tool to add fixed text below each marker.

Is it possible to do something similar, to have fixed text below each marker, but when the map is initialized with the markers grouped?

  iniciarMarkersGroup();
    dados.forEach(function (item, i) {

        let sInfo ='example';

        var marker;

        if (mapaAgrupado == "1") {
            marker = adicionarMarkerGroup(item.LAT, item.LONG, item.NAME, item.CUSTOM_IMG, sInfo);

        }
        else {
            marker = adicionarMarker(item.LAT, item.LONG, item.NAME, item.CUSTOM_IMG, sInfo);

            if (item.NAME != null && item.NAME != '') {
                marker.bindTooltip(item.NAME, {
                    permanent: true,
                    direction: 'bottom',
                    offset: [10, 10]
                });
            }
        }

if i use this example, when a user has “mapaAgrupado” , im trying exibes markers with a group function, and it is working. but if i try add a .bindTooltip , im receive a error, its possible use .bindTooltip with grouped markers?

Javascript tankgame, tanks wont move

I have followed a Youtube guide (https://www.youtube.com/watch?v=D9LqQEPGoo8) on how to make a 2D tank game with JS. I feel like I have done/written the same things as he did, but when I test out the movement of the tanks, my wont move at all?

Im completely new to programming, and trying to get a hang on it. I have tried to find a solution myself but I cant figure out the problem.

The images are getting draw, and I have have tested that it takes “key-inputs” and I can console.log its values, but it still doesn’t work.

Can you figure out whats wrong?

I have tried to switch a bit up on the variables, to see how the game would react and it feels like it does the right thing. I just doesn’t wont to move. Maybe the problem is at controls()?

<body>
    <canvas id="myCanvas" width="800" height="600"></canvas>
    <script type="text/javascript">
        let canvas = document.getElementById("myCanvas");
        let ctx = canvas.getContext("2d");
        document.addEventListener("keydown", keyDownHandler, false);
        document.addEventListener("keyup", keyUpHandler, false);

        // Tanks udseende

        let tank1 = new Image();
        tank1.src = "tank1.png";
        let tank2 = new Image();
        tank2.src = "tank2.png";
        
        // Definering af variabler til controls

        let upPressed = false;
        let downPressed = false;
        let leftPressed = false;
        let rightPressed = false;
        let zeroPressed = false;
        let wPressed = false;
        let sPressed = false;
        let dPressed = false;
        let aPressed = false;
        let spacePressed = false;

        // keyUp og Down kontrollere om knappen bliver trykket eller ej
        // Tank 1 controls

    function keyDownHandler(e) {
            if (e.keyCode == 38)
        {
            upPressed = true;
        }
        if (e.keyCode == 40)
        {
            downPressed = true;
        }
        if (e.keyCode == 37)
        {
            leftPressed = true;
        }
        if (e.keyCode == 39)
        {
            rightPressed = true;
        }
        if (e.keyCode == 32)
        {
            spacePressed = true;
        }


        // Tank 2 controls
       
        if (e.keyCode == 87)
        {
            wPressed = true;
        }
        if (e.keyCode == 83)
        {
            sPressed = true;
        }
        if (e.keyCode == 65)
        {
            aPressed = true;
        }
        if (e.keyCode == 68)
        {
            dPressed = true;
        }
        if (e.keyCode == 96)
        {
            zeroPressed = true;
        }
    }
        
    function keyUpHandler(e) {

        if (e.keyCode == 38)
        {
            upPressed = false;
        }
        if (e.keyCode == 40)
        {
            downPressed = false;
        }
        if (e.keyCode == 37)
        {
            leftPressed = false;
        }
        if (e.keyCode == 39)
        {
            rightPressed = false;
        }
        if (e.keyCode == 32)
        {
            spacePressed = false;
        }


        // Tank 2 controls
       
        if (e.keyCode == 87)
        {
            wPressed = false;
        }
        if (e.keyCode == 83)
        {
            sPressed = false;
        }
        if (e.keyCode == 65)
        {
            aPressed = false;
        }
        if (e.keyCode == 68)
        {
            dPressed = false;
        }
        if (e.keyCode == 96)
        {
            zeroPressed = false;
        }
    }
   
        // For rotere img

    function drawImageRot(img, x, y, width, height, deg)
    {
        let rad = deg * Math.PI / 180;
        ctx.translate( x + width / 2, y + height / 2);
        ctx.rotate(rad);
        ctx.drawImage(img, width / 2 * -1, height / 2 * -1, width, height);
        ctx.rotate(rad * -1);
        ctx.translate(x + width / 2 * -1, y + height / 2 * -1);
    }

    let player1 = new Player(50, 100, 0, 40, 30);
    let player2 = new Player(300, 300, 0, 40, 30);


    function controls() 
    {
        // Tank1
        if (leftPressed)
        {
            player1.rot -= 1;
        }
        if (rightPressed) 
        {
            player1.rot += 1;
        }
        if (upPressed)
        {
            player1.x += Math.cos(player1.rot * Math.PI / 180);
            player1.y += Math.sin(player1.rot * Math.PI / 180);
        }
        if (downPressed)
        {
            player1.x -= Math.cos(player1.rot * Math.PI / 180);
            player1.y -= Math.sin(player1.rot * Math.PI / 180);
        }

        // Tank2
        if (aPressed)
        {
            player2.rot -= 1;
        }
        if (dPressed) 
        {
            player2.rot += 1;
        }
        if (wPressed)
        {
            player2.x += Math.cos(player2.rot * Math.PI / 180);
            player2.y += Math.sin(player2.rot * Math.PI / 180);
        }
        if (sPressed)
        {
            player2.x -= Math.cos(player2.rot * Math.PI / 180);
            player2.y -= Math.sin(player2.rot * Math.PI / 180);
        }
    }
    
    // Playerframework

    function Player(x, y, rot, w, h) 
    {
        this.x = x;
        this.y = y;
        this.rot = rot;
        this.w = w;
        this.h = h;
        this.canFire = true;
        this.score = 0;
        this.hasBeenHit = false;
    }

    function draw() 
    {
        ctx.clearRect (0, 0, myCanvas.width, myCanvas.height);
        controls();

        if (!player1.hasBeenHit)
    {
        drawImageRot(tank1, player1.x, player1.y, player1.w, player1.h, player1.rot);
    }
        if (!player2.hasBeenHit)
    {
        drawImageRot(tank2, player2.x, player2.y, player2.w, player2.h, player2.rot);
    }
    

    }

    setInterval (draw, 10);

    

    </script>
</body>

Why can ClientRequest.setTimeout take much longer than the provided duration?

In the following nodejs program, I am patching the dns.lookup function in order to investigate how a slow DNS lookup would behave when a timeout is set on a request. The DNS lookup will (appear to) take 10 seconds, so I expect my 1000ms timeout on the request to be triggered.

My timeout on the request is indeed triggered, but after around 5000ms instead of 1000ms as expected. Why could this be?

const dns = require('dns');
const http = require('http');
const lookup = dns.lookup;

const now = Date.now();

// I'm trying to simulate a slow DNS lookup here, to test how it behaves with the various nodejs
// timeout options.
dns.lookup = function patchedLookup(...args) {
  setTimeout(() => {
    lookup.apply(this, args);
  }, 10_000);
};

const req = http.request('http://joebarnett.xyz');

// The slow DNS lookup should cause this to timeout after 1000ms.
req.setTimeout(1000, () => {
  // Logs something like "timed out after 5007ms" - why not after 1000ms?
  console.error(`timed out after ${Date.now() - now}ms`);
  req.abort();
});

req.on('error', (err) => {
  console.error(`error after ${Date.now() - now}ms: ${err}`);
});

req.end();

Using Markdown-it HighlightJS incorrect rendering of block codes

I’m trying to learn about rendering Markdown inside HTML, and using Markdown-it and Highlight.js I use that code:

template.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <!-- Required meta tags -->
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

        <link rel="stylesheet" href="css/bootstrap.min.css">
        <link rel="stylesheet" href="/js/styles/dark.min.css" />

        <title>Example Markdown-it</title>
    </head>
    <body>
        <div class="container">

        <div class="markdown">
        ## Example Markdown Content

        Example list:

        *   One

        *   Two

        *   Three

        A code segment:

        ```js
        window.onload = function() {
            var md = window.markdownit();
            var div = document.getElementsByClassName('markdown');
            for (var i = 0; i < div.length; i++) {
                var content = div[i].innerHTML;
                document.getElementsByClassName('markdown')[i].innerHTML = md.render(content);
            }
        }
        ```

        And now a C snippet:

        ```c
        #include <stdio.h>
        #include <other.h>

        int main() {
            printf("hello world!n");
            int x = 100;
            if (x > 50)
                printf("x is greater than 50n");
            return 0;
        }
        ```
        </div> <!-- end of markdown content -->

    </div>

    <script src="js/markdown-it.min.js"></script>
    <script src="js/highlight.min.js"></script>

    <script src="js/test.js"></script>
    </body>
</html>

and that is the Javascript:

  window.onload = function() {
    
    const md = markdownit({
      highlight: function (str, lang) {
        if (lang && hljs.getLanguage(lang)) {
          try {
            return '<pre><code class="hljs">' +
                   hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
                   '</code></pre>';
          } catch (__) {}
        }

        return '<pre><code class="hljs">' + md.utils.escapeHtml(str) + '</code></pre>';
      }
    });

    var div = document.getElementsByClassName('markdown');
    for (var i = 0; i < div.length; i++) {
        var content = div[i].innerHTML;
        document.getElementsByClassName('markdown')[i].innerHTML =  md.render(content);
    }
}

the problem is when this render the Markdown produce this (incorrect) output:

![](how output render)

Is escaping < and > inside the code block although thats not I want, do that without Highlight.js, clearly is Markdown-it that produce the problem, and why auto-complete (incorrectly recognition) the #includes inside the block code?, I don’t know much Javascript
beyond the basic, but I don’t think the error is in this code, problably set any other option in Markdown-it to avoid this behavior?

The code used is from https://github.com/markdown-it/markdown-it?tab=readme-ov-file#syntax-highlighting:

const md = markdownit({
      highlight: function (str, lang) {
        if (lang && hljs.getLanguage(lang)) {
          try {
            return '<pre><code class="hljs">' +
                   hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
                   '</code></pre>';
          } catch (__) {}
        }

        return '<pre><code class="hljs">' + md.utils.escapeHtml(str) + '</code></pre>';
      }
    });

And from How do I use markdown-it without node.js?:

    var div = document.getElementsByClassName('markdown');
    for (var i = 0; i < div.length; i++) {
        var content = div[i].innerHTML;
        document.getElementsByClassName('markdown')[i].innerHTML = md.render(content);
    }

Detect when a new Web Animation API is created

Is it possible to detect when a new Web Animation API is created? Something like an event-listener on the creation of Web Animation.

I guess that by pooling document.getAnimations() every few ms it should be possible, but I’d prefer a more resilient approach. When it is a CSS animations, I can use document.addEventListener("transitionstart", () => {…}) but I’m looking for something that works for all animations.

<!doctype html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <style>
      #animatedElt {
          /* Any change will take 1s to complete */
          transition: all 5000ms;
      }
      moved {
          transform: translate(100px, 100px);
      }
    </style>
  </head>
  <body>
    <main id="screenshotTarget" style="background-color: red; width: 1000px; height: 800px;">
      This element will be paused in the middle of the transition. Can I then move it to a <b>precise</b> point it time, like move forward by 0.5s? 
      <div id="animatedElt" style="background-color: blue; width: 100px; height: 100px;" class="fadeMeMoveMeAnim">
      </div>
    </main>
    <script>
      document.addEventListener("transitionstart", () => {
        console.log("a transition starts. I want the same think but not specific to transitions");
      });
      setTimeout(() => {
        document.getElementById("animatedElt").style.transform = "translate(100px, 100px)";
        document.getElementById("animatedElt").style.backgroundColor = "green";
        setTimeout(() => {
          document.getAnimations().map(anim => {
            anim.pause();
          });
          setTimeout(() => {
            document.getAnimations().map(x => {
              x.currentTime += 500;
            })
          }
                   , 1000);
        }, 2000);
      }, 0)
    </script>
  </body>
</html>

Calculate the height of the visible part of a flex item (regardless of its content)

I’m trying to zoom children of a container to make it fit the container’s height. The container is a flexbox item and may share the available space with other elements, i.e. a heading.

My problem is that I don’t know how to examine the visible height of a flex item, minus the height of siblings:

screenshot

I have created a codepen example here:

https://codepen.io/jmuheim/pen/GgRBMbZ

In the end, all cards should have the same height (so the first two cards’ contents need to shrink even more).

I played around with scrollHeight, clientHeight, offsetHeight, getBoundingClientRect().height, but didn’t succeed.

tracing settimeout warnings in angular with zone.js

I wrote a library for a third party component provider, which basically adds some new features to one of it’s components. Everything was fine, performance was fine, all OK. All was written with the default change detection mechanism and with use of zone.js.

Now, I updated both Angular and the third party component to the latest, and I get console warnings like [Violation] 'setTimeout' handler took 537ms and [Violation] Forced reflow while executing JavaScript took 222ms. And the page becomes noticeable slow. Before the updating I also got this kind of warnings, but the delays were like 10 to 50 ms.

Before or after updating, I didn’t add any new code to the library. The only changes were the updating to the latest versions. I guess, it must be some internal changes in the third party component.

The question is, how can I trace this warnings? I’m more interested in the setTimeout warning, but also the forced reflow could be interesting.

Thansk.

I’m Having Trouble with a Google Apps Script Array to Iterate Thru Rows

So, I’ve been teaching myself JavaScript to use with Google Sheets to make little programs to improve my life for several months now (side projects). I’m working on a randomizing Dinner Picker right now, but I’ve been stuck on this looping array for weeks now, and scouring Google and forums hasn’t yielded results yet.

This is where I am stuck. The array works with the logger portion, but nothing else. I cannot figure out what I need to replace the ??? with to get the values of certain cells in the rows, so I can check against them, and add the values of one cell into another.

// A looping function that goes down the rows, starting with row 2, and adds +1 to +5 depending on the priority of the meal.
// Stops and continues the main script once a priority is null. 
function iterateThroughRows() {
  var activePage = SpreadsheetApp.getActive().getSheetByName("Meal List");
  var data = activePage.getDataRange().getValues();

  data.forEach(function (row) { 
    Logger.log(row);
    var mealPriority = ???(row, 2).getValue(); // MEAL ( B / 2 )
    var mealSkip = ???(row, 3).getValue(); // TEMP_SKIP ( C / 3 )
    var mealPickedChance = ???(row, 4).getValue(); // PICKED_CHANCE ( D / 4 )

    console.log("Logger Row"); // DEBUGGING LOGS
    console.log("mealPriority = " + mealPriority); // DEBUGGING LOGS
    console.log("mealSkip = " + mealSkip); // DEBUGGING LOGS
    console.log("mealPickedChance = " + mealPickedChance); // DEBUGGING LOGS

    // if mealSkip == TRUE (set to FALSE and skip to the next row)
    // else mealPickedChance.setValue(mealPickedChance+mealPriority);
  });
}

I am trying to capture the values of 3 cells in each row.
One value is a bool, if it is set to TRUE, I want to change it to FALSE and them skip to the next row.
If that value is FALSE, I want to take the int value of one cell and add it into another.

(Example, if mealPriority = 5 and mealPickedChance = 4, then mealPickedChance would get updated to = 9.)
Rinse and repeat until the array finishes all rows.

So far I have tried:

  • getRange

  • getRow

  • getColumn

  • getCell

  • row

  • column

I’m pretty sure I can figure out the if and else statement and how to add the value from one cell to another. I’m just stuck on how to capture those values in the first place. Any help in the right direction would be greatly appreciated.

Regular expressions loop code, how Backtracking works?

Following the brilliant presentation of “Damian Conway” on how regular expression work, I have taken his pseudo-code and used my own example to try to understand it.

(see for reference the following 42:56) on
https://www.infoq.com/presentations/regex/

He conceptualises the 0 or more loop /X*/ as the following pseudocode

maxreps = Infinity;
loop {
    repcount = 0;
    for 1..maxreps {
        str[matchpos] == 'X' or exit for;
        matchpos++;
        repcount++;
    }
    try {
        // the rest of regex's commands here
    }
    catch Backtracking {
        maxreps = repcount - 1;
        maxreps >= 0 or throw Backtracking;
        next loop;
    }
    finally {
        exit loop;
    }
}

For that I have taken my example /X*i/ on the string deXXXixia ho
Transcribing it to Javascript

const Backtracking = new Error("Backtracking exception");

function executeRegex(str, startPos) {
    var returnState = false;


    matchPos = startPos
    while( matchPos <= str.length ) {

        maxReps = Infinity;
        while(true) {
            var repCount = 0;
            debugger;

            for (let j = 0; j < maxReps; j++ ) {
                if ( !(str[matchPos] == 'X') ) break ;
                matchPos++ ;
                repCount ++;
            } try {
                    if ( !(str[matchPos] == 'i') ) throw Backtracking ;
                    matchPos++ ;
                    returnState = true;
            } catch (e) {
                if (! (e == Backtracking)) throw e;            // Only catch Backtracking errors
                maxReps = repCount - 1;
                continue;
            } finally {
                matchPos++;
                break;
            }
        }
    }

    return returnState;                                       // Exhausting the whole string
}

console.log(executeRegex('deXXXoxia ho', 0));
//console.log(executeRegex('deXXXixia ho', 0));

Running the Node debugger with the following variables to watch

watch('startPos'); watch('matchPos'); watch('str[matchPos]'); watch('repCount'); watch('returnState')

I have an issue with the finally incrementing matchPos. Even if there is no match this will get incremented.
I know Damian didn’t add that matchPos++ after the finnally , but if I don’t add it it simply dont process the string if there is no initial Match.

Reimplementing Underscore’s _.reduce function by using the functionality of the _.each function

I’m working on problem for an upcoming bootcamp. Here’s where I’m at so far:

_.reduce = function (collection, iteratee, accumulator, context) {
if (arguments[2] !== undefined) {
    _.each(collection, function (element, key) {
      accumulator = iteratee.call(context, accumulator, element, key, collection);
    });
  } else {
    _.each(collection, function (element, key) {
      if (key === ???) {
        accumulator = collection[key];
      } else {
        accumulator = iteratee.call(context, accumulator, element, key, collection);
      }
    });
  }
  return accumulator;
};

I could write this longhand (iterating through objects || arrays manually), without using _.each. But a) that would spoil the fun and b) I get the feeling it’s possible as above. The issue is, in the instance that the accumulator argument isn’t provided as an argument, I need to iterate from the second value of the object || array, using the first value as the accumulator. But in writing the logic for this, I’m stuck on how to identify this first value, given it could be either an object property, or an array element. Hence the ??? in line 8. Hints welcome.

Cheers.

Why is my React State element being overwritten instead of replaced?

Ok I’m trying out something unique. I have a component where the state of the component is an element itself (not a simple variable or array). And this state element is directly being returned.

I realize this is not in line with the general principles of React but there is a reason why I’ve made it this way.

My component is a network of different SVG paths. Each path has a ‘d’ attribute which is undergoing changes. The state of the compoenent is an element which looks something like this:


<g className='PathNetwork'>
  <g>
    <Path d="pathCoordinates">
    <Path d="pathCoordinates">
    <Path d="pathCoordinates">
  </g>

  <g>
    <Path d="pathCoordinates">
    <Path d="pathCoordinates">
    <Path d="pathCoordinates">
  </g>
</g>

This “Pathnetwork” is the state of the component. And so when I want to update it, I end up creating a new structure similar to the one above with new “pathCoordinates” which will be assigned to the ‘d’ property. And once that new structure is created, I will insert it into the setter of the component’s state.

It seems to be working initially, but I am finding that the path network on my page is being over-drawn….the paths are being drawn, and then drawn on top of that….the paths are literally getting brighter with each second.

I’m wondering if I am updating the state correctly. Here is the relevant code. As you can see, I am procedurally creating new path objects, and inserting them into new elements, and finally when I’m doing I am trying to replace the data in the existing state with that new element. Am I doing it correctly? :

 const [pathNetwork, set_pathNetwork] = useState(createPathNetwork(props.coordinatesArr));

 //PathNetwork updating hook
    useEffect(()=>{
        if ( props.coordinatesArr.length >=1){
            updateDPropOfPaths( props.coordinatesArr) );
        }
    }, [ props.coordinatesArr]);


return(
        <g>
           {
           arrOfRayPaths != null ?
            arrOfRayPaths

            :null
           }          
         </g>
        )

function updateDPropOfPaths(freshCoordsArr){
   let compositePathsArr = pathNetwork.props.children;
   let finalStruct = React.createElement('g', {}, []);

   for (let x = 0; x < compositePathsArr .length; x++){
      let currCompRay = compositePathsArr[x];

       for(let i=0; i<freshCoordsArr.length; i++){ 
          let currTierStruct = React.createElement('g', {}, []);
          let originalIndividualPathsArr = currCompRay.props.children; 
           
           for(let c=0; c<3; c++ ){
              let currPath = originalIndividualPathsArr[c];
              let freshPath = createFreshPath(currPath, freshCoordsArr[i]);
              currTierStruct.props.children.push(freshPath);
           }
       finalStruct.props.children.push(currTierStruct);
        }
    }

      //Replacing the existing state structure with the newly created <g> element
      set_pathNetwork(null);
      set_pathNetwork(finalStruct);
 
}

Cropping text in animation by text height

I have a block with the text TEXT TEST. Here the word text should change with the help of animation. But I have a problem that during animation the text TEST goes beyond the height of the text TEXT, which should not happen. And I can’t make it so that TEST is cut off

This is how it works for me now

enter image description here

And it should be something like this

enter image description here

Help me please

$(document).ready(function() {
    let currentAnimation = true;

    function animateText() {
        if (currentAnimation) {
            $(".red").css({
                transform: "translateY(-100%)",
                opacity: 0
            });

            $(".blue").css({
                transform: "translateY(0)",
                opacity: 1
            });
        } else {
            $(".red").css({
                transform: "translateY(0)",
                opacity: 1
            });

            $(".blue").css({
                transform: "translateY(100%)",
                opacity: 0
            });
        }

        currentAnimation = !currentAnimation;

        setTimeout(() => {
            requestAnimationFrame(animateText);
        }, 2000);
    }

    requestAnimationFrame(animateText);
});
body {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background-color: #111;
  color: white;
  font-size: 48px;
  font-family: Arial, sans-serif;
}

.title {
  display: inline-block;
  overflow: hidden;
}

.red, .blue {
  position: absolute;
  display: inline-block;
  transition: transform 1s ease, opacity 1s ease;
}

.red {
  color: red;
}

.blue {
  color: blue;
  transform: translateY(100%);
  opacity: 0;
}
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>

<div class="title">TEXT<span class="red">TEST</span><span class="blue">TEST</span></div>