How can I hide the parent component on click of a child component?

I am having trouble figuring out a solution to hiding my parent element when a button in a child element is clicked.

What I have is basically a list of checkboxes and each checkbox has a filter button in it. On click of this filter button, it should remove the entire list of checkboxes (parent) and show a filter menu instead. However, the way I have it, since it’s mapping through each, all of the filter menus appear instead of just the one I clicked on.

For example imagine the following parent component which is a list of checkboxes.

enter image description here

And if you click on one of the right icons then just that rows filter form should pop up, not all 3 items filter forms.

enter image description here

Here is my code:

export default function CheckboxList({ data }: Props) {
  const [showFilterContent, setShowFilterContent] = useState(false);
  return data.map((item) => { // because if this it renders all 3 MenuFilterForm 
    return (
      <ListMenu
        data={item}
        showFilterContent={showFilterContent}
        setShowFilterContent={setShowFilterContent}
      />
    );
  });
}


export default function ListMenu({
  data,
  showFilterContent,
  setShowFilterContent,
}: Props) {
  const [checked, setChecked] = React.useState([0]);
  const { setItem, getItem } = useLocalStorage("datasets");
  const activeDatasets = getItem();

  const handleClick = () => {
    setShowFilterContent(!showFilterContent);
  };

  const handleToggle = (value: number) => () => {
    const currentIndex = checked.indexOf(value);
    const newChecked = [...checked];

    if (currentIndex === -1) {
      newChecked.push(value);
    } else {
      newChecked.splice(currentIndex, 1);
    }

    setChecked(newChecked);
    setItem("people", newChecked);
  };

  return showFilterContent ? (
    <MenuFilterForm data={data} handleClick={handleClick} />
  ) : (
    <ListItems
      data={data}
      handleClick={handleClick}
      handleToggle={handleToggle}
      checked={checked}
      activeDatasets={activeDatasets}
    />
  );
}

My shopping cart vanishes when product is added, coupons not automatically adding to checkout, and cart updates clear cart

I need to fix this and I’m going crazy trying to make it work. I’m using php and js for a spin the wheel function. the objective of the spin the wheel is as follows.
user spins the wheel at checkout, whatever they land on gets added to the checkout as well as a coupon to make that product 100% off. Not the whole cart just that item. 3 of the four items on the spin the wheel are actual products while the 4th reward is a 20% off coupon.

Wheel is spinning and looks good the issue is the actual functions of adding to cart.

The code I have right now is bugging out the menu cart.
When I open cart on inital page load It’s blank (theres supposed to be a no items in cart message). but when I add an item to cart it shows and when I remove it shows the message properly.
when I reload cart or checkout the items disappear
coupons are not automatically being added to checkout.
only way I can get the items in checkout is on another page not checkout page. If i reload the checkout the initial items are either replaced by the spin the wheel reward (still cant get discount to be applied) or cart ends up empty.

php is in functions.php

// Check if a coupon exists
function coupon_exists($coupon_code) {
    global $wpdb;
    $sql = $wpdb->prepare("SELECT post_name FROM $wpdb->posts WHERE post_type = 'shop_coupon' AND post_name = %s", $coupon_code);
    $coupon_codes = $wpdb->get_results($sql);
    return count($coupon_codes) > 0;
}

// Generate a coupon if it doesn't exist
function generate_coupon($coupon_code, $discount_type = 'percent', $amount = '20', $expires_in_days = 1) {
    $date_expires = date('Y-m-d', strtotime("+$expires_in_days days"));
    $coupon = new WC_Coupon();
    $coupon->set_code($coupon_code);
    $coupon->set_discount_type($discount_type);
    $coupon->set_amount($amount);
    $coupon->set_date_expires($date_expires);
    $coupon->save();
    return $coupon_code;
}

