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

pict-section-form-host

v1.0.0

Published

A cohesive programmatic container for embedding a pict-section-form into a div or iframe, with a single configuration surface for the form manifest, render destination, AppData marshaling location and lifecycle hooks.

Readme

pict-section-form-host

A cohesive programmatic container for embedding a pict-section-form into a div (or an iframe) with a single configuration surface.

pict-section-form is powerful, but standing a form up by hand means assembling a metacontroller view, a DataBroker marshal destination, a pile of container element conventions and the render / marshal / solve calls yourself, in several different places. pict-section-form-host collapses all of that into one object you configure with four questions:

  1. What form? (the manifest)
  2. Rendered where? (a div or an iframe, your choice at runtime)
  3. Where does the data live? (a Pict state address such as AppData.MyForm)
  4. What should run on lifecycle events? (hooks)

It then exposes a small, stable API -- loadForm, render, marshalToView, marshalFromView, getFormData, setFormData, solve -- so the software using it never has to reach into the internals of pict-section-form.

Install

npm install pict-section-form-host

pict-section-form and pict-application come along as dependencies.

Quick start

const libPictSectionFormHost = require('pict-section-form-host');

// Inside a Pict application (or against any pict instance):
const tmpFormHost = pict.addProvider('MyForm',
    {
        Form:               require('./My-Form-Manifest.json'),
        DestinationType:    'div',                 // 'div' (default) or 'iframe'
        DestinationAddress: '#My-Form-Container',  // where to mount
        DataAddress:        'AppData.MyForm',       // where the data lives
        onSave: (pContext) => console.log('saved', pContext.Data)
    }, libPictSectionFormHost);

// Because `Form` was supplied, the host loads and renders itself on initialize.
// From there, drive it programmatically:
tmpFormHost.setFormData({ FirstName: 'Ada' });   // push a record into the form
let tmpData = tmpFormHost.getFormData();          // read the bound data object
tmpFormHost.marshalFromView();                    // pull the DOM back into AppData (+ onSave)
tmpFormHost.loadForm(anotherManifest);            // swap the whole form config in place

If you would rather not auto-load, omit Form and call loadForm(manifest) when you are ready:

const tmpFormHost = pict.addProvider('MyForm',
    { DestinationAddress: '#My-Form-Container', DataAddress: 'AppData.MyForm' },
    libPictSectionFormHost);

tmpFormHost.loadForm(require('./My-Form-Manifest.json'));

The manifest is exactly the shape pict-section-form consumes (Descriptors, Sections, Solvers, PickLists, ...). The host does not reinvent it -- it embeds it.

Configuration

| Option | Default | Meaning | |---|---|---| | Form | false | The form manifest. Provide it to auto-load on initialize, or pass it later to loadForm(). | | DestinationType | 'div' | 'div' renders into an element in the host page; 'iframe' renders into a same-origin iframe for CSS isolation. | | DestinationAddress | '#Pict-Form-Host-Container' | CSS selector of the mount element (the div, or the element the iframe is placed in). | | CreateDestinationElement | true | When the mount element is missing, append one to <body> rather than erroring. | | DataAddress | 'AppData' | The Pict state address the form marshals to and from. Anything pict.resolveStateFromAddress understands: AppData, AppData.MyRecord, Bundle.Thing, ... The object is created if absent. | | AutoRenderOnLoad | true | Render as soon as loadForm() completes. | | AutoMarshalToViewAfterRender | true | Push the data at DataAddress into the inputs after each render. | | PopulateDefaultObject | true | Fill DataAddress with the manifest's declared Default values for missing fields. | | SolveOnLoad | true | Run the manifest solvers after render. | | DistinctManifest | false | (div mode) Namespace the manifest's hashes / addresses per instance so the SAME manifest can be embedded by several hosts on one page. | | IframeScripts | false | (iframe mode) Script URLs to load into the iframe realm so the child has window.Pict + window.PictSectionFormHost. When false, the host auto-clones the host document's external <script src> tags. | | IframeSrc | false | (iframe mode) URL of an externally hosted child page for a cross-origin child (skips the generated same-origin srcdoc). | | IframeTitle / IframeClass / IframeStyle / IframeDocumentCSS | see source | iframe-mode iframe element + document tuning. | | MetacontrollerPrototype | false | Advanced: override the metacontroller class the host wraps. Defaults to pict-section-form's PictFormMetacontroller. |

Hooks can be provided as top-level options (onSave: fn) or grouped under a Hooks: { onSave: fn } object, and added later with on(name, fn).

Lifecycle hooks

Every handler receives a single context object carrying at least { Host, HookName, DataAddress }, plus a hook-specific payload.

| Hook | Fires | Extra context | |---|---|---| | onBeforeLoad | Before a form is (re)loaded | Manifest, IsSwap | | onAfterLoad | After a form is loaded (and rendered, if auto) | Manifest, IsSwap | | onBeforeRender | Before each render | Manifest | | onAfterRender | After each render | Manifest | | onSave | After marshalFromView() / save() collects the DOM into data | Data |

