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

@taskon/widget-react

v0.0.1-beta.2

Published

TaskOn React Widget Library

Readme

@taskon/widget-react

TaskOn React Widget - Embeddable white-label components for integrating TaskOn quest/task functionality into your application.

Installation

npm install @taskon/widget-react @taskon/core
# or
pnpm add @taskon/widget-react @taskon/core
# or
yarn add @taskon/widget-react @taskon/core

Quick Start

// Providers from core (minimal CSS ~3KB)
import { TaskOnProvider } from "@taskon/widget-react/core";
// Widgets from their sub-paths (isolated CSS)
import { QuestWidget } from "@taskon/widget-react/quest";

const App = () => (
  <TaskOnProvider
    config={{
      apiKey: "your-api-key",
    }}
  >
    <YourApp />
  </TaskOnProvider>
);

Import Methods

Recommended: Sub-path Imports (Optimal CSS)

// Core: Providers and hooks only (~3KB CSS for Toast)
import { TaskOnProvider, ThemeProvider, useTaskOnAuth } from "@taskon/widget-react/core";

// Widgets: Each loads only its own CSS
import { QuestWidget } from "@taskon/widget-react/quest";           // ~26KB CSS
import { CommunityTaskList } from "@taskon/widget-react/community-task"; // ~51KB CSS
import { LeaderboardWidget } from "@taskon/widget-react/leaderboard";   // ~17KB CSS
import { UserCenterWidget } from "@taskon/widget-react/user-center";    // UserCenter CSS only

Alternative: Main Entry Import (Loads All CSS)

// Loads ALL widget CSS (~92KB) - not recommended for production
import { TaskOnProvider, QuestWidget, CommunityTaskList } from "@taskon/widget-react";

Usage Example

import { TaskOnProvider, useTaskOnAuth } from "@taskon/widget-react/core";
import { QuestWidget } from "@taskon/widget-react/quest";

const App = () => (
  <TaskOnProvider
    config={{
      apiKey: "your-api-key",
    }}
  >
    <YourApp />
  </TaskOnProvider>
);

// Your app controls the login UI
const YourApp = () => {
  const { userId, login, logout } = useTaskOnAuth();
  const { user, getSignature } = useYourAuth(); // Your auth hook

  // When user logs in to your app, login to TaskOn
  useEffect(() => {
    if (user?.email && !userId) {
      const { sign, timestamp } = getSignature(); // Get signature from your backend
      login({ method: "email", value: user.email, sign, timestamp });
    }
  }, [user, userId]);

  // When user logs out from your app, logout from TaskOn
  useEffect(() => {
    if (!user && userId) {
      logout();
    }
  }, [user, userId]);

  return (
    <div>
      {userId && <p>TaskOn User ID: {userId}</p>}
      {/* Theme configured in TaskOn Dashboard */}
      <QuestWidget configId="cfg_abc123" />
    </div>
  );
};

Architecture

┌─ TaskOnProvider ─────────────────────────────────────────┐
│  config: { apiKey }                                      │
│  Purpose: Authentication only                            │
│                                                          │
│  ┌─ Mode A: Cloud Config ──────────────────────────────┐ │
│  │  <QuestWidget configId="cfg_abc123" />              │ │
│  │  → Theme from TaskOn cloud                          │ │
│  └─────────────────────────────────────────────────────┘ │
│                                                          │
│  ┌─ Mode B: Local Theme ───────────────────────────────┐ │
│  │  <ThemeProvider theme={{ mode: 'dark' }}>           │ │
│  │    <QuestWidget />  /* no configId */               │ │
│  │  </ThemeProvider>                                   │ │
│  └─────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘

Theme Source (mutually exclusive)

| Mode | Theme Source | | --------------------- | ------------------------------------ | | configId provided | Cloud config (ThemeProvider ignored) | | No configId | ThemeProvider or default theme |

Security

TaskOn uses API Key authentication to verify that widget requests come from authorized projects.

Step 1: Get API Key from TaskOn Dashboard

API Key:  /KDiqEFNCaGTVTdTpCFrZOsUj5vDi5uGLSFmwyHeboE=  (for X-API-Key header)

Step 2: Configure TaskOnProvider

<TaskOnProvider
  config={{
    apiKey: "your-api-key",
  }}
>
  <YourApp />
</TaskOnProvider>;

HTTP Headers

