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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@cw-parcelpanel/headless-react

v1.3.14

Published

ParcelPanel Headless React Component - EDD & Tracking widgets for Shopify stores with TypeScript support

Readme

ParcelPanel React Components

Professional React components for ParcelPanel's delivery and tracking widgets, specifically designed for Shopify Headless commerce solutions.

Components

  • ParcelPanelEDD - Estimated Delivery Date (EDD) widget for headless product pages
  • TrackingWidget - Order tracking widget for headless tracking pages

Why Choose ParcelPanel for Shopify Headless?

  • 🏪 Shopify Native - Built specifically for Shopify's ecosystem
  • 🚀 Headless Ready - Perfect for custom storefronts and mobile apps
  • 📦 Enterprise Grade - Trusted by thousands of Shopify merchants
  • 🔧 Developer Friendly - Clean APIs and comprehensive TypeScript support

Features

  • 🚀 Easy Integration - Simple React component with minimal setup
  • 📱 Responsive Design - Automatically adapts to different screen sizes
  • 🌍 Multi-language Support - Built-in internationalization support
  • 🎨 Customizable Styling - Flexible styling options and CSS customization
  • Performance Optimized - Lightweight and efficient rendering
  • 🔧 TypeScript Support - Full TypeScript definitions included

Installation

For Shopify Headless projects (Next.js, Remix, Hydrogen, etc.):

npm install @cw-parcelpanel/headless-react

Note: This package is designed for Shopify headless commerce solutions. If you're using traditional Shopify themes, please use our theme-based solution instead.

Quick Start

EDD Widget (Headless Product Pages)

Perfect for Next.js, Remix, Hydrogen, or any React-based Shopify headless storefront:

import React from 'react';
import { ParcelPanelEDD } from '@cw-parcelpanel/headless-react';

function ProductPage({ product }) {
  return (
    <div>
      <h1>{product.title}</h1>
      <div className="product-details">
        {/* Your product content */}
      </div>
      
      {/* ParcelPanel EDD Widget */}
      <ParcelPanelEDD
        shopDomain="your-shop.myshopify.com"
        productId={product.id}
        locale="en"
        customer={{
          country_code: "US", // From user's location or checkout
          province_code: "CA"
        }}
        onLoaded={(sdk) => console.log('EDD widget loaded:', sdk)}
        onError={(error) => console.error('EDD error:', error)}
      />
    </div>
  );
}

Tracking Widget (Headless Tracking Pages)

Ideal for custom tracking pages in headless storefronts:

import React from 'react';
import { TrackingWidget } from '@cw-parcelpanel/headless-react';

function TrackingPage() {
  return (
    <div>
      <h1>Track Your Order</h1>
      <p>Enter your tracking information below:</p>
      
      {/* ParcelPanel Tracking Widget */}
      <TrackingWidget
        shopDomain="your-shop.myshopify.com"
        locale="en"
        className="tracking-container"
        onLoaded={() => console.log('Tracking widget loaded')}
        onError={(error) => console.error('Tracking error:', error)}
      />
    </div>
  );
}

API Reference

ParcelPanelEDD Props

| Prop | Type | Required | Description | |------|------|----------|-------------| | shopDomain | string | ✅ | Your Shopify shop domain (e.g., "example.myshopify.com") | | productId | number \| string | ❌ | Product ID to display delivery estimates for | | locale | string | ❌ | Language locale (e.g., "en", "zh-CN", "es") | | className | string | ❌ | CSS class name for styling | | style | React.CSSProperties | ❌ | Inline styles object | | isPreview | boolean | ❌ | Enable preview mode for testing | | apiEndpoint | 'test' \| 'prod' \| string | ❌ | API endpoint configuration | | customer | Customer | ❌ | Customer location information (country and province codes) | | settings | WidgetSettings | ❌ | Widget styling configuration | | selectorOptions | SelectorOptions | ❌ | Address selector configuration | | onLoaded | (sdk: SDK) => void | ❌ | Callback when component loads successfully | | onError | (error: Error) => void | ❌ | Callback when an error occurs | | onLocationChange | (location: Location) => void | ❌ | Callback when address/location changes |

Ref Methods (Optional)

Use useRef to access component methods when you need programmatic control. This is optional - the component works perfectly without refs for most use cases:

import React, { useRef } from 'react';
import { ParcelPanelEDD, ParcelPanelEDDRef } from '@cw-parcelpanel/headless-react';

