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

@htmlbricks/hb-json-viewer

v0.76.5

Published

Renders JSON as an expandable, syntax-colored tree. Accepts a parsed object or a JSON string and supports initial expand modes (`open`, `closed`, `first`). Optional `edit` / `strict_schema` enable inline key/value editing and structure add/delete with `up

Readme

hb-json-viewer

Category: data · Tags: data, json · Package: @htmlbricks/hb-json-viewer

Description

hb-json-viewer renders JSON as an expandable, syntax-highlighted tree inside a shadow root. The payload may be a JavaScript object (when you set the json property from code) or a JSON string (from the json attribute or property). When json is a string, the component tries JSON.parse; on failure it logs a console.error and keeps the unparsed string as json.

Optional edit mode (edit="yes") adds inline controls to rename object keys, change primitive values, delete nodes, and append children. Each structural change dispatches an update event on the host whose detail includes deep snapshots previous_json and json so hosts can persist or diff the tree without re-reading the DOM.

Initial expand mode (status)

The status attribute controls the initial collapsed state per depth. Users can still expand or collapse nodes afterward.

| Value | Behavior | |-------|----------| | open | All levels start expanded (default). | | closed | All object/array nodes start collapsed. | | first | Only the root level is expanded; nested containers start collapsed. |

Edit mode and strict_schema

When edit is no (default), the tree is read-only.

When edit is yes, object keys show a pencil control for renaming, primitives show a pencil for values, non-primitive nodes can add children, and deletable nodes show a remove control. Renaming is ignored if the new key is already taken on the same parent. Add child: arrays receive a new null element; objects receive a new property newKey (or newKey_1, newKey_2, … if those names already exist) with value null.

strict_schema (default yes) controls how values are edited:

  • strict_schema="yes" — Only string, number, and boolean leaves are editable. Strings use a single-line input or a textarea when the value is long or contains newlines. Numbers use a numeric input; booleans use a true / false select. null, undefined, and other primitive-like displays are not opened for value editing in this mode (structure can still be changed with add/delete where applicable).
  • strict_schema="no" — Any primitive leaf uses one textarea prefilled with JSON.stringify-style text; confirming parses with JSON.parse, or keeps the raw string if parsing fails.

Styling (Bulma and tree tokens)

The component forwards Bulma into the shadow root and themes the tree with --jn-* tokens and --bulma-* variables on :host. Defaults chain through Bulma’s variable system — see Bulma CSS variables.

There are no ::part hooks; customize appearance by setting CSS custom properties on hb-json-viewer.

Notable groups:

  • Tree chrome: --jn-bracket, --jn-close, --jn-key, --jn-sep, --jn-string, --jn-children-border, --jn-button-border, --jn-button-hover-bg, --jn-type-object, --jn-type-array, --jn-popover-*.
  • Edit UI: --jn-edit-icon, --jn-edit-border, --jn-edit-focus-border, --jn-edit-bg, --jn-delete-icon, --jn-delete-icon-hover.
  • Scheme: --bulma-text, --bulma-text-weak, --bulma-background (and other Bulma tokens as needed).

Dark appearance follows prefers-color-scheme: dark, or data-theme="dark" / .theme-dark on html or body, or data-theme="dark" on the host element.

The authoritative list (types, defaults, and descriptions) lives in extra/docs.ts (styleSetup.vars).

CSS parts

None.

HTML slots

| Slot | Description | |------|-------------| | default | Optional light-DOM content rendered below the JSON tree (for example toolbars, help text, or footnotes). |

Custom element

| Name | Tag | | --- | --- | | hb-json-viewer | <hb-json-viewer …></hb-json-viewer> |

Attributes (snake_case; string encodings in HTML)

Web component attributes are strings. Use "yes" / "no" for booleans as reflected in HTML.

| Attribute | Required | Default | Description | |-----------|----------|---------|-------------| | id | No | — | Optional element id. | | style | No | — | Optional inline styles on the host. | | json | No* | — | JSON document as a string in markup, a parsed object from JavaScript, or omitted / undefined for the empty state. If the assigned json is a string, the component parses it when possible. | | status | No | open | open | closed | first — initial expand/collapse behavior (see above). | | edit | No | no | yes enables editing and add/delete controls; no is read-only. | | strict_schema | No | yes | yes uses type-specific editors for primitives; no uses a JSON textarea per leaf. |

*If json is missing or undefined, the host shows a short “No data” message (see component.wc.svelte).

Events

update

Fired after every successful edit-mode mutation. detail matches JsonViewerUpdateDetail in the types below.

| detail.type | Meaning | Extra fields | |---------------|---------|----------------| | editvalue | Primitive value changed | oldValue, newValue | | editkey | Object property renamed | oldKey, newKey | | deletenode | Entry removed from object or array | deletedValue | | addnode | New null entry added | — |

Always present: type, previous_json, json (deep clones of the tree before and after), and keyPath ((string | number)[] path to the affected node; for editkey, the path uses the new key as the last segment).

Usage notes

  • Large payloads in HTML: Prefer assigning element.json = myObject or element.setAttribute('json', JSON.stringify(obj)) from script instead of embedding huge escaped strings in static HTML.
  • Key paths: Indices in keyPath are numeric positions for array elements and string keys for object properties.
  • Snapshots: previous_json and json are produced with structuredClone when available, otherwise JSON.parse(JSON.stringify(...)) with a best-effort fallback.

Types

export type Component = {
  id?: string;
  json?: any;
  status?: "open" | "closed" | "first";
  edit?: "yes" | "no";
  strict_schema?: "yes" | "no";
};

/** Discriminant for `update` — which operation produced the new tree */
export type JsonViewerUpdateType =
  | "editvalue"
  | "editkey"
  | "deletenode"
  | "addnode";

export type JsonViewerUpdateDetail = {
  type: JsonViewerUpdateType;
  /** Full tree before this change (deep snapshot) */
  previous_json: any;
  /** Full tree after this change (deep snapshot) */
  json: any;
  keyPath: (string | number)[];
  oldValue?: any;
  newValue?: any;
  oldKey?: string;
  newKey?: string;
  deletedValue?: any;
};

export type Events = {
  update: JsonViewerUpdateDetail;
};

Examples

Static HTML

<hb-json-viewer
  json='{"hello":"world","nested":{"a":1}}'
  status="first"
  edit="no"
></hb-json-viewer>

JavaScript (property API and events)

<hb-json-viewer id="viewer" status="open" edit="yes" strict_schema="yes"></hb-json-viewer>
<script type="module">
  const el = document.getElementById("viewer");
  const data = { title: "Demo", count: 3, items: ["a", "b"] };
  el.json = data;
  el.addEventListener("update", (e) => {
    const { type, json, keyPath } = e.detail;
    console.log(type, keyPath, json);
  });
</script>

Additional structured examples (orders, analytics-style payloads, strict vs flexible edit) are defined in extra/docs.ts (examples).