All API requests include:

X-API-Key: your-api-key        # Project authorization
Authorization: Bearer xxx       # User authorization (after login)

Security Best Practices

  1. Keep API Key secure - Don't expose in public repositories
  2. Use HTTPS - All communication must be encrypted

TaskOnProvider

The root provider component for authentication. Must wrap your application.

Props

| Prop | Type | Required | Default | Description | | ------------ | ------------------------ | -------- | ------- | -------------------- | | config | TaskOnProviderConfig | Yes | - | Configuration object | | children | ReactNode | Yes | - | Child components |

TaskOnProviderConfig

interface TaskOnProviderConfig {
  // Required: API Key for authentication (X-API-Key header)
  apiKey: string;

  // Locale setting
  locale?: "en" | "ko" | "ja" | "ru" | "es"; // default: auto-detect

  // Wallet configuration (only needed if using wallet login)
  walletConfig?: {
    evmAdapter?: WalletAdapter; // Custom EVM wallet adapter
    solanaAdapter?: WalletAdapter; // Custom Solana wallet adapter
    disableAutoDetect?: boolean; // Disable auto-detection
  };

  // WalletConnect Project ID (required for WalletConnect support)
  // Get your project ID at https://cloud.walletconnect.com
  walletConnectProjectId?: string;

  // Callback when user needs to login (e.g., clicks login overlay)
  onRequestLogin?: () => void;
}

Internationalization

Supported Locales

| Locale | Language | | ------ | ----------------- | | en | English (default) | | ko | Korean | | ja | Japanese | | ru | Russian | | es | Spanish |

Configuration

<TaskOnProvider
  config={{
    apiKey: "your-api-key",
    locale: "ko",
  }}
>
  <App />
</TaskOnProvider>

Dynamic Locale Switching

Control locale via your own state:

const App = () => {
  const [locale, setLocale] = useState("en");

  return (
    <TaskOnProvider config={{ apiKey: "your-api-key", locale }}>
      <select value={locale} onChange={(e) => setLocale(e.target.value)}>
        <option value="en">English</option>
        <option value="ko">한국어</option>
        <option value="ja">日本語</option>
      </select>
      <QuestWidget configId="cfg_abc123" />
    </TaskOnProvider>
  );
};

Locale Auto-Detection

When locale is not specified, TaskOn detects from browser language, falling back to en.

ThemeProvider

Optional provider for theme configuration. Supports nesting for different theme zones.

Props

| Prop | Type | Required | Default | Description | | ------------ | --------------------- | -------- | -------- | -------------------- | | theme | TaskOnThemeConfig | No | - | Theme configuration | | children | ReactNode | Yes | - | Child components | | inherit | boolean | No | true | Inherit parent theme |

TaskOnThemeConfig

interface TaskOnThemeConfig {
  // Theme mode
  mode?: "light" | "dark" | "auto"; // default: 'light'

  // Compact mode
  compact?: boolean; // default: false

  // Seed tokens - algorithm input, auto-derives other values
  seed?: SeedToken;

  // Map tokens - override derived values
  map?: MapToken;

  // Optional: separate config for light/dark mode
  light?: {
    seed?: SeedToken;
    map?: MapToken;
  };
  dark?: {
    seed?: SeedToken;
    map?: MapToken;
  };
}

interface SeedToken {
  colorPrimary?: string; // e.g., '#6366f1'
  colorSecondary?: string;
  colorSuccess?: string;
  colorWarning?: string;
  colorError?: string;
  borderRadius?: number; // e.g., 8
  fontSize?: number; // e.g., 14
  fontFamily?: string;
}

interface MapToken {
  // Primary colors (derived from seed.colorPrimary)
  colorPrimary?: string;
  colorPrimaryHover?: string;
  colorPrimaryActive?: string;
  colorPrimaryBg?: string;

  // Background
  colorBg?: string;
  colorBgElevated?: string;
  colorBgSpotlight?: string;

  // Text
  colorText?: string;
  colorTextSecondary?: string;
  colorTextTertiary?: string;
  colorTextDisabled?: string;

  // Border
  colorBorder?: string;
  colorBorderSecondary?: string;

  // Layout
  borderRadius?: number;
  borderRadiusSm?: number;
  borderRadiusLg?: number;

  // Typography
  fontSize?: number;
  fontSizeSm?: number;
  fontSizeLg?: number;

