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

solid-nativescript-js

v0.0.1

Published

Zero-overhead SolidJS <-> NativeScript bridge. PascalCase elements mapped 1:1 to @nativescript/core classes — no DOM emulation layer.

Readme

solid-nativescript-js

Zero-overhead SolidJS ↔ NativeScript bridge. JSX tags written in their original PascalCase (<StackLayout>, <ActionBar>, <Label>, ...) are matched 1:1 to their @nativescript/core class constructors — no document, no dominative, no undom-ng, and the tag string is never lowercased anywhere on the path.

import { run, Frame, Page, ActionBar, StackLayout, Label, Button, createSignal } from 'solid-nativescript-js'

const Home = () => {
  const [count, setCount] = createSignal(0)
  return (
    <>
      <ActionBar title="App" />
      <StackLayout>
        <Label text="Clean Code" />
        <Button text="Tap me" onTap={() => setCount(c => c + 1)} />
      </StackLayout>
    </>
  )
}

run(() => (
  <Frame>
    <Page><Home /></Page>
  </Frame>
))

Why this package exists

The legacy @nativescript-community/solid-js stack renders through dominative + undom-ng, a full web-DOM emulation layer on top of NativeScript. This package replaces that stack with a lean universal reconciler: SolidJS's own createRenderer (from solid-js/universal) drives diffing and effect-based updates; this package supplies native operations that talk directly to @nativescript/core views.

Architecture

| Module | Responsibility | | ----------------- | ------------------------------------------------------------------------------ | | src/registry.ts | PascalCase tag → core constructor map (+ registerElement for plugin views). | | src/renderer.ts | createRenderer wiring: createElement/insert/remove/setText on native views. | | src/props.ts | Attribute binding: splits onTap/on:tap events from props, class, style, ref, android:/ios: prefixes. | | src/nodes.ts | Per-container-kind child insertion (layouts, content slots, ActionBar, FormattedString, TabView, Frame navigation) + recursive destroyView teardown. | | src/listeners.ts| Strict event-lifecycle tracking: every .on() the bridge registers is tracked so teardown can always unbind it. Leak audits via activeListenerCount() / getGlobalListenerReport(). | | src/component.ts+ src/elements.ts | Typed components for every built-in view. TypeScript resolves UPPERCASE JSX tags as values, so each view is exported as a component that instantiates the native class via the registry. Generated from the nativescript-dom/types workspace (scripts/generate-pascal-types.py). | | src/app.ts | run() / createAppRoot(): root context, view-tree instantiation, anchoring into Application.run, full disposal. | | src/vite.ts | solidNativeScript() Vite plugin: universal-mode Solid compiler (moduleName: 'solid-nativescript-js') + solid-js aliasing (client dists only; solid-js/web rerouted to this bridge). |

Memory management

NativeScript bridges V8/JSC to Java/Objective-C, so orphaned closures leak across runtimes. The bridge therefore:

  • tracks every event listener it binds (listeners.ts), with optional bind/unbind logging via setListenerLogging(true);
  • removes a node ⇒ recursively destroys it: unbinds all tracked listeners, detaches/destroys children, nulls bridge back-references, empties container slots and calls disposeNativeView() so platform GC can reclaim memory;
  • disposes the Solid root and tears down the whole tree via the disposer returned by render()/createAppRoot() (and disposeCurrentApp()).

Usage

Install

npm i solid-nativescript-js solid-js @nativescript/core
npm i -D @nativescript/vite vite vite-plugin-solid \
  @nativescript-dom/core-types @nativescript-dom/solidjs-types

vite.config.mts

import { defineConfig, mergeConfig } from 'vite'
import { baseConfig } from '@nativescript/vite/base'
import { solidNativeScript } from 'solid-nativescript-js/vite'

export default defineConfig(({ mode }) =>
  mergeConfig(baseConfig({ mode, flavor: 'solid' }), {
    plugins: [solidNativeScript({ mode })],
  })
)

nativescript.config.ts

export default {
  // ...
  bundler: 'vite',
  bundlerConfigPath: 'vite.config.mts',
} as NativeScriptConfig

Typings

Set the JSX type source to the official nativescript-dom typings and import your elements from this package (TypeScript resolves uppercase JSX tags as component values):

// tsconfig.json
{
  "compilerOptions": {
    "jsx": "preserve",
    "jsxImportSource": "@nativescript-dom/solidjs-types",
    "types": ["@nativescript-dom/core-types", "@nativescript-dom/solidjs-types"]
  }
}

Events

  • onTap={fn}view.on('tap', fn) (the char after on is lowercased: onTextChangetextChange).
  • on:tap={fn} binds the raw event name verbatim.
  • Reassignment unbinds the previous handler; node removal unbinds everything.

Plugin views

import { registerElement } from 'solid-nativescript-js'
import { RadSideDrawer } from '@nativescript-community/ui-drawer'
registerElement('RadSideDrawer', RadSideDrawer, 'content')

Development

bun install        # deps
bun test           # unit/integration suite (bun, mocked @nativescript/core, real solid-js)
bun run typecheck  # strict TS
bun run build      # emit dist/ (ESM + d.ts)
python3 scripts/generate-pascal-types.py   # regenerate src/elements.ts from types/

Tests mock @nativescript/core but run the real solid-js universal renderer, so reconciliation, moves, keyed lists and disposal are covered end-to-end.