jazz-tools 0.16.6 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/.svelte-kit/__package__/index.d.ts +1 -0
  2. package/.svelte-kit/__package__/index.d.ts.map +1 -1
  3. package/.svelte-kit/__package__/index.js +1 -0
  4. package/.svelte-kit/__package__/media/image.svelte +131 -0
  5. package/.svelte-kit/__package__/media/image.svelte.d.ts +10 -0
  6. package/.svelte-kit/__package__/media/image.svelte.d.ts.map +1 -0
  7. package/.svelte-kit/__package__/media/index.d.ts +2 -0
  8. package/.svelte-kit/__package__/media/index.d.ts.map +1 -0
  9. package/.svelte-kit/__package__/media/index.js +1 -0
  10. package/.svelte-kit/__package__/tests/media/image.svelte.test.d.ts +2 -0
  11. package/.svelte-kit/__package__/tests/media/image.svelte.test.d.ts.map +1 -0
  12. package/.svelte-kit/__package__/tests/media/image.svelte.test.js +430 -0
  13. package/.svelte-kit/__package__/tests/testUtils.d.ts +11 -0
  14. package/.svelte-kit/__package__/tests/testUtils.d.ts.map +1 -0
  15. package/.svelte-kit/__package__/tests/testUtils.js +17 -0
  16. package/.svelte-kit/__package__/tests/types.d.ts +3 -0
  17. package/.turbo/turbo-build.log +42 -46
  18. package/CHANGELOG.md +12 -0
  19. package/dist/{chunk-R2VNCMG6.js → chunk-2SH44VLX.js} +33 -38
  20. package/dist/chunk-2SH44VLX.js.map +1 -0
  21. package/dist/index.js +1 -1
  22. package/dist/media/chunk-BBSS3NEY.js +211 -0
  23. package/dist/media/chunk-BBSS3NEY.js.map +1 -0
  24. package/dist/media/create-image.d.ts +48 -0
  25. package/dist/media/create-image.d.ts.map +1 -0
  26. package/dist/media/create-image.test.d.ts +2 -0
  27. package/dist/media/create-image.test.d.ts.map +1 -0
  28. package/dist/media/index.browser.d.ts +15 -0
  29. package/dist/media/index.browser.d.ts.map +1 -0
  30. package/dist/media/index.browser.js +113 -0
  31. package/dist/media/index.browser.js.map +1 -0
  32. package/dist/media/index.d.ts +53 -0
  33. package/dist/media/index.d.ts.map +1 -0
  34. package/dist/media/index.js +13 -0
  35. package/dist/media/index.js.map +1 -0
  36. package/dist/media/index.native.d.ts +17 -0
  37. package/dist/media/index.native.d.ts.map +1 -0
  38. package/dist/media/index.native.js +126 -0
  39. package/dist/media/index.native.js.map +1 -0
  40. package/dist/media/utils.d.ts +17 -0
  41. package/dist/media/utils.d.ts.map +1 -0
  42. package/dist/media/utils.test.d.ts +2 -0
  43. package/dist/media/utils.test.d.ts.map +1 -0
  44. package/dist/react/index.d.ts +1 -2
  45. package/dist/react/index.d.ts.map +1 -1
  46. package/dist/react/index.js +176 -59
  47. package/dist/react/index.js.map +1 -1
  48. package/dist/react/media/image.d.ts +62 -0
  49. package/dist/react/media/image.d.ts.map +1 -0
  50. package/dist/react/tests/media/image.test.d.ts +2 -0
  51. package/dist/react/tests/media/image.test.d.ts.map +1 -0
  52. package/dist/react-core/tests/useDemoAuth.test.d.ts +2 -0
  53. package/dist/react-core/tests/useDemoAuth.test.d.ts.map +1 -0
  54. package/dist/react-native-core/index.d.ts +1 -1
  55. package/dist/react-native-core/index.d.ts.map +1 -1
  56. package/dist/react-native-core/index.js +84 -66
  57. package/dist/react-native-core/index.js.map +1 -1
  58. package/dist/react-native-core/media/image.d.ts +93 -0
  59. package/dist/react-native-core/media/image.d.ts.map +1 -0
  60. package/dist/react-native-core/testing.d.ts +2 -0
  61. package/dist/react-native-core/testing.d.ts.map +1 -0
  62. package/dist/svelte/index.d.ts +1 -0
  63. package/dist/svelte/index.d.ts.map +1 -1
  64. package/dist/svelte/index.js +1 -0
  65. package/dist/svelte/media/image.svelte +131 -0
  66. package/dist/svelte/media/image.svelte.d.ts +10 -0
  67. package/dist/svelte/media/image.svelte.d.ts.map +1 -0
  68. package/dist/svelte/media/index.d.ts +2 -0
  69. package/dist/svelte/media/index.d.ts.map +1 -0
  70. package/dist/svelte/media/index.js +1 -0
  71. package/dist/svelte/tests/media/image.svelte.test.d.ts +2 -0
  72. package/dist/svelte/tests/media/image.svelte.test.d.ts.map +1 -0
  73. package/dist/svelte/tests/media/image.svelte.test.js +430 -0
  74. package/dist/svelte/tests/testUtils.d.ts +11 -0
  75. package/dist/svelte/tests/testUtils.d.ts.map +1 -0
  76. package/dist/svelte/tests/testUtils.js +17 -0
  77. package/dist/svelte/tests/types.d.ts +3 -0
  78. package/dist/testing.js +1 -1
  79. package/dist/tools/coValues/coFeed.d.ts +15 -0
  80. package/dist/tools/coValues/coFeed.d.ts.map +1 -1
  81. package/dist/tools/coValues/extensions/imageDef.d.ts +3 -9
  82. package/dist/tools/coValues/extensions/imageDef.d.ts.map +1 -1
  83. package/dist/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts +1 -0
  84. package/dist/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.d.ts.map +1 -1
  85. package/package.json +12 -12
  86. package/src/media/create-image.test.ts +195 -0
  87. package/src/media/create-image.ts +180 -0
  88. package/src/media/index.browser.ts +150 -0
  89. package/src/media/index.native.ts +153 -0
  90. package/src/media/index.ts +61 -0
  91. package/src/media/utils.test.ts +327 -0
  92. package/src/media/utils.ts +202 -0
  93. package/src/react/index.ts +1 -2
  94. package/src/react/media/image.tsx +210 -0
  95. package/src/react/tests/media/image.test.tsx +588 -0
  96. package/src/react-native-core/index.ts +1 -1
  97. package/src/react-native-core/media/image.tsx +159 -0
  98. package/src/svelte/index.ts +1 -0
  99. package/src/svelte/media/image.svelte +131 -0
  100. package/src/svelte/media/index.ts +1 -0
  101. package/src/svelte/tests/media/image.svelte.test.ts +583 -0
  102. package/src/svelte/tests/testUtils.ts +33 -0
  103. package/src/svelte/tests/types.d.ts +3 -0
  104. package/src/tools/coValues/coFeed.ts +37 -5
  105. package/src/tools/coValues/extensions/imageDef.ts +3 -49
  106. package/src/tools/implementation/zodSchema/schemaTypes/FileStreamSchema.ts +6 -0
  107. package/src/tools/tests/coMap.record.test.ts +3 -2
  108. package/src/tools/tests/coOptional.test.ts +3 -1
  109. package/tsconfig.json +1 -0
  110. package/tsup.config.ts +4 -9
  111. package/vitest.config.ts +14 -1
  112. package/dist/browser-media-images/index.d.ts +0 -9
  113. package/dist/browser-media-images/index.d.ts.map +0 -1
  114. package/dist/browser-media-images/index.js +0 -72
  115. package/dist/browser-media-images/index.js.map +0 -1
  116. package/dist/chunk-R2VNCMG6.js.map +0 -1
  117. package/dist/react/media.d.ts +0 -24
  118. package/dist/react/media.d.ts.map +0 -1
  119. package/dist/react-native-core/media.d.ts +0 -24
  120. package/dist/react-native-core/media.d.ts.map +0 -1
  121. package/dist/react-native-media-images/index.d.ts +0 -7
  122. package/dist/react-native-media-images/index.d.ts.map +0 -1
  123. package/dist/react-native-media-images/index.js +0 -177
  124. package/dist/react-native-media-images/index.js.map +0 -1
  125. package/dist/tools/tests/imageDef.test.d.ts +0 -2
  126. package/dist/tools/tests/imageDef.test.d.ts.map +0 -1
  127. package/src/browser-media-images/index.ts +0 -131
  128. package/src/react/media.tsx +0 -74
  129. package/src/react/scratch.tsx +0 -50
  130. package/src/react-native-core/media.tsx +0 -79
  131. package/src/react-native-media-images/index.ts +0 -238
  132. package/src/tools/tests/imageDef.test.ts +0 -278
