Determinate groups in parsing obj 3d model in javascript

I want to detect group sub object bounds from obj file content.
In blender for example create obj with sub group CUBE.COLLIDER. In js loader i want center or bounds of CUBE.COLLIDER for later (For physics body).
I need simple and pragmatic solution.For example to create exstra data holder for CUBE.COLLIDER group vertices…

What is the l case? It is unsed flag in my program at the moment.

For now i see g.

...
l 5 19
l 6 20
g Cube.ME.COLLIDER_Mesh
v -0.515941 -3.226738 -4.906731
v -0.515941 2.340278 -4.906731
...

Any suggestion ?

Most important code lines:

 
export class constructMesh {
    constructor(objectData, inputArg) {
        this.inputArg = inputArg;
        this.objectData = objectData;
        this.create(objectData, inputArg);
        this.setScale = (s) => {
            this.inputArg.scale = s;
            initMeshBuffers(world.GL.gl, this.create(this.objectData, this.inputArg));
        };
        this.updateBuffers = () => {
            this.inputArg.scale = 1;
            initMeshBuffers(world.GL.gl, this.create(this.objectData, this.inputArg));
        };
    }

    create = (objectData, inputArg, callback) => {
        if(typeof callback === 'undefined') callback = function() {};
        let initOrientation = [0, 1, 2];
        /*
            To solve the issue of duplicate Vertices (the `(vertex, [texture], normal)`
            groups), while iterating through the face lines, when a group is encountered
            the whole group string ('16/92/11') is checked to see if it exists in the
            packed.hashindices object, and if it doesn't, the indices it specifies
            are used to look up each attribute in the corresponding attribute arrays
            already created. The values are then copied to the corresponding unpacked
            array (flattened to play nice with WebGL's ELEMENT_ARRAY_BUFFER indexing),
            the group string is added to the hashindices set and the current unpacked
            index is used as this hashindices value so that the group of elements can
            be reused. The unpacked index is incremented. If the group string already
            exists in the hashindices object, its corresponding value is the index of
            that group and is appended to the unpacked indices array.
            */
        var verts = [],
            vertNormals = [],
            textures = [],
            unpacked = {};
        // unpacking stuff
        unpacked.verts = [];
        unpacked.norms = [];
        unpacked.textures = [];
        unpacked.hashindices = {};
        unpacked.indices = [];
        unpacked.index = 0;
        // array of lines separated by the newline
        var lines = objectData.split('n');
        // update swap orientation
        if(inputArg.swap[0] !== null) {
            swap(inputArg.swap[0], inputArg.swap[1], initOrientation);
        }

        var VERTEX_RE = /^vs/;
        var NORMAL_RE = /^vns/;
        var TEXTURE_RE = /^vts/;
        var FACE_RE = /^fs/;
        var WHITESPACE_RE = /s+/;

        for(var i = 0;i < lines.length;i++) {
            var line = lines[i].trim();
            var elements = line.split(WHITESPACE_RE);
            elements.shift();

            if(VERTEX_RE.test(line)) {
                // if this is a vertex
                verts.push.apply(verts, elements);
            } else if(NORMAL_RE.test(line)) {
                // if this is a vertex normal
                vertNormals.push.apply(vertNormals, elements);
            } else if(TEXTURE_RE.test(line)) {
                // if this is a texture
                textures.push.apply(textures, elements);
            } else if(FACE_RE.test(line)) {
                // if this is a face
                /*
                    split this face into an array of vertex groups
                    for example:
                        f 16/92/11 14/101/22 1/69/1
                    becomes:
                        ['16/92/11', '14/101/22', '1/69/1'];
                    */
                var quad = false;
                for(var j = 0, eleLen = elements.length;j < eleLen;j++) {
                    // Triangulating quads
                    // quad: 'f v0/t0/vn0 v1/t1/vn1 v2/t2/vn2 v3/t3/vn3/'
                    // corresponding triangles:
                    //      'f v0/t0/vn0 v1/t1/vn1 v2/t2/vn2'
                    //      'f v2/t2/vn2 v3/t3/vn3 v0/t0/vn0'
                    if(j === 3 && !quad) {
                        // add v2/t2/vn2 in again before continuing to 3
                        j = 2;
                        quad = true;
                    }
                    if(elements[j] in unpacked.hashindices) {
                        unpacked.indices.push(unpacked.hashindices[elements[j]]);
                    } else {
 
                        var vertex = elements[j].split('/');
 
                        // vertex position
                        unpacked.verts.push(+verts[(vertex[0] - 1) * 3 + initOrientation[0]] * inputArg.scale);
                        unpacked.verts.push(+verts[(vertex[0] - 1) * 3 + initOrientation[1]] * inputArg.scale);
                        unpacked.verts.push(+verts[(vertex[0] - 1) * 3 + initOrientation[2]] * inputArg.scale);

                        // vertex textures
                        if(textures.length) {
                            unpacked.textures.push(+textures[(vertex[1] - 1) * 2 + 0]);
                            unpacked.textures.push(+textures[(vertex[1] - 1) * 2 + 1]);
                        }
                        // vertex normals
                        unpacked.norms.push(+vertNormals[(vertex[2] - 1) * 3 + 0]);
                        unpacked.norms.push(+vertNormals[(vertex[2] - 1) * 3 + 1]);
                        unpacked.norms.push(+vertNormals[(vertex[2] - 1) * 3 + 2]);
                        // add the newly created vertex to the list of indices
                        unpacked.hashindices[elements[j]] = unpacked.index;
                        unpacked.indices.push(unpacked.index);
                        // increment the counter
                        unpacked.index += 1;
                    }
                    if(j === 3 && quad) {
                        // add v0/t0/vn0 onto the second triangle
                        unpacked.indices.push(unpacked.hashindices[elements[0]]);
                    }
                }
            } else {
                console.log(':::::::obj loader:::::::::::', line)
                  }
        }
        this.vertices = unpacked.verts;
        this.vertexNormals = unpacked.norms;
        this.textures = unpacked.textures;
        this.indices = unpacked.indices;
        callback();
        return this;
    };

}
 
