New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@shopkit/cart

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@shopkit/cart

Cart state management, hooks, and services for e-commerce storefronts

latest
npmnpm
Version
0.1.4
Version published
Maintainers
1
Created
Source

@shopkit/cart

Cart state management for e-commerce storefronts.

Installation

npm install @shopkit/cart
# or
bun add @shopkit/cart

Quick Start

1. Configure the cart at app startup

// app/providers.tsx or similar
import {
  configureCart,
  DefaultCartService,
  DefaultCartStorage,
} from '@shopkit/cart';

// Configure once at app initialization
configureCart({
  merchantName: 'my-store',
  cartService: new DefaultCartService('/api/cart'),
  cartStorage: new DefaultCartStorage('my-store'),
  defaultCurrencyCode: 'USD',
  onCartEvent: (event) => {
    console.log('Cart event:', event);
  },
});

2. Initialize the cart in your layout

// app/layout.tsx
import { CartInitializer } from '@shopkit/cart';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <CartInitializer merchantName="my-store" />
        {children}
      </body>
    </html>
  );
}

3. Use the cart store in components

import { useCartStore, mapProductToCartItem, useCartCount, useCartToggle } from '@shopkit/cart';

function ProductCard({ product }) {
  const { addItem, loadingItems } = useCartStore();
  const cartCount = useCartCount();
  const toggleCart = useCartToggle();

  const variantId = product.variant?.id || product.variantId;
  const isLoading = loadingItems[variantId] || false;

  const handleAddToCart = () => {
    const cartItem = mapProductToCartItem(product);
    addItem(cartItem);
  };

  return (
    <div>
      <h3>{product.title}</h3>
      <button onClick={handleAddToCart} disabled={isLoading}>
        {isLoading ? 'Adding...' : 'Add to Cart'}
      </button>
      <button onClick={toggleCart}>
        Cart ({cartCount})
      </button>
    </div>
  );
}

Note: Developers are responsible for mapping product data to the correct CartItem format. Use the mapProductToCartItem utility for common product structures.

API Reference

Configuration

configureCart(config: CartConfig)

Configure the cart module. Must be called before using any cart functionality.

interface CartConfig {
  merchantName: string;
  cartService: ICartService;
  cartStorage: ICartStorage;
  defaultCurrencyCode?: string;
  onCartEvent?: (event: CartEvent) => void;
}

Store

useCartStore()

The main hook for all cart operations. Provides access to cart state and actions.

State:

PropertyTypeDescription
itemsCartItem[]Items currently in the cart
isOpenbooleanWhether the cart drawer/modal is open
isLoadingbooleanWhether any cart operation is in progress
loadingItemsRecord<string, boolean>Per-item loading states keyed by variantId
errorstring | nullCurrent error message, if any
cartTokenstring | nullCart token for API authentication
checkoutUrlstring | undefinedURL to proceed to checkout
totalAmount{ amount: number; currencyCode: string } | undefinedServer-calculated total
isInitializedbooleanWhether the cart has been initialized

Actions:

MethodSignatureDescription
initializeCart(merchantName?: string) => Promise<void>Initialize the cart
addItem(item: CartItem) => Promise<void>Add a single item to cart
addItems(items: CartItemRequest[]) => Promise<void>Add multiple items to cart
removeItem(lineId: string, variantId?: string) => Promise<void>Remove an item from cart
incrementItem(lineId: string, variantId?: string) => Promise<void>Increment item quantity by 1
decrementItem(lineId: string, variantId?: string) => Promise<void>Decrement item quantity by 1
setItemQuantity(lineId: string, quantity: number, variantId?: string) => Promise<void>Set item quantity directly
clearCart() => Promise<void>Clear cart after purchase: removes stale token from localStorage, resets in-memory state, and immediately creates a fresh cart
openCart() => Promise<void>Open the cart drawer/modal
closeCart() => voidClose the cart drawer/modal
toggleCart() => Promise<void>Toggle cart open/closed

