@buoy-gg/assets 7.0.36 → 7.0.38

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 (165) hide show
  1. package/README.md +41 -12
  2. package/lib/commonjs/capture/expo.js +1 -46
  3. package/lib/commonjs/capture/install.js +1 -78
  4. package/lib/commonjs/capture/isBuoyAsset.js +1 -0
  5. package/lib/commonjs/capture/measure.js +1 -186
  6. package/lib/commonjs/capture/metroGraph.js +1 -148
  7. package/lib/commonjs/capture/registry.js +1 -127
  8. package/lib/commonjs/components/AssetDetail.js +1 -214
  9. package/lib/commonjs/components/AssetImage.js +1 -0
  10. package/lib/commonjs/components/AssetRow.js +1 -233
  11. package/lib/commonjs/components/AssetsFilterBar.js +1 -96
  12. package/lib/commonjs/components/AssetsHeader.js +1 -72
  13. package/lib/commonjs/components/AssetsIcon.js +1 -19
  14. package/lib/commonjs/components/AssetsListControls.js +1 -96
  15. package/lib/commonjs/components/AssetsModal.js +1 -347
  16. package/lib/commonjs/components/ScanNotice.js +1 -0
  17. package/lib/commonjs/components/optionalExpoImage.js +1 -0
  18. package/lib/commonjs/components/optionalExpoImage.web.js +1 -0
  19. package/lib/commonjs/export.js +1 -62
  20. package/lib/commonjs/format.js +1 -59
  21. package/lib/commonjs/hooks/useAssetRecords.js +1 -22
  22. package/lib/commonjs/hooks/useAssetScanStatus.js +1 -0
  23. package/lib/commonjs/index.js +1 -313
  24. package/lib/commonjs/preset.js +1 -39
  25. package/lib/commonjs/remote.js +1 -65
  26. package/lib/commonjs/state.js +1 -51
  27. package/lib/commonjs/store/assetStore.js +1 -241
  28. package/lib/commonjs/store/baseline.js +1 -173
  29. package/lib/commonjs/store/insights.js +1 -120
  30. package/lib/commonjs/sync/assetsSyncAdapter.js +1 -157
  31. package/lib/commonjs/types.js +1 -2
  32. package/lib/commonjs/utils/deviceScale.js +1 -50
  33. package/lib/commonjs/utils/testIDs.js +1 -114
  34. package/lib/module/capture/expo.js +1 -41
  35. package/lib/module/capture/install.js +1 -72
  36. package/lib/module/capture/isBuoyAsset.js +1 -0
  37. package/lib/module/capture/measure.js +1 -179
  38. package/lib/module/capture/metroGraph.js +1 -141
  39. package/lib/module/capture/registry.js +1 -120
  40. package/lib/module/components/AssetDetail.js +1 -210
  41. package/lib/module/components/AssetImage.js +1 -0
  42. package/lib/module/components/AssetRow.js +1 -229
  43. package/lib/module/components/AssetsFilterBar.js +1 -92
  44. package/lib/module/components/AssetsHeader.js +1 -68
  45. package/lib/module/components/AssetsIcon.js +1 -12
  46. package/lib/module/components/AssetsListControls.js +1 -92
  47. package/lib/module/components/AssetsModal.js +1 -342
  48. package/lib/module/components/ScanNotice.js +1 -0
  49. package/lib/module/components/optionalExpoImage.js +1 -0
  50. package/lib/module/components/optionalExpoImage.web.js +1 -0
  51. package/lib/module/export.js +1 -57
  52. package/lib/module/format.js +1 -51
  53. package/lib/module/hooks/useAssetRecords.js +1 -18
  54. package/lib/module/hooks/useAssetScanStatus.js +1 -0
  55. package/lib/module/index.js +1 -63
  56. package/lib/module/preset.js +1 -35
  57. package/lib/module/remote.js +1 -58
  58. package/lib/module/state.js +1 -47
  59. package/lib/module/store/assetStore.js +1 -226
  60. package/lib/module/store/baseline.js +1 -165
  61. package/lib/module/store/insights.js +1 -116
  62. package/lib/module/sync/assetsSyncAdapter.js +1 -153
  63. package/lib/module/types.js +1 -2
  64. package/lib/module/utils/deviceScale.js +1 -46
  65. package/lib/module/utils/testIDs.js +1 -103
  66. package/lib/typescript/capture/isBuoyAsset.d.ts +9 -0
  67. package/lib/typescript/capture/registry.d.ts +1 -1
  68. package/lib/typescript/components/AssetDetail.d.ts +2 -2
  69. package/lib/typescript/components/AssetImage.d.ts +9 -0
  70. package/lib/typescript/components/AssetsFilterBar.d.ts +3 -2
  71. package/lib/typescript/components/AssetsHeader.d.ts +2 -1
  72. package/lib/typescript/components/AssetsListControls.d.ts +2 -9
  73. package/lib/typescript/components/ScanNotice.d.ts +7 -0
  74. package/lib/typescript/components/optionalExpoImage.d.ts +13 -0
  75. package/lib/typescript/components/optionalExpoImage.web.d.ts +3 -0
  76. package/lib/typescript/hooks/useAssetScanStatus.d.ts +6 -0
  77. package/lib/typescript/state.d.ts +2 -0
  78. package/lib/typescript/store/assetStore.d.ts +3 -1
  79. package/lib/typescript/types.d.ts +3 -0
  80. package/lib/typescript/utils/testIDs.d.ts +2 -5
  81. package/package.json +7 -3
  82. package/lib/commonjs/capture/expo.js.map +0 -1
  83. package/lib/commonjs/capture/install.js.map +0 -1
  84. package/lib/commonjs/capture/measure.js.map +0 -1
  85. package/lib/commonjs/capture/metroGraph.js.map +0 -1
  86. package/lib/commonjs/capture/registry.js.map +0 -1
  87. package/lib/commonjs/components/AssetDetail.js.map +0 -1
  88. package/lib/commonjs/components/AssetRow.js.map +0 -1
  89. package/lib/commonjs/components/AssetsFilterBar.js.map +0 -1
  90. package/lib/commonjs/components/AssetsHeader.js.map +0 -1
  91. package/lib/commonjs/components/AssetsIcon.js.map +0 -1
  92. package/lib/commonjs/components/AssetsListControls.js.map +0 -1
  93. package/lib/commonjs/components/AssetsModal.js.map +0 -1
  94. package/lib/commonjs/components/BaselineBar.js +0 -115
  95. package/lib/commonjs/components/BaselineBar.js.map +0 -1
  96. package/lib/commonjs/export.js.map +0 -1
  97. package/lib/commonjs/format.js.map +0 -1
  98. package/lib/commonjs/hooks/useAssetRecords.js.map +0 -1
  99. package/lib/commonjs/index.js.map +0 -1
  100. package/lib/commonjs/preset.js.map +0 -1
  101. package/lib/commonjs/remote.js.map +0 -1
  102. package/lib/commonjs/state.js.map +0 -1
  103. package/lib/commonjs/store/assetStore.js.map +0 -1
  104. package/lib/commonjs/store/baseline.js.map +0 -1
  105. package/lib/commonjs/store/insights.js.map +0 -1
  106. package/lib/commonjs/sync/assetsSyncAdapter.js.map +0 -1
  107. package/lib/commonjs/types.js.map +0 -1
  108. package/lib/commonjs/utils/deviceScale.js.map +0 -1
  109. package/lib/commonjs/utils/testIDs.js.map +0 -1
  110. package/lib/module/capture/expo.js.map +0 -1
  111. package/lib/module/capture/install.js.map +0 -1
  112. package/lib/module/capture/measure.js.map +0 -1
  113. package/lib/module/capture/metroGraph.js.map +0 -1
  114. package/lib/module/capture/registry.js.map +0 -1
  115. package/lib/module/components/AssetDetail.js.map +0 -1
  116. package/lib/module/components/AssetRow.js.map +0 -1
  117. package/lib/module/components/AssetsFilterBar.js.map +0 -1
  118. package/lib/module/components/AssetsHeader.js.map +0 -1
  119. package/lib/module/components/AssetsIcon.js.map +0 -1
  120. package/lib/module/components/AssetsListControls.js.map +0 -1
  121. package/lib/module/components/AssetsModal.js.map +0 -1
  122. package/lib/module/components/BaselineBar.js +0 -111
  123. package/lib/module/components/BaselineBar.js.map +0 -1
  124. package/lib/module/export.js.map +0 -1
  125. package/lib/module/format.js.map +0 -1
  126. package/lib/module/hooks/useAssetRecords.js.map +0 -1
  127. package/lib/module/index.js.map +0 -1
  128. package/lib/module/preset.js.map +0 -1
  129. package/lib/module/remote.js.map +0 -1
  130. package/lib/module/state.js.map +0 -1
  131. package/lib/module/store/assetStore.js.map +0 -1
  132. package/lib/module/store/baseline.js.map +0 -1
  133. package/lib/module/store/insights.js.map +0 -1
  134. package/lib/module/sync/assetsSyncAdapter.js.map +0 -1
  135. package/lib/module/types.js.map +0 -1
  136. package/lib/module/utils/deviceScale.js.map +0 -1
  137. package/lib/module/utils/testIDs.js.map +0 -1
  138. package/lib/typescript/capture/expo.d.ts.map +0 -1
  139. package/lib/typescript/capture/install.d.ts.map +0 -1
  140. package/lib/typescript/capture/measure.d.ts.map +0 -1
  141. package/lib/typescript/capture/metroGraph.d.ts.map +0 -1
  142. package/lib/typescript/capture/registry.d.ts.map +0 -1
  143. package/lib/typescript/components/AssetDetail.d.ts.map +0 -1
  144. package/lib/typescript/components/AssetRow.d.ts.map +0 -1
  145. package/lib/typescript/components/AssetsFilterBar.d.ts.map +0 -1
  146. package/lib/typescript/components/AssetsHeader.d.ts.map +0 -1
  147. package/lib/typescript/components/AssetsIcon.d.ts.map +0 -1
  148. package/lib/typescript/components/AssetsListControls.d.ts.map +0 -1
  149. package/lib/typescript/components/AssetsModal.d.ts.map +0 -1
  150. package/lib/typescript/components/BaselineBar.d.ts +0 -13
  151. package/lib/typescript/components/BaselineBar.d.ts.map +0 -1
  152. package/lib/typescript/export.d.ts.map +0 -1
  153. package/lib/typescript/format.d.ts.map +0 -1
  154. package/lib/typescript/hooks/useAssetRecords.d.ts.map +0 -1
  155. package/lib/typescript/index.d.ts.map +0 -1
  156. package/lib/typescript/preset.d.ts.map +0 -1
  157. package/lib/typescript/remote.d.ts.map +0 -1
  158. package/lib/typescript/state.d.ts.map +0 -1
  159. package/lib/typescript/store/assetStore.d.ts.map +0 -1
  160. package/lib/typescript/store/baseline.d.ts.map +0 -1
  161. package/lib/typescript/store/insights.d.ts.map +0 -1
  162. package/lib/typescript/sync/assetsSyncAdapter.d.ts.map +0 -1
  163. package/lib/typescript/types.d.ts.map +0 -1
  164. package/lib/typescript/utils/deviceScale.d.ts.map +0 -1
  165. package/lib/typescript/utils/testIDs.d.ts.map +0 -1