export var downloadMeshes = function(nameAndURLs, completionCallback, inputArg) {
    // the total number of meshes. this is used to implement "blocking"
    var semaphore = Object.keys(nameAndURLs).length;
    // if error is true, an alert will given
    var error = false;
    // this is used to check if all meshes have been downloaded
    // if meshes is supplied, then it will be populated, otherwise
    // a new object is created. this will be passed into the completionCallback
    if(typeof inputArg === 'undefined') {
        var inputArg = {
            scale: 1,
            swap: [null]
        };
    }
    if(typeof inputArg.scale === 'undefined') inputArg.scale = 1;
    if(typeof inputArg.swap === 'undefined') inputArg.swap = [null];

    var meshes = {};

    // loop over the mesh_name,url key,value pairs
    for(var mesh_name in nameAndURLs) {
        if(nameAndURLs.hasOwnProperty(mesh_name)) {
            new Ajax().get(
                nameAndURLs[mesh_name],
                (function(name) {
                    return function(data, status) {
                        if(status === 200) {
                            meshes[name] = new constructMesh(data, inputArg);
                        } else {
                            error = true;
                            console.error('An error has occurred and the mesh "' + name + '" could not be downloaded.');
                        }
                        // the request has finished, decrement the counter
                        semaphore--;
                        if(semaphore === 0) {
                            if(error) {
                                // if an error has occurred, the user is notified here and the
                                // callback is not called
                                console.error('An error has occurred and one or meshes has not been ' + 'downloaded. The execution of the script has terminated.');
                                throw '';
                            }
                            // there haven't been any errors in retrieving the meshes
                            // call the callback
                            completionCallback(meshes);
                        }
                    };
                })(mesh_name)
            );
        }
    }
};

var _buildBuffer = function(gl, type, data, itemSize) {
    var buffer = gl.createBuffer();
    var arrayView = type === gl.ARRAY_BUFFER ? Float32Array : Uint16Array;
    gl.bindBuffer(type, buffer);
    gl.bufferData(type, new arrayView(data), gl.STATIC_DRAW);
    buffer.itemSize = itemSize;
    buffer.numItems = data.length / itemSize;
    return buffer;
};

export var initMeshBuffers = function(gl, mesh) {
    mesh.normalBuffer = _buildBuffer(gl, gl.ARRAY_BUFFER, mesh.vertexNormals, 3);
    mesh.textureBuffer = _buildBuffer(gl, gl.ARRAY_BUFFER, mesh.textures, 2);
    mesh.vertexBuffer = _buildBuffer(gl, gl.ARRAY_BUFFER, mesh.vertices, 3);
    mesh.indexBuffer = _buildBuffer(gl, gl.ELEMENT_ARRAY_BUFFER, mesh.indices, 1);
};

OUTPUT FOR ELSE :
(console.log(‘:::::::obj loader:::::::::::’, line))

:::::::obj loader::::::::::: # Blender 4.1.1
app.js:1976 :::::::obj loader::::::::::: # www.blender.org
app.js:1976 :::::::obj loader::::::::::: mtllib door1.mtl
app.js:1976 :::::::obj loader::::::::::: g Cube_Mesh
app.js:1976 :::::::obj loader::::::::::: s 0
app.js:1976 :::::::obj loader::::::::::: usemtl Material
app.js:1976 :::::::obj loader::::::::::: l 1 17
app.js:1976 :::::::obj loader::::::::::: l 2 18
app.js:1976 :::::::obj loader::::::::::: l 5 19
app.js:1976 :::::::obj loader::::::::::: l 6 20
app.js:1976 :::::::obj loader::::::::::: g Cube.ME.COLLIDER_Mesh
app.js:1976 :::::::obj loader::::::::::: s 0
app.js:1976 :::::::obj loader::::::::::: g Cube.ME.COLLIDER2_Mesh
app.js:1976 :::::::obj loader::::::::::: s 0
app.js:1976 :::::::obj loader::::::::::: 

Unhandled Runtime Error TypeError: Cannot read properties of null (reading ‘default’) occurs on Next.js while fetching blogs using useEffect

