@getspot/spot-widget 0.1.4 → 1.0.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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @getspot/spot-widget@0.1.4 build /builds/getspot/spot-widget/packages/core
2
+ > @getspot/spot-widget@1.0.0 build /builds/getspot/spot-widget/packages/core
3
3
  > vite build
4
4
 
5
5
  The CJS build of Vite's Node API is deprecated. See https://vite.dev/guide/troubleshooting.html#vite-cjs-node-api-deprecated for more details.
@@ -8,6 +8,6 @@ transforming...
8
8
  ✓ 5 modules transformed.
9
9
  rendering chunks...
10
10
  computing gzip size...
11
- dist/index.umd.js 22.00 kB │ gzip: 7.06 kB
12
- dist/index.es.js 24.07 kB │ gzip: 7.30 kB
13
- ✓ built in 152ms
11
+ dist/index.umd.js 22.95 kB │ gzip: 7.21 kB
12
+ dist/index.es.js 25.38 kB │ gzip: 7.48 kB
13
+ ✓ built in 159ms
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @getspot/spot-widget
2
2
 
3
+ ## 1.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - 4f9e10e: First major release of all the widget variants.
8
+
9
+ This is really a major release for the sake of having our first major bump. The package is now ready for external use.
10
+
11
+ Includes updated functionality for updating quotes.
12
+
13
+ ## 0.2.0
14
+
15
+ ### Minor Changes
16
+
17
+ - 25bba43: Making cartId required on quoteRequest
18
+
3
19
  ## 0.1.4
4
20
 
5
21
  ### Patch Changes
