Back to Website
Show / Hide Table of Contents

Plugin API

  • Last updated on September 12, 2025
  • •
  • 7 minutes to read

The Plugin API is a framework built for Handy Editor and related to Customers Canvas products. Unlike the Web-component API, this solution designed to address specific, advanced tasks and is intended as a powerful but complex tool that may require expertise in Design Atoms (DA), Angular, and NGRx. It should be used only when other integration options are insufficient or unavailable for solving your task.

This API is tailored to work with Handy Editor's internal architecture:

  • NGRX for state management.
  • Design Atoms as the rendering engine.
  • Custom tokens (e.g., PRICE_TOKEN, STORE_TOKEN) to access internal services.

This makes it similar to plugins in tools like Adobe Photoshop or Figma, but unique to Handy Editor.

Getting Started

To use the Plugin API, add the following script to your page before the main CDN script:

if (window.AurigmaWebComponents == null) {
    window.AurigmaWebComponents = {};
}

window.AurigmaWebComponents.handyEditor = { autoBootstrapping: false };
// For 3D viewer, use:
// window.AurigmaWebComponents.handyEditor3d = { autoBootstrapping: false };
Important

This script must run before the main CDN file is executed.

Overriding Entities

To override workflow element entities, use token names and create provider constants:

  • For class entities:

    const SOME_CLASS_PROVIDER = {
        provide: "SOME_TOKEN",
        useClass: YourImplementedClass
    };
    
  • For string, function, object, etc.:

    const SOME_VALUE_PROVIDER = {
        provide: "SOME_TOKEN",
        useValue: YOUR_VALUE
    };
    

Then, load the module with these providers:

window.addEventListener("DOMContentLoaded", async () => {
    await window.AurigmaWebComponents.handyEditor.bootstrap([SOME_CLASS_PROVIDER, SOME_VALUE_PROVIDER]);
    // For 3D viewer:
    // await window.AurigmaWebComponents.handyEditor3d.bootstrap([...]);
});

External Implementations

External implementations allow you to extend the editor's functionality or integrate with external systems. Implement your JS class based on the provided API:

class CustomService {
    constructor() {
        const inject = AurigmaWebComponents.handyEditor.inject;
        this.store = inject("STORE_TOKEN");
        this.store.subscribe(state => console.warn(state));
    }
}

Then, load the module with this class:

window.addEventListener("DOMContentLoaded", async () => {
    await window.AurigmaWebComponents.handyEditor.bootstrap([], [CustomService]);
});
Note

You can implement as many classes as needed and pass them as an array in the second argument of the bootstrap function. To access your class instance, use the injector property of the web component.

API

NGRX Store

Token: "STORE_TOKEN"

Description: NGRX storage for most application data.

Important

Avoid subscribing directly to the Store! Even though it provides full access to the editor's state, the Store's internal structure may change over time. Instead, use the select method with the NGRX selectors listed in this article to safely retrieve data.

Example:

class CustomService {
    constructor() {
        const inject = AurigmaWebComponents.handyEditor.inject;
        this.store = inject("STORE_TOKEN");
        this.store.subscribe(state => console.warn(state));
    }
}

NGRX Utilities

Token: "NGRX_UTILS_TOKEN"

Description: NGRX functions for use in JS.

Available functions:

  • select: The RXJS operator to extract data using selectors. For more details, refer to the documentation.
  • ofType: The RXJS operator to filter events by type. For more details, refer to the documentation.
  • createEffect: The RXJS function that accepts an observable object returned by NGRX action and create effects from actions. For more details, refer to the documentation.

Example:

class CustomAnalyticsService {
    constructor() {
        const inject = AurigmaWebComponents.handyEditor.inject;
        const { select, ofType, createEffect } = inject("NGRX_UTILS_TOKEN");
        const { selectCurrentVariantId } = inject("SELECTORS_TOKEN");
        const actions$ = inject("ACTIONS_SERVICE_TOKEN");

        this.store = inject("STORE_TOKEN");
        this.store.pipe(select(selectCurrentVariantId))
            .subscribe(variantId => {
                console.log(`Current variant ID: ${variantId}`);
                this.sendAnalyticsEvent("variant_changed", { variantId });
            });

        const addImageEffect = createEffect(() =>
            actions$.pipe(
                ofType("ADD_IMAGE_ACTION"),
                tap(action => {
                    console.log("Image added:", action.payload);
                    this.sendAnalyticsEvent("image_added", action.payload);
                })
            )
        );
    }