While making a portfolio website with Next.js v13 page Router, this is some sort of RunTime error that I’m fetching blogs from dev.to article using api
This api actually fetches blogs but since I have used useEffect so blogsData returns empty at inital loading and fetches later actually.

This is the error message.

Unhandled Runtime Error
TypeError: Cannot read properties of null (reading 'default')

Call Stack
default
node_modulesnextdistsharedlibget-img-props.js (20:15)
isStaticRequire
node_modulesnextdistsharedlibget-img-props.js (26:39)
isStaticImport
node_modulesnextdistsharedlibget-img-props.js (196:8)
props
node_modulesnextdistclientimage-component.js (242:84)
renderWithHooks
node_modulesreact-domcjsreact-dom.development.js (16305:0)
updateForwardRef
node_modulesreact-domcjsreact-dom.development.js (19226:0)
beginWork
node_modulesreact-domcjsreact-dom.development.js (21636:0)
HTMLUnknownElement.callCallback
node_modulesreact-domcjsreact-dom.development.js (4164:0)
Object.invokeGuardedCallbackDev
node_modulesreact-domcjsreact-dom.development.js (4213:0)
invokeGuardedCallback
node_modulesreact-domcjsreact-dom.development.js (4277:0)
beginWork$1
node_modulesreact-domcjsreact-dom.development.js (27451:0)
performUnitOfWork
node_modulesreact-domcjsreact-dom.development.js (26557:0)
workLoopSync
node_modulesreact-domcjsreact-dom.development.js (26466:0)
renderRootSync
node_modulesreact-domcjsreact-dom.development.js (26434:0)
performConcurrentWorkOnRoot
node_modulesreact-domcjsreact-dom.development.js (25738:0)
workLoop
node_modulesschedulercjsscheduler.development.js (266:0)
flushWork
node_modulesschedulercjsscheduler.development.js (239:0)
MessagePort.performWorkUntilDeadline
node_modulesschedulercjsscheduler.development.js (533:0)

I am using useEffect to fetch blogs from dev.to like this

export default function Home() {
  // Loaders
  const [blogsLoading, setBlogsLoading] = useState(true);
  const [mounted, setMounted] = useState(false);
  const [blogsData, setBlogsData] = useState<DevToArticleType[]>([]);

  useEffect(() => {  
    setMounted(true);
    fetch(`https://dev.to/api/articles?username=${profileInfo.devUsername}`)  
      .then(res => {  
        if (!res.ok) {  
          throw new Error('Network response was not ok');  
        }  
        return res.json();  
      })  
      .then(data => {  
        const sortedData = Array.isArray(data) ? data.sort((b, a) =>  
          new Date(b.published_at).getTime() - new Date(a.published_at).getTime()  
        ) : [];
        if(sortedData.length > 0) {
          setBlogsData(sortedData);
          setBlogsLoading(false);
        }
      })  
      .catch(error => {  
        console.error('Error fetching blogs:', error);
      })  
      .finally(() => {  
        setBlogsLoading(false);
      });  
  }, []);  

  if (!mounted) {
    return null;
  }

  console.log("blogsData------->", blogsData);
  const latest_experience: ExperienceType = Experience[0];

  return (
      <>
        ...
          {blogsLoading ? (
            <Loader />
          ) : blogsData?.length > 0 ? (
            <BlogsSection blogs={blogsData} />
          ) : (
            <NoData />
          )}
      </>
   )
}

The console.log message for blogsData shows empty array at initial loading and shows blog detail after that.
But it shows unhandled runtime error.
How to fix that?

Pause asynchronous animation on hover

I want the animation of the hovered ball to pause, others should keep animating. Chat GPT has no clue. According to css hover should also reveal the 2nd image – > this only works when i remove javascript altogether.

Here’s the codepen

const balls = document.querySelectorAll('.ball');

// Function to animate the sway of a ball
function swayBall(ball, offsetAngle) {
    const amplitude = Math.random() * 1 + 1; 
    const speed = Math.random() * 0.02 + 0.01; 

    let angle = offsetAngle; 
    let isHovered = false; 
    let animationId; // 

    function animate() {
        if (!isHovered) {
            angle += speed; 
            const swayAngle = Math.sin(angle) * amplitude; 
            ball.style.transform = `rotate(${swayAngle}deg)`; 
        }
        animationId = requestAnimationFrame(animate); 
    }

    // Start animation
    animate();

    // Stop animation on hover
    ball.addEventListener('mouseenter', () => {
        isHovered = true; // Stop animation
        cancelAnimationFrame(animationId); 
        ball.style.transform = ''; 
        console.log(`Hover started on:`, ball); 
    });

    // Resume animation on mouse leave
    ball.addEventListener('mouseleave', () => {
        isHovered = false; 
        animate(); 
        console.log(`Hover ended on:`, ball); 
    });
}

balls.forEach((ball, index) => {
    const offsetAngle = Math.random() * Math.PI * 2; 
    swayBall(ball, offsetAngle);
});

Animation works fine, but it does not stop on hover, nor does it reveal the image below.

