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

@pixeasy/customizer

v2.0.1

Published

Framework-agnostic SDK to embed the Pixeasy customizer in Angular, React, Vue, or any ESM app.

Readme

Pixeasy Customizer SDK

Framework-agnostic SDK to embed the Pixeasy customizer in Angular, React, Vue, or any ESM app.

Installation

npm install @pixeasy/customizer

Quick Start

import { createPixeasyBuilder } from '@pixeasy/customizer';
import '@pixeasy/customizer/styles.css';

const builder = createPixeasyBuilder();

builder.open({
  container: 'pixeasyBuilder',
  apiKey: 'dk_xxx_yyy',
  productId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
});

Note: container can be a CSS selector string (element id) or an HTMLElement reference.

API Reference

createPixeasyBuilder()

Creates and returns a new PixeasyBuilder instance. You can create multiple builder instances if needed.

const builder = createPixeasyBuilder();

PixeasyBuilder.open(options)

Opens the customizer with the specified configuration.

Options

type PixeasyOpenOptions = {
  // Required
  container: string | HTMLElement; // CSS selector or DOM element to mount the customizer
  apiKey: string; // Your API key (format: dk_xxx_yyy)
  productId: string; // Product ID (UUID format)

  // Optional
  predesignId?: string; // Load a pre-designed template
  submissionNumber?: string; // Load an existing submission for editing
  locale?: string; // Language/locale code (e.g., 'en', 'fr', 'de')
  theme?: string; // Theme name or color scheme
  readonly?: boolean; // Set to true to disable editing (view-only mode)
};

Option Details

| Option | Type | Required | Description | | ------------------ | ----------------------- | -------- | ------------------------------------------------------------------------------------- | | container | string \| HTMLElement | Yes | Target container to mount the customizer. If string, treated as element ID. | | apiKey | string | Yes | Your Pixeasy API key for authentication. | | productId | string | Yes | UUID of the product to customize. | | predesignId | string | No | Load a pre-designed template/predesign. Useful for template-based workflows. | | submissionNumber | string | No | Load an existing submission for editing or review. Use with readonly for view-only. | | locale | string | No | Set the UI language. Examples: 'en', 'fr', 'de', 'es'. | | theme | string | No | Apply a theme or color scheme to the customizer UI. | | readonly | boolean | No | Enable view-only mode. Prevents editing and submission. Perfect for order review. |

Events

All events can be subscribed using builder.on(eventName, handler).

| Event | When it fires | Payload | | -------------------- | -------------------------------------------------------------------------------------------- | ------------------------------ | | manifest-loaded | After the product manifest loads successfully. | ManifestLoadedEventDetail | | sdk-ready | After the customizer initializes and is ready for interaction. | SdkReadyEventDetail | | submission:success | After a successful submission. | SubmissionSuccessEventDetail | | submission:failed | When submission fails (API error, network issue, or validation error). | SubmissionFailedEventDetail | | error | When a runtime error occurs (invalid config, manifest load failed, asset load failed, etc.). | ErrorEventDetail | | closed | When the customizer is closed via builder.close(). | undefined |

Event Payload Types

// Fires after manifest is loaded
interface ManifestLoadedEventDetail {
  productId: string;
  manifestMeta?: {
    version?: string;
  } | null;
}

// Fires when SDK is ready for use
interface SdkReadyEventDetail {
  productId: string;
}

// Fires on successful submission
interface SubmissionSuccessEventDetail {
  productId?: string;
  views?: string[]; // Generated views/angles
  submissionNumber: string; // Unique submission identifier
}

// Fires when submission fails
interface SubmissionFailedEventDetail {
  productId?: string;
  views?: string[];
  message: string; // Error message
  errors?: string[]; // Detailed error list
}

// Fires on SDK errors
interface ErrorEventDetail {
  code: 'INVALID_CONFIG' | 'MANIFEST_LOAD_FAILED' | 'ASSET_LOAD_FAILED' | 'RUNTIME_ERROR';
  message: string;
}

Event Subscription Example

import { SDK_EVENTS } from '@pixeasy/customizer';

const builder = createPixeasyBuilder();

builder.open({
  container: 'pixeasyBuilder',
  apiKey: 'dk_xxx_yyy',
  productId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
});