@@ -0,0 +1,126 @@
1
+ import {
2
+ createImageFactory,
3
+ highestResAvailable,
4
+ loadImage,
5
+ loadImageBySize
6
+ } from "./chunk-BBSS3NEY.js";
7
+
8
+ // src/media/index.native.ts
9
+ import ImageResizer from "@bam.tech/react-native-image-resizer";
10
+ import { FileStream } from "jazz-tools";
11
+ import { Image } from "react-native";
12
+ async function createImage(imageBlobOrFile, options) {
13
+ return createImageFactory({
14
+ getImageSize,
15
+ getPlaceholderBase64,
16
+ createFileStreamFromSource,
17
+ resize
18
+ })(imageBlobOrFile, options || {});
19
+ }
20
+ async function getImageSize(filePath) {
21
+ if (typeof filePath !== "string") {
22
+ throw new Error(
23
+ "createImage(Blob | File) is not supported on this platform"
24
+ );
25
+ }
26
+ const { width, height } = await Image.getSize(filePath);
27
+ return { width, height };
28
+ }
29
+ async function getPlaceholderBase64(filePath) {
30
+ if (typeof filePath !== "string") {
31
+ throw new Error(
32
+ "createImage(Blob | File) is not supported on this platform"
33
+ );
34
+ }
35
+ if (typeof ImageResizer === "undefined" || ImageResizer === null) {
36
+ throw new Error(
37
+ "ImageResizer is not installed, please run `npm install @bam.tech/react-native-image-resizer`"
38
+ );
39
+ }
40
+ const { uri } = await ImageResizer.createResizedImage(
41
+ filePath,
42
+ 8,
43
+ 8,
44
+ "PNG",
45
+ 100
46
+ );
47
+ return imageUrlToBase64(uri);
48
+ }
49
+ async function resize(filePath, width, height) {
50
+ if (typeof filePath !== "string") {
51
+ throw new Error(
52
+ "createImage(Blob | File) is not supported on this platform"
53
+ );
54
+ }
55
+ if (typeof ImageResizer === "undefined" || ImageResizer === null) {
56
+ throw new Error(
57
+ "ImageResizer is not installed, please run `npm install @bam.tech/react-native-image-resizer`"
58
+ );
59
+ }
60
+ const mimeType = await getMimeType(filePath);
61
+ const { uri } = await ImageResizer.createResizedImage(
62
+ filePath,
63
+ width,
64
+ height,
65
+ contentTypeToFormat(mimeType),
66
+ 80
67
+ );
68
+ return uri;
69
+ }
70
+ function getMimeType(filePath) {
71
+ return fetch(filePath).then((res) => res.blob()).then((blob) => blob.type);
72
+ }
73
+ function contentTypeToFormat(contentType) {
74
+ if (contentType.includes("image/png")) return "PNG";
75
+ if (contentType.includes("image/jpeg")) return "JPEG";
76
+ if (contentType.includes("image/webp")) return "WEBP";
77
+ return "PNG";
78
+ }
79
+ async function createFileStreamFromSource(filePath, owner) {
80
+ if (typeof filePath !== "string") {
81
+ throw new Error(
82
+ "createImage(Blob | File) is not supported on this platform"
83
+ );
84
+ }
85
+ const blob = await fetch(filePath).then((res) => res.blob());
86
+ const arrayBuffer = await toArrayBuffer(blob);
87
+ return FileStream.createFromArrayBuffer(arrayBuffer, blob.type, void 0, {
88
+ owner
89
+ });
90
+ }
91
+ function toArrayBuffer(blob) {
92
+ return new Promise((resolve, reject) => {
93
+ const reader = new FileReader();
94
+ reader.onloadend = () => {
95
+ resolve(reader.result);
96
+ };
97
+ reader.onerror = (error) => {
98
+ reject(error);
99
+ };
100
+ reader.readAsArrayBuffer(blob);
101
+ });
102
+ }
103
+ async function imageUrlToBase64(url) {
104
+ const response = await fetch(url);
105
+ const blob = await response.blob();
106
+ return new Promise((onSuccess, onError) => {
107
+ try {
108
+ const reader = new FileReader();
109
+ reader.onload = function() {
110
+ onSuccess(reader.result);
111
+ };
112
+ reader.readAsDataURL(blob);
113
+ } catch (e) {
114
+ onError(e);
115
+ }
116
+ });
117
+ }
118
+ export {
119
+ createFileStreamFromSource,
120
+ createImage,
121
+ createImageFactory,
122
+ highestResAvailable,
123
+ loadImage,
124
+ loadImageBySize
125
+ };
126
+ //# sourceMappingURL=index.native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/media/index.native.ts"],"sourcesContent":["import ImageResizer from \"@bam.tech/react-native-image-resizer\";\nimport type { Account, Group, ImageDefinition } from \"jazz-tools\";\nimport { FileStream } from \"jazz-tools\";\nimport { Image } from \"react-native\";\nimport {\n CreateImageOptions,\n SourceType,\n createImageFactory,\n} from \"./create-image.js\";\n\nexport { highestResAvailable, loadImage, loadImageBySize } from \"./utils.js\";\nexport { createImageFactory };\n\nexport async function createImage(\n imageBlobOrFile: Blob | File | string,\n options?: CreateImageOptions,\n) {\n return createImageFactory({\n getImageSize,\n getPlaceholderBase64,\n createFileStreamFromSource,\n resize,\n })(imageBlobOrFile, options || {});\n}\n\nasync function getImageSize(\n filePath: SourceType,\n): Promise<{ width: number; height: number }> {\n if (typeof filePath !== \"string\") {\n throw new Error(\n \"createImage(Blob | File) is not supported on this platform\",\n );\n }\n\n const { width, height } = await Image.getSize(filePath);\n\n return { width, height };\n}\n\nasync function getPlaceholderBase64(filePath: SourceType): Promise<string> {\n if (typeof filePath !== \"string\") {\n throw new Error(\n \"createImage(Blob | File) is not supported on this platform\",\n );\n }\n\n if (typeof ImageResizer === \"undefined\" || ImageResizer === null) {\n throw new Error(\n \"ImageResizer is not installed, please run `npm install @bam.tech/react-native-image-resizer`\",\n );\n }\n\n const { uri } = await ImageResizer.createResizedImage(\n filePath,\n 8,\n 8,\n \"PNG\",\n 100,\n );\n\n return imageUrlToBase64(uri);\n}\n\nasync function resize(\n filePath: SourceType,\n width: number,\n height: number,\n): Promise<string> {\n if (typeof filePath !== \"string\") {\n throw new Error(\n \"createImage(Blob | File) is not supported on this platform\",\n );\n }\n\n if (typeof ImageResizer === \"undefined\" || ImageResizer === null) {\n throw new Error(\n \"ImageResizer is not installed, please run `npm install @bam.tech/react-native-image-resizer`\",\n );\n }\n\n const mimeType = await getMimeType(filePath);\n\n const { uri } = await ImageResizer.createResizedImage(\n filePath,\n width,\n height,\n contentTypeToFormat(mimeType),\n 80,\n );\n\n return uri;\n}\n\nfunction getMimeType(filePath: string): Promise<string> {\n return fetch(filePath)\n .then((res) => res.blob())\n .then((blob) => blob.type);\n}\n\nfunction contentTypeToFormat(contentType: string) {\n if (contentType.includes(\"image/png\")) return \"PNG\";\n if (contentType.includes(\"image/jpeg\")) return \"JPEG\";\n if (contentType.includes(\"image/webp\")) return \"WEBP\";\n return \"PNG\";\n}\n\nexport async function createFileStreamFromSource(\n filePath: SourceType,\n owner?: Account | Group,\n): Promise<FileStream> {\n if (typeof filePath !== \"string\") {\n throw new Error(\n \"createImage(Blob | File) is not supported on this platform\",\n );\n }\n\n const blob = await fetch(filePath).then((res) => res.blob());\n const arrayBuffer = await toArrayBuffer(blob);\n\n return FileStream.createFromArrayBuffer(arrayBuffer, blob.type, undefined, {\n owner,\n });\n}\n\n// TODO: look for more efficient way to do this as React Native hasn't blob.arrayBuffer()\nfunction toArrayBuffer(blob: Blob): Promise<ArrayBuffer> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onloadend = () => {\n resolve(reader.result as ArrayBuffer);\n };\n reader.onerror = (error) => {\n reject(error);\n };\n reader.readAsArrayBuffer(blob);\n });\n}\n\nasync function imageUrlToBase64(url: string): Promise<string> {\n const response = await fetch(url);\n const blob = await response.blob();\n return new Promise((onSuccess, onError) => {\n try {\n const reader = new FileReader();\n reader.onload = function () {\n onSuccess(reader.result as string);\n };\n reader.readAsDataURL(blob);\n } catch (e) {\n onError(e);\n }\n });\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,17 @@
1
+ import { FileStream, ImageDefinition } from "jazz-tools";
2
+ export declare function highestResAvailable(image: ImageDefinition, wantedWidth: number, wantedHeight: number): {
3
+ width: number;
4
+ height: number;
5
+ image: FileStream;
6
+ } | null;
7
+ export declare function loadImage(imageOrId: ImageDefinition | string): Promise<{
8
+ width: number;
9
+ height: number;
10
+ image: FileStream;
11
+ } | null>;
12
+ export declare function loadImageBySize(imageOrId: ImageDefinition | string, wantedWidth: number, wantedHeight: number): Promise<{
13
+ width: number;
14
+ height: number;
15
+ image: FileStream;
16
+ } | null>;
17
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/media/utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAW,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElE,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,eAAe,EACtB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,GAAG,IAAI,CAuE7D;AA6BD,wBAAsB,SAAS,CAC7B,SAAS,EAAE,eAAe,GAAG,MAAM,GAClC,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,GAAG,IAAI,CAAC,CAmCtE;AAED,wBAAsB,eAAe,CACnC,SAAS,EAAE,eAAe,GAAG,MAAM,EACnC,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,GAAG,IAAI,CAAC,CAmDtE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=utils.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.test.d.ts","sourceRoot":"","sources":["../../src/media/utils.test.ts"],"names":[],"mappings":""}
@@ -3,6 +3,5 @@ export type { JazzProviderProps } from "./provider.js";
3
3
  export { useAccount, useCoState, useAcceptInvite, experimental_useInboxSender, useJazzContext, useAuthSecretStorage, } from "./hooks.js";