    sendAnalyticsEvent(eventName, data) {
        console.log(`[Analytics] Event: ${eventName}`, data);
    }
}

NGRX Selectors

Token: "SELECTORS_TOKEN"

Description: Functions to extract values from NGRX storage.

Available selectors:

Selector Description
selectCurrentVariantId Extracts the ID of the current variant from storage.
selectCurrentVariant Extracts information about the current variant from storage.
selectProductId Extracts the ID of the current PIM product from storage.
selectProductVersionId Extracts the version ID of the current PIM product from storage.
selectCurrentSurface Extracts the descriptor (SurfaceDescription) of the current design surface from storage.
selectSurfaces Extracts descriptors (SurfaceDescription) of all surfaces in the current design from storage.
selectCountOfSurfaces Extracts the number of surfaces (pages) in the current design from storage.
selectNextStepIsAvailable Extracts a value indicating whether the transition to the next step is available.

Example:

class CustomService {
    constructor() {
        const inject = AurigmaWebComponents.handyEditor.inject;
        const { selectCurrentVariantId } = inject("SELECTORS_TOKEN");
        const { select } = inject("NGRX_UTILS_TOKEN");
        this.store = inject("STORE_TOKEN");
        this.store.pipe(select(selectCurrentVariantId))
            .subscribe(id => console.warn(id));
    }
}

NGRX Actions Service

Token: "ACTIONS_SERVICE_TOKEN"

Description: Provides an observable Actions object to track NGRX events.

Example:

class ActionLoggerService {
    constructor() {
        const inject = AurigmaWebComponents.handyEditor.inject;
        const actions$ = inject("ACTIONS_SERVICE_TOKEN");
        actions$.subscribe(action => {
            console.log(`[Action] ${action.type}`, action.payload);
        });
    }
}

NGRX Actions

Token: "ACTIONS_TOKEN"

Description: Functions to dispatch actions.

Available actions:

Action Description
openPanelAction(payload) Opens the assets panel.
openOverlaySpinnerAction(payload) Opens the loading spinner overlay.
closeOverlaySpinnerAction() Closes the loading spinner overlay.
deletePrivateImageAction() Deletes an image from private storage.
deletePrivateImageSuccessAction() Notifies about the successful deletion of a file from private storage.
openFileDialogForUploadAction() Opens a file dialog for selecting a file to upload.
setUploadedImagesAction() Notifies that the user has selected files for upload to private storage.
successUploadImageAction() Notifies about the successful upload of a file to private storage.
setPrivateImagesAction() Notifies about receiving private images from the server.
addToCanvasPrivateImageSuccessAction() Notifies about the successful addition of an image from private storage to the canvas.
addToCanvasPrivateImageAction() Adds an image from private storage to the canvas.
nextStepIsAvailableActions() Sets the state of the "Next Step" button (enabled/disabled).
viewer3dLoadedAction() Notifies about the successful initialization of the 3D Viewer (for Handy Editor 3D only).
Note

Actions can be listened to for side effects or dispatched for processing.

Example:

class CustomWorkflowService {
    constructor() {
        const inject = AurigmaWebComponents.handyEditor.inject;
        const actions = inject("ACTIONS_TOKEN");

        const openAssetsPanel = () => {
            actions.openPanelAction({ panelType: "ASSETS" });
        };

        const uploadImageWithSpinner = async (file) => {
            actions.openOverlaySpinnerAction({ message: "Uploading image..." });
            try {
                await this.uploadImage(file);
                actions.closeOverlaySpinnerAction();
            } catch (error) {
                actions.closeOverlaySpinnerAction();
                console.error("Upload failed:", error);
            }
        };
    }

    async uploadImage(file) {
        return new Promise(resolve => setTimeout(resolve, 2000));
    }
}

Additional API Tokens

Token Description
"INJECTOR_TOKEN" Angular Injector
"HOTKEYS_TOKEN" Hotkeys service
"PRODUCT_INDEXER_TOKEN" Product indexer for getting real Design Atoms Model entities using descriptor identifiers from the NgRx storage
"VIEWER_TOKEN" Design Atoms Viewer instance of the application
"EVENT_MANAGER_TOKEN" Design Atoms EventManager instance listening to Design Atoms events
"COMMAND_MANAGER_TOKEN" Design Atoms CommandManager instance executing commands on actions
"COMMAND_MANAGER_COMMANDS_TOKEN" Enumerations for CommandManager commands
"ITEMS_DATA_APPLIER_TOKEN" Design Atoms ItemsDataApplier updating the data of the Design Atoms Model elements
"HISTORY_TOKEN" Design Atoms History interacting and managing the editor's history
"DESIGN_ATOMS_ITEMS_TOKEN" Classes for Design Atoms Model items (e.g., RectangleItem, BarcodeItem)
"DESIGN_ATOMS_COLORS_TOKEN" Classes for Design Atoms Model colors (e.g., CmykColor, RgbColor)
"DESIGN_ATOMS_MATH_TOKEN" Classes for Design Atoms math utilities (e.g., RectangleF, PointF)
"RXJS_OPERATORS_TOKEN" RxJS operators (e.g., map, filter, debounceTime)