package/dist/index.es.js CHANGED
@@ -1,23 +1,23 @@
1
1
  async function b(s, e, t) {
2
2
  try {
3
- const o = await fetch(s, {
3
+ const r = await fetch(s, {
4
4
  method: "POST",
5
5
  headers: {
6
6
  "Content-Type": "application/json",
7
7
  "X-Spot-Partner-Id": e
8
8
  },
9
9
  body: JSON.stringify(t)
10
- }), n = await o.json();
11
- if (!o.ok) {
12
- const r = new Error((n == null ? void 0 : n.message) || "Failed to fetch quote");
13
- throw r.status = o.status, r.responseBody = n, r;
10
+ }), n = await r.json();
11
+ if (!r.ok) {
12
+ const o = new Error((n == null ? void 0 : n.message) || "Failed to fetch quote");
13
+ throw o.status = r.status, o.responseBody = n, o;
14
14
  }
15
15
  return n;
16
- } catch (o) {
17
- throw o instanceof Error ? o : new Error("Unknown error occurred while fetching quote");
16
+ } catch (r) {
17
+ throw r instanceof Error ? r : new Error("Unknown error occurred while fetching quote");
18
18
  }
19
19
  }
20
- const w = {
20
+ const y = {
21
21
  sandbox: "https://api.sandbox.getspot.com/v1/quote",
22
22
  production: "https://api.getspot.com/v1/quote"
23
23
  };
@@ -25,17 +25,17 @@ function _(s) {
25
25
  const {
26
26
  apiConfig: e = {},
27
27
  quoteRequestData: t,
28
- callbacks: o = {},
28
+ callbacks: r = {},
29
29
  location: n,
30
- theme: r
30
+ theme: o
31
31
  } = s, {
32
32
  environment: a = "sandbox",
33
33
  partnerId: p,
34
- endpoint: l
34
+ endpoint: c
35
35
  } = e;
36
36
  if (!p || typeof p != "string")
37
37
  throw new Error("Invalid or missing partnerId in apiConfig");
38
- if (!(l || w[a]))
38
+ if (!(c || y[a]))
39
39
  throw new Error(`Invalid environment in apiConfig: ${a}`);
40
40
  if (!t || typeof t != "object")
41
41
  throw new Error("quoteRequestData must be a non-null object");
@@ -48,15 +48,16 @@ function _(s) {
48
48
  "productDuration",
49
49
  "productPrice",
50
50
  "productId",
51
+ "cartId",
51
52
  "productName"
52
- ].forEach((c) => {
53
- if (!Object.prototype.hasOwnProperty.call(t, c) || t[c] === void 0 || t[c] === null)
54
- throw new Error(`Missing required quoteRequestData field: '${c}'`);
53
+ ].forEach((u) => {
54
+ if (!Object.prototype.hasOwnProperty.call(t, u) || t[u] === void 0 || t[u] === null)
55
+ throw new Error(`Missing required quoteRequestData field: '${u}'`);
55
56
  });
56
- const f = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/;
57
- if (!f.test(t.startDate))
57
+ const m = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/;
58
+ if (!m.test(t.startDate))
58
59
  throw new Error("startDate must be a valid ISO8601 string");
59
- if (!f.test(t.endDate))
60
+ if (!m.test(t.endDate))
60
61
  throw new Error("endDate must be a valid ISO8601 string");
61
62
  if (typeof t.currencyCode != "string")
62
63
  throw new Error("currencyCode must be a string");
@@ -66,10 +67,10 @@ function _(s) {
66
67
  throw new Error("eventType must be a string");
67
68
  if (typeof t.productType != "string")
68
69
  throw new Error("productType must be a string");
69
- const u = ["Pass", "Trip", "Registration"];
70
- if (!u.includes(t.productType))
70
+ const f = ["Pass", "Trip", "Registration"];
71
+ if (!f.includes(t.productType))
71
72
  throw new Error(
72
- `productType must be one of ${u.join(", ")}`
73
+ `productType must be one of ${f.join(", ")}`
73
74
  );
74
75
  if (typeof t.productDuration != "string")
75
76
  throw new Error("productDuration must be a string");
@@ -82,6 +83,8 @@ function _(s) {
82
83
  throw new Error("productPrice must be a valid number");
83
84
  if (typeof t.productId != "string")
84
85
  throw new Error("productId must be a string");
86
+ if (typeof t.cartId != "string")
87
+ throw new Error("cartId must be a string");
85
88
  if (typeof t.productName != "string")
86
89
  throw new Error("productName must be a string");
87
90
  if ([
@@ -90,22 +93,22 @@ function _(s) {
90
93
  "onQuoteRetrieved",
91
94
  "onError",
92
95
  "noMatchingQuote"
93
- ].forEach((c) => {
94
- const g = o[c];
96
+ ].forEach((u) => {
97
+ const g = r[u];
95
98
  if (g && typeof g != "function")
96
- throw new Error(`Callback '${c}' must be a function.`);
99
+ throw new Error(`Callback '${u}' must be a function.`);
97
100
  }), typeof n == "string" && !document.querySelector(n))
98
101
  throw new Error(`Invalid location selector: '${n}'`);
99
- if (r && typeof r != "object")
102
+ if (o && typeof o != "object")
100
103
  throw new Error(
101
104
  "Theme must be an object with CSS variables, do not include the '--' prefix"
102
105
  );
103
106
  }
104
- function i(s, { text: e, className: t, parent: o, innerHTML: n } = {}) {
105
- const r = document.createElement(s);
106
- return t && (r.className = t), e != null && (r.textContent = e), n != null && (r.innerHTML = n), o && o.appendChild(r), r;
107
+ function i(s, { text: e, className: t, parent: r, innerHTML: n } = {}) {
108
+ const o = document.createElement(s);
109
+ return t && (o.className = t), e != null && (o.textContent = e), n != null && (o.innerHTML = n), r && r.appendChild(o), o;
107
110
  }
108
- function y(s, { name: e, description: t }) {
111
+ function C(s, { name: e, description: t }) {
109
112
  i("div", {
110
113
  className: "spot-header__title",
111
114
  text: e,
@@ -116,46 +119,46 @@ function y(s, { name: e, description: t }) {
116
119
  parent: s
117
120
  });
118
121
  }
119
- function C(s, e = []) {
122
+ function v(s, e = []) {
120
123
  const t = i("ul", {
121
124
  className: "spot-benefits__list",
122
125
  parent: s
123
126
  });
124
- e.forEach((o) => {
127
+ e.forEach((r) => {
125
128
  const n = i("li", { parent: t });
126
129
  n.innerHTML = `
127
130
  <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
128
131
  <path d="M11.6666 3.5L5.24998 9.91667L2.33331 7"
129
132
  stroke="#2E2E2E" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
130
- </svg>`, i("span", { text: o, parent: n });
133
+ </svg>`, i("span", { text: r, parent: n });
131
134
  });
132
135
  }
133
- function v(s, e = []) {
136
+ function E(s, e = []) {
134
137
  const t = i("div", {
135
138
  className: "spot-table__container",
136
139
  parent: s
137
- }), o = i("table", {
140
+ }), r = i("table", {
138
141
  className: "spot-refund__table spot-table--dynamic",
139
142
  parent: t
140
- }), n = i("thead", { parent: o }), r = i("tr", { parent: n });
141
- i("th", { text: "When you cancel", parent: r }), i("th", { text: "You will receive", parent: r });
142
- const a = i("tbody", { parent: o });
143
- e.forEach(({ text: p, percent: l, amount: d }) => {
144
- const m = i("tr", { parent: a });
145
- i("td", { text: p, parent: m });
146
- const f = l === "Not eligible for refund" ? "Not eligible for a refund" : `$${d} refund`;
147
- i("td", { text: f, parent: m });
143
+ }), n = i("thead", { parent: r }), o = i("tr", { parent: n });
144
+ i("th", { text: "When you cancel", parent: o }), i("th", { text: "You will receive", parent: o });
145
+ const a = i("tbody", { parent: r });
146
+ e.forEach(({ text: p, percent: c, amount: l }) => {
147
+ const d = i("tr", { parent: a });
148
+ i("td", { text: p, parent: d });
149
+ const m = c === "Not eligible for refund" ? "Not eligible for a refund" : `$${l} refund`;
150
+ i("td", { text: m, parent: d });
148
151
  });
149
152
  }
150
- function E(s, e, t) {
151
- const o = i("div", {
153
+ function k(s, e, t) {
154
+ const r = i("div", {
152
155
  className: "spot-selection__options",
153
156
  parent: s
154
157
  }), n = i("label", {
155
158
  className: `spot-selection__option ${t ? "selected" : ""}`,
156
- parent: o
157
- }), r = i("input", { parent: n });
158
- r.type = "radio", r.name = "selection", r.value = "yes", t && (r.checked = !0), i("strong", {
159
+ parent: r
160
+ }), o = i("input", { parent: n });
161
+ o.type = "radio", o.name = "selection", o.value = "yes", t && (o.checked = !0), i("strong", {
159
162
  text: `Yes, protect my booking for $${e}`,
160
163
  parent: n
161
164
  }), i("span", {
@@ -165,26 +168,26 @@ function E(s, e, t) {
165
168
  });
166
169
  const a = i("label", {
167
170
  className: "spot-selection__option",
168
- parent: o
171
+ parent: r
169
172
  }), p = i("input", { parent: a });
170
- return p.type = "radio", p.name = "selection", p.value = "no", i("span", { text: "No, do not protect my booking", parent: a }), o;
173
+ return p.type = "radio", p.name = "selection", p.value = "no", i("span", { text: "No, do not protect my booking", parent: a }), r;
171
174
  }
172
- function k(s, e) {
175
+ function q(s, e) {
173
176
  const t = i("div", {
174
177
  className: "spot-footer__container",
175
178
  parent: s
176
- }), o = i("div", {
179
+ }), r = i("div", {
177
180
  className: "spot-footer__terms",
178
181
  parent: t
179
182
  });
180
183
  i("span", {
181
184
  innerHTML: e.communication.legalDisclaimer,
182
- parent: o
183
- }), i("br", { parent: o }), i("a", {
185
+ parent: r
186
+ }), i("br", { parent: r }), i("a", {
184
187
  href: e.communication.termsAndConditionsUrl,
185
188
  className: "spot-footer__terms-link",
186
189
  text: "Refund Guarantee Terms and Conditions",
187
- parent: o
190
+ parent: r
188
191
  });
189
192
  const n = i("p", {
190
193
  className: "spot-footer__powered-by",
@@ -213,11 +216,11 @@ function H(s) {
213
216
  e.textContent = s, document.head.appendChild(e);
214
217
  }
215
218
  H(x);
216
- const q = {
219
+ const w = {
217
220
  sandbox: "https://api.sandbox.getspot.com/api/v1/quote",
218
221
  production: "https://api.getspot.com/api/v1/quote"
219
222
  };
220
- class M {
223
+ class I {
221
224
  constructor(e = {}) {
222
225
  this.options = {
223
226
  location: "body",
@@ -230,16 +233,16 @@ class M {
230
233
  }, 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();
231
234
  }
232
235
  async _init() {
233
- var e, t, o, n;
236
+ var e, t, r, n, o;
234
237
  try {
235
238
  _(this.options);
236
239
  const {
237
- environment: r,
238
- partnerId: a,
239
- endpoint: p
240
- } = this.options.apiConfig, l = p || q[r], d = await b(
240
+ environment: a,
241
+ partnerId: p,
242
+ endpoint: c
243
+ } = this.options.apiConfig, l = c || w[a], d = await b(
241
244
  l,
242
- a,
245
+ p,
243
246
  this.options.quoteRequestData
244
247
  );
245
248
  if (d.status !== "QUOTE_AVAILABLE") {
@@ -253,44 +256,44 @@ class M {
253
256
  status: "QUOTE_ACCEPTED",
254
257
  spotPrice: this.quote.spotPrice,
255
258
  quoteId: this.quote.id
256
- }), (o = this.options.callbacks) != null && o.onQuoteRetrieved && this.options.callbacks.onQuoteRetrieved(this.quote);
257
- } catch (r) {
258
- (n = this.options.callbacks) == null || n.onError({
259
- message: r.message,
260
- status: r.status,
261
- responseBody: r.responseBody
262
- });
259
+ }), (r = this.options.callbacks) != null && r.onQuoteRetrieved && this.options.callbacks.onQuoteRetrieved(this.quote);
260
+ } catch (a) {
261
+ (n = this.options.callbacks) != null && n.onError && ((o = this.options.callbacks) == null || o.onError({
262
+ message: a.message,
263
+ status: a.status,
264
+ responseBody: a.responseBody
265
+ }));
263
266
  }
264
267
  }
265
268
  _renderWidget() {
266
- this.container = document.createElement("div"), this.container.className = "spot-refund-guarantee", this.root.appendChild(this.container), Object.entries(this.options.theme || {}).forEach(([o, n]) => {
267
- const r = `--${o}`;
268
- this.container.style.setProperty(r, n);
269
- }), y(this.container, this.quote.communication);
269
+ this.container = document.createElement("div"), this.container.className = "spot-refund-guarantee", this.root.appendChild(this.container), Object.entries(this.options.theme || {}).forEach(([r, n]) => {
270
+ const o = `--${r}`;
271
+ this.container.style.setProperty(o, n);
272
+ }), C(this.container, this.quote.communication);
270
273
  const e = document.createElement("div");
271
- e.className = "spot-content__wrapper", this.container.appendChild(e), C(e, this.quote.communication.bulletPoints), this.options.showTable && v(e, this.quote.payoutSchedule);
272
- const t = E(
274
+ e.className = "spot-content__wrapper", this.container.appendChild(e), v(e, this.quote.communication.bulletPoints), this.options.showTable && E(e, this.quote.payoutSchedule);
275
+ const t = k(
273
276
  e,
274
277
  this.quote.spotPrice,
275
278
  this.options.optInSelected
276
279
  );
277
- e.appendChild(t), k(this.container, this.quote), window.addEventListener("resize", this._onResize), this._updateLayout(), this._setupOptionListeners(t);
280
+ e.appendChild(t), q(this.container, this.quote), window.addEventListener("resize", this._onResize), this._updateLayout(), this._setupOptionListeners(t);
278
281
  }
279
282
  _updateLayout() {
280
283
  const e = window.matchMedia("(min-width: 768px)").matches;
281
284
  this.container.querySelector(".spot-content__wrapper").classList.toggle("desktop-layout", e && this.options.showTable);
282
285
  }
283
286
  _setupOptionListeners(e) {
284
- const t = e.querySelectorAll('input[type="radio"]'), o = e.querySelectorAll(".spot-selection__option");
287
+ const t = e.querySelectorAll('input[type="radio"]'), r = e.querySelectorAll(".spot-selection__option");
285
288
  t.forEach((n) => {
286
- n.addEventListener("change", (r) => {
287
- var p, l, d;
288
- const a = r.target.value;
289
- this.hideSelectionError(), this.currentSelection = a, o.forEach((m) => m.classList.remove("selected")), (p = r.target.closest(".spot-selection__option")) == null || p.classList.add("selected"), a === "yes" && ((l = this.options.callbacks) != null && l.onOptIn) && this.options.callbacks.onOptIn({
289
+ n.addEventListener("change", (o) => {
290
+ var p, c, l;
291
+ const a = o.target.value;
292
+ this.hideSelectionError(), this.currentSelection = a, r.forEach((d) => d.classList.remove("selected")), (p = o.target.closest(".spot-selection__option")) == null || p.classList.add("selected"), a === "yes" && ((c = this.options.callbacks) != null && c.onOptIn) && this.options.callbacks.onOptIn({
290
293
  status: "QUOTE_ACCEPTED",
291
294
  spotPrice: this.quote.spotPrice,
292
295
  quoteId: this.quote.id
293
- }), a === "no" && ((d = this.options.callbacks) != null && d.onOptOut) && this.options.callbacks.onOptOut({
296
+ }), a === "no" && ((l = this.options.callbacks) != null && l.onOptOut) && this.options.callbacks.onOptOut({
294
297
  status: "QUOTE_DECLINED",
295
298
  quoteId: this.quote.id
296
299
  });
@@ -318,6 +321,38 @@ class M {
318
321
  );
319
322
  return e ? this.hideSelectionError() : this.showSelectionError(), e;
320
323
  }
324
+ async updateQuote(e) {
325
+ var t, r, n;
326
+ try {
327
+ const o = {
328
+ ...this.options,
329
+ quoteRequestData: {
330
+ ...this.options.quoteRequestData,
331
+ ...e
332
+ }
333
+ };
334
+ _(o);
335
+ const {
336
+ environment: a,
337
+ partnerId: p,
338
+ endpoint: c
339
+ } = this.options.apiConfig, l = c || w[a], d = await b(
340
+ l,
341
+ p,
342
+ o.quoteRequestData
343
+ );
344
+ return d.status !== "QUOTE_AVAILABLE" ? (d.status === "NO_MATCHING_QUOTE" && ((t = this.options.callbacks) != null && t.noMatchingQuote) && this.options.callbacks.noMatchingQuote({
345
+ status: "NO_MATCHING_QUOTE",
346
+ data: o.quoteRequestData
347
+ }), !1) : (this.options.quoteRequestData = o.quoteRequestData, this.quote = d.data, this.currentSelection = null, this.destroy(), this._renderWidget(), (r = this.options.callbacks) != null && r.onQuoteRetrieved && this.options.callbacks.onQuoteRetrieved(this.quote), !0);
348
+ } catch (o) {
349
+ return (n = this.options.callbacks) == null || n.onError({
350
+ message: o.message,
351
+ status: o.status,
352
+ responseBody: o.responseBody
353
+ }), !1;
354
+ }
355
+ }
321
356
  getSelection() {
322
357
  var e, t;
323
358
  return this.currentSelection == null ? null : {
@@ -332,5 +367,5 @@ class M {
332
367
  }
333
368
  }
334
369
  export {
335
- M as default
370
+ I as default
336
371
  };
package/dist/index.umd.js CHANGED
@@ -1,8 +1,8 @@
1
- (function(f,m){typeof exports=="object"&&typeof module<"u"?module.exports=m():typeof define=="function"&&define.amd?define(m):(f=typeof globalThis<"u"?globalThis:f||self,f.SpotWidget=m())})(this,function(){"use strict";async function f(s,e,t){try{const o=await fetch(s,{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 m={sandbox:"https://api.sandbox.getspot.com/v1/quote",production:"https://api.getspot.com/v1/quote"};function _(s){const{apiConfig:e={},quoteRequestData:t,callbacks:o={},location:n,theme:r}=s,{environment:a="sandbox",partnerId:p,endpoint:l}=e;if(!p||typeof p!="string")throw new Error("Invalid or missing partnerId in apiConfig");if(!(l||m[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","productName"].forEach(c=>{if(!Object.prototype.hasOwnProperty.call(t,c)||t[c]===void 0||t[c]===null)throw new Error(`Missing required quoteRequestData field: '${c}'`)});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 g=["Pass","Trip","Registration"];if(!g.includes(t.productType))throw new Error(`productType must be one of ${g.join(", ")}`);if(typeof t.productDuration!="string")throw new Error("productDuration must be a string");const b=["Daily","Seasonal","Trip","Event"];if(!b.includes(t.productDuration))throw new Error(`productDuration must be one of ${b.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.productName!="string")throw new Error("productName must be a string");if(["onOptIn","onOptOut","onQuoteRetrieved","onError","noMatchingQuote"].forEach(c=>{const w=o[c];if(w&&typeof w!="function")throw new Error(`Callback '${c}' 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 i(s,{text:e,className:t,parent:o,innerHTML:n}={}){const r=document.createElement(s);return t&&(r.className=t),e!=null&&(r.textContent=e),n!=null&&(r.innerHTML=n),o&&o.appendChild(r),r}function y(s,{name:e,description:t}){i("div",{className:"spot-header__title",text:e,parent:s}),i("div",{className:"spot-header__description",text:t,parent:s})}function C(s,e=[]){const t=i("ul",{className:"spot-benefits__list",parent:s});e.forEach(o=>{const n=i("li",{parent:t});n.innerHTML=`
1
+ (function(f,m){typeof exports=="object"&&typeof module<"u"?module.exports=m():typeof define=="function"&&define.amd?define(m):(f=typeof globalThis<"u"?globalThis:f||self,f.SpotWidget=m())})(this,function(){"use strict";async function f(s,e,t){try{const r=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json","X-Spot-Partner-Id":e},body:JSON.stringify(t)}),n=await r.json();if(!r.ok){const o=new Error((n==null?void 0:n.message)||"Failed to fetch quote");throw o.status=r.status,o.responseBody=n,o}return n}catch(r){throw r instanceof Error?r:new Error("Unknown error occurred while fetching quote")}}const m={sandbox:"https://api.sandbox.getspot.com/v1/quote",production:"https://api.getspot.com/v1/quote"};function g(s){const{apiConfig:e={},quoteRequestData:t,callbacks:r={},location:n,theme:o}=s,{environment:a="sandbox",partnerId:p,endpoint:c}=e;if(!p||typeof p!="string")throw new Error("Invalid or missing partnerId in apiConfig");if(!(c||m[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(u=>{if(!Object.prototype.hasOwnProperty.call(t,u)||t[u]===void 0||t[u]===null)throw new Error(`Missing required quoteRequestData field: '${u}'`)});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 _=["Pass","Trip","Registration"];if(!_.includes(t.productType))throw new Error(`productType must be one of ${_.join(", ")}`);if(typeof t.productDuration!="string")throw new Error("productDuration must be a string");const w=["Daily","Seasonal","Trip","Event"];if(!w.includes(t.productDuration))throw new Error(`productDuration must be one of ${w.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(u=>{const y=r[u];if(y&&typeof y!="function")throw new Error(`Callback '${u}' must be a function.`)}),typeof n=="string"&&!document.querySelector(n))throw new Error(`Invalid location selector: '${n}'`);if(o&&typeof o!="object")throw new Error("Theme must be an object with CSS variables, do not include the '--' prefix")}function i(s,{text:e,className:t,parent:r,innerHTML:n}={}){const o=document.createElement(s);return t&&(o.className=t),e!=null&&(o.textContent=e),n!=null&&(o.innerHTML=n),r&&r.appendChild(o),o}function C(s,{name:e,description:t}){i("div",{className:"spot-header__title",text:e,parent:s}),i("div",{className:"spot-header__description",text:t,parent:s})}function v(s,e=[]){const t=i("ul",{className:"spot-benefits__list",parent:s});e.forEach(r=>{const n=i("li",{parent:t});n.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>`,i("span",{text:o,parent:n})})}function v(s,e=[]){const t=i("div",{className:"spot-table__container",parent:s}),o=i("table",{className:"spot-refund__table spot-table--dynamic",parent:t}),n=i("thead",{parent:o}),r=i("tr",{parent:n});i("th",{text:"When you cancel",parent:r}),i("th",{text:"You will receive",parent:r});const a=i("tbody",{parent:o});e.forEach(({text:p,percent:l,amount:d})=>{const u=i("tr",{parent:a});i("td",{text:p,parent:u});const h=l==="Not eligible for refund"?"Not eligible for a refund":`$${d} refund`;i("td",{text:h,parent:u})})}function E(s,e,t){const o=i("div",{className:"spot-selection__options",parent:s}),n=i("label",{className:`spot-selection__option ${t?"selected":""}`,parent:o}),r=i("input",{parent:n});r.type="radio",r.name="selection",r.value="yes",t&&(r.checked=!0),i("strong",{text:`Yes, protect my booking for $${e}`,parent:n}),i("span",{className:"spot-selection__recommended-tag",text:"Recommended",parent:n});const a=i("label",{className:"spot-selection__option",parent:o}),p=i("input",{parent:a});return p.type="radio",p.name="selection",p.value="no",i("span",{text:"No, do not protect my booking",parent:a}),o}function k(s,e){const t=i("div",{className:"spot-footer__container",parent:s}),o=i("div",{className:"spot-footer__terms",parent:t});i("span",{innerHTML:e.communication.legalDisclaimer,parent:o}),i("br",{parent:o}),i("a",{href:e.communication.termsAndConditionsUrl,className:"spot-footer__terms-link",text:"Refund Guarantee Terms and Conditions",parent:o});const n=i("p",{className:"spot-footer__powered-by",parent:t});return n.innerHTML=`
5
+ </svg>`,i("span",{text:r,parent:n})})}function E(s,e=[]){const t=i("div",{className:"spot-table__container",parent:s}),r=i("table",{className:"spot-refund__table spot-table--dynamic",parent:t}),n=i("thead",{parent:r}),o=i("tr",{parent:n});i("th",{text:"When you cancel",parent:o}),i("th",{text:"You will receive",parent:o});const a=i("tbody",{parent:r});e.forEach(({text:p,percent:c,amount:l})=>{const d=i("tr",{parent:a});i("td",{text:p,parent:d});const h=c==="Not eligible for refund"?"Not eligible for a refund":`$${l} refund`;i("td",{text:h,parent:d})})}function k(s,e,t){const r=i("div",{className:"spot-selection__options",parent:s}),n=i("label",{className:`spot-selection__option ${t?"selected":""}`,parent:r}),o=i("input",{parent:n});o.type="radio",o.name="selection",o.value="yes",t&&(o.checked=!0),i("strong",{text:`Yes, protect my booking for $${e}`,parent:n}),i("span",{className:"spot-selection__recommended-tag",text:"Recommended",parent:n});const a=i("label",{className:"spot-selection__option",parent:r}),p=i("input",{parent:a});return p.type="radio",p.name="selection",p.value="no",i("span",{text:"No, do not protect my booking",parent:a}),r}function x(s,e){const t=i("div",{className:"spot-footer__container",parent:s}),r=i("div",{className:"spot-footer__terms",parent:t});i("span",{innerHTML:e.communication.legalDisclaimer,parent:r}),i("br",{parent:r}),i("a",{href:e.communication.termsAndConditionsUrl,className:"spot-footer__terms-link",text:"Refund Guarantee Terms and Conditions",parent:r});const n=i("p",{className:"spot-footer__powered-by",parent:t});return n.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 x=":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-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-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(s){const e=document.createElement("style");e.textContent=s,document.head.appendChild(e)}H(x);const q={sandbox:"https://api.sandbox.getspot.com/api/v1/quote",production:"https://api.getspot.com/api/v1/quote"};class T{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;try{_(this.options);const{environment:r,partnerId:a,endpoint:p}=this.options.apiConfig,l=p||q[r],d=await f(l,a,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(r){(n=this.options.callbacks)==null||n.onError({message:r.message,status:r.status,responseBody:r.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)}),y(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&&v(e,this.quote.payoutSchedule);const t=E(e,this.quote.spotPrice,this.options.optInSelected);e.appendChild(t),k(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,l,d;const a=r.target.value;this.hideSelectionError(),this.currentSelection=a,o.forEach(u=>u.classList.remove("selected")),(p=r.target.closest(".spot-selection__option"))==null||p.classList.add("selected"),a==="yes"&&((l=this.options.callbacks)!=null&&l.onOptIn)&&this.options.callbacks.onOptIn({status:"QUOTE_ACCEPTED",spotPrice:this.quote.spotPrice,quoteId:this.quote.id}),a==="no"&&((d=this.options.callbacks)!=null&&d.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}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 T});
20
+ </svg>`,t}const q=":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-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-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(s){const e=document.createElement("style");e.textContent=s,document.head.appendChild(e)}H(q);const b={sandbox:"https://api.sandbox.getspot.com/api/v1/quote",production:"https://api.getspot.com/api/v1/quote"};class T{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,r,n,o;try{g(this.options);const{environment:a,partnerId:p,endpoint:c}=this.options.apiConfig,l=c||b[a],d=await f(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}),(r=this.options.callbacks)!=null&&r.onQuoteRetrieved&&this.options.callbacks.onQuoteRetrieved(this.quote)}catch(a){(n=this.options.callbacks)!=null&&n.onError&&((o=this.options.callbacks)==null||o.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(([r,n])=>{const o=`--${r}`;this.container.style.setProperty(o,n)}),C(this.container,this.quote.communication);const e=document.createElement("div");e.className="spot-content__wrapper",this.container.appendChild(e),v(e,this.quote.communication.bulletPoints),this.options.showTable&&E(e,this.quote.payoutSchedule);const t=k(e,this.quote.spotPrice,this.options.optInSelected);e.appendChild(t),x(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"]'),r=e.querySelectorAll(".spot-selection__option");t.forEach(n=>{n.addEventListener("change",o=>{var p,c,l;const a=o.target.value;this.hideSelectionError(),this.currentSelection=a,r.forEach(d=>d.classList.remove("selected")),(p=o.target.closest(".spot-selection__option"))==null||p.classList.add("selected"),a==="yes"&&((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,r,n;try{const o={...this.options,quoteRequestData:{...this.options.quoteRequestData,...e}};g(o);const{environment:a,partnerId:p,endpoint:c}=this.options.apiConfig,l=c||b[a],d=await f(l,p,o.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:o.quoteRequestData}),!1):(this.options.quoteRequestData=o.quoteRequestData,this.quote=d.data,this.currentSelection=null,this.destroy(),this._renderWidget(),(r=this.options.callbacks)!=null&&r.onQuoteRetrieved&&this.options.callbacks.onQuoteRetrieved(this.quote),!0)}catch(o){return(n=this.options.callbacks)==null||n.onError({message:o.message,status:o.status,responseBody:o.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 T});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getspot/spot-widget",
3
- "version": "0.1.4",
3
+ "version": "1.0.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
package/src/index.js CHANGED
@@ -90,11 +90,13 @@ class SpotWidget {
90
90
  this.options.callbacks.onQuoteRetrieved(this.quote);
91
91
  }
92
92
  } catch (err) {
93
- this.options.callbacks?.onError({
94
- message: err.message,
95
- status: err.status,
96
- responseBody: err.responseBody,
97
- });
93
+ if (this.options.callbacks?.onError) {
94
+ this.options.callbacks?.onError({
95
+ message: err.message,
96
+ status: err.status,
97
+ responseBody: err.responseBody,
98
+ });
99
+ }
98
100
  }
99
101
  }
100
102
 
@@ -205,6 +207,68 @@ class SpotWidget {
205
207
  return isSelected;
206
208
  }
207
209
 
210
+ async updateQuote(newQuoteRequestData) {
211
+ try {
212
+ const updatedOptions = {
213
+ ...this.options,
214
+ quoteRequestData: {
215
+ ...this.options.quoteRequestData,
216
+ ...newQuoteRequestData,
217
+ },
218
+ };
219
+
220
+ validateOptions(updatedOptions);
221
+
222
+ const {
223
+ environment,
224
+ partnerId,
225
+ endpoint: customEndpoint,
226
+ } = this.options.apiConfig;
227
+
228
+ const endpoint = customEndpoint || apiEndpoint[environment];
229
+
230
+ const response = await fetchQuote(
231
+ endpoint,
232
+ partnerId,
233
+ updatedOptions.quoteRequestData
234
+ );
235
+
236
+ if (response.status !== "QUOTE_AVAILABLE") {
237
+ if (
238
+ response.status === "NO_MATCHING_QUOTE" &&
239
+ this.options.callbacks?.noMatchingQuote
240
+ ) {
241
+ this.options.callbacks.noMatchingQuote({
242
+ status: "NO_MATCHING_QUOTE",
243
+ data: updatedOptions.quoteRequestData,
244
+ });
245
+ }
246
+ return false;
247
+ }
248
+
249
+ this.options.quoteRequestData = updatedOptions.quoteRequestData;
250
+ this.quote = response.data;
251
+ this.currentSelection = null;
252
+
253
+ this.destroy();
254
+
255
+ this._renderWidget();
256
+
257
+ if (this.options.callbacks?.onQuoteRetrieved) {
258
+ this.options.callbacks.onQuoteRetrieved(this.quote);
259
+ }
260
+
261
+ return true;
262
+ } catch (err) {
263
+ this.options.callbacks?.onError({
264
+ message: err.message,
265
+ status: err.status,
266
+ responseBody: err.responseBody,
267
+ });
268
+ return false;
269
+ }
270
+ }
271
+
208
272
  getSelection() {
209
273
  if (this.currentSelection == null) return null;
210
274
 
@@ -41,6 +41,7 @@ export function validateOptions(options) {
41
41
  "productDuration",
42
42
  "productPrice",
43
43
  "productId",
44
+ "cartId",
44
45
  "productName",
45
46
  ];
46
47
 
@@ -108,6 +109,10 @@ export function validateOptions(options) {
108
109
  throw new Error("productId must be a string");
109
110
  }
110
111
 
112
+ if (typeof quoteRequestData.cartId !== "string") {
113
+ throw new Error("cartId must be a string");
114
+ }
115
+
111
116
  if (typeof quoteRequestData.productName !== "string") {
112
117
  throw new Error("productName must be a string");
113
118
  }