@shopify/shop-minis-react 0.0.33 → 0.0.35

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 (86) hide show
  1. package/dist/_virtual/index10.js +2 -2
  2. package/dist/_virtual/index2.js +4 -4
  3. package/dist/_virtual/index3.js +4 -4
  4. package/dist/_virtual/index8.js +2 -2
  5. package/dist/_virtual/index9.js +2 -2
  6. package/dist/components/atoms/alert-dialog.js.map +1 -1
  7. package/dist/components/atoms/icon-button.js +12 -12
  8. package/dist/components/atoms/icon-button.js.map +1 -1
  9. package/dist/components/atoms/image.js +52 -0
  10. package/dist/components/atoms/image.js.map +1 -0
  11. package/dist/components/atoms/text-input.js +22 -0
  12. package/dist/components/atoms/text-input.js.map +1 -0
  13. package/dist/components/commerce/merchant-card.js +2 -1
  14. package/dist/components/commerce/merchant-card.js.map +1 -1
  15. package/dist/components/commerce/product-card.js +11 -11
  16. package/dist/components/commerce/product-card.js.map +1 -1
  17. package/dist/components/content/image-content-wrapper.js +29 -22
  18. package/dist/components/content/image-content-wrapper.js.map +1 -1
  19. package/dist/components/ui/input.js +15 -9
  20. package/dist/components/ui/input.js.map +1 -1
  21. package/dist/hooks/content/useCreateImageContent.js +16 -22
  22. package/dist/hooks/content/useCreateImageContent.js.map +1 -1
  23. package/dist/hooks/storage/useImageUpload.js +36 -37
  24. package/dist/hooks/storage/useImageUpload.js.map +1 -1
  25. package/dist/hooks/util/useKeyboardAvoidingView.js +23 -0
  26. package/dist/hooks/util/useKeyboardAvoidingView.js.map +1 -0
  27. package/dist/index.js +218 -212
  28. package/dist/index.js.map +1 -1
  29. package/dist/mocks.js +4 -1
  30. package/dist/mocks.js.map +1 -1
  31. package/dist/shop-minis-platform/src/types/content.js.map +1 -1
  32. package/dist/shop-minis-react/node_modules/.pnpm/@xmldom_xmldom@0.8.10/node_modules/@xmldom/xmldom/lib/index.js +1 -1
  33. package/dist/shop-minis-react/node_modules/.pnpm/color-string@1.9.1/node_modules/color-string/index.js +1 -1
  34. package/dist/shop-minis-react/node_modules/.pnpm/use-sync-external-store@1.5.0_react@19.1.0/node_modules/use-sync-external-store/shim/index.js +1 -1
  35. package/dist/shop-minis-react/node_modules/.pnpm/video.js@8.23.3/node_modules/video.js/dist/video.es.js +1 -1
  36. package/dist/utils/colors.js +1 -1
  37. package/dist/utils/image.js +46 -9
  38. package/dist/utils/image.js.map +1 -1
  39. package/package.json +21 -4
  40. package/src/components/atoms/alert-dialog.test.tsx +67 -0
  41. package/src/components/atoms/alert-dialog.tsx +13 -11
  42. package/src/components/atoms/favorite-button.test.tsx +56 -0
  43. package/src/components/atoms/icon-button.tsx +1 -1
  44. package/src/components/atoms/image.test.tsx +108 -0
  45. package/src/components/atoms/{thumbhash-image.tsx → image.tsx} +14 -14
  46. package/src/components/atoms/product-variant-price.test.tsx +128 -0
  47. package/src/components/atoms/text-input.test.tsx +104 -0
  48. package/src/components/atoms/text-input.tsx +31 -0
  49. package/src/components/commerce/merchant-card.test.tsx +261 -0
  50. package/src/components/commerce/merchant-card.tsx +4 -2
  51. package/src/components/commerce/product-card.test.tsx +364 -0
  52. package/src/components/commerce/product-card.tsx +2 -2
  53. package/src/components/commerce/product-link.test.tsx +483 -0
  54. package/src/components/commerce/quantity-selector.test.tsx +382 -0
  55. package/src/components/commerce/search.test.tsx +487 -0
  56. package/src/components/content/image-content-wrapper.test.tsx +92 -0
  57. package/src/components/content/image-content-wrapper.tsx +9 -2
  58. package/src/components/index.ts +2 -1
  59. package/src/components/navigation/transition-link.test.tsx +155 -0
  60. package/src/components/ui/input.test.tsx +21 -0
  61. package/src/components/ui/input.tsx +10 -1
  62. package/src/hooks/content/useCreateImageContent.test.ts +352 -0
  63. package/src/hooks/content/useCreateImageContent.ts +1 -7
  64. package/src/hooks/index.ts +1 -0
  65. package/src/hooks/navigation/useNavigateWithTransition.test.ts +371 -0
  66. package/src/hooks/navigation/useViewTransitions.test.ts +469 -0
  67. package/src/hooks/product/useProductSearch.test.ts +470 -0
  68. package/src/hooks/storage/useAsyncStorage.test.ts +225 -0
  69. package/src/hooks/storage/useImageUpload.test.ts +322 -0
  70. package/src/hooks/storage/useImageUpload.ts +22 -20
  71. package/src/hooks/util/useKeyboardAvoidingView.ts +37 -0
  72. package/src/internal/useHandleAction.test.ts +265 -0
  73. package/src/internal/useShopActionsDataFetching.test.ts +465 -0
  74. package/src/mocks.ts +3 -1
  75. package/src/providers/ImagePickerProvider.test.tsx +467 -0
  76. package/src/stories/ProductCard.stories.tsx +2 -2
  77. package/src/stories/TextInput.stories.tsx +26 -0
  78. package/src/test-setup.ts +34 -0
  79. package/src/test-utils.tsx +167 -0
  80. package/src/utils/image.ts +73 -0
  81. package/src/utils/index.ts +1 -1
  82. package/dist/components/atoms/thumbhash-image.js +0 -54
  83. package/dist/components/atoms/thumbhash-image.js.map +0 -1
  84. package/dist/utils/imageToDataUri.js +0 -10
  85. package/dist/utils/imageToDataUri.js.map +0 -1
  86. package/src/utils/imageToDataUri.ts +0 -8
