jazz-tools 0.19.21 → 0.20.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 (223) hide show
  1. package/.svelte-kit/__package__/react.d.ts.map +1 -1
  2. package/.svelte-kit/__package__/react.tsx +5 -2
  3. package/.turbo/turbo-build.log +77 -89
  4. package/CHANGELOG.md +84 -0
  5. package/dist/better-auth/auth/react.d.ts.map +1 -1
  6. package/dist/better-auth/auth/react.js +5 -2
  7. package/dist/better-auth/auth/react.js.map +1 -1
  8. package/dist/browser/createBrowserContext.d.ts +1 -2
  9. package/dist/browser/createBrowserContext.d.ts.map +1 -1
  10. package/dist/browser/index.js +1 -8
  11. package/dist/browser/index.js.map +1 -1
  12. package/dist/browser/provideBrowserLockSession/SessionIDStorage.d.ts +1 -1
  13. package/dist/{chunk-QCTQH5RS.js → chunk-3CAPPS2F.js} +234 -101
  14. package/dist/chunk-3CAPPS2F.js.map +1 -0
  15. package/dist/{chunk-M2HGBOXS.js → chunk-K4D7IMFM.js} +3 -3
  16. package/dist/chunk-K4D7IMFM.js.map +1 -0
  17. package/dist/expo/auth/clerk/index.d.ts.map +1 -1
  18. package/dist/expo/index.js +5 -2
  19. package/dist/expo/index.js.map +1 -1
  20. package/dist/index.js +39 -2
  21. package/dist/index.js.map +1 -1
  22. package/dist/inspector/{chunk-YQNK5Y7B.js → chunk-MCTB5ZJC.js} +1 -1
  23. package/dist/inspector/chunk-MCTB5ZJC.js.map +1 -0
  24. package/dist/inspector/contexts/node.d.ts.map +1 -1
  25. package/dist/inspector/{custom-element-KYV64IOC.js → custom-element-5YWVZBWA.js} +1 -1
  26. package/dist/inspector/{custom-element-KYV64IOC.js.map → custom-element-5YWVZBWA.js.map} +1 -1
  27. package/dist/inspector/index.js +3 -3
  28. package/dist/inspector/index.js.map +1 -1
  29. package/dist/inspector/register-custom-element.js +1 -1
  30. package/dist/inspector/standalone.js +1 -1
  31. package/dist/media/{chunk-3LKBM3G3.js → chunk-IRL3KNPO.js} +2 -2
  32. package/dist/media/{chunk-3LKBM3G3.js.map → chunk-IRL3KNPO.js.map} +1 -1
  33. package/dist/media/create-image/react-native.d.ts +1 -1
  34. package/dist/media/create-image/react-native.d.ts.map +1 -1
  35. package/dist/media/index.browser.js +1 -1
  36. package/dist/media/index.js +1 -1
  37. package/dist/media/index.native.js +5 -5
  38. package/dist/media/index.native.js.map +1 -1
  39. package/dist/media/index.server.js +1 -1
  40. package/dist/react/auth/Clerk.d.ts.map +1 -1
  41. package/dist/react/hooks.d.ts +1 -1
  42. package/dist/react/hooks.d.ts.map +1 -1
  43. package/dist/react/index.js +61 -47
  44. package/dist/react/index.js.map +1 -1
  45. package/dist/react/provider.d.ts.map +1 -1
  46. package/dist/react/ssr.js +2 -2
  47. package/dist/react/ssr.js.map +1 -1
  48. package/dist/react-core/chunk-UOYH6JFJ.js +10 -0
  49. package/dist/react-core/chunk-UOYH6JFJ.js.map +1 -0
  50. package/dist/react-core/hooks.d.ts +3 -3
  51. package/dist/react-core/hooks.d.ts.map +1 -1
  52. package/dist/react-core/index.js +27 -25
  53. package/dist/react-core/index.js.map +1 -1
  54. package/dist/react-core/provider.d.ts +2 -3
  55. package/dist/react-core/provider.d.ts.map +1 -1
  56. package/dist/react-core/testing.d.ts.map +1 -1
  57. package/dist/react-core/testing.js +4 -10
  58. package/dist/react-core/testing.js.map +1 -1
  59. package/dist/react-native/index.js +61 -53
  60. package/dist/react-native/index.js.map +1 -1
  61. package/dist/react-native-core/ReactNativeContextManager.d.ts +0 -1
  62. package/dist/react-native-core/ReactNativeContextManager.d.ts.map +1 -1
  63. package/dist/react-native-core/hooks.d.ts +1 -1
  64. package/dist/react-native-core/hooks.d.ts.map +1 -1
  65. package/dist/react-native-core/index.js +58 -50
  66. package/dist/react-native-core/index.js.map +1 -1
  67. package/dist/react-native-core/platform.d.ts +0 -4
  68. package/dist/react-native-core/platform.d.ts.map +1 -1
  69. package/dist/react-native-core/provider.d.ts +2 -1
  70. package/dist/react-native-core/provider.d.ts.map +1 -1
  71. package/dist/svelte/jazz.class.svelte.d.ts.map +1 -1
  72. package/dist/svelte/jazz.class.svelte.js +2 -8
  73. package/dist/svelte/tests/AccountCoState.svelte.test.d.ts +2 -0
  74. package/dist/svelte/tests/AccountCoState.svelte.test.d.ts.map +1 -0
  75. package/dist/svelte/tests/AccountCoState.svelte.test.js +59 -0
  76. package/dist/svelte/tests/CoState.svelte.test.js +23 -0
  77. package/dist/svelte/tests/TestAccountCoStateWrapper.svelte +24 -0
  78. package/dist/svelte/tests/TestAccountCoStateWrapper.svelte.d.ts +11 -0
  79. package/dist/svelte/tests/TestAccountCoStateWrapper.svelte.d.ts.map +1 -0
  80. package/dist/testing.js +6 -6
  81. package/dist/testing.js.map +1 -1
  82. package/dist/tools/coValues/coList.d.ts +2 -2
  83. package/dist/tools/coValues/coList.d.ts.map +1 -1
  84. package/dist/tools/coValues/coMap.d.ts +2 -2
  85. package/dist/tools/coValues/deepLoading.d.ts +2 -2
  86. package/dist/tools/coValues/deepLoading.d.ts.map +1 -1
  87. package/dist/tools/coValues/interfaces.d.ts +32 -0
  88. package/dist/tools/coValues/interfaces.d.ts.map +1 -1
  89. package/dist/tools/exports.d.ts +2 -1
  90. package/dist/tools/exports.d.ts.map +1 -1
  91. package/dist/tools/implementation/ContextManager.d.ts.map +1 -1
  92. package/dist/tools/implementation/createContext.d.ts.map +1 -1
  93. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts +3 -2
  94. package/dist/tools/implementation/zodSchema/schemaTypes/AccountSchema.d.ts.map +1 -1
  95. package/dist/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.d.ts +3 -2
  96. package/dist/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.d.ts.map +1 -1
  97. package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts +3 -3
  98. package/dist/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.d.ts.map +1 -1
  99. package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts +3 -2
  100. package/dist/tools/implementation/zodSchema/schemaTypes/CoListSchema.d.ts.map +1 -1
  101. package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts +5 -2
  102. package/dist/tools/implementation/zodSchema/schemaTypes/CoMapSchema.d.ts.map +1 -1
  103. package/dist/tools/implementation/zodSchema/zodCo.d.ts.map +1 -1
  104. package/dist/tools/ssr.js +1 -1
  105. package/dist/tools/subscribe/JazzError.d.ts +3 -3
  106. package/dist/tools/subscribe/JazzError.d.ts.map +1 -1
  107. package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
  108. package/dist/tools/subscribe/types.d.ts +5 -1
  109. package/dist/tools/subscribe/types.d.ts.map +1 -1
  110. package/dist/tools/testing.d.ts +3 -3
  111. package/dist/tools/testing.d.ts.map +1 -1
  112. package/dist/tools/tests/deleteCoValues.test.d.ts +2 -0
  113. package/dist/tools/tests/deleteCoValues.test.d.ts.map +1 -0
  114. package/dist/tools/tests/deletedState.test.d.ts +2 -0
  115. package/dist/tools/tests/deletedState.test.d.ts.map +1 -0
  116. package/dist/worker/JazzMessageChannel.d.ts +36 -0
  117. package/dist/worker/JazzMessageChannel.d.ts.map +1 -0
  118. package/dist/worker/edge-wasm.js +2 -1
  119. package/dist/worker/edge-wasm.js.map +1 -1
  120. package/dist/worker/index.d.ts +7 -1
  121. package/dist/worker/index.d.ts.map +1 -1
  122. package/dist/worker/index.js +28 -17
  123. package/dist/worker/index.js.map +1 -1
  124. package/dist/worker/wasm.d.ts +2 -0
  125. package/dist/worker/wasm.d.ts.map +1 -0
  126. package/package.json +9 -28
  127. package/src/better-auth/auth/react.tsx +5 -2
  128. package/src/browser/createBrowserContext.ts +2 -5
  129. package/src/expo/auth/clerk/index.tsx +5 -2
  130. package/src/inspector/contexts/node.tsx +1 -2
  131. package/src/inspector/index.tsx +2 -2
  132. package/src/media/create-image/react-native.ts +9 -7
  133. package/src/media/create-image-factory.test.ts +1 -1
  134. package/src/media/create-image-factory.ts +1 -1
  135. package/src/react/auth/Clerk.tsx +5 -2
  136. package/src/react/auth/PasskeyAuth.tsx +2 -2
  137. package/src/react/hooks.tsx +3 -2
  138. package/src/react/provider.tsx +45 -41
  139. package/src/react-core/auth/DemoAuth.tsx +2 -2
  140. package/src/react-core/auth/PassphraseAuth.tsx +2 -2
  141. package/src/react-core/hooks.ts +26 -27
  142. package/src/react-core/provider.tsx +1 -5
  143. package/src/react-core/testing.tsx +3 -11
  144. package/src/react-core/tests/testUtils.tsx +2 -2
  145. package/src/react-core/tests/useAccount.selector.test.ts +2 -3
  146. package/src/react-core/tests/useAccount.test.ts +57 -7
  147. package/src/react-core/tests/useCoState.test.ts +37 -0
  148. package/src/react-core/tests/useInboxSender.test.ts +2 -5
  149. package/src/react-core/tests/useSuspenseAccount.test.tsx +68 -0
  150. package/src/react-core/tests/useSuspenseCoState.test.tsx +44 -0
  151. package/src/react-native-core/ReactNativeContextManager.ts +0 -3
  152. package/src/react-native-core/auth/usePasskeyAuth.tsx +2 -2
  153. package/src/react-native-core/hooks.tsx +3 -3
  154. package/src/react-native-core/platform.ts +2 -6
  155. package/src/react-native-core/provider.tsx +47 -43
  156. package/src/svelte/jazz.class.svelte.ts +2 -8
  157. package/src/svelte/tests/AccountCoState.svelte.test.ts +79 -0
  158. package/src/svelte/tests/CoState.svelte.test.ts +36 -0
  159. package/src/svelte/tests/TestAccountCoStateWrapper.svelte +24 -0
  160. package/src/tools/coValues/deepLoading.ts +2 -0
  161. package/src/tools/coValues/interfaces.ts +170 -32
  162. package/src/tools/exports.ts +6 -0
  163. package/src/tools/implementation/ContextManager.ts +2 -2
  164. package/src/tools/implementation/createContext.ts +4 -0
  165. package/src/tools/implementation/zodSchema/schemaTypes/AccountSchema.ts +30 -6
  166. package/src/tools/implementation/zodSchema/schemaTypes/CoDiscriminatedUnionSchema.ts +55 -7
  167. package/src/tools/implementation/zodSchema/schemaTypes/CoFeedSchema.ts +33 -14
  168. package/src/tools/implementation/zodSchema/schemaTypes/CoListSchema.ts +35 -6
  169. package/src/tools/implementation/zodSchema/schemaTypes/CoMapSchema.ts +35 -14
  170. package/src/tools/ssr/ssr.ts +2 -2
  171. package/src/tools/subscribe/CoValueCoreSubscription.ts +1 -0
  172. package/src/tools/subscribe/JazzError.ts +4 -1
  173. package/src/tools/subscribe/SubscriptionScope.ts +23 -0
  174. package/src/tools/subscribe/types.ts +5 -0
  175. package/src/tools/testing.ts +5 -5
  176. package/src/tools/tests/PassphraseAuth.test.ts +5 -5
  177. package/src/tools/tests/deleteCoValues.test.ts +231 -0
  178. package/src/tools/tests/deletedState.test.ts +110 -0
  179. package/src/tools/tests/request.test.ts +15 -2
  180. package/src/tools/tests/testStorage.ts +2 -2
  181. package/src/worker/JazzMessageChannel.ts +73 -0
  182. package/src/worker/edge-wasm.ts +2 -1
  183. package/src/worker/index.ts +36 -17
  184. package/src/worker/wasm.ts +1 -0
  185. package/tsup.config.ts +0 -4
  186. package/dist/browser/storageOptions.d.ts +0 -8
  187. package/dist/browser/storageOptions.d.ts.map +0 -1
  188. package/dist/browser/tests/storageOptions.test.d.ts +0 -2
  189. package/dist/browser/tests/storageOptions.test.d.ts.map +0 -1
  190. package/dist/chunk-M2HGBOXS.js.map +0 -1
  191. package/dist/chunk-QCTQH5RS.js.map +0 -1
  192. package/dist/expo/crypto.d.ts +0 -2
  193. package/dist/expo/crypto.d.ts.map +0 -1
  194. package/dist/expo/crypto.js +0 -6
  195. package/dist/expo/crypto.js.map +0 -1
  196. package/dist/inspector/chunk-YQNK5Y7B.js.map +0 -1
  197. package/dist/react-core/chunk-7DYMJ74I.js +0 -12
  198. package/dist/react-core/chunk-7DYMJ74I.js.map +0 -1
  199. package/dist/react-native/chunk-DGUM43GV.js +0 -11
  200. package/dist/react-native/chunk-DGUM43GV.js.map +0 -1
  201. package/dist/react-native/crypto.d.ts +0 -2
  202. package/dist/react-native/crypto.d.ts.map +0 -1
  203. package/dist/react-native/crypto.js +0 -8
  204. package/dist/react-native/crypto.js.map +0 -1
  205. package/dist/react-native-core/chunk-DGUM43GV.js +0 -11
  206. package/dist/react-native-core/chunk-DGUM43GV.js.map +0 -1
  207. package/dist/react-native-core/crypto/RNCrypto.d.ts +0 -2
  208. package/dist/react-native-core/crypto/RNCrypto.d.ts.map +0 -1
  209. package/dist/react-native-core/crypto/RNCrypto.js +0 -3
  210. package/dist/react-native-core/crypto/RNCrypto.js.map +0 -1
  211. package/dist/react-native-core/crypto/RNQuickCrypto.d.ts +0 -17
  212. package/dist/react-native-core/crypto/RNQuickCrypto.d.ts.map +0 -1
  213. package/dist/react-native-core/crypto/index.d.ts +0 -2
  214. package/dist/react-native-core/crypto/index.d.ts.map +0 -1
  215. package/dist/react-native-core/crypto.js +0 -89
  216. package/dist/react-native-core/crypto.js.map +0 -1
  217. package/src/browser/storageOptions.ts +0 -17
  218. package/src/browser/tests/storageOptions.test.ts +0 -33
  219. package/src/expo/crypto.ts +0 -1
  220. package/src/react-native/crypto.ts +0 -1
  221. package/src/react-native-core/crypto/RNCrypto.ts +0 -1
  222. package/src/react-native-core/crypto/RNQuickCrypto.ts +0 -122
  223. package/src/react-native-core/crypto/index.ts +0 -1
