npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@namphuongtechnologi/np-hub

v0.2.4

Published

NP Hub Web Component toolkit for support flows.

Readme

@namphuongtechnologi/np-hub

Floating support widget for Nam Phương So applications. Drop it into any static site or React app — users open a form, submit a support request, and the request is sent to the Nam Phương API.

npm version License: MIT


Features

  • Web Component (<np-hub>) — works in plain HTML and most frameworks
  • React wrapper — typed SupportWidget component
  • Drag-and-drop launcher — position persists in localStorage
  • Form prefill — optional user / content / attachment seeding; required fields still validated on submit
  • Submit feedback toast — centered popup on success or API error; auto-closes or user can dismiss
  • Configurable stacking — optional zIndex (default 10000)
  • Environment switch — Production by default; Development via isDev / is-dev

Installation

npm install @namphuongtechnologi/np-hub

Peer dependency (React wrapper only): react >= 18

CDN (static HTML, no bundler): pin the version to match the package you want (current: 0.2.3):

https://cdn.jsdelivr.net/npm/@namphuongtechnologi/[email protected]/dist/np-hub.min.global.js

Quick start

Static HTML (CDN)

Create a config script, then include it once in your page.

np-hub.js

var NP_HUB_CDN =
  "https://cdn.jsdelivr.net/npm/@namphuongtechnologi/[email protected]/dist/np-hub.min.global.js";

function initNpHub() {
  var widget = document.createElement("np-hub");

  widget.setConfig({
    projectId: "NPP",
    isDev: false,
    priority: 0,
    coordinators: [],
    emailContacts: [],
  });

  document.body.appendChild(widget);

  widget.addEventListener("np-hub-submit-success", function (event) {
    console.log("Support request created:", event.detail);
  });

  widget.addEventListener("np-hub-submit-error", function (event) {
    console.error("Support request failed:", event.detail);
  });
}

var script = document.createElement("script");
script.src = NP_HUB_CDN;
script.onload = initNpHub;
document.head.appendChild(script);

index.html

<!doctype html>
<html lang="vi">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My Site</title>
  </head>
  <body>
    <script src="./np-hub.js"></script>
  </body>
</html>

Web Component via npm (bundler)

import "@namphuongtechnologi/np-hub/widget";

const widget = document.createElement("np-hub");
widget.setConfig({
  projectId: "NPP",
  isDev: false,
});
document.body.appendChild(widget);

React

Requires React >= 18. Mount once at the application root (App.tsx, main.tsx, or root layout).

import { SupportWidget } from "@namphuongtechnologi/np-hub/react";

export default function App() {
  return (
    <>
      {/* app content */}
      <SupportWidget
        projectId="NPP"
        isDev={false}
        priority={0}
        coordinators={[]}
        emailContacts={[]}
        onSubmitSuccess={(detail) => console.log("Success:", detail)}
        onSubmitError={(error) => console.error("Error:", error)}
      />
    </>
  );
}

Configuration

setConfig / React props

| Name | Required | Default | Description | | --------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------- | | projectId | React: yes · WC: no | — | Project code forwarded to the API. If set, must be a non-empty string. | | isDev | No | false | true → Development API; otherwise Production | | priority | No | — | Request priority. Sent only when set (number). | | coordinators | No | [] | Coordinator email list | | emailContacts | No | [] | Contact emails that receive the notification | | toastDuration | No | 4000 | Toast auto-close delay in ms. Number, or { success?: number, error?: number } | | zIndex | No | 10000 | CSS z-index of the floating widget. Omit to keep the default. |

Prefill (optional)

| Name | Method / prop | Description | | ------------ | -------------------------------- | --------------------------------------------------------------------------- | | User | setUser / user | Prefills name, email, phone. Form UI still requires these fields on submit. | | Form content | setFormPrefill / formPrefill | Prefills content and attachments (array of URL strings; fetched on submit). |

// Web Component
widget.setUser({
  name: "Nguyen Van A",
  email: "[email protected]",
  phoneNumber: "0912345678",
});

widget.setFormPrefill({
  content: "Describe the issue...",
  attachments: ["https://example.com/screenshot.png"],
});
// React
<SupportWidget
  projectId="NPP"
  user={{
    name: "Nguyen Van A",
    email: "[email protected]",
    phoneNumber: "0912345678",
  }}
  formPrefill={{
    content: "Describe the issue...",
    attachments: ["https://example.com/screenshot.png"],
  }}
