@shopify/shop-minis-react 0.0.19 → 0.0.21

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.
Files changed (60) hide show
  1. package/dist/components/MinisContainer.js +13 -11
  2. package/dist/components/MinisContainer.js.map +1 -1
  3. package/dist/components/atoms/list.js +52 -0
  4. package/dist/components/atoms/list.js.map +1 -0
  5. package/dist/components/atoms/pagination.js +10 -0
  6. package/dist/components/atoms/pagination.js.map +1 -0
  7. package/dist/components/atoms/tracking-pixel.js +32 -0
  8. package/dist/components/atoms/tracking-pixel.js.map +1 -0
  9. package/dist/hooks/storage/useImageUpload.js.map +1 -1
  10. package/dist/hooks/util/useErrorScreen.js.map +1 -1
  11. package/dist/hooks/util/useErrorToast.js.map +1 -1
  12. package/dist/index.js +194 -189
  13. package/dist/index.js.map +1 -1
  14. package/dist/internal/useShopActions.js.map +1 -1
  15. package/dist/internal/useShopActionsDataFetching.js +26 -26
  16. package/dist/internal/useShopActionsDataFetching.js.map +1 -1
  17. package/dist/internal/useShopActionsPaginatedDataFetching.js.map +1 -1
  18. package/dist/mocks.js +267 -0
  19. package/dist/mocks.js.map +1 -0
  20. package/dist/shop-minis-react/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js +8 -0
  21. package/dist/shop-minis-react/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js.map +1 -0
  22. package/dist/shop-minis-react/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/extends.js +13 -0
  23. package/dist/shop-minis-react/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/extends.js.map +1 -0
  24. package/dist/shop-minis-react/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/inheritsLoose.js +8 -0
  25. package/dist/shop-minis-react/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/inheritsLoose.js.map +1 -0
  26. package/dist/shop-minis-react/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js +9 -0
  27. package/dist/shop-minis-react/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js.map +1 -0
  28. package/dist/shop-minis-react/node_modules/.pnpm/memoize-one@5.2.1/node_modules/memoize-one/dist/memoize-one.esm.js +28 -0
  29. package/dist/shop-minis-react/node_modules/.pnpm/memoize-one@5.2.1/node_modules/memoize-one/dist/memoize-one.esm.js.map +1 -0
  30. package/dist/shop-minis-react/node_modules/.pnpm/react-intersection-observer@9.16.0_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/react-intersection-observer/dist/index.js +135 -0
  31. package/dist/shop-minis-react/node_modules/.pnpm/react-intersection-observer@9.16.0_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/react-intersection-observer/dist/index.js.map +1 -0
  32. package/dist/shop-minis-react/node_modules/.pnpm/react-window@1.8.11_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/react-window/dist/index.esm.js +375 -0
  33. package/dist/shop-minis-react/node_modules/.pnpm/react-window@1.8.11_react-dom@19.1.0_react@19.1.0__react@19.1.0/node_modules/react-window/dist/index.esm.js.map +1 -0
  34. package/dist/shop-minis-react.css +1 -0
  35. package/package.json +9 -4
  36. package/src/components/MinisContainer.tsx +4 -1
  37. package/src/components/atoms/list.tsx +101 -0
  38. package/src/components/atoms/pagination.tsx +19 -0
  39. package/src/components/atoms/tracking-pixel.tsx +40 -0
  40. package/src/components/index.ts +2 -0
  41. package/src/hooks/navigation/useCloseMini.example.tsx +1 -1
  42. package/src/hooks/navigation/useShopNavigation.example.tsx +12 -9
  43. package/src/hooks/product/useProductListActions.example.tsx +19 -16
  44. package/src/hooks/shop/useShopCartActions.example.tsx +2 -2
  45. package/src/hooks/storage/useImageUpload.example.tsx +1 -1
  46. package/src/hooks/storage/useImageUpload.ts +3 -2
  47. package/src/hooks/user/useFollowedShopsActions.example.tsx +6 -8
  48. package/src/hooks/user/useSavedProductsActions.example.tsx +8 -6
  49. package/src/hooks/util/useErrorScreen.example.tsx +1 -2
  50. package/src/hooks/util/useErrorScreen.ts +2 -1
  51. package/src/hooks/util/useErrorToast.example.tsx +1 -1
  52. package/src/hooks/util/useErrorToast.ts +2 -1
  53. package/src/hooks/util/useImagePicker.example.tsx +4 -12
  54. package/src/index.css +1 -0
  55. package/src/internal/useShopActions.ts +1 -1
  56. package/src/internal/useShopActionsDataFetching.ts +6 -7
  57. package/src/internal/useShopActionsPaginatedDataFetching.ts +3 -6
  58. package/src/mocks.ts +20 -8
  59. package/src/stories/List.stories.tsx +68 -0
  60. package/src/styles/utilities.css +22 -0
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.19",
4
+ "version": "0.0.21",
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.6",
41
+ "@shopify/shop-minis-platform": "0.0.7",
42
42
  "@tailwindcss/vite": "4.1.8",