FullCalendar Events from a Function

I am trying the following code to get FullCalendar events from an existing array

events: function(start, end, callback) {
  var events = [];
  for (var i = 0; i < calendarCount; i++) {
    events.push({
      title: calendarObject[i].title,
      start: new Date(calendarObject[i].startDate * 1000),
      end: new Date(calendarObject[i].endDate * 1000),
      allDay: calendarObject[i].isAllDay,
      color: calendarObject[i].color
    });
  }
  console.log(events)
  callback(events);
}

The events array succesfully prints out in the console. But FullCalendar spits out the following error message:

screenshot

Among other variations found, I have also tried this…

for (var i = 0; i < calendarCount; i++) {
  var buildingEvents = $.map(calendarObject, function(item) {
    return {
      title: calendarObject[i].title,
      start: new Date(calendarObject[i].startDate * 1000),
      end: new Date(calendarObject[i].endDate * 1000),
      allDay: calendarObject[i].isAllDay,
      color: calendarObject[i].color
    };
  });
}

…and then just events: buildingEvents
That did not spit out any errors in console but the calendar had no events.

How to accept a empty value for single daterangepicker?

i use a singledaterange picker in a field wich can, but not must have a date. So if a user click into the empty field he can select a date and the date will be moved from the calendar view into the field.
At second time the user open his settings and the field has already a date, now the user want to delete the date completely, how does it works?

Is there a way to delete the entry of a single-daterangepicker field and let it blank?

Here is my code:

$('.singledatepicker').daterangepicker({
  singleDatePicker: true,
  showDropdowns: true,
  minYear: 2023,
  maxYear: parseInt(moment().format('YYYY'),10),
  locale: {
    format: 'DD/MM/YYYY',
  },
  //autoApply:true,
  //autoUpdateInput: false
});

I tried to play around with the “autoApply:true” and “autoUpdateInput: false” but it failed…

Is there a way to use jest-snapshot in a different test framework?

I prefer Jasmine over Jest, but I really like Jest’s snapshot matcher. Apparently, you can install jest-snapshot separately. Is there a way to run it without using Jest as a test runner? Here’s what I’ve tried:

import { expect as jestExpect } from '@jest/globals';