tmpFormHost.on('onSave', (pContext) =>
{
    persistToServer(pContext.Data);
});

API

| Method | Description | |---|---| | loadForm(manifest?, overrides?) | Load (or swap) the form. overrides may carry { DataAddress, DestinationType, DestinationAddress }. Defaults to the configured Form. | | setConfiguration(manifest) | Alias for loadForm(manifest) that reads as a config swap. | | reload() | Reload the current manifest from scratch. | | render() | Render (or re-render) the form. | | marshalToView() | Push the data at DataAddress into the inputs (data -> DOM). | | marshalFromView() / save() | Pull the input values back into the data, then fire onSave (DOM -> data). | | solve() | Run the manifest solvers, then reflect computed values in the inputs. | | getFormData() | The live data object at DataAddress. | | setFormData(data) / loadData(data) | Replace the data object and push it into the view. | | getValueByHash(hash) / setValueByHash(hash, value) | Read / write a single field by descriptor hash. | | getMetacontroller() | The dedicated metacontroller instance driving this host. | | getSectionViews() | The section-form views this host owns. | | getDataAddress() / setDataAddress(address) | Read / retarget the data address. | | getDestinationType() / getIframeElement() | Inspect the mount. | | isLoaded() / isRendered() | State flags. | | destroy() | Remove the section views + metacontroller and clean up (restores ContentAssignment in iframe mode). |

iframe mode

Set DestinationType: 'iframe' and the host boots a genuinely independent child pict inside the iframe. The form renders in the child's own realm -- its own document, its own CSS cascade, its own event handlers -- so it is truly isolated from the host page. The parent host never reaches into the iframe; it talks to the child over a small postMessage protocol and mirrors the form data back into DataAddress.

pict.addProvider('MyForm',
    {
        Form: manifest,
        DestinationType: 'iframe',
        DestinationAddress: '#My-Form-Mount',
        DataAddress: 'AppData.MyForm',
        // Load the runtime into the iframe realm: pict, then this module's
        // bundle (which carries pict-section-form).
        IframeScripts: [ './pict.min.js', './pict-section-form-host.min.js' ],
        onSave: (pContext) => console.log('saved', pContext.Data)
    }, libPictSectionFormHost);

How it works:

  • The host builds the iframe (a same-origin srcdoc by default), injects the runtime scripts plus a small child bootstrap, and the child boots its own pict and renders the form with a plain div-mode host inside the frame.
  • The child needs window.Pict and window.PictSectionFormHost present in its realm. Provide the script URLs with IframeScripts; when omitted, the host auto-clones the host document's own external <script src> tags (which works when the app loads those runtimes as separate script tags).
  • Data crosses the boundary over postMessage: the child relays edits and saves out, the parent mirrors them into DataAddress (so getFormData() stays current) and fires onSave when the child reports a save.

Because the boundary is postMessage, iframe-mode data flow is asynchronous: getFormData() reflects the most recent message from the child, and onSave / onAfterLoad fire when the child reports the corresponding step. Div mode stays fully synchronous.

For a cross-origin child, host a page carrying the child runtime elsewhere and pass its URL as IframeSrc; the protocol is identical.

Multiple forms on one page

Add the host under different hashes to drive independent form regions:

pict.addProvider('LeftForm',  { DestinationAddress: '#left',  DataAddress: 'AppData.Left'  }, libPictSectionFormHost);
pict.addProvider('RightForm', { DestinationAddress: '#right', DataAddress: 'AppData.Right' }, libPictSectionFormHost);

Each host owns its own metacontroller, renders only its own sections and marshals to its own data address. If two hosts must render the SAME manifest, set DistinctManifest: true on both so their section hashes and data addresses are namespaced per instance.

Examples

Two runnable example applications live in example_applications/:

  • simple_host -- one order form embedded in a div, bound to AppData, with live solver-computed totals and a lifecycle-hook status line. (Basic)
  • iframe_switcher -- a form embedded in a style-isolated iframe, swapping between Contact / Feedback / Shipping configurations at runtime, each with its own AppData address. (Intermediate)

Build and open one with:

cd example_applications/simple_host
npm install
npm run build
# then serve ./dist and open index.html

How it works

The host is a pict-provider with two rendering strategies behind one API.

div mode renders in the host's own pict. On load it:

  1. Ensures a PictApplication and the pict-section-form dependency providers are present (adding a minimal default application if the host is dropped onto a bare pict instance).
  2. Creates a dedicated metacontroller (a thin subclass of PictFormMetacontroller) with per-instance template / renderable / destination hashes, scoped so it only ever renders and marshals its own sections.
  3. Bootstraps the section views from the manifest, points them at DataAddress, generates the container metatemplate and renders.

The dedicated, scoped metacontroller is what lets several div-mode hosts coexist without stepping on one another.

iframe mode renders in a child pict inside the iframe. On load it builds the iframe, injects the runtime, and a small child bootstrap stands up its own pict running a plain div-mode host in the frame's realm. The parent proxies the API to the child over postMessage and mirrors the data back into DataAddress. The child is genuinely isolated -- there is no parent monkey-patching of the child's document.

License

MIT