Example - Cart Drawer:

function CartDrawer() {
  const { items, isOpen, closeCart, removeItem, incrementItem, decrementItem, loadingItems } = useCartStore();

  if (!isOpen) return null;

  return (
    <div className="cart-drawer">
      <button onClick={closeCart}>Close</button>
      {items.map((item) => {
        const isItemLoading = loadingItems[item.variantId || item.id] || false;
        return (
          <div key={item.id}>
            <span>{item.title}</span>
            <button onClick={() => decrementItem(item.id, item.variantId)} disabled={isItemLoading}>-</button>
            <span>{item.quantity}</span>
            <button onClick={() => incrementItem(item.id, item.variantId)} disabled={isItemLoading}>+</button>
            <button onClick={() => removeItem(item.id, item.variantId)} disabled={isItemLoading}>Remove</button>
          </div>
        );
      })}
    </div>
  );
}

Per-Item Loading States

The loadingItems property tracks loading state for each item individually, allowing you to show loading indicators only for the specific item being modified.

const { loadingItems, addItem, incrementItem } = useCartStore();

// Check if a specific product is loading
const isProductLoading = (variantId: string) => loadingItems[variantId] || false;

// Use in component
function ProductButton({ product }) {
  const variantId = product.variant?.id || product.variantId;
  const isLoading = isProductLoading(variantId);

  return (
    <button disabled={isLoading}>
      {isLoading ? <Spinner /> : 'Add to Cart'}
    </button>
  );
}

Selector Hooks

Convenience hooks for specific state slices:

HookReturn TypeDescription
useCartCount()numberNumber of unique items in cart
useCartTotalQuantity()numberTotal quantity of all items
useCartItems()CartItem[]Array of cart items
useCartToggle()() => voidFunction to toggle cart open/closed
useCartStatus(){ isLoading, error }Loading and error state
useCartTotal()numberClient-calculated total price
useCartTotalAmount(){ amount, currencyCode } | undefinedServer-calculated total
useIsInCart(productId, variantId?)booleanCheck if product is in cart
useCartItem(productId, variantId?)CartItem | undefinedGet specific cart item
useCheckoutUrl()string | undefinedGet checkout URL

Utils

mapProductToCartItem(product, variantId?, quantity?, currencyCode?)

Map a product object to a CartItem. Use this to convert your product data structure to the format required by the cart.

import { mapProductToCartItem } from '@shopkit/cart';

const cartItem = mapProductToCartItem(product);
addItem(cartItem);

formatPrice(amount, currencyCode?, locale?)

Format a price amount for display.

formatPrice(29.99, 'USD', 'en-US'); // "$29.99"

calculateCartTotal(items)

Calculate the total price of cart items (client-side).

calculateSavings(items)

Calculate total savings from compare-at prices.

Services

DefaultCartService

Default HTTP-based cart service implementation.

const service = new DefaultCartService('/api/cart');

DefaultCartStorage

Default localStorage-based cart storage.

const storage = new DefaultCartStorage('my-store');

Components

<CartInitializer merchantName="..." />

Initialize the cart on mount. Must be rendered after configureCart() is called.

Custom Services

Implement ICartService for custom cart backends:

import { ICartService, CartResponse, CartItemRequest } from '@shopkit/cart';

class MyCartService implements ICartService {
  async createCart(merchantName: string): Promise<CartResponse> {
    // Your implementation
  }

  async getCart(cartId: string): Promise<CartResponse> {
    // Your implementation
  }

  async addToCart(cartId: string, items: CartItemRequest[]): Promise<void> {
    // Your implementation
  }

  async removeFromCart(cartId: string, itemIds: string[]): Promise<void> {
    // Your implementation
  }

  async updateCart(cartId: string, items: CartItemRequest[]): Promise<void> {
    // Your implementation
  }
}

License

MIT

Keywords

cart

FAQs

Package last updated on 01 Apr 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts