@getspot/spot-widget-vue 1.4.0 → 2.0.1
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/CHANGELOG.md +18 -0
- package/README.md +432 -5
- package/dist/index.d.ts +23 -0
- package/package.json +21 -4
- package/.turbo/turbo-build.log +0 -14
- package/src/VueSpotWidget.vue +0 -227
- package/vite.config.js +0 -24
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @getspot/spot-widget-vue
|
|
2
2
|
|
|
3
|
+
## 2.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [ccc78eb]
|
|
8
|
+
- @getspot/spot-widget@2.0.1
|
|
9
|
+
|
|
10
|
+
## 2.0.0
|
|
11
|
+
|
|
12
|
+
### Major Changes
|
|
13
|
+
|
|
14
|
+
- 4c59d56: Typescript support
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Updated dependencies [4c59d56]
|
|
19
|
+
- @getspot/spot-widget@2.0.0
|
|
20
|
+
|
|
3
21
|
## 1.4.0
|
|
4
22
|
|
|
5
23
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -1,12 +1,439 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @getspot/spot-widget-vue
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Vue 3 component wrapper for the Spot refund guarantee widget.
|
|
4
|
+
|
|
5
|
+
> **Note:** This Vue wrapper uses types from [@getspot/spot-widget](https://www.npmjs.com/package/@getspot/spot-widget).
|
|
6
|
+
|
|
7
|
+
### Key Types
|
|
8
|
+
- `ApiConfig` - API configuration (environment, partnerId, customEndpoint)
|
|
9
|
+
- `QuoteRequestData` - Quote request data for single items or batch requests
|
|
10
|
+
- `SelectionData` - User selection data returned in callbacks
|
|
11
|
+
- `Quote` - Quote response data with pricing and terms
|
|
12
|
+
- `Theme` - Styling customization options
|
|
13
|
+
|
|
14
|
+
For complete type definitions, see the [@getspot/spot-widget documentation](https://www.npmjs.com/package/@getspot/spot-widget).
|
|
5
15
|
|
|
6
16
|
## Installation
|
|
7
17
|
|
|
8
18
|
```bash
|
|
9
|
-
npm install
|
|
19
|
+
npm install @getspot/spot-widget-vue
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
```vue
|
|
25
|
+
<template>
|
|
26
|
+
<VueSpotWidget
|
|
27
|
+
:api-config="{
|
|
28
|
+
environment: 'production',
|
|
29
|
+
partnerId: 'your-partner-id'
|
|
30
|
+
}"
|
|
31
|
+
:quote-request-data="quoteData"
|
|
32
|
+
:show-table="true"
|
|
33
|
+
:opt-in-selected="false"
|
|
34
|
+
@quote-retrieved="onQuoteRetrieved"
|
|
35
|
+
@opt-in="onOptIn"
|
|
36
|
+
@opt-out="onOptOut"
|
|
37
|
+
@error="onError"
|
|
38
|
+
/>
|
|
39
|
+
</template>
|
|
40
|
+
|
|
41
|
+
<script setup>
|
|
42
|
+
import VueSpotWidget from '@getspot/spot-widget-vue';
|
|
43
|
+
|
|
44
|
+
const quoteData = {
|
|
45
|
+
startDate: '2024-01-01T00:00:00Z',
|
|
46
|
+
endDate: '2024-01-07T23:59:59Z',
|
|
47
|
+
currencyCode: 'USD',
|
|
48
|
+
eventType: 'Ski Trip',
|
|
49
|
+
productType: 'Trip',
|
|
50
|
+
productDuration: 'Trip',
|
|
51
|
+
productPrice: 500,
|
|
52
|
+
productId: 'ski-trip-2024',
|
|
53
|
+
cartId: 'cart-123',
|
|
54
|
+
productName: 'Aspen Ski Trip 2024'
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const onQuoteRetrieved = (quote) => {
|
|
58
|
+
console.log('Quote retrieved:', quote);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const onOptIn = (data) => {
|
|
62
|
+
console.log('User opted in:', data);
|
|
63
|
+
// Handle opt-in logic
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const onOptOut = (data) => {
|
|
67
|
+
console.log('User opted out:', data);
|
|
68
|
+
// Handle opt-out logic
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const onError = (error) => {
|
|
72
|
+
console.error('Widget error:', error);
|
|
73
|
+
// Handle errors
|
|
74
|
+
};
|
|
75
|
+
</script>
|
|
10
76
|
```
|
|
11
77
|
|
|
12
|
-
##
|
|
78
|
+
## TypeScript Support
|
|
79
|
+
|
|
80
|
+
This package includes full TypeScript definitions for Vue 3.
|
|
81
|
+
|
|
82
|
+
```vue
|
|
83
|
+
<script setup lang="ts">
|
|
84
|
+
import VueSpotWidget from '@getspot/spot-widget-vue';
|
|
85
|
+
import type { Quote, SelectionData } from '@getspot/spot-widget';
|
|
86
|
+
|
|
87
|
+
interface QuoteData {
|
|
88
|
+
startDate: string;
|
|
89
|
+
endDate: string;
|
|
90
|
+
currencyCode: 'USD' | 'CAD' | 'AUD';
|
|
91
|
+
eventType: string;
|
|
92
|
+
productType: 'Pass' | 'Trip' | 'Registration';
|
|
93
|
+
productDuration: 'Daily' | 'Seasonal' | 'Trip' | 'Event';
|
|
94
|
+
productPrice: number;
|
|
95
|
+
productId: string;
|
|
96
|
+
cartId: string;
|
|
97
|
+
productName: string;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const quoteData: QuoteData = {
|
|
101
|
+
// ... your quote data
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const onQuoteRetrieved = (quote: Quote) => {
|
|
105
|
+
console.log('Quote retrieved:', quote);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const onOptIn = (data: SelectionData) => {
|
|
109
|
+
console.log('User opted in:', data);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const onOptOut = (data: SelectionData) => {
|
|
113
|
+
console.log('User opted out:', data);
|
|
114
|
+
};
|
|
115
|
+
</script>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Props
|
|
119
|
+
|
|
120
|
+
### Required Props
|
|
121
|
+
|
|
122
|
+
| Prop | Type | Description |
|
|
123
|
+
|------|------|-------------|
|
|
124
|
+
| `apiConfig` | `ApiConfig` | Configuration for the Spot API including environment and partner ID |
|
|
125
|
+
| `quoteRequestData` | `QuoteRequestData` | Quote request data containing product and cart information |
|
|
126
|
+
|
|
127
|
+
### Optional Props
|
|
128
|
+
|
|
129
|
+
| Prop | Type | Default | Description |
|
|
130
|
+
|------|------|---------|-------------|
|
|
131
|
+
| `showTable` | `boolean` | `true` | Whether to show the payout table |
|
|
132
|
+
| `optInSelected` | `boolean` | `false` | Whether the widget should be pre-selected for opt-in |
|
|
133
|
+
| `theme` | `Theme` | `undefined` | Theme customization options for styling the widget |
|
|
134
|
+
|
|
135
|
+
## Events
|
|
136
|
+
|
|
137
|
+
The component emits the following events:
|
|
138
|
+
|
|
139
|
+
### @quote-retrieved
|
|
140
|
+
|
|
141
|
+
Emitted when a quote is successfully retrieved.
|
|
142
|
+
|
|
143
|
+
```vue
|
|
144
|
+
<VueSpotWidget @quote-retrieved="onQuoteRetrieved" />
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Payload:** `Quote` object
|
|
148
|
+
|
|
149
|
+
### @opt-in
|
|
150
|
+
|
|
151
|
+
Emitted when user opts in to the refund guarantee.
|
|
152
|
+
|
|
153
|
+
```vue
|
|
154
|
+
<VueSpotWidget @opt-in="onOptIn" />
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Payload:** `SelectionData` object with `status: 'QUOTE_ACCEPTED'`
|
|
158
|
+
|
|
159
|
+
### @opt-out
|
|
160
|
+
|
|
161
|
+
Emitted when user opts out of the refund guarantee.
|
|
162
|
+
|
|
163
|
+
```vue
|
|
164
|
+
<VueSpotWidget @opt-out="onOptOut" />
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**Payload:** `SelectionData` object with `status: 'QUOTE_DECLINED'`
|
|
168
|
+
|
|
169
|
+
### @error
|
|
170
|
+
|
|
171
|
+
Emitted when an error occurs during quote retrieval.
|
|
172
|
+
|
|
173
|
+
```vue
|
|
174
|
+
<VueSpotWidget @error="onError" />
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**Payload:** Error object with `message`, `status`, and `responseBody`
|
|
178
|
+
|
|
179
|
+
### @no-matching-quote
|
|
180
|
+
|
|
181
|
+
Emitted when no matching quote is found.
|
|
182
|
+
|
|
183
|
+
```vue
|
|
184
|
+
<VueSpotWidget @no-matching-quote="onNoMatchingQuote" />
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**Payload:** Object with `status: 'NO_MATCHING_QUOTE'` and original request data
|
|
188
|
+
|
|
189
|
+
### @selection-change
|
|
190
|
+
|
|
191
|
+
Emitted when user changes their selection (opt-in or opt-out).
|
|
192
|
+
|
|
193
|
+
```vue
|
|
194
|
+
<VueSpotWidget @selection-change="onSelectionChange" />
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Payload:** `SelectionData` object
|
|
198
|
+
|
|
199
|
+
## Exposed Methods
|
|
200
|
+
|
|
201
|
+
You can access widget methods using template refs:
|
|
202
|
+
|
|
203
|
+
```vue
|
|
204
|
+
<template>
|
|
205
|
+
<div>
|
|
206
|
+
<VueSpotWidget
|
|
207
|
+
ref="spotWidget"
|
|
208
|
+
v-bind="widgetProps"
|
|
209
|
+
/>
|
|
210
|
+
<button @click="updateQuote">Update Quote</button>
|
|
211
|
+
<button @click="getSelection">Get Selection</button>
|
|
212
|
+
<button @click="validateSelection">Validate Selection</button>
|
|
213
|
+
</div>
|
|
214
|
+
</template>
|
|
215
|
+
|
|
216
|
+
<script setup>
|
|
217
|
+
import { ref } from 'vue';
|
|
218
|
+
import VueSpotWidget from '@getspot/spot-widget-vue';
|
|
219
|
+
|
|
220
|
+
const spotWidget = ref();
|
|
221
|
+
|
|
222
|
+
const updateQuote = async () => {
|
|
223
|
+
const success = await spotWidget.value?.updateQuote({
|
|
224
|
+
// new quote data
|
|
225
|
+
});
|
|
226
|
+
console.log('Quote updated:', success);
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const getSelection = () => {
|
|
230
|
+
const selection = spotWidget.value?.getSelection();
|
|
231
|
+
console.log('Current selection:', selection);
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
const validateSelection = () => {
|
|
235
|
+
const isValid = spotWidget.value?.validateSelection();
|
|
236
|
+
console.log('Selection is valid:', isValid);
|
|
237
|
+
};
|
|
238
|
+
</script>
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Available Methods
|
|
242
|
+
|
|
243
|
+
| Method | Return Type | Description |
|
|
244
|
+
|--------|-------------|-------------|
|
|
245
|
+
| `updateQuote(data)` | `Promise<boolean>` | Update the quote with new request data |
|
|
246
|
+
| `getSelection()` | `SelectionData \| null` | Get the current user selection |
|
|
247
|
+
| `validateSelection()` | `boolean` | Validate that the user has made a selection |
|
|
248
|
+
| `destroy()` | `void` | Destroy the widget instance and clean up resources |
|
|
249
|
+
|
|
250
|
+
## Configuration
|
|
251
|
+
|
|
252
|
+
### API Configuration
|
|
253
|
+
|
|
254
|
+
The `apiConfig` prop accepts the following options:
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
{
|
|
258
|
+
environment: 'production' | 'sandbox' | 'local',
|
|
259
|
+
partnerId: string,
|
|
260
|
+
customEndpoint?: string // Optional custom API endpoint
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Quote Request Data
|
|
265
|
+
|
|
266
|
+
#### Single Quote Format
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
{
|
|
270
|
+
startDate: string, // ISO 8601 date string
|
|
271
|
+
endDate: string, // ISO 8601 date string
|
|
272
|
+
currencyCode: 'USD' | 'CAD' | 'AUD',
|
|
273
|
+
eventType: string, // e.g., "Ski Trip", "Concert"
|
|
274
|
+
productType: 'Pass' | 'Trip' | 'Registration',
|
|
275
|
+
productDuration: 'Daily' | 'Seasonal' | 'Trip' | 'Event',
|
|
276
|
+
productPrice: number, // Price in specified currency
|
|
277
|
+
productId: string, // Unique product identifier
|
|
278
|
+
cartId: string, // Cart identifier
|
|
279
|
+
productName: string, // Human-readable product name
|
|
280
|
+
participantDescription?: string // Optional participant details
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
#### Batch Quote Format
|
|
285
|
+
|
|
286
|
+
For multiple items in a cart:
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
{
|
|
290
|
+
cartInfo: {
|
|
291
|
+
cartId: string,
|
|
292
|
+
cartName: string,
|
|
293
|
+
currencyCode: 'USD' | 'CAD' | 'AUD'
|
|
294
|
+
},
|
|
295
|
+
items: Array<{
|
|
296
|
+
// Same fields as single quote, minus cartId and currencyCode
|
|
297
|
+
cartItemId?: string // Optional unique identifier for cart item
|
|
298
|
+
}>
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## Styling
|
|
303
|
+
|
|
304
|
+
Customize the widget appearance using the `theme` prop:
|
|
305
|
+
|
|
306
|
+
```vue
|
|
307
|
+
<template>
|
|
308
|
+
<VueSpotWidget
|
|
309
|
+
:theme="{
|
|
310
|
+
primaryColor: '#007bff',
|
|
311
|
+
borderRadius: '8px',
|
|
312
|
+
fontFamily: 'Arial, sans-serif'
|
|
313
|
+
}"
|
|
314
|
+
v-bind="otherProps"
|
|
315
|
+
/>
|
|
316
|
+
</template>
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## Options API Usage
|
|
320
|
+
|
|
321
|
+
If you prefer the Options API:
|
|
322
|
+
|
|
323
|
+
```vue
|
|
324
|
+
<template>
|
|
325
|
+
<VueSpotWidget
|
|
326
|
+
:api-config="apiConfig"
|
|
327
|
+
:quote-request-data="quoteRequestData"
|
|
328
|
+
@opt-in="handleOptIn"
|
|
329
|
+
@opt-out="handleOptOut"
|
|
330
|
+
@error="handleError"
|
|
331
|
+
/>
|
|
332
|
+
</template>
|
|
333
|
+
|
|
334
|
+
<script>
|
|
335
|
+
import VueSpotWidget from '@getspot/spot-widget-vue';
|
|
336
|
+
|
|
337
|
+
export default {
|
|
338
|
+
components: {
|
|
339
|
+
VueSpotWidget
|
|
340
|
+
},
|
|
341
|
+
|
|
342
|
+
data() {
|
|
343
|
+
return {
|
|
344
|
+
apiConfig: {
|
|
345
|
+
environment: 'production',
|
|
346
|
+
partnerId: 'your-partner-id'
|
|
347
|
+
},
|
|
348
|
+
quoteRequestData: {
|
|
349
|
+
startDate: '2024-01-01T00:00:00Z',
|
|
350
|
+
endDate: '2024-01-07T23:59:59Z',
|
|
351
|
+
currencyCode: 'USD',
|
|
352
|
+
eventType: 'Test Event',
|
|
353
|
+
productType: 'Trip',
|
|
354
|
+
productDuration: 'Trip',
|
|
355
|
+
productPrice: 100,
|
|
356
|
+
productId: 'test-product',
|
|
357
|
+
cartId: 'test-cart',
|
|
358
|
+
productName: 'Test Product'
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
},
|
|
362
|
+
|
|
363
|
+
methods: {
|
|
364
|
+
handleOptIn(data) {
|
|
365
|
+
console.log('User opted in:', data);
|
|
366
|
+
// Handle opt-in logic
|
|
367
|
+
},
|
|
368
|
+
|
|
369
|
+
handleOptOut(data) {
|
|
370
|
+
console.log('User opted out:', data);
|
|
371
|
+
// Handle opt-out logic
|
|
372
|
+
},
|
|
373
|
+
|
|
374
|
+
handleError(error) {
|
|
375
|
+
console.error('Widget error:', error);
|
|
376
|
+
// Handle error
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
</script>
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
## Error Handling
|
|
384
|
+
|
|
385
|
+
Always implement error handling for production use:
|
|
386
|
+
|
|
387
|
+
```vue
|
|
388
|
+
<template>
|
|
389
|
+
<div>
|
|
390
|
+
<VueSpotWidget
|
|
391
|
+
v-bind="widgetProps"
|
|
392
|
+
@error="handleError"
|
|
393
|
+
@no-matching-quote="handleNoQuote"
|
|
394
|
+
/>
|
|
395
|
+
<div v-if="errorMessage" class="error-message">
|
|
396
|
+
{{ errorMessage }}
|
|
397
|
+
</div>
|
|
398
|
+
</div>
|
|
399
|
+
</template>
|
|
400
|
+
|
|
401
|
+
<script setup>
|
|
402
|
+
import { ref } from 'vue';
|
|
403
|
+
|
|
404
|
+
const errorMessage = ref('');
|
|
405
|
+
|
|
406
|
+
const handleError = (error) => {
|
|
407
|
+
console.error('Spot Widget Error:', error);
|
|
408
|
+
|
|
409
|
+
// Show user-friendly message
|
|
410
|
+
errorMessage.value = 'Unable to load refund options. Please try again.';
|
|
411
|
+
|
|
412
|
+
// Track error in analytics
|
|
413
|
+
if (window.analytics) {
|
|
414
|
+
window.analytics.track('spot_widget_error', {
|
|
415
|
+
message: error.message,
|
|
416
|
+
status: error.status
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
const handleNoQuote = () => {
|
|
422
|
+
errorMessage.value = 'No refund guarantee available for this product.';
|
|
423
|
+
};
|
|
424
|
+
</script>
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
## Compatibility
|
|
428
|
+
|
|
429
|
+
- **Vue**: 3.x
|
|
430
|
+
- **TypeScript**: 5.x
|
|
431
|
+
- **Node.js**: 16+
|
|
432
|
+
|
|
433
|
+
## License
|
|
434
|
+
|
|
435
|
+
See the main package for license information.
|
|
436
|
+
|
|
437
|
+
## Support
|
|
438
|
+
|
|
439
|
+
For support, please contact [support@getspot.com](mailto:support@getspot.com).
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { DefineComponent } from 'vue';
|
|
2
|
+
import type { SpotWidgetOptions, SelectionData, Quote } from '@getspot/spot-widget';
|
|
3
|
+
|
|
4
|
+
export interface VueSpotWidgetProps extends Omit<SpotWidgetOptions, 'location' | 'callbacks'> {
|
|
5
|
+
onQuoteRetrieved?: (quote: Quote) => void;
|
|
6
|
+
onOptIn?: (data: SelectionData) => void;
|
|
7
|
+
onOptOut?: (data: SelectionData) => void;
|
|
8
|
+
onError?: (error: { message: string; status?: number; responseBody?: any }) => void;
|
|
9
|
+
onNoMatchingQuote?: (data: { status: string; data: any }) => void;
|
|
10
|
+
onSelectionChange?: (data: SelectionData) => void;
|
|
11
|
+
callbacks?: SpotWidgetOptions['callbacks'];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface VueSpotWidgetMethods {
|
|
15
|
+
updateQuote: (newQuoteRequestData: SpotWidgetOptions['quoteRequestData']) => Promise<boolean>;
|
|
16
|
+
getSelection: () => SelectionData | null;
|
|
17
|
+
validateSelection: () => boolean;
|
|
18
|
+
destroy: () => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
declare const VueSpotWidget: DefineComponent<VueSpotWidgetProps, {}, {}, {}, VueSpotWidgetMethods>;
|
|
22
|
+
|
|
23
|
+
export default VueSpotWidget;
|
package/package.json
CHANGED
|
@@ -1,22 +1,39 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getspot/spot-widget-vue",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
7
|
"main": "dist/index.umd.js",
|
|
8
8
|
"module": "dist/index.es.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md",
|
|
13
|
+
"CHANGELOG.md"
|
|
14
|
+
],
|
|
9
15
|
"dependencies": {
|
|
10
|
-
"@getspot/spot-widget": "
|
|
16
|
+
"@getspot/spot-widget": "2.0.1"
|
|
11
17
|
},
|
|
12
18
|
"peerDependencies": {
|
|
13
19
|
"vue": "^3.0.0"
|
|
14
20
|
},
|
|
15
21
|
"devDependencies": {
|
|
16
22
|
"vite": "^5.0.0",
|
|
17
|
-
"@vitejs/plugin-vue": "^5.0.0"
|
|
23
|
+
"@vitejs/plugin-vue": "^5.0.0",
|
|
24
|
+
"vitest": "^1.0.0",
|
|
25
|
+
"@vue/test-utils": "^2.4.0",
|
|
26
|
+
"jsdom": "^23.0.0",
|
|
27
|
+
"@vitest/coverage-v8": "^1.0.0",
|
|
28
|
+
"typescript": "^5.0.0",
|
|
29
|
+
"vue-tsc": "^1.8.0"
|
|
18
30
|
},
|
|
19
31
|
"scripts": {
|
|
20
|
-
"build": "vite build"
|
|
32
|
+
"build": "vite build && cp src/index.d.ts dist/index.d.ts",
|
|
33
|
+
"docs:readme": "node scripts/generate-readme.js",
|
|
34
|
+
"test": "vitest",
|
|
35
|
+
"test:watch": "vitest --watch",
|
|
36
|
+
"test:coverage": "vitest --coverage",
|
|
37
|
+
"test:ci": "vitest run --coverage"
|
|
21
38
|
}
|
|
22
39
|
}
|
package/.turbo/turbo-build.log
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
> @getspot/spot-widget-vue@1.4.0 build /builds/getspot/spot-widget/packages/vue
|
|
3
|
-
> vite build
|
|
4
|
-
|
|
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
|
|
6
|
-
[36mvite v5.4.18 [32mbuilding for production...[36m[39m
|
|
7
|
-
transforming...
|
|
8
|
-
[32m✓[39m 2 modules transformed.
|
|
9
|
-
No name was provided for external module "@getspot/spot-widget" in "output.globals" – guessing "SpotWidget".
|
|
10
|
-
rendering chunks...
|
|
11
|
-
computing gzip size...
|
|
12
|
-
[2mdist/[22m[36mindex.umd.js [39m[1m[2m3.65 kB[22m[1m[22m[2m │ gzip: 1.19 kB[22m
|
|
13
|
-
[2mdist/[22m[36mindex.es.js [39m[1m[2m4.99 kB[22m[1m[22m[2m │ gzip: 1.30 kB[22m
|
|
14
|
-
[32m✓ built in 341ms[39m
|
package/src/VueSpotWidget.vue
DELETED
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div ref="container" />
|
|
3
|
-
</template>
|
|
4
|
-
|
|
5
|
-
<script>
|
|
6
|
-
import SpotWidget from "@getspot/spot-widget";
|
|
7
|
-
|
|
8
|
-
export default {
|
|
9
|
-
name: "VueSpotWidget",
|
|
10
|
-
props: {
|
|
11
|
-
apiConfig: {
|
|
12
|
-
type: Object,
|
|
13
|
-
default: undefined,
|
|
14
|
-
},
|
|
15
|
-
quoteRequestData: {
|
|
16
|
-
type: [Object, Array],
|
|
17
|
-
default: undefined,
|
|
18
|
-
},
|
|
19
|
-
showTable: {
|
|
20
|
-
type: Boolean,
|
|
21
|
-
default: true,
|
|
22
|
-
},
|
|
23
|
-
optInSelected: {
|
|
24
|
-
type: Boolean,
|
|
25
|
-
default: false,
|
|
26
|
-
},
|
|
27
|
-
theme: {
|
|
28
|
-
type: Object,
|
|
29
|
-
default: undefined,
|
|
30
|
-
},
|
|
31
|
-
callbacks: {
|
|
32
|
-
type: Object,
|
|
33
|
-
default: () => ({}),
|
|
34
|
-
},
|
|
35
|
-
onQuoteRetrieved: {
|
|
36
|
-
type: Function,
|
|
37
|
-
default: undefined,
|
|
38
|
-
},
|
|
39
|
-
onOptIn: {
|
|
40
|
-
type: Function,
|
|
41
|
-
default: undefined,
|
|
42
|
-
},
|
|
43
|
-
onOptOut: {
|
|
44
|
-
type: Function,
|
|
45
|
-
default: undefined,
|
|
46
|
-
},
|
|
47
|
-
onError: {
|
|
48
|
-
type: Function,
|
|
49
|
-
default: undefined,
|
|
50
|
-
},
|
|
51
|
-
onNoMatchingQuote: {
|
|
52
|
-
type: Function,
|
|
53
|
-
default: undefined,
|
|
54
|
-
},
|
|
55
|
-
onSelectionChange: {
|
|
56
|
-
type: Function,
|
|
57
|
-
default: undefined,
|
|
58
|
-
},
|
|
59
|
-
options: {
|
|
60
|
-
type: Object,
|
|
61
|
-
default: () => ({}),
|
|
62
|
-
},
|
|
63
|
-
},
|
|
64
|
-
data() {
|
|
65
|
-
return {
|
|
66
|
-
widget: null,
|
|
67
|
-
reinitTimeout: null,
|
|
68
|
-
};
|
|
69
|
-
},
|
|
70
|
-
computed: {
|
|
71
|
-
mergedCallbacks() {
|
|
72
|
-
return {
|
|
73
|
-
...this.callbacks,
|
|
74
|
-
...(this.onQuoteRetrieved && { onQuoteRetrieved: this.onQuoteRetrieved }),
|
|
75
|
-
...(this.onOptIn && {
|
|
76
|
-
onOptIn: (data) => {
|
|
77
|
-
this.onOptIn?.(data);
|
|
78
|
-
this.onSelectionChange?.(data);
|
|
79
|
-
}
|
|
80
|
-
}),
|
|
81
|
-
...(this.onOptOut && {
|
|
82
|
-
onOptOut: (data) => {
|
|
83
|
-
this.onOptOut?.(data);
|
|
84
|
-
this.onSelectionChange?.(data);
|
|
85
|
-
}
|
|
86
|
-
}),
|
|
87
|
-
...(this.onError && { onError: this.onError }),
|
|
88
|
-
...(this.onNoMatchingQuote && { onNoMatchingQuote: this.onNoMatchingQuote }),
|
|
89
|
-
};
|
|
90
|
-
},
|
|
91
|
-
widgetOptions() {
|
|
92
|
-
return {
|
|
93
|
-
apiConfig: this.apiConfig,
|
|
94
|
-
quoteRequestData: this.quoteRequestData,
|
|
95
|
-
showTable: this.showTable,
|
|
96
|
-
optInSelected: this.optInSelected,
|
|
97
|
-
theme: this.theme,
|
|
98
|
-
callbacks: this.mergedCallbacks,
|
|
99
|
-
...this.options,
|
|
100
|
-
};
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
mounted() {
|
|
104
|
-
this.initializeWidget();
|
|
105
|
-
},
|
|
106
|
-
watch: {
|
|
107
|
-
quoteRequestData: {
|
|
108
|
-
handler(newQuoteRequestData, oldQuoteRequestData) {
|
|
109
|
-
if (this.widget && newQuoteRequestData && JSON.stringify(newQuoteRequestData) !== JSON.stringify(oldQuoteRequestData)) {
|
|
110
|
-
// Debounce reinitialize to prevent multiple rapid updates
|
|
111
|
-
if (this.reinitTimeout) {
|
|
112
|
-
clearTimeout(this.reinitTimeout);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
this.reinitTimeout = setTimeout(() => {
|
|
116
|
-
this.reinitializeWidget();
|
|
117
|
-
this.reinitTimeout = null;
|
|
118
|
-
}, 100);
|
|
119
|
-
}
|
|
120
|
-
},
|
|
121
|
-
deep: true,
|
|
122
|
-
},
|
|
123
|
-
apiConfig: {
|
|
124
|
-
handler() {
|
|
125
|
-
this.reinitializeWidget();
|
|
126
|
-
},
|
|
127
|
-
deep: true,
|
|
128
|
-
},
|
|
129
|
-
showTable(newVal, oldVal) {
|
|
130
|
-
if (newVal !== oldVal) {
|
|
131
|
-
this.reinitializeWidget();
|
|
132
|
-
}
|
|
133
|
-
},
|
|
134
|
-
optInSelected(newVal, oldVal) {
|
|
135
|
-
if (newVal !== oldVal) {
|
|
136
|
-
this.reinitializeWidget();
|
|
137
|
-
}
|
|
138
|
-
},
|
|
139
|
-
theme: {
|
|
140
|
-
handler(newTheme, oldTheme) {
|
|
141
|
-
if (this.widget && JSON.stringify(newTheme) !== JSON.stringify(oldTheme)) {
|
|
142
|
-
this.updateTheme(newTheme);
|
|
143
|
-
}
|
|
144
|
-
},
|
|
145
|
-
deep: true,
|
|
146
|
-
},
|
|
147
|
-
mergedCallbacks: {
|
|
148
|
-
handler(newCallbacks, oldCallbacks) {
|
|
149
|
-
if (this.widget && JSON.stringify(newCallbacks) !== JSON.stringify(oldCallbacks)) {
|
|
150
|
-
this.updateCallbacks(newCallbacks);
|
|
151
|
-
}
|
|
152
|
-
},
|
|
153
|
-
deep: true,
|
|
154
|
-
},
|
|
155
|
-
},
|
|
156
|
-
methods: {
|
|
157
|
-
initializeWidget() {
|
|
158
|
-
// Destroy any existing widget first
|
|
159
|
-
if (this.widget) {
|
|
160
|
-
this.widget.destroy();
|
|
161
|
-
this.widget = null;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// Clear the container completely
|
|
165
|
-
if (this.$refs.container) {
|
|
166
|
-
this.$refs.container.innerHTML = '';
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Add a small delay to ensure DOM is ready
|
|
170
|
-
this.$nextTick(() => {
|
|
171
|
-
try {
|
|
172
|
-
this.widget = new SpotWidget({
|
|
173
|
-
...this.widgetOptions,
|
|
174
|
-
location: this.$refs.container,
|
|
175
|
-
});
|
|
176
|
-
} catch (err) {
|
|
177
|
-
this.$emit("error", err);
|
|
178
|
-
this.onError?.(err);
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
},
|
|
182
|
-
reinitializeWidget() {
|
|
183
|
-
if (this.widget) {
|
|
184
|
-
this.widget.destroy();
|
|
185
|
-
this.widget = null;
|
|
186
|
-
}
|
|
187
|
-
this.initializeWidget();
|
|
188
|
-
},
|
|
189
|
-
async updateQuote(newQuoteRequestData) {
|
|
190
|
-
return this.widget?.updateQuote(newQuoteRequestData);
|
|
191
|
-
},
|
|
192
|
-
getSelection() {
|
|
193
|
-
return this.widget?.getSelection();
|
|
194
|
-
},
|
|
195
|
-
validateSelection() {
|
|
196
|
-
return this.widget?.validateSelection();
|
|
197
|
-
},
|
|
198
|
-
updateTheme(newTheme) {
|
|
199
|
-
if (!this.widget || !this.widget.container) return;
|
|
200
|
-
|
|
201
|
-
Object.entries(newTheme || {}).forEach(([k, v]) => {
|
|
202
|
-
const cssVariable = `--${k}`;
|
|
203
|
-
this.widget.container.style.setProperty(cssVariable, v);
|
|
204
|
-
});
|
|
205
|
-
},
|
|
206
|
-
updateCallbacks(newCallbacks) {
|
|
207
|
-
if (!this.widget) return;
|
|
208
|
-
|
|
209
|
-
this.widget.options.callbacks = newCallbacks;
|
|
210
|
-
},
|
|
211
|
-
destroy() {
|
|
212
|
-
if (this.widget && typeof this.widget.destroy === "function") {
|
|
213
|
-
this.widget.destroy();
|
|
214
|
-
this.widget = null;
|
|
215
|
-
}
|
|
216
|
-
},
|
|
217
|
-
},
|
|
218
|
-
beforeUnmount() {
|
|
219
|
-
if (this.reinitTimeout) {
|
|
220
|
-
clearTimeout(this.reinitTimeout);
|
|
221
|
-
}
|
|
222
|
-
if (this.widget && typeof this.widget.destroy === "function") {
|
|
223
|
-
this.widget.destroy();
|
|
224
|
-
}
|
|
225
|
-
},
|
|
226
|
-
};
|
|
227
|
-
</script>
|
package/vite.config.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from "vite";
|
|
2
|
-
import vue from "@vitejs/plugin-vue";
|
|
3
|
-
import path from "path";
|
|
4
|
-
|
|
5
|
-
export default defineConfig({
|
|
6
|
-
plugins: [vue()],
|
|
7
|
-
build: {
|
|
8
|
-
outDir: "dist",
|
|
9
|
-
lib: {
|
|
10
|
-
entry: path.resolve(__dirname, "src/VueSpotWidget.vue"),
|
|
11
|
-
name: "VueSpotWidget",
|
|
12
|
-
fileName: (format) => `index.${format}.js`,
|
|
13
|
-
formats: ["umd", "es"],
|
|
14
|
-
},
|
|
15
|
-
rollupOptions: {
|
|
16
|
-
external: ["vue", "@getspot/spot-widget"],
|
|
17
|
-
output: {
|
|
18
|
-
globals: {
|
|
19
|
-
vue: "Vue",
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
});
|