@@ -5,12 +5,12 @@ import {
5
5
  InMemoryRouterProvider,
6
6
  NodeProvider,
7
7
  PageStack
8
- } from "./chunk-YQNK5Y7B.js";
8
+ } from "./chunk-MCTB5ZJC.js";
9
9
 
10
10
  // src/inspector/index.tsx
11
11
  import React, { useEffect as useEffect2, useState as useState2 } from "react";
12
12
  import { setup } from "goober";
13
- import { useJazzContext } from "jazz-tools/react-core";
13
+ import { useJazzContextValue } from "jazz-tools/react-core";
14
14
 
15
15
  // src/inspector/in-app.tsx
16
16
  import { styled as styled2 } from "goober";
@@ -159,7 +159,7 @@ var InspectorContainer = styled2("div")`
159
159
  // src/inspector/index.tsx
160
160
  import { jsx as jsx3 } from "react/jsx-runtime";
161
161
  function JazzInspector({ position = "right" }) {
162
- const context = useJazzContext();
162
+ const context = useJazzContextValue();
163
163
  const localNode = context.node;
164
164
  const me = "me" in context ? context.me : void 0;
165
165
  const [isCSR, setIsCSR] = useState2(false);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/inspector/index.tsx","../../src/inspector/in-app.tsx","../../src/inspector/viewer/inspector-button.tsx","../../src/inspector/viewer/use-open-inspector.ts"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport { setup } from \"goober\";\nimport { useJazzContext } from \"jazz-tools/react-core\";\nimport { Account } from \"jazz-tools\";\nimport { InspectorInApp } from \"./in-app.js\";\nimport { Position } from \"./viewer/inspector-button.js\";\n\nexport function JazzInspector({ position = \"right\" }: { position?: Position }) {\n const context = useJazzContext<Account>();\n const localNode = context.node;\n const me = \"me\" in context ? context.me : undefined;\n\n const [isCSR, setIsCSR] = useState(false);\n useEffect(() => {\n setIsCSR(true);\n }, []);\n\n if (!isCSR) {\n return null;\n }\n\n return (\n <InspectorInApp\n position={position}\n localNode={localNode}\n accountId={me?.$jazz.raw.id}\n />\n );\n}\n\nsetup(React.createElement);\n","import { CoID, LocalNode, RawAccount } from \"cojson\";\nimport { styled } from \"goober\";\nimport { PageStack } from \"./viewer/page-stack.js\";\nimport { GlobalStyles } from \"./ui/global-styles.js\";\nimport { InspectorButton, type Position } from \"./viewer/inspector-button.js\";\nimport { useOpenInspector } from \"./viewer/use-open-inspector.js\";\nimport { NodeProvider } from \"./contexts/node.js\";\nimport { InMemoryRouterProvider } from \"./router/in-memory-router.js\";\nimport { Header } from \"./viewer/header.js\";\n\nexport function InspectorInApp({\n position = \"right\",\n localNode,\n accountId,\n}: {\n position?: Position;\n localNode?: LocalNode;\n accountId?: CoID<RawAccount>;\n}) {\n const [open, setOpen] = useOpenInspector();\n\n if (!open) {\n return (\n <InspectorButton position={position} onClick={() => setOpen(true)} />\n );\n }\n\n return (\n <NodeProvider localNode={localNode ?? null} accountID={accountId ?? null}>\n <InMemoryRouterProvider>\n <InspectorContainer as={GlobalStyles} style={{ zIndex: 999 }}>\n <Header\n showDeleteLocalData={true}\n showClose={true}\n onClose={() => setOpen(false)}\n />\n\n <PageStack />\n </InspectorContainer>\n </InMemoryRouterProvider>\n </NodeProvider>\n );\n}\n\nconst InspectorContainer = styled(\"div\")`\n position: fixed;\n height: 50vh;\n max-height: 800px;\n display: flex;\n flex-direction: column;\n bottom: 0;\n left: 0;\n width: 100%;\n background-color: white;\n border-top: 1px solid var(--j-border-color);\n color: var(--j-text-color);\n\n @media (prefers-color-scheme: dark) {\n background-color: var(--j-background);\n }\n`;\n","import { styled } from \"goober\";\nimport React from \"react\";\n\nexport type Position =\n | \"bottom right\"\n | \"bottom left\"\n | \"top right\"\n | \"top left\"\n | \"right\"\n | \"left\";\n\nconst StyledInspectorButton = styled(\"button\")<{ position: Position }>`\n position: fixed;\n width: 2.5rem;\n height: 2.5rem;\n background-color: white;\n box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);\n margin: 1rem;\n padding: 0.5rem !important;\n border: 1px solid #e5e3e4;\n border-radius: 0.375rem;\n z-index: 999;\n \n ${(props) => {\n switch (props.position) {\n case \"bottom right\":\n return \"bottom: 0; right: 0;\";\n case \"bottom left\":\n return \"bottom: 0; left: 0;\";\n case \"top right\":\n return \"top: 0; right: 0;\";\n case \"top left\":\n return \"top: 0; left: 0;\";\n case \"right\":\n return \"right: 0; top: 50%; transform: translateY(-50%);\";\n case \"left\":\n return \"left: 0; top: 50%; transform: translateY(-50%);\";\n default:\n return \"\";\n }\n }}\n`;\n\nconst JazzIcon = styled(\"svg\")`\n width: 100%;\n height: auto;\n position: relative;\n left: -1px;\n color: #146AFF;\n`;\n\nexport function InspectorButton({\n position = \"right\",\n ...buttonProps\n}: React.ComponentPropsWithoutRef<\"button\"> & { position?: Position }) {\n return (\n <StyledInspectorButton position={position} {...buttonProps}>\n <JazzIcon\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"119\"\n height=\"115\"\n viewBox=\"0 0 119 115\"\n fill=\"none\"\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M118.179 23.8277V0.167999C99.931 7.5527 79.9854 11.6192 59.0897 11.6192C47.1466 11.6192 35.5138 10.2908 24.331 7.7737V30.4076V60.1508C23.2955 59.4385 22.1568 58.8458 20.9405 58.3915C18.1732 57.358 15.128 57.0876 12.1902 57.6145C9.2524 58.1414 6.5539 59.4419 4.4358 61.3516C2.3178 63.2613 0.875401 65.6944 0.291001 68.3433C-0.293399 70.9921 0.00659978 73.7377 1.1528 76.2329C2.2991 78.728 4.2403 80.861 6.7308 82.361C9.2214 83.862 12.1495 84.662 15.1448 84.662C15.6054 84.662 15.8365 84.662 16.0314 84.659C26.5583 84.449 35.042 75.9656 35.2513 65.4386C35.2534 65.3306 35.2544 65.2116 35.2548 65.0486L35.2552 64.7149V64.5521V61.0762V32.1993C43.0533 33.2324 51.0092 33.7656 59.0897 33.7656C59.6696 33.7656 60.2489 33.7629 60.8276 33.7574V89.696C59.792 88.983 58.6533 88.391 57.437 87.936C54.6697 86.903 51.6246 86.632 48.6867 87.159C45.7489 87.686 43.0504 88.987 40.9323 90.896C38.8143 92.806 37.3719 95.239 36.7875 97.888C36.2032 100.537 36.5031 103.283 37.6494 105.778C38.7956 108.273 40.7368 110.405 43.2273 111.906C45.7179 113.406 48.646 114.207 51.6414 114.207C52.1024 114.207 52.3329 114.207 52.5279 114.203C63.0548 113.994 71.5385 105.51 71.7478 94.983C71.7517 94.788 71.7517 94.558 71.7517 94.097V90.621V33.3266C83.962 32.4768 95.837 30.4075 107.255 27.2397V59.9017C106.219 59.1894 105.081 58.5966 103.864 58.1424C101.097 57.1089 98.052 56.8384 95.114 57.3653C92.176 57.8922 89.478 59.1927 87.36 61.1025C85.242 63.0122 83.799 65.4453 83.215 68.0941C82.631 70.743 82.931 73.4886 84.077 75.9837C85.223 78.4789 87.164 80.612 89.655 82.112C92.145 83.612 95.073 84.413 98.069 84.413C98.53 84.413 98.76 84.413 98.955 84.409C109.482 84.2 117.966 75.7164 118.175 65.1895C118.179 64.9945 118.179 64.764 118.179 64.3029V60.8271V23.8277Z\"\n fill=\"currentColor\"\n />\n </JazzIcon>\n <span\n style={{\n position: \"absolute\",\n width: \"1px\",\n height: \"1px\",\n padding: \"0\",\n margin: \"-1px\",\n overflow: \"hidden\",\n clip: \"rect(0, 0, 0, 0)\",\n whiteSpace: \"nowrap\",\n border: \"0\",\n }}\n >\n Open Jazz Inspector\n </span>\n </StyledInspectorButton>\n );\n}\n","import { useEffect, useState } from \"react\";\n\nconst STORAGE_KEY = \"jazz-inspector-open\";\n\nexport function useOpenInspector() {\n const [open, setOpen] = useState(() => {\n // Initialize from localStorage if available\n if (typeof window === \"undefined\") return false;\n const stored = localStorage.getItem(STORAGE_KEY);\n return stored ? JSON.parse(stored) : false;\n });\n\n // Update localStorage when open state changes\n useEffect(() => {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(open));\n }, [open]);\n\n return [open, setOpen];\n}\n"],"mappings":"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","names":["useEffect","useState","styled","jsx","jsxs","styled","jsx","useState","useEffect"]}
