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

@deloraprotocol/widget

v1.0.23

Published

A React widget component library with light/dark themes and CSS variable overrides

Readme

@deloraprotocol/widget

A React widget component library for crypto trading UI, migrated from delora-exchange (Angular). Includes Trade widget, token selection, network selection, and slippage panel. Consumers do not need Tailwind — the library ships compiled CSS.

Note: By default the widget manages wallet connection and transaction execution itself. If your app already owns wallet connection, pass it explicitly via TradeWidgetWalletProvider.

Installation

npm install @deloraprotocol/widget react react-dom

Import styles

You must import the library CSS once in your app (e.g. in your root entry file):

import "@deloraprotocol/widget/styles.css";

Usage

Trade Widget

import { TradeWidget } from "@deloraprotocol/widget";

<TradeWidget
  theme="dark"
  config={{}}
  initialBuyToken={{ chainId: 1, address: "0x..." }}
  lockBuyToken
  onQuote={(quote) => console.log("quote", quote)}
  onApprove={(payload) => console.log("approve", payload)}
  onSwap={(payload) => console.log("swap", payload)}
  onError={(error) => console.error(error)}
/>

apiUrl is used for:

  • /v1/chains
  • /v1/tokens
  • /v1/tools
  • /v1/quotes

If omitted, the widget defaults to https://api.delora.build.

apiKey is optional. For browser embeds, prefer keeping the key on your backend and pointing config.apiUrl to your own proxy instead of exposing the key in the client.

If you need to resolve relative image URLs from a custom source, pass assetBaseUrl.

External Wallet Management

Explicit Host-Managed Wallets

If your app already owns wallet connection, wrap the widget in TradeWidgetWalletProvider. The widget will use your external connect/disconnect flow and your connected providers for approve/swap execution.

import {
  TradeWidget,
  TradeWidgetWalletProvider,
} from "@deloraprotocol/widget";

<TradeWidgetWalletProvider
  value={{
    origin: {
      namespace: connected ? "EVM" : null,
      address: connectedAddress ?? null,
      walletName: "My App Wallet",
      evmProvider,
      connect: async ({ namespace }) => {
        await openMyWalletModal(namespace);
        return true;
      },
      disconnect: async () => {
        await disconnectWallet();
      },
    },
  }}
>
  <TradeWidget
    theme="dark"
    config={{
      apiUrl: "https://api.delora.build",
    }}
  />
</TradeWidgetWalletProvider>

Notes:

  • Provide origin to control the sell-side wallet. Provide destination too if your app also manages a separate receiver wallet.
  • Keep status, namespace, address, walletName, provider refs, and error fields current. The widget treats this object as the source of truth in external mode.
  • You can pass raw providers via evmProvider / solanaProvider, or getter functions if your wallet layer resolves them lazily.
  • If walletOptions is empty, the widget connect button calls connectPreferred / connect on your host wallet directly.
  • If walletOptions is provided, the widget renders its wallet picker, then delegates the selected option to your connectWalletOption.
  • For custom wallet branding in the widget UI, pass walletOptions and connectedWalletId, or set connectedWalletVisualId / connectedWalletIconUrl directly on the managed wallet.
  • If a side is omitted from TradeWidgetWalletProvider, that side uses the widget's built-in wallet flow.

Widget Picker + Host Connect

Use this mode when you want Delora's wallet selection UI but still want all connection state owned by the host app.

import {
  TradeWidget,
  TradeWidgetWalletProvider,
  type TradeWidgetManagedWallet,
} from "@deloraprotocol/widget";

const originWallet: TradeWidgetManagedWallet = {
  status,
  namespace,
  address,
  walletName,
  evmProvider,
  walletOptions: [
    {
      id: "metamask",
      label: "MetaMask",
      type: "EVM",
      availableNamespaces: ["EVM"],
      detected: Boolean(window.ethereum),
      visualId: "metamask",
    },
  ],
  connectWalletOption: async (walletId, namespace) => {
    await connectInHostWalletLayer({ walletId, namespace });
    return true;
  },
  disconnect: disconnectInHostWalletLayer,
};

<TradeWidgetWalletProvider value={{ origin: originWallet }}>
  <TradeWidget config={{ apiUrl: "https://api.delora.build" }} />
