@shopify/shop-minis-react 0.0.24 → 0.0.25

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 (29) hide show
  1. package/dist/_virtual/index4.js +3 -2
  2. package/dist/_virtual/index4.js.map +1 -1
  3. package/dist/_virtual/index5.js +2 -3
  4. package/dist/_virtual/index5.js.map +1 -1
  5. package/dist/_virtual/index6.js +3 -2
  6. package/dist/_virtual/index6.js.map +1 -1
  7. package/dist/_virtual/index7.js +2 -3
  8. package/dist/_virtual/index7.js.map +1 -1
  9. package/dist/hooks/content/useCreateImageContent.js +37 -0
  10. package/dist/hooks/content/useCreateImageContent.js.map +1 -0
  11. package/dist/hooks/storage/useImageUpload.js +49 -40
  12. package/dist/hooks/storage/useImageUpload.js.map +1 -1
  13. package/dist/index.js +57 -53
  14. package/dist/index.js.map +1 -1
  15. package/dist/mocks.js +62 -45
  16. package/dist/mocks.js.map +1 -1
  17. package/dist/shop-minis-react/node_modules/.pnpm/@radix-ui_react-use-is-hydrated@0.1.0_@types_react@19.1.6_react@19.1.0/node_modules/@radix-ui/react-use-is-hydrated/dist/index.js +1 -1
  18. package/dist/shop-minis-react/node_modules/.pnpm/@videojs_xhr@2.7.0/node_modules/@videojs/xhr/lib/index.js +1 -1
  19. package/dist/shop-minis-react/node_modules/.pnpm/mpd-parser@1.3.1/node_modules/mpd-parser/dist/mpd-parser.es.js +1 -1
  20. package/dist/shop-minis-react/node_modules/.pnpm/querystringify@2.2.0/node_modules/querystringify/index.js +1 -1
  21. package/dist/utils/imageToDataUri.js +10 -0
  22. package/dist/utils/imageToDataUri.js.map +1 -0
  23. package/package.json +2 -2
  24. package/src/hooks/content/useCreateImageContent.ts +65 -0
  25. package/src/hooks/index.ts +1 -0
  26. package/src/hooks/storage/useImageUpload.ts +27 -11
  27. package/src/mocks.ts +17 -0
  28. package/src/utils/imageToDataUri.ts +8 -0
  29. package/src/utils/index.ts +1 -0
@@ -1,5 +1,6 @@
1
- var r = {};
1
+ import { __require as r } from "../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";
2
+ var i = r();
2
3
  export {
3
- r as __exports
4
+ i as s
4
5
  };
5
6
  //# sourceMappingURL=index4.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index4.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
