How can I use a custom hook in other custom hook?

I am building a roster management application.
I have built a roster viewer.

I have built a useRosterViewer hook for the roster viewer.

The source code is something like:

let reducer = (state, action) => {
    let result = { ...state };
    switch (action.type) {
        case "init":
            result.roster = action.roster;
            result.isLoading = false;
            break;
        ........... 
        default:
            break;
    }
    return result;
}
export function useRosterViewer() {
    const [itemList, updateItemList] = useReducer(reducer, {
        error: null,
        isLoading: true,
        roster: null,
        ............
    });
    useEffect(() => {
        let getData = async () => {
            let now = new Date();
            let rosterYear = now.getFullYear();
            let rosterMonth = now.getMonth();
            let roster = await Roster(rosterYear, rosterMonth + 1);
            updateItemList({
                roster,
                systemParam,
                type: "init"
            }); 
        }
        getData();
    },[]);
    return {
        error: itemList.error,
        isLoading: itemList.isLoading,
        roster: itemList.roster,
        .............
    }
}

I am going to build a roster editor.
When I am building another hook such as useRosterEditor, the source code is something like:

export function useRosterEditor(){
    const { error, isLoading, roster } = useRosterViewer();
    const [itemList, updateItemList] = useReducer(reducer, {
        error,
        isLoading,
        roster,
    });
    return {
        error: itemList.error,
        isLoading: itemList.isLoading,
        roster: itemList.roster,     
    }
}

The useRosterEditor consumption component reports that the data has not been updated.
So, how can I reuse the useRosterViewer hook?

How do I run 2 different functions from 1 file with 2 different command line prompts in Node.js?

I have a .js file in my project that imports an NPM package and has 2 functions that use that package:

//replacePaths.js
import {replaceInFile} from 'replace-in-file';
async function replace() {
    const options = {
        files: 'src/**/*.jsx',
        from: 'dev/svgs/icons-main.svg',
        to: 'staging/media/svgs/icons-main.svg',
    };

    try {
        const results = await replaceInFile(options);
    } catch (error) {
        console.error('Error occurred:', error);
    }
}

async function revert() {
    const options = {
        files: 'src/**/*.jsx',
        from: 'staging/media/svgs/icons-main.svg',
        to: 'dev/svgs/icons-main.svg',
    };

    try {
        const results = await replaceInFile(options);
    } catch (error) {
        console.error('Error occurred:', error);
    }
}
module.exports = {
    replace,
    revert
};

I want to be able to run these functions from the command line. I’ve Googled around and to do this it seems I just add the following to my package.json file:

"scripts": {
    ...
    "replace": "node replacePaths.js replace",
    "revert" : "node replacePaths.js revert",
    ...
}

I the first of these in the command line as such: npm run replace, but I got the error ReferenceError: module is not defined in ES module scope.

Googling that, I changed the exports part to:

export default replace;
export default revert;

and tried again. I didn’t get any errors, but instead just got the line node replacePaths.js replace printed in the console.

I can run the functions by removing the export part and just having replace() or revert() on the JS file, but that’s not helpful to me if I want to have 2 functions on the same file.

Would anyone be able to point me in the right direction?

Parallel execution with NodeJs and Puppeteer

I’m using NodeJs and Puppeteer to scrap data from an website.
My goal is to run multiple instances of Puppeteer when scraping data.
However, i may be doing something wrong. Because it is running only one instances, and sending multiple data at once.

Here is what is my code do:

  1. Open an XLSX file from the computer
  2. Do some processing and then read the file into the memory(a list of numCpfCnpj and numAcordo)
  3. Separate the entries in batches of 5, for multiple processing.
  4. Call puppeteer to login on the page and and search for the numCpfCnpj.
  5. After searching the numCpfCnpj, should search for numAcordo and continue with the logic.

However, i can’t figure out how to run more than one instance. It it possible with Puppeteer?
Or should i just throw the script in a cloud service (like AWS Lambda) and run multiple instances of without worrying about anything else?