4
4
  export { createInviteLink, parseInviteLink } from "jazz-tools/browser";
5
5
  export * from "./auth/auth.js";
6
- export * from "./media.js";
7
- export { createImage } from "jazz-tools/browser-media-images";
6
+ export * from "./media/image.js";
8
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EACL,UAAU,EACV,UAAU,EACV,eAAe,EACf,2BAA2B,EAC3B,cAAc,EACd,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEvE,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EACL,UAAU,EACV,UAAU,EACV,eAAe,EACf,2BAA2B,EAC3B,cAAc,EACd,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEvE,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC"}
@@ -142,14 +142,14 @@ function RegisterClerkAuth(props) {
142
142
  return props.children;
143
143
  }
144
144
  var JazzReactProviderWithClerk = (props) => {
145
- const [isLoaded, setIsLoaded] = useState(false);
145
+ const [isLoaded2, setIsLoaded] = useState(false);
146
146
  useEffect3(() => {
147
147
  setupKvStore();
148
148
  JazzClerkAuth.initializeAuth(props.clerk).then(() => {
149
149
  setIsLoaded(true);
150
150
  });
151
151
  }, []);
152
- if (!isLoaded) {
152
+ if (!isLoaded2) {
153
153
  return null;
154
154
  }
155
155
  return /* @__PURE__ */ jsx2(JazzReactProvider, { ...props, logOutReplacement: props.clerk.signOut, children: /* @__PURE__ */ jsx2(RegisterClerkAuth, { clerk: props.clerk, children: props.children }) });
@@ -620,70 +620,188 @@ import {
620
620
  usePassphraseAuth as usePassphraseAuth2
621
621
  } from "jazz-tools/react-core";
622
622
 
623
- // src/react/media.tsx
624
- import { ImageDefinition } from "jazz-tools";
625
- import { useEffect as useEffect4, useState as useState5 } from "react";
626
- function useProgressiveImg({
627
- image,
628
- maxWidth,
629
- targetWidth
630
- }) {
631
- const [current, setCurrent] = useState5(void 0);
632
- useEffect4(() => {
633
- let lastHighestRes;
634
- if (!image) return;
635
- const unsub = image.subscribe({}, (update) => {
636
- const highestRes = ImageDefinition.highestResAvailable(update, {
637
- maxWidth,
638
- targetWidth
639
- });
640
- if (highestRes) {
641
- if (highestRes.res !== lastHighestRes) {
642
- lastHighestRes = highestRes.res;
643
- const blob = highestRes.stream.toBlob();
644
- if (blob) {
645
- const blobURI = URL.createObjectURL(blob);
646
- setCurrent({ src: blobURI, res: highestRes.res });
647
- return () => {
648
- setTimeout(() => URL.revokeObjectURL(blobURI), 200);
649
- };
650
- }
651
- }
652
- } else {
653
- setCurrent({
654
- src: update?.placeholderDataURL,
655
- res: "placeholder"
656
- });
657
- }
658
- });
659
- return unsub;
660
- }, [image?.id, maxWidth]);
661
- return {
662
- src: current?.src,
663
- res: current?.res,
664
- originalSize: image?.originalSize
665
- };
623
+ // src/react/media/image.tsx
624
+ import { ImageDefinition as ImageDefinition3 } from "jazz-tools";
625
+ import {
626
+ forwardRef,
627
+ useCallback,
628
+ useEffect as useEffect4,
629
+ useMemo as useMemo3,
630
+ useRef as useRef2,
631
+ useState as useState5
632
+ } from "react";
633
+
634
+ // src/media/create-image.ts
635
+ import {
636
+ ImageDefinition
637
+ } from "jazz-tools";
638
+
639
+ // src/media/utils.ts
640
+ import { Account as Account3, ImageDefinition as ImageDefinition2 } from "jazz-tools";
641
+ function highestResAvailable(image, wantedWidth, wantedHeight) {
642
+ const availableSizes = image._raw.keys().filter((key) => /^\d+x\d+$/.test(key)).map((key) => {
643
+ const [w, h] = key.split("x").map(Number);
644
+ return [w, h, key];
645
+ });
646
+ if (availableSizes.length === 0) {
647
+ return image.original ? {
648
+ width: image.originalSize[0],
649
+ height: image.originalSize[1],
650
+ image: image.original
651
+ } : null;
652
+ }
653
+ const sortedSizes = availableSizes.map((size) => {
654
+ return {
655
+ size,
656
+ match: sizesMatchWanted(size[0], size[1], wantedWidth, wantedHeight),
657
+ isLoaded: isLoaded(image._raw.get(size[2]))
658
+ };
659
+ }).sort((a, b) => a.match - b.match);
660
+ const bestLoaded = [...sortedSizes].reverse().find((el) => el.isLoaded && image[el.size[2]]?.getChunks());
661
+ const bestTarget = sortedSizes.find((el) => el.match > 0.95) || sortedSizes.at(-1);
662
+ if (image[bestTarget.size[2]]?.getChunks()) {
663
+ return image[bestTarget.size[2]] ? {
664
+ width: bestTarget.size[0],
665
+ height: bestTarget.size[1],
666
+ image: image[bestTarget.size[2]]
667
+ } : null;
668
+ }
669
+ if (bestLoaded) {
670
+ image[bestTarget.size[2]]?.getChunks();
671
+ return image[bestLoaded.size[2]] ? {
672
+ width: bestLoaded.size[0],
673
+ height: bestLoaded.size[1],
674
+ image: image[bestLoaded.size[2]]
675
+ } : null;
676
+ }
677
+ for (let size of sortedSizes) {
678
+ if (size.match <= bestTarget.match) {
679
+ image[size.size[2]]?.getChunks();
680
+ }
681
+ }
682
+ return null;
666
683
  }
667
- function ProgressiveImg({
668
- children,
669
- image,
670
- maxWidth,
671
- targetWidth
672
- }) {
673
- const result = useProgressiveImg({ image, maxWidth, targetWidth });
674
- return result ? children(result) : null;
684
+ function sizesMatchWanted(w, h, wantedW, wantedH) {
685
+ const area1 = w * h;
686
+ const area2 = wantedW * wantedH;
687
+ const areaRatio = area1 / area2;
688
+ return areaRatio;
689
+ }
690
+ function isLoaded(id) {
691
+ if (!id) {
692
+ return false;
693
+ }
694
+ return !!Account3.getMe()._raw.core.node.getLoaded(id);
675
695
  }
676
696
 
677
- // src/react/index.ts
678
- import { createImage } from "jazz-tools/browser-media-images";
697
+ // src/react/media/image.tsx
698
+ import { jsx as jsx6 } from "react/jsx-runtime";
699
+ var Image = forwardRef(function Image2({ imageId, width, height, ...props }, ref) {
700
+ const image = useCoState(ImageDefinition3, imageId);
701
+ const lastBestImage = useRef2(null);
702
+ const [waitingLazyLoading, setWaitingLazyLoading] = useState5(
703
+ props.loading === "lazy"
704
+ );
705
+ const lazyPlaceholder = useMemo3(
706
+ () => waitingLazyLoading ? URL.createObjectURL(emptyPixelBlob) : void 0,
707
+ [waitingLazyLoading]
708
+ );
709
+ const dimensions = useMemo3(() => {
710
+ const originalWidth = image?.originalSize?.[0];
711
+ const originalHeight = image?.originalSize?.[1];
712
+ if (width === "original" && height === "original") {
713
+ return { width: originalWidth, height: originalHeight };
714
+ }
715
+ if (width === "original" && typeof height === "number") {
716
+ if (originalWidth && originalHeight) {
717
+ return {
718
+ width: Math.round(height * originalWidth / originalHeight),
719
+ height
720
+ };
721
+ }
722
+ return { width: void 0, height };
723
+ }
724
+ if (height === "original" && typeof width === "number") {
725
+ if (originalWidth && originalHeight) {
726
+ return {
727
+ width,
728
+ height: Math.round(width * originalHeight / originalWidth)
729
+ };
730
+ }
731
+ return { width, height: void 0 };
732
+ }
733
+ return {
734
+ width: width === "original" ? originalWidth : width,
735
+ height: height === "original" ? originalHeight : height
736
+ };
737
+ }, [image?.originalSize, width, height]);
738
+ const src = useMemo3(() => {
739
+ if (waitingLazyLoading) {
740
+ return lazyPlaceholder;
741
+ }
742
+ if (!image) return void 0;
743
+ const bestImage = highestResAvailable(
744
+ image,
745
+ dimensions.width || dimensions.height || 9999,
746
+ dimensions.height || dimensions.width || 9999
747
+ );
748
+ if (!bestImage) return image.placeholderDataURL;
749
+ if (lastBestImage.current?.[0] === bestImage.image.id)
750
+ return lastBestImage.current?.[1];
751
+ const blob = bestImage.image.toBlob();
752
+ if (blob) {
753
+ const url = URL.createObjectURL(blob);
754
+ revokeObjectURL(lastBestImage.current?.[1]);
755
+ lastBestImage.current = [bestImage.image.id, url];
756
+ return url;
757
+ }
758
+ return image.placeholderDataURL;
759
+ }, [image, dimensions.width, dimensions.height, waitingLazyLoading]);
760
+ const onThresholdReached = useCallback(() => {
761
+ setWaitingLazyLoading(false);
762
+ }, []);
763
+ useEffect4(
764
+ () => () => {
765
+ if (process.env.NODE_ENV === "development") return;
766
+ revokeObjectURL(lastBestImage.current?.[1]);
767
+ },
768
+ []
769
+ );
770
+ return /* @__PURE__ */ jsx6(
771
+ "img",
772
+ {
773
+ ref,
774
+ src,
775
+ width: dimensions.width,
776
+ height: dimensions.height,
777
+ onLoad: waitingLazyLoading ? onThresholdReached : void 0,
778
+ ...props
779
+ }
780
+ );
781
+ });
782
+ function revokeObjectURL(url) {
783
+ if (url && url.startsWith("blob:")) {
784
+ URL.revokeObjectURL(url);
785
+ }
786
+ }
787
+ var emptyPixelBlob = new Blob(
788
+ [
789
+ Uint8Array.from(
790
+ atob(
791
+ "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg=="
792
+ ),
793
+ (c) => c.charCodeAt(0)
794
+ )
795
+ ],
796
+ { type: "image/png" }
797
+ );
679
798
  export {
680
799
  DemoAuthBasicUI,
800
+ Image,
681
801
  JazzReactProvider,
682
802
  JazzReactProviderWithClerk,
683
803
  PasskeyAuthBasicUI,
684
804
  PassphraseAuthBasicUI,
685
- ProgressiveImg,
686
- createImage,
687
805
  createInviteLink,
688
806
  experimental_useInboxSender,
689
807
  parseInviteLink,
@@ -695,7 +813,6 @@ export {
695
813
  useIsAuthenticated2 as useIsAuthenticated,
696
814
  useJazzContext2 as useJazzContext,
697
815
  usePasskeyAuth,
698
- usePassphraseAuth2 as usePassphraseAuth,
699
- useProgressiveImg
816
+ usePassphraseAuth2 as usePassphraseAuth
700
817
  };
701
818
  //# sourceMappingURL=index.js.map