test( ... // Jasmine `test`

    jestExpect(foo).toMatchSnapshot();

...

But this throws an error when I run it:

Error: Do not import `@jest/globals` outside of the Jest test environment

I’m only importing @jest/globals because I don’t know how to pass foo directly into the snapshot API. Does jest-snapshot have an API I can call without needing the jest test runner?

AntD DatePicker and date-fns configuring

As you know rc-picker is a part of AntD DatePicker. We want to use AntD DatePicker with date-fns library and using guide from official source we need to import ‘generateConfig’ file from rc-picker/lib/generate/dateFns.

We have rc-picker like dependency of AntD dependency in node_modules. How we can use this file without extra installing rc-picker

visual studio code – discord.js – online 24/7

I am trying to make a discord bot, and I want to know how to make a discord.js or something like that code that could run the code 24/7, even when my laptop is on sleep mode or visual studio code is closed.
Is there any way I could do that?

I tried searching for solutions, but I just can’t find any way of doing it.

what do I need to change to get these forms to swap without reloading the page? [duplicate]

The script I’m using worked perfectly on a test page with up to three options, but when I try to implement the same script on the forms page it doesn’t work. Clicking the buttons only shows the alternate form for a second before returning to the first form.

This is the relevant section of code, the buttons and script are the same as my test page (only id’s are changed)

<!... lines omitted ...>

<div class="container">
          <form class="form" id="login">
            <h1 class="header-text" id="form-title">Login</h1>
            <div class="form_input-group">
              <label class="form_label" for="user">Email : </label>
              <input type="text" class="form_input" name="user" autofocus>                  
            </div>
            <div class="form_input-group">
              <label class="form_label" for="pwd">Password : </label>
                <input type="text" class="form_input" id="pwd">                    
              <button class="form_button" onclick="alert('You have successfully logged in!')">Login</button>
            </div>
            <div>
              <button class="flip" id=regBtn onclick="goReg()">Don't have an account? Register</button>
            </div>                                 
          </form>          
          <form class="form" id="signup">
            <h1 class="header-text" id="form-title">Register</h1>
            <div class="form_input-group">
              <label class="form_label" for="user">Enter your Email : </label>
              <input type="text" class="form_input" name="user" autofocus>               
            </div>
            <div class="form_input-group">
              <label class="form_label" for="pwd">Enter Password : </label>
              <input type="text" class="form_input" id="pwd">                                    
            </div>
            <div class="form_input-group">
              <label class="form_label" for="pwd">Re-enter Password : </label>
              <input type="text" class="form_input" id="pwd2">                    
              <button class="form_button" onclick="alert('Congratulations! Your account was successfully created.')">Register</button>
            </div>
            <div>
              <button class="flip" id="logBtn" onclick="goLog()">Already have an account? Login</button>              
            </div>                                    
          </form>    
        </div>
  <script>      
function goLog() {
    document.getElementById("login").style.display = "block";
    document.getElementById("signup").style.display = "none";    
  };
        
function goReg() {
    document.getElementById("login").style.display = "none";
    document.getElementById("signup").style.display = "block";          
  };      
  </script>
<!... lines omitted ...>
 

Hostlistener beforeunload not working for navigation within Angular application

I want a banner that says “Settings saved succesfully” to display on the home page of my application, but for it to stop displaying after the user navigates away from the home page. My solution to this is on the save-settings page set a variable settingsSavedSuccesfully in SESSION_STORAGE. The process of saving the settings takes the user back to the home page where the banner uses ngIF to check for settingsSavedSuccesfully. I thought I could then remove that variable when the window beforeunload event is triggered.

I have attempted two ways of implimenting this. First is by adding it within the constructor of the home page

constructor(
    ...
    @Inject(SESSION_STORAGE) private sessionStorage: StorageService,
  ) {
    window.addEventListener("beforeunload", (event) => {
      this.sessionStorage.remove("settingsSavedSuccesfully");
    });
  }

The other is by adding this HostListener method at the bottom of the home page’s TypeScript

@HostListener("window:beforeunload", ["$event"])
  onPageClose(): void {
    this.sessionStorage.remove("settingsSavedSuccesfully");
  }

Refreshing the page will cause either of these to trigger. However, if I navigate away from home, within the application, it seems like beforeunload is not triggered. I have tested this on Google Chrome and on Firefox. I am assuming this is something to do with it being a “single-page web application”.

stewdebaker’s answer under a similar question implies that if things are “configured correctly” the Hostlistener should be able from “both in-app and external navigation at the same time”. Does anyone know if there’s something I need to configure to make HostListener and beforeunload behave in the way I want them to? Did I misunderstood stewdbebaker’s answer?

My Angular CLI is version 18.0.6 incase that’s relevant.

POST API request using PowerQuery in Excel

When using the following code:

let
    url = "https://api.scb.se/OV0104/v1/doris/en/ssd/BO/BO0101/BO0101G/LghHustypKv",
    headers = [#"Content-Type"="application/json"],
    body = "{
            ""query"": [{""code"":""Region"",
                        ""selection"":{""filter"":""item"",""values"":[""00""]}},
                        {""code"":""Hustyp"",
                        ""selection"":{""filter"":""item"",""values"":[""1113"",""21""]}}],
            ""response"": {""format"":""csv""}
            }",
    Source = Json.Document(Web.Contents(url,[Headers = headers,Content = Text.ToBinary(body)]))
in
    Source

I receive the following error:

DataFormat.Error: We found extra characters at the end of the JSON input.
Details:
Value=,
Position=8

As I am new to this, I am not sure what’s wrong. It works in Postman, but cannot get it to work in PowerQuery.

I tried to mimic what’s done here: https://community.fabric.microsoft.com/t5/Power-Query/Sending-a-POST-API-request-using-PowerQuery-on-Excel-PBI-with-a/td-p/2764875

Thanks!

Tailwind classes not extracting from component even when mentioned under content within tailwind.config.ts – Next.js

Problem Statement

Tailwind classes are not being extracted from a particular component even though files is specified under content in tailwind.config.ts

Project Setup

I have 2 projects. Lets call them project A and B. Project A is a common design UI component library, where I am building and exporting components that are then consumed by other projects such as project B.

Dependencies of project A

  • Next.js
  • Tailwind
  • Storybook
  • Radix

Dependencies of project B

  • Next.js
  • Tailwind
  • Project A

Problem Details

I am using tailwindcss dependency to pre-compile the css before exporting project A so that project B can use it out of the box.

However when I run "build:css": "npx tailwindcss -c tailwind.config.ts -i ./src/app/globals.css -o ./dist/styles.css" certain classes from a particular component called nl-header.tsx is not being exported properly.

In particular the responsive classes like lg:col-span-3 and lg:col-span-3 are not being compiled. I know this because I can see the compiled styles.css and lg:col-span-3 and lg:col-span-3 are missing.

I also want to add, all the other classes from all other components are working perfectly, just this component is acting wonky.

I have shared the code for the nl-header.tsx and the resultant styles.css are mentioned below.

I know this is exactly the issue because when I include the project A package within the content of the consuming project which is project B the issues go away

  content: [
    "./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
    "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
    "./src/app/**/*.{js,ts,jsx,tsx,mdx}",
    // "./node_modules/@name-of-package/common-design-system/src/components/header/nl-header.tsx",
    // When I un-comment above line the styles and responsive classes work perfectly
    // because tailwind is able to identify the classes, but it also shows
    // that they are exported by project A
  ],

Project Setup Details

Lets dive in the details of Project A
Folder structure looks like this

.
├── README.md
├── components.json
├── dist
│   ├── index.d.mts
│   ├── index.d.ts
│   ├── index.js
│   ├── index.js.map
│   ├── index.mjs
│   ├── index.mjs.map
│   └── styles.css
├── next-env.d.ts
├── next.config.mjs
├── package-lock.json
├── package.json
├── postcss.config.mjs
├── scripts
├── src
│   ├── Configure.mdx
│   ├── app
│   │   ├── globals.css
│   │   ├── layout.tsx
│   │   └── page.tsx
│   ├── components
│   │   ├── filter
│   │   │   ├── nl-filter.stories.tsx
│   │   │   └── nl-filter.tsx
│   │   ├── header
│   │   │   ├── nl-header.stories.tsx
│   │   │   └── nl-header.tsx
│   │   ├── loading
│   │   │   ├── nl-loading.stories.tsx
│   │   │   └── nl-loading.tsx
│   │   ├── news
│   │   │   ├── ...
│   │   │   ├── ...
│   │   │   ├── ...
│   │   │   └── ...
│   │   ├── primitives
│   │   │   ├── ...
│   │   │   ├── ...
│   │   │   ├── ...
│   │   │   └── ...
│   │   ├── sidebar
│   │   │   ├── ...
│   │   │   ├── ...
│   │   │   ├── ...
│   │   │   └── ...
│   │   ├── tab
│   │   │   ├── nl-tab-bar.stories.tsx
│   │   │   └── nl-tab-bar.tsx
│   │   └── typography
│   │       ├── nl-block-quote-tag.stories.tsx
│   │       ├── nl-block-quote-tag.tsx
│   │       └── ...
│   ├── index.ts
│   └── lib
│       └── utils.ts
├── storybook-static
│   ├── sb-addons
│   │   ├── chromatic-com-storybook-9
│   │   ├── essentials-actions-3
│   │   ├── essentials-backgrounds-4
│   │   ├── essentials-controls-2
│   │   ├── essentials-measure-7
│   │   ├── essentials-outline-8
│   │   ├── essentials-toolbars-6
│   │   ├── essentials-viewport-5
│   │   ├── interactions-10
│   │   ├── onboarding-1
│   │   └── storybook-core-core-server-presets-0
│   ├── sb-common-assets
│   ├── sb-manager
│   └── sb-preview
├── tailwind.config.ts
├── tsconfig.json
└── tsup.config.ts

tailwind.config.ts looks like this – I have tried adding classes to the safe list, but it does not work completely (some classes are still missing) and I do not see this is as a scalable solution.

import type { Config } from "tailwindcss";
import tailwindcssAnimate from "tailwindcss-animate";

const config: Config = {
  darkMode: ["class"],
  content: [
    "./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
    "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
    "./src/app/**/*.{js,ts,jsx,tsx,mdx}",
    "./.storybook/**/*.{js,ts,jsx,tsx,mdx}",
    "./src/**/*.{js,ts,jsx,tsx,mdx}",
  ],
  theme: {
    extend: {
      colors: {
        background: "hsl(var(--background) / <alpha-value>)",
        foreground: "hsl(var(--foreground) / <alpha-value>)",
        ...
        ...
        ...
        ...
        ...
      },
    },
  },
  plugins: [tailwindcssAnimate],
  safelist: [], // I have tried adding classes here to no avail
};
export default config;

postcss.config.mjs looks like this

/** @type {import('postcss-load-config').Config} */
const config = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};

