@shopify/shop-minis-react 0.0.29 → 0.0.31
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/components/atoms/list.js +37 -31
- package/dist/components/atoms/list.js.map +1 -1
- package/dist/components/commerce/search.js.map +1 -1
- package/dist/hooks/navigation/useNavigateWithTransition.js.map +1 -1
- package/dist/hooks/navigation/useShopNavigation.js.map +1 -1
- package/dist/hooks/user/useCurrentUser.js.map +1 -1
- package/dist/hooks/user/useFollowedShopsActions.js.map +1 -1
- package/dist/hooks/user/useGenerateUserToken.js +12 -0
- package/dist/hooks/user/useGenerateUserToken.js.map +1 -0
- package/dist/hooks/util/useImagePicker.js.map +1 -1
- package/dist/index.js +111 -106
- package/dist/index.js.map +1 -1
- package/dist/mocks.js +24 -16
- package/dist/mocks.js.map +1 -1
- package/dist/shop-minis-platform/src/types/user.js +6 -0
- package/dist/shop-minis-platform/src/types/user.js.map +1 -0
- package/package.json +2 -2
- package/src/components/atoms/list.tsx +24 -4
- package/src/components/commerce/search.tsx +1 -1
- package/src/hooks/index.ts +1 -0
- package/src/hooks/navigation/useNavigateWithTransition.ts +6 -1
- package/src/hooks/navigation/useShopNavigation.ts +3 -1
- package/src/hooks/user/useCurrentUser.ts +3 -0
- package/src/hooks/user/useFollowedShopsActions.ts +2 -2
- package/src/hooks/user/useGenerateUserToken.ts +25 -0
- package/src/hooks/util/{useImagePicker.tsx → useImagePicker.ts} +8 -2
- package/src/mocks.ts +11 -4
- package/src/stories/ImageContentWrapper.stories.tsx +68 -0
- package/src/stories/MerchantCard.stories.tsx +21 -0
- package/src/stories/ProductCard.stories.tsx +10 -3
- package/src/stories/ProductLink.stories.tsx +3 -3
- package/src/stories/QuantitySelector.stories.tsx +78 -0
- package/src/stories/VideoPlayer.stories.tsx +129 -0
- package/src/hooks/util/useImagePicker.doc.tsx +0 -41
package/dist/mocks.js
CHANGED
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
import { UserState as p } from "./shop-minis-platform/src/types/user.js";
|
|
2
|
+
const e = (t, o, r = "99.99", s) => ({
|
|
2
3
|
id: t,
|
|
3
4
|
title: o,
|
|
4
5
|
price: { amount: r, currencyCode: "USD" },
|
|
5
|
-
...
|
|
6
|
-
compareAtPrice: { amount:
|
|
6
|
+
...s && {
|
|
7
|
+
compareAtPrice: { amount: s, currencyCode: "USD" }
|
|
7
8
|
},
|
|
8
9
|
reviewAnalytics: { averageRating: 4.5, reviewCount: 10 },
|
|
9
10
|
shop: i("shop1", "Mock Shop"),
|
|
10
11
|
defaultVariantId: `variant-${t}`,
|
|
11
12
|
isFavorited: !1,
|
|
12
13
|
featuredImage: {
|
|
13
|
-
url: "https://cdn.shopify.com/
|
|
14
|
+
url: "https://cdn.shopify.com/static/sample-images/teapot.jpg",
|
|
14
15
|
altText: o
|
|
15
16
|
}
|
|
16
17
|
}), i = (t, o, r) => {
|
|
17
|
-
const c = Array.from({ length: 3 }, (
|
|
18
|
-
url: `https://picsum.photos/400/400?random=${t}-${
|
|
18
|
+
const c = Array.from({ length: 3 }, (g, n) => ({
|
|
19
|
+
url: `https://picsum.photos/400/400?random=${t}-${n}`,
|
|
19
20
|
sensitive: !1,
|
|
20
|
-
altText: `${o} featured image ${
|
|
21
|
+
altText: `${o} featured image ${n + 1}`
|
|
21
22
|
}));
|
|
22
23
|
return {
|
|
23
24
|
id: t,
|
|
@@ -45,10 +46,10 @@ const e = (t, o, r = "99.99", n) => ({
|
|
|
45
46
|
name: o,
|
|
46
47
|
products: r
|
|
47
48
|
});
|
|
48
|
-
function
|
|
49
|
+
function l(t, o) {
|
|
49
50
|
return (r) => (console.log(`[Mock Action] ${String(t)}`, r), Promise.resolve({ ok: !0, data: o }));
|
|
50
51
|
}
|
|
51
|
-
function
|
|
52
|
+
function u() {
|
|
52
53
|
const t = {
|
|
53
54
|
followShop: !0,
|
|
54
55
|
unfollowShop: !1,
|
|
@@ -274,7 +275,7 @@ function l() {
|
|
|
274
275
|
externalId: null,
|
|
275
276
|
image: {
|
|
276
277
|
id: "img-123",
|
|
277
|
-
url: "https://
|
|
278
|
+
url: "https://cdn.shopify.com/s/files/1/0633/6574/2742/files/Namnlosdesign-47.png?v=1740438079",
|
|
278
279
|
width: 800,
|
|
279
280
|
height: 600
|
|
280
281
|
},
|
|
@@ -291,7 +292,7 @@ function l() {
|
|
|
291
292
|
publicId: "content-123",
|
|
292
293
|
image: {
|
|
293
294
|
id: "img-123",
|
|
294
|
-
url: "https://
|
|
295
|
+
url: "https://cdn.shopify.com/s/files/1/0633/6574/2742/files/Namnlosdesign-47.png?v=1740438079",
|
|
295
296
|
width: 800,
|
|
296
297
|
height: 600
|
|
297
298
|
},
|
|
@@ -299,20 +300,27 @@ function l() {
|
|
|
299
300
|
visibility: ["DISCOVERABLE"]
|
|
300
301
|
}
|
|
301
302
|
]
|
|
303
|
+
},
|
|
304
|
+
generateUserToken: {
|
|
305
|
+
data: {
|
|
306
|
+
token: "user-token-123",
|
|
307
|
+
expiresAt: "2025-01-01",
|
|
308
|
+
userState: p.VERIFIED
|
|
309
|
+
}
|
|
302
310
|
}
|
|
303
311
|
}, o = {};
|
|
304
312
|
for (const r in t)
|
|
305
|
-
Object.prototype.hasOwnProperty.call(t, r) && (o[r] =
|
|
313
|
+
Object.prototype.hasOwnProperty.call(t, r) && (o[r] = l(
|
|
306
314
|
r,
|
|
307
315
|
t[r]
|
|
308
316
|
));
|
|
309
317
|
return o;
|
|
310
318
|
}
|
|
311
|
-
const
|
|
319
|
+
const m = () => {
|
|
312
320
|
const t = navigator.userAgent.toLowerCase(), o = /iphone|ipad|ipod/.test(t), r = /android/.test(t);
|
|
313
321
|
return o || r;
|
|
314
|
-
},
|
|
315
|
-
|
|
322
|
+
}, h = () => {
|
|
323
|
+
m() || window.minisSDK || (window.minisSDK = u(), window.minisParams = {
|
|
316
324
|
handle: "mock-handle",
|
|
317
325
|
initialUrl: "/mock-initial-url",
|
|
318
326
|
platform: "web"
|
|
@@ -321,6 +329,6 @@ const u = () => {
|
|
|
321
329
|
export {
|
|
322
330
|
e as createProduct,
|
|
323
331
|
i as createShop,
|
|
324
|
-
|
|
332
|
+
h as injectMocks
|
|
325
333
|
};
|
|
326
334
|
//# sourceMappingURL=mocks.js.map
|
package/dist/mocks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mocks.js","sources":["../src/mocks.ts"],"sourcesContent":["import {Product, Gender} from '@shopify/shop-minis-platform'\nimport {ShopActions} from '@shopify/shop-minis-platform/actions'\n\n// Helper functions for common data structures\nexport const createProduct = (\n id: string,\n title: string,\n price = '99.99',\n compareAtPrice?: string\n): Product => ({\n id,\n title,\n price: {amount: price, currencyCode: 'USD'},\n ...(compareAtPrice && {\n compareAtPrice: {amount: compareAtPrice, currencyCode: 'USD'},\n }),\n reviewAnalytics: {averageRating: 4.5, reviewCount: 10},\n shop: createShop('shop1', 'Mock Shop'),\n defaultVariantId: `variant-${id}`,\n isFavorited: false,\n featuredImage: {\n url: `https://cdn.shopify.com/s/files/1/0621/0463/3599/files/61ChhrRjK9L._AC_SL1000_1639abe8-4cd3-4bee-9867-73f26b0acf0a.jpg?v=1702559955`,\n altText: title,\n },\n})\n\nexport const createShop = (\n id: string,\n name: string,\n options?: {\n themeType?: 'coverImage' | 'brandColor' | 'logoColor' | 'none'\n withBrandSettings?: boolean\n primaryColor?: string\n logoDominantColor?: string\n logoAverageColor?: string\n coverDominantColor?: string\n wordmarkUrl?: string\n coverImageUrl?: string\n featuredImagesLimit?: number\n }\n) => {\n // Determine theme configuration\n const themeType = options?.themeType || 'none'\n const shouldHaveBrandSettings =\n options?.withBrandSettings || themeType !== 'none'\n\n // Generate featured images\n const featuredImagesCount = options?.featuredImagesLimit || 3\n const featuredImages = Array.from({length: featuredImagesCount}, (_, i) => ({\n url: `https://picsum.photos/400/400?random=${id}-${i}`,\n sensitive: false,\n altText: `${name} featured image ${i + 1}`,\n }))\n\n // Configure colors based on theme type\n const getThemeColors = () => {\n switch (themeType) {\n case 'coverImage':\n return {\n primary: options?.primaryColor,\n logoDominant: options?.logoDominantColor,\n logoAverage: options?.logoAverageColor,\n coverDominant: options?.coverDominantColor || '#FF6B35',\n }\n case 'brandColor':\n return {\n primary: options?.primaryColor || '#27AE60',\n logoDominant: options?.logoDominantColor,\n logoAverage: options?.logoAverageColor,\n coverDominant: options?.coverDominantColor,\n }\n case 'logoColor':\n return {\n primary: options?.primaryColor,\n logoDominant: options?.logoDominantColor || '#E74C3C',\n logoAverage: options?.logoAverageColor,\n coverDominant: options?.coverDominantColor,\n }\n default:\n return {\n primary: options?.primaryColor,\n logoDominant: options?.logoDominantColor,\n logoAverage: options?.logoAverageColor,\n coverDominant: options?.coverDominantColor,\n }\n }\n }\n\n // Configure header theme\n const createHeaderTheme = () => {\n if (themeType === 'coverImage' || options?.coverImageUrl) {\n return {\n id: `header-theme-${id}`,\n coverImage: {\n url:\n options?.coverImageUrl ||\n 'https://images.unsplash.com/photo-1441986300917-64674bd600d8?w=800&h=400&fit=crop',\n altText: `${name} cover image`,\n sensitive: false,\n thumbhash: 'k9oGHQRnh493V4dIeHeXh4h3iIeI',\n },\n wordmark:\n options?.wordmarkUrl || themeType === 'coverImage'\n ? {\n url:\n options?.wordmarkUrl ||\n 'https://merrypeople.com/cdn/shop/files/Transparent_Background_1.png?v=1696465429&width=1024',\n altText: `${name} wordmark`,\n sensitive: false,\n }\n : undefined,\n }\n }\n\n if (options?.wordmarkUrl) {\n return {\n id: `header-theme-${id}`,\n wordmark: {\n url: options.wordmarkUrl,\n altText: `${name} wordmark`,\n sensitive: false,\n },\n }\n }\n\n return undefined\n }\n\n return {\n id,\n name,\n primaryDomain: {\n url: `https://${name.toLowerCase().replace(/\\s+/g, '-')}.com`,\n },\n reviewAnalytics: {averageRating: 4.3, reviewCount: 50},\n visualTheme: {\n id: `visual-theme-${id}`,\n featuredImages,\n logoImage: {\n url: `https://picsum.photos/100/100?random=${id}`,\n sensitive: false,\n },\n brandSettings: shouldHaveBrandSettings\n ? {\n id: `brand-settings-${id}`,\n colors: {\n id: `colors-${id}`,\n ...getThemeColors(),\n },\n headerTheme: createHeaderTheme(),\n }\n : undefined,\n },\n }\n}\n\nconst createPagination = (hasNext = false) => ({\n hasNextPage: hasNext,\n endCursor: hasNext ? 'cursor123' : null,\n})\n\nconst createProductList = (id: string, name: string, products: any[] = []) => ({\n id,\n publicId: `public-${id}`,\n name,\n products,\n})\n\n// Helper type to extract the data type from a ShopAction\ntype ShopActionDataType<T> = T extends (\n ...args: any[]\n) => Promise<{ok: true; data: infer R} | {ok: false; error: any}>\n ? R\n : never\n\nfunction makeMockMethod<K extends keyof ShopActions>(\n key: K,\n result: ShopActionDataType<ShopActions[K]>\n): ShopActions[K] {\n return ((params: Parameters<ShopActions[K]>[0]) => {\n console.log(`[Mock Action] ${String(key)}`, params)\n return Promise.resolve({ok: true as const, data: result})\n }) as ShopActions[K]\n}\n\nfunction makeMockActions(): ShopActions {\n const results: {\n [K in keyof ShopActions]: ShopActionDataType<ShopActions[K]>\n } = {\n followShop: true,\n unfollowShop: false,\n favorite: undefined,\n unfavorite: undefined,\n getShopAppInformation: {\n appVersion: '1.0.0',\n buildNumber: '12345',\n buildId: 'dev-build-123',\n },\n productRecommendationImpression: undefined,\n productRecommendationClick: undefined,\n hideEntryPoint: undefined,\n closeMini: undefined,\n getAccountInformation: {\n status: 'available',\n value: 'user@example.com',\n },\n getCurrentUser: {\n data: {\n displayName: 'John Doe',\n avatarImage: {url: 'https://example.com/avatar.jpg'},\n },\n },\n createOrderAttribution: undefined,\n addToCart: undefined,\n buyProduct: undefined,\n buyProducts: undefined,\n showErrorScreen: undefined,\n showErrorToast: undefined,\n getDeeplinkPaths: {\n matchers: ['/products', '/collections', '/cart'],\n },\n navigateToDeeplink: undefined,\n navigateToShop: undefined,\n navigateToProduct: undefined,\n navigateToOrder: undefined,\n navigateToCheckout: undefined,\n createImageUploadLink: {\n targets: [\n {\n url: 'https://example.com/upload',\n resourceUrl: 'https://example.com/resource',\n parameters: [{name: 'key', value: 'upload-123'}],\n },\n ],\n },\n completeImageUpload: {\n files: [\n {\n id: 'file-123',\n fileStatus: 'READY',\n image: {url: 'https://example.com/image.jpg'},\n },\n ],\n },\n getPersistedItem: 'stored-value',\n setPersistedItem: undefined,\n removePersistedItem: undefined,\n getAllPersistedKeys: ['key1', 'key2', 'key3'],\n clearPersistedItems: undefined,\n getInternalPersistedItem: 'internal-value',\n setInternalPersistedItem: undefined,\n removeInternalPersistedItem: undefined,\n getAllInternalPersistedKeys: ['internal-key1', 'internal-key2'],\n clearInternalPersistedItems: undefined,\n getSecret: 'secret-value',\n setSecret: undefined,\n removeSecret: undefined,\n reportInteraction: undefined,\n reportImpression: undefined,\n reportContentImpression: undefined,\n getProductLists: {\n data: [\n createProductList('list-1', 'Wishlist'),\n createProductList('list-2', 'Favorites'),\n ],\n pageInfo: createPagination(),\n },\n getProductList: {\n data: createProductList('list-1', 'Wishlist', [\n createProduct('prod-1', 'Sample Product'),\n ]),\n pageInfo: createPagination(),\n },\n addProductList: createProductList('list-3', 'New List'),\n removeProductList: undefined,\n renameProductList: createProductList('list-1', 'Updated Wishlist'),\n addProductListItem: undefined,\n removeProductListItem: undefined,\n getRecommendedProducts: {\n data: [\n createProduct('rec-1', 'Recommended Product 1', '79.99'),\n createProduct('rec-2', 'Recommended Product 2', '129.99'),\n createProduct('rec-3', 'Recommended Product 3', '129.99'),\n createProduct('rec-4', 'Recommended Product 4', '29.99'),\n createProduct('rec-5', 'Recommended Product 5', '39.99'),\n createProduct('rec-6', 'Recommended Product 6', '49.99'),\n createProduct('rec-7', 'Recommended Product 7', '59.99'),\n createProduct('rec-8', 'Recommended Product 8', '69.99'),\n createProduct('rec-9', 'Recommended Product 9', '129.99'),\n ],\n pageInfo: createPagination(),\n },\n getRecommendedShops: {\n data: [\n createShop('shop-1', 'Amazing Store'),\n createShop('shop-2', 'Best Deals Shop'),\n ],\n pageInfo: createPagination(),\n },\n searchProductsByShop: {\n data: [\n createProduct('search-1', 'Search Result 1', '59.99'),\n createProduct('search-2', 'Search Result 2', '89.99'),\n ],\n pageInfo: createPagination(),\n },\n getOrders: {\n data: [\n {\n id: 'order-1',\n name: '#1001',\n lineItems: [\n {\n productTitle: 'Sample Product',\n variantTitle: 'Medium',\n quantity: 2,\n product: null,\n },\n ],\n shop: createShop('shop-1', 'Sample Shop'),\n },\n ],\n pageInfo: createPagination(),\n },\n getBuyerAttributes: {\n data: {\n genderAffinity: 'NEUTRAL' as Gender,\n categoryAffinities: [\n {id: 'cat1', name: 'Electronics'},\n {id: 'cat2', name: 'Clothing'},\n ],\n },\n },\n showFeedbackSheet: undefined,\n getPopularProducts: {\n data: [\n createProduct('pop-1', 'The Hero Snowboard', '702.95'),\n createProduct('pop-2', 'Snow Jacket', '605.95', '702.00'),\n createProduct('pop-3', 'Winter Gloves', '89.95'),\n createProduct('pop-4', 'Summer Gloves', '89.95'),\n createProduct('pop-5', 'Spring Gloves', '89.95'),\n createProduct('pop-6', 'Playstation 5', '499.95'),\n createProduct('pop-7', 'Xbox Series X', '499.95'),\n createProduct('pop-8', 'Nintendo Switch', '299.95'),\n createProduct('pop-9', 'Playstation 4', '299.95'),\n createProduct('pop-10', 'Nintendo 3DS', '89.95'),\n ],\n pageInfo: createPagination(),\n },\n share: {\n message: 'Shared!',\n success: true,\n },\n getCuratedProducts: {\n data: [\n createProduct('cur-1', 'Curated Product 1', '79.99'),\n createProduct('cur-2', 'Curated Product 2', '129.99'),\n ],\n pageInfo: createPagination(),\n },\n getSavedProducts: {\n data: [createProduct('saved-1', 'Saved Product 1', '49.99')],\n pageInfo: createPagination(),\n },\n getRecentProducts: {\n data: [createProduct('recent-1', 'Recent Product 1', '59.99')],\n pageInfo: createPagination(),\n },\n getProductSearch: {\n data: [createProduct('search-3', 'Search Product 3', '39.99')],\n pageInfo: createPagination(),\n },\n getProducts: {data: [createProduct('prod-2', 'Product 2', '19.99')]},\n getProduct: {data: createProduct('prod-1', 'Sample Product')},\n getProductVariants: {\n data: [\n {\n id: 'variant-1',\n isFavorited: false,\n image: {url: 'https://example.com/variant-1.jpg'},\n price: {amount: '19.99', currencyCode: 'USD'},\n compareAtPrice: {amount: '29.99', currencyCode: 'USD'},\n },\n ],\n pageInfo: createPagination(),\n },\n getProductMedia: {\n data: [\n {\n id: 'media-1',\n image: {url: 'https://example.com/media-1.jpg'},\n mediaContentType: 'IMAGE',\n alt: 'Sample product image',\n },\n ],\n pageInfo: createPagination(),\n },\n getShop: {data: createShop('shop-1', 'Sample Shop')},\n getRecentShops: {\n data: [createShop('recent-shop-1', 'Recent Shop 1')],\n pageInfo: createPagination(),\n },\n getFollowedShops: {\n data: [createShop('followed-shop-1', 'Followed Shop 1')],\n pageInfo: createPagination(),\n },\n previewProductInAr: undefined,\n createContent: {\n data: {\n publicId: 'content-123',\n externalId: null,\n image: {\n id: 'img-123',\n url: 'https://example.com/content-image.jpg',\n width: 800,\n height: 600,\n },\n title: 'Mock Content',\n description: 'This is a mock content item',\n visibility: ['DISCOVERABLE'],\n shareableUrl: 'https://example.com/content/123',\n products: null,\n },\n },\n getContent: {\n data: [\n {\n publicId: 'content-123',\n image: {\n id: 'img-123',\n url: 'https://example.com/content-image.jpg',\n width: 800,\n height: 600,\n },\n title: 'Mock Content',\n visibility: ['DISCOVERABLE'],\n },\n ],\n },\n } as const\n\n const mock: Partial<ShopActions> = {}\n for (const key in results) {\n if (Object.prototype.hasOwnProperty.call(results, key)) {\n // @ts-expect-error: dynamic assignment is safe due to exhaustive mapping\n mock[key] = makeMockMethod(\n key as keyof ShopActions,\n results[key as keyof typeof results]\n )\n }\n }\n return mock as ShopActions\n}\n\n// Detect if running on a mobile device\nconst isMobile = (): boolean => {\n const userAgent = navigator.userAgent.toLowerCase()\n const isIOS = /iphone|ipad|ipod/.test(userAgent)\n const isAndroid = /android/.test(userAgent)\n\n return isIOS || isAndroid\n}\n\nexport const injectMocks = () => {\n // Only inject mocks if we aren't on a mobile device\n if (isMobile()) {\n return\n }\n\n if (!window.minisSDK) {\n window.minisSDK = makeMockActions()\n window.minisParams = {\n handle: 'mock-handle',\n initialUrl: '/mock-initial-url',\n platform: 'web',\n }\n }\n}\n"],"names":["createProduct","id","title","price","compareAtPrice","createShop","name","options","featuredImages","_","i","createPagination","hasNext","createProductList","products","makeMockMethod","key","result","params","makeMockActions","results","mock","isMobile","userAgent","isIOS","isAndroid","injectMocks"],"mappings":"AAIO,MAAMA,IAAgB,CAC3BC,GACAC,GACAC,IAAQ,SACRC,OACa;AAAA,EACb,IAAAH;AAAA,EACA,OAAAC;AAAA,EACA,OAAO,EAAC,QAAQC,GAAO,cAAc,MAAK;AAAA,EAC1C,GAAIC,KAAkB;AAAA,IACpB,gBAAgB,EAAC,QAAQA,GAAgB,cAAc,MAAK;AAAA,EAC9D;AAAA,EACA,iBAAiB,EAAC,eAAe,KAAK,aAAa,GAAE;AAAA,EACrD,MAAMC,EAAW,SAAS,WAAW;AAAA,EACrC,kBAAkB,WAAWJ,CAAE;AAAA,EAC/B,aAAa;AAAA,EACb,eAAe;AAAA,IACb,KAAK;AAAA,IACL,SAASC;AAAA,EAAA;AAEb,IAEaG,IAAa,CACxBJ,GACAK,GACAC,MAWG;AAQG,QAAAC,IAAiB,MAAM,KAAK,EAAC,QAAQ,EAAmB,GAAG,CAACC,GAAGC,OAAO;AAAA,IAC1E,KAAK,wCAAwCT,CAAE,IAAIS,CAAC;AAAA,IACpD,WAAW;AAAA,IACX,SAAS,GAAGJ,CAAI,mBAAmBI,IAAI,CAAC;AAAA,EAAA,EACxC;AA4EK,SAAA;AAAA,IACL,IAAAT;AAAA,IACA,MAAAK;AAAA,IACA,eAAe;AAAA,MACb,KAAK,WAAWA,EAAK,cAAc,QAAQ,QAAQ,GAAG,CAAC;AAAA,IACzD;AAAA,IACA,iBAAiB,EAAC,eAAe,KAAK,aAAa,GAAE;AAAA,IACrD,aAAa;AAAA,MACX,IAAI,gBAAgBL,CAAE;AAAA,MACtB,gBAAAO;AAAA,MACA,WAAW;AAAA,QACT,KAAK,wCAAwCP,CAAE;AAAA,QAC/C,WAAW;AAAA,MACb;AAAA,MACA,eASI;AAAA,IAAA;AAAA,EAER;AACF,GAEMU,IAAmB,CAACC,IAAU,QAAW;AAAA,EAC7C,aAAaA;AAAA,EACb,WAAWA,IAAU,cAAc;AACrC,IAEMC,IAAoB,CAACZ,GAAYK,GAAcQ,IAAkB,CAAA,OAAQ;AAAA,EAC7E,IAAAb;AAAA,EACA,UAAU,UAAUA,CAAE;AAAA,EACtB,MAAAK;AAAA,EACA,UAAAQ;AACF;AASA,SAASC,EACPC,GACAC,GACgB;AAChB,SAAQ,CAACC,OACP,QAAQ,IAAI,iBAAiB,OAAOF,CAAG,CAAC,IAAIE,CAAM,GAC3C,QAAQ,QAAQ,EAAC,IAAI,IAAe,MAAMD,GAAO;AAE5D;AAEA,SAASE,IAA+B;AACtC,QAAMC,IAEF;AAAA,IACF,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,uBAAuB;AAAA,MACrB,YAAY;AAAA,MACZ,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,IACA,iCAAiC;AAAA,IACjC,4BAA4B;AAAA,IAC5B,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,uBAAuB;AAAA,MACrB,QAAQ;AAAA,MACR,OAAO;AAAA,IACT;AAAA,IACA,gBAAgB;AAAA,MACd,MAAM;AAAA,QACJ,aAAa;AAAA,QACb,aAAa,EAAC,KAAK,iCAAgC;AAAA,MAAA;AAAA,IAEvD;AAAA,IACA,wBAAwB;AAAA,IACxB,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,kBAAkB;AAAA,MAChB,UAAU,CAAC,aAAa,gBAAgB,OAAO;AAAA,IACjD;AAAA,IACA,oBAAoB;AAAA,IACpB,gBAAgB;AAAA,IAChB,mBAAmB;AAAA,IACnB,iBAAiB;AAAA,IACjB,oBAAoB;AAAA,IACpB,uBAAuB;AAAA,MACrB,SAAS;AAAA,QACP;AAAA,UACE,KAAK;AAAA,UACL,aAAa;AAAA,UACb,YAAY,CAAC,EAAC,MAAM,OAAO,OAAO,aAAa,CAAA;AAAA,QAAA;AAAA,MACjD;AAAA,IAEJ;AAAA,IACA,qBAAqB;AAAA,MACnB,OAAO;AAAA,QACL;AAAA,UACE,IAAI;AAAA,UACJ,YAAY;AAAA,UACZ,OAAO,EAAC,KAAK,gCAA+B;AAAA,QAAA;AAAA,MAC9C;AAAA,IAEJ;AAAA,IACA,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,qBAAqB;AAAA,IACrB,qBAAqB,CAAC,QAAQ,QAAQ,MAAM;AAAA,IAC5C,qBAAqB;AAAA,IACrB,0BAA0B;AAAA,IAC1B,0BAA0B;AAAA,IAC1B,6BAA6B;AAAA,IAC7B,6BAA6B,CAAC,iBAAiB,eAAe;AAAA,IAC9D,6BAA6B;AAAA,IAC7B,WAAW;AAAA,IACX,WAAW;AAAA,IACX,cAAc;AAAA,IACd,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,IAClB,yBAAyB;AAAA,IACzB,iBAAiB;AAAA,MACf,MAAM;AAAA,QACJP,EAAkB,UAAU,UAAU;AAAA,QACtCA,EAAkB,UAAU,WAAW;AAAA,MACzC;AAAA,MACA,UAAUF,EAAiB;AAAA,IAC7B;AAAA,IACA,gBAAgB;AAAA,MACd,MAAME,EAAkB,UAAU,YAAY;AAAA,QAC5Cb,EAAc,UAAU,gBAAgB;AAAA,MAAA,CACzC;AAAA,MACD,UAAUW,EAAiB;AAAA,IAC7B;AAAA,IACA,gBAAgBE,EAAkB,UAAU,UAAU;AAAA,IACtD,mBAAmB;AAAA,IACnB,mBAAmBA,EAAkB,UAAU,kBAAkB;AAAA,IACjE,oBAAoB;AAAA,IACpB,uBAAuB;AAAA,IACvB,wBAAwB;AAAA,MACtB,MAAM;AAAA,QACJb,EAAc,SAAS,yBAAyB,OAAO;AAAA,QACvDA,EAAc,SAAS,yBAAyB,QAAQ;AAAA,QACxDA,EAAc,SAAS,yBAAyB,QAAQ;AAAA,QACxDA,EAAc,SAAS,yBAAyB,OAAO;AAAA,QACvDA,EAAc,SAAS,yBAAyB,OAAO;AAAA,QACvDA,EAAc,SAAS,yBAAyB,OAAO;AAAA,QACvDA,EAAc,SAAS,yBAAyB,OAAO;AAAA,QACvDA,EAAc,SAAS,yBAAyB,OAAO;AAAA,QACvDA,EAAc,SAAS,yBAAyB,QAAQ;AAAA,MAC1D;AAAA,MACA,UAAUW,EAAiB;AAAA,IAC7B;AAAA,IACA,qBAAqB;AAAA,MACnB,MAAM;AAAA,QACJN,EAAW,UAAU,eAAe;AAAA,QACpCA,EAAW,UAAU,iBAAiB;AAAA,MACxC;AAAA,MACA,UAAUM,EAAiB;AAAA,IAC7B;AAAA,IACA,sBAAsB;AAAA,MACpB,MAAM;AAAA,QACJX,EAAc,YAAY,mBAAmB,OAAO;AAAA,QACpDA,EAAc,YAAY,mBAAmB,OAAO;AAAA,MACtD;AAAA,MACA,UAAUW,EAAiB;AAAA,IAC7B;AAAA,IACA,WAAW;AAAA,MACT,MAAM;AAAA,QACJ;AAAA,UACE,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,WAAW;AAAA,YACT;AAAA,cACE,cAAc;AAAA,cACd,cAAc;AAAA,cACd,UAAU;AAAA,cACV,SAAS;AAAA,YAAA;AAAA,UAEb;AAAA,UACA,MAAMN,EAAW,UAAU,aAAa;AAAA,QAAA;AAAA,MAE5C;AAAA,MACA,UAAUM,EAAiB;AAAA,IAC7B;AAAA,IACA,oBAAoB;AAAA,MAClB,MAAM;AAAA,QACJ,gBAAgB;AAAA,QAChB,oBAAoB;AAAA,UAClB,EAAC,IAAI,QAAQ,MAAM,cAAa;AAAA,UAChC,EAAC,IAAI,QAAQ,MAAM,WAAU;AAAA,QAAA;AAAA,MAC/B;AAAA,IAEJ;AAAA,IACA,mBAAmB;AAAA,IACnB,oBAAoB;AAAA,MAClB,MAAM;AAAA,QACJX,EAAc,SAAS,sBAAsB,QAAQ;AAAA,QACrDA,EAAc,SAAS,eAAe,UAAU,QAAQ;AAAA,QACxDA,EAAc,SAAS,iBAAiB,OAAO;AAAA,QAC/CA,EAAc,SAAS,iBAAiB,OAAO;AAAA,QAC/CA,EAAc,SAAS,iBAAiB,OAAO;AAAA,QAC/CA,EAAc,SAAS,iBAAiB,QAAQ;AAAA,QAChDA,EAAc,SAAS,iBAAiB,QAAQ;AAAA,QAChDA,EAAc,SAAS,mBAAmB,QAAQ;AAAA,QAClDA,EAAc,SAAS,iBAAiB,QAAQ;AAAA,QAChDA,EAAc,UAAU,gBAAgB,OAAO;AAAA,MACjD;AAAA,MACA,UAAUW,EAAiB;AAAA,IAC7B;AAAA,IACA,OAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS;AAAA,IACX;AAAA,IACA,oBAAoB;AAAA,MAClB,MAAM;AAAA,QACJX,EAAc,SAAS,qBAAqB,OAAO;AAAA,QACnDA,EAAc,SAAS,qBAAqB,QAAQ;AAAA,MACtD;AAAA,MACA,UAAUW,EAAiB;AAAA,IAC7B;AAAA,IACA,kBAAkB;AAAA,MAChB,MAAM,CAACX,EAAc,WAAW,mBAAmB,OAAO,CAAC;AAAA,MAC3D,UAAUW,EAAiB;AAAA,IAC7B;AAAA,IACA,mBAAmB;AAAA,MACjB,MAAM,CAACX,EAAc,YAAY,oBAAoB,OAAO,CAAC;AAAA,MAC7D,UAAUW,EAAiB;AAAA,IAC7B;AAAA,IACA,kBAAkB;AAAA,MAChB,MAAM,CAACX,EAAc,YAAY,oBAAoB,OAAO,CAAC;AAAA,MAC7D,UAAUW,EAAiB;AAAA,IAC7B;AAAA,IACA,aAAa,EAAC,MAAM,CAACX,EAAc,UAAU,aAAa,OAAO,CAAC,EAAC;AAAA,IACnE,YAAY,EAAC,MAAMA,EAAc,UAAU,gBAAgB,EAAC;AAAA,IAC5D,oBAAoB;AAAA,MAClB,MAAM;AAAA,QACJ;AAAA,UACE,IAAI;AAAA,UACJ,aAAa;AAAA,UACb,OAAO,EAAC,KAAK,oCAAmC;AAAA,UAChD,OAAO,EAAC,QAAQ,SAAS,cAAc,MAAK;AAAA,UAC5C,gBAAgB,EAAC,QAAQ,SAAS,cAAc,MAAK;AAAA,QAAA;AAAA,MAEzD;AAAA,MACA,UAAUW,EAAiB;AAAA,IAC7B;AAAA,IACA,iBAAiB;AAAA,MACf,MAAM;AAAA,QACJ;AAAA,UACE,IAAI;AAAA,UACJ,OAAO,EAAC,KAAK,kCAAiC;AAAA,UAC9C,kBAAkB;AAAA,UAClB,KAAK;AAAA,QAAA;AAAA,MAET;AAAA,MACA,UAAUA,EAAiB;AAAA,IAC7B;AAAA,IACA,SAAS,EAAC,MAAMN,EAAW,UAAU,aAAa,EAAC;AAAA,IACnD,gBAAgB;AAAA,MACd,MAAM,CAACA,EAAW,iBAAiB,eAAe,CAAC;AAAA,MACnD,UAAUM,EAAiB;AAAA,IAC7B;AAAA,IACA,kBAAkB;AAAA,MAChB,MAAM,CAACN,EAAW,mBAAmB,iBAAiB,CAAC;AAAA,MACvD,UAAUM,EAAiB;AAAA,IAC7B;AAAA,IACA,oBAAoB;AAAA,IACpB,eAAe;AAAA,MACb,MAAM;AAAA,QACJ,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,OAAO;AAAA,UACL,IAAI;AAAA,UACJ,KAAK;AAAA,UACL,OAAO;AAAA,UACP,QAAQ;AAAA,QACV;AAAA,QACA,OAAO;AAAA,QACP,aAAa;AAAA,QACb,YAAY,CAAC,cAAc;AAAA,QAC3B,cAAc;AAAA,QACd,UAAU;AAAA,MAAA;AAAA,IAEd;AAAA,IACA,YAAY;AAAA,MACV,MAAM;AAAA,QACJ;AAAA,UACE,UAAU;AAAA,UACV,OAAO;AAAA,YACL,IAAI;AAAA,YACJ,KAAK;AAAA,YACL,OAAO;AAAA,YACP,QAAQ;AAAA,UACV;AAAA,UACA,OAAO;AAAA,UACP,YAAY,CAAC,cAAc;AAAA,QAAA;AAAA,MAC7B;AAAA,IACF;AAAA,EAEJ,GAEMU,IAA6B,CAAC;AACpC,aAAWL,KAAOI;AAChB,IAAI,OAAO,UAAU,eAAe,KAAKA,GAASJ,CAAG,MAEnDK,EAAKL,CAAG,IAAID;AAAA,MACVC;AAAA,MACAI,EAAQJ,CAA2B;AAAA,IACrC;AAGG,SAAAK;AACT;AAGA,MAAMC,IAAW,MAAe;AACxB,QAAAC,IAAY,UAAU,UAAU,YAAY,GAC5CC,IAAQ,mBAAmB,KAAKD,CAAS,GACzCE,IAAY,UAAU,KAAKF,CAAS;AAE1C,SAAOC,KAASC;AAClB,GAEaC,IAAc,MAAM;AAE/B,EAAIJ,OAIC,OAAO,aACV,OAAO,WAAWH,EAAgB,GAClC,OAAO,cAAc;AAAA,IACnB,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAEJ;"}
|
|
1
|
+
{"version":3,"file":"mocks.js","sources":["../src/mocks.ts"],"sourcesContent":["import {Product, Gender, UserState} from '@shopify/shop-minis-platform'\nimport {ShopActions} from '@shopify/shop-minis-platform/actions'\n\n// Helper functions for common data structures\nexport const createProduct = (\n id: string,\n title: string,\n price = '99.99',\n compareAtPrice?: string\n): Product => ({\n id,\n title,\n price: {amount: price, currencyCode: 'USD'},\n ...(compareAtPrice && {\n compareAtPrice: {amount: compareAtPrice, currencyCode: 'USD'},\n }),\n reviewAnalytics: {averageRating: 4.5, reviewCount: 10},\n shop: createShop('shop1', 'Mock Shop'),\n defaultVariantId: `variant-${id}`,\n isFavorited: false,\n featuredImage: {\n url: `https://cdn.shopify.com/static/sample-images/teapot.jpg`,\n altText: title,\n },\n})\n\nexport const createShop = (\n id: string,\n name: string,\n options?: {\n themeType?: 'coverImage' | 'brandColor' | 'logoColor' | 'none'\n withBrandSettings?: boolean\n primaryColor?: string\n logoDominantColor?: string\n logoAverageColor?: string\n coverDominantColor?: string\n wordmarkUrl?: string\n coverImageUrl?: string\n featuredImagesLimit?: number\n }\n) => {\n // Determine theme configuration\n const themeType = options?.themeType || 'none'\n const shouldHaveBrandSettings =\n options?.withBrandSettings || themeType !== 'none'\n\n // Generate featured images\n const featuredImagesCount = options?.featuredImagesLimit || 3\n const featuredImages = Array.from({length: featuredImagesCount}, (_, i) => ({\n url: `https://picsum.photos/400/400?random=${id}-${i}`,\n sensitive: false,\n altText: `${name} featured image ${i + 1}`,\n }))\n\n // Configure colors based on theme type\n const getThemeColors = () => {\n switch (themeType) {\n case 'coverImage':\n return {\n primary: options?.primaryColor,\n logoDominant: options?.logoDominantColor,\n logoAverage: options?.logoAverageColor,\n coverDominant: options?.coverDominantColor || '#FF6B35',\n }\n case 'brandColor':\n return {\n primary: options?.primaryColor || '#27AE60',\n logoDominant: options?.logoDominantColor,\n logoAverage: options?.logoAverageColor,\n coverDominant: options?.coverDominantColor,\n }\n case 'logoColor':\n return {\n primary: options?.primaryColor,\n logoDominant: options?.logoDominantColor || '#E74C3C',\n logoAverage: options?.logoAverageColor,\n coverDominant: options?.coverDominantColor,\n }\n default:\n return {\n primary: options?.primaryColor,\n logoDominant: options?.logoDominantColor,\n logoAverage: options?.logoAverageColor,\n coverDominant: options?.coverDominantColor,\n }\n }\n }\n\n // Configure header theme\n const createHeaderTheme = () => {\n if (themeType === 'coverImage' || options?.coverImageUrl) {\n return {\n id: `header-theme-${id}`,\n coverImage: {\n url:\n options?.coverImageUrl ||\n 'https://images.unsplash.com/photo-1441986300917-64674bd600d8?w=800&h=400&fit=crop',\n altText: `${name} cover image`,\n sensitive: false,\n thumbhash: 'k9oGHQRnh493V4dIeHeXh4h3iIeI',\n },\n wordmark:\n options?.wordmarkUrl || themeType === 'coverImage'\n ? {\n url:\n options?.wordmarkUrl ||\n 'https://merrypeople.com/cdn/shop/files/Transparent_Background_1.png?v=1696465429&width=1024',\n altText: `${name} wordmark`,\n sensitive: false,\n }\n : undefined,\n }\n }\n\n if (options?.wordmarkUrl) {\n return {\n id: `header-theme-${id}`,\n wordmark: {\n url: options.wordmarkUrl,\n altText: `${name} wordmark`,\n sensitive: false,\n },\n }\n }\n\n return undefined\n }\n\n return {\n id,\n name,\n primaryDomain: {\n url: `https://${name.toLowerCase().replace(/\\s+/g, '-')}.com`,\n },\n reviewAnalytics: {averageRating: 4.3, reviewCount: 50},\n visualTheme: {\n id: `visual-theme-${id}`,\n featuredImages,\n logoImage: {\n url: `https://picsum.photos/100/100?random=${id}`,\n sensitive: false,\n },\n brandSettings: shouldHaveBrandSettings\n ? {\n id: `brand-settings-${id}`,\n colors: {\n id: `colors-${id}`,\n ...getThemeColors(),\n },\n headerTheme: createHeaderTheme(),\n }\n : undefined,\n },\n }\n}\n\nconst createPagination = (hasNext = false) => ({\n hasNextPage: hasNext,\n endCursor: hasNext ? 'cursor123' : null,\n})\n\nconst createProductList = (id: string, name: string, products: any[] = []) => ({\n id,\n publicId: `public-${id}`,\n name,\n products,\n})\n\n// Helper type to extract the data type from a ShopAction\ntype ShopActionDataType<T> = T extends (\n ...args: any[]\n) => Promise<{ok: true; data: infer R} | {ok: false; error: any}>\n ? R\n : never\n\nfunction makeMockMethod<K extends keyof ShopActions>(\n key: K,\n result: ShopActionDataType<ShopActions[K]>\n): ShopActions[K] {\n return ((params: Parameters<ShopActions[K]>[0]) => {\n console.log(`[Mock Action] ${String(key)}`, params)\n return Promise.resolve({ok: true as const, data: result})\n }) as ShopActions[K]\n}\n\nfunction makeMockActions(): ShopActions {\n const results: {\n [K in keyof ShopActions]: ShopActionDataType<ShopActions[K]>\n } = {\n followShop: true,\n unfollowShop: false,\n favorite: undefined,\n unfavorite: undefined,\n getShopAppInformation: {\n appVersion: '1.0.0',\n buildNumber: '12345',\n buildId: 'dev-build-123',\n },\n productRecommendationImpression: undefined,\n productRecommendationClick: undefined,\n hideEntryPoint: undefined,\n closeMini: undefined,\n getAccountInformation: {\n status: 'available',\n value: 'user@example.com',\n },\n getCurrentUser: {\n data: {\n displayName: 'John Doe',\n avatarImage: {url: 'https://example.com/avatar.jpg'},\n },\n },\n createOrderAttribution: undefined,\n addToCart: undefined,\n buyProduct: undefined,\n buyProducts: undefined,\n showErrorScreen: undefined,\n showErrorToast: undefined,\n getDeeplinkPaths: {\n matchers: ['/products', '/collections', '/cart'],\n },\n navigateToDeeplink: undefined,\n navigateToShop: undefined,\n navigateToProduct: undefined,\n navigateToOrder: undefined,\n navigateToCheckout: undefined,\n createImageUploadLink: {\n targets: [\n {\n url: 'https://example.com/upload',\n resourceUrl: 'https://example.com/resource',\n parameters: [{name: 'key', value: 'upload-123'}],\n },\n ],\n },\n completeImageUpload: {\n files: [\n {\n id: 'file-123',\n fileStatus: 'READY',\n image: {url: 'https://example.com/image.jpg'},\n },\n ],\n },\n getPersistedItem: 'stored-value',\n setPersistedItem: undefined,\n removePersistedItem: undefined,\n getAllPersistedKeys: ['key1', 'key2', 'key3'],\n clearPersistedItems: undefined,\n getInternalPersistedItem: 'internal-value',\n setInternalPersistedItem: undefined,\n removeInternalPersistedItem: undefined,\n getAllInternalPersistedKeys: ['internal-key1', 'internal-key2'],\n clearInternalPersistedItems: undefined,\n getSecret: 'secret-value',\n setSecret: undefined,\n removeSecret: undefined,\n reportInteraction: undefined,\n reportImpression: undefined,\n reportContentImpression: undefined,\n getProductLists: {\n data: [\n createProductList('list-1', 'Wishlist'),\n createProductList('list-2', 'Favorites'),\n ],\n pageInfo: createPagination(),\n },\n getProductList: {\n data: createProductList('list-1', 'Wishlist', [\n createProduct('prod-1', 'Sample Product'),\n ]),\n pageInfo: createPagination(),\n },\n addProductList: createProductList('list-3', 'New List'),\n removeProductList: undefined,\n renameProductList: createProductList('list-1', 'Updated Wishlist'),\n addProductListItem: undefined,\n removeProductListItem: undefined,\n getRecommendedProducts: {\n data: [\n createProduct('rec-1', 'Recommended Product 1', '79.99'),\n createProduct('rec-2', 'Recommended Product 2', '129.99'),\n createProduct('rec-3', 'Recommended Product 3', '129.99'),\n createProduct('rec-4', 'Recommended Product 4', '29.99'),\n createProduct('rec-5', 'Recommended Product 5', '39.99'),\n createProduct('rec-6', 'Recommended Product 6', '49.99'),\n createProduct('rec-7', 'Recommended Product 7', '59.99'),\n createProduct('rec-8', 'Recommended Product 8', '69.99'),\n createProduct('rec-9', 'Recommended Product 9', '129.99'),\n ],\n pageInfo: createPagination(),\n },\n getRecommendedShops: {\n data: [\n createShop('shop-1', 'Amazing Store'),\n createShop('shop-2', 'Best Deals Shop'),\n ],\n pageInfo: createPagination(),\n },\n searchProductsByShop: {\n data: [\n createProduct('search-1', 'Search Result 1', '59.99'),\n createProduct('search-2', 'Search Result 2', '89.99'),\n ],\n pageInfo: createPagination(),\n },\n getOrders: {\n data: [\n {\n id: 'order-1',\n name: '#1001',\n lineItems: [\n {\n productTitle: 'Sample Product',\n variantTitle: 'Medium',\n quantity: 2,\n product: null,\n },\n ],\n shop: createShop('shop-1', 'Sample Shop'),\n },\n ],\n pageInfo: createPagination(),\n },\n getBuyerAttributes: {\n data: {\n genderAffinity: 'NEUTRAL' as Gender,\n categoryAffinities: [\n {id: 'cat1', name: 'Electronics'},\n {id: 'cat2', name: 'Clothing'},\n ],\n },\n },\n showFeedbackSheet: undefined,\n getPopularProducts: {\n data: [\n createProduct('pop-1', 'The Hero Snowboard', '702.95'),\n createProduct('pop-2', 'Snow Jacket', '605.95', '702.00'),\n createProduct('pop-3', 'Winter Gloves', '89.95'),\n createProduct('pop-4', 'Summer Gloves', '89.95'),\n createProduct('pop-5', 'Spring Gloves', '89.95'),\n createProduct('pop-6', 'Playstation 5', '499.95'),\n createProduct('pop-7', 'Xbox Series X', '499.95'),\n createProduct('pop-8', 'Nintendo Switch', '299.95'),\n createProduct('pop-9', 'Playstation 4', '299.95'),\n createProduct('pop-10', 'Nintendo 3DS', '89.95'),\n ],\n pageInfo: createPagination(),\n },\n share: {\n message: 'Shared!',\n success: true,\n },\n getCuratedProducts: {\n data: [\n createProduct('cur-1', 'Curated Product 1', '79.99'),\n createProduct('cur-2', 'Curated Product 2', '129.99'),\n ],\n pageInfo: createPagination(),\n },\n getSavedProducts: {\n data: [createProduct('saved-1', 'Saved Product 1', '49.99')],\n pageInfo: createPagination(),\n },\n getRecentProducts: {\n data: [createProduct('recent-1', 'Recent Product 1', '59.99')],\n pageInfo: createPagination(),\n },\n getProductSearch: {\n data: [createProduct('search-3', 'Search Product 3', '39.99')],\n pageInfo: createPagination(),\n },\n getProducts: {data: [createProduct('prod-2', 'Product 2', '19.99')]},\n getProduct: {data: createProduct('prod-1', 'Sample Product')},\n getProductVariants: {\n data: [\n {\n id: 'variant-1',\n isFavorited: false,\n image: {url: 'https://example.com/variant-1.jpg'},\n price: {amount: '19.99', currencyCode: 'USD'},\n compareAtPrice: {amount: '29.99', currencyCode: 'USD'},\n },\n ],\n pageInfo: createPagination(),\n },\n getProductMedia: {\n data: [\n {\n id: 'media-1',\n image: {url: 'https://example.com/media-1.jpg'},\n mediaContentType: 'IMAGE',\n alt: 'Sample product image',\n },\n ],\n pageInfo: createPagination(),\n },\n getShop: {data: createShop('shop-1', 'Sample Shop')},\n getRecentShops: {\n data: [createShop('recent-shop-1', 'Recent Shop 1')],\n pageInfo: createPagination(),\n },\n getFollowedShops: {\n data: [createShop('followed-shop-1', 'Followed Shop 1')],\n pageInfo: createPagination(),\n },\n previewProductInAr: undefined,\n createContent: {\n data: {\n publicId: 'content-123',\n externalId: null,\n image: {\n id: 'img-123',\n url: 'https://cdn.shopify.com/s/files/1/0633/6574/2742/files/Namnlosdesign-47.png?v=1740438079',\n width: 800,\n height: 600,\n },\n title: 'Mock Content',\n description: 'This is a mock content item',\n visibility: ['DISCOVERABLE'],\n shareableUrl: 'https://example.com/content/123',\n products: null,\n },\n },\n getContent: {\n data: [\n {\n publicId: 'content-123',\n image: {\n id: 'img-123',\n url: 'https://cdn.shopify.com/s/files/1/0633/6574/2742/files/Namnlosdesign-47.png?v=1740438079',\n width: 800,\n height: 600,\n },\n title: 'Mock Content',\n visibility: ['DISCOVERABLE'],\n },\n ],\n },\n generateUserToken: {\n data: {\n token: 'user-token-123',\n expiresAt: '2025-01-01',\n userState: UserState.VERIFIED,\n },\n },\n } as const\n\n const mock: Partial<ShopActions> = {}\n for (const key in results) {\n if (Object.prototype.hasOwnProperty.call(results, key)) {\n // @ts-expect-error: dynamic assignment is safe due to exhaustive mapping\n mock[key] = makeMockMethod(\n key as keyof ShopActions,\n results[key as keyof typeof results]\n )\n }\n }\n return mock as ShopActions\n}\n\n// Detect if running on a mobile device\nconst isMobile = (): boolean => {\n const userAgent = navigator.userAgent.toLowerCase()\n const isIOS = /iphone|ipad|ipod/.test(userAgent)\n const isAndroid = /android/.test(userAgent)\n\n return isIOS || isAndroid\n}\n\nexport const injectMocks = () => {\n // Only inject mocks if we aren't on a mobile device\n if (isMobile()) {\n return\n }\n\n if (!window.minisSDK) {\n window.minisSDK = makeMockActions()\n window.minisParams = {\n handle: 'mock-handle',\n initialUrl: '/mock-initial-url',\n platform: 'web',\n }\n }\n}\n"],"names":["createProduct","id","title","price","compareAtPrice","createShop","name","options","featuredImages","_","i","createPagination","hasNext","createProductList","products","makeMockMethod","key","result","params","makeMockActions","results","UserState","mock","isMobile","userAgent","isIOS","isAndroid","injectMocks"],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
var I = /* @__PURE__ */ ((N) => (N.MINI_NOT_FOUND = "MINI_NOT_FOUND", N.USER_NOT_FOUND = "USER_NOT_FOUND", N))(I || {}), O = /* @__PURE__ */ ((N) => (N.GUEST = "GUEST", N.VERIFIED = "VERIFIED", N))(O || {});
|
|
2
|
+
export {
|
|
3
|
+
O as UserState,
|
|
4
|
+
I as UserTokenGenerateUserErrorCode
|
|
5
|
+
};
|
|
6
|
+
//# sourceMappingURL=user.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.js","sources":["../../../../../shop-minis-platform/src/types/user.ts"],"sourcesContent":["/* eslint-disable @shopify/typescript/prefer-pascal-case-enums */ export interface UserProfile {\n displayName?: string | null\n avatarImage?: {\n url: string\n } | null\n}\n\nexport interface BuyerAttributes {\n genderAffinity?: Gender\n categoryAffinities: TaxonomyCategory[]\n}\n\nexport type Gender = 'MALE' | 'FEMALE' | 'NEUTRAL'\n\nexport interface TaxonomyCategory {\n id: string\n name: string\n ancestors?: TaxonomyCategory[]\n}\n\nexport enum UserTokenGenerateUserErrorCode {\n MINI_NOT_FOUND = 'MINI_NOT_FOUND',\n USER_NOT_FOUND = 'USER_NOT_FOUND',\n}\n\nexport enum UserState {\n GUEST = 'GUEST',\n VERIFIED = 'VERIFIED',\n}\n\nexport type ISO8601DateTime = string\n\nexport interface UserTokenGenerateUserErrors {\n code: UserTokenGenerateUserErrorCode\n message: string\n field?: string[] | null\n}\n\nexport interface GeneratedTokenData {\n /**\n * A temporary token for the user.\n */\n token?: string | null\n /**\n * The expiration time of the token.\n */\n expiresAt?: ISO8601DateTime | null\n /**\n * Whether the user is verified or a guest.\n */\n userState?: UserState | null\n}\n"],"names":["UserTokenGenerateUserErrorCode","UserState"],"mappings":"AAoBY,IAAAA,sBAAAA,OACVA,EAAA,iBAAiB,kBACjBA,EAAA,iBAAiB,kBAFPA,IAAAA,KAAA,CAAA,CAAA,GAKAC,sBAAAA,OACVA,EAAA,QAAQ,SACRA,EAAA,WAAW,YAFDA,IAAAA,KAAA,CAAA,CAAA;"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shopify/shop-minis-react",
|
|
3
3
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.31",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"type": "module",
|
|
7
7
|
"engines": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"typescript": ">=5.0.0"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@shopify/shop-minis-platform": "0.0.
|
|
41
|
+
"@shopify/shop-minis-platform": "0.0.10",
|
|
42
42
|
"@tailwindcss/vite": "4.1.8",
|
|
43
43
|
"@types/color": "3.0.6",
|
|
44
44
|
"@types/lodash": "4.17.20",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {ComponentType, useCallback} from 'react'
|
|
1
|
+
import {ComponentType, useCallback, useRef} from 'react'
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
VariableSizeList as _VariableSizeList,
|
|
@@ -24,7 +24,7 @@ interface Props<T = any>
|
|
|
24
24
|
showScrollbar?: boolean
|
|
25
25
|
header?: React.ReactNode
|
|
26
26
|
headerHeight?: number
|
|
27
|
-
fetchMore?: () => void
|
|
27
|
+
fetchMore?: () => Promise<void>
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
export function List<T = any>({
|
|
@@ -40,6 +40,26 @@ export function List<T = any>({
|
|
|
40
40
|
overscanCount,
|
|
41
41
|
...listProps
|
|
42
42
|
}: Props<T>) {
|
|
43
|
+
const inFlightFetchMoreRef = useRef<Promise<void> | null>(null)
|
|
44
|
+
|
|
45
|
+
// This is workaround to prevent multiple calls to fetchMore
|
|
46
|
+
// react-window re-renders the rows while scrolling,
|
|
47
|
+
// and the TrackingPixel could be triggered multiple times
|
|
48
|
+
|
|
49
|
+
const _fetchMore = useCallback(() => {
|
|
50
|
+
// Dedupe concurrent calls by returning the same in-flight promise
|
|
51
|
+
if (inFlightFetchMoreRef.current) return
|
|
52
|
+
|
|
53
|
+
const current = Promise.resolve(fetchMore?.()).finally(() => {
|
|
54
|
+
// Only clear if this is still the most recent promise
|
|
55
|
+
if (inFlightFetchMoreRef.current === current) {
|
|
56
|
+
inFlightFetchMoreRef.current = null
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
inFlightFetchMoreRef.current = current
|
|
61
|
+
}, [fetchMore])
|
|
62
|
+
|
|
43
63
|
const rowRenderer = useCallback(
|
|
44
64
|
({index, style}: {index: number; style: React.CSSProperties}) => {
|
|
45
65
|
// prepend the header to the first row if it exists
|
|
@@ -58,7 +78,7 @@ export function List<T = any>({
|
|
|
58
78
|
<div style={style}>
|
|
59
79
|
{renderItem(items[index], index)}
|
|
60
80
|
<div style={{bottom: 0}}>
|
|
61
|
-
<Pagination fetchMore={
|
|
81
|
+
<Pagination fetchMore={_fetchMore} />
|
|
62
82
|
</div>
|
|
63
83
|
</div>
|
|
64
84
|
)
|
|
@@ -66,7 +86,7 @@ export function List<T = any>({
|
|
|
66
86
|
|
|
67
87
|
return <div style={style}>{renderItem(items[index], index)}</div>
|
|
68
88
|
},
|
|
69
|
-
[items, renderItem, header,
|
|
89
|
+
[items, renderItem, header, headerHeight, _fetchMore, fetchMore]
|
|
70
90
|
)
|
|
71
91
|
|
|
72
92
|
const getItemSize = useCallback(
|
package/src/hooks/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ export * from './user/useFollowedShopsActions'
|
|
|
8
8
|
export * from './user/useCurrentUser'
|
|
9
9
|
export * from './user/useOrders'
|
|
10
10
|
export * from './user/useBuyerAttributes'
|
|
11
|
+
export * from './user/useGenerateUserToken'
|
|
11
12
|
|
|
12
13
|
// - Product Hooks
|
|
13
14
|
export * from './product/useProductListActions'
|
|
@@ -2,7 +2,12 @@ import {useLocation, useNavigate, NavigateOptions} from 'react-router'
|
|
|
2
2
|
|
|
3
3
|
import {DATA_NAVIGATION_TYPE_ATTRIBUTE} from '../../types'
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
type UseNavigateWithTransitionReturns = (
|
|
6
|
+
to: string | number,
|
|
7
|
+
options?: NavigateOptions
|
|
8
|
+
) => void | Promise<void>
|
|
9
|
+
|
|
10
|
+
export function useNavigateWithTransition(): UseNavigateWithTransitionReturns {
|
|
6
11
|
const navigate = useNavigate()
|
|
7
12
|
const location = useLocation()
|
|
8
13
|
|
|
@@ -21,7 +21,9 @@ interface UseShopNavigationReturns {
|
|
|
21
21
|
* Navigates to an order.
|
|
22
22
|
*/
|
|
23
23
|
navigateToOrder: (params: NavigateToOrderParams) => Promise<void>
|
|
24
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Navigates to a checkout.
|
|
26
|
+
*/
|
|
25
27
|
navigateToCheckout: (params: NavigateToCheckoutParams) => Promise<void>
|
|
26
28
|
}
|
|
27
29
|
|
|
@@ -8,11 +8,11 @@ import {useShopActions} from '../../internal/useShopActions'
|
|
|
8
8
|
|
|
9
9
|
interface UseFollowedShopsActionsReturns {
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
11
|
+
* Follows a shop.
|
|
12
12
|
*/
|
|
13
13
|
followShop: (params: FollowShopParams) => Promise<boolean>
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
15
|
+
* Unfollows a shop.
|
|
16
16
|
*/
|
|
17
17
|
unfollowShop: (params: UnfollowShopParams) => Promise<boolean>
|
|
18
18
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
GeneratedTokenData,
|
|
3
|
+
UserTokenGenerateUserErrors,
|
|
4
|
+
} from '@shopify/shop-minis-platform'
|
|
5
|
+
|
|
6
|
+
import {useHandleAction} from '../../internal/useHandleAction'
|
|
7
|
+
import {useShopActions} from '../../internal/useShopActions'
|
|
8
|
+
|
|
9
|
+
interface UseGenerateUserTokenReturns {
|
|
10
|
+
/**
|
|
11
|
+
* Generates a temporary token for the user.
|
|
12
|
+
*/
|
|
13
|
+
generateUserToken: () => Promise<{
|
|
14
|
+
data: GeneratedTokenData
|
|
15
|
+
userErrors?: UserTokenGenerateUserErrors[]
|
|
16
|
+
}>
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function useGenerateUserToken(): UseGenerateUserTokenReturns {
|
|
20
|
+
const {generateUserToken} = useShopActions()
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
generateUserToken: useHandleAction(generateUserToken),
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -3,12 +3,18 @@ import {
|
|
|
3
3
|
useImagePickerContext,
|
|
4
4
|
} from '../../providers/ImagePickerProvider'
|
|
5
5
|
|
|
6
|
-
interface
|
|
6
|
+
interface UseImagePickerReturns {
|
|
7
|
+
/**
|
|
8
|
+
* Opens the camera to take a photo.
|
|
9
|
+
*/
|
|
7
10
|
openCamera: (cameraFacing?: CameraFacing) => Promise<File>
|
|
11
|
+
/**
|
|
12
|
+
* Opens the gallery to select an image.
|
|
13
|
+
*/
|
|
8
14
|
openGallery: () => Promise<File>
|
|
9
15
|
}
|
|
10
16
|
|
|
11
|
-
export function useImagePicker():
|
|
17
|
+
export function useImagePicker(): UseImagePickerReturns {
|
|
12
18
|
const {openCamera, openGallery} = useImagePickerContext()
|
|
13
19
|
|
|
14
20
|
return {
|
package/src/mocks.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {Product, Gender} from '@shopify/shop-minis-platform'
|
|
1
|
+
import {Product, Gender, UserState} from '@shopify/shop-minis-platform'
|
|
2
2
|
import {ShopActions} from '@shopify/shop-minis-platform/actions'
|
|
3
3
|
|
|
4
4
|
// Helper functions for common data structures
|
|
@@ -19,7 +19,7 @@ export const createProduct = (
|
|
|
19
19
|
defaultVariantId: `variant-${id}`,
|
|
20
20
|
isFavorited: false,
|
|
21
21
|
featuredImage: {
|
|
22
|
-
url: `https://cdn.shopify.com/
|
|
22
|
+
url: `https://cdn.shopify.com/static/sample-images/teapot.jpg`,
|
|
23
23
|
altText: title,
|
|
24
24
|
},
|
|
25
25
|
})
|
|
@@ -411,7 +411,7 @@ function makeMockActions(): ShopActions {
|
|
|
411
411
|
externalId: null,
|
|
412
412
|
image: {
|
|
413
413
|
id: 'img-123',
|
|
414
|
-
url: 'https://
|
|
414
|
+
url: 'https://cdn.shopify.com/s/files/1/0633/6574/2742/files/Namnlosdesign-47.png?v=1740438079',
|
|
415
415
|
width: 800,
|
|
416
416
|
height: 600,
|
|
417
417
|
},
|
|
@@ -428,7 +428,7 @@ function makeMockActions(): ShopActions {
|
|
|
428
428
|
publicId: 'content-123',
|
|
429
429
|
image: {
|
|
430
430
|
id: 'img-123',
|
|
431
|
-
url: 'https://
|
|
431
|
+
url: 'https://cdn.shopify.com/s/files/1/0633/6574/2742/files/Namnlosdesign-47.png?v=1740438079',
|
|
432
432
|
width: 800,
|
|
433
433
|
height: 600,
|
|
434
434
|
},
|
|
@@ -437,6 +437,13 @@ function makeMockActions(): ShopActions {
|
|
|
437
437
|
},
|
|
438
438
|
],
|
|
439
439
|
},
|
|
440
|
+
generateUserToken: {
|
|
441
|
+
data: {
|
|
442
|
+
token: 'user-token-123',
|
|
443
|
+
expiresAt: '2025-01-01',
|
|
444
|
+
userState: UserState.VERIFIED,
|
|
445
|
+
},
|
|
446
|
+
},
|
|
440
447
|
} as const
|
|
441
448
|
|
|
442
449
|
const mock: Partial<ShopActions> = {}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import {fn} from 'storybook/test'
|
|
2
|
+
|
|
3
|
+
import {ImageContentWrapper} from '../components/content/image-content-wrapper'
|
|
4
|
+
import {injectMocks} from '../mocks'
|
|
5
|
+
|
|
6
|
+
import type {Meta, StoryObj} from '@storybook/react-vite'
|
|
7
|
+
|
|
8
|
+
const meta = {
|
|
9
|
+
title: 'Content/ImageContentWrapper',
|
|
10
|
+
component: ImageContentWrapper,
|
|
11
|
+
parameters: {
|
|
12
|
+
layout: 'padded',
|
|
13
|
+
},
|
|
14
|
+
args: {
|
|
15
|
+
onLoad: fn(),
|
|
16
|
+
},
|
|
17
|
+
argTypes: {
|
|
18
|
+
publicId: {
|
|
19
|
+
control: 'text',
|
|
20
|
+
},
|
|
21
|
+
externalId: {
|
|
22
|
+
control: 'text',
|
|
23
|
+
},
|
|
24
|
+
width: {
|
|
25
|
+
control: 'number',
|
|
26
|
+
},
|
|
27
|
+
height: {
|
|
28
|
+
control: 'number',
|
|
29
|
+
},
|
|
30
|
+
className: {
|
|
31
|
+
control: 'text',
|
|
32
|
+
},
|
|
33
|
+
Loader: {
|
|
34
|
+
control: 'text',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
tags: ['autodocs'],
|
|
38
|
+
} satisfies Meta<typeof ImageContentWrapper>
|
|
39
|
+
|
|
40
|
+
export default meta
|
|
41
|
+
type Story = StoryObj<typeof meta>
|
|
42
|
+
|
|
43
|
+
injectMocks()
|
|
44
|
+
|
|
45
|
+
export const WithPublicId: Story = {
|
|
46
|
+
args: {
|
|
47
|
+
publicId: 'content-123',
|
|
48
|
+
width: 400,
|
|
49
|
+
height: 300,
|
|
50
|
+
},
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export const WithExternalId: Story = {
|
|
54
|
+
args: {
|
|
55
|
+
externalId: 'external-123',
|
|
56
|
+
width: 400,
|
|
57
|
+
height: 300,
|
|
58
|
+
},
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export const WithCustomLoader: Story = {
|
|
62
|
+
args: {
|
|
63
|
+
publicId: 'content-123',
|
|
64
|
+
width: 400,
|
|
65
|
+
height: 300,
|
|
66
|
+
Loader: 'Loading image...',
|
|
67
|
+
},
|
|
68
|
+
}
|
|
@@ -31,6 +31,13 @@ type Story = StoryObj<typeof meta>
|
|
|
31
31
|
injectMocks()
|
|
32
32
|
|
|
33
33
|
export const Default: Story = {
|
|
34
|
+
decorators: [
|
|
35
|
+
Story => (
|
|
36
|
+
<div style={{maxWidth: 200}}>
|
|
37
|
+
<Story />
|
|
38
|
+
</div>
|
|
39
|
+
),
|
|
40
|
+
],
|
|
34
41
|
args: {
|
|
35
42
|
shop: {
|
|
36
43
|
...createShop('shop1', 'Amazing Store'),
|
|
@@ -40,6 +47,13 @@ export const Default: Story = {
|
|
|
40
47
|
}
|
|
41
48
|
|
|
42
49
|
export const CoverImageDark: Story = {
|
|
50
|
+
decorators: [
|
|
51
|
+
Story => (
|
|
52
|
+
<div style={{maxWidth: 200}}>
|
|
53
|
+
<Story />
|
|
54
|
+
</div>
|
|
55
|
+
),
|
|
56
|
+
],
|
|
43
57
|
name: 'Cover Image',
|
|
44
58
|
args: {
|
|
45
59
|
shop: createShop('cover3', 'Midnight Store', {
|
|
@@ -50,6 +64,13 @@ export const CoverImageDark: Story = {
|
|
|
50
64
|
}
|
|
51
65
|
|
|
52
66
|
export const BrandColorWordmark: Story = {
|
|
67
|
+
decorators: [
|
|
68
|
+
Story => (
|
|
69
|
+
<div style={{maxWidth: 200}}>
|
|
70
|
+
<Story />
|
|
71
|
+
</div>
|
|
72
|
+
),
|
|
73
|
+
],
|
|
53
74
|
name: 'Brand Color + Wordmark',
|
|
54
75
|
args: {
|
|
55
76
|
shop: createShop('brand2', 'Amazing Store', {
|
|
@@ -34,10 +34,17 @@ type Story = StoryObj<typeof meta>
|
|
|
34
34
|
injectMocks()
|
|
35
35
|
|
|
36
36
|
export const Single: Story = {
|
|
37
|
+
decorators: [
|
|
38
|
+
Story => (
|
|
39
|
+
<div style={{maxWidth: 200}}>
|
|
40
|
+
<Story />
|
|
41
|
+
</div>
|
|
42
|
+
),
|
|
43
|
+
],
|
|
37
44
|
args: {
|
|
38
45
|
product: {
|
|
39
46
|
id: '1',
|
|
40
|
-
title: '
|
|
47
|
+
title: 'Teapot',
|
|
41
48
|
|
|
42
49
|
price: {
|
|
43
50
|
amount: '100',
|
|
@@ -61,7 +68,7 @@ export const Single: Story = {
|
|
|
61
68
|
isFavorited: true,
|
|
62
69
|
|
|
63
70
|
featuredImage: {
|
|
64
|
-
url: 'https://
|
|
71
|
+
url: 'https://cdn.shopify.com/static/sample-images/teapot.jpg',
|
|
65
72
|
altText: 'Product 1',
|
|
66
73
|
},
|
|
67
74
|
},
|
|
@@ -80,6 +87,6 @@ export const Grid: Story = {
|
|
|
80
87
|
),
|
|
81
88
|
],
|
|
82
89
|
args: {
|
|
83
|
-
product: createProduct('1', '
|
|
90
|
+
product: createProduct('1', 'Teapot', '100', '120'),
|
|
84
91
|
},
|
|
85
92
|
}
|
|
@@ -20,13 +20,13 @@ injectMocks()
|
|
|
20
20
|
|
|
21
21
|
export const Default: Story = {
|
|
22
22
|
args: {
|
|
23
|
-
product: createProduct('1', '
|
|
23
|
+
product: createProduct('1', 'Teapot', '100', '120'),
|
|
24
24
|
},
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
export const WithDiscount: Story = {
|
|
28
28
|
args: {
|
|
29
|
-
product: createProduct('2', '
|
|
29
|
+
product: createProduct('2', 'Discounted Teapot', '80', '120'),
|
|
30
30
|
},
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -41,6 +41,6 @@ export const List: Story = {
|
|
|
41
41
|
),
|
|
42
42
|
],
|
|
43
43
|
args: {
|
|
44
|
-
product: createProduct('1', '
|
|
44
|
+
product: createProduct('1', 'Teapot', '100', '120'),
|
|
45
45
|
},
|
|
46
46
|
}
|