1
+ {"version":3,"sources":["../../src/inspector/index.tsx","../../src/inspector/in-app.tsx","../../src/inspector/viewer/inspector-button.tsx","../../src/inspector/viewer/use-open-inspector.ts"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport { setup } from \"goober\";\nimport { useJazzContextValue } from \"jazz-tools/react-core\";\nimport { Account } from \"jazz-tools\";\nimport { InspectorInApp } from \"./in-app.js\";\nimport { Position } from \"./viewer/inspector-button.js\";\n\nexport function JazzInspector({ position = \"right\" }: { position?: Position }) {\n const context = useJazzContextValue<Account>();\n const localNode = context.node;\n const me = \"me\" in context ? context.me : undefined;\n\n const [isCSR, setIsCSR] = useState(false);\n useEffect(() => {\n setIsCSR(true);\n }, []);\n\n if (!isCSR) {\n return null;\n }\n\n return (\n <InspectorInApp\n position={position}\n localNode={localNode}\n accountId={me?.$jazz.raw.id}\n />\n );\n}\n\nsetup(React.createElement);\n","import { CoID, LocalNode, RawAccount } from \"cojson\";\nimport { styled } from \"goober\";\nimport { PageStack } from \"./viewer/page-stack.js\";\nimport { GlobalStyles } from \"./ui/global-styles.js\";\nimport { InspectorButton, type Position } from \"./viewer/inspector-button.js\";\nimport { useOpenInspector } from \"./viewer/use-open-inspector.js\";\nimport { NodeProvider } from \"./contexts/node.js\";\nimport { InMemoryRouterProvider } from \"./router/in-memory-router.js\";\nimport { Header } from \"./viewer/header.js\";\n\nexport function InspectorInApp({\n position = \"right\",\n localNode,\n accountId,\n}: {\n position?: Position;\n localNode?: LocalNode;\n accountId?: CoID<RawAccount>;\n}) {\n const [open, setOpen] = useOpenInspector();\n\n if (!open) {\n return (\n <InspectorButton position={position} onClick={() => setOpen(true)} />\n );\n }\n\n return (\n <NodeProvider localNode={localNode ?? null} accountID={accountId ?? null}>\n <InMemoryRouterProvider>\n <InspectorContainer as={GlobalStyles} style={{ zIndex: 999 }}>\n <Header\n showDeleteLocalData={true}\n showClose={true}\n onClose={() => setOpen(false)}\n />\n\n <PageStack />\n </InspectorContainer>\n </InMemoryRouterProvider>\n </NodeProvider>\n );\n}\n\nconst InspectorContainer = styled(\"div\")`\n position: fixed;\n height: 50vh;\n max-height: 800px;\n display: flex;\n flex-direction: column;\n bottom: 0;\n left: 0;\n width: 100%;\n background-color: white;\n border-top: 1px solid var(--j-border-color);\n color: var(--j-text-color);\n\n @media (prefers-color-scheme: dark) {\n background-color: var(--j-background);\n }\n`;\n","import { styled } from \"goober\";\nimport React from \"react\";\n\nexport type Position =\n | \"bottom right\"\n | \"bottom left\"\n | \"top right\"\n | \"top left\"\n | \"right\"\n | \"left\";\n\nconst StyledInspectorButton = styled(\"button\")<{ position: Position }>`\n position: fixed;\n width: 2.5rem;\n height: 2.5rem;\n background-color: white;\n box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);\n margin: 1rem;\n padding: 0.5rem !important;\n border: 1px solid #e5e3e4;\n border-radius: 0.375rem;\n z-index: 999;\n \n ${(props) => {\n switch (props.position) {\n case \"bottom right\":\n return \"bottom: 0; right: 0;\";\n case \"bottom left\":\n return \"bottom: 0; left: 0;\";\n case \"top right\":\n return \"top: 0; right: 0;\";\n case \"top left\":\n return \"top: 0; left: 0;\";\n case \"right\":\n return \"right: 0; top: 50%; transform: translateY(-50%);\";\n case \"left\":\n return \"left: 0; top: 50%; transform: translateY(-50%);\";\n default:\n return \"\";\n }\n }}\n`;\n\nconst JazzIcon = styled(\"svg\")`\n width: 100%;\n height: auto;\n position: relative;\n left: -1px;\n color: #146AFF;\n`;\n\nexport function InspectorButton({\n position = \"right\",\n ...buttonProps\n}: React.ComponentPropsWithoutRef<\"button\"> & { position?: Position }) {\n return (\n <StyledInspectorButton position={position} {...buttonProps}>\n <JazzIcon\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"119\"\n height=\"115\"\n viewBox=\"0 0 119 115\"\n fill=\"none\"\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M118.179 23.8277V0.167999C99.931 7.5527 79.9854 11.6192 59.0897 11.6192C47.1466 11.6192 35.5138 10.2908 24.331 7.7737V30.4076V60.1508C23.2955 59.4385 22.1568 58.8458 20.9405 58.3915C18.1732 57.358 15.128 57.0876 12.1902 57.6145C9.2524 58.1414 6.5539 59.4419 4.4358 61.3516C2.3178 63.2613 0.875401 65.6944 0.291001 68.3433C-0.293399 70.9921 0.00659978 73.7377 1.1528 76.2329C2.2991 78.728 4.2403 80.861 6.7308 82.361C9.2214 83.862 12.1495 84.662 15.1448 84.662C15.6054 84.662 15.8365 84.662 16.0314 84.659C26.5583 84.449 35.042 75.9656 35.2513 65.4386C35.2534 65.3306 35.2544 65.2116 35.2548 65.0486L35.2552 64.7149V64.5521V61.0762V32.1993C43.0533 33.2324 51.0092 33.7656 59.0897 33.7656C59.6696 33.7656 60.2489 33.7629 60.8276 33.7574V89.696C59.792 88.983 58.6533 88.391 57.437 87.936C54.6697 86.903 51.6246 86.632 48.6867 87.159C45.7489 87.686 43.0504 88.987 40.9323 90.896C38.8143 92.806 37.3719 95.239 36.7875 97.888C36.2032 100.537 36.5031 103.283 37.6494 105.778C38.7956 108.273 40.7368 110.405 43.2273 111.906C45.7179 113.406 48.646 114.207 51.6414 114.207C52.1024 114.207 52.3329 114.207 52.5279 114.203C63.0548 113.994 71.5385 105.51 71.7478 94.983C71.7517 94.788 71.7517 94.558 71.7517 94.097V90.621V33.3266C83.962 32.4768 95.837 30.4075 107.255 27.2397V59.9017C106.219 59.1894 105.081 58.5966 103.864 58.1424C101.097 57.1089 98.052 56.8384 95.114 57.3653C92.176 57.8922 89.478 59.1927 87.36 61.1025C85.242 63.0122 83.799 65.4453 83.215 68.0941C82.631 70.743 82.931 73.4886 84.077 75.9837C85.223 78.4789 87.164 80.612 89.655 82.112C92.145 83.612 95.073 84.413 98.069 84.413C98.53 84.413 98.76 84.413 98.955 84.409C109.482 84.2 117.966 75.7164 118.175 65.1895C118.179 64.9945 118.179 64.764 118.179 64.3029V60.8271V23.8277Z\"\n fill=\"currentColor\"\n />\n </JazzIcon>\n <span\n style={{\n position: \"absolute\",\n width: \"1px\",\n height: \"1px\",\n padding: \"0\",\n margin: \"-1px\",\n overflow: \"hidden\",\n clip: \"rect(0, 0, 0, 0)\",\n whiteSpace: \"nowrap\",\n border: \"0\",\n }}\n >\n Open Jazz Inspector\n </span>\n </StyledInspectorButton>\n );\n}\n","import { useEffect, useState } from \"react\";\n\nconst STORAGE_KEY = \"jazz-inspector-open\";\n\nexport function useOpenInspector() {\n const [open, setOpen] = useState(() => {\n // Initialize from localStorage if available\n if (typeof window === \"undefined\") return false;\n const stored = localStorage.getItem(STORAGE_KEY);\n return stored ? JSON.parse(stored) : false;\n });\n\n // Update localStorage when open state changes\n useEffect(() => {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(open));\n }, [open]);\n\n return [open, setOpen];\n}\n"],"mappings":"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","names":["useEffect","useState","styled","jsx","jsxs","styled","jsx","useState","useEffect"]}
@@ -1,5 +1,5 @@
1
1
  // src/inspector/register-custom-element.ts
2
2
  if (typeof window !== "undefined" && process.env.NODE_ENV === "development") {
3
- import("./custom-element-KYV64IOC.js");
3
+ import("./custom-element-5YWVZBWA.js");
4
4
  }
5
5
  //# sourceMappingURL=register-custom-element.js.map
@@ -12,7 +12,7 @@ import {
12
12
  NodeProvider,
13
13
  PageStack,
14
14
  useNode
15
- } from "./chunk-YQNK5Y7B.js";
15
+ } from "./chunk-MCTB5ZJC.js";
16
16
 
17
17
  // src/inspector/standalone.tsx
18
18
  import React2 from "react";
@@ -187,7 +187,7 @@ async function createImage(imageBlobOrFile, options, impl) {
187
187
  );