43
43
  "@types/url-parse": "1.4.9",
44
44
  "@vitejs/plugin-react": "4.5.1",
@@ -51,8 +51,10 @@
51
51
  "motion": "12.17.3",
52
52
  "next-themes": "0.4.6",
53
53
  "radix-ui": "1.4.2",
54
+ "react-intersection-observer": "^9.13.1",
54
55
  "react-resizable-panels": "3.0.2",
55
56
  "react-router": "^7.7.0",
57
+ "react-window": "^1.8.11",
56
58
  "sonner": "2.0.5",
57
59
  "tailwind-merge": "2.6.0",
58
60
  "tailwindcss": "4.1.8",
@@ -68,7 +70,8 @@
68
70
  "@types/node": "^20.12.1",
69
71
  "@types/react": "^19.1.6",
70
72
  "@types/react-dom": "^19.1.2",
71
- "eslint": "^9.31.0",
73
+ "@types/react-window": "^1.8.8",
74
+ "eslint": "^8.57.0",
72
75
  "eslint-plugin-storybook": "^9.0.16",
73
76
  "react": "^19.1.0",
74
77
  "react-dom": "^19.1.0",
@@ -102,6 +105,8 @@
102
105
  "type-check": "tsc --noEmit",
103
106
  "clean": "rm -rf dist",
104
107
  "storybook": "storybook dev -p 6006",
105
- "build-storybook": "storybook build"
108
+ "build-storybook": "storybook build",
109
+ "lint": "eslint . --format codeframe --cache",
110
+ "lint:fix": "eslint . --format codeframe --cache --fix"
106
111
  }
107
112
  }
@@ -1,7 +1,10 @@
1
1
  import React, {useEffect, useState} from 'react'
2
2
 
3
+ import {injectMocks} from '../mocks'
3
4
  import {ImagePickerProvider} from '../providers/ImagePickerProvider'
4
5
 
