@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,229 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * AssetRow — one bundled asset as a family-style card (matching the network
5
- * tool's rows): rounded card, colored accent edge per kind, thumbnail, name,
6
- * quiet metadata, bold right-aligned size, and finding badges ONLY when a
7
- * finding exists. A thin proportional bar along the card bottom makes the
8
- * heavy assets feel heavy at a glance.
9
- *
10
- * Thumbnails render through the NUMERIC registry id when available — that
11
- * routes through resolveAssetSource natively, so it works in dev, iOS
12
- * release (file://) and Android release (bare resource id) alike. They carry
13
- * the buoy-internal testID so the images tool never records our own UI.
14
- */
15
-
16
- import { Image, StyleSheet, Text, TouchableOpacity, View } from "react-native";
17
- import { macOSColors, night, Pill } from "@buoy-gg/shared-ui";
18
- import { displaySource } from "../capture/measure";
19
- import { formatDimensions, formatScales, formatSize, KIND_COLORS, KIND_LABELS } from "../format";
20
- import { estDecodedBytes } from "../store/assetStore";
21
- import { assetBadgeTestID, assetRowTestID } from "../utils/testIDs";
22
-
23
- /** Which audit findings apply to this record (drives the row badges). */
24
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
25
- function Badge({
26
- label,
27
- color,
28
- testID
29
- }) {
30
- // Quiet chip: legibility from light-gray text on a neutral fill. Only the
31
- // serious tiers (red) and WEBP (blue) carry a small dot; the rest are plain.
32
- return /*#__PURE__*/_jsx(Pill, {
33
- label: label,
34
- color: color,
35
- variant: "quiet",
36
- dot: Boolean(color),
37
- style: {
38
- paddingVertical: 2.5
39
- },
40
- testID: testID
41
- });
42
- }
43
- export function AssetRow({
44
- record,
45
- flags,
46
- sizeFraction,
47
- onPress
48
- }) {
49
- const accent = KIND_COLORS[record.kind];
50
- const thumbSource = record.kind === "image" ? displaySource(record) : null;
51
- const badges = [];
52
- if (!record.loaded) badges.push({
53
- label: "UNUSED"
54
- });
55
- if (flags.oversize) badges.push({
56
- label: "OVERSIZE",
57
- color: macOSColors.semantic.error
58
- });
59
- if (flags.duplicate) badges.push({
60
- label: "DUP"
61
- });
62
- if (flags.heavy) badges.push({
63
- label: "HEAVY"
64
- });
65
- if (flags.scaleAnomaly) badges.push({
66
- label: "BAD SCALE",
67
- color: macOSColors.semantic.error
68
- });else if (flags.scaleGap) badges.push({
69
- label: "LOW-RES"
70
- });
71
- if (flags.webp) badges.push({
72
- label: "WEBP",
73
- color: macOSColors.semantic.info
74
- });
75
- return /*#__PURE__*/_jsxs(TouchableOpacity, {
76
- style: styles.card,
77
- testID: assetRowTestID(record.name, record.type),
78
- onPress: () => onPress(record.id),
79
- activeOpacity: 0.7,
80
- children: [/*#__PURE__*/_jsxs(View, {
81
- style: styles.body,
82
- children: [/*#__PURE__*/_jsx(View, {
83
- style: styles.thumbBox,
84
- children: thumbSource != null ? /*#__PURE__*/_jsx(Image
85
- // buoy-internal- prefix: the images tool skips its own toolchain's
86
- // views, so previewing an asset never records a render of itself.
87
- , {
88
- testID: "buoy-internal-assets-thumb",
89
- source: thumbSource,
90
- style: styles.thumb,
91
- resizeMode: "contain"
92
- }) : /*#__PURE__*/_jsx(Text, {
93
- style: [styles.thumbFallback, {
94
- color: accent
95
- }],
96
- children: KIND_LABELS[record.kind]
97
- })
98
- }), /*#__PURE__*/_jsxs(View, {
99
- style: styles.main,
100
- children: [/*#__PURE__*/_jsxs(Text, {
101
- style: styles.name,
102
- numberOfLines: 1,
103
- testID: `${assetRowTestID(record.name, record.type)}-name`,
104
- children: [record.name, /*#__PURE__*/_jsxs(Text, {
105
- style: styles.ext,
106
- children: [".", record.type]
107
- })]
108
- }), /*#__PURE__*/_jsxs(View, {
109
- style: styles.metaRow,
110
- children: [record.kind === "image" && record.width != null ? /*#__PURE__*/_jsx(Text, {
111
- style: styles.meta,
112
- children: formatDimensions(record)
113
- }) : null, record.kind === "image" && record.scales.length ? /*#__PURE__*/_jsx(Text, {
114
- style: styles.meta,
115
- children: formatScales(record.scales)
116
- }) : null]
117
- })]
118
- }), /*#__PURE__*/_jsxs(View, {
119
- style: styles.right,
120
- children: [/*#__PURE__*/_jsx(Text, {
121
- style: styles.size,
122
- testID: `${assetRowTestID(record.name, record.type)}-size`,
123
- children: formatSize(record, estDecodedBytes(record))
124
- }), badges.length ? /*#__PURE__*/_jsx(View, {
125
- style: styles.badgeRow,
126
- children: badges.slice(0, 3).map(b => /*#__PURE__*/_jsx(Badge, {
127
- label: b.label,
128
- color: b.color,
129
- testID: assetBadgeTestID(record.name, record.type, b.label)
130
- }, b.label))
131
- }) : null]
132
- })]
133
- }), sizeFraction > 0 ? /*#__PURE__*/_jsx(View, {
134
- style: styles.sizeTrack,
135
- children: /*#__PURE__*/_jsx(View, {
136
- style: [styles.sizeFill, {
137
- backgroundColor: accent,
138
- width: `${Math.max(2, Math.round(sizeFraction * 100))}%`
139
- }]
140
- })
141
- }) : null]
142
- });
143
- }
144
- const styles = StyleSheet.create({
145
- card: {
146
- marginHorizontal: 10,
147
- marginTop: 6,
148
- borderRadius: 10,
149
- backgroundColor: night.color.surface,
150
- borderWidth: 1,
151
- borderColor: night.color.border,
152
- overflow: "hidden"
153
- },
154
- body: {
155
- flexDirection: "row",
156
- alignItems: "center",
157
- paddingVertical: 8,
158
- paddingHorizontal: 12,
159
- gap: 10
160
- },
161
- thumbBox: {
162
- width: 40,
163
- height: 40,
164
- borderRadius: 8,
165
- // Light plate so dark glyph assets stay visible on the dark card.
166
- backgroundColor: "rgba(255,255,255,0.10)",
167
- borderWidth: 1,
168
- borderColor: night.color.border,
169
- alignItems: "center",
170
- justifyContent: "center",
171
- overflow: "hidden"
172
- },
173
- thumb: {
174
- width: 34,
175
- height: 34
176
- },
177
- thumbFallback: {
178
- fontSize: 9,
179
- fontWeight: "700",
180
- letterSpacing: 0.5
181
- },
182
- main: {
183
- flex: 1,
184
- gap: 3
185
- },
186
- name: {
187
- color: night.color.text,
188
- fontSize: 12,
189
- fontWeight: "600"
190
- },
191
- ext: {
192
- color: night.color.textTertiary,
193
- fontWeight: "400"
194
- },
195
- metaRow: {
196
- flexDirection: "row",
197
- alignItems: "center",
198
- gap: 8
199
- },
200
- meta: {
201
- color: night.color.textSecondary,
202
- fontSize: 10,
203
- fontVariant: ["tabular-nums"]
204
- },
205
- right: {
206
- alignItems: "flex-end",
207
- gap: 4
208
- },
209
- size: {
210
- color: night.color.text,
211
- fontSize: 12,
212
- fontWeight: "700",
213
- fontVariant: ["tabular-nums"]
214
- },
215
- badgeRow: {
216
- flexDirection: "row",
217
- gap: 4
218
- },
219
- sizeTrack: {
220
- height: 2,
221
- backgroundColor: "transparent"
222
- },
223
- sizeFill: {
224
- height: 2,
225
- opacity: 0.45,
226
- borderTopRightRadius: 2
227
- }
228
- });
229
- //# sourceMappingURL=AssetRow.js.map
1
+ "use strict";import{StyleSheet,Text,TouchableOpacity,View}from"react-native";import{macOSColors,night,Pill}from"@buoy-gg/shared-ui";import{AssetImage}from"./AssetImage";import{formatDimensions,formatScales,formatSize,KIND_COLORS,KIND_LABELS}from"../format";import{estDecodedBytes}from"../store/assetStore";import{assetBadgeTestID,assetRowTestID}from"../utils/testIDs";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";function Badge({label:e,color:t,testID:s}){return _jsx(Pill,{label:e,color:t,variant:"quiet",dot:Boolean(t),style:{paddingVertical:2.5},testID:s})}export function AssetRow({record:e,flags:t,sizeFraction:s,onPress:o}){const l=KIND_COLORS[e.kind],r=[];return e.loaded||r.push({label:"NOT OBSERVED"}),t.oversize&&r.push({label:"OVERSIZE",color:macOSColors.semantic.error}),t.duplicate&&r.push({label:"DUP"}),t.heavy&&r.push({label:"HEAVY"}),t.scaleAnomaly?r.push({label:"BAD SCALE",color:macOSColors.semantic.error}):t.scaleGap&&r.push({label:"LOW-RES"}),t.webp&&r.push({label:"WEBP",color:macOSColors.semantic.info}),_jsxs(TouchableOpacity,{style:styles.card,testID:assetRowTestID(e.name,e.type),onPress:()=>o(e.id),activeOpacity:.7,children:[_jsxs(View,{style:styles.body,children:[_jsx(View,{style:styles.thumbBox,children:"image"===e.kind?_jsx(AssetImage,{testID:"buoy-internal-assets-thumb",record:e,style:styles.thumb,compact:!0}):_jsx(Text,{style:[styles.thumbFallback,{color:l}],children:KIND_LABELS[e.kind]})}),_jsxs(View,{style:styles.main,children:[_jsxs(Text,{style:styles.name,numberOfLines:1,testID:`${assetRowTestID(e.name,e.type)}-name`,children:[e.name,_jsxs(Text,{style:styles.ext,children:[".",e.type]})]}),_jsxs(View,{style:styles.metaRow,children:["image"===e.kind&&null!=e.width?_jsx(Text,{style:styles.meta,children:formatDimensions(e)}):null,"image"===e.kind&&e.scales.length?_jsx(Text,{style:styles.meta,children:formatScales(e.scales)}):null]})]}),_jsxs(View,{style:styles.right,children:[_jsx(Text,{style:styles.size,testID:`${assetRowTestID(e.name,e.type)}-size`,children:formatSize(e,estDecodedBytes(e))}),r.length?_jsx(View,{style:styles.badgeRow,children:r.slice(0,3).map(t=>_jsx(Badge,{label:t.label,color:t.color,testID:assetBadgeTestID(e.name,e.type,t.label)},t.label))}):null]})]}),s>0?_jsx(View,{style:styles.sizeTrack,children:_jsx(View,{style:[styles.sizeFill,{backgroundColor:l,width:`${Math.max(2,Math.round(100*s))}%`}]})}):null]})}const styles=StyleSheet.create({card:{marginHorizontal:10,marginTop:6,borderRadius:10,backgroundColor:night.color.surface,borderWidth:1,borderColor: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: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:night.color.text,fontSize:12,fontWeight:"600"},ext:{color:night.color.textTertiary,fontWeight:"400"},metaRow:{flexDirection:"row",alignItems:"center",gap:8},meta:{color:night.color.textSecondary,fontSize:10,fontVariant:["tabular-nums"]},right:{alignItems:"flex-end",gap:4},size:{color: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}});
@@ -1,92 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * AssetsFilterBar — kind filter pills with counts, styled like the network
5
- * tool's bordered pills: outlined, kind-accent-colored when active. Wrapping
6
- * row, not a horizontal ScrollView (same height-measurement pitfall the
7
- * images tool documents).
8
- */
9
-
10
- import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
11
- import { night } from "@buoy-gg/shared-ui";
12
- import { KIND_COLORS, KIND_LABELS } from "../format";
13
- import { ASSETS_TEST_IDS, assetFilterTestID } from "../utils/testIDs";
14
- import { jsx as _jsx } from "react/jsx-runtime";
15
- export function AssetsFilterBar({
16
- stats,
17
- filter,
18
- onChange
19
- }) {
20
- const chips = [{
21
- key: "all",
22
- label: `ALL ${stats.total}`,
23
- accent: night.color.textSecondary
24
- }];
25
- for (const kind of Object.keys(stats.byKind)) {
26
- const entry = stats.byKind[kind];
27
- if (entry.count > 0) {
28
- chips.push({
29
- key: kind,
30
- label: `${KIND_LABELS[kind]} ${entry.count}`,
31
- accent: KIND_COLORS[kind]
32
- });
33
- }
34
- }
35
- if (stats.neverLoaded > 0) {
36
- // Amber, not semantic.warning — the bright yellow reads as an alarm.
37
- chips.push({
38
- key: "unused",
39
- label: `UNUSED ${stats.neverLoaded}`,
40
- accent: "#FF9F1C"
41
- });
42
- }
43
- if (chips.length <= 1) return null;
44
- return /*#__PURE__*/_jsx(View, {
45
- style: styles.bar,
46
- testID: ASSETS_TEST_IDS.filterBar,
47
- children: chips.map(chip => {
48
- const active = chip.key === filter;
49
- return /*#__PURE__*/_jsx(TouchableOpacity, {
50
- testID: assetFilterTestID(chip.key),
51
- style: [styles.chip, active && {
52
- borderColor: chip.accent,
53
- backgroundColor: `${chip.accent}1A`
54
- }]
55
- // Tapping the active chip again untoggles back to ALL.
56
- ,
57
- onPress: () => onChange(active ? "all" : chip.key),
58
- children: /*#__PURE__*/_jsx(Text, {
59
- testID: `${assetFilterTestID(chip.key)}-label`,
60
- style: [styles.chipText, {
61
- color: active ? chip.accent : night.color.textSecondary
62
- }],
63
- children: chip.label
64
- })
65
- }, chip.key);
66
- })
67
- });
68
- }
69
- const styles = StyleSheet.create({
70
- bar: {
71
- flexDirection: "row",
72
- flexWrap: "wrap",
73
- gap: 6,
74
- paddingHorizontal: 10,
75
- paddingVertical: 8
76
- },
77
- chip: {
78
- borderWidth: 1,
79
- borderColor: night.color.border,
80
- backgroundColor: night.color.surface,
81
- borderRadius: 999,
82
- paddingHorizontal: 10,
83
- paddingVertical: 5
84
- },
85
- chipText: {
86
- fontSize: 10,
87
- fontWeight: "700",
88
- letterSpacing: 0.4,
89
- lineHeight: 13
90
- }
91
- });
92
- //# sourceMappingURL=AssetsFilterBar.js.map
1
+ "use strict";import{StyleSheet,Text,TouchableOpacity,View}from"react-native";import{night}from"@buoy-gg/shared-ui";import{KIND_COLORS,KIND_LABELS}from"../format";import{ASSETS_TEST_IDS,assetFilterTestID}from"../utils/testIDs";import{jsx as _jsx}from"react/jsx-runtime";export function AssetsFilterBar({stats:e,duplicateCount:t,filter:r,onChange:o}){const l=[{key:"all",label:`ALL ${e.total}`,accent: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&&l.push({key:t,label:`${KIND_LABELS[t]} ${r.count}`,accent:KIND_COLORS[t]})}return e.neverLoaded>0&&l.push({key:"unused",label:`NOT OBSERVED ${e.neverLoaded}`,accent:"#FF9F1C"}),l.length<=1?null:_jsx(View,{style:styles.bar,testID:ASSETS_TEST_IDS.filterBar,children:l.map(e=>{const t=e.key===r;return _jsx(TouchableOpacity,{accessibilityRole:"button",accessibilityState:{selected:t},testID:assetFilterTestID(e.key),style:[styles.chip,t&&{borderColor:e.accent,backgroundColor:`${e.accent}1A`}],onPress:()=>o(t?"all":e.key),children:_jsx(Text,{testID:`${assetFilterTestID(e.key)}-label`,style:[styles.chipText,{color:t?e.accent:night.color.textSecondary}],children:e.label})},e.key)})})}const styles=StyleSheet.create({bar:{flexDirection:"row",flexWrap:"wrap",gap:6,paddingHorizontal:10,paddingVertical:8},chip:{borderWidth:1,borderColor:night.color.border,backgroundColor:night.color.surface,borderRadius:999,paddingHorizontal:10,paddingVertical:5},chipText:{fontSize:10,fontWeight:"700",letterSpacing:.4,lineHeight:13}});
@@ -1,68 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * AssetsHeader — shared ModalHeader wiring, matching the Images/Console
5
- * header pattern. List mode shows inventory totals plus the shared
6
- * ToolbarCopyButton (full markdown report); detail mode shows back
7
- * navigation and the single-asset report.
8
- */
9
-
10
- import { ModalHeader, ToolbarClearButton, ToolbarCopyButton } from "@buoy-gg/shared-ui";
11
- import { formatBytes } from "../format";
12
- import { ASSETS_TEST_IDS } from "../utils/testIDs";
13
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
- export function AssetsHeader({
15
- stats,
16
- measuring,
17
- detailOpen,
18
- detailIndex = -1,
19
- detailTotal = 0,
20
- onCloseDetail,
21
- onClear,
22
- getReport,
23
- onBack
24
- }) {
25
- if (detailOpen) {
26
- const counter = detailIndex >= 0 && detailTotal > 0 ? `${detailIndex + 1} of ${detailTotal}` : undefined;
27
- return /*#__PURE__*/_jsxs(ModalHeader, {
28
- children: [/*#__PURE__*/_jsx(ModalHeader.Navigation, {
29
- onBack: onCloseDetail
30
- }), /*#__PURE__*/_jsx(ModalHeader.Content, {
31
- title: "Asset detail",
32
- subtitle: counter,
33
- testID: ASSETS_TEST_IDS.title
34
- }), /*#__PURE__*/_jsx(ModalHeader.Actions, {
35
- children: /*#__PURE__*/_jsx(ToolbarCopyButton, {
36
- value: getReport,
37
- testID: ASSETS_TEST_IDS.copy
38
- })
39
- })]
40
- });
41
- }
42
- const subtitleParts = [`${stats.total} assets`];
43
- // A mid-measure byte total reads as nonsense ("653 B+") — wait it out.
44
- if (stats.totalBytes > 0 && !measuring) {
45
- const partial = stats.measuredCount < stats.total ? "+" : "";
46
- subtitleParts.push(`${formatBytes(stats.totalBytes)}${partial}`);
47
- }
48
- if (stats.neverLoaded > 0) subtitleParts.push(`${stats.neverLoaded} never loaded`);
49
- if (stats.fontFamilies > 0) subtitleParts.push(`${stats.fontFamilies} fonts`);
50
- return /*#__PURE__*/_jsxs(ModalHeader, {
51
- children: [onBack ? /*#__PURE__*/_jsx(ModalHeader.Navigation, {
52
- onBack: onBack
53
- }) : null, /*#__PURE__*/_jsx(ModalHeader.Content, {
54
- title: "Assets",
55
- subtitle: subtitleParts.join(" · "),
56
- testID: ASSETS_TEST_IDS.title
57
- }), /*#__PURE__*/_jsxs(ModalHeader.Actions, {
58
- children: [/*#__PURE__*/_jsx(ToolbarCopyButton, {
59
- value: getReport,
60
- testID: ASSETS_TEST_IDS.copy
61
- }), /*#__PURE__*/_jsx(ToolbarClearButton, {
62
- onPress: onClear,
63
- testID: ASSETS_TEST_IDS.clear
64
- })]
65
- })]
66
- });
67
- }
68
- //# sourceMappingURL=AssetsHeader.js.map
1
+ "use strict";import{ModalHeader,ToolbarClearButton,ToolbarCopyButton}from"@buoy-gg/shared-ui";import{formatBytes}from"../format";import{ASSETS_TEST_IDS}from"../utils/testIDs";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";export function AssetsHeader({stats:t,measuring:e,discovering:o=!1,detailOpen:s,detailIndex:a=-1,detailTotal:r=0,onCloseDetail:l,onClear:n,getReport:i,onBack:d}){if(s){const t=a>=0&&r>0?`${a+1} of ${r}`:void 0;return _jsxs(ModalHeader,{children:[_jsx(ModalHeader.Navigation,{onBack:l}),_jsx(ModalHeader.Content,{title:"Asset detail",subtitle:t,testID:ASSETS_TEST_IDS.title}),_jsx(ModalHeader.Actions,{children:_jsx(ToolbarCopyButton,{value:i,testID:ASSETS_TEST_IDS.copy})})]})}const S=[`${t.total} assets${o?" so far":""}`];if(t.totalBytes>0&&!e&&!o){const e=t.measuredCount<t.total?"+":"";S.push(`${formatBytes(t.totalBytes)}${e}`)}return t.neverLoaded>0&&S.push(`${t.neverLoaded} not observed`),t.fontFamilies>0&&S.push(`${t.fontFamilies} fonts`),_jsxs(ModalHeader,{children:[d?_jsx(ModalHeader.Navigation,{onBack:d}):null,_jsx(ModalHeader.Content,{title:"Assets",subtitle:S.join(" · "),testID:ASSETS_TEST_IDS.title}),_jsxs(ModalHeader.Actions,{children:[_jsx(ToolbarCopyButton,{value:i,testID:ASSETS_TEST_IDS.copy}),_jsx(ToolbarClearButton,{onPress:n,testID:ASSETS_TEST_IDS.clear})]})]})}
@@ -1,12 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * AssetsIcon — re-exported from the Buoy Icon Format.
5
- *
6
- * The artwork lives in shared/icons/assets.json and is generated into
7
- * @buoy-gg/floating-tools-core, so React Native, the desktop dashboard and
8
- * Flutter all render the same drawing. Edit the JSON, then `pnpm icons`.
9
- */
10
-
11
- export { AssetsIcon, ASSETS_ICON_COLOR } from "@buoy-gg/shared-ui";
12
- //# sourceMappingURL=AssetsIcon.js.map
1
+ "use strict";export{AssetsIcon,ASSETS_ICON_COLOR}from"@buoy-gg/shared-ui";
@@ -1,92 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * AssetsListControls — one compact row: name search, sort cycle (SIZE →
5
- * NAME → TYPE), and — when no baseline exists yet — the BASE button that
6
- * saves one. Once a baseline exists the BaselineBar takes over the diff UI,
7
- * so this row never wastes space on a hint sentence.
8
- */
9
-
10
- import { StyleSheet, Text, TextInput, TouchableOpacity, View } from "react-native";
11
- import { night } from "@buoy-gg/shared-ui";
12
- import { saveBaseline } from "../store/baseline";
13
- import { ASSETS_TEST_IDS } from "../utils/testIDs";
14
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
15
- const NEXT_SORT = {
16
- size: "name",
17
- name: "type",
18
- type: "size"
19
- };
20
- export function AssetsListControls({
21
- query,
22
- onQueryChange,
23
- sort,
24
- onSortChange,
25
- showBaselineButton
26
- }) {
27
- return /*#__PURE__*/_jsxs(View, {
28
- style: styles.row,
29
- children: [/*#__PURE__*/_jsx(TextInput, {
30
- style: styles.input,
31
- value: query,
32
- onChangeText: onQueryChange,
33
- placeholder: "Search assets\u2026",
34
- placeholderTextColor: night.color.placeholder,
35
- autoCapitalize: "none",
36
- autoCorrect: false,
37
- testID: ASSETS_TEST_IDS.search
38
- }), /*#__PURE__*/_jsx(TouchableOpacity, {
39
- style: styles.button,
40
- onPress: () => onSortChange(NEXT_SORT[sort]),
41
- testID: ASSETS_TEST_IDS.sort,
42
- children: /*#__PURE__*/_jsxs(Text, {
43
- style: styles.buttonText,
44
- testID: `${ASSETS_TEST_IDS.sort}-label`,
45
- children: ["\u2193 ", sort.toUpperCase()]
46
- })
47
- }), showBaselineButton ? /*#__PURE__*/_jsx(TouchableOpacity, {
48
- style: styles.button,
49
- onPress: () => void saveBaseline(),
50
- testID: ASSETS_TEST_IDS.saveBaseline,
51
- children: /*#__PURE__*/_jsx(Text, {
52
- style: styles.buttonText,
53
- children: "BASE"
54
- })
55
- }) : null]
56
- });
57
- }
58
- const styles = StyleSheet.create({
59
- row: {
60
- flexDirection: "row",
61
- alignItems: "center",
62
- gap: 8,
63
- paddingHorizontal: 10,
64
- paddingBottom: 8
65
- },
66
- input: {
67
- flex: 1,
68
- backgroundColor: night.color.surfaceElevated,
69
- borderWidth: 1,
70
- borderColor: night.color.border,
71
- borderRadius: 8,
72
- paddingHorizontal: 10,
73
- paddingVertical: 6,
74
- color: night.color.text,
75
- fontSize: 12
76
- },
77
- button: {
78
- backgroundColor: night.color.surface,
79
- borderWidth: 1,
80
- borderColor: night.color.border,
81
- borderRadius: 8,
82
- paddingHorizontal: 10,
83
- paddingVertical: 7
84
- },
85
- buttonText: {
86
- color: night.color.textSecondary,
87
- fontSize: 10,
88
- fontWeight: "700",
89
- letterSpacing: 0.5
90
- }
91
- });
92
- //# sourceMappingURL=AssetsListControls.js.map
1
+ "use strict";import{StyleSheet,Text,TextInput,TouchableOpacity,View}from"react-native";import{night}from"@buoy-gg/shared-ui";import{ASSETS_TEST_IDS}from"../utils/testIDs";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const NEXT_SORT={size:"name",name:"type",type:"size"};export function AssetsListControls({query:t,onQueryChange:e,sort:o,onSortChange:r}){return _jsxs(View,{style:styles.row,children:[_jsx(TextInput,{style:styles.input,value:t,onChangeText:e,placeholder:"Search assets…",placeholderTextColor:night.color.placeholder,autoCapitalize:"none",autoCorrect:!1,testID:ASSETS_TEST_IDS.search}),_jsx(TouchableOpacity,{style:styles.button,onPress:()=>r(NEXT_SORT[o]),testID:ASSETS_TEST_IDS.sort,children:_jsxs(Text,{style:styles.buttonText,testID:`${ASSETS_TEST_IDS.sort}-label`,children:["↓ ",o.toUpperCase()]})})]})}const styles=StyleSheet.create({row:{flexDirection:"row",alignItems:"center",gap:8,paddingHorizontal:10,paddingBottom:8},input:{flex:1,backgroundColor:night.color.surfaceElevated,borderWidth:1,borderColor:night.color.border,borderRadius:8,paddingHorizontal:10,paddingVertical:6,color:night.color.text,fontSize:12},button:{backgroundColor:night.color.surface,borderWidth:1,borderColor:night.color.border,borderRadius:8,paddingHorizontal:10,paddingVertical:7},buttonText:{color:night.color.textSecondary,fontSize:10,fontWeight:"700",letterSpacing:.5}});