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

@bitforgehq/ui

v0.3.0

Published

Bitforge UI: Angular 22 widgets (Meadow Sage design, Tailwind v4, signals-first) and, from v0.2, a Capacitor app shell.

Readme

@bitforgehq/ui

Bitforge's shared Angular component library: Meadow Sage design, Tailwind CSS v4, signals-first, Angular 22.

  • Widgets: @bitforgehq/ui
  • Number field: @bitforgehq/ui/number-input (bf-number-input; loads Angular Forms, peer dependency @angular/forms)
  • Icons: @bitforgehq/ui/icons (Lucide data, peer dependency lucide)
  • Overlay core: @bitforgehq/ui/overlay (no Capacitor; peer dependencies @angular/cdk and rxjs)
  • Mobile shell: @bitforgehq/ui/mobile (from v0.2)
  • Test support: @bitforgehq/ui/testing (jsdom shims, provideBfTesting(), CDK component harnesses; needs @angular/cdk as a dev dependency)

Install, theming and every component's API are documented for humans and agents in ai/UI_GUIDE.md and ai/components/*.md inside this package, and at the docs site (https://bitforge-ui.web.app).

Install

1. Check the prerequisites

Node 22.22.3 or later in the 22 line, 24.15 or later in the 24 line, or 26 and later (the Angular CLI 22 range ^22.22.3 || ^24.15.0 || >=26.0.0; it refuses older versions and warns on odd releases such as 23 and 25), Bun 1.3 or later and the Angular CLI 22.

node --version # v22.22.3+, v24.15+ or v26+
bun --version # 1.3 or later
bun add --global @angular/cli@22

2. Create the app

A new Angular 22 app with plain CSS styles. Skip this step in an existing app.

ng new my-app --style css --package-manager bun
cd my-app

3. Add Tailwind CSS

The theme is a Tailwind CSS 4 theme. ng add tailwindcss installs Tailwind and its PostCSS plugin and writes .postcssrc.json.

ng add tailwindcss

4. Add the packages

lucide provides the icon data for bf-icon; the two @fontsource packages provide the Manrope and JetBrains Mono fonts.

bun add @bitforgehq/ui lucide @fontsource/manrope @fontsource/jetbrains-mono

5. Wire the theme into styles.css

Replace the contents of src/styles.css. Keep tailwindcss first: the theme redefines the palette its utilities read, and registers the package as a Tailwind source, so no tailwind.config.js is needed.

@import 'tailwindcss';
@import '@bitforgehq/ui/theme.css';
@import '@fontsource/manrope/500.css';
@import '@fontsource/manrope/600.css';
@import '@fontsource/manrope/700.css';
@import '@fontsource/manrope/800.css';
@import '@fontsource/jetbrains-mono/400.css';

6. Theme the page

In src/index.html, give <body> the theme background and text colour, so the page itself follows light and dark mode.

<body class="bg-bg text-text">
  <app-root></app-root>
</body>

7. Switch to dark mode

Add the dark class to <html> (and remove it for light mode). Every token is redefined under .dark, and the theme sets color-scheme, so scrollbars and native controls follow too. Components need no dark: classes.

<html lang="en" class="dark">
  <!-- head and body stay as they are -->
</html>

8. Use a first component

Import a widget from @bitforgehq/ui into the component that uses it. Replace src/app/app.ts with the code below and delete the welcome page it no longer uses, app.html and app.css. app.spec.ts tests that welcome page too: delete its should render title case (or make it check the button), so ng test keeps passing.

import { Component } from '@angular/core';
import { BfButtonComponent } from '@bitforgehq/ui';

@Component({
  selector: 'app-root',
  imports: [BfButtonComponent],
  template: `<bf-button variant="primary">Save</bf-button>`,
})
export class App {}

9. Check it

Run the app and open it: you should now see an indigo, pill-shaped Save button in Manrope on the theme background. With class="dark" on <html>, the whole page is dark.