// Apply coupon automatically to the cart
function apply_spin_coupons_to_cart($cart) {
    if (is_admin() && !defined('DOING_AJAX')) return;

    if (isset($_SESSION['spin_coupons']) && !empty($_SESSION['spin_coupons'])) {
        foreach ($_SESSION['spin_coupons'] as $coupon_code) {
            $coupon_code = sanitize_text_field($coupon_code);

            if (!coupon_exists($coupon_code)) {
                generate_coupon($coupon_code); // Ensure the coupon exists
            }

            // Apply the coupon to the cart
            if (!in_array($coupon_code, $cart->get_applied_coupons())) {
                $cart->apply_coupon($coupon_code);
            }
        }
    }
}
add_action('woocommerce_cart_updated', 'apply_spin_coupons_to_cart', 20);

// Set the coupon codes in the session
function set_spin_coupons() {
    if (isset($_POST['coupon_codes']) && is_array($_POST['coupon_codes'])) {
        session_start();
        $coupon_codes = array_map('sanitize_text_field', $_POST['coupon_codes']);
        $_SESSION['spin_coupons'] = $coupon_codes; // Store multiple coupons in session
        wp_send_json_success(['message' => 'Coupon codes set successfully']);
    } else {
        wp_send_json_error(['message' => 'No coupon codes provided']);
    }
}
add_action('wp_ajax_set_spin_coupons', 'set_spin_coupons');
add_action('wp_ajax_nopriv_set_spin_coupons', 'set_spin_coupons');

// Debugging: Display session data in the footer
add_action('wp_footer', function () {
    if (session_status() === PHP_SESSION_ACTIVE) {
        echo '<pre>Session Data: ' . print_r($_SESSION, true) . '</pre>';
    }
});

// Start PHP session
function ensure_php_session_start() {
    if (session_status() === PHP_SESSION_NONE) {
        session_start();
    }
}
add_action('init', 'ensure_php_session_start', 1);




<script>
       $(document).ready(function () {
    const prizes = [
        { angle: 22.5, prize: "20% Off", type: "discount", code: "spin20" },
        { angle: 67.5, prize: "Basketball", type: "product", productId: 14256, coupon: "basketball100" },
        { angle: 112.5, prize: "Tote Bag", type: "product", productId: 14257, coupon: "totebag100" },
        { angle: 157.5, prize: "Mouse Pad", type: "product", productId: 4788, coupon: "mouse100" },
    ];

    $("#spin-btn").click(function () {
        const randomDegrees = Math.floor(Math.random() * 360) + 3600;
        $("#wheel").css({
            "transition": "transform 3s ease-out",
            "transform": `rotate(${randomDegrees}deg)`
        });

        setTimeout(() => {
            const finalAngle = randomDegrees % 360;
            const prizeIndex = Math.floor(finalAngle / 45);
            const prize = prizes[prizeIndex];
            const coupons = [];

            if (prize.type === "discount") {
                coupons.push(prize.code);
            }

            if (prize.type === "product") {
                $.post("/?wc-ajax=add_to_cart", { product_id: prize.productId, quantity: 1 }, function () {
                    alert(`Congratulations! You've won a ${prize.prize}. It has been added to your cart.`);
                    $(document.body).trigger("wc_fragment_refresh");
                });

                coupons.push(prize.coupon);
            }

            if (coupons.length > 0) {
                $.post("/wp-admin/admin-ajax.php", {
                    action: "set_spin_coupons",
                    coupon_codes: coupons
                }, function (response) {
                    if (response.success) {
                        alert("Your coupon(s) have been applied.");
                        $(document.body).trigger("wc_fragment_refresh");
                    }
                });
            }
        }, 3000);
    });

    // Ensure cart fragments refresh
    $(document.body).on("added_to_cart", function () {
        $(document.body).trigger("wc_fragment_refresh");
    });
});

    </script>

html and js in html widget

the objective of the spin the wheel is as follows.
user spins the wheel at checkout, whatever they land on gets added to the checkout as well as a coupon to make that product 100% off. Not the whole cart just that item. 3 of the four items on the spin the wheel are actual products while the 4th reward is a 20% off coupon.

Why does this Wix site go to a blank page when refreshed, or when accessed directly using the URL?

