@buoy-gg/assets 7.0.40 → 7.0.42

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 (193) hide show
  1. package/README.md +12 -69
  2. package/bundlers/vite.d.ts +7 -0
  3. package/bundlers/vite.mjs +1 -0
  4. package/lib/commonjs/autoCapture.js +1 -0
  5. package/lib/commonjs/autoCapture.web.js +1 -0
  6. package/lib/commonjs/capture/assetLifecycle.js +1 -0
  7. package/lib/commonjs/capture/assetLifecycle.web.js +1 -0
  8. package/lib/commonjs/capture/browserAssets.js +1 -0
  9. package/lib/commonjs/capture/expo.js +1 -46
  10. package/lib/commonjs/capture/expo.web.js +1 -0
  11. package/lib/commonjs/capture/install.js +1 -91
  12. package/lib/commonjs/capture/install.web.js +1 -0
  13. package/lib/commonjs/capture/isBuoyAsset.js +1 -23
  14. package/lib/commonjs/capture/measure.js +1 -186
  15. package/lib/commonjs/capture/metroGraph.js +1 -175
  16. package/lib/commonjs/capture/metroGraph.web.js +1 -0
  17. package/lib/commonjs/capture/registry.js +1 -127
  18. package/lib/commonjs/components/AssetDetail.js +1 -211
  19. package/lib/commonjs/components/AssetImage.js +1 -66
  20. package/lib/commonjs/components/AssetRow.js +1 -232
  21. package/lib/commonjs/components/AssetsFilterBar.js +1 -105
  22. package/lib/commonjs/components/AssetsHeader.js +1 -73
  23. package/lib/commonjs/components/AssetsIcon.js +1 -19
  24. package/lib/commonjs/components/AssetsListControls.js +1 -81
  25. package/lib/commonjs/components/AssetsModal.js +1 -378
  26. package/lib/commonjs/components/ScanNotice.js +1 -85
  27. package/lib/commonjs/components/optionalExpoImage.js +1 -16
  28. package/lib/commonjs/components/optionalExpoImage.web.js +1 -11
  29. package/lib/commonjs/export.js +1 -62
  30. package/lib/commonjs/format.js +1 -59
  31. package/lib/commonjs/hooks/useAssetRecords.js +1 -22
  32. package/lib/commonjs/hooks/useAssetScanStatus.js +1 -28
  33. package/lib/commonjs/index.js +1 -313
  34. package/lib/commonjs/preset.js +1 -39
  35. package/lib/commonjs/remote.js +1 -68
  36. package/lib/commonjs/state.js +1 -51
  37. package/lib/commonjs/store/assetStore.js +1 -256
  38. package/lib/commonjs/store/baseline.js +1 -175
  39. package/lib/commonjs/store/insights.js +1 -120
  40. package/lib/commonjs/sync/assetsSyncAdapter.js +1 -157
  41. package/lib/commonjs/types.js +0 -1
  42. package/lib/commonjs/utils/deviceScale.js +1 -50
  43. package/lib/commonjs/utils/testIDs.js +1 -110
  44. package/lib/module/autoCapture.js +1 -0
  45. package/lib/module/autoCapture.web.js +1 -0
  46. package/lib/module/capture/assetLifecycle.js +1 -0
  47. package/lib/module/capture/assetLifecycle.web.js +1 -0
  48. package/lib/module/capture/browserAssets.js +1 -0
  49. package/lib/module/capture/expo.js +1 -41
  50. package/lib/module/capture/expo.web.js +1 -0
  51. package/lib/module/capture/install.js +1 -85
  52. package/lib/module/capture/install.web.js +1 -0
  53. package/lib/module/capture/isBuoyAsset.js +1 -18
  54. package/lib/module/capture/measure.js +1 -179
  55. package/lib/module/capture/metroGraph.js +1 -168
  56. package/lib/module/capture/metroGraph.web.js +1 -0
  57. package/lib/module/capture/registry.js +1 -120
  58. package/lib/module/components/AssetDetail.js +1 -207
  59. package/lib/module/components/AssetImage.js +1 -62
  60. package/lib/module/components/AssetRow.js +1 -228
  61. package/lib/module/components/AssetsFilterBar.js +1 -101
  62. package/lib/module/components/AssetsHeader.js +1 -69
  63. package/lib/module/components/AssetsIcon.js +1 -12
  64. package/lib/module/components/AssetsListControls.js +1 -77
  65. package/lib/module/components/AssetsModal.js +1 -373
  66. package/lib/module/components/ScanNotice.js +1 -81
  67. package/lib/module/components/optionalExpoImage.js +1 -12
  68. package/lib/module/components/optionalExpoImage.web.js +1 -7
  69. package/lib/module/export.js +1 -57
  70. package/lib/module/format.js +1 -51
  71. package/lib/module/hooks/useAssetRecords.js +1 -18
  72. package/lib/module/hooks/useAssetScanStatus.js +1 -23
  73. package/lib/module/index.js +1 -63
  74. package/lib/module/preset.js +1 -35
  75. package/lib/module/remote.js +1 -61
  76. package/lib/module/state.js +1 -47
  77. package/lib/module/store/assetStore.js +1 -240
  78. package/lib/module/store/baseline.js +1 -167
  79. package/lib/module/store/insights.js +1 -116
  80. package/lib/module/sync/assetsSyncAdapter.js +1 -153
  81. package/lib/module/types.js +0 -1
  82. package/lib/module/utils/deviceScale.js +1 -46
  83. package/lib/module/utils/testIDs.js +1 -99
  84. package/lib/typescript/autoCapture.d.ts +2 -0
  85. package/lib/typescript/autoCapture.web.d.ts +2 -0
  86. package/lib/typescript/capture/assetLifecycle.d.ts +3 -0
  87. package/lib/typescript/capture/assetLifecycle.web.d.ts +2 -0
  88. package/lib/typescript/capture/browserAssets.d.ts +13 -0
  89. package/lib/typescript/capture/expo.web.d.ts +3 -0
  90. package/lib/typescript/capture/install.web.d.ts +6 -0
  91. package/lib/typescript/capture/measure.d.ts +0 -10
  92. package/lib/typescript/capture/metroGraph.web.d.ts +12 -0
  93. package/lib/typescript/components/optionalExpoImage.web.d.ts +1 -1
  94. package/lib/typescript/index.d.ts +3 -0
  95. package/lib/typescript/types.d.ts +2 -1
  96. package/lib/web/index.mjs +3 -0
  97. package/package.json +46 -7
  98. package/lib/commonjs/capture/expo.js.map +0 -1
  99. package/lib/commonjs/capture/install.js.map +0 -1
  100. package/lib/commonjs/capture/isBuoyAsset.js.map +0 -1
  101. package/lib/commonjs/capture/measure.js.map +0 -1
  102. package/lib/commonjs/capture/metroGraph.js.map +0 -1
  103. package/lib/commonjs/capture/registry.js.map +0 -1
  104. package/lib/commonjs/components/AssetDetail.js.map +0 -1
  105. package/lib/commonjs/components/AssetImage.js.map +0 -1
  106. package/lib/commonjs/components/AssetRow.js.map +0 -1
  107. package/lib/commonjs/components/AssetsFilterBar.js.map +0 -1
  108. package/lib/commonjs/components/AssetsHeader.js.map +0 -1
  109. package/lib/commonjs/components/AssetsIcon.js.map +0 -1
  110. package/lib/commonjs/components/AssetsListControls.js.map +0 -1
  111. package/lib/commonjs/components/AssetsModal.js.map +0 -1
  112. package/lib/commonjs/components/ScanNotice.js.map +0 -1
  113. package/lib/commonjs/components/optionalExpoImage.js.map +0 -1
  114. package/lib/commonjs/components/optionalExpoImage.web.js.map +0 -1
  115. package/lib/commonjs/export.js.map +0 -1
  116. package/lib/commonjs/format.js.map +0 -1
  117. package/lib/commonjs/hooks/useAssetRecords.js.map +0 -1
  118. package/lib/commonjs/hooks/useAssetScanStatus.js.map +0 -1
  119. package/lib/commonjs/index.js.map +0 -1
  120. package/lib/commonjs/preset.js.map +0 -1
  121. package/lib/commonjs/remote.js.map +0 -1
  122. package/lib/commonjs/state.js.map +0 -1
  123. package/lib/commonjs/store/assetStore.js.map +0 -1
  124. package/lib/commonjs/store/baseline.js.map +0 -1
  125. package/lib/commonjs/store/insights.js.map +0 -1
  126. package/lib/commonjs/sync/assetsSyncAdapter.js.map +0 -1
  127. package/lib/commonjs/types.js.map +0 -1
  128. package/lib/commonjs/utils/deviceScale.js.map +0 -1
  129. package/lib/commonjs/utils/testIDs.js.map +0 -1
  130. package/lib/module/capture/expo.js.map +0 -1
  131. package/lib/module/capture/install.js.map +0 -1
  132. package/lib/module/capture/isBuoyAsset.js.map +0 -1
  133. package/lib/module/capture/measure.js.map +0 -1
  134. package/lib/module/capture/metroGraph.js.map +0 -1
  135. package/lib/module/capture/registry.js.map +0 -1
  136. package/lib/module/components/AssetDetail.js.map +0 -1
  137. package/lib/module/components/AssetImage.js.map +0 -1
  138. package/lib/module/components/AssetRow.js.map +0 -1
  139. package/lib/module/components/AssetsFilterBar.js.map +0 -1
  140. package/lib/module/components/AssetsHeader.js.map +0 -1
  141. package/lib/module/components/AssetsIcon.js.map +0 -1
  142. package/lib/module/components/AssetsListControls.js.map +0 -1
  143. package/lib/module/components/AssetsModal.js.map +0 -1
  144. package/lib/module/components/ScanNotice.js.map +0 -1
  145. package/lib/module/components/optionalExpoImage.js.map +0 -1
  146. package/lib/module/components/optionalExpoImage.web.js.map +0 -1
  147. package/lib/module/export.js.map +0 -1
  148. package/lib/module/format.js.map +0 -1
  149. package/lib/module/hooks/useAssetRecords.js.map +0 -1
  150. package/lib/module/hooks/useAssetScanStatus.js.map +0 -1
  151. package/lib/module/index.js.map +0 -1
  152. package/lib/module/preset.js.map +0 -1
  153. package/lib/module/remote.js.map +0 -1
  154. package/lib/module/state.js.map +0 -1
  155. package/lib/module/store/assetStore.js.map +0 -1
  156. package/lib/module/store/baseline.js.map +0 -1
  157. package/lib/module/store/insights.js.map +0 -1
  158. package/lib/module/sync/assetsSyncAdapter.js.map +0 -1
  159. package/lib/module/types.js.map +0 -1
  160. package/lib/module/utils/deviceScale.js.map +0 -1
  161. package/lib/module/utils/testIDs.js.map +0 -1
  162. package/lib/typescript/capture/expo.d.ts.map +0 -1
  163. package/lib/typescript/capture/install.d.ts.map +0 -1
  164. package/lib/typescript/capture/isBuoyAsset.d.ts.map +0 -1
  165. package/lib/typescript/capture/measure.d.ts.map +0 -1
  166. package/lib/typescript/capture/metroGraph.d.ts.map +0 -1
  167. package/lib/typescript/capture/registry.d.ts.map +0 -1
  168. package/lib/typescript/components/AssetDetail.d.ts.map +0 -1
  169. package/lib/typescript/components/AssetImage.d.ts.map +0 -1
  170. package/lib/typescript/components/AssetRow.d.ts.map +0 -1
  171. package/lib/typescript/components/AssetsFilterBar.d.ts.map +0 -1
  172. package/lib/typescript/components/AssetsHeader.d.ts.map +0 -1
  173. package/lib/typescript/components/AssetsIcon.d.ts.map +0 -1
  174. package/lib/typescript/components/AssetsListControls.d.ts.map +0 -1
  175. package/lib/typescript/components/AssetsModal.d.ts.map +0 -1
  176. package/lib/typescript/components/ScanNotice.d.ts.map +0 -1
  177. package/lib/typescript/components/optionalExpoImage.d.ts.map +0 -1
  178. package/lib/typescript/components/optionalExpoImage.web.d.ts.map +0 -1
  179. package/lib/typescript/export.d.ts.map +0 -1
  180. package/lib/typescript/format.d.ts.map +0 -1
  181. package/lib/typescript/hooks/useAssetRecords.d.ts.map +0 -1
  182. package/lib/typescript/hooks/useAssetScanStatus.d.ts.map +0 -1
  183. package/lib/typescript/index.d.ts.map +0 -1
  184. package/lib/typescript/preset.d.ts.map +0 -1
  185. package/lib/typescript/remote.d.ts.map +0 -1
  186. package/lib/typescript/state.d.ts.map +0 -1
  187. package/lib/typescript/store/assetStore.d.ts.map +0 -1
  188. package/lib/typescript/store/baseline.d.ts.map +0 -1
  189. package/lib/typescript/store/insights.d.ts.map +0 -1
  190. package/lib/typescript/sync/assetsSyncAdapter.d.ts.map +0 -1
  191. package/lib/typescript/types.d.ts.map +0 -1
  192. package/lib/typescript/utils/deviceScale.d.ts.map +0 -1
  193. package/lib/typescript/utils/testIDs.d.ts.map +0 -1
