ngx-libs-workspace

April 25, 2026 · View on GitHub

ngx-libs-workspace

A small family of reactive Angular form controls — built on Signal Forms, themable via CSS custom properties, and free of Angular Material, CDK and ControlValueAccessor.

ci deploy playground CodeQL Coverage Status FOSSA Status

Live playground · Releases · Issues


The libraries

LibraryWhat it isnpmDemo
ngx-pass-code
OTP / pass-code input — one box per character, with paste-anywhere, autofocus/autoblur, and text / number / password modes.
ngx-pass-code previewnpm dltry it ↗
ngx-numeric-range-form-field
Composite numeric range — two number inputs, one value. Four composable validators for order, bounds, completeness and span.
ngx-numeric-range-form-field previewnpm dltry it ↗
ngx-phone-form-field
International phone field — country picker with flags + national-number input as a single E.164 string. Powered by libphonenumber-js/max.
ngx-phone-form-field previewnpm dltry it ↗
ngx-time-range-form-field
Composite time range — two <input type="time"> fields, one value. Four composable validators for order, bounds, completeness and span; mixed HH:mm / HH:mm:ss precision normalised before comparison.
ngx-time-range-form-field previewnpm dltry it ↗
ngx-overflow-tooltip
Headless directive — flags whether a host element's text is ellipsized via ResizeObserver + MutationObserver, exposes an isTruncated signal so any tooltip surface (Material, custom popover, plain title) only fires when the content is actually clipped.
ngx-overflow-tooltip previewnpm dltry it ↗

What every lib in here gives you

  • Standalone — no module to register, no peer dep on Angular Material, CDK or any third-party runtime.
  • Signal-based inputs end-to-end. Form-field libs implement FormValueControl and plug into a parent form() schema via [formField]; the directive lib (ngx-overflow-tooltip) exposes its state as a public signal.
  • Form-field libs ship outlined styling reskinnable via CSS custom properties — no ::ng-deep, no global CSS leaks. Schema-driven validation (required, readonly, disabled, validate, …) is owned by the consumer's form() definition.
  • OnPush change detection, zoneless-friendly setup.
  • Tree-shakable (sideEffects: false), npm-published with provenance.

The form-field libs target @angular/forms/signals, which is marked @experimental 21.0.0. Consumers adopt the same experimental surface.


Workspace layout

ngx-libs-workspace/
├─ apps/
│  ├─ playground/          # demo app deployed to GitHub Pages
│  └─ playground-e2e/      # Cypress end-to-end tests
└─ libs/
   ├─ ngx-pass-code/                    # publishable
   ├─ ngx-numeric-range-form-field/     # publishable
   ├─ ngx-phone-form-field/             # publishable
   ├─ ngx-time-range-form-field/        # publishable
   └─ ngx-overflow-tooltip/             # publishable

Quick start

corepack enable
pnpm install --frozen-lockfile
pnpm nx serve playground   # → http://localhost:4200

The playground live-reloads on source changes and consumes all five libraries directly from libs/ — no rebuild needed.

Requires Node.js >=20.19 (see .nvmrc) and pnpm >=10 (pinned in package.json).


Daily commands

All commands run from the repo root via pnpm. Every command is Nx-cached — re-runs return instantly when nothing changed.

Lint
pnpm nx lint ngx-pass-code
pnpm nx lint ngx-numeric-range-form-field
pnpm nx lint ngx-phone-form-field
pnpm nx run-many -t lint            # everything
pnpm nx affected -t lint            # only what changed vs. main
Test
pnpm nx test ngx-pass-code
pnpm nx test ngx-numeric-range-form-field
pnpm nx test ngx-phone-form-field
pnpm nx run-many -t test            # everything
pnpm nx affected -t test            # only what changed vs. main

Coverage for the publishable libraries:

pnpm ngx-pass-code:test:ci
pnpm ngx-numeric-range-form-field:test:ci
pnpm ngx-phone-form-field:test:ci
Build
pnpm nx build ngx-pass-code                   # → dist/libs/ngx-pass-code
pnpm nx build ngx-numeric-range-form-field    # → dist/libs/ngx-numeric-range-form-field
pnpm nx build ngx-phone-form-field            # → dist/libs/ngx-phone-form-field
pnpm nx build playground                      # → dist/apps/playground
pnpm nx run-many -t build                     # everything
Library publish dry-run
pnpm ngx-pass-code:publish:dry-run
pnpm ngx-numeric-range-form-field:publish:dry-run
pnpm ngx-phone-form-field:publish:dry-run
Workspace graph
pnpm nx graph

Releasing libraries

Publishing is fully automated for every library in this workspace:

  1. Commit to main using Conventional Commits (feat:, fix:, feat!:, …). Affected files determine which library gets a release PR.

  2. release-please opens/updates a release PR per library, bumping libs/<lib>/package.json and CHANGELOG.md.

  3. Merging the release PR creates a GitHub Release + tag of the form <lib-name>@x.y.z (e.g. ngx-pass-code@2.0.1, ngx-phone-form-field@1.0.0).

  4. The tag triggers the matching publish workflow:

    Each runs nx build <lib> --configuration=production and npm publish --provenance --access public using the NPM_TOKEN repo secret (OIDC-backed provenance).

Consumer-facing docs live in each lib's README — see the table at the top.


Contributing

  1. Create a feature branch off main.
  2. Commit with Conventional Commit messages — a commit-msg husky hook runs commitlint to enforce this.
  3. Pre-commit runs Prettier on staged files and nx affected -t lint on the affected projects.
  4. Open a PR; CI (ci.yml) runs lint, test, build in parallel via nx affected and publishes coverage to Coveralls.

License

MIT © Dino Klicek · See the FOSSA report.