@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,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:!0}),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(void 0!==cachedRegistry)return cachedRegistry;let e=null;try{e=require("@react-native/assets-registry/registry")}catch{try{e=require("react-native/Libraries/Image/AssetRegistry")}catch{e=null}}return cachedRegistry=e&&"function"==typeof e.getAssetByID?e:null,cachedRegistry}function resolveRegistryAsset(e){try{const{Image:t}=require("react-native"),r=t.resolveAssetSource(e);if(r&&"string"==typeof r.uri)return{uri:r.uri,scale:r.scale??1}}catch{}return null}function upsertFromPackagerAsset(e,t){const r=resolveRegistryAsset(e);return(0,_assetStore.upsertRecord)({key:(0,_assetStore.assetKey)(t.httpServerLocation,t.name,t.type),name:t.name,type:t.type,origin:"registry",registryId:e,hash:t.hash,httpServerLocation:t.httpServerLocation,width:t.width??void 0,height:t.height??void 0,scales:t.scales,resolvedUri:r?.uri,resolvedScale:r?.scale,loaded:!0})}function walkRegistry(){const e=getRegistryModule();if(!e)return 0;let t=0;for(;;){const r=e.getAssetByID(t+1);if(!r)break;t++,upsertFromPackagerAsset(t,r)}return t}const PATCH_MARKER="__buoyAssetsPatched";function patchRegisterAsset(){const e=getRegistryModule();if(!e)return!1;const t=e.registerAsset;if(t[PATCH_MARKER])return!0;const r=r=>{const s=t.call(e,r);try{upsertFromPackagerAsset(s,r)}catch{}return s};r[PATCH_MARKER]=!0;try{e.registerAsset=r}catch{return!1}return!0}
@@ -1,214 +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 _measure = require("../capture/measure");
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 render through the numeric registry id (works in every
19
- * environment); 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
- const source = (0, _measure.displaySource)(record);
48
- if (source == null) return null;
49
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
50
- style: styles.previewBox,
51
- testID: _testIDs.ASSETS_TEST_IDS.detailPreview,
52
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Image, {
53
- testID: "buoy-internal-assets-preview",
54
- source: source,
55
- style: styles.previewImage,
56
- resizeMode: "contain"
57
- })
58
- });
59
- }
60
- if (record.kind === "font") {
61
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
62
- style: styles.previewBox,
63
- testID: _testIDs.ASSETS_TEST_IDS.detailFontPreview,
64
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
65
- style: [styles.fontPreview, {
66
- fontFamily: record.name
67
- }],
68
- children: "The quick brown fox jumps over the lazy dog 0123456789"
69
- })
70
- });
71
- }
72
- return null;
73
- }
74
- function AssetDetail({
75
- record,
76
- insights
77
- }) {
78
- const findings = [];
79
- if (insights.neverLoaded.includes(record.id)) {
80
- findings.push("Never loaded — shipped in the bundle but no code required it");
81
- }
82
- if (insights.scaleGaps.includes(record.id)) {
83
- findings.push("Scale gap — no variant covers this device's pixel ratio");
84
- }
85
- if (insights.webpCandidates.includes(record.id)) {
86
- findings.push("WebP candidate — large png/jpeg, converting typically saves 20–40%");
87
- }
88
- const duplicate = insights.duplicates.find(d => d.ids.includes(record.id));
89
- if (duplicate) {
90
- findings.push(`Duplicate content — identical bytes shipped ${duplicate.ids.length} times`);
91
- }
92
- if (insights.overDecode.includes(record.id)) {
93
- findings.push("Decodes larger than 2× this entire screen — resize the source, no view can need this many pixels");
94
- }
95
- if (insights.heavyGifs.includes(record.id)) {
96
- findings.push("Heavy GIF — every frame decodes into memory; a video or Lottie is typically ~90% smaller");
97
- }
98
- if (insights.heavyFonts.includes(record.id)) {
99
- findings.push("Heavy font — likely an unsubset icon font; subsetting to used glyphs usually saves most of it");
100
- }
101
- if (insights.scaleAnomalies.includes(record.id)) {
102
- findings.push("Scale anomaly — a higher-resolution variant is smaller in bytes than a lower one; check the exports");
103
- }
104
- const estimate = (0, _assetStore.estDecodedBytes)(record);
105
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.ScrollView, {
106
- style: styles.scroll,
107
- contentContainerStyle: styles.content,
108
- testID: _testIDs.ASSETS_TEST_IDS.detailScroll,
109
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Preview, {
110
- record: record
111
- }), findings.length > 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
112
- style: styles.findings,
113
- testID: _testIDs.ASSETS_TEST_IDS.detailFindings,
114
- children: findings.map((finding, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
115
- style: styles.findingText,
116
- testID: (0, _testIDs.assetFindingTestID)(index),
117
- children: finding
118
- }, finding))
119
- }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
120
- label: "Name",
121
- value: `${record.name}.${record.type}`
122
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
123
- label: "Kind",
124
- value: record.kind
125
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
126
- label: "Status",
127
- value: record.loaded ? "Loaded (registered at runtime)" : "In bundle, never loaded"
128
- }), record.kind === "image" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
129
- label: "Dimensions",
130
- value: `${(0, _format.formatDimensions)(record)} (logical)`
131
- }) : null, record.kind === "image" && record.scales.length ? /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
132
- label: "Scales",
133
- value: (0, _format.formatScales)(record.scales)
134
- }) : null, record.sizesByScale ? Object.entries(record.sizesByScale).map(([scale, bytes]) => /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
135
- label: `Size @${scale}x`,
136
- value: (0, _format.formatBytes)(bytes)
137
- }, scale)) : null, record.sizeBytes != null && record.sizeSource === "measured" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
138
- label: "Total size",
139
- value: (0, _format.formatBytes)(record.sizeBytes)
140
- }) : null, estimate > 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
141
- label: "Decoded memory",
142
- value: `~${(0, _format.formatBytes)(estimate)} (RGBA)`
143
- }) : null, record.registryId != null ? /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
144
- label: "Registry id",
145
- value: String(record.registryId)
146
- }) : null, record.hash ? /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
147
- label: "Hash",
148
- value: record.hash
149
- }) : null, record.httpServerLocation ? /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
150
- label: "Location",
151
- value: record.httpServerLocation
152
- }) : null, record.fileSystemLocation ? /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
153
- label: "Source dir",
154
- value: record.fileSystemLocation
155
- }) : null, record.resolvedUri ? /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
156
- label: "Resolved URI",
157
- value: record.resolvedUri
158
- }) : null]
159
- });
160
- }
161
- const styles = _reactNative.StyleSheet.create({
162
- scroll: {
163
- flex: 1
164
- },
165
- content: {
166
- padding: 12,
167
- gap: 8
168
- },
169
- previewBox: {
170
- borderRadius: 8,
171
- backgroundColor: _sharedUi.night.color.bg,
172
- padding: 12,
173
- alignItems: "center",
174
- justifyContent: "center",
175
- minHeight: 96
176
- },
177
- previewImage: {
178
- width: "100%",
179
- height: 140
180
- },
181
- fontPreview: {
182
- color: _sharedUi.night.color.text,
183
- fontSize: 16,
184
- textAlign: "center"
185
- },
186
- findings: {
187
- borderRadius: 8,
188
- borderWidth: 1,
189
- borderColor: _sharedUi.night.color.border,
190
- backgroundColor: _sharedUi.night.color.surface,
191
- padding: 10,
192
- gap: 6
193
- },
194
- findingText: {
195
- color: _sharedUi.night.color.textSecondary,
196
- fontSize: 11,
197
- lineHeight: 15
198
- },
199
- kvRow: {
200
- gap: 2
201
- },
202
- kvLabel: {
203
- color: _sharedUi.night.color.textTertiary,
204
- fontSize: 9,
205
- fontWeight: "700",
206
- letterSpacing: 0.5,
207
- textTransform: "uppercase"
208
- },
209
- kvValue: {
210
- color: _sharedUi.night.color.text,
211
- fontSize: 12
212
- }
213
- });
214
- //# sourceMappingURL=AssetDetail.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.AssetDetail=AssetDetail;var _reactNative=require("react-native"),_sharedUi=require("@buoy-gg/shared-ui"),_AssetImage=require("./AssetImage"),_format=require("../format"),_assetStore=require("../store/assetStore"),_testIDs=require("../utils/testIDs"),_jsxRuntime=require("react/jsx-runtime");function Row({label:e,value:t}){const s=(0,_testIDs.assetDetailRowTestID)(e);return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.kvRow,testID:s,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.kvLabel,children:e}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.kvValue,selectable:!0,testID:`${s}-value`,children:t})]})}function Preview({record:e}){return"image"===e.kind?(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})}):"font"===e.kind?(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"})}):null}function AssetDetail({record:e,insights:t}){const s=[];t.neverLoaded.includes(e.id)&&s.push("Not observed in the runtime registry this app run. This does not prove the asset is unused."),t.scaleGaps.includes(e.id)&&s.push("Scale gap — no variant covers this device's pixel ratio"),t.webpCandidates.includes(e.id)&&s.push("WebP candidate — large png/jpeg, converting typically saves 20–40%");const i=t.duplicates.find(t=>t.ids.includes(e.id));i&&s.push(`Duplicate content — identical bytes shipped ${i.ids.length} times`),t.overDecode.includes(e.id)&&s.push("Decodes larger than 2× this entire screen — resize the source, no view can need this many pixels"),t.heavyGifs.includes(e.id)&&s.push("Heavy GIF — every frame decodes into memory; a video or Lottie is typically ~90% smaller"),t.heavyFonts.includes(e.id)&&s.push("Heavy font — likely an unsubset icon font; subsetting to used glyphs usually saves most of it"),t.scaleAnomalies.includes(e.id)&&s.push("Scale anomaly — a higher-resolution variant is smaller in bytes than a lower one; check the exports");const l=(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}),s.length>0?(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.findings,testID:_testIDs.ASSETS_TEST_IDS.detailFindings,children:s.map((e,t)=>(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.findingText,testID:(0,_testIDs.assetFindingTestID)(t),children:e},e))}):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"}),"image"===e.kind?(0,_jsxRuntime.jsx)(Row,{label:"Dimensions",value:`${(0,_format.formatDimensions)(e)} (logical)`}):null,"image"===e.kind&&e.scales.length?(0,_jsxRuntime.jsx)(Row,{label:"Scales",value:(0,_format.formatScales)(e.scales)}):null,e.sizesByScale?Object.entries(e.sizesByScale).map(([e,t])=>(0,_jsxRuntime.jsx)(Row,{label:`Size @${e}x`,value:(0,_format.formatBytes)(t)},e)):null,null!=e.sizeBytes&&"measured"===e.sizeSource?(0,_jsxRuntime.jsx)(Row,{label:"Total size",value:(0,_format.formatBytes)(e.sizeBytes)}):null,l>0?(0,_jsxRuntime.jsx)(Row,{label:"Decoded memory",value:`~${(0,_format.formatBytes)(l)} (RGBA)`}):null,null!=e.registryId?(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}});
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.AssetImage=AssetImage;var _react=require("react"),_reactNative=require("react-native"),_sharedUi=require("@buoy-gg/shared-ui"),_measure=require("../capture/measure"),_optionalExpoImage=require("./optionalExpoImage"),_jsxRuntime=require("react/jsx-runtime");function AssetImage({record:e,style:t,testID:r,compact:a=!1}){const s=(0,_measure.displaySource)(e),i="svg"===e.type.toLowerCase(),n=i&&"web"!==_reactNative.Platform.OS?(0,_optionalExpoImage.getExpoPreviewImage)():null,o=`${e.key}:${e.hash??""}:${"number"==typeof s?s:s?.uri??""}`,[c,l]=(0,_react.useState)(null);if(null==s||c===o||i&&"web"!==_reactNative.Platform.OS&&!n){const e=i?"SVG preview unavailable":"Image preview unavailable";return(0,_jsxRuntime.jsx)(_reactNative.View,{style:[t,styles.fallback],accessibilityLabel:e,testID:`${r}-unavailable`,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.text,children:a?i?"SVG":"IMG":e})})}const u=()=>l(o);return n?(0,_jsxRuntime.jsx)(n,{source:s,style:t,contentFit:"contain",onError:u,testID:r}):(0,_jsxRuntime.jsx)(_reactNative.Image,{source:s,style:t,resizeMode:"contain",onError:u,testID:r})}const styles=_reactNative.StyleSheet.create({fallback:{alignItems:"center",justifyContent:"center"},text:{color:_sharedUi.night.color.textSecondary,fontSize:10,textAlign:"center"}});
@@ -1,233 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.AssetRow = AssetRow;
7
- var _reactNative = require("react-native");
8
- var _sharedUi = require("@buoy-gg/shared-ui");
9
- var _measure = require("../capture/measure");
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
- * AssetRow — one bundled asset as a family-style card (matching the network
16
- * tool's rows): rounded card, colored accent edge per kind, thumbnail, name,
17
- * quiet metadata, bold right-aligned size, and finding badges ONLY when a
18
- * finding exists. A thin proportional bar along the card bottom makes the
19
- * heavy assets feel heavy at a glance.
20
- *
21
- * Thumbnails render through the NUMERIC registry id when available — that
22
- * routes through resolveAssetSource natively, so it works in dev, iOS
23
- * release (file://) and Android release (bare resource id) alike. They carry
24
- * the buoy-internal testID so the images tool never records our own UI.
25
- */
26
-
27
- /** Which audit findings apply to this record (drives the row badges). */
28
-
29
- function Badge({
30
- label,
31
- color,
32
- testID
33
- }) {
34
- // Quiet chip: legibility from light-gray text on a neutral fill. Only the
35
- // serious tiers (red) and WEBP (blue) carry a small dot; the rest are plain.
36
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Pill, {
37
- label: label,
38
- color: color,
39
- variant: "quiet",
40
- dot: Boolean(color),
41
- style: {
42
- paddingVertical: 2.5
43
- },
44
- testID: testID
45
- });
46
- }
47
- function AssetRow({
48
- record,
49
- flags,
50
- sizeFraction,
51
- onPress
52
- }) {
53
- const accent = _format.KIND_COLORS[record.kind];
54
- const thumbSource = record.kind === "image" ? (0, _measure.displaySource)(record) : null;
55
- const badges = [];
56
- if (!record.loaded) badges.push({
57
- label: "UNUSED"
58
- });
59
- if (flags.oversize) badges.push({
60
- label: "OVERSIZE",
61
- color: _sharedUi.macOSColors.semantic.error
62
- });
63
- if (flags.duplicate) badges.push({
64
- label: "DUP"
65
- });
66
- if (flags.heavy) badges.push({
67
- label: "HEAVY"
68
- });
69
- if (flags.scaleAnomaly) badges.push({
70
- label: "BAD SCALE",
71
- color: _sharedUi.macOSColors.semantic.error
72
- });else if (flags.scaleGap) badges.push({
73
- label: "LOW-RES"
74
- });
75
- if (flags.webp) badges.push({
76
- label: "WEBP",
77
- color: _sharedUi.macOSColors.semantic.info
78
- });
79
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
80
- style: styles.card,
81
- testID: (0, _testIDs.assetRowTestID)(record.name, record.type),
82
- onPress: () => onPress(record.id),
83
- activeOpacity: 0.7,
84
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
85
- style: styles.body,
86
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
87
- style: styles.thumbBox,
88
- children: thumbSource != null ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Image
89
- // buoy-internal- prefix: the images tool skips its own toolchain's
90
- // views, so previewing an asset never records a render of itself.
91
- , {
92
- testID: "buoy-internal-assets-thumb",
93
- source: thumbSource,
94
- style: styles.thumb,
95
- resizeMode: "contain"
96
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
97
- style: [styles.thumbFallback, {
98
- color: accent
99
- }],
100
- children: _format.KIND_LABELS[record.kind]
101
- })
102
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
103
- style: styles.main,
104
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
105
- style: styles.name,
106
- numberOfLines: 1,
107
- testID: `${(0, _testIDs.assetRowTestID)(record.name, record.type)}-name`,
108
- children: [record.name, /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
109
- style: styles.ext,
110
- children: [".", record.type]
111
- })]
112
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
113
- style: styles.metaRow,
114
- children: [record.kind === "image" && record.width != null ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
115
- style: styles.meta,
116
- children: (0, _format.formatDimensions)(record)
117
- }) : null, record.kind === "image" && record.scales.length ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
118
- style: styles.meta,
119
- children: (0, _format.formatScales)(record.scales)
120
- }) : null]
121
- })]
122
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
123
- style: styles.right,
124
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
125
- style: styles.size,
126
- testID: `${(0, _testIDs.assetRowTestID)(record.name, record.type)}-size`,
127
- children: (0, _format.formatSize)(record, (0, _assetStore.estDecodedBytes)(record))
128
- }), badges.length ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
129
- style: styles.badgeRow,
130
- children: badges.slice(0, 3).map(b => /*#__PURE__*/(0, _jsxRuntime.jsx)(Badge, {
131
- label: b.label,
132
- color: b.color,
133
- testID: (0, _testIDs.assetBadgeTestID)(record.name, record.type, b.label)
134
- }, b.label))
135
- }) : null]
136
- })]
137
- }), sizeFraction > 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
138
- style: styles.sizeTrack,
139
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
140
- style: [styles.sizeFill, {
141
- backgroundColor: accent,
142
- width: `${Math.max(2, Math.round(sizeFraction * 100))}%`
143
- }]
144
- })
145
- }) : null]
146
- });
147
- }
148
- const styles = _reactNative.StyleSheet.create({
149
- card: {
150
- marginHorizontal: 10,
151
- marginTop: 6,
152
- borderRadius: 10,
153
- backgroundColor: _sharedUi.night.color.surface,
154
- borderWidth: 1,
155
- borderColor: _sharedUi.night.color.border,
156
- overflow: "hidden"
157
- },
158
- body: {
159
- flexDirection: "row",
160
- alignItems: "center",
161
- paddingVertical: 8,
162
- paddingHorizontal: 12,
163
- gap: 10
164
- },
165
- thumbBox: {
166
- width: 40,
167
- height: 40,
168
- borderRadius: 8,
169
- // Light plate so dark glyph assets stay visible on the dark card.
170
- backgroundColor: "rgba(255,255,255,0.10)",
171
- borderWidth: 1,
172
- borderColor: _sharedUi.night.color.border,
173
- alignItems: "center",
174
- justifyContent: "center",
175
- overflow: "hidden"
176
- },
177
- thumb: {
178
- width: 34,
179
- height: 34
180
- },
181
- thumbFallback: {
182
- fontSize: 9,
183
- fontWeight: "700",
184
- letterSpacing: 0.5
185
- },
186
- main: {
187
- flex: 1,
188
- gap: 3
189
- },
190
- name: {
191
- color: _sharedUi.night.color.text,
192
- fontSize: 12,
193
- fontWeight: "600"
194
- },
195
- ext: {
196
- color: _sharedUi.night.color.textTertiary,
197
- fontWeight: "400"
198
- },
199
- metaRow: {
200
- flexDirection: "row",
201
- alignItems: "center",
202
- gap: 8
203
- },
204
- meta: {
205
- color: _sharedUi.night.color.textSecondary,
206
- fontSize: 10,
207
- fontVariant: ["tabular-nums"]
208
- },
209
- right: {
210
- alignItems: "flex-end",
211
- gap: 4
212
- },
213
- size: {
214
- color: _sharedUi.night.color.text,
215
- fontSize: 12,
216
- fontWeight: "700",
217
- fontVariant: ["tabular-nums"]
218
- },
219
- badgeRow: {
220
- flexDirection: "row",
221
- gap: 4
222
- },
223
- sizeTrack: {
224
- height: 2,
225
- backgroundColor: "transparent"
226
- },
227
- sizeFill: {
228
- height: 2,
229
- opacity: 0.45,
230
- borderTopRightRadius: 2
231
- }
232
- });
233
- //# sourceMappingURL=AssetRow.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.AssetRow=AssetRow;var _reactNative=require("react-native"),_sharedUi=require("@buoy-gg/shared-ui"),_AssetImage=require("./AssetImage"),_format=require("../format"),_assetStore=require("../store/assetStore"),_testIDs=require("../utils/testIDs"),_jsxRuntime=require("react/jsx-runtime");function Badge({label:e,color:t,testID:s}){return(0,_jsxRuntime.jsx)(_sharedUi.Pill,{label:e,color:t,variant:"quiet",dot:Boolean(t),style:{paddingVertical:2.5},testID:s})}function AssetRow({record:e,flags:t,sizeFraction:s,onPress:a}){const r=_format.KIND_COLORS[e.kind],i=[];return e.loaded||i.push({label:"NOT OBSERVED"}),t.oversize&&i.push({label:"OVERSIZE",color:_sharedUi.macOSColors.semantic.error}),t.duplicate&&i.push({label:"DUP"}),t.heavy&&i.push({label:"HEAVY"}),t.scaleAnomaly?i.push({label:"BAD SCALE",color:_sharedUi.macOSColors.semantic.error}):t.scaleGap&&i.push({label:"LOW-RES"}),t.webp&&i.push({label:"WEBP",color:_sharedUi.macOSColors.semantic.info}),(0,_jsxRuntime.jsxs)(_reactNative.TouchableOpacity,{style:styles.card,testID:(0,_testIDs.assetRowTestID)(e.name,e.type),onPress:()=>a(e.id),activeOpacity:.7,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.body,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.thumbBox,children:"image"===e.kind?(0,_jsxRuntime.jsx)(_AssetImage.AssetImage,{testID:"buoy-internal-assets-thumb",record:e,style:styles.thumb,compact:!0}):(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.thumbFallback,{color:r}],children:_format.KIND_LABELS[e.kind]})}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.main,children:[(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.name,numberOfLines:1,testID:`${(0,_testIDs.assetRowTestID)(e.name,e.type)}-name`,children:[e.name,(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.ext,children:[".",e.type]})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.metaRow,children:["image"===e.kind&&null!=e.width?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.meta,children:(0,_format.formatDimensions)(e)}):null,"image"===e.kind&&e.scales.length?(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.meta,children:(0,_format.formatScales)(e.scales)}):null]})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.right,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.size,testID:`${(0,_testIDs.assetRowTestID)(e.name,e.type)}-size`,children:(0,_format.formatSize)(e,(0,_assetStore.estDecodedBytes)(e))}),i.length?(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.badgeRow,children:i.slice(0,3).map(t=>(0,_jsxRuntime.jsx)(Badge,{label:t.label,color:t.color,testID:(0,_testIDs.assetBadgeTestID)(e.name,e.type,t.label)},t.label))}):null]})]}),s>0?(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.sizeTrack,children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.sizeFill,{backgroundColor:r,width:`${Math.max(2,Math.round(100*s))}%`}]})}):null]})}const styles=_reactNative.StyleSheet.create({card:{marginHorizontal:10,marginTop:6,borderRadius:10,backgroundColor:_sharedUi.night.color.surface,borderWidth:1,borderColor:_sharedUi.night.color.border,overflow:"hidden"},body:{flexDirection:"row",alignItems:"center",paddingVertical:8,paddingHorizontal:12,gap:10},thumbBox:{width:40,height:40,borderRadius:8,backgroundColor:"rgba(255,255,255,0.10)",borderWidth:1,borderColor:_sharedUi.night.color.border,alignItems:"center",justifyContent:"center",overflow:"hidden"},thumb:{width:34,height:34},thumbFallback:{fontSize:9,fontWeight:"700",letterSpacing:.5},main:{flex:1,gap:3},name:{color:_sharedUi.night.color.text,fontSize:12,fontWeight:"600"},ext:{color:_sharedUi.night.color.textTertiary,fontWeight:"400"},metaRow:{flexDirection:"row",alignItems:"center",gap:8},meta:{color:_sharedUi.night.color.textSecondary,fontSize:10,fontVariant:["tabular-nums"]},right:{alignItems:"flex-end",gap:4},size:{color:_sharedUi.night.color.text,fontSize:12,fontWeight:"700",fontVariant:["tabular-nums"]},badgeRow:{flexDirection:"row",gap:4},sizeTrack:{height:2,backgroundColor:"transparent"},sizeFill:{height:2,opacity:.45,borderTopRightRadius:2}});