Question:
https://www.roofaesthetics.com/book

Does anyone know why this page is blank when you go directly to that URL? But when you access that page by clicking on the menu link (like from the home page), it loads fine. But when you refresh that page, it goes blank.

If it is related to having javascript errors, then could you please help me figure out how to change that? I am not good at javascript (sorry).

Product:
Wix Editor

What are you trying to achieve:
I would like the page to load properly, not go blank.

Additional information:
This is for a client’s site. I am not very good at coding, so please bear with me. I appreciate your patience with me.

What have you already tried:
Searched Google and Wix Studio Forum

I’ve posted on reddit. I was told that the page has lots of javascript errors.

I’ve deleted the page and made a new page called /book2, which works fine. However, the client wants it to be /book. Even when I duplicate /book2 and call it /book (after deleting the original /book page), the problem comes back.

The page works fine when I change the slug to anything but /book.

I deleted any redirects on the redirect manager.

Characters appearing simultaneously in React components

I’m making a game about pokemon in React and there’s a component called Announcer which announces what is happening in it.

I made the letters appear one by one just like old games and I wanted that this behavior would happen one message at a time, but React is rendering all messages simultaneously:

https://i.sstatic.net/IYLLcYTW.gif

Here’s the code of the Announcer and AnnouncerMessage

import AnnouncerMessage from "./AnnouncerMessage";

const Announcer = ({ messages }) => {
  return (
    <div className="announcer">
      <div className="announcerMessages">
        {messages.map((msg) => (
          <AnnouncerMessage message={msg} />
        ))}
      </div>
    </div>
  );
};

export default Announcer;

import { useState, useEffect, useRef } from "react";

const AnnouncerMessage = ({ message }) => {
  const [placeholder, setPlaceholder] = useState("");

  const index = useRef(1);

  useEffect(() => {
    const tick = () => {
      setPlaceholder(message.slice(0, index.current));
      index.current++;
    };
    if (index.current <= message.length) {
      setTimeout(tick, 25);
    }
  }, [placeholder]);

  return <p>{placeholder}</p>;
};

export default AnnouncerMessage;

Form rules and validation not working, only HTML is working

This is my first time using JQuery, and im really struggling with it, my form validation/rules arent working at all. And im just curious as to why? if anyone could help.

I’m currently trying to make the forms first name and last name need a minimum of 2 letters and have email validation. but i dont know why none of it is appearing? heres my js and form

                <form id="contactForm">
                    <label for="fname">First Name</label>
                    <input type="text" id="fname" name="firstname" placeholder="First Name..." required>
                
                    <label for="lname">Last Name</label>
                    <input type="text" id="lname" name="lastname" placeholder="Last Name..." required>
                
                    <label for="email">Email</label>
                    <input type="email" id="email" name="email" placeholder="[email protected]..." required>
                
                    <label for="subject">Query</label>
                    <textarea name="subject" id="subject" cols="30" rows="10" required></textarea>
                
                    <input type="submit" value="Submit">
                </form>
    <script src="https://cdn.jsdelivr.net/jquery.validation/1.19.5/jquery.validate.min.js"></script>
    <script src="js/script.js"></script> 
    <script>
        AOS.init();
    </script>
    <script>
        jQuery(document).ready(function () {
            jQuery("#contactForm").validate({
                rules: {
                    firstname: "required",
                    lastname: "required",

                    email: { 
                        required: true, 
                        email: true 
                    },
                    subject: { 
                        required: true,
                        minlength: 10 
                    }
                },
                messages: {
                    firstname: "Please enter your firstname",
                    lastname: "Please enter your lastname",
                    email: {
                        required: "Please enter your email address",
                        email: "Please enter a valid email address"
                    },
                    subject: {
                        required: "Please enter your query",
                        minlength: "Your query must be at least 10 characters long"
                    }
                },
                submitHandler: function (form) {
                    form.submit();
                }
                
            });
        });
    </script>

Create a new object when it already exist an object (JS) [closed]