Here is the code that calls the methods:

const puppeteer = require('puppeteer');
const XLSX = require('xlsx');

const handleLogin = async (page, login, password) => {
    await page.goto('https://www.santandernegocios.com.br/portaldenegocios/#/externo');
    await page.waitForSelector('#userLogin__input');
    await page.waitForSelector('#userPassword__input');
    await page.type('#userLogin__input', login);
    await page.type('#userPassword__input', password);
    await page.focus('#userPassword__input');
    await page.keyboard.press('Enter');
    await page.waitForNavigation();
};

const searchAndNavigate = async (page, cpfCnpj) => {
    await page.waitForSelector('input[name="inputSearch"]');

    // Ensure cpfCnpj is a string
    if (typeof cpfCnpj !== 'string') {
        throw new TypeError('cpfCnpj must be a string');
    }

    await page.type('input[name="inputSearch"]', cpfCnpj);

  
    await page.waitForFunction(
        (selector, text) => {
            const input = document.querySelector(selector);
            return input && input.value === text;
        },
        {},
        'input[name="inputSearch"]',
        cpfCnpj
    );

    await page.focus('input[name="inputSearch"]');
    await page.keyboard.press('Enter');
    await page.waitForNavigation({ waitUntil: 'networkidle2' });
};

const clickMenuLink = async (page, menuTexts) => {
    await page.evaluate(menuTexts => {
        const sessionMenu = document.querySelector('div.session-menu');
        if (sessionMenu) {
            const ul = sessionMenu.querySelector('ul');
            if (ul) {
                for (let text of menuTexts) {
                    const link = Array.from(ul.querySelectorAll('li a')).find(anchor => anchor.textContent.trim() === text);
                    if (link) {
                        link.click();
                        return;
                    }
                }
            }
        }
    }, menuTexts);
};

const processXlsxFile = async (filePath) => {
    const workbook = XLSX.readFile(filePath);
    const sheet = workbook.Sheets[workbook.SheetNames[0]];
    const data = XLSX.utils.sheet_to_json(sheet, { header: 1 });

    const rows = data.slice(1); // Skip header row
    const groupedEntries = [];
    const groupSize = 5;

    for (let i = 0; i < rows.length; i += groupSize) {
        groupedEntries.push(rows.slice(i, i + groupSize).map(row => ({
            numCpfCnpj: String(row[0]),  // Ensure it's a string
            numAcordo: String(row[1])    // Ensure it's a string
        })));
    }

    return groupedEntries;
};


const processEntries = async (page, entries, menuTexts) => {
    await Promise.all(entries.map(async (entry) => {
        try {
            console.log(entry.numCpfCnpj);
            await searchAndNavigate(page, entry.numCpfCnpj);
            await clickMenuLink(page, menuTexts);
            console.log(`Processed: ${entry.numCpfCnpj} - ${entry.numAcordo}`);
        } catch (error) {
            console.error(`Error processing ${entry.numCpfCnpj} - ${entry.numAcordo}:`, error);
        }
    }));
};

const runPuppeteer = async (filePath, login, password, menuTexts) => {
    const browser = await puppeteer.launch({ headless: false });
    const page = await browser.newPage();

    try {
        await handleLogin(page, login, password);
        const entries = await processXlsxFile(filePath);
        
        // Process each group of entries with a limit of 5 simultaneous tasks
        for (const group of entries) {
            // Process each group with a maximum of 5 simultaneous tasks
            const chunkSize = 5;
            for (let i = 0; i < group.length; i += chunkSize) {
                const chunk = group.slice(i, i + chunkSize);
                await processEntries(page, chunk, menuTexts);
            }
        }
        
    } catch (error) {
        console.error('Error occurred:', error);
    } finally {
        await browser.close();
    }
};

module.exports = { runPuppeteer };

Thanks a lot. If any additional information is needed i’ll reply as soon as i see the notitification.

