@shopify/shop-minis-react 0.0.11 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/debounce.js +8 -0
- package/dist/_virtual/debounce.js.map +1 -0
- package/dist/_virtual/index2.js +3 -2
- package/dist/_virtual/index2.js.map +1 -1
- package/dist/_virtual/index3.js +2 -3
- package/dist/_virtual/index3.js.map +1 -1
- package/dist/components/commerce/merchant-card.js +201 -0
- package/dist/components/commerce/merchant-card.js.map +1 -0
- package/dist/components/commerce/product-card.js +11 -9
- package/dist/components/commerce/product-card.js.map +1 -1
- package/dist/hooks/product/useCuratedProducts.js +20 -0
- package/dist/hooks/product/useCuratedProducts.js.map +1 -0
- package/dist/hooks/product/useProduct.js +24 -0
- package/dist/hooks/product/useProduct.js.map +1 -0
- package/dist/hooks/product/useProductMedia.js +24 -0
- package/dist/hooks/product/useProductMedia.js.map +1 -0
- package/dist/hooks/product/useProductSearch.js +44 -0
- package/dist/hooks/product/useProductSearch.js.map +1 -0
- package/dist/hooks/product/useProductVariants.js +21 -0
- package/dist/hooks/product/useProductVariants.js.map +1 -0
- package/dist/hooks/product/useProducts.js +17 -0
- package/dist/hooks/product/useProducts.js.map +1 -0
- package/dist/hooks/shop/useShop.js +17 -0
- package/dist/hooks/shop/useShop.js.map +1 -0
- package/dist/hooks/user/useFollowedShops.js +21 -0
- package/dist/hooks/user/useFollowedShops.js.map +1 -0
- package/dist/hooks/user/useRecentProducts.js +21 -0
- package/dist/hooks/user/useRecentProducts.js.map +1 -0
- package/dist/hooks/user/useRecentShops.js +21 -0
- package/dist/hooks/user/useRecentShops.js.map +1 -0
- package/dist/hooks/user/useSavedProducts.js +21 -0
- package/dist/hooks/user/useSavedProducts.js.map +1 -0
- package/dist/index.js +210 -178
- package/dist/index.js.map +1 -1
- package/dist/internal/useShopActionsPaginatedDataFetching.js +24 -24
- package/dist/internal/useShopActionsPaginatedDataFetching.js.map +1 -1
- package/dist/node_modules/.pnpm/@radix-ui_react-use-is-hydrated@0.1.0_@types_react@19.1.6_react@19.1.0/node_modules/@radix-ui/react-use-is-hydrated/dist/index.js +1 -1
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_Symbol.js +12 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_Symbol.js.map +1 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_baseGetTag.js +17 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_baseGetTag.js.map +1 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_baseTrim.js +15 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_baseTrim.js.map +1 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_freeGlobal.js +12 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_freeGlobal.js.map +1 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_getRawTag.js +22 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_getRawTag.js.map +1 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_objectToString.js +14 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_objectToString.js.map +1 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_root.js +12 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_root.js.map +1 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_trimmedEndIndex.js +16 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/_trimmedEndIndex.js.map +1 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/debounce.js +61 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/debounce.js.map +1 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/isObject.js +14 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/isObject.js.map +1 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/isObjectLike.js +13 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/isObjectLike.js.map +1 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/isSymbol.js +16 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/isSymbol.js.map +1 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/now.js +14 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/now.js.map +1 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/toNumber.js +29 -0
- package/dist/node_modules/.pnpm/lodash@4.17.21/node_modules/lodash/toNumber.js.map +1 -0
- package/dist/node_modules/.pnpm/querystringify@2.2.0/node_modules/querystringify/index.js +1 -1
- package/dist/types/minisSDK.generated.d.js.map +1 -1
- package/package.json +4 -3
- package/src/base.css +264 -0
- package/src/components/commerce/merchant-card.tsx +262 -0
- package/src/components/commerce/product-card.tsx +3 -1
- package/src/components/index.ts +1 -0
- package/src/hooks/index.ts +11 -0
- package/src/hooks/product/useCuratedProducts.doc.ts +32 -0
- package/src/hooks/product/useCuratedProducts.example.tsx +10 -0
- package/src/hooks/product/useCuratedProducts.ts +41 -0
- package/src/hooks/product/useProduct.ts +45 -0
- package/src/hooks/product/useProductMedia.ts +51 -0
- package/src/hooks/product/useProductSearch.doc.ts +32 -0
- package/src/hooks/product/useProductSearch.example.tsx +13 -0
- package/src/hooks/product/useProductSearch.ts +95 -0
- package/src/hooks/product/useProductVariants.ts +48 -0
- package/src/hooks/product/useProducts.ts +38 -0
- package/src/hooks/shop/useShop.doc.ts +31 -0
- package/src/hooks/shop/useShop.example.tsx +7 -0
- package/src/hooks/shop/useShop.ts +38 -0
- package/src/hooks/user/useFollowedShops.ts +43 -0
- package/src/hooks/user/useRecentProducts.doc.ts +32 -0
- package/src/hooks/user/useRecentProducts.example.tsx +13 -0
- package/src/hooks/user/useRecentProducts.ts +46 -0
- package/src/hooks/user/useRecentShops.ts +43 -0
- package/src/hooks/user/useSavedProducts.doc.ts +32 -0
- package/src/hooks/user/useSavedProducts.example.tsx +13 -0
- package/src/hooks/user/useSavedProducts.ts +46 -0
- package/src/index.css +1 -221
- package/src/internal/useShopActionsPaginatedDataFetching.ts +8 -8
- package/src/types/minisSDK.generated.d.ts +239 -4
- package/src/dev.tsx +0 -868
- package/src/mockActions.ts +0 -237
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
|
|
3
|
+
import {cva, type VariantProps} from 'class-variance-authority'
|
|
4
|
+
import {Star} from 'lucide-react'
|
|
5
|
+
import {Slot as SlotPrimitive} from 'radix-ui'
|
|
6
|
+
|
|
7
|
+
import {useShopNavigation} from '../../hooks/navigation/useShopNavigation'
|
|
8
|
+
import {cn} from '../../lib/utils'
|
|
9
|
+
import {type Shop} from '../../types/minisSDK.generated.d'
|
|
10
|
+
import {Touchable} from '../atoms/touchable'
|
|
11
|
+
|
|
12
|
+
const merchantCardVariants = cva(
|
|
13
|
+
'relative w-full aspect-square overflow-hidden rounded-xl border border-grayscale-l20 bg-grayscale-l0 flex flex-col',
|
|
14
|
+
{
|
|
15
|
+
variants: {
|
|
16
|
+
touchable: {
|
|
17
|
+
true: 'cursor-pointer',
|
|
18
|
+
false: '',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
defaultVariants: {
|
|
22
|
+
touchable: true,
|
|
23
|
+
},
|
|
24
|
+
}
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
function formatReviewCount(count: number): string {
|
|
28
|
+
if (count >= 1000000) {
|
|
29
|
+
return `${Math.floor(count / 100000) / 10}M`
|
|
30
|
+
}
|
|
31
|
+
if (count >= 1000) {
|
|
32
|
+
return `${Math.floor(count / 1000)}K`
|
|
33
|
+
}
|
|
34
|
+
return count.toString()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function normalizeRating(rating: number): number {
|
|
38
|
+
return Math.round(rating * 10) / 10
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface MerchantCardRootProps
|
|
42
|
+
extends React.ComponentProps<'div'>,
|
|
43
|
+
VariantProps<typeof merchantCardVariants> {
|
|
44
|
+
touchable?: boolean
|
|
45
|
+
asChild?: boolean
|
|
46
|
+
onPress?: () => void
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function MerchantCardRoot({
|
|
50
|
+
className,
|
|
51
|
+
touchable = true,
|
|
52
|
+
asChild = false,
|
|
53
|
+
onPress,
|
|
54
|
+
...props
|
|
55
|
+
}: MerchantCardRootProps) {
|
|
56
|
+
const Comp = asChild ? SlotPrimitive.Slot : 'div'
|
|
57
|
+
|
|
58
|
+
const content = (
|
|
59
|
+
<Comp
|
|
60
|
+
className={cn(merchantCardVariants({touchable}), className)}
|
|
61
|
+
{...props}
|
|
62
|
+
/>
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
if (touchable && onPress) {
|
|
66
|
+
return (
|
|
67
|
+
<Touchable
|
|
68
|
+
onClick={onPress}
|
|
69
|
+
whileTap={{opacity: 0.7}}
|
|
70
|
+
transition={{
|
|
71
|
+
opacity: {type: 'tween', duration: 0.08, ease: 'easeInOut'},
|
|
72
|
+
}}
|
|
73
|
+
>
|
|
74
|
+
{content}
|
|
75
|
+
</Touchable>
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return content
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function MerchantCardImageContainer({
|
|
83
|
+
className,
|
|
84
|
+
...props
|
|
85
|
+
}: React.ComponentProps<'div'>) {
|
|
86
|
+
return (
|
|
87
|
+
<div
|
|
88
|
+
data-slot="merchant-card-image-container"
|
|
89
|
+
className={cn('relative overflow-hidden w-full flex-grow', className)}
|
|
90
|
+
{...props}
|
|
91
|
+
/>
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function MerchantCardImage({
|
|
96
|
+
className,
|
|
97
|
+
src,
|
|
98
|
+
alt,
|
|
99
|
+
...props
|
|
100
|
+
}: React.ComponentProps<'img'> & {
|
|
101
|
+
src?: string
|
|
102
|
+
alt?: string
|
|
103
|
+
}) {
|
|
104
|
+
return src ? (
|
|
105
|
+
<img
|
|
106
|
+
data-slot="merchant-card-image"
|
|
107
|
+
src={src}
|
|
108
|
+
alt={alt}
|
|
109
|
+
className={cn('w-full h-full object-cover', className)}
|
|
110
|
+
{...props}
|
|
111
|
+
/>
|
|
112
|
+
) : (
|
|
113
|
+
<div className="w-full h-full bg-grayscale-l10" />
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function MerchantCardLogo({
|
|
118
|
+
className,
|
|
119
|
+
src,
|
|
120
|
+
alt,
|
|
121
|
+
...props
|
|
122
|
+
}: React.ComponentProps<'div'> & {
|
|
123
|
+
src?: string
|
|
124
|
+
alt?: string
|
|
125
|
+
}) {
|
|
126
|
+
return (
|
|
127
|
+
<div
|
|
128
|
+
data-slot="merchant-card-logo"
|
|
129
|
+
className={cn(
|
|
130
|
+
'absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2',
|
|
131
|
+
'w-14 h-14 rounded-xl',
|
|
132
|
+
'flex items-center justify-center overflow-hidden',
|
|
133
|
+
className
|
|
134
|
+
)}
|
|
135
|
+
{...props}
|
|
136
|
+
>
|
|
137
|
+
{src ? (
|
|
138
|
+
<img src={src} alt={alt} className="w-full h-full object-cover" />
|
|
139
|
+
) : (
|
|
140
|
+
<div className="w-full h-full bg-grayscale-l20" />
|
|
141
|
+
)}
|
|
142
|
+
</div>
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function MerchantCardInfo({className, ...props}: React.ComponentProps<'div'>) {
|
|
147
|
+
return (
|
|
148
|
+
<div
|
|
149
|
+
data-slot="merchant-card-info"
|
|
150
|
+
className={cn('p-3 space-y-1 flex-shrink-0', className)}
|
|
151
|
+
{...props}
|
|
152
|
+
/>
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function MerchantCardName({
|
|
157
|
+
className,
|
|
158
|
+
children,
|
|
159
|
+
...props
|
|
160
|
+
}: React.ComponentProps<'h3'>) {
|
|
161
|
+
return (
|
|
162
|
+
<h3
|
|
163
|
+
data-slot="merchant-card-name"
|
|
164
|
+
className={cn(
|
|
165
|
+
'text-sm font-medium text-grayscale-d100',
|
|
166
|
+
'truncate overflow-hidden whitespace-nowrap text-ellipsis',
|
|
167
|
+
className
|
|
168
|
+
)}
|
|
169
|
+
{...props}
|
|
170
|
+
>
|
|
171
|
+
{children}
|
|
172
|
+
</h3>
|
|
173
|
+
)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function MerchantCardRating({
|
|
177
|
+
className,
|
|
178
|
+
rating,
|
|
179
|
+
reviewCount,
|
|
180
|
+
...props
|
|
181
|
+
}: React.ComponentProps<'div'> & {
|
|
182
|
+
rating?: number | null
|
|
183
|
+
reviewCount?: number
|
|
184
|
+
}) {
|
|
185
|
+
if (!rating || !reviewCount) return null
|
|
186
|
+
|
|
187
|
+
return (
|
|
188
|
+
<div
|
|
189
|
+
data-slot="merchant-card-rating"
|
|
190
|
+
className={cn(
|
|
191
|
+
'flex items-center gap-1 text-sm text-grayscale-d100',
|
|
192
|
+
className
|
|
193
|
+
)}
|
|
194
|
+
{...props}
|
|
195
|
+
>
|
|
196
|
+
<Star className="h-3.5 w-3.5 fill-current" />
|
|
197
|
+
<>
|
|
198
|
+
{normalizeRating(rating)} ({formatReviewCount(reviewCount)})
|
|
199
|
+
</>
|
|
200
|
+
</div>
|
|
201
|
+
)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export interface MerchantCardProps {
|
|
205
|
+
shop: Shop
|
|
206
|
+
touchable?: boolean
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Composed MerchantCard component
|
|
210
|
+
function MerchantCard({shop, touchable = true}: MerchantCardProps) {
|
|
211
|
+
const {navigateToShop} = useShopNavigation()
|
|
212
|
+
|
|
213
|
+
const {
|
|
214
|
+
id,
|
|
215
|
+
name,
|
|
216
|
+
logoImage,
|
|
217
|
+
reviewAnalytics: {averageRating, reviewCount},
|
|
218
|
+
} = shop
|
|
219
|
+
|
|
220
|
+
const handlePress = React.useCallback(() => {
|
|
221
|
+
if (!touchable) return
|
|
222
|
+
navigateToShop({shopId: id})
|
|
223
|
+
}, [navigateToShop, id, touchable])
|
|
224
|
+
|
|
225
|
+
return (
|
|
226
|
+
<MerchantCardRoot touchable={touchable} onPress={handlePress}>
|
|
227
|
+
<MerchantCardImageContainer>
|
|
228
|
+
{/* TODO: Add featured image */}
|
|
229
|
+
<MerchantCardImage src={undefined} alt={`${name} featured image`} />
|
|
230
|
+
<MerchantCardLogo src={logoImage?.url} alt={`${name} logo`} />
|
|
231
|
+
</MerchantCardImageContainer>
|
|
232
|
+
|
|
233
|
+
<MerchantCardInfo>
|
|
234
|
+
<MerchantCardName>{name}</MerchantCardName>
|
|
235
|
+
<MerchantCardRating rating={averageRating} reviewCount={reviewCount} />
|
|
236
|
+
</MerchantCardInfo>
|
|
237
|
+
</MerchantCardRoot>
|
|
238
|
+
)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Export with Object.assign pattern
|
|
242
|
+
export const MerchantCardPrimitive = Object.assign(MerchantCardRoot, {
|
|
243
|
+
ImageContainer: MerchantCardImageContainer,
|
|
244
|
+
Image: MerchantCardImage,
|
|
245
|
+
Logo: MerchantCardLogo,
|
|
246
|
+
Info: MerchantCardInfo,
|
|
247
|
+
Name: MerchantCardName,
|
|
248
|
+
Rating: MerchantCardRating,
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
export {
|
|
252
|
+
// Composed component
|
|
253
|
+
MerchantCard,
|
|
254
|
+
// Primitive components for custom composition
|
|
255
|
+
MerchantCardRoot,
|
|
256
|
+
MerchantCardImageContainer,
|
|
257
|
+
MerchantCardImage,
|
|
258
|
+
MerchantCardLogo,
|
|
259
|
+
MerchantCardInfo,
|
|
260
|
+
MerchantCardName,
|
|
261
|
+
MerchantCardRating,
|
|
262
|
+
}
|
|
@@ -96,6 +96,8 @@ function ProductCardImageContainer({
|
|
|
96
96
|
<div
|
|
97
97
|
data-slot="product-card-image-container"
|
|
98
98
|
className={cn(
|
|
99
|
+
// Ensure the product image is stretched to the full size of the container (can't use width/height: 100% because of flex)
|
|
100
|
+
'flex justify-stretch items-stretch',
|
|
99
101
|
'relative overflow-hidden rounded-xl border border-gray-200',
|
|
100
102
|
'w-full aspect-square',
|
|
101
103
|
variant === 'compact' ? 'min-h-[104px]' : 'min-h-[134px]',
|
|
@@ -116,7 +118,7 @@ function ProductCardImage({
|
|
|
116
118
|
alt?: string
|
|
117
119
|
}) {
|
|
118
120
|
return (
|
|
119
|
-
<div className="
|
|
121
|
+
<div className="bg-gray-100 flex items-center justify-center">
|
|
120
122
|
{src ? (
|
|
121
123
|
<img
|
|
122
124
|
data-slot="product-card-image"
|
package/src/components/index.ts
CHANGED
package/src/hooks/index.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
// - User Hooks
|
|
2
|
+
export * from './user/useRecentProducts'
|
|
3
|
+
export * from './user/useRecentShops'
|
|
4
|
+
export * from './user/useSavedProducts'
|
|
2
5
|
export * from './user/useSavedProductsActions'
|
|
6
|
+
export * from './user/useFollowedShops'
|
|
3
7
|
export * from './user/useFollowedShopsActions'
|
|
4
8
|
export * from './user/useCurrentUser'
|
|
5
9
|
export * from './user/useOrders'
|
|
@@ -9,8 +13,14 @@ export * from './user/useBuyerAttributes'
|
|
|
9
13
|
export * from './product/useProductListActions'
|
|
10
14
|
export * from './product/useProductLists'
|
|
11
15
|
export * from './product/useProductList'
|
|
16
|
+
export * from './product/useProduct'
|
|
17
|
+
export * from './product/useProducts'
|
|
18
|
+
export * from './product/useProductVariants'
|
|
19
|
+
export * from './product/useProductMedia'
|
|
20
|
+
export * from './product/useProductSearch'
|
|
12
21
|
export * from './product/useRecommendedProducts'
|
|
13
22
|
export * from './product/usePopularProducts'
|
|
23
|
+
export * from './product/useCuratedProducts'
|
|
14
24
|
|
|
15
25
|
// - Storage Hooks
|
|
16
26
|
export * from './storage/useAsyncStorage'
|
|
@@ -23,6 +33,7 @@ export * from './navigation/useCloseMini'
|
|
|
23
33
|
export * from './navigation/useDeeplink'
|
|
24
34
|
|
|
25
35
|
// - Shop Hooks
|
|
36
|
+
export * from './shop/useShop'
|
|
26
37
|
export * from './shop/useShopCartActions'
|
|
27
38
|
export * from './shop/useRecommendedShops'
|
|
28
39
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {ReferenceEntityTemplateSchema} from '@shopify/generate-docs'
|
|
2
|
+
|
|
3
|
+
const data: ReferenceEntityTemplateSchema = {
|
|
4
|
+
name: 'useCuratedProducts',
|
|
5
|
+
category: 'hooks',
|
|
6
|
+
subCategory: 'product',
|
|
7
|
+
isVisualComponent: false,
|
|
8
|
+
related: [],
|
|
9
|
+
description:
|
|
10
|
+
'The `useCuratedProducts` hook enables fetching lists of products curated by the Shop team.',
|
|
11
|
+
type: 'hook',
|
|
12
|
+
defaultExample: {
|
|
13
|
+
codeblock: {
|
|
14
|
+
tabs: [
|
|
15
|
+
{
|
|
16
|
+
code: './useCuratedProducts.example.tsx',
|
|
17
|
+
language: 'tsx',
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
title: 'Example code',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
definitions: [
|
|
24
|
+
{
|
|
25
|
+
title: '',
|
|
26
|
+
type: 'UseCuratedProductsGeneratedType',
|
|
27
|
+
description: '',
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default data
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import {useCuratedProducts} from '@shopify/shop-minis-react'
|
|
2
|
+
|
|
3
|
+
export default function MyComponent() {
|
|
4
|
+
const {products, loading, error} = useCuratedProducts({
|
|
5
|
+
handle: 'ar-models',
|
|
6
|
+
requiredTags: ['furniture'],
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
console.log({products, loading, error})
|
|
10
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import {useShopActions} from '../../internal/useShopActions'
|
|
2
|
+
import {useShopActionsPaginatedDataFetching} from '../../internal/useShopActionsPaginatedDataFetching'
|
|
3
|
+
import {
|
|
4
|
+
Product,
|
|
5
|
+
PaginatedDataHookOptionsBase,
|
|
6
|
+
PaginatedDataHookReturnsBase,
|
|
7
|
+
} from '../../types'
|
|
8
|
+
|
|
9
|
+
interface UseCuratedProductsParams extends PaginatedDataHookOptionsBase {
|
|
10
|
+
handle: string
|
|
11
|
+
requiredTags?: string[]
|
|
12
|
+
anyOfTags?: string[]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface UseCuratedProductsReturns extends PaginatedDataHookReturnsBase {
|
|
16
|
+
products: Product[] | null
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param options - The options for the query
|
|
21
|
+
*/
|
|
22
|
+
export const useCuratedProducts = (
|
|
23
|
+
params: UseCuratedProductsParams
|
|
24
|
+
): UseCuratedProductsReturns => {
|
|
25
|
+
const {getCuratedProducts} = useShopActions()
|
|
26
|
+
const {skip, ...shopActionParams} = params ?? {}
|
|
27
|
+
|
|
28
|
+
const {data, ...rest} = useShopActionsPaginatedDataFetching(
|
|
29
|
+
getCuratedProducts,
|
|
30
|
+
shopActionParams,
|
|
31
|
+
{
|
|
32
|
+
skip,
|
|
33
|
+
hook: 'useCuratedProducts',
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
...rest,
|
|
39
|
+
products: data,
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {useMemo} from 'react'
|
|
2
|
+
|
|
3
|
+
import {useShopActions} from '../../internal/useShopActions'
|
|
4
|
+
import {useShopActionsDataFetching} from '../../internal/useShopActionsDataFetching'
|
|
5
|
+
import {DataHookOptionsBase, DataHookReturnsBase, Product} from '../../types'
|
|
6
|
+
|
|
7
|
+
export interface UseProductParams extends DataHookOptionsBase {
|
|
8
|
+
/**
|
|
9
|
+
* The product ID to fetch.
|
|
10
|
+
*/
|
|
11
|
+
id: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface UseProductReturns extends DataHookReturnsBase {
|
|
15
|
+
/**
|
|
16
|
+
* The product returned from the query.
|
|
17
|
+
*/
|
|
18
|
+
product: Product | null
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const useProduct = (params: UseProductParams): UseProductReturns => {
|
|
22
|
+
const {getProduct} = useShopActions()
|
|
23
|
+
const {id, skip = false, ...restParams} = params
|
|
24
|
+
|
|
25
|
+
const {data, ...rest} = useShopActionsDataFetching(
|
|
26
|
+
getProduct,
|
|
27
|
+
{
|
|
28
|
+
id,
|
|
29
|
+
...restParams,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
skip,
|
|
33
|
+
hook: 'useProduct',
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
const product = useMemo(() => {
|
|
38
|
+
return data ?? null
|
|
39
|
+
}, [data])
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
...rest,
|
|
43
|
+
product,
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {useMemo} from 'react'
|
|
2
|
+
|
|
3
|
+
import {useShopActions} from '../../internal/useShopActions'
|
|
4
|
+
import {useShopActionsPaginatedDataFetching} from '../../internal/useShopActionsPaginatedDataFetching'
|
|
5
|
+
import {
|
|
6
|
+
PaginatedDataHookOptionsBase,
|
|
7
|
+
PaginatedDataHookReturnsBase,
|
|
8
|
+
ProductMedia,
|
|
9
|
+
} from '../../types'
|
|
10
|
+
|
|
11
|
+
export interface UseProductMediaParams extends PaginatedDataHookOptionsBase {
|
|
12
|
+
/**
|
|
13
|
+
* The product ID to fetch media for.
|
|
14
|
+
*/
|
|
15
|
+
id: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface UseProductMediaReturns extends PaginatedDataHookReturnsBase {
|
|
19
|
+
/**
|
|
20
|
+
* The product media returned from the query.
|
|
21
|
+
*/
|
|
22
|
+
media: ProductMedia[] | null
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const useProductMedia = (
|
|
26
|
+
params: UseProductMediaParams
|
|
27
|
+
): UseProductMediaReturns => {
|
|
28
|
+
const {getProductMedia} = useShopActions()
|
|
29
|
+
const {id, skip = false, ...restParams} = params
|
|
30
|
+
|
|
31
|
+
const {data, ...rest} = useShopActionsPaginatedDataFetching(
|
|
32
|
+
getProductMedia,
|
|
33
|
+
{
|
|
34
|
+
id,
|
|
35
|
+
...restParams,
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
skip,
|
|
39
|
+
hook: 'useProductMedia',
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
const media = useMemo(() => {
|
|
44
|
+
return data ?? null
|
|
45
|
+
}, [data])
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
...rest,
|
|
49
|
+
media,
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {ReferenceEntityTemplateSchema} from '@shopify/generate-docs'
|
|
2
|
+
|
|
3
|
+
const data: ReferenceEntityTemplateSchema = {
|
|
4
|
+
name: 'useProductSearch',
|
|
5
|
+
category: 'hooks',
|
|
6
|
+
subCategory: 'product',
|
|
7
|
+
isVisualComponent: false,
|
|
8
|
+
related: [],
|
|
9
|
+
description:
|
|
10
|
+
'The `useProductSearch` hook fetches products based on a search query.',
|
|
11
|
+
type: 'hook',
|
|
12
|
+
defaultExample: {
|
|
13
|
+
codeblock: {
|
|
14
|
+
tabs: [
|
|
15
|
+
{
|
|
16
|
+
code: './useProductSearch.example.tsx',
|
|
17
|
+
language: 'tsx',
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
title: 'Example code',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
definitions: [
|
|
24
|
+
{
|
|
25
|
+
title: '',
|
|
26
|
+
type: 'UseProductSearchGeneratedType',
|
|
27
|
+
description: '',
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default data
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import {useProductSearch} from '@shopify/shop-minis-react'
|
|
2
|
+
|
|
3
|
+
export default function MyComponent() {
|
|
4
|
+
const {products, loading} = useProductSearch({
|
|
5
|
+
query: 'shirt',
|
|
6
|
+
first: 10,
|
|
7
|
+
filters: {
|
|
8
|
+
color: ['RED'],
|
|
9
|
+
},
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
console.log({products, loading})
|
|
13
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import {useCallback, useEffect, useMemo, useState} from 'react'
|
|
2
|
+
|
|
3
|
+
import debounce from 'lodash/debounce'
|
|
4
|
+
|
|
5
|
+
import {useShopActions} from '../../internal/useShopActions'
|
|
6
|
+
import {useShopActionsPaginatedDataFetching} from '../../internal/useShopActionsPaginatedDataFetching'
|
|
7
|
+
import {
|
|
8
|
+
PaginatedDataHookOptionsBase,
|
|
9
|
+
PaginatedDataHookReturnsBase,
|
|
10
|
+
Product,
|
|
11
|
+
ProductFilters,
|
|
12
|
+
ProductSearchSortBy,
|
|
13
|
+
} from '../../types'
|
|
14
|
+
|
|
15
|
+
export interface UseProductSearchParams extends PaginatedDataHookOptionsBase {
|
|
16
|
+
/**
|
|
17
|
+
* The search query.
|
|
18
|
+
*/
|
|
19
|
+
query: string
|
|
20
|
+
/**
|
|
21
|
+
* The filters to apply to the search.
|
|
22
|
+
*/
|
|
23
|
+
filters?: ProductFilters
|
|
24
|
+
/**
|
|
25
|
+
* The sort order of the results.
|
|
26
|
+
*/
|
|
27
|
+
sortBy?: ProductSearchSortBy
|
|
28
|
+
/**
|
|
29
|
+
* Whether to include sensitive products.
|
|
30
|
+
*/
|
|
31
|
+
includeSensitive?: boolean
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface UseProductSearchReturns extends PaginatedDataHookReturnsBase {
|
|
35
|
+
/**
|
|
36
|
+
* The products returned from the query.
|
|
37
|
+
*/
|
|
38
|
+
products: Product[] | null
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const useProductSearch = (
|
|
42
|
+
params: UseProductSearchParams
|
|
43
|
+
): UseProductSearchReturns => {
|
|
44
|
+
const {getProductSearch} = useShopActions()
|
|
45
|
+
const {
|
|
46
|
+
query,
|
|
47
|
+
filters,
|
|
48
|
+
sortBy,
|
|
49
|
+
includeSensitive = false,
|
|
50
|
+
skip = false,
|
|
51
|
+
...restParams
|
|
52
|
+
} = params ?? {}
|
|
53
|
+
|
|
54
|
+
const [debouncedQuery, setDebouncedQuery] = useState<string>(query)
|
|
55
|
+
|
|
56
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
57
|
+
const debouncedSetQuery = useCallback(
|
|
58
|
+
debounce((newQuery: string) => {
|
|
59
|
+
setDebouncedQuery(newQuery)
|
|
60
|
+
}, 300),
|
|
61
|
+
[]
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
debouncedSetQuery(query)
|
|
66
|
+
|
|
67
|
+
return () => {
|
|
68
|
+
debouncedSetQuery.cancel()
|
|
69
|
+
}
|
|
70
|
+
}, [query, debouncedSetQuery])
|
|
71
|
+
|
|
72
|
+
const {data, ...rest} = useShopActionsPaginatedDataFetching(
|
|
73
|
+
getProductSearch,
|
|
74
|
+
{
|
|
75
|
+
query: debouncedQuery,
|
|
76
|
+
filters,
|
|
77
|
+
sortBy,
|
|
78
|
+
includeSensitive,
|
|
79
|
+
...restParams,
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
skip,
|
|
83
|
+
hook: 'useProductSearch',
|
|
84
|
+
}
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
const products = useMemo(() => {
|
|
88
|
+
return data ?? null
|
|
89
|
+
}, [data])
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
...rest,
|
|
93
|
+
products,
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {useMemo} from 'react'
|
|
2
|
+
|
|
3
|
+
import {useShopActions} from '../../internal/useShopActions'
|
|
4
|
+
import {useShopActionsPaginatedDataFetching} from '../../internal/useShopActionsPaginatedDataFetching'
|
|
5
|
+
import {
|
|
6
|
+
PaginatedDataHookOptionsBase,
|
|
7
|
+
PaginatedDataHookReturnsBase,
|
|
8
|
+
ProductVariant,
|
|
9
|
+
} from '../../types'
|
|
10
|
+
|
|
11
|
+
export interface UseProductVariantsParams extends PaginatedDataHookOptionsBase {
|
|
12
|
+
/**
|
|
13
|
+
* The product ID to fetch variants for.
|
|
14
|
+
*/
|
|
15
|
+
id: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface UseProductVariantsReturns extends PaginatedDataHookReturnsBase {
|
|
19
|
+
/**
|
|
20
|
+
* The product variants returned from the query.
|
|
21
|
+
*/
|
|
22
|
+
variants: ProductVariant[] | null
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const useProductVariants = (
|
|
26
|
+
params: UseProductVariantsParams
|
|
27
|
+
): UseProductVariantsReturns => {
|
|
28
|
+
const {getProductVariants} = useShopActions()
|
|
29
|
+
const {skip = false, ...restParams} = params
|
|
30
|
+
|
|
31
|
+
const {data, ...rest} = useShopActionsPaginatedDataFetching(
|
|
32
|
+
getProductVariants,
|
|
33
|
+
restParams,
|
|
34
|
+
{
|
|
35
|
+
skip,
|
|
36
|
+
hook: 'useProductVariants',
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
const variants = useMemo(() => {
|
|
41
|
+
return data ?? null
|
|
42
|
+
}, [data])
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
...rest,
|
|
46
|
+
variants,
|
|
47
|
+
}
|
|
48
|
+
}
|