JAVASCRIPT. If i need to create a new object to get a spesific fahrenheit temperature , how do I do it?

i already has an object.

let weather = {
        town: {
          temp: 10,
          humidity: 80,
        },
 town: {
          temp: 10,
          humidity: 80,
        },
 town: {
          temp: 10,
          humidity: 80,
        },
}

In my console log to a new ${something} , it is written “object not redefined” ?

Where or how do i have to create new object? Is it like ann arrays, like this:

let city = [
                   {
                     name: "something",
                     something: 30,
                   },
                      
                 ];

?

or what?

I am new to coding. I try to understand and learn.

I try to make spesific number to an alert message with a new object which is not in my object already has.

${something}

How to add an ‘Enter’ key event listener to an input bar that I’ve grabbed with querySelector?

Basically, I’m following this exercise
https://www.youtube.com/watch?v=EerdGm-ehJQ&t=50183s
14n, part 2.

My page looks like this:I’m focusing on the input bar with the ‘3’ inside it

When I press ‘Enter’ I want to run some code (the console.log is just a test), but I can’t even get Javascript to recognise the ‘event.key’ part that I’m using to select ‘Enter’

Here’s what I have, and ‘event’ is crossed out and is ‘deprecated’ (idk what that means)

document.querySelectorAll('.quantity-input')
  .forEach((inputBar) => {
    inputBar.addEventListener('keydown', () => {
      if (event.key === enter) {
        console.log('hello')
      }
    })
  }) 

The ‘.quantity-input’ is the class name of the input bar where you type the quantity.

To me, the code above does this:

  1. Get every input element on the page
  2. For each of those input elements, make them look out for key presses on the keyboard.
  3. If one of those keypresses is equal to ‘Enter’.
  4. Run some code

But the ‘event’ in ‘event.key’ is crossed out.

I’m sorry I couldn’t word this question any better, the project is quite big and it’s hard to know what relevant bits of code to include.

Btw, when I click enter, this is what the page will look like (the exact same as when I click save)
The update button comes back, ready to be pressed again

How to properly dynamically load a webpack bundle created from Webpack 5 CacheGroups?

I have this webpack cacheGroup optimization:

optimization: {
                splitChunks: {
                    chunks: 'all', // Apply splitting to all types of chunks
                    minChunks: 2, // Minimum number of chunks that must share a module before splitting
                    maxAsyncRequests: 10, // Maximum number of parallel requests when loading asynchronously
                    maxInitialRequests: 10, // Maximum number of parallel requests at an entry point
                    cacheGroups: {
                        main: {
                            test: /[\/]public[\/]js[\/](utils|middleware)[\/]/,
                            name: 'main',
                            priority: 3,
                            enforce: true,
                            reuseExistingChunk: true
                        },

                    }
                },
              
            }

The output path for this writes to public/dist/main.bundle.js.

What I want to be able to do is at a particular point in my app when a reload happens I want to be able to dynamically load in this bundle. The bundle paths are written to a webpack_paths json file and I am trying something like this:

const webpackPaths = require('../dist/webpack_paths.json');

const loadBundle = async (bundleName) => {
    const bundlePath = webpackPaths[bundleName]; //Points to the path public/dist/main.bundle.js

    if (!bundlePath) {
        throw new Error(`Bundle path for ${bundleName} not found in webpack paths json file.`);
    }

    try {
        const imported = await import(/* webpackFetchPriority: "high" */ bundlePath);

        return imported;
    } catch (error) {
        console.error(`Failed to import bundle: ${bundleName} from path: ${bundlePath}`, error);
        throw error;
    }
};

const loadMainBundle = () => loadBundle('main.js'); // Resolves to correct path in json file.

export {
    loadMainBundle,
};

It always results in an error even though the file exists at this exact path in my repo:

code
: 
"MODULE_NOT_FOUND"
message
: 
"Cannot find module '/public/dist/main.bundle.js'"

What is the correct way to dynamically load in my webpack bundle so I can load it on demand where I need it?