/>

Launcher size & position

Default: 65×65px, anchored 20px from the bottom-right corner.

| Attribute / prop | Description | | ------------------ | --------------------------------------------------- | | width / height | Launcher size (default 65) | | right / bottom | Offset from bottom-right (default 20) | | left / top | Use instead of right / bottom for other corners |

Numeric values from React props are treated as pixels. After the user drags the launcher, the stored localStorage position takes precedence.

widget.setAttribute("right", "24");
widget.setAttribute("bottom", "24");
<SupportWidget projectId="NPP" right={24} bottom={24} />

Stacking order (zIndex)

Default: 10000. Raise it if the widget sits under other overlays on the host page.

widget.setConfig({ projectId: "NPP", zIndex: 20000 });
// or: widget.setAttribute("z-index", "20000");
<SupportWidget projectId="NPP" zIndex={20000} />

Submit feedback toast

After a successful API submit or an API/exception failure, the widget shows a centered toast with the result message.

| Behavior | Detail | | ----------------- | ----------------------------------------------------------------------------------------------------- | | When shown | Submit success, or API / runtime error | | When hidden | Missing required fields (only inline field highlighting) | | Auto-close | After toastDuration ms (default 4000). Pauses countdown on cursor hover. | | Copy actions | Success toast: quick-copy for request code and lookup URL | | Manual close | User can dismiss via the × button | | Success follow-up | Modal closes automatically after the success toast auto-closes (toastDuration / success value) |

toastDuration can be a single number (applies to both success/error) or structured with separate values:

widget.setConfig({
  projectId: "NPP",
  toastDuration: {
    success: 3000, // closes success toast after 3s
    error: 8000, // keeps error toast open for 8s
  },
});
<SupportWidget
  projectId="NPP"
  toastDuration={{ success: 3000, error: 8000 }}
/>

Events & methods

Events (Web Component)

| Event | When | | ----------------------- | -------------------------------- | | np-hub-open | Modal opens | | np-hub-close | Modal closes | | np-hub-submit-success | API accepted the support request | | np-hub-submit-error | Validation or API failure |

React equivalent props: onOpen, onClose, onSubmitSuccess, onSubmitError.

Methods (Web Component)

| Method | Description | | ---------------------- | ---------------------------------------------------------------------- | | setConfig(config) | Apply project / API settings | | setUser(user) | Prefill requester fields | | setFormPrefill(data) | Prefill content / attachment URLs | | open() / close() | Open or close the modal | | showDemoToast(type) | Show a dummy toast for testing/dev ("success" or "error") |


Package entry points

| Import | Use when | | -------------------------------------- | --------------------------------------------- | | @namphuongtechnologi/np-hub/react | React apps (SupportWidget) | | @namphuongtechnologi/np-hub/widget | Register <np-hub> in a bundler / vanilla JS | | @namphuongtechnologi/np-hub | Types + registerSupportWidget / element |

CDN users only need the np-hub.min.global.js script (auto-registers <np-hub>).


API environments

| Environment | Base URL | | -------------------------------- | --------------------------------------------- | | Production (default) | https://namphuong-api.azurewebsites.net | | Development (isDev / is-dev) | https://namphuong-api-dev.azurewebsites.net |

Use Production on live sites. Reserve Development for local / staging.


Troubleshooting

| Error | Resolution | | ------------------------------------------ | ------------------------------------------------------------------ | | projectId cannot be empty. | If provided, projectId / project-id must be a non-empty string | | user.name/email/phoneNumber is required. | Requester fields are required on submit; user only prefills | | Content is required. | User must enter message content before submit | | Widget hidden under modals / sticky UI | Raise zIndex (default 10000) | | API call fails in local testing | Set isDev / is-dev when targeting the Development environment | | CDN 404 / old behavior | Pin CDN URL to the same version as the npm package you intend |


More docs (shipped in the package)

| Document | Audience | | ------------------------------------------------ | ------------ | | docs/USAGE_STATIC_REACT.md | Integrators | | docs/DEVELOPER_GUIDE.md | Contributors | | docs/PUBLIC_RELEASE.md | Maintainers |

After npm install, these files live under node_modules/@namphuongtechnologi/np-hub/docs/.


License

MIT © Nam Phương So