1
+ {"version":3,"file":"index4.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
@@ -1,6 +1,5 @@
1
- import { __require as r } from "../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";
2
- var i = r();
1
+ var e = { exports: {} };
3
2
  export {
4
- i as s
3
+ e as __module
5
4
  };
6
5
  //# sourceMappingURL=index5.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index5.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
1
+ {"version":3,"file":"index5.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -1,5 +1,6 @@
1
- var e = { exports: {} };
1
+ import { __require as r } from "../shop-minis-react/node_modules/.pnpm/@xmldom_xmldom@0.8.10/node_modules/@xmldom/xmldom/lib/index.js";
2
+ var i = r();
2
3
  export {
3
- e as __module
4
+ i as l
4
5
  };
5
6
  //# sourceMappingURL=index6.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index6.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
1
+ {"version":3,"file":"index6.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
@@ -1,6 +1,5 @@
1
- import { __require as r } from "../shop-minis-react/node_modules/.pnpm/@xmldom_xmldom@0.8.10/node_modules/@xmldom/xmldom/lib/index.js";
2
- var i = r();
1
+ var r = {};
3
2
  export {
4
- i as l
3
+ r as __exports
5
4
  };
6
5
  //# sourceMappingURL=index7.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index7.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
1
+ {"version":3,"file":"index7.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -0,0 +1,37 @@
1
+ import { useCallback as s } from "react";
2
+ import { useHandleAction as p } from "../../internal/useHandleAction.js";
3
+ import { useShopActions as c } from "../../internal/useShopActions.js";
4
+ import { useImageUpload as u } from "../storage/useImageUpload.js";
5
+ import { fileToDataUri as g } from "../../utils/imageToDataUri.js";
6
+ const C = () => {
7
+ const { createContent: t } = c(), { uploadImage: o } = u(), a = s(
8
+ async (i) => {
9
+ const { image: e, contentTitle: n, visibility: m } = i;
10
+ if (!e.type)
11
+ throw new Error("Unable to determine file type");
12
+ if (!e.type.startsWith("image/"))
13
+ throw new Error("Invalid file type: must be an image");
14
+ const [l] = await o([
15
+ {
16
+ mimeType: e.type,
17
+ uri: await g(e)
18
+ }
19
+ ]), r = l.imageUrl;
20
+ if (!r)
21
+ throw new Error("Image upload failed");
22
+ return t({
23
+ title: n,
24
+ imageUrl: r,
25
+ visibility: m
26
+ });
27
+ },
28
+ [t, o]
29
+ );
30
+ return {
31
+ createImageContent: p(a)
32
+ };
33
+ };
34
+ export {
35
+ C as useCreateImageContent
36
+ };
37
+ //# sourceMappingURL=useCreateImageContent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCreateImageContent.js","sources":["../../../src/hooks/content/useCreateImageContent.ts"],"sourcesContent":["import {useCallback} from 'react'\n\nimport {ContentVisibility} from '@shopify/shop-minis-platform'\nimport {CreateContentResponse} from '@shopify/shop-minis-platform/actions'\n\nimport {useHandleAction} from '../../internal/useHandleAction'\nimport {useShopActions} from '../../internal/useShopActions'\nimport {fileToDataUri} from '../../utils'\nimport {useImageUpload} from '../storage/useImageUpload'\n\ninterface CreateImageContentParams {\n image: File\n contentTitle: string\n visibility?: ContentVisibility[] | null\n}\n\ninterface UseCreateImageContentReturns {\n /**\n * Upload an image and create content.\n */\n createImageContent: (\n params: CreateImageContentParams\n ) => Promise<CreateContentResponse>\n}\n\nexport const useCreateImageContent = (): UseCreateImageContentReturns => {\n const {createContent} = useShopActions()\n const {uploadImage} = useImageUpload()\n\n const createImageContent = useCallback(\n async (params: CreateImageContentParams) => {\n const {image, contentTitle, visibility} = params\n\n if (!image.type) {\n throw new Error('Unable to determine file type')\n }\n if (!image.type.startsWith('image/')) {\n throw new Error('Invalid file type: must be an image')\n }\n\n const [uploadImageResult] = await uploadImage([\n {\n mimeType: image.type,\n uri: await fileToDataUri(image),\n },\n ])\n const uploadImageUrl = uploadImageResult.imageUrl\n\n if (!uploadImageUrl) {\n throw new Error('Image upload failed')\n }\n\n return createContent({\n title: contentTitle,\n imageUrl: uploadImageUrl,\n visibility,\n })\n },\n [createContent, uploadImage]\n )\n\n return {\n createImageContent: useHandleAction(createImageContent),\n }\n}\n"],"names":["useCreateImageContent","createContent","useShopActions","uploadImage","useImageUpload","createImageContent","useCallback","params","image","contentTitle","visibility","uploadImageResult","fileToDataUri","uploadImageUrl","useHandleAction"],"mappings":";;;;;AAyBO,MAAMA,IAAwB,MAAoC;AACjE,QAAA,EAAC,eAAAC,EAAa,IAAIC,EAAe,GACjC,EAAC,aAAAC,EAAW,IAAIC,EAAe,GAE/BC,IAAqBC;AAAA,IACzB,OAAOC,MAAqC;AAC1C,YAAM,EAAC,OAAAC,GAAO,cAAAC,GAAc,YAAAC,EAAc,IAAAH;AAEtC,UAAA,CAACC,EAAM;AACH,cAAA,IAAI,MAAM,+BAA+B;AAEjD,UAAI,CAACA,EAAM,KAAK,WAAW,QAAQ;AAC3B,cAAA,IAAI,MAAM,qCAAqC;AAGvD,YAAM,CAACG,CAAiB,IAAI,MAAMR,EAAY;AAAA,QAC5C;AAAA,UACE,UAAUK,EAAM;AAAA,UAChB,KAAK,MAAMI,EAAcJ,CAAK;AAAA,QAAA;AAAA,MAChC,CACD,GACKK,IAAiBF,EAAkB;AAEzC,UAAI,CAACE;AACG,cAAA,IAAI,MAAM,qBAAqB;AAGvC,aAAOZ,EAAc;AAAA,QACnB,OAAOQ;AAAA,QACP,UAAUI;AAAA,QACV,YAAAH;AAAA,MAAA,CACD;AAAA,IACH;AAAA,IACA,CAACT,GAAeE,CAAW;AAAA,EAC7B;AAEO,SAAA;AAAA,IACL,oBAAoBW,EAAgBT,CAAkB;AAAA,EACxD;AACF;"}
@@ -1,62 +1,71 @@
1
- import { useCallback as p } from "react";
1
+ import { useCallback as m } from "react";
2
2
  import { useShopActions as u } from "../../internal/useShopActions.js";
3
- const m = async (t, a) => {
4
- const i = new FormData();
5
- a.parameters.forEach(({ name: r, value: l }) => {
6
- i.append(r, l);
7
- }), i.append("file", new Blob([t.uri], { type: t.mimeType }));
8
- const o = await fetch(a.url, {
3
+ const d = async (e) => {
4
+ const r = await (await fetch(e.uri)).blob();
5
+ return {
6
+ ...e,
7
+ fileSize: e.fileSize ?? r.size,
8
+ fileBlob: r
9
+ };
10
+ }, f = async (e, o) => {
11
+ const r = new FormData();
12
+ o.parameters.forEach(({ name: l, value: t }) => {
13
+ r.append(l, t);
14
+ }), r.append("file", e.fileBlob);
15
+ const a = await fetch(o.url, {
9
16
  method: "POST",
10
- body: i
17
+ body: r
11
18
  });
12
- return o.ok ? {} : (console.error("Failed to upload image", {
13
- response: await o.text()
19
+ return a.ok ? {} : (console.error("Failed to upload image", {
20
+ response: await a.text()
14
21
  }), { error: "Failed to upload image" });
15
- }, w = () => {
16
- const { createImageUploadLink: t, completeImageUpload: a } = u();
22
+ }, h = () => {
23
+ const { createImageUploadLink: e, completeImageUpload: o } = u();
17
24
  return {
18
- uploadImage: p(
19
- async (o) => {
20
- if (o.length > 1)
25
+ uploadImage: m(
26
+ async (a) => {
27
+ if (a.length > 1)
21
28
  throw new Error("Multiple image upload is not supported yet");
22
- const r = await t({
23
- input: o.map((e) => ({
24
- mimeType: e.mimeType,
25
- fileSize: e.fileSize
26
- }))
29
+ const l = a[0], t = await d(l), s = await e({
30
+ input: [
31
+ {
32
+ mimeType: t.mimeType,
33
+ fileSize: t.fileSize
34
+ }
35
+ ]
27
36
  });
28
- if (!r.ok)
29
- throw new Error(r.error.message);
30
- const { error: l } = await m(
31
- o[0],
32
- r?.data?.targets?.[0]
37
+ if (!s.ok)
38
+ throw new Error(s.error.message);
39
+ const { error: p } = await f(
40
+ t,
41
+ s?.data?.targets?.[0]
33
42
  );
34
- if (l)
35
- throw new Error(l);
36
- let n = 0;
37
- for (; n < 30; ) {
38
- const e = await a({
39
- resourceUrls: r?.data?.targets?.map((s) => s.resourceUrl) || []
43
+ if (p)
44
+ throw new Error(p);
45
+ let c = 0;
46
+ for (; c < 30; ) {
47
+ const i = await o({
48
+ resourceUrls: s?.data?.targets?.map((n) => n.resourceUrl) || []
40
49
  });
41
- if (!e.ok)
42
- throw new Error(e.error.message);
43
- if (e.data?.files?.[0]?.fileStatus === "READY")
50
+ if (!i.ok)
51
+ throw new Error(i.error.message);
52
+ if (i.data?.files?.[0]?.fileStatus === "READY")
44
53
  return [
45
54
  {
46
- id: e.data.files[0].id,
47
- imageUrl: e.data.files[0].image?.url,
48
- resourceUrl: r?.data?.targets?.[0]?.resourceUrl
55
+ id: i.data.files[0].id,
56
+ imageUrl: i.data.files[0].image?.url,
57
+ resourceUrl: s?.data?.targets?.[0]?.resourceUrl
49
58
  }
50
59
  ];
51
- await new Promise((s) => setTimeout(s, 1e3)), n++;
60
+ await new Promise((n) => setTimeout(n, 1e3)), c++;
52
61
  }
53
62
  throw new Error("Image upload completion timed out");
54
63
  },
55
- [t, a]
64
+ [e, o]
56
65
  )
57
66
  };
58
67
  };
59
68
  export {
60
- w as useImageUpload
69
+ h as useImageUpload
61
70
  };
62
71
  //# sourceMappingURL=useImageUpload.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useImageUpload.js","sources":["../../../src/hooks/storage/useImageUpload.ts"],"sourcesContent":["import {useCallback} from 'react'\n\nimport {useShopActions} from '../../internal/useShopActions'\n\nimport type {UploadTarget} from '@shopify/shop-minis-platform/actions'\n\nexport interface UploadImageParams {\n /**\n * The MIME type of the image.\n */\n mimeType: string\n /**\n * The size of the image in bytes.\n */\n fileSize: number\n /**\n * The URI of the image to upload.\n */\n uri: string\n}\n\nexport interface UploadedImage {\n /**\n * The ID of the uploaded image.\n */\n id: string\n /**\n * The URL of the uploaded image.\n */\n imageUrl?: string\n /**\n * The resource URL of the uploaded image.\n */\n resourceUrl?: string\n}\n\ninterface UseImageUploadReturns {\n /**\n * Upload an image attached to the current user.\n */\n uploadImage: (params: UploadImageParams[]) => Promise<UploadedImage[]>\n}\n\nconst uploadFileToGCS = async (\n image: UploadImageParams,\n target: UploadTarget\n) => {\n const formData = new FormData()\n target.parameters.forEach(({name, value}: {name: string; value: string}) => {\n formData.append(name, value)\n })\n // Append the actual file data last\n formData.append('file', new Blob([image.uri], {type: image.mimeType}))\n\n const uploadResponse = await fetch(target.url, {\n method: 'POST',\n body: formData,\n })\n\n if (!uploadResponse.ok) {\n console.error('Failed to upload image', {\n response: await uploadResponse.text(),\n })\n return {error: 'Failed to upload image'}\n }\n\n return {}\n}\n\nexport const useImageUpload = (): UseImageUploadReturns => {\n const {createImageUploadLink, completeImageUpload} = useShopActions()\n\n const uploadImage = useCallback(\n async (params: UploadImageParams[]) => {\n if (params.length > 1) {\n throw new Error('Multiple image upload is not supported yet')\n }\n\n const links = await createImageUploadLink({\n input: params.map(image => ({\n mimeType: image.mimeType,\n fileSize: image.fileSize,\n })),\n })\n\n if (!links.ok) {\n throw new Error(links.error.message)\n }\n\n // Upload single file to GCS\n // TODO: Upload multiple files to GCS\n const {error: uploadError} = await uploadFileToGCS(\n params[0],\n links?.data?.targets?.[0]!\n )\n\n if (uploadError) {\n throw new Error(uploadError)\n }\n\n // 10 second polling for image upload\n let count = 0\n while (count < 30) {\n const result = await completeImageUpload({\n resourceUrls:\n links?.data?.targets?.map(target => target.resourceUrl) || [],\n })\n\n if (!result.ok) {\n throw new Error(result.error.message)\n }\n\n // TODO: Add support for multiple files\n if (result.data?.files?.[0]?.fileStatus === 'READY') {\n return [\n {\n id: result.data.files[0].id,\n imageUrl: result.data.files[0].image?.url,\n resourceUrl: links?.data?.targets?.[0]?.resourceUrl,\n },\n ]\n }\n\n await new Promise(resolve => setTimeout(resolve, 1000))\n count++\n }\n\n throw new Error('Image upload completion timed out')\n },\n [createImageUploadLink, completeImageUpload]\n )\n\n return {\n uploadImage,\n }\n}\n"],"names":["uploadFileToGCS","image","target","formData","name","value","uploadResponse","useImageUpload","createImageUploadLink","completeImageUpload","useShopActions","useCallback","params","links","uploadError","count","result","resolve"],"mappings":";;AA2CA,MAAMA,IAAkB,OACtBC,GACAC,MACG;AACG,QAAAC,IAAW,IAAI,SAAS;AAC9B,EAAAD,EAAO,WAAW,QAAQ,CAAC,EAAC,MAAAE,GAAM,OAAAC,QAA0C;AACjE,IAAAF,EAAA,OAAOC,GAAMC,CAAK;AAAA,EAAA,CAC5B,GAEDF,EAAS,OAAO,QAAQ,IAAI,KAAK,CAACF,EAAM,GAAG,GAAG,EAAC,MAAMA,EAAM,SAAS,CAAA,CAAC;AAErE,QAAMK,IAAiB,MAAM,MAAMJ,EAAO,KAAK;AAAA,IAC7C,QAAQ;AAAA,IACR,MAAMC;AAAA,EAAA,CACP;AAEG,SAACG,EAAe,KAOb,CAAC,KANN,QAAQ,MAAM,0BAA0B;AAAA,IACtC,UAAU,MAAMA,EAAe,KAAK;AAAA,EAAA,CACrC,GACM,EAAC,OAAO,yBAAwB;AAI3C,GAEaC,IAAiB,MAA6B;AACzD,QAAM,EAAC,uBAAAC,GAAuB,qBAAAC,EAAmB,IAAIC,EAAe;AA8D7D,SAAA;AAAA,IACL,aA7DkBC;AAAA,MAClB,OAAOC,MAAgC;AACjC,YAAAA,EAAO,SAAS;AACZ,gBAAA,IAAI,MAAM,4CAA4C;AAGxD,cAAAC,IAAQ,MAAML,EAAsB;AAAA,UACxC,OAAOI,EAAO,IAAI,CAAUX,OAAA;AAAA,YAC1B,UAAUA,EAAM;AAAA,YAChB,UAAUA,EAAM;AAAA,UAAA,EAChB;AAAA,QAAA,CACH;AAEG,YAAA,CAACY,EAAM;AACT,gBAAM,IAAI,MAAMA,EAAM,MAAM,OAAO;AAKrC,cAAM,EAAC,OAAOC,EAAW,IAAI,MAAMd;AAAA,UACjCY,EAAO,CAAC;AAAA,UACRC,GAAO,MAAM,UAAU,CAAC;AAAA,QAC1B;AAEA,YAAIC;AACI,gBAAA,IAAI,MAAMA,CAAW;AAI7B,YAAIC,IAAQ;AACZ,eAAOA,IAAQ,MAAI;AACX,gBAAAC,IAAS,MAAMP,EAAoB;AAAA,YACvC,cACEI,GAAO,MAAM,SAAS,IAAI,CAAUX,MAAAA,EAAO,WAAW,KAAK,CAAA;AAAA,UAAC,CAC/D;AAEG,cAAA,CAACc,EAAO;AACV,kBAAM,IAAI,MAAMA,EAAO,MAAM,OAAO;AAItC,cAAIA,EAAO,MAAM,QAAQ,CAAC,GAAG,eAAe;AACnC,mBAAA;AAAA,cACL;AAAA,gBACE,IAAIA,EAAO,KAAK,MAAM,CAAC,EAAE;AAAA,gBACzB,UAAUA,EAAO,KAAK,MAAM,CAAC,EAAE,OAAO;AAAA,gBACtC,aAAaH,GAAO,MAAM,UAAU,CAAC,GAAG;AAAA,cAAA;AAAA,YAE5C;AAGF,gBAAM,IAAI,QAAQ,CAAAI,MAAW,WAAWA,GAAS,GAAI,CAAC,GACtDF;AAAA,QAAA;AAGI,cAAA,IAAI,MAAM,mCAAmC;AAAA,MACrD;AAAA,MACA,CAACP,GAAuBC,CAAmB;AAAA,IAC7C;AAAA,EAIA;AACF;"}
1
+ {"version":3,"file":"useImageUpload.js","sources":["../../../src/hooks/storage/useImageUpload.ts"],"sourcesContent":["import {useCallback} from 'react'\n\nimport {useShopActions} from '../../internal/useShopActions'\n\nimport type {UploadTarget} from '@shopify/shop-minis-platform/actions'\n\nexport interface UploadImageParams {\n /**\n * The MIME type of the image.\n */\n mimeType: string\n /**\n * The size of the image in bytes.\n */\n fileSize?: number\n /**\n * The URI of the image to upload.\n */\n uri: string\n}\n\nexport interface UploadedImage {\n /**\n * The ID of the uploaded image.\n */\n id: string\n /**\n * The URL of the uploaded image.\n */\n imageUrl?: string\n /**\n * The resource URL of the uploaded image.\n */\n resourceUrl?: string\n}\n\ninterface UseImageUploadReturns {\n /**\n * Upload an image attached to the current user.\n */\n uploadImage: (params: UploadImageParams[]) => Promise<UploadedImage[]>\n}\n\n// Fetch file data and detect file sizes if not provided\n// Works with file://, data:, and http(s):// URIs\nconst processFileData = async (image: UploadImageParams) => {\n const response = await fetch(image.uri)\n const blob = await response.blob()\n\n return {\n ...image,\n fileSize: image.fileSize ?? blob.size,\n fileBlob: blob,\n }\n}\n\nconst uploadFileToGCS = async (\n image: UploadImageParams & {fileSize: number; fileBlob: Blob},\n target: UploadTarget\n) => {\n const formData = new FormData()\n target.parameters.forEach(({name, value}: {name: string; value: string}) => {\n formData.append(name, value)\n })\n\n formData.append('file', image.fileBlob)\n\n const uploadResponse = await fetch(target.url, {\n method: 'POST',\n body: formData,\n })\n\n if (!uploadResponse.ok) {\n console.error('Failed to upload image', {\n response: await uploadResponse.text(),\n })\n return {error: 'Failed to upload image'}\n }\n\n return {}\n}\n\nexport const useImageUpload = (): UseImageUploadReturns => {\n const {createImageUploadLink, completeImageUpload} = useShopActions()\n\n const uploadImage = useCallback(\n async (params: UploadImageParams[]) => {\n if (params.length > 1) {\n throw new Error('Multiple image upload is not supported yet')\n }\n\n const imageParams = params[0]\n const processedImageParams = await processFileData(imageParams)\n\n const links = await createImageUploadLink({\n input: [\n {\n mimeType: processedImageParams.mimeType,\n fileSize: processedImageParams.fileSize,\n },\n ],\n })\n\n if (!links.ok) {\n throw new Error(links.error.message)\n }\n\n // Upload single file to GCS\n const {error: uploadError} = await uploadFileToGCS(\n processedImageParams,\n links?.data?.targets?.[0]!\n )\n\n if (uploadError) {\n throw new Error(uploadError)\n }\n\n // 10 second polling for image upload\n let count = 0\n while (count < 30) {\n const result = await completeImageUpload({\n resourceUrls:\n links?.data?.targets?.map(target => target.resourceUrl) || [],\n })\n\n if (!result.ok) {\n throw new Error(result.error.message)\n }\n\n if (result.data?.files?.[0]?.fileStatus === 'READY') {\n return [\n {\n id: result.data.files[0].id,\n imageUrl: result.data.files[0].image?.url,\n resourceUrl: links?.data?.targets?.[0]?.resourceUrl,\n },\n ]\n }\n\n await new Promise(resolve => setTimeout(resolve, 1000))\n count++\n }\n\n throw new Error('Image upload completion timed out')\n },\n [createImageUploadLink, completeImageUpload]\n )\n\n return {\n uploadImage,\n }\n}\n"],"names":["processFileData","image","blob","uploadFileToGCS","target","formData","name","value","uploadResponse","useImageUpload","createImageUploadLink","completeImageUpload","useShopActions","useCallback","params","imageParams","processedImageParams","links","uploadError","count","result","resolve"],"mappings":";;AA6CA,MAAMA,IAAkB,OAAOC,MAA6B;AAEpD,QAAAC,IAAO,OADI,MAAM,MAAMD,EAAM,GAAG,GACV,KAAK;AAE1B,SAAA;AAAA,IACL,GAAGA;AAAA,IACH,UAAUA,EAAM,YAAYC,EAAK;AAAA,IACjC,UAAUA;AAAA,EACZ;AACF,GAEMC,IAAkB,OACtBF,GACAG,MACG;AACG,QAAAC,IAAW,IAAI,SAAS;AAC9B,EAAAD,EAAO,WAAW,QAAQ,CAAC,EAAC,MAAAE,GAAM,OAAAC,QAA0C;AACjE,IAAAF,EAAA,OAAOC,GAAMC,CAAK;AAAA,EAAA,CAC5B,GAEQF,EAAA,OAAO,QAAQJ,EAAM,QAAQ;AAEtC,QAAMO,IAAiB,MAAM,MAAMJ,EAAO,KAAK;AAAA,IAC7C,QAAQ;AAAA,IACR,MAAMC;AAAA,EAAA,CACP;AAEG,SAACG,EAAe,KAOb,CAAC,KANN,QAAQ,MAAM,0BAA0B;AAAA,IACtC,UAAU,MAAMA,EAAe,KAAK;AAAA,EAAA,CACrC,GACM,EAAC,OAAO,yBAAwB;AAI3C,GAEaC,IAAiB,MAA6B;AACzD,QAAM,EAAC,uBAAAC,GAAuB,qBAAAC,EAAmB,IAAIC,EAAe;AAiE7D,SAAA;AAAA,IACL,aAhEkBC;AAAA,MAClB,OAAOC,MAAgC;AACjC,YAAAA,EAAO,SAAS;AACZ,gBAAA,IAAI,MAAM,4CAA4C;AAGxD,cAAAC,IAAcD,EAAO,CAAC,GACtBE,IAAuB,MAAMhB,EAAgBe,CAAW,GAExDE,IAAQ,MAAMP,EAAsB;AAAA,UACxC,OAAO;AAAA,YACL;AAAA,cACE,UAAUM,EAAqB;AAAA,cAC/B,UAAUA,EAAqB;AAAA,YAAA;AAAA,UACjC;AAAA,QACF,CACD;AAEG,YAAA,CAACC,EAAM;AACT,gBAAM,IAAI,MAAMA,EAAM,MAAM,OAAO;AAIrC,cAAM,EAAC,OAAOC,EAAW,IAAI,MAAMf;AAAA,UACjCa;AAAA,UACAC,GAAO,MAAM,UAAU,CAAC;AAAA,QAC1B;AAEA,YAAIC;AACI,gBAAA,IAAI,MAAMA,CAAW;AAI7B,YAAIC,IAAQ;AACZ,eAAOA,IAAQ,MAAI;AACX,gBAAAC,IAAS,MAAMT,EAAoB;AAAA,YACvC,cACEM,GAAO,MAAM,SAAS,IAAI,CAAUb,MAAAA,EAAO,WAAW,KAAK,CAAA;AAAA,UAAC,CAC/D;AAEG,cAAA,CAACgB,EAAO;AACV,kBAAM,IAAI,MAAMA,EAAO,MAAM,OAAO;AAGtC,cAAIA,EAAO,MAAM,QAAQ,CAAC,GAAG,eAAe;AACnC,mBAAA;AAAA,cACL;AAAA,gBACE,IAAIA,EAAO,KAAK,MAAM,CAAC,EAAE;AAAA,gBACzB,UAAUA,EAAO,KAAK,MAAM,CAAC,EAAE,OAAO;AAAA,gBACtC,aAAaH,GAAO,MAAM,UAAU,CAAC,GAAG;AAAA,cAAA;AAAA,YAE5C;AAGF,gBAAM,IAAI,QAAQ,CAAAI,MAAW,WAAWA,GAAS,GAAI,CAAC,GACtDF;AAAA,QAAA;AAGI,cAAA,IAAI,MAAM,mCAAmC;AAAA,MACrD;AAAA,MACA,CAACT,GAAuBC,CAAmB;AAAA,IAC7C;AAAA,EAIA;AACF;"}
package/dist/index.js CHANGED
@@ -2,11 +2,11 @@ import { DATA_NAVIGATION_TYPE_ATTRIBUTE as o, NAVIGATION_TYPES as t } from "./ty
2
2
  import { MinisContainer as i } from "./components/MinisContainer.js";
3
3
  import { ProductCard as p } from "./components/commerce/product-card.js";
4
4
  import { ProductLink as s } from "./components/commerce/product-link.js";
5
- import { MerchantCard as u, MerchantCardPrimitive as x } from "./components/commerce/merchant-card.js";
5
+ import { MerchantCard as f, MerchantCardPrimitive as u } from "./components/commerce/merchant-card.js";
6
6
  import { ProductCardSkeleton as c } from "./components/commerce/product-card-skeleton.js";
7
7
  import { MerchantCardSkeleton as g } from "./components/commerce/merchant-card-skeleton.js";
8
8
  import { QuantitySelector as D } from "./components/commerce/quantity-selector.js";
9
- import { TransitionContainer as C } from "./components/navigation/transition-container.js";
9
+ import { TransitionContainer as A } from "./components/navigation/transition-container.js";
10
10
  import { TransitionLink as T } from "./components/navigation/transition-link.js";
11
11
  import { Button as I } from "./components/atoms/button.js";
12
12
  import { FavoriteButton as v } from "./components/atoms/favorite-button.js";
@@ -16,28 +16,28 @@ import { Touchable as E } from "./components/atoms/touchable.js";
16
16
  import { AlertDialogAtom as N } from "./components/atoms/alert-dialog.js";
17
17
  import { List as L } from "./components/atoms/list.js";
18
18
  import { VideoPlayer as H } from "./components/atoms/video-player.js";
19
- import { Accordion as V, AccordionContent as U, AccordionItem as z, AccordionTrigger as _ } from "./components/ui/accordion.js";
19
+ import { Accordion as U, AccordionContent as V, AccordionItem as z, AccordionTrigger as _ } from "./components/ui/accordion.js";
20
20
  import { Alert as Q, AlertDescription as W, AlertTitle as j } from "./components/ui/alert.js";
21
21
  import { AlertDialog as J, AlertDialogAction as K, AlertDialogCancel as X, AlertDialogContent as Z, AlertDialogDescription as $, AlertDialogFooter as rr, AlertDialogHeader as er, AlertDialogOverlay as or, AlertDialogPortal as tr, AlertDialogTitle as ar, AlertDialogTrigger as ir } from "./components/ui/alert-dialog.js";
22
22
  import { Avatar as pr, AvatarFallback as mr, AvatarImage as sr } from "./components/ui/avatar.js";
23
- import { Badge as ur, badgeVariants as xr } from "./components/ui/badge.js";
24
- import { Card as cr, CardAction as dr, CardContent as gr, CardDescription as Sr, CardFooter as Dr, CardHeader as Ar, CardTitle as Cr } from "./components/ui/card.js";
23
+ import { Badge as fr, badgeVariants as ur } from "./components/ui/badge.js";
24
+ import { Card as cr, CardAction as dr, CardContent as gr, CardDescription as Sr, CardFooter as Dr, CardHeader as Cr, CardTitle as Ar } from "./components/ui/card.js";
25
25
  import { Carousel as Tr, CarouselContent as hr, CarouselItem as Ir, CarouselNext as wr, CarouselPrevious as vr } from "./components/ui/carousel.js";
26
26
  import { Checkbox as br } from "./components/ui/checkbox.js";
27
27
  import { Dialog as kr, DialogClose as Br, DialogContent as Er, DialogDescription as Mr, DialogFooter as Nr, DialogHeader as yr, DialogOverlay as Lr, DialogPortal as Gr, DialogTitle as Hr, DialogTrigger as Or } from "./components/ui/dialog.js";
28
- import { Drawer as Ur, DrawerClose as zr, DrawerContent as _r, DrawerDescription as Yr, DrawerFooter as Qr, DrawerHeader as Wr, DrawerOverlay as jr, DrawerPortal as qr, DrawerTitle as Jr, DrawerTrigger as Kr } from "./components/ui/drawer.js";
28
+ import { Drawer as Vr, DrawerClose as zr, DrawerContent as _r, DrawerDescription as Yr, DrawerFooter as Qr, DrawerHeader as Wr, DrawerOverlay as jr, DrawerPortal as qr, DrawerTitle as Jr, DrawerTrigger as Kr } from "./components/ui/drawer.js";
29
29
  import { Input as Zr } from "./components/ui/input.js";
30
30
  import { Label as re } from "./components/ui/label.js";
31
31
  import { Progress as oe } from "./components/ui/progress.js";
32
32
  import { RadioGroup as ae, RadioGroupItem as ie } from "./components/ui/radio-group.js";
33
33
  import { ResizableHandle as pe, ResizablePanel as me, ResizablePanelGroup as se } from "./components/ui/resizable.js";
34
- import { ScrollArea as ue, ScrollBar as xe } from "./components/ui/scroll-area.js";
35
- import { Select as ce, SelectContent as de, SelectGroup as ge, SelectItem as Se, SelectLabel as De, SelectScrollDownButton as Ae, SelectScrollUpButton as Ce, SelectSeparator as Pe, SelectTrigger as Te, SelectValue as he } from "./components/ui/select.js";
34
+ import { ScrollArea as fe, ScrollBar as ue } from "./components/ui/scroll-area.js";
35
+ import { Select as ce, SelectContent as de, SelectGroup as ge, SelectItem as Se, SelectLabel as De, SelectScrollDownButton as Ce, SelectScrollUpButton as Ae, SelectSeparator as Pe, SelectTrigger as Te, SelectValue as he } from "./components/ui/select.js";
36
36
  import { Separator as we } from "./components/ui/separator.js";
37
37
  import { Sheet as Re, SheetClose as be, SheetContent as Fe, SheetDescription as ke, SheetFooter as Be, SheetHeader as Ee, SheetTitle as Me, SheetTrigger as Ne } from "./components/ui/sheet.js";
38
38
  import { Toaster as Le } from "./components/ui/sonner.js";
39
39
  import { Skeleton as He } from "./components/ui/skeleton.js";
40
- import { useRecentProducts as Ve } from "./hooks/user/useRecentProducts.js";
40
+ import { useRecentProducts as Ue } from "./hooks/user/useRecentProducts.js";
41
41
  import { useRecentShops as ze } from "./hooks/user/useRecentShops.js";
42
42
  import { useSavedProducts as Ye } from "./hooks/user/useSavedProducts.js";
43
43
  import { useSavedProductsActions as We } from "./hooks/user/useSavedProductsActions.js";
@@ -50,10 +50,10 @@ import { useProductListActions as ao } from "./hooks/product/useProductListActio
50
50
  import { useProductLists as lo } from "./hooks/product/useProductLists.js";
51
51
  import { useProductList as mo } from "./hooks/product/useProductList.js";
52
52
  import { useProduct as no } from "./hooks/product/useProduct.js";
53
- import { useProducts as xo } from "./hooks/product/useProducts.js";
53
+ import { useProducts as uo } from "./hooks/product/useProducts.js";
54
54
  import { useProductVariants as co } from "./hooks/product/useProductVariants.js";
55
55
  import { useProductMedia as So } from "./hooks/product/useProductMedia.js";
56
- import { useProductSearch as Ao } from "./hooks/product/useProductSearch.js";
56
+ import { useProductSearch as Co } from "./hooks/product/useProductSearch.js";
57
57
  import { useRecommendedProducts as Po } from "./hooks/product/useRecommendedProducts.js";
58
58
  import { usePopularProducts as ho } from "./hooks/product/usePopularProducts.js";
59
59
  import { useCuratedProducts as wo } from "./hooks/product/useCuratedProducts.js";
@@ -64,20 +64,22 @@ import { useShopNavigation as Mo } from "./hooks/navigation/useShopNavigation.js
64
64
  import { useCloseMini as yo } from "./hooks/navigation/useCloseMini.js";
65
65
  import { useDeeplink as Go } from "./hooks/navigation/useDeeplink.js";
66
66
  import { useNavigateWithTransition as Oo } from "./hooks/navigation/useNavigateWithTransition.js";
67
- import { useShop as Uo } from "./hooks/shop/useShop.js";
67
+ import { useShop as Vo } from "./hooks/shop/useShop.js";
68
68
  import { useShopCartActions as _o } from "./hooks/shop/useShopCartActions.js";
69
69
  import { useRecommendedShops as Qo } from "./hooks/shop/useRecommendedShops.js";
70
- import { useErrorToast as jo } from "./hooks/util/useErrorToast.js";
71
- import { useErrorScreen as Jo } from "./hooks/util/useErrorScreen.js";
72
- import { useShare as Xo } from "./hooks/util/useShare.js";
73
- import { useImagePicker as $o } from "./hooks/util/useImagePicker.js";
74
- import { MiniEntityNotFoundError as et, MiniError as ot, MiniNetworkError as tt, formatError as at } from "./utils/errors.js";
75
- import { extractBrandTheme as lt, formatReviewCount as pt, getFeaturedImages as mt, normalizeRating as st } from "./utils/merchant-card.js";
76
- import { parseUrl as ut } from "./utils/parseUrl.js";
77
- import { Consent as ft, ConsentStatus as ct } from "./shop-minis-platform/src/types/permissions.js";
70
+ import { useCreateImageContent as jo } from "./hooks/content/useCreateImageContent.js";
71
+ import { useErrorToast as Jo } from "./hooks/util/useErrorToast.js";
72
+ import { useErrorScreen as Xo } from "./hooks/util/useErrorScreen.js";
73
+ import { useShare as $o } from "./hooks/util/useShare.js";
74
+ import { useImagePicker as et } from "./hooks/util/useImagePicker.js";
75
+ import { MiniEntityNotFoundError as tt, MiniError as at, MiniNetworkError as it, formatError as lt } from "./utils/errors.js";
76
+ import { extractBrandTheme as mt, formatReviewCount as st, getFeaturedImages as nt, normalizeRating as ft } from "./utils/merchant-card.js";
77
+ import { parseUrl as xt } from "./utils/parseUrl.js";
78
+ import { fileToDataUri as dt } from "./utils/imageToDataUri.js";
79
+ import { Consent as St, ConsentStatus as Dt } from "./shop-minis-platform/src/types/permissions.js";
78
80
  export {
79
- V as Accordion,
80
- U as AccordionContent,
81
+ U as Accordion,
82
+ V as AccordionContent,
81
83
  z as AccordionItem,
82
84
  _ as AccordionTrigger,
83
85
  Q as Alert,
@@ -98,23 +100,23 @@ export {
98
100
  pr as Avatar,
99
101
  mr as AvatarFallback,
100
102
  sr as AvatarImage,
101
- ur as Badge,
103
+ fr as Badge,
102
104
  I as Button,
103
105
  cr as Card,
104
106
  dr as CardAction,
105
107
  gr as CardContent,
106
108
  Sr as CardDescription,
107
109
  Dr as CardFooter,
108
- Ar as CardHeader,
109
- Cr as CardTitle,
110
+ Cr as CardHeader,
111
+ Ar as CardTitle,
110
112
  Tr as Carousel,
111
113
  hr as CarouselContent,
112
114
  Ir as CarouselItem,
113
115
  wr as CarouselNext,
114
116
  vr as CarouselPrevious,
115
117
  br as Checkbox,
116
- ft as Consent,
117
- ct as ConsentStatus,
118
+ St as Consent,
119
+ Dt as ConsentStatus,
118
120
  o as DATA_NAVIGATION_TYPE_ATTRIBUTE,
119
121
  kr as Dialog,
120
122
  Br as DialogClose,
@@ -126,7 +128,7 @@ export {
126
128
  Gr as DialogPortal,
127
129
  Hr as DialogTitle,
128
130
  Or as DialogTrigger,
129
- Ur as Drawer,
131
+ Vr as Drawer,
130
132
  zr as DrawerClose,
131
133
  _r as DrawerContent,
132
134
  Yr as DrawerDescription,
@@ -141,12 +143,12 @@ export {
141
143
  Zr as Input,
142
144
  re as Label,
143
145
  L as List,
144
- u as MerchantCard,
145
- x as MerchantCardPrimitive,
146
+ f as MerchantCard,
147
+ u as MerchantCardPrimitive,
146
148
  g as MerchantCardSkeleton,
147
- et as MiniEntityNotFoundError,
148
- ot as MiniError,
149
- tt as MiniNetworkError,
149
+ tt as MiniEntityNotFoundError,
150
+ at as MiniError,
151
+ it as MiniNetworkError,
150
152
  i as MinisContainer,
151
153
  t as NAVIGATION_TYPES,
152
154
  p as ProductCard,
@@ -159,15 +161,15 @@ export {
159
161
  pe as ResizableHandle,
160
162
  me as ResizablePanel,
161
163
  se as ResizablePanelGroup,
162
- ue as ScrollArea,
163
- xe as ScrollBar,
164
+ fe as ScrollArea,
165
+ ue as ScrollBar,
164
166
  ce as Select,
165
167
  de as SelectContent,
166
168
  ge as SelectGroup,
167
169
  Se as SelectItem,
168
170
  De as SelectLabel,
169
- Ae as SelectScrollDownButton,
170
- Ce as SelectScrollUpButton,
171
+ Ce as SelectScrollDownButton,
172
+ Ae as SelectScrollUpButton,
171
173
  Pe as SelectSeparator,
172
174
  Te as SelectTrigger,
173
175
  he as SelectValue,
@@ -184,27 +186,29 @@ export {
184
186
  k as ThumbhashImage,
185
187
  Le as Toaster,
186
188
  E as Touchable,
187
- C as TransitionContainer,
189
+ A as TransitionContainer,
188
190
  T as TransitionLink,
189
191
  H as VideoPlayer,
190
- xr as badgeVariants,
191
- lt as extractBrandTheme,
192
- at as formatError,
193
- pt as formatReviewCount,
194
- mt as getFeaturedImages,
195
- st as normalizeRating,
196
- ut as parseUrl,
192
+ ur as badgeVariants,
193
+ mt as extractBrandTheme,
194
+ dt as fileToDataUri,
195
+ lt as formatError,
196
+ st as formatReviewCount,
197
+ nt as getFeaturedImages,
198
+ ft as normalizeRating,
199
+ xt as parseUrl,
197
200
  Ro as useAsyncStorage,
198
201
  oo as useBuyerAttributes,
199
202
  yo as useCloseMini,
203
+ jo as useCreateImageContent,
200
204
  wo as useCuratedProducts,
201
205
  Ze as useCurrentUser,
202
206
  Go as useDeeplink,
203
- Jo as useErrorScreen,
204
- jo as useErrorToast,
207
+ Xo as useErrorScreen,
208
+ Jo as useErrorToast,
205
209
  qe as useFollowedShops,
206
210
  Ke as useFollowedShopsActions,
207
- $o as useImagePicker,
211
+ et as useImagePicker,
208
212
  Bo as useImageUpload,
209
213
  Oo as useNavigateWithTransition,
210
214
  ro as useOrders,
@@ -214,18 +218,18 @@ export {
214
218
  ao as useProductListActions,
215
219
  lo as useProductLists,
216
220
  So as useProductMedia,
217
- Ao as useProductSearch,
221
+ Co as useProductSearch,
218
222
  co as useProductVariants,
219
- xo as useProducts,
220
- Ve as useRecentProducts,
223
+ uo as useProducts,
224
+ Ue as useRecentProducts,
221
225
  ze as useRecentShops,
222
226
  Po as useRecommendedProducts,
223
227
  Qo as useRecommendedShops,
224
228
  Ye as useSavedProducts,
225
229
  We as useSavedProductsActions,
226
230
  Fo as useSecureStorage,
227
- Xo as useShare,
228
- Uo as useShop,
231
+ $o as useShare,
232
+ Vo as useShop,
229
233
  _o as useShopCartActions,
230
234
  Mo as useShopNavigation
231
235
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/mocks.js CHANGED
@@ -1,19 +1,19 @@
1
- const e = (t, o, a = "99.99", s) => ({
1
+ const e = (t, o, r = "99.99", s) => ({
2
2
  id: t,
3
3
  title: o,
4
- price: { amount: a, currencyCode: "USD" },
4
+ price: { amount: r, currencyCode: "USD" },
5
5
  ...s && {
6
6
  compareAtPrice: { amount: s, currencyCode: "USD" }
7
7
  },
8
8
  reviewAnalytics: { averageRating: 4.5, reviewCount: 10 },
9
- shop: d("shop1", "Mock Shop"),
9
+ shop: i("shop1", "Mock Shop"),
10
10
  defaultVariantId: `variant-${t}`,
11
11
  isFavorited: !1,
12
12
  featuredImage: {
13
13
  url: "https://cdn.shopify.com/s/files/1/0621/0463/3599/files/61ChhrRjK9L._AC_SL1000_1639abe8-4cd3-4bee-9867-73f26b0acf0a.jpg?v=1702559955",
14
14
  altText: o
15
15
  }
16
- }), d = (t, o, a) => {
16
+ }), i = (t, o, r) => {
17
17
  const c = Array.from({ length: 3 }, (m, n) => ({
18
18
  url: `https://picsum.photos/400/400?random=${t}-${n}`,
19
19
  sensitive: !1,
@@ -36,19 +36,19 @@ const e = (t, o, a = "99.99", s) => ({
36
36
  brandSettings: void 0
37
37
  }
38
38
  };
39
- }, r = (t = !1) => ({
39
+ }, a = (t = !1) => ({
40
40
  hasNextPage: t,
41
41
  endCursor: t ? "cursor123" : null
42
- }), i = (t, o, a = []) => ({
42
+ }), d = (t, o, r = []) => ({
43
43
  id: t,
44
44
  publicId: `public-${t}`,
45
45
  name: o,
46
- products: a
46
+ products: r
47
47
  });
48
48
  function p(t, o) {
49
- return (a) => (console.log(`[Mock Action] ${String(t)}`, a), Promise.resolve({ ok: !0, data: o }));
49
+ return (r) => (console.log(`[Mock Action] ${String(t)}`, r), Promise.resolve({ ok: !0, data: o }));
50
50
  }
51
- function u() {
51
+ function l() {
52
52
  const t = {
53
53
  followShop: !0,
54
54
  unfollowShop: !1,
@@ -123,20 +123,20 @@ function u() {
123
123
  reportContentImpression: void 0,
124
124
  getProductLists: {
125
125
  data: [
126
- i("list-1", "Wishlist"),
127
- i("list-2", "Favorites")
126
+ d("list-1", "Wishlist"),
127
+ d("list-2", "Favorites")
128
128
  ],
129
- pageInfo: r()
129
+ pageInfo: a()
130
130
  },
131
131
  getProductList: {
132
- data: i("list-1", "Wishlist", [
132
+ data: d("list-1", "Wishlist", [
133
133
  e("prod-1", "Sample Product")
134
134
  ]),
135
- pageInfo: r()
135
+ pageInfo: a()
136
136
  },
137
- addProductList: i("list-3", "New List"),
137
+ addProductList: d("list-3", "New List"),
138
138
  removeProductList: void 0,
139
- renameProductList: i("list-1", "Updated Wishlist"),
139
+ renameProductList: d("list-1", "Updated Wishlist"),
140
140
  addProductListItem: void 0,
141
141
  removeProductListItem: void 0,
142
142
  getRecommendedProducts: {
@@ -151,21 +151,21 @@ function u() {
151
151
  e("rec-8", "Recommended Product 8", "69.99"),
152
152
  e("rec-9", "Recommended Product 9", "129.99")
153
153
  ],
154
- pageInfo: r()
154
+ pageInfo: a()
155
155
  },
156
156
  getRecommendedShops: {
157
157
  data: [
158
- d("shop-1", "Amazing Store"),
159
- d("shop-2", "Best Deals Shop")
158
+ i("shop-1", "Amazing Store"),
159
+ i("shop-2", "Best Deals Shop")
160
160
  ],
161
- pageInfo: r()
161
+ pageInfo: a()
162
162
  },
163
163
  searchProductsByShop: {
164
164
  data: [
165
165
  e("search-1", "Search Result 1", "59.99"),
166
166
  e("search-2", "Search Result 2", "89.99")
167
167
  ],
168
- pageInfo: r()
168
+ pageInfo: a()
169
169
  },
170
170
  getOrders: {
171
171
  data: [
@@ -180,10 +180,10 @@ function u() {
180
180
  product: null
181
181
  }
182
182
  ],
183
- shop: d("shop-1", "Sample Shop")
183
+ shop: i("shop-1", "Sample Shop")
184
184
  }
185
185
  ],
186
- pageInfo: r()
186
+ pageInfo: a()
187
187
  },
188
188
  getBuyerAttributes: {
189
189
  data: {
@@ -208,7 +208,7 @@ function u() {
208
208
  e("pop-9", "Playstation 4", "299.95"),
209
209
  e("pop-10", "Nintendo 3DS", "89.95")
210
210
  ],
211
- pageInfo: r()
211
+ pageInfo: a()
212
212
  },
213
213
  share: {
214
214
  message: "Shared!",
@@ -219,19 +219,19 @@ function u() {
219
219
  e("cur-1", "Curated Product 1", "79.99"),
220
220
  e("cur-2", "Curated Product 2", "129.99")
221
221
  ],
222
- pageInfo: r()
222
+ pageInfo: a()
223
223
  },
224
224
  getSavedProducts: {
225
225
  data: [e("saved-1", "Saved Product 1", "49.99")],
226
- pageInfo: r()
226
+ pageInfo: a()
227
227
  },
228
228
  getRecentProducts: {
229
229
  data: [e("recent-1", "Recent Product 1", "59.99")],
230
- pageInfo: r()
230
+ pageInfo: a()
231
231
  },
232
232
  getProductSearch: {
233
233
  data: [e("search-3", "Search Product 3", "39.99")],
234
- pageInfo: r()
234
+ pageInfo: a()
235
235
  },
236
236
  getProducts: { data: [e("prod-2", "Product 2", "19.99")] },
237
237
  getProduct: { data: e("prod-1", "Sample Product") },
@@ -245,7 +245,7 @@ function u() {
245
245
  compareAtPrice: { amount: "29.99", currencyCode: "USD" }
246
246
  }
247
247
  ],
248
- pageInfo: r()
248
+ pageInfo: a()
249
249
  },
250
250
  getProductMedia: {
251
251
  data: [
@@ -256,31 +256,48 @@ function u() {
256
256
  alt: "Sample product image"
257
257
  }
258
258
  ],
259
- pageInfo: r()
259
+ pageInfo: a()
260
260
  },
261
- getShop: { data: d("shop-1", "Sample Shop") },
261
+ getShop: { data: i("shop-1", "Sample Shop") },
262
262
  getRecentShops: {
263
- data: [d("recent-shop-1", "Recent Shop 1")],
264
- pageInfo: r()
263
+ data: [i("recent-shop-1", "Recent Shop 1")],
264
+ pageInfo: a()
265
265
  },
266
266
  getFollowedShops: {
267
- data: [d("followed-shop-1", "Followed Shop 1")],
268
- pageInfo: r()
267
+ data: [i("followed-shop-1", "Followed Shop 1")],
268
+ pageInfo: a()
269
269
  },
270
- previewProductInAr: void 0
270
+ previewProductInAr: void 0,
271
+ createContent: {
272
+ data: {
273
+ publicId: "content-123",
274
+ externalId: null,
275
+ image: {
276
+ id: "img-123",
277
+ url: "https://example.com/content-image.jpg",
278
+ width: 800,
279
+ height: 600
280
+ },
281
+ title: "Mock Content",
282
+ description: "This is a mock content item",
283
+ visibility: ["DISCOVERABLE"],
284
+ shareableUrl: "https://example.com/content/123",
285
+ products: null
286
+ }
287
+ }
271
288
  }, o = {};
272
- for (const a in t)
273
- Object.prototype.hasOwnProperty.call(t, a) && (o[a] = p(
274
- a,
275
- t[a]
289
+ for (const r in t)
290
+ Object.prototype.hasOwnProperty.call(t, r) && (o[r] = p(
291
+ r,
292
+ t[r]
276
293
  ));
277
294
  return o;
278
295
  }
279
- const l = () => {
280
- const t = navigator.userAgent.toLowerCase(), o = /iphone|ipad|ipod/.test(t), a = /android/.test(t);
281
- return o || a;
296
+ const u = () => {
297
+ const t = navigator.userAgent.toLowerCase(), o = /iphone|ipad|ipod/.test(t), r = /android/.test(t);
298
+ return o || r;
282
299
  }, g = () => {
283
- l() || window.minisSDK || (window.minisSDK = u(), window.minisParams = {
300
+ u() || window.minisSDK || (window.minisSDK = l(), window.minisParams = {
284
301
  handle: "mock-handle",
285
302
  initialUrl: "/mock-initial-url",
286
303
  platform: "web"
@@ -288,7 +305,7 @@ const l = () => {
288
305
  };
289
306
  export {
290
307
  e as createProduct,
291
- d as createShop,
308
+ i as createShop,
292
309
  g as injectMocks
293
310
  };
294
311
  //# 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 } 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,EACtB,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} 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 } 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":"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"}
@@ -1,4 +1,4 @@
1
- import { s as r } from "../../../../../../../../_virtual/index5.js";
1
+ import { s as r } from "../../../../../../../../_virtual/index4.js";
2
2
  function s() {
3
3
  return r.useSyncExternalStore(
4
4
  e,
@@ -1,4 +1,4 @@
1
- import { __module as q } from "../../../../../../../../_virtual/index6.js";
1
+ import { __module as q } from "../../../../../../../../_virtual/index5.js";
2
2
  import { __require as F } from "../../../../../global@4.4.0/node_modules/global/window.js";
3
3
  import { __require as N } from "../../../../../@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/extends.js";
4
4
  import { __require as J } from "../../../../../is-function@1.0.2/node_modules/is-function/index.js";
@@ -2,7 +2,7 @@ import L from "../../../../@videojs_vhs-utils@4.1.1/node_modules/@videojs/vhs-ut
2
2
  import T from "../../../../../../../_virtual/window.js";
3
3
  import { forEachMediaGroup as Z } from "../../../../@videojs_vhs-utils@4.1.1/node_modules/@videojs/vhs-utils/es/media-groups.js";
4
4
  import J from "../../../../@videojs_vhs-utils@4.1.1/node_modules/@videojs/vhs-utils/es/decode-b64-to-uint8-array.js";
5
- import { l as Q } from "../../../../../../../_virtual/index7.js";
5
+ import { l as Q } from "../../../../../../../_virtual/index6.js";
6
6
  /*! @name mpd-parser @version 1.3.1 @license Apache-2.0 */
7
7
  const w = (e) => !!e && typeof e == "object", E = (...e) => e.reduce((n, t) => (typeof t != "object" || Object.keys(t).forEach((r) => {
8
8
  Array.isArray(n[r]) && Array.isArray(t[r]) ? n[r] = n[r].concat(t[r]) : w(n[r]) && w(t[r]) ? n[r] = E(n[r], t[r]) : n[r] = t[r];
@@ -1,4 +1,4 @@
1
- import { __exports as i } from "../../../../../../_virtual/index4.js";
1
+ import { __exports as i } from "../../../../../../_virtual/index7.js";
2
2
  var c;
3
3
  function d() {
4
4
  if (c) return i;
@@ -0,0 +1,10 @@
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
@@ -0,0 +1 @@
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;"}
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.24",
4
+ "version": "0.0.25",
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.7",
41
+ "@shopify/shop-minis-platform": "0.0.8",
42
42
  "@tailwindcss/vite": "4.1.8",
43
43
  "@types/url-parse": "1.4.9",
44
44
  "@types/video.js": "7.3.58",
@@ -0,0 +1,65 @@
1
+ import {useCallback} from 'react'
2
+
3
+ import {ContentVisibility} from '@shopify/shop-minis-platform'
4
+ import {CreateContentResponse} from '@shopify/shop-minis-platform/actions'
5
+
6
+ import {useHandleAction} from '../../internal/useHandleAction'
7
+ import {useShopActions} from '../../internal/useShopActions'
8
+ import {fileToDataUri} from '../../utils'
9
+ import {useImageUpload} from '../storage/useImageUpload'
10
+
11
+ interface CreateImageContentParams {
12
+ image: File
13
+ contentTitle: string
14
+ visibility?: ContentVisibility[] | null
15
+ }
16
+
17
+ interface UseCreateImageContentReturns {
18
+ /**
19
+ * Upload an image and create content.
20
+ */
21
+ createImageContent: (
22
+ params: CreateImageContentParams
23
+ ) => Promise<CreateContentResponse>
24
+ }
25
+
26
+ export const useCreateImageContent = (): UseCreateImageContentReturns => {
27
+ const {createContent} = useShopActions()
28
+ const {uploadImage} = useImageUpload()
29
+
30
+ const createImageContent = useCallback(
31
+ async (params: CreateImageContentParams) => {
32
+ const {image, contentTitle, visibility} = params
33
+
34
+ if (!image.type) {
35
+ throw new Error('Unable to determine file type')
36
+ }
37
+ if (!image.type.startsWith('image/')) {
38
+ throw new Error('Invalid file type: must be an image')
39
+ }
40
+
41
+ const [uploadImageResult] = await uploadImage([
42
+ {
43
+ mimeType: image.type,
44
+ uri: await fileToDataUri(image),
45
+ },
46
+ ])
47
+ const uploadImageUrl = uploadImageResult.imageUrl
48
+
49
+ if (!uploadImageUrl) {
50
+ throw new Error('Image upload failed')
51
+ }
52
+
53
+ return createContent({
54
+ title: contentTitle,
55
+ imageUrl: uploadImageUrl,
56
+ visibility,
57
+ })
58
+ },
59
+ [createContent, uploadImage]
60
+ )
61
+
62
+ return {
63
+ createImageContent: useHandleAction(createImageContent),
64
+ }
65
+ }
@@ -39,6 +39,7 @@ export * from './shop/useShopCartActions'
39
39
  export * from './shop/useRecommendedShops'
40
40
 
41
41
  // - Content Hooks
42
+ export * from './content/useCreateImageContent'
42
43
 
43
44
  // - Utility Hooks
44
45
  export * from './util/useErrorToast'
@@ -12,7 +12,7 @@ export interface UploadImageParams {
12
12
  /**
13
13
  * The size of the image in bytes.
14
14
  */
15
- fileSize: number
15
+ fileSize?: number
16
16
  /**
17
17
  * The URI of the image to upload.
18
18
  */
@@ -41,16 +41,29 @@ interface UseImageUploadReturns {
41
41
  uploadImage: (params: UploadImageParams[]) => Promise<UploadedImage[]>
42
42
  }
43
43
 
44
+ // Fetch file data and detect file sizes if not provided
45
+ // Works with file://, data:, and http(s):// URIs
46
+ const processFileData = async (image: UploadImageParams) => {
47
+ const response = await fetch(image.uri)
48
+ const blob = await response.blob()
49
+
50
+ return {
51
+ ...image,
52
+ fileSize: image.fileSize ?? blob.size,
53
+ fileBlob: blob,
54
+ }
55
+ }
56
+
44
57
  const uploadFileToGCS = async (
45
- image: UploadImageParams,
58
+ image: UploadImageParams & {fileSize: number; fileBlob: Blob},
46
59
  target: UploadTarget
47
60
  ) => {
48
61
  const formData = new FormData()
49
62
  target.parameters.forEach(({name, value}: {name: string; value: string}) => {
50
63
  formData.append(name, value)
51
64
  })
52
- // Append the actual file data last
53
- formData.append('file', new Blob([image.uri], {type: image.mimeType}))
65
+
66
+ formData.append('file', image.fileBlob)
54
67
 
55
68
  const uploadResponse = await fetch(target.url, {
56
69
  method: 'POST',
@@ -76,11 +89,16 @@ export const useImageUpload = (): UseImageUploadReturns => {
76
89
  throw new Error('Multiple image upload is not supported yet')
77
90
  }
78
91
 
92
+ const imageParams = params[0]
93
+ const processedImageParams = await processFileData(imageParams)
94
+
79
95
  const links = await createImageUploadLink({
80
- input: params.map(image => ({
81
- mimeType: image.mimeType,
82
- fileSize: image.fileSize,
83
- })),
96
+ input: [
97
+ {
98
+ mimeType: processedImageParams.mimeType,
99
+ fileSize: processedImageParams.fileSize,
100
+ },
101
+ ],
84
102
  })
85
103
 
86
104
  if (!links.ok) {
@@ -88,9 +106,8 @@ export const useImageUpload = (): UseImageUploadReturns => {
88
106
  }
89
107
 
90
108
  // Upload single file to GCS
91
- // TODO: Upload multiple files to GCS
92
109
  const {error: uploadError} = await uploadFileToGCS(
93
- params[0],
110
+ processedImageParams,
94
111
  links?.data?.targets?.[0]!
95
112
  )
96
113
 
@@ -110,7 +127,6 @@ export const useImageUpload = (): UseImageUploadReturns => {
110
127
  throw new Error(result.error.message)
111
128
  }
112
129
 
113
- // TODO: Add support for multiple files
114
130
  if (result.data?.files?.[0]?.fileStatus === 'READY') {
115
131
  return [
116
132
  {
package/src/mocks.ts CHANGED
@@ -405,6 +405,23 @@ function makeMockActions(): ShopActions {
405
405
  pageInfo: createPagination(),
406
406
  },
407
407
  previewProductInAr: undefined,
408
+ createContent: {
409
+ data: {
410
+ publicId: 'content-123',
411
+ externalId: null,
412
+ image: {
413
+ id: 'img-123',
414
+ url: 'https://example.com/content-image.jpg',
415
+ width: 800,
416
+ height: 600,
417
+ },
418
+ title: 'Mock Content',
419
+ description: 'This is a mock content item',
420
+ visibility: ['DISCOVERABLE'],
421
+ shareableUrl: 'https://example.com/content/123',
422
+ products: null,
423
+ },
424
+ },
408
425
  } as const
409
426
 
410
427
  const mock: Partial<ShopActions> = {}
@@ -0,0 +1,8 @@
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
+ }
@@ -1,3 +1,4 @@
1
1
  export * from './errors'
2
2
  export * from './merchant-card'
3
3
  export * from './parseUrl'
4
+ export * from './imageToDataUri'