New Tab Opens Login Page Even When Already Logged In (Node-RED Session Issue)

I’m working on a Node-RED application, and I’m encountering an issue with session handling when opening a new tab in the same browser.

Here’s what’s happening:

I log in to http://localhost:1880/api/login in one tab, which successfully creates a session and sets a session cookie.

When I open a new tab and navigate to http://localhost:1880/api/login, it shows the login page again instead of redirecting to the dashboard or maintaining the session.

If I log in again from the new tab, it creates a new session. This new session overrides the session cookie in the browser, even though the database has multiple sessions for the same user.

When I open a new tab, the session should persist, and I should be redirected to the dashboard if already logged in.

How to apply anime.js keyframes in A-Frame

In this example, we can see how keyframes work in anime.js. Inspired by this answer and A-Frame doc, I tried to apply it with the following code without success:

/* global AFRAME */

AFRAME.registerComponent('animation-test', {
    schema: {

    },

    init: function () {
        this.el.setAttribute('animation__001', {
            'property': 'position',
            // 'to': { x: -0.47, y: 1.73, z: -0.3 },
            'keyframes': [
                { x: -0.47, y: 1.63, z: -0.5 },
                { x: -0.47, y: 1.73, z: -0.5 },
                { x: -0.47, y: 1.73, z: -0.3 },
            ],
            'duration': 4000,
            'startEvents': 'startanim001'
        });
        this.el.emit('startanim001', null, false);
    },

I expected the animation to take 4 seconds, and in that time to move the object to different coordinates.

Or is there another way to use keyframes?
Thank you in advance.

Using Webpack Module Federation with “react”: “^18.3.1”, host and client face ScriptExternalLoadError:

While loading the host application I’m facing issue with the webpack module federation with the error “Initialization of sharing external failed: ScriptExternalLoadError: Loading script failed.”.

Here is my web pack configuration.

Host

//host-app/webpack.config.js
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const { dependencies } = require("./package.json");
 
module.exports = {
 entry: "./src/index",
 mode: "development",
 optimization: {
    // runtimeChunk: 'single',
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendor: {
          test: /[\/]node_modules[\/]/,
          name: module => (module.context.match(/[\/]node_modules[\/](.*?)([\/]|$)/) || [])[1]
        }
      }
    }
  },
 devServer: {
   port: 3000, 
   open: true,
   hot: true,
   historyApiFallback: true,
   headers: {
    "Access-Control-Allow-Origin": "*",
  },
 },
 module: {
   rules: [
     {
       test: /.(js|jsx)?$/,
       exclude: /node_modules/,
       use: [
         {
           loader: "babel-loader",
           options: {
             presets: ["@babel/preset-env", "@babel/preset-react"],
           },
         },
       ],
     },
     {
       test: /.css$/i,
       use: ["style-loader", "css-loader"],
     },
   ],
 },
 plugins: [
   new HtmlWebpackPlugin({
     template: "./public/index.html",
     favicon: "./public/favicon.ico",
     manifest: "./public/manifest.json",
   }),
   new ModuleFederationPlugin({
    name: "Remote CoreShell Client",
    remotes: {
      // TODO replace the url with base url 
      Remote: `Remote@http://localhost:3001/moduleEntry.js`,
    },  
    shared: {
      ...dependencies,
      react: {
        singleton: true,
        eager: true,
        requiredVersion: dependencies["react"],
      },
      "react-dom": {
        singleton: true,
        eager: true,
        requiredVersion: dependencies["react-dom"],
      },
    },
  }),
 ],
 resolve: {
   extensions: [".js", ".jsx"],
 },
 target: "web",
}

Remote

const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
const { ModuleFederationPlugin } = require('webpack').container;
const TerserPlugin = require('terser-webpack-plugin');
const { dependencies } = require("./package.json");
 
