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

@mosaicoo/form-angular

v0.9.3

Published

Angular renderer for Mosaicoo Form: accessible, token-themable dynamic forms with wizard mode and host-provided dynamic options

Readme

@mosaicoo/form-angular

Angular renderer for Mosaicoo Form: renders dynamic forms at runtime from a schema (or any definition an importer understands), with validation, conditional visibility, repeatable rows, tabs and wizard mode — accessible by default and themable by CSS tokens.

import { FormRendererComponent } from '@mosaicoo/form-angular';

@Component({
  imports: [FormRendererComponent],
  template: `
    <mform-renderer
      [source]="definition"
      [optionsProviders]="providers"
      [messages]="ptBr"
      (submitted)="onSubmitted($event)"
    />
  `,
})
export class MyPage {}

Highlights

  • Standalone, signals, zoneless-ready — Angular 21+, OnPush throughout.
  • Accessible by default — linked labels, aria-required/invalid/ describedby, role=alert errors, focus moves to the first invalid field on submit.
  • Wizard mode — schemas with display: 'wizard' render top-level containers as steps; Next is blocked by per-step validation and submit jumps to the step owning the first error.
  • Dynamic options without scripts[optionsProviders] maps named providers to host functions (authenticated APIs, caching, tenant catalogs); refreshOn re-resolves when observed data changes.
  • Own look, host's brand — every style reads a --mform-* CSS custom property with a built-in fallback. Define the tokens on any ancestor and the form adopts your design system; override [labels] and [messages] to localize.

Designer

Visual authoring ships as a separate entry point — apps that only render never load it:

import { FormDesignerComponent } from '@mosaicoo/form-angular/designer';
<mform-designer [source]="definition" (schemaChanged)="save($event)" />

Palette, canvas with selection, structure tree, property inspector, undo/redo (Ctrl+Z/Y), duplicate/delete/move, live schema diagnostics, import/export and a Preview mode with test data. The host owns persistence: schemaChanged hands you the versioned schema document.

Custom types in the palette — register the component in the runtime and contribute a palette entry; the Inspector edits its settings through the props JSON editor, so a board, a map or a chart becomes a first-class field:

<mform-designer [extraCatalog]="[{
  label: 'My components',
  entries: [{ type: 'board', label: 'Board', icon: '▤', create: (schema) => ({
    kind: 'input', key: generateKey(schema, 'board'), type: 'board',
    dataType: 'object', props: { columns: ['To do', 'Doing', 'Done'] },
  }) }],
}]" />

Workspace — panels (Fields, Structure, Properties) dock left or right or hide, with presets and per-user persistence, like a professional IDE.

Drag and drop — drag palette entries onto the canvas, INTO containers and into individual columns; reorder nodes by dragging. Drop zones highlight the landing position and the columns map stays consistent automatically.

Localizable — every designer string comes from [labels] (partial overrides fall back to English); translate the palette by passing your own [catalog] (start from DEFAULT_CATALOG).

Resizable docks — drag the splitter between a panel rail and the canvas; widths persist with the layout.

Keyboard — Ctrl+Z/Y undo/redo, Ctrl+D duplicate, Del delete, Alt+↑/↓ move, Alt+→ nest into the container above, Alt+← move out of it, Esc clears the selection.

Responsive preview — preview at desktop, tablet or mobile width. Layout reacts to the FORM's own width (CSS container queries), so a form inside a narrow drawer stacks its columns even on a wide screen.

Reusable blocks — save any subtree as a named block and drop it into other forms (keys are regenerated). Blocks persist locally by default; bind [blocks] / (blocksChanged) to store them wherever your platform keeps shared assets.

The canvas renders leaves with the RUNTIME components and the runtime theme, so what you design is exactly what your users get.

Material Design 3 adapter

Optional entry point (requires @angular/material, an optional peer):

import { provideMaterialForms } from '@mosaicoo/form-angular/material';

bootstrapApplication(App, { providers: [provideMaterialForms()] });

Swaps text/number/select/checkbox/radio (and friends) for Material components styled by YOUR M3 theme; unmapped types keep the accessible built-in renderers. Individual types can still be overridden by later provideMosaicooForm({components}) calls.

Extending

// Register custom field components and your HTTP transport once:
bootstrapApplication(App, {
  providers: [
    provideMosaicooForm({
      components: { signature: SignatureFieldComponent }, // new or overridden types
      remoteFetcher: (url) => api.get(url),               // auth/caching stay yours
    }),
  ],
});

A registered component receives field, engine, path and tick as signal inputs and talks to the form exclusively through the engine (engine.getValue/setValue/markTouched) — validation, conditional visibility and events keep working with no extra wiring.

Theming example

:root {
  --mform-primary: #0f766e;
  --mform-radius: 2px;
  --mform-font: Georgia, serif;
}