UNPKG

shopar-plugin

Version:

Plugin for the Web that seamlessly integrates into your webpage to create embedded virtual try-on and 3D preview capabilities.

620 lines (612 loc) 21 kB
type SkuData = { category?: AssetCategory; arUrl?: string; arEnvUrl?: string; arDiamondEnvUrl?: string; arToneMapping?: ToneMapping; arToneMappingExposure?: number; arBloomEnabled?: boolean; arBloomStrength?: number; arBloomRadius?: number; arBloomThreshold?: number; arKey?: string; arPromptEnabled?: boolean; arPromptText?: string; arPromptImage?: string; previewUrl?: string; previewEnvUrl?: string; previewDiamondEnvUrl?: string; previewToneMapping?: ToneMapping; previewToneMappingExposure?: number; previewBloomEnabled?: boolean; previewBloomStrength?: number; previewBloomRadius?: number; previewBloomThreshold?: number; previewPosterUrl?: string; cameraErrorText?: string; qrPromptText?: string; }; declare const ASSET_CATEGORIES: readonly ["Glasses", "Shoes", "Watches", "Bracelets", "Handbags", "Rings", "Bottles", "Scarves", "Hats", "Necklaces", "Earrings"]; type AssetCategory = typeof ASSET_CATEGORIES[number]; declare const TONE_MAPPINGS: readonly ["ACES", "Linear", "Neutral"]; type ToneMapping = typeof TONE_MAPPINGS[number]; declare const strings_: { 'loading.ar': string; 'prompt.ar.shoes': string | undefined; 'prompt.ar.glasses': string | undefined; 'prompt.ar.watches': string | undefined; 'prompt.ar.bracelets': string | undefined; 'prompt.ar.scarves': string | undefined; 'prompt.ar.hats': string | undefined; 'prompt.ar.necklaces': string | undefined; }; type Strings = typeof strings_; /** * Truescale output measurements */ type FaceMeasurement = { /** * Face width in millimeters. */ faceWidth: number; /** * Interpupillary distance in millimeters. */ IPD: number; }; /** * Type that wraps face position and orientation. */ type FacePose = { /** * Face position in uncalibrated 3D space. */ translation: number[]; /** * Face rotation represented as Tait-Bryan angles (nautical angles). * * Sequence of fields in this array is yaw, pitch, roll (heading, elevation, bank). */ rotation: number[]; }; /** * Plugin controller. */ type Plugin = { /** * Launches the AR view. * Set to `undefined` if AR is not supported for given SKU. * * @returns A promise that resolves when AR is launched. */ launchAR?: () => Promise<void>; /** * Launches the 3D view. * Set to `undefined` if 3D is not supported for given SKU. * * @returns A promise that resolves when 3D is launched. */ launch3D?: () => Promise<void>; /** * Closes the AR view. * Set to `undefined` if AR is not supported for given SKU. * * @returns A promise that resolves when AR is closed. */ closeAR?: () => Promise<void>; /** * Closes the 3D view. * Set to `undefined` if 3D is not supported for given SKU. * * @returns A promise that resolves when 3D is closed. */ close3D?: () => Promise<void>; /** * Closes the AR or 3D view. * Set to `undefined` if neither AR nor 3D are supported for given SKU. * * @returns A promise that resolves when AR or 3D is closed. */ close?: () => Promise<void>; /** * Returns the current user interactivity value. * * @returns `true` is user interactivity is enabled and `false` otherwise. */ isInteractive: () => boolean; /** * Sets user interactivity to the provided value. Set to `false` to ignore input events. * * @param value The provided value. */ setInteractive: (interactive: boolean) => void; /** * Zooms the 3D view in. * The magnification is multiplied by `2^power`, so a power of 1 doubles the magnification. * Has no effect if the 3D view is not currently active. * Set to `undefined` if 3D is not supported for given SKU. * * @param power The exponent applied to the zoom. Each unit doubles the magnification. */ zoomIn3D?: (power: number) => void; /** * Zooms the 3D view out. * The magnification is divided by `2^power`, so a power of 1 halves the magnification. * Has no effect if the 3D view is not currently active. * Set to `undefined` if 3D is not supported for given SKU. * * @param power The exponent applied to the zoom. Each unit halves the magnification. */ zoomOut3D?: (power: number) => void; /** * Rotates the 3D model horizontally by the specified number of degrees. * The initial animation is stopped on the first call. * Has no effect if the 3D view is not currently active. * Set to `undefined` if 3D is not supported for given SKU. * * @param degrees The rotation angle in degrees. Positive values rotate the model right, negative values rotate left. */ rotateHorizontally3D?: (degrees: number) => void; /** * Rotates the 3D model vertically by the specified number of degrees. * The initial animation is stopped on the first call. * Has no effect if the 3D view is not currently active. * Set to `undefined` if 3D is not supported for given SKU. * * @param degrees The rotation angle in degrees. Positive values rotate the model up, negative values rotate down. */ rotateVertically3D?: (degrees: number) => void; }; /** * Vision plugin controller */ type VisionPlugin = { /** * Register a face pose callback which will be called if face is detected. */ registerFacePoseListener?: (facePoseListener: (facePose: FacePose) => void) => void; /** * Register a face measurement callback which will be called if face is detected. */ registerFaceMeasurementListener?: (faceMeasurementListener: (faceMeasurement: FaceMeasurement) => void) => void; /** * Switch the AR effect for preview * * This call is a thin wrapper around DeepAR.switchEffect API. * * @param arUrl A path to the AR effect file * @returns Promise that resolves when an effect start rendering */ switchEffect?: (arUrl: string) => Promise<void>; /** * Clear the AR effect * * Call this after switchEffect to clear the loaded effect. * @returns void */ clearEffect?: () => void; /** * Closes the vision plugin and releases the camera. * * @returns A promise that resolves when AR is closed. */ close?: () => void; }; type ArVideoConfig = { video: HTMLVideoElement; mirror: boolean; }; /** Preview state values. */ declare const PREVIEW_STATES: readonly ["AR", "3D"]; /** Preview state type. */ type PreviewState = typeof PREVIEW_STATES[number]; /** * Configuration of an animation key frame at the specified time point. */ type KeyFrameConfig = { /** Timestamp (in ms). */ time: number; /** Vertical angle of rotation (in degrees). */ pitch?: number; /** Horizontal angle of rotation (in degrees). */ yaw?: number; /** Camera's field of view (in degrees). */ fov?: number; /** * Easing function used for interpolating the values between this and the next key frame. * * Supported options are: * - `'hold'`: maintain the current value without interpolation. * - `'linear'`: linear interpolation. * - `'sine'`: sine wave interpolation. * - `'ease'`: starts slowly, accelerates sharply and slows gradually towards the end. * - `'ease-in'`: starts slowly, progressively speeds up until the end, at which point it stops abruptly. * - `'ease-out'`: starts abruptly and progressively slows down towards the end. * - `'ease-in-out'`: smooth start and end with gradual acceleration and decceleration. * * Additionally, it's possible to specify a custom Bézier function: * - `'cubic-bezier(x1, y1, x2, y2)'`: define two 2D points for a custom interpolation curve. * * @default 'ease-in-out' */ interpolation?: string; }; /** * Options used for the plugin setup. */ type SetupOptions = { /** API key found in the ShopAR dashboard. */ apiKey: string; /** Product identifier. */ sku: string; /** * If provided, the API call is skipped and this SKU data is used instead. */ skuData?: SkuData; /** * The element to inflate with ShopAR UI. * * @remarks If using default UI, its CSS position property must be either 'static' or 'relative'. */ targetElement: HTMLElement; /** * If provided, defines which preview type the plugin initializes to. */ initialState?: PreviewState; /** * If provided, defines where the additional ShopAR plugin files are fetched from. * * @default `https://cdn.jsdelivr.net/npm/shopar-plugin@${version}/` */ baseUrl?: string; /** * If provided and set to `false`, disables the default UI such as buttons, loading and error views. * * When the default UI is disabled, use the returned object as a controller: * ```js * const shopAR = await ShopAR.plugin.setup({ * // ... * defaultUI: false, * }); * shopAR.launchAR(); * ``` * * @default true */ defaultUI?: boolean; /** * If provided and set to `false`, disables user interactivity by ignoring input events. * * @default true */ interactive?: boolean; /** * If provided, the corresponding touch scroll behavior will be used in 3D. * * Supported values are: * - `none`: Touch gestures are never interpreted as scrolling. This might be useful if 3D occupies the whole viewport. * - `pan-x`: Touch gestures that start horizontally are interpreted as scrolling. * - `pan-y`: Touch gestures that start vertically are interpreted as scrolling. * * @default 'pan-y' */ touchAction?: 'none' | 'pan-x' | 'pan-y'; /** * If provided and set to `false`, disables zoom in 3D by ignoring mouse scroll or pinch touch events. * * @default true */ zoomEnabled?: boolean; /** * If provided, it will be used as the minimum zoom level in 3D. * * @default 0.625 */ minZoom?: number; /** * If provided, it will be used as the maximum zoom level in 3D. * * @default 5 */ maxZoom?: number; /** * If provided and set to `true`, transparent background will always be used in 3D. * * This overrides the default behaviour which uses the transparent background only for models **without** transmissive materials. * * WARNING: * Opaque background is intentionally used for models with transmission to avoid the associated rendering issues. * When using this feature, please make sure that the transmissive parts of the model look as desired. * * @default false */ alwaysTransparentBackground?: boolean; strings?: Partial<Strings>; /** * If provided, replaces the default interactivity animation in 3D with a custom one. * * Two formats are supported: `KeyFrameConfig[]` and `string`. * For more information on the `KeyFrameConfig[]` format, see {@link KeyFrameConfig}. * * The `string` format is interpreted as a plain-text table. Empty lines and comments are ignored. * First line defines the columns and all subsequent lines define data per key frame. * * Supported columns are: * - `time`: timestamp of the key frame. * - `pitch`: vertical angle of rotation. * - `yaw`: horizontal angle of rotation. * - `fov`: camera's field of view. * - `interpolation`: easing function used for interpolating the values between this and the next key frame. * See {@link KeyFrameConfig.interpolation} for supported options. * * Timestamps are specified with or without a unit (`ms` or `s`). When not specified, milliseconds are used. * * Angles are specified with or without a unit (`deg` or `rad`). When not specified, degrees are used. * * @example * ` * # Empty lines and comments are ignored. * * time pitch yaw fov interpolation * 0s 45deg 60deg 25deg hold * 1s 45deg 60deg 25deg ease-in-out * 2s 60deg -60deg 20deg hold * 3s 60deg -60deg 20deg ease-in-out * 4s 90deg 90deg 40deg hold * 5s 90deg 90deg 40deg ease-in-out * 6s 45deg 420deg 25deg hold * ` * * @example * [ * { time: 0, pitch: 45, yaw: 60, fov: 25, interpolation: 'hold' }, * { time: 1000, pitch: 45, yaw: 60, fov: 25, interpolation: 'ease-in-out' }, * { time: 2000, pitch: 60, yaw: -60, fov: 20, interpolation: 'hold' }, * { time: 3000, pitch: 60, yaw: -60, fov: 20, interpolation: 'ease-in-out' }, * { time: 4000, pitch: 90, yaw: 90, fov: 40, interpolation: 'hold' }, * { time: 5000, pitch: 90, yaw: 90, fov: 40, interpolation: 'ease-in-out' }, * { time: 6000, pitch: 45, yaw: 420, fov: 25, interpolation: 'hold' }, * ] */ initialAnimation?: KeyFrameConfig[] | string; /** * If provided, it will be called the first time the user's subject is detected in AR (e.g. face, feet, wrist). * It fires only once per setup. */ onFirstAREngagement?: () => void; /** * If provided, it will be called the first time the user engages with the 3D view (rotate, pan or zoom). * It fires only once per setup. */ onFirst3DEngagement?: () => void; /** * If provided, it will be used as the debounce duration for debounced AR engagement tracking. * * @default 2000 * @see onDebouncedAREngagement */ debounceAREngagementMs?: number; /** * If provided, it will get called with the engagement duration on every (debounced) AR engagement. * * AR engagement is measured as the time spent by the user virtually trying out the product in AR. * The callback is called after engagement stops for the specified debounce duration. * Additionally, any outstanding engagement duration is flushed when AR is closed. * * @param durationMs Engagement duration in milliseconds. * @see debounceAREngagementMs */ onDebouncedAREngagement?: (durationMs: number) => void; /** * If provided, it will be used as the debounce duration for debounced 3D engagement tracking. * * @default 2000 * @see onDebounced3DEngagement */ debounce3DEngagementMs?: number; /** * If provided, it will be called with the engagement duration on every (debounced) 3D engagement. * * 3D engagement is measured as the time spent by the user rotating, panning or zooming the product in 3D. * The callback is called after engagement stops for the specified debounce duration. * Additionally, any outstanding engagement duration is flushed when 3D is closed. * * @param durationMs Engagement duration in milliseconds. * @see debounce3DEngagementMs */ onDebounced3DEngagement?: (durationMs: number) => void; /** * If provided, it will be called when the maximum zoom level (`maxZoom`) is reached in 3D. */ onMaxZoomEnter?: () => void; /** * If provided, it will be called when the zoom level moves away from the maximum (`maxZoom`) in 3D. */ onMaxZoomLeave?: () => void; /** * If provided, it will be called when the minimum zoom level (`minZoom`) is reached in 3D. */ onMinZoomEnter?: () => void; /** * If provided, it will be called when the zoom level moves away from the minimum (`minZoom`) in 3D. */ onMinZoomLeave?: () => void; /** * If provided, it will be called when the minimum vertical angle is reached in 3D. * This corresponds to the camera being positioned at the top of the orbit, looking down at the object. */ onMinVerticalAngleEnter?: () => void; /** * If provided, it will be called when the vertical angle moves away from the minimum in 3D. * The camera is no longer at the top of the orbit. */ onMinVerticalAngleLeave?: () => void; /** * If provided, it will be called when the maximum vertical angle is reached in 3D. * This corresponds to the camera being positioned at the bottom of the orbit, looking up at the object. */ onMaxVerticalAngleEnter?: () => void; /** * If provided, it will be called when the vertical angle moves away from the maximum in 3D. * The camera is no longer at the bottom of the orbit. */ onMaxVerticalAngleLeave?: () => void; /** * If provided, it will be used as the video source for AR instead of the default camera used by plugin. * * Example of loading HTMLVideoElement: * ```js * function loadVideo(src) { * const video = document.createElement('video'); * video.src = src; * video.muted = true; * video.setAttribute("playsinline", "playsinline"); * video.load(); * video.onloadedmetadata = () => { * video.play(); * }; * * return video; * } * ``` */ customArVideo?: ArVideoConfig; /** * If provided, it will be used as the true scale face width, in millimeters, for AR glasses. * * If not provided, the value is determined by ShopAR True Scale technology. */ customTrueScaleFaceWidth?: number; _internalOptions?: any; }; /** * Options used for the vision plugin setup. */ type VisionOptions = { /** API key found in the ShopAR dashboard. */ apiKey: string; /** * The element to inflate with camera canvas. */ targetElement: HTMLElement; /** * If provided, defines where the additional ShopAR plugin files are fetched from. * * @default `https://cdn.jsdelivr.net/npm/shopar-plugin@${version}/` */ baseUrl?: string; }; /** * Base error class for all ShopAR plugin errors. */ declare class PluginError extends Error { constructor(message: string); } /** * Error thrown when setup or option validation fails. */ declare class ValidationError extends PluginError { constructor(message: string); } /** * Error thrown when the ShopAR API call fails. */ declare class ApiError extends PluginError { status: number | undefined; constructor(message: string, status?: number); } /** * Error thrown when SKU data sanitization fails. */ declare class SanitizationError extends PluginError { constructor(message: string); } /** * Error thrown when 3D fails to launch. */ declare class Launch3DError extends PluginError { constructor(message?: string); } /** * Error thrown when AR fails to launch. */ declare class LaunchARError extends PluginError { constructor(message?: string); } /** * Error thrown when the user denies camera permissions. */ declare class CameraPermissionDeniedError extends LaunchARError { constructor(message?: string); } /** * Error thrown when QR code launch fails. */ declare class QRError extends LaunchARError { constructor(message?: string); } /** * ShopAR vision plugin. * * @example * Using CDN: * ```html * <script src="../../shopar-plugin/shopar-plugin.js"></script> * <script> * const vision = ShopAR.vision.setup({ ... }); * </script> * ``` * * @example * Using a module bundler: * ```js * import { ShopAR } from 'shopar-plugin'; * * const vision = ShopAR.vision.setup({ ... }); * ``` */ declare const vision: { /** * Initializes vision modules and renderes deepar canvas. * * If successful, function returns a handle to the VisionPlugin. This component alows for lower level control * over DeepAR and truescale components. * * @param options Setup options. */ setup: (options: VisionOptions) => Promise<VisionPlugin>; }; /** * The ShopAR plugin. * * @example * Using CDN: * ```html * <script src="../../shopar-plugin/shopar-plugin.js"></script> * <script> * ShopAR.plugin.setup({ ... }); * </script> * ``` * * @example * Using a module bundler: * ```js * import { ShopAR } from 'shopar-plugin'; * * ShopAR.plugin.setup({ ... }); * ``` */ declare const plugin: { /** * Fetches the specified product from the ShopAR API and renders the ShopAR UI. * * Optionally, you can provide a `skuData` object to bypass the API call and use the provided SKU data directly. * * @param options Setup options. */ setup: (options: SetupOptions) => Promise<Plugin>; /** Plugin version. */ version: string; }; export { ApiError, CameraPermissionDeniedError, Launch3DError, LaunchARError, PREVIEW_STATES, PluginError, QRError, SanitizationError, ValidationError, plugin, vision }; export type { ArVideoConfig, FaceMeasurement, FacePose, KeyFrameConfig, Plugin, PreviewState, SetupOptions, SkuData, VisionOptions, VisionPlugin };