@@ -1,175 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.fetchAssetGraph = fetchAssetGraph;
7
- exports.getDevServerOrigin = getDevServerOrigin;
8
- exports.getGraphURLCandidates = getGraphURLCandidates;
9
- exports.getScriptURL = getScriptURL;
10
- var _state = require("../state");
11
- var _assetStore = require("../store/assetStore");
12
- /**
13
- * Metro dev-server graph fetch.
14
- *
15
- * The dev server serves `<entry>.assets` next to `<entry>.bundle` — the full
16
- * dependency graph's AssetData[], INCLUDING assets never required at runtime
17
- * and the `fileSystemLocation`/`files` fields Metro strips from runtime
18
- * records. Deriving the URL by swapping `.bundle` → `.assets` on the running
19
- * bundle's scriptURL keeps the entry path and platform/dev query params
20
- * intact for both RN CLI (index.bundle) and Expo (…/entry.bundle) layouts.
21
- *
22
- * Graph-only records (in the graph, not the registry) are exactly the
23
- * "shipped but never loaded" set. Dev-only: no server, no graph.
24
- */
25
-
26
- const GRAPH_TIMEOUT_MS = 90_000;
27
-
28
- /** Bound the whole discovery pass, including response body reads. */
29
- async function fetchGraphPayload(url, remainingMs) {
30
- const controller = new AbortController();
31
- let timer;
32
- try {
33
- return await Promise.race([(async () => {
34
- const response = await fetch(url, {
35
- signal: controller.signal
36
- });
37
- if (!response.ok) throw new Error(`Metro responded ${response.status} for ${url}`);
38
- return response.json();
39
- })(), new Promise((_, reject) => {
40
- timer = setTimeout(() => {
41
- reject(new Error("Asset discovery timed out. Try again."));
42
- controller.abort();
43
- }, Math.max(0, remainingMs));
44
- })]);
45
- } finally {
46
- clearTimeout(timer);
47
- }
48
- }
49
- function getScriptURL() {
50
- try {
51
- const {
52
- NativeModules
53
- } = require("react-native");
54
- const sourceCode = NativeModules?.SourceCode;
55
- const url = sourceCode?.getConstants?.().scriptURL ?? sourceCode?.scriptURL;
56
- return typeof url === "string" ? url : null;
57
- } catch {
58
- return null;
59
- }
60
- }
61
-
62
- /** http(s) origin of the Metro dev server, or null when running embedded. */
63
- function getDevServerOrigin() {
64
- const scriptURL = getScriptURL();
65
- const match = scriptURL?.match(/^https?:\/\/[^/]+/);
66
- return match ? match[0] : null;
67
- }
68
-
69
- /**
70
- * Candidate graph URLs, most-likely first. The straight `.bundle`→`.assets`
71
- * swap works for RN CLI, but Expo dev builds serve a VIRTUAL entry
72
- * (.expo/.virtual-metro-entry.bundle) that only exists for .bundle requests —
73
- * its .assets twin 404s — so the real entry modules are tried next, keeping
74
- * the original query string (platform/dev/etc.) intact.
75
- */
76
- function getGraphURLCandidates() {
77
- const scriptURL = getScriptURL();
78
- if (!scriptURL || !/^https?:\/\//.test(scriptURL)) return [];
79
- const origin = getDevServerOrigin();
80
- const queryIndex = scriptURL.indexOf("?");
81
- const query = queryIndex >= 0 ? scriptURL.slice(queryIndex) : "?platform=ios&dev=true";
82
- const candidates = [];
83
- if (scriptURL.includes(".bundle")) {
84
- candidates.push(scriptURL.replace(".bundle", ".assets"));
85
- }
86
- if (origin) {
87
- candidates.push(`${origin}/node_modules/expo-router/entry.assets${query}`, `${origin}/node_modules/expo/AppEntry.assets${query}`, `${origin}/index.assets${query}`);
88
- }
89
- return candidates;
90
- }
91
-
92
- /** Fetch the full asset graph from the dev server and merge it into the store. */
93
- async function fetchAssetGraph() {
94
- const s = (0, _state.assetsState)();
95
- const candidates = getGraphURLCandidates();
96
- if (!candidates.length) {
97
- s.graphSupported = false;
98
- s.graphError = "No Metro dev server (embedded bundle)";
99
- (0, _assetStore.invalidate)();
100
- return {
101
- ok: false,
102
- message: s.graphError
103
- };
104
- }
105
- if (s.graphFetchInFlight) return {
106
- ok: false,
107
- message: "Graph fetch already running"
108
- };
109
- s.graphFetchInFlight = true;
110
- s.graphFetchStartedAt = Date.now();
111
- s.graphError = null;
112
- (0, _assetStore.invalidate)();
113
- const deadline = s.graphFetchStartedAt + GRAPH_TIMEOUT_MS;
114
- try {
115
- let data = null;
116
- let lastError = "";
117
- for (const url of candidates) {
118
- try {
119
- const parsed = await fetchGraphPayload(url, deadline - Date.now());
120
- if (Array.isArray(parsed)) {
121
- data = parsed;
122
- break;
123
- }
124
- lastError = "Unexpected .assets payload shape";
125
- } catch (error) {
126
- lastError = String(error?.message ?? error);
127
- if (Date.now() >= deadline) break;
128
- }
129
- }
130
- if (!Array.isArray(data)) throw new Error(lastError || "No graph endpoint answered");
131
- const graph = data;
132
- let count = 0;
133
- for (const asset of graph) {
134
- if (!asset || typeof asset.name !== "string" || typeof asset.type !== "string") {
135
- continue;
136
- }
137
- const record = (0, _assetStore.upsertRecord)({
138
- key: (0, _assetStore.assetKey)(asset.httpServerLocation, asset.name, asset.type),
139
- name: asset.name,
140
- type: asset.type,
141
- origin: "graph",
142
- hash: asset.hash,
143
- httpServerLocation: asset.httpServerLocation,
144
- width: asset.width ?? undefined,
145
- height: asset.height ?? undefined,
146
- scales: asset.scales,
147
- fileSystemLocation: asset.fileSystemLocation,
148
- files: asset.files,
149
- fileHashes: asset.fileHashes
150
- });
151
- if (record) count++;
152
- }
153
- s.graphSupported = true;
154
- s.graphCount = count;
155
- s.graphError = null;
156
- (0, _assetStore.invalidate)();
157
- return {
158
- ok: true,
159
- count
160
- };
161
- } catch (error) {
162
- s.graphSupported = getDevServerOrigin() != null;
163
- s.graphError = String(error?.message ?? error);
164
- (0, _assetStore.invalidate)();
165
- return {
166
- ok: false,
167
- message: s.graphError
168
- };
169
- } finally {
170
- s.graphFetchInFlight = false;
171
- s.graphFetchStartedAt = null;
172
- (0, _assetStore.invalidate)();
173
- }
174
- }
175
- //# sourceMappingURL=metroGraph.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.fetchAssetGraph=fetchAssetGraph;exports.getDevServerOrigin=getDevServerOrigin;exports.getGraphURLCandidates=getGraphURLCandidates;exports.getScriptURL=getScriptURL;var _state=require("../state");var _assetStore=require("../store/assetStore");const GRAPH_TIMEOUT_MS=9e4;async function fetchGraphPayload(e,r){const n=new AbortController;let s;try{return await Promise.race([(async()=>{const a=await fetch(e,{signal:n.signal});if(!a.ok)throw new Error(`Metro responded ${a.status} for ${e}`);return a.json()})(),new Promise((a,i)=>{s=setTimeout(()=>{i(new Error("Asset discovery timed out. Try again."));n.abort()},Math.max(0,r))})])}finally{clearTimeout(s)}}function getScriptURL(){try{const{NativeModules:e}=require("react-native");const r=e?.SourceCode;const n=r?.getConstants?.().scriptURL??r?.scriptURL;return typeof n==="string"?n:null}catch{return null}}function getDevServerOrigin(){const e=getScriptURL();const r=e?.match(/^https?:\/\/[^/]+/);return r?r[0]:null}function getGraphURLCandidates(){const e=getScriptURL();if(!e||!/^https?:\/\//.test(e))return[];const r=getDevServerOrigin();const n=e.indexOf("?");const s=n>=0?e.slice(n):"?platform=ios&dev=true";const a=[];if(e.includes(".bundle")){a.push(e.replace(".bundle",".assets"))}if(r){a.push(`${r}/node_modules/expo-router/entry.assets${s}`,`${r}/node_modules/expo/AppEntry.assets${s}`,`${r}/index.assets${s}`)}return a}async function fetchAssetGraph(){const e=(0,_state.assetsState)();const r=getGraphURLCandidates();if(!r.length){e.graphSupported=false;e.graphError="No Metro dev server (embedded bundle)";(0,_assetStore.invalidate)();return{ok:false,message:e.graphError}}if(e.graphFetchInFlight)return{ok:false,message:"Graph fetch already running"};e.graphFetchInFlight=true;e.graphFetchStartedAt=Date.now();e.graphError=null;(0,_assetStore.invalidate)();const n=e.graphFetchStartedAt+GRAPH_TIMEOUT_MS;try{let s=null;let a="";for(const t of r){try{const o=await fetchGraphPayload(t,n-Date.now());if(Array.isArray(o)){s=o;break}a="Unexpected .assets payload shape"}catch(o){a=String(o?.message??o);if(Date.now()>=n)break}}if(!Array.isArray(s))throw new Error(a||"No graph endpoint answered");const i=s;let c=0;for(const t of i){if(!t||typeof t.name!=="string"||typeof t.type!=="string"){continue}const o=(0,_assetStore.upsertRecord)({key:(0,_assetStore.assetKey)(t.httpServerLocation,t.name,t.type),name:t.name,type:t.type,origin:"graph",hash:t.hash,httpServerLocation:t.httpServerLocation,width:t.width??void 0,height:t.height??void 0,scales:t.scales,fileSystemLocation:t.fileSystemLocation,files:t.files,fileHashes:t.fileHashes});if(o)c++}e.graphSupported=true;e.graphCount=c;e.graphError=null;(0,_assetStore.invalidate)();return{ok:true,count:c}}catch(s){e.graphSupported=getDevServerOrigin()!=null;e.graphError=String(s?.message??s);(0,_assetStore.invalidate)();return{ok:false,message:e.graphError}}finally{e.graphFetchInFlight=false;e.graphFetchStartedAt=null;(0,_assetStore.invalidate)()}}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.fetchAssetGraph=fetchAssetGraph;exports.getDevServerOrigin=getDevServerOrigin;exports.getScriptURL=getScriptURL;var _browserAssets=require("./browserAssets");function getScriptURL(){return null}function getDevServerOrigin(){return null}async function fetchAssetGraph(){(0,_browserAssets.scanBrowserAssets)();const e=(0,_browserAssets.getBrowserAssetManifest)().length;return e?{ok:true,count:e}:{ok:false,message:"Register a browser asset manifest to inspect files that have not loaded yet."}}
@@ -1,127 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.getRegistryModule = getRegistryModule;
7
- exports.patchRegisterAsset = patchRegisterAsset;
8
- exports.resolveRegistryAsset = resolveRegistryAsset;
9
- exports.upsertFromPackagerAsset = upsertFromPackagerAsset;
10
- exports.walkRegistry = walkRegistry;
11
- var _assetStore = require("../store/assetStore");
12
- /**
13
- * Runtime access to @react-native/assets-registry.
14
- *
15
- * Asset ids are contiguous 1..N (`assets.push` return value), so a plain
16
- * getAssetByID walk enumerates every asset registered so far — including
17
- * everything registered BEFORE this tool was evaluated. That's why, unlike
18
- * the images tool, there is no "must be the first import" requirement here:
19
- * the walk backfills whatever the patch missed.
20
- *
21
- * registerAsset is patched (plain non-frozen CommonJS export, looked up at
22
- * call time by Metro's generated asset modules) purely for LIVE updates as
23
- * lazily-required assets register later.
24
- */
25
-
26
- /** Runtime shape of a registry entry (fileSystemLocation/files are stripped by Metro). */
27
-
28
- let cachedRegistry;
29
- function getRegistryModule() {
30
- if (cachedRegistry !== undefined) return cachedRegistry;
31
- let mod = null;
32
- try {
33
- mod = require("@react-native/assets-registry/registry");
34
- } catch {
35
- // Old RN layouts (< 0.72) don't ship @react-native/assets-registry as a
36
- // resolvable package — the registry only exists at this deep path. RN's
37
- // deep-import deprecation warning fires when this executes, but it only
38
- // executes on those old layouts, where there is no other way in.
39
- try {
40
- mod = require("react-native/Libraries/Image/AssetRegistry");
41
- } catch {
42
- mod = null;
43
- }
44
- }
45
- cachedRegistry = mod && typeof mod.getAssetByID === "function" ? mod : null;
46
- return cachedRegistry;
47
- }
48
-
49
- /** resolveAssetSource(id) → this environment's URI (dev URL / file:// / res id). */
50
- function resolveRegistryAsset(registryId) {
51
- try {
52
- const {
53
- Image
54
- } = require("react-native");
55
- const resolved = Image.resolveAssetSource(registryId);
56
- if (resolved && typeof resolved.uri === "string") {
57
- return {
58
- uri: resolved.uri,
59
- scale: resolved.scale ?? 1
60
- };
61
- }
62
- } catch {
63
- // resolution is enrichment — never let it break the walk
64
- }
65
- return null;
66
- }
67
- function upsertFromPackagerAsset(registryId, asset) {
68
- const resolved = resolveRegistryAsset(registryId);
69
- return (0, _assetStore.upsertRecord)({
70
- key: (0, _assetStore.assetKey)(asset.httpServerLocation, asset.name, asset.type),
71
- name: asset.name,
72
- type: asset.type,
73
- origin: "registry",
74
- registryId,
75
- hash: asset.hash,
76
- httpServerLocation: asset.httpServerLocation,
77
- width: asset.width ?? undefined,
78
- height: asset.height ?? undefined,
79
- scales: asset.scales,
80
- resolvedUri: resolved?.uri,
81
- resolvedScale: resolved?.scale,
82
- loaded: true
83
- });
84
- }
85
-
86
- /** Enumerate every asset registered so far. Returns the highest id seen. */
87
- function walkRegistry() {
88
- const registry = getRegistryModule();
89
- if (!registry) return 0;
90
- let id = 0;
91
- for (;;) {
92
- const asset = registry.getAssetByID(id + 1);
93
- if (!asset) break;
94
- id++;
95
- upsertFromPackagerAsset(id, asset);
96
- }
97
- return id;
98
- }
99
- const PATCH_MARKER = "__buoyAssetsPatched";
100
-
101
- /**
102
- * Wrap registerAsset so future registrations stream in live. Safe to call
103
- * more than once (marker guard); the walk covers anything registered before.
104
- */
105
- function patchRegisterAsset() {
106
- const registry = getRegistryModule();
107
- if (!registry) return false;
108
- const original = registry.registerAsset;
109
- if (original[PATCH_MARKER]) return true;
110
- const wrapped = asset => {
111
- const id = original.call(registry, asset);
112
- try {
113
- upsertFromPackagerAsset(id, asset);
114
- } catch {
115
- // never break app asset registration
116
- }
117
- return id;
118
- };
119
- wrapped[PATCH_MARKER] = true;
120
- try {
121
- registry.registerAsset = wrapped;
122
- } catch {
123
- return false;
124
- }
125
- return true;
126
- }
127
- //# sourceMappingURL=registry.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.getRegistryModule=getRegistryModule;exports.patchRegisterAsset=patchRegisterAsset;exports.resolveRegistryAsset=resolveRegistryAsset;exports.upsertFromPackagerAsset=upsertFromPackagerAsset;exports.walkRegistry=walkRegistry;var _assetStore=require("../store/assetStore");let cachedRegistry;function getRegistryModule(){if(cachedRegistry!==void 0)return cachedRegistry;let t=null;try{t=require("@react-native/assets-registry/registry")}catch{try{t=require("react-native/Libraries/Image/AssetRegistry")}catch{t=null}}cachedRegistry=t&&typeof t.getAssetByID==="function"?t:null;return cachedRegistry}function resolveRegistryAsset(t){try{const{Image:e}=require("react-native");const r=e.resolveAssetSource(t);if(r&&typeof r.uri==="string"){return{uri:r.uri,scale:r.scale??1}}}catch{}return null}function upsertFromPackagerAsset(t,e){const r=resolveRegistryAsset(t);return(0,_assetStore.upsertRecord)({key:(0,_assetStore.assetKey)(e.httpServerLocation,e.name,e.type),name:e.name,type:e.type,origin:"registry",registryId:t,hash:e.hash,httpServerLocation:e.httpServerLocation,width:e.width??void 0,height:e.height??void 0,scales:e.scales,resolvedUri:r?.uri,resolvedScale:r?.scale,loaded:true})}function walkRegistry(){const t=getRegistryModule();if(!t)return 0;let e=0;for(;;){const r=t.getAssetByID(e+1);if(!r)break;e++;upsertFromPackagerAsset(e,r)}return e}const PATCH_MARKER="__buoyAssetsPatched";function patchRegisterAsset(){const t=getRegistryModule();if(!t)return false;const e=t.registerAsset;if(e[PATCH_MARKER])return true;const r=s=>{const i=e.call(t,s);try{upsertFromPackagerAsset(i,s)}catch{}return i};r[PATCH_MARKER]=true;try{t.registerAsset=r}catch{return false}return true}
@@ -1,211 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.AssetDetail = AssetDetail;
7
- var _reactNative = require("react-native");
8
- var _sharedUi = require("@buoy-gg/shared-ui");
9
- var _AssetImage = require("./AssetImage");
10
- var _format = require("../format");
11
- var _assetStore = require("../store/assetStore");
12
- var _testIDs = require("../utils/testIDs");
13
- var _jsxRuntime = require("react/jsx-runtime");
14
- /**
15
- * AssetDetail — full metadata for one asset: preview, identity, dimensions,
16
- * per-scale sizes, resolution info, and which audit findings apply.
17
- *
18
- * Image previews use registry ids or asset URLs, with optional expo-image for
19
- * native SVGs; fonts render a pangram with fontFamily set to the asset name
20
- * — a best-effort guess (family ≠ filename for many fonts) that falls back
21
- * to the system font silently when it misses.
22
- */
23
-
24
- function Row({
25
- label,
26
- value
27
- }) {
28
- const testID = (0, _testIDs.assetDetailRowTestID)(label);
29
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
30
- style: styles.kvRow,
31
- testID: testID,
32
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
33
- style: styles.kvLabel,
34
- children: label
35
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
36
- style: styles.kvValue,
37
- selectable: true,
38
- testID: `${testID}-value`,
39
- children: value
40
- })]
41
- });
42
- }
43
- function Preview({
44
- record
45
- }) {
46
- if (record.kind === "image") {
47
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
48
- style: styles.previewBox,
49
- testID: _testIDs.ASSETS_TEST_IDS.detailPreview,
50
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_AssetImage.AssetImage, {
51
- testID: "buoy-internal-assets-preview",
52
- record: record,
53
- style: styles.previewImage
54
- })
55
- });
56
- }
57
- if (record.kind === "font") {
58
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
59
- style: styles.previewBox,
60
- testID: _testIDs.ASSETS_TEST_IDS.detailFontPreview,
61
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
62
- style: [styles.fontPreview, {
63
- fontFamily: record.name
64
- }],
65
- children: "The quick brown fox jumps over the lazy dog 0123456789"
66
- })
67
- });
68
- }
69
- return null;
70
- }
71
- function AssetDetail({
72
- record,
73
- insights
74
- }) {
75
- const findings = [];
76
- if (insights.neverLoaded.includes(record.id)) {
77
- findings.push("Not observed in the runtime registry this app run. This does not prove the asset is unused.");
78
- }
79
- if (insights.scaleGaps.includes(record.id)) {
80
- findings.push("Scale gap — no variant covers this device's pixel ratio");
81
- }
82
- if (insights.webpCandidates.includes(record.id)) {
83
- findings.push("WebP candidate — large png/jpeg, converting typically saves 20–40%");
84
- }
85
- const duplicate = insights.duplicates.find(d => d.ids.includes(record.id));
86
- if (duplicate) {
87
- findings.push(`Duplicate content — identical bytes shipped ${duplicate.ids.length} times`);
88
- }
89
- if (insights.overDecode.includes(record.id)) {
90
- findings.push("Decodes larger than 2× this entire screen — resize the source, no view can need this many pixels");
91
- }
92
- if (insights.heavyGifs.includes(record.id)) {
93
- findings.push("Heavy GIF — every frame decodes into memory; a video or Lottie is typically ~90% smaller");
94
- }
95
- if (insights.heavyFonts.includes(record.id)) {
96
- findings.push("Heavy font — likely an unsubset icon font; subsetting to used glyphs usually saves most of it");
97
- }
98
- if (insights.scaleAnomalies.includes(record.id)) {
99
- findings.push("Scale anomaly — a higher-resolution variant is smaller in bytes than a lower one; check the exports");
100
- }
101
- const estimate = (0, _assetStore.estDecodedBytes)(record);
102
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.ScrollView, {
103
- style: styles.scroll,
104
- contentContainerStyle: styles.content,
105
- testID: _testIDs.ASSETS_TEST_IDS.detailScroll,
106
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Preview, {
107
- record: record
108
- }), findings.length > 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
109
- style: styles.findings,
110
- testID: _testIDs.ASSETS_TEST_IDS.detailFindings,
111
- children: findings.map((finding, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
112
- style: styles.findingText,
113
- testID: (0, _testIDs.assetFindingTestID)(index),
114
- children: finding
115
- }, finding))
116
- }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
117
- label: "Name",
118
- value: `${record.name}.${record.type}`
119
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
120
- label: "Kind",
121
- value: record.kind
122
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
123
- label: "Status",
124
- value: record.loaded ? "Loaded (registered at runtime)" : "Not observed in the runtime registry"
125
- }), record.kind === "image" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
126
- label: "Dimensions",
127
- value: `${(0, _format.formatDimensions)(record)} (logical)`
128
- }) : null, record.kind === "image" && record.scales.length ? /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
129
- label: "Scales",
130
- value: (0, _format.formatScales)(record.scales)
131
- }) : null, record.sizesByScale ? Object.entries(record.sizesByScale).map(([scale, bytes]) => /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
132
- label: `Size @${scale}x`,
133
- value: (0, _format.formatBytes)(bytes)
134
- }, scale)) : null, record.sizeBytes != null && record.sizeSource === "measured" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
135
- label: "Total size",
136
- value: (0, _format.formatBytes)(record.sizeBytes)
137
- }) : null, estimate > 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
138
- label: "Decoded memory",
139
- value: `~${(0, _format.formatBytes)(estimate)} (RGBA)`
140
- }) : null, record.registryId != null ? /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
141
- label: "Registry id",
142
- value: String(record.registryId)
143
- }) : null, record.hash ? /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
144
- label: "Hash",
145
- value: record.hash
146
- }) : null, record.httpServerLocation ? /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
147
- label: "Location",
148
- value: record.httpServerLocation
149
- }) : null, record.fileSystemLocation ? /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
150
- label: "Source dir",
151
- value: record.fileSystemLocation
152
- }) : null, record.resolvedUri ? /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
153
- label: "Resolved URI",
154
- value: record.resolvedUri
155
- }) : null]
156
- });
157
- }
158
- const styles = _reactNative.StyleSheet.create({
159
- scroll: {
160
- flex: 1
161
- },
162
- content: {
163
- padding: 12,
164
- gap: 8
165
- },
166
- previewBox: {
167
- borderRadius: 8,
168
- backgroundColor: _sharedUi.night.color.bg,
169
- padding: 12,
170
- alignItems: "center",
171
- justifyContent: "center",
172
- minHeight: 96
173
- },
174
- previewImage: {
175
- width: "100%",
176
- height: 140
177
- },
178
- fontPreview: {
179
- color: _sharedUi.night.color.text,
180
- fontSize: 16,
181
- textAlign: "center"
182
- },
183
- findings: {
184
- borderRadius: 8,
185
- borderWidth: 1,
186
- borderColor: _sharedUi.night.color.border,
187
- backgroundColor: _sharedUi.night.color.surface,
188
- padding: 10,
189
- gap: 6
190
- },
191
- findingText: {
192
- color: _sharedUi.night.color.textSecondary,
193
- fontSize: 11,
194
- lineHeight: 15
195
- },
196
- kvRow: {
197
- gap: 2
198
- },
199
- kvLabel: {
200
- color: _sharedUi.night.color.textTertiary,
201
- fontSize: 9,
202
- fontWeight: "700",
203
- letterSpacing: 0.5,
204
- textTransform: "uppercase"
205
- },
206
- kvValue: {
207
- color: _sharedUi.night.color.text,
208
- fontSize: 12
209
- }
210
- });
211
- //# sourceMappingURL=AssetDetail.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.AssetDetail=AssetDetail;var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _AssetImage=require("./AssetImage");var _format=require("../format");var _assetStore=require("../store/assetStore");var _testIDs=require("../utils/testIDs");var _jsxRuntime=require("react/jsx-runtime");function Row({label:e,value:s}){const t=(0,_testIDs.assetDetailRowTestID)(e);return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.kvRow,testID:t,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.kvLabel,children:e}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.kvValue,selectable:true,testID:`${t}-value`,children:s})]})}function Preview({record:e}){if(e.kind==="image"){return(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.previewBox,testID:_testIDs.ASSETS_TEST_IDS.detailPreview,children:(0,_jsxRuntime.jsx)(_AssetImage.AssetImage,{testID:"buoy-internal-assets-preview",record:e,style:styles.previewImage})})}if(e.kind==="font"){return(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.previewBox,testID:_testIDs.ASSETS_TEST_IDS.detailFontPreview,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.fontPreview,{fontFamily:e.name}],children:"The quick brown fox jumps over the lazy dog 0123456789"})})}return null}function AssetDetail({record:e,insights:s}){const t=[];if(s.neverLoaded.includes(e.id)){t.push("Not observed in the runtime registry this app run. This does not prove the asset is unused.")}if(s.scaleGaps.includes(e.id)){t.push("Scale gap \u2014 no variant covers this device's pixel ratio")}if(s.webpCandidates.includes(e.id)){t.push("WebP candidate \u2014 large png/jpeg, converting typically saves 20\u201340%")}const a=s.duplicates.find(i=>i.ids.includes(e.id));if(a){t.push(`Duplicate content \u2014 identical bytes shipped ${a.ids.length} times`)}if(s.overDecode.includes(e.id)){t.push("Decodes larger than 2\xD7 this entire screen \u2014 resize the source, no view can need this many pixels")}if(s.heavyGifs.includes(e.id)){t.push("Heavy GIF \u2014 every frame decodes into memory; a video or Lottie is typically ~90% smaller")}if(s.heavyFonts.includes(e.id)){t.push("Heavy font \u2014 likely an unsubset icon font; subsetting to used glyphs usually saves most of it")}if(s.scaleAnomalies.includes(e.id)){t.push("Scale anomaly \u2014 a higher-resolution variant is smaller in bytes than a lower one; check the exports")}const n=(0,_assetStore.estDecodedBytes)(e);return(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:styles.scroll,contentContainerStyle:styles.content,testID:_testIDs.ASSETS_TEST_IDS.detailScroll,children:[(0,_jsxRuntime.jsx)(Preview,{record:e}),t.length>0?(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.findings,testID:_testIDs.ASSETS_TEST_IDS.detailFindings,children:t.map((i,l)=>(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.findingText,testID:(0,_testIDs.assetFindingTestID)(l),children:i},i))}):null,(0,_jsxRuntime.jsx)(Row,{label:"Name",value:`${e.name}.${e.type}`}),(0,_jsxRuntime.jsx)(Row,{label:"Kind",value:e.kind}),(0,_jsxRuntime.jsx)(Row,{label:"Status",value:e.loaded?"Loaded (registered at runtime)":"Not observed in the runtime registry"}),e.kind==="image"?(0,_jsxRuntime.jsx)(Row,{label:"Dimensions",value:`${(0,_format.formatDimensions)(e)} (logical)`}):null,e.kind==="image"&&e.scales.length?(0,_jsxRuntime.jsx)(Row,{label:"Scales",value:(0,_format.formatScales)(e.scales)}):null,e.sizesByScale?Object.entries(e.sizesByScale).map(([i,l])=>(0,_jsxRuntime.jsx)(Row,{label:`Size @${i}x`,value:(0,_format.formatBytes)(l)},i)):null,e.sizeBytes!=null&&e.sizeSource==="measured"?(0,_jsxRuntime.jsx)(Row,{label:"Total size",value:(0,_format.formatBytes)(e.sizeBytes)}):null,n>0?(0,_jsxRuntime.jsx)(Row,{label:"Decoded memory",value:`~${(0,_format.formatBytes)(n)} (RGBA)`}):null,e.registryId!=null?(0,_jsxRuntime.jsx)(Row,{label:"Registry id",value:String(e.registryId)}):null,e.hash?(0,_jsxRuntime.jsx)(Row,{label:"Hash",value:e.hash}):null,e.httpServerLocation?(0,_jsxRuntime.jsx)(Row,{label:"Location",value:e.httpServerLocation}):null,e.fileSystemLocation?(0,_jsxRuntime.jsx)(Row,{label:"Source dir",value:e.fileSystemLocation}):null,e.resolvedUri?(0,_jsxRuntime.jsx)(Row,{label:"Resolved URI",value:e.resolvedUri}):null]})}const styles=_reactNative.StyleSheet.create({scroll:{flex:1},content:{padding:12,gap:8},previewBox:{borderRadius:8,backgroundColor:_sharedUi.night.color.bg,padding:12,alignItems:"center",justifyContent:"center",minHeight:96},previewImage:{width:"100%",height:140},fontPreview:{color:_sharedUi.night.color.text,fontSize:16,textAlign:"center"},findings:{borderRadius:8,borderWidth:1,borderColor:_sharedUi.night.color.border,backgroundColor:_sharedUi.night.color.surface,padding:10,gap:6},findingText:{color:_sharedUi.night.color.textSecondary,fontSize:11,lineHeight:15},kvRow:{gap:2},kvLabel:{color:_sharedUi.night.color.textTertiary,fontSize:9,fontWeight:"700",letterSpacing:.5,textTransform:"uppercase"},kvValue:{color:_sharedUi.night.color.text,fontSize:12}});
@@ -1,66 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.AssetImage = AssetImage;
7
- var _react = require("react");
8
- var _reactNative = require("react-native");
9
- var _sharedUi = require("@buoy-gg/shared-ui");
10
- var _measure = require("../capture/measure");
11
- var _optionalExpoImage = require("./optionalExpoImage");
12
- var _jsxRuntime = require("react/jsx-runtime");
13
- function AssetImage({
14
- record,
15
- style,
16
- testID,
17
- compact = false
18
- }) {
19
- const source = (0, _measure.displaySource)(record);
20
- const svg = record.type.toLowerCase() === "svg";
21
- const ExpoImage = svg && _reactNative.Platform.OS !== "web" ? (0, _optionalExpoImage.getExpoPreviewImage)() : null;
22
- const sourceKey = `${record.key}:${record.hash ?? ""}:${typeof source === "number" ? source : source?.uri ?? ""}`;
23
- const [failedSource, setFailedSource] = (0, _react.useState)(null);
24
- const unavailable = source == null || failedSource === sourceKey || svg && _reactNative.Platform.OS !== "web" && !ExpoImage;
25
- if (unavailable) {
26
- const label = svg ? "SVG preview unavailable" : "Image preview unavailable";
27
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
28
- style: [style, styles.fallback],
29
- accessibilityLabel: label,
30
- testID: `${testID}-unavailable`,
31
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
32
- style: styles.text,
33
- children: compact ? svg ? "SVG" : "IMG" : label
34
- })
35
- });
36
- }
37
- const onError = () => setFailedSource(sourceKey);
38
- if (ExpoImage) {
39
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(ExpoImage, {
40
- source: source,
41
- style: style,
42
- contentFit: "contain",
43
- onError: onError,
44
- testID: testID
45
- });
46
- }
47
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Image, {
48
- source: source,
49
- style: style,
50
- resizeMode: "contain",
51
- onError: onError,
52
- testID: testID
53
- });
54
- }
55
- const styles = _reactNative.StyleSheet.create({
56
- fallback: {
57
- alignItems: "center",
58
- justifyContent: "center"
59
- },
60
- text: {
61
- color: _sharedUi.night.color.textSecondary,
62
- fontSize: 10,
63
- textAlign: "center"
64
- }
65
- });
66
- //# sourceMappingURL=AssetImage.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.AssetImage=AssetImage;var _react=require("react");var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _measure=require("../capture/measure");var _optionalExpoImage=require("./optionalExpoImage");var _jsxRuntime=require("react/jsx-runtime");function AssetImage({record:t,style:a,testID:s,compact:u=false}){const e=(0,_measure.displaySource)(t);const r=t.type.toLowerCase()==="svg";const n=r&&_reactNative.Platform.OS!=="web"?(0,_optionalExpoImage.getExpoPreviewImage)():null;const o=`${t.key}:${t.hash??""}:${typeof e==="number"?e:e?.uri??""}`;const[c,v]=(0,_react.useState)(null);const x=e==null||c===o||r&&_reactNative.Platform.OS!=="web"&&!n;if(x){const l=r?"SVG preview unavailable":"Image preview unavailable";return(0,_jsxRuntime.jsx)(_reactNative.View,{style:[a,styles.fallback],accessibilityLabel:l,testID:`${s}-unavailable`,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.text,children:u?r?"SVG":"IMG":l})})}const i=()=>v(o);if(n){return(0,_jsxRuntime.jsx)(n,{source:e,style:a,contentFit:"contain",onError:i,testID:s})}return(0,_jsxRuntime.jsx)(_reactNative.Image,{source:e,style:a,resizeMode:"contain",onError:i,testID:s})}const styles=_reactNative.StyleSheet.create({fallback:{alignItems:"center",justifyContent:"center"},text:{color:_sharedUi.night.color.textSecondary,fontSize:10,textAlign:"center"}});