@shopify/shop-minis-react 0.1.7 → 0.2.0

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.
@@ -0,0 +1,130 @@
1
+ {
2
+ "useAsyncStorage": [
3
+ "GET_PERSISTED_ITEM",
4
+ "SET_PERSISTED_ITEM",
5
+ "REMOVE_PERSISTED_ITEM",
6
+ "GET_ALL_PERSISTED_KEYS",
7
+ "CLEAR_PERSISTED_ITEMS"
8
+ ],
9
+ "useBuyerAttributes": [
10
+ "GET_BUYER_ATTRIBUTES"
11
+ ],
12
+ "useCloseMini": [
13
+ "CLOSE_MINI"
14
+ ],
15
+ "useContent": [
16
+ "GET_CONTENT"
17
+ ],
18
+ "useCreateImageContent": [
19
+ "CREATE_CONTENT"
20
+ ],
21
+ "useCuratedProducts": [
22
+ "GET_CURATED_PRODUCTS"
23
+ ],
24
+ "useCurrentUser": [
25
+ "GET_CURRENT_USER"
26
+ ],
27
+ "useErrorScreen": [
28
+ "SHOW_ERROR_SCREEN"
29
+ ],
30
+ "useErrorToast": [
31
+ "SHOW_ERROR_TOAST"
32
+ ],
33
+ "useFollowedShops": [
34
+ "GET_FOLLOWED_SHOPS"
35
+ ],
36
+ "useFollowedShopsActions": [
37
+ "FOLLOW_SHOP",
38
+ "UNFOLLOW_SHOP"
39
+ ],
40
+ "useGenerateUserToken": [
41
+ "GENERATE_USER_TOKEN"
42
+ ],
43
+ "useImageUpload": [
44
+ "CREATE_IMAGE_UPLOAD_LINK",
45
+ "COMPLETE_IMAGE_UPLOAD"
46
+ ],
47
+ "useKeyboardAvoidingView": [
48
+ "TRANSLATE_CONTENT_UP",
49
+ "TRANSLATE_CONTENT_DOWN"
50
+ ],
51
+ "useOrders": [
52
+ "GET_ORDERS"
53
+ ],
54
+ "usePopularProducts": [
55
+ "GET_POPULAR_PRODUCTS"
56
+ ],
57
+ "useProduct": [
58
+ "GET_PRODUCT"
59
+ ],
60
+ "useProductList": [
61
+ "GET_PRODUCT_LIST"
62
+ ],
63
+ "useProductListActions": [
64
+ "ADD_PRODUCT_LIST",
65
+ "REMOVE_PRODUCT_LIST",
66
+ "RENAME_PRODUCT_LIST",
67
+ "ADD_PRODUCT_LIST_ITEM",
68
+ "REMOVE_PRODUCT_LIST_ITEM"
69
+ ],
70
+ "useProductLists": [
71
+ "GET_PRODUCT_LISTS"
72
+ ],
73
+ "useProductMedia": [
74
+ "GET_PRODUCT_MEDIA"
75
+ ],
76
+ "useProductSearch": [
77
+ "GET_PRODUCT_SEARCH"
78
+ ],
79
+ "useProductVariants": [
80
+ "GET_PRODUCT_VARIANTS"
81
+ ],
82
+ "useProducts": [
83
+ "GET_PRODUCTS"
84
+ ],
85
+ "useRecentProducts": [
86
+ "GET_RECENT_PRODUCTS"
87
+ ],
88
+ "useRecentShops": [
89
+ "GET_RECENT_SHOPS"
90
+ ],
91
+ "useRecommendedProducts": [
92
+ "GET_RECOMMENDED_PRODUCTS"
93
+ ],
94
+ "useRecommendedShops": [
95
+ "GET_RECOMMENDED_SHOPS"
96
+ ],
97
+ "useRequestPermissions": [
98
+ "REQUEST_PERMISSION"
99
+ ],
100
+ "useSavedProducts": [
101
+ "GET_SAVED_PRODUCTS"
102
+ ],
103
+ "useSavedProductsActions": [
104
+ "FAVORITE",
105
+ "UNFAVORITE"
106
+ ],
107
+ "useSecureStorage": [
108
+ "GET_SECRET",
109
+ "SET_SECRET",
110
+ "REMOVE_SECRET"
111
+ ],
112
+ "useShare": [
113
+ "SHARE",
114
+ "SHARE_SINGLE"
115
+ ],
116
+ "useShop": [
117
+ "GET_SHOP"
118
+ ],
119
+ "useShopCartActions": [
120
+ "ADD_TO_CART",
121
+ "BUY_PRODUCT"
122
+ ],
123
+ "useShopNavigation": [
124
+ "NAVIGATE_TO_PRODUCT",
125
+ "NAVIGATE_TO_SHOP",
126
+ "NAVIGATE_TO_ORDER",
127
+ "NAVIGATE_TO_CHECKOUT",
128
+ "NAVIGATE_TO_CART"
129
+ ]
130
+ }
@@ -0,0 +1,48 @@
1
+ {
2
+ "useBuyerAttributes": [
3
+ "profile"
4
+ ],
5
+ "useCurrentUser": [
6
+ "user_settings:read"
7
+ ],
8
+ "useFollowedShops": [
9
+ "shops:follows:read"
10
+ ],
11
+ "useFollowedShopsActions": [
12
+ "shops:follows:write"
13
+ ],
14
+ "useGenerateUserToken": [
15
+ "openid"
16
+ ],
17
+ "useOrders": [
18
+ "orders"
19
+ ],
20
+ "useProductList": [
21
+ "product_list:read"
22
+ ],
23
+ "useProductListActions": [
24
+ "product_list:write",
25
+ "product_list_item:write"
26
+ ],
27
+ "useProductLists": [
28
+ "product_list:read"
29
+ ],
30
+ "useRecentProducts": [
31
+ "products:recent:read"
32
+ ],
33
+ "useRecentShops": [
34
+ "shops:recent:read"
35
+ ],
36
+ "useRecommendedProducts": [
37
+ "products:recommendations:read"
38
+ ],
39
+ "useRecommendedShops": [
40
+ "shops:recommendations:read"
41
+ ],
42
+ "useSavedProducts": [
43
+ "product_list:read"
44
+ ],
45
+ "useSavedProductsActions": [
46
+ "product_list:write"
47
+ ]
48
+ }
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.1.7",
4
+ "version": "0.2.0",
5
5
  "sideEffects": false,