188
188
  if (options?.progressive) {
189
189
  imageCoValue.$jazz.set("progressive", true);
190
- const resizes = [256, 1024, 2048].filter(
190
+ const resizes = [256, 512, 1024, 2048].filter(
191
191
  (s) => s < Math.max(imageCoValue.originalSize[0], imageCoValue.originalSize[1])
192
192
  );
193
193
  for (const size of resizes) {
@@ -224,4 +224,4 @@ export {
224
224
  loadImageBySize,
225
225
  createImageFactory
226
226
  };
227
- //# sourceMappingURL=chunk-3LKBM3G3.js.map
227
+ //# sourceMappingURL=chunk-IRL3KNPO.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/media/utils.ts","../../src/media/create-image-factory.ts"],"sourcesContent":["import type { CoID } from \"cojson\";\nimport { Account, FileStream, ImageDefinition, MaybeLoaded } from \"jazz-tools\";\n\nexport function highestResAvailable(\n image: ImageDefinition,\n wantedWidth: number,\n wantedHeight: number,\n): { width: number; height: number; image: FileStream } | null {\n const availableSizes: [number, number, string][] = image.$jazz.raw\n .keys()\n .filter((key) => /^\\d+x\\d+$/.test(key))\n .map((key) => {\n const [w, h] = key.split(\"x\").map(Number) as [number, number];\n return [w, h, key];\n });\n\n if (availableSizes.length === 0) {\n return image.original.$isLoaded\n ? {\n width: image.originalSize[0],\n height: image.originalSize[1],\n image: image.original,\n }\n : null;\n }\n\n const sortedSizes = availableSizes\n .map((size) => {\n return {\n size,\n match: sizesMatchWanted(size[0], size[1], wantedWidth, wantedHeight),\n isLoaded: isLoaded(\n image.$jazz.raw.get(size[2]) as CoID<any> | undefined,\n ),\n };\n })\n .sort((a, b) => a.match - b.match);\n\n // We try to find the better already loaded image\n // note: `toReversed` is not available in react-native.\n const bestLoaded = [...sortedSizes]\n .reverse()\n .find((el) => el.isLoaded && getImageChunks(image[el.size[2]]));\n\n // if I can't find a good match, let's use the highest resolution\n const bestTarget =\n sortedSizes.find((el) => el.match > 0.95) || sortedSizes.at(-1);\n\n // if the best target is already loaded, we are done\n const bestTargetImage = image[bestTarget!.size[2]];\n if (getImageChunks(bestTargetImage)) {\n return bestTargetImage?.$isLoaded\n ? {\n width: bestTarget!.size[0],\n height: bestTarget!.size[1],\n image: bestTargetImage,\n }\n : null;\n }\n\n // if the best already loaded is not the best target\n // let's trigger the load of the best target\n if (bestLoaded) {\n getImageChunks(bestTargetImage);\n const bestLoadedImage = image[bestLoaded.size[2]];\n return bestLoadedImage?.$isLoaded\n ? {\n width: bestLoaded.size[0],\n height: bestLoaded.size[1],\n image: bestLoadedImage,\n }\n : null;\n }\n\n // if nothing is loaded, then start fetching all the images till the best\n for (let size of sortedSizes) {\n if (size.match <= bestTarget!.match) {\n getImageChunks(image[size.size[2]]);\n }\n }\n\n return null;\n}\n\nfunction getImageChunks(file: MaybeLoaded<FileStream> | undefined) {\n if (!file || !file.$isLoaded) {\n return undefined;\n }\n return file.getChunks();\n}\n\nfunction sizesMatchWanted(\n w: number,\n h: number,\n wantedW: number,\n wantedH: number,\n): number {\n const area1 = w * h;\n const area2 = wantedW * wantedH;\n\n const areaRatio = area1 / area2;\n\n // // Below 0.95 means the image is too small, we don't want to upscale it\n // if (areaRatio < 0.95) {\n // return 9999;\n // }\n\n return areaRatio;\n}\n\nfunction isLoaded(id: CoID<any> | null | undefined): boolean {\n if (!id) {\n return false;\n }\n\n return !!Account.getMe().$jazz.localNode.getLoaded(id);\n}\n\nexport async function loadImage(\n imageOrId: ImageDefinition | string,\n): Promise<{ width: number; height: number; image: FileStream } | null> {\n if (typeof imageOrId === \"string\") {\n const image = await ImageDefinition.load(imageOrId, {\n resolve: {\n original: true,\n },\n });\n\n if (!image.$isLoaded) {\n return null;\n }\n\n return {\n width: image.originalSize[0],\n height: image.originalSize[1],\n image: image.original,\n };\n }\n\n if (!imageOrId.original.$isLoaded) {\n console.warn(\"Unable to find the original image\");\n return null;\n }\n\n const loadedOriginal = await FileStream.load(imageOrId.original.$jazz.id);\n\n if (!loadedOriginal.$isLoaded) {\n console.warn(\"Unable to find the original image\");\n return null;\n }\n\n return {\n width: imageOrId.originalSize[0],\n height: imageOrId.originalSize[1],\n image: loadedOriginal,\n };\n}\n\nexport async function loadImageBySize(\n imageOrId: ImageDefinition | string,\n wantedWidth: number,\n wantedHeight: number,\n): Promise<{ width: number; height: number; image: FileStream } | null> {\n // @ts-expect-error The resolved type for CoMap does not include catchall properties\n const image: MaybeLoaded<ImageDefinition> =\n typeof imageOrId === \"string\"\n ? await ImageDefinition.load(imageOrId)\n : imageOrId;\n\n if (image.$isLoaded === false) {\n return null;\n }\n\n if (image.progressive === false) {\n return loadImage(imageOrId);\n }\n\n const availableSizes: [number, number, string][] = image.$jazz.raw\n .keys()\n .filter((key) => /^\\d+x\\d+$/.test(key))\n .map((key) => {\n const [w, h] = key.split(\"x\").map(Number) as [number, number];\n return [w, h, key];\n });\n\n if (availableSizes.length === 0) {\n return null;\n }\n\n const sortedSizes = availableSizes\n .map((size) => ({\n size,\n match: sizesMatchWanted(size[0], size[1], wantedWidth, wantedHeight),\n }))\n .sort((a, b) => a.match - b.match);\n\n const bestTarget =\n sortedSizes.find((el) => el.match > 0.95) || sortedSizes.at(-1)!;\n\n // The image's `wxh` keys reference FileStream.\n // image[bestTarget.size[2]] returns undefined if FileStream hasn't loaded yet.\n // Since we only need the file's ID to fetch it later, we check the raw _refs\n // which contain only the linked covalue's ID.\n const file = image.$jazz.refs[bestTarget.size[2]];\n\n if (!file) {\n return null;\n }\n\n const loadedFile = await FileStream.load(file.id);\n\n if (!loadedFile.$isLoaded) {\n return null;\n }\n\n return {\n width: bestTarget.size[0],\n height: bestTarget.size[1],\n image: loadedFile,\n };\n}\n","import {\n Account,\n FileStream,\n Group,\n ImageDefinition,\n type Loaded,\n} from \"jazz-tools\";\n\nexport type SourceType = Blob | File | string;\n\nexport type ResizeOutput = Blob | string;\n\nexport type CreateImageOptions = {\n /** The owner of the image. Can be either a Group or Account. If not specified, the current user will be the owner. */\n owner?: Group | Account;\n /**\n * Controls placeholder generation for the image.\n * - `\"blur\"`: Generates a blurred placeholder image (default)\n * - `false`: No placeholder is generated\n * @default \"blur\"\n */\n placeholder?: \"blur\" | false;\n /**\n * Maximum size constraint for the image. The image will be resized to fit within this size while maintaining aspect ratio.\n * If the image is smaller than maxSize in both dimensions, no resizing occurs.\n * @example 1024 // Resizes image to fit within 1024px in the largest dimension\n */\n maxSize?: number; // | [number, number];\n /**\n * The progressive loading pattern is a technique that allows images to load incrementally, starting with a small version and gradually replacing it with a larger version as it becomes available.\n * This is useful for improving the user experience by showing a placeholder while the image is loading.\n *\n * Passing progressive: true to createImage() will create internal smaller versions of the image for future uses.\n *\n * @default false\n */\n progressive?: boolean;\n};\n\nexport type CreateImageReturnType = Loaded<\n typeof ImageDefinition,\n { original: true }\n>;\n\nexport type CreateImageImpl<\n TSourceType = SourceType,\n TResizeOutput = ResizeOutput,\n> = {\n createFileStreamFromSource: (\n imageBlobOrFile: TSourceType | TResizeOutput,\n owner?: Group | Account,\n ) => Promise<FileStream>;\n getImageSize: (\n imageBlobOrFile: TSourceType,\n ) => Promise<{ width: number; height: number }>;\n getPlaceholderBase64: (imageBlobOrFile: TSourceType) => Promise<string>;\n resize: (\n imageBlobOrFile: TSourceType,\n width: number,\n height: number,\n ) => Promise<TResizeOutput>;\n};\n\nexport function createImageFactory<TSourceType, TResizeOutput>(\n impl: CreateImageImpl<TSourceType, TResizeOutput>,\n imageTypeGuard?: (imageBlobOrFile: TSourceType) => void,\n) {\n return (source: TSourceType, options?: CreateImageOptions) => {\n imageTypeGuard?.(source);\n return createImage(source, options ?? {}, impl);\n };\n}\n\nasync function createImage<TSourceType, TResizeOutput>(\n imageBlobOrFile: TSourceType,\n options: CreateImageOptions,\n impl: CreateImageImpl<TSourceType, TResizeOutput>,\n): Promise<CreateImageReturnType> {\n // Get the original size of the image\n const { width: originalWidth, height: originalHeight } =\n await impl.getImageSize(imageBlobOrFile);\n\n const def: {\n originalSize: [number, number];\n progressive: boolean;\n placeholderDataURL: string | undefined;\n original?: FileStream;\n files: Record<string, FileStream>;\n } = {\n originalSize: [originalWidth, originalHeight],\n progressive: false,\n placeholderDataURL: undefined,\n files: {},\n };\n\n // Placeholder\n if (options?.placeholder === \"blur\") {\n def.placeholderDataURL = await impl.getPlaceholderBase64(imageBlobOrFile);\n }\n\n /**\n * Original\n *\n * Save the original image.\n * If the maxSize is set, resize the image to the maxSize if needed\n */\n if (options?.maxSize === undefined) {\n def.original = await impl.createFileStreamFromSource(\n imageBlobOrFile,\n options?.owner,\n );\n def.files[`${originalWidth}x${originalHeight}`] = def.original;\n } else if (\n options?.maxSize >= originalWidth &&\n options?.maxSize >= originalHeight\n ) {\n // no resizes required, just return the original image\n def.original = await impl.createFileStreamFromSource(\n imageBlobOrFile,\n options?.owner,\n );\n def.files[`${originalWidth}x${originalHeight}`] = def.original;\n } else {\n const { width, height } = getNewDimensions(\n originalWidth,\n originalHeight,\n options.maxSize,\n );\n\n const blob = await impl.resize(imageBlobOrFile, width, height);\n def.originalSize = [width, height];\n def.original = await impl.createFileStreamFromSource(blob, options?.owner);\n def.files[`${width}x${height}`] = def.original;\n }\n\n const imageCoValue = ImageDefinition.create(\n {\n originalSize: def.originalSize,\n progressive: def.progressive,\n placeholderDataURL: def.placeholderDataURL,\n original: def.original,\n ...def.files,\n },\n options?.owner,\n );\n\n /**\n * Progressive loading\n *\n * Save a set of resized images using three sizes: 256, 1024, 2048\n *\n * On the client side, the image will be loaded progressively, starting from the smallest size and increasing the size until the original size is reached.\n */\n if (options?.progressive) {\n imageCoValue.$jazz.set(\"progressive\", true);\n\n const resizes = ([256, 1024, 2048] as const).filter(\n (s) =>\n s <\n Math.max(imageCoValue.originalSize[0], imageCoValue.originalSize[1]),\n );\n\n for (const size of resizes) {\n const { width, height } = getNewDimensions(\n originalWidth,\n originalHeight,\n size,\n );\n\n const blob = await impl.resize(imageBlobOrFile, width, height);\n imageCoValue.$jazz.set(\n `${width}x${height}`,\n await impl.createFileStreamFromSource(blob, options?.owner),\n );\n }\n }\n\n return imageCoValue;\n}\n\nconst getNewDimensions = (\n originalWidth: number,\n originalHeight: number,\n maxSize: number,\n) => {\n if (originalWidth > originalHeight) {\n return {\n width: maxSize,\n height: Math.round(maxSize * (originalHeight / originalWidth)),\n };\n }\n\n return {\n width: Math.round(maxSize * (originalWidth / originalHeight)),\n height: maxSize,\n };\n};\n"],"mappings":"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","names":["ImageDefinition"]}
1
+ {"version":3,"sources":["../../src/media/utils.ts","../../src/media/create-image-factory.ts"],"sourcesContent":["import type { CoID } from \"cojson\";\nimport { Account, FileStream, ImageDefinition, MaybeLoaded } from \"jazz-tools\";\n\nexport function highestResAvailable(\n image: ImageDefinition,\n wantedWidth: number,\n wantedHeight: number,\n): { width: number; height: number; image: FileStream } | null {\n const availableSizes: [number, number, string][] = image.$jazz.raw\n .keys()\n .filter((key) => /^\\d+x\\d+$/.test(key))\n .map((key) => {\n const [w, h] = key.split(\"x\").map(Number) as [number, number];\n return [w, h, key];\n });\n\n if (availableSizes.length === 0) {\n return image.original.$isLoaded\n ? {\n width: image.originalSize[0],\n height: image.originalSize[1],\n image: image.original,\n }\n : null;\n }\n\n const sortedSizes = availableSizes\n .map((size) => {\n return {\n size,\n match: sizesMatchWanted(size[0], size[1], wantedWidth, wantedHeight),\n isLoaded: isLoaded(\n image.$jazz.raw.get(size[2]) as CoID<any> | undefined,\n ),\n };\n })\n .sort((a, b) => a.match - b.match);\n\n // We try to find the better already loaded image\n // note: `toReversed` is not available in react-native.\n const bestLoaded = [...sortedSizes]\n .reverse()\n .find((el) => el.isLoaded && getImageChunks(image[el.size[2]]));\n\n // if I can't find a good match, let's use the highest resolution\n const bestTarget =\n sortedSizes.find((el) => el.match > 0.95) || sortedSizes.at(-1);\n\n // if the best target is already loaded, we are done\n const bestTargetImage = image[bestTarget!.size[2]];\n if (getImageChunks(bestTargetImage)) {\n return bestTargetImage?.$isLoaded\n ? {\n width: bestTarget!.size[0],\n height: bestTarget!.size[1],\n image: bestTargetImage,\n }\n : null;\n }\n\n // if the best already loaded is not the best target\n // let's trigger the load of the best target\n if (bestLoaded) {\n getImageChunks(bestTargetImage);\n const bestLoadedImage = image[bestLoaded.size[2]];\n return bestLoadedImage?.$isLoaded\n ? {\n width: bestLoaded.size[0],\n height: bestLoaded.size[1],\n image: bestLoadedImage,\n }\n : null;\n }\n\n // if nothing is loaded, then start fetching all the images till the best\n for (let size of sortedSizes) {\n if (size.match <= bestTarget!.match) {\n getImageChunks(image[size.size[2]]);\n }\n }\n\n return null;\n}\n\nfunction getImageChunks(file: MaybeLoaded<FileStream> | undefined) {\n if (!file || !file.$isLoaded) {\n return undefined;\n }\n return file.getChunks();\n}\n\nfunction sizesMatchWanted(\n w: number,\n h: number,\n wantedW: number,\n wantedH: number,\n): number {\n const area1 = w * h;\n const area2 = wantedW * wantedH;\n\n const areaRatio = area1 / area2;\n\n // // Below 0.95 means the image is too small, we don't want to upscale it\n // if (areaRatio < 0.95) {\n // return 9999;\n // }\n\n return areaRatio;\n}\n\nfunction isLoaded(id: CoID<any> | null | undefined): boolean {\n if (!id) {\n return false;\n }\n\n return !!Account.getMe().$jazz.localNode.getLoaded(id);\n}\n\nexport async function loadImage(\n imageOrId: ImageDefinition | string,\n): Promise<{ width: number; height: number; image: FileStream } | null> {\n if (typeof imageOrId === \"string\") {\n const image = await ImageDefinition.load(imageOrId, {\n resolve: {\n original: true,\n },\n });\n\n if (!image.$isLoaded) {\n return null;\n }\n\n return {\n width: image.originalSize[0],\n height: image.originalSize[1],\n image: image.original,\n };\n }\n\n if (!imageOrId.original.$isLoaded) {\n console.warn(\"Unable to find the original image\");\n return null;\n }\n\n const loadedOriginal = await FileStream.load(imageOrId.original.$jazz.id);\n\n if (!loadedOriginal.$isLoaded) {\n console.warn(\"Unable to find the original image\");\n return null;\n }\n\n return {\n width: imageOrId.originalSize[0],\n height: imageOrId.originalSize[1],\n image: loadedOriginal,\n };\n}\n\nexport async function loadImageBySize(\n imageOrId: ImageDefinition | string,\n wantedWidth: number,\n wantedHeight: number,\n): Promise<{ width: number; height: number; image: FileStream } | null> {\n // @ts-expect-error The resolved type for CoMap does not include catchall properties\n const image: MaybeLoaded<ImageDefinition> =\n typeof imageOrId === \"string\"\n ? await ImageDefinition.load(imageOrId)\n : imageOrId;\n\n if (image.$isLoaded === false) {\n return null;\n }\n\n if (image.progressive === false) {\n return loadImage(imageOrId);\n }\n\n const availableSizes: [number, number, string][] = image.$jazz.raw\n .keys()\n .filter((key) => /^\\d+x\\d+$/.test(key))\n .map((key) => {\n const [w, h] = key.split(\"x\").map(Number) as [number, number];\n return [w, h, key];\n });\n\n if (availableSizes.length === 0) {\n return null;\n }\n\n const sortedSizes = availableSizes\n .map((size) => ({\n size,\n match: sizesMatchWanted(size[0], size[1], wantedWidth, wantedHeight),\n }))\n .sort((a, b) => a.match - b.match);\n\n const bestTarget =\n sortedSizes.find((el) => el.match > 0.95) || sortedSizes.at(-1)!;\n\n // The image's `wxh` keys reference FileStream.\n // image[bestTarget.size[2]] returns undefined if FileStream hasn't loaded yet.\n // Since we only need the file's ID to fetch it later, we check the raw _refs\n // which contain only the linked covalue's ID.\n const file = image.$jazz.refs[bestTarget.size[2]];\n\n if (!file) {\n return null;\n }\n\n const loadedFile = await FileStream.load(file.id);\n\n if (!loadedFile.$isLoaded) {\n return null;\n }\n\n return {\n width: bestTarget.size[0],\n height: bestTarget.size[1],\n image: loadedFile,\n };\n}\n","import {\n Account,\n FileStream,\n Group,\n ImageDefinition,\n type Loaded,\n} from \"jazz-tools\";\n\nexport type SourceType = Blob | File | string;\n\nexport type ResizeOutput = Blob | string;\n\nexport type CreateImageOptions = {\n /** The owner of the image. Can be either a Group or Account. If not specified, the current user will be the owner. */\n owner?: Group | Account;\n /**\n * Controls placeholder generation for the image.\n * - `\"blur\"`: Generates a blurred placeholder image (default)\n * - `false`: No placeholder is generated\n * @default \"blur\"\n */\n placeholder?: \"blur\" | false;\n /**\n * Maximum size constraint for the image. The image will be resized to fit within this size while maintaining aspect ratio.\n * If the image is smaller than maxSize in both dimensions, no resizing occurs.\n * @example 1024 // Resizes image to fit within 1024px in the largest dimension\n */\n maxSize?: number; // | [number, number];\n /**\n * The progressive loading pattern is a technique that allows images to load incrementally, starting with a small version and gradually replacing it with a larger version as it becomes available.\n * This is useful for improving the user experience by showing a placeholder while the image is loading.\n *\n * Passing progressive: true to createImage() will create internal smaller versions of the image for future uses.\n *\n * @default false\n */\n progressive?: boolean;\n};\n\nexport type CreateImageReturnType = Loaded<\n typeof ImageDefinition,\n { original: true }\n>;\n\nexport type CreateImageImpl<\n TSourceType = SourceType,\n TResizeOutput = ResizeOutput,\n> = {\n createFileStreamFromSource: (\n imageBlobOrFile: TSourceType | TResizeOutput,\n owner?: Group | Account,\n ) => Promise<FileStream>;\n getImageSize: (\n imageBlobOrFile: TSourceType,\n ) => Promise<{ width: number; height: number }>;\n getPlaceholderBase64: (imageBlobOrFile: TSourceType) => Promise<string>;\n resize: (\n imageBlobOrFile: TSourceType,\n width: number,\n height: number,\n ) => Promise<TResizeOutput>;\n};\n\nexport function createImageFactory<TSourceType, TResizeOutput>(\n impl: CreateImageImpl<TSourceType, TResizeOutput>,\n imageTypeGuard?: (imageBlobOrFile: TSourceType) => void,\n) {\n return (source: TSourceType, options?: CreateImageOptions) => {\n imageTypeGuard?.(source);\n return createImage(source, options ?? {}, impl);\n };\n}\n\nasync function createImage<TSourceType, TResizeOutput>(\n imageBlobOrFile: TSourceType,\n options: CreateImageOptions,\n impl: CreateImageImpl<TSourceType, TResizeOutput>,\n): Promise<CreateImageReturnType> {\n // Get the original size of the image\n const { width: originalWidth, height: originalHeight } =\n await impl.getImageSize(imageBlobOrFile);\n\n const def: {\n originalSize: [number, number];\n progressive: boolean;\n placeholderDataURL: string | undefined;\n original?: FileStream;\n files: Record<string, FileStream>;\n } = {\n originalSize: [originalWidth, originalHeight],\n progressive: false,\n placeholderDataURL: undefined,\n files: {},\n };\n\n // Placeholder\n if (options?.placeholder === \"blur\") {\n def.placeholderDataURL = await impl.getPlaceholderBase64(imageBlobOrFile);\n }\n\n /**\n * Original\n *\n * Save the original image.\n * If the maxSize is set, resize the image to the maxSize if needed\n */\n if (options?.maxSize === undefined) {\n def.original = await impl.createFileStreamFromSource(\n imageBlobOrFile,\n options?.owner,\n );\n def.files[`${originalWidth}x${originalHeight}`] = def.original;\n } else if (\n options?.maxSize >= originalWidth &&\n options?.maxSize >= originalHeight\n ) {\n // no resizes required, just return the original image\n def.original = await impl.createFileStreamFromSource(\n imageBlobOrFile,\n options?.owner,\n );\n def.files[`${originalWidth}x${originalHeight}`] = def.original;\n } else {\n const { width, height } = getNewDimensions(\n originalWidth,\n originalHeight,\n options.maxSize,\n );\n\n const blob = await impl.resize(imageBlobOrFile, width, height);\n def.originalSize = [width, height];\n def.original = await impl.createFileStreamFromSource(blob, options?.owner);\n def.files[`${width}x${height}`] = def.original;\n }\n\n const imageCoValue = ImageDefinition.create(\n {\n originalSize: def.originalSize,\n progressive: def.progressive,\n placeholderDataURL: def.placeholderDataURL,\n original: def.original,\n ...def.files,\n },\n options?.owner,\n );\n\n /**\n * Progressive loading\n *\n * Save a set of resized images using three sizes: 256, 1024, 2048\n *\n * On the client side, the image will be loaded progressively, starting from the smallest size and increasing the size until the original size is reached.\n */\n if (options?.progressive) {\n imageCoValue.$jazz.set(\"progressive\", true);\n\n const resizes = ([256, 512, 1024, 2048] as const).filter(\n (s) =>\n s <\n Math.max(imageCoValue.originalSize[0], imageCoValue.originalSize[1]),\n );\n\n for (const size of resizes) {\n const { width, height } = getNewDimensions(\n originalWidth,\n originalHeight,\n size,\n );\n\n const blob = await impl.resize(imageBlobOrFile, width, height);\n imageCoValue.$jazz.set(\n `${width}x${height}`,\n await impl.createFileStreamFromSource(blob, options?.owner),\n );\n }\n }\n\n return imageCoValue;\n}\n\nconst getNewDimensions = (\n originalWidth: number,\n originalHeight: number,\n maxSize: number,\n) => {\n if (originalWidth > originalHeight) {\n return {\n width: maxSize,\n height: Math.round(maxSize * (originalHeight / originalWidth)),\n };\n }\n\n return {\n width: Math.round(maxSize * (originalWidth / originalHeight)),\n height: maxSize,\n };\n};\n"],"mappings":";AACA,SAAS,SAAS,YAAY,uBAAoC;AAE3D,SAAS,oBACd,OACA,aACA,cAC6D;AAC7D,QAAM,iBAA6C,MAAM,MAAM,IAC5D,KAAK,EACL,OAAO,CAAC,QAAQ,YAAY,KAAK,GAAG,CAAC,EACrC,IAAI,CAAC,QAAQ;AACZ,UAAM,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,GAAG,EAAE,IAAI,MAAM;AACxC,WAAO,CAAC,GAAG,GAAG,GAAG;AAAA,EACnB,CAAC;AAEH,MAAI,eAAe,WAAW,GAAG;AAC/B,WAAO,MAAM,SAAS,YAClB;AAAA,MACE,OAAO,MAAM,aAAa,CAAC;AAAA,MAC3B,QAAQ,MAAM,aAAa,CAAC;AAAA,MAC5B,OAAO,MAAM;AAAA,IACf,IACA;AAAA,EACN;AAEA,QAAM,cAAc,eACjB,IAAI,CAAC,SAAS;AACb,WAAO;AAAA,MACL;AAAA,MACA,OAAO,iBAAiB,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,aAAa,YAAY;AAAA,MACnE,UAAU;AAAA,QACR,MAAM,MAAM,IAAI,IAAI,KAAK,CAAC,CAAC;AAAA,MAC7B;AAAA,IACF;AAAA,EACF,CAAC,EACA,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAInC,QAAM,aAAa,CAAC,GAAG,WAAW,EAC/B,QAAQ,EACR,KAAK,CAAC,OAAO,GAAG,YAAY,eAAe,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;AAGhE,QAAM,aACJ,YAAY,KAAK,CAAC,OAAO,GAAG,QAAQ,IAAI,KAAK,YAAY,GAAG,EAAE;AAGhE,QAAM,kBAAkB,MAAM,WAAY,KAAK,CAAC,CAAC;AACjD,MAAI,eAAe,eAAe,GAAG;AACnC,WAAO,iBAAiB,YACpB;AAAA,MACE,OAAO,WAAY,KAAK,CAAC;AAAA,MACzB,QAAQ,WAAY,KAAK,CAAC;AAAA,MAC1B,OAAO;AAAA,IACT,IACA;AAAA,EACN;AAIA,MAAI,YAAY;AACd,mBAAe,eAAe;AAC9B,UAAM,kBAAkB,MAAM,WAAW,KAAK,CAAC,CAAC;AAChD,WAAO,iBAAiB,YACpB;AAAA,MACE,OAAO,WAAW,KAAK,CAAC;AAAA,MACxB,QAAQ,WAAW,KAAK,CAAC;AAAA,MACzB,OAAO;AAAA,IACT,IACA;AAAA,EACN;AAGA,WAAS,QAAQ,aAAa;AAC5B,QAAI,KAAK,SAAS,WAAY,OAAO;AACnC,qBAAe,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC;AAAA,IACpC;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,eAAe,MAA2C;AACjE,MAAI,CAAC,QAAQ,CAAC,KAAK,WAAW;AAC5B,WAAO;AAAA,EACT;AACA,SAAO,KAAK,UAAU;AACxB;AAEA,SAAS,iBACP,GACA,GACA,SACA,SACQ;AACR,QAAM,QAAQ,IAAI;AAClB,QAAM,QAAQ,UAAU;AAExB,QAAM,YAAY,QAAQ;AAO1B,SAAO;AACT;AAEA,SAAS,SAAS,IAA2C;AAC3D,MAAI,CAAC,IAAI;AACP,WAAO;AAAA,EACT;AAEA,SAAO,CAAC,CAAC,QAAQ,MAAM,EAAE,MAAM,UAAU,UAAU,EAAE;AACvD;AAEA,eAAsB,UACpB,WACsE;AACtE,MAAI,OAAO,cAAc,UAAU;AACjC,UAAM,QAAQ,MAAM,gBAAgB,KAAK,WAAW;AAAA,MAClD,SAAS;AAAA,QACP,UAAU;AAAA,MACZ;AAAA,IACF,CAAC;AAED,QAAI,CAAC,MAAM,WAAW;AACpB,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,MACL,OAAO,MAAM,aAAa,CAAC;AAAA,MAC3B,QAAQ,MAAM,aAAa,CAAC;AAAA,MAC5B,OAAO,MAAM;AAAA,IACf;AAAA,EACF;AAEA,MAAI,CAAC,UAAU,SAAS,WAAW;AACjC,YAAQ,KAAK,mCAAmC;AAChD,WAAO;AAAA,EACT;AAEA,QAAM,iBAAiB,MAAM,WAAW,KAAK,UAAU,SAAS,MAAM,EAAE;AAExE,MAAI,CAAC,eAAe,WAAW;AAC7B,YAAQ,KAAK,mCAAmC;AAChD,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,OAAO,UAAU,aAAa,CAAC;AAAA,IAC/B,QAAQ,UAAU,aAAa,CAAC;AAAA,IAChC,OAAO;AAAA,EACT;AACF;AAEA,eAAsB,gBACpB,WACA,aACA,cACsE;AAEtE,QAAM,QACJ,OAAO,cAAc,WACjB,MAAM,gBAAgB,KAAK,SAAS,IACpC;AAEN,MAAI,MAAM,cAAc,OAAO;AAC7B,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,gBAAgB,OAAO;AAC/B,WAAO,UAAU,SAAS;AAAA,EAC5B;AAEA,QAAM,iBAA6C,MAAM,MAAM,IAC5D,KAAK,EACL,OAAO,CAAC,QAAQ,YAAY,KAAK,GAAG,CAAC,EACrC,IAAI,CAAC,QAAQ;AACZ,UAAM,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,GAAG,EAAE,IAAI,MAAM;AACxC,WAAO,CAAC,GAAG,GAAG,GAAG;AAAA,EACnB,CAAC;AAEH,MAAI,eAAe,WAAW,GAAG;AAC/B,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,eACjB,IAAI,CAAC,UAAU;AAAA,IACd;AAAA,IACA,OAAO,iBAAiB,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,aAAa,YAAY;AAAA,EACrE,EAAE,EACD,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAEnC,QAAM,aACJ,YAAY,KAAK,CAAC,OAAO,GAAG,QAAQ,IAAI,KAAK,YAAY,GAAG,EAAE;AAMhE,QAAM,OAAO,MAAM,MAAM,KAAK,WAAW,KAAK,CAAC,CAAC;AAEhD,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,MAAM,WAAW,KAAK,KAAK,EAAE;AAEhD,MAAI,CAAC,WAAW,WAAW;AACzB,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,OAAO,WAAW,KAAK,CAAC;AAAA,IACxB,QAAQ,WAAW,KAAK,CAAC;AAAA,IACzB,OAAO;AAAA,EACT;AACF;;;AC5NA;AAAA,EAIE,mBAAAA;AAAA,OAEK;AAyDA,SAAS,mBACd,MACA,gBACA;AACA,SAAO,CAAC,QAAqB,YAAiC;AAC5D,qBAAiB,MAAM;AACvB,WAAO,YAAY,QAAQ,WAAW,CAAC,GAAG,IAAI;AAAA,EAChD;AACF;AAEA,eAAe,YACb,iBACA,SACA,MACgC;AAEhC,QAAM,EAAE,OAAO,eAAe,QAAQ,eAAe,IACnD,MAAM,KAAK,aAAa,eAAe;AAEzC,QAAM,MAMF;AAAA,IACF,cAAc,CAAC,eAAe,cAAc;AAAA,IAC5C,aAAa;AAAA,IACb,oBAAoB;AAAA,IACpB,OAAO,CAAC;AAAA,EACV;AAGA,MAAI,SAAS,gBAAgB,QAAQ;AACnC,QAAI,qBAAqB,MAAM,KAAK,qBAAqB,eAAe;AAAA,EAC1E;AAQA,MAAI,SAAS,YAAY,QAAW;AAClC,QAAI,WAAW,MAAM,KAAK;AAAA,MACxB;AAAA,MACA,SAAS;AAAA,IACX;AACA,QAAI,MAAM,GAAG,aAAa,IAAI,cAAc,EAAE,IAAI,IAAI;AAAA,EACxD,WACE,SAAS,WAAW,iBACpB,SAAS,WAAW,gBACpB;AAEA,QAAI,WAAW,MAAM,KAAK;AAAA,MACxB;AAAA,MACA,SAAS;AAAA,IACX;AACA,QAAI,MAAM,GAAG,aAAa,IAAI,cAAc,EAAE,IAAI,IAAI;AAAA,EACxD,OAAO;AACL,UAAM,EAAE,OAAO,OAAO,IAAI;AAAA,MACxB;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,IACV;AAEA,UAAM,OAAO,MAAM,KAAK,OAAO,iBAAiB,OAAO,MAAM;AAC7D,QAAI,eAAe,CAAC,OAAO,MAAM;AACjC,QAAI,WAAW,MAAM,KAAK,2BAA2B,MAAM,SAAS,KAAK;AACzE,QAAI,MAAM,GAAG,KAAK,IAAI,MAAM,EAAE,IAAI,IAAI;AAAA,EACxC;AAEA,QAAM,eAAeA,iBAAgB;AAAA,IACnC;AAAA,MACE,cAAc,IAAI;AAAA,MAClB,aAAa,IAAI;AAAA,MACjB,oBAAoB,IAAI;AAAA,MACxB,UAAU,IAAI;AAAA,MACd,GAAG,IAAI;AAAA,IACT;AAAA,IACA,SAAS;AAAA,EACX;AASA,MAAI,SAAS,aAAa;AACxB,iBAAa,MAAM,IAAI,eAAe,IAAI;AAE1C,UAAM,UAAW,CAAC,KAAK,KAAK,MAAM,IAAI,EAAY;AAAA,MAChD,CAAC,MACC,IACA,KAAK,IAAI,aAAa,aAAa,CAAC,GAAG,aAAa,aAAa,CAAC,CAAC;AAAA,IACvE;AAEA,eAAW,QAAQ,SAAS;AAC1B,YAAM,EAAE,OAAO,OAAO,IAAI;AAAA,QACxB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,YAAM,OAAO,MAAM,KAAK,OAAO,iBAAiB,OAAO,MAAM;AAC7D,mBAAa,MAAM;AAAA,QACjB,GAAG,KAAK,IAAI,MAAM;AAAA,QAClB,MAAM,KAAK,2BAA2B,MAAM,SAAS,KAAK;AAAA,MAC5D;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,IAAM,mBAAmB,CACvB,eACA,gBACA,YACG;AACH,MAAI,gBAAgB,gBAAgB;AAClC,WAAO;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,KAAK,MAAM,WAAW,iBAAiB,cAAc;AAAA,IAC/D;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,KAAK,MAAM,WAAW,gBAAgB,eAAe;AAAA,IAC5D,QAAQ;AAAA,EACV;AACF;","names":["ImageDefinition"]}
@@ -1,5 +1,5 @@
1
1
  import type { Account, Group } from "jazz-tools";
2
- import { FileStream } from "jazz-tools";
2
+ import { type FileStream } from "jazz-tools";
3
3
  /**
4
4
  * Creates an ImageDefinition from an image file path with built-in UX features.
5
5
  *
@@ -1 +1 @@
1
- {"version":3,"file":"react-native.d.ts","sourceRoot":"","sources":["../../../src/media/create-image/react-native.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAIxC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,WAAW;;;;;;;;;+BAcvB,CAAC;AAqHF,wBAAsB,0BAA0B,CAC9C,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,OAAO,GAAG,KAAK,GACtB,OAAO,CAAC,UAAU,CAAC,CAOrB"}
1
+ {"version":3,"file":"react-native.d.ts","sourceRoot":"","sources":["../../../src/media/create-image/react-native.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAM,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAIjD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,WAAW;;;;;;;;;+BAcvB,CAAC;AAsHF,wBAAsB,0BAA0B,CAC9C,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,OAAO,GAAG,KAAK,GACtB,OAAO,CAAC,UAAU,CAAC,CASrB"}
@@ -3,7 +3,7 @@ import {
3
3
  highestResAvailable,
4
4
  loadImage,
5
5
  loadImageBySize
6
- } from "./chunk-3LKBM3G3.js";
6
+ } from "./chunk-IRL3KNPO.js";
7
7
 
8
8
  // src/media/create-image/browser.ts
9
9
  import { FileStream } from "jazz-tools";
@@ -3,7 +3,7 @@ import {
3
3
  highestResAvailable,
4
4
  loadImage,
5
5
  loadImageBySize
6
- } from "./chunk-3LKBM3G3.js";
6
+ } from "./chunk-IRL3KNPO.js";
7
7
  export {
8
8
  createImageFactory,
9
9
  highestResAvailable,
@@ -3,10 +3,10 @@ import {
3
3
  highestResAvailable,
4
4
  loadImage,
5
5
  loadImageBySize
6
- } from "./chunk-3LKBM3G3.js";
6
+ } from "./chunk-IRL3KNPO.js";
7
7
 
8
8
  // src/media/create-image/react-native.ts
9
- import { FileStream } from "jazz-tools";
9
+ import { co } from "jazz-tools";
10
10
  import { Image } from "react-native";
11
11
  var createImage = createImageFactory(
12
12
  {
@@ -71,7 +71,7 @@ async function getPlaceholderBase64(filePath) {
71
71
  "Failed to get generate placeholder using expo-image-manipulator"
72
72
  );
73
73
  }
74
- return base64;
74
+ return "data:image/png;base64," + base64;
75
75
  }
76
76
  }
77
77
  async function resize(filePath, width, height) {
@@ -98,7 +98,7 @@ async function resize(filePath, width, height) {
98
98
  return result.uri;
99
99
  }
100
100
  }
101
- function getMimeType(filePath) {
101
+ async function getMimeType(filePath) {
102
102
  return fetch(filePath).then((res) => res.blob()).then((blob) => blob.type);
103
103
  }
104
104
  function contentTypeToFormat(contentType) {
@@ -110,7 +110,7 @@ function contentTypeToFormat(contentType) {
110
110
  async function createFileStreamFromSource(filePath, owner) {
111
111
  const blob = await fetch(filePath).then((res) => res.blob());
112
112
  const arrayBuffer = await toArrayBuffer(blob);
113
- return FileStream.createFromArrayBuffer(arrayBuffer, blob.type, void 0, {
113
+ return co.fileStream().createFromArrayBuffer(arrayBuffer, blob.type, void 0, {
114
114
  owner
115
115
  });
116
116
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/media/create-image/react-native.ts"],"sourcesContent":["import { NativeModules } from \"react-native\";\nimport type ImageResizerType from \"@bam.tech/react-native-image-resizer\";\nimport type ImageManipulatorType from \"expo-image-manipulator\";\nimport type { Account, Group } from \"jazz-tools\";\nimport { FileStream } from \"jazz-tools\";\nimport { Image } from \"react-native\";\nimport { createImageFactory } from \"../create-image-factory\";\n\n/**\n * Creates an ImageDefinition from an image file path with built-in UX features.\n *\n * This function creates a specialized CoValue for managing images in Jazz applications.\n * It supports blurry placeholders, built-in resizing, and progressive loading patterns.\n *\n * @returns Promise that resolves to an ImageDefinition\n *\n * @example\n * ```ts\n * import { createImage } from \"jazz-tools/media\";\n *\n * async function uploadImageFromCamera(imagePath: string) {\n * const image = await createImage(imagePath, {\n * maxSize: 800,\n * placeholder: \"blur\",\n * progressive: false,\n * });\n *\n * return image;\n * }\n * ```\n */\nexport const createImage = createImageFactory(\n {\n getImageSize,\n getPlaceholderBase64,\n createFileStreamFromSource,\n resize,\n },\n (filePath) => {\n if (typeof filePath !== \"string\") {\n throw new Error(\n \"createImage(Blob | File) is not supported on this platform\",\n );\n }\n },\n);\n\nasync function getResizer(): Promise<\n typeof ImageResizerType | typeof ImageManipulatorType\n> {\n try {\n const rnImageResizer = await import(\"@bam.tech/react-native-image-resizer\");\n\n if (rnImageResizer.default !== undefined) {\n return rnImageResizer.default;\n }\n } catch (e) {}\n\n try {\n const expoImageManipulator = await import(\"expo-image-manipulator\");\n if (expoImageManipulator.ImageManipulator !== undefined) {\n return expoImageManipulator;\n }\n } catch (e) {}\n\n throw new Error(\n \"No resizer lib found. Please install `@bam.tech/react-native-image-resizer` or `expo-image-manipulator`\",\n );\n}\n\nasync function getImageSize(\n filePath: string,\n): Promise<{ width: number; height: number }> {\n const { width, height } = await Image.getSize(filePath);\n\n return { width, height };\n}\n\nasync function getPlaceholderBase64(filePath: string): Promise<string> {\n const ImageResizer = await getResizer();\n\n if (\"createResizedImage\" in ImageResizer) {\n const { uri } = await ImageResizer.createResizedImage(\n filePath,\n 8,\n 8,\n \"PNG\",\n 100,\n );\n\n return imageUrlToBase64(uri);\n } else {\n const ctx = ImageResizer.ImageManipulator.manipulate(filePath);\n\n ctx.resize({ width: 8, height: 8 });\n\n const im = await ctx.renderAsync();\n const result = await im.saveAsync({\n base64: true,\n format: ImageResizer.SaveFormat.PNG,\n });\n\n const base64 = result.base64;\n\n if (!base64) {\n throw new Error(\n \"Failed to get generate placeholder using expo-image-manipulator\",\n );\n }\n\n return base64;\n }\n}\n\nasync function resize(\n filePath: string,\n width: number,\n height: number,\n): Promise<string> {\n const ImageResizer = await getResizer();\n\n const mimeType = await getMimeType(filePath);\n\n if (\"createResizedImage\" in ImageResizer) {\n const { uri } = await ImageResizer.createResizedImage(\n filePath,\n width,\n height,\n contentTypeToFormat(mimeType),\n 80,\n );\n\n return uri;\n } else {\n const ctx = ImageResizer.ImageManipulator.manipulate(filePath);\n ctx.resize({ width: width, height: height });\n\n const mime = contentTypeToFormat(mimeType);\n\n const im = await ctx.renderAsync();\n const result = await im.saveAsync({\n format: ImageResizer.SaveFormat[mime],\n compress: 0.8,\n });\n\n return result.uri;\n }\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: string,\n owner?: Account | Group,\n): Promise<FileStream> {\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":[]}
1
+ {"version":3,"sources":["../../src/media/create-image/react-native.ts"],"sourcesContent":["import type ImageResizerType from \"@bam.tech/react-native-image-resizer\";\nimport type ImageManipulatorType from \"expo-image-manipulator\";\nimport type { Account, Group } from \"jazz-tools\";\nimport { co, type FileStream } from \"jazz-tools\";\nimport { Image } from \"react-native\";\nimport { createImageFactory } from \"../create-image-factory\";\n\n/**\n * Creates an ImageDefinition from an image file path with built-in UX features.\n *\n * This function creates a specialized CoValue for managing images in Jazz applications.\n * It supports blurry placeholders, built-in resizing, and progressive loading patterns.\n *\n * @returns Promise that resolves to an ImageDefinition\n *\n * @example\n * ```ts\n * import { createImage } from \"jazz-tools/media\";\n *\n * async function uploadImageFromCamera(imagePath: string) {\n * const image = await createImage(imagePath, {\n * maxSize: 800,\n * placeholder: \"blur\",\n * progressive: false,\n * });\n *\n * return image;\n * }\n * ```\n */\nexport const createImage = createImageFactory(\n {\n getImageSize,\n getPlaceholderBase64,\n createFileStreamFromSource,\n resize,\n },\n (filePath) => {\n if (typeof filePath !== \"string\") {\n throw new Error(\n \"createImage(Blob | File) is not supported on this platform\",\n );\n }\n },\n);\n\nasync function getResizer(): Promise<\n typeof ImageResizerType | typeof ImageManipulatorType\n> {\n try {\n const rnImageResizer = await import(\"@bam.tech/react-native-image-resizer\");\n\n if (rnImageResizer.default !== undefined) {\n return rnImageResizer.default;\n }\n } catch (e) {}\n\n try {\n const expoImageManipulator = await import(\"expo-image-manipulator\");\n if (expoImageManipulator.ImageManipulator !== undefined) {\n return expoImageManipulator;\n }\n } catch (e) {}\n\n throw new Error(\n \"No resizer lib found. Please install `@bam.tech/react-native-image-resizer` or `expo-image-manipulator`\",\n );\n}\n\nasync function getImageSize(\n filePath: string,\n): Promise<{ width: number; height: number }> {\n const { width, height } = await Image.getSize(filePath);\n\n return { width, height };\n}\n\nasync function getPlaceholderBase64(filePath: string): Promise<string> {\n const ImageResizer = await getResizer();\n\n if (\"createResizedImage\" in ImageResizer) {\n const { uri } = await ImageResizer.createResizedImage(\n filePath,\n 8,\n 8,\n \"PNG\",\n 100,\n );\n\n return imageUrlToBase64(uri);\n } else {\n const ctx = ImageResizer.ImageManipulator.manipulate(filePath);\n\n ctx.resize({ width: 8, height: 8 });\n\n const im = await ctx.renderAsync();\n const result = await im.saveAsync({\n base64: true,\n format: ImageResizer.SaveFormat.PNG,\n });\n\n const base64 = result.base64;\n\n if (!base64) {\n throw new Error(\n \"Failed to get generate placeholder using expo-image-manipulator\",\n );\n }\n\n // Convert base64 to data URL\n return \"data:image/png;base64,\" + base64;\n }\n}\n\nasync function resize(\n filePath: string,\n width: number,\n height: number,\n): Promise<string> {\n const ImageResizer = await getResizer();\n\n const mimeType = await getMimeType(filePath);\n\n if (\"createResizedImage\" in ImageResizer) {\n const { uri } = await ImageResizer.createResizedImage(\n filePath,\n width,\n height,\n contentTypeToFormat(mimeType),\n 80,\n );\n\n return uri;\n } else {\n const ctx = ImageResizer.ImageManipulator.manipulate(filePath);\n ctx.resize({ width: width, height: height });\n\n const mime = contentTypeToFormat(mimeType);\n\n const im = await ctx.renderAsync();\n const result = await im.saveAsync({\n format: ImageResizer.SaveFormat[mime],\n compress: 0.8,\n });\n\n return result.uri;\n }\n}\n\nasync function 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: string,\n owner?: Account | Group,\n): Promise<FileStream> {\n const blob = await fetch(filePath).then((res) => res.blob());\n const arrayBuffer = await toArrayBuffer(blob);\n\n return co\n .fileStream()\n .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":[]}
@@ -3,7 +3,7 @@ import {
3
3
  highestResAvailable,
4
4
  loadImage,
5
5
  loadImageBySize
6
- } from "./chunk-3LKBM3G3.js";
6
+ } from "./chunk-IRL3KNPO.js";
7
7
 
8
8
  // src/media/create-image/server.ts
9
9
  import { FileStream } from "jazz-tools";
@@ -1 +1 @@
1
- {"version":3,"file":"Clerk.d.ts","sourceRoot":"","sources":["../../../src/react/auth/Clerk.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EACL,OAAO,EACP,YAAY,EACZ,gBAAgB,EAChB,cAAc,EAGf,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,SAAS,EAAgC,MAAM,OAAO,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAqB,MAAM,gBAAgB,CAAC;AAgCtE,eAAO,MAAM,0BAA0B,GACrC,CAAC,SACG,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,GACjD,gBAAgB,SAEb;IACL,KAAK,EAAE,kBAAkB,CAAC;CAC3B,GAAG,iBAAiB,CAAC,CAAC,CAAC,gUA4BzB,CAAC"}
1
+ {"version":3,"file":"Clerk.d.ts","sourceRoot":"","sources":["../../../src/react/auth/Clerk.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EACL,OAAO,EACP,YAAY,EACZ,gBAAgB,EAChB,cAAc,EAGf,MAAM,YAAY,CAAC;AAMpB,OAAO,EAAE,SAAS,EAAgC,MAAM,OAAO,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAqB,MAAM,gBAAgB,CAAC;AAgCtE,eAAO,MAAM,0BAA0B,GACrC,CAAC,SACG,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,GACjD,gBAAgB,SAEb;IACL,KAAK,EAAE,kBAAkB,CAAC;CAC3B,GAAG,iBAAiB,CAAC,CAAC,CAAC,gUA4BzB,CAAC"}
@@ -4,5 +4,5 @@ export declare function useAcceptInvite<S extends CoValueClassOrSchema>({ invite
4
4
  onAccept: (valueID: string) => void;
5
5
  forValueHint?: string;
6
6
  }): void;
7
- export { experimental_useInboxSender, useJazzContext, useAuthSecretStorage, useAccount, useCoState, useCoStates, useAgent, useLogOut, useSyncConnectionStatus, useCoValueSubscription, useAccountSubscription, useSubscriptionSelector, useSuspenseAccount, useSuspenseCoState, useSuspenseCoStates, } from "jazz-tools/react-core";
7
+ export { experimental_useInboxSender, useJazzContextValue, useJazzContext, useAuthSecretStorage, useAccount, useCoState, useCoStates, useAgent, useLogOut, useSyncConnectionStatus, useCoValueSubscription, useAccountSubscription, useSubscriptionSelector, useSuspenseAccount, useSuspenseCoState, useSuspenseCoStates, } from "jazz-tools/react-core";
8
8
  //# sourceMappingURL=hooks.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/react/hooks.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGlD,wBAAgB,eAAe,CAAC,CAAC,SAAS,oBAAoB,EAAE,EAC9D,mBAAmB,EACnB,QAAQ,EACR,YAAY,GACb,EAAE;IACD,mBAAmB,EAAE,CAAC,CAAC;IACvB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,IAAI,CA8BP;AAED,OAAO,EACL,2BAA2B,EAC3B,cAAc,EACd,oBAAoB,EACpB,UAAU,EACV,UAAU,EACV,WAAW,EACX,QAAQ,EACR,SAAS,EACT,uBAAuB,EACvB,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/react/hooks.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGlD,wBAAgB,eAAe,CAAC,CAAC,SAAS,oBAAoB,EAAE,EAC9D,mBAAmB,EACnB,QAAQ,EACR,YAAY,GACb,EAAE;IACD,mBAAmB,EAAE,CAAC,CAAC;IACvB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,IAAI,CA8BP;AAED,OAAO,EACL,2BAA2B,EAC3B,mBAAmB,EACnB,cAAc,EACd,oBAAoB,EACpB,UAAU,EACV,UAAU,EACV,WAAW,EACX,QAAQ,EACR,SAAS,EACT,uBAAuB,EACvB,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,uBAAuB,CAAC"}
@@ -4,8 +4,15 @@
4
4
  import {
5
5
  JazzBrowserContextManager
6
6
  } from "jazz-tools/browser";
7
- import { JazzContext, JazzContextManagerContext } from "jazz-tools/react-core";
8
- import React, { useEffect, useRef } from "react";
7
+ import { JazzContext } from "jazz-tools/react-core";
8
+ import React, {
9
+ useCallback,
10
+ useContext,
11
+ useEffect,
12
+ useMemo,
13
+ useRef,
14
+ useSyncExternalStore
15
+ } from "react";
9
16
  import { jsx } from "react/jsx-runtime";
10
17
  function JazzReactProvider({
11
18
  children,
@@ -21,6 +28,11 @@ function JazzReactProvider({
21
28
  fallback = null,
22
29
  authSecretStorageKey
23
30
  }) {
31
+ if (useContext(JazzContext)) {
32
+ throw new Error(
33
+ "You can't nest a JazzProvider inside another JazzProvider."
34
+ );
35
+ }
24
36
  const [contextManager] = React.useState(
25
37
  () => new JazzBrowserContextManager({
26
38
  useAnonymousFallback: enableSSR,
@@ -32,36 +44,33 @@ function JazzReactProvider({
32
44
  const onAnonymousAccountDiscardedRefCallback = useRefCallback(
33
45
  onAnonymousAccountDiscarded
34
46
  );
35
- const logoutReplacementActiveRef = useRef(false);
36
- logoutReplacementActiveRef.current = Boolean(logOutReplacement);
37
- const onAnonymousAccountDiscardedEnabled = Boolean(
38
- onAnonymousAccountDiscarded
39
- );
40
- const value = React.useSyncExternalStore(
41
- React.useCallback(
47
+ const props = useMemo(() => {
48
+ return {
49
+ AccountSchema,
50
+ guestMode,
51
+ sync,
52
+ storage,
53
+ defaultProfileName,
54
+ onLogOut: onLogOutRefCallback,
55
+ logOutReplacement: logOutReplacement ? logOutReplacementRefCallback : void 0,
56
+ onAnonymousAccountDiscarded: onAnonymousAccountDiscarded ? onAnonymousAccountDiscardedRefCallback : void 0
57
+ };
58
+ }, [guestMode, sync.peer, sync.when, storage]);
59
+ if (contextManager.propsChanged(props) && typeof window !== "undefined") {
60
+ contextManager.createContext(props).catch((error) => {
61
+ console.log(error.stack);
62
+ console.error("Error creating Jazz browser context:", error);
63
+ });
64
+ }
65
+ const isReady = useSyncExternalStore(
66
+ useCallback(
42
67
  (callback) => {
43
- const props = {
44
- AccountSchema,
45
- guestMode,
46
- sync,
47
- storage,
48
- defaultProfileName,
49
- onLogOut: onLogOutRefCallback,
50
- logOutReplacement: logoutReplacementActiveRef.current ? logOutReplacementRefCallback : void 0,
51
- onAnonymousAccountDiscarded: onAnonymousAccountDiscardedEnabled ? onAnonymousAccountDiscardedRefCallback : void 0
52
- };
53
- if (contextManager.propsChanged(props)) {
54
- contextManager.createContext(props).catch((error) => {
55
- console.log(error.stack);
56
- console.error("Error creating Jazz browser context:", error);
57
- });
58
- }
59
68
  return contextManager.subscribe(callback);
60
69
  },
61
- [sync, guestMode].concat(storage)
70
+ [contextManager]
62
71
  ),
63
- () => contextManager.getCurrentValue(),
64
- () => contextManager.getCurrentValue()
72
+ () => Boolean(contextManager.getCurrentValue()),
73
+ () => Boolean(contextManager.getCurrentValue())
65
74
  );
66
75
  useEffect(() => {
67
76
  if (process.env.NODE_ENV === "development") return;
@@ -69,7 +78,7 @@ function JazzReactProvider({
69
78
  contextManager.done();
70
79
  };
71
80
  }, []);
72
- return /* @__PURE__ */ jsx(JazzContext.Provider, { value, children: /* @__PURE__ */ jsx(JazzContextManagerContext.Provider, { value: contextManager, children: value ? children : fallback }) });
81
+ return /* @__PURE__ */ jsx(JazzContext.Provider, { value: contextManager, children: isReady ? children : fallback });
73
82
  }
74
83
  function useRefCallback(callback) {
75
84
  const callbackRef = React.useRef(callback);
@@ -82,10 +91,11 @@ function useRefCallback(callback) {
82
91
  // src/react/hooks.tsx
83
92
  import { consumeInviteLinkFromWindowLocation } from "jazz-tools/browser";
84
93
  import { useEffect as useEffect2 } from "react";
85
- import { useJazzContext } from "jazz-tools/react-core";
94
+ import { useJazzContextValue } from "jazz-tools/react-core";
86
95
  import {
87
96
  experimental_useInboxSender,
88
- useJazzContext as useJazzContext2,
97
+ useJazzContextValue as useJazzContextValue2,
98
+ useJazzContext,
89
99
  useAuthSecretStorage,
90
100
  useAccount,
91
101
  useCoState,
@@ -105,7 +115,7 @@ function useAcceptInvite({
105
115
  onAccept,
106
116
  forValueHint
107
117
  }) {
108
- const context = useJazzContext();
118
+ const context = useJazzContextValue();
109
119
  if (!("me" in context)) {
110
120
  throw new Error(
111
121
  "useAcceptInvite can't be used in a JazzProvider with auth === 'guest'."
@@ -142,16 +152,19 @@ import {
142
152
  KvStoreContext
143
153
  } from "jazz-tools";
144
154
  import { LocalStorageKVStore } from "jazz-tools/browser";
145
- import { useAuthSecretStorage as useAuthSecretStorage2, useJazzContext as useJazzContext3 } from "jazz-tools/react-core";
146
- import { useEffect as useEffect3, useMemo, useState } from "react";
155
+ import {
156
+ useAuthSecretStorage as useAuthSecretStorage2,
157
+ useJazzContextValue as useJazzContextValue3
158
+ } from "jazz-tools/react-core";
159
+ import { useEffect as useEffect3, useMemo as useMemo2, useState } from "react";
147
160
  import { jsx as jsx2 } from "react/jsx-runtime";
148
161
  function useJazzClerkAuth(clerk) {
149
- const context = useJazzContext3();
162
+ const context = useJazzContextValue3();
150
163
  const authSecretStorage = useAuthSecretStorage2();
151
164
  if ("guest" in context) {
152
165
  throw new Error("Clerk auth is not supported in guest mode");
153
166
  }
154
- const authMethod = useMemo(() => {
167
+ const authMethod = useMemo2(() => {
155
168
  return new JazzClerkAuth(
156
169
  context.authenticate,
157
170
  context.logOut,
@@ -320,20 +333,20 @@ import { BrowserPasskeyAuth } from "jazz-tools/browser";
320
333
  import {
321
334
  useAuthSecretStorage as useAuthSecretStorage3,
322
335
  useIsAuthenticated,
323
- useJazzContext as useJazzContext4
336
+ useJazzContextValue as useJazzContextValue4
324
337
  } from "jazz-tools/react-core";
325
- import { useMemo as useMemo2, useState as useState3 } from "react";
338
+ import { useMemo as useMemo3, useState as useState3 } from "react";
326
339
  import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
327
340
  function usePasskeyAuth({
328
341
  appName,
329
342
  appHostname
330
343
  }) {
331
- const context = useJazzContext4();
344
+ const context = useJazzContextValue4();
332
345
  const authSecretStorage = useAuthSecretStorage3();
333
346
  if ("guest" in context) {
334
347
  throw new Error("Passkey auth is not supported in guest mode");
335
348
  }
336
- const authMethod = useMemo2(() => {
349
+ const authMethod = useMemo3(() => {
337
350
  return new BrowserPasskeyAuth(
338
351
  context.node.crypto,
339
352
  context.authenticate,
@@ -649,9 +662,9 @@ import {
649
662
  import { CoValueLoadingState, ImageDefinition as ImageDefinition3 } from "jazz-tools";
650
663
  import {
651
664
  forwardRef,
652
- useCallback,
665
+ useCallback as useCallback2,
653
666
  useEffect as useEffect4,
654
- useMemo as useMemo3,
667
+ useMemo as useMemo4,
655
668
  useRef as useRef2,
656
669
  useState as useState5
657
670
  } from "react";
@@ -745,11 +758,11 @@ var Image = forwardRef(function Image2({ imageId, width, height, ...props }, ref
745
758
  const [waitingLazyLoading, setWaitingLazyLoading] = useState5(
746
759
  props.loading === "lazy"
747
760
  );
748
- const lazyPlaceholder = useMemo3(
761
+ const lazyPlaceholder = useMemo4(
749
762
  () => waitingLazyLoading ? URL.createObjectURL(getEmptyPixelBlob()) : void 0,
750
763
  [waitingLazyLoading]
751
764
  );
752
- const dimensions = useMemo3(() => {
765
+ const dimensions = useMemo4(() => {
753
766
  const originalWidth = image?.originalSize?.[0];
754
767
  const originalHeight = image?.originalSize?.[1];
755
768
  if (width === "original" && height === "original") {
@@ -778,7 +791,7 @@ var Image = forwardRef(function Image2({ imageId, width, height, ...props }, ref
778
791
  height: height === "original" ? originalHeight : height
779
792
  };
780
793
  }, [image?.originalSize, width, height]);
781
- const src = useMemo3(() => {
794
+ const src = useMemo4(() => {
782
795
  if (waitingLazyLoading) {
783
796
  return lazyPlaceholder;
784
797
  }
@@ -802,7 +815,7 @@ var Image = forwardRef(function Image2({ imageId, width, height, ...props }, ref
802
815
  }
803
816
  return image.placeholderDataURL ?? props?.placeholder;
804
817
  }, [image, dimensions.width, dimensions.height, waitingLazyLoading]);
805
- const onThresholdReached = useCallback(() => {
818
+ const onThresholdReached = useCallback2(() => {
806
819
  setWaitingLazyLoading(false);
807
820
  }, []);
808
821
  useEffect4(
@@ -868,7 +881,8 @@ export {
868
881
  useCoValueSubscription,
869
882
  useDemoAuth2 as useDemoAuth,
870
883
  useIsAuthenticated2 as useIsAuthenticated,
871
- useJazzContext2 as useJazzContext,
884
+ useJazzContext,
885
+ useJazzContextValue2 as useJazzContextValue,
872
886
  useLogOut,
873
887
  usePasskeyAuth,
874
888
  usePassphraseAuth2 as usePassphraseAuth,