@revova/hydrogen 1.0.0 → 1.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/README.md +144 -52
- package/dist/index.cjs +45 -17
- package/dist/index.d.cts +55 -42
- package/dist/index.d.ts +55 -42
- package/dist/index.js +44 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,42 +11,126 @@ npm install @revova/hydrogen
|
|
|
11
11
|
## Requirements
|
|
12
12
|
|
|
13
13
|
- React 18+
|
|
14
|
-
- Shopify Hydrogen storefront with the Revova app installed
|
|
14
|
+
- Shopify Hydrogen storefront with the Revova app installed on the store
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
-
##
|
|
18
|
+
## How it works
|
|
19
|
+
|
|
20
|
+
Revova uses Shopify's built-in **App Proxy**. When the Revova app is installed on a store, Shopify automatically registers the route `/apps/revova` on the `myshopify.com` domain.
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
In Hydrogen, your storefront runs on its own domain (Oxygen, Vercel, etc.), so you must pass the **absolute** proxy URL — not a relative path.
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
https://yourstore.myshopify.com/apps/revova
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
No API keys. No CORS config. Shopify handles all of it.
|
|
21
29
|
|
|
22
30
|
---
|
|
23
31
|
|
|
24
|
-
##
|
|
32
|
+
## Setup (Hydrogen)
|
|
25
33
|
|
|
26
|
-
###
|
|
34
|
+
### 1 — Install the Revova app on your Shopify store
|
|
27
35
|
|
|
28
|
-
|
|
36
|
+
Same as any merchant. The App Proxy is registered automatically on install.
|
|
37
|
+
|
|
38
|
+
### 2 — Expose your store domain in the Hydrogen environment
|
|
39
|
+
|
|
40
|
+
```env
|
|
41
|
+
# .env
|
|
42
|
+
PUBLIC_STORE_DOMAIN=yourstore.myshopify.com
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Hydrogen exposes this through `context.env` in loaders:
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
// app/root.tsx or any route loader
|
|
49
|
+
export async function loader({ context }: LoaderArgs) {
|
|
50
|
+
return {
|
|
51
|
+
storeDomain: context.env.PUBLIC_STORE_DOMAIN,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 3 — Pass `storeDomain` (or `proxyUrl`) to any component
|
|
57
|
+
|
|
58
|
+
Every component accepts either prop — use whichever is more convenient:
|
|
29
59
|
|
|
30
60
|
```tsx
|
|
31
|
-
|
|
61
|
+
// Recommended — convenience shorthand
|
|
62
|
+
<ReviewWidget storeDomain={storeDomain} productId={product.id} />
|
|
63
|
+
|
|
64
|
+
// Explicit — same result
|
|
65
|
+
<ReviewWidget
|
|
66
|
+
proxyUrl={`https://${storeDomain}/apps/revova`}
|
|
67
|
+
productId={product.id}
|
|
68
|
+
/>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Quick Start
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
// app/routes/products.$handle.tsx
|
|
77
|
+
import { ReviewWidget, FloatingReviewButton } from '@revova/hydrogen';
|
|
78
|
+
|
|
79
|
+
export async function loader({ context, params }: LoaderArgs) {
|
|
80
|
+
const product = await getProduct(params.handle);
|
|
81
|
+
return {
|
|
82
|
+
product,
|
|
83
|
+
storeDomain: context.env.PUBLIC_STORE_DOMAIN,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
32
86
|
|
|
33
87
|
export default function ProductPage() {
|
|
34
|
-
const { product } = useLoaderData<typeof loader>();
|
|
88
|
+
const { product, storeDomain } = useLoaderData<typeof loader>();
|
|
35
89
|
|
|
36
90
|
return (
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
91
|
+
<>
|
|
92
|
+
<h1>{product.title}</h1>
|
|
93
|
+
|
|
94
|
+
<ReviewWidget
|
|
95
|
+
storeDomain={storeDomain}
|
|
96
|
+
productId={product.id}
|
|
97
|
+
/>
|
|
98
|
+
|
|
99
|
+
<FloatingReviewButton
|
|
100
|
+
storeDomain={storeDomain}
|
|
101
|
+
productId={product.id}
|
|
102
|
+
/>
|
|
103
|
+
</>
|
|
41
104
|
);
|
|
42
105
|
}
|
|
43
106
|
```
|
|
44
107
|
|
|
45
|
-
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Components
|
|
111
|
+
|
|
112
|
+
All components accept either `storeDomain` **or** `proxyUrl` — never both.
|
|
113
|
+
|
|
114
|
+
### `<ReviewWidget>`
|
|
115
|
+
|
|
116
|
+
Full review list with pagination, sorting, and an inline submission form.
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
import { ReviewWidget } from '@revova/hydrogen';
|
|
120
|
+
|
|
121
|
+
<ReviewWidget
|
|
122
|
+
storeDomain={storeDomain}
|
|
123
|
+
productId={product.id}
|
|
124
|
+
pageSize={10}
|
|
125
|
+
showForm
|
|
126
|
+
locale="fr"
|
|
127
|
+
/>
|
|
128
|
+
```
|
|
46
129
|
|
|
47
130
|
| Prop | Type | Default | Description |
|
|
48
131
|
|---|---|---|---|
|
|
49
|
-
| `
|
|
132
|
+
| `storeDomain` | `string` | — | Your `myshopify.com` domain (e.g. `yourstore.myshopify.com`) |
|
|
133
|
+
| `proxyUrl` | `string` | — | Explicit proxy URL — use instead of `storeDomain` if preferred |
|
|
50
134
|
| `productId` | `string` | — | Shopify product GID |
|
|
51
135
|
| `locale` | `string` | — | Locale code for translated reviews (e.g. `fr`) |
|
|
52
136
|
| `pageSize` | `number` | `10` | Reviews per page |
|
|
@@ -65,14 +149,14 @@ import { ReviewForm } from '@revova/hydrogen';
|
|
|
65
149
|
|
|
66
150
|
// `form` comes from the ReviewsResponse returned by useReviews
|
|
67
151
|
<ReviewForm
|
|
68
|
-
|
|
152
|
+
storeDomain={storeDomain}
|
|
69
153
|
productId={product.id}
|
|
70
154
|
form={data.form}
|
|
71
155
|
onSuccess={() => console.log('submitted')}
|
|
72
156
|
/>
|
|
73
157
|
```
|
|
74
158
|
|
|
75
|
-
**Props:** `proxyUrl`, `productId`, `form` (required — `ResolvedForm` from loader), `onSuccess?`, `className?`
|
|
159
|
+
**Props:** `storeDomain` or `proxyUrl`, `productId`, `form` (required — `ResolvedForm` from loader), `onSuccess?`, `className?`
|
|
76
160
|
|
|
77
161
|
---
|
|
78
162
|
|
|
@@ -92,16 +176,15 @@ import { StarRating } from '@revova/hydrogen';
|
|
|
92
176
|
|
|
93
177
|
### `<ReviewCount>`
|
|
94
178
|
|
|
95
|
-
Aggregate rating + review count badge.
|
|
179
|
+
Aggregate rating + review count badge. Great for product cards and PDP headers.
|
|
96
180
|
|
|
97
181
|
```tsx
|
|
98
182
|
import { ReviewCount } from '@revova/hydrogen';
|
|
99
183
|
|
|
100
|
-
|
|
101
|
-
<ReviewCount proxyUrl="/apps/revova" starSize={14} />
|
|
184
|
+
<ReviewCount storeDomain={storeDomain} starSize={14} />
|
|
102
185
|
```
|
|
103
186
|
|
|
104
|
-
**Props:** `proxyUrl`, `starColor?`, `starSize?`, `className?`
|
|
187
|
+
**Props:** `storeDomain` or `proxyUrl`, `starColor?`, `starSize?`, `className?`
|
|
105
188
|
|
|
106
189
|
---
|
|
107
190
|
|
|
@@ -113,14 +196,14 @@ Auto-advancing carousel of recent reviews. Includes previous/next arrows and dot
|
|
|
113
196
|
import { ReviewCarousel } from '@revova/hydrogen';
|
|
114
197
|
|
|
115
198
|
<ReviewCarousel
|
|
116
|
-
|
|
199
|
+
storeDomain={storeDomain}
|
|
117
200
|
limit={10}
|
|
118
201
|
autoPlay
|
|
119
202
|
intervalMs={4000}
|
|
120
203
|
/>
|
|
121
204
|
```
|
|
122
205
|
|
|
123
|
-
**Props:** `proxyUrl`, `limit?` (default 10), `autoPlay?` (default `true`), `intervalMs?` (default 4000), `starColor?`, `className?`
|
|
206
|
+
**Props:** `storeDomain` or `proxyUrl`, `limit?` (default 10), `autoPlay?` (default `true`), `intervalMs?` (default 4000), `starColor?`, `className?`
|
|
124
207
|
|
|
125
208
|
---
|
|
126
209
|
|
|
@@ -132,13 +215,13 @@ Masonry photo grid of reviews that have images. Clicking any photo opens a light
|
|
|
132
215
|
import { ReviewGallery } from '@revova/hydrogen';
|
|
133
216
|
|
|
134
217
|
<ReviewGallery
|
|
135
|
-
|
|
218
|
+
storeDomain={storeDomain}
|
|
136
219
|
columns={3}
|
|
137
220
|
limit={20}
|
|
138
221
|
/>
|
|
139
222
|
```
|
|
140
223
|
|
|
141
|
-
**Props:** `proxyUrl`, `limit?` (default 20), `columns?` (default 3), `starColor?`, `className?`
|
|
224
|
+
**Props:** `storeDomain` or `proxyUrl`, `limit?` (default 20), `columns?` (default 3), `starColor?`, `className?`
|
|
142
225
|
|
|
143
226
|
---
|
|
144
227
|
|
|
@@ -150,12 +233,12 @@ Product Q&A — lists questions with answers and includes an ask-a-question form
|
|
|
150
233
|
import { QnAWidget } from '@revova/hydrogen';
|
|
151
234
|
|
|
152
235
|
<QnAWidget
|
|
153
|
-
|
|
236
|
+
storeDomain={storeDomain}
|
|
154
237
|
productId={product.id}
|
|
155
238
|
/>
|
|
156
239
|
```
|
|
157
240
|
|
|
158
|
-
**Props:** `proxyUrl`, `productId`, `className?`
|
|
241
|
+
**Props:** `storeDomain` or `proxyUrl`, `productId`, `className?`
|
|
159
242
|
|
|
160
243
|
---
|
|
161
244
|
|
|
@@ -167,16 +250,16 @@ Aggregate rating badge in three styles: `pill` (default), `inline`, or `card`.
|
|
|
167
250
|
import { TrustBadge } from '@revova/hydrogen';
|
|
168
251
|
|
|
169
252
|
// Pill — great for footers, headers
|
|
170
|
-
<TrustBadge
|
|
253
|
+
<TrustBadge storeDomain={storeDomain} style="pill" />
|
|
171
254
|
|
|
172
255
|
// Card — great for landing pages
|
|
173
|
-
<TrustBadge
|
|
256
|
+
<TrustBadge storeDomain={storeDomain} style="card" />
|
|
174
257
|
|
|
175
258
|
// Inline — great inside sentences or product specs
|
|
176
|
-
<TrustBadge
|
|
259
|
+
<TrustBadge storeDomain={storeDomain} style="inline" />
|
|
177
260
|
```
|
|
178
261
|
|
|
179
|
-
**Props:** `proxyUrl`, `style?` (`'pill' | 'inline' | 'card'`, default `'pill'`), `starColor?`, `className?`
|
|
262
|
+
**Props:** `storeDomain` or `proxyUrl`, `style?` (`'pill' | 'inline' | 'card'`, default `'pill'`), `starColor?`, `className?`
|
|
180
263
|
|
|
181
264
|
---
|
|
182
265
|
|
|
@@ -188,33 +271,32 @@ A continuously scrolling marquee of recent review snippets — ideal for homepag
|
|
|
188
271
|
import { ReviewTicker } from '@revova/hydrogen';
|
|
189
272
|
|
|
190
273
|
<ReviewTicker
|
|
191
|
-
|
|
274
|
+
storeDomain={storeDomain}
|
|
192
275
|
limit={20}
|
|
193
276
|
speedSeconds={30}
|
|
194
277
|
/>
|
|
195
278
|
```
|
|
196
279
|
|
|
197
|
-
**Props:** `proxyUrl`, `limit?` (default 20), `speedSeconds?` (default 30), `starColor?`, `className?`
|
|
280
|
+
**Props:** `storeDomain` or `proxyUrl`, `limit?` (default 20), `speedSeconds?` (default 30), `starColor?`, `className?`
|
|
198
281
|
|
|
199
282
|
---
|
|
200
283
|
|
|
201
284
|
### `<SocialProofPopup>`
|
|
202
285
|
|
|
203
|
-
A timed floating popup showing recent reviews one at a time.
|
|
286
|
+
A timed floating popup showing recent reviews one at a time. Add once to your root layout.
|
|
204
287
|
|
|
205
288
|
```tsx
|
|
206
289
|
import { SocialProofPopup } from '@revova/hydrogen';
|
|
207
290
|
|
|
208
|
-
// Add once to your root layout
|
|
209
291
|
<SocialProofPopup
|
|
210
|
-
|
|
292
|
+
storeDomain={storeDomain}
|
|
211
293
|
position="bottom-left"
|
|
212
294
|
intervalMs={8000}
|
|
213
295
|
displayMs={5000}
|
|
214
296
|
/>
|
|
215
297
|
```
|
|
216
298
|
|
|
217
|
-
**Props:** `proxyUrl`, `position?` (`'bottom-left' | 'bottom-right'`, default `'bottom-left'`), `intervalMs?` (default 8000), `displayMs?` (default 5000), `starColor?`, `className?`
|
|
299
|
+
**Props:** `storeDomain` or `proxyUrl`, `position?` (`'bottom-left' | 'bottom-right'`, default `'bottom-left'`), `intervalMs?` (default 8000), `displayMs?` (default 5000), `starColor?`, `className?`
|
|
218
300
|
|
|
219
301
|
---
|
|
220
302
|
|
|
@@ -226,14 +308,14 @@ A sticky tab fixed to the left or right edge of the viewport. Clicking it slides
|
|
|
226
308
|
import { FloatingReviewsTab } from '@revova/hydrogen';
|
|
227
309
|
|
|
228
310
|
<FloatingReviewsTab
|
|
229
|
-
|
|
311
|
+
storeDomain={storeDomain}
|
|
230
312
|
label="Reviews"
|
|
231
313
|
position="right"
|
|
232
314
|
color="#111827"
|
|
233
315
|
/>
|
|
234
316
|
```
|
|
235
317
|
|
|
236
|
-
**Props:** `proxyUrl`, `label?` (default `'Reviews'`), `position?` (`'left' | 'right'`, default `'right'`), `color?`, `limit?` (default 5), `starColor?`, `className?`
|
|
318
|
+
**Props:** `storeDomain` or `proxyUrl`, `label?` (default `'Reviews'`), `position?` (`'left' | 'right'`, default `'right'`), `color?`, `limit?` (default 5), `starColor?`, `className?`
|
|
237
319
|
|
|
238
320
|
---
|
|
239
321
|
|
|
@@ -245,7 +327,7 @@ A fixed "Write a Review" button that opens a modal with the submission form.
|
|
|
245
327
|
import { FloatingReviewButton } from '@revova/hydrogen';
|
|
246
328
|
|
|
247
329
|
<FloatingReviewButton
|
|
248
|
-
|
|
330
|
+
storeDomain={storeDomain}
|
|
249
331
|
productId={product.id}
|
|
250
332
|
text="Write a Review"
|
|
251
333
|
position="bottom-right"
|
|
@@ -253,23 +335,29 @@ import { FloatingReviewButton } from '@revova/hydrogen';
|
|
|
253
335
|
/>
|
|
254
336
|
```
|
|
255
337
|
|
|
256
|
-
**Props:** `proxyUrl`, `productId`, `text?` (default `'Write a Review'`), `color?`, `position?` (`'bottom-left' | 'bottom-right'`, default `'bottom-right'`), `className?`
|
|
338
|
+
**Props:** `storeDomain` or `proxyUrl`, `productId`, `text?` (default `'Write a Review'`), `color?`, `position?` (`'bottom-left' | 'bottom-right'`, default `'bottom-right'`), `className?`
|
|
257
339
|
|
|
258
340
|
---
|
|
259
341
|
|
|
260
342
|
## Hooks
|
|
261
343
|
|
|
262
|
-
Use hooks to build fully custom UIs while Revova handles data fetching.
|
|
344
|
+
Use hooks to build fully custom UIs while Revova handles data fetching. Hooks take `proxyUrl` as a plain string — use the exported `resolveProxyUrl` helper to build it from `storeDomain`.
|
|
345
|
+
|
|
346
|
+
```ts
|
|
347
|
+
import { resolveProxyUrl } from '@revova/hydrogen';
|
|
348
|
+
|
|
349
|
+
const proxyUrl = resolveProxyUrl({ storeDomain }); // or { proxyUrl }
|
|
350
|
+
```
|
|
263
351
|
|
|
264
352
|
### `useReviews(options)`
|
|
265
353
|
|
|
266
354
|
Paginated reviews for a product with sorting controls.
|
|
267
355
|
|
|
268
356
|
```tsx
|
|
269
|
-
import { useReviews } from '@revova/hydrogen';
|
|
357
|
+
import { useReviews, resolveProxyUrl } from '@revova/hydrogen';
|
|
270
358
|
|
|
271
359
|
const { data, loading, error, setPage, setSort, currentPage, currentSort, refetch } = useReviews({
|
|
272
|
-
proxyUrl:
|
|
360
|
+
proxyUrl: resolveProxyUrl({ storeDomain }),
|
|
273
361
|
productId: product.id,
|
|
274
362
|
limit: 5,
|
|
275
363
|
sort: 'helpful', // 'recent' | 'helpful' | 'rating_high' | 'rating_low'
|
|
@@ -282,10 +370,10 @@ const { data, loading, error, setPage, setSort, currentPage, currentSort, refetc
|
|
|
282
370
|
Shop-level stats and recent reviews. Used internally by `<ReviewCount>`, `<TrustBadge>`, `<ReviewCarousel>`, `<ReviewGallery>`, `<ReviewTicker>`, `<SocialProofPopup>`, and `<FloatingReviewsTab>`.
|
|
283
371
|
|
|
284
372
|
```tsx
|
|
285
|
-
import { useWidgetGlobals } from '@revova/hydrogen';
|
|
373
|
+
import { useWidgetGlobals, resolveProxyUrl } from '@revova/hydrogen';
|
|
286
374
|
|
|
287
375
|
const { data, loading, error } = useWidgetGlobals({
|
|
288
|
-
proxyUrl:
|
|
376
|
+
proxyUrl: resolveProxyUrl({ storeDomain }),
|
|
289
377
|
limit: 20,
|
|
290
378
|
});
|
|
291
379
|
|
|
@@ -300,9 +388,11 @@ const { data, loading, error } = useWidgetGlobals({
|
|
|
300
388
|
Submit a new review programmatically.
|
|
301
389
|
|
|
302
390
|
```tsx
|
|
303
|
-
import { useSubmitReview } from '@revova/hydrogen';
|
|
391
|
+
import { useSubmitReview, resolveProxyUrl } from '@revova/hydrogen';
|
|
304
392
|
|
|
305
|
-
const { submit, submitting, success, error, result, reset } = useSubmitReview(
|
|
393
|
+
const { submit, submitting, success, error, result, reset } = useSubmitReview(
|
|
394
|
+
resolveProxyUrl({ storeDomain })
|
|
395
|
+
);
|
|
306
396
|
|
|
307
397
|
await submit({
|
|
308
398
|
productId: 'gid://shopify/Product/123',
|
|
@@ -321,7 +411,7 @@ await submit({
|
|
|
321
411
|
Fetch and submit Q&A for a product.
|
|
322
412
|
|
|
323
413
|
```tsx
|
|
324
|
-
import { useQnA } from '@revova/hydrogen';
|
|
414
|
+
import { useQnA, resolveProxyUrl } from '@revova/hydrogen';
|
|
325
415
|
|
|
326
416
|
const {
|
|
327
417
|
data,
|
|
@@ -331,9 +421,11 @@ const {
|
|
|
331
421
|
submitAnswer,
|
|
332
422
|
submitState,
|
|
333
423
|
resetSubmit,
|
|
334
|
-
} = useQnA({
|
|
424
|
+
} = useQnA({
|
|
425
|
+
proxyUrl: resolveProxyUrl({ storeDomain }),
|
|
426
|
+
productId: product.id,
|
|
427
|
+
});
|
|
335
428
|
|
|
336
|
-
// Submit a question
|
|
337
429
|
await submitQuestion({
|
|
338
430
|
intent: 'question',
|
|
339
431
|
productId: product.id,
|
|
@@ -347,9 +439,9 @@ await submitQuestion({
|
|
|
347
439
|
Cast a helpful / not-helpful vote on a review.
|
|
348
440
|
|
|
349
441
|
```tsx
|
|
350
|
-
import { useHelpfulVote } from '@revova/hydrogen';
|
|
442
|
+
import { useHelpfulVote, resolveProxyUrl } from '@revova/hydrogen';
|
|
351
443
|
|
|
352
|
-
const { vote, loading, voted } = useHelpfulVote(
|
|
444
|
+
const { vote, loading, voted } = useHelpfulVote(resolveProxyUrl({ storeDomain }));
|
|
353
445
|
|
|
354
446
|
<button onClick={() => vote({ reviewId: review.id, vote: 'helpful' })} disabled={voted}>
|
|
355
447
|
Helpful ({review.helpfulCount})
|
package/dist/index.cjs
CHANGED
|
@@ -42,6 +42,7 @@ __export(index_exports, {
|
|
|
42
42
|
SocialProofPopup: () => SocialProofPopup,
|
|
43
43
|
StarRating: () => StarRating,
|
|
44
44
|
TrustBadge: () => TrustBadge,
|
|
45
|
+
resolveProxyUrl: () => resolveProxyUrl,
|
|
45
46
|
useForm: () => useForm,
|
|
46
47
|
useHelpfulVote: () => useHelpfulVote,
|
|
47
48
|
useQnA: () => useQnA,
|
|
@@ -54,6 +55,14 @@ module.exports = __toCommonJS(index_exports);
|
|
|
54
55
|
// src/components/ReviewWidget.tsx
|
|
55
56
|
var import_react4 = require("react");
|
|
56
57
|
|
|
58
|
+
// src/utils.ts
|
|
59
|
+
var PROXY_PATH = "/apps/revova";
|
|
60
|
+
function resolveProxyUrl(props) {
|
|
61
|
+
if (props.storeDomain) return `https://${props.storeDomain}${PROXY_PATH}`;
|
|
62
|
+
if (props.proxyUrl) return props.proxyUrl;
|
|
63
|
+
throw new Error("[Revova] Provide either proxyUrl or storeDomain.");
|
|
64
|
+
}
|
|
65
|
+
|
|
57
66
|
// src/hooks/useReviews.ts
|
|
58
67
|
var import_react = require("react");
|
|
59
68
|
function useReviews({
|
|
@@ -479,8 +488,9 @@ function FieldRenderer(props) {
|
|
|
479
488
|
return null;
|
|
480
489
|
}
|
|
481
490
|
}
|
|
482
|
-
function ReviewForm({ proxyUrl, productId, form, onSuccess, className }) {
|
|
483
|
-
const
|
|
491
|
+
function ReviewForm({ proxyUrl, storeDomain, productId, form, onSuccess, className }) {
|
|
492
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
493
|
+
const { submit, submitting, success, error, result } = useSubmitReview(resolvedUrl);
|
|
484
494
|
const [answers, setAnswers] = (0, import_react3.useState)({});
|
|
485
495
|
const [email, setEmail] = (0, import_react3.useState)("");
|
|
486
496
|
const starField = form.fields.find((f) => f.type === "STAR_RATING");
|
|
@@ -588,6 +598,7 @@ function ReviewForm({ proxyUrl, productId, form, onSuccess, className }) {
|
|
|
588
598
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
589
599
|
function ReviewWidget({
|
|
590
600
|
proxyUrl,
|
|
601
|
+
storeDomain,
|
|
591
602
|
productId,
|
|
592
603
|
locale,
|
|
593
604
|
pageSize = 10,
|
|
@@ -595,9 +606,10 @@ function ReviewWidget({
|
|
|
595
606
|
starColor,
|
|
596
607
|
className
|
|
597
608
|
}) {
|
|
609
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
598
610
|
const [showingForm, setShowingForm] = (0, import_react4.useState)(false);
|
|
599
611
|
const { data, loading, error, setPage, setSort, currentPage, currentSort } = useReviews({
|
|
600
|
-
proxyUrl,
|
|
612
|
+
proxyUrl: resolvedUrl,
|
|
601
613
|
productId,
|
|
602
614
|
limit: pageSize,
|
|
603
615
|
...locale !== void 0 ? { locale } : {}
|
|
@@ -632,7 +644,7 @@ function ReviewWidget({
|
|
|
632
644
|
showingForm && form && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { marginBottom: 24 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
633
645
|
ReviewForm,
|
|
634
646
|
{
|
|
635
|
-
proxyUrl,
|
|
647
|
+
proxyUrl: resolvedUrl,
|
|
636
648
|
productId,
|
|
637
649
|
form,
|
|
638
650
|
onSuccess: () => setShowingForm(false)
|
|
@@ -715,8 +727,9 @@ function useWidgetGlobals({ proxyUrl, limit = 20 }) {
|
|
|
715
727
|
|
|
716
728
|
// src/components/ReviewCount.tsx
|
|
717
729
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
718
|
-
function ReviewCount({ proxyUrl, starColor, starSize, className }) {
|
|
719
|
-
const
|
|
730
|
+
function ReviewCount({ proxyUrl, storeDomain, starColor, starSize, className }) {
|
|
731
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
732
|
+
const { data, loading } = useWidgetGlobals({ proxyUrl: resolvedUrl });
|
|
720
733
|
if (loading || !data?.stats?.averageRating) return null;
|
|
721
734
|
const avg = parseFloat(data.stats.averageRating);
|
|
722
735
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className, style: { display: "inline-flex", alignItems: "center", gap: 6 }, children: [
|
|
@@ -735,13 +748,15 @@ var import_react6 = __toESM(require("react"), 1);
|
|
|
735
748
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
736
749
|
function ReviewCarousel({
|
|
737
750
|
proxyUrl,
|
|
751
|
+
storeDomain,
|
|
738
752
|
limit = 10,
|
|
739
753
|
autoPlay = true,
|
|
740
754
|
intervalMs = 4e3,
|
|
741
755
|
starColor,
|
|
742
756
|
className
|
|
743
757
|
}) {
|
|
744
|
-
const
|
|
758
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
759
|
+
const { data, loading } = useWidgetGlobals({ proxyUrl: resolvedUrl, limit });
|
|
745
760
|
const [index, setIndex] = (0, import_react6.useState)(0);
|
|
746
761
|
const reviews = data?.reviews ?? [];
|
|
747
762
|
import_react6.default.useEffect(() => {
|
|
@@ -790,12 +805,14 @@ var import_react7 = require("react");
|
|
|
790
805
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
791
806
|
function ReviewGallery({
|
|
792
807
|
proxyUrl,
|
|
808
|
+
storeDomain,
|
|
793
809
|
limit = 20,
|
|
794
810
|
columns = 3,
|
|
795
811
|
starColor,
|
|
796
812
|
className
|
|
797
813
|
}) {
|
|
798
|
-
const
|
|
814
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
815
|
+
const { data, loading } = useWidgetGlobals({ proxyUrl: resolvedUrl, limit });
|
|
799
816
|
const [lightbox, setLightbox] = (0, import_react7.useState)(null);
|
|
800
817
|
const items = (data?.reviews ?? []).filter((r) => r.image).map((r) => ({ url: r.image, review: r })).slice(0, limit);
|
|
801
818
|
if (loading) return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className, children: "Loading gallery\u2026" });
|
|
@@ -979,9 +996,10 @@ function useQnA({ proxyUrl, productId, page: initialPage = 1, sort = "recent" })
|
|
|
979
996
|
|
|
980
997
|
// src/components/QnAWidget.tsx
|
|
981
998
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
982
|
-
function QnAWidget({ proxyUrl, productId, className }) {
|
|
999
|
+
function QnAWidget({ proxyUrl, storeDomain, productId, className }) {
|
|
1000
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
983
1001
|
const { data, loading, error, setPage, currentPage, submitQuestion, submitState, resetSubmit } = useQnA({
|
|
984
|
-
proxyUrl,
|
|
1002
|
+
proxyUrl: resolvedUrl,
|
|
985
1003
|
productId
|
|
986
1004
|
});
|
|
987
1005
|
const [showForm, setShowForm] = (0, import_react9.useState)(false);
|
|
@@ -1074,13 +1092,15 @@ var import_react10 = require("react");
|
|
|
1074
1092
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1075
1093
|
function SocialProofPopup({
|
|
1076
1094
|
proxyUrl,
|
|
1095
|
+
storeDomain,
|
|
1077
1096
|
position = "bottom-left",
|
|
1078
1097
|
intervalMs = 8e3,
|
|
1079
1098
|
displayMs = 5e3,
|
|
1080
1099
|
starColor,
|
|
1081
1100
|
className
|
|
1082
1101
|
}) {
|
|
1083
|
-
const
|
|
1102
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
1103
|
+
const { data } = useWidgetGlobals({ proxyUrl: resolvedUrl });
|
|
1084
1104
|
const [current, setCurrent] = (0, import_react10.useState)(null);
|
|
1085
1105
|
const [visible, setVisible] = (0, import_react10.useState)(false);
|
|
1086
1106
|
const [dismissed, setDismissed] = (0, import_react10.useState)(false);
|
|
@@ -1183,12 +1203,14 @@ var import_react11 = require("react");
|
|
|
1183
1203
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1184
1204
|
function ReviewTicker({
|
|
1185
1205
|
proxyUrl,
|
|
1206
|
+
storeDomain,
|
|
1186
1207
|
limit = 20,
|
|
1187
1208
|
speedSeconds = 30,
|
|
1188
1209
|
starColor,
|
|
1189
1210
|
className
|
|
1190
1211
|
}) {
|
|
1191
|
-
const
|
|
1212
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
1213
|
+
const { data, loading } = useWidgetGlobals({ proxyUrl: resolvedUrl, limit });
|
|
1192
1214
|
const trackRef = (0, import_react11.useRef)(null);
|
|
1193
1215
|
const reviews = data?.reviews ?? [];
|
|
1194
1216
|
if (loading || reviews.length === 0) return null;
|
|
@@ -1250,6 +1272,7 @@ var import_react12 = require("react");
|
|
|
1250
1272
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1251
1273
|
function FloatingReviewsTab({
|
|
1252
1274
|
proxyUrl,
|
|
1275
|
+
storeDomain,
|
|
1253
1276
|
label = "Reviews",
|
|
1254
1277
|
position = "right",
|
|
1255
1278
|
color = "#111827",
|
|
@@ -1257,7 +1280,8 @@ function FloatingReviewsTab({
|
|
|
1257
1280
|
starColor,
|
|
1258
1281
|
className
|
|
1259
1282
|
}) {
|
|
1260
|
-
const
|
|
1283
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
1284
|
+
const { data } = useWidgetGlobals({ proxyUrl: resolvedUrl, limit });
|
|
1261
1285
|
const [open, setOpen] = (0, import_react12.useState)(false);
|
|
1262
1286
|
const reviews = data?.reviews ?? [];
|
|
1263
1287
|
const stats = data?.stats;
|
|
@@ -1334,8 +1358,9 @@ function FloatingReviewsTab({
|
|
|
1334
1358
|
|
|
1335
1359
|
// src/components/TrustBadge.tsx
|
|
1336
1360
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1337
|
-
function TrustBadge({ proxyUrl, style: badgeStyle = "pill", starColor, className }) {
|
|
1338
|
-
const
|
|
1361
|
+
function TrustBadge({ proxyUrl, storeDomain, style: badgeStyle = "pill", starColor, className }) {
|
|
1362
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
1363
|
+
const { data, loading } = useWidgetGlobals({ proxyUrl: resolvedUrl });
|
|
1339
1364
|
if (loading || !data?.stats?.averageRating) return null;
|
|
1340
1365
|
const avg = parseFloat(data.stats.averageRating);
|
|
1341
1366
|
const count = data.stats.totalReviews;
|
|
@@ -1441,14 +1466,16 @@ function useForm(proxyUrl, productId) {
|
|
|
1441
1466
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1442
1467
|
function FloatingReviewButton({
|
|
1443
1468
|
proxyUrl,
|
|
1469
|
+
storeDomain,
|
|
1444
1470
|
productId,
|
|
1445
1471
|
text = "Write a Review",
|
|
1446
1472
|
color = "#111827",
|
|
1447
1473
|
position = "bottom-right",
|
|
1448
1474
|
className
|
|
1449
1475
|
}) {
|
|
1476
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
1450
1477
|
const [open, setOpen] = (0, import_react14.useState)(false);
|
|
1451
|
-
const { form, loading } = useForm(
|
|
1478
|
+
const { form, loading } = useForm(resolvedUrl, productId);
|
|
1452
1479
|
const posStyle = position === "bottom-right" ? { bottom: 24, right: 24 } : { bottom: 24, left: 24 };
|
|
1453
1480
|
if (!loading && !form) return null;
|
|
1454
1481
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
@@ -1526,7 +1553,7 @@ function FloatingReviewButton({
|
|
|
1526
1553
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1527
1554
|
ReviewForm,
|
|
1528
1555
|
{
|
|
1529
|
-
proxyUrl,
|
|
1556
|
+
proxyUrl: resolvedUrl,
|
|
1530
1557
|
productId,
|
|
1531
1558
|
form,
|
|
1532
1559
|
onSuccess: () => setOpen(false)
|
|
@@ -1578,6 +1605,7 @@ function useHelpfulVote(proxyUrl) {
|
|
|
1578
1605
|
SocialProofPopup,
|
|
1579
1606
|
StarRating,
|
|
1580
1607
|
TrustBadge,
|
|
1608
|
+
resolveProxyUrl,
|
|
1581
1609
|
useForm,
|
|
1582
1610
|
useHelpfulVote,
|
|
1583
1611
|
useQnA,
|
package/dist/index.d.cts
CHANGED
|
@@ -1,16 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
-
type ReviewWidgetProps = {
|
|
4
|
-
proxyUrl: string;
|
|
5
|
-
productId: string;
|
|
6
|
-
locale?: string;
|
|
7
|
-
pageSize?: number;
|
|
8
|
-
showForm?: boolean;
|
|
9
|
-
starColor?: string;
|
|
10
|
-
className?: string;
|
|
11
|
-
};
|
|
12
|
-
declare function ReviewWidget({ proxyUrl, productId, locale, pageSize, showForm, starColor, className, }: ReviewWidgetProps): React.JSX.Element | null;
|
|
13
|
-
|
|
14
3
|
type ReviewMedia = {
|
|
15
4
|
url: string;
|
|
16
5
|
mimeType: string;
|
|
@@ -162,6 +151,25 @@ type HelpfulVoteResponse = {
|
|
|
162
151
|
helpfulCount: number;
|
|
163
152
|
};
|
|
164
153
|
type SortKey = 'recent' | 'helpful' | 'rating_high' | 'rating_low';
|
|
154
|
+
/**
|
|
155
|
+
* Every public component and hook accepts either an explicit proxyUrl or a
|
|
156
|
+
* storeDomain shorthand. Provide exactly one of the two.
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* // explicit
|
|
160
|
+
* proxyUrl={`https://${env.PUBLIC_STORE_DOMAIN}/apps/revova`}
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* // shorthand (Hydrogen-friendly)
|
|
164
|
+
* storeDomain={env.PUBLIC_STORE_DOMAIN}
|
|
165
|
+
*/
|
|
166
|
+
type ProxyProps = {
|
|
167
|
+
proxyUrl: string;
|
|
168
|
+
storeDomain?: never;
|
|
169
|
+
} | {
|
|
170
|
+
storeDomain: string;
|
|
171
|
+
proxyUrl?: never;
|
|
172
|
+
};
|
|
165
173
|
type UseReviewsOptions = {
|
|
166
174
|
proxyUrl: string;
|
|
167
175
|
productId: string;
|
|
@@ -223,22 +231,30 @@ type UseQnAOptions = {
|
|
|
223
231
|
sort?: 'recent' | 'helpful';
|
|
224
232
|
};
|
|
225
233
|
|
|
226
|
-
type
|
|
227
|
-
|
|
234
|
+
type ReviewWidgetProps = ProxyProps & {
|
|
235
|
+
productId: string;
|
|
236
|
+
locale?: string;
|
|
237
|
+
pageSize?: number;
|
|
238
|
+
showForm?: boolean;
|
|
239
|
+
starColor?: string;
|
|
240
|
+
className?: string;
|
|
241
|
+
};
|
|
242
|
+
declare function ReviewWidget({ proxyUrl, storeDomain, productId, locale, pageSize, showForm, starColor, className, }: ReviewWidgetProps): React.JSX.Element | null;
|
|
243
|
+
|
|
244
|
+
type ReviewFormProps = ProxyProps & {
|
|
228
245
|
productId: string;
|
|
229
246
|
form: ResolvedForm;
|
|
230
247
|
onSuccess?: () => void;
|
|
231
248
|
className?: string;
|
|
232
249
|
};
|
|
233
|
-
declare function ReviewForm({ proxyUrl, productId, form, onSuccess, className }: ReviewFormProps): React.JSX.Element;
|
|
250
|
+
declare function ReviewForm({ proxyUrl, storeDomain, productId, form, onSuccess, className }: ReviewFormProps): React.JSX.Element;
|
|
234
251
|
|
|
235
|
-
type ReviewCountProps = {
|
|
236
|
-
proxyUrl: string;
|
|
252
|
+
type ReviewCountProps = ProxyProps & {
|
|
237
253
|
starColor?: string;
|
|
238
254
|
starSize?: number;
|
|
239
255
|
className?: string;
|
|
240
256
|
};
|
|
241
|
-
declare function ReviewCount({ proxyUrl, starColor, starSize, className }: ReviewCountProps): React.JSX.Element | null;
|
|
257
|
+
declare function ReviewCount({ proxyUrl, storeDomain, starColor, starSize, className }: ReviewCountProps): React.JSX.Element | null;
|
|
242
258
|
|
|
243
259
|
type StarRatingProps = {
|
|
244
260
|
rating: number;
|
|
@@ -249,53 +265,47 @@ type StarRatingProps = {
|
|
|
249
265
|
};
|
|
250
266
|
declare function StarRating({ rating, max, size, color, className }: StarRatingProps): React.JSX.Element;
|
|
251
267
|
|
|
252
|
-
type ReviewCarouselProps = {
|
|
253
|
-
proxyUrl: string;
|
|
268
|
+
type ReviewCarouselProps = ProxyProps & {
|
|
254
269
|
limit?: number;
|
|
255
270
|
autoPlay?: boolean;
|
|
256
271
|
intervalMs?: number;
|
|
257
272
|
starColor?: string;
|
|
258
273
|
className?: string;
|
|
259
274
|
};
|
|
260
|
-
declare function ReviewCarousel({ proxyUrl, limit, autoPlay, intervalMs, starColor, className, }: ReviewCarouselProps): React.JSX.Element | null;
|
|
275
|
+
declare function ReviewCarousel({ proxyUrl, storeDomain, limit, autoPlay, intervalMs, starColor, className, }: ReviewCarouselProps): React.JSX.Element | null;
|
|
261
276
|
|
|
262
|
-
type ReviewGalleryProps = {
|
|
263
|
-
proxyUrl: string;
|
|
277
|
+
type ReviewGalleryProps = ProxyProps & {
|
|
264
278
|
limit?: number;
|
|
265
279
|
columns?: number;
|
|
266
280
|
starColor?: string;
|
|
267
281
|
className?: string;
|
|
268
282
|
};
|
|
269
|
-
declare function ReviewGallery({ proxyUrl, limit, columns, starColor, className, }: ReviewGalleryProps): React.JSX.Element | null;
|
|
283
|
+
declare function ReviewGallery({ proxyUrl, storeDomain, limit, columns, starColor, className, }: ReviewGalleryProps): React.JSX.Element | null;
|
|
270
284
|
|
|
271
|
-
type QnAWidgetProps = {
|
|
272
|
-
proxyUrl: string;
|
|
285
|
+
type QnAWidgetProps = ProxyProps & {
|
|
273
286
|
productId: string;
|
|
274
287
|
className?: string;
|
|
275
288
|
};
|
|
276
|
-
declare function QnAWidget({ proxyUrl, productId, className }: QnAWidgetProps): React.JSX.Element | null;
|
|
289
|
+
declare function QnAWidget({ proxyUrl, storeDomain, productId, className }: QnAWidgetProps): React.JSX.Element | null;
|
|
277
290
|
|
|
278
|
-
type SocialProofPopupProps = {
|
|
279
|
-
proxyUrl: string;
|
|
291
|
+
type SocialProofPopupProps = ProxyProps & {
|
|
280
292
|
position?: 'bottom-left' | 'bottom-right';
|
|
281
293
|
intervalMs?: number;
|
|
282
294
|
displayMs?: number;
|
|
283
295
|
starColor?: string;
|
|
284
296
|
className?: string;
|
|
285
297
|
};
|
|
286
|
-
declare function SocialProofPopup({ proxyUrl, position, intervalMs, displayMs, starColor, className, }: SocialProofPopupProps): React.JSX.Element | null;
|
|
298
|
+
declare function SocialProofPopup({ proxyUrl, storeDomain, position, intervalMs, displayMs, starColor, className, }: SocialProofPopupProps): React.JSX.Element | null;
|
|
287
299
|
|
|
288
|
-
type ReviewTickerProps = {
|
|
289
|
-
proxyUrl: string;
|
|
300
|
+
type ReviewTickerProps = ProxyProps & {
|
|
290
301
|
limit?: number;
|
|
291
302
|
speedSeconds?: number;
|
|
292
303
|
starColor?: string;
|
|
293
304
|
className?: string;
|
|
294
305
|
};
|
|
295
|
-
declare function ReviewTicker({ proxyUrl, limit, speedSeconds, starColor, className, }: ReviewTickerProps): React.JSX.Element | null;
|
|
306
|
+
declare function ReviewTicker({ proxyUrl, storeDomain, limit, speedSeconds, starColor, className, }: ReviewTickerProps): React.JSX.Element | null;
|
|
296
307
|
|
|
297
|
-
type FloatingReviewsTabProps = {
|
|
298
|
-
proxyUrl: string;
|
|
308
|
+
type FloatingReviewsTabProps = ProxyProps & {
|
|
299
309
|
label?: string;
|
|
300
310
|
position?: 'left' | 'right';
|
|
301
311
|
color?: string;
|
|
@@ -303,25 +313,28 @@ type FloatingReviewsTabProps = {
|
|
|
303
313
|
starColor?: string;
|
|
304
314
|
className?: string;
|
|
305
315
|
};
|
|
306
|
-
declare function FloatingReviewsTab({ proxyUrl, label, position, color, limit, starColor, className, }: FloatingReviewsTabProps): React.JSX.Element;
|
|
316
|
+
declare function FloatingReviewsTab({ proxyUrl, storeDomain, label, position, color, limit, starColor, className, }: FloatingReviewsTabProps): React.JSX.Element;
|
|
307
317
|
|
|
308
|
-
type TrustBadgeProps = {
|
|
309
|
-
proxyUrl: string;
|
|
318
|
+
type TrustBadgeProps = ProxyProps & {
|
|
310
319
|
style?: 'inline' | 'pill' | 'card';
|
|
311
320
|
starColor?: string;
|
|
312
321
|
className?: string;
|
|
313
322
|
};
|
|
314
|
-
declare function TrustBadge({ proxyUrl, style: badgeStyle, starColor, className }: TrustBadgeProps): React.JSX.Element | null;
|
|
323
|
+
declare function TrustBadge({ proxyUrl, storeDomain, style: badgeStyle, starColor, className }: TrustBadgeProps): React.JSX.Element | null;
|
|
315
324
|
|
|
316
|
-
type FloatingReviewButtonProps = {
|
|
317
|
-
proxyUrl: string;
|
|
325
|
+
type FloatingReviewButtonProps = ProxyProps & {
|
|
318
326
|
productId: string;
|
|
319
327
|
text?: string;
|
|
320
328
|
color?: string;
|
|
321
329
|
position?: 'bottom-left' | 'bottom-right';
|
|
322
330
|
className?: string;
|
|
323
331
|
};
|
|
324
|
-
declare function FloatingReviewButton({ proxyUrl, productId, text, color, position, className, }: FloatingReviewButtonProps): React.JSX.Element | null;
|
|
332
|
+
declare function FloatingReviewButton({ proxyUrl, storeDomain, productId, text, color, position, className, }: FloatingReviewButtonProps): React.JSX.Element | null;
|
|
333
|
+
|
|
334
|
+
declare function resolveProxyUrl(props: {
|
|
335
|
+
proxyUrl?: string | undefined;
|
|
336
|
+
storeDomain?: string | undefined;
|
|
337
|
+
}): string;
|
|
325
338
|
|
|
326
339
|
type State$3 = {
|
|
327
340
|
data: ReviewsResponse | null;
|
|
@@ -395,4 +408,4 @@ type State = {
|
|
|
395
408
|
*/
|
|
396
409
|
declare function useForm(proxyUrl: string, productId: string): State;
|
|
397
410
|
|
|
398
|
-
export { type AdminReply, type AttributeRating, FloatingReviewButton, FloatingReviewsTab, type FormField, type GlobalReview, type HelpfulVotePayload, type HelpfulVoteResponse, type ProductQuestion, type QnAAnswer, type QnAPagination, type QnAResponse, QnAWidget, type ResolvedForm, type Review, ReviewCarousel, ReviewCount, type ReviewFieldAnswer, ReviewForm, ReviewGallery, type ReviewMedia, ReviewTicker, ReviewWidget, type ReviewsPagination, type ReviewsResponse, type ShopStats, SocialProofPopup, type SortKey, StarRating, type SubmitAnswerPayload, type SubmitQuestionPayload, type SubmitReviewPayload, type SubmitReviewResponse, TrustBadge, type UseQnAOptions, type UseReviewsOptions, type UseWidgetGlobalsOptions, type WidgetConfig, type WidgetGlobalsResponse, type WidgetTheme, useForm, useHelpfulVote, useQnA, useReviews, useSubmitReview, useWidgetGlobals };
|
|
411
|
+
export { type AdminReply, type AttributeRating, FloatingReviewButton, FloatingReviewsTab, type FormField, type GlobalReview, type HelpfulVotePayload, type HelpfulVoteResponse, type ProductQuestion, type ProxyProps, type QnAAnswer, type QnAPagination, type QnAResponse, QnAWidget, type ResolvedForm, type Review, ReviewCarousel, ReviewCount, type ReviewFieldAnswer, ReviewForm, ReviewGallery, type ReviewMedia, ReviewTicker, ReviewWidget, type ReviewsPagination, type ReviewsResponse, type ShopStats, SocialProofPopup, type SortKey, StarRating, type SubmitAnswerPayload, type SubmitQuestionPayload, type SubmitReviewPayload, type SubmitReviewResponse, TrustBadge, type UseQnAOptions, type UseReviewsOptions, type UseWidgetGlobalsOptions, type WidgetConfig, type WidgetGlobalsResponse, type WidgetTheme, resolveProxyUrl, useForm, useHelpfulVote, useQnA, useReviews, useSubmitReview, useWidgetGlobals };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
-
type ReviewWidgetProps = {
|
|
4
|
-
proxyUrl: string;
|
|
5
|
-
productId: string;
|
|
6
|
-
locale?: string;
|
|
7
|
-
pageSize?: number;
|
|
8
|
-
showForm?: boolean;
|
|
9
|
-
starColor?: string;
|
|
10
|
-
className?: string;
|
|
11
|
-
};
|
|
12
|
-
declare function ReviewWidget({ proxyUrl, productId, locale, pageSize, showForm, starColor, className, }: ReviewWidgetProps): React.JSX.Element | null;
|
|
13
|
-
|
|
14
3
|
type ReviewMedia = {
|
|
15
4
|
url: string;
|
|
16
5
|
mimeType: string;
|
|
@@ -162,6 +151,25 @@ type HelpfulVoteResponse = {
|
|
|
162
151
|
helpfulCount: number;
|
|
163
152
|
};
|
|
164
153
|
type SortKey = 'recent' | 'helpful' | 'rating_high' | 'rating_low';
|
|
154
|
+
/**
|
|
155
|
+
* Every public component and hook accepts either an explicit proxyUrl or a
|
|
156
|
+
* storeDomain shorthand. Provide exactly one of the two.
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* // explicit
|
|
160
|
+
* proxyUrl={`https://${env.PUBLIC_STORE_DOMAIN}/apps/revova`}
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* // shorthand (Hydrogen-friendly)
|
|
164
|
+
* storeDomain={env.PUBLIC_STORE_DOMAIN}
|
|
165
|
+
*/
|
|
166
|
+
type ProxyProps = {
|
|
167
|
+
proxyUrl: string;
|
|
168
|
+
storeDomain?: never;
|
|
169
|
+
} | {
|
|
170
|
+
storeDomain: string;
|
|
171
|
+
proxyUrl?: never;
|
|
172
|
+
};
|
|
165
173
|
type UseReviewsOptions = {
|
|
166
174
|
proxyUrl: string;
|
|
167
175
|
productId: string;
|
|
@@ -223,22 +231,30 @@ type UseQnAOptions = {
|
|
|
223
231
|
sort?: 'recent' | 'helpful';
|
|
224
232
|
};
|
|
225
233
|
|
|
226
|
-
type
|
|
227
|
-
|
|
234
|
+
type ReviewWidgetProps = ProxyProps & {
|
|
235
|
+
productId: string;
|
|
236
|
+
locale?: string;
|
|
237
|
+
pageSize?: number;
|
|
238
|
+
showForm?: boolean;
|
|
239
|
+
starColor?: string;
|
|
240
|
+
className?: string;
|
|
241
|
+
};
|
|
242
|
+
declare function ReviewWidget({ proxyUrl, storeDomain, productId, locale, pageSize, showForm, starColor, className, }: ReviewWidgetProps): React.JSX.Element | null;
|
|
243
|
+
|
|
244
|
+
type ReviewFormProps = ProxyProps & {
|
|
228
245
|
productId: string;
|
|
229
246
|
form: ResolvedForm;
|
|
230
247
|
onSuccess?: () => void;
|
|
231
248
|
className?: string;
|
|
232
249
|
};
|
|
233
|
-
declare function ReviewForm({ proxyUrl, productId, form, onSuccess, className }: ReviewFormProps): React.JSX.Element;
|
|
250
|
+
declare function ReviewForm({ proxyUrl, storeDomain, productId, form, onSuccess, className }: ReviewFormProps): React.JSX.Element;
|
|
234
251
|
|
|
235
|
-
type ReviewCountProps = {
|
|
236
|
-
proxyUrl: string;
|
|
252
|
+
type ReviewCountProps = ProxyProps & {
|
|
237
253
|
starColor?: string;
|
|
238
254
|
starSize?: number;
|
|
239
255
|
className?: string;
|
|
240
256
|
};
|
|
241
|
-
declare function ReviewCount({ proxyUrl, starColor, starSize, className }: ReviewCountProps): React.JSX.Element | null;
|
|
257
|
+
declare function ReviewCount({ proxyUrl, storeDomain, starColor, starSize, className }: ReviewCountProps): React.JSX.Element | null;
|
|
242
258
|
|
|
243
259
|
type StarRatingProps = {
|
|
244
260
|
rating: number;
|
|
@@ -249,53 +265,47 @@ type StarRatingProps = {
|
|
|
249
265
|
};
|
|
250
266
|
declare function StarRating({ rating, max, size, color, className }: StarRatingProps): React.JSX.Element;
|
|
251
267
|
|
|
252
|
-
type ReviewCarouselProps = {
|
|
253
|
-
proxyUrl: string;
|
|
268
|
+
type ReviewCarouselProps = ProxyProps & {
|
|
254
269
|
limit?: number;
|
|
255
270
|
autoPlay?: boolean;
|
|
256
271
|
intervalMs?: number;
|
|
257
272
|
starColor?: string;
|
|
258
273
|
className?: string;
|
|
259
274
|
};
|
|
260
|
-
declare function ReviewCarousel({ proxyUrl, limit, autoPlay, intervalMs, starColor, className, }: ReviewCarouselProps): React.JSX.Element | null;
|
|
275
|
+
declare function ReviewCarousel({ proxyUrl, storeDomain, limit, autoPlay, intervalMs, starColor, className, }: ReviewCarouselProps): React.JSX.Element | null;
|
|
261
276
|
|
|
262
|
-
type ReviewGalleryProps = {
|
|
263
|
-
proxyUrl: string;
|
|
277
|
+
type ReviewGalleryProps = ProxyProps & {
|
|
264
278
|
limit?: number;
|
|
265
279
|
columns?: number;
|
|
266
280
|
starColor?: string;
|
|
267
281
|
className?: string;
|
|
268
282
|
};
|
|
269
|
-
declare function ReviewGallery({ proxyUrl, limit, columns, starColor, className, }: ReviewGalleryProps): React.JSX.Element | null;
|
|
283
|
+
declare function ReviewGallery({ proxyUrl, storeDomain, limit, columns, starColor, className, }: ReviewGalleryProps): React.JSX.Element | null;
|
|
270
284
|
|
|
271
|
-
type QnAWidgetProps = {
|
|
272
|
-
proxyUrl: string;
|
|
285
|
+
type QnAWidgetProps = ProxyProps & {
|
|
273
286
|
productId: string;
|
|
274
287
|
className?: string;
|
|
275
288
|
};
|
|
276
|
-
declare function QnAWidget({ proxyUrl, productId, className }: QnAWidgetProps): React.JSX.Element | null;
|
|
289
|
+
declare function QnAWidget({ proxyUrl, storeDomain, productId, className }: QnAWidgetProps): React.JSX.Element | null;
|
|
277
290
|
|
|
278
|
-
type SocialProofPopupProps = {
|
|
279
|
-
proxyUrl: string;
|
|
291
|
+
type SocialProofPopupProps = ProxyProps & {
|
|
280
292
|
position?: 'bottom-left' | 'bottom-right';
|
|
281
293
|
intervalMs?: number;
|
|
282
294
|
displayMs?: number;
|
|
283
295
|
starColor?: string;
|
|
284
296
|
className?: string;
|
|
285
297
|
};
|
|
286
|
-
declare function SocialProofPopup({ proxyUrl, position, intervalMs, displayMs, starColor, className, }: SocialProofPopupProps): React.JSX.Element | null;
|
|
298
|
+
declare function SocialProofPopup({ proxyUrl, storeDomain, position, intervalMs, displayMs, starColor, className, }: SocialProofPopupProps): React.JSX.Element | null;
|
|
287
299
|
|
|
288
|
-
type ReviewTickerProps = {
|
|
289
|
-
proxyUrl: string;
|
|
300
|
+
type ReviewTickerProps = ProxyProps & {
|
|
290
301
|
limit?: number;
|
|
291
302
|
speedSeconds?: number;
|
|
292
303
|
starColor?: string;
|
|
293
304
|
className?: string;
|
|
294
305
|
};
|
|
295
|
-
declare function ReviewTicker({ proxyUrl, limit, speedSeconds, starColor, className, }: ReviewTickerProps): React.JSX.Element | null;
|
|
306
|
+
declare function ReviewTicker({ proxyUrl, storeDomain, limit, speedSeconds, starColor, className, }: ReviewTickerProps): React.JSX.Element | null;
|
|
296
307
|
|
|
297
|
-
type FloatingReviewsTabProps = {
|
|
298
|
-
proxyUrl: string;
|
|
308
|
+
type FloatingReviewsTabProps = ProxyProps & {
|
|
299
309
|
label?: string;
|
|
300
310
|
position?: 'left' | 'right';
|
|
301
311
|
color?: string;
|
|
@@ -303,25 +313,28 @@ type FloatingReviewsTabProps = {
|
|
|
303
313
|
starColor?: string;
|
|
304
314
|
className?: string;
|
|
305
315
|
};
|
|
306
|
-
declare function FloatingReviewsTab({ proxyUrl, label, position, color, limit, starColor, className, }: FloatingReviewsTabProps): React.JSX.Element;
|
|
316
|
+
declare function FloatingReviewsTab({ proxyUrl, storeDomain, label, position, color, limit, starColor, className, }: FloatingReviewsTabProps): React.JSX.Element;
|
|
307
317
|
|
|
308
|
-
type TrustBadgeProps = {
|
|
309
|
-
proxyUrl: string;
|
|
318
|
+
type TrustBadgeProps = ProxyProps & {
|
|
310
319
|
style?: 'inline' | 'pill' | 'card';
|
|
311
320
|
starColor?: string;
|
|
312
321
|
className?: string;
|
|
313
322
|
};
|
|
314
|
-
declare function TrustBadge({ proxyUrl, style: badgeStyle, starColor, className }: TrustBadgeProps): React.JSX.Element | null;
|
|
323
|
+
declare function TrustBadge({ proxyUrl, storeDomain, style: badgeStyle, starColor, className }: TrustBadgeProps): React.JSX.Element | null;
|
|
315
324
|
|
|
316
|
-
type FloatingReviewButtonProps = {
|
|
317
|
-
proxyUrl: string;
|
|
325
|
+
type FloatingReviewButtonProps = ProxyProps & {
|
|
318
326
|
productId: string;
|
|
319
327
|
text?: string;
|
|
320
328
|
color?: string;
|
|
321
329
|
position?: 'bottom-left' | 'bottom-right';
|
|
322
330
|
className?: string;
|
|
323
331
|
};
|
|
324
|
-
declare function FloatingReviewButton({ proxyUrl, productId, text, color, position, className, }: FloatingReviewButtonProps): React.JSX.Element | null;
|
|
332
|
+
declare function FloatingReviewButton({ proxyUrl, storeDomain, productId, text, color, position, className, }: FloatingReviewButtonProps): React.JSX.Element | null;
|
|
333
|
+
|
|
334
|
+
declare function resolveProxyUrl(props: {
|
|
335
|
+
proxyUrl?: string | undefined;
|
|
336
|
+
storeDomain?: string | undefined;
|
|
337
|
+
}): string;
|
|
325
338
|
|
|
326
339
|
type State$3 = {
|
|
327
340
|
data: ReviewsResponse | null;
|
|
@@ -395,4 +408,4 @@ type State = {
|
|
|
395
408
|
*/
|
|
396
409
|
declare function useForm(proxyUrl: string, productId: string): State;
|
|
397
410
|
|
|
398
|
-
export { type AdminReply, type AttributeRating, FloatingReviewButton, FloatingReviewsTab, type FormField, type GlobalReview, type HelpfulVotePayload, type HelpfulVoteResponse, type ProductQuestion, type QnAAnswer, type QnAPagination, type QnAResponse, QnAWidget, type ResolvedForm, type Review, ReviewCarousel, ReviewCount, type ReviewFieldAnswer, ReviewForm, ReviewGallery, type ReviewMedia, ReviewTicker, ReviewWidget, type ReviewsPagination, type ReviewsResponse, type ShopStats, SocialProofPopup, type SortKey, StarRating, type SubmitAnswerPayload, type SubmitQuestionPayload, type SubmitReviewPayload, type SubmitReviewResponse, TrustBadge, type UseQnAOptions, type UseReviewsOptions, type UseWidgetGlobalsOptions, type WidgetConfig, type WidgetGlobalsResponse, type WidgetTheme, useForm, useHelpfulVote, useQnA, useReviews, useSubmitReview, useWidgetGlobals };
|
|
411
|
+
export { type AdminReply, type AttributeRating, FloatingReviewButton, FloatingReviewsTab, type FormField, type GlobalReview, type HelpfulVotePayload, type HelpfulVoteResponse, type ProductQuestion, type ProxyProps, type QnAAnswer, type QnAPagination, type QnAResponse, QnAWidget, type ResolvedForm, type Review, ReviewCarousel, ReviewCount, type ReviewFieldAnswer, ReviewForm, ReviewGallery, type ReviewMedia, ReviewTicker, ReviewWidget, type ReviewsPagination, type ReviewsResponse, type ShopStats, SocialProofPopup, type SortKey, StarRating, type SubmitAnswerPayload, type SubmitQuestionPayload, type SubmitReviewPayload, type SubmitReviewResponse, TrustBadge, type UseQnAOptions, type UseReviewsOptions, type UseWidgetGlobalsOptions, type WidgetConfig, type WidgetGlobalsResponse, type WidgetTheme, resolveProxyUrl, useForm, useHelpfulVote, useQnA, useReviews, useSubmitReview, useWidgetGlobals };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
// src/components/ReviewWidget.tsx
|
|
2
2
|
import { useState as useState4 } from "react";
|
|
3
3
|
|
|
4
|
+
// src/utils.ts
|
|
5
|
+
var PROXY_PATH = "/apps/revova";
|
|
6
|
+
function resolveProxyUrl(props) {
|
|
7
|
+
if (props.storeDomain) return `https://${props.storeDomain}${PROXY_PATH}`;
|
|
8
|
+
if (props.proxyUrl) return props.proxyUrl;
|
|
9
|
+
throw new Error("[Revova] Provide either proxyUrl or storeDomain.");
|
|
10
|
+
}
|
|
11
|
+
|
|
4
12
|
// src/hooks/useReviews.ts
|
|
5
13
|
import { useEffect, useState, useCallback } from "react";
|
|
6
14
|
function useReviews({
|
|
@@ -426,8 +434,9 @@ function FieldRenderer(props) {
|
|
|
426
434
|
return null;
|
|
427
435
|
}
|
|
428
436
|
}
|
|
429
|
-
function ReviewForm({ proxyUrl, productId, form, onSuccess, className }) {
|
|
430
|
-
const
|
|
437
|
+
function ReviewForm({ proxyUrl, storeDomain, productId, form, onSuccess, className }) {
|
|
438
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
439
|
+
const { submit, submitting, success, error, result } = useSubmitReview(resolvedUrl);
|
|
431
440
|
const [answers, setAnswers] = useState3({});
|
|
432
441
|
const [email, setEmail] = useState3("");
|
|
433
442
|
const starField = form.fields.find((f) => f.type === "STAR_RATING");
|
|
@@ -535,6 +544,7 @@ function ReviewForm({ proxyUrl, productId, form, onSuccess, className }) {
|
|
|
535
544
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
536
545
|
function ReviewWidget({
|
|
537
546
|
proxyUrl,
|
|
547
|
+
storeDomain,
|
|
538
548
|
productId,
|
|
539
549
|
locale,
|
|
540
550
|
pageSize = 10,
|
|
@@ -542,9 +552,10 @@ function ReviewWidget({
|
|
|
542
552
|
starColor,
|
|
543
553
|
className
|
|
544
554
|
}) {
|
|
555
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
545
556
|
const [showingForm, setShowingForm] = useState4(false);
|
|
546
557
|
const { data, loading, error, setPage, setSort, currentPage, currentSort } = useReviews({
|
|
547
|
-
proxyUrl,
|
|
558
|
+
proxyUrl: resolvedUrl,
|
|
548
559
|
productId,
|
|
549
560
|
limit: pageSize,
|
|
550
561
|
...locale !== void 0 ? { locale } : {}
|
|
@@ -579,7 +590,7 @@ function ReviewWidget({
|
|
|
579
590
|
showingForm && form && /* @__PURE__ */ jsx3("div", { style: { marginBottom: 24 }, children: /* @__PURE__ */ jsx3(
|
|
580
591
|
ReviewForm,
|
|
581
592
|
{
|
|
582
|
-
proxyUrl,
|
|
593
|
+
proxyUrl: resolvedUrl,
|
|
583
594
|
productId,
|
|
584
595
|
form,
|
|
585
596
|
onSuccess: () => setShowingForm(false)
|
|
@@ -662,8 +673,9 @@ function useWidgetGlobals({ proxyUrl, limit = 20 }) {
|
|
|
662
673
|
|
|
663
674
|
// src/components/ReviewCount.tsx
|
|
664
675
|
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
665
|
-
function ReviewCount({ proxyUrl, starColor, starSize, className }) {
|
|
666
|
-
const
|
|
676
|
+
function ReviewCount({ proxyUrl, storeDomain, starColor, starSize, className }) {
|
|
677
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
678
|
+
const { data, loading } = useWidgetGlobals({ proxyUrl: resolvedUrl });
|
|
667
679
|
if (loading || !data?.stats?.averageRating) return null;
|
|
668
680
|
const avg = parseFloat(data.stats.averageRating);
|
|
669
681
|
return /* @__PURE__ */ jsxs4("span", { className, style: { display: "inline-flex", alignItems: "center", gap: 6 }, children: [
|
|
@@ -682,13 +694,15 @@ import React3, { useState as useState6 } from "react";
|
|
|
682
694
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
683
695
|
function ReviewCarousel({
|
|
684
696
|
proxyUrl,
|
|
697
|
+
storeDomain,
|
|
685
698
|
limit = 10,
|
|
686
699
|
autoPlay = true,
|
|
687
700
|
intervalMs = 4e3,
|
|
688
701
|
starColor,
|
|
689
702
|
className
|
|
690
703
|
}) {
|
|
691
|
-
const
|
|
704
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
705
|
+
const { data, loading } = useWidgetGlobals({ proxyUrl: resolvedUrl, limit });
|
|
692
706
|
const [index, setIndex] = useState6(0);
|
|
693
707
|
const reviews = data?.reviews ?? [];
|
|
694
708
|
React3.useEffect(() => {
|
|
@@ -737,12 +751,14 @@ import { useState as useState7 } from "react";
|
|
|
737
751
|
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
738
752
|
function ReviewGallery({
|
|
739
753
|
proxyUrl,
|
|
754
|
+
storeDomain,
|
|
740
755
|
limit = 20,
|
|
741
756
|
columns = 3,
|
|
742
757
|
starColor,
|
|
743
758
|
className
|
|
744
759
|
}) {
|
|
745
|
-
const
|
|
760
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
761
|
+
const { data, loading } = useWidgetGlobals({ proxyUrl: resolvedUrl, limit });
|
|
746
762
|
const [lightbox, setLightbox] = useState7(null);
|
|
747
763
|
const items = (data?.reviews ?? []).filter((r) => r.image).map((r) => ({ url: r.image, review: r })).slice(0, limit);
|
|
748
764
|
if (loading) return /* @__PURE__ */ jsx6("div", { className, children: "Loading gallery\u2026" });
|
|
@@ -926,9 +942,10 @@ function useQnA({ proxyUrl, productId, page: initialPage = 1, sort = "recent" })
|
|
|
926
942
|
|
|
927
943
|
// src/components/QnAWidget.tsx
|
|
928
944
|
import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
929
|
-
function QnAWidget({ proxyUrl, productId, className }) {
|
|
945
|
+
function QnAWidget({ proxyUrl, storeDomain, productId, className }) {
|
|
946
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
930
947
|
const { data, loading, error, setPage, currentPage, submitQuestion, submitState, resetSubmit } = useQnA({
|
|
931
|
-
proxyUrl,
|
|
948
|
+
proxyUrl: resolvedUrl,
|
|
932
949
|
productId
|
|
933
950
|
});
|
|
934
951
|
const [showForm, setShowForm] = useState9(false);
|
|
@@ -1021,13 +1038,15 @@ import { useEffect as useEffect4, useState as useState10 } from "react";
|
|
|
1021
1038
|
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1022
1039
|
function SocialProofPopup({
|
|
1023
1040
|
proxyUrl,
|
|
1041
|
+
storeDomain,
|
|
1024
1042
|
position = "bottom-left",
|
|
1025
1043
|
intervalMs = 8e3,
|
|
1026
1044
|
displayMs = 5e3,
|
|
1027
1045
|
starColor,
|
|
1028
1046
|
className
|
|
1029
1047
|
}) {
|
|
1030
|
-
const
|
|
1048
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
1049
|
+
const { data } = useWidgetGlobals({ proxyUrl: resolvedUrl });
|
|
1031
1050
|
const [current, setCurrent] = useState10(null);
|
|
1032
1051
|
const [visible, setVisible] = useState10(false);
|
|
1033
1052
|
const [dismissed, setDismissed] = useState10(false);
|
|
@@ -1130,12 +1149,14 @@ import { useRef } from "react";
|
|
|
1130
1149
|
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1131
1150
|
function ReviewTicker({
|
|
1132
1151
|
proxyUrl,
|
|
1152
|
+
storeDomain,
|
|
1133
1153
|
limit = 20,
|
|
1134
1154
|
speedSeconds = 30,
|
|
1135
1155
|
starColor,
|
|
1136
1156
|
className
|
|
1137
1157
|
}) {
|
|
1138
|
-
const
|
|
1158
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
1159
|
+
const { data, loading } = useWidgetGlobals({ proxyUrl: resolvedUrl, limit });
|
|
1139
1160
|
const trackRef = useRef(null);
|
|
1140
1161
|
const reviews = data?.reviews ?? [];
|
|
1141
1162
|
if (loading || reviews.length === 0) return null;
|
|
@@ -1197,6 +1218,7 @@ import { useState as useState11 } from "react";
|
|
|
1197
1218
|
import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1198
1219
|
function FloatingReviewsTab({
|
|
1199
1220
|
proxyUrl,
|
|
1221
|
+
storeDomain,
|
|
1200
1222
|
label = "Reviews",
|
|
1201
1223
|
position = "right",
|
|
1202
1224
|
color = "#111827",
|
|
@@ -1204,7 +1226,8 @@ function FloatingReviewsTab({
|
|
|
1204
1226
|
starColor,
|
|
1205
1227
|
className
|
|
1206
1228
|
}) {
|
|
1207
|
-
const
|
|
1229
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
1230
|
+
const { data } = useWidgetGlobals({ proxyUrl: resolvedUrl, limit });
|
|
1208
1231
|
const [open, setOpen] = useState11(false);
|
|
1209
1232
|
const reviews = data?.reviews ?? [];
|
|
1210
1233
|
const stats = data?.stats;
|
|
@@ -1281,8 +1304,9 @@ function FloatingReviewsTab({
|
|
|
1281
1304
|
|
|
1282
1305
|
// src/components/TrustBadge.tsx
|
|
1283
1306
|
import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1284
|
-
function TrustBadge({ proxyUrl, style: badgeStyle = "pill", starColor, className }) {
|
|
1285
|
-
const
|
|
1307
|
+
function TrustBadge({ proxyUrl, storeDomain, style: badgeStyle = "pill", starColor, className }) {
|
|
1308
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
1309
|
+
const { data, loading } = useWidgetGlobals({ proxyUrl: resolvedUrl });
|
|
1286
1310
|
if (loading || !data?.stats?.averageRating) return null;
|
|
1287
1311
|
const avg = parseFloat(data.stats.averageRating);
|
|
1288
1312
|
const count = data.stats.totalReviews;
|
|
@@ -1388,14 +1412,16 @@ function useForm(proxyUrl, productId) {
|
|
|
1388
1412
|
import { Fragment as Fragment5, jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1389
1413
|
function FloatingReviewButton({
|
|
1390
1414
|
proxyUrl,
|
|
1415
|
+
storeDomain,
|
|
1391
1416
|
productId,
|
|
1392
1417
|
text = "Write a Review",
|
|
1393
1418
|
color = "#111827",
|
|
1394
1419
|
position = "bottom-right",
|
|
1395
1420
|
className
|
|
1396
1421
|
}) {
|
|
1422
|
+
const resolvedUrl = resolveProxyUrl({ proxyUrl, storeDomain });
|
|
1397
1423
|
const [open, setOpen] = useState13(false);
|
|
1398
|
-
const { form, loading } = useForm(
|
|
1424
|
+
const { form, loading } = useForm(resolvedUrl, productId);
|
|
1399
1425
|
const posStyle = position === "bottom-right" ? { bottom: 24, right: 24 } : { bottom: 24, left: 24 };
|
|
1400
1426
|
if (!loading && !form) return null;
|
|
1401
1427
|
return /* @__PURE__ */ jsxs12(Fragment5, { children: [
|
|
@@ -1473,7 +1499,7 @@ function FloatingReviewButton({
|
|
|
1473
1499
|
/* @__PURE__ */ jsx12(
|
|
1474
1500
|
ReviewForm,
|
|
1475
1501
|
{
|
|
1476
|
-
proxyUrl,
|
|
1502
|
+
proxyUrl: resolvedUrl,
|
|
1477
1503
|
productId,
|
|
1478
1504
|
form,
|
|
1479
1505
|
onSuccess: () => setOpen(false)
|
|
@@ -1524,6 +1550,7 @@ export {
|
|
|
1524
1550
|
SocialProofPopup,
|
|
1525
1551
|
StarRating,
|
|
1526
1552
|
TrustBadge,
|
|
1553
|
+
resolveProxyUrl,
|
|
1527
1554
|
useForm,
|
|
1528
1555
|
useHelpfulVote,
|
|
1529
1556
|
useQnA,
|