</TradeWidgetWalletProvider>;

Optional Adapter Package

@deloraprotocol/widget-wallet-management provides LI.FI-style adapters around the low-level contract above. It is separate from @deloraprotocol/widget, so Wagmi, RainbowKit, Reown, Dynamic, and Solana Wallet Adapter dependencies do not enter the core widget bundle.

npm install @deloraprotocol/widget-wallet-management

Install the peer wallet libraries your app already uses. For example, a Wagmi host installs wagmi; a Solana host installs @solana/wallet-adapter-react. If you do not install both wallet stacks, prefer subpath imports such as @deloraprotocol/widget-wallet-management/wagmi and @deloraprotocol/widget-wallet-management/solana.

Exports:

  • DeloraAutoWalletManagementProvider
  • useWagmiManagedWallet
  • useSolanaWalletAdapterManagedWallet
  • useCompositeManagedWallet
  • DeloraWalletManagementProvider
  • subpaths: /auto, /wagmi, /solana, /provider, /composite
Auto-detect External Contexts

Use DeloraAutoWalletManagementProvider when your app already renders WagmiProvider and/or Solana WalletProvider above the widget. It detects the available contexts and wires them into Delora without requiring manual adapter hooks in your app component.

import { TradeWidget } from "@deloraprotocol/widget";
import {
  DeloraAutoWalletManagementProvider,
} from "@deloraprotocol/widget-wallet-management/auto";

function DeloraWithAutoWallets() {
  return (
    <DeloraAutoWalletManagementProvider
      evm={{
        walletOptions: [],
        openConnectModal: () => openRainbowKitModal(),
      }}
      solana={{
        walletOptions: [],
        openConnectModal: () => openSolanaWalletModal(),
      }}
      usePartialWalletManagement
    >
      <TradeWidget config={{ apiUrl: "https://api.delora.build" }} />
    </DeloraAutoWalletManagementProvider>
  );
}

Partial wallet management is enabled by default. If only Wagmi is detected, Delora uses the external Wagmi wallet for EVM and keeps the built-in Solana flow. If only Solana Wallet Adapter is detected, Delora keeps the built-in EVM flow. Set usePartialWalletManagement={false} when the host wants to own all wallet namespaces and fail explicitly instead of falling back to built-in wallets. Set forceInternalWalletManagement to ignore detected contexts completely.

Wagmi / RainbowKit
import { TradeWidget } from "@deloraprotocol/widget";
import {
  DeloraWalletManagementProvider,
} from "@deloraprotocol/widget-wallet-management/provider";
import {
  useWagmiManagedWallet,
} from "@deloraprotocol/widget-wallet-management/wagmi";
import { useConnectModal } from "@rainbow-me/rainbowkit";

function DeloraWithRainbowKit() {
  const { openConnectModal } = useConnectModal();
  const evmWallet = useWagmiManagedWallet({
    walletOptions: [],
    openConnectModal: async () => {
      if (!openConnectModal) {
        throw new Error("RainbowKit connect modal is not available");
      }
      openConnectModal();
    },
  });

  return (
    <DeloraWalletManagementProvider origin={evmWallet}>
      <TradeWidget config={{ apiUrl: "https://api.delora.build" }} />
    </DeloraWalletManagementProvider>
  );
}

When openConnectModal is used, the adapter waits until Wagmi account state is actually connected before resolving the widget connect action.

For a Delora-rendered wallet picker, omit walletOptions: []. The Wagmi adapter only exposes recognized wallet rows by default, so service connectors such as Safe or Base Account do not show up unless you explicitly opt into unknown connectors with includeUnknownWalletOptions.

Solana Wallet Adapter
import { TradeWidget } from "@deloraprotocol/widget";
import {
  DeloraWalletManagementProvider,
} from "@deloraprotocol/widget-wallet-management/provider";
import {
  useSolanaWalletAdapterManagedWallet,
} from "@deloraprotocol/widget-wallet-management/solana";
import { useWalletModal } from "@solana/wallet-adapter-react-ui";

