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

@adhix11/clientdesk-react

v1.0.0

Published

A client-facing React SDK for SaaS products to collect support tickets, bug reports, service requests, and change management requests with user context, attachments, and configurable API endpoints.

Readme

@adhix11/clientdesk-react

A client-facing React SDK for SaaS products to collect support tickets, bug reports, service requests, and change management requests with user context, attachments, and configurable API endpoints.

npm version license


What is ClientDesk React?

ClientDesk React is a client-facing ticket and change request submission SDK — not a full ticketing system.

It lets SaaS products add a polished, branded reporting widget so users can:

  • 🐛 Report bugs and issues
  • 🎫 Raise support tickets
  • 🔄 Request feature/workflow/configuration changes
  • 📎 Upload screenshots and file attachments

Your SDK captures rich user context (browser, device, page URL, timezone) automatically and sends everything as structured data to your own API.

Important: This SDK does not manage admin workflows, assignment, SLA, internal comments, escalation, or approvals. It only captures and submits structured client requests.


Installation

npm install @adhix11/clientdesk-react

Peer dependencies: react >= 17, react-dom >= 17


Quick Start

Both Ticketing + Change Requests

import { ClientDeskProvider, ClientRequestWidget } from "@adhix11/clientdesk-react";

function App() {
  return (
    <ClientDeskProvider
      config={{
        apiUrl: "https://api.your-saas.com",
        clientKey: "public_client_key",
        mode: "both",
      }}
    >
      <ClientRequestWidget />
    </ClientDeskProvider>
  );
}

Ticketing Only

import { ClientDeskProvider, TicketReporter } from "@adhix11/clientdesk-react";

function App() {
  return (
    <ClientDeskProvider
      config={{
        apiUrl: "https://api.example.com",
        clientKey: "client_key",
        mode: "ticket",
      }}
    >
      <TicketReporter />
    </ClientDeskProvider>
  );
}

Change Management Only

import { ClientDeskProvider, ChangeRequestReporter } from "@adhix11/clientdesk-react";

function App() {
  return (
    <ClientDeskProvider
      config={{
        apiUrl: "https://api.example.com",
        clientKey: "client_key",
        mode: "change",
      }}
    >
      <ChangeRequestReporter />
    </ClientDeskProvider>
  );
}

Components

| Component | Purpose | |-----------|---------| | <ClientDeskProvider /> | Global config: API URL, key, user, theme | | <ClientRequestWidget /> | Floating button/modal with ticket + change options | | <TicketReporter /> | Ticket submission form | | <ChangeRequestReporter /> | Change request submission form | | <MyRequests /> | Client-side list of user's own submitted requests | | <AttachmentUploader /> | Image/file upload helper |


Component API

<ClientDeskProvider />

Wrap your app or a subtree with this provider.

<ClientDeskProvider
  config={{
    apiUrl: "https://api.example.com",      // Required
    clientKey: "public_client_key",          // Required
    mode: "both",                            // "ticket" | "change" | "both"
    endpoints: {                             // Custom API paths
      createTicket: "/client/tickets",
      createChangeRequest: "/client/change-requests",
      uploadAttachment: "/client/attachments",
      listMyRequests: "/client/requests/me",
    },
    user: {                                  // User info
      id: "user_123",
      name: "John Doe",
      email: "[email protected]",
      companyId: "company_456",
      role: "Manager",
    },
    theme: {                                 // Theme customization
      primaryColor: "#6366f1",
      accentColor: "#8b5cf6",
      mode: "light",                         // "light" | "dark"
      borderRadius: 12,
    },
    getAuthToken: () => localStorage.getItem("token"),
    appName: "MyApp",
    appVersion: "2.1.0",
    environment: "production",
  }}
>
  {children}
</ClientDeskProvider>

<ClientRequestWidget />

Floating action button with a modal menu.

<ClientRequestWidget
  position="bottom-right"           // "bottom-right" | "bottom-left" | "top-right" | "top-left"
  ticketCustomFields={[...]}        // Custom fields for ticket form
  changeCustomFields={[...]}        // Custom fields for change form
  onSuccess={(data) => console.log(data)}
  onError={(err) => console.error(err)}
/>

<TicketReporter />

// Inline
<TicketReporter />

// Button trigger (opens modal)
<TicketReporter trigger="button" buttonText="Report Issue" />

// With custom fields
<TicketReporter
  customFields={[
    { name: "assetId", label: "Asset ID", type: "text" },
    { name: "location", label: "Location", type: "select", options: ["Chennai", "Salem", "Bangalore"] },
  ]}
  onSuccess={(data) => console.log(data)}
/>

<ChangeRequestReporter />

// Inline
<ChangeRequestReporter />

// Button trigger
<ChangeRequestReporter trigger="button" buttonText="Request Change" />

<MyRequests />

<MyRequests
  limit={10}
  onRequestClick={(request) => console.log(request)}
/>

<AttachmentUploader />

const [files, setFiles] = useState([]);

<AttachmentUploader
  files={files}
  onChange={setFiles}
  maxFileSize={10 * 1024 * 1024}  // 10MB
  maxFiles={5}
/>

Custom Fields

Every SaaS product has different needs. Add custom fields to any form:

<TicketReporter
  customFields={[
    { name: "assetId", label: "Asset ID", type: "text", required: true },
    { name: "location", label: "Location", type: "select", options: ["Chennai", "Salem", "Bangalore"] },
    { name: "tags", label: "Tags", type: "multi-select", options: ["Urgent", "Frontend", "Backend", "Data"] },
    { name: "deadline", label: "Deadline", type: "date" },
    { name: "count", label: "Affected Users", type: "number" },
    { name: "critical", label: "Is Critical?", type: "checkbox" },
    { name: "env", label: "Environment", type: "radio", options: ["Production", "Staging", "Dev"] },
    { name: "notes", label: "Additional Notes", type: "textarea" },
    { name: "logFile", label: "Log File", type: "file" },
  ]}
/>

Supported types: text, textarea, select, multi-select, date, number, checkbox, radio, file


Auto-Captured Context

Every submission automatically includes:

| Field | Source | |-------|--------| | Page URL | window.location.href | | Browser | User agent parsing | | Browser Version | User agent parsing | | Operating System | User agent parsing | | Device Type | User agent parsing | | Screen Size | window.innerWidth/Height | | Timezone | Intl.DateTimeFormat | | Timestamp | new Date().toISOString() | | Language | navigator.language | | App Name | Config | | App Version | Config | | Module Name | Config | | Environment | Config |


API Configuration

Endpoints are fully configurable — works with any REST backend:

<ClientDeskProvider
  config={{
    apiUrl: "https://api.example.com",
    clientKey: "public_client_key",
    endpoints: {
      createTicket: "/client/tickets",
      createChangeRequest: "/client/change-requests",
      uploadAttachment: "/client/attachments",
      listMyRequests: "/client/requests/me",
    },
  }}
>

Compatible with: LoopBack 4, Express, NestJS, Laravel, Django, Spring Boot, or any REST API.


Authentication

The clientKey is a public project/client identifier (not a secret). For secure apps, inject auth tokens:

// Dynamic token
<ClientDeskProvider
  config={{
    apiUrl: "https://api.example.com",
    clientKey: "public_client_key",
    getAuthToken: () => localStorage.getItem("token"),
  }}
>

// Static headers
<ClientDeskProvider
  config={{
    apiUrl: "https://api.example.com",
    clientKey: "public_client_key",
    headers: {
      Authorization: "Bearer your_token_here",
    },
  }}
>

The backend should verify the real user/session. The frontend key only identifies the SaaS client/project.


Theme Customization

<ClientDeskProvider
  config={{
    ...config,
    theme: {
      primaryColor: "#6366f1",
      accentColor: "#8b5cf6",
      backgroundColor: "#f8fafc",
      surfaceColor: "#ffffff",
      textColor: "#0f172a",
      mutedColor: "#64748b",
      borderColor: "#e2e8f0",
      successColor: "#10b981",
      errorColor: "#ef4444",
      warningColor: "#f59e0b",
      fontFamily: "'Inter', sans-serif",
      borderRadius: 12,
      mode: "dark",  // "light" | "dark"
    },
  }}
>

Ticket Form Fields

| Field | Type | |-------|------| | Subject | text (required) | | Description | textarea (required) | | Issue Type | select: Bug, Support, Access Issue, Performance Issue, Data Issue, Payment Issue, Other | | Category/Module | text | | Priority | select: Low, Medium, High, Critical | | Severity | select: Minor, Major, Critical, Blocker | | Steps to Reproduce | textarea | | Expected Result | textarea | | Actual Result | textarea | | Attachments | file upload |

Change Request Form Fields

| Field | Type | |-------|------| | Change Title | text (required) | | Description | textarea (required) | | Change Type | select: Feature, Configuration, Workflow, Report, User Access, Data, Integration, Other | | Business Reason | textarea (required) | | Affected Module | text | | Expected Outcome | textarea | | Urgency | select: Low, Medium, High, Critical | | Impact Level | select: Low, Medium, High, Enterprise-Wide | | Preferred Date | date | | Attachments | file upload |


UI Modes

// Floating widget (default)
<ClientRequestWidget position="bottom-right" />

// Inline form
<TicketReporter />

// Modal button
<TicketReporter trigger="button" buttonText="Report Issue" />

Hook: useClientDesk

Access config, theme, and API client programmatically:

import { useClientDesk } from "@adhix11/clientdesk-react";

function MyComponent() {
  const { config, theme, apiClient } = useClientDesk();
  // ...
}

TypeScript

Fully typed. Import any type you need:

import type {
  ClientDeskConfig,
  TicketFormData,
  ChangeRequestFormData,
  CustomField,
  CapturedContext,
  ApiResponse,
} from "@adhix11/clientdesk-react";

License

MIT © adhix11