Command Manager Commands

  • SurfaceCommand
  • ItemsCommand
  • ProductCommand
  • ViewerCommand
  • ZoomCommand
  • SelectionCommand

Design Atoms Model Items

  • Item
  • BarcodeItem
  • EllipseItem
  • RectangleItem
  • ShapeItem
  • ClipartItem
  • ImageItem
  • GroupItem
  • PlainTextItem
  • BoundedTextItem

Example:

class CustomService {
  constructor() {
    const inject = AurigmaWebComponents.handyEditor.inject;

    this._viewer = inject("VIEWER_TOKEN");
    const { RectangleItem, BarcodeItem } = inject("DESIGN_ATOMS_ITEMS_TOKEN");
    const item = this._viewer.seletedItems.at(0)

    if (item instanceof RectangleItem) {
      console.warn("Selected RectangleItem")
    }
  }
}

Dsign Atoms Model Colors

  • CmykColor
  • Color
  • HsbColor
  • RgbColor
  • SpotColor
  • Swatch
  • Ink
  • GrayscaleColor
  • Palette

Example:

class CustomService {
  constructor() {
    const inject = AurigmaWebComponents.handyEditor.inject;

    this._viewer = inject("VIEWER_TOKEN");
    const { CmykColor, RgbColor} = inject("DESIGN_ATOMS_COLORS_TOKEN");
    const fillColor= this._viewer.seletedItems.at(0)?.fillColor;

    if (fillColor instanceof CmykColor) {
      console.warn("fillColor is CmykColor")
    }
    if (fillColor instanceof RgbColor) {
      console.warn("fillColor is RgbColor")
    }
  }
}

Dsign Atoms Model Math

  • RectangleF
  • Path
  • RotatedRectangleF
  • PointF

RxJs Operators

  • map
  • filter
  • tap
  • debounceTime
  • first
  • skip
  • switchMap
  • throttleTime
  • merge
  • forkJoin
  • fromEvent
  • from
  • iif
  • of
  • catchError

Example:

class CustomService {
  constructor() {
    const inject = AurigmaWebComponents.handyEditor.inject;

    const { map, fromEvent } = inject("RXJS_OPERATORS_TOKEN");
    fromEvent(document, "click")
      .pipe(map(e => ({ x: e.pageX, y e.pageY }))
      .subsribe((point) => console.warn("Click to point", point));
  }
}

Client Use Cases

Custom Analytics Tracking

Task: Track user interactions (e.g., design changes, panel openings).

Solution: Use ACTIONS_SERVICE_TOKEN to log events.

class AnalyticsService {
    constructor() {
        const inject = AurigmaWebComponents.handyEditor.inject;
        const actions$ = inject("ACTIONS_SERVICE_TOKEN");
        actions$.subscribe(action => {
            this.sendToAnalytics(action.type, action.payload);
        });
    }
    sendToAnalytics(eventName, data) {
        console.log(`[Analytics] ${eventName}`, data);
    }
}

Automation: Apply a Template to All Pages

Task: Automatically apply a design template to every surface.

Solution: Use CommandManager and selectSurfaces.

class TemplateApplierService {
    constructor() {
        const inject = AurigmaWebComponents.handyEditor.inject;
        const { selectSurfaces } = inject("SELECTORS_TOKEN");
        const commandManager = inject("COMMAND_MANAGER_TOKEN");

        this.store = inject("STORE_TOKEN");
        this.store.pipe(select(selectSurfaces)).subscribe(surfaces => {
            surfaces.forEach(surface => {
                commandManager.execute({
                    type: "APPLY_TEMPLATE",
                    surfaceId: surface.id,
                    templateId: "your_template_id",
                });
            });
        });
    }
}
Was this page helpful?
Thanks for your feedback!
Back to top Copyright © 2001–2025 Aurigma, Inc. All rights reserved.
Loading...
    Thank for your vote
    Your opinion is important to us. To provide details, send feedback.
    Send feedback