function DeloraWithSolanaWalletAdapter() {
  const { setVisible } = useWalletModal();
  const solanaWallet = useSolanaWalletAdapterManagedWallet({
    walletOptions: [],
    openConnectModal: () => setVisible(true),
  });

  return (
    <DeloraWalletManagementProvider destination={solanaWallet}>
      <TradeWidget config={{ apiUrl: "https://api.delora.build" }} />
    </DeloraWalletManagementProvider>
  );
}

The Solana adapter maps Wallet Adapter state to Delora's SolanaProvider contract. v1 execution requires a wallet adapter with signTransaction. Undetected Solana adapters are hidden from the widget picker by default; pass includeUndetectedWallets: true to show installable rows.

Composite EVM + Solana
const evm = useWagmiManagedWallet();
const solana = useSolanaWalletAdapterManagedWallet();
const wallet = useCompositeManagedWallet({ evm, solana });

<DeloraWalletManagementProvider wallet={wallet}>
  <TradeWidget config={{ apiUrl: "https://api.delora.build" }} />
</DeloraWalletManagementProvider>;

For cross-chain flows where origin and destination should prefer different namespaces, pass separate composites:

const origin = useCompositeManagedWallet({
  evm,
  solana,
  preferredNamespace: "EVM",
});
const destination = useCompositeManagedWallet({
  evm,
  solana,
  preferredNamespace: "SVM",
});

<DeloraWalletManagementProvider origin={origin} destination={destination}>
  <TradeWidget config={{ apiUrl: "https://api.delora.build" }} />
</DeloraWalletManagementProvider>;

Scope for the adapter package v1 is EVM + SVM. Sui and Bitcoin are not included because the current Delora execution flow does not support them.

Simple Widget (MyWidget)

import { MyWidget, TradeWidget } from "@deloraprotocol/widget";

<MyWidget theme="light" />
<MyWidget theme="dark" />
<MyWidget vars={{ accent: "#22c55e", radius: "24px" }} />
<TradeWidget
  config={{ apiUrl: "https://api.delora.build" }}
  vars={{ radius: "24px", actionButtonRadius: "999px" }}
/>
<MyWidget className="max-w-md" style={{ marginLeft: "2rem" }} />

radius controls the widget surface corners, while actionButtonRadius lets you round the main CTA independently.

API

Exports

Additional wallet-management exports:

  • TradeWidgetWalletProvider

  • TradeWidgetManagedWallet

  • TradeWidgetWalletManagement

  • MyWidget — the widget component

  • TradeWidget — trade widget with token/network selection and quote flow

  • MyWidgetTheme"light" | "dark"

  • MyWidgetVars — typed object for token overrides

  • MyWidgetProps — component props

  • TradeWidgetProps, TradeWidgetConfig

  • TradeWidgetTokenSelection

  • TradeWidgetQuotePayload

  • TradeWidgetActionPayload

  • TradeWidgetErrorPayload

  • Token, Network

MyWidgetProps

| Prop | Type | Description | |----------|-------------------|--------------------------------------------------| | theme | "light" \| "dark" | Built-in theme (default: "light") | | vars | Partial<MyWidgetVars> | Override theme tokens via CSS variables | | className | string | Applied to root (for host layout/styling) | | style | React.CSSProperties | Applied last for advanced overrides |

Extends React.HTMLAttributes<HTMLDivElement> for other div props.

TradeWidgetProps

TradeWidgetProps extends normal root div props except DOM onError, which is reserved for the widget error callback below.

| Prop | Type | Description | |----------|-------------------|--------------------------------------------------| | config | TradeWidgetConfig | Widget runtime config | | theme | "light" \| "dark" | Built-in theme (default: "dark") | | vars | Partial<MyWidgetVars> | Override theme tokens via CSS variables | | initialSellToken | { chainId: number; address: string } | Preselect sell token | | initialBuyToken | { chainId: number; address: string } | Preselect buy token | | initialSellNetworkId | number | Preselect sell network | | initialBuyNetworkId | number | Preselect buy network | | lockSellToken | boolean | Prevent changing sell token | | lockBuyToken | boolean | Prevent changing buy token | | lockSellNetwork | boolean | Prevent changing sell network | | lockBuyNetwork | boolean | Prevent changing buy network | | onQuote | (payload) => void | Called when a new quote is resolved | | onApprove | (payload) => void | Called when the user presses Approve | | onSwap | (payload) => void | Called when the user presses Swap | | onError | (payload) => void | Called for metadata, selection, and quote errors |