  // Spacing
  spacing?: number; // base spacing unit, e.g., 8
  spacingXs?: number; // e.g., 4
  spacingSm?: number; // e.g., 8
  spacingMd?: number; // e.g., 16
  spacingLg?: number; // e.g., 24
  spacingXl?: number; // e.g., 32
}

Token Priority

light/dark.map > light/dark.seed (derived) > map > seed (derived) > default

Theme Inheritance

Nested ThemeProviders inherit from parent and can override specific values:

<TaskOnProvider config={{ apiKey: "your-api-key" }}>
  <ThemeProvider theme={{ mode: "light", seed: { colorPrimary: "#6366f1" } }}>
    <Header /> {/* light + primary #6366f1 */}
    <ThemeProvider theme={{ mode: "dark" }}>
      <Sidebar /> {/* dark + inherits primary #6366f1 */}
    </ThemeProvider>
    <ThemeProvider theme={{ seed: { colorPrimary: "#ef4444" } }}>
      <DangerZone /> {/* light + primary #ef4444 */}
    </ThemeProvider>
  </ThemeProvider>
</TaskOnProvider>

Light/Dark Separate Config

Configure different themes for light and dark modes:

// Different primary colors for each mode
<ThemeProvider
  theme={{
    mode: 'auto',
    light: { seed: { colorPrimary: '#6366f1' } },
    dark: { seed: { colorPrimary: '#818cf8' } },
  }}
>
  <App />
</ThemeProvider>

// Override specific derived values
<ThemeProvider
  theme={{
    mode: 'auto',
    light: {
      seed: { colorPrimary: '#6366f1' },
      map: { colorPrimaryHover: '#4f46e5' },
    },
    dark: {
      seed: { colorPrimary: '#818cf8' },
      map: { colorBg: '#0a0a0a' },
    },
  }}
>
  <App />
</ThemeProvider>

Disable Inheritance

Use inherit={false} for completely independent themes:

<ThemeProvider theme={{ mode: "dark" }}>
  <DarkContent />

  <ThemeProvider theme={{ mode: "light" }} inherit={false}>
    <LightPopup /> {/* Fully independent light theme */}
  </ThemeProvider>
</ThemeProvider>

Widgets

Cloud Configuration

Widgets support cloud configuration via configId. Configure in TaskOn Dashboard and load at runtime:

// Cloud config includes: theme, feature flags, custom texts
<QuestWidget configId="cfg_abc123" />

Widget Props

interface WidgetProps {
  // Cloud config ID from TaskOn Dashboard
  configId?: string;

  // Custom class names for widget parts
  classNames?: {
    root?: string;
    header?: string;
    body?: string;
    footer?: string;
    // ... widget-specific parts
  };

  // Custom inline styles for widget parts
  styles?: {
    root?: React.CSSProperties;
    header?: React.CSSProperties;
    body?: React.CSSProperties;
    footer?: React.CSSProperties;
    // ... widget-specific parts
  };
}

Styling with classNames and styles

Widgets support fine-grained styling via classNames and styles props:

// Using classNames
<QuestWidget
  configId="cfg_abc123"
  classNames={{
    root: 'my-quest-widget',
    header: 'my-quest-header',
    body: 'my-quest-body',
  }}
/>

// Using inline styles
<QuestWidget
  configId="cfg_abc123"
  styles={{
    root: { maxWidth: 400 },
    header: { borderBottom: '1px solid #eee' },
    body: { padding: 24 },
  }}
/>

// Combining both
<QuestWidget
  configId="cfg_abc123"
  classNames={{ root: 'custom-widget' }}
  styles={{ header: { backgroundColor: 'transparent' } }}
/>

Each widget documents its available parts in its own API reference.

Usage Examples

// Example 1: Using cloud config (theme from Dashboard)
<TaskOnProvider config={{ apiKey: 'your-api-key' }}>
  <QuestWidget configId="cfg_abc123" />
  <TaskWidget configId="cfg_xyz789" />
</TaskOnProvider>

// Example 2: Using local theme (no cloud config)
<TaskOnProvider config={{ apiKey: 'your-api-key' }}>
  <ThemeProvider theme={{ mode: 'dark', seed: { colorPrimary: '#6366f1' } }}>
    <QuestWidget />
    <TaskWidget />
  </ThemeProvider>
</TaskOnProvider>