@@ -14,5 +14,78 @@ export function getThumbhashDataURL(thumbhash?: string): string | undefined {
14
14
  return thumbHashToDataURL(thumbhashArray)
15
15
  } catch (error) {
16
16
  console.warn('Failed to decode thumbhash to data URL', error)
17
+ return undefined
17
18
  }
18
19
  }
20
+
21
+ /** Converts a file to a data URI
22
+ * @param file The file to convert
23
+ * @returns A promise that resolves to the data URI string
24
+ */
25
+ export function fileToDataUri(file: File): Promise<string> {
26
+ return new Promise((resolve, reject) => {
27
+ const reader = new FileReader()
28
+ reader.onloadend = () => resolve(reader.result as string)
29
+ reader.onerror = reject
30
+ reader.readAsDataURL(file)
31
+ })
32
+ }
33
+
34
+ const ImageSizes = {
35
+ xxsUrl: 32,
36
+ xsUrl: 64,
37
+ sUrl: 128,
38
+ xxsmUrl: 256,
39
+ xsmUrl: 384,
40
+ smUrl: 512,
41
+ mUrl: 640,
42
+ lUrl: 1080,
43
+ xlUrl: 2048,
44
+ } as const
45
+
46
+ type Key = keyof typeof ImageSizes
47
+
48
+ /**
49
+ * Acceptable offset for image sizes. An image could use the size that is within this offset.
50
+ */
51
+ const offsetPercentage = 0.05
52
+
53
+ const sortedImageSizes = Object.entries(ImageSizes).sort(
54
+ ([, firstSize], [, secondSize]) => firstSize - secondSize
55
+ )
56
+
57
+ const getImageSizeKeyWithSize = (size: number): Key => {
58
+ for (const [key, imgSize] of sortedImageSizes) {
59
+ const upperBoundSize = imgSize + imgSize * offsetPercentage
60
+ if (size <= upperBoundSize) return key as Key
61
+ }
62
+
63
+ return 'xlUrl'
64
+ }
65
+
66
+ const resizeImage = (imageUrl: string, width: number) => {
67
+ const pattern = new RegExp(/\?+/g)
68
+ const delimiter = pattern.test(imageUrl) ? '&' : '?'
69
+ return `${imageUrl}${delimiter}width=${width}`
70
+ }
71
+
72
+ /**
73
+ * Optimizes Shopify CDN image URLs by adding a width parameter based on screen size
74
+ * @param url The image URL to optimize
75
+ * @returns The optimized URL with width parameter if it's a Shopify CDN image, otherwise returns the original URL
76
+ */
77
+
78
+ export const getResizedImageUrl = (url?: string): string => {
79
+ if (!url) return ''
80
+
81
+ // Only process Shopify CDN images
82
+ if (!url.startsWith('https://cdn.shopify.com')) {
83
+ return url
84
+ }
85
+
86
+ const width = window.innerWidth ?? screen.width
87
+
88
+ const key = getImageSizeKeyWithSize(width)
89
+
90
+ return resizeImage(url, ImageSizes[key])
91
+ }
@@ -1,4 +1,4 @@
1
1
  export * from './errors'