TradeWidgetConfig

| Prop | Type | Description | |----------|-------------------|--------------------------------------------------| | apiUrl | string | Optional Delora API base for /v1/chains, /v1/tokens, /v1/tools, /v1/quotes | | rpcUrls | Record<number, string[]> | Optional RPC override map by chain id | | integrator | string | Optional integrator id passed to quote requests | | apiKey | string | Optional Delora API key sent as x-api-key; for browser embeds, prefer using a backend proxy | | fee | number | Optional Delora fee value for quote requests, in the range 0..0.1 | | slippage | number | Optional initial slippage override | | excludeBridges | string[] | Optional bridge denylist for quotes | | excludeExchanges | string[] | Optional exchange denylist for quotes | | assetBaseUrl | string | Optional base for resolving relative image URLs | | termsUrl | string | Optional Terms of Use URL shown in the connect modal | | privacyPolicyUrl | string | Optional Privacy Policy URL shown in the connect modal | | walletConnectProjectId | string | Optional WalletConnect Cloud project id |

Callback payloads

  • onQuote(payload) returns selected sell/buy network, selected sell/buy token, current sell/buy amounts, slippage, and the raw Delora quote.
  • onApprove(payload) and onSwap(payload) return the current selection plus quote, txData, price, and gasCostUSD.
  • onError(payload) returns { source, message, status?, statusCode?, error? }, where source is one of metadata, selection, or quote.

Locking behavior

  • lockBuyToken / lockSellToken disable token picking and also freeze the related network, because the token already implies a chain.
  • lockBuyNetwork / lockSellNetwork disable network changes but keep token selection available within the locked chain.
  • Any lock also disables the center "swap sides" button to avoid silently breaking host-provided constraints.

Why no Tailwind required in host

The library uses Tailwind only at build time to author styles. The output is plain compiled CSS shipped in dist/styles.css. Your host app imports this CSS file and does not need Tailwind, PostCSS, or any build-time Tailwind configuration.

Style isolation

The library provides style isolation without Shadow DOM:

  1. Our styles don't affect the host: We disable Tailwind preflight and do not emit global element selectors (e.g. no button {} or h1 {}). All styling is class-based and scoped within the widget markup.

  2. Host styles have limited impact on us: We add a minimal scoped reset under [data-delora-widget-root]:

    • box-sizing: border-box on root and descendants
    • Explicit font-family, font-size, color, line-height on the root
  3. Limitations: Host global styles (e.g. * { box-sizing: content-box; } or button { font-size: 30px; }) can still affect the widget in extreme cases. We mitigate by setting explicit values on the widget root and avoiding reliance on inherited defaults.

Build

npm run build

Outputs:

  • dist/index.js (ESM)
  • dist/index.d.ts
  • dist/styles.css

Publishing to npm

Prerequisites

First-time publish

  1. Build the package:

    npm run build
  2. Log in to npm:

    npm login

    Enter your username, password, and email. If 2FA is enabled, enter the one-time code.

  3. Publish (scoped packages require --access public):

    npm publish --access public

Publishing updates

  1. Bump the version:

    npm version patch   # 1.0.0 → 1.0.1 (bug fixes)
    npm version minor   # 1.0.0 → 1.1.0 (new features)
    npm version major   # 1.0.0 → 2.0.0 (breaking changes)
  2. Build and publish:

    npm run build
    npm publish --access public

Org members

  • Add members under Organization → Members on npmjs.com
  • Any member with publish rights can publish and update the package
  • Only one person needs to create the org; others can be invited

Running the widget locally

One-time setup

npm install
npm run build
cd playground && npm install

Development

npm run playground:dev

This runs the library watcher and the playground dev server together. The playground uses the built output from dist/.

When errors occur or the UI shows stale/broken code: run npm run build separately to rebuild the library, then restart or refresh the playground. The playground does not auto-rebuild the library.

Alternative: build then run

npm run build
cd playground && npm run dev

Build the library first, then run only the playground dev server.