// Example 3: Different local themes for different areas
<TaskOnProvider config={{ apiKey: 'your-api-key' }}>
  <ThemeProvider theme={{ mode: 'light' }}>
    <TaskWidget />
  </ThemeProvider>

  <ThemeProvider theme={{ mode: 'dark', compact: true }}>
    <QuestWidget />
  </ThemeProvider>
</TaskOnProvider>

// Example 4: Mixed - some with cloud config, some with local theme
<TaskOnProvider config={{ apiKey: 'your-api-key' }}>
  {/* Cloud config */}
  <QuestWidget configId="cfg_abc123" />

  {/* Local theme */}
  <ThemeProvider theme={{ mode: 'dark' }}>
    <TaskWidget />
  </ThemeProvider>
</TaskOnProvider>

Login Methods

TaskOn uses a unified login method with signature verification. All login methods require a backend signature for security.

Unified Login API

import { useTaskOnAuth } from "@taskon/widget-react";

const { login } = useTaskOnAuth();

// Login with any method
await login({
  method: "evm_wallet", // Login method type
  value: "0x1234...", // Address / email / OAuth token
  sign: signatureFromBackend, // Backend signature
  timestamp: 1234567890, // Signature timestamp (seconds)
});

Supported Methods

| Method | method value | value parameter | | ------------- | ----------------- | ----------------------- | | EVM Wallet | evm_wallet | Wallet address (0x...) | | Solana Wallet | solana_wallet | Wallet address (base58) | | Email | email | Email address | | Discord | discord | OAuth token | | Twitter | twitter | OAuth token | | Telegram | telegram | OAuth token |

LoginParams Type

interface LoginParams {
  method: LoginMethod; // Login method type
  value: string; // Address / email / OAuth token
  sign: string; // Backend signature
  timestamp: number; // Signature timestamp (seconds)
}

type LoginMethod =
  | "evm_wallet"
  | "solana_wallet"
  | "email"
  | "discord"
  | "twitter"
  | "telegram";

Wallet Integration

When tasks or rewards involve blockchain operations (e.g., token rewards, NFT minting, on-chain verification), widgets need to interact with the user's wallet for:

  • Connecting wallet - Get user's wallet address
  • Signing messages - Verify wallet ownership
  • Calling contracts - Claim on-chain rewards, execute transactions

Overview

TaskOn widgets include built-in wallet management, but also support external wallet providers for seamless integration with existing dApps. When wrapped in an external provider, the widget automatically detects and reuses your wallet management.

Wallet Management

TaskOn provides flexible wallet integration options:

| Setup | Behavior | | -------------- | ------------------------------------- | | Custom adapter | Uses your provided WalletAdapter | | Default | Uses built-in window.ethereum adapter |

Custom Wallet Adapter (Recommended)

If you want full control over wallet connection (e.g., using RainbowKit, Web3Modal), provide a custom adapter:

import { createWalletAdapter } from "./my-wallet-adapter";

<TaskOnProvider
  config={{
    apiKey: "your-api-key",
    walletConfig: {
      evmAdapter: createWalletAdapter(),
    },
  }}
>
  <App />
</TaskOnProvider>;

Built-in Wallet Support

If no custom adapter is provided, TaskOn automatically uses window.ethereum to connect to browser wallets like MetaMask:

// No wallet config needed - uses window.ethereum by default
<TaskOnProvider config={{ apiKey: "your-api-key" }}>
  <App />
</TaskOnProvider>

Built-in Wallet Binding Dialog

When tasks require wallet binding (e.g., on-chain verification), TaskOn shows a built-in wallet selection dialog:

Desktop (without adapter):

  • MetaMask
  • ONTO Wallet
  • Bitget Wallet
  • OKX Wallet
  • WalletConnect (requires walletConnectProjectId)

Mobile (non-Dapp browser):

  • WalletConnect only (requires walletConnectProjectId)

Mobile (Dapp browser / wallet app):

  • Uses injected provider directly

To enable WalletConnect in the dialog:

<TaskOnProvider
  config={{
    apiKey: "your-api-key",
    walletConnectProjectId: "your-project-id", // Get from cloud.walletconnect.com
  }}
>
  <App />
</TaskOnProvider>

Built-in Wallet Management

If no external provider is detected, the widget uses its built-in wallet management. No configuration needed:

