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

@xtyle/svelte

v0.8.0

Published

Thin Svelte wrappers over the @xtyle/core/elements custom elements.

Downloads

577

Readme

@xtyle/svelte

npm docs license

Thin Svelte 5 wrappers over the @xtyle/core custom elements, the Svelte binding of the xtyle component contract. Each wrapper is a typed Svelte component that renders the matching <xtyle-*> element and forwards its props, slots, and arbitrary attributes ({...rest} lands on the element).

Install

npm install @xtyle/svelte @xtyle/core

svelte@^5 is a peer dependency; @xtyle/core (pulled in automatically) provides the custom elements and the derivation engine.

Usage

<script>
  import { Button, Badge, Card } from "@xtyle/svelte";
</script>

<Card>
  <Badge tone="success">new</Badge>
  <Button tone="accent">Save</Button>
</Card>

Components are styled entirely by design tokens, the CSS custom properties a xtyle algorithm derives. Drop a derived theme on :root (or any ancestor) and every component themes with it; no per-component styling required. See @xtyle/core for deriving and applying a theme, and xtyle.dev for the full component reference.

Importing a component registers only that element

This is a behavior change. Each wrapper now pulls in its own custom element (@xtyle/core/elements/button.js) instead of the whole-element barrel. Importing Button registers <xtyle-button> — and nothing else.

Previously, importing any component registered all 87 elements as a side effect, so hand-written markup happened to work whether or not you had imported the matching wrapper. That also meant a page rendering a single Card shipped every element in the library, plus the ~300 Prism grammar chunks the code element's language table reaches. A single-component build drops from 308 files / 11.5 MiB to 9 files / 9.9 MiB on this change alone (and to 7 files / 2.1 MiB once the QuickJS debug variants are stubbed — see below).

What breaks: hand-written <xtyle-*> markup for an element whose wrapper you never imported. It will render as an inert unknown tag — no upgrade, no styling, no error.

<script>
  import { Button } from "@xtyle/svelte";
</script>

<Button>fine</Button>
<!-- inert: nothing registered <xtyle-badge> -->
<xtyle-badge tone="accent">not upgraded</xtyle-badge>

Two ways to fix it. Import the wrapper and use it (preferred — you keep the payload win):

<script>
  import { Button, Badge } from "@xtyle/svelte";
</script>

<Badge tone="accent">upgraded</Badge>

…or restore the old register-everything behavior in one line, if you drive the elements as raw markup and don't want to enumerate them:

<script>
  import "@xtyle/svelte/register";
</script>

<xtyle-badge tone="accent">upgraded</xtyle-badge>

@xtyle/svelte/register registers all 87 elements up front. It is the explicit opt-in to the old behavior, and it costs the old bundle size — reach for it only when you need it.

Trimming the QuickJS debug WebAssembly

Components paint their chrome through xript's sandboxed QuickJS runtime, so its WebAssembly is load-bearing — but only the release variants are ever selected. quickjs-emscripten statically imports all four variants behind getters a bundler cannot see through, so the two debug builds (7.81 MiB of .wasm) land in every consumer bundle with nothing referencing them. Alias them to an inert stub:

// vite.config.js
import { defineConfig } from "vite";

export default defineConfig({
  resolve: {
    alias: {
      "@jitl/quickjs-wasmfile-debug-sync": "/path/to/quickjs-debug-stub.js",
      "@jitl/quickjs-wasmfile-debug-asyncify": "/path/to/quickjs-debug-stub.js",
    },
  },
});
// quickjs-debug-stub.js — importing it is inert; only *using* a debug variant raises.
export default new Proxy(
  {},
  {
    get(_t, prop) {
      if (prop === "then" || typeof prop === "symbol") return undefined;
      throw new Error("QuickJS debug variants are stubbed out at build time.");
    },
  },
);

This drops the two debug .wasm files and leaves the release pair (1.52 MiB) that the runtime actually loads. Do not stub the release variants: without them the fragment runtime cannot initialize and client-rendered elements log the component fragment runtime failed to load and paint nothing.

License

MIT