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.
The libraries
| Library | What it is | npm | Demo |
|---|---|---|---|
| ngx-pass-code OTP / pass-code input — one box per character, with paste-anywhere, autofocus/autoblur, and text / number / password modes. | ![]() | try it ↗ | |
| ngx-numeric-range-form-field Composite numeric range — two number inputs, one value. Four composable validators for order, bounds, completeness and span. | ![]() | try 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. | ![]() | try 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. | ![]() | try 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. | ![]() | try 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
FormValueControland plug into a parentform()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'sform()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 inpackage.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:
-
Commit to
mainusing Conventional Commits (feat:,fix:,feat!:, …). Affected files determine which library gets a release PR. -
release-pleaseopens/updates a release PR per library, bumpinglibs/<lib>/package.jsonandCHANGELOG.md. -
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). -
The tag triggers the matching publish workflow:
publish-ngx-pass-code.ymlpublish-ngx-numeric-range-form-field.ymlpublish-ngx-phone-form-field.ymlpublish-ngx-time-range-form-field.ymlpublish-ngx-overflow-tooltip.yml
Each runs
nx build <lib> --configuration=productionandnpm publish --provenance --access publicusing theNPM_TOKENrepo secret (OIDC-backed provenance).
Consumer-facing docs live in each lib's README — see the table at the top.
Contributing
- Create a feature branch off
main. - Commit with Conventional Commit messages — a
commit-msghusky hook runs commitlint to enforce this. - Pre-commit runs Prettier on staged files and
nx affected -t linton the affected projects. - Open a PR; CI (
ci.yml) runslint,test,buildin parallel vianx affectedand publishes coverage to Coveralls.
License
MIT © Dino Klicek · See the FOSSA report.




