{"id":51254981,"url":"https://github.com/humanspeak/svelte-json-view-lite","last_synced_at":"2026-06-29T09:32:09.881Z","repository":{"id":352480675,"uuid":"1215129637","full_name":"humanspeak/svelte-json-view-lite","owner":"humanspeak","description":"Lightweight JSON tree view component for Svelte — fast, zero-dependency, collapsible, and fully customizable.","archived":false,"fork":false,"pushed_at":"2026-06-25T20:16:07.000Z","size":10259,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-25T21:15:37.713Z","etag":null,"topics":["a11y","collapsible","frontend","json","json-view","json-viewer","keyboard-navigation","lightweight","runes","svelte","svelte-component","svelte-library","svelte5","sveltekit","syntax-highlighting","tree-view","typescript","zero-dependencies"],"latest_commit_sha":null,"homepage":"https://jsonview.svelte.page","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/humanspeak.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"github":["humanspeak"]}},"created_at":"2026-04-19T14:19:19.000Z","updated_at":"2026-06-25T20:16:13.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/humanspeak/svelte-json-view-lite","commit_stats":null,"previous_names":["humanspeak/svelte-json-view-lite"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/humanspeak/svelte-json-view-lite","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humanspeak%2Fsvelte-json-view-lite","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humanspeak%2Fsvelte-json-view-lite/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humanspeak%2Fsvelte-json-view-lite/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humanspeak%2Fsvelte-json-view-lite/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/humanspeak","download_url":"https://codeload.github.com/humanspeak/svelte-json-view-lite/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/humanspeak%2Fsvelte-json-view-lite/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34921804,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-29T02:00:05.398Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["a11y","collapsible","frontend","json","json-view","json-viewer","keyboard-navigation","lightweight","runes","svelte","svelte-component","svelte-library","svelte5","sveltekit","syntax-highlighting","tree-view","typescript","zero-dependencies"],"created_at":"2026-06-29T09:32:05.249Z","updated_at":"2026-06-29T09:32:09.861Z","avatar_url":"https://github.com/humanspeak.png","language":"TypeScript","funding_links":["https://github.com/sponsors/humanspeak"],"categories":[],"sub_categories":[],"readme":"# @humanspeak/svelte-json-view-lite\n\nFast, tiny JSON tree viewer for Svelte 5 — a port of\n[react-json-view-lite](https://github.com/AnyRoad/react-json-view-lite)\n(MIT © 2024 AnyRoad) with runes, SSR, per-type snippet overrides, and zero\nruntime dependencies.\n\n[![NPM version](https://img.shields.io/npm/v/@humanspeak/svelte-json-view-lite.svg)](https://www.npmjs.com/package/@humanspeak/svelte-json-view-lite)\n[![Build Status](https://github.com/humanspeak/svelte-json-view-lite/actions/workflows/npm-publish.yml/badge.svg)](https://github.com/humanspeak/svelte-json-view-lite/actions/workflows/npm-publish.yml)\n[![Coverage Status](https://coveralls.io/repos/github/humanspeak/svelte-json-view-lite/badge.svg?branch=main)](https://coveralls.io/github/humanspeak/svelte-json-view-lite?branch=main)\n[![License](https://img.shields.io/npm/l/@humanspeak/svelte-json-view-lite.svg)](https://github.com/humanspeak/svelte-json-view-lite/blob/main/LICENSE)\n[![Downloads](https://img.shields.io/npm/dm/@humanspeak/svelte-json-view-lite.svg)](https://www.npmjs.com/package/@humanspeak/svelte-json-view-lite)\n[![CodeQL](https://github.com/humanspeak/svelte-json-view-lite/actions/workflows/codeql.yml/badge.svg)](https://github.com/humanspeak/svelte-json-view-lite/actions/workflows/codeql.yml)\n[![Install size](https://packagephobia.com/badge?p=@humanspeak/svelte-json-view-lite)](https://packagephobia.com/result?p=@humanspeak/svelte-json-view-lite)\n[![Code Style: Trunk](https://img.shields.io/badge/code%20style-trunk-blue.svg)](https://trunk.io)\n[![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/)\n[![Types](https://img.shields.io/npm/types/@humanspeak/svelte-json-view-lite.svg)](https://www.npmjs.com/package/@humanspeak/svelte-json-view-lite)\n[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/humanspeak/svelte-json-view-lite/graphs/commit-activity)\n\n## Features\n\n- Svelte 5 runes throughout (`$props`, `$state`, `$derived`, `$effect`).\n- Drop-in API parity with `react-json-view-lite`: same prop names, themes,\n  and strategy helpers.\n- Per-type `Snippet` overrides for custom value rendering (strings, numbers,\n  dates, etc.) — new in the Svelte port.\n- SSR-safe: uses `$props.id()` for stable `aria-controls` linkage across\n  server/client.\n- Keyboard accessible: roving tabindex + `ArrowUp`/`ArrowDown`/`ArrowLeft`/\n  `ArrowRight` navigation, full WAI-ARIA treeview semantics.\n- Ships built-in light and dark themes via CSS Modules.\n\n## Installation\n\n```bash\nnpm i -S @humanspeak/svelte-json-view-lite\n# or\npnpm add @humanspeak/svelte-json-view-lite\n```\n\n## Basic usage\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n    import { JsonView, defaultStyles } from '@humanspeak/svelte-json-view-lite'\n\n    const data = {\n        name: 'Ada Lovelace',\n        tags: ['admin', 'beta'],\n        active: true,\n        joined: new Date('2024-01-15')\n    }\n\u003c/script\u003e\n\n\u003cJsonView {data} style={defaultStyles} /\u003e\n```\n\n## Props\n\n| Prop                    | Type                                     | Default         | Description                                                                        |\n| ----------------------- | ---------------------------------------- | --------------- | ---------------------------------------------------------------------------------- |\n| `data`                  | `object \\| unknown[]`                    | —               | The JSON-shaped value to render.                                                   |\n| `style`                 | `Partial\u003cStyleProps\u003e`                    | `defaultStyles` | Classname-map that themes every slot.                                              |\n| `shouldExpandNode`      | `(level, value, field?) =\u003e boolean`      | `allExpanded`   | Initial-expand strategy per node.                                                  |\n| `clickToExpandNode`     | `boolean`                                | `false`         | When true, clicking the field label also toggles the node.                         |\n| `beforeExpandChange`    | `(event: NodeExpandingEvent) =\u003e boolean` | —               | Return `false` to veto an expand/collapse transition.                              |\n| `compactTopLevel`       | `boolean`                                | `false`         | Spread root-object entries instead of nesting them under a single root expander.   |\n| `string`, `number`, ... | `Snippet\u003c[{ value, field?, level }]\u003e`    | —               | Optional per-type renderer overrides. See [Snippet overrides](#snippet-overrides). |\n\nAny additional HTML attributes (`aria-*`, `data-*`, `id`, `class`, etc.) are\nforwarded onto the root `\u003cdiv role=\"tree\"\u003e`.\n\n## Themes\n\nTwo themes ship out of the box:\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n    import { JsonView, defaultStyles, darkStyles } from '@humanspeak/svelte-json-view-lite'\n\u003c/script\u003e\n\n\u003cJsonView data={json} style={darkStyles} /\u003e\n```\n\nOverride individual slots by spreading:\n\n```svelte\n\u003cJsonView\n    {data}\n    style={{\n        ...defaultStyles,\n        stringValue: 'my-custom-string-class',\n        punctuation: 'my-custom-punctuation-class'\n    }}\n/\u003e\n```\n\n## Retheme via CSS variables\n\nEvery color in the built-in themes is declared as a CSS custom property\non the root container, so you can tweak one or more colors without\nswapping the entire `style` prop or bringing your own classname map.\nThe variables all live under the `--sjv-*` namespace:\n\n| Variable            | Default (light)    | Default (dark)       | Applies to                                 |\n| ------------------- | ------------------ | -------------------- | ------------------------------------------ |\n| `--sjv-background`  | `#eee`             | `rgb(0, 43, 54)`     | Root container background                  |\n| `--sjv-label`       | `#000000`          | `rgb(253, 246, 227)` | Field label text                           |\n| `--sjv-punctuation` | `#000000`          | `rgb(253, 246, 227)` | Brackets, colons, commas                   |\n| `--sjv-string`      | `rgb(42, 63, 60)`  | `rgb(203, 75, 22)`   | String values                              |\n| `--sjv-number`      | `#0b75f5`          | `rgb(211, 54, 130)`  | Number \u0026 BigInt values                     |\n| `--sjv-boolean`     | `rgb(70, 144, 56)` | `rgb(174, 129, 255)` | Boolean values                             |\n| `--sjv-null`        | `#df113a`          | `rgb(129, 181, 172)` | `null` literal                             |\n| `--sjv-undefined`   | `#df113a`          | `rgb(129, 181, 172)` | `undefined` literal                        |\n| `--sjv-other`       | `#43413d`          | `rgb(38, 139, 210)`  | Dates, functions, symbols, etc.            |\n| `--sjv-expander`    | `#000000`          | `rgb(253, 246, 227)` | `▸` / `▾` icons and collapsed `...` marker |\n\n**Global override** — applies to every `JsonView` on the page:\n\n```css\n:root {\n    --sjv-string: lavender;\n    --sjv-number: #ff71ce;\n}\n```\n\n**Scoped override** — target one component (or a subtree):\n\n```svelte\n\u003cdiv class=\"vaporwave\"\u003e\n    \u003cJsonView {data} style={defaultStyles} /\u003e\n\u003c/div\u003e\n\n\u003cstyle\u003e\n    .vaporwave :global(div[role='tree']) {\n        --sjv-background: #2b1055;\n        --sjv-string: #01cdfe;\n        --sjv-number: #05ffa1;\n        --sjv-boolean: #b967ff;\n    }\n\u003c/style\u003e\n```\n\n**Per-instance override** — forward inline styles via the root div (ARIA\nattrs and `style` on `\u003cJsonView\u003e` are spread onto the wrapper):\n\n```svelte\n\u003cJsonView {data} style={defaultStyles} style:--sjv-number=\"tomato\" /\u003e\n```\n\nAll three patterns work with either `defaultStyles` or `darkStyles` —\nthe variables are defined on both container classes with theme-specific\nfallback defaults, so one override applies to whichever theme is active.\n\nSee the `/test/css-variables` playground route for a live example.\n\n## Snippet overrides\n\nUnlike the React lib, `svelte-json-view-lite` exposes typed `Snippet`\noverrides for every primitive type plus the field label. Each snippet\nreceives `{ value, field?, level }`; omit the snippet to fall through to\nthe default rendering.\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n    import {\n        JsonView,\n        type DateSnippetProps,\n        type StringSnippetProps\n    } from '@humanspeak/svelte-json-view-lite'\n\n    const data = {\n        joined: new Date('2024-01-15'),\n        docs: 'https://example.com/docs'\n    }\n\n    function relative(d: Date): string {\n        const days = Math.round((d.getTime() - Date.now()) / 86_400_000)\n        return new Intl.RelativeTimeFormat('en').format(days, 'day')\n    }\n\u003c/script\u003e\n\n\u003cJsonView {data}\u003e\n    {#snippet date({ value }: DateSnippetProps)}\n        \u003cspan title={value.toISOString()}\u003e{relative(value)}\u003c/span\u003e\n    {/snippet}\n    {#snippet string({ value }: StringSnippetProps)}\n        {#if /^https?:/.test(value)}\n            \u003ca href={value}\u003e{value}\u003c/a\u003e\n        {:else}\n            \"{value}\"\n        {/if}\n    {/snippet}\n\u003c/JsonView\u003e\n```\n\nAvailable snippets: `string`, `number`, `boolean`, `null`, `undefined`,\n`bigint`, `date`, `function`, `label`. Their typed prop interfaces\n(`StringSnippetProps`, `LabelSnippetProps`, etc.) are all exported from\nthe package root.\n\n## Expand strategies\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n    import { JsonView, collapseAllNested, allExpanded } from '@humanspeak/svelte-json-view-lite'\n\u003c/script\u003e\n\n\u003c!-- expand only the root, collapse every child --\u003e\n\u003cJsonView {data} shouldExpandNode={collapseAllNested} /\u003e\n\n\u003c!-- expand everything (default) --\u003e\n\u003cJsonView {data} shouldExpandNode={allExpanded} /\u003e\n\n\u003c!-- custom: expand up to depth 2 --\u003e\n\u003cJsonView {data} shouldExpandNode={(level) =\u003e level \u003c 2} /\u003e\n```\n\n## Migrating from `react-json-view-lite`\n\nThe Svelte API preserves the React prop names and theme-object shape. Only\ntwo differences exist:\n\n| React                       | Svelte                                                     |\n| --------------------------- | ---------------------------------------------------------- |\n| `style.ariaLables` (typoed) | `style.ariaLabels` (fixed; typo still honored with a warn) |\n| — (not supported)           | Per-type `Snippet` overrides                               |\n\nEverything else — `style`, `clickToExpandNode`, `compactTopLevel`,\n`beforeExpandChange`, `shouldExpandNode`, `defaultStyles`, `darkStyles`,\n`allExpanded`, `collapseAllNested` — works identically.\n\n## Accessibility\n\n- Root element has `role=\"tree\"` with `aria-label=\"JSON view\"` (overridable).\n- Every expandable node is a `role=\"treeitem\"` with live `aria-expanded`\n  and, when open, `aria-controls` pointing at its child `\u003cul role=\"group\"\u003e`.\n- Keyboard support follows the [WAI-ARIA 1.2 Treeview pattern]:\n    - `ArrowRight` expands, `ArrowLeft` collapses.\n    - `ArrowDown` / `ArrowUp` move focus between expanders (wrapping).\n    - Roving `tabindex` keeps only one expander in the tab order.\n\n[WAI-ARIA 1.2 Treeview pattern]: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/\n\n## Development\n\n```bash\npnpm install\npnpm dev          # launch SvelteKit playground on :8233\npnpm check        # svelte-check\npnpm test         # vitest + coverage\npnpm build        # vite build + svelte-package + publint\n```\n\n\u003c!-- docs-kit:ecosystem start --\u003e\n\n## Svelte 5 ecosystem\n\nPart of the [Humanspeak](https://humanspeak.com) family of runes-native Svelte 5 packages:\n\n| Package | Description |\n| --- | --- |\n| [@humanspeak/svelte-markdown](https://markdown.svelte.page) | Runtime markdown renderer for Svelte |\n| [@humanspeak/svelte-virtual-list](https://virtuallist.svelte.page) | Virtual scrolling for Svelte |\n| [@humanspeak/svelte-motion](https://motion.svelte.page) | Framer Motion for Svelte 5 |\n| [@humanspeak/svelte-headless-table](https://table.svelte.page) | Headless data tables for Svelte |\n| [@humanspeak/svelte-diff-match-patch](https://diff.svelte.page) | Diff comparison for Svelte |\n| [@humanspeak/svelte-purify](https://purify.svelte.page) | HTML sanitisation for Svelte |\n| [@humanspeak/svelte-virtual-chat](https://virtualchat.svelte.page) | Virtual chat viewport for Svelte 5 |\n| [@humanspeak/memory-cache](https://memory.svelte.page) | In-memory cache for TypeScript |\n| **[@humanspeak/svelte-json-view-lite](https://jsonview.svelte.page)** — _this package_ | JSON tree viewer for Svelte 5 |\n| [@humanspeak/svelte-scoped-props](https://scoped.svelte.page) | Scoped class props for Svelte |\n\n## License\n\nMIT © [Humanspeak, Inc.](LICENSE)\n\n## Credits\n\nMade with ❤️ by [Humanspeak](https://humanspeak.com)\n\n\u003c!-- docs-kit:ecosystem end --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhumanspeak%2Fsvelte-json-view-lite","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhumanspeak%2Fsvelte-json-view-lite","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhumanspeak%2Fsvelte-json-view-lite/lists"}