ng serve

Peer dependencies

@bitforgehq/ui (the widgets entry) needs @angular/common, @angular/core, @angular/forms and lucide (for @bitforgehq/ui/icons and /mobile); these are required peers. The widgets entry loads no @angular/forms code at runtime (its form widgets only implement the Signal Forms interfaces); @bitforgehq/ui/number-input does, since bf-number-input parses through Angular's transformedValue(), so @angular/forms is required for it. The overlay entry @bitforgehq/ui/overlay (the Capacitor-free overlay core) additionally needs @angular/cdk and rxjs (a CDK peer). The mobile entry @bitforgehq/ui/mobile needs those plus @angular/router and @capacitor/core. They are declared optional so a desktop-only install stays free of them: an app that imports /overlay or /mobile installs them itself. The Capacitor plugins @capacitor/app, @capacitor/keyboard and @capacitor/haptics are optional peers too; install only the ones your app uses, and /mobile builds and runs without the others.

Compatibility

@bitforgehq/ui 0.x is client-rendered only. SSR, hydration and prerendering of pages that render its components are not supported or tested. Component ids come from a module-level counter and can differ between server and client, and the shell's theme is read from localStorage on the client. Render library components only in the browser, for example in a @defer block or a client-only route. Support will be decided before 1.0.

The one server-side check is a render smoke, not a support test: the library repository's tools/ssr-smoke.ts renders 28 fixtures with renderApplication() (every root widget, bf-icon, bf-number-input, a /mobile page with provideBfShell(), bf-page, bf-header and bf-content, bf-tabs with bf-stack-outlet under the router, and an /overlay dialog), and all of them render without an error. 19 of them render identically twice. The other 9 number their ids differently on every render, from a module-level counter, so they could not hydrate: bf-checkbox, bf-input, bf-radio-group, bf-segmented, bf-select, bf-textarea, bf-toggle, bf-number-input and the /overlay dialog. Hydration itself is still not supported or tested, and more stands in its way: /mobile writes to <html> and adds a keyboard probe to <body>, and an /overlay dialog renders outside the app root and marks it inert.

Testing

@bitforgehq/ui/testing is for your specs only (Vitest, the Angular CLI default, or Jest) and needs @angular/cdk as a dev dependency (bun add -d @angular/cdk) even in an app that never opens an overlay. Call installBfJsdomShims() in the runner's setup file (the setupFiles of the test target in angular.json): it adds the Web Animations API, PointerEvent and matchMedia where jsdom lacks them. provideBfTesting() passes defaults and labels to the widgets and cleans up what overlays and themes leave on the document after each test (when TestBed destroys the test environment, so keep its default teardown: { destroyAfterEach: true }), and the CDK harnesses (BfSelectHarness, BfRadioGroupHarness, BfSegmentedHarness, BfDialogHarness, BfMenuButtonHarness, BfMenuHarness, BfMenuItemHarness, BfDesktopToastHarness) drive the widgets whose DOM a spec should not query by hand; overlays come from TestbedHarnessEnvironment.documentRootLoader(fixture). An app on the mobile shell uses provideBfShellTesting() from @bitforgehq/ui/mobile instead (router, shell, an in-memory theme store and the same cleanup), so /testing itself never loads Capacitor.

Density and labels

Every field and control shares one height scale (BfSize: sm 32, md 40, lg 48 px) with a compact md default for desktop web apps. Set another step once with provideBfDefaults() in ApplicationConfig.providers ({ size: 'sm' } for a data-dense app, { fieldSize: 'lg' } for a Capacitor app, because under touch the actions and choice controls reach 44 px through an invisible extension but text fields get none, so only the fields need the 48 px step) or in a component's providers for one part of the app, such as a dense toolbar. provideBfLabels() replaces every built-in English string, including the default error text shown for a validator without a message, the same two ways. The docs site's Density and Labels guides list the scale and every string.