<TaskOnProvider config={{ apiKey: "your-api-key" }}>
  <App /> {/* Widget handles wallet connection internally */}
</TaskOnProvider>

Configuration Options

interface WalletConfig {
  // EVM wallet adapter (highest priority)
  evmAdapter?: WalletAdapter;

  // Solana wallet adapter (highest priority)
  solanaAdapter?: WalletAdapter;

  // Disable auto-detection of external providers
  disableAutoDetect?: boolean;
}

Custom Wallet Adapter

For projects with their own wallet management:

// Example: Custom wallet management
const useCustomWalletAdapter = (): WalletAdapter => {
  const { openWalletModal, connectedAddress, chainId } = useYourWalletManager();

  return {
    connect: async () => {
      // Open your wallet selection modal, return selected address
      const address = await openWalletModal();
      return address;
    },
    disconnect: async () => {
      await yourDisconnectLogic();
    },
    signMessage: async (message) => {
      return await yourSignMessageLogic(message);
    },
    getAddress: () => connectedAddress,
    getChainId: () => chainId,
    switchNetwork: async (chainId) => {
      await yourSwitchNetworkLogic(chainId);
    },
  };
};

const App = () => {
  const evmAdapter = useCustomWalletAdapter();

  return (
    <TaskOnProvider
      config={{
        apiKey: "your-api-key",
        walletConfig: { evmAdapter },
      }}
    >
      <YourApp />
    </TaskOnProvider>
  );
};

Priority Order

When multiple options are available:

  1. Custom Adapter - walletConfig.evmAdapter / solanaAdapter (highest)
  2. Built-in Adapter - window.ethereum adapter for EVM wallets (lowest)

Hooks

useTaskOnAuth

Access TaskOn authentication with unified login method.

import { useTaskOnAuth } from "@taskon/widget-react";

const Component = () => {
  const {
    // State
    userId, // TaskOn user ID (number | null)
    isLoggedIn, // Whether user is logged in
    isInitializing, // Whether provider is initializing

    // Unified login method
    login, // (params: LoginParams) => Promise<void>

    // Logout
    logout, // () => void
  } = useTaskOnAuth();

  return <div>TaskOn ID: {userId}</div>;
};

Login Function

// Unified login method
login: (params: LoginParams) => Promise<void>;

// LoginParams
interface LoginParams {
  method: LoginMethod;  // Login method type
  value: string;        // Address / email / OAuth token
  sign: string;         // Backend signature
  timestamp: number;    // Signature timestamp (seconds)
}

// Logout
logout: () => void;

useTaskOnTheme

Access current theme. Must be used within ThemeProvider.

import { useTaskOnTheme } from "@taskon/widget-react";

const Component = () => {
  const theme = useTaskOnTheme();

  return (
    <div
      style={{
        background: theme.tokens.colorBg,
        color: theme.tokens.colorText,
        padding: theme.tokens.spacingMd,
        borderRadius: theme.tokens.borderRadius,
      }}
    >
      Current mode: {theme.mode}
    </div>
  );
};

Integration Examples

// Example 1: With EVM Wallet
const EVMWalletIntegration = () => {
  const { evmAddress } = useWallet(); // TaskOn wallet hook
  const { userId, login } = useTaskOnAuth();

  const handleLogin = async () => {
    if (evmAddress && !userId) {
      // Get signature from your backend
      const { sign, timestamp } = await fetchSignatureFromBackend(evmAddress);
      await login({
        method: "evm_wallet",
        value: evmAddress,
        sign,
        timestamp,
      });
    }
  };

  useEffect(() => {
    handleLogin();
  }, [evmAddress, userId]);

  return <div>{userId ? `TaskOn: ${userId}` : "Not logged in"}</div>;
};

// Example 2: With Custom Wallet Adapter
const CustomWalletIntegration = () => {
  const { evmAddress, connectEvm } = useWallet();
  const { userId, login } = useTaskOnAuth();

  const handleLogin = async () => {
    if (publicKey && !userId) {
      const address = publicKey.toBase58();
      const { sign, timestamp } = await fetchSignatureFromBackend(address);
      await login({
        method: "solana_wallet",
        value: address,
        sign,
        timestamp,
      });
    }
  };

  useEffect(() => {
    handleLogin();
  }, [publicKey, userId]);

  return <div>{userId ? `TaskOn: ${userId}` : "Not logged in"}</div>;
};