// Subscribe to events
builder
  .on(SDK_EVENTS.MANIFEST_LOADED, (event) => {
    console.log('Manifest loaded for product:', event.productId);
  })
  .on(SDK_EVENTS.SDK_READY, (event) => {
    console.log('Customizer is ready!', event.productId);
  })
  .on(SDK_EVENTS.SUBMISSION_SUCCESS, (event) => {
    console.log('Submission successful:', event.submissionNumber);
    console.log('Generated views:', event.views);
  })
  .on(SDK_EVENTS.SUBMISSION_FAILED, (event) => {
    console.error('Submission failed:', event.message);
    if (event.errors) {
      console.error('Errors:', event.errors);
    }
  })
  .on(SDK_EVENTS.ERROR, (event) => {
    console.error(`Error [${event.code}]:`, event.message);
  })
  .on(SDK_EVENTS.CLOSED, () => {
    console.log('Customizer closed');
  });

Unsubscribing from Events

const handleSuccess = (event) => console.log('Success:', event.submissionNumber);

builder.on(SDK_EVENTS.SUBMISSION_SUCCESS, handleSuccess);

// Later, remove the listener
builder.off(SDK_EVENTS.SUBMISSION_SUCCESS, handleSuccess);

Framework Examples

React

Basic Usage

import { useEffect } from 'react';
import { createPixeasyBuilder } from '@pixeasy/customizer';
import '@pixeasy/customizer/styles.css';

export function CustomizerHost() {
  useEffect(() => {
    const builder = createPixeasyBuilder();

    builder.open({
      container: 'pixeasyBuilder',
      apiKey: 'dk_xxx_yyy',
      productId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
    });

    return () => builder.close();
  }, []);

  return <div id="pixeasyBuilder" />;
}

Advanced Usage with Events

import { useEffect } from 'react';
import { createPixeasyBuilder, SDK_EVENTS } from '@pixeasy/customizer';
import '@pixeasy/customizer/styles.css';

export function CustomizerWithEvents() {
  useEffect(() => {
    const builder = createPixeasyBuilder();

    builder
      .on(SDK_EVENTS.SDK_READY, () => {
        console.log('Customizer ready');
      })
      .on(SDK_EVENTS.SUBMISSION_SUCCESS, (event) => {
        console.log('Submission successful:', event.submissionNumber);
        // Handle success - e.g., show confirmation, redirect, etc.
      })
      .on(SDK_EVENTS.ERROR, (event) => {
        console.error('Error occurred:', event.message);
      })
      .open({
        container: 'pixeasyBuilder',
        apiKey: 'dk_xxx_yyy',
        productId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
        locale: 'en',
        theme: 'dark',
      });

    return () => builder.close();
  }, []);

  return <div id="pixeasyBuilder" style={{ width: '100%', height: '100vh' }} />;
}

Load Existing Submission

import { useEffect } from 'react';
import { createPixeasyBuilder, SDK_EVENTS } from '@pixeasy/customizer';
import '@pixeasy/customizer/styles.css';

export function EditSubmission({ submissionNumber }: { submissionNumber: string }) {
  useEffect(() => {
    const builder = createPixeasyBuilder();

    builder
      .on(SDK_EVENTS.SUBMISSION_SUCCESS, (event) => {
        console.log('Updated submission:', event.submissionNumber);
      })
      .open({
        container: 'pixeasyBuilder',
        apiKey: 'dk_xxx_yyy',
        productId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
        submissionNumber: submissionNumber, // Load for editing
      });

    return () => builder.close();
  }, [submissionNumber]);

  return <div id="pixeasyBuilder" />;
}

View-Only Mode

import { useEffect } from 'react';
import { createPixeasyBuilder } from '@pixeasy/customizer';
import '@pixeasy/customizer/styles.css';

export function ViewSubmission({ submissionNumber }: { submissionNumber: string }) {
  useEffect(() => {
    const builder = createPixeasyBuilder();

    builder.open({
      container: 'pixeasyBuilder',
      apiKey: 'dk_xxx_yyy',
      productId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
      submissionNumber: submissionNumber,
      readonly: true, // Enable view-only mode
    });

    return () => builder.close();
  }, [submissionNumber]);

  return <div id="pixeasyBuilder" />;
}

Vue

Basic Usage

import { onMounted, onBeforeUnmount } from 'vue';
import { createPixeasyBuilder } from '@pixeasy/customizer';
import '@pixeasy/customizer/styles.css';