function ProductPage() {
  const eddRef = useRef<ParcelPanelEDDRef>(null);

  const handleUpdateProduct = () => {
    // Only needed if you want to update product programmatically
    eddRef.current?.setProduct({
      id: 789,
      available: true,
      variants: [...]
    });
  };

  return (
    <ParcelPanelEDD
      ref={eddRef}
      shopDomain="your-shop.myshopify.com"
      productId={123}
    />
  );
}

Note: For most use cases, you can simply pass props to the component and it will handle everything automatically. Refs are only needed for advanced programmatic control.

Available ref methods:

| Method | Parameters | Description | |--------|------------|-------------| | getSDK() | - | Get the underlying SDK instance | | setProduct(info) | SDKProductInfo | Update product information | | setCustomer(customer) | Customer | Update customer location information | | setSettings(settings) | WidgetSettings | Update widget styling | | updateConfig(config) | Partial<SDKConfig> | Update SDK configuration | | destroy() | - | Clean up and destroy the component |

Type Definitions

Customer

interface Customer {
  country_code: string;       // Country code (ISO 3166-1 alpha-2), e.g., "US", "CN"
  province_code: string;      // Province/state code, e.g., "CA", "NY"
}

WidgetSettings

interface WidgetSettings {
  corner_radius?: number;     // Border radius in pixels
  margin_top?: number;        // Top margin in pixels
  margin_bottom?: number;     // Bottom margin in pixels
  padding_x?: number;         // Horizontal padding in pixels
  padding_y?: number;         // Vertical padding in pixels
}

SelectorOptions

interface SelectorOptions {
  country?: string;           // Default country code
  province?: string;          // Default province/state code
  settings?: string;          // JSON string of additional settings
}

Advanced Usage

Custom Styling

<ParcelPanelEDD
  shopDomain="your-shop.myshopify.com"
  productId={123}
  className="my-edd-widget"
  style={{
    border: '1px solid #e1e5e9',
    borderRadius: '8px',
    padding: '16px'
  }}
  settings={{
    corner_radius: 8,
    margin_top: 10,
    margin_bottom: 10,
    padding_x: 16,
    padding_y: 12
  }}
/>

Handling Events

<ParcelPanelEDD
  shopDomain="your-shop.myshopify.com"
  productId={123}
  customer={{ country_code: "US", province_code: "CA" }}
  onLoaded={(sdk) => {
    console.log('Widget loaded successfully');
    // Access SDK methods
    console.log('Current config:', sdk.getConfig());
  }}
  onError={(error) => {
    console.error('Failed to load widget:', error);
    // Handle error (show fallback UI, report to analytics, etc.)
  }}
  onLocationChange={(location) => {
    console.log('Selected location:', location);
    // Update shipping calculations, etc.
  }}
/>

Dynamic Product Updates

function ProductVariantSelector() {
  const eddRef = useRef<ParcelPanelEDDRef>(null);
  const [selectedVariant, setSelectedVariant] = useState(null);

  useEffect(() => {
    if (selectedVariant && eddRef.current) {
      // Update the EDD widget when variant changes
      eddRef.current.setProduct({
        id: selectedVariant.product_id,
        available: selectedVariant.available,
        variants: [{
          id: selectedVariant.id,
          available: selectedVariant.available,
          requires_shipping: selectedVariant.requires_shipping
        }]
      });
    }
  }, [selectedVariant]);

  return (
    <div>
      {/* Variant selector UI */}
      
      <ParcelPanelEDD
        ref={eddRef}
        shopDomain="your-shop.myshopify.com"
        productId={123}
      />
    </div>
  );
}

TrackingWidget Component

The TrackingWidget component provides order tracking functionality, allowing customers to track their orders directly within your application.

Basic Usage

import React from 'react';
import { TrackingWidget } from '@cw-parcelpanel/headless-react';

function TrackingPage() {
  return (
    <div>
      <h1>Track Your Order</h1>
      
      <TrackingWidget
        shopDomain="your-shop.myshopify.com"
        locale="en"
        onLoaded={() => console.log('Tracking widget loaded')}
        onError={(error) => console.error('Tracking error:', error)}
      />
    </div>
  );
}

TrackingWidget Props

