UNPKG

@spiffcommerce/core

Version:

Core client API for interacting with the Spiff Commerce backend.

1,351 lines (1,334 loc) • 231 kB
import { FunctionComponent, ReactNode } from 'preact/compat'; import * as _apollo_client_core from '@apollo/client/core'; import { OperationVariables, QueryOptions, ApolloQueryResult, DefaultContext, MutationOptions, FetchResult, ApolloClient } from '@apollo/client/core'; import { RenderableContextService, RenderableContext, ModelContainer, ThreeDPreviewService } from '@spiffcommerce/preview'; import * as lodash from 'lodash'; import { CompleteQuoteMessage, ThemeInstallConfigurationGraphQl, ConversionConfiguration } from '@spiffcommerce/theme-bridge'; export { ConversionConfiguration, ConversionData, ConversionDataType, ConversionLocation } from '@spiffcommerce/theme-bridge'; import { Currency } from 'dinero.js'; import { FuseResult } from 'fuse.js'; import { Font } from 'opentype.js'; /** * A renderable scene is a scene that can be displayed to the user. This is based on the workflow state. */ interface RenderableScene { /** * The id of the scene. */ id: string; /** * The title of the scene. */ title: string; /** * The id of each step inside the scene that can be rendered. This is based on the workflow state. */ renderableSteps: string[]; /** * The WorkflowScene representation of this object. Provided for backwards compatibility. * @deprecated */ workflowScene: WorkflowScene; } /** * Information parsed froma workflow structure that is relevant * to a given scene. */ interface WorkflowScene { /** * A unique identifier for the scene. */ name: string; /** * A human-readable title for the scene. */ title: string; /** * Steps which can display to the user. * But may be conditionally hidden based on workflow logic */ renderableSteps: Step<AnyStepData>[]; /** * Steps which don't display to the user. * Their behavior is always silent & executed in the background. * @deprecated Silent steps are no longer handled seperately from normal steps. */ silentSteps: Step<AnyStepData>[]; } /** * A queue promise is a container for a promise that can be * executed at a later time. */ declare abstract class QueueablePromise { readonly timestamp: number; abstract execute(): Promise<any>; } /** * A promise queue contains any number of QueuePromise objects. These objects are stored within a PromiseQueue and executed * as quickly as possible in order. This is ideal in situations where a specific operation should be * applied in an ordered way while still making. */ declare class PromiseQueue<T extends QueueablePromise> { private queue; private activePromise?; private queueMaxSize; private isEnabled; /** * Constructs a new promise queue. * @param queueMaxSize An optional maximum size, when the max size is hit. * The older promises will be discarded. * @param enabled When false, the queue will not process any jobs. Assign `enabled` to true to start processing. */ constructor(queueMaxSize?: number, enabled?: boolean); /** * Enqueue a new promise. * @param promise A new promise to add to the queue. */ enqueue(promise: T): void; get enabled(): boolean; /** * Enable or disable the queue. When disabled, the queue will not process any jobs. * Disabling processing will not cancel any active promises. */ set enabled(value: boolean); /** * @returns Returns true when work is being actively processed by this queue. */ hasActivePromise(): boolean; /** * @returns The number of unexecuted jobs remaining in the queue. Not including the active job. */ getRemainingQueueSize(): number; /** * Finalize the queue, any jobs that come in while this is in progress will result * in the promise being extended. */ finalize(): Promise<void>; /** * Once called will recursively resolve the jobs in the * queue until no more are available. */ private dequeue; } /** * Bounds the offsets for an image to the box, preventing * the user from moving the image in a way that wouldn't be intended. * @param newOffsets The new intended offsets for the image. * @param frameData The current frame information * @param borderWidth The width of the border added by the cropper. * @param mustCover When true the image sgould be bounded in such a way that it covers the entire frame at all times. */ declare function getBoundedOffsets(newOffsets: FrameOffsets, frameData: FrameData, imageData: PatternImageData, mustCover?: boolean): FrameOffsets; declare class FrameService { private offsets; private thresholdSettings; private forceImageCover?; private initialZoom?; private targetElements; private imageData?; private frameData?; private readonly _debouncedUpdateFrameOffsets; /** * The calculated minimum zoom value, per frame. */ minZoomScale: number[]; /** * The calculated maximum zoom value. Note: This is calculated based on the first frame. */ maxZoomScale: number[]; private onFrameDataChangeListeners; private onZoomChangeListeners; private workflowManager?; private stepName?; constructor(forceImageCover?: boolean, initialZoom?: number); /** * When we want to connect a workflow manager to the state of the image cropper we * can pass it to this function. Inside we'll attach any required event listeners. * @param workflowManager The workflow manager to attach. * @param stepName The specific step we want to attach to within the manager. */ connectWorkflowManager(workflowManager: WorkflowManager, stepName?: string): void; /** * Sets the elements that should be update when changes are made to * the cropper that owns this service. * @param targetElements A list of element Ids to track */ setTargetElements(targetElements: string[]): void; /** * Gets the current calculated frame data * @returns A FrameData object or undefined if no frame has been set. */ getFrameData(): FrameData[] | undefined; /** * Sets the current frame data. Note: * @param paths The paths to lookup in our frame data cache. */ setFrameData(paths: string[] | undefined): void; /** * Gets the currently set image of the frame.. * @returns A PatternImageData object, or undefined if no image is set. */ getImageData(): PatternImageData | undefined; /** * Helper function to get the src of the image of the frame, since it can be an svg with modified colors. * @returns A url (a data url if svg), or undefined if no image is set. */ getImageSrc(): string | undefined; /** * Gets the current calculated offsets of the pattern within the frame. * @returns A FrameOffsets object or undefined if no offsets are defined. */ getOffsets(): FrameOffsets[] | undefined; /** * Updates the frame offsets explicitly. */ setOffsets(offsets: FrameOffsets[]): void; /** * Sets the zoom of the cropper that owns this service. * @param zoom The new zoom value, per frame. * @param cX The center of zoom on x axis, per frame. * @param cY The center of zoom on Y axis, per frame. * @param onComplete A function to call when zoom changes have been completed */ setZoom(zoom: number[], cX: number[], cY: number[], onComplete?: () => void): void; /** * Sets the image currently contained by this frame. * @param value The new image as an ImageData property * @param [recalculateOffsets=true] Optional: Enable/disable re-calculating of frame offsets. Default: `true`. * Note: Will always calculate when offsets have not been calculated. */ setPatternData(value: PatternImageData, recalculateOffsets?: boolean): void; /** * Modify the offsets of the frame. * @param value The new FrameOffsets objects. * @param onComplete A callback, called when the modification is complete * @param forceUpdate When true the offsets will be updated even if they haven't changed. */ updateOffsets(value: FrameOffsets[], onComplete?: () => void, forceUpdate?: boolean): void; getThresholdSettings(): FrameThresholdSettings; setThresholdSettings(settings: FrameThresholdSettings): void; onFrameDataChanged(newListener: (frameData: FrameData[] | undefined) => void): void; /** * Append a new listener to zoom events on this frame. * @param newListener */ onZoom(newListener: (zoomValue: number[]) => void): void; /** * Updates the offsets of the frame * @param newOffsets New offset object * @param imageData The image data * @param frameData The frame data * @param targetElements A list of elements that need updating, by ID * @param onComplete A callback when the operation is completed. */ private updateFrameOffsets; /** * Determines limitations of zoom based on relative size of image and frame. * @param imageData The image to include in calculations * @param frameData The frame to include in calculations. */ private recalculateZoomLimits; private recalculateOffsets; } declare class Poller { private pollingId; private attempts; private readonly interval; private readonly maxAttempts; private readonly predicate; private readonly onSuccess; private readonly onFailure; private poll; /** * Constructs a new polling service. * @param predicate An async function that returns true when polling has returned a successful result. * @param onSuccess The callback to be called when polling has returned a successful result. * @param onFailure The callback to be called when polling has returned a failed result. * @param interval The number of milliseconds to wait between each poll. * @param maxAttempts The maximum amount of times to check the condition. */ constructor(predicate: () => Promise<boolean>, onSuccess: () => void, onFailure: () => void, interval?: number, maxAttempts?: number); } declare abstract class ModuleProduct { /** * Name used by class. Usually product or brand name. */ abstract moduleName: string; /** * SVG with styled path positioned on a background image. To be displayed to user. */ abstract svgPreview(text: string, region: Region): string; /** * SVG with styled path positioned on a background image. To be submitted for print. */ abstract svgPrint(text: string, region: Region): string; } interface DesignInputStep { data: DesignInputStepData; name: string; } interface DesignInputStepData { } interface SVGLayoutProps { configuration: RenderingConfiguration; preserveAspectRatio?: string; outlineArea?: { x?: number; y?: number; width?: number; height?: number; scale?: number; hidden?: boolean; }; viewBox?: { x: number; y: number; width: number; height: number; }; width: number | string; height: number | string; position?: string; maxWidth?: string; maxHeight?: string; elements: LayoutElement[]; backgroundColor?: string; outlineColor?: string; omitBoundClipping?: boolean; borderRadius?: number; } /** * An abstract base class from which to extend all potential element commands. These commands * follow the command design pattern in software development. To learn more about this pattern * take a look at the following link. * * https://sourcemaking.com/design_patterns/command * */ declare abstract class CanvasCommand { abstract apply(state: LayoutsState): LayoutsState; protected oldState?: LayoutsState; undo(): LayoutsState; overrideOldState(state: LayoutsState): void; sequenceId?: string; } /** * Shifts an element with given ID from its current position to a new position. */ declare class MoveCommand extends CanvasCommand { private id; private x; private y; constructor(id: string, x: number, y: number); apply(state: LayoutsState): { layouts: { [x: string]: LayoutState; }; serializableWorkflow: SerializableWorkflow; }; } /** * Rotates an element to a given angle in degrees. */ declare class RotateCommand extends CanvasCommand { private id; private angle; constructor(id: string, angle: number); apply(state: LayoutsState): { layouts: { [x: string]: LayoutState; }; serializableWorkflow: SerializableWorkflow; }; } /** * Updates the width and height of an element to reflect a new size. Negative values will be * converted to their absolute value. ie. -10 will become 10. */ declare class ResizeCommand extends CanvasCommand { private id; private width; private height; constructor(id: string, width: number, height: number); apply(state: LayoutsState): { layouts: { [x: string]: LayoutState; }; serializableWorkflow: SerializableWorkflow; }; } /** * Applys a list of command objects to the current state, the final state * will be that of all commands applied in the order of left to right. */ declare class GroupCommand extends CanvasCommand { private commands; constructor(commands: CanvasCommand[]); apply(state: LayoutsState): LayoutsState; } declare class CreateLayoutCommand extends CanvasCommand { private layout; constructor(layout: ILayout); apply(state: LayoutsState): LayoutsState; } /** * Add an element to the canvas */ declare class CreateElementCommand<T extends LayoutElement> extends CanvasCommand { private element; private layout; /** * @param initialParams The initial parameters to be set on this new object * @param callback An optional callback function to be notified when the object has been instantiated * @param layout */ constructor(element: T, layout: ILayout); apply(state: LayoutsState): { layouts: { [x: string]: LayoutState | { elements: LayoutElement[]; modificationID: string; layout: ILayout; }; }; serializableWorkflow: SerializableWorkflow; }; private assignIndex; } /** * Delete an element on the canvas */ declare class DeleteElementCommand extends CanvasCommand { private id; constructor(id: string); apply(state: LayoutsState): { layouts: { [key: string]: LayoutState; }; serializableWorkflow: SerializableWorkflow; }; } declare class FontColorCommand extends CanvasCommand { private id; private color; private textFillSpotColor?; constructor(id: string, color: string, textFillSpotColor?: TextFillSpotColor$1); apply(state: LayoutsState): { layouts: { [x: string]: LayoutState; }; serializableWorkflow: SerializableWorkflow; }; } declare class FontSizeCommand extends CanvasCommand { private id; private size; constructor(id: string, size: number); apply(state: LayoutsState): { layouts: { [x: string]: LayoutState; }; serializableWorkflow: SerializableWorkflow; }; } declare class FontSourceCommand extends CanvasCommand { private id; private fontData; constructor(id: string, fontData: FontData); apply(state: LayoutsState): { layouts: { [x: string]: LayoutState; }; serializableWorkflow: SerializableWorkflow; }; } declare class FontAlignmentCommand extends CanvasCommand { private id; private align; constructor(id: string, align: "left" | "center" | "right"); apply(state: LayoutsState): { layouts: { [x: string]: LayoutState; }; serializableWorkflow: SerializableWorkflow; }; } declare class UpdateImageSourceCommand extends CanvasCommand { private id; private src; constructor(id: string, src: string); apply(state: LayoutsState): LayoutsState; } /** * TextChange will modify the text displayed in a text box */ declare class TextChangeCommand extends CanvasCommand { private id; private text; constructor(id: string, text: string); apply(state: LayoutsState): { layouts: { [x: string]: LayoutState; }; serializableWorkflow: SerializableWorkflow; }; } declare class BringToFrontCommand extends CanvasCommand { private id; /** * @param id The targeted element to bring to the front. */ constructor(id: string); apply(state: LayoutsState): { layouts: { [x: string]: LayoutState | { elements: LayoutElement[]; modificationID: string; layout: ILayout; }; }; serializableWorkflow: SerializableWorkflow; }; } declare class BringToBackCommand extends CanvasCommand { private id; /** * @param id The targeted element to bring to the back. */ constructor(id: string); apply(state: LayoutsState): { layouts: { [x: string]: LayoutState | { elements: LayoutElement[]; modificationID: string; layout: ILayout; }; }; serializableWorkflow: SerializableWorkflow; }; } /** * Bring an element forward by one layer. Does nothing if the element is already at the front. */ declare class BringForwardCommand extends CanvasCommand { private id; /** * @param id The targeted element to bring to the front. */ constructor(id: string); apply(state: LayoutsState): { layouts: { [x: string]: LayoutState | { elements: LayoutElement[]; modificationID: string; layout: ILayout; }; }; serializableWorkflow: SerializableWorkflow; }; } /** * Send an element backwards by one layer. Does nothing if the element is already at the back. */ declare class SendBackwardsCommand extends CanvasCommand { private id; /** * @param id The targeted element to bring to the front. */ constructor(id: string); apply(state: LayoutsState): { layouts: { [x: string]: LayoutState | { elements: LayoutElement[]; modificationID: string; layout: ILayout; }; }; serializableWorkflow: SerializableWorkflow; }; } interface CommandState { transaction: LayoutsState; } interface LayoutComponentConfiguration { renderingConfiguration: RenderingConfiguration; outlineArea?: { x?: number; y?: number; width?: number; height?: number; scale?: number; hidden?: boolean; }; viewBox?: { x: number; y: number; width: number; height: number; }; maxHeight?: string; maxWidth?: string; height?: string | number; width?: string | number; position?: string; borderRadius?: number; outlineColor?: string; backgroundColor?: string; } declare class CommandContext { private state; private stateCallbacks; private id; private prevCommands; private nextCommands; constructor(); registerStateCallback(callback: () => void): void; unregisterStateCallback(callback: () => void): void; getState(): CommandState | undefined; private runStateCallbacks; apply(command: CanvasCommand, leaveOffUndoStack?: boolean): void; undo(): void; redo(): void; /** * Find all commands in history with the given sequence ID, * discard all but the last and overwrite its oldState. */ flattenSequence(sequenceId: string, initialState: LayoutsState): void; getLayoutById(layoutId: string): LayoutData; getAllLayouts(): LayoutData[]; private getLayoutDataWithState; initialize(layouts: ILayout[], reloadedState?: LayoutsState): void; private commandReducer; } declare const getSvgElement: (layout: ILayout, elements: LayoutElement[], configuration: LayoutComponentConfiguration) => PapyrusNode; interface LayoutData { layoutState: LayoutState; Component: PapyrusComponent<SVGLayoutProps>; getComponentWithProps: (configuration: LayoutComponentConfiguration) => PapyrusComponent<SVGLayoutProps>; } declare class LayoutPreviewService implements RenderableContextService { private readonly layouts; private workflowManager?; private handleCompleteRender; constructor(layouts: ILayout[]); setCompleteRenderCallback(handleCompleteRender: (layouts: LayoutPreviewBridge[]) => void): void; onCompleteRender(): void; getAll(): ReadonlyMap<string, LayoutPreviewBridge>; setWorkflowManager(workflowManager: WorkflowManager): void; getWorkflowManager(): WorkflowManager | undefined; } /** * The panel canvas class that stores both the main rendering canvas as well as rendering context * for a rendering context */ declare class LayoutPreviewBridge implements RenderableContext { hasSetStaticContext: boolean; private readonly id; private readonly name; private readonly panelSize; private readonly getWorkflowManager?; private service; private interactiveDirty; private textureCtx?; private staticCtxDirty; private lastRequestedRenderArguments; private lastCompletedStaticRender; private renderQueue; constructor(id: string, name: string, service: LayoutPreviewService, panelSize: { width: number; height: number; }, getWorkflowManager?: () => WorkflowManager | undefined); getID(): string; getName(): string; getPanelSize(): { width: number; height: number; }; getStaticContext(): CanvasRenderingContext2D | undefined; /** * Register canvas to be rendered to. */ setStaticContext(ctx: CanvasRenderingContext2D): void; getStaticContextDirty(): boolean; setStaticContextDirty(dirty: boolean): void; getInteractiveCanvasDirty(): boolean; setInteractiveCanvasDirty(dirty: boolean): void; markLastCompletedStaticRender(): void; /** * Returns a timestamp for the last time that this canvas rendered to its dynamic texture in the * form of Date.now(). If this panel has never rendered undefined will be returned. */ getLastCompletedStaticRender(): number | undefined; /** * Actions to perform when a static render event is fired for this canvas. */ render(layouts: LayoutData[]): Promise<void>; } interface StepAspectValue { stepName: string; stepAspectType: string; value?: string; } declare const stepAspectValuesToDesignInputSteps: (stepAspectValues: StepAspectValue[], workflow: Workflow) => DesignInputStep[]; declare const generateStateFromDesignInputSteps: (designInputSteps: DesignInputStep[], workflow: Workflow, layouts: ILayout[], productOverlayImageUrl?: string) => Promise<LayoutsState>; /** * An asset manager provides a way to create and * manage assets on the Spiff Commerce Platform. */ interface AssetManager { /** * Uploads a file to the Spiff Commerce Platform. */ uploadFile: (file: File, onProgress: (val: number) => void) => Promise<Asset>; /** * From an existing asset, generates a new asset that has the background replaced with transparency. * This process is idempotent, i.e. it will only run once for a given asset. * @param asset The existing asset to remove the background from. * @returns A promise that resolves with a new asset. */ removeBackgroundFromAsset(asset: Asset): Promise<Asset>; } declare class AssetService implements AssetManager { private cache; /** * Promise cache for BG removal processes. Values only present while process is active. * Use BGRMStorage and the regular asset promise cache to cache the actual objects. */ private bgrmProcessCache; private materialCache; /** * Allows for retrieving an asset, returns the option from a cache if possible. */ getLocalOrFromServer(assetKey: string): Promise<Asset>; /** * Retrieves the asset from the server, bypassing cache (but still writing the result to cache) */ getFromServer(assetKey: string): Promise<Asset>; keyFromURL(url: string): string | undefined; /** * Caches an asset if it doesn't already exist. */ cacheAsset(asset: Asset): void; /** * Caches a material if it doesn't already exist. */ cacheMaterial(material: MaterialResource): void; /** * Allows for retrieving a material, returns the option from a cache if possible. * @param id The option ID to be retrieved. */ getMaterialLocalOrFromServer(id: string): Promise<MaterialResource>; /** * Upload a user asset to the server. Using callbacks to notify important events. * The asset will be stored via the persistence service for future access, if available. */ uploadAssetWithProgress(file: FileInfo, assetType: AssetType, onProgress: (val: number) => void, anonymous?: boolean, temporary?: boolean): Promise<Asset>; uploadAsset(file: FileInfo, assetType: AssetType, anonymous?: boolean, temporary?: boolean): Promise<Asset>; uploadFile(file: File, onProgress: (val: number) => void): Promise<Asset>; removeBackgroundFromAsset(asset: Asset): Promise<Asset>; removePersistedAsset(assetKey: string): void; getPersistedAssets(): PersistedAsset[]; registerPersistedAssetListener(callback: () => void): void; unRegisterPersistedAssetListener(callback: () => void): void; /** * Convert a File object for an image into a FileInfo. */ loadImageAsFileInfo: (file: File) => Promise<FileInfo>; private isRaster; private postProcessFileUpload; /** * Handles mimeType resolution & asset creation request * @param file A file info object containing data about the file and its name * @param assetType The type of asset we're expecting to upload */ private dispatchCreateAssetRequest; private guessMIME; } interface PersistedAsset { assetKey: string; src: string; } declare const assetService: AssetService; /** * A wrapping component that provides a simple interface for interacting with a variant. */ declare class Variant { private readonly variantData; constructor(variant: VariantResource); getType(): AssetType | undefined; /** * @returns The unique identifier for the variant. */ getId(): string; /** * @returns The configured name of the variant. Generally a human readable value. */ getName(): string; /** * @returns The price modifier for this variant. This is the amount that will be added to the base price of the product. */ getPriceFormatted(locales?: Intl.LocalesArgument, options?: Intl.NumberFormatOptions | undefined): string; /** * @returns The price modifier for this variant. This is the amount that will be added to the base price of the product. * Presented in subunits of the currency of the option. For example, if the option is configured to use USD, the price modifier will be in cents. */ getPrice(): number; /** * @returns The URL for the base asset resource configured on this variant */ getAsset(): string | undefined; /** * @returns The URL for the base asset resource configured on this variant */ getAssetResource(): Asset | undefined; /** * @returns The URL for a thumbnail resource configured on this variant. */ getThumbnail(): string | undefined; /** * @returns When this variant is configured to have a color, this will return the hex value for that color. */ getColor(): string | undefined; /** * @returns True when the variant is the default for its containing option. False otherwise. */ isDefault(): boolean; /** * @returns The underlying variant resource. Generally not needed but made available just incase. */ getResource(): VariantResource; /** * @returns True when the variant is enabled. False otherwise. */ isEnabled(): boolean; } /** * Steps that support custom color variants should implement the following interface to * add the behavior in the way that makes sense to the step. */ interface CustomColorSupport { /** * Allows for setting a custom color when the custom variant is selected. Will * throw when a non-custom variant is selected. */ setCustomColor(color: string): any; /** * Get the custom color that is currently set on the step. */ getCustomColor(): string; } /** * A StepHandle allows for managing the state of a specific step in a workflow. This class * abstracts away the complexities of dealing with a step directly and allows for using high level * concepts instead of dealing with the underlying data structures. */ declare abstract class StepHandle<T extends AnyStepData> { /** * Stores whether or not the step is currently updating. */ private static readonly updateState; /** * Access to the workflow manager this step is contained by. */ protected readonly manager: WorkflowManager; /** * The step metadata, useful for determining logic based on configuration. */ protected readonly step: Step<T>; /** * The tags set against this step. */ protected readonly tags: string[]; constructor(manager: WorkflowManager, step: Step<T>, tags: string[]); /** * Set the current update state of this step. All step handles pointing to this step will * see this value. * @param value The new value */ protected setUpdateState(value: boolean): void; /** * @returns Gets the current update state of this step. All step handles for this step will see this value. */ protected getUpdateState(): boolean; /** * Gets the currently selected variant, or undefined if no variant is selected. */ getCurrentVariant(): Variant | undefined; /** * @returns A list of valid variants for this step. Does not include disabled variants. */ getAvailableVariants(): Variant[]; /** * @returns A list of all variants for this step, including disabled ones. */ getAllVariants(): Variant[]; /** * Most step types have a base option type that variants can be selected for. * Selects a specific variant for this step. This will execute all required changes to * the design and update the metadata to include the new selection. Any conditions * that would be triggered will also be executed. */ abstract selectVariant(variant: Variant): Promise<void>; /** * @returns A unique identifier for this step within the workflow. */ getId(): string; /** * @returns The name of the step */ getName(): string; /** * @returns A message that can accompany the step name in UI components. Used to describe the purpose of the step in more detail. */ getHelpText(): string | undefined; /** * @returns The type of the step handle. */ getType(): StepType; /** * @returns The underlying data for this step. Favor using the step handle methods instead of this. */ getRaw(): Step<T>; /** * @returns Returns all of the tags that are present on this step. */ getTags(): string[]; /** * @param tag The tag to check for. * @returns True if the step has the specified tag, false otherwise. */ hasTag(tag: string): boolean; /** * @returns True if the step is required to be filled by the customer. False otherwise. */ getMandatory(): boolean; /** * @param type The AspectType to fetch the value for. * @returns A boolean indicating whether this step should override Global Properties. * Only relevant when the Workflow Experience is associated with a Bundle that is using Global Properties, * and when this step is associated with one or more Global Property Aspects. */ getOverrideGlobalPropertyConfiguration(type: AspectType): boolean; /** * Sets whether or not this step should override Global Properties. * Only relevant when the Workflow Experience is associated with a Bundle that is using Global Properties, * and when this step is associated with one or more Global Property Aspects. * @param type The AspectType to override. */ setOverrideGlobalPropertyConfiguration(type: AspectType, value: boolean): void; /** * Retrieves the identifiers of all of the configured aspects for the specified Global Property Configuration. * @param configurationId The ID of the Global Property Configuration. You can usually find this with `bundle.getGlobalPropertyConfiguration()?.id` * @returns An array of strings matching the keys of all the Global Property Aspects in the Configuration that this step is configured to use. */ getGlobalPropertyAspects(configurationId: string): string[]; /** * Fires any configured animations on the 3D preview for this step. * This includes camera & model animations. If the preview is unavailable * this function will do nothing. */ executeAnimations(immediate?: boolean): void; } interface SavedDesign { /** * The user's name for this saved design. */ title: string; /** * A URL pointing to an image of the design. Typically a data URL */ thumbnail?: string; /** * The ID of the transaction relating to this design. */ transactionId: string; /** * The product ID for this transaction. */ productId: string; /** * The integration product ID related to this order. */ integrationProductId: string; /** * The name of the workflow annotated at time of save (may be different from current workflow name). */ workflowName: string; /** * The ID of the workflow annotated at time of save. */ workflowId: string; /** * The last edit that occured on this saved design. */ lastEdited: Date; } /** * The design service exposes helper functionality wrapping important design management operations. * NOTE: In the future this interface should allow for storing/pulling designs from the server. */ declare class DesignService { readonly localPersistenceKey = "designTransactions"; private storageMethod; private designSavedListeners; /** * @param func The function to call when a design is saved. */ attachSaveListener(func: (design: SavedDesign) => void): void; /** * @param func The function to remove from the list of listeners. */ detachSaveListener(func: (design: SavedDesign) => void): void; /** * Gets the currently persisted designs. */ getSavedDesigns(): Promise<SavedDesign[]>; /** * Search for a transaction that has been saved. * @param transactionId The id to search for. * @returns The transaction for the given id provided it has been saved. undefined if it doesn't exist. */ getSavedDesignByTransaction(transactionId: string): Promise<SavedDesign | undefined>; /** * Saves a design to storage. * @param design The design to save. */ addDesign(design: SavedDesign): Promise<void>; /** * Change the user's name of the given saved design. */ renameDesign(transactionId: string, title: string): Promise<void>; /** * Removes a given design from storage. * @param transactionId */ removeDesign(transactionId: string): Promise<void>; private setDesigns; } declare const designService: DesignService; interface GraphQlClient { query<T = any, TVariables extends OperationVariables = OperationVariables>(options: QueryOptions<TVariables, T>): Promise<ApolloQueryResult<T>>; mutate<TData = any, TVariables extends OperationVariables = OperationVariables, TContext extends Record<string, any> = DefaultContext>(options: MutationOptions<TData, TVariables, TContext>): Promise<FetchResult<TData>>; } type GraphQlClientFunc = () => GraphQlClient; /** * A scene is a collection of steps that can be used to group steps together. */ interface Scene { /** * The unique identifier for the scene. */ id?: string; /** * The name of the scene. */ name: string; /** * The steps that are part of the scene. A list of ids. See getStepById. */ stepIds: string[]; } /** * State related to a workflow experience. */ interface ExperienceOptions { transaction: Transaction; workflow?: Workflow; modelContainer?: ModelContainer; renderableContextService?: LayoutPreviewService; reloadedState?: LayoutsState; /** * When true the experience is intended to be immutable. */ readOnly?: boolean; /** * A function that communicates state changes to the server. */ stateMutationFunc: StateMutationFunc; /** * The interface for the graphql client */ graphQlClient: GraphQlClientFunc; /** * Should be set to true when the experience is loaded from an existing transaction. * FIXME: Wouldn't we know this from existance of reloadedState */ isReloadedTransaction?: boolean; /** * When true the system will treat steps with * a single variant as renderable. False * by default. */ singleVariantsRenderable?: boolean; /** * When true, will delay syncing the workflow state until manually enabled. */ delayWorkflowStateSync?: boolean; } /** * A Workflow experience encapsulates the workflow manager and command context. It * provides a simplified interface for interacting with the workflow manager. You * should get an instance of this class from a Client you have constructed previously. */ interface WorkflowExperience { /** * Get the current transaction for this experience. */ getTransaction(): Transaction; /** * Get the bundle this experience is part of. May be undefined. */ getBundle(): Bundle$1 | undefined; /** * Set the bundle this experience is part of. Can be cleared using undefined. */ setBundle(bundle: Bundle$1 | undefined): any; /** * Get the current product for this experience. May be undefined. */ getProduct(): Product | undefined; /** * Get the current profanity list for this experience. May be empty. */ getProfanityList(): string[]; /** * Set the current product for this experience. * @param product The new product to set. */ setProduct(integrationProductId: string): Promise<void>; /** * Clear the product from this experience. */ clearProduct(): Promise<void>; /** * Get the current workflow for this experience. May be undefined. */ getWorkflow(): Workflow | undefined; /** * Set the current workflow for this experience. * @param workflow The new workflow to set. */ setWorkflow(workflow: Workflow): Promise<void>; /** * Returns the client that was responsible for spawning this experience. */ getClient(): SpiffCommerceClient; /** * State related to the design of the user. */ getCommandContext(): CommandContext; /** * Returns true when the user may only view the design. */ getIsReadOnly(): boolean; /** * Get the low level workflow amanager instance for this experience. Don't touch this unless you're willing to break things. */ getWorkflowManager(): WorkflowManager; /** * Returns the step matching a given name, undefined if not found. * @param id The id the step must match. */ getStepById(id: string): StepHandle<AnyStepData> | undefined; /** * Returns the step matching a given name, undefined if not found. * @param name The name the step must match. */ getStepByName(name: string): StepHandle<AnyStepData> | undefined; /** * Returns all steps matching a specific type in the workflow. These steps * may be across multiple scenes and may or may not be active based on condition state. */ getStepsByType(type: StepType): StepHandle<AnyStepData>[]; /** * Returns all steps that are children of a given scene. * @param scene The scene you want the steps for. */ getStepsByScene(scene: Scene): StepHandle<AnyStepData>[]; /** * Returns all steps in the workflow. Ordered by scene and appearance within their respective scenes. */ getSteps(): StepHandle<AnyStepData>[]; /** * Returns all steps in the workflow that are conditionally active. Ordered by scene and appearance within their respective scenes. */ getStepsConditionallyActive(): StepHandle<AnyStepData>[]; /** * Returns a list of scenes that are configured in the workflow. Each scene * contains a list of steps. See getStepsByScene to access these. */ getScenes(): Scene[]; /** * Returns the total cost in subunits for all selections made on the design. * @param disablePriceBreaks Whether to exclude price breaks from the calculation. */ getSelectionPriceSubunits(disablePriceBreaks?: boolean): number; /** * Returns the total cost in subunits for the base product. * @param includeAdditionalProduct When true the additional product cost will be included in the total (if configured). * @param disablePriceBreaks Whether to exclude price breaks from the calculation. */ getBasePriceSubunits(includeAdditionalProduct?: boolean, disablePriceBreaks?: boolean): number; /** * If an additional product is configured, returns the base price of that product. Returns undefined otherwise. * @param disablePriceBreaks Whether to exclude price breaks from the calculation. */ getAdditionalProductPriceSubunits(disablePriceBreaks?: boolean): number | undefined; /** * A convenience function returning the sum of the selection and base price values. * @param disablePriceBreaks Whether to exclude price breaks from the calculation. */ getTotalPriceSubunits(disablePriceBreaks?: boolean): number; /** * The price break percentage that is expected to be applied in price calculations. */ priceBreakToBeApplied(): number; /** * Calculates the price break and fires the "PriceBreakChanged" event if required. * This function is primarily intended for internal use. */ checkForPriceBreakChanges(): void; /** * Takes selections made by the user in another workflow and applies them to this workflow. For * selections to be copied they must both have a matching global property configuration. * @param experience The experience to take selections from. * @param filter A list of steps to apply the selections to. If undefined all steps will be updated. */ copySelectionsViaGlobalConfiguration(bundle: Bundle$1, experience: WorkflowExperience, filter?: StepHandle<AnyStepData>[]): Promise<void>; /** * Attach specific details about the customer to the experience. This is useful for things like retargeting. Currently only * email is supported. From SpiffCommerce hosted experiences these details will be attached whenever the customer has provided & given permission. * @param details The new customer details. Only email is supported. * @deprecated Use assignCustomerDetails instead. */ attachCustomerDetails(details: { /** * An email used for things like sending a design to the user. */ email: string; }): Promise<void>; /** * Attach specific details about the customer to the experience. This is useful for things like retargeting. * From SpiffCommerce hosted experiences these details will be attached whenever the customer has provided & given permission. * @param details The new customer details. */ assignCustomerDetails(details: CustomerDetailsInput): Promise<void>; /** * Attaches a listener to the scenes on a workflow experience. The scenes returned are a subset of the scenes configured in the * workflow and are based on the current state of the experience. This is useful for building a navigation menu. * @param cb The callback to be called when the scenes change. The new scenes are passed as an argument. */ attachRenderableSceneListener(cb: (scenes: RenderableScene[]) => void): void; /** * Detaches a listener from the scenes on a workflow experience. */ detachRenderableSceneListener(cb: (scenes: RenderableScene[]) => void): void; /** * Saves this experience to storage. This may be local or remote depending * on configuration. * @param title The title for the saved design. */ save(title: string): Promise<SavedDesign>; /** * Returns a copy of the currently loaded design as a new, seperated workflow experience with * a fresh transaction. */ copy(): Promise<WorkflowExperience>; /** * Creates a data URL preview for the current design. */ createPreviewImage(isThreeD?: boolean, resolution?: number): Promise<string>; /** * To be called when the workflow experience is considered completed by the user. * @param onProgressUpdate Progress callback for finalizing the design. Optional * @param capturePreviewImage When true a preview image will be generated for the design. Defaults to true. */ onDesignFinished(capturePreviewImage?: boolean): Promise<DesignCreationMessage>; /** * Returns the metadata associated with this workflow experience. * This is a combination of the metadata from the workflow, and the selections made by the user. * @returns An array of ExportedStepData objects, each containing the step ID, title, and properties. */ getExportedStepData(): ExportedStepData[]; /** * Get the quantity of this WorkflowExperience's Transaction. * @returns The amount that was, or will be, ordered. */ getQuantity(): number; /** * Sets the quantity of this WorkflowExperience's Transaction. * @throws {Error} if the WorkflowExperience is read-only. * @throws {RangeError} if the value is below 1. * @param quantity The amount that was, or will be, ordered. * @returns A promise that resolves when the Transaction has been updated on the server. */ setQuantity(quantity: number): Promise<void>; /** * Registers a callback function to be called when the specified event is raised. * TODO: We should include a second param to pass information about the event? * @param type The type of event to listen for. * @param callback The function to call when the event occurs. */ addEventListener(type: WorkflowExperienceEventType, callback: (workflowExperience: WorkflowExperience) => void): void; /** * Removes a previously registered callback. * @param type The type of event. * @param callback The function to remove. */ removeEventListener(type: WorkflowExperienceEventType, callback: (workflowExperience: WorkflowExperience) => void): void; attachAddress(streetAddress?: string, apartment?: string, city?: string, country?: string, state?: string, postCode?: string): Promise<void>; attachOrganization(name: string): Promise<void>; callEvent(type: WorkflowExperienceEventType): any; } type ExportedStepDataPropertyType = "selection" | "color" | "image" | "text"; interface ExportedStepDataProperty { type: ExportedStepDataPropertyType; value: string; priceModifier: number; } interface ExportedStepData { stepId: string; title: string; properties: ExportedStepDataProperty[]; } declare enum WorkflowExperienceEventType { PriceBreakChanged = "PriceBreakChanged", ProductChanged = "ProductChanged", QuantityChanged = "QuantityChanged", RecipientChanged = "RecipientChanged", SelectionChanged = "SelectionChanged" } declare class WorkflowExperienceImpl implements WorkflowExperience { readonly client: SpiffCommerceClient; readonly transaction: Transaction; readonly graphQlClient: GraphQlClientFunc; readonly workflowManager: WorkflowManager; readonly isReadOnly: boolean; readonly cachedStepHandles: Map<string, StepHandle<any>>; /** * Bundle this experience has been added to. */ private bundle?; private profanityList; private workflow?; private currentPriceBreak; private renderableScenes; private renderableSceneCallbacks; private eventCallbacks; constructor(client: SpiffCommerceClient, experienceOptions: ExperienceOptions); getTransaction(): Transaction; getProduct(): Product | undefined; getProfanityList(): string[]; setProduct(integrationProductId: string): Promise<void>; clearProduct(): Promise<void>; getWorkflow(): Workflow | undefined; setWorkflow(workflow: Workflow): Promise<void>; attachAddress(streetAddress?: string, apartment?: string, city?: string, country?: string, state?: string, postCode?: string): Promise<void>; attachOrganization(name: string): Promise<void>; getBundle(): Bundle$1 | undefined; setBundle(bundle: Bundle$1): void; getClient(): SpiffCommerceClient; getIsReadOnly(): boolean; getCommandContext(): CommandContext; getWorkflowManager(): WorkflowManager; createPreviewImage(isThreeD?: boolean, resolution?: number): Promise<string>;