i wanna make my calculator evaluate a single operation at a time but it doesn’t do that

the calculator should not evaluate more than a single pair of numbers at a time. Example: you press a number button (12), followed by an operator button (+), a second number button (7), and finally a second operator button (-). the calculator should then do the following: first, evaluate the first pair of numbers (12 + 7), second, display the result of that calculation (19), and finally, use that result (19) as the first number in your new calculation, along with the next operator
here’s my code

const numBtn = Array.from(document.querySelectorAll(".number"));

const operatorbtn = Array.from(document.querySelectorAll(".operator"));

const display = document.querySelector(".display");

let firstNum = null;

let secondNum = null;

let operator = null;



function add(a, b) {
    return a + b;
}

function subtract(a, b) {
    return a - b;
}

function multiply(a, b) {
    return a * b;
}

function divide(a, b) {
    return a / b;
}

function operate(num1, num2, operator) {
    switch (operator) {
        case "+":
            return add(num1, num2);
        case "-":
            return subtract(num1, num2);

        case "*":
            return multiply(num1, num2);
        case "/":
            if (num2 === 0) {
                return "lmao";
            }
            return divide(num1, num2);
    }
}

function updateDisplay(string) {
    if (display.textContent === "0") {
        display.textContent = "";
    }
    display.textContent += string;
}

numBtn.forEach((button) => {
    button.addEventListener("click", (e) => {
        console.log(typeof e.target.textContent);
        updateDisplay(e.target.textContent);
    });
});

operatorbtn.forEach((button) => {
    button.addEventListener("click", (e) => {
        console.log(typeof e.target.textContent);

        const operatorInput = e.target.textContent;
        if (operatorInput === "AC") {
            display.textContent = 0;
            firstNum = null;
            secondNum = null;
            operator = null;
            return;
        }
        if (operatorInput === "=") {
            // turn the operation into an array
            const operation = display.textContent.split("");

            //get operator index
            const operatorIndex = operation.findIndex((el) =>
                ["+", "-", "*", "/"].includes(el)
            );
            firstNum = parseInt(operation.slice(0, operatorIndex).join(""));
            operator = operation[operatorIndex];

            secondNum = parseInt(operation.slice(operatorIndex + 1).join(""));

            console.log(operate(firstNum, secondNum, operator));
            display.textContent = operate(firstNum, secondNum, operator);

            return;
        }
        updateDisplay(e.target.textContent);
    });
});

id like it if someone told me how to implement the functionality mentioned above

JavaScript Defining static fields with conditions in a class

I want to create code(example) like this:

class foo {
    static [x % 2 == 0]() {
        return x / 2;
    }
    static [x % 2 == 1]() {
        return x * 3 + 1;
    }
}

I tried many ways but it didn’t work.

Is it possible to get the key value used to access a field in JavaScript?
Or is it possible to give default values ​​to undefined fields?

How to Edit an Array in Firebase Database using the Namespaced API in vanilla Javascript?

I have an array of objects called ‘markers’ in the Firebase Database. How do I edit a single object from the ‘markers’ array using the namespaced API in vanilla Javascript? Do I have to JSON.stringify?

