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

@chobantonov/jsonforms-svelte-skeleton-webcomponent

v1.0.2

Published

Skeleton-based JSONForms Svelte Web Component

Readme

@chobantonov/jsonforms-svelte-skeleton-webcomponent

A standalone Skeleton JSON Forms custom element built with Svelte 5. It includes both the base and extended renderer sets, cells, validation, and styles inside an open shadow root. The consuming page does not need Svelte or a build tool.

Loading from an npm CDN

Load the browser bundle directly from jsDelivr:

<script
  type="module"
  src="https://cdn.jsdelivr.net/npm/@chobantonov/[email protected]/dist/jsonforms-svelte-skeleton.js"
></script>

Or use UNPKG with the same package version and file path:

<script
  type="module"
  src="https://unpkg.com/@chobantonov/[email protected]/dist/jsonforms-svelte-skeleton.js"
></script>

Choose one CDN. These examples pin version 1.0.2; update the version to the published release you want to use. The module registers <jsonforms-svelte-skeleton> and loads its supporting chunks relative to its own URL. No separate renderer, Svelte, or global stylesheet imports are needed for the form.

Complete HTML example

Save this as index.html and serve it over HTTP(S). It loads the npm bundle, configures a form, displays its current data and validation errors, and handles an extended renderer button action. The page also demonstrates changing properties after initialization.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>JSON Forms Skeleton Web Component</title>
    <style>
      body {
        max-width: 800px;
        margin: 2rem auto;
        padding: 0 1rem;
        font-family: sans-serif;
      }
      jsonforms-svelte-skeleton {
        display: block;
        margin: 1rem 0;
      }
      pre {
        white-space: pre-wrap;
        overflow-wrap: anywhere;
      }
    </style>
  </head>
  <body>
    <h1>Profile</h1>
    <button id="reset" type="button">Reset data</button>
    <label><input id="readonly" type="checkbox" /> Read-only</label>
    <label>
      Appearance
      <select id="mode">
        <option value="system">System</option>
        <option value="light">Light</option>
        <option value="dark">Dark</option>
      </select>
    </label>

    <div id="form-container"></div>
    <p id="status" role="status">Loading form…</p>
    <h2>Current data</h2>
    <pre id="data"></pre>
    <h2>Validation errors</h2>
    <pre id="errors"></pre>

    <script type="module">
      import 'https://cdn.jsdelivr.net/npm/@chobantonov/[email protected]/dist/jsonforms-svelte-skeleton.js';

      await customElements.whenDefined('jsonforms-svelte-skeleton');
      const form = document.createElement('jsonforms-svelte-skeleton');
      form.id = 'form';
      form.locale = 'en';
      form.mode = 'system';
      const status = document.getElementById('status');
      const initialData = { name: 'Ada', age: 37, newsletter: false };

      // Register listeners before assigning the form inputs.
      form.addEventListener('change', (event) => {
        // Native input change events can also bubble out of the shadow root.
        if (!(event instanceof CustomEvent)) return;
        const { data, errors = [] } = event.detail;
        document.getElementById('data').textContent = JSON.stringify(data, null, 2);
        document.getElementById('errors').textContent = JSON.stringify(errors, null, 2);
        status.textContent = errors.length
          ? `${errors.length} validation error(s)`
          : 'Form is valid';
      });
      form.addEventListener('handle-action', (event) => {
        const { action, context, params } = event.detail;
        if (action === 'showData') {
          status.textContent = `${params.message} ${JSON.stringify(context.data)}`;
        }
      });

      form.schema = {
        type: 'object',
        properties: {
          name: { type: 'string', minLength: 1 },
          age: { type: 'integer', minimum: 0 },
          newsletter: { type: 'boolean' },
        },
        required: ['name'],
      };
      form.uischema = {
        type: 'VerticalLayout',
        elements: [
          { type: 'Control', scope: '#/properties/name' },
          { type: 'Control', scope: '#/properties/age' },
          { type: 'Control', scope: '#/properties/newsletter' },
          {
            type: 'Button',
            label: 'Show data',
            action: 'showData',
            params: { message: 'Current profile:' },
          },
        ],
      };
      form.config = { showUnfocusedDescription: true };
      form.validationMode = 'ValidateAndShow';
      form.data = { ...initialData };
      // Attach after configuring so the first render has all inputs.
      document.getElementById('form-container').append(form);

      document.getElementById('reset').addEventListener('click', () => {
        form.data = { ...initialData };
      });
      document.getElementById('readonly').addEventListener('change', (event) => {
        form.readonly = event.target.checked;
      });
      document.getElementById('mode').addEventListener('change', (event) => {
        form.mode = event.target.value;
      });
    </script>
  </body>
</html>

The change event supplies the current edited data; keep application state from event.detail.data rather than treating the data input property as an output binding. Assign a new object or array to update the form externally, rather than mutating a nested input in place.

npm installation and self-hosting

pnpm add @chobantonov/jsonforms-svelte-skeleton-webcomponent