export default {
  setup() {
    const builder = createPixeasyBuilder();

    onMounted(() => {
      builder.open({
        container: 'pixeasyBuilder',
        apiKey: 'dk_xxx_yyy',
        productId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
      });
    });

    onBeforeUnmount(() => builder.close());

    return {};
  },
};

With Events and Options

import { onMounted, onBeforeUnmount } from 'vue';
import { createPixeasyBuilder, SDK_EVENTS } from '@pixeasy/customizer';
import '@pixeasy/customizer/styles.css';

export default {
  props: {
    submissionNumber: [String, null],
  },
  setup(props) {
    const builder = createPixeasyBuilder();

    onMounted(() => {
      builder
        .on(SDK_EVENTS.SDK_READY, () => {
          console.log('Customizer initialized');
        })
        .on(SDK_EVENTS.SUBMISSION_SUCCESS, (event) => {
          console.log('Saved:', event.submissionNumber);
        })
        .open({
          container: 'pixeasyBuilder',
          apiKey: 'dk_xxx_yyy',
          productId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
          submissionNumber: props.submissionNumber || undefined,
          locale: 'en',
        });
    });

    onBeforeUnmount(() => builder.close());

    return {};
  },
};

Exports

The package exports the following:

Classes & Functions

  • createPixeasyBuilder() - Factory function to create a new PixeasyBuilder instance
  • PixeasyBuilder - Main class for managing the customizer lifecycle
  • definePixeasyCustomizerElement() - Registers the <pixeasy-customizer> custom element (auto-called internally)
  • generateThumbnails() - Utility function to generate product thumbnails from SVG and 3D models

Types

  • PixeasyOpenOptions - Configuration object for builder.open()
  • SdkElementConfig - Base configuration interface
  • ManifestLoadedEventDetail - Payload for manifest-loaded event
  • SdkReadyEventDetail - Payload for sdk-ready event
  • SubmissionSuccessEventDetail - Payload for submission:success event
  • SubmissionFailedEventDetail - Payload for submission:failed event
  • ErrorEventDetail - Payload for error event
  • SDK_EVENTS - Enum of all available event names
  • BuilderEventName - Type-safe event name type
  • ThumbnailView - View types for thumbnail generation ('front' | 'right' | 'back' | 'left')
  • GeneratedThumbnail - Thumbnail generation result

Stylesheets

  • @pixeasy/customizer/styles.css - Required stylesheet (import once in your app)

Common Use Cases

Create a New Design from Scratch

builder.open({
  container: 'pixeasyBuilder',
  apiKey: 'dk_xxx_yyy',
  productId: 'product-uuid',
});

Use a Template/Predesign

builder.open({
  container: 'pixeasyBuilder',
  apiKey: 'dk_xxx_yyy',
  productId: 'product-uuid',
  predesignId: 'predesign-uuid', // Start with a pre-designed template
});

Edit an Existing Submission

builder.open({
  container: 'pixeasyBuilder',
  apiKey: 'dk_xxx_yyy',
  productId: 'product-uuid',
  submissionNumber: 'SUB-12345', // Load existing submission
});

Review Order (Read-Only)

builder.open({
  container: 'pixeasyBuilder',
  apiKey: 'dk_xxx_yyy',
  productId: 'product-uuid',
  submissionNumber: 'SUB-12345',
  readonly: true, // Disable editing
});

Multi-Language Support

builder.open({
  container: 'pixeasyBuilder',
  apiKey: 'dk_xxx_yyy',
  productId: 'product-uuid',
  locale: 'de', // German, or 'fr', 'es', etc.
});

Best Practices

  1. Always import styles - Include the CSS stylesheet once in your app:

    import '@pixeasy/customizer/styles.css';
  2. Handle errors gracefully - Always subscribe to the error event:

    builder.on(SDK_EVENTS.ERROR, (event) => {
      console.error(`Error [${event.code}]: ${event.message}`);
      // Show user-friendly error message
    });
  3. Validate API key and Product ID - These are required for the customizer to function:

    if (!apiKey || !productId) {
      throw new Error('Missing required configuration');
    }
  4. Clean up on unmount - Always call builder.close() when the component unmounts to prevent memory leaks

  5. Use events for flow control - Subscribe to submission:success to handle post-submission actions

  6. Handle locale properly - Set the locale to match user preferences before opening

  7. Use readonly mode for reviews - Enable readonly: true when showing past submissions or previews