I tried using database.ref[‘markers’].set(, however errors kept appearing such as:
Uncaught Error: set failed: value argument contains undefined in property ‘markers.1.comments.0.user’

Identify who login and submit form with pre-fill and hide content problem

I have a project to make job evaluation performance system by

  • use Web app for login feature by coding in GAS in google sheet.
  • get user and password to match in UserCredentials sheet in google sheet
  • if user and password match case then open form that match case with pre-fill username in the first question and blind it and show other question for fill up by user

problem is I found out many ways to active pre-fill and hide first question , but it’s not work till the end. I’d like to use process auto detect entry ID from first question insteed direct fill-up in sheet bacause of there’re so many form in project.(BTW even direct fill-up Entry ID also not work in pre-fill function)

so could you please advise to me how to process the next step to complete this project?

  • Sample Code and materials

https://docs.google.com/document/d/1EaUVucNPBfj5UaALQoeFJF5BuxMtF9EwMG4mMCW5-Sw/edit?usp=sharing

so could you please advise to me how to process the next step to complete this project?

Vue js Preview lottie file before upload

How to preview lottie file when select change on input file, anyone could help me pls? I’ve tried with vue3 lottie and dotlottie components, but it supports only option url or I missed something? pls help.(file extension .lottie)

<script setup>
const fileUrl = ref('')
const newSelectedFile = ref({})
const changeFile = (event) => {
    newSelectedFile.value = event.target.files[0];
}
</script>
<DotLottieVue v-if="!newSelectedFile" style="height: 200px; width: 200px" ref="playerRef" :useFrameInterpolation="true"
                :renderConfig="configOption" :autoplay="true" :loop="true" :src="fileUrl" />
<DotLottieVue v-else style="height: 200px; width: 200px" ref="playerRef" :useFrameInterpolation="true"
                :renderConfig="configOption" :autoplay="true" :loop="true" :data="newSelectedFile" />
<input type="file" ref="fileRef" id="lottie_file" @change="changeFile" hidden>

Can I skip RSPack resolution for a specific file that is imported for local configuration in strictly the development mode?

I have a Typescript app building with RSPack that leverages some options that are configurable via a local json file, let’s call it local-config.json. There’s a line that attempts to import those configuration options like so:

const localConfig = import('./local-config.json')

When I run the rspack command to build the assets, I get the following error:

ERROR in ./path/to/file/location/index.ts
  × Resolve error: Can't resolve './local-config.json' in 'path/to/file/location'

I’m wondering if there’s a way I can tell RSPack to not try to resolve that specific file or to skip this check in that block of code?

I’ve tried looking through the various options in RSPack, like the Rules, but I don’t see options that specifically allow me to do what I’m trying to do here.

Identify [or restrict] if a class’s method was called from another instance of the class

I have a class with a private data store, in a custom format. I have made the data store private, so that people will work with the API and not directly mess with the underlying structure.

I want to implement a merge method, that will allow one instance of my class to merge into another. To make this performant, the merge function needs access to both instances’ data stores.

class MyClass() {
  #myDataStore; // custom data structure that i don't want people messing with. (private)
  ...
  mergeDataStores(instance2) {
    const dataToMerge = instance2.#myDataStore; // !IMPORTANT! - this what I want to be able to do
    ... // perform the actions needed to merge the two.
  }
  ...
}

const instance1 = new MyClass();
const instance2 = new MyClass();
... // various actions that load data into instance1 and instance2
instance1.merge(instance2);

is there any way I can accomplish this without exposing my data store?

Solutions that I don’t know how to implement, if they are even possible

  1. Is it possible to have an access modifier (aka another option for what other languages would call public, private or protected) that means “this value can only be accessed by an instance of the same class”?
  2. In a method, is it possible to check the instance of the class that invoked the method? That would let me create a getter that checks if (!(invokingContext instanceof MyClass)) throw new Error("Access denied!");

Am I missing another option?

escribir y enviar mensaje en el chat de twitch [closed]

quiero realizar una extensión de chrome twitch que escriba un mensaje automático cada cierto tiempo, pero no logro hacer que el mensaje se mande estoy usando el siguiente código

  const chatInput = document.querySelector('div[data-a-target="chat-input"]');
      if (chatInput) {
        
        const event = new Event('input', { bubbles: true });

        chatInput.value = 'hola' // NO Cambia el valor

        chatInput.dispatchEvent(event); // Dispara el evento de entrada

        // Encuentra el botón de enviar y haz clic en él
        const sendButton = document.querySelector('button[data-a-target="chat-send-button"]');
        if (sendButton) {
            sendButton.click();
          // Detén el intervalo una vez que se haya enviado el mensaje
        }

usando

chatInput.textContent = 'hola'

si cambia el texto pero no se envia, se sobre pone al Placeholder
imagen de referencia
asi es como se ve el input de la pagina

<div id="WYSIWGChatInputEditor_SkipChat" class="Layout-sc-1xcs6mc-0 pJTym"><div class="chat-wysiwyg-input__box">
<div class="chat-wysiwyg-input__placeholder" style="padding-left: 1rem; margin-left: 2px;">Enviar un mensaje</div>
<div role="textbox" aria-multiline="true" data-a-target="chat-input" data-test-selector="chat-input" aria-label="Enviar un mensaje" data-placeholder="Enviar un mensaje" class="chat-wysiwyg-input__editor" tabindex="0" spellcheck="true" data-slate-editor="true" data-slate-node="value" contenteditable="true" zindex="-1" style="position: relative; white-space: pre-wrap; overflow-wrap: break-word; padding-left: 1rem; padding-right: 65px; max-height: calc(105px + 2rem); outline: none; padding-bottom: 1rem;"><div data-slate-node="element"><span data-slate-node="text">
<span data-slate-leaf="true" class="ScTransitionBase-sc-hx4quq-0 iEzfDB tw-transition" data-a-target="chat-input-text" aria-hidden="false">
<span data-slate-zero-width="n" data-slate-length="0"><br>
</span></span>
</span></div></div></div></div>

me podrían apoyar con esto, que opciones hay para poder enviarlo correctamente

ya no se que hacer para hacerlo

Dropdown multi select not maintaining after closing out

 type SortingKey =
    | "Duration"
    | "Favorited Territories"
    | "Favorited Offices"
    | "Requestable"
    | "Non-Requestable"
    | "Non-Full";

  const [sortingStates, setSortingStates] = useState<{
    [key in SortingKey]: boolean;
  }>({
    Duration: false,
    "Favorited Territories": false,
    "Favorited Offices": false,
    Requestable: false,
    "Non-Requestable": false,
    "Non-Full": false,
  });
const topContent = React.useMemo(() => {
    return (
      <div className="flex flex-col gap-4">
        <div className="flex flex-wrap justify-between items-center gap-4 w-full">
          {/* Dropdown for selecting search criteria */}
          <Dropdown>
            <DropdownTrigger>
              <Button size="sm" variant="flat">
                Search Criteria
              </Button>
            </DropdownTrigger>
            <DropdownMenu aria-label="Search Criteria" closeOnSelect>
              {columns
                .filter(
                  (column) =>
                    column.uid !== "actions" &&
                    column.uid !== "eventDate" &&
                    column.uid !== "eventType" &&
                    column.uid !== "startTime" &&
                    column.uid !== "favorited"
                )
                .map((column) => (
                  <DropdownItem
                    key={column.uid}
                    className="capitalize"
                    onClick={() => {
                      let lowercasedName = column.name.toLowerCase();
                      // Manually map column names to their corresponding values
                      if (lowercasedName === "office") {
                        setSearchCriteria("Office");
                        setFilterCriteria("officeName");
                      } else if (lowercasedName === "location") {
                        setSearchCriteria("Location");
                        setFilterCriteria("location");
                      } else if (lowercasedName === "territories") {
                        setSearchCriteria("Territories");
                        setFilterCriteria("territory");
                      } else if (lowercasedName === "specialty") {
                        setSearchCriteria("Specialties");
                        setFilterCriteria("specialty");
                      } else if (lowercasedName === "providers") {
                        setSearchCriteria("Providers");
                        setFilterCriteria("providers");
                      }

                      setSearchValue(""); // Clear the search input when changing criteria
                    }}
                  >
                    {column.name.toLowerCase()}
                  </DropdownItem>
                ))}
            </DropdownMenu>
          </Dropdown>

          {/* Search input */}
          <Input
            isClearable
            classNames={{
              base: "w-full sm:max-w-[44%]",
            }}
            placeholder={`Search by ` + searchCriteria}
            size="sm"
            startContent={
              <FontAwesomeIcon
                icon={faMagnifyingGlass}
                width="16"
                height="16"
              />
            }
            variant="underlined"
            value={searchValue}
            onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
              setSearchValue(e.target.value);
            }}
            classname="larger-text"
          />

          {/* Dropdown for Specialty */}
          <Dropdown>
            <DropdownTrigger>
              <Button size="sm" variant="flat">
                {filterSpecialty}
              </Button>
            </DropdownTrigger>
            <DropdownMenu
              aria-label="Specialty"
              closeOnSelect={true}
              style={{ maxHeight: "400px", overflowY: "auto" }}
            >
              {specialty_columns.map((specialty) => (
                <DropdownItem
                  key={specialty}
                  onClick={() => {
                    const value =
                      specialty === "Unselect Specialty"
                        ? "Select Specialty"
                        : specialty;
                    setFilterSpecialty(value);
                  }}
                >
                  {specialty}
                </DropdownItem>
              ))}
            </DropdownMenu>
          </Dropdown>

          {/* Dropdown for Type */}
          <Dropdown>
            <DropdownTrigger>
              <Button size="sm" variant="flat">
                {filterType}
              </Button>
            </DropdownTrigger>
            <DropdownMenu aria-label="Type" closeOnSelect={true}>
              {/* Map your types here */}
              {type_columns.map((type) => (
                <DropdownItem
                  key={type}
                  onClick={() => {
                    const value =
                      type === "Unselect Type" ? "Select Type" : type;
                    setFilterType(value);
                  }}
                >
                  {type}
                </DropdownItem>
              ))}
            </DropdownMenu>
          </Dropdown>

          <Dropdown>
            <DropdownTrigger>
              <Button size="sm" variant="flat">
                Sorting Options
              </Button>
            </DropdownTrigger>
            <DropdownMenu
              aria-label="Sort Criteria"
              closeOnSelect={false}
              selectionMode="multiple"
            >
              {SORTING_COLUMNS.map((column) => (
                <DropdownItem onClick={() => handleSortOptions(column)}>
                  {column}
                </DropdownItem>
              ))}
            </DropdownMenu>
          </Dropdown>
          <Dropdown>
            <DropdownTrigger className="hidden sm:flex px-6">
              <Button
                endContent={<FontAwesomeIcon icon={faChevronDown} />}
                size="sm"
                variant="flat"
              >
                Display Columns
              </Button>
            </DropdownTrigger>
            <DropdownMenu
              disallowEmptySelection
              aria-label="Table Columns"
              closeOnSelect={false}
              selectedKeys={visibleColumns}
              selectionMode="multiple"
              //This is to change the different columns shown, ignore error from typescript
              onSelectionChange={(newVisibleColumns) => {
                console.log(
                  "Attempting to update visible columns to:",
                  newVisibleColumns
                );

                if (newVisibleColumns.size > 0) {
                  setVisibleColumns(newVisibleColumns);
                } else {
                  //Can provide feedback that they need one box selected atleast here.
                }
              }}
            >
              {columns.map((column) => (
                <DropdownItem key={column.uid} className="capitalize">
                  {column.name.toLowerCase()}
                </DropdownItem>
              ))}
            </DropdownMenu>
          </Dropdown>
        </div>

        <div className="flex justify-between items-center">
          <span className="text-default-400 text-small">
            Total {meetings.length} meetings
          </span>
          <label className="flex items-center text-default-400 text-small">
            Rows per page:
            <select
              className="bg-transparent outline-none text-default-400 text-small"
              onChange={onRowsPerPageChange}
            >
              <option value="15">15</option>
              <option value="30">30</option>
              <option value="45">45</option>
            </select>
          </label>
        </div>
      </div>
    );
  }, [
    filterSpecialty,
    filterType,
    //setSortingStates,
    searchCriteria,
    searchValue,
    filterCriteria,
    visibleColumns,
    onRowsPerPageChange,
    meetings.length,
  ]);
return (
    <>
      <ProfileDrawer
        isOpen={drawerOpenOffice}
        onClose={() => setDrawerOpenOffice(false)}
        ID={officeModalId ? officeModalId : "null"}
      />
      <ProviderProfileDrawer
        isOpen={drawerOpenProviders}
        onClose={() => setDrawerOpenProviders(false)}
        providerAtEvent={providerInfo} //provider info
      />
      <div></div>
      <Table
        isCompact
        removeWrapper
        aria-label="Meetings table data"
        bottomContent={bottomContent}
        bottomContentPlacement="outside"
        //sortDescriptor={sortDescriptor}
        topContent={topContent}
        topContentPlacement="outside"
        //onSortChange={setSortDescriptor}
      >
        <TableHeader columns={headerColumns}>
          {(column) => (
            <TableColumn
              key={column.uid}
              align="center"
              allowsSorting={column.sortable}
            >
              <span className="larger-text">{column.name}</span>
            </TableColumn>
          )}
        </TableHeader>
        <TableBody emptyContent={"No meetings found"} items={items}>
          {(item) => (
            <TableRow key={item.id}>
              {(columnKey) => (
                <TableCell className="larger-text">
                  {renderCell(item, columnKey)}
                </TableCell>
              )}
            </TableRow>
          )}
        </TableBody>
      </Table>
    </>

Currently my Sorting Options dropdown allows me to select different options and it filters a table full of things by these options. The problem is when I click on some filters, then i close the sorting options list, the filters remain. However, when I open the sorting options list again, the filtered options arent selected.

Basically the check mark that appears near sorting options doesnt stay when I close it.

HTML canvas game giving error cant import outside of a module

The file that isn’t working is a js file and I’m trying to import a resource.js file to get the game objects loaded

SyntaxError: Cannot use import statement outside a module

If I remove that js import the same error pops up for my CSS stylesheet saying the same thing.
I’m on node 20.16.0 and I’m running the files in google chrome, but the error is happening even if I switch browsers.

I have looked through some forums and have made myself a live server which fixed my export problem I was having before this, but it didn’t help with the import statement. The import statement I’m using is:

import {Resources} from "./src/resources.js"
import './src/style.css'

I have the CSS linked with this in the area

<link rel="stylesheet" href="src/style.css"></link>

and I have the 2 js files linked with this:

<script src="src/resources.js" type="module"></script>
<script src="main.js"></script>

I’ve tried to flip the way I called the scripts in the html, I’ve tried calling both of them as modules or switching which of them was called as a module which resulted in an error saying it couldn’t fetch the files.

No friction on tweened sprite

I have a moving platform and box on top of it. No matter how fast the platform is moving, the box doesnt move sideways along with the platform and eventually falls down if the platform slipped away.

I tried different combinations of friction and frictionStatic.

   const box = this.matter.add.rectangle(700, ScreenHelper.sceneWrapperSize.height - 110, 20, 20, {
      collisionFilter: {
        category: CAT_BLOCK_A,
        mask: CAT_FLOOR,
        group: 0
      },
      friction: 1,
    })

    const platform = this.matter.add.sprite(664, ScreenHelper.sceneWrapperSize.height - 100, "brick", undefined, {
      isStatic: true,
      collisionFilter: {
        category: CAT_FLOOR,
        mask: CAT_PLAYER | CAT_PLAYER_BOTTOM_SENSOR | CAT_BLOCK_A,
        group: 0
      },
      friction: 1,
      frictionStatic: 1,
    });
    platform.setDisplaySize(200, 20)

    this.tweens.add({
      targets: platform,
      x: 300,
      ease: Phaser.Math.Easing.Quintic.InOut,
      duration: 3000,
      yoyo: true,
      repeat: -1
    });