@spiffcommerce/core 5.0.2 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -69,7 +69,7 @@ var t=require("@apollo/client"),e=require("lodash.clonedeep"),A=require("react/j
69
69
  `,sn=t.gql`
70
70
  mutation CreateAsset($name: String!, $type: String!, $mimeType: String!, $anonymous: Boolean) {
71
71
  assetCreate(name: $name, type: $type, mimeType: $mimeType, anonymous: $anonymous) {
72
- uploadUrl,
72
+ uploadUrl
73
73
  asset {
74
74
  name
75
75
  key
@@ -80,7 +80,7 @@ var t=require("@apollo/client"),e=require("lodash.clonedeep"),A=require("react/j
80
80
  }
81
81
  }
82
82
  }
83
- `,cn=async t=>(await en.getShadowGraphqlClient().query({query:an,errorPolicy:"all",fetchPolicy:"no-cache",variables:{keys:t}})).data.assets;const gn="persistentAssets";class ln{static add(t){if(!t.fileLink)return void console.error("Failed to find cdn link on asset, cannot persist!");const e=new Map;e.set(t.key||"",t.fileLink);const A=XA.getMap(gn);A&&A.forEach(((t,A)=>{e.set(A,t)})),XA.setMap(gn,e)}static remove(t){const e=XA.getMap(gn);if(!e)return;const A=Array.from(e.entries()).find((e=>e[0]===t));A&&(e.delete(A[0]),XA.setMap(gn,e))}static list(){const t=XA.getMap(gn);return t?Array.from(t.entries()).map((t=>({assetKey:t[0],src:t[1]}))):[]}}const Bn=new class{constructor(){An(this,"cache",new Map),An(this,"materialCache",new Map),An(this,"loadImageAsFileInfo",(async t=>{const e=await t.arrayBuffer(),A=await lA(e);return{name:t.name.substring(t.name.lastIndexOf("/")+1),blob:((t,e)=>{let A=atob(t.split(",")[1]),n=[];for(let t=0;t<A.length;t++)n.push(A.charCodeAt(t));return new Blob([new Uint8Array(n)],{type:e})})(A.dataUrl,t.type)}}))}async getLocalOrFromServer(t){if(this.cache.has(t)){const e=this.cache.get(t);if(!e)throw new OA("Failed to get asset from cache!");return e}const e=(async()=>(await cn([t]))[0])();return this.cache.set(t,e),e}async getMaterialLocalOrFromServer(t){if(this.materialCache.has(t))return this.materialCache.get(t);const e=(async()=>(await(async t=>(await en.getShadowGraphqlClient().query({query:rn,errorPolicy:"all",fetchPolicy:"no-cache",variables:{ids:t}})).data.materials)([t]))[0])();return this.materialCache.set(t,e),e}async uploadAssetWithProgress(t,e,A,n){const i=await this.dispatchCreateAssetRequest(t,e,n);if(!i)throw new Error("Failed to create asset.");return await new Promise(((e,n)=>{var a=new XMLHttpRequest;a.open("PUT",i.assetResponse.uploadUrl,!0),a.setRequestHeader("Content-Type",i.mimeType),a.setRequestHeader("Cache-Control","public,max-age=31536000,immutable"),a.upload.onprogress=t=>{t.lengthComputable&&A(100*t.loaded/t.total)},a.onload=()=>{const t=i.assetResponse.asset;ln.add(i.assetResponse.asset),e(t)},a.onerror=n,a.send(t.blob)})),i.assetResponse.asset}async uploadFile(t,e){const A=!("image/svg+xml"===t.type||"application/pdf"===t.type),n=A?z.Image:z.Illustration;if(A){const A=await this.loadImageAsFileInfo(t);return await this.uploadAssetWithProgress(A,n,e,!0)}{const A={name:t.name,blob:new Blob([t],{type:t.type})};return await Bn.uploadAssetWithProgress(A,n,e,!0)}}removePersistedAsset(t){ln.remove(t)}getPersistedAssets(){return ln.list()}async dispatchCreateAssetRequest(t,e,A){const n=t.blob.type?t.blob.type:this.guessMIME(t.name),i=await(async(t,e,A,n)=>(await en.getShadowGraphqlClient().mutate({mutation:sn,errorPolicy:"all",fetchPolicy:"no-cache",variables:{name:t,type:e,mimeType:A,anonymous:n}})).data?.assetCreate)(t.name,e,n,A);if(i)return{assetResponse:i,mimeType:n}}guessMIME(t){const e=t.split(".").pop();switch(e){case"glb":return"model/gltf-binary";case"ttf":return"font/ttf";case"mkv":return"video/x-matroska";default:throw new OA("Unexpected mimetype: "+e)}}};function wn(t,e,A){return(e=function(t){var e=function(t,e){if("object"!=typeof t||null===t)return t;var A=t[Symbol.toPrimitive];if(void 0!==A){var n=A.call(t,e||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"==typeof e?e:String(e)}(e))in t?Object.defineProperty(t,e,{value:A,enumerable:!0,configurable:!0,writable:!0}):t[e]=A,t}const hn=t.gql`
83
+ `,cn=async t=>(await en.getShadowGraphqlClient().query({query:an,errorPolicy:"all",fetchPolicy:"no-cache",variables:{keys:t}})).data.assets;const gn="persistentAssets";class ln{static add(t){if(!t.fileLink)return void console.error("Failed to find cdn link on asset, cannot persist!");const e=new Map;e.set(t.key||"",t.fileLink);const A=XA.getMap(gn);A&&A.forEach(((t,A)=>{e.set(A,t)})),XA.setMap(gn,e)}static remove(t){const e=XA.getMap(gn);if(!e)return;const A=Array.from(e.entries()).find((e=>e[0]===t));A&&(e.delete(A[0]),XA.setMap(gn,e))}static list(){const t=XA.getMap(gn);return t?Array.from(t.entries()).map((t=>({assetKey:t[0],src:t[1]}))):[]}}const Bn=new class{constructor(){An(this,"cache",new Map),An(this,"materialCache",new Map),An(this,"loadImageAsFileInfo",(async t=>{const e=await t.arrayBuffer(),A=await lA(e);return{name:t.name.substring(t.name.lastIndexOf("/")+1),blob:((t,e)=>{const A=atob(t.split(",")[1]),n=[];for(let t=0;t<A.length;t++)n.push(A.charCodeAt(t));return new Blob([new Uint8Array(n)],{type:e})})(A.dataUrl,t.type)}}))}async getLocalOrFromServer(t){if(this.cache.has(t)){const e=this.cache.get(t);if(!e)throw new OA("Failed to get asset from cache!");return e}const e=(async()=>(await cn([t]))[0])();return this.cache.set(t,e),e}async getMaterialLocalOrFromServer(t){if(this.materialCache.has(t))return this.materialCache.get(t);const e=(async()=>(await(async t=>(await en.getShadowGraphqlClient().query({query:rn,errorPolicy:"all",fetchPolicy:"no-cache",variables:{ids:t}})).data.materials)([t]))[0])();return this.materialCache.set(t,e),e}async uploadAssetWithProgress(t,e,A,n){const i=await this.dispatchCreateAssetRequest(t,e,n);if(!i)throw new Error("Failed to create asset.");return await new Promise(((e,n)=>{const a=new XMLHttpRequest;a.open("PUT",i.assetResponse.uploadUrl,!0),a.setRequestHeader("Content-Type",i.mimeType),a.setRequestHeader("Cache-Control","public,max-age=31536000,immutable"),a.upload.onprogress=t=>{t.lengthComputable&&A(100*t.loaded/t.total)},a.onload=()=>{const t=i.assetResponse.asset;ln.add(i.assetResponse.asset),e(t)},a.onerror=n,a.send(t.blob)})),i.assetResponse.asset}async uploadFile(t,e){const A=!("image/svg+xml"===t.type||"application/pdf"===t.type),n=A?z.Image:z.Illustration;if(A){const A=await this.loadImageAsFileInfo(t);return await this.uploadAssetWithProgress(A,n,e,!0)}{const A={name:t.name,blob:new Blob([t],{type:t.type})};return await Bn.uploadAssetWithProgress(A,n,e,!0)}}removePersistedAsset(t){ln.remove(t)}getPersistedAssets(){return ln.list()}async dispatchCreateAssetRequest(t,e,A){const n=t.blob.type?t.blob.type:this.guessMIME(t.name),i=await(async(t,e,A,n)=>(await en.getShadowGraphqlClient().mutate({mutation:sn,errorPolicy:"all",fetchPolicy:"no-cache",variables:{name:t,type:e,mimeType:A,anonymous:n}})).data?.assetCreate)(t.name,e,n,A);if(i)return{assetResponse:i,mimeType:n}}guessMIME(t){const e=t.split(".").pop();switch(e){case"glb":return"model/gltf-binary";case"ttf":return"font/ttf";case"mkv":return"video/x-matroska";default:throw new OA("Unexpected mimetype: "+e)}}};function wn(t,e,A){return(e=function(t){var e=function(t,e){if("object"!=typeof t||null===t)return t;var A=t[Symbol.toPrimitive];if(void 0!==A){var n=A.call(t,e||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"==typeof e?e:String(e)}(e))in t?Object.defineProperty(t,e,{value:A,enumerable:!0,configurable:!0,writable:!0}):t[e]=A,t}const hn=t.gql`
84
84
  fragment OptionFields on Option {
85
85
  id
86
86
  name
@@ -463,7 +463,7 @@ var t=require("@apollo/client"),e=require("lodash.clonedeep"),A=require("react/j
463
463
  }
464
464
  }
465
465
  }
466
- `,Qo=(t,e,A)=>{const n={};return e.steps.forEach((e=>{Object.assign(n,(e=>{const n={};if("Frame"===e.type){const i=t[e.stepName],a=e.data;if(!i||a.hideImageInCart&&A)return n;n[`${e.stepTitle} image`]=i.image}if("Illustration"===e.type){const i=t[e.stepName],a=e.data;if(!i||a.hideColorsInCart&&A||!i.colors)return n;if(i.colors.length>0){const t=i.colors.join(", ").toUpperCase();n[`${e.stepTitle} colors`]=t}}if("Module"===e.type){const i=t[e.stepName],a=e.data;if(!i||a.hideTextInCart&&A)return n;n[`${e.stepTitle} text`]=i.text}if("Text"===e.type){const i=t[e.stepName];if(!i)return n;const a=e.data;a.hideTextInCart&&A||(n[`${e.stepTitle} text`]=i.text),!i.color||a.hideColorInCart&&A||(n[`${e.stepTitle} color`]=i.color)}return n})(e))})),n},Co=(t,e,A,n,i,a,o,r,s)=>{const c={event:"onComplete",lineItemImageUrl:o||"",transactionId:t.id,designProductVariantId:t.externalDesignProductVariantId,designProductId:t.externalDesignProductId,externalCartProductId:t.externalCartProductId,externalCartProductVariantId:t.externalCartProductVariantId,baseCost:A,weight:e.weight,optionsCost:n,exportedData:a,workflowViewerLink:t.workflowViewerLink||"",workflowViewerReadOnlyLink:t.workflowViewerReadOnlyLink||""};return i&&(c.metadata=i),r&&(c.selectedVariants=r),s&&(c.sku=s),c},mo=async(t,e,A,n,i,a,o)=>{const r=t.product?.basePrice||0,s=t.priceModifierTotal||0,c=((t,e,A,n)=>{const i={};let a;if(A){a=Qo(A,e,!1);for(const t of Object.keys(a))i[t]={value:a[t],priceModifier:0}}else if(n){a=n;for(const t of Object.keys(a))i[t]={value:a[t],priceModifier:0}}for(const A of Object.keys(t)){const n=t[A],a=e.steps.find((t=>t.stepTitle===A));if(1===n.length)i[`${a?.stepTitle} selection`]={value:n[0].name,priceModifier:n[0].priceModifier};else if(n.length>1)for(let t=0;t<n.length;t++)i[`${a?.stepTitle} selection ${t+1}`]={value:n[t].name,priceModifier:n[t].priceModifier}}return i})(n,A,void 0,a);return Co(t,e,r,s,a,c,o,n,i)},po=async(t,e,A,n,i,a,o,r,s,c,g,l,B)=>{s("workflow.steps.finish.finalize.buildingLayouts"),await t.outstandingRequestsPromise();const w=en.getShadowGraphqlClient();await w.resetStore();const h=await w.query({query:ha,variables:{id:a.id},errorPolicy:"all"}),d=h.data?.transactions[0].workflowState;!h.errors&&d||(console.warn("State mismatch detected. Uploading known state explicitly"),console.warn("State Object:",JSON.stringify(n())),h.errors&&h.errors.forEach((t=>{h.errors&&console.log("Server Error:",t.message)})),await t.updateStateWithServerImmediate(n),console.log("Server state is undefined @ Workflow completion"));const E=t.getPreviewService(),u=e?.finalizeStepConfig?.lookAtAnimation,Q=E&&100===E.getSceneInitializationProgress()&&e.showModelOnFinishStep&&!!u,C=B&&Qo(B,e,!0),m=B&&Qo(B,e,!1),p=async t=>{const A={};let n=0;if(Object.keys(o).length>0)for(const i of Object.keys(o)){const a=o[i],r=e.steps.find((t=>t.stepName===i));for(let e=0;e<a.selections.length;++e){const i=a.selections[e];if(r&&(!t||r.option&&(r.option.variants||[]).length>1&&!r.data.hideSelectionInCart&&!r.data.hideSelectionsInCart)){const t=r.stepTitle;A[t]?A[t].push({id:i.id||"",name:i.name,priceModifier:i.priceModifier}):A[t]=[{id:i.id||"",name:i.name,priceModifier:i.priceModifier}]}n+=i.priceModifier}}return[A,n]},[f]=await p(!0),D=Object.fromEntries(Object.keys(f).map((t=>[t,f[t].map((t=>t.id))]))),[I]=await p(!1),y=Object.fromEntries(Object.keys(I).map((t=>[t,I[t].map((t=>t.id))]))),M=await l(Q);s("workflow.steps.finish.finalize.creatingDesign"),a.bulk&&await c(g);const x=await(async t=>(await en.getShadowGraphqlClient().mutate({mutation:uo,errorPolicy:"all",fetchPolicy:"no-cache",variables:{name:t.name,layouts:t.layouts,workflowId:t.workflowId,transactionId:t.transactionId,previewImage:t.previewImage,useThreeDimPreview:t.useThreeDimPreview,metadata:t.metadata,selectedVariants:t.selectedVariants}})).data?.designCreate)((()=>{const t={name:r,layouts:A.map((t=>({index:t.index,panelId:t.panelId}))),workflowId:e.id,transactionId:a.id,useThreeDimPreview:Q,previewImage:M};if(m){const e=[];for(const[t,A]of Object.entries(m))e.push({key:t,value:A});t.metadata=e}if(D){const e=[];for(const[t,A]of Object.entries(y))e.push({key:t,ids:A});t.selectedVariants=e}return t})()),F=x?.transaction?.previewImageLink;s("workflow.steps.finish.finalize.updatingTransaction");const Y=(await en.getShadowGraphqlClient().query({query:wa,variables:{id:a.id}})).data.transactions[0];return a.bulk?((t,e,A)=>{const n=(t.product?.basePrice||0)*(t.variationsCount||0),i=t.priceModifierTotal||0,a={items:{value:t.variationsCount?`${t.variationsCount}`:"0",priceModifier:0}};return Co(t,e,n,i,void 0,a,A)})(Y,i,F):await mo(Y,i,e,f,x?.sku,C,F)};let fo;var Do;(Do=fo||(fo={})).Local="Local",Do.Remote="Remote";const Io=new class{constructor(){Eo(this,"localPersistenceKey","designTransactions"),Eo(this,"storageMethod",fo.Local),Eo(this,"designSavedListeners",[])}attachSaveListener(t){this.designSavedListeners.push(t)}detachSaveListener(t){this.designSavedListeners=this.designSavedListeners.filter((e=>e!==t))}async getSavedDesigns(){return await this.getDesigns()}async getSavedDesignByTransaction(t){return(await this.getSavedDesigns()).find((e=>e.transactionId===t))}async addDesign(t){const e=(await this.getSavedDesigns()).filter((e=>e.transactionId!==t.transactionId));e.unshift(t),await this.setDesigns(e),this.notifyDesignSaved(t)}async removeDesign(t){const e=await this.getSavedDesigns();await this.setDesigns(e.filter((e=>e.transactionId!==t)))}async setDesigns(t){if(this.storageMethod!==fo.Local)throw new OA("Unexpected storage method requested");XA.set(this.localPersistenceKey,JSON.stringify(t))}async getDesigns(){if(this.storageMethod===fo.Local){const t=XA.get(this.localPersistenceKey);return t?JSON.parse(t):[]}throw new OA("Unexpected storage method requested")}notifyDesignSaved(t){this.designSavedListeners.forEach((e=>e(t)))}};function yo(t,e,A){return(e=function(t){var e=function(t,e){if("object"!=typeof t||null===t)return t;var A=t[Symbol.toPrimitive];if(void 0!==A){var n=A.call(t,e||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"==typeof e?e:String(e)}(e))in t?Object.defineProperty(t,e,{value:A,enumerable:!0,configurable:!0,writable:!0}):t[e]=A,t}class Mo{constructor(t,e){if(yo(this,"client",void 0),yo(this,"commandContext",void 0),yo(this,"workflowManager",void 0),yo(this,"isReadOnly",void 0),yo(this,"renderableScenes",[]),yo(this,"renderableSceneCallbacks",[]),yo(this,"debouncedSavedDesignUpdate",I(p)((async()=>{await Io.getSavedDesignByTransaction(this.getWorkflowManager().getTransaction().id)&&this.save()}),2500)),yo(this,"getCanvasObjectURLAsync",(async t=>new Promise(((e,A)=>{try{t.toBlob((t=>{if(t){const A=URL.createObjectURL(t);e(A)}}))}catch(t){A(t)}})))),!e.workflow)throw new Error("No Workflow ID provided.");this.client=t;const A=e.layouts;this.commandContext=new Me,this.commandContext.initialize(A,e.reloadedState),this.isReadOnly=!!e.transaction.lineItem?.id||!XA.getMap("transactionOwnerIds")?.get(e.transaction.id)||!!e.readOnly,this.workflowManager=new $a(e.workflow,e.product.profanities?.map((t=>t.word))||[],A,this.commandContext,(t=>{try{this.debouncedSavedDesignUpdate()}catch{console.error("Failed to update saved design details.")}return e.stateMutationFunc(t)}),e.transaction,e.product,e.previewService,e.renderableContextService,e.reloadedState,e.readOnly),this.workflowManager.addSelectionCallback((t=>{const e=t.traversableScenes.map((t=>{const e=t.renderableSteps.map((t=>t.stepName));return{id:t.name,title:t.title,renderableSteps:e}}));this.renderableScenes=e,this.renderableSceneCallbacks.forEach((t=>t(e)))}))}getClient(){return this.client}getIsReadOnly(){return this.isReadOnly}getCommandContext(){return this.commandContext}getWorkflowManager(){return this.workflowManager}async updateVariationRecords(t){await en.getShadowGraphqlClient().mutate({mutation:Ba,variables:{transactionId:this.workflowManager.getTransaction().id,updates:t.map((t=>({recordNumber:t.recordNumber,values:t.values.map((t=>({aspect:t.aspect,stepName:t.stepName,value:t.value})))})))}})}async createPreviewImage(t,e){const A=this.workflowManager.getWorkflow(),n=A?.finalizeStepConfig?.lookAtAnimation;if(t){if(!n)throw new Error("Failed to generate cart preview image!");return await(this.workflowManager.getPreviewService()?.renderSceneScreenshot(512,n))||""}const i=document.createElement("canvas");let a=2048;e&&e<=2048&&(a=e),i.width=a,i.height=a;const o=this.commandContext.getAllLayouts(),r=A.defaultPreviewPanelIndex||0,s=A.panels[r],c=o.find((t=>t.layoutState?.layout.panelId===s?.name))||o[0],g=c.layoutState.layout.previewRegion?{x:c.layoutState.layout.previewRegion.left,y:c.layoutState.layout.previewRegion.top,width:c.layoutState.layout.previewRegion.width,height:c.layoutState.layout.previewRegion.height}:{x:0,y:0,width:c.layoutState.layout.width,height:c.layoutState.layout.height},l=this.commandContext.getLayoutById(c.layoutState.layout.id),w=i.getContext("2d");if(!w)throw new jA("Failed to obtain 2D context for preview image creation");const h=Fe(l.layoutState.layout,l.layoutState.elements,{renderingConfiguration:{purpose:H.Print,region:{left:g.x,top:g.y,width:g.width,height:g.height}}}),d=I(Q).renderToStaticMarkup(h),E=await B.Canvg.from(w,d,{anonymousCrossOrigin:!0,ignoreDimensions:!1});await E.render();const u=await this.getCanvasObjectURLAsync(i);return i.toDataURL(u)}getStepById(t){const e=this.getWorkflowManager().getWorkflow().steps.find((e=>e.stepName===t));if(e&&this.stepHasHandle(e))return ho.get(this.getWorkflowManager(),e)}getSteps(){return this.getScenes().flatMap((t=>this.getStepsByScene(t)))}getScenes(){return this.getWorkflowManager().getWorkflow().stepGroups.map((t=>({id:t.id,name:t.name,stepIds:t.stepNames})))}getBulkStep(){if(this.getWorkflowManager().getTransaction().bulk){const t=this.getWorkflowManager().getProduct().bulkConfiguration,e={type:K.Bulk,stepName:"Bulk",stepTitle:t?.stepTitle??"workflow.steps.bulk.title",helpText:t?.helpText,data:{aspects:da(this.getWorkflowManager().getWorkflow())},conditions:[]};return ho.get(this.getWorkflowManager(),e)}}getStepByName(t){const e=this.getWorkflowManager().getWorkflow().steps.find((e=>e.stepTitle===t));if(e&&this.stepHasHandle(e))return ho.get(this.getWorkflowManager(),e)}getStepsByType(t){return this.getWorkflowManager().getWorkflow().steps.filter((e=>e.type===t)).map((t=>ho.get(this.getWorkflowManager(),t)))}getStepsByScene(t){if(!this.getWorkflowManager().getWorkflow().stepGroups.find((e=>e.name===t.name)))throw new Error("Given scene is not present on workflow! Be careful when persisting scenes that you only use them with the relevant workflow.");return t.stepIds.map((t=>this.getWorkflowManager().getWorkflow().steps.find((e=>e.stepName===t)))).filter((t=>this.stepHasHandle(t))).map((t=>ho.get(this.getWorkflowManager(),t)))}async attachCustomerDetails(t){return this.assignCustomerDetails({emailAddress:t.email})}async assignCustomerDetails(t){await en.getShadowGraphqlClient().mutate({mutation:io,variables:{id:this.getWorkflowManager().getTransaction().id,details:t,type:"Owner"}}),this.getWorkflowManager().setTransactionCustomer(t)}attachRenderableSceneListener(t){this.renderableSceneCallbacks.push(t),t(this.renderableScenes)}detachRenderableSceneListener(t){this.renderableSceneCallbacks=this.renderableSceneCallbacks.filter((e=>e!==t))}async save(t){if(!this.getCommandContext().getState())throw new OA("State undefined!");const e={title:await(async()=>{if(t)return t;const e=this.getWorkflowManager().getTransaction().id,A=(await Io.getSavedDesigns()).find((t=>t.transactionId===e))?.title;return A||"My design"})(),thumbnail:await this.createPreviewImage(!1,256),transactionId:this.getWorkflowManager().getTransaction().id,productId:this.getWorkflowManager().getProduct().id,integrationProductId:this.getWorkflowManager().getTransaction().integrationProduct.id,workflowName:this.getWorkflowManager().getWorkflow().name,workflowId:this.getWorkflowManager().getWorkflow().id,lastEdited:new Date};return await Io.addDesign(e),e}async copy(){const t=I(e)(this.getCommandContext().getState());if(!t)throw new OA("Internal state is undefined! Cannot copy experience!");const A=JSON.stringify(t.transaction),n=this.getWorkflowManager().getWorkflow(),i=new Ro({}),a=this.getWorkflowManager().getTransaction().integrationProduct?.id;if(!a)throw new OA("Integration product id is undefined!");await i.initFromIntegrationProduct(a);return await i.getWorkflowExperience(n.id,A,void 0)}async onDesignFinished(t){return po(this.workflowManager,this.workflowManager.getWorkflow(),this.workflowManager.getLayouts(),(()=>this.commandContext.getState()),this.workflowManager.getProduct(),this.workflowManager.getTransaction(),this.workflowManager.getWorkflowSelections(),this.workflowManager.getWorkflow().name,t||(()=>{}),(t=>this.updateVariationRecords(t)),this.workflowManager.getVariationRecords(),(t=>this.createPreviewImage(t)),this.workflowManager.getWorkflowMetadata())}stepHasHandle(t){return t.type!==K.SilentIllustration&&t.type!==K.ProductOverlay}getExportedData(){const t=new Map,e=this.getWorkflowManager().getWorkflowMetadata(),A=this.getWorkflowManager().getWorkflowSelections();return Object.keys(e).forEach((A=>{const n=this.workflowManager.getWorkflow().steps.find((t=>t.stepName===A));if(!n)return;t.has(n.stepTitle)||t.set(n.stepTitle,{});const i=e[A];Object.keys(i).forEach((e=>{t.get(n.stepTitle)[e]=i[e]}))})),Object.keys(A)?.forEach((e=>{const n=this.workflowManager.getWorkflow().steps.find((t=>t.stepName===e));n&&(t.has(n.stepTitle)||t.set(n.stepTitle,{}),t.get(n.stepTitle).selection=A[e].selections[0].name)})),t}}function xo(t,e,A){return(e=function(t){var e=function(t,e){if("object"!=typeof t||null===t)return t;var A=t[Symbol.toPrimitive];if(void 0!==A){var n=A.call(t,e||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"==typeof e?e:String(e)}(e))in t?Object.defineProperty(t,e,{value:A,enumerable:!0,configurable:!0,writable:!0}):t[e]=A,t}const Fo=t.gql`
466
+ `,Qo=(t,e,A)=>{const n={};return e.steps.forEach((e=>{Object.assign(n,(e=>{const n={};if("Frame"===e.type){const i=t[e.stepName],a=e.data;if(!i||a.hideImageInCart&&A)return n;n[`${e.stepTitle} image`]=i.image}if("Illustration"===e.type){const i=t[e.stepName],a=e.data;if(!i||a.hideColorsInCart&&A||!i.colors)return n;if(i.colors.length>0){const t=i.colors.join(", ").toUpperCase();n[`${e.stepTitle} colors`]=t}}if("Module"===e.type){const i=t[e.stepName],a=e.data;if(!i||a.hideTextInCart&&A)return n;n[`${e.stepTitle} text`]=i.text}if("Text"===e.type){const i=t[e.stepName];if(!i)return n;const a=e.data;a.hideTextInCart&&A||(n[`${e.stepTitle} text`]=i.text),!i.color||a.hideColorInCart&&A||(n[`${e.stepTitle} color`]=i.color)}return n})(e))})),n},Co=(t,e,A,n,i,a,o,r,s)=>{const c=(XA.getMap("transactionOwnerIds")||new Map).get(t.id),g={event:"onComplete",lineItemImageUrl:o||"",transactionId:t.id,designProductVariantId:t.externalDesignProductVariantId,designProductId:t.externalDesignProductId,externalCartProductId:t.externalCartProductId,externalCartProductVariantId:t.externalCartProductVariantId,baseCost:A,weight:e.weight,optionsCost:n,exportedData:a,workflowViewerLink:t.workflowViewerLink||"",workflowViewerReadOnlyLink:t.workflowViewerReadOnlyLink||"",transactionOwnerId:c};return i&&(g.metadata=i),r&&(g.selectedVariants=r),s&&(g.sku=s),g},mo=async(t,e,A,n,i,a,o)=>{const r=t.product?.basePrice||0,s=t.priceModifierTotal||0,c=((t,e,A,n)=>{const i={};let a;if(A){a=Qo(A,e,!1);for(const t of Object.keys(a))i[t]={value:a[t],priceModifier:0}}else if(n){a=n;for(const t of Object.keys(a))i[t]={value:a[t],priceModifier:0}}for(const A of Object.keys(t)){const n=t[A],a=e.steps.find((t=>t.stepTitle===A));if(1===n.length)i[`${a?.stepTitle} selection`]={value:n[0].name,priceModifier:n[0].priceModifier};else if(n.length>1)for(let t=0;t<n.length;t++)i[`${a?.stepTitle} selection ${t+1}`]={value:n[t].name,priceModifier:n[t].priceModifier}}return i})(n,A,void 0,a);return Co(t,e,r,s,a,c,o,n,i)},po=async(t,e,A,n,i,a,o,r,s,c,g,l,B)=>{s("workflow.steps.finish.finalize.buildingLayouts"),await t.outstandingRequestsPromise();const w=en.getShadowGraphqlClient();await w.resetStore();const h=await w.query({query:ha,variables:{id:a.id},errorPolicy:"all"}),d=h.data?.transactions[0].workflowState;!h.errors&&d||(console.warn("State mismatch detected. Uploading known state explicitly"),console.warn("State Object:",JSON.stringify(n())),h.errors&&h.errors.forEach((t=>{h.errors&&console.log("Server Error:",t.message)})),await t.updateStateWithServerImmediate(n),console.log("Server state is undefined @ Workflow completion"));const E=t.getPreviewService(),u=e?.finalizeStepConfig?.lookAtAnimation,Q=E&&100===E.getSceneInitializationProgress()&&e.showModelOnFinishStep&&!!u,C=B&&Qo(B,e,!0),m=B&&Qo(B,e,!1),p=async t=>{const A={};let n=0;if(Object.keys(o).length>0)for(const i of Object.keys(o)){const a=o[i],r=e.steps.find((t=>t.stepName===i));for(let e=0;e<a.selections.length;++e){const i=a.selections[e];if(r&&(!t||r.option&&(r.option.variants||[]).length>1&&!r.data.hideSelectionInCart&&!r.data.hideSelectionsInCart)){const t=r.stepTitle;A[t]?A[t].push({id:i.id||"",name:i.name,priceModifier:i.priceModifier}):A[t]=[{id:i.id||"",name:i.name,priceModifier:i.priceModifier}]}n+=i.priceModifier}}return[A,n]},[f]=await p(!0),D=Object.fromEntries(Object.keys(f).map((t=>[t,f[t].map((t=>t.id))]))),[I]=await p(!1),y=Object.fromEntries(Object.keys(I).map((t=>[t,I[t].map((t=>t.id))]))),M=await l(Q);s("workflow.steps.finish.finalize.creatingDesign"),a.bulk&&await c(g);const x=await(async t=>(await en.getShadowGraphqlClient().mutate({mutation:uo,errorPolicy:"all",fetchPolicy:"no-cache",variables:{name:t.name,layouts:t.layouts,workflowId:t.workflowId,transactionId:t.transactionId,previewImage:t.previewImage,useThreeDimPreview:t.useThreeDimPreview,metadata:t.metadata,selectedVariants:t.selectedVariants}})).data?.designCreate)((()=>{const t={name:r,layouts:A.map((t=>({index:t.index,panelId:t.panelId}))),workflowId:e.id,transactionId:a.id,useThreeDimPreview:Q,previewImage:M};if(m){const e=[];for(const[t,A]of Object.entries(m))e.push({key:t,value:A});t.metadata=e}if(D){const e=[];for(const[t,A]of Object.entries(y))e.push({key:t,ids:A});t.selectedVariants=e}return t})()),F=x?.transaction?.previewImageLink;s("workflow.steps.finish.finalize.updatingTransaction");const Y=(await en.getShadowGraphqlClient().query({query:wa,variables:{id:a.id}})).data.transactions[0];return a.bulk?((t,e,A)=>{const n=(t.product?.basePrice||0)*(t.variationsCount||0),i=t.priceModifierTotal||0,a={items:{value:t.variationsCount?`${t.variationsCount}`:"0",priceModifier:0}};return Co(t,e,n,i,void 0,a,A)})(Y,i,F):await mo(Y,i,e,f,x?.sku,C,F)};let fo;var Do;(Do=fo||(fo={})).Local="Local",Do.Remote="Remote";const Io=new class{constructor(){Eo(this,"localPersistenceKey","designTransactions"),Eo(this,"storageMethod",fo.Local),Eo(this,"designSavedListeners",[])}attachSaveListener(t){this.designSavedListeners.push(t)}detachSaveListener(t){this.designSavedListeners=this.designSavedListeners.filter((e=>e!==t))}async getSavedDesigns(){return await this.getDesigns()}async getSavedDesignByTransaction(t){return(await this.getSavedDesigns()).find((e=>e.transactionId===t))}async addDesign(t){const e=(await this.getSavedDesigns()).filter((e=>e.transactionId!==t.transactionId));e.unshift(t),await this.setDesigns(e),this.notifyDesignSaved(t)}async removeDesign(t){const e=await this.getSavedDesigns();await this.setDesigns(e.filter((e=>e.transactionId!==t)))}async setDesigns(t){if(this.storageMethod!==fo.Local)throw new OA("Unexpected storage method requested");XA.set(this.localPersistenceKey,JSON.stringify(t))}async getDesigns(){if(this.storageMethod===fo.Local){const t=XA.get(this.localPersistenceKey);return t?JSON.parse(t):[]}throw new OA("Unexpected storage method requested")}notifyDesignSaved(t){this.designSavedListeners.forEach((e=>e(t)))}};function yo(t,e,A){return(e=function(t){var e=function(t,e){if("object"!=typeof t||null===t)return t;var A=t[Symbol.toPrimitive];if(void 0!==A){var n=A.call(t,e||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"==typeof e?e:String(e)}(e))in t?Object.defineProperty(t,e,{value:A,enumerable:!0,configurable:!0,writable:!0}):t[e]=A,t}class Mo{constructor(t,e){if(yo(this,"client",void 0),yo(this,"commandContext",void 0),yo(this,"workflowManager",void 0),yo(this,"isReadOnly",void 0),yo(this,"renderableScenes",[]),yo(this,"renderableSceneCallbacks",[]),yo(this,"debouncedSavedDesignUpdate",I(p)((async()=>{await Io.getSavedDesignByTransaction(this.getWorkflowManager().getTransaction().id)&&this.save()}),2500)),yo(this,"getCanvasObjectURLAsync",(async t=>new Promise(((e,A)=>{try{t.toBlob((t=>{if(t){const A=URL.createObjectURL(t);e(A)}}))}catch(t){A(t)}})))),!e.workflow)throw new Error("No Workflow ID provided.");this.client=t;const A=e.layouts;this.commandContext=new Me,this.commandContext.initialize(A,e.reloadedState),this.isReadOnly=!!e.transaction.lineItem?.id||!XA.getMap("transactionOwnerIds")?.get(e.transaction.id)||!!e.readOnly,this.workflowManager=new $a(e.workflow,e.product.profanities?.map((t=>t.word))||[],A,this.commandContext,(t=>{try{this.debouncedSavedDesignUpdate()}catch{console.error("Failed to update saved design details.")}return e.stateMutationFunc(t)}),e.transaction,e.product,e.previewService,e.renderableContextService,e.reloadedState,e.readOnly),this.workflowManager.addSelectionCallback((t=>{const e=t.traversableScenes.map((t=>{const e=t.renderableSteps.map((t=>t.stepName));return{id:t.name,title:t.title,renderableSteps:e}}));this.renderableScenes=e,this.renderableSceneCallbacks.forEach((t=>t(e)))}))}getClient(){return this.client}getIsReadOnly(){return this.isReadOnly}getCommandContext(){return this.commandContext}getWorkflowManager(){return this.workflowManager}async updateVariationRecords(t){await en.getShadowGraphqlClient().mutate({mutation:Ba,variables:{transactionId:this.workflowManager.getTransaction().id,updates:t.map((t=>({recordNumber:t.recordNumber,values:t.values.map((t=>({aspect:t.aspect,stepName:t.stepName,value:t.value})))})))}})}async createPreviewImage(t,e){const A=this.workflowManager.getWorkflow(),n=A?.finalizeStepConfig?.lookAtAnimation;if(t){if(!n)throw new Error("Failed to generate cart preview image!");return await(this.workflowManager.getPreviewService()?.renderSceneScreenshot(512,n))||""}const i=document.createElement("canvas");let a=2048;e&&e<=2048&&(a=e),i.width=a,i.height=a;const o=this.commandContext.getAllLayouts(),r=A.defaultPreviewPanelIndex||0,s=A.panels[r],c=o.find((t=>t.layoutState?.layout.panelId===s?.name))||o[0],g=c.layoutState.layout.previewRegion?{x:c.layoutState.layout.previewRegion.left,y:c.layoutState.layout.previewRegion.top,width:c.layoutState.layout.previewRegion.width,height:c.layoutState.layout.previewRegion.height}:{x:0,y:0,width:c.layoutState.layout.width,height:c.layoutState.layout.height},l=this.commandContext.getLayoutById(c.layoutState.layout.id),w=i.getContext("2d");if(!w)throw new jA("Failed to obtain 2D context for preview image creation");const h=Fe(l.layoutState.layout,l.layoutState.elements,{renderingConfiguration:{purpose:H.Print,region:{left:g.x,top:g.y,width:g.width,height:g.height}}}),d=I(Q).renderToStaticMarkup(h),E=await B.Canvg.from(w,d,{anonymousCrossOrigin:!0,ignoreDimensions:!1});await E.render();const u=await this.getCanvasObjectURLAsync(i);return i.toDataURL(u)}getStepById(t){const e=this.getWorkflowManager().getWorkflow().steps.find((e=>e.stepName===t));if(e&&this.stepHasHandle(e))return ho.get(this.getWorkflowManager(),e)}getSteps(){return this.getScenes().flatMap((t=>this.getStepsByScene(t)))}getScenes(){return this.getWorkflowManager().getWorkflow().stepGroups.map((t=>({id:t.id,name:t.name,stepIds:t.stepNames})))}getBulkStep(){if(this.getWorkflowManager().getTransaction().bulk){const t=this.getWorkflowManager().getProduct().bulkConfiguration,e={type:K.Bulk,stepName:"Bulk",stepTitle:t?.stepTitle??"workflow.steps.bulk.title",helpText:t?.helpText,data:{aspects:da(this.getWorkflowManager().getWorkflow())},conditions:[]};return ho.get(this.getWorkflowManager(),e)}}getStepByName(t){const e=this.getWorkflowManager().getWorkflow().steps.find((e=>e.stepTitle===t));if(e&&this.stepHasHandle(e))return ho.get(this.getWorkflowManager(),e)}getStepsByType(t){return this.getWorkflowManager().getWorkflow().steps.filter((e=>e.type===t)).map((t=>ho.get(this.getWorkflowManager(),t)))}getStepsByScene(t){if(!this.getWorkflowManager().getWorkflow().stepGroups.find((e=>e.name===t.name)))throw new Error("Given scene is not present on workflow! Be careful when persisting scenes that you only use them with the relevant workflow.");return t.stepIds.map((t=>this.getWorkflowManager().getWorkflow().steps.find((e=>e.stepName===t)))).filter((t=>this.stepHasHandle(t))).map((t=>ho.get(this.getWorkflowManager(),t)))}async attachCustomerDetails(t){return this.assignCustomerDetails({emailAddress:t.email})}async assignCustomerDetails(t){await en.getShadowGraphqlClient().mutate({mutation:io,variables:{id:this.getWorkflowManager().getTransaction().id,details:t,type:"Owner"}}),this.getWorkflowManager().setTransactionCustomer(t)}attachRenderableSceneListener(t){this.renderableSceneCallbacks.push(t),t(this.renderableScenes)}detachRenderableSceneListener(t){this.renderableSceneCallbacks=this.renderableSceneCallbacks.filter((e=>e!==t))}async save(t){if(!this.getCommandContext().getState())throw new OA("State undefined!");const e={title:await(async()=>{if(t)return t;const e=this.getWorkflowManager().getTransaction().id,A=(await Io.getSavedDesigns()).find((t=>t.transactionId===e))?.title;return A||"My design"})(),thumbnail:await this.createPreviewImage(!1,256),transactionId:this.getWorkflowManager().getTransaction().id,productId:this.getWorkflowManager().getProduct().id,integrationProductId:this.getWorkflowManager().getTransaction().integrationProduct.id,workflowName:this.getWorkflowManager().getWorkflow().name,workflowId:this.getWorkflowManager().getWorkflow().id,lastEdited:new Date};return await Io.addDesign(e),e}async copy(){const t=I(e)(this.getCommandContext().getState());if(!t)throw new OA("Internal state is undefined! Cannot copy experience!");const A=JSON.stringify(t.transaction),n=this.getWorkflowManager().getWorkflow(),i=new Ro({}),a=this.getWorkflowManager().getTransaction().integrationProduct?.id;if(!a)throw new OA("Integration product id is undefined!");await i.initFromIntegrationProduct(a);return await i.getWorkflowExperience(n.id,A,void 0)}async onDesignFinished(t){return po(this.workflowManager,this.workflowManager.getWorkflow(),this.workflowManager.getLayouts(),(()=>this.commandContext.getState()),this.workflowManager.getProduct(),this.workflowManager.getTransaction(),this.workflowManager.getWorkflowSelections(),this.workflowManager.getWorkflow().name,t||(()=>{}),(t=>this.updateVariationRecords(t)),this.workflowManager.getVariationRecords(),(t=>this.createPreviewImage(t)),this.workflowManager.getWorkflowMetadata())}stepHasHandle(t){return t.type!==K.SilentIllustration&&t.type!==K.ProductOverlay}getExportedData(){const t=new Map,e=this.getWorkflowManager().getWorkflowMetadata(),A=this.getWorkflowManager().getWorkflowSelections();return Object.keys(e).forEach((A=>{const n=this.workflowManager.getWorkflow().steps.find((t=>t.stepName===A));if(!n)return;t.has(n.stepTitle)||t.set(n.stepTitle,{});const i=e[A];Object.keys(i).forEach((e=>{t.get(n.stepTitle)[e]=i[e]}))})),Object.keys(A)?.forEach((e=>{const n=this.workflowManager.getWorkflow().steps.find((t=>t.stepName===e));n&&(t.has(n.stepTitle)||t.set(n.stepTitle,{}),t.get(n.stepTitle).selection=A[e].selections[0].name)})),t}}function xo(t,e,A){return(e=function(t){var e=function(t,e){if("object"!=typeof t||null===t)return t;var A=t[Symbol.toPrimitive];if(void 0!==A){var n=A.call(t,e||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"==typeof e?e:String(e)}(e))in t?Object.defineProperty(t,e,{value:A,enumerable:!0,configurable:!0,writable:!0}):t[e]=A,t}const Fo=t.gql`
467
467
  fragment RegionFields on Region {
468
468
  width
469
469
  top
package/dist/module.js CHANGED
@@ -69,7 +69,7 @@ import{CommandContext as A,AssetType as t,BringForwardCommand as e,BringToFrontC
69
69
  `,pt=pA`
70
70
  mutation CreateAsset($name: String!, $type: String!, $mimeType: String!, $anonymous: Boolean) {
71
71
  assetCreate(name: $name, type: $type, mimeType: $mimeType, anonymous: $anonymous) {
72
- uploadUrl,
72
+ uploadUrl
73
73
  asset {
74
74
  name
75
75
  key
@@ -80,7 +80,7 @@ import{CommandContext as A,AssetType as t,BringForwardCommand as e,BringToFrontC
80
80
  }
81
81
  }
82
82
  }
83
- `,It=async A=>(await ht.getShadowGraphqlClient().query({query:ut,errorPolicy:"all",fetchPolicy:"no-cache",variables:{keys:A}})).data.assets;const ft="persistentAssets";class Mt{static add(A){if(!A.fileLink)return void console.error("Failed to find cdn link on asset, cannot persist!");const t=new Map;t.set(A.key||"",A.fileLink);const e=gt.getMap(ft);e&&e.forEach(((A,e)=>{t.set(e,A)})),gt.setMap(ft,t)}static remove(A){const t=gt.getMap(ft);if(!t)return;const e=Array.from(t.entries()).find((t=>t[0]===A));e&&(t.delete(e[0]),gt.setMap(ft,t))}static list(){const A=gt.getMap(ft);return A?Array.from(A.entries()).map((A=>({assetKey:A[0],src:A[1]}))):[]}}const yt=new class{constructor(){Qt(this,"cache",new Map),Qt(this,"materialCache",new Map),Qt(this,"loadImageAsFileInfo",(async A=>{const t=await A.arrayBuffer(),e=await S(t);return{name:A.name.substring(A.name.lastIndexOf("/")+1),blob:((A,t)=>{let e=atob(A.split(",")[1]),n=[];for(let A=0;A<e.length;A++)n.push(e.charCodeAt(A));return new Blob([new Uint8Array(n)],{type:t})})(e.dataUrl,A.type)}}))}async getLocalOrFromServer(A){if(this.cache.has(A)){const t=this.cache.get(A);if(!t)throw new nt("Failed to get asset from cache!");return t}const t=(async()=>(await It([A]))[0])();return this.cache.set(A,t),t}async getMaterialLocalOrFromServer(A){if(this.materialCache.has(A))return this.materialCache.get(A);const t=(async()=>(await(async A=>(await ht.getShadowGraphqlClient().query({query:mt,errorPolicy:"all",fetchPolicy:"no-cache",variables:{ids:A}})).data.materials)([A]))[0])();return this.materialCache.set(A,t),t}async uploadAssetWithProgress(A,t,e,n){const i=await this.dispatchCreateAssetRequest(A,t,n);if(!i)throw new Error("Failed to create asset.");return await new Promise(((t,n)=>{var a=new XMLHttpRequest;a.open("PUT",i.assetResponse.uploadUrl,!0),a.setRequestHeader("Content-Type",i.mimeType),a.setRequestHeader("Cache-Control","public,max-age=31536000,immutable"),a.upload.onprogress=A=>{A.lengthComputable&&e(100*A.loaded/A.total)},a.onload=()=>{const A=i.assetResponse.asset;Mt.add(i.assetResponse.asset),t(A)},a.onerror=n,a.send(A.blob)})),i.assetResponse.asset}async uploadFile(A,e){const n=!("image/svg+xml"===A.type||"application/pdf"===A.type),i=n?t.Image:t.Illustration;if(n){const t=await this.loadImageAsFileInfo(A);return await this.uploadAssetWithProgress(t,i,e,!0)}{const t={name:A.name,blob:new Blob([A],{type:A.type})};return await yt.uploadAssetWithProgress(t,i,e,!0)}}removePersistedAsset(A){Mt.remove(A)}getPersistedAssets(){return Mt.list()}async dispatchCreateAssetRequest(A,t,e){const n=A.blob.type?A.blob.type:this.guessMIME(A.name),i=await(async(A,t,e,n)=>(await ht.getShadowGraphqlClient().mutate({mutation:pt,errorPolicy:"all",fetchPolicy:"no-cache",variables:{name:A,type:t,mimeType:e,anonymous:n}})).data?.assetCreate)(A.name,t,n,e);if(i)return{assetResponse:i,mimeType:n}}guessMIME(A){const t=A.split(".").pop();switch(t){case"glb":return"model/gltf-binary";case"ttf":return"font/ttf";case"mkv":return"video/x-matroska";default:throw new nt("Unexpected mimetype: "+t)}}};function Ft(A,t,e){return(t=function(A){var t=function(A,t){if("object"!=typeof A||null===A)return A;var e=A[Symbol.toPrimitive];if(void 0!==e){var n=e.call(A,t||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(A)}(A,"string");return"symbol"==typeof t?t:String(t)}(t))in A?Object.defineProperty(A,t,{value:e,enumerable:!0,configurable:!0,writable:!0}):A[t]=e,A}const Yt=pA`
83
+ `,It=async A=>(await ht.getShadowGraphqlClient().query({query:ut,errorPolicy:"all",fetchPolicy:"no-cache",variables:{keys:A}})).data.assets;const ft="persistentAssets";class Mt{static add(A){if(!A.fileLink)return void console.error("Failed to find cdn link on asset, cannot persist!");const t=new Map;t.set(A.key||"",A.fileLink);const e=gt.getMap(ft);e&&e.forEach(((A,e)=>{t.set(e,A)})),gt.setMap(ft,t)}static remove(A){const t=gt.getMap(ft);if(!t)return;const e=Array.from(t.entries()).find((t=>t[0]===A));e&&(t.delete(e[0]),gt.setMap(ft,t))}static list(){const A=gt.getMap(ft);return A?Array.from(A.entries()).map((A=>({assetKey:A[0],src:A[1]}))):[]}}const yt=new class{constructor(){Qt(this,"cache",new Map),Qt(this,"materialCache",new Map),Qt(this,"loadImageAsFileInfo",(async A=>{const t=await A.arrayBuffer(),e=await S(t);return{name:A.name.substring(A.name.lastIndexOf("/")+1),blob:((A,t)=>{const e=atob(A.split(",")[1]),n=[];for(let A=0;A<e.length;A++)n.push(e.charCodeAt(A));return new Blob([new Uint8Array(n)],{type:t})})(e.dataUrl,A.type)}}))}async getLocalOrFromServer(A){if(this.cache.has(A)){const t=this.cache.get(A);if(!t)throw new nt("Failed to get asset from cache!");return t}const t=(async()=>(await It([A]))[0])();return this.cache.set(A,t),t}async getMaterialLocalOrFromServer(A){if(this.materialCache.has(A))return this.materialCache.get(A);const t=(async()=>(await(async A=>(await ht.getShadowGraphqlClient().query({query:mt,errorPolicy:"all",fetchPolicy:"no-cache",variables:{ids:A}})).data.materials)([A]))[0])();return this.materialCache.set(A,t),t}async uploadAssetWithProgress(A,t,e,n){const i=await this.dispatchCreateAssetRequest(A,t,n);if(!i)throw new Error("Failed to create asset.");return await new Promise(((t,n)=>{const a=new XMLHttpRequest;a.open("PUT",i.assetResponse.uploadUrl,!0),a.setRequestHeader("Content-Type",i.mimeType),a.setRequestHeader("Cache-Control","public,max-age=31536000,immutable"),a.upload.onprogress=A=>{A.lengthComputable&&e(100*A.loaded/A.total)},a.onload=()=>{const A=i.assetResponse.asset;Mt.add(i.assetResponse.asset),t(A)},a.onerror=n,a.send(A.blob)})),i.assetResponse.asset}async uploadFile(A,e){const n=!("image/svg+xml"===A.type||"application/pdf"===A.type),i=n?t.Image:t.Illustration;if(n){const t=await this.loadImageAsFileInfo(A);return await this.uploadAssetWithProgress(t,i,e,!0)}{const t={name:A.name,blob:new Blob([A],{type:A.type})};return await yt.uploadAssetWithProgress(t,i,e,!0)}}removePersistedAsset(A){Mt.remove(A)}getPersistedAssets(){return Mt.list()}async dispatchCreateAssetRequest(A,t,e){const n=A.blob.type?A.blob.type:this.guessMIME(A.name),i=await(async(A,t,e,n)=>(await ht.getShadowGraphqlClient().mutate({mutation:pt,errorPolicy:"all",fetchPolicy:"no-cache",variables:{name:A,type:t,mimeType:e,anonymous:n}})).data?.assetCreate)(A.name,t,n,e);if(i)return{assetResponse:i,mimeType:n}}guessMIME(A){const t=A.split(".").pop();switch(t){case"glb":return"model/gltf-binary";case"ttf":return"font/ttf";case"mkv":return"video/x-matroska";default:throw new nt("Unexpected mimetype: "+t)}}};function Ft(A,t,e){return(t=function(A){var t=function(A,t){if("object"!=typeof A||null===A)return A;var e=A[Symbol.toPrimitive];if(void 0!==e){var n=e.call(A,t||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(A)}(A,"string");return"symbol"==typeof t?t:String(t)}(t))in A?Object.defineProperty(A,t,{value:e,enumerable:!0,configurable:!0,writable:!0}):A[t]=e,A}const Yt=pA`
84
84
  fragment OptionFields on Option {
85
85
  id
86
86
  name
@@ -463,7 +463,7 @@ import{CommandContext as A,AssetType as t,BringForwardCommand as e,BringToFrontC
463
463
  }
464
464
  }
465
465
  }
466
- `,Ni=(A,t,e)=>{const n={};return t.steps.forEach((t=>{Object.assign(n,(t=>{const n={};if("Frame"===t.type){const i=A[t.stepName],a=t.data;if(!i||a.hideImageInCart&&e)return n;n[`${t.stepTitle} image`]=i.image}if("Illustration"===t.type){const i=A[t.stepName],a=t.data;if(!i||a.hideColorsInCart&&e||!i.colors)return n;if(i.colors.length>0){const A=i.colors.join(", ").toUpperCase();n[`${t.stepTitle} colors`]=A}}if("Module"===t.type){const i=A[t.stepName],a=t.data;if(!i||a.hideTextInCart&&e)return n;n[`${t.stepTitle} text`]=i.text}if("Text"===t.type){const i=A[t.stepName];if(!i)return n;const a=t.data;a.hideTextInCart&&e||(n[`${t.stepTitle} text`]=i.text),!i.color||a.hideColorInCart&&e||(n[`${t.stepTitle} color`]=i.color)}return n})(t))})),n},Ri=(A,t,e,n,i,a,o,r,s)=>{const c={event:"onComplete",lineItemImageUrl:o||"",transactionId:A.id,designProductVariantId:A.externalDesignProductVariantId,designProductId:A.externalDesignProductId,externalCartProductId:A.externalCartProductId,externalCartProductVariantId:A.externalCartProductVariantId,baseCost:e,weight:t.weight,optionsCost:n,exportedData:a,workflowViewerLink:A.workflowViewerLink||"",workflowViewerReadOnlyLink:A.workflowViewerReadOnlyLink||""};return i&&(c.metadata=i),r&&(c.selectedVariants=r),s&&(c.sku=s),c},Hi=async(A,t,e,n,i,a,o)=>{const r=A.product?.basePrice||0,s=A.priceModifierTotal||0,c=((A,t,e,n)=>{const i={};let a;if(e){a=Ni(e,t,!1);for(const A of Object.keys(a))i[A]={value:a[A],priceModifier:0}}else if(n){a=n;for(const A of Object.keys(a))i[A]={value:a[A],priceModifier:0}}for(const e of Object.keys(A)){const n=A[e],a=t.steps.find((A=>A.stepTitle===e));if(1===n.length)i[`${a?.stepTitle} selection`]={value:n[0].name,priceModifier:n[0].priceModifier};else if(n.length>1)for(let A=0;A<n.length;A++)i[`${a?.stepTitle} selection ${A+1}`]={value:n[A].name,priceModifier:n[A].priceModifier}}return i})(n,e,void 0,a);return Ri(A,t,r,s,a,c,o,n,i)},Ui=async(A,t,e,n,i,a,o,r,s,c,g,B,l)=>{s("workflow.steps.finish.finalize.buildingLayouts"),await A.outstandingRequestsPromise();const w=ht.getShadowGraphqlClient();await w.resetStore();const E=await w.query({query:xn,variables:{id:a.id},errorPolicy:"all"}),d=E.data?.transactions[0].workflowState;!E.errors&&d||(console.warn("State mismatch detected. Uploading known state explicitly"),console.warn("State Object:",JSON.stringify(n())),E.errors&&E.errors.forEach((A=>{E.errors&&console.log("Server Error:",A.message)})),await A.updateStateWithServerImmediate(n),console.log("Server state is undefined @ Workflow completion"));const h=A.getPreviewService(),Q=t?.finalizeStepConfig?.lookAtAnimation,C=h&&100===h.getSceneInitializationProgress()&&t.showModelOnFinishStep&&!!Q,u=l&&Ni(l,t,!0),D=l&&Ni(l,t,!1),m=async A=>{const e={};let n=0;if(Object.keys(o).length>0)for(const i of Object.keys(o)){const a=o[i],r=t.steps.find((A=>A.stepName===i));for(let t=0;t<a.selections.length;++t){const i=a.selections[t];if(r&&(!A||r.option&&(r.option.variants||[]).length>1&&!r.data.hideSelectionInCart&&!r.data.hideSelectionsInCart)){const A=r.stepTitle;e[A]?e[A].push({id:i.id||"",name:i.name,priceModifier:i.priceModifier}):e[A]=[{id:i.id||"",name:i.name,priceModifier:i.priceModifier}]}n+=i.priceModifier}}return[e,n]},[p]=await m(!0),I=Object.fromEntries(Object.keys(p).map((A=>[A,p[A].map((A=>A.id))]))),[f]=await m(!1),M=Object.fromEntries(Object.keys(f).map((A=>[A,f[A].map((A=>A.id))]))),y=await B(C);s("workflow.steps.finish.finalize.creatingDesign"),a.bulk&&await c(g);const F=await(async A=>(await ht.getShadowGraphqlClient().mutate({mutation:vi,errorPolicy:"all",fetchPolicy:"no-cache",variables:{name:A.name,layouts:A.layouts,workflowId:A.workflowId,transactionId:A.transactionId,previewImage:A.previewImage,useThreeDimPreview:A.useThreeDimPreview,metadata:A.metadata,selectedVariants:A.selectedVariants}})).data?.designCreate)((()=>{const A={name:r,layouts:e.map((A=>({index:A.index,panelId:A.panelId}))),workflowId:t.id,transactionId:a.id,useThreeDimPreview:C,previewImage:y};if(D){const t=[];for(const[A,e]of Object.entries(D))t.push({key:A,value:e});A.metadata=t}if(I){const t=[];for(const[A,e]of Object.entries(M))t.push({key:A,ids:e});A.selectedVariants=t}return A})()),Y=F?.transaction?.previewImageLink;s("workflow.steps.finish.finalize.updatingTransaction");const x=(await ht.getShadowGraphqlClient().query({query:Yn,variables:{id:a.id}})).data.transactions[0];return a.bulk?((A,t,e)=>{const n=(A.product?.basePrice||0)*(A.variationsCount||0),i=A.priceModifierTotal||0,a={items:{value:A.variationsCount?`${A.variationsCount}`:"0",priceModifier:0}};return Ri(A,t,n,i,void 0,a,e)})(x,i,Y):await Hi(x,i,t,p,F?.sku,u,Y)};let Pi;var Gi;(Gi=Pi||(Pi={})).Local="Local",Gi.Remote="Remote";const ki=new class{constructor(){Si(this,"localPersistenceKey","designTransactions"),Si(this,"storageMethod",Pi.Local),Si(this,"designSavedListeners",[])}attachSaveListener(A){this.designSavedListeners.push(A)}detachSaveListener(A){this.designSavedListeners=this.designSavedListeners.filter((t=>t!==A))}async getSavedDesigns(){return await this.getDesigns()}async getSavedDesignByTransaction(A){return(await this.getSavedDesigns()).find((t=>t.transactionId===A))}async addDesign(A){const t=(await this.getSavedDesigns()).filter((t=>t.transactionId!==A.transactionId));t.unshift(A),await this.setDesigns(t),this.notifyDesignSaved(A)}async removeDesign(A){const t=await this.getSavedDesigns();await this.setDesigns(t.filter((t=>t.transactionId!==A)))}async setDesigns(A){if(this.storageMethod!==Pi.Local)throw new nt("Unexpected storage method requested");gt.set(this.localPersistenceKey,JSON.stringify(A))}async getDesigns(){if(this.storageMethod===Pi.Local){const A=gt.get(this.localPersistenceKey);return A?JSON.parse(A):[]}throw new nt("Unexpected storage method requested")}notifyDesignSaved(A){this.designSavedListeners.forEach((t=>t(A)))}};function Ji(A,t,e){return(t=function(A){var t=function(A,t){if("object"!=typeof A||null===A)return A;var e=A[Symbol.toPrimitive];if(void 0!==e){var n=e.call(A,t||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(A)}(A,"string");return"symbol"==typeof t?t:String(t)}(t))in A?Object.defineProperty(A,t,{value:e,enumerable:!0,configurable:!0,writable:!0}):A[t]=e,A}class bi{constructor(t,e){if(Ji(this,"client",void 0),Ji(this,"commandContext",void 0),Ji(this,"workflowManager",void 0),Ji(this,"isReadOnly",void 0),Ji(this,"renderableScenes",[]),Ji(this,"renderableSceneCallbacks",[]),Ji(this,"debouncedSavedDesignUpdate",VA((async()=>{await ki.getSavedDesignByTransaction(this.getWorkflowManager().getTransaction().id)&&this.save()}),2500)),Ji(this,"getCanvasObjectURLAsync",(async A=>new Promise(((t,e)=>{try{A.toBlob((A=>{if(A){const e=URL.createObjectURL(A);t(e)}}))}catch(A){e(A)}})))),!e.workflow)throw new Error("No Workflow ID provided.");this.client=t;const n=e.layouts;this.commandContext=new A,this.commandContext.initialize(n,e.reloadedState),this.isReadOnly=!!e.transaction.lineItem?.id||!gt.getMap("transactionOwnerIds")?.get(e.transaction.id)||!!e.readOnly,this.workflowManager=new wi(e.workflow,e.product.profanities?.map((A=>A.word))||[],n,this.commandContext,(A=>{try{this.debouncedSavedDesignUpdate()}catch{console.error("Failed to update saved design details.")}return e.stateMutationFunc(A)}),e.transaction,e.product,e.previewService,e.renderableContextService,e.reloadedState,e.readOnly),this.workflowManager.addSelectionCallback((A=>{const t=A.traversableScenes.map((A=>{const t=A.renderableSteps.map((A=>A.stepName));return{id:A.name,title:A.title,renderableSteps:t}}));this.renderableScenes=t,this.renderableSceneCallbacks.forEach((A=>A(t)))}))}getClient(){return this.client}getIsReadOnly(){return this.isReadOnly}getCommandContext(){return this.commandContext}getWorkflowManager(){return this.workflowManager}async updateVariationRecords(A){await ht.getShadowGraphqlClient().mutate({mutation:Fn,variables:{transactionId:this.workflowManager.getTransaction().id,updates:A.map((A=>({recordNumber:A.recordNumber,values:A.values.map((A=>({aspect:A.aspect,stepName:A.stepName,value:A.value})))})))}})}async createPreviewImage(A,t){const e=this.workflowManager.getWorkflow(),n=e?.finalizeStepConfig?.lookAtAnimation;if(A){if(!n)throw new Error("Failed to generate cart preview image!");return await(this.workflowManager.getPreviewService()?.renderSceneScreenshot(512,n))||""}const i=document.createElement("canvas");let a=2048;t&&t<=2048&&(a=t),i.width=a,i.height=a;const o=this.commandContext.getAllLayouts(),r=e.defaultPreviewPanelIndex||0,s=e.panels[r],c=o.find((A=>A.layoutState?.layout.panelId===s?.name))||o[0],g=c.layoutState.layout.previewRegion?{x:c.layoutState.layout.previewRegion.left,y:c.layoutState.layout.previewRegion.top,width:c.layoutState.layout.previewRegion.width,height:c.layoutState.layout.previewRegion.height}:{x:0,y:0,width:c.layoutState.layout.width,height:c.layoutState.layout.height},B=this.commandContext.getLayoutById(c.layoutState.layout.id),l=i.getContext("2d");if(!l)throw new ot("Failed to obtain 2D context for preview image creation");const w=R(B.layoutState.layout,B.layoutState.elements,{renderingConfiguration:{purpose:W.Print,region:{left:g.x,top:g.y,width:g.width,height:g.height}}}),E=zA.renderToStaticMarkup(w),d=await OA.from(l,E,{anonymousCrossOrigin:!0,ignoreDimensions:!1});await d.render();const h=await this.getCanvasObjectURLAsync(i);return i.toDataURL(h)}getStepById(A){const t=this.getWorkflowManager().getWorkflow().steps.find((t=>t.stepName===A));if(t&&this.stepHasHandle(t))return xi.get(this.getWorkflowManager(),t)}getSteps(){return this.getScenes().flatMap((A=>this.getStepsByScene(A)))}getScenes(){return this.getWorkflowManager().getWorkflow().stepGroups.map((A=>({id:A.id,name:A.name,stepIds:A.stepNames})))}getBulkStep(){if(this.getWorkflowManager().getTransaction().bulk){const A=this.getWorkflowManager().getProduct().bulkConfiguration,t={type:m.Bulk,stepName:"Bulk",stepTitle:A?.stepTitle??"workflow.steps.bulk.title",helpText:A?.helpText,data:{aspects:Sn(this.getWorkflowManager().getWorkflow())},conditions:[]};return xi.get(this.getWorkflowManager(),t)}}getStepByName(A){const t=this.getWorkflowManager().getWorkflow().steps.find((t=>t.stepTitle===A));if(t&&this.stepHasHandle(t))return xi.get(this.getWorkflowManager(),t)}getStepsByType(A){return this.getWorkflowManager().getWorkflow().steps.filter((t=>t.type===A)).map((A=>xi.get(this.getWorkflowManager(),A)))}getStepsByScene(A){if(!this.getWorkflowManager().getWorkflow().stepGroups.find((t=>t.name===A.name)))throw new Error("Given scene is not present on workflow! Be careful when persisting scenes that you only use them with the relevant workflow.");return A.stepIds.map((A=>this.getWorkflowManager().getWorkflow().steps.find((t=>t.stepName===A)))).filter((A=>this.stepHasHandle(A))).map((A=>xi.get(this.getWorkflowManager(),A)))}async attachCustomerDetails(A){return this.assignCustomerDetails({emailAddress:A.email})}async assignCustomerDetails(A){await ht.getShadowGraphqlClient().mutate({mutation:ui,variables:{id:this.getWorkflowManager().getTransaction().id,details:A,type:"Owner"}}),this.getWorkflowManager().setTransactionCustomer(A)}attachRenderableSceneListener(A){this.renderableSceneCallbacks.push(A),A(this.renderableScenes)}detachRenderableSceneListener(A){this.renderableSceneCallbacks=this.renderableSceneCallbacks.filter((t=>t!==A))}async save(A){if(!this.getCommandContext().getState())throw new nt("State undefined!");const t={title:await(async()=>{if(A)return A;const t=this.getWorkflowManager().getTransaction().id,e=(await ki.getSavedDesigns()).find((A=>A.transactionId===t))?.title;return e||"My design"})(),thumbnail:await this.createPreviewImage(!1,256),transactionId:this.getWorkflowManager().getTransaction().id,productId:this.getWorkflowManager().getProduct().id,integrationProductId:this.getWorkflowManager().getTransaction().integrationProduct.id,workflowName:this.getWorkflowManager().getWorkflow().name,workflowId:this.getWorkflowManager().getWorkflow().id,lastEdited:new Date};return await ki.addDesign(t),t}async copy(){const A=TA(this.getCommandContext().getState());if(!A)throw new nt("Internal state is undefined! Cannot copy experience!");const t=JSON.stringify(A.transaction),e=this.getWorkflowManager().getWorkflow(),n=new ji({}),i=this.getWorkflowManager().getTransaction().integrationProduct?.id;if(!i)throw new nt("Integration product id is undefined!");await n.initFromIntegrationProduct(i);return await n.getWorkflowExperience(e.id,t,void 0)}async onDesignFinished(A){return Ui(this.workflowManager,this.workflowManager.getWorkflow(),this.workflowManager.getLayouts(),(()=>this.commandContext.getState()),this.workflowManager.getProduct(),this.workflowManager.getTransaction(),this.workflowManager.getWorkflowSelections(),this.workflowManager.getWorkflow().name,A||(()=>{}),(A=>this.updateVariationRecords(A)),this.workflowManager.getVariationRecords(),(A=>this.createPreviewImage(A)),this.workflowManager.getWorkflowMetadata())}stepHasHandle(A){return A.type!==m.SilentIllustration&&A.type!==m.ProductOverlay}getExportedData(){const A=new Map,t=this.getWorkflowManager().getWorkflowMetadata(),e=this.getWorkflowManager().getWorkflowSelections();return Object.keys(t).forEach((e=>{const n=this.workflowManager.getWorkflow().steps.find((A=>A.stepName===e));if(!n)return;A.has(n.stepTitle)||A.set(n.stepTitle,{});const i=t[e];Object.keys(i).forEach((t=>{A.get(n.stepTitle)[t]=i[t]}))})),Object.keys(e)?.forEach((t=>{const n=this.workflowManager.getWorkflow().steps.find((A=>A.stepName===t));n&&(A.has(n.stepTitle)||A.set(n.stepTitle,{}),A.get(n.stepTitle).selection=e[t].selections[0].name)})),A}}function Li(A,t,e){return(t=function(A){var t=function(A,t){if("object"!=typeof A||null===A)return A;var e=A[Symbol.toPrimitive];if(void 0!==e){var n=e.call(A,t||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(A)}(A,"string");return"symbol"==typeof t?t:String(t)}(t))in A?Object.defineProperty(A,t,{value:e,enumerable:!0,configurable:!0,writable:!0}):A[t]=e,A}const Ti=pA`
466
+ `,Ni=(A,t,e)=>{const n={};return t.steps.forEach((t=>{Object.assign(n,(t=>{const n={};if("Frame"===t.type){const i=A[t.stepName],a=t.data;if(!i||a.hideImageInCart&&e)return n;n[`${t.stepTitle} image`]=i.image}if("Illustration"===t.type){const i=A[t.stepName],a=t.data;if(!i||a.hideColorsInCart&&e||!i.colors)return n;if(i.colors.length>0){const A=i.colors.join(", ").toUpperCase();n[`${t.stepTitle} colors`]=A}}if("Module"===t.type){const i=A[t.stepName],a=t.data;if(!i||a.hideTextInCart&&e)return n;n[`${t.stepTitle} text`]=i.text}if("Text"===t.type){const i=A[t.stepName];if(!i)return n;const a=t.data;a.hideTextInCart&&e||(n[`${t.stepTitle} text`]=i.text),!i.color||a.hideColorInCart&&e||(n[`${t.stepTitle} color`]=i.color)}return n})(t))})),n},Ri=(A,t,e,n,i,a,o,r,s)=>{const c=(gt.getMap("transactionOwnerIds")||new Map).get(A.id),g={event:"onComplete",lineItemImageUrl:o||"",transactionId:A.id,designProductVariantId:A.externalDesignProductVariantId,designProductId:A.externalDesignProductId,externalCartProductId:A.externalCartProductId,externalCartProductVariantId:A.externalCartProductVariantId,baseCost:e,weight:t.weight,optionsCost:n,exportedData:a,workflowViewerLink:A.workflowViewerLink||"",workflowViewerReadOnlyLink:A.workflowViewerReadOnlyLink||"",transactionOwnerId:c};return i&&(g.metadata=i),r&&(g.selectedVariants=r),s&&(g.sku=s),g},Hi=async(A,t,e,n,i,a,o)=>{const r=A.product?.basePrice||0,s=A.priceModifierTotal||0,c=((A,t,e,n)=>{const i={};let a;if(e){a=Ni(e,t,!1);for(const A of Object.keys(a))i[A]={value:a[A],priceModifier:0}}else if(n){a=n;for(const A of Object.keys(a))i[A]={value:a[A],priceModifier:0}}for(const e of Object.keys(A)){const n=A[e],a=t.steps.find((A=>A.stepTitle===e));if(1===n.length)i[`${a?.stepTitle} selection`]={value:n[0].name,priceModifier:n[0].priceModifier};else if(n.length>1)for(let A=0;A<n.length;A++)i[`${a?.stepTitle} selection ${A+1}`]={value:n[A].name,priceModifier:n[A].priceModifier}}return i})(n,e,void 0,a);return Ri(A,t,r,s,a,c,o,n,i)},Ui=async(A,t,e,n,i,a,o,r,s,c,g,B,l)=>{s("workflow.steps.finish.finalize.buildingLayouts"),await A.outstandingRequestsPromise();const w=ht.getShadowGraphqlClient();await w.resetStore();const E=await w.query({query:xn,variables:{id:a.id},errorPolicy:"all"}),d=E.data?.transactions[0].workflowState;!E.errors&&d||(console.warn("State mismatch detected. Uploading known state explicitly"),console.warn("State Object:",JSON.stringify(n())),E.errors&&E.errors.forEach((A=>{E.errors&&console.log("Server Error:",A.message)})),await A.updateStateWithServerImmediate(n),console.log("Server state is undefined @ Workflow completion"));const h=A.getPreviewService(),Q=t?.finalizeStepConfig?.lookAtAnimation,C=h&&100===h.getSceneInitializationProgress()&&t.showModelOnFinishStep&&!!Q,u=l&&Ni(l,t,!0),D=l&&Ni(l,t,!1),m=async A=>{const e={};let n=0;if(Object.keys(o).length>0)for(const i of Object.keys(o)){const a=o[i],r=t.steps.find((A=>A.stepName===i));for(let t=0;t<a.selections.length;++t){const i=a.selections[t];if(r&&(!A||r.option&&(r.option.variants||[]).length>1&&!r.data.hideSelectionInCart&&!r.data.hideSelectionsInCart)){const A=r.stepTitle;e[A]?e[A].push({id:i.id||"",name:i.name,priceModifier:i.priceModifier}):e[A]=[{id:i.id||"",name:i.name,priceModifier:i.priceModifier}]}n+=i.priceModifier}}return[e,n]},[p]=await m(!0),I=Object.fromEntries(Object.keys(p).map((A=>[A,p[A].map((A=>A.id))]))),[f]=await m(!1),M=Object.fromEntries(Object.keys(f).map((A=>[A,f[A].map((A=>A.id))]))),y=await B(C);s("workflow.steps.finish.finalize.creatingDesign"),a.bulk&&await c(g);const F=await(async A=>(await ht.getShadowGraphqlClient().mutate({mutation:vi,errorPolicy:"all",fetchPolicy:"no-cache",variables:{name:A.name,layouts:A.layouts,workflowId:A.workflowId,transactionId:A.transactionId,previewImage:A.previewImage,useThreeDimPreview:A.useThreeDimPreview,metadata:A.metadata,selectedVariants:A.selectedVariants}})).data?.designCreate)((()=>{const A={name:r,layouts:e.map((A=>({index:A.index,panelId:A.panelId}))),workflowId:t.id,transactionId:a.id,useThreeDimPreview:C,previewImage:y};if(D){const t=[];for(const[A,e]of Object.entries(D))t.push({key:A,value:e});A.metadata=t}if(I){const t=[];for(const[A,e]of Object.entries(M))t.push({key:A,ids:e});A.selectedVariants=t}return A})()),Y=F?.transaction?.previewImageLink;s("workflow.steps.finish.finalize.updatingTransaction");const x=(await ht.getShadowGraphqlClient().query({query:Yn,variables:{id:a.id}})).data.transactions[0];return a.bulk?((A,t,e)=>{const n=(A.product?.basePrice||0)*(A.variationsCount||0),i=A.priceModifierTotal||0,a={items:{value:A.variationsCount?`${A.variationsCount}`:"0",priceModifier:0}};return Ri(A,t,n,i,void 0,a,e)})(x,i,Y):await Hi(x,i,t,p,F?.sku,u,Y)};let Pi;var Gi;(Gi=Pi||(Pi={})).Local="Local",Gi.Remote="Remote";const ki=new class{constructor(){Si(this,"localPersistenceKey","designTransactions"),Si(this,"storageMethod",Pi.Local),Si(this,"designSavedListeners",[])}attachSaveListener(A){this.designSavedListeners.push(A)}detachSaveListener(A){this.designSavedListeners=this.designSavedListeners.filter((t=>t!==A))}async getSavedDesigns(){return await this.getDesigns()}async getSavedDesignByTransaction(A){return(await this.getSavedDesigns()).find((t=>t.transactionId===A))}async addDesign(A){const t=(await this.getSavedDesigns()).filter((t=>t.transactionId!==A.transactionId));t.unshift(A),await this.setDesigns(t),this.notifyDesignSaved(A)}async removeDesign(A){const t=await this.getSavedDesigns();await this.setDesigns(t.filter((t=>t.transactionId!==A)))}async setDesigns(A){if(this.storageMethod!==Pi.Local)throw new nt("Unexpected storage method requested");gt.set(this.localPersistenceKey,JSON.stringify(A))}async getDesigns(){if(this.storageMethod===Pi.Local){const A=gt.get(this.localPersistenceKey);return A?JSON.parse(A):[]}throw new nt("Unexpected storage method requested")}notifyDesignSaved(A){this.designSavedListeners.forEach((t=>t(A)))}};function Ji(A,t,e){return(t=function(A){var t=function(A,t){if("object"!=typeof A||null===A)return A;var e=A[Symbol.toPrimitive];if(void 0!==e){var n=e.call(A,t||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(A)}(A,"string");return"symbol"==typeof t?t:String(t)}(t))in A?Object.defineProperty(A,t,{value:e,enumerable:!0,configurable:!0,writable:!0}):A[t]=e,A}class bi{constructor(t,e){if(Ji(this,"client",void 0),Ji(this,"commandContext",void 0),Ji(this,"workflowManager",void 0),Ji(this,"isReadOnly",void 0),Ji(this,"renderableScenes",[]),Ji(this,"renderableSceneCallbacks",[]),Ji(this,"debouncedSavedDesignUpdate",VA((async()=>{await ki.getSavedDesignByTransaction(this.getWorkflowManager().getTransaction().id)&&this.save()}),2500)),Ji(this,"getCanvasObjectURLAsync",(async A=>new Promise(((t,e)=>{try{A.toBlob((A=>{if(A){const e=URL.createObjectURL(A);t(e)}}))}catch(A){e(A)}})))),!e.workflow)throw new Error("No Workflow ID provided.");this.client=t;const n=e.layouts;this.commandContext=new A,this.commandContext.initialize(n,e.reloadedState),this.isReadOnly=!!e.transaction.lineItem?.id||!gt.getMap("transactionOwnerIds")?.get(e.transaction.id)||!!e.readOnly,this.workflowManager=new wi(e.workflow,e.product.profanities?.map((A=>A.word))||[],n,this.commandContext,(A=>{try{this.debouncedSavedDesignUpdate()}catch{console.error("Failed to update saved design details.")}return e.stateMutationFunc(A)}),e.transaction,e.product,e.previewService,e.renderableContextService,e.reloadedState,e.readOnly),this.workflowManager.addSelectionCallback((A=>{const t=A.traversableScenes.map((A=>{const t=A.renderableSteps.map((A=>A.stepName));return{id:A.name,title:A.title,renderableSteps:t}}));this.renderableScenes=t,this.renderableSceneCallbacks.forEach((A=>A(t)))}))}getClient(){return this.client}getIsReadOnly(){return this.isReadOnly}getCommandContext(){return this.commandContext}getWorkflowManager(){return this.workflowManager}async updateVariationRecords(A){await ht.getShadowGraphqlClient().mutate({mutation:Fn,variables:{transactionId:this.workflowManager.getTransaction().id,updates:A.map((A=>({recordNumber:A.recordNumber,values:A.values.map((A=>({aspect:A.aspect,stepName:A.stepName,value:A.value})))})))}})}async createPreviewImage(A,t){const e=this.workflowManager.getWorkflow(),n=e?.finalizeStepConfig?.lookAtAnimation;if(A){if(!n)throw new Error("Failed to generate cart preview image!");return await(this.workflowManager.getPreviewService()?.renderSceneScreenshot(512,n))||""}const i=document.createElement("canvas");let a=2048;t&&t<=2048&&(a=t),i.width=a,i.height=a;const o=this.commandContext.getAllLayouts(),r=e.defaultPreviewPanelIndex||0,s=e.panels[r],c=o.find((A=>A.layoutState?.layout.panelId===s?.name))||o[0],g=c.layoutState.layout.previewRegion?{x:c.layoutState.layout.previewRegion.left,y:c.layoutState.layout.previewRegion.top,width:c.layoutState.layout.previewRegion.width,height:c.layoutState.layout.previewRegion.height}:{x:0,y:0,width:c.layoutState.layout.width,height:c.layoutState.layout.height},B=this.commandContext.getLayoutById(c.layoutState.layout.id),l=i.getContext("2d");if(!l)throw new ot("Failed to obtain 2D context for preview image creation");const w=R(B.layoutState.layout,B.layoutState.elements,{renderingConfiguration:{purpose:W.Print,region:{left:g.x,top:g.y,width:g.width,height:g.height}}}),E=zA.renderToStaticMarkup(w),d=await OA.from(l,E,{anonymousCrossOrigin:!0,ignoreDimensions:!1});await d.render();const h=await this.getCanvasObjectURLAsync(i);return i.toDataURL(h)}getStepById(A){const t=this.getWorkflowManager().getWorkflow().steps.find((t=>t.stepName===A));if(t&&this.stepHasHandle(t))return xi.get(this.getWorkflowManager(),t)}getSteps(){return this.getScenes().flatMap((A=>this.getStepsByScene(A)))}getScenes(){return this.getWorkflowManager().getWorkflow().stepGroups.map((A=>({id:A.id,name:A.name,stepIds:A.stepNames})))}getBulkStep(){if(this.getWorkflowManager().getTransaction().bulk){const A=this.getWorkflowManager().getProduct().bulkConfiguration,t={type:m.Bulk,stepName:"Bulk",stepTitle:A?.stepTitle??"workflow.steps.bulk.title",helpText:A?.helpText,data:{aspects:Sn(this.getWorkflowManager().getWorkflow())},conditions:[]};return xi.get(this.getWorkflowManager(),t)}}getStepByName(A){const t=this.getWorkflowManager().getWorkflow().steps.find((t=>t.stepTitle===A));if(t&&this.stepHasHandle(t))return xi.get(this.getWorkflowManager(),t)}getStepsByType(A){return this.getWorkflowManager().getWorkflow().steps.filter((t=>t.type===A)).map((A=>xi.get(this.getWorkflowManager(),A)))}getStepsByScene(A){if(!this.getWorkflowManager().getWorkflow().stepGroups.find((t=>t.name===A.name)))throw new Error("Given scene is not present on workflow! Be careful when persisting scenes that you only use them with the relevant workflow.");return A.stepIds.map((A=>this.getWorkflowManager().getWorkflow().steps.find((t=>t.stepName===A)))).filter((A=>this.stepHasHandle(A))).map((A=>xi.get(this.getWorkflowManager(),A)))}async attachCustomerDetails(A){return this.assignCustomerDetails({emailAddress:A.email})}async assignCustomerDetails(A){await ht.getShadowGraphqlClient().mutate({mutation:ui,variables:{id:this.getWorkflowManager().getTransaction().id,details:A,type:"Owner"}}),this.getWorkflowManager().setTransactionCustomer(A)}attachRenderableSceneListener(A){this.renderableSceneCallbacks.push(A),A(this.renderableScenes)}detachRenderableSceneListener(A){this.renderableSceneCallbacks=this.renderableSceneCallbacks.filter((t=>t!==A))}async save(A){if(!this.getCommandContext().getState())throw new nt("State undefined!");const t={title:await(async()=>{if(A)return A;const t=this.getWorkflowManager().getTransaction().id,e=(await ki.getSavedDesigns()).find((A=>A.transactionId===t))?.title;return e||"My design"})(),thumbnail:await this.createPreviewImage(!1,256),transactionId:this.getWorkflowManager().getTransaction().id,productId:this.getWorkflowManager().getProduct().id,integrationProductId:this.getWorkflowManager().getTransaction().integrationProduct.id,workflowName:this.getWorkflowManager().getWorkflow().name,workflowId:this.getWorkflowManager().getWorkflow().id,lastEdited:new Date};return await ki.addDesign(t),t}async copy(){const A=TA(this.getCommandContext().getState());if(!A)throw new nt("Internal state is undefined! Cannot copy experience!");const t=JSON.stringify(A.transaction),e=this.getWorkflowManager().getWorkflow(),n=new ji({}),i=this.getWorkflowManager().getTransaction().integrationProduct?.id;if(!i)throw new nt("Integration product id is undefined!");await n.initFromIntegrationProduct(i);return await n.getWorkflowExperience(e.id,t,void 0)}async onDesignFinished(A){return Ui(this.workflowManager,this.workflowManager.getWorkflow(),this.workflowManager.getLayouts(),(()=>this.commandContext.getState()),this.workflowManager.getProduct(),this.workflowManager.getTransaction(),this.workflowManager.getWorkflowSelections(),this.workflowManager.getWorkflow().name,A||(()=>{}),(A=>this.updateVariationRecords(A)),this.workflowManager.getVariationRecords(),(A=>this.createPreviewImage(A)),this.workflowManager.getWorkflowMetadata())}stepHasHandle(A){return A.type!==m.SilentIllustration&&A.type!==m.ProductOverlay}getExportedData(){const A=new Map,t=this.getWorkflowManager().getWorkflowMetadata(),e=this.getWorkflowManager().getWorkflowSelections();return Object.keys(t).forEach((e=>{const n=this.workflowManager.getWorkflow().steps.find((A=>A.stepName===e));if(!n)return;A.has(n.stepTitle)||A.set(n.stepTitle,{});const i=t[e];Object.keys(i).forEach((t=>{A.get(n.stepTitle)[t]=i[t]}))})),Object.keys(e)?.forEach((t=>{const n=this.workflowManager.getWorkflow().steps.find((A=>A.stepName===t));n&&(A.has(n.stepTitle)||A.set(n.stepTitle,{}),A.get(n.stepTitle).selection=e[t].selections[0].name)})),A}}function Li(A,t,e){return(t=function(A){var t=function(A,t){if("object"!=typeof A||null===A)return A;var e=A[Symbol.toPrimitive];if(void 0!==e){var n=e.call(A,t||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(A)}(A,"string");return"symbol"==typeof t?t:String(t)}(t))in A?Object.defineProperty(A,t,{value:e,enumerable:!0,configurable:!0,writable:!0}):A[t]=e,A}const Ti=pA`
467
467
  ${Ct}
468
468
  ${Dt}
469
469
  ${Yt}
package/dist/types.d.ts CHANGED
@@ -595,6 +595,7 @@ export interface DesignCreationMessage {
595
595
  sku?: string;
596
596
  workflowViewerLink: string;
597
597
  workflowViewerReadOnlyLink: string;
598
+ transactionOwnerId?: string;
598
599
  }
599
600
  /**
600
601
  * Represents a transaction.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spiffcommerce/core",
3
- "version": "5.0.2",
3
+ "version": "5.1.0",
4
4
  "description": "Core client API for interacting with the Spiff Commerce backend.",
5
5
  "source": "src/index.ts",
6
6
  "main": "dist/main.js",