@buoy-gg/assets 7.0.41 → 7.0.43

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 (204) hide show
  1. package/README.md +12 -73
  2. package/bundlers/vite.mjs +1 -53
  3. package/lib/commonjs/autoCapture.js +1 -5
  4. package/lib/commonjs/autoCapture.web.js +1 -6
  5. package/lib/commonjs/capture/assetLifecycle.js +1 -11
  6. package/lib/commonjs/capture/assetLifecycle.web.js +1 -20
  7. package/lib/commonjs/capture/browserAssets.js +1 -83
  8. package/lib/commonjs/capture/expo.js +1 -46
  9. package/lib/commonjs/capture/expo.web.js +1 -19
  10. package/lib/commonjs/capture/install.js +1 -91
  11. package/lib/commonjs/capture/install.web.js +1 -75
  12. package/lib/commonjs/capture/isBuoyAsset.js +1 -23
  13. package/lib/commonjs/capture/measure.js +1 -187
  14. package/lib/commonjs/capture/metroGraph.js +1 -175
  15. package/lib/commonjs/capture/metroGraph.web.js +1 -27
  16. package/lib/commonjs/capture/registry.js +1 -127
  17. package/lib/commonjs/components/AssetDetail.js +1 -211
  18. package/lib/commonjs/components/AssetImage.js +1 -66
  19. package/lib/commonjs/components/AssetRow.js +1 -232
  20. package/lib/commonjs/components/AssetsFilterBar.js +1 -105
  21. package/lib/commonjs/components/AssetsHeader.js +1 -73
  22. package/lib/commonjs/components/AssetsIcon.js +1 -19
  23. package/lib/commonjs/components/AssetsListControls.js +1 -81
  24. package/lib/commonjs/components/AssetsModal.js +1 -378
  25. package/lib/commonjs/components/ScanNotice.js +1 -86
  26. package/lib/commonjs/components/optionalExpoImage.js +1 -16
  27. package/lib/commonjs/components/optionalExpoImage.web.js +1 -10
  28. package/lib/commonjs/export.js +1 -62
  29. package/lib/commonjs/format.js +1 -59
  30. package/lib/commonjs/hooks/useAssetRecords.js +1 -22
  31. package/lib/commonjs/hooks/useAssetScanStatus.js +1 -28
  32. package/lib/commonjs/index.js +1 -294
  33. package/lib/commonjs/preset.js +1 -39
  34. package/lib/commonjs/remote.js +1 -68
  35. package/lib/commonjs/state.js +1 -51
  36. package/lib/commonjs/store/assetStore.js +1 -256
  37. package/lib/commonjs/store/baseline.js +1 -175
  38. package/lib/commonjs/store/insights.js +1 -120
  39. package/lib/commonjs/sync/assetsSyncAdapter.js +1 -157
  40. package/lib/commonjs/types.js +0 -1
  41. package/lib/commonjs/utils/deviceScale.js +1 -50
  42. package/lib/commonjs/utils/testIDs.js +1 -110
  43. package/lib/module/autoCapture.js +1 -5
  44. package/lib/module/autoCapture.web.js +1 -5
  45. package/lib/module/capture/assetLifecycle.js +1 -7
  46. package/lib/module/capture/assetLifecycle.web.js +1 -16
  47. package/lib/module/capture/browserAssets.js +1 -75
  48. package/lib/module/capture/expo.js +1 -41
  49. package/lib/module/capture/expo.web.js +1 -14
  50. package/lib/module/capture/install.js +1 -85
  51. package/lib/module/capture/install.web.js +1 -68
  52. package/lib/module/capture/isBuoyAsset.js +1 -18
  53. package/lib/module/capture/measure.js +1 -180
  54. package/lib/module/capture/metroGraph.js +1 -168
  55. package/lib/module/capture/metroGraph.web.js +1 -21
  56. package/lib/module/capture/registry.js +1 -120
  57. package/lib/module/components/AssetDetail.js +1 -207
  58. package/lib/module/components/AssetImage.js +1 -62
  59. package/lib/module/components/AssetRow.js +1 -228
  60. package/lib/module/components/AssetsFilterBar.js +1 -101
  61. package/lib/module/components/AssetsHeader.js +1 -69
  62. package/lib/module/components/AssetsIcon.js +1 -12
  63. package/lib/module/components/AssetsListControls.js +1 -77
  64. package/lib/module/components/AssetsModal.js +1 -373
  65. package/lib/module/components/ScanNotice.js +1 -82
  66. package/lib/module/components/optionalExpoImage.js +1 -12
  67. package/lib/module/components/optionalExpoImage.web.js +1 -6
  68. package/lib/module/export.js +1 -57
  69. package/lib/module/format.js +1 -51
  70. package/lib/module/hooks/useAssetRecords.js +1 -18
  71. package/lib/module/hooks/useAssetScanStatus.js +1 -23
  72. package/lib/module/index.js +1 -64
  73. package/lib/module/preset.js +1 -35
  74. package/lib/module/remote.js +1 -61
  75. package/lib/module/state.js +1 -47
  76. package/lib/module/store/assetStore.js +1 -240
  77. package/lib/module/store/baseline.js +1 -167
  78. package/lib/module/store/insights.js +1 -116
  79. package/lib/module/sync/assetsSyncAdapter.js +1 -153
  80. package/lib/module/types.js +0 -1
  81. package/lib/module/utils/deviceScale.js +1 -46
  82. package/lib/module/utils/testIDs.js +1 -99
  83. package/lib/web/index.mjs +3 -4
  84. package/package.json +3 -8
  85. package/lib/commonjs/autoCapture.js.map +0 -1
  86. package/lib/commonjs/autoCapture.web.js.map +0 -1
  87. package/lib/commonjs/capture/assetLifecycle.js.map +0 -1
  88. package/lib/commonjs/capture/assetLifecycle.web.js.map +0 -1
  89. package/lib/commonjs/capture/browserAssets.js.map +0 -1
  90. package/lib/commonjs/capture/expo.js.map +0 -1
  91. package/lib/commonjs/capture/expo.web.js.map +0 -1
  92. package/lib/commonjs/capture/install.js.map +0 -1
  93. package/lib/commonjs/capture/install.web.js.map +0 -1
  94. package/lib/commonjs/capture/isBuoyAsset.js.map +0 -1
  95. package/lib/commonjs/capture/measure.js.map +0 -1
  96. package/lib/commonjs/capture/metroGraph.js.map +0 -1
  97. package/lib/commonjs/capture/metroGraph.web.js.map +0 -1
  98. package/lib/commonjs/capture/registry.js.map +0 -1
  99. package/lib/commonjs/components/AssetDetail.js.map +0 -1
  100. package/lib/commonjs/components/AssetImage.js.map +0 -1
  101. package/lib/commonjs/components/AssetRow.js.map +0 -1
  102. package/lib/commonjs/components/AssetsFilterBar.js.map +0 -1
  103. package/lib/commonjs/components/AssetsHeader.js.map +0 -1
  104. package/lib/commonjs/components/AssetsIcon.js.map +0 -1
  105. package/lib/commonjs/components/AssetsListControls.js.map +0 -1
  106. package/lib/commonjs/components/AssetsModal.js.map +0 -1
  107. package/lib/commonjs/components/ScanNotice.js.map +0 -1
  108. package/lib/commonjs/components/optionalExpoImage.js.map +0 -1
  109. package/lib/commonjs/components/optionalExpoImage.web.js.map +0 -1
  110. package/lib/commonjs/export.js.map +0 -1
  111. package/lib/commonjs/format.js.map +0 -1
  112. package/lib/commonjs/hooks/useAssetRecords.js.map +0 -1
  113. package/lib/commonjs/hooks/useAssetScanStatus.js.map +0 -1
  114. package/lib/commonjs/index.js.map +0 -1
  115. package/lib/commonjs/preset.js.map +0 -1
  116. package/lib/commonjs/remote.js.map +0 -1
  117. package/lib/commonjs/state.js.map +0 -1
  118. package/lib/commonjs/store/assetStore.js.map +0 -1
  119. package/lib/commonjs/store/baseline.js.map +0 -1
  120. package/lib/commonjs/store/insights.js.map +0 -1
  121. package/lib/commonjs/sync/assetsSyncAdapter.js.map +0 -1
  122. package/lib/commonjs/types.js.map +0 -1
  123. package/lib/commonjs/utils/deviceScale.js.map +0 -1
  124. package/lib/commonjs/utils/testIDs.js.map +0 -1
  125. package/lib/module/autoCapture.js.map +0 -1
  126. package/lib/module/autoCapture.web.js.map +0 -1
  127. package/lib/module/capture/assetLifecycle.js.map +0 -1
  128. package/lib/module/capture/assetLifecycle.web.js.map +0 -1
  129. package/lib/module/capture/browserAssets.js.map +0 -1
  130. package/lib/module/capture/expo.js.map +0 -1
  131. package/lib/module/capture/expo.web.js.map +0 -1
  132. package/lib/module/capture/install.js.map +0 -1
  133. package/lib/module/capture/install.web.js.map +0 -1
  134. package/lib/module/capture/isBuoyAsset.js.map +0 -1
  135. package/lib/module/capture/measure.js.map +0 -1
  136. package/lib/module/capture/metroGraph.js.map +0 -1
  137. package/lib/module/capture/metroGraph.web.js.map +0 -1
  138. package/lib/module/capture/registry.js.map +0 -1
  139. package/lib/module/components/AssetDetail.js.map +0 -1
  140. package/lib/module/components/AssetImage.js.map +0 -1
  141. package/lib/module/components/AssetRow.js.map +0 -1
  142. package/lib/module/components/AssetsFilterBar.js.map +0 -1
  143. package/lib/module/components/AssetsHeader.js.map +0 -1
  144. package/lib/module/components/AssetsIcon.js.map +0 -1
  145. package/lib/module/components/AssetsListControls.js.map +0 -1
  146. package/lib/module/components/AssetsModal.js.map +0 -1
  147. package/lib/module/components/ScanNotice.js.map +0 -1
  148. package/lib/module/components/optionalExpoImage.js.map +0 -1
  149. package/lib/module/components/optionalExpoImage.web.js.map +0 -1
  150. package/lib/module/export.js.map +0 -1
  151. package/lib/module/format.js.map +0 -1
  152. package/lib/module/hooks/useAssetRecords.js.map +0 -1
  153. package/lib/module/hooks/useAssetScanStatus.js.map +0 -1
  154. package/lib/module/index.js.map +0 -1
  155. package/lib/module/preset.js.map +0 -1
  156. package/lib/module/remote.js.map +0 -1
  157. package/lib/module/state.js.map +0 -1
  158. package/lib/module/store/assetStore.js.map +0 -1
  159. package/lib/module/store/baseline.js.map +0 -1
  160. package/lib/module/store/insights.js.map +0 -1
  161. package/lib/module/sync/assetsSyncAdapter.js.map +0 -1
  162. package/lib/module/types.js.map +0 -1
  163. package/lib/module/utils/deviceScale.js.map +0 -1
  164. package/lib/module/utils/testIDs.js.map +0 -1
  165. package/lib/typescript/autoCapture.d.ts.map +0 -1
  166. package/lib/typescript/autoCapture.web.d.ts.map +0 -1
  167. package/lib/typescript/capture/assetLifecycle.d.ts.map +0 -1
  168. package/lib/typescript/capture/assetLifecycle.web.d.ts.map +0 -1
  169. package/lib/typescript/capture/browserAssets.d.ts.map +0 -1
  170. package/lib/typescript/capture/expo.d.ts.map +0 -1
  171. package/lib/typescript/capture/expo.web.d.ts.map +0 -1
  172. package/lib/typescript/capture/install.d.ts.map +0 -1
  173. package/lib/typescript/capture/install.web.d.ts.map +0 -1
  174. package/lib/typescript/capture/isBuoyAsset.d.ts.map +0 -1
  175. package/lib/typescript/capture/measure.d.ts.map +0 -1
  176. package/lib/typescript/capture/metroGraph.d.ts.map +0 -1
  177. package/lib/typescript/capture/metroGraph.web.d.ts.map +0 -1
  178. package/lib/typescript/capture/registry.d.ts.map +0 -1
  179. package/lib/typescript/components/AssetDetail.d.ts.map +0 -1
  180. package/lib/typescript/components/AssetImage.d.ts.map +0 -1
  181. package/lib/typescript/components/AssetRow.d.ts.map +0 -1
  182. package/lib/typescript/components/AssetsFilterBar.d.ts.map +0 -1
  183. package/lib/typescript/components/AssetsHeader.d.ts.map +0 -1
  184. package/lib/typescript/components/AssetsIcon.d.ts.map +0 -1
  185. package/lib/typescript/components/AssetsListControls.d.ts.map +0 -1
  186. package/lib/typescript/components/AssetsModal.d.ts.map +0 -1
  187. package/lib/typescript/components/ScanNotice.d.ts.map +0 -1
  188. package/lib/typescript/components/optionalExpoImage.d.ts.map +0 -1
  189. package/lib/typescript/components/optionalExpoImage.web.d.ts.map +0 -1
  190. package/lib/typescript/export.d.ts.map +0 -1
  191. package/lib/typescript/format.d.ts.map +0 -1
  192. package/lib/typescript/hooks/useAssetRecords.d.ts.map +0 -1
  193. package/lib/typescript/hooks/useAssetScanStatus.d.ts.map +0 -1
  194. package/lib/typescript/index.d.ts.map +0 -1
  195. package/lib/typescript/preset.d.ts.map +0 -1
  196. package/lib/typescript/remote.d.ts.map +0 -1
  197. package/lib/typescript/state.d.ts.map +0 -1
  198. package/lib/typescript/store/assetStore.d.ts.map +0 -1
  199. package/lib/typescript/store/baseline.d.ts.map +0 -1
  200. package/lib/typescript/store/insights.d.ts.map +0 -1
  201. package/lib/typescript/sync/assetsSyncAdapter.d.ts.map +0 -1
  202. package/lib/typescript/types.d.ts.map +0 -1
  203. package/lib/typescript/utils/deviceScale.d.ts.map +0 -1
  204. package/lib/typescript/utils/testIDs.d.ts.map +0 -1