@@ -1,96 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.AssetsFilterBar = AssetsFilterBar;
7
- var _reactNative = require("react-native");
8
- var _sharedUi = require("@buoy-gg/shared-ui");
9
- var _format = require("../format");
10
- var _testIDs = require("../utils/testIDs");
11
- var _jsxRuntime = require("react/jsx-runtime");
12
- /**
13
- * AssetsFilterBar — kind filter pills with counts, styled like the network
14
- * tool's bordered pills: outlined, kind-accent-colored when active. Wrapping
15
- * row, not a horizontal ScrollView (same height-measurement pitfall the
16
- * images tool documents).
17
- */
18
-
19
- function AssetsFilterBar({
20
- stats,
21
- filter,
22
- onChange
23
- }) {
24
- const chips = [{
25
- key: "all",
26
- label: `ALL ${stats.total}`,
27
- accent: _sharedUi.night.color.textSecondary
28
- }];
29
- for (const kind of Object.keys(stats.byKind)) {
30
- const entry = stats.byKind[kind];
31
- if (entry.count > 0) {
32
- chips.push({
33
- key: kind,
34
- label: `${_format.KIND_LABELS[kind]} ${entry.count}`,
35
- accent: _format.KIND_COLORS[kind]
36
- });
37
- }
38
- }
39
- if (stats.neverLoaded > 0) {
40
- // Amber, not semantic.warning — the bright yellow reads as an alarm.
41
- chips.push({
42
- key: "unused",
43
- label: `UNUSED ${stats.neverLoaded}`,
44
- accent: "#FF9F1C"
45
- });
46
- }
47
- if (chips.length <= 1) return null;
48
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
49
- style: styles.bar,
50
- testID: _testIDs.ASSETS_TEST_IDS.filterBar,
51
- children: chips.map(chip => {
52
- const active = chip.key === filter;
53
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
54
- testID: (0, _testIDs.assetFilterTestID)(chip.key),
55
- style: [styles.chip, active && {
56
- borderColor: chip.accent,
57
- backgroundColor: `${chip.accent}1A`
58
- }]
59
- // Tapping the active chip again untoggles back to ALL.
60
- ,
61
- onPress: () => onChange(active ? "all" : chip.key),
62
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
63
- testID: `${(0, _testIDs.assetFilterTestID)(chip.key)}-label`,
64
- style: [styles.chipText, {
65
- color: active ? chip.accent : _sharedUi.night.color.textSecondary
66
- }],
67
- children: chip.label
68
- })
69
- }, chip.key);
70
- })
71
- });
72
- }
73
- const styles = _reactNative.StyleSheet.create({
74
- bar: {
75
- flexDirection: "row",
76
- flexWrap: "wrap",
77
- gap: 6,
78
- paddingHorizontal: 10,
79
- paddingVertical: 8
80
- },
81
- chip: {
82
- borderWidth: 1,
83
- borderColor: _sharedUi.night.color.border,
84
- backgroundColor: _sharedUi.night.color.surface,
85
- borderRadius: 999,
86
- paddingHorizontal: 10,
87
- paddingVertical: 5
88
- },
89
- chipText: {
90
- fontSize: 10,
91
- fontWeight: "700",
92
- letterSpacing: 0.4,
93
- lineHeight: 13
94
- }
95
- });
96
- //# sourceMappingURL=AssetsFilterBar.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.AssetsFilterBar=AssetsFilterBar;var _reactNative=require("react-native"),_sharedUi=require("@buoy-gg/shared-ui"),_format=require("../format"),_testIDs=require("../utils/testIDs"),_jsxRuntime=require("react/jsx-runtime");function AssetsFilterBar({stats:e,duplicateCount:t,filter:r,onChange:a}){const s=[{key:"all",label:`ALL ${e.total}`,accent:_sharedUi.night.color.textSecondary},{key:"duplicates",label:`DUPLICATES ${t}`,accent:"#FF9F1C"}];for(const t of Object.keys(e.byKind)){const r=e.byKind[t];r.count>0&&s.push({key:t,label:`${_format.KIND_LABELS[t]} ${r.count}`,accent:_format.KIND_COLORS[t]})}return e.neverLoaded>0&&s.push({key:"unused",label:`NOT OBSERVED ${e.neverLoaded}`,accent:"#FF9F1C"}),s.length<=1?null:(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.bar,testID:_testIDs.ASSETS_TEST_IDS.filterBar,children:s.map(e=>{const t=e.key===r;return(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{accessibilityRole:"button",accessibilityState:{selected:t},testID:(0,_testIDs.assetFilterTestID)(e.key),style:[styles.chip,t&&{borderColor:e.accent,backgroundColor:`${e.accent}1A`}],onPress:()=>a(t?"all":e.key),children:(0,_jsxRuntime.jsx)(_reactNative.Text,{testID:`${(0,_testIDs.assetFilterTestID)(e.key)}-label`,style:[styles.chipText,{color:t?e.accent:_sharedUi.night.color.textSecondary}],children:e.label})},e.key)})})}const styles=_reactNative.StyleSheet.create({bar:{flexDirection:"row",flexWrap:"wrap",gap:6,paddingHorizontal:10,paddingVertical:8},chip:{borderWidth:1,borderColor:_sharedUi.night.color.border,backgroundColor:_sharedUi.night.color.surface,borderRadius:999,paddingHorizontal:10,paddingVertical:5},chipText:{fontSize:10,fontWeight:"700",letterSpacing:.4,lineHeight:13}});
@@ -1,72 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.AssetsHeader = AssetsHeader;
7
- var _sharedUi = require("@buoy-gg/shared-ui");
8
- var _format = require("../format");
9
- var _testIDs = require("../utils/testIDs");
10
- var _jsxRuntime = require("react/jsx-runtime");
11
- /**
12
- * AssetsHeader — shared ModalHeader wiring, matching the Images/Console
13
- * header pattern. List mode shows inventory totals plus the shared
14
- * ToolbarCopyButton (full markdown report); detail mode shows back
15
- * navigation and the single-asset report.
16
- */
17
-
18
- function AssetsHeader({
19
- stats,
20
- measuring,
21
- detailOpen,
22
- detailIndex = -1,
23
- detailTotal = 0,
24
- onCloseDetail,
25
- onClear,
26
- getReport,
27
- onBack
28
- }) {
29
- if (detailOpen) {
30
- const counter = detailIndex >= 0 && detailTotal > 0 ? `${detailIndex + 1} of ${detailTotal}` : undefined;
31
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.ModalHeader, {
32
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Navigation, {
33
- onBack: onCloseDetail
34
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Content, {
35
- title: "Asset detail",
36
- subtitle: counter,
37
- testID: _testIDs.ASSETS_TEST_IDS.title
38
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Actions, {
39
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ToolbarCopyButton, {
40
- value: getReport,
41
- testID: _testIDs.ASSETS_TEST_IDS.copy
42
- })
43
- })]
44
- });
45
- }
46
- const subtitleParts = [`${stats.total} assets`];
47
- // A mid-measure byte total reads as nonsense ("653 B+") — wait it out.
48
- if (stats.totalBytes > 0 && !measuring) {
49
- const partial = stats.measuredCount < stats.total ? "+" : "";
50
- subtitleParts.push(`${(0, _format.formatBytes)(stats.totalBytes)}${partial}`);
51
- }
52
- if (stats.neverLoaded > 0) subtitleParts.push(`${stats.neverLoaded} never loaded`);
53
- if (stats.fontFamilies > 0) subtitleParts.push(`${stats.fontFamilies} fonts`);
54
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.ModalHeader, {
55
- children: [onBack ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Navigation, {
56
- onBack: onBack
57
- }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ModalHeader.Content, {
58
- title: "Assets",
59
- subtitle: subtitleParts.join(" · "),
60
- testID: _testIDs.ASSETS_TEST_IDS.title
61
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.ModalHeader.Actions, {
62
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ToolbarCopyButton, {
63
- value: getReport,
64
- testID: _testIDs.ASSETS_TEST_IDS.copy
65
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ToolbarClearButton, {
66
- onPress: onClear,
67
- testID: _testIDs.ASSETS_TEST_IDS.clear
68
- })]
69
- })]
70
- });
71
- }
72
- //# sourceMappingURL=AssetsHeader.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.AssetsHeader=AssetsHeader;var _sharedUi=require("@buoy-gg/shared-ui"),_format=require("../format"),_testIDs=require("../utils/testIDs"),_jsxRuntime=require("react/jsx-runtime");function AssetsHeader({stats:e,measuring:t,discovering:s=!1,detailOpen:a,detailIndex:r=-1,detailTotal:i=0,onCloseDetail:o,onClear:n,getReport:d,onBack:l}){if(a){const e=r>=0&&i>0?`${r+1} of ${i}`:void 0;return(0,_jsxRuntime.jsxs)(_sharedUi.ModalHeader,{children:[(0,_jsxRuntime.jsx)(_sharedUi.ModalHeader.Navigation,{onBack:o}),(0,_jsxRuntime.jsx)(_sharedUi.ModalHeader.Content,{title:"Asset detail",subtitle:e,testID:_testIDs.ASSETS_TEST_IDS.title}),(0,_jsxRuntime.jsx)(_sharedUi.ModalHeader.Actions,{children:(0,_jsxRuntime.jsx)(_sharedUi.ToolbarCopyButton,{value:d,testID:_testIDs.ASSETS_TEST_IDS.copy})})]})}const _=[`${e.total} assets${s?" so far":""}`];if(e.totalBytes>0&&!t&&!s){const t=e.measuredCount<e.total?"+":"";_.push(`${(0,_format.formatBytes)(e.totalBytes)}${t}`)}return e.neverLoaded>0&&_.push(`${e.neverLoaded} not observed`),e.fontFamilies>0&&_.push(`${e.fontFamilies} fonts`),(0,_jsxRuntime.jsxs)(_sharedUi.ModalHeader,{children:[l?(0,_jsxRuntime.jsx)(_sharedUi.ModalHeader.Navigation,{onBack:l}):null,(0,_jsxRuntime.jsx)(_sharedUi.ModalHeader.Content,{title:"Assets",subtitle:_.join(" · "),testID:_testIDs.ASSETS_TEST_IDS.title}),(0,_jsxRuntime.jsxs)(_sharedUi.ModalHeader.Actions,{children:[(0,_jsxRuntime.jsx)(_sharedUi.ToolbarCopyButton,{value:d,testID:_testIDs.ASSETS_TEST_IDS.copy}),(0,_jsxRuntime.jsx)(_sharedUi.ToolbarClearButton,{onPress:n,testID:_testIDs.ASSETS_TEST_IDS.clear})]})]})}
@@ -1,19 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- Object.defineProperty(exports, "ASSETS_ICON_COLOR", {
7
- enumerable: true,
8
- get: function () {
9
- return _sharedUi.ASSETS_ICON_COLOR;
10
- }
11
- });
12
- Object.defineProperty(exports, "AssetsIcon", {
13
- enumerable: true,
14
- get: function () {
15
- return _sharedUi.AssetsIcon;
16
- }
17
- });
18
- var _sharedUi = require("@buoy-gg/shared-ui");
19
- //# sourceMappingURL=AssetsIcon.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"ASSETS_ICON_COLOR",{enumerable:!0,get:function(){return _sharedUi.ASSETS_ICON_COLOR}}),Object.defineProperty(exports,"AssetsIcon",{enumerable:!0,get:function(){return _sharedUi.AssetsIcon}});var _sharedUi=require("@buoy-gg/shared-ui");
@@ -1,96 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.AssetsListControls = AssetsListControls;
7
- var _reactNative = require("react-native");
8
- var _sharedUi = require("@buoy-gg/shared-ui");
9
- var _baseline = require("../store/baseline");
10
- var _testIDs = require("../utils/testIDs");
11
- var _jsxRuntime = require("react/jsx-runtime");
12
- /**
13
- * AssetsListControls — one compact row: name search, sort cycle (SIZE →
14
- * NAME → TYPE), and — when no baseline exists yet — the BASE button that
15
- * saves one. Once a baseline exists the BaselineBar takes over the diff UI,
16
- * so this row never wastes space on a hint sentence.
17
- */
18
-
19
- const NEXT_SORT = {
20
- size: "name",
21
- name: "type",
22
- type: "size"
23
- };
24
- function AssetsListControls({
25
- query,
26
- onQueryChange,
27
- sort,
28
- onSortChange,
29
- showBaselineButton
30
- }) {
31
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
32
- style: styles.row,
33
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
34
- style: styles.input,
35
- value: query,
36
- onChangeText: onQueryChange,
37
- placeholder: "Search assets\u2026",
38
- placeholderTextColor: _sharedUi.night.color.placeholder,
39
- autoCapitalize: "none",
40
- autoCorrect: false,
41
- testID: _testIDs.ASSETS_TEST_IDS.search
42
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
43
- style: styles.button,
44
- onPress: () => onSortChange(NEXT_SORT[sort]),
45
- testID: _testIDs.ASSETS_TEST_IDS.sort,
46
- children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
47
- style: styles.buttonText,
48
- testID: `${_testIDs.ASSETS_TEST_IDS.sort}-label`,
49
- children: ["\u2193 ", sort.toUpperCase()]
50
- })
51
- }), showBaselineButton ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
52
- style: styles.button,
53
- onPress: () => void (0, _baseline.saveBaseline)(),
54
- testID: _testIDs.ASSETS_TEST_IDS.saveBaseline,
55
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
56
- style: styles.buttonText,
57
- children: "BASE"
58
- })
59
- }) : null]
60
- });
61
- }
62
- const styles = _reactNative.StyleSheet.create({
63
- row: {
64
- flexDirection: "row",
65
- alignItems: "center",
66
- gap: 8,
67
- paddingHorizontal: 10,
68
- paddingBottom: 8
69
- },
70
- input: {
71
- flex: 1,
72
- backgroundColor: _sharedUi.night.color.surfaceElevated,
73
- borderWidth: 1,
74
- borderColor: _sharedUi.night.color.border,
75
- borderRadius: 8,
76
- paddingHorizontal: 10,
77
- paddingVertical: 6,
78
- color: _sharedUi.night.color.text,
79
- fontSize: 12
80
- },
81
- button: {
82
- backgroundColor: _sharedUi.night.color.surface,
83
- borderWidth: 1,
84
- borderColor: _sharedUi.night.color.border,
85
- borderRadius: 8,
86
- paddingHorizontal: 10,
87
- paddingVertical: 7
88
- },
89
- buttonText: {
90
- color: _sharedUi.night.color.textSecondary,
91
- fontSize: 10,
92
- fontWeight: "700",
93
- letterSpacing: 0.5
94
- }
95
- });
96
- //# sourceMappingURL=AssetsListControls.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.AssetsListControls=AssetsListControls;var _reactNative=require("react-native"),_sharedUi=require("@buoy-gg/shared-ui"),_testIDs=require("../utils/testIDs"),_jsxRuntime=require("react/jsx-runtime");const NEXT_SORT={size:"name",name:"type",type:"size"};function AssetsListControls({query:e,onQueryChange:t,sort:r,onSortChange:o}){return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.row,children:[(0,_jsxRuntime.jsx)(_reactNative.TextInput,{style:styles.input,value:e,onChangeText:t,placeholder:"Search assets…",placeholderTextColor:_sharedUi.night.color.placeholder,autoCapitalize:"none",autoCorrect:!1,testID:_testIDs.ASSETS_TEST_IDS.search}),(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{style:styles.button,onPress:()=>o(NEXT_SORT[r]),testID:_testIDs.ASSETS_TEST_IDS.sort,children:(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.buttonText,testID:`${_testIDs.ASSETS_TEST_IDS.sort}-label`,children:["↓ ",r.toUpperCase()]})})]})}const styles=_reactNative.StyleSheet.create({row:{flexDirection:"row",alignItems:"center",gap:8,paddingHorizontal:10,paddingBottom:8},input:{flex:1,backgroundColor:_sharedUi.night.color.surfaceElevated,borderWidth:1,borderColor:_sharedUi.night.color.border,borderRadius:8,paddingHorizontal:10,paddingVertical:6,color:_sharedUi.night.color.text,fontSize:12},button:{backgroundColor:_sharedUi.night.color.surface,borderWidth:1,borderColor:_sharedUi.night.color.border,borderRadius:8,paddingHorizontal:10,paddingVertical:7},buttonText:{color:_sharedUi.night.color.textSecondary,fontSize:10,fontWeight:"700",letterSpacing:.5}});
@@ -1,347 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.AssetsModal = AssetsModal;
7
- exports.AssetsToolView = AssetsToolView;
8
- var _react = require("react");
9
- var _reactNative = require("react-native");
10
- var _sharedUi = require("@buoy-gg/shared-ui");
11
- var _install = require("../capture/install");
12
- var _export = require("../export");
13
- var _useAssetRecords = require("../hooks/useAssetRecords");
14
- var _remote = require("../remote");
15
- var _assetStore = require("../store/assetStore");
16
- var _baseline = require("../store/baseline");
17
- var _AssetDetail = require("./AssetDetail");
18
- var _AssetRow = require("./AssetRow");
19
- var _AssetsFilterBar = require("./AssetsFilterBar");
20
- var _AssetsHeader = require("./AssetsHeader");
21
- var _AssetsListControls = require("./AssetsListControls");
22
- var _BaselineBar = require("./BaselineBar");
23
- var _testIDs = require("../utils/testIDs");
24
- var _jsxRuntime = require("react/jsx-runtime");
25
- /**
26
- * AssetsModal — bottom-sheet wrapper rendered by FloatingDevTools when the
27
- * Assets tool is opened. Inventory list (largest first) → tap for detail.
28
- * Opening triggers a full rescan (registry walk + Metro graph + size
29
- * measurement); merely installing the package never hits the network.
30
- */
31
-
32
- function ScanNotice() {
33
- const status = (0, _install.getScanStatus)();
34
- const notices = [];
35
- if (!status.registryAvailable) {
36
- notices.push("Asset registry unavailable — this environment doesn't expose @react-native/assets-registry.");
37
- } else if (!status.graphSupported && status.graphError) {
38
- notices.push("No Metro dev server — showing runtime-registered assets only. The full bundle inventory and byte sizes need a dev build.");
39
- }
40
- if (status.measuring) notices.push("Measuring sizes from the dev server…");
41
- if (notices.length === 0) return null;
42
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
43
- style: styles.notice,
44
- testID: _testIDs.ASSETS_TEST_IDS.notice,
45
- children: notices.map(n => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
46
- style: styles.noticeText,
47
- testID: _testIDs.ASSETS_TEST_IDS.noticeText,
48
- children: n
49
- }, n))
50
- });
51
- }
52
- function FontFamilies() {
53
- const families = (0, _install.getScanStatus)().fontFamilies;
54
- if (!families.length) return null;
55
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
56
- style: styles.fontsBox,
57
- testID: _testIDs.ASSETS_TEST_IDS.fonts,
58
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
59
- style: styles.fontsTitle,
60
- testID: _testIDs.ASSETS_TEST_IDS.fontsTitle,
61
- children: ["LOADED FONT FAMILIES (", families.length, ")"]
62
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
63
- style: styles.fontsWrap,
64
- children: families.map(family => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
65
- style: styles.fontChip,
66
- testID: (0, _testIDs.assetFontChipTestID)(family),
67
- children: family
68
- }, family))
69
- })]
70
- });
71
- }
72
- function EmptyState() {
73
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ToolEmptyState, {
74
- testID: _testIDs.ASSETS_TEST_IDS.empty
75
- // scanning: a scan ran and found nothing — the copy says "try Rescan".
76
- ,
77
- otto: "scanning",
78
- title: "No assets found yet",
79
- message: "Every bundled asset — images, fonts, video, audio — appears here with sizes, scale coverage, and never-loaded detection. Try Rescan after navigating around the app."
80
- });
81
- }
82
-
83
- /** Largest first — measured bytes, falling back to decoded estimate. */
84
- function bySizeDesc(a, b) {
85
- return (b.sizeBytes ?? (0, _assetStore.estDecodedBytes)(b)) - (a.sizeBytes ?? (0, _assetStore.estDecodedBytes)(a));
86
- }
87
- const COMPARATORS = {
88
- size: bySizeDesc,
89
- name: (a, b) => a.name.localeCompare(b.name) || a.type.localeCompare(b.type),
90
- type: (a, b) => a.type.localeCompare(b.type) || bySizeDesc(a, b)
91
- };
92
- function AssetsModal({
93
- visible,
94
- onClose,
95
- onBack,
96
- onMinimize,
97
- persistenceKey,
98
- inline = false
99
- }) {
100
- // Safety net: the index import normally installed this already.
101
- (0, _install.installAssetCapture)();
102
- const {
103
- records,
104
- stats,
105
- insights
106
- } = (0, _useAssetRecords.useAssetRecords)();
107
- const [selectedId, setSelectedId] = (0, _react.useState)(null);
108
- const [filter, setFilter] = (0, _react.useState)("all");
109
- const [query, setQuery] = (0, _react.useState)("");
110
- const [sort, setSort] = (0, _react.useState)("size");
111
- const selected = selectedId != null ? (0, _assetStore.getRecord)(selectedId) : undefined;
112
-
113
- // Full scan on open — locally on device, forwarded on dashboard mirrors.
114
- // The baseline load is async and re-renders through the store emit.
115
- (0, _react.useEffect)(() => {
116
- if (!visible) return;
117
- void (0, _baseline.loadBaseline)();
118
- const remote = (0, _remote.remoteAssetsDispatch)();
119
- if (remote) {
120
- remote("rescan").catch(() => {});
121
- } else {
122
- void (0, _install.rescan)();
123
- }
124
- }, [visible]);
125
- const sorted = [...records].sort(COMPARATORS[sort]);
126
- const trimmedQuery = query.trim().toLowerCase();
127
- const filtered = sorted.filter(r => {
128
- if (filter === "unused" && r.loaded) return false;
129
- if (filter !== "all" && filter !== "unused" && r.kind !== filter) return false;
130
- if (trimmedQuery && !`${r.name}.${r.type}`.toLowerCase().includes(trimmedQuery)) {
131
- return false;
132
- }
133
- return true;
134
- });
135
- const selectedIndex = selected ? filtered.findIndex(r => r.id === selected.id) : -1;
136
- const stepTo = index => {
137
- const target = filtered[index];
138
- if (target) setSelectedId(target.id);
139
- };
140
-
141
- // Set lookups so each row's badge checks are O(1).
142
- const flagSets = {
143
- scaleGaps: new Set(insights.scaleGaps),
144
- scaleAnomalies: new Set(insights.scaleAnomalies),
145
- duplicates: new Set(insights.duplicates.flatMap(d => d.ids)),
146
- webpCandidates: new Set(insights.webpCandidates),
147
- overDecode: new Set(insights.overDecode),
148
- heavy: new Set([...insights.heavyGifs, ...insights.heavyFonts])
149
- };
150
- const diff = (0, _baseline.getDiff)();
151
-
152
- // The proportional size bar is relative to the largest asset in view.
153
- let maxBytes = 0;
154
- for (const r of filtered) {
155
- const bytes = r.sizeBytes ?? (0, _assetStore.estDecodedBytes)(r);
156
- if (bytes > maxBytes) maxBytes = bytes;
157
- }
158
- const getReport = () => selected ? (0, _export.formatAssetMarkdown)(selected) : (0, _export.formatInventoryMarkdown)(sorted, stats, insights, (0, _install.getScanStatus)(), (0, _baseline.getDiff)());
159
- const headerContent = /*#__PURE__*/(0, _jsxRuntime.jsx)(_AssetsHeader.AssetsHeader, {
160
- stats: stats,
161
- measuring: (0, _install.getScanStatus)().measuring,
162
- detailOpen: selected != null,
163
- detailIndex: selectedIndex,
164
- detailTotal: filtered.length,
165
- onCloseDetail: () => setSelectedId(null),
166
- onClear: _assetStore.clearRecords,
167
- getReport: getReport,
168
- onBack: onBack
169
- });
170
- const body = selected ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
171
- style: styles.detailContainer,
172
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_AssetDetail.AssetDetail, {
173
- record: selected,
174
- insights: insights
175
- }), selectedIndex >= 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.EventStepperFooter, {
176
- currentIndex: selectedIndex,
177
- totalItems: filtered.length,
178
- itemLabel: "Asset",
179
- onPrevious: () => stepTo(selectedIndex - 1),
180
- onNext: () => stepTo(selectedIndex + 1)
181
- }) : null]
182
- }) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
183
- style: styles.listContainer,
184
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_AssetsFilterBar.AssetsFilterBar, {
185
- stats: stats,
186
- filter: filter,
187
- onChange: setFilter
188
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_AssetsListControls.AssetsListControls, {
189
- query: query,
190
- onQueryChange: setQuery,
191
- sort: sort,
192
- onSortChange: setSort,
193
- showBaselineButton: diff == null
194
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_BaselineBar.BaselineBar, {
195
- diff: diff
196
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(ScanNotice, {}), filter === "font" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(FontFamilies, {}) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.FlatList, {
197
- testID: _testIDs.ASSETS_TEST_IDS.list,
198
- data: filtered,
199
- keyExtractor: item => String(item.id),
200
- contentContainerStyle: styles.listContent,
201
- renderItem: ({
202
- item
203
- }) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_AssetRow.AssetRow, {
204
- record: item,
205
- flags: {
206
- scaleGap: flagSets.scaleGaps.has(item.id),
207
- scaleAnomaly: flagSets.scaleAnomalies.has(item.id),
208
- duplicate: flagSets.duplicates.has(item.id),
209
- webp: flagSets.webpCandidates.has(item.id),
210
- oversize: flagSets.overDecode.has(item.id),
211
- heavy: flagSets.heavy.has(item.id)
212
- },
213
- sizeFraction: maxBytes > 0 ? (item.sizeBytes ?? (0, _assetStore.estDecodedBytes)(item)) / maxBytes : 0
214
- // Guarded: programmatic invocations (automation) can call this
215
- // with an event object instead of an id.
216
- ,
217
- onPress: id => setSelectedId(typeof id === "number" ? id : null)
218
- }),
219
- ListEmptyComponent: /*#__PURE__*/(0, _jsxRuntime.jsx)(EmptyState, {})
220
- })]
221
- });
222
-
223
- // The ONLY difference between phone and desktop is which shell the header
224
- // and body go in (same pattern as ImagesModal).
225
- if (inline) {
226
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
227
- style: styles.inlineRoot,
228
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
229
- style: styles.inlineHeader,
230
- ..._sharedUi.windowDragProps,
231
- children: headerContent
232
- }), body]
233
- });
234
- }
235
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.JsModal, {
236
- visible: visible,
237
- onClose: onClose,
238
- onMinimize: onMinimize,
239
- persistenceKey: persistenceKey,
240
- header: {
241
- showToggleButton: true,
242
- customContent: headerContent
243
- },
244
- enablePersistence: true,
245
- initialMode: "bottomSheet",
246
- disableScrollWrapper: true,
247
- children: body
248
- });
249
- }
250
-
251
- /**
252
- * The same Assets tool rendered INLINE for hosts that place tools in a panel
253
- * rather than a modal (the desktop dashboard). One implementation only.
254
- */
255
- function AssetsToolView(props = {}) {
256
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(AssetsModal, {
257
- ...props,
258
- inline: true,
259
- visible: true,
260
- onClose: () => {}
261
- });
262
- }
263
- const styles = _reactNative.StyleSheet.create({
264
- inlineRoot: {
265
- flex: 1,
266
- minHeight: 0,
267
- // Transparent so the desktop workbench's hoisted sky (one field spanning
268
- // sidebar + panel) shows through — the shell paints its base beneath it.
269
- backgroundColor: "transparent"
270
- },
271
- inlineHeader: {
272
- paddingHorizontal: 12,
273
- paddingVertical: 8,
274
- borderBottomWidth: 1,
275
- borderBottomColor: _sharedUi.macOSColors.border.default,
276
- // Clear, like Bench — the host's hoisted sky shows through the header.
277
- backgroundColor: "transparent"
278
- },
279
- listContainer: {
280
- flex: 1
281
- },
282
- listContent: {
283
- paddingBottom: 16
284
- },
285
- detailContainer: {
286
- flex: 1
287
- },
288
- notice: {
289
- marginHorizontal: 10,
290
- marginBottom: 8,
291
- padding: 10,
292
- borderRadius: 8,
293
- borderWidth: 1,
294
- borderColor: _sharedUi.night.color.border,
295
- backgroundColor: _sharedUi.night.color.surface,
296
- gap: 4
297
- },
298
- noticeText: {
299
- color: _sharedUi.night.color.textSecondary,
300
- fontSize: 11
301
- },
302
- fontsBox: {
303
- marginHorizontal: 10,
304
- marginTop: 8,
305
- padding: 10,
306
- borderRadius: 8,
307
- backgroundColor: _sharedUi.night.color.surface,
308
- gap: 6
309
- },
310
- fontsTitle: {
311
- color: _sharedUi.night.color.textTertiary,
312
- fontSize: 9,
313
- fontWeight: "700",
314
- letterSpacing: 0.5
315
- },
316
- fontsWrap: {
317
- flexDirection: "row",
318
- flexWrap: "wrap",
319
- gap: 6
320
- },
321
- fontChip: {
322
- color: _sharedUi.night.color.textSecondary,
323
- fontSize: 10,
324
- backgroundColor: _sharedUi.night.color.bg,
325
- borderRadius: 999,
326
- paddingHorizontal: 8,
327
- paddingVertical: 3,
328
- overflow: "hidden"
329
- },
330
- empty: {
331
- alignItems: "center",
332
- padding: 32,
333
- gap: 8
334
- },
335
- emptyTitle: {
336
- color: _sharedUi.night.color.text,
337
- fontSize: 13,
338
- fontWeight: "600"
339
- },
340
- emptyText: {
341
- color: _sharedUi.night.color.textSecondary,
342
- fontSize: 11,
343
- textAlign: "center",
344
- lineHeight: 16
345
- }
346
- });
347
- //# sourceMappingURL=AssetsModal.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.AssetsModal=AssetsModal,exports.AssetsToolView=AssetsToolView;var _react=require("react"),_reactNative=require("react-native"),_sharedUi=require("@buoy-gg/shared-ui"),_install=require("../capture/install"),_export=require("../export"),_useAssetRecords=require("../hooks/useAssetRecords"),_useAssetScanStatus=require("../hooks/useAssetScanStatus"),_remote=require("../remote"),_assetStore=require("../store/assetStore"),_baseline=require("../store/baseline"),_AssetDetail=require("./AssetDetail"),_AssetRow=require("./AssetRow"),_AssetsFilterBar=require("./AssetsFilterBar"),_AssetsHeader=require("./AssetsHeader"),_AssetsListControls=require("./AssetsListControls"),_ScanNotice=require("./ScanNotice"),_testIDs=require("../utils/testIDs"),_jsxRuntime=require("react/jsx-runtime");function FontFamilies({names:e}){const t=[...new Set(e)];return t.length?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.fontsBox,testID:_testIDs.ASSETS_TEST_IDS.fonts,children:[(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.fontsTitle,testID:_testIDs.ASSETS_TEST_IDS.fontsTitle,children:["LOADED FONT FAMILIES (",t.length,")"]}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.fontsWrap,children:t.map(e=>(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.fontChip,testID:(0,_testIDs.assetFontChipTestID)(e),children:e},e))})]}):null}function EmptyState({duplicates:e=!1}){return(0,_jsxRuntime.jsx)(_sharedUi.ToolEmptyState,{testID:_testIDs.ASSETS_TEST_IDS.empty,otto:"scanning",title:e?"No duplicates found":"No assets found yet",message:e?"No assets in this view share a content hash.":"Every bundled asset — images, fonts, video, audio — appears here with sizes, scale coverage, and runtime registration status. Try Rescan after navigating around the app."})}function bySizeDesc(e,t){return(t.sizeBytes??(0,_assetStore.estDecodedBytes)(t))-(e.sizeBytes??(0,_assetStore.estDecodedBytes)(e))}const COMPARATORS={size:bySizeDesc,name:(e,t)=>e.name.localeCompare(t.name)||e.type.localeCompare(t.type),type:(e,t)=>e.type.localeCompare(t.type)||bySizeDesc(e,t)};function AssetsModal({visible:e,onClose:t,onBack:s,onMinimize:i,persistenceKey:a,inline:r=!1}){(0,_install.installAssetCapture)();const{records:n,stats:o,insights:l}=(0,_useAssetRecords.useAssetRecords)(),c=(0,_useAssetScanStatus.useAssetScanStatus)(),[d,u]=(0,_react.useState)(!1);(0,_react.useEffect)(()=>{u(!1)},[c.graphFetchInFlight,c.lastScanAt]);const _=()=>{u(!1);const e=(0,_remote.remoteAssetsDispatch)();e?e("rescan").catch(()=>u(!0)):(0,_install.rescan)()},[h,p]=(0,_react.useState)(null),[x,m]=(0,_react.useState)("all"),[y,S]=(0,_react.useState)(""),[g,f]=(0,_react.useState)("size"),j=null!=h?(0,_assetStore.getRecord)(h):void 0;(0,_react.useEffect)(()=>{if(!e)return;(0,_baseline.loadBaseline)(),u(!1);const t=(0,_remote.remoteAssetsDispatch)();t?t("rescan").catch(()=>u(!0)):(0,_install.rescan)()},[e]);const A=new Set(l.duplicates.flatMap(e=>e.ids)),R=[...n].sort(COMPARATORS[g]),v=y.trim().toLowerCase(),C=R.filter(e=>!("unused"===x&&e.loaded||"duplicates"===x&&!A.has(e.id)||"all"!==x&&"unused"!==x&&"duplicates"!==x&&e.kind!==x||v&&!`${e.name}.${e.type}`.toLowerCase().includes(v))),T=j?C.findIndex(e=>e.id===j.id):-1,b=e=>{const t=C[e];t&&p(t.id)},D={scaleGaps:new Set(l.scaleGaps),scaleAnomalies:new Set(l.scaleAnomalies),duplicates:A,webpCandidates:new Set(l.webpCandidates),overDecode:new Set(l.overDecode),heavy:new Set([...l.heavyGifs,...l.heavyFonts])};let w=0;for(const e of C){const t=e.sizeBytes??(0,_assetStore.estDecodedBytes)(e);t>w&&(w=t)}const I=(0,_jsxRuntime.jsx)(_AssetsHeader.AssetsHeader,{stats:o,measuring:c.measuring,discovering:c.graphFetchInFlight,detailOpen:null!=j,detailIndex:T,detailTotal:C.length,onCloseDetail:()=>p(null),onClear:_assetStore.clearRecords,getReport:()=>j?(0,_export.formatAssetMarkdown)(j):(0,_export.formatInventoryMarkdown)(R,o,l,(0,_install.getScanStatus)(),(0,_baseline.getDiff)()),onBack:s}),N=j?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.detailContainer,children:[(0,_jsxRuntime.jsx)(_AssetDetail.AssetDetail,{record:j,insights:l}),T>=0?(0,_jsxRuntime.jsx)(_sharedUi.EventStepperFooter,{currentIndex:T,totalItems:C.length,itemLabel:"Asset",onPrevious:()=>b(T-1),onNext:()=>b(T+1)}):null]}):(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.listContainer,children:[(0,_jsxRuntime.jsx)(_AssetsFilterBar.AssetsFilterBar,{stats:o,duplicateCount:A.size,filter:x,onChange:e=>{m(e),"duplicates"===e&&S("")}}),(0,_jsxRuntime.jsx)(_AssetsListControls.AssetsListControls,{query:y,onQueryChange:S,sort:g,onSortChange:f}),(0,_jsxRuntime.jsx)(_ScanNotice.ScanNotice,{status:c,total:o.total,onRetry:_}),d&&!c.graphFetchInFlight?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.notice,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.noticeText,children:"Couldn't request an asset scan from the device."}),(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{accessibilityRole:"button",onPress:_,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.retryText,children:"Retry"})})]}):null,"unused"===x?(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.notice,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.noticeText,children:"Not seen in React Native's asset registry this app run. Assets loaded through other paths may appear here; this does not prove they are unused."})}):null,"font"===x?(0,_jsxRuntime.jsx)(FontFamilies,{names:c.fontFamilies}):null,(0,_jsxRuntime.jsx)(_reactNative.FlatList,{testID:_testIDs.ASSETS_TEST_IDS.list,data:C,keyExtractor:e=>String(e.id),contentContainerStyle:styles.listContent,renderItem:({item:e})=>(0,_jsxRuntime.jsx)(_AssetRow.AssetRow,{record:e,flags:{scaleGap:D.scaleGaps.has(e.id),scaleAnomaly:D.scaleAnomalies.has(e.id),duplicate:D.duplicates.has(e.id),webp:D.webpCandidates.has(e.id),oversize:D.overDecode.has(e.id),heavy:D.heavy.has(e.id)},sizeFraction:w>0?(e.sizeBytes??(0,_assetStore.estDecodedBytes)(e))/w:0,onPress:e=>p("number"==typeof e?e:null)}),ListEmptyComponent:c.graphFetchInFlight?null:(0,_jsxRuntime.jsx)(EmptyState,{duplicates:"duplicates"===x})})]});return r?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.inlineRoot,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.inlineHeader,..._sharedUi.windowDragProps,children:I}),N]}):(0,_jsxRuntime.jsx)(_sharedUi.JsModal,{visible:e,onClose:t,onMinimize:i,persistenceKey:a,header:{showToggleButton:!0,customContent:I},enablePersistence:!0,initialMode:"bottomSheet",disableScrollWrapper:!0,children:N})}function AssetsToolView(e={}){return(0,_jsxRuntime.jsx)(AssetsModal,{...e,inline:!0,visible:!0,onClose:()=>{}})}const styles=_reactNative.StyleSheet.create({inlineRoot:{flex:1,minHeight:0,backgroundColor:"transparent"},inlineHeader:{paddingHorizontal:12,paddingVertical:8,borderBottomWidth:1,borderBottomColor:_sharedUi.macOSColors.border.default,backgroundColor:"transparent"},listContainer:{flex:1},listContent:{paddingBottom:16},detailContainer:{flex:1},notice:{marginHorizontal:10,marginBottom:8,padding:10,borderRadius:8,borderWidth:1,borderColor:_sharedUi.night.color.border,backgroundColor:_sharedUi.night.color.surface,gap:4},noticeText:{color:_sharedUi.night.color.textSecondary,fontSize:11},retryText:{color:_sharedUi.night.color.text,fontSize:12,paddingVertical:6},fontsBox:{marginHorizontal:10,marginTop:8,padding:10,borderRadius:8,backgroundColor:_sharedUi.night.color.surface,gap:6},fontsTitle:{color:_sharedUi.night.color.textTertiary,fontSize:9,fontWeight:"700",letterSpacing:.5},fontsWrap:{flexDirection:"row",flexWrap:"wrap",gap:6},fontChip:{color:_sharedUi.night.color.textSecondary,fontSize:10,backgroundColor:_sharedUi.night.color.bg,borderRadius:999,paddingHorizontal:8,paddingVertical:3,overflow:"hidden"},empty:{alignItems:"center",padding:32,gap:8},emptyTitle:{color:_sharedUi.night.color.text,fontSize:13,fontWeight:"600"},emptyText:{color:_sharedUi.night.color.textSecondary,fontSize:11,textAlign:"center",lineHeight:16}});
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ScanNotice=ScanNotice;var _react=require("react"),_reactNative=require("react-native"),_sharedUi=require("@buoy-gg/shared-ui"),_testIDs=require("../utils/testIDs"),_jsxRuntime=require("react/jsx-runtime");function ScanNotice({status:e,total:t,onRetry:r}){const[s,i]=(0,_react.useState)(!1);(0,_react.useEffect)(()=>{if(i(!1),!e.graphFetchInFlight)return;const t=null==e.graphFetchStartedAt?0:Math.max(0,Date.now()-e.graphFetchStartedAt),r=setTimeout(()=>i(!0),Math.max(0,8e3-t));return()=>clearTimeout(r)},[e.graphFetchInFlight,e.graphFetchStartedAt]);const a=[];e.graphFetchInFlight&&(a.push(`Finding assets… ${t} found so far.`),s&&a.push("Still finding assets. This is taking longer than usual.")),e.registryAvailable||a.push("The asset registry is unavailable in this environment."),e.graphFetchInFlight||e.graphSupported||!e.graphError||a.push("Showing runtime-registered assets only. A development server is needed to find more assets and measure their sizes.");const n=!e.graphFetchInFlight&&e.graphSupported&&!!e.graphError;return n&&a.push(`Couldn't finish finding assets. Showing ${t} assets found so far.`),e.measuring&&!e.graphFetchInFlight&&a.push("Checking asset sizes…"),0===a.length?null:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.notice,testID:_testIDs.ASSETS_TEST_IDS.notice,children:[e.graphFetchInFlight?(0,_jsxRuntime.jsx)(_reactNative.ActivityIndicator,{size:"small",color:_sharedUi.night.color.textSecondary,accessibilityLabel:"Finding assets",testID:_testIDs.ASSETS_TEST_IDS.discoverySpinner}):null,a.map(e=>(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.noticeText,testID:_testIDs.ASSETS_TEST_IDS.noticeText,children:e},e)),n?(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{accessibilityRole:"button",onPress:r,testID:_testIDs.ASSETS_TEST_IDS.retry,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.retryText,children:"Retry"})}):null]})}const styles=_reactNative.StyleSheet.create({notice:{marginHorizontal:10,marginBottom:8,padding:10,borderRadius:8,borderWidth:1,borderColor:_sharedUi.night.color.border,backgroundColor:_sharedUi.night.color.surface,gap:4},noticeText:{color:_sharedUi.night.color.textSecondary,fontSize:11},retryText:{color:_sharedUi.night.color.text,fontSize:12,paddingVertical:6}});
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.getExpoPreviewImage=getExpoPreviewImage;let ExpoImage=null;try{ExpoImage=require("expo-image").Image??null}catch{}function getExpoPreviewImage(){return ExpoImage}
@@ -0,0 +1 @@
1
+ "use strict";function getExpoPreviewImage(){return null}Object.defineProperty(exports,"__esModule",{value:!0}),exports.getExpoPreviewImage=getExpoPreviewImage;