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

@neovici/cosmoz-treenode-navigator

v8.1.6

Published

A Pion component that lets you navigate and search through hierarchically structured data-nodes and select one of them.

Downloads

3,155

Readme

cosmoz-treenode-navigator

Build Status semantic-release

A PionJS-based web component for navigating, searching, and selecting nodes in a hierarchical tree structure.

Installation

npm install @neovici/cosmoz-treenode-navigator

Quick Start

import { component, html } from '@pionjs/pion';
import '@neovici/cosmoz-treenode-navigator/cosmoz-treenode-button-view';
import { DefaultTree } from '@neovici/cosmoz-tree';

const treeData = {
	1: {
		name: 'Root',
		pathLocator: '1',
		children: {
			2: {
				name: 'Child A',
				pathLocator: '1.2',
				children: {},
			},
			3: {
				name: 'Child B',
				pathLocator: '1.3',
				children: {
					4: { name: 'Grandchild', pathLocator: '1.3.4', children: {} },
				},
			},
		},
	},
};

const tree = new DefaultTree(treeData);

const MyApp = () => html`
	<cosmoz-treenode-button-view
		.tree=${tree}
		show-reset
		@node-path-changed=${(e) => console.log('Selected:', e.detail.value)}
	></cosmoz-treenode-button-view>
`;

customElements.define('my-app', component(MyApp));

Tree Data Structure

The component expects a Tree object from @neovici/cosmoz-tree, typically instantiated with new DefaultTree(data).

The data is a nested object keyed by node IDs:

{
	"1": {
		"name": "Root",
		"pathLocator": "1",
		"children": {
			"7": {
				"name": "child seven",
				"pathLocator": "1.7",
				"children": {}
			},
			"8": {
				"name": "child eight",
				"pathLocator": "1.8",
				"children": {
					"9": {
						"name": "child nine",
						"pathLocator": "1.8.9",
						"children": {}
					}
				}
			}
		}
	}
}

The property names name and children are configurable via DefaultTree options (searchProperty, childProperty). The pathLocatorSeparator defaults to ".".

Components

<cosmoz-treenode-button-view>

A trigger button that opens a dialog containing the tree navigator. This is the main component most consumers will use.

Properties / Attributes

| Property | Attribute | Type | Default | Description | | ----------------------- | ------------------- | --------- | ------- | ----------------------------------------------- | | tree | -- | Tree | -- | The tree data structure (set via JS) | | nodePath | -- | string | '' | Selected node's path locator (two-way bindable) | | opened | -- | boolean | false | Whether the dialog is open (two-way bindable) | | showReset | show-reset | boolean | false | Show the reset/clear button | | searchMinLength | search-min-length | number | 3 | Minimum characters to trigger search | | searchDebounceTimeout | -- | number | 500 | Debounce timeout (ms) before search triggers |

Events

| Event | Detail | Description | | ------------------- | -------------------- | ----------------------------------------- | | node-path-changed | { value: string } | Fired when the selected node path changes | | opened-changed | { value: boolean } | Fired when the dialog opens or closes |

Slots

| Slot | Description | | ----------- | ------------------------------------------------------------ | | prefix | Button icon (defaults to folder icon, override to customize) | | suffix | Content after the button label | | (default) | Passed through to the inner <cosmoz-treenode-navigator> |

CSS Parts

| Part | Description | | --------------- | ------------------------------------------------------------------------------ | | actions | Container for the open button and optional reset button | | action-open | The main trigger button (cosmoz-button) | | action-reset | The reset/clear button (cosmoz-button, visible when showReset && nodePath) | | dialog | The <dialog> element | | header | Dialog header | | heading | Dialog heading (<h1>) | | main | Dialog main content area | | footer | Dialog footer | | select-button | The "Select" confirmation button | | cancel-button | The "Cancel" button |

Container Query Support

The host element is declared as a CSS container (container-type: inline-size). When the component's width shrinks to 80px or less, the selected node path text is automatically hidden, leaving only the icon. This allows graceful degradation in narrow layouts without media queries.

/* Built-in behavior */
:host {
	container-type: inline-size;
}

@container (max-width: 80px) {
	.path-text {
		display: none;
	}
}

<cosmoz-treenode-navigator>

The inner navigator component that provides tree browsing, search, and keyboard navigation. Typically used inside <cosmoz-treenode-button-view>, but can be used standalone.

Properties

