@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.
- package/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +16 -0
- package/dist/index.es.js +118 -83
- package/dist/index.umd.js +3 -3
- package/package.json +1 -1
- package/src/index.js +69 -5
- package/src/validateOptions.js +5 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @getspot/spot-widget@0.
|
|
2
|
+
> @getspot/spot-widget@1.0.0 build /builds/getspot/spot-widget/packages/core
|
|
3
3
|
> vite build
|
|
4
4
|
|
|
5
5
|
[33mThe CJS build of Vite's Node API is deprecated. See https://vite.dev/guide/troubleshooting.html#vite-cjs-node-api-deprecated for more details.[39m
|
|
@@ -8,6 +8,6 @@ transforming...
|
|
|
8
8
|
[32m✓[39m 5 modules transformed.
|
|
9
9
|
rendering chunks...
|
|
10
10
|
computing gzip size...
|
|
11
|
-
[2mdist/[22m[36mindex.umd.js [39m[1m[2m22.
|
|
12
|
-
[2mdist/[22m[36mindex.es.js [39m[1m[
|
|
13
|
-
[32m✓ built in
|
|
11
|
+
[2mdist/[22m[36mindex.umd.js [39m[1m[2m22.95 kB[22m[1m[22m[2m │ gzip: 7.21 kB[22m
|
|
12
|
+
[2mdist/[22m[36mindex.es.js [39m[1m[2m25.38 kB[22m[1m[22m[2m │ gzip: 7.48 kB[22m
|
|
13
|
+
[32m✓ built in 159ms[39m
|
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
|
|
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
|
|
11
|
-
if (!
|
|
12
|
-
const
|
|
13
|
-
throw
|
|
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 (
|
|
17
|
-
throw
|
|
16
|
+
} catch (r) {
|
|
17
|
+
throw r instanceof Error ? r : new Error("Unknown error occurred while fetching quote");
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
|
-
const
|
|
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:
|
|
28
|
+
callbacks: r = {},
|
|
29
29
|
location: n,
|
|
30
|
-
theme:
|
|
30
|
+
theme: o
|
|
31
31
|
} = s, {
|
|
32
32
|
environment: a = "sandbox",
|
|
33
33
|
partnerId: p,
|
|
34
|
-
endpoint:
|
|
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 (!(
|
|
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((
|
|
53
|
-
if (!Object.prototype.hasOwnProperty.call(t,
|
|
54
|
-
throw new Error(`Missing required quoteRequestData field: '${
|
|
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
|
|
57
|
-
if (!
|
|
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 (!
|
|
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
|
|
70
|
-
if (!
|
|
70
|
+
const f = ["Pass", "Trip", "Registration"];
|
|
71
|
+
if (!f.includes(t.productType))
|
|
71
72
|
throw new Error(
|
|
72
|
-
`productType must be one of ${
|
|
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((
|
|
94
|
-
const g =
|
|
96
|
+
].forEach((u) => {
|
|
97
|
+
const g = r[u];
|
|
95
98
|
if (g && typeof g != "function")
|
|
96
|
-
throw new Error(`Callback '${
|
|
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 (
|
|
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:
|
|
105
|
-
const
|
|
106
|
-
return t && (
|
|
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
|
|
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
|
|
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((
|
|
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:
|
|
133
|
+
</svg>`, i("span", { text: r, parent: n });
|
|
131
134
|
});
|
|
132
135
|
}
|
|
133
|
-
function
|
|
136
|
+
function E(s, e = []) {
|
|
134
137
|
const t = i("div", {
|
|
135
138
|
className: "spot-table__container",
|
|
136
139
|
parent: s
|
|
137
|
-
}),
|
|
140
|
+
}), r = i("table", {
|
|
138
141
|
className: "spot-refund__table spot-table--dynamic",
|
|
139
142
|
parent: t
|
|
140
|
-
}), n = i("thead", { parent:
|
|
141
|
-
i("th", { text: "When you cancel", parent:
|
|
142
|
-
const a = i("tbody", { parent:
|
|
143
|
-
e.forEach(({ text: p, percent:
|
|
144
|
-
const
|
|
145
|
-
i("td", { text: p, parent:
|
|
146
|
-
const
|
|
147
|
-
i("td", { text:
|
|
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
|
|
151
|
-
const
|
|
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:
|
|
157
|
-
}),
|
|
158
|
-
|
|
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:
|
|
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 }),
|
|
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
|
|
175
|
+
function q(s, e) {
|
|
173
176
|
const t = i("div", {
|
|
174
177
|
className: "spot-footer__container",
|
|
175
178
|
parent: s
|
|
176
|
-
}),
|
|
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:
|
|
183
|
-
}), i("br", { parent:
|
|
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:
|
|
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
|
|
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
|
|
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,
|
|
236
|
+
var e, t, r, n, o;
|
|
234
237
|
try {
|
|
235
238
|
_(this.options);
|
|
236
239
|
const {
|
|
237
|
-
environment:
|
|
238
|
-
partnerId:
|
|
239
|
-
endpoint:
|
|
240
|
-
} = this.options.apiConfig, l =
|
|
240
|
+
environment: a,
|
|
241
|
+
partnerId: p,
|
|
242
|
+
endpoint: c
|
|
243
|
+
} = this.options.apiConfig, l = c || w[a], d = await b(
|
|
241
244
|
l,
|
|
242
|
-
|
|
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
|
-
}), (
|
|
257
|
-
} catch (
|
|
258
|
-
(n = this.options.callbacks) == null ||
|
|
259
|
-
message:
|
|
260
|
-
status:
|
|
261
|
-
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(([
|
|
267
|
-
const
|
|
268
|
-
this.container.style.setProperty(
|
|
269
|
-
}),
|
|
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),
|
|
272
|
-
const t =
|
|
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),
|
|
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"]'),
|
|
287
|
+
const t = e.querySelectorAll('input[type="radio"]'), r = e.querySelectorAll(".spot-selection__option");
|
|
285
288
|
t.forEach((n) => {
|
|
286
|
-
n.addEventListener("change", (
|
|
287
|
-
var p,
|
|
288
|
-
const a =
|
|
289
|
-
this.hideSelectionError(), this.currentSelection = a,
|
|
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" && ((
|
|
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
|
-
|
|
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
|
|
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:
|
|
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
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
|
package/src/validateOptions.js
CHANGED
|
@@ -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
|
}
|