module.exports = {
 entry: "./src/index.js",
 mode: "production",
 devServer: {
   static: {
     directory: path.join(__dirname, "dist"),
   },
   port: 3001,
   historyApiFallback: true,
  //  watchFiles: ["src/**/*"],
   client: {
    webSocketURL: 'ws://localhost:3000/ws',
  },
 },
 output: {
  filename: '[name].js',
  path: path.resolve(__dirname, 'dist'),
  publicPath: 'http://localhost:3001/'
},
optimization: {
  minimize: true,
  minimizer: [
    new TerserPlugin({
      terserOptions: {
        compress: {
          drop_console: true, // Optional: Drop console statements
        },
      },
    }),
  ],
  splitChunks: {
      chunks: 'all',
      cacheGroups: {
          vendor: {
              test: /[\/]node_modules[\/]/,
              name: 'vendor', // Fixed name for the vendor bundle
              chunks: 'all',
          },
      },
  }
},
module: {
  rules: [
      {
          test: /.js$/,
          exclude: /node_modules/,
          use: {
              loader: 'babel-loader',
              options: {
                  presets: ['@babel/preset-env', '@babel/preset-react']
                }
          }
      }, {
          test: /.css$/,
          use: ['style-loader', 'css-loader'],
      },{
          test: /.json$/,
          loader: 'json-loader', // Add this rule for JSON files
          type: 'javascript/auto',
      },
      {
          test: /.(png|svg|jpg|gif)$/,
          use: [
              'file-loader'
          ]
      },
      {
          test: /.(woff|woff2|eot|ttf|otf)$/,
          use: [
              'file-loader'
          ]
      }
  ]
},
 plugins: [
   new HtmlWebpackPlugin({
    template: path.join(__dirname, "public", "index.html"),
     publicPath: "http://localhost:3001/", // Add this to resolve PUBLIC_URL issues
     inject: true,
   }),
   new ModuleFederationPlugin({
    name: "Remote",
    filename: "moduleEntry.js",
    exposes: {
      "./Dashboard": "./src/App",
    },
    shared: {
      ...dependencies,
      react: {
        singleton: true,
        requiredVersion: dependencies["react"],
        eager: true
      },
      "react-dom": {
        singleton: true,
        requiredVersion: dependencies["react-dom"],
        eager: true
      },
    },
  }),
 ],
 resolve: {
   extensions: [".js", ".jsx"],
 },
 target: "web",
};

The dependencies versions that I’m using for this application are .

“react”: “^18.3.1”,
“react-dom”: “^18.3.1”,
“webpack”: “^5.96.1”

I can see the module http://localhost:3001/moduleEntry.js loading in the remote app but having this issue.

Initialization of sharing external failed: ScriptExternalLoadError: Loading script failed.

How do I draw a circle in Canvas that is set to a defined number of degrees?

I simulate an interactive view for a player. As long as a component of the game is within the view width, it should be possible to interact with it. With my code, it is not a problem to play the different directions, but only in 180°. Can I limit the view further so that it is a variable number, as you can see here in my sketch?

Blue is the player’s collision area.
Red is the current view width.
Gray is the desired view width.

https://i.imgur.com/cyNYpv3.png

Interact with the canvas in focusing the window and WASD or Arrow-Keys.

const canvas = document.querySelector('canvas')
const context = canvas.getContext('2d');

canvas.height = window.innerHeight;
canvas.width = window.innerWidth;

const keymap = [];

const player = { 
  x: window.innerWidth / 2 - 50, 
  y: window.innerHeight / 2 - 50,
  size: 100,
  range: 200,
  view: {
    start: 0,
    end: Math.PI
  }
};

const draw = () => {
  context.clearRect(0, 0, canvas.width, canvas.height);
  
  context.fillStyle = 'rgba(0, 0, 255, .6)';
  context.fillRect(
    player.x,
    player.y,
    player.size, 
    player.size, 
  );
  
  context.fillStyle = 'rgba(0, 0, 0, .6)';
  context.beginPath();
  context.arc(
    player.x + player.size / 2, 
    player.y + player.size / 2, 
    player.range, 
    player.view.start, 
    player.view.end, 
    false
  );
  context.fill();
};