| Property | Type | Default | Description | | ----------------------- | --------- | ----------- | ----------------------------------------------- | | tree | Tree | -- | The tree data structure (set via JS) | | nodePath | string | '' | Selected node's path locator (two-way bindable) | | highlightedNodePath | string | '' | Currently highlighted node's path (notify only) | | opened | boolean | undefined | Controls keyboard listeners and scroll behavior | | searchMinLength | number | 3 | Minimum characters to trigger search | | searchDebounceTimeout | number | 500 | Debounce timeout (ms) before search triggers |

Events

| Event | Detail | Description | | ------------------------------- | ------------------- | ----------------------------------------- | | node-path-changed | { value: string } | Fired when the selected node path changes | | highlighted-node-path-changed | { value: string } | Fired when the highlighted node changes |

CSS Custom Properties

| Property | Default | Description | | ----------------------------------------------------- | ------------------------------- | ------------------------------------------- | | --cosmoz-treenode-navigator-icon-color | currentColor | Color of navigation icons (home, arrow) | | --cosmoz-treenode-navigator-select-node-icon-color | var(--primary-color, #3a91e2) | Color of the selected/highlighted node icon | | --cosmoz-treenode-navigator-list-item-focused-color | #f0f8ff | Background color of focused list items | | --cosmoz-treenode-navigator-list-height | 50vh | Height of the scrollable node list | | --cz-text-color | inherit | General text color | | --cz-bg-color | #f5f5f5 | Section header background color |

Internationalization

All UI text is managed via i18next. The English text is used as the translation key, so it works out of the box when no translations are loaded (i18next returns the key as-is).

Consumers must initialize i18next before using the components:

import i18next from 'i18next';

i18next.init({ lng: 'en', resources: {} });

To provide translations, use i18next.addResourceBundle() or any i18next backend:

i18next.addResourceBundle('sv', 'translation', {
	'Select a node': 'Valj en nod',
	'Search or navigate to chosen destination':
		'Sok eller navigera till vald destination',
	'Search...': 'Sok...',
	'Click to search again but globally': 'Klicka for att soka igen men globalt',
	Select: 'Valj',
	Cancel: 'Avbryt',
});

Translation Keys

| Key | Used in | | ------------------------------------------ | ------------------------------------------- | | Select a node | Button placeholder when no node is selected | | Search or navigate to chosen destination | Dialog heading | | Search... | Search input placeholder | | Click to search again but globally | Global search button label | | Select | Dialog confirm button | | Cancel | Dialog cancel button |

Migrating from v7

This version includes breaking changes to the component API.

Property Changes

| Before | After | Notes | | ------------------------- | -------------------- | ------------------------------------------------------------ | | noReset (opt-out) | showReset (opt-in) | Inverted logic: set show-reset to display the reset button | | selectedNode | removed | Use nodePath instead | | highlightedNode | removed | Use highlightedNodePath (on the navigator) instead | | dialogText | removed | Now managed via i18next.t() | | buttonTextPlaceholder | removed | Now managed via i18next.t() | | searchPlaceholder | removed | Now managed via i18next.t() | | searchGlobalPlaceholder | removed | Now managed via i18next.t() |

nodePath is now the single source of truth for the selected node. Dialog navigation no longer affects the selected node until explicitly confirmed via the Select button.

Dependency Changes

| Before | After | | ------------------------- | ----------------------------- | | @neovici/cosmoz-i18next | i18next (direct dependency) |

All UI text is now translated via i18next.t() instead of being passed as component properties. See Internationalization for details.

Selector Changes

All buttons have been converted to cosmoz-button components. Update any CSS selectors accordingly:

| Before | After | | ------------------------------ | ------------------------------------- | | button.action-open | cosmoz-button[part="action-open"] | | button.action-reset | cosmoz-button[part="action-reset"] | | button[part="select-button"] | cosmoz-button[part="select-button"] | | button[part="cancel-button"] | cosmoz-button[part="cancel-button"] | | button.btn-ghost | cosmoz-button[variant="link"] |

Slot Changes

| Before | After | Notes | | --------------- | -------- | ---------------------------------------------------------- | | button-before | prefix | Now uses default slot content instead of JS-based toggling | | button-after | suffix | Renamed for consistency |

Development

| Command | Description | | ------------------------- | -------------------------------------------------- | | npm start | Start Storybook dev server on port 8000 | | npm test | Run all tests (unit + storybook interaction tests) | | npm run test:unit | Run unit tests only | | npm run test:storybook | Run storybook interaction tests only | | npm run test:watch | Run tests in watch mode | | npm run lint | Lint with ESLint | | npm run build | Compile TypeScript | | npm run storybook:build | Build static Storybook |

Tests use Vitest with two projects: unit (jsdom) for helper function tests, and storybook (Playwright browser mode) for component interaction tests via Storybook play functions.

License

Apache-2.0