@@ -1,51 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * Shared formatting helpers for rows, detail view, and markdown export.
5
- */
6
-
7
- export function formatBytes(bytes) {
8
- if (bytes == null || bytes <= 0) return "—";
9
- if (bytes < 1024) return `${bytes} B`;
10
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
11
- return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
12
- }
13
- export function formatScales(scales) {
14
- const unique = [...new Set(scales)].sort((a, b) => a - b);
15
- if (!unique.length) return "—";
16
- if (unique.length === 1) return `@${unique[0]}x`;
17
- if (unique.length <= 3) return unique.map(s => `@${s}x`).join(" ");
18
- return `@${unique[0]}x–@${unique[unique.length - 1]}x`;
19
- }
20
- export function formatDimensions(record) {
21
- if (record.width == null || record.height == null) return "—";
22
- return `${Math.round(record.width)}×${Math.round(record.height)}`;
23
- }
24
-
25
- /** Display size: measured bytes, or "~" decoded estimate for unmeasured images. */
26
- export function formatSize(record, estDecoded) {
27
- if (record.sizeBytes != null && record.sizeSource === "measured") {
28
- return formatBytes(record.sizeBytes);
29
- }
30
- if (estDecoded > 0) return `~${formatBytes(estDecoded)}`;
31
- return "—";
32
- }
33
- export const KIND_LABELS = {
34
- image: "IMG",
35
- font: "FONT",
36
- video: "VID",
37
- audio: "AUD",
38
- data: "DATA",
39
- other: "MISC"
40
- };
41
-
42
- /** Family accent per kind — the card's left edge, like network's method bar. */
43
- export const KIND_COLORS = {
44
- image: "#2DD4BF",
45
- font: "#C084FC",
46
- video: "#FF9F1C",
47
- audio: "#FF3366",
48
- data: "#00D4FF",
49
- other: "#8E8E93"
50
- };
51
- //# sourceMappingURL=format.js.map
1
+ "use strict";export function formatBytes(t){if(t==null||t<=0)return"\u2014";if(t<1024)return`${t} B`;if(t<1024*1024)return`${(t/1024).toFixed(1)} KB`;return`${(t/(1024*1024)).toFixed(2)} MB`}export function formatScales(t){const n=[...new Set(t)].sort((e,i)=>e-i);if(!n.length)return"\u2014";if(n.length===1)return`@${n[0]}x`;if(n.length<=3)return n.map(e=>`@${e}x`).join(" ");return`@${n[0]}x\u2013@${n[n.length-1]}x`}export function formatDimensions(t){if(t.width==null||t.height==null)return"\u2014";return`${Math.round(t.width)}\xD7${Math.round(t.height)}`}export function formatSize(t,n){if(t.sizeBytes!=null&&t.sizeSource==="measured"){return formatBytes(t.sizeBytes)}if(n>0)return`~${formatBytes(n)}`;return"\u2014"}export const KIND_LABELS={image:"IMG",font:"FONT",video:"VID",audio:"AUD",data:"DATA",other:"MISC"};export const KIND_COLORS={image:"#2DD4BF",font:"#C084FC",video:"#FF9F1C",audio:"#FF3366",data:"#00D4FF",other:"#8E8E93"};
@@ -1,18 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * React bindings for the asset store.
5
- */
6
-
7
- import { useMemo, useSyncExternalStore } from "react";
8
- import { computeStats, getSnapshot, subscribe } from "../store/assetStore";
9
- import { computeInsights } from "../store/insights";
10
- export function useAssetRecords() {
11
- const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
12
- return useMemo(() => ({
13
- records: snapshot,
14
- stats: computeStats(snapshot),
15
- insights: computeInsights(snapshot)
16
- }), [snapshot]);
17
- }
18
- //# sourceMappingURL=useAssetRecords.js.map
1
+ "use strict";import{useMemo as o,useSyncExternalStore as e}from"react";import{computeStats as r,getSnapshot as s,subscribe as n}from"../store/assetStore";import{computeInsights as c}from"../store/insights";export function useAssetRecords(){const t=e(n,s,s);return o(()=>({records:t,stats:r(t),insights:c(t)}),[t])}
@@ -1,23 +1 @@
1
- "use strict";
2
-
3
- import { useSyncExternalStore } from "react";
4
- import { getScanStatus } from "../capture/install";
5
- import { getSnapshot, subscribe } from "../store/assetStore";
6
- let previousRecords;
7
- let previousStatus;
8
-
9
- /** Each store notification replaces the records snapshot, including status-only updates. */
10
- export function getAssetScanSnapshot() {
11
- const records = getSnapshot();
12
- if (records !== previousRecords) {
13
- previousRecords = records;
14
- previousStatus = getScanStatus();
15
- }
16
- return previousStatus;
17
- }
18
-
19
- /** Keep scan status reactive in apps that use React Compiler. */
20
- export function useAssetScanStatus() {
21
- return useSyncExternalStore(subscribe, getAssetScanSnapshot, getAssetScanSnapshot);
22
- }
23
- //# sourceMappingURL=useAssetScanStatus.js.map
1
+ "use strict";import{useSyncExternalStore as s}from"react";import{getScanStatus as o}from"../capture/install";import{getSnapshot as n,subscribe as u}from"../store/assetStore";let e;let r;export function getAssetScanSnapshot(){const t=n();if(t!==e){e=t;r=o()}return r}export function useAssetScanStatus(){return s(u,getAssetScanSnapshot,getAssetScanSnapshot)}
@@ -1,64 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * @buoy-gg/assets — bundled-asset inventory for React Native / Expo.
5
- *
6
- * Enumerates every asset in the app (images, fonts, video, audio, …) via the
7
- * runtime asset registry, enriched in dev with the Metro graph (full-bundle
8
- * coverage, byte sizes, never-loaded detection) and on Expo with loaded font
9
- * families + the updates localAssets map. Zero configuration: importing this
10
- * package installs the (cheap, synchronous) registry capture.
11
- */
12
-
13
- // ---------------------------------------------------------------------------
14
- // Tool preset (FloatingDevTools)
15
- // ---------------------------------------------------------------------------
16
- export { assetsToolPreset, createAssetsTool } from "./preset";
17
-
18
- // ---------------------------------------------------------------------------
19
- // Components
20
- // ---------------------------------------------------------------------------
21
- export { AssetsModal, AssetsToolView } from "./components/AssetsModal";
22
- export { AssetsIcon, ASSETS_ICON_COLOR } from "./components/AssetsIcon";
23
-
24
- // ---------------------------------------------------------------------------
25
- // Capture / scanning
26
- // ---------------------------------------------------------------------------
27
- export { installAssetCapture, rescan, getScanStatus } from "./capture/install";
28
- export { measureSizes } from "./capture/measure";
29
- export { fetchAssetGraph, getDevServerOrigin } from "./capture/metroGraph";
30
- export { getLoadedFontFamilies, getLocalAssets } from "./capture/expo";
31
-
32
- // ---------------------------------------------------------------------------
33
- // Store
34
- // ---------------------------------------------------------------------------
35
- export { clearRecords, computeStats, estDecodedBytes, getRecord, getSnapshot, subscribe } from "./store/assetStore";
36
- export { computeInsights } from "./store/insights";
37
- export { clearBaseline, computeDiff, getDiff, loadBaseline, saveBaseline } from "./store/baseline";
38
- export { useAssetRecords } from "./hooks/useAssetRecords";
39
-
40
- // ---------------------------------------------------------------------------
41
- // Reports
42
- // ---------------------------------------------------------------------------
43
- export { formatAssetMarkdown, formatInventoryMarkdown } from "./export";
44
-
45
- // ---------------------------------------------------------------------------
46
- // External sync (desktop dashboard + MCP)
47
- // ---------------------------------------------------------------------------
48
- export { assetsSyncAdapter } from "./sync/assetsSyncAdapter";
49
- export { disableAssetsCapture, replaceAssetsFromSnapshot, setRemoteAssetsHandler } from "./remote";
50
- // ---------------------------------------------------------------------------
51
- // Automation handles
52
- // ---------------------------------------------------------------------------
53
- export { ASSETS_TEST_IDS, assetBadgeTestID, assetDetailRowTestID, assetFilterTestID, assetFindingTestID, assetFontChipTestID, assetRowTestID, assetSlug } from "./utils/testIDs";
54
-
55
- // ---------------------------------------------------------------------------
56
- // Types
57
- // ---------------------------------------------------------------------------
58
-
59
- // Side effect: install the registry capture at import (walk + patch — cheap,
60
- // synchronous, no network). The Metro graph fetch waits for the modal/action.
61
- import "./autoCapture";
62
- export { registerBrowserAssetManifest, loadBrowserAssetManifest, getBrowserAssetManifest } from "./capture/browserAssets";
63
- export { startBrowserAssetCapture } from "./capture/assetLifecycle";
64
- //# sourceMappingURL=index.js.map
1
+ "use strict";export{assetsToolPreset,createAssetsTool}from"./preset";export{AssetsModal,AssetsToolView}from"./components/AssetsModal";export{AssetsIcon,ASSETS_ICON_COLOR}from"./components/AssetsIcon";export{installAssetCapture,rescan,getScanStatus}from"./capture/install";export{measureSizes}from"./capture/measure";export{fetchAssetGraph,getDevServerOrigin}from"./capture/metroGraph";export{getLoadedFontFamilies,getLocalAssets}from"./capture/expo";export{clearRecords,computeStats,estDecodedBytes,getRecord,getSnapshot,subscribe}from"./store/assetStore";export{computeInsights}from"./store/insights";export{clearBaseline,computeDiff,getDiff,loadBaseline,saveBaseline}from"./store/baseline";export{useAssetRecords}from"./hooks/useAssetRecords";export{formatAssetMarkdown,formatInventoryMarkdown}from"./export";export{assetsSyncAdapter}from"./sync/assetsSyncAdapter";export{disableAssetsCapture,replaceAssetsFromSnapshot,setRemoteAssetsHandler}from"./remote";export{ASSETS_TEST_IDS,assetBadgeTestID,assetDetailRowTestID,assetFilterTestID,assetFindingTestID,assetFontChipTestID,assetRowTestID,assetSlug}from"./utils/testIDs";import"./autoCapture";export{registerBrowserAssetManifest,loadBrowserAssetManifest,getBrowserAssetManifest}from"./capture/browserAssets";export{startBrowserAssetCapture}from"./capture/assetLifecycle";
@@ -1,35 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * Pre-configured Assets tool for FloatingDevTools.
5
- *
6
- * @example
7
- * ```tsx
8
- * import { assetsToolPreset } from '@buoy-gg/assets';
9
- *
10
- * <FloatingDevTools apps={[assetsToolPreset]} />
11
- * ```
12
- */
13
-
14
- import { AssetsIcon, ASSETS_ICON_COLOR } from "./components/AssetsIcon";
15
- import { AssetsModal } from "./components/AssetsModal";
16
- import { createToolFactory, defineToolPreset } from "@buoy-gg/shared-ui";
17
- import { jsx as _jsx } from "react/jsx-runtime";
18
- export const assetsToolPreset = defineToolPreset({
19
- id: "assets",
20
- name: "ASSETS",
21
- description: "Every bundled asset — sizes, scale coverage, unused detection",
22
- slot: "both",
23
- icon: ({
24
- size,
25
- color
26
- }) => /*#__PURE__*/_jsx(AssetsIcon, {
27
- size: size,
28
- color: color || ASSETS_ICON_COLOR
29
- }),
30
- component: AssetsModal
31
- });
32
-
33
- /** Create a custom Assets tool configuration. */
34
- export const createAssetsTool = createToolFactory(assetsToolPreset);
35
- //# sourceMappingURL=preset.js.map
1
+ "use strict";import{AssetsIcon as e,ASSETS_ICON_COLOR as t}from"./components/AssetsIcon";import{AssetsModal as r}from"./components/AssetsModal";import{createToolFactory as c,defineToolPreset as i}from"@buoy-gg/shared-ui";import{jsx as n}from"react/jsx-runtime";export const assetsToolPreset=i({id:"assets",name:"ASSETS",description:"Every bundled asset \u2014 sizes, scale coverage, unused detection",slot:"both",icon:({size:o,color:s})=>n(e,{size:o,color:s||t}),component:r});export const createAssetsTool=c(assetsToolPreset);
@@ -1,61 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * Remote-dispatch seam for dashboard mirrors (Buoy Desktop).
5
- *
6
- * On device this stays null and every action runs locally. A dashboard sets
7
- * a handler that forwards action name + params over external-sync to the
8
- * SAME adapter actions the MCP uses (sync/assetsSyncAdapter.ts), so one
9
- * action vocabulary serves phone UI, desktop UI, and LLM automation.
10
- */
11
-
12
- import { assetsState } from "./state";
13
- import { invalidate } from "./store/assetStore";
14
- export function setRemoteAssetsHandler(handler) {
15
- assetsState().remoteDispatch = handler;
16
- }
17
- export function remoteAssetsDispatch() {
18
- return assetsState().remoteDispatch;
19
- }
20
-
21
- /** Dashboards never scan their own bundle — the store is purely a mirror. */
22
- export function disableAssetsCapture() {
23
- assetsState().captureDisabled = true;
24
- }
25
-
26
- /** Replace the whole store from a synced adapter snapshot. */
27
- export function replaceAssetsFromSnapshot(payload) {
28
- const s = assetsState();
29
- const wire = payload.records ?? [];
30
- s.records = wire.map(w => ({
31
- id: w.id,
32
- key: w.key,
33
- registryId: w.registryId ?? undefined,
34
- name: w.name,
35
- type: w.type,
36
- kind: w.kind,
37
- hash: w.hash ?? undefined,
38
- httpServerLocation: w.location ?? undefined,
39
- width: w.width ?? undefined,
40
- height: w.height ?? undefined,
41
- scales: w.scales,
42
- resolvedUri: w.uri ?? undefined,
43
- loaded: w.loaded,
44
- origin: w.registryId != null ? "registry" : "graph",
45
- sizeBytes: w.sizeBytes ?? undefined,
46
- sizeSource: w.sizeSource ?? undefined,
47
- firstSeenAt: Date.now()
48
- }));
49
- s.byKey = new Map(s.records.map(r => [r.key, r]));
50
- s.byId = new Map(s.records.map(r => [r.id, r]));
51
- if (payload.scanStatus) {
52
- s.fontFamilies = [...new Set(payload.scanStatus.fontFamilies ?? [])];
53
- s.mirrorScanStatus = {
54
- ...payload.scanStatus,
55
- fontFamilies: s.fontFamilies
56
- };
57
- }
58
- s.mirrorDiff = payload.diff ?? null;
59
- invalidate();
60
- }
61
- //# sourceMappingURL=remote.js.map
1
+ "use strict";import{assetsState as s}from"./state";import{invalidate as r}from"./store/assetStore";export function setRemoteAssetsHandler(i){s().remoteDispatch=i}export function remoteAssetsDispatch(){return s().remoteDispatch}export function disableAssetsCapture(){s().captureDisabled=true}export function replaceAssetsFromSnapshot(i){const t=s();const n=i.records??[];t.records=n.map(e=>({id:e.id,key:e.key,registryId:e.registryId??void 0,name:e.name,type:e.type,kind:e.kind,hash:e.hash??void 0,httpServerLocation:e.location??void 0,width:e.width??void 0,height:e.height??void 0,scales:e.scales,resolvedUri:e.uri??void 0,loaded:e.loaded,origin:e.registryId!=null?"registry":"graph",sizeBytes:e.sizeBytes??void 0,sizeSource:e.sizeSource??void 0,firstSeenAt:Date.now()}));t.byKey=new Map(t.records.map(e=>[e.key,e]));t.byId=new Map(t.records.map(e=>[e.id,e]));if(i.scanStatus){t.fontFamilies=[...new Set(i.scanStatus.fontFamilies??[])];t.mirrorScanStatus={...i.scanStatus,fontFamilies:t.fontFamilies}}t.mirrorDiff=i.diff??null;r()}
@@ -1,47 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * Global singleton state for the Assets tool.
5
- *
6
- * Same rationale as the images tool: the package can be evaluated as two
7
- * module instances (lib vs src resolution), and the registerAsset patch must
8
- * share one store with whichever copy the UI renders from. All mutable state
9
- * lives on globalThis under a well-known symbol.
10
- */
11
-
12
- const KEY = Symbol.for("buoy.assets.globalState.v1");
13
- export function assetsState() {
14
- const g = globalThis;
15
- if (!g[KEY]) {
16
- g[KEY] = {
17
- records: [],
18
- byKey: new Map(),
19
- byId: new Map(),
20
- nextId: 1,
21
- listeners: new Set(),
22
- snapshot: [],
23
- emitScheduled: false,
24
- installed: false,
25
- patched: false,
26
- registryAvailable: false,
27
- graphSupported: false,
28
- graphCount: null,
29
- graphError: null,
30
- graphFetchInFlight: false,
31
- lastScanAt: null,
32
- measuring: false,
33
- measuredCount: 0,
34
- fontFamilies: [],
35
- localAssetCount: null,
36
- baseline: null,
37
- baselineLoaded: false,
38
- captureDisabled: false,
39
- remoteDispatch: null,
40
- mirrorScanStatus: null,
41
- mirrorPixelRatio: null,
42
- mirrorDiff: null
43
- };
44
- }
45
- return g[KEY];
46
- }
47
- //# sourceMappingURL=state.js.map
1
+ "use strict";const l=Symbol.for("buoy.assets.globalState.v1");export function assetsState(){const e=globalThis;if(!e[l]){e[l]={records:[],byKey:new Map,byId:new Map,nextId:1,listeners:new Set,snapshot:[],emitScheduled:false,installed:false,patched:false,registryAvailable:false,graphSupported:false,graphCount:null,graphError:null,graphFetchInFlight:false,lastScanAt:null,measuring:false,measuredCount:0,fontFamilies:[],localAssetCount:null,baseline:null,baselineLoaded:false,captureDisabled:false,remoteDispatch:null,mirrorScanStatus:null,mirrorPixelRatio:null,mirrorDiff:null}}return e[l]}
@@ -1,240 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * assetStore
5
- *
6
- * Bounded store of AssetRecords keyed by their stable asset key
7
- * (`location/name.type`). Follows the images tool's store shape — Set of
8
- * listeners, frame-coalesced emit, all mutable state on the globalThis
9
- * singleton (../state.ts) so dual module instances share one store.
10
- *
11
- * Unlike the images tool this is an INVENTORY, not an event log: upserts
12
- * merge into the existing record for a key instead of appending, and there
13
- * is no ring-buffer cap (a bundle has a bounded asset count by construction).
14
- */
15
-
16
- import { assetsState } from "../state";
17
- import { isBuoyAsset } from "../capture/isBuoyAsset";
18
- import { effectivePixelRatio, pickScale } from "../utils/deviceScale";
19
- function emit() {
20
- const s = assetsState();
21
- if (s.emitScheduled) return;
22
- s.emitScheduled = true;
23
- requestAnimationFrame(() => {
24
- s.emitScheduled = false;
25
- for (const listener of s.listeners) listener();
26
- });
27
- }
28
-
29
- /** Snapshot identity only changes on emit, so useSyncExternalStore stays cheap. */
30
- export function invalidate() {
31
- const s = assetsState();
32
- s.snapshot = [...s.records];
33
- emit();
34
- }
35
- const KIND_BY_EXT = {
36
- png: "image",
37
- jpg: "image",
38
- jpeg: "image",
39
- gif: "image",
40
- webp: "image",
41
- bmp: "image",
42
- psd: "image",
43
- svg: "image",
44
- tiff: "image",
45
- ktx: "image",
46
- heic: "image",
47
- heif: "image",
48
- avif: "image",
49
- ttf: "font",
50
- otf: "font",
51
- woff: "font",
52
- woff2: "font",
53
- ttc: "font",
54
- mp4: "video",
55
- m4v: "video",
56
- mov: "video",
57
- mpeg: "video",
58
- mpg: "video",
59
- webm: "video",
60
- avi: "video",
61
- mp3: "audio",
62
- wav: "audio",
63
- aac: "audio",
64
- aiff: "audio",
65
- caf: "audio",
66
- m4a: "audio",
67
- ogg: "audio",
68
- json: "data",
69
- db: "data",
70
- yaml: "data",
71
- yml: "data",
72
- xml: "data",
73
- html: "data",
74
- pdf: "data",
75
- zip: "data"
76
- };
77
- export function kindForType(type) {
78
- return KIND_BY_EXT[type.toLowerCase()] ?? "other";
79
- }
80
- export function assetKey(httpServerLocation, name, type) {
81
- // The runtime registry percent-encodes ?unstable_path= locations while the
82
- // Metro graph endpoint returns them decoded — normalize or every asset
83
- // splits into a registry record + a graph record.
84
- let location = httpServerLocation ?? "";
85
- try {
86
- location = decodeURIComponent(location);
87
- } catch {
88
- // malformed escapes: keep the raw string
89
- }
90
- return `${location}/${name}.${type}`;
91
- }
92
- /** Merge an asset sighting into the store; creates the record on first sight. */
93
- export function upsertRecord(input) {
94
- if (isBuoyAsset(input)) return undefined;
95
- const s = assetsState();
96
- let record = s.byKey.get(input.key);
97
- if (!record) {
98
- record = {
99
- id: s.nextId++,
100
- key: input.key,
101
- name: input.name,
102
- type: input.type,
103
- kind: kindForType(input.type),
104
- scales: input.scales ?? [],
105
- loaded: input.loaded ?? false,
106
- origin: input.origin,
107
- firstSeenAt: Date.now()
108
- };
109
- s.records.push(record);
110
- s.byKey.set(record.key, record);
111
- s.byId.set(record.id, record);
112
- }
113
- if (input.registryId != null) record.registryId = input.registryId;
114
- if (input.hash != null) record.hash = input.hash;
115
- if (input.httpServerLocation != null) record.httpServerLocation = input.httpServerLocation;
116
- if (input.width != null) record.width = input.width;
117
- if (input.height != null) record.height = input.height;
118
- if (input.scales && input.scales.length) {
119
- // Dedupe: foo.png + foo@1x.png both existing yields [1, 1, …] from Metro.
120
- record.scales = [...new Set(input.scales)].sort((a, b) => a - b);
121
- }
122
- if (input.resolvedUri != null) record.resolvedUri = input.resolvedUri;
123
- if (input.resolvedScale != null) record.resolvedScale = input.resolvedScale;
124
- if (input.loaded) record.loaded = true;
125
- if (input.fileSystemLocation != null) record.fileSystemLocation = input.fileSystemLocation;
126
- if (input.files) record.files = input.files;
127
- if (input.fileHashes) record.fileHashes = input.fileHashes;
128
- invalidate();
129
- return record;
130
- }
131
-
132
- /** Mutate a record in place (records are owned by the store) and notify. */
133
- export function updateRecord(id, patch) {
134
- const s = assetsState();
135
- const record = s.byId.get(id);
136
- if (!record) return undefined;
137
- Object.assign(record, patch);
138
- invalidate();
139
- return record;
140
- }
141
- export function getRecord(id) {
142
- return assetsState().byId.get(id);
143
- }
144
- export function getRecordByKey(key) {
145
- return assetsState().byKey.get(key);
146
- }
147
- export function getSnapshot() {
148
- return assetsState().snapshot;
149
- }
150
- export function subscribe(listener) {
151
- const s = assetsState();
152
- s.listeners.add(listener);
153
- return () => assetsState().listeners.delete(listener);
154
- }
155
- export function clearRecords() {
156
- const s = assetsState();
157
- s.records = [];
158
- s.byKey = new Map();
159
- s.byId = new Map();
160
- s.measuredCount = 0;
161
- s.graphCount = null;
162
- invalidate();
163
- }
164
-
165
- /** Remove records captured before the exclusion was installed through Fast Refresh. */
166
- export function removeBuoyRecords() {
167
- const s = assetsState();
168
- const remaining = s.records.filter(record => !isBuoyAsset(record));
169
- if (remaining.length === s.records.length) return;
170
- s.records = remaining;
171
- s.byKey = new Map(remaining.map(record => [record.key, record]));
172
- s.byId = new Map(remaining.map(record => [record.id, record]));
173
- s.measuredCount = remaining.filter(record => record.sizeSource === "measured").length;
174
- invalidate();
175
- }
176
-
177
- /**
178
- * Estimated decoded-bitmap memory (RGBA8888) at the scale this device would
179
- * pick — the size fallback when bytes can't be measured (release builds).
180
- *
181
- * `resolvedScale` is React Native's own answer and is authoritative, but it
182
- * only exists once the asset has been REGISTERED. For everything still known
183
- * only from the Metro graph — the never-loaded set, which is most of what this
184
- * tool is for — the scale has to be predicted the same way AssetSourceResolver
185
- * would, not taken as the largest variant shipped.
186
- */
187
- export function estDecodedBytes(record) {
188
- if (record.kind !== "image" || !record.width || !record.height) return 0;
189
- const scale = record.resolvedScale ?? pickScale(record.scales, effectivePixelRatio());
190
- return Math.round(record.width * scale * record.height * scale * 4);
191
- }
192
- export function computeStats(list) {
193
- const s = assetsState();
194
- const byKind = {
195
- image: {
196
- count: 0,
197
- bytes: 0
198
- },
199
- font: {
200
- count: 0,
201
- bytes: 0
202
- },
203
- video: {
204
- count: 0,
205
- bytes: 0
206
- },
207
- audio: {
208
- count: 0,
209
- bytes: 0
210
- },
211
- data: {
212
- count: 0,
213
- bytes: 0
214
- },
215
- other: {
216
- count: 0,
217
- bytes: 0
218
- }
219
- };
220
- const stats = {
221
- total: list.length,
222
- loaded: 0,
223
- neverLoaded: 0,
224
- byKind,
225
- totalBytes: 0,
226
- measuredCount: 0,
227
- fontFamilies: s.fontFamilies.length
228
- };
229
- for (const r of list) {
230
- if (r.loaded) stats.loaded++;else stats.neverLoaded++;
231
- byKind[r.kind].count++;
232
- if (r.sizeBytes != null && r.sizeSource === "measured") {
233
- byKind[r.kind].bytes += r.sizeBytes;
234
- stats.totalBytes += r.sizeBytes;
235
- stats.measuredCount++;
236
- }
237
- }
238
- return stats;
239
- }
240
- //# sourceMappingURL=assetStore.js.map
1
+ "use strict";import{assetsState as a}from"../state";import{isBuoyAsset as r}from"../capture/isBuoyAsset";import{effectivePixelRatio as n,pickScale as d}from"../utils/deviceScale";function l(){const e=a();if(e.emitScheduled)return;e.emitScheduled=true;requestAnimationFrame(()=>{e.emitScheduled=false;for(const o of e.listeners)o()})}export function invalidate(){const e=a();e.snapshot=[...e.records];l()}const c={png:"image",jpg:"image",jpeg:"image",gif:"image",webp:"image",bmp:"image",psd:"image",svg:"image",tiff:"image",ktx:"image",heic:"image",heif:"image",avif:"image",ttf:"font",otf:"font",woff:"font",woff2:"font",ttc:"font",mp4:"video",m4v:"video",mov:"video",mpeg:"video",mpg:"video",webm:"video",avi:"video",mp3:"audio",wav:"audio",aac:"audio",aiff:"audio",caf:"audio",m4a:"audio",ogg:"audio",json:"data",db:"data",yaml:"data",yml:"data",xml:"data",html:"data",pdf:"data",zip:"data"};export function kindForType(e){return c[e.toLowerCase()]??"other"}export function assetKey(e,o,t){let s=e??"";try{s=decodeURIComponent(s)}catch{}return`${s}/${o}.${t}`}export function upsertRecord(e){if(r(e))return void 0;const o=a();let t=o.byKey.get(e.key);if(!t){t={id:o.nextId++,key:e.key,name:e.name,type:e.type,kind:kindForType(e.type),scales:e.scales??[],loaded:e.loaded??false,origin:e.origin,firstSeenAt:Date.now()};o.records.push(t);o.byKey.set(t.key,t);o.byId.set(t.id,t)}if(e.registryId!=null)t.registryId=e.registryId;if(e.hash!=null)t.hash=e.hash;if(e.httpServerLocation!=null)t.httpServerLocation=e.httpServerLocation;if(e.width!=null)t.width=e.width;if(e.height!=null)t.height=e.height;if(e.scales&&e.scales.length){t.scales=[...new Set(e.scales)].sort((s,i)=>s-i)}if(e.resolvedUri!=null)t.resolvedUri=e.resolvedUri;if(e.resolvedScale!=null)t.resolvedScale=e.resolvedScale;if(e.loaded)t.loaded=true;if(e.fileSystemLocation!=null)t.fileSystemLocation=e.fileSystemLocation;if(e.files)t.files=e.files;if(e.fileHashes)t.fileHashes=e.fileHashes;invalidate();return t}export function updateRecord(e,o){const t=a();const s=t.byId.get(e);if(!s)return void 0;Object.assign(s,o);invalidate();return s}export function getRecord(e){return a().byId.get(e)}export function getRecordByKey(e){return a().byKey.get(e)}export function getSnapshot(){return a().snapshot}export function subscribe(e){const o=a();o.listeners.add(e);return()=>a().listeners.delete(e)}export function clearRecords(){const e=a();e.records=[];e.byKey=new Map;e.byId=new Map;e.measuredCount=0;e.graphCount=null;invalidate()}export function removeBuoyRecords(){const e=a();const o=e.records.filter(t=>!r(t));if(o.length===e.records.length)return;e.records=o;e.byKey=new Map(o.map(t=>[t.key,t]));e.byId=new Map(o.map(t=>[t.id,t]));e.measuredCount=o.filter(t=>t.sizeSource==="measured").length;invalidate()}export function estDecodedBytes(e){if(e.kind!=="image"||!e.width||!e.height)return 0;const o=e.resolvedScale??d(e.scales,n());return Math.round(e.width*o*e.height*o*4)}export function computeStats(e){const o=a();const t={image:{count:0,bytes:0},font:{count:0,bytes:0},video:{count:0,bytes:0},audio:{count:0,bytes:0},data:{count:0,bytes:0},other:{count:0,bytes:0}};const s={total:e.length,loaded:0,neverLoaded:0,byKind:t,totalBytes:0,measuredCount:0,fontFamilies:o.fontFamilies.length};for(const i of e){if(i.loaded)s.loaded++;else s.neverLoaded++;t[i.kind].count++;if(i.sizeBytes!=null&&i.sizeSource==="measured"){t[i.kind].bytes+=i.sizeBytes;s.totalBytes+=i.sizeBytes;s.measuredCount++}}return s}