const change = () => {
  let tempChange = { x: 0, y: 0 };
  
  keymap.forEach(direction => {
    if (direction === 'KeyS' || direction === 'ArrowDown') {
      tempChange.y = 1;
    }

    if (direction === 'KeyA' || direction === 'ArrowLeft') {
      tempChange.x = -1;
    }

    if (direction === 'KeyW' || direction === 'ArrowUp') {
      tempChange.y = -1;
    }

    if (direction === 'KeyD' || direction === 'ArrowRight') {
      tempChange.x = 1;
    }
  });
  
  const actions = {
    '1_1': () => {
      // Down Right
      player.view.start = 1.75 * Math.PI;
      player.view.end = 0.75 * Math.PI;
    },
    '1_-1': () => {
      // Up Right
      player.view.start = 1.25 * Math.PI;
      player.view.end = 0.25 * Math.PI;
    },
    '1_0': () => {
      // Right
      player.view.start = 1.5 * Math.PI;
      player.view.end = 0.5 * Math.PI;
    },
    '-1_1': () => {
      // Down Left
      player.view.start = 0.25 * Math.PI;
      player.view.end = 1.25 * Math.PI;
    },
    '-1_-1': () => {
      // Up Left
      player.view.start = 0.75 * Math.PI;
      player.view.end = 1.75 * Math.PI;
    },
    '-1_0': () => {
      // Left
      player.view.start = 0.5 * Math.PI;
      player.view.end = 1.5 * Math.PI;
    },
    '0_1': () => {
      // Down
      player.view.start = 0;
      player.view.end = Math.PI;
    },
    '0_-1': () => {
      // Up
      player.view.start = Math.PI;
      player.view.end = 0;
    },
    '0_0': () => {},
  };

  const dir = tempChange.x + '_' + tempChange.y;
  const func = actions[dir];
  func();
};

const loop = () => {
  change();
  draw();
  
  requestAnimationFrame(loop);
};

const setup = () => {
  window.addEventListener('keydown', event => {
    const key = event.code;
    const index = keymap.indexOf(key);

    if (index > -1)
      keymap.splice(index, 1);

    keymap.push(key);
  });

  window.addEventListener('keyup', event => {
    const key = event.code;
    const index = keymap.indexOf(key);

    if (index > -1)
      keymap.splice(index, 1);
  });
};

setup();
requestAnimationFrame(loop);
<canvas></canvas>

How can I make the cursor state persist between pages?

I implemented a cursor from this library https://cursor.oooo.so/ in my portfolio made with astro and preact, my jsx file looks like this:

import { useEffect } from "preact/hooks";
import { initCursor, updateCursor } from "ipad-cursor";


const CustomCursor = () => {
  useEffect(() => {
    if (!window.cursorInitialized) {
      // Inicializa el cursor solo una vez
      initCursor({
        normalStyle: { background: "rgba(0, 0, 0, 0.5)" },
        textStyle: { background: "blue" },
        blockStyle: { background: "green" },
      });
      window.cursorInitialized = true;
    }

    // Asegura que el cursor se actualice al cambiar de página
    updateCursor();
  }, []);

  return nul; // Este componente no necesita renderizar nada
};

export default CustomCursor;

I implemented this in my layout like this:

<html>
  <body class="dark:bg-[#0e0e0e] bg-white">
    <!-- <article
            class="bg-[url('noise.gif')] fixed top-0 left-0 w-full h-screen opacity-[0.025] z-[-1] pointer-events-none"
        >
        </article> -->
    <slot />
    <Cursor client:load transition:name="cursor" transition:persist/>
    <Button animate="hidden">
      <ThemeSwitcher />
    </Button>
    <script
      src="https://cdnjs.cloudflare.com/ajax/libs/flowbite/2.3.0/flowbite.min.js"
    ></script>
  </body>
</html>

it is assumed that adding transition:name y transition:persist, Adding this is supposed to persist the state but when I navigate to another page the cursor changes to the Windows cursor and I have to reload the page for it to work again