Copy the package's entire dist directory, including chunks/ and assets/, to a public directory such as /vendor/jsonforms-svelte-skeleton/. Preserve its layout; copying only the entry JavaScript file is not sufficient. Then replace the CDN import in the example with:

import '/vendor/jsonforms-svelte-skeleton/jsonforms-svelte-skeleton.js';

Serve the files over HTTP(S) with JavaScript module MIME types. The entry point is a browser module that registers the element as a side effect, not a component constructor to instantiate or a Node.js entry point.

Browser import and TypeScript

The package exposes the browser registration module through the package root:

// Run in the browser (for example, inside Svelte's onMount).
await import('@chobantonov/jsonforms-svelte-skeleton-webcomponent');
await customElements.whenDefined('jsonforms-svelte-skeleton');
const form = document.createElement('jsonforms-svelte-skeleton');
form.data = { name: 'Ada' };

Published declarations type the custom element via HTMLElementTagNameMap and export the type JsonFormsSkeletonElement. The module has no runtime named exports. For self-hosting, keep copying the complete dist directory; the ./dist/* and ./package.json subpaths are exported for asset tooling.

Properties and attributes

Prefer JavaScript properties for objects and arrays. HTML attributes contain strings; serialize JSON-valued inputs with JSON. Wait for customElements.whenDefined('jsonforms-svelte-skeleton') before assigning properties.

| JavaScript property | HTML attribute | Accepted value / purpose | Default | | ------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------- | ------------------ | | data | data | Any JSON-compatible form value, or serialized JSON. A string that cannot be parsed as JSON is retained as a string. | undefined | | schema | schema | JSON Schema object or JSON string. | undefined | | uischema | uischema | JSON Forms UI schema object or JSON string; omitted UI schemas are generated by JSON Forms. | undefined | | uischemas | uischemas | Additional UI schema registry entries; use properties for entries containing tester functions. | [] after parsing | | config | config | JSON Forms configuration object or JSON string. | {} | | readonly | readonly | Boolean or string "true" / "false". | false | | validationMode | validationmode | ValidateAndShow, ValidateAndHide, or NoValidation. | ValidateAndShow | | locale | locale | Locale for translation and validation messages, such as en, de, or bg. | en | | translations | translations | Object keyed by locale, or its JSON string. | undefined | | additionalErrors | additionalerrors | Array of AJV error objects, or JSON string, for external validation errors. | [] | | mode | mode | system, light, or dark; auto means system, and booleans / "true" / "false" mean dark / light. | system | | customStyle | customstyle | CSS text appended inside the shadow root. | '' | | theme | theme | Included color theme name; see below. | cerberus |

Attribute names are lowercase, without hyphens: use validationmode, not validation-mode. In JavaScript use the camelCase names shown above. The readonly parser requires an explicit value: use readonly="true", not a bare readonly attribute.

<jsonforms-svelte-skeleton
  schema='{"type":"object","properties":{"name":{"type":"string"}}}'
  data='{"name":"Ada"}'
  readonly="true"
  validationmode="ValidateAndHide"
></jsonforms-svelte-skeleton>

For a literal string that also parses as JSON (for example "123"), use form.data = JSON.stringify('123') to preserve its string type.

Translation and styling

form.locale = 'de';
form.translations = {
  en: { name: { label: 'Name' } },
  de: { name: { label: 'Name auf Deutsch' } },
};
form.customStyle = ':host { display: block; }';
form.setAttribute('dir', 'rtl'); // Standard HTML direction attribute.

Translation lookup uses the requested locale, then its language prefix (for example de for de-DE), then English when the locale dictionary is missing. Missing messages fall back to the JSON Forms default. Page CSS does not cross the shadow boundary; use customStyle for CSS targeting the rendered form.

Included Skeleton themes: catppuccin, cerberus, concord, crimson, fennec, hamlindigo, legacy, mint, modern, mona, nosh, nouveau, pine, reign, rocket, rose, sahara, seafoam, terminus, vintage, vox, and wintry. Set form.theme = 'modern' to switch theme independently of light/dark mode.

Events

Both events are CustomEvents with bubbles: true and composed: true, so they can be handled on the element or an ancestor outside the shadow root. event.detail is an object, not an array.

| Event | event.detail | When emitted | | --------------- | --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | | change | { data, errors }, where errors contains AJV validation errors when available. | Initial form evaluation and JSON Forms data/validation changes. | | handle-action | { action, params, context, $el, callback? }. | An extended renderer dispatches a named action, such as the Button in the sample. |

context provides the current form state, including data, schema, uischema, errors, config, and locale; $el is the originating element. For asynchronous action handling, assign event.detail.callback synchronously in the listener so the renderer can await your work:

form.addEventListener('handle-action', (event) => {
  if (event.detail.action === 'save') {
    event.detail.callback = async ({ context }) => {
      console.log('Save this data:', context.data);
      // await your application's save operation here.
    };
  }
});

No submission or network request is performed automatically. Your application handles persistence and decides whether validation errors allow submission.

Development playground

From the monorepo root:

pnpm run wc:skeleton:dev
pnpm run wc:skeleton:build
pnpm run wc:skeleton:preview