6
+ injectMocks()
7
+
5
8
  export function MinisContainer({children}: {children: React.ReactNode}) {
6
9
  const [isSDKReady, setIsSDKReady] = useState(false)
7
10
 
@@ -42,7 +45,7 @@ export function MinisContainer({children}: {children: React.ReactNode}) {
42
45
 
43
46
  // Cleanup
44
47
  return () => {
45
- // clearInterval(pollInterval);
48
+ clearInterval(pollInterval)
46
49
  window.removeEventListener('message', handleSDKReady)
47
50
  document.removeEventListener('message', handleSDKReady)
48
51
  }
@@ -0,0 +1,101 @@
1
+ import {ComponentType, useCallback} from 'react'
2
+
3
+ import {
4
+ VariableSizeList as _VariableSizeList,
5
+ VariableSizeListProps,
6
+ } from 'react-window'
7
+
8
+ import {cn} from '../../lib/utils'
9
+ import '../../styles/utilities.css'
10
+
11
+ import {Pagination} from './pagination'
12
+
13
+ const VariableSizeList =
14
+ _VariableSizeList as unknown as ComponentType<VariableSizeListProps>
15
+
16
+ interface Props<T = any>
17
+ extends Omit<
18
+ VariableSizeListProps<T>,
19
+ 'children' | 'itemCount' | 'width' | 'itemSize' | 'direction'
20
+ > {
21
+ items: T[]
22
+ renderItem: (item: T, index: number) => React.ReactNode
23
+ itemSizeForRow: (index: number) => number
24
+ showScrollbar?: boolean
25
+ header?: React.ReactNode
26
+ headerHeight?: number
27
+ fetchMore?: () => void
28
+ }
29
+
30
+ export function List<T = any>({
31
+ items,
32
+ height,
33
+ renderItem,
34
+ className,
35
+ showScrollbar = false,
36
+ header,
37
+ headerHeight,
38
+ itemSizeForRow,
39
+ fetchMore,
40
+ overscanCount,
41
+ ...listProps
42
+ }: Props<T>) {
43
+ const rowRenderer = useCallback(
44
+ ({index, style}: {index: number; style: React.CSSProperties}) => {
45
+ // prepend the header to the first row if it exists
46
+ if (header && index === 0) {
47
+ return (
48
+ <div style={style}>
49
+ {header}
50
+ <div style={{top: headerHeight}}>{renderItem(items[0], 0)}</div>
51
+ </div>
52
+ )
53
+ }
54
+
55
+ // append the pagination spinner to the last row if fetchMore exists
56
+ if (fetchMore && index === items.length - 1) {
57
+ return (
58
+ <div style={style}>
59
+ {renderItem(items[index], index)}
60
+ <div style={{bottom: 0}}>
61
+ <Pagination fetchMore={fetchMore} />
62
+ </div>
63
+ </div>
64
+ )
65
+ }
66
+
67
+ return <div style={style}>{renderItem(items[index], index)}</div>
68
+ },
69
+ [items, renderItem, header, fetchMore, headerHeight]
70
+ )
71
+
72
+ const getItemSize = useCallback(
73
+ (index: number) => {
74
+ // include the header height in the first row height
75
+ if (header && index === 0) {
76
+ const _headerHeight = headerHeight || 0
77
+ return _headerHeight + itemSizeForRow(index)
78
+ }
79
+
80
+ return itemSizeForRow(index)
81
+ },
82
+ [itemSizeForRow, header, headerHeight]
83
+ )
84
+
85
+ const classNames = cn(showScrollbar ? undefined : 'no-scrollbars', className)
86
+
87
+ return (
88
+ <VariableSizeList
89
+ className={classNames}
90
+ height={height}
91
+ direction="vertical"
92
+ width="100%"
93
+ itemCount={items.length}
94
+ overscanCount={overscanCount}
95
+ itemSize={getItemSize}
96
+ {...listProps}
97
+ >
98
+ {rowRenderer}
99
+ </VariableSizeList>
100
+ )
101
+ }
@@ -0,0 +1,19 @@
1
+ import {Skeleton} from '../ui/skeleton'
2
+
3
+ import {TrackingPixel} from './tracking-pixel'
4
+
5
+ interface Props {
6
+ loadingComponent?: React.ReactNode
7
+ isFetchingMore?: boolean
8
+ fetchMore: () => void
9
+ }
10
+
11
+ export function Pagination({loadingComponent, fetchMore}: Props) {
12
+ const loadingPlaceholder = loadingComponent ?? (
13
+ <Skeleton className="h-10 w-full p-8" />
14
+ )
15
+
16
+ return (
17
+ <TrackingPixel onImpression={fetchMore}>{loadingPlaceholder}</TrackingPixel>
18
+ )
19
+ }
@@ -0,0 +1,40 @@
1
+ import {useCallback} from 'react'
2
+
3
+ import {InView} from 'react-intersection-observer'
4
+
5
+ interface Props {
6
+ children: React.ReactNode
7
+ onImpression?: () => void
8
+ triggerOnce?: boolean
9
+ threshold?: number
10
+ className?: string
11
+ }
12
+
13
+ export const TrackingPixel = ({
14
+ children,
15
+ onImpression,
16
+ triggerOnce = false,
17
+ threshold,
18
+ className,
19
+ }: Props) => {
20
+ const onChange = useCallback(
21
+ (inView: boolean) => {
22
+ if (inView) {
23
+ onImpression?.()
24
+ }
25
+ },
26
+ [onImpression]
27
+ )
28
+
29
+ return (
30
+ <InView
31
+ as="div"
32
+ onChange={onChange}
33
+ triggerOnce={triggerOnce}
34
+ className={className}
35
+ threshold={threshold}
36
+ >
37
+ {children}
38
+ </InView>
39
+ )
40
+ }
@@ -15,11 +15,13 @@ export * from './atoms/icon-button'
15
15
  export * from './atoms/thumbhash-image'
16
16
  export * from './atoms/touchable'
17
17
  export * from './atoms/alert-dialog'
18
+ export * from './atoms/list'
18
19
 
19
20
  export * from './ui/accordion'
20
21
  export * from './ui/alert'
21
22
  export * from './ui/alert-dialog'
22
23
  export * from './ui/avatar'
24
+ export * from './ui/badge'
23
25
  export * from './ui/card'
24
26
  export * from './ui/carousel'
25
27
  export * from './ui/checkbox'
@@ -3,5 +3,5 @@ import {useCloseMini, Button} from '@shopify/shop-minis-react'
3
3
  export function Example() {
4
4
  const {closeMini} = useCloseMini()
5
5
 
6
- return <Button onPress={closeMini} text="Close Mini" />
6
+ return <Button onClick={closeMini}>Close Mini</Button>
7
7
  }
@@ -7,23 +7,26 @@ export default function MyComponent() {
7
7
  return (
8
8
  <>
9
9
  <Button
10
- onPress={() =>
10
+ onClick={() =>
11
11
  navigateToProduct({productId: 'gid://shopify/Product/123'})
12
12
  }
13
- text="View Product"
14
- />
13
+ >
14
+ View Product
15
+ </Button>
15
16
  <Button
16
- onPress={() =>
17
+ onClick={() =>
17
18
  navigateToShop({
18
19
  shopId: 'gid://shopify/Shop/123',
19
20
  })
20
21
  }
21
- text="Go to Shop"
22
- />
22
+ >
23
+ Go to Shop
24
+ </Button>
23
25
  <Button
24
- onPress={() => navigateToOrder({orderId: 'gid://shopify/Order/123'})}
25
- text="View Order"
26
- />
26
+ onClick={() => navigateToOrder({orderId: 'gid://shopify/Order/123'})}
27
+ >
28
+ View Order
29
+ </Button>
27
30
  </>
28
31
  )
29
32
  }
@@ -11,25 +11,26 @@ export default function MyComponent() {
11
11
 
12
12
  return (
13
13
  <>
14
+ <Button onClick={() => addProductList({name: 'My product list'})}>
15
+ Add product list
16
+ </Button>
14
17
  <Button
15
- onPress={() => addProductList({name: 'My product list'})}
16
- text="Add product list"
17
- />
18
+ onClick={() => removeProductList({id: 'gid://shopapp/ProductList/123'})}
19
+ >
20
+ Remove product list
21
+ </Button>
18
22
  <Button
19
- onPress={() => removeProductList({id: 'gid://shopapp/ProductList/123'})}
20
- text="Remove product list"
21
- />
22
- <Button
23
- onPress={() =>
23
+ onClick={() =>
24
24
  renameProductList({
25
25
  id: 'gid://shopapp/ProductList/123',
26
26
  name: 'My renamed product list',
27
27
  })
28
28
  }
29
- text="Rename product list"
30
- />
29
+ >
30
+ Rename product list
31
+ </Button>
31
32
  <Button
32
- onPress={() =>
33
+ onClick={() =>
33
34
  addProductListItem({
34
35
  shopId: 'gid://shopify/Shop/42',
35
36
  productId: 'gid://shopify/Product/123',
@@ -38,10 +39,11 @@ export default function MyComponent() {
38
39
  publicListId: 'abc123',
39
40
  })
40
41
  }
41
- text="Add product to list"
42
- />
42
+ >
43
+ Add product to list
44
+ </Button>
43
45
  <Button
44
- onPress={() =>
46
+ onClick={() =>
45
47
  removeProductListItem({
46
48
  shopId: 'gid://shopify/Shop/42',
47
49
  productId: 'gid://shopify/Product/123',
@@ -50,8 +52,9 @@ export default function MyComponent() {
50
52
  publicListId: 'abc123',
51
53
  })
52
54
  }
53
- text="Remove product from list"
54
- />
55
+ >
56
+ Remove product from list
57
+ </Button>
55
58
  </>
56
59
  )
57
60
  }
@@ -21,8 +21,8 @@ export default function MyComponent() {
21
21
 
22
22
  return (
23
23
  <>
24
- <Button text="Add to cart" onPress={handleAddToCart} />
25
- <Button text="Buy now" onPress={handleBuyNow} />
24
+ <Button onClick={handleAddToCart}>Add to cart</Button>
25
+ <Button onClick={handleBuyNow}>Buy now</Button>
26
26
  </>
27
27
  )
28
28
  }
@@ -16,5 +16,5 @@ export default function MyComponent() {
16
16
  console.log('Uploaded image:', result[0])
17
17
  }, [uploadImage])
18
18
 
19
- return <Button onPress={handleUpload} text="Upload image" />
19
+ return <Button onClick={handleUpload}>Upload image</Button>
20
20
  }
@@ -1,7 +1,8 @@
1
1
  import {useCallback} from 'react'
2
2
 
3
3
  import {useShopActions} from '../../internal/useShopActions'
4
- import {UploadTarget} from '../../types'
4
+
5
+ import type {UploadTarget} from '@shopify/shop-minis-platform/actions'
5
6
 
6
7
  export interface UploadImageParams {
7
8
  /**
@@ -45,7 +46,7 @@ const uploadFileToGCS = async (
45
46
  target: UploadTarget
46
47
  ) => {
47
48
  const formData = new FormData()
48
- target.parameters.forEach(({name, value}) => {
49
+ target.parameters.forEach(({name, value}: {name: string; value: string}) => {
49
50
  formData.append(name, value)
50
51
  })
51
52
  // Append the actual file data last
@@ -5,14 +5,12 @@ export default function MyComponent() {
5
5
 
6
6
  return (
7
7
  <>
8
- <Button
9
- onPress={() => followShop({shopId: 'gid://shopify/Shop/123'})}
10
- text="Follow shop"
11
- />
12
- <Button
13
- onPress={() => unfollowShop({shopId: 'gid://shopify/Shop/123'})}
14
- text="Unfollow shop"
15
- />
8
+ <Button onClick={() => followShop({shopId: 'gid://shopify/Shop/123'})}>
9
+ Follow shop
10
+ </Button>
11
+ <Button onClick={() => unfollowShop({shopId: 'gid://shopify/Shop/123'})}>
12
+ Unfollow shop
13
+ </Button>
16
14
  </>
17
15
  )
18
16
  }
@@ -6,25 +6,27 @@ export default function MyComponent() {
6
6
  return (
7
7
  <>
8
8
  <Button
9
- onPress={() =>
9
+ onClick={() =>
10
10
  saveProduct({
11
11
  productId: 'gid://shopify/Product/123',
12
12
  productVariantId: 'gid://shopify/ProductVariant/456',
13
13
  shopId: 'gid://shopify/Shop/42',
14
14
  })
15
15
  }
16
- text="Save product"
17
- />
16
+ >
17
+ Save product
18
+ </Button>
18
19
  <Button
19
- onPress={() =>
20
+ onClick={() =>
20
21
  unsaveProduct({
21
22
  productId: 'gid://shopify/Product/123',
22
23
  productVariantId: 'gid://shopify/ProductVariant/456',
23
24
  shopId: 'gid://shopify/Shop/42',
24
25
  })
25
26
  }
26
- text="Unsave product"
27
- />
27
+ >
28
+ Unsave product
29
+ </Button>
28
30
  </>
29
31
  )
30
32
  }
@@ -8,9 +8,8 @@ export default function MyComponent() {
8
8
  const handleError = useCallback(() => {
9
9
  showErrorScreen({
10
10
  message: 'Something went wrong',
11
- title: 'Error',
12
11
  })
13
12
  }, [showErrorScreen])
14
13
 
15
- return <Button onPress={handleError} text="Show error screen" />
14
+ return <Button onClick={handleError}>Show error screen</Button>
16
15
  }
@@ -1,5 +1,6 @@
1
+ import {ShopActions} from '@shopify/shop-minis-platform/actions'
2
+
1
3
  import {useShopActions} from '../../internal/useShopActions'
2
- import {ShopActions} from '../../types'
3
4
 
4
5
  interface UseErrorScreenReturns {
5
6
  /**
@@ -11,5 +11,5 @@ export default function MyComponent() {
11
11
  })
12
12
  }, [showErrorToast])
13
13
 
14
- return <Button onPress={handleError} text="Show error toast" />
14
+ return <Button onClick={handleError}>Show error toast</Button>
15
15
  }
@@ -1,5 +1,6 @@
1
+ import {ShopActions} from '@shopify/shop-minis-platform/actions'
2
+
1
3
  import {useShopActions} from '../../internal/useShopActions'
2
- import {ShopActions} from '../../types'
3
4
 
4
5
  interface UseErrorToastReturns {
5
6
  /**
@@ -1,9 +1,7 @@
1
1
  import React, {useState} from 'react'
2
2
 
3
- import {Camera, Image} from 'lucide-react'
4
-
3
+ import {Button} from '../../components/atoms/button'
5
4
  import {Alert, AlertDescription, AlertTitle} from '../../components/ui/alert'
6
- import {Button} from '../../components/ui/button'
7
5
  import {
8
6
  Card,
9
7
  CardContent,
@@ -16,14 +14,12 @@ import {useImagePicker} from './useImagePicker'
16
14
  export const UseImagePickerExample = () => {
17
15
  const [selectedImage, setSelectedImage] = useState<string | null>(null)
18
16
  const [error, setError] = useState<string | null>(null)
19
- const {openCamera, openGallery, ImagePickerInputs} = useImagePicker({
20
- cameraFacing: 'user',
21
- })
17
+ const {openCamera, openGallery} = useImagePicker()
22
18
 
23
19
  const handleCameraCapture = async () => {
24
20
  try {
25
21
  setError(null)
26
- const file = await openCamera()
22
+ const file = await openCamera('front')
27
23
  const url = URL.createObjectURL(file)
28
24
  setSelectedImage(url)
29
25
  } catch (err) {
@@ -48,16 +44,12 @@ export const UseImagePickerExample = () => {
48
44
  <CardTitle>Image Picker Example</CardTitle>
49
45
  </CardHeader>
50
46
  <CardContent className="space-y-4">
51
- <ImagePickerInputs />
52
-
53
47
  <div className="flex gap-2">
54
- <Button onClick={handleCameraCapture} variant="primary">
55
- <Camera className="mr-2 h-4 w-4" />
48
+ <Button onClick={handleCameraCapture} variant="default">
56
49
  Open Camera
57
50
  </Button>
58
51
 
59
52
  <Button onClick={handleGallerySelect} variant="secondary">
60
- <Image className="mr-2 h-4 w-4" />
61
53
  Open Gallery
62
54
  </Button>
63
55
  </div>
package/src/index.css CHANGED
@@ -4,6 +4,7 @@
4
4
  @import './styles/theme.css';
5
5
  @import './styles/globals.css';
6
6
  @import './styles/animations.css';
7
+ @import './styles/utilities.css';
7
8
 
8
9
  /* When consumed as npm package, this path resolves from the consuming app's location */
9
10
  @source '../node_modules/@shopify/shop-minis-react/src';
@@ -1,4 +1,4 @@
1
- import {ShopActions} from '../types'
1
+ import {ShopActions} from '@shopify/shop-minis-platform/actions'
2
2
 
3
3
  export function useShopActions(): ShopActions {
4
4
  return window.minisSDK
@@ -41,13 +41,12 @@ export const useShopActionsDataFetching = <
41
41
  validator?.(dataToValidate)
42
42
  return null
43
43
  } catch (err) {
44
- return (
45
- err ??
46
- new MiniError({
47
- hook,
48
- message: 'Validation failed',
49
- })
50
- )
44
+ if (err instanceof Error) return err
45
+
46
+ return new MiniError({
47
+ hook,
48
+ message: 'Validation failed',
49
+ })
51
50
  }
52
51
  },
53
52
  [validator, hook]
@@ -1,11 +1,8 @@
1
1
  import {useCallback, useEffect, useMemo, useState} from 'react'
2
2
 
3
- import {
4
- DataHookFetchPolicy,
5
- PaginatedDataHookReturnsBase,
6
- PaginationInfo,
7
- ShopAction,
8
- } from '../types'
3
+ import {ShopAction, PaginationInfo} from '@shopify/shop-minis-platform/actions'
4
+
5
+ import {DataHookFetchPolicy, PaginatedDataHookReturnsBase} from '../types'
9
6
  import {formatError, MiniError} from '../utils/errors'
10
7
 
11
8
  export interface ShopActionsDataFetchingResult<S>
package/src/mocks.ts CHANGED
@@ -288,15 +288,27 @@ function makeMockActions(): ShopActions {
288
288
  return mock as ShopActions
289
289
  }
290
290
 
291
+ // Detect if running on a mobile device
292
+ const isMobile = (): boolean => {
293
+ const userAgent = navigator.userAgent.toLowerCase()
294
+ const isIOS = /iphone|ipad|ipod/.test(userAgent)
295
+ const isAndroid = /android/.test(userAgent)
296
+
297
+ return isIOS || isAndroid
298
+ }
299
+
291
300
  export const injectMocks = () => {
292
- window.minisSDK = makeMockActions()
293
- window.minisParams = {
294
- handle: 'mock-handle',
295
- initialUrl: '/mock-initial-url',
296
- platform: 'ios',
301
+ // Only inject mocks if we aren't on a mobile device
302
+ if (isMobile()) {
303
+ return
297
304
  }
298
- }
299
305
 
300
- if (!window.minisSDK) {
301
- injectMocks()
306
+ if (!window.minisSDK) {
307
+ window.minisSDK = makeMockActions()
308
+ window.minisParams = {
309
+ handle: 'mock-handle',
310
+ initialUrl: '/mock-initial-url',
311
+ platform: 'web',
312
+ }
313
+ }
302
314
  }