@getspot/spot-widget 1.1.1 → 1.3.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/index.umd.js CHANGED
@@ -1,8 +1,8 @@
1
- (function(u,f){typeof exports=="object"&&typeof module<"u"?module.exports=f():typeof define=="function"&&define.amd?define(f):(u=typeof globalThis<"u"?globalThis:u||self,u.SpotWidget=f())})(this,function(){"use strict";async function u(i,e,t){try{const o=await fetch(i,{method:"POST",headers:{"Content-Type":"application/json","X-Spot-Partner-Id":e},body:JSON.stringify(t)}),n=await o.json();if(!o.ok){const r=new Error((n==null?void 0:n.message)||"Failed to fetch quote");throw r.status=o.status,r.responseBody=n,r}return n}catch(o){throw o instanceof Error?o:new Error("Unknown error occurred while fetching quote")}}const f={sandbox:"https://api.sandbox.getspot.com/v1/quote",production:"https://api.getspot.com/v1/quote"};function g(i){const{apiConfig:e={},quoteRequestData:t,callbacks:o={},location:n,theme:r}=i,{environment:a="sandbox",partnerId:p,endpoint:c}=e;if(!p||typeof p!="string")throw new Error("Invalid or missing partnerId in apiConfig");if(!(c||f[a]))throw new Error(`Invalid environment in apiConfig: ${a}`);if(!t||typeof t!="object")throw new Error("quoteRequestData must be a non-null object");["startDate","endDate","currencyCode","eventType","productType","productDuration","productPrice","productId","cartId","productName"].forEach(m=>{if(!Object.prototype.hasOwnProperty.call(t,m)||t[m]===void 0||t[m]===null)throw new Error(`Missing required quoteRequestData field: '${m}'`)});const h=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/;if(!h.test(t.startDate))throw new Error("startDate must be a valid ISO8601 string");if(!h.test(t.endDate))throw new Error("endDate must be a valid ISO8601 string");if(typeof t.currencyCode!="string")throw new Error("currencyCode must be a string");if(!["USD","CAD","AUD"].includes(t.currencyCode))throw new Error(`Invalid currency code: ${t.currencyCode}`);if(typeof t.eventType!="string")throw new Error("eventType must be a string");if(typeof t.productType!="string")throw new Error("productType must be a string");const y=["Pass","Trip","Registration"];if(!y.includes(t.productType))throw new Error(`productType must be one of ${y.join(", ")}`);if(typeof t.productDuration!="string")throw new Error("productDuration must be a string");const _=["Daily","Seasonal","Trip","Event"];if(!_.includes(t.productDuration))throw new Error(`productDuration must be one of ${_.join(", ")}`);if(typeof t.productPrice!="number"||isNaN(t.productPrice))throw new Error("productPrice must be a valid number");if(typeof t.productId!="string")throw new Error("productId must be a string");if(typeof t.cartId!="string")throw new Error("cartId must be a string");if(typeof t.productName!="string")throw new Error("productName must be a string");if(["onOptIn","onOptOut","onQuoteRetrieved","onError","noMatchingQuote"].forEach(m=>{const v=o[m];if(v&&typeof v!="function")throw new Error(`Callback '${m}' must be a function.`)}),typeof n=="string"&&!document.querySelector(n))throw new Error(`Invalid location selector: '${n}'`);if(r&&typeof r!="object")throw new Error("Theme must be an object with CSS variables, do not include the '--' prefix")}function s(i,{text:e,className:t,parent:o,innerHTML:n}={}){const r=document.createElement(i);return t&&(r.className=t),e!=null&&(r.textContent=e),n!=null&&(r.innerHTML=n),o&&o.appendChild(r),r}function w(i,{name:e,description:t}){s("div",{className:"spot-header__title",text:e,parent:i}),s("div",{className:"spot-header__description",text:t,parent:i})}function C(i,e=[]){const t=s("ul",{className:"spot-benefits__list",parent:i});e.forEach(o=>{const n=s("li",{parent:t});n.innerHTML=`
1
+ (function(_,C){typeof exports=="object"&&typeof module<"u"?module.exports=C():typeof define=="function"&&define.amd?define(C):(_=typeof globalThis<"u"?globalThis:_||self,_.SpotWidget=C())})(this,function(){"use strict";async function _(c,e,o){try{const n=await fetch(c,{method:"POST",headers:{"Content-Type":"application/json","X-Spot-Partner-Id":e},body:JSON.stringify(o)}),t=await n.json();if(!n.ok){const r=new Error((t==null?void 0:t.message)||"Failed to fetch quote");throw r.status=n.status,r.responseBody=t,r}return t}catch(n){throw n instanceof Error?n:new Error("Unknown error occurred while fetching quote")}}async function C(c,e,o){try{const n=c.replace("/quote","/quote/batch"),t=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json","X-Spot-Partner-Id":e},body:JSON.stringify(o)}),r=await t.json();if(!t.ok){const p=new Error((r==null?void 0:r.message)||"Failed to fetch batch quote");throw p.status=t.status,p.responseBody=r,p}return r}catch(n){throw n instanceof Error?n:new Error("Unknown error occurred while fetching batch quote")}}async function I(c,e,o){try{const n={cartId:o.cartInfo.cartId,cartName:o.cartInfo.cartName,currencyCode:o.cartInfo.currencyCode,items:o.items.map((i,u)=>({cartItemId:i.cartItemId||`item-${u+1}`,productPrice:i.productPrice,productType:i.productType,productDuration:i.productDuration,productId:i.productId,productName:i.productName,participantDescription:i.participantDescription,eventType:i.eventType,startDate:i.startDate,endDate:i.endDate}))},t=await C(c,e,n);if(t.status!=="QUOTES_AVAILABLE"&&t.status!=="QUOTE_AVAILABLE")return{status:"NO_MATCHING_QUOTE"};const r=t.quotes.map(i=>{const u=o.items.find(g=>(g.cartItemId||`item-${o.items.indexOf(g)+1}`)===i.cartItemId);return u?u.participantDescription?`${u.productName} - ${u.participantDescription}`:u.productName:`Item ${i.cartItemId}`}),p=Math.round((t.totalSpotPrice||t.spotPrice||0)*100)/100;return{status:"QUOTE_AVAILABLE",data:{id:t.quotes?t.quotes.map(i=>i.id).join(","):t.id,spotPrice:p,currencyCode:t.currencyCode,communication:{...t.communication,yesOptionText:t.communication.yesOptionText.replace(t.totalSpotPrice,p)},payoutSchedule:t.payoutSchedule.map(i=>({...i,amount:i.amount!==void 0?i.amount:0})),coveredItems:r,originalQuotes:t.quotes||[t]},spotPrice:p,coveredItems:r}}catch(n){throw n instanceof Error?n:new Error("Unknown error occurred while fetching multiple quotes")}}const N={sandbox:"https://api.sandbox.getspot.com/v1/quote",production:"https://api.getspot.com/v1/quote",local:"http://localhost:3999/api/v1/quote"};function D(c){const{apiConfig:e={},quoteRequestData:o,callbacks:n={},location:t,theme:r}=c,{environment:p="sandbox",partnerId:i,endpoint:u}=e;if(!i||typeof i!="string")throw new Error("Invalid or missing partnerId in apiConfig");if(!(u||N[p]))throw new Error(`Invalid environment in apiConfig: ${p}`);if(!o||typeof o!="object"&&!Array.isArray(o))throw new Error("quoteRequestData must be a non-null object or array");const h=["startDate","endDate","currencyCode","eventType","productType","productDuration","productPrice","productId","cartId","productName"];function d(s,l=null){const f=l!==null?`quoteRequestData[${l}]`:"quoteRequestData";h.forEach(v=>{if(!Object.prototype.hasOwnProperty.call(s,v)||s[v]===void 0||s[v]===null)throw new Error(`Missing required ${f} field: '${v}'`)});const w=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/;if(!w.test(s.startDate))throw new Error(`${f}.startDate must be a valid ISO8601 string`);if(!w.test(s.endDate))throw new Error(`${f}.endDate must be a valid ISO8601 string`);if(typeof s.currencyCode!="string")throw new Error(`${f}.currencyCode must be a string`);if(!["USD","CAD","AUD"].includes(s.currencyCode))throw new Error(`Invalid ${f}.currencyCode: ${s.currencyCode}`);if(typeof s.eventType!="string")throw new Error(`${f}.eventType must be a string`);if(typeof s.productType!="string")throw new Error(`${f}.productType must be a string`);const E=["Pass","Trip","Registration"];if(!E.includes(s.productType))throw new Error(`${f}.productType must be one of ${E.join(", ")}`);if(typeof s.productDuration!="string")throw new Error(`${f}.productDuration must be a string`);const y=["Daily","Seasonal","Trip","Event"];if(!y.includes(s.productDuration))throw new Error(`${f}.productDuration must be one of ${y.join(", ")}`);if(typeof s.productPrice!="number"||isNaN(s.productPrice))throw new Error(`${f}.productPrice must be a valid number`);if(typeof s.productId!="string")throw new Error(`${f}.productId must be a string`);if(typeof s.cartId!="string")throw new Error(`${f}.cartId must be a string`);if(typeof s.productName!="string")throw new Error(`${f}.productName must be a string`)}if(o.cartInfo&&o.items){const{cartInfo:s,items:l}=o;if(!s||typeof s!="object")throw new Error("quoteRequestData.cartInfo must be a non-null object");if(!s.cartId||typeof s.cartId!="string")throw new Error("quoteRequestData.cartInfo.cartId must be a string");if(!s.cartName||typeof s.cartName!="string")throw new Error("quoteRequestData.cartInfo.cartName must be a string");if(!s.currencyCode||typeof s.currencyCode!="string")throw new Error("quoteRequestData.cartInfo.currencyCode must be a string");if(!["USD","CAD","AUD"].includes(s.currencyCode))throw new Error(`Invalid quoteRequestData.cartInfo.currencyCode: ${s.currencyCode}`);if(!Array.isArray(l)||l.length===0)throw new Error("quoteRequestData.items must be a non-empty array");const w=h.filter(m=>m!=="cartId"&&m!=="currencyCode");l.forEach((m,E)=>{if(!m||typeof m!="object")throw new Error(`quoteRequestData.items[${E}] must be a non-null object`);const y=`quoteRequestData.items[${E}]`;w.forEach(q=>{if(!Object.prototype.hasOwnProperty.call(m,q)||m[q]===void 0||m[q]===null)throw new Error(`Missing required ${y} field: '${q}'`)});const v=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/;if(!v.test(m.startDate))throw new Error(`${y}.startDate must be a valid ISO8601 string`);if(!v.test(m.endDate))throw new Error(`${y}.endDate must be a valid ISO8601 string`);if(typeof m.eventType!="string")throw new Error(`${y}.eventType must be a string`);if(typeof m.productType!="string")throw new Error(`${y}.productType must be a string`);const T=["Pass","Trip","Registration"];if(!T.includes(m.productType))throw new Error(`${y}.productType must be one of ${T.join(", ")}`);if(typeof m.productDuration!="string")throw new Error(`${y}.productDuration must be a string`);const x=["Daily","Seasonal","Trip","Event"];if(!x.includes(m.productDuration))throw new Error(`${y}.productDuration must be one of ${x.join(", ")}`);if(typeof m.productPrice!="number"||isNaN(m.productPrice))throw new Error(`${y}.productPrice must be a valid number`);if(typeof m.productId!="string")throw new Error(`${y}.productId must be a string`);if(typeof m.productName!="string")throw new Error(`${y}.productName must be a string`)})}else if(Array.isArray(o)){if(o.length===0)throw new Error("quoteRequestData array cannot be empty");o.forEach((s,l)=>{if(!s||typeof s!="object")throw new Error(`quoteRequestData[${l}] must be a non-null object`);d(s,l)})}else d(o);if(["onOptIn","onOptOut","onQuoteRetrieved","onError","noMatchingQuote"].forEach(s=>{const l=n[s];if(l&&typeof l!="function")throw new Error(`Callback '${s}' must be a function.`)}),typeof t=="string"&&!document.querySelector(t))throw new Error(`Invalid location selector: '${t}'`);if(r&&typeof r!="object")throw new Error("Theme must be an object with CSS variables, do not include the '--' prefix")}function a(c,{text:e,className:o,parent:n,innerHTML:t}={}){const r=document.createElement(c);return o&&(r.className=o),e!=null&&(r.textContent=e),t!=null&&(r.innerHTML=t),n&&n.appendChild(r),r}function O(c,{name:e,description:o}){a("div",{className:"spot-header__title",text:e,parent:c}),a("div",{className:"spot-header__description",text:o,parent:c})}function P(c,e=[]){const o=a("ul",{className:"spot-benefits__list",parent:c});e.forEach(n=>{const t=a("li",{parent:o});t.innerHTML=`
2
2
  <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
3
3
  <path d="M11.6666 3.5L5.24998 9.91667L2.33331 7"
4
4
  stroke="#2E2E2E" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5
- </svg>`,s("span",{text:o,parent:n})})}function E(i,e=[]){const t=s("div",{className:"spot-table__container",parent:i}),o=s("table",{className:"spot-refund__table spot-table--dynamic",parent:t}),n=s("thead",{parent:o}),r=s("tr",{parent:n});s("th",{text:"When you cancel",parent:r}),s("th",{text:"You will receive",parent:r});const a=s("tbody",{parent:o});e.forEach(({text:p,percent:c,amount:l})=>{const d=s("tr",{parent:a});s("td",{text:p,parent:d});const h=c==="Not eligible for refund"?"Not eligible for a refund":`$${l} refund`;s("td",{text:h,parent:d})})}function k(i,e,t){const o=s("div",{className:"spot-selection__options",parent:i}),n=s("label",{className:`spot-selection__option ${e?"selected":""}`,parent:o}),r=s("input",{parent:n});r.type="radio",r.name="selection",r.value="yes",e&&(r.checked=!0),s("strong",{text:t.yesOptionText,parent:n}),s("span",{className:"spot-selection__recommended-tag",text:"Recommended",parent:n});const a=s("label",{className:"spot-selection__option",parent:o}),p=s("input",{parent:a});return p.type="radio",p.name="selection",p.value="no",s("span",{text:t.noOptionText,parent:a}),o}function x(i,e){var n;const t=(n=e.communication)==null?void 0:n.paymentTerms,o=s("div",{className:"spot-payment-terms",parent:i});return s("div",{className:"spot-payment-terms__header",text:"PAYMENT TERMS",parent:o}),s("div",{className:"spot-payment-terms__body",text:t,parent:o}),o}function q(i,e){const t=s("div",{className:"spot-footer__container",parent:i}),o=s("div",{className:"spot-footer__terms",parent:t});s("span",{innerHTML:e.communication.legalDisclaimer,parent:o}),s("br",{parent:o}),s("a",{href:e.communication.termsAndConditionsUrl,className:"spot-footer__terms-link",text:"Refund Guarantee Terms and Conditions",parent:o});const n=s("p",{className:"spot-footer__powered-by",parent:t});return n.innerHTML=`
5
+ </svg>`,a("span",{text:n,parent:t})})}function $(c,e=[]){if(e.length===0)return;const o=a("div",{className:"spot-covered-items__container",parent:c});a("div",{className:"spot-covered-items__title",text:"Items covered in your cart:",parent:o});const n=a("ul",{className:"spot-covered-items__list",parent:o});e.forEach(t=>{const r=a("li",{parent:n});a("span",{text:t,parent:r})})}function R(c,e=[]){const o=a("div",{className:"spot-table__container",parent:c}),n=a("table",{className:"spot-refund__table spot-table--dynamic",parent:o}),t=a("thead",{parent:n}),r=a("tr",{parent:t});a("th",{text:"When you cancel",parent:r}),a("th",{text:"You will receive",parent:r});const p=a("tbody",{parent:n});e.forEach(({text:i,percent:u,amount:g})=>{const h=a("tr",{parent:p});a("td",{text:i,parent:h});const d=u==="Not eligible for refund"?"Not eligible for a refund":`$${g} refund`;a("td",{text:d,parent:h})})}function Q(c,e,o){const n=a("div",{className:"spot-selection__options",parent:c}),t=a("label",{className:`spot-selection__option ${e?"selected":""}`,parent:n}),r=a("input",{parent:t});r.type="radio",r.name="selection",r.value="yes",e&&(r.checked=!0),a("strong",{text:o.yesOptionText,parent:t}),a("span",{className:"spot-selection__recommended-tag",text:"Recommended",parent:t});const p=a("label",{className:"spot-selection__option",parent:n}),i=a("input",{parent:p});return i.type="radio",i.name="selection",i.value="no",a("span",{text:o.noOptionText,parent:p}),n}function S(c,e){var t;const o=(t=e.communication)==null?void 0:t.paymentTerms,n=a("div",{className:"spot-payment-terms",parent:c});return a("div",{className:"spot-payment-terms__header",text:"PAYMENT TERMS",parent:n}),a("div",{className:"spot-payment-terms__body",text:o,parent:n}),n}function H(c,e){const o=a("div",{className:"spot-footer__container",parent:c}),n=a("div",{className:"spot-footer__terms",parent:o});a("span",{innerHTML:e.communication.legalDisclaimer,parent:n}),a("br",{parent:n}),a("a",{href:e.communication.termsAndConditionsUrl,className:"spot-footer__terms-link",text:"Refund Guarantee Terms and Conditions",parent:n});const t=a("p",{className:"spot-footer__powered-by",parent:o});return t.innerHTML=`
6
6
  <svg width="145" height="28" viewBox="0 0 145 28" fill="none" xmlns="http://www.w3.org/2000/svg">
7
7
  <rect width="145" height="28"/>
8
8
  <rect x="-655" y="-270" width="819" height="325" rx="10"/>
@@ -17,4 +17,4 @@
17
17
  <rect width="45.405" height="14.8867" fill="white" transform="translate(87 8)"/>
18
18
  </clipPath>
19
19
  </defs>
20
- </svg>`,t}const T=":root{--spot-font-family: Arial;--spot-padding: 1.25rem;--spot-background-color: #ffffff;--spot-font-color: #000000;--spot-border-radius: .5rem;--spot-title-font-size: 1.25rem;--spot-title-font-weight: 700;--spot-title-padding: 0 0 1.25rem 0;--spot-description-font-size: .875rem;--spot-description-font-weight: 400;--spot-description-padding: 0 0 .5rem 0;--spot-bullets-font-size: .875rem;--spot-bullets-font-weight: 400;--spot-bullets-padding: .3125rem;--spot-table-border-radius: .625rem;--spot-table-header-font-size: .875rem;--spot-table-header-font-weight: 700;--spot-table-header-padding: 0 .5rem .625rem;--spot-table-cell-font-size: .815rem;--spot-table-cell-font-weight: 400;--spot-table-cell-padding: 0 .625rem;--spot-radio-border: #000000;--spot-radio-border-radius: .625rem;--spot-radio-checked-background: #000000;--spot-radio-text-font-size: .875rem;--spot-radio-text-font-weight: 400;--spot-radio-text-padding: .625rem;--spot-radio-selection-background: #f4f4f4;--spot-radio-selection-border-radius: .625rem;--spot-radio-selection-padding: .625rem;--spot-recommended-tag-background: #000000;--spot-recommended-tag-font-color: #ffffff;--spot-recommended-tag-font-size: .875rem;--spot-recommended-tag-font-weight: 700;--spot-recommended-tag-padding: .25rem .5rem;--spot-recommended-tag-border-radius: .5rem;--spot-selection-error-font-color: #ff0000;--spot-selection-error-font-size: .875rem;--spot-selection-error-padding: .5rem;--spot-payment-terms-background: #f4f4f4;--spot-payment-terms-border-radius: .625rem;--spot-payment-terms-padding: 1rem;--spot-payment-terms-font-color: #636569;--spot-payment-terms-font-size: .75rem;--spot-payment-terms-header-font-weight: 700;--spot-payment-terms-header-font-size: .875rem;--spot-payment-terms-header-margin-bottom: .5rem;--spot-payment-terms-header-border-color: #c2c2c2;--spot-payment-terms-header-padding: 0 0 .5rem 0;--spot-terms-font-size: .75rem;--spot-terms-font-weight: 400;--spot-terms-font-color: #636569;--spot-terms-padding: 0;--spot-terms-link-text-decoration: underline;--spot-terms-link-font-size: .75rem;--spot-terms-link-font-weight: 400;--spot-terms-link-font-color: #636569;--spot-terms-link-padding: 0}.spot-refund-guarantee{font-family:var(--spot-font-family);padding:var(--spot-padding);background-color:var(--spot-background-color);color:var(--spot-font-color);border:.0625rem solid #e0e0e0;border-radius:var(--spot-border-radius);max-width:51rem;margin:1rem}.spot-refund-guarantee *{color:inherit}.spot-header__title{font-size:var(--spot-title-font-size);font-weight:var(--spot-title-font-weight);padding:var(--spot-title-padding);color:var(--spot-title-font-color);font-family:var(--spot-title-font-family);line-height:120%;letter-spacing:-.03125rem}.spot-header__description{font-size:var(--spot-description-font-size);font-weight:var(--spot-description-font-weight);color:var(--spot-description-font-color);font-family:var(--spot-description-font-family);padding:var(--spot-description-padding);line-height:125%;letter-spacing:-.025rem}.spot-content__wrapper{display:flex;flex-direction:column}@media (min-width: 48rem){.spot-content__wrapper.desktop-layout{display:grid;grid-template-columns:1fr 20.3125rem;align-items:start;gap:1rem}.desktop-layout .spot-benefits__list{grid-row:1}.desktop-layout .spot-selection__options{grid-row:2}.desktop-layout .spot-table__container{grid-row:1 / span 2}}@media (max-width: 52.438rem){.spot-selection__recommended-tag{display:inline-block;margin-left:0}}@media (max-width: 47.938rem){.spot-selection__recommended-tag{margin-top:0rem}}@media (max-width: 32.125rem){.spot-selection__recommended-tag{margin-top:.5rem}}@media (max-width: 47.9375rem){.spot-table__container{display:flex;justify-content:center}.spot-selection__recommended-tag{display:inline-block;margin-left:0}.spot-footer__container{flex-direction:column;margin-top:.5rem}.spot-refund__table{width:100%;table-layout:auto}.spot-refund__table th{padding:0rem}}.spot-benefits__list{list-style-type:none;line-height:125%;gap:.5625rem;font-size:var(--spot-bullets-font-size);font-weight:var(--spot-bullets-font-weight);color:var(--spot-bullets-font-color);font-family:var(--spot-bullets-font-family);padding:var(--spot-bullets-padding);margin-block-start:0rem;margin-block-end:0rem}.spot-benefits__list li{margin-bottom:.5rem;display:flex;align-items:flex-start;gap:.5rem}.spot-benefits__list li svg{flex-shrink:0;position:relative;top:.125rem}.spot-table__container{width:100%}.spot-refund__table{max-width:22rem;border-radius:var(--spot-table-border-radius);overflow:hidden;border:.09375rem solid #636569;table-layout:fixed;margin-bottom:1.5rem;margin-top:.25rem;padding:.625rem}.spot-refund__table--dynamic{height:auto!important;min-height:7.5rem}.spot-refund__table td,.spot-refund__table th{padding:.375rem .625rem;text-align:left}.spot-refund__table th{text-align:left;font-size:var(--spot-table-header-font-size);font-weight:var(--spot-table-header-font-weight);color:var(--spot-table-header-font-color);font-family:var(--spot-table-header-font-family);padding:var(--spot-table-header-padding)}.spot-refund__table td{text-align:left;font-size:var(--spot-table-cell-font-size);font-weight:var(--spot-table-cell-font-weight);color:var(--spot-table-cell-font-color);font-family:var(--spot-table-cell-font-family);padding:var(--spot-table-cell-padding)}input[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:.75rem;height:.75rem;border:.0625rem solid var(--spot-radio-border);border-radius:var(--spot-radio-border-radius);margin-right:.5rem;position:relative;vertical-align:middle;top:-.0625rem;cursor:pointer}input[type=radio]:checked{background:var(--spot-radio-checked-background);box-shadow:inset 0 0 0 .0625rem #fff}.spot-selection__options{display:flex;flex-direction:column;gap:.5rem}.spot-selection__option{display:block;position:relative;transition:background .2s;cursor:pointer;font-size:var(--spot-radio-text-font-size);font-weight:var(--spot-radio-text-font-weight);color:var(--spot-radio-text-font-color);font-family:var(--spot-radio-text-font-family);padding:var(--spot-radio-text-padding);margin-right:.5rem;gap:.5rem;flex:1 0 0;align-self:stretch}.spot-selection__option.selected{background:var(--spot-radio-selection-background);border-radius:var(--spot-radio-selection-border-radius);padding:var(--spot-radio-selection-padding)}.spot-selection__recommended-tag{background:var(--spot-recommended-tag-background);color:var(--spot-recommended-tag-font-color);font-size:var(--spot-recommended-tag-font-size);font-weight:var(--spot-recommended-tag-font-weight);padding:var(--spot-recommended-tag-padding);border-radius:var(--spot-recommended-tag-border-radius);margin-left:1.5rem;white-space:nowrap}.spot-selection__error{color:var(--spot-selection-error-font-color);font-size:var(--spot-selection-error-font-size);padding:var(--spot-selection-error-padding);display:none}.spot-payment-terms__wrapper{margin-top:1rem}.spot-payment-terms__header{font-weight:var(--spot-payment-terms-header-font-weight);margin-bottom:.5rem;padding:var(--spot-payment-terms-header-padding);font-size:var(--spot-payment-terms-header-font-size);border-bottom:1px solid var(--spot-payment-terms-header-border-color)}.spot-payment-terms{background-color:var(--spot-payment-terms-background);border-radius:var(--spot-payment-terms-border-radius);padding:var(--spot-payment-terms-padding);margin-right:.5rem;color:var(--spot-payment-terms-font-color);font-size:var(--spot-payment-terms-font-size)}.spot-footer__terms{margin-top:.625rem;margin-right:.25rem;font-size:var(--spot-terms-font-size);font-weight:var(--spot-terms-font-weight);color:var(--spot-terms-font-color);font-family:var(--spot-terms-font-family);padding:var(--spot-terms-padding)}.spot-footer__terms-link{text-decoration:var(--spot-terms-link-text-decoration);font-size:var(--spot-terms-link-font-size);font-weight:var(--spot-terms-link-font-weight);color:var(--spot-terms-link-font-color);font-family:var(--spot-terms-link-font-family);padding:var(--spot-terms-link-padding)}.spot-footer__container{display:flex;justify-content:space-between;align-items:center}.spot-footer__powered-by{margin-top:1.5rem}";function H(i){const e=document.createElement("style");e.textContent=i,document.head.appendChild(e)}H(T);const b={sandbox:"https://api.sandbox.getspot.com/api/v1/quote",production:"https://api.getspot.com/api/v1/quote"};class z{constructor(e={}){this.options={location:"body",showTable:!0,optInSelected:!1,apiConfig:{environment:"production",partnerId:""},quoteRequestData:{},callbacks:{},...e},this._onResize=this._updateLayout.bind(this),this.root=typeof this.options.location=="string"?document.querySelector(this.options.location):this.options.location,this.currentSelection=this.options.optInSelected?"yes":null,this._init()}async _init(){var e,t,o,n,r;try{g(this.options);const{environment:a,partnerId:p}=this.options.apiConfig,l=this.options.apiConfig.customEndpoint||b[a],d=await u(l,p,this.options.quoteRequestData);if(d.status!=="QUOTE_AVAILABLE"){d.status==="NO_MATCHING_QUOTE"&&((e=this.options.callbacks)!=null&&e.noMatchingQuote)&&this.options.callbacks.noMatchingQuote({status:"NO_MATCHING_QUOTE",data:this.options.quoteRequestData});return}this.quote=d.data,this._renderWidget(),this.options.optInSelected&&((t=this.options.callbacks)!=null&&t.onOptIn)&&this.options.callbacks.onOptIn({status:"QUOTE_ACCEPTED",spotPrice:this.quote.spotPrice,quoteId:this.quote.id}),(o=this.options.callbacks)!=null&&o.onQuoteRetrieved&&this.options.callbacks.onQuoteRetrieved(this.quote)}catch(a){(n=this.options.callbacks)!=null&&n.onError&&((r=this.options.callbacks)==null||r.onError({message:a.message,status:a.status,responseBody:a.responseBody}))}}_renderWidget(){this.container=document.createElement("div"),this.container.className="spot-refund-guarantee",this.root.appendChild(this.container),Object.entries(this.options.theme||{}).forEach(([o,n])=>{const r=`--${o}`;this.container.style.setProperty(r,n)}),w(this.container,this.quote.communication);const e=document.createElement("div");e.className="spot-content__wrapper",this.container.appendChild(e),C(e,this.quote.communication.bulletPoints),this.options.showTable&&E(e,this.quote.payoutSchedule);const t=k(e,this.options.optInSelected,this.quote.communication);e.appendChild(t),this.paymentTermsEl=s("div",{className:"spot-payment-terms__wrapper",parent:e}),q(this.container,this.quote),window.addEventListener("resize",this._onResize),this._updateLayout(),this._setupOptionListeners(t)}_updateLayout(){const e=window.matchMedia("(min-width: 768px)").matches;this.container.querySelector(".spot-content__wrapper").classList.toggle("desktop-layout",e&&this.options.showTable)}_setupOptionListeners(e){const t=e.querySelectorAll('input[type="radio"]'),o=e.querySelectorAll(".spot-selection__option");t.forEach(n=>{n.addEventListener("change",r=>{var p,c,l;const a=r.target.value;this.hideSelectionError(),this.currentSelection=a,o.forEach(d=>d.classList.remove("selected")),(p=r.target.closest(".spot-selection__option"))==null||p.classList.add("selected"),this.paymentTermsEl&&(this.paymentTermsEl.innerHTML=""),a==="yes"&&(this.options.quoteRequestData.isPartialPayment&&x(this.paymentTermsEl,this.quote),(c=this.options.callbacks)!=null&&c.onOptIn&&this.options.callbacks.onOptIn({status:"QUOTE_ACCEPTED",spotPrice:this.quote.spotPrice,quoteId:this.quote.id})),a==="no"&&((l=this.options.callbacks)!=null&&l.onOptOut)&&this.options.callbacks.onOptOut({status:"QUOTE_DECLINED",quoteId:this.quote.id})})})}showSelectionError(){var e;if(!this.errorEl){this.errorEl=document.createElement("div"),this.errorEl.className="spot-selection__error",this.errorEl.textContent="Please make a selection";const t=(e=this.container)==null?void 0:e.querySelector(".spot-selection__options");t&&t.insertAdjacentElement("afterend",this.errorEl)}this.errorEl.style.display="block"}hideSelectionError(){this.errorEl&&(this.errorEl.style.display="none")}validateSelection(){if(!this.container)return!1;const e=!!this.container.querySelector('input[name="selection"]:checked');return e?this.hideSelectionError():this.showSelectionError(),e}async updateQuote(e){var t,o,n;try{const r={...this.options,quoteRequestData:{...this.options.quoteRequestData,...e}};g(r);const{environment:a,partnerId:p,endpoint:c}=this.options.apiConfig,l=c||b[a],d=await u(l,p,r.quoteRequestData);return d.status!=="QUOTE_AVAILABLE"?(d.status==="NO_MATCHING_QUOTE"&&((t=this.options.callbacks)!=null&&t.noMatchingQuote)&&this.options.callbacks.noMatchingQuote({status:"NO_MATCHING_QUOTE",data:r.quoteRequestData}),!1):(this.options.quoteRequestData=r.quoteRequestData,this.quote=d.data,this.currentSelection=null,this.destroy(),this._renderWidget(),(o=this.options.callbacks)!=null&&o.onQuoteRetrieved&&this.options.callbacks.onQuoteRetrieved(this.quote),!0)}catch(r){return(n=this.options.callbacks)==null||n.onError({message:r.message,status:r.status,responseBody:r.responseBody}),!1}}getSelection(){var e,t;return this.currentSelection==null?null:{selection:this.currentSelection,quoteId:(e=this.quote)==null?void 0:e.id,spotPrice:(t=this.quote)==null?void 0:t.spotPrice,status:this.currentSelection==="yes"?"QUOTE_ACCEPTED":"QUOTE_DECLINED"}}destroy(){window.removeEventListener("resize",this._onResize),this.container&&this.container.parentNode&&this.container.parentNode.removeChild(this.container)}}return z});
20
+ </svg>`,o}const z=":root{--spot-font-family: Arial;--spot-padding: 1.25rem;--spot-background-color: #ffffff;--spot-font-color: #000000;--spot-border-radius: .5rem;--spot-title-font-size: 1.25rem;--spot-title-font-weight: 700;--spot-title-padding: 0 0 1.25rem 0;--spot-description-font-size: .875rem;--spot-description-font-weight: 400;--spot-description-padding: 0 0 .5rem 0;--spot-bullets-font-size: .875rem;--spot-bullets-font-weight: 400;--spot-bullets-padding: .3125rem;--spot-table-border-radius: .625rem;--spot-table-header-font-size: .875rem;--spot-table-header-font-weight: 700;--spot-table-header-padding: 0 .5rem .625rem;--spot-table-cell-font-size: .815rem;--spot-table-cell-font-weight: 400;--spot-table-cell-padding: 0 .625rem;--spot-radio-border: #000000;--spot-radio-border-radius: .625rem;--spot-radio-checked-background: #000000;--spot-radio-text-font-size: .875rem;--spot-radio-text-font-weight: 400;--spot-radio-text-padding: .625rem;--spot-radio-selection-background: #f4f4f4;--spot-radio-selection-border-radius: .625rem;--spot-radio-selection-padding: .625rem;--spot-recommended-tag-background: #000000;--spot-recommended-tag-font-color: #ffffff;--spot-recommended-tag-font-size: .875rem;--spot-recommended-tag-font-weight: 700;--spot-recommended-tag-padding: .25rem .5rem;--spot-recommended-tag-border-radius: .5rem;--spot-selection-error-font-color: #ff0000;--spot-selection-error-font-size: .875rem;--spot-selection-error-padding: .5rem;--spot-payment-terms-background: #f4f4f4;--spot-payment-terms-border-radius: .625rem;--spot-payment-terms-padding: 1rem;--spot-payment-terms-font-color: #636569;--spot-payment-terms-font-size: .75rem;--spot-payment-terms-header-font-weight: 700;--spot-payment-terms-header-font-size: .875rem;--spot-payment-terms-header-margin-bottom: .5rem;--spot-payment-terms-header-border-color: #c2c2c2;--spot-payment-terms-header-padding: 0 0 .5rem 0;--spot-terms-font-size: .75rem;--spot-terms-font-weight: 400;--spot-terms-font-color: #636569;--spot-terms-padding: 0;--spot-terms-link-text-decoration: underline;--spot-terms-link-font-size: .75rem;--spot-terms-link-font-weight: 400;--spot-terms-link-font-color: #636569;--spot-terms-link-padding: 0}.spot-refund-guarantee{font-family:var(--spot-font-family);padding:var(--spot-padding);background-color:var(--spot-background-color);color:var(--spot-font-color);border:.0625rem solid #e0e0e0;border-radius:var(--spot-border-radius);max-width:51rem;margin:1rem}.spot-refund-guarantee *{color:inherit}.spot-header__title{font-size:var(--spot-title-font-size);font-weight:var(--spot-title-font-weight);padding:var(--spot-title-padding);color:var(--spot-title-font-color);font-family:var(--spot-title-font-family);line-height:120%;letter-spacing:-.03125rem}.spot-header__description{font-size:var(--spot-description-font-size);font-weight:var(--spot-description-font-weight);color:var(--spot-description-font-color);font-family:var(--spot-description-font-family);padding:var(--spot-description-padding);line-height:125%;letter-spacing:-.025rem}.spot-content__wrapper{display:flex;flex-direction:column}@media (min-width: 48rem){.spot-content__wrapper.desktop-layout{display:grid;grid-template-columns:1fr 20.3125rem;align-items:start;gap:1rem}.desktop-layout .spot-benefits__list{grid-row:1}.desktop-layout .spot-covered-items__container{grid-row:2;grid-column:1}.desktop-layout .spot-selection__options{grid-row:3}.desktop-layout .spot-table__container{grid-row:1 / span 3}}@media (max-width: 52.438rem){.spot-selection__recommended-tag{display:inline-block;margin-left:0}}@media (max-width: 47.938rem){.spot-selection__recommended-tag{margin-top:0rem}}@media (max-width: 32.125rem){.spot-selection__recommended-tag{margin-top:.5rem}}@media (max-width: 47.9375rem){.spot-table__container{display:flex;justify-content:center}.spot-selection__recommended-tag{display:inline-block;margin-left:0}.spot-footer__container{flex-direction:column;margin-top:.5rem}.spot-refund__table{width:100%;table-layout:auto}.spot-refund__table th{padding:0rem}}.spot-benefits__list{list-style-type:none;line-height:125%;gap:.5625rem;font-size:var(--spot-bullets-font-size);font-weight:var(--spot-bullets-font-weight);color:var(--spot-bullets-font-color);font-family:var(--spot-bullets-font-family);padding:var(--spot-bullets-padding);margin-block-start:0rem;margin-block-end:0rem}.spot-benefits__list li{margin-bottom:.5rem;display:flex;align-items:flex-start;gap:.5rem}.spot-benefits__list li svg{flex-shrink:0;position:relative;top:.125rem}.spot-covered-items__container{margin-top:0;margin-bottom:1rem}.spot-covered-items__title{font-size:var(--spot-description-font-size);font-weight:var(--spot-description-font-weight);color:var(--spot-description-font-color);font-family:var(--spot-description-font-family);padding:0 .3125rem .25rem;line-height:125%;margin:0}.spot-covered-items__list{list-style-type:disc;list-style-position:inside;line-height:125%;gap:.5625rem;font-size:var(--spot-bullets-font-size);font-weight:var(--spot-bullets-font-weight);color:var(--spot-bullets-font-color);font-family:var(--spot-bullets-font-family);padding:var(--spot-bullets-padding);margin-block-start:0rem;margin-block-end:0rem}.spot-covered-items__list li{margin-bottom:.3rem;text-align:left}.spot-table__container{width:100%}.spot-refund__table{max-width:22rem;border-radius:var(--spot-table-border-radius);overflow:hidden;border:.09375rem solid #636569;table-layout:fixed;margin-bottom:1.5rem;margin-top:.25rem;padding:.625rem}.spot-refund__table--dynamic{height:auto!important;min-height:7.5rem}.spot-refund__table td,.spot-refund__table th{padding:.375rem .625rem;text-align:left}.spot-refund__table th{text-align:left;font-size:var(--spot-table-header-font-size);font-weight:var(--spot-table-header-font-weight);color:var(--spot-table-header-font-color);font-family:var(--spot-table-header-font-family);padding:var(--spot-table-header-padding)}.spot-refund__table td{text-align:left;font-size:var(--spot-table-cell-font-size);font-weight:var(--spot-table-cell-font-weight);color:var(--spot-table-cell-font-color);font-family:var(--spot-table-cell-font-family);padding:var(--spot-table-cell-padding)}input[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:.75rem;height:.75rem;border:.0625rem solid var(--spot-radio-border);border-radius:var(--spot-radio-border-radius);margin-right:.5rem;position:relative;vertical-align:middle;top:-.0625rem;cursor:pointer}input[type=radio]:checked{background:var(--spot-radio-checked-background);box-shadow:inset 0 0 0 .0625rem #fff}.spot-selection__options{display:flex;flex-direction:column;gap:.5rem}.spot-selection__option{display:block;position:relative;transition:background .2s;cursor:pointer;font-size:var(--spot-radio-text-font-size);font-weight:var(--spot-radio-text-font-weight);color:var(--spot-radio-text-font-color);font-family:var(--spot-radio-text-font-family);padding:var(--spot-radio-text-padding);margin-right:.5rem;gap:.5rem;flex:1 0 0;align-self:stretch}.spot-selection__option.selected{background:var(--spot-radio-selection-background);border-radius:var(--spot-radio-selection-border-radius);padding:var(--spot-radio-selection-padding)}.spot-selection__recommended-tag{background:var(--spot-recommended-tag-background);color:var(--spot-recommended-tag-font-color);font-size:var(--spot-recommended-tag-font-size);font-weight:var(--spot-recommended-tag-font-weight);padding:var(--spot-recommended-tag-padding);border-radius:var(--spot-recommended-tag-border-radius);margin-left:1.5rem;white-space:nowrap}.spot-selection__error{color:var(--spot-selection-error-font-color);font-size:var(--spot-selection-error-font-size);padding:var(--spot-selection-error-padding);display:none}.spot-payment-terms__wrapper{margin-top:1rem}.spot-payment-terms__header{font-weight:var(--spot-payment-terms-header-font-weight);margin-bottom:.5rem;padding:var(--spot-payment-terms-header-padding);font-size:var(--spot-payment-terms-header-font-size);border-bottom:1px solid var(--spot-payment-terms-header-border-color)}.spot-payment-terms{background-color:var(--spot-payment-terms-background);border-radius:var(--spot-payment-terms-border-radius);padding:var(--spot-payment-terms-padding);margin-right:.5rem;color:var(--spot-payment-terms-font-color);font-size:var(--spot-payment-terms-font-size)}.spot-footer__terms{margin-top:.625rem;margin-right:.25rem;font-size:var(--spot-terms-font-size);font-weight:var(--spot-terms-font-weight);color:var(--spot-terms-font-color);font-family:var(--spot-terms-font-family);padding:var(--spot-terms-padding)}.spot-footer__terms-link{text-decoration:var(--spot-terms-link-text-decoration);font-size:var(--spot-terms-link-font-size);font-weight:var(--spot-terms-link-font-weight);color:var(--spot-terms-link-font-color);font-family:var(--spot-terms-link-font-family);padding:var(--spot-terms-link-padding)}.spot-footer__container{display:flex;justify-content:space-between;align-items:center}.spot-footer__powered-by{margin-top:1.5rem}";function M(c){const e=document.createElement("style");e.textContent=c,document.head.appendChild(e)}M(z);const k={sandbox:"https://api.sandbox.getspot.com/api/v1/quote",production:"https://api.getspot.com/api/v1/quote",local:"http://localhost:3999/api/v1/quote"};class L{constructor(e={}){this.options={location:"body",showTable:!0,optInSelected:!1,apiConfig:{environment:"production",partnerId:""},quoteRequestData:{},callbacks:{},...e},this._onResize=this._updateLayout.bind(this),this.root=typeof this.options.location=="string"?document.querySelector(this.options.location):this.options.location,this.currentSelection=this.options.optInSelected?"yes":null,this._init()}async _init(){var e,o,n,t,r;try{D(this.options);const{environment:p,partnerId:i}=this.options.apiConfig,g=this.options.apiConfig.customEndpoint||k[p],d=this.options.quoteRequestData.cartInfo&&this.options.quoteRequestData.items?await I(g,i,this.options.quoteRequestData):await _(g,i,this.options.quoteRequestData);if(d.status!=="QUOTE_AVAILABLE"){d.status==="NO_MATCHING_QUOTE"&&((e=this.options.callbacks)!=null&&e.noMatchingQuote)&&this.options.callbacks.noMatchingQuote({status:"NO_MATCHING_QUOTE",data:this.options.quoteRequestData});return}if(this.quote=d.data,this._renderWidget(),this.options.optInSelected&&((o=this.options.callbacks)!=null&&o.onOptIn)){const b={status:"QUOTE_ACCEPTED",spotPrice:this.quote.spotPrice,quoteId:this.quote.id};this.quote.originalQuotes&&this.quote.originalQuotes.length>0&&(b.batchQuoteDetails=this.quote.originalQuotes.map(s=>{var f;const l=(f=this.options.quoteRequestData.items)==null?void 0:f.find(w=>(w.cartItemId||`item-${this.options.quoteRequestData.items.indexOf(w)+1}`)===s.cartItemId);return{quoteId:s.id,productPrice:(l==null?void 0:l.productPrice)||s.spotPrice,cartItemId:s.cartItemId}})),this.options.callbacks.onOptIn(b)}(n=this.options.callbacks)!=null&&n.onQuoteRetrieved&&this.options.callbacks.onQuoteRetrieved(this.quote)}catch(p){(t=this.options.callbacks)!=null&&t.onError&&((r=this.options.callbacks)==null||r.onError({message:p.message,status:p.status,responseBody:p.responseBody}))}}_renderWidget(){this.container=document.createElement("div"),this.container.className="spot-refund-guarantee",this.root.appendChild(this.container),Object.entries(this.options.theme||{}).forEach(([n,t])=>{const r=`--${n}`;this.container.style.setProperty(r,t)}),O(this.container,this.quote.communication);const e=document.createElement("div");e.className="spot-content__wrapper",this.container.appendChild(e),P(e,this.quote.communication.bulletPoints),this.quote.coveredItems&&$(e,this.quote.coveredItems),this.options.showTable&&R(e,this.quote.payoutSchedule);const o=Q(e,this.options.optInSelected,this.quote.communication);e.appendChild(o),this.paymentTermsEl=a("div",{className:"spot-payment-terms__wrapper",parent:e}),H(this.container,this.quote),window.addEventListener("resize",this._onResize),this._updateLayout(),this._setupOptionListeners(o)}_updateLayout(){const e=window.matchMedia("(min-width: 768px)").matches;this.container.querySelector(".spot-content__wrapper").classList.toggle("desktop-layout",e&&this.options.showTable)}_setupOptionListeners(e){const o=e.querySelectorAll('input[type="radio"]'),n=e.querySelectorAll(".spot-selection__option");o.forEach(t=>{t.addEventListener("change",r=>{var i,u,g;const p=r.target.value;if(this.hideSelectionError(),this.currentSelection=p,n.forEach(h=>h.classList.remove("selected")),(i=r.target.closest(".spot-selection__option"))==null||i.classList.add("selected"),this.paymentTermsEl&&(this.paymentTermsEl.innerHTML=""),p==="yes"&&(this.options.quoteRequestData.isPartialPayment&&S(this.paymentTermsEl,this.quote),(u=this.options.callbacks)!=null&&u.onOptIn)){const h={status:"QUOTE_ACCEPTED",spotPrice:this.quote.spotPrice,quoteId:this.quote.id};this.quote.originalQuotes&&this.quote.originalQuotes.length>0&&(h.batchQuoteDetails=this.quote.originalQuotes.map(d=>{var s;const b=(s=this.options.quoteRequestData.items)==null?void 0:s.find(l=>(l.cartItemId||`item-${this.options.quoteRequestData.items.indexOf(l)+1}`)===d.cartItemId);return{quoteId:d.id,productPrice:(b==null?void 0:b.productPrice)||d.spotPrice,cartItemId:d.cartItemId}})),this.options.callbacks.onOptIn(h)}if(p==="no"&&((g=this.options.callbacks)!=null&&g.onOptOut)){const h={status:"QUOTE_DECLINED",quoteId:this.quote.id};this.quote.originalQuotes&&this.quote.originalQuotes.length>0&&(h.batchQuoteDetails=this.quote.originalQuotes.map(d=>{var s;const b=(s=this.options.quoteRequestData.items)==null?void 0:s.find(l=>(l.cartItemId||`item-${this.options.quoteRequestData.items.indexOf(l)+1}`)===d.cartItemId);return{quoteId:d.id,productPrice:(b==null?void 0:b.productPrice)||d.spotPrice,cartItemId:d.cartItemId}})),this.options.callbacks.onOptOut(h)}})})}showSelectionError(){var e;if(!this.errorEl){this.errorEl=document.createElement("div"),this.errorEl.className="spot-selection__error",this.errorEl.textContent="Please make a selection";const o=(e=this.container)==null?void 0:e.querySelector(".spot-selection__options");o&&o.insertAdjacentElement("afterend",this.errorEl)}this.errorEl.style.display="block"}hideSelectionError(){this.errorEl&&(this.errorEl.style.display="none")}validateSelection(){if(!this.container)return!1;const e=!!this.container.querySelector('input[name="selection"]:checked');return e?this.hideSelectionError():this.showSelectionError(),e}async updateQuote(e){var o,n,t;try{const r={...this.options,quoteRequestData:e};D(r);const{environment:p,partnerId:i,endpoint:u}=this.options.apiConfig,g=u||k[p],d=r.quoteRequestData.cartInfo&&r.quoteRequestData.items?await I(g,i,r.quoteRequestData):await _(g,i,r.quoteRequestData);return d.status!=="QUOTE_AVAILABLE"?(d.status==="NO_MATCHING_QUOTE"&&((o=this.options.callbacks)!=null&&o.noMatchingQuote)&&this.options.callbacks.noMatchingQuote({status:"NO_MATCHING_QUOTE",data:r.quoteRequestData}),!1):(this.options.quoteRequestData=r.quoteRequestData,this.quote=d.data,this.currentSelection=null,this.destroy(),this._renderWidget(),(n=this.options.callbacks)!=null&&n.onQuoteRetrieved&&this.options.callbacks.onQuoteRetrieved(this.quote),!0)}catch(r){return(t=this.options.callbacks)==null||t.onError({message:r.message,status:r.status,responseBody:r.responseBody}),!1}}getSelection(){var o,n,t;if(this.currentSelection==null)return null;const e={selection:this.currentSelection,quoteId:(o=this.quote)==null?void 0:o.id,spotPrice:(n=this.quote)==null?void 0:n.spotPrice,status:this.currentSelection==="yes"?"QUOTE_ACCEPTED":"QUOTE_DECLINED"};return(t=this.quote)!=null&&t.originalQuotes&&this.quote.originalQuotes.length>0&&(e.batchQuoteDetails=this.quote.originalQuotes.map(r=>{var i;const p=(i=this.options.quoteRequestData.items)==null?void 0:i.find(u=>(u.cartItemId||`item-${this.options.quoteRequestData.items.indexOf(u)+1}`)===r.cartItemId);return{quoteId:r.id,productPrice:(p==null?void 0:p.productPrice)||r.spotPrice,cartItemId:r.cartItemId}})),e}destroy(){window.removeEventListener("resize",this._onResize),this.container&&this.container.parentNode&&this.container.parentNode.removeChild(this.container)}}return L});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getspot/spot-widget",
3
- "version": "1.1.1",
3
+ "version": "1.3.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
package/src/api.js CHANGED
@@ -30,3 +30,125 @@ export async function fetchQuote(endpoint, partnerId, payload) {
30
30
  : new Error("Unknown error occurred while fetching quote");
31
31
  }
32
32
  }
33
+
34
+ /**
35
+ * Retrieve batch quote from Spot API
36
+ * @param {string} endpoint – Spot API URL
37
+ * @param {string} partnerId – partner UUID
38
+ * @param {object} batchPayload – batch request data with items array
39
+ * @returns {Promise<{ status: string, data?: object }>}
40
+ */
41
+ export async function fetchBatchQuote(endpoint, partnerId, batchPayload) {
42
+ try {
43
+ const batchEndpoint = endpoint.replace('/quote', '/quote/batch');
44
+ const res = await fetch(batchEndpoint, {
45
+ method: "POST",
46
+ headers: {
47
+ "Content-Type": "application/json",
48
+ "X-Spot-Partner-Id": partnerId,
49
+ },
50
+ body: JSON.stringify(batchPayload),
51
+ });
52
+ const body = await res.json();
53
+ if (!res.ok) {
54
+ const error = new Error(body?.message || "Failed to fetch batch quote");
55
+ error.status = res.status;
56
+ error.responseBody = body;
57
+ throw error;
58
+ }
59
+
60
+ return body;
61
+ } catch (err) {
62
+ throw err instanceof Error
63
+ ? err
64
+ : new Error("Unknown error occurred while fetching batch quote");
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Retrieve multiple quotes in parallel from Spot API
70
+ * @param {string} endpoint – Spot API URL
71
+ * @param {string} partnerId – partner UUID
72
+ * @param {object} batchData – batch quote data with cartInfo and items
73
+ * @param {object} batchData.cartInfo – cart-level information
74
+ * @param {string} batchData.cartInfo.cartId – cart ID
75
+ * @param {string} batchData.cartInfo.cartName – cart name
76
+ * @param {string} batchData.cartInfo.currencyCode – currency code
77
+ * @param {object[]} batchData.items – array of item data
78
+ * @returns {Promise<{ status: string, data?: object, spotPrice?: number, coveredItems?: string[] }>}
79
+ */
80
+ export async function fetchMultipleQuotes(endpoint, partnerId, batchData) {
81
+ try {
82
+ // Transform into batch format for API
83
+ const batchPayload = {
84
+ cartId: batchData.cartInfo.cartId,
85
+ cartName: batchData.cartInfo.cartName,
86
+ currencyCode: batchData.cartInfo.currencyCode,
87
+ items: batchData.items.map((item, index) => ({
88
+ cartItemId: item.cartItemId || `item-${index + 1}`,
89
+ productPrice: item.productPrice,
90
+ productType: item.productType,
91
+ productDuration: item.productDuration,
92
+ productId: item.productId,
93
+ productName: item.productName,
94
+ participantDescription: item.participantDescription,
95
+ eventType: item.eventType,
96
+ startDate: item.startDate,
97
+ endDate: item.endDate
98
+ }))
99
+ };
100
+
101
+ const response = await fetchBatchQuote(endpoint, partnerId, batchPayload);
102
+
103
+ // Check for various success statuses
104
+ if (response.status !== "QUOTES_AVAILABLE" && response.status !== "QUOTE_AVAILABLE") {
105
+ return { status: "NO_MATCHING_QUOTE" };
106
+ }
107
+
108
+ // Extract covered items only for successful quotes
109
+ const coveredItems = response.quotes.map(quote => {
110
+ // Find the corresponding item from the original request using cartItemId
111
+ const originalItem = batchData.items.find(item =>
112
+ (item.cartItemId || `item-${batchData.items.indexOf(item) + 1}`) === quote.cartItemId
113
+ );
114
+
115
+ if (originalItem) {
116
+ return originalItem.participantDescription
117
+ ? `${originalItem.productName} - ${originalItem.participantDescription}`
118
+ : originalItem.productName;
119
+ }
120
+
121
+ // Fallback if we can't find the original item
122
+ return `Item ${quote.cartItemId}`;
123
+ });
124
+
125
+ // Fix floating point precision issue
126
+ const totalSpotPrice = Math.round((response.totalSpotPrice || response.spotPrice || 0) * 100) / 100;
127
+
128
+ // Build response in expected format
129
+ return {
130
+ status: "QUOTE_AVAILABLE",
131
+ data: {
132
+ id: response.quotes ? response.quotes.map(q => q.id).join(',') : response.id,
133
+ spotPrice: totalSpotPrice,
134
+ currencyCode: response.currencyCode,
135
+ communication: {
136
+ ...response.communication,
137
+ yesOptionText: response.communication.yesOptionText.replace(response.totalSpotPrice, totalSpotPrice)
138
+ },
139
+ payoutSchedule: response.payoutSchedule.map(item => ({
140
+ ...item,
141
+ amount: item.amount !== undefined ? item.amount : 0
142
+ })),
143
+ coveredItems: coveredItems,
144
+ originalQuotes: response.quotes || [response]
145
+ },
146
+ spotPrice: totalSpotPrice,
147
+ coveredItems
148
+ };
149
+ } catch (err) {
150
+ throw err instanceof Error
151
+ ? err
152
+ : new Error("Unknown error occurred while fetching multiple quotes");
153
+ }
154
+ }
package/src/index.js CHANGED
@@ -1,8 +1,9 @@
1
- import { fetchQuote } from "./api.js";
1
+ import { fetchQuote, fetchMultipleQuotes } from "./api.js";
2
2
  import { validateOptions } from "./validateOptions.js";
3
3
  import {
4
4
  renderHeader,
5
5
  renderBenefits,
6
+ renderCoveredItems,
6
7
  renderTable,
7
8
  renderOptions,
8
9
  renderFooter,
@@ -23,6 +24,7 @@ injectStyles(styles);
23
24
  const apiEndpoint = {
24
25
  sandbox: "https://api.sandbox.getspot.com/api/v1/quote",
25
26
  production: "https://api.getspot.com/api/v1/quote",
27
+ local: "http://localhost:3999/api/v1/quote"
26
28
  };
27
29
 
28
30
  class SpotWidget {
@@ -56,11 +58,10 @@ class SpotWidget {
56
58
 
57
59
  const endpoint = customEndpoint || apiEndpoint[environment];
58
60
 
59
- const response = await fetchQuote(
60
- endpoint,
61
- partnerId,
62
- this.options.quoteRequestData
63
- );
61
+ const isBatchQuote = this.options.quoteRequestData.cartInfo && this.options.quoteRequestData.items;
62
+ const response = isBatchQuote
63
+ ? await fetchMultipleQuotes(endpoint, partnerId, this.options.quoteRequestData)
64
+ : await fetchQuote(endpoint, partnerId, this.options.quoteRequestData);
64
65
 
65
66
  if (response.status !== "QUOTE_AVAILABLE") {
66
67
  if (
@@ -79,11 +80,27 @@ class SpotWidget {
79
80
  this._renderWidget();
80
81
 
81
82
  if (this.options.optInSelected && this.options.callbacks?.onOptIn) {
82
- this.options.callbacks.onOptIn({
83
+ const optInData = {
83
84
  status: "QUOTE_ACCEPTED",
84
85
  spotPrice: this.quote.spotPrice,
85
- quoteId: this.quote.id,
86
- });
86
+ quoteId: this.quote.id
87
+ };
88
+
89
+ // For batch quotes, include detailed quote information
90
+ if (this.quote.originalQuotes && this.quote.originalQuotes.length > 0) {
91
+ optInData.batchQuoteDetails = this.quote.originalQuotes.map(q => {
92
+ const originalItem = this.options.quoteRequestData.items?.find(item =>
93
+ (item.cartItemId || `item-${this.options.quoteRequestData.items.indexOf(item) + 1}`) === q.cartItemId
94
+ );
95
+ return {
96
+ quoteId: q.id,
97
+ productPrice: originalItem?.productPrice || q.spotPrice,
98
+ cartItemId: q.cartItemId
99
+ };
100
+ });
101
+ }
102
+
103
+ this.options.callbacks.onOptIn(optInData);
87
104
  }
88
105
 
89
106
  if (this.options.callbacks?.onQuoteRetrieved) {
@@ -116,6 +133,9 @@ class SpotWidget {
116
133
  this.container.appendChild(cw);
117
134
 
118
135
  renderBenefits(cw, this.quote.communication.bulletPoints);
136
+ if (this.quote.coveredItems) {
137
+ renderCoveredItems(cw, this.quote.coveredItems);
138
+ }
119
139
  if (this.options.showTable) renderTable(cw, this.quote.payoutSchedule);
120
140
  const optsEl = renderOptions(
121
141
  cw,
@@ -162,18 +182,50 @@ class SpotWidget {
162
182
  renderPaymentTerms(this.paymentTermsEl, this.quote);
163
183
  }
164
184
  if (this.options.callbacks?.onOptIn) {
165
- this.options.callbacks.onOptIn({
185
+ const optInData = {
166
186
  status: "QUOTE_ACCEPTED",
167
187
  spotPrice: this.quote.spotPrice,
168
- quoteId: this.quote.id,
169
- });
188
+ quoteId: this.quote.id
189
+ };
190
+
191
+ // For batch quotes, include detailed quote information
192
+ if (this.quote.originalQuotes && this.quote.originalQuotes.length > 0) {
193
+ optInData.batchQuoteDetails = this.quote.originalQuotes.map(q => {
194
+ const originalItem = this.options.quoteRequestData.items?.find(item =>
195
+ (item.cartItemId || `item-${this.options.quoteRequestData.items.indexOf(item) + 1}`) === q.cartItemId
196
+ );
197
+ return {
198
+ quoteId: q.id,
199
+ productPrice: originalItem?.productPrice || q.spotPrice,
200
+ cartItemId: q.cartItemId
201
+ };
202
+ });
203
+ }
204
+
205
+ this.options.callbacks.onOptIn(optInData);
170
206
  }
171
207
  }
172
208
  if (val === "no" && this.options.callbacks?.onOptOut) {
173
- this.options.callbacks.onOptOut({
209
+ const optOutData = {
174
210
  status: "QUOTE_DECLINED",
175
- quoteId: this.quote.id,
176
- });
211
+ quoteId: this.quote.id
212
+ };
213
+
214
+ // For batch quotes, include detailed quote information
215
+ if (this.quote.originalQuotes && this.quote.originalQuotes.length > 0) {
216
+ optOutData.batchQuoteDetails = this.quote.originalQuotes.map(q => {
217
+ const originalItem = this.options.quoteRequestData.items?.find(item =>
218
+ (item.cartItemId || `item-${this.options.quoteRequestData.items.indexOf(item) + 1}`) === q.cartItemId
219
+ );
220
+ return {
221
+ quoteId: q.id,
222
+ productPrice: originalItem?.productPrice || q.spotPrice,
223
+ cartItemId: q.cartItemId
224
+ };
225
+ });
226
+ }
227
+
228
+ this.options.callbacks.onOptOut(optOutData);
177
229
  }
178
230
  });
179
231
  });
@@ -221,10 +273,7 @@ class SpotWidget {
221
273
  try {
222
274
  const updatedOptions = {
223
275
  ...this.options,
224
- quoteRequestData: {
225
- ...this.options.quoteRequestData,
226
- ...newQuoteRequestData,
227
- },
276
+ quoteRequestData: newQuoteRequestData
228
277
  };
229
278
 
230
279
  validateOptions(updatedOptions);
@@ -237,11 +286,10 @@ class SpotWidget {
237
286
 
238
287
  const endpoint = customEndpoint || apiEndpoint[environment];
239
288
 
240
- const response = await fetchQuote(
241
- endpoint,
242
- partnerId,
243
- updatedOptions.quoteRequestData
244
- );
289
+ const isBatchQuote = updatedOptions.quoteRequestData.cartInfo && updatedOptions.quoteRequestData.items;
290
+ const response = isBatchQuote
291
+ ? await fetchMultipleQuotes(endpoint, partnerId, updatedOptions.quoteRequestData)
292
+ : await fetchQuote(endpoint, partnerId, updatedOptions.quoteRequestData);
245
293
 
246
294
  if (response.status !== "QUOTE_AVAILABLE") {
247
295
  if (
@@ -282,13 +330,29 @@ class SpotWidget {
282
330
  getSelection() {
283
331
  if (this.currentSelection == null) return null;
284
332
 
285
- return {
333
+ const selectionData = {
286
334
  selection: this.currentSelection,
287
335
  quoteId: this.quote?.id,
288
336
  spotPrice: this.quote?.spotPrice,
289
337
  status:
290
- this.currentSelection === "yes" ? "QUOTE_ACCEPTED" : "QUOTE_DECLINED",
338
+ this.currentSelection === "yes" ? "QUOTE_ACCEPTED" : "QUOTE_DECLINED"
291
339
  };
340
+
341
+ // For batch quotes, include detailed quote information
342
+ if (this.quote?.originalQuotes && this.quote.originalQuotes.length > 0) {
343
+ selectionData.batchQuoteDetails = this.quote.originalQuotes.map(q => {
344
+ const originalItem = this.options.quoteRequestData.items?.find(item =>
345
+ (item.cartItemId || `item-${this.options.quoteRequestData.items.indexOf(item) + 1}`) === q.cartItemId
346
+ );
347
+ return {
348
+ quoteId: q.id,
349
+ productPrice: originalItem?.productPrice || q.spotPrice,
350
+ cartItemId: q.cartItemId
351
+ };
352
+ });
353
+ }
354
+
355
+ return selectionData;
292
356
  }
293
357
 
294
358
  destroy() {
package/src/styles.css CHANGED
@@ -127,12 +127,17 @@
127
127
  grid-row: 1;
128
128
  }
129
129
 
130
- .desktop-layout .spot-selection__options {
130
+ .desktop-layout .spot-covered-items__container {
131
131
  grid-row: 2;
132
+ grid-column: 1;
133
+ }
134
+
135
+ .desktop-layout .spot-selection__options {
136
+ grid-row: 3;
132
137
  }
133
138
 
134
139
  .desktop-layout .spot-table__container {
135
- grid-row: 1 / span 2;
140
+ grid-row: 1 / span 3;
136
141
  }
137
142
  }
138
143
 
@@ -207,6 +212,41 @@
207
212
  top: 0.125rem;
208
213
  }
209
214
 
215
+ /* Covered Items List */
216
+ .spot-covered-items__container {
217
+ margin-top: 0;
218
+ margin-bottom: 1rem;
219
+ }
220
+
221
+ .spot-covered-items__title {
222
+ font-size: var(--spot-description-font-size);
223
+ font-weight: var(--spot-description-font-weight);
224
+ color: var(--spot-description-font-color);
225
+ font-family: var(--spot-description-font-family);
226
+ padding: 0 0.3125rem 0.25rem 0.3125rem;
227
+ line-height: 125%;
228
+ margin: 0;
229
+ }
230
+
231
+ .spot-covered-items__list {
232
+ list-style-type: disc;
233
+ list-style-position: inside;
234
+ line-height: 125%;
235
+ gap: 0.5625rem;
236
+ font-size: var(--spot-bullets-font-size);
237
+ font-weight: var(--spot-bullets-font-weight);
238
+ color: var(--spot-bullets-font-color);
239
+ font-family: var(--spot-bullets-font-family);
240
+ padding: var(--spot-bullets-padding);
241
+ margin-block-start: 0rem;
242
+ margin-block-end: 0rem;
243
+ }
244
+
245
+ .spot-covered-items__list li {
246
+ margin-bottom: 0.3rem;
247
+ text-align: left;
248
+ }
249
+
210
250
  /* Payout Table */
211
251
  .spot-table__container {
212
252
  width: 100%;
package/src/ui.js CHANGED
@@ -38,6 +38,32 @@ export function renderBenefits(container, bullets = []) {
38
38
  });
39
39
  }
40
40
 
41
+ // covered items for multi-quote
42
+ export function renderCoveredItems(container, coveredItems = []) {
43
+ if (coveredItems.length === 0) return;
44
+
45
+ const wrapper = makeEl("div", {
46
+ className: "spot-covered-items__container",
47
+ parent: container,
48
+ });
49
+
50
+ makeEl("div", {
51
+ className: "spot-covered-items__title",
52
+ text: "Items covered in your cart:",
53
+ parent: wrapper,
54
+ });
55
+
56
+ const ul = makeEl("ul", {
57
+ className: "spot-covered-items__list",
58
+ parent: wrapper,
59
+ });
60
+
61
+ coveredItems.forEach((item) => {
62
+ const li = makeEl("li", { parent: ul });
63
+ makeEl("span", { text: item, parent: li });
64
+ });
65
+ }
66
+
41
67
  // payout table
42
68
  export function renderTable(container, schedule = []) {
43
69
  const wrapper = makeEl("div", {