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

@restrella/form-builder

v0.2.8

Published

Visual builder for @restrella/form-generator forms. Standalone app, or embed it with mountFormBuilder().

Readme

Form visual builder

📖 Read the documentation → balance3840.github.io/form-builder/ · ▶ Try it in the playground

A visual editor for forms that writes the form-generator v2 JSON under the hood. Built for people who do not want to touch JSON: drag fields in, tweak them in a side panel, restyle the form, preview it on a phone, and hand over the result.

Features

  • Drag and drop 25 field types (text, email, dropdown, single / multiple choice, rating, opinion scale, slider, file upload, dates, country, headings, page breaks…). Click to add, drag to reorder, duplicate, delete, undo / redo (Ctrl/Cmd+Z).
  • WYSIWYG canvas that renders the real generator, so what you build is what people see. Rows and columns like Notion or Tally: drag a field to the left or right edge of another to create columns, stack several fields in a column, pick a layout (1/2 + 1/2, 1/3 + 2/3, 3 equal…) and align rows (top / middle / bottom, left / center / right).
  • Inspector per field: question, help text, options editor (with bulk edit), validation with custom messages, width, conditional logic ("show this when…"), advanced field keys.
  • Multi-step forms with a Page break block, an automatic progress bar and optional step titles. With the Step list layout (advanced view) you can add progress rings per step, a back link at the top of the list (with "Saved 5 minutes ago" via {saved}) and buttons under the steps (send, next step or an event for your page).
  • Address search with friendly settings: pick a provider (OpenStreetMap by default; Google Places, Mapbox, Geoapify, Denmark's official register with your own key; or your own service), countries, city, what is saved, and a Test it box. Own services can also search step by step (street → number → floor and door).
  • Search & pick field: live autocomplete against any JSON endpoint (OpenStreetMap addresses and countries presets), single or multiple with chips. Inputs can have a text before/after (e.g. "m²"), and rows accept custom column widths.
  • Choice fields: pre-selected options (single and multiple), option groups, options per row, and an "Other…" option with a text box. In the advanced view each radio / checkbox option has a More area for a badge ("Most used"), a description, a logo, a "Read more" link and help behind a "?"; the field settings add Show at first (only the first few options, the rest behind "Show more options") and every question can get a Tooltip.
  • Design: 8 themes, colours, fonts, roundness, input style, spacing, button style, custom CSS, with a live preview.
  • Preview on desktop / tablet / phone; submit it to see the data it produces.
  • JSON tab: the form is the JSON. Edit it live, copy it, download it, or get an embed snippet / standalone HTML page.
  • App-like flows: Sections (titled cards), Repeating groups (guests, rooms, items… as cards or a table, with "Add" choices that pre-fill an item, nested groups, a "Done" chip), Buttons with an action list (next step, go to a step, set an answer, add an item, send, open a link, tell your own code), Message boxes, Signatures, choice cards with descriptions, and a step list layout with ticks for finished steps, "Save and exit" and drafts kept in the browser.
  • Dialogs, tabs and item pages: pop-up forms (add / edit an item, set a value on every item, sign), tabs inside a step, repeating items as small cards with a ⋮ menu, a Done button and drag to reorder, opened as their own page with a Back link, choices that come from the items of another group, numbered cards that unlock step by step.
  • Rules: any number of rules per field or block: show, hide, disable, only enable, or make required, based on other answers (inside a repeating group they can use the other fields of the same item, and the number of items).
  • Multi-language (like Typeform): add languages, translate every text side by side in the Translate tab with progress per language (or Export them as a JSON file for a translator or an AI and Import the result: one row per text with its key, where it is, the original and a column per language; a new language column adds that language, empty values and texts no longer in the form are skipped, and one Undo takes the import back), auto-detect the visitor's browser language, an optional flag / dropdown switcher, or force one with language="es". Buttons and default error messages are built in for 9 languages. In JSON → Embed you can export for all languages, force one on the page (language="es"), or get a smaller single-language copy.
  • Spam protection: Cloudflare Turnstile, hCaptcha, Google reCAPTCHA v2 / v3, or a keyless honeypot, with the provider test keys one click away and a copy-paste server check. Address API keys come with a restriction checklist and a generated Cloudflare Worker proxy to keep the key off the page.
  • Interface in several languages: English, Español, Dansk, Svenska and Português (Portugal), picked from the top bar or the browser's language. Adding a language is adding a folder of JSON files: see src/i18n/README.md.
  • Import / migrate: paste a v1 schema and get a converted v2 form plus a report of every change.
  • Templates: about 40 ready-made forms with search and groups (see Templates), and autosave to the browser.

Installation

npm install @restrella/form-builder @restrella/form-generator

@restrella/form-generator is a peer dependency. Then mount the builder in any page, see Embedding the builder.

Templates

A searchable picker with about 40 ready-made forms in eight groups. Each one is a normal form you can change completely, and each is translated into every interface language.

| Group (templateCategories) | Templates | | --- | --- | | general | contact, support, bug, newsletter, quote, appointment, suggestion | | feedback | feedback, survey, nps, product, website, feature | | events | event, rsvp, workshop, webinar, volunteer | | work | job, timeoff, expense, onboarding, employeeSurvey | | education | course, courseEvaluation, permissionSlip | | health | patientIntake, waiver | | business | order, return, donation, membership | | property | maintenance, report, visitor, parking, moving |

Three more are made for one kind of application and are not offered unless you list them in templateIds:

| Id | What it is | | --- | --- | | inspection | A multi-step property inspection: step list, repeating people / rooms / meters / keys, a table per room, rules and signatures (Danish translation included) | | lease | Fills in the official Danish lease contract (Typeformular A). Set settings.pdf to lease-a10; the PDF itself is made by your server | | waitingList | A sign-up form whose answers use fixed names (first_name, mail, phone…). Some choices (config.optionsFrom: "platform") must be filled in by your application when the form is served |

Choose what your people see with two options of mountFormBuilder:

mountFormBuilder(el, {
  templateCategories: ['general', 'feedback'],   // only these groups (default: all of them)
  templateIds: ['inspection', 'blank'],          // or exactly these templates, specific ones included
});

Using the output

Download the JSON and give it to the component:

document.querySelector('re-form-generator').schema = await (await fetch('form.json')).json();

or use JSON → Embed to copy a ready-made HTML snippet.

Embedding the builder in another app

The builder is also a library, @restrella/form-builder. It draws itself inside a shadow root, so its styles and your page's styles never touch each other.

import { mountFormBuilder } from '@restrella/form-builder';

const builder = mountFormBuilder(document.getElementById('host')!, {
  document: savedDocument,                 // the v2 JSON, or nothing for a new form
  prefillSources: [{ key: 'contact.phone', label: 'Phone', group: 'Primary contact', kind: 'tel' }],
  defaultPhoneCountry: 'dk',               // optional: new phone fields start with +45 (default: the form's language)
  templateCategories: ['general', 'feedback'], // optional: limit the template picker to some groups (or list `templateIds`)
  onSave: async doc => { await api.save(doc); builder.markSaved(); },
  autosave: true,                          // optional: save by itself after edits, no Save button. On failure throw an Error:
                                           // its message is shown to people (keep it plain), and the builder retries by itself
  onChange: doc => { /* every edit, debounced */ },
  hideActionSettings: true,                // the host decides where answers go
  hideCaptchaSettings: true,
  hideScriptSettings: false,               // true hides “Custom code” (the form's own JavaScript, run in a sandbox)
  editCode: (code, { title, reference }) => openMyEditor(code), // optional: your own editor for the larger view; resolve with the code or null. Without it the builder opens Monaco (from cdn.jsdelivr.net, a text box when that is blocked)
  hideExport: true,
});
// builder.getDocument() · builder.setDocument(doc) · builder.update({...}) · builder.save() · builder.destroy()

The host element needs a height. @restrella/form-generator is a peer dependency: install it next to the builder.

Interface language

The builder's own interface follows the browser's language (or the person's last choice in the top bar). An embedding app can choose it, add languages or change some words:

mountFormBuilder(el, {
  locale: 'da',                                         // 'en' | 'es' | 'da' | 'sv' | 'pt' | a code added below
  locales: { de: { name: 'Deutsch', messages: { 'topbar.undo': 'Rückgängig' /* … */ } } },
  hideLocalePicker: true,                               // the host app decides
  onLocaleChange: code => saveUserPreference(code),
});
builder.update({ locale: 'sv' });

Missing words fall back to English. To contribute a language to the project, see src/i18n/README.md and check it with npm run i18n:check.

Simple and advanced view

The builder has a Simple / Advanced switch in the top bar (remembered per person; new people start in Simple). Every field type is available in both. The simple view shows what most forms need (question, help text, options, required, each type's essentials) and keeps validation rules, conditional logic, layout, field keys, auto-fill, detailed design, spam protection, endpoints and the JSON tab for the advanced view. Settings made in the advanced view stay in the form; the simple view tells when a field has some ("This field also has: 2 validation rules, conditional logic").

mountFormBuilder(el, {
  view: 'simple',              // or 'advanced'; default: the person's last choice
  allowAdvancedView: false,    // keep everyone in the simple view (no switch)
  onViewChange: view => savePreference(view),
});

Auto-fill

Give the builder a list of prefillSources and every field gets an Auto-fill from… choice (stored as field.config.prefill, with config.prefillLock to make the value read-only). Texts can use {{key}} tokens, e.g. a description of {{contact.address}}. When the form is opened, the host calls applyPrefill(document, data) from @restrella/form-generator and renders the returned doc with the returned values as the generator's model.

Contributing

See CONTRIBUTING.md to run the project locally and for the release process.

License

MIT