| Prop | Type | Required | Description | |------|------|----------|-------------| | shopDomain | string | ✅ | Your Shopify shop domain (e.g., "your-shop.myshopify.com") | | locale | string | ❌ | Language locale (e.g., "en", "zh-CN", "ja"). Defaults to "en" | | className | string | ❌ | CSS class name for styling | | style | React.CSSProperties | ❌ | Inline styles object | | onLoaded | () => void | ❌ | Callback when tracking widget loads successfully | | onError | (error: Error) => void | ❌ | Callback when an error occurs |

Multi-language Support

// English tracking page
<TrackingWidget shopDomain="your-shop.myshopify.com" locale="en" />

// Chinese tracking page
<TrackingWidget shopDomain="your-shop.myshopify.com" locale="zh-CN" />

// Japanese tracking page
<TrackingWidget shopDomain="your-shop.myshopify.com" locale="ja" />

Custom Styling

<TrackingWidget
  shopDomain="your-shop.myshopify.com"
  className="custom-tracking-widget"
  style={{
    minHeight: '400px',
    backgroundColor: '#f5f5f5',
    padding: '20px',
    borderRadius: '8px'
  }}
/>

Error Handling

function TrackingPage() {
  const handleTrackingError = (error: Error) => {
    console.error('Tracking widget error:', error);
    // You can show a user-friendly error message
    alert('Failed to load tracking information. Please try again.');
  };

  return (
    <TrackingWidget
      shopDomain="your-shop.myshopify.com"
      onError={handleTrackingError}
    />
  );
}

Automatic Variant Detection

The component automatically detects variant changes from:

  1. URL Parameters - ?variant=123456 in the URL
  2. Shopify Form Inputs - Product form variant selectors
  3. Manual Updates - Via ref methods or prop changes

No need to manually pass variantId - the widget handles variant detection automatically!

Shopify Headless Integration

Next.js Integration

// pages/products/[handle].tsx or app/products/[handle]/page.tsx
import { ParcelPanelEDD } from '@cw-parcelpanel/headless-react';

export default function ProductPage({ product }) {
  return (
    <main>
      {/* Your product layout */}
      <ParcelPanelEDD
        shopDomain={process.env.NEXT_PUBLIC_SHOPIFY_SHOP_DOMAIN}
        productId={product.id}
        locale={product.locale}
        apiEndpoint={process.env.NODE_ENV === 'production' ? 'prod' : 'test'}
      />
    </main>
  );
}

Hydrogen Integration

// app/routes/products.$handle.tsx
import { ParcelPanelEDD } from '@cw-parcelpanel/headless-react';

export default function Product() {
  const { product } = useLoaderData();
  
  return (
    <div>
      {/* Your Hydrogen product template */}
      <ParcelPanelEDD
        shopDomain={shop.primaryDomain.url.replace('https://', '')}
        productId={product.id}
        locale={request.locale}
      />
    </div>
  );
}

Remix Integration

// app/routes/products.$handle.tsx
import { ParcelPanelEDD } from '@cw-parcelpanel/headless-react';

export default function ProductRoute() {
  const { product } = useLoaderData();
  
  return (
    <div>
      {/* Your Remix product template */}
      <ParcelPanelEDD
        shopDomain={ENV.SHOPIFY_SHOP_DOMAIN}
        productId={product.id}
      />
    </div>
  );
}

Environment Configuration

// Development
<ParcelPanelEDD
  shopDomain="your-shop.myshopify.com"
  productId={123}
  apiEndpoint="test"
  isPreview={true}
/>

// Production
<ParcelPanelEDD
  shopDomain="your-shop.myshopify.com"
  productId={123}
  apiEndpoint="prod"
/>

Internationalization

The component supports multiple languages:

// English
<ParcelPanelEDD shopDomain="your-shop.myshopify.com" locale="en" />

// Chinese (Simplified)
<ParcelPanelEDD shopDomain="your-shop.myshopify.com" locale="zh-CN" />

// Spanish
<ParcelPanelEDD shopDomain="your-shop.myshopify.com" locale="es" />

// French
<ParcelPanelEDD shopDomain="your-shop.myshopify.com" locale="fr" />

Troubleshooting

Common Issues

  1. Widget not displaying

    • Ensure shopDomain is correct and accessible
    • Check that the product exists and is available
    • Verify API endpoint configuration
  2. TypeScript errors

    • Make sure you're importing types correctly
    • Check that all required props are provided
  3. Styling issues

    • Use browser dev tools to inspect the widget
    • Ensure CSS specificity is sufficient
    • Check for conflicting styles