2
2
  export * from './merchant-card'
3
3
  export * from './parseUrl'
4
- export * from './imageToDataUri'
4
+ export * from './image'
@@ -1,54 +0,0 @@
1
- import { jsx as t } from "react/jsx-runtime";
2
- import { memo as p, useState as g, useMemo as L, useCallback as v } from "react";
3
- import { cn as s } from "../../lib/utils.js";
4
- import { getThumbhashDataURL as k } from "../../utils/image.js";
5
- const j = p(function(r) {
6
- const {
7
- src: c,
8
- alt: m,
9
- thumbhash: o,
10
- onLoad: a,
11
- className: l,
12
- style: i,
13
- aspectRatio: n = "auto",
14
- ...u
15
- } = r, [d, h] = g(!1), e = L(
16
- () => k(o ?? void 0),
17
- [o]
18
- ), b = v(
19
- (f) => {
20
- h(!0), a?.(f);
21
- },
22
- [a]
23
- );
24
- return /* @__PURE__ */ t(
25
- "div",
26
- {
27
- className: s("relative w-full ", l),
28
- style: {
29
- ...i,
30
- aspectRatio: n,
31
- backgroundImage: e ? `url(${e})` : void 0,
32
- backgroundSize: "cover",
33
- backgroundPosition: "center"
34
- },
35
- children: /* @__PURE__ */ t(
36
- "img",
37
- {
38
- className: s(
39
- "absolute inset-0 w-full h-full opacity-0 object-cover",
40
- d && "opacity-100"
41
- ),
42
- src: c,
43
- alt: m,
44
- onLoad: b,
45
- ...u
46
- }
47
- )
48
- }
49
- );
50
- });
51
- export {
52
- j as ThumbhashImage
53
- };
54
- //# sourceMappingURL=thumbhash-image.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"thumbhash-image.js","sources":["../../../src/components/atoms/thumbhash-image.tsx"],"sourcesContent":["/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */\nimport {ImgHTMLAttributes, useCallback, useMemo, memo, useState} from 'react'\n\nimport {cn} from '../../lib/utils'\nimport {getThumbhashDataURL} from '../../utils/image'\n\ntype ThumbhashImageProps = ImgHTMLAttributes<HTMLImageElement> & {\n src: string\n thumbhash: string\n alt?: string | null\n aspectRatio?: number | string\n}\n\nexport const ThumbhashImage = memo(function ThumbhashImage(\n props: ThumbhashImageProps\n) {\n const {\n src,\n alt,\n thumbhash,\n onLoad,\n className,\n style,\n aspectRatio = 'auto',\n ...restProps\n } = props\n\n const [isLoaded, setIsLoaded] = useState(false)\n\n const dataURL = useMemo(\n () => getThumbhashDataURL(thumbhash ?? undefined),\n [thumbhash]\n )\n\n const handleLoad = useCallback(\n (event: React.SyntheticEvent<HTMLImageElement, Event>) => {\n setIsLoaded(true)\n onLoad?.(event)\n },\n [onLoad]\n )\n\n return (\n <div\n className={cn('relative w-full ', className)}\n style={{\n ...style,\n aspectRatio,\n backgroundImage: dataURL ? `url(${dataURL})` : undefined,\n backgroundSize: 'cover',\n backgroundPosition: 'center',\n }}\n >\n <img\n className={cn(\n 'absolute inset-0 w-full h-full opacity-0 object-cover',\n isLoaded && 'opacity-100'\n )}\n src={src}\n alt={alt}\n onLoad={handleLoad}\n {...restProps}\n />\n </div>\n )\n})\n"],"names":["ThumbhashImage","memo","props","src","alt","thumbhash","onLoad","className","style","aspectRatio","restProps","isLoaded","setIsLoaded","useState","dataURL","useMemo","getThumbhashDataURL","handleLoad","useCallback","event","jsx","cn"],"mappings":";;;;AAaO,MAAMA,IAAiBC,EAAK,SACjCC,GACA;AACM,QAAA;AAAA,IACJ,KAAAC;AAAA,IACA,KAAAC;AAAA,IACA,WAAAC;AAAA,IACA,QAAAC;AAAA,IACA,WAAAC;AAAA,IACA,OAAAC;AAAA,IACA,aAAAC,IAAc;AAAA,IACd,GAAGC;AAAA,EAAA,IACDR,GAEE,CAACS,GAAUC,CAAW,IAAIC,EAAS,EAAK,GAExCC,IAAUC;AAAA,IACd,MAAMC,EAAoBX,KAAa,MAAS;AAAA,IAChD,CAACA,CAAS;AAAA,EACZ,GAEMY,IAAaC;AAAA,IACjB,CAACC,MAAyD;AACxD,MAAAP,EAAY,EAAI,GAChBN,IAASa,CAAK;AAAA,IAChB;AAAA,IACA,CAACb,CAAM;AAAA,EACT;AAGE,SAAA,gBAAAc;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWC,EAAG,oBAAoBd,CAAS;AAAA,MAC3C,OAAO;AAAA,QACL,GAAGC;AAAA,QACH,aAAAC;AAAA,QACA,iBAAiBK,IAAU,OAAOA,CAAO,MAAM;AAAA,QAC/C,gBAAgB;AAAA,QAChB,oBAAoB;AAAA,MACtB;AAAA,MAEA,UAAA,gBAAAM;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAWC;AAAA,YACT;AAAA,YACAV,KAAY;AAAA,UACd;AAAA,UACA,KAAAR;AAAA,UACA,KAAAC;AAAA,UACA,QAAQa;AAAA,UACP,GAAGP;AAAA,QAAA;AAAA,MAAA;AAAA,IACN;AAAA,EACF;AAEJ,CAAC;"}
@@ -1,10 +0,0 @@
1
- function a(r) {
2
- return new Promise((n, o) => {
3
- const e = new FileReader();
4
- e.onloadend = () => n(e.result), e.onerror = o, e.readAsDataURL(r);
5
- });
6
- }
7
- export {
8
- a as fileToDataUri
9
- };
10
- //# sourceMappingURL=imageToDataUri.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"imageToDataUri.js","sources":["../../src/utils/imageToDataUri.ts"],"sourcesContent":["export function fileToDataUri(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onloadend = () => resolve(reader.result as string)\n reader.onerror = reject\n reader.readAsDataURL(file)\n })\n}\n"],"names":["fileToDataUri","file","resolve","reject","reader"],"mappings":"AAAO,SAASA,EAAcC,GAA6B;AACzD,SAAO,IAAI,QAAQ,CAACC,GAASC,MAAW;AAChC,UAAAC,IAAS,IAAI,WAAW;AAC9B,IAAAA,EAAO,YAAY,MAAMF,EAAQE,EAAO,MAAgB,GACxDA,EAAO,UAAUD,GACjBC,EAAO,cAAcH,CAAI;AAAA,EAAA,CAC1B;AACH;"}
@@ -1,8 +0,0 @@
1
- export function fileToDataUri(file: File): Promise<string> {
2
- return new Promise((resolve, reject) => {
3
- const reader = new FileReader()
4
- reader.onloadend = () => resolve(reader.result as string)
5
- reader.onerror = reject
6
- reader.readAsDataURL(file)
7
- })
8
- }