// Example 3: Email login
const EmailLogin = () => {
  const { login } = useTaskOnAuth();

  const handleEmailLogin = async (email: string) => {
    const { sign, timestamp } = await fetchSignatureFromBackend(email);
    await login({
      method: "email",
      value: email,
      sign,
      timestamp,
    });
  };

  return (
    <button onClick={() => handleEmailLogin("[email protected]")}>Login</button>
  );
};

// Example 4: Discord OAuth callback
const DiscordCallback = () => {
  const { login } = useTaskOnAuth();

  useEffect(() => {
    // After your Discord OAuth flow
    const processOAuth = async () => {
      const oauthToken = getDiscordTokenFromOAuth();
      const { sign, timestamp } = await fetchSignatureFromBackend(oauthToken);
      await login({
        method: "discord",
        value: oauthToken,
        sign,
        timestamp,
      });
    };
    processOAuth();
  }, []);

  return <div>Processing...</div>;
};

WalletAdapter Interface

For custom wallet integration:

interface WalletAdapter {
  // Required
  connect: () => Promise<string>;
  disconnect: () => Promise<void>;
  signMessage: (message: string) => Promise<string>;
  getAddress: () => string | null;

  // Optional (EVM only)
  getChainId?: () => number | null;
  switchNetwork?: (chainId: number) => Promise<void>;

  // Optional (Event subscriptions)
  onAccountChange?: (callback: (address: string | null) => void) => () => void;
  onChainChange?: (callback: (chainId: number) => void) => () => void;
}

Types

TaskOnAuthState

interface TaskOnAuthState {
  userId: number | null; // TaskOn user ID (null if not logged in)
  isLoggedIn: boolean; // Whether user is logged in
  isInitializing: boolean; // Whether provider is initializing
}

LoginParams

interface LoginParams {
  method: LoginMethod; // Login method type
  value: string; // Address / email / OAuth token
  sign: string; // Backend signature
  timestamp: number; // Signature timestamp (seconds)
}

type LoginMethod =
  | "evm_wallet"
  | "solana_wallet"
  | "email"
  | "discord"
  | "twitter"
  | "telegram";

TaskOnTheme

The resolved theme object returned by useTaskOnTheme():

interface TaskOnTheme {
  mode: "light" | "dark";
  compact: boolean;

  // All tokens are resolved (seed + derived + overrides)
  tokens: {
    // Primary colors
    colorPrimary: string;
    colorPrimaryHover: string;
    colorPrimaryActive: string;
    colorPrimaryBg: string;

    // Secondary colors
    colorSecondary: string;

    // Status colors
    colorSuccess: string;
    colorWarning: string;
    colorError: string;

    // Background
    colorBg: string;
    colorBgElevated: string;
    colorBgSpotlight: string;

    // Text
    colorText: string;
    colorTextSecondary: string;
    colorTextTertiary: string;
    colorTextDisabled: string;

    // Border
    colorBorder: string;
    colorBorderSecondary: string;

    // Layout
    borderRadius: number;
    borderRadiusSm: number;
    borderRadiusLg: number;

    // Typography
    fontSize: number;
    fontSizeSm: number;
    fontSizeLg: number;
    fontFamily: string;

    // Spacing
    spacing: number;
    spacingXs: number;
    spacingSm: number;
    spacingMd: number;
    spacingLg: number;
    spacingXl: number;
  };
}

SSR Compatibility

This package is SSR-compatible:

  • All components are marked with 'use client'
  • Browser APIs are safely wrapped
  • No hydration mismatches

Works with:

  • Next.js App Router
  • Next.js Pages Router
  • Remix
  • Other React SSR frameworks

Peer Dependencies

  • react >= 18.0.0
  • react-dom >= 18.0.0
  • @taskon/core >= 0.0.0

Optional Peer Dependencies

For WalletConnect support in the built-in wallet binding dialog:

npm install @walletconnect/ethereum-provider @walletconnect/modal

Then configure your project ID:

<TaskOnProvider
  config={{
    apiKey: "your-api-key",
    walletConnectProjectId: "your-walletconnect-project-id",
  }}
>
  <App />
</TaskOnProvider>

Get your WalletConnect Project ID at https://cloud.walletconnect.com

If not configured, the WalletConnect option will be disabled in the wallet binding dialog.

License

MIT