6
6
  "type": "module",
7
7
  "engines": {
@@ -18,6 +18,9 @@
18
18
  "files": [
19
19
  "src/**/*.{ts,tsx,css}",
20
20
  "dist/**/*",
21
+ "eslint/**/*.cjs",
22
+ "eslint/**/*.md",
23
+ "generated-hook-maps/**/*.json",
21
24
  "README.md",
22
25
  "LICENSE.txt"
23
26
  ],
@@ -29,7 +32,9 @@
29
32
  },
30
33
  "./styles": "./src/index.css",
31
34
  "./mocks": "./src/mocks.ts",
32
- "./src/*": "./src/*"
35
+ "./src/*": "./src/*",
36
+ "./eslint": "./eslint/index.cjs",
37
+ "./eslint/config": "./eslint/config.cjs"
33
38
  },
34
39
  "peerDependencies": {
35
40
  "react": ">=18.2.0",
@@ -38,7 +43,7 @@
38
43
  "typescript": ">=5.0.0"
39
44
  },
40
45
  "dependencies": {
41
- "@shopify/shop-minis-platform": "0.5.0",
46
+ "@shopify/shop-minis-platform": "0.6.0",
42
47
  "@tailwindcss/vite": "4.1.8",
43
48
  "@types/color": "3.0.6",
44
49
  "@types/lodash": "4.17.20",
@@ -56,6 +61,8 @@
56
61
  "motion": "12.17.3",
57
62
  "next-themes": "0.4.6",
58
63
  "radix-ui": "1.4.2",
64
+ "eslint": "^8.57.0",
65
+ "@typescript-eslint/parser": "^7.0.0",
59
66
  "react-intersection-observer": "9.13.1",
60
67
  "react-resizable-panels": "3.0.2",
61
68
  "react-router": "7.7.0",
@@ -83,7 +90,6 @@
83
90
  "@types/react-dom": "^19.1.2",
84
91
  "@vitest/coverage-v8": "^2.1.8",
85
92
  "@vitest/ui": "^2.1.8",
86
- "eslint": "^8.57.0",
87
93
  "eslint-plugin-storybook": "^9.0.16",
88
94
  "jsdom": "^25.0.1",
89
95
  "react": "^19.1.0",
@@ -76,12 +76,13 @@ describe('Image', () => {
76
76
  expect(wrapper.style.aspectRatio).toBe('16/9')
77
77
  })
78
78
 
79
- it('uses thumbhash as background when provided', () => {
79
+ it('uses thumbhash as background when provided with fixed aspect ratio', () => {
80
80
  const {container} = render(
81
81
  <Image
82
82
  src="https://example.com/image.jpg"
83
83
  alt="Test image"
84
84
  thumbhash="testThumbhash"
85
+ aspectRatio="1"
85
86
  />
86
87
  )
87
88
 
@@ -91,6 +92,45 @@ describe('Image', () => {
91
92
  )
92
93
  })
93
94
 
95
+ it('renders with natural sizing when aspectRatio is auto', () => {
96
+ const {container} = render(
97
+ <Image
98
+ src="https://example.com/image.jpg"
99
+ alt="Test image"
100
+ aspectRatio="auto"
101
+ className="custom-class"
102
+ />
103
+ )
104
+
105
+ const wrapper = container.firstChild as HTMLElement
106
+ const img = screen.getByRole('img')
107
+
108
+ expect(wrapper.tagName).toBe('DIV')
109
+ expect(wrapper).toHaveClass('custom-class')
110
+ expect(wrapper.style.aspectRatio).toBe('')
111
+ expect(img).toHaveClass('w-full', 'h-auto')
112
+ expect(img).toHaveAttribute('src', 'https://example.com/image.jpg')
113
+ })
114
+
115
+ it('preserves thumbhash with natural sizing', () => {
116
+ const {container} = render(
117
+ <Image
118
+ src="https://example.com/image.jpg"
119
+ alt="Test image"
120
+ aspectRatio="auto"
121
+ thumbhash="testThumbhash"
122
+ />
123
+ )
124
+
125
+ const wrapper = container.firstChild as HTMLElement
126
+ const img = screen.getByRole('img')
127
+
128
+ expect(wrapper.style.backgroundImage).toContain(
129
+ 'data:image/png;base64,testThumbhash'
130
+ )
131
+ expect(img).toHaveClass('w-full', 'h-auto')
132
+ })
133
+
94
134
  it('passes additional props to img element', () => {
95
135
  render(
96
136
  <Image
@@ -17,6 +17,7 @@ type ImageProps = ImgHTMLAttributes<HTMLImageElement> & {
17
17
  file?: File
18
18
  thumbhash?: string | null
19
19
  aspectRatio?: number | string
20
+ objectFit?: 'cover' | 'contain' | 'fill' | 'scale-down' | 'none'
20
21
  }
21
22
 
22
23
  export const Image = memo(function Image(props: ImageProps) {
@@ -28,6 +29,7 @@ export const Image = memo(function Image(props: ImageProps) {
28
29
  className,
29
30
  style,
30
31
  aspectRatio = 'auto',
32
+ objectFit = 'contain',
31
33
  ...restProps
32
34
  } = props
33
35
 
@@ -71,10 +73,10 @@ export const Image = memo(function Image(props: ImageProps) {
71
73
 
72
74
  return (
73
75
  <div
74
- className={cn('relative w-full ', className)}
76
+ className={cn('relative w-full', className)}
75
77
  style={{
76
78
  ...style,
77
- aspectRatio,
79
+ ...(aspectRatio !== 'auto' && {aspectRatio}),
78
80
  backgroundImage: thumbhashDataURL
79
81
  ? `url(${thumbhashDataURL})`
80
82
  : undefined,
@@ -84,7 +86,10 @@ export const Image = memo(function Image(props: ImageProps) {
84
86
  >
85
87
  <img
86
88
  className={cn(
87
- 'absolute inset-0 opacity-0 size-full object-cover',
89
+ aspectRatio === 'auto'
90
+ ? 'opacity-0 w-full h-auto'
91
+ : 'absolute inset-0 opacity-0 size-full',
92
+ `object-${objectFit}`,
88
93
  isLoaded && 'opacity-100'
89
94
  )}
90
95
  src={imageSrc}