export default config;

tsup.config.ts looks like this

// tsup.config.ts
import { defineConfig } from "tsup";

export default defineConfig({
  entry: ["src/index.ts"],
  format: ["cjs", "esm"],
  external: ["react", "react-dom"],
  dts: true, // Enable declaration files
  clean: true,
  splitting: false,
  sourcemap: true,
  minify: false,
  target: "esnext",
});

package.json looks like this, pay special attention to the build and build:css command

{
  "name": "...",
  "version": "0.1.84",
  "private": false,
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "peerDependencies": {
    "react": ">=16.8.0 <19.0.0",
    "react-dom": ">=16.8.0 <19.0.0"
  },
  "files": [
    "dist/",
    "src/",
    "README.md",
    "dist/styles.css"
  ],
  "publishConfig": {
    "registry": "..."
  },
  "scripts": {
    "build:css": "npx tailwindcss -c tailwind.config.ts -i ./src/app/globals.css -o ./dist/styles.css",
    "build": "tsup src/index.ts --format cjs,esm --dts && npm run build:css --external react,react-dom",
    "storybook": "storybook dev -p 6006",
    "build-storybook": "storybook build",
    "prepare": "npm run build",
    "dev": "next dev"
  },

nl-header.tsx looks like this

import React, { useState } from "react";
import * as Select from "@radix-ui/react-select";
import { ChevronDown, ChevronUp, X } from "lucide-react";
import { LargeTextTagNL } from "@/components/typography/nl-large-text-tag";
import * as Avatar from "@radix-ui/react-avatar";
import * as Popover from "@radix-ui/react-popover";
import { MutedTextTagNL } from "../typography/nl-muted-text-tag";

import { NLSideBarItem } from "@/components/sidebar/nl-side-bar-item";
import { NLLogo } from "@/components/primitives/nl-logo";
import * as Dialog from "@radix-ui/react-dialog";
import { Menu } from "lucide-react";
import { H4TagNL } from "@/components/typography/nl-h4-tag";
import { PTagNL } from "@/components/typography/nl-p-tag";

export interface Property {
  id: string;
  name: string;
}

export interface HeaderSideBarElementInterface {
  icon: React.ReactNode;
  title: string;
  onClick: () => void;
}

export interface NLHeaderProps {
  properties: Property[];
  avatarImage?: string;
  firstName: string;
  lastName?: string;
  email: string;
  id: string;
  popoverItems: Array<{ element: React.ReactNode; onClick: () => void }>;
  sideBarElements: HeaderSideBarElementInterface[];
  logoLabel: string;
  version: string;
}

export function NLHeader({
  properties,
  avatarImage,
  firstName,
  lastName,
  email,
  popoverItems,
  logoLabel, // sideBarElements --> START HERE
  sideBarElements,
  version,
}: NLHeaderProps) {
  // SideBar State Variables
  const [dialogOpen, setDialogOpen] = useState(false);
  const [active, setActive] = useState(sideBarElements?.[0]?.title);

  // Header State Variables
  const [currentProperty, setCurrentProperty] = useState(properties[0].name);
  const [isOpen, setIsOpen] = useState(false);

  return (
    <Dialog.Root open={dialogOpen} onOpenChange={setDialogOpen}>
      {/* Mobile View - for the side bar*/}
      <div className="md:hidden">
          ... // This part of the code is working fine
      </div>
      {/* Header */}
      {/* Especially the responsive classes are not working */}
      <div className="grid grid-cols-12 h-[10vh] w-full">
        <div className="col-span-2 lg:hidden flex items-center justify-center"> // These classes are not exporting
          <Dialog.Trigger asChild>
            <button>
              <Menu />
            </button>
          </Dialog.Trigger>
        </div>
        <div className="col-span-5 lg:col-span-9">
          <div className="hidden lg:flex items-center justify-start gap-4 p-5"> // These classes are not exporting
                ...
                ...
          </div>
        </div>
        <div className="col-span-5 lg:col-span-3 flex items-center justify-end gap-4 p-5"> // These classes are not exporting
           ...
           ...
        </div>
      </div>
    </Dialog.Root>
  );
}

Here is the resultant styles.css in the dist folder

https://codefile.io/f/FdIxH5kx5u#

Lets also look at the consuming project B briefly to rule out any potential issues there. The setup is similar to the project A. There are the addons:

Importing the styles from the package of project A

import "@name-of-the-package/common-design-system/dist/styles.css"; // Import the design system styles
import "./globals.css";

Here is how the header component is being consumed:

"use client";

import React from "react";
import { useAuth0 } from "@auth0/auth0-react";
import { useEffect, useState } from "react";
import { AppDispatch, RootState } from "@/lib/store";
import { useDispatch, useSelector } from "react-redux";
import { fetchClaims } from "@/lib/redux/authSlice";
// import { setLocaleLang } from "@/lib/redux/localeSlice";

import {
  NLSideBar,
  NLHeader,
  NLFilter,
  NLTabBar,
  H1TagNL,
  NLNewsFeed,
  NLLoading,
} from "@name-of-the-package/common-design-system";
import {
  Calendar,
  CreditCard,
  FileSearch,
  House,
  LogOut,
  Moon,
  Network,
  Newspaper,
  Sun,
  Users,
  Wrench,
} from "lucide-react";
import { useTheme } from "next-themes";

// Create typed hooks for better TypeScript support
const useAppDispatch = () => useDispatch<AppDispatch>();
const useAppSelector = useSelector.withTypes<RootState>();

interface Dictionary {
  HomePage: {
    sideBarItemHomePage: string;
    sideBarItemCommunity: string;
    sideBarItemPolicies: string;
    sideBarItemMaintainance: string;
    sideBarItemPayments: string;
  };
}

interface CustomClaim {
  id: string;
  email: string;
  picture: string;
  firstName: string;
  lastName: string;
  internalRoles: string[];
}

export default function HomePage() {
    ...
    ...
    ...
    ...
    ...
    ...

  // Render dashboard if authenticated
  return (
    <div className="h-screen w-screen">
      <div className="grid grid-cols-1 xl:grid-cols-8">
        {/* Sidebar */}
        <div className="hidden xl:block xl:col-span-1 min-w-fit bg-white dark:bg-slate-800">
          <NLSideBar
            className="px-1.5"
            sideBarElements={sideBarData?.sideBarElements}
            logoLabel={sideBarData?.logoLabel}
            version={sideBarData?.version}
          />
        </div>
        {/* Main content */}
        <div className="col-span-7">
          <div className="h-[10vh] border-red-400 border-4">
            <NLHeader
              id={id}
              popoverItems={popoverItems}
              email={email}
              properties={headerData?.properties}
              avatarImage={headerData?.avatarImage}
              firstName={headerData?.firstName}
              lastName={headerData?.lastName}
              sideBarElements={sideBarData?.sideBarElements}
              logoLabel={sideBarData?.logoLabel}
              version={sideBarData?.version}
            />
          </div>
          <div className="grid grid-cols-1 xl:grid-cols-10 w-full h-[90vh]">
            {/* Filter section */}
            <div className="col-span-1 xl:col-span-2 px-8 pt-5 lg:px-3">
              <NLFilter filters={homeFilters} />
            </div>
            {/* Tab bar section */}
            <div className="col-span-1 xl:col-span-7 px-8 lg:pt-0 flex justify-center">
              <NLTabBar tabBarElements={tabData} />
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

I have read all surrounding dicussions, tried safelist approach, tailwind imports in the globals.css file etc to no avail.

@connect tag not working in TamperMonkey/Chrome?

I have an issue similar to this one, except—as far as I can tell—my directives are correct as per the answer on that question.

My header is as follows:

// ==UserScript==
// @name         My Userscript
// @namespace    com.example.my-userscript
// @version      0.2.14
// @description  Do things
// @author       Doktor J
// @match        https://example.com/index.php?id=*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=example.com
// @require      https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js
// @require      https://example.org/path/jquery-csv.min.js
// @license      Mozilla Public License 2.0
// @grant        GM_addStyle
// @grant        GM_xmlhttpRequest
// @connect      example.org
// ==/UserScript==

However, when I call the following:

GM_xmlhttpRequest({
    method: "GET",
    url: "https://example.org/path/data.csv",
    onload: function (response) {
        console.log(response.status);
        myData = $.csv.toObjects(response.responseText);
    }
});

I still get the following error:

VM122:10 injected: Refused to connect to "https://example.org/path/data.csv": URL is not permitted

How to import multiple custom JS files into one main ‘app.js’ file?

I am using Webpack for my website and in my src/js/ I have created three files ; app.js, gsap-animations.js and script.js. My initial idea was to import my other custom js files into one single js file (in this case app.js) just like this :

// -------------------------------------------------------------------
// ----- import node_modules scripts
// -------------------------------------------------------------------

import $ from "jquery";
import "bootstrap";
import gsap from "gsap";
import ScrollTrigger from "gsap/ScrollTrigger";


// -------------------------------------------------------------------
// ----- import custom scripts
// -------------------------------------------------------------------

import "./script.js";
import "./gsap-animations.js";

The first custom file, script.js, loads up fine ; I am using jquery and have functions in there that I can see loaded up on my website. It’s clearly doing things. Weirdly enough though, the second custom file, gsap-animations.js, does not ever load. I was just testing around as I am pretty new with GSAP to begin with :

gsap.to('.test-img', {
    ScrollTrigger: '.test-img',
    y: 500,
    duration: 3
});

This is supposed to make my image move on the y axis whenever it comes into the viewport.

After some fiddling around, I realized that if I move the import gsap from "gsap"; AND import scrollTrigger from "gsap/ScrollTrigger"; INTO gsap-animations.js, IT WORKS. The question is WHY ?

Am I missing something ? Clearly, I use jquery in script.js but have the import $ from "jquery"; in the app.js file, not script.js. I am able to use jquery in script.js just fine though.

So why when it comes to GSAP I have to load it up in the specific file where I am using GSAP ? Am I just too dumb to notice something obvious here ?

Sorry, I know this is pretty newbie. I’m just confused and this is also extremely hard to explain so feel free to ask for clarification.

Convert Multipart/mixed format into XML or Json

I want to convert multipart/mixed format into either XMl or Json format.
I built up sample code that generate XML, but this code did not expected.
This java script has to be built in BTP CI

Input:

--789901289D3B067293B4A5D8BC2033B80
        Content-Type: application/http
        Content-Length: 1279
        content-transfer-encoding: binary
        
        HTTP/1.1 404 Not Found
        Content-Type: application/json;odata.metadata=minimal;charset=utf-8
        Content-Length: 1097
        
        {
        "error": {
            "code": "/SCWM/ODATA_API/126",
            "message": "task item 1 doesn't exist in warehouse1.",
            "target": "$Parameter/_it",
            "@SAP__core.ContentID": "1",
            "details": {
                "message": "task 1 doesn't exist in warehouse."
            }
        }
    }

--789901289D3B067293B4A5D8BC2033B80--

JS code:

importClass(com.sap.gateway.ip.core.customdev.util.Message);

function processData(message) {
    //Body
    var body = message.getBody(java.lang.String);
    
    var docstart = body.indexOf('HTTP/1.1 404 Not Found') + 16;
    var documentValue = body.substr(docstart, body.indexOf('---', docstart)
    - docstart);
    documentValue=documentValue.trim();
           var resp = '<error><info>';
            resp = resp.concat(documentValue);
            resp = resp.concat('</info><error>');
            
            message.setPayload(resp);

    return message;
}

Output expected

<error>
<info>{
        "error": {
            "code": "/SCWM/ODATA_API/126",
            "message": "Task item 1 doesn't exist in warehouse1.",
            "target": "$Parameter/_it",
            "@SAP__core.ContentID": "1",
            "details": {
                "message": "task 1 doesn't exist in warehouse."
            }
        }
    }</info></error>

Thank you in advance.

With Best Regards,
Sateesh