cursedbelt 1.0.0 โ†’ 2.5.0

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 (537) hide show
  1. package/dist/client/index.js +1 -1
  2. package/dist/core/category/index.d.ts.map +1 -1
  3. package/dist/core/category/index.js +2 -1
  4. package/dist/core/category/index.js.map +1 -1
  5. package/dist/core/category/types.js +1 -1
  6. package/dist/core/category/types.js.map +1 -1
  7. package/dist/core/file-tree/fileTreeModel.d.ts +49 -0
  8. package/dist/core/file-tree/fileTreeModel.d.ts.map +1 -1
  9. package/dist/core/file-tree/fileTreeModel.js +84 -0
  10. package/dist/core/file-tree/fileTreeModel.js.map +1 -1
  11. package/dist/core/layout/index.js +1 -1
  12. package/dist/core/layout/index.js.map +1 -1
  13. package/dist/core/media/index.js +1 -1
  14. package/dist/core/media/index.js.map +1 -1
  15. package/dist/core/media/types.js +1 -1
  16. package/dist/core/media/types.js.map +1 -1
  17. package/dist/core/media/uploadLimits.js +1 -1
  18. package/dist/core/media/uploadLimits.js.map +1 -1
  19. package/dist/core/sharing/model.d.ts +1 -1
  20. package/dist/ctgr/index.js +1 -1
  21. package/dist/index.js +1 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/react/activity-bar/ActivityBar.d.ts +17 -0
  24. package/dist/react/activity-bar/ActivityBar.d.ts.map +1 -1
  25. package/dist/react/activity-bar/ActivityBar.js.map +1 -1
  26. package/dist/react/analytics/index.d.ts +1 -1
  27. package/dist/react/analytics/index.js +1 -1
  28. package/dist/react/chat/MessageComposer.d.ts.map +1 -1
  29. package/dist/react/chat/MessageComposer.js +5 -4
  30. package/dist/react/chat/MessageComposer.js.map +1 -1
  31. package/dist/react/components/Button.d.ts.map +1 -1
  32. package/dist/react/components/Button.js +3 -2
  33. package/dist/react/components/Button.js.map +1 -1
  34. package/dist/react/components/Checkbox.d.ts +19 -3
  35. package/dist/react/components/Checkbox.d.ts.map +1 -1
  36. package/dist/react/components/Checkbox.js +29 -12
  37. package/dist/react/components/Checkbox.js.map +1 -1
  38. package/dist/react/components/CodeArea.d.ts.map +1 -1
  39. package/dist/react/components/CodeArea.js +2 -1
  40. package/dist/react/components/CodeArea.js.map +1 -1
  41. package/dist/react/components/Collapsible.d.ts.map +1 -1
  42. package/dist/react/components/Collapsible.js +2 -1
  43. package/dist/react/components/Collapsible.js.map +1 -1
  44. package/dist/react/components/ComboboxField.d.ts.map +1 -1
  45. package/dist/react/components/ComboboxField.js +3 -2
  46. package/dist/react/components/ComboboxField.js.map +1 -1
  47. package/dist/react/components/CopyButton.d.ts.map +1 -1
  48. package/dist/react/components/CopyButton.js +2 -1
  49. package/dist/react/components/CopyButton.js.map +1 -1
  50. package/dist/react/components/DataTable/ColumnChecklist.d.ts.map +1 -1
  51. package/dist/react/components/DataTable/ColumnChecklist.js +2 -1
  52. package/dist/react/components/DataTable/ColumnChecklist.js.map +1 -1
  53. package/dist/react/components/DataTable/Pagination.d.ts.map +1 -1
  54. package/dist/react/components/DataTable/Pagination.js +2 -1
  55. package/dist/react/components/DataTable/Pagination.js.map +1 -1
  56. package/dist/react/components/DataTable/SortHeader.d.ts.map +1 -1
  57. package/dist/react/components/DataTable/SortHeader.js +2 -1
  58. package/dist/react/components/DataTable/SortHeader.js.map +1 -1
  59. package/dist/react/components/DataTable/TableFilterBuilder.d.ts +61 -0
  60. package/dist/react/components/DataTable/TableFilterBuilder.d.ts.map +1 -0
  61. package/dist/react/components/DataTable/{FilterBuilder.js โ†’ TableFilterBuilder.js} +26 -3
  62. package/dist/react/components/DataTable/TableFilterBuilder.js.map +1 -0
  63. package/dist/react/components/DataTable/Toolbar.d.ts +1 -1
  64. package/dist/react/components/DataTable/Toolbar.js +3 -3
  65. package/dist/react/components/DataTable/Toolbar.js.map +1 -1
  66. package/dist/react/components/DataTable/cells/LinkCell.d.ts.map +1 -1
  67. package/dist/react/components/DataTable/cells/LinkCell.js +2 -1
  68. package/dist/react/components/DataTable/cells/LinkCell.js.map +1 -1
  69. package/dist/react/components/DataTable/index.d.ts +1 -1
  70. package/dist/react/components/DataTable/index.d.ts.map +1 -1
  71. package/dist/react/components/DataTable/index.js +4 -1
  72. package/dist/react/components/DataTable/index.js.map +1 -1
  73. package/dist/react/components/DragHandle.d.ts.map +1 -1
  74. package/dist/react/components/DragHandle.js +2 -1
  75. package/dist/react/components/DragHandle.js.map +1 -1
  76. package/dist/react/components/EmojiField.d.ts.map +1 -1
  77. package/dist/react/components/EmojiField.js +2 -1
  78. package/dist/react/components/EmojiField.js.map +1 -1
  79. package/dist/react/components/EventTimeline.d.ts +3 -2
  80. package/dist/react/components/EventTimeline.d.ts.map +1 -1
  81. package/dist/react/components/EventTimeline.js +3 -2
  82. package/dist/react/components/EventTimeline.js.map +1 -1
  83. package/dist/react/components/IconButton.d.ts +1 -1
  84. package/dist/react/components/IconButton.js +1 -1
  85. package/dist/react/components/InfoHint.d.ts.map +1 -1
  86. package/dist/react/components/InfoHint.js +5 -4
  87. package/dist/react/components/InfoHint.js.map +1 -1
  88. package/dist/react/components/InheritBadge.js +1 -1
  89. package/dist/react/components/InheritBadge.js.map +1 -1
  90. package/dist/react/components/InlineEditableText.d.ts.map +1 -1
  91. package/dist/react/components/InlineEditableText.js +2 -1
  92. package/dist/react/components/InlineEditableText.js.map +1 -1
  93. package/dist/react/components/MeterList.d.ts.map +1 -1
  94. package/dist/react/components/MeterList.js +2 -1
  95. package/dist/react/components/MeterList.js.map +1 -1
  96. package/dist/react/components/PathText.d.ts +2 -2
  97. package/dist/react/components/PathText.d.ts.map +1 -1
  98. package/dist/react/components/PathText.js +2 -1
  99. package/dist/react/components/PathText.js.map +1 -1
  100. package/dist/react/components/RatingField.d.ts.map +1 -1
  101. package/dist/react/components/RatingField.js +2 -1
  102. package/dist/react/components/RatingField.js.map +1 -1
  103. package/dist/react/components/SecretInput.js +3 -2
  104. package/dist/react/components/SecretInput.js.map +1 -1
  105. package/dist/react/components/SegmentedControl.d.ts.map +1 -1
  106. package/dist/react/components/SegmentedControl.js +2 -1
  107. package/dist/react/components/SegmentedControl.js.map +1 -1
  108. package/dist/react/components/StarRating.d.ts.map +1 -1
  109. package/dist/react/components/StarRating.js +9 -5
  110. package/dist/react/components/StarRating.js.map +1 -1
  111. package/dist/react/components/StatStrip.d.ts.map +1 -1
  112. package/dist/react/components/StatStrip.js +2 -1
  113. package/dist/react/components/StatStrip.js.map +1 -1
  114. package/dist/react/components/StatTile.d.ts.map +1 -1
  115. package/dist/react/components/StatTile.js +3 -2
  116. package/dist/react/components/StatTile.js.map +1 -1
  117. package/dist/react/components/Tabs.d.ts.map +1 -1
  118. package/dist/react/components/Tabs.js +2 -1
  119. package/dist/react/components/Tabs.js.map +1 -1
  120. package/dist/react/components/TruncatedText.d.ts +2 -1
  121. package/dist/react/components/TruncatedText.d.ts.map +1 -1
  122. package/dist/react/components/TruncatedText.js +2 -1
  123. package/dist/react/components/TruncatedText.js.map +1 -1
  124. package/dist/react/components/calendar/MonthGrid.d.ts.map +1 -1
  125. package/dist/react/components/calendar/MonthGrid.js +2 -1
  126. package/dist/react/components/calendar/MonthGrid.js.map +1 -1
  127. package/dist/react/components/calendar/WeekView.d.ts.map +1 -1
  128. package/dist/react/components/calendar/WeekView.js +2 -1
  129. package/dist/react/components/calendar/WeekView.js.map +1 -1
  130. package/dist/react/components/revealOnHover.d.ts.map +1 -1
  131. package/dist/react/components/revealOnHover.js +2 -1
  132. package/dist/react/components/revealOnHover.js.map +1 -1
  133. package/dist/react/file-tree/FileTree.d.ts +50 -1
  134. package/dist/react/file-tree/FileTree.d.ts.map +1 -1
  135. package/dist/react/file-tree/FileTree.js +234 -6
  136. package/dist/react/file-tree/FileTree.js.map +1 -1
  137. package/dist/react/file-tree/fileTree.css +52 -0
  138. package/dist/react/filter-rail/FilterRail.d.ts.map +1 -1
  139. package/dist/react/filter-rail/FilterRail.js +5 -4
  140. package/dist/react/filter-rail/FilterRail.js.map +1 -1
  141. package/dist/react/folder-tree/FolderTreeRail.d.ts.map +1 -1
  142. package/dist/react/folder-tree/FolderTreeRail.js +2 -1
  143. package/dist/react/folder-tree/FolderTreeRail.js.map +1 -1
  144. package/dist/react/index.d.ts +5 -1
  145. package/dist/react/index.d.ts.map +1 -1
  146. package/dist/react/index.js +5 -1
  147. package/dist/react/index.js.map +1 -1
  148. package/dist/react/layoutEngine/index.js +1 -1
  149. package/dist/react/layoutEngine/index.js.map +1 -1
  150. package/dist/react/lib/field.d.ts.map +1 -1
  151. package/dist/react/lib/field.js +3 -2
  152. package/dist/react/lib/field.js.map +1 -1
  153. package/dist/react/lib/floatingStyles.d.ts.map +1 -1
  154. package/dist/react/lib/floatingStyles.js +2 -1
  155. package/dist/react/lib/floatingStyles.js.map +1 -1
  156. package/dist/react/lib/tapTarget.d.ts +96 -0
  157. package/dist/react/lib/tapTarget.d.ts.map +1 -0
  158. package/dist/react/lib/tapTarget.js +96 -0
  159. package/dist/react/lib/tapTarget.js.map +1 -0
  160. package/dist/react/media/VideoTrimmer.d.ts +1 -1
  161. package/dist/react/media/VideoTrimmer.js +1 -1
  162. package/dist/react/media/denseGallery.css +3 -3
  163. package/dist/react/media/ffmpegWasm.js +2 -2
  164. package/dist/react/media/ffmpegWasm.js.map +1 -1
  165. package/dist/react/media/videoPlayer.css +42 -0
  166. package/dist/react/namespace/NamespaceTargetCapsule.d.ts +2 -2
  167. package/dist/react/namespace/NamespaceTargetCapsule.d.ts.map +1 -1
  168. package/dist/react/nav/BreadcrumbTrail.d.ts.map +1 -1
  169. package/dist/react/nav/BreadcrumbTrail.js +4 -3
  170. package/dist/react/nav/BreadcrumbTrail.js.map +1 -1
  171. package/dist/react/nav/HubTileGrid.d.ts.map +1 -1
  172. package/dist/react/nav/HubTileGrid.js +2 -1
  173. package/dist/react/nav/HubTileGrid.js.map +1 -1
  174. package/dist/react/nav/SideNav.d.ts.map +1 -1
  175. package/dist/react/nav/SideNav.js +4 -3
  176. package/dist/react/nav/SideNav.js.map +1 -1
  177. package/dist/react/nav/SideNavCustomize.d.ts.map +1 -1
  178. package/dist/react/nav/SideNavCustomize.js +2 -1
  179. package/dist/react/nav/SideNavCustomize.js.map +1 -1
  180. package/dist/react/palette/CommandPalette.d.ts.map +1 -1
  181. package/dist/react/palette/CommandPalette.js +3 -2
  182. package/dist/react/palette/CommandPalette.js.map +1 -1
  183. package/dist/server/drivers/pooledControlStores.pg.test.js +1 -0
  184. package/dist/server/drivers/pooledControlStores.pg.test.js.map +1 -1
  185. package/dist/server/drivers/pooledIdentityStore.pg.test.js +1 -0
  186. package/dist/server/drivers/pooledIdentityStore.pg.test.js.map +1 -1
  187. package/dist/server/drivers/retentionPolicy.pg.test.js +1 -0
  188. package/dist/server/drivers/retentionPolicy.pg.test.js.map +1 -1
  189. package/dist/server/guard/argon2Binding.d.ts +1 -1
  190. package/dist/server/guard/argon2Binding.js +1 -1
  191. package/dist/server/incidents/store.d.ts +3 -3
  192. package/dist/server/index.js +1 -1
  193. package/dist/server/index.js.map +1 -1
  194. package/dist/server/master-lock/masterLock.d.ts +1 -1
  195. package/dist/server/media-bun/index.js +1 -1
  196. package/dist/server/media-bun/index.js.map +1 -1
  197. package/dist/server/paths/appDataHome.d.ts +20 -0
  198. package/dist/server/paths/appDataHome.d.ts.map +1 -0
  199. package/dist/server/paths/appDataHome.js +69 -0
  200. package/dist/server/paths/appDataHome.js.map +1 -0
  201. package/dist/server/retention/archive.d.ts +3 -4
  202. package/dist/server/retention/archive.d.ts.map +1 -1
  203. package/dist/server/retention/archive.js +20 -15
  204. package/dist/server/retention/archive.js.map +1 -1
  205. package/dist/server/retention/index.d.ts +1 -1
  206. package/dist/server/retention/index.js +1 -1
  207. package/dist/server/retention/policy.d.ts +2 -2
  208. package/dist/server/retention/policy.d.ts.map +1 -1
  209. package/dist/server/retention/policy.js +1 -1
  210. package/dist/server/retention/store.d.ts.map +1 -1
  211. package/dist/server/retention/store.js +27 -20
  212. package/dist/server/retention/store.js.map +1 -1
  213. package/dist/server/runtime/localHost.d.ts +10 -5
  214. package/dist/server/runtime/localHost.d.ts.map +1 -1
  215. package/dist/server/runtime/localHost.js +12 -8
  216. package/dist/server/runtime/localHost.js.map +1 -1
  217. package/dist/server/runtime/meterRollup.pg.test.js +1 -0
  218. package/dist/server/runtime/meterRollup.pg.test.js.map +1 -1
  219. package/dist/server/runtime/recipe.d.ts +4 -4
  220. package/dist/server/runtime/retentionJob.pg.test.js +1 -0
  221. package/dist/server/runtime/retentionJob.pg.test.js.map +1 -1
  222. package/dist/server/search/pgSearchProvider.pg.test.js +1 -0
  223. package/dist/server/search/pgSearchProvider.pg.test.js.map +1 -1
  224. package/dist/shared/errors.d.ts +1 -1
  225. package/dist/shared/errors.js +1 -1
  226. package/dist/styles-static.css +413 -0
  227. package/dist/styles-utilities.css +5074 -0
  228. package/dist/styles.css +49 -0
  229. package/package.json +30 -168
  230. package/scripts/generateStaticStyles.ts +122 -0
  231. package/scripts/generateUtilityStyles.ts +215 -0
  232. package/scripts/publicSurface.ts +455 -0
  233. package/scripts/testTmpRoot.ts +34 -5
  234. package/src/client/index.ts +1 -1
  235. package/src/core/category/index.ts +2 -1
  236. package/src/core/category/types.ts +1 -1
  237. package/src/core/file-tree/fileTreeModel.spec.ts +134 -0
  238. package/src/core/file-tree/fileTreeModel.ts +104 -0
  239. package/src/core/layout/index.ts +1 -1
  240. package/src/core/media/index.ts +1 -1
  241. package/src/core/media/types.ts +1 -1
  242. package/src/core/media/uploadLimits.ts +1 -1
  243. package/src/core/sharing/model.ts +1 -1
  244. package/src/ctgr/index.ts +1 -1
  245. package/src/declaredDepsAreImported.spec.ts +87 -0
  246. package/src/demoFixture.spec.ts +133 -0
  247. package/src/index.ts +1 -1
  248. package/src/lockfileIsTracked.spec.ts +50 -0
  249. package/src/namedSubpathsResolve.spec.ts +119 -0
  250. package/src/publicSurface.spec.ts +72 -0
  251. package/src/react/activity-bar/ActivityBar.tsx +17 -0
  252. package/src/react/analytics/index.ts +1 -1
  253. package/src/react/chat/MessageComposer.tsx +5 -4
  254. package/src/react/components/Button.tsx +3 -2
  255. package/src/react/components/Checkbox.spec.tsx +51 -0
  256. package/src/react/components/Checkbox.tsx +68 -26
  257. package/src/react/components/CodeArea.tsx +2 -1
  258. package/src/react/components/CodeChip.spec.tsx +2 -2
  259. package/src/react/components/Collapsible.tsx +2 -1
  260. package/src/react/components/ComboboxField.tsx +3 -2
  261. package/src/react/components/CopyButton.tsx +2 -1
  262. package/src/react/components/CopyableText.spec.tsx +1 -1
  263. package/src/react/components/DataTable/ColumnChecklist.tsx +2 -1
  264. package/src/react/components/DataTable/Pagination.tsx +2 -1
  265. package/src/react/components/DataTable/SortHeader.tsx +2 -1
  266. package/src/react/components/DataTable/{FilterBuilder.tsx โ†’ TableFilterBuilder.tsx} +33 -5
  267. package/src/react/components/DataTable/Toolbar.tsx +3 -3
  268. package/src/react/components/DataTable/cells/LinkCell.tsx +2 -1
  269. package/src/react/components/DataTable/index.ts +8 -1
  270. package/src/react/components/DragHandle.tsx +2 -1
  271. package/src/react/components/EmojiField.tsx +2 -1
  272. package/src/react/components/EventTimeline.tsx +3 -2
  273. package/src/react/components/FileLocation.spec.tsx +1 -1
  274. package/src/react/components/IconButton.tsx +1 -1
  275. package/src/react/components/InfoHint.tsx +5 -4
  276. package/src/react/components/InheritBadge.tsx +1 -1
  277. package/src/react/components/InlineEditableText.tsx +2 -1
  278. package/src/react/components/MeterList.tsx +2 -1
  279. package/src/react/components/PathText.tsx +4 -3
  280. package/src/react/components/RatingField.tsx +2 -1
  281. package/src/react/components/SecretInput.tsx +3 -3
  282. package/src/react/components/SegmentedControl.tsx +2 -2
  283. package/src/react/components/StarRating.spec.tsx +2 -2
  284. package/src/react/components/StarRating.tsx +9 -5
  285. package/src/react/components/StatStrip.tsx +2 -1
  286. package/src/react/components/StatTile.tsx +3 -3
  287. package/src/react/components/Tabs.spec.tsx +3 -2
  288. package/src/react/components/Tabs.tsx +2 -1
  289. package/src/react/components/TruncatedText.tsx +2 -1
  290. package/src/react/components/calendar/MonthGrid.spec.tsx +2 -1
  291. package/src/react/components/calendar/MonthGrid.tsx +2 -1
  292. package/src/react/components/calendar/WeekView.tsx +2 -1
  293. package/src/react/components/revealOnHover.ts +3 -2
  294. package/src/react/file-tree/FileTree.spec.tsx +248 -0
  295. package/src/react/file-tree/FileTree.tsx +304 -4
  296. package/src/react/file-tree/fileTree.css +52 -0
  297. package/src/react/file-tree/fileTreeGeometry.fixture.json +151 -0
  298. package/src/react/file-tree/fileTreeGeometry.spec.ts +33 -52
  299. package/src/react/filter-rail/FilterRail.spec.tsx +2 -1
  300. package/src/react/filter-rail/FilterRail.tsx +5 -4
  301. package/src/react/folder-tree/FolderTreeRail.tsx +2 -1
  302. package/src/react/index.ts +13 -3
  303. package/src/react/layoutEngine/index.ts +1 -1
  304. package/src/react/layoutEngine/types.ts +1 -1
  305. package/src/react/lib/field.ts +4 -2
  306. package/src/react/lib/floatingStyles.spec.ts +2 -1
  307. package/src/react/lib/floatingStyles.ts +3 -1
  308. package/src/react/lib/tapTarget.ts +100 -0
  309. package/src/react/media/MaskPainter.tsx +2 -2
  310. package/src/react/media/VideoTrimmer.tsx +1 -1
  311. package/src/react/media/denseGallery.css +3 -3
  312. package/src/react/media/ffmpegWasm.ts +2 -2
  313. package/src/react/media/videoPlayer.css +42 -0
  314. package/src/react/namespace/NamespaceTargetCapsule.tsx +2 -2
  315. package/src/react/nav/BreadcrumbTrail.tsx +4 -3
  316. package/src/react/nav/HubTileGrid.tsx +2 -1
  317. package/src/react/nav/SideNav.tsx +4 -3
  318. package/src/react/nav/SideNavCustomize.tsx +2 -1
  319. package/src/react/palette/CommandPalette.tsx +3 -2
  320. package/src/server/ctgr.ts +1 -1
  321. package/src/server/drivers/pooledControlStores.pg.test.ts +1 -0
  322. package/src/server/drivers/pooledIdentityStore.pg.test.ts +1 -0
  323. package/src/server/drivers/retentionPolicy.pg.test.ts +1 -0
  324. package/src/server/guard/argon2Binding.ts +1 -1
  325. package/src/server/incidents/store.ts +3 -3
  326. package/src/server/index.ts +1 -1
  327. package/src/server/master-lock/masterLock.spec.ts +18 -2
  328. package/src/server/master-lock/masterLock.ts +1 -1
  329. package/src/server/media-bun/image.spec.ts +1 -0
  330. package/src/server/media-bun/index.ts +1 -1
  331. package/src/server/media-bun/video.spec.ts +1 -0
  332. package/src/server/paths/appDataHome.spec.ts +87 -0
  333. package/src/server/paths/appDataHome.ts +84 -0
  334. package/src/server/retention/archive.spec.ts +26 -4
  335. package/src/server/retention/archive.ts +20 -15
  336. package/src/server/retention/index.ts +1 -1
  337. package/src/server/retention/policy.ts +2 -2
  338. package/src/server/retention/store.spec.ts +38 -10
  339. package/src/server/retention/store.ts +26 -19
  340. package/src/server/runtime/localHost.spec.ts +22 -3
  341. package/src/server/runtime/localHost.ts +12 -9
  342. package/src/server/runtime/meterRollup.pg.test.ts +1 -0
  343. package/src/server/runtime/recipe.ts +4 -4
  344. package/src/server/runtime/retentionJob.pg.test.ts +1 -0
  345. package/src/server/search/pgSearchProvider.pg.test.ts +1 -0
  346. package/src/server/storage/binaryServerProcessing.integration.spec.ts +6 -2
  347. package/src/server/storage/chunked.integration.spec.ts +5 -2
  348. package/src/server/storage/fileUploadClient-chunked.integration.spec.ts +5 -2
  349. package/src/server/storage/files/adapter.photo.display.spec.ts +1 -0
  350. package/src/server/storage/imageThumbnail.spec.ts +1 -0
  351. package/src/server/storage/transcode.integration.spec.ts +5 -2
  352. package/src/server/storage/videoProcessor.posterOnly.spec.ts +1 -0
  353. package/src/shared/errors.ts +1 -1
  354. package/src/skippedTestsAreAnswered.spec.ts +215 -0
  355. package/src/styles-static.css +413 -0
  356. package/src/styles-utilities.css +5074 -0
  357. package/src/styles.css +49 -0
  358. package/src/stylesStaticMatches.spec.ts +134 -0
  359. package/src/stylesUtilitiesMatches.spec.ts +314 -0
  360. package/src/tapTargetStylesheet.spec.ts +150 -0
  361. package/src/testTmpRoot.spec.ts +102 -0
  362. package/dist/core/duplicates/index.d.ts +0 -116
  363. package/dist/core/duplicates/index.d.ts.map +0 -1
  364. package/dist/core/duplicates/index.js +0 -178
  365. package/dist/core/duplicates/index.js.map +0 -1
  366. package/dist/core/namespace/helpers.d.ts +0 -14
  367. package/dist/core/namespace/helpers.d.ts.map +0 -1
  368. package/dist/core/namespace/helpers.js +0 -29
  369. package/dist/core/namespace/helpers.js.map +0 -1
  370. package/dist/core/namespace/index.d.ts +0 -4
  371. package/dist/core/namespace/index.d.ts.map +0 -1
  372. package/dist/core/namespace/index.js +0 -6
  373. package/dist/core/namespace/index.js.map +0 -1
  374. package/dist/core/namespace/memoryStore.d.ts +0 -19
  375. package/dist/core/namespace/memoryStore.d.ts.map +0 -1
  376. package/dist/core/namespace/memoryStore.js +0 -70
  377. package/dist/core/namespace/memoryStore.js.map +0 -1
  378. package/dist/core/namespace/types.d.ts +0 -44
  379. package/dist/core/namespace/types.d.ts.map +0 -1
  380. package/dist/core/namespace/types.js +0 -8
  381. package/dist/core/namespace/types.js.map +0 -1
  382. package/dist/game/core/DisposeRegistry.d.ts +0 -42
  383. package/dist/game/core/DisposeRegistry.d.ts.map +0 -1
  384. package/dist/game/core/DisposeRegistry.js +0 -67
  385. package/dist/game/core/DisposeRegistry.js.map +0 -1
  386. package/dist/game/core/drawBudget.d.ts +0 -26
  387. package/dist/game/core/drawBudget.d.ts.map +0 -1
  388. package/dist/game/core/drawBudget.js +0 -55
  389. package/dist/game/core/drawBudget.js.map +0 -1
  390. package/dist/game/core/fixedTimestep.d.ts +0 -38
  391. package/dist/game/core/fixedTimestep.d.ts.map +0 -1
  392. package/dist/game/core/fixedTimestep.js +0 -47
  393. package/dist/game/core/fixedTimestep.js.map +0 -1
  394. package/dist/game/core/index.d.ts +0 -9
  395. package/dist/game/core/index.d.ts.map +0 -1
  396. package/dist/game/core/index.js +0 -8
  397. package/dist/game/core/index.js.map +0 -1
  398. package/dist/game/core/inputCollector.d.ts +0 -82
  399. package/dist/game/core/inputCollector.d.ts.map +0 -1
  400. package/dist/game/core/inputCollector.js +0 -176
  401. package/dist/game/core/inputCollector.js.map +0 -1
  402. package/dist/game/core/resizeCanvas.d.ts +0 -19
  403. package/dist/game/core/resizeCanvas.d.ts.map +0 -1
  404. package/dist/game/core/resizeCanvas.js +0 -29
  405. package/dist/game/core/resizeCanvas.js.map +0 -1
  406. package/dist/game/react/index.d.ts +0 -3
  407. package/dist/game/react/index.d.ts.map +0 -1
  408. package/dist/game/react/index.js +0 -5
  409. package/dist/game/react/index.js.map +0 -1
  410. package/dist/game/react/useGameEngine.d.ts +0 -64
  411. package/dist/game/react/useGameEngine.d.ts.map +0 -1
  412. package/dist/game/react/useGameEngine.js +0 -78
  413. package/dist/game/react/useGameEngine.js.map +0 -1
  414. package/dist/react/canvas/CanvasNavHUD.d.ts +0 -64
  415. package/dist/react/canvas/CanvasNavHUD.d.ts.map +0 -1
  416. package/dist/react/canvas/CanvasNavHUD.js +0 -58
  417. package/dist/react/canvas/CanvasNavHUD.js.map +0 -1
  418. package/dist/react/canvas/fitLabel.d.ts +0 -53
  419. package/dist/react/canvas/fitLabel.d.ts.map +0 -1
  420. package/dist/react/canvas/fitLabel.js +0 -104
  421. package/dist/react/canvas/fitLabel.js.map +0 -1
  422. package/dist/react/canvas/index.d.ts +0 -4
  423. package/dist/react/canvas/index.d.ts.map +0 -1
  424. package/dist/react/canvas/index.js +0 -4
  425. package/dist/react/canvas/index.js.map +0 -1
  426. package/dist/react/canvas/lod.d.ts +0 -40
  427. package/dist/react/canvas/lod.d.ts.map +0 -1
  428. package/dist/react/canvas/lod.js +0 -37
  429. package/dist/react/canvas/lod.js.map +0 -1
  430. package/dist/react/components/DataTable/FilterBuilder.d.ts +0 -38
  431. package/dist/react/components/DataTable/FilterBuilder.d.ts.map +0 -1
  432. package/dist/react/components/DataTable/FilterBuilder.js.map +0 -1
  433. package/dist/react/seo/HeadProvider.d.ts +0 -14
  434. package/dist/react/seo/HeadProvider.d.ts.map +0 -1
  435. package/dist/react/seo/HeadProvider.js +0 -44
  436. package/dist/react/seo/HeadProvider.js.map +0 -1
  437. package/dist/react/seo/applyHeadToDocument.d.ts +0 -3
  438. package/dist/react/seo/applyHeadToDocument.d.ts.map +0 -1
  439. package/dist/react/seo/applyHeadToDocument.js +0 -66
  440. package/dist/react/seo/applyHeadToDocument.js.map +0 -1
  441. package/dist/react/seo/index.d.ts +0 -3
  442. package/dist/react/seo/index.d.ts.map +0 -1
  443. package/dist/react/seo/index.js +0 -7
  444. package/dist/react/seo/index.js.map +0 -1
  445. package/dist/react/timeline/ClipView.d.ts +0 -29
  446. package/dist/react/timeline/ClipView.d.ts.map +0 -1
  447. package/dist/react/timeline/ClipView.js +0 -53
  448. package/dist/react/timeline/ClipView.js.map +0 -1
  449. package/dist/react/timeline/Playhead.d.ts +0 -16
  450. package/dist/react/timeline/Playhead.d.ts.map +0 -1
  451. package/dist/react/timeline/Playhead.js +0 -26
  452. package/dist/react/timeline/Playhead.js.map +0 -1
  453. package/dist/react/timeline/TimeRuler.d.ts +0 -21
  454. package/dist/react/timeline/TimeRuler.d.ts.map +0 -1
  455. package/dist/react/timeline/TimeRuler.js +0 -31
  456. package/dist/react/timeline/TimeRuler.js.map +0 -1
  457. package/dist/react/timeline/TimelineSurface.d.ts +0 -29
  458. package/dist/react/timeline/TimelineSurface.d.ts.map +0 -1
  459. package/dist/react/timeline/TimelineSurface.js +0 -56
  460. package/dist/react/timeline/TimelineSurface.js.map +0 -1
  461. package/dist/react/timeline/TrackLane.d.ts +0 -31
  462. package/dist/react/timeline/TrackLane.d.ts.map +0 -1
  463. package/dist/react/timeline/TrackLane.js +0 -32
  464. package/dist/react/timeline/TrackLane.js.map +0 -1
  465. package/dist/react/timeline/index.d.ts +0 -6
  466. package/dist/react/timeline/index.d.ts.map +0 -1
  467. package/dist/react/timeline/index.js +0 -12
  468. package/dist/react/timeline/index.js.map +0 -1
  469. package/dist/server/private-media/index.d.ts +0 -7
  470. package/dist/server/private-media/index.d.ts.map +0 -1
  471. package/dist/server/private-media/index.js +0 -13
  472. package/dist/server/private-media/index.js.map +0 -1
  473. package/dist/server/seo/index.d.ts +0 -3
  474. package/dist/server/seo/index.d.ts.map +0 -1
  475. package/dist/server/seo/index.js +0 -6
  476. package/dist/server/seo/index.js.map +0 -1
  477. package/dist/server/seo/mountSeoRoutes.d.ts +0 -9
  478. package/dist/server/seo/mountSeoRoutes.d.ts.map +0 -1
  479. package/dist/server/seo/mountSeoRoutes.js +0 -19
  480. package/dist/server/seo/mountSeoRoutes.js.map +0 -1
  481. package/dist/server/seo/serveHeadInjectedIndex.d.ts +0 -9
  482. package/dist/server/seo/serveHeadInjectedIndex.d.ts.map +0 -1
  483. package/dist/server/seo/serveHeadInjectedIndex.js +0 -20
  484. package/dist/server/seo/serveHeadInjectedIndex.js.map +0 -1
  485. package/dist/upload.d.ts +0 -148
  486. package/dist/upload.d.ts.map +0 -1
  487. package/dist/upload.js +0 -159
  488. package/dist/upload.js.map +0 -1
  489. package/dist/verify/runtime/index.d.ts +0 -16
  490. package/dist/verify/runtime/index.d.ts.map +0 -1
  491. package/dist/verify/runtime/index.js +0 -16
  492. package/dist/verify/runtime/index.js.map +0 -1
  493. package/scripts/demoCheck.ts +0 -42
  494. package/src/core/duplicates/index.spec.ts +0 -116
  495. package/src/core/duplicates/index.ts +0 -203
  496. package/src/core/namespace/helpers.ts +0 -31
  497. package/src/core/namespace/index.ts +0 -12
  498. package/src/core/namespace/memoryStore.ts +0 -77
  499. package/src/core/namespace/namespace.spec.ts +0 -117
  500. package/src/core/namespace/types.ts +0 -53
  501. package/src/game/core/DisposeRegistry.spec.ts +0 -53
  502. package/src/game/core/DisposeRegistry.ts +0 -70
  503. package/src/game/core/drawBudget.spec.ts +0 -51
  504. package/src/game/core/drawBudget.ts +0 -75
  505. package/src/game/core/fixedTimestep.spec.ts +0 -91
  506. package/src/game/core/fixedTimestep.ts +0 -79
  507. package/src/game/core/index.ts +0 -16
  508. package/src/game/core/inputCollector.spec.ts +0 -29
  509. package/src/game/core/inputCollector.ts +0 -245
  510. package/src/game/core/resizeCanvas.ts +0 -31
  511. package/src/game/react/index.ts +0 -10
  512. package/src/game/react/useGameEngine.ts +0 -125
  513. package/src/react/canvas/CanvasNavHUD.spec.tsx +0 -62
  514. package/src/react/canvas/CanvasNavHUD.tsx +0 -210
  515. package/src/react/canvas/fitLabel.spec.ts +0 -82
  516. package/src/react/canvas/fitLabel.ts +0 -150
  517. package/src/react/canvas/index.ts +0 -15
  518. package/src/react/canvas/lod.ts +0 -53
  519. package/src/react/seo/HeadProvider.tsx +0 -67
  520. package/src/react/seo/applyHeadToDocument.ts +0 -73
  521. package/src/react/seo/index.ts +0 -12
  522. package/src/react/seo/seo.spec.tsx +0 -101
  523. package/src/react/timeline/ClipView.tsx +0 -146
  524. package/src/react/timeline/Playhead.tsx +0 -63
  525. package/src/react/timeline/TimeRuler.tsx +0 -85
  526. package/src/react/timeline/TimelineSurface.tsx +0 -157
  527. package/src/react/timeline/TrackLane.tsx +0 -87
  528. package/src/react/timeline/index.ts +0 -12
  529. package/src/react/timeline/timeline.spec.tsx +0 -175
  530. package/src/server/private-media/index.ts +0 -45
  531. package/src/server/seo/index.ts +0 -8
  532. package/src/server/seo/mountSeoRoutes.ts +0 -37
  533. package/src/server/seo/seo.spec.ts +0 -128
  534. package/src/server/seo/serveHeadInjectedIndex.ts +0 -36
  535. package/src/upload.spec.ts +0 -300
  536. package/src/upload.ts +0 -288
  537. package/src/verify/runtime/index.ts +0 -64
package/src/styles.css CHANGED
@@ -5,6 +5,55 @@
5
5
  * @import "cursedbelt/theme.css";
6
6
  * This `@source` makes Tailwind v4 scan cursedbelt's source files so the utility
7
7
  * classes used by its components are generated in the app's stylesheet.
8
+ *
9
+ * โ”€โ”€ Two ways in, and which one an app wants โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
10
+ * `@source "."` is the expensive half: it points Tailwind's JIT at cursedbelt's
11
+ * ENTIRE source tree, so the app emits the union of the whole design system
12
+ * whether it renders three components or eighty, and its own build walks 827
13
+ * files it does not own. Everything else in this file is CSS the components
14
+ * genuinely need and no app can do without.
15
+ *
16
+ * A CSS `@import` takes the whole file, so the split is two more subpaths:
17
+ *
18
+ * cursedbelt/styles.css this file โ€” the real CSS + the `@source` scan
19
+ * cursedbelt/styles-static.css the same file MINUS the `@source` line
20
+ * cursedbelt/styles-utilities.css the utilities that `@source` line would have
21
+ * produced, precompiled at cursedbelt's build
22
+ *
23
+ * The second two are a PAIR and neither is usable alone โ€” `styles-static.css` on
24
+ * its own gets the tooltip pointer-events fix, the Progress keyframes, the
25
+ * lightbox bridge, the ambient/glass layer and `tw-animate-css`, and emits none
26
+ * of cursedbelt's utility classes, i.e. an unstyled app:
27
+ *
28
+ * @import "tailwindcss";
29
+ * @import "cursedbelt/styles-static.css";
30
+ * @import "cursedbelt/styles-utilities.css";
31
+ * @import "cursedbelt/theme.css";
32
+ *
33
+ * ๐Ÿ”ด Do NOT hand-list cursedbelt's component files to get the utilities back.
34
+ * Tailwind v4 resolves every `@source` to a DIRECTORY and scans it recursively โ€”
35
+ * a file path and a glob are both silently widened to their parent โ€” and
36
+ * `VirtualList`/`VirtualCardGrid` live at the root of `src/react/`, so the finest
37
+ * grain an app can write is the whole design system. A relative `@source` reaching
38
+ * into this package's source tree is also a `file:` dependency wearing a
39
+ * stylesheet's clothes, and it buys nothing: it is the thing the previous
40
+ * generation's 29-line-per-app arrangement is remembered for, and those 29 lines
41
+ * were never file-level scoping either.
42
+ *
43
+ * The pair is not SMALLER than this file โ€” measured, both routes emit the same
44
+ * rules within 54 bytes. What it buys is a build that scans nothing of another
45
+ * package's source tree, and a `styles-static.css` that finally has a correct
46
+ * use. The measurements, and what would actually shrink a consumer, are in the
47
+ * header of `scripts/generateUtilityStyles.ts`.
48
+ *
49
+ * ๐Ÿ”ด This header is in BOTH of the first two files, because one is generated from
50
+ * the other and a test holds them byte-identical apart from the `@source` line.
51
+ * Always edit `src/styles.css`; never `src/styles-static.css`, which
52
+ * `scripts/generateStaticStyles.ts` rewrites on every `bun run build` and
53
+ * `src/stylesStaticMatches.spec.ts` fails on when it is stale. Editing this file
54
+ * invalidates `src/styles-utilities.css` too โ€” it is compiled against the static
55
+ * variant, `scripts/generateUtilityStyles.ts` rewrites it in the same build step,
56
+ * and `src/stylesUtilitiesMatches.spec.ts` is what fails when it is stale.
8
57
  */
9
58
 
10
59
  /* Animation utilities (animate-in/out, fade/zoom/slide-in-from-*) consumed by the
@@ -0,0 +1,134 @@
1
+ /**
2
+ * `src/styles-static.css` is `src/styles.css` minus its `@source` line โ€” and
3
+ * nothing else (2026-09-14).
4
+ *
5
+ * ## What this exists to prevent
6
+ *
7
+ * The scoped entry point has to be a SECOND FILE, because a CSS `@import` takes
8
+ * the whole of the one it is given: an app cannot ask for `styles.css` without
9
+ * `@source "."`, and `@source "."` is what makes every consumer emit the union
10
+ * of the entire design system.
11
+ *
12
+ * The previous generation's second file was `satellite-kit/styles/belt-static.css`
13
+ * โ€” a hand-kept copy with the one line deleted and nothing comparing the two.
14
+ * That is a file that drifts, and drifts SILENTLY: the day someone adds a rule to
15
+ * `styles.css` and not to the copy, every scoped app quietly loses it. The loss is
16
+ * invisible in review (the diff looks complete), invisible to `tsc` (it is CSS),
17
+ * and invisible to Biome (nothing is wrong with either file). It shows up as a
18
+ * tooltip eating a click, or a Progress bar that never animates, in one app, weeks
19
+ * later.
20
+ *
21
+ * So the copy is OUTPUT โ€” `scripts/generateStaticStyles.ts`, which `bun run build`
22
+ * runs before it compiles โ€” and this spec is the gate that makes that true rather
23
+ * than merely intended. `bun run verify` builds before it tests, so a forgotten
24
+ * regeneration self-heals there; editing `styles.css` and running `bun test src`
25
+ * alone is where this goes red.
26
+ *
27
+ * The assertions deliberately come at it from both sides: one compares the file on
28
+ * disk to what the generator produces (is the checked-in output current?), and the
29
+ * rest compare it to `styles.css` DIRECTLY (is the generator still doing only what
30
+ * it claims?). A spec that only asked the generator to agree with itself would pass
31
+ * a generator that had started dropping real rules.
32
+ *
33
+ * ๐Ÿ”ด `Bun.file`, NOT node:fs โ€” this package's test preload virtualizes node:fs, so
34
+ * a `readFileSync` here would read MOCK data and pass against files it never
35
+ * opened. Same trap as `src/publishShape.spec.ts`; see its header.
36
+ */
37
+ import { describe, expect, it } from 'bun:test';
38
+ import pkg from '../package.json';
39
+ import {
40
+ REPO_ROOT,
41
+ SOURCE_DIRECTIVE,
42
+ STATIC_STYLESHEET,
43
+ readStylesheets,
44
+ staticStylesFrom,
45
+ } from '../scripts/generateStaticStyles';
46
+
47
+ const { source, expected, onDisk } = await readStylesheets();
48
+
49
+ /** The command every failure below is fixed by, as a line the owner can paste. */
50
+ const REGENERATE = `cd ${REPO_ROOT} && bun run styles:static`;
51
+
52
+ const lines = (css: string): string[] => css.split('\n');
53
+ const directives = (css: string): string[] => lines(css).filter((l) => SOURCE_DIRECTIVE.test(l));
54
+
55
+ describe('styles-static.css is a generated, gated copy of styles.css', () => {
56
+ it('is checked in and byte-identical to what the generator produces', () => {
57
+ expect(onDisk, `${STATIC_STYLESHEET} is missing. It is generated:\n ${REGENERATE}`).not.toBeNull();
58
+ expect(
59
+ onDisk,
60
+ `${STATIC_STYLESHEET} is stale โ€” src/styles.css changed and the static variant was not\n` +
61
+ 'regenerated, so every app importing `cursedbelt/styles-static.css` is missing the\n' +
62
+ `difference. Run:\n ${REGENERATE}`,
63
+ ).toBe(expected);
64
+ });
65
+
66
+ it('drops the `@source` line and keeps every other line, in order', () => {
67
+ // The independent half: compared against styles.css itself, not against the
68
+ // generator's output. Blank lines are excluded from the sequence check only
69
+ // because the dropped directive takes its trailing blank line with it; the
70
+ // exact line-count assertion below is what pins that down.
71
+ const kept = lines(source).filter((l) => l.trim() !== '' && !SOURCE_DIRECTIVE.test(l));
72
+ expect(lines(expected).filter((l) => l.trim() !== '')).toEqual(kept);
73
+ });
74
+
75
+ it('removes exactly the directive and the blank line it leaves behind', () => {
76
+ expect(
77
+ directives(source),
78
+ 'src/styles.css must carry exactly the one `@source "."` this whole split is about',
79
+ ).toEqual(['@source ".";']);
80
+ expect(directives(expected), 'the static variant must carry no `@source` at all').toEqual([]);
81
+ // 2 = the directive + the now-orphaned blank line after it. A third line
82
+ // going missing means the transform grew a second job.
83
+ expect(lines(source).length - lines(expected).length).toBe(2);
84
+ });
85
+
86
+ it('is not a pointless duplicate', () => {
87
+ // If `@source "."` ever leaves styles.css, the two files become identical and
88
+ // the static subpath is dead weight โ€” but worse, the FULL entry point has
89
+ // stopped scanning and every consuming app emits no cursedbelt utilities.
90
+ expect(expected).not.toBe(source);
91
+ });
92
+
93
+ it('is exported as a subpath that resolves into a directory `files` ships', () => {
94
+ const exports = (pkg as { exports: Record<string, unknown> }).exports;
95
+ expect(exports['./styles-static.css']).toBe(`./${STATIC_STYLESHEET}`);
96
+ // It must resolve out of `src/`, exactly like its sibling: `./styles.css`
97
+ // points at the SOURCE tree (not dist) because `@source "."` has to resolve
98
+ // relative to the files it is meant to scan, and a pair of app-facing
99
+ // stylesheets served from two different directories is a difference nobody
100
+ // can see in CSS.
101
+ expect(exports['./styles.css']).toBe('./src/styles.css');
102
+ // `files` ships whole directories, so `src` is what actually puts both of
103
+ // them in the tarball. publishShape.spec.ts proves the general rule; this is
104
+ // the one line that makes THIS subpath's failure legible.
105
+ expect((pkg as { files: string[] }).files).toContain('src');
106
+ });
107
+
108
+ it('resolves as `cursedbelt/styles-static.css` through the real resolver', () => {
109
+ // The assertions above read the manifest; this one RESOLVES the specifier the
110
+ // way a consumer's bundler does, through the package's own `exports` map (bun
111
+ // honours a self-reference by package name). An export entry pointing at a
112
+ // path that does not exist satisfies every string comparison in this file and
113
+ // fails here โ€” which is the failure `belt-static.css` would have been.
114
+ expect(Bun.resolveSync(`${pkg.name}/styles-static.css`, REPO_ROOT)).toBe(
115
+ `${REPO_ROOT}/${STATIC_STYLESHEET}`,
116
+ );
117
+ });
118
+
119
+ it('is regenerated by the build, so a stale copy cannot be published', () => {
120
+ // `prepublishOnly` โ†’ `verify` โ†’ `build`, so the tarball's copy is always the
121
+ // one this repo's current styles.css produces. Without this step in `build`,
122
+ // the only thing standing between a drifted copy and a publish is a person
123
+ // remembering to run a script.
124
+ expect((pkg as { scripts: Record<string, string> }).scripts.build).toContain(
125
+ 'scripts/generateStaticStyles.ts',
126
+ );
127
+ });
128
+
129
+ it('exposes the transform as a pure function', () => {
130
+ // Cheap guard on the one behaviour every assertion above leans on.
131
+ expect(staticStylesFrom('a\n@source ".";\n\nb\n')).toBe('a\nb\n');
132
+ expect(staticStylesFrom('a\nb\n')).toBe('a\nb\n');
133
+ });
134
+ });
@@ -0,0 +1,314 @@
1
+ /**
2
+ * `src/styles-utilities.css` is a current, COMPLETE precompile of `src/react/**`
3
+ * (2026-09-14).
4
+ *
5
+ * ## What this exists to prevent
6
+ *
7
+ * The artifact replaces a `@source` scan the consuming app used to run. The scan
8
+ * was self-healing โ€” it read whatever was in `src/react` at the app's build time โ€”
9
+ * and the artifact is not: it is a file, generated once here, and every app that
10
+ * imports it gets exactly what was checked in.
11
+ *
12
+ * Its failure mode is SILENT and it is the worst one available. A stale artifact
13
+ * is missing the utilities a new component uses, so that component renders
14
+ * unstyled in every app; a collapsed scan writes an empty utility layer, so the
15
+ * WHOLE app renders unstyled. Neither is visible to `tsc` (it is CSS), to Biome
16
+ * (nothing is wrong with the file), or to a byte count read in one direction (a
17
+ * smaller stylesheet is the thing the split was asked for).
18
+ *
19
+ * So the assertions below do not compare size. They compile a consuming app BOTH
20
+ * ways โ€” `@import "cursedbelt/styles.css"` (today, scanning) against
21
+ * `styles-static.css` + `styles-utilities.css` with `source(none)` (after
22
+ * adoption, scanning nothing) โ€” and compare the rules that come out: every
23
+ * selector, every declaration, every custom property the declarations reference.
24
+ * `scripts/generateUtilityStyles.ts` owns the WHY and the measurements; this file
25
+ * is the WHETHER.
26
+ *
27
+ * Two differences between the two routes are real, deliberate and normalised for
28
+ * below rather than papered over โ€” each is asserted to STILL BE the only one of
29
+ * its kind, so the normalisation cannot quietly widen into an amnesty:
30
+ *
31
+ * ยท `var(--x)` on the scanning route vs `var(--x, <literal>)` on the
32
+ * precompiled one, for tokens that reach the compiler through `@reference`.
33
+ * Same variable, same computed value, plus a fallback.
34
+ * ยท `@theme inline` alias declarations (`--color-card: var(--card)`) that the
35
+ * scanning route emits into `:root` and nothing ever reads โ€” `inline` means
36
+ * the utility itself carries `var(--card)`, so the alias is bookkeeping. Only
37
+ * custom properties something actually `var()`s are compared.
38
+ *
39
+ * `Bun.file` for every read here, not node:fs โ€” the convention the sibling specs
40
+ * (`src/publishShape.spec.ts`, `src/declaredDepsAreImported.spec.ts`) state and
41
+ * the reason they give: a spec that reads through a mockable builtin can pass
42
+ * against files it never opened. The Tailwind compiler this file drives does use
43
+ * node:fs internally, which is unavoidable and is the point โ€” it is resolving the
44
+ * same `@import`s a consumer's bundler will.
45
+ */
46
+ import { describe, expect, it } from 'bun:test';
47
+ import pkg from '../package.json';
48
+ import {
49
+ CONSUMER_PRECOMPILED,
50
+ CONSUMER_SCANNING,
51
+ MIN_CANDIDATES,
52
+ REPO_ROOT,
53
+ UTILITY_STYLESHEET,
54
+ compileStylesheet,
55
+ readUtilityStylesheet,
56
+ } from '../scripts/generateUtilityStyles';
57
+
58
+ const { expected, onDisk, candidates } = await readUtilityStylesheet();
59
+
60
+ /** The command every staleness failure below is fixed by, as a line the owner can paste. */
61
+ const REGENERATE = `cd ${REPO_ROOT} && bun run styles:utilities`;
62
+
63
+ /**
64
+ * Flatten a stylesheet into `at-rule โ€– โ€ฆ โ€– selector` โ†’ the set of declarations in
65
+ * that block, merging blocks that repeat (both routes emit `@keyframes spin`
66
+ * twice; a consumer's browser does not care, and neither should a comparison).
67
+ *
68
+ * A hand-rolled walk rather than a CSS parser because the only input is Tailwind's
69
+ * own output: well-formed, and the one construct that could confuse brace counting
70
+ * โ€” a `{` inside a string or a comment โ€” is skipped explicitly.
71
+ */
72
+ const flatten = (css: string): Map<string, Set<string>> => {
73
+ const out = new Map<string, Set<string>>();
74
+ const stack: string[] = [];
75
+ const open: string[][] = [[]];
76
+ let buf = '';
77
+ const push = (raw: string): void => {
78
+ const decl = raw.trim();
79
+ if (decl) open[open.length - 1]?.push(decl);
80
+ };
81
+ for (let i = 0; i < css.length; i++) {
82
+ const ch = css[i];
83
+ if (ch === '/' && css[i + 1] === '*') {
84
+ i = css.indexOf('*/', i) + 1;
85
+ continue;
86
+ }
87
+ if (ch === '"' || ch === "'") {
88
+ const end = css.indexOf(ch, i + 1);
89
+ buf += css.slice(i, end + 1);
90
+ i = end;
91
+ continue;
92
+ }
93
+ if (ch === '{') {
94
+ stack.push(buf.trim().replace(/\s+/g, ' '));
95
+ buf = '';
96
+ open.push([]);
97
+ continue;
98
+ }
99
+ if (ch === '}') {
100
+ push(buf);
101
+ buf = '';
102
+ const key = stack.join(' โ€– ');
103
+ const set = out.get(key) ?? new Set<string>();
104
+ for (const decl of open.pop() ?? []) set.add(decl);
105
+ out.set(key, set);
106
+ stack.pop();
107
+ continue;
108
+ }
109
+ // At depth 0 a `;` ends a statement at-rule (`@layer a, b;`, `@import โ€ฆ`),
110
+ // which carries no declarations and must not stick to the next selector.
111
+ if (ch === ';') {
112
+ if (stack.length) push(buf);
113
+ buf = '';
114
+ continue;
115
+ }
116
+ buf += ch;
117
+ }
118
+ return out;
119
+ };
120
+
121
+ /** `var(--x, <anything>)` โ†’ `var(--x)`, so a fallback reads as the same declaration. */
122
+ const dropFallbacks = (decl: string): string => decl.replace(/var\((\s*--[\w-]+)[^)]*\)/g, 'var($1)');
123
+
124
+ const CUSTOM_PROPERTY = /^(--[\w-]+)\s*:/;
125
+
126
+ /** Every custom property a stylesheet actually reads through `var()`. */
127
+ const referenced = (css: string): Set<string> => {
128
+ const out = new Set<string>();
129
+ for (const m of css.matchAll(/var\(\s*(--[\w-]+)/g)) out.add(m[1] as string);
130
+ return out;
131
+ };
132
+
133
+ /** Every custom property a stylesheet declares, including `@property` registrations. */
134
+ const declared = (css: string): Set<string> => {
135
+ const out = new Set<string>();
136
+ for (const m of css.matchAll(/(?:^|[;{\s])(--[\w-]+)\s*:/g)) out.add(m[1] as string);
137
+ for (const m of css.matchAll(/@property\s+(--[\w-]+)/g)) out.add(m[1] as string);
138
+ return out;
139
+ };
140
+
141
+ // The two routes, compiled from the SAME candidate list (the classes cursedbelt's
142
+ // components use), so neither side is credited with utilities the other was never
143
+ // asked for. The precompiled route is built with no candidates at all: everything
144
+ // it emits came out of the artifact on disk.
145
+ const scanning = (await compileStylesheet(CONSUMER_SCANNING)).build(candidates);
146
+ const precompiled = (await compileStylesheet(CONSUMER_PRECOMPILED)).build([]);
147
+ const before = flatten(scanning);
148
+ const after = flatten(precompiled);
149
+ /** Hoisted: both loops below ask this per declaration, over 160 KB of CSS. */
150
+ const readByScanning = referenced(scanning);
151
+
152
+ describe('styles-utilities.css is a generated, gated precompile of src/react', () => {
153
+ it('is checked in and byte-identical to what the generator produces', () => {
154
+ expect(onDisk, `${UTILITY_STYLESHEET} is missing. It is generated:\n ${REGENERATE}`).not.toBeNull();
155
+ expect(
156
+ onDisk,
157
+ `${UTILITY_STYLESHEET} is stale โ€” src/react (or src/styles.css, which it is compiled\n` +
158
+ 'against) changed and the artifact was not regenerated, so every app importing\n' +
159
+ `\`cursedbelt/styles-utilities.css\` is missing the difference. Run:\n ${REGENERATE}`,
160
+ ).toBe(expected);
161
+ });
162
+
163
+ it('was compiled from a scan that did not collapse', () => {
164
+ // The generator throws below its own floor; this is the assertion that says
165
+ // what the floor is FOR, and it fails here rather than at publish time.
166
+ expect(candidates.length).toBeGreaterThanOrEqual(MIN_CANDIDATES);
167
+ });
168
+
169
+ it('has compiled two real consumer stylesheets to compare', () => {
170
+ // Guards every assertion below: two empty strings agree about everything.
171
+ expect(before.size).toBeGreaterThan(500);
172
+ expect(after.size).toBeGreaterThan(500);
173
+ });
174
+
175
+ it('emits every rule the `@source` scan emits, with the same declarations', () => {
176
+ // The core proof, and the reason this spec does not read a byte count: an
177
+ // app that adopts the pair must RENDER the same. A missing key is a selector
178
+ // that vanished; a missing declaration is a property that stopped applying.
179
+ const lostRules: string[] = [];
180
+ const lostDeclarations: string[] = [];
181
+ for (const [key, decls] of before) {
182
+ const mine = after.get(key);
183
+ if (!mine) {
184
+ lostRules.push(key);
185
+ continue;
186
+ }
187
+ const theirs = new Set([...mine].map(dropFallbacks));
188
+ for (const decl of decls) {
189
+ // `@theme inline` aliases nothing reads โ€” see the header.
190
+ const prop = CUSTOM_PROPERTY.exec(decl)?.[1];
191
+ if (prop && !readByScanning.has(prop)) continue;
192
+ if (!theirs.has(dropFallbacks(decl))) lostDeclarations.push(`${key} โ†’ ${decl}`);
193
+ }
194
+ }
195
+ expect(
196
+ lostRules,
197
+ '`styles-static.css` + `styles-utilities.css` emits FEWER rules than\n' +
198
+ '`styles.css` does. Every selector listed here renders unstyled in any app that\n' +
199
+ `adopted the pair. Usually staleness:\n ${REGENERATE}`,
200
+ ).toEqual([]);
201
+ expect(
202
+ lostDeclarations,
203
+ 'the precompiled pair emits these selectors but not these declarations, so the\n' +
204
+ `affected components render PARTLY styled. Usually staleness:\n ${REGENERATE}`,
205
+ ).toEqual([]);
206
+ });
207
+
208
+ it('reads no custom property the files beside it do not declare', async () => {
209
+ // The trap the split creates and the scan never could: Tailwind emits only
210
+ // the theme variables its own build finds a use for, so a utility shipped in
211
+ // a prebuilt file can reference a `--text-sm` the consuming app never had a
212
+ // reason to emit โ€” and `font-size: var(--text-sm)` with no `--text-sm` is an
213
+ // invisible nothing.
214
+ //
215
+ // ๐Ÿ”ด Asked of the FILES, not of a compile. Tailwind v4 back-fills: it tracks
216
+ // the `var()`s in whatever CSS it is handed, so the artifact's whole theme
217
+ // layer can be deleted and a compiled consumer still declares everything
218
+ // (verified by deleting it). That back-fill is real and it is why the rule
219
+ // comparison above passes โ€” but it is Tailwind's promise, not this file's,
220
+ // and a `<link>` tag gets none of it. This asks what the artifact and the
221
+ // stylesheets a consumer imports beside it actually WRITE DOWN.
222
+ const artifact = onDisk ?? '';
223
+ // styles-static.css carries exactly one bare specifier, and its `@utility`
224
+ // definitions and `@property` registrations are where the `--tw-enter-*` /
225
+ // `--tw-animation-*` the artifact reads are declared. Pinned so the coupling
226
+ // cannot rot into a silent pass.
227
+ const animateDir = `${REPO_ROOT}/node_modules/tw-animate-css`;
228
+ expect(
229
+ (pkg as { dependencies: Record<string, string> }).dependencies['tw-animate-css'],
230
+ 'tw-animate-css is what src/styles.css @imports',
231
+ ).toBeDefined();
232
+ // Its own `exports` map, not a guessed filename โ€” a CSS-only package resolves
233
+ // through the `style` condition, which Bun.resolveSync does not follow.
234
+ const animateManifest = (await Bun.file(`${animateDir}/package.json`).json()) as {
235
+ exports: Record<string, { style?: string }>;
236
+ };
237
+ const animateEntry = animateManifest.exports['.']?.style;
238
+ expect(animateEntry, 'tw-animate-css no longer exports a `style` entry').toBeDefined();
239
+ const animateCss = await Bun.file(`${animateDir}/${animateEntry}`).text();
240
+ expect(animateCss.length, 'tw-animate-css moved its stylesheet').toBeGreaterThan(1_000);
241
+ const beside = await Promise.all(
242
+ ['src/theme.css', 'src/styles-static.css'].map((f) => Bun.file(`${REPO_ROOT}/${f}`).text()),
243
+ );
244
+ const provided = new Set([artifact, animateCss, ...beside].flatMap((css) => [...declared(css)]));
245
+ // Differential, not an allowlist: whatever the scanning route leaves to the
246
+ // runtime (`--radix-*`/`--reka-*` from the positioning libraries, `--cb-*`
247
+ // set inline by components) is fine here too, and nothing NEW is.
248
+ const declaredByScanning = declared(scanning);
249
+ const known = [...readByScanning].filter((v) => !declaredByScanning.has(v));
250
+ expect(
251
+ [...referenced(artifact)].filter((v) => !provided.has(v) && !known.includes(v)).sort(),
252
+ `${UTILITY_STYLESHEET} reads these custom properties and neither it, src/theme.css,\n` +
253
+ 'src/styles-static.css nor tw-animate-css declares them. Under the `@source` scan the\n' +
254
+ "consuming app's own build emitted them; a prebuilt file cannot count on that.\n" +
255
+ `Run:\n ${REGENERATE}`,
256
+ ).toEqual([]);
257
+ });
258
+
259
+ it('normalised exactly the two differences its header documents, and no more', () => {
260
+ // The two allowances above are the difference between a proof and a rubber
261
+ // stamp, so they are measured rather than trusted: if either grows, this
262
+ // fails and the header has to be rewritten before the pair ships again.
263
+ const fallbackOnly: string[] = [];
264
+ const aliasOnly: string[] = [];
265
+ const read = referenced(scanning);
266
+ for (const [key, decls] of before) {
267
+ const mine = after.get(key);
268
+ if (!mine) continue;
269
+ for (const decl of decls) {
270
+ if (mine.has(decl)) continue;
271
+ const prop = CUSTOM_PROPERTY.exec(decl)?.[1];
272
+ if (prop && !read.has(prop)) aliasOnly.push(`${key} โ†’ ${decl}`);
273
+ else fallbackOnly.push(`${key} โ†’ ${decl}`);
274
+ }
275
+ }
276
+ // One: `.animate-progress-indeterminate`, whose `@theme` token reaches the
277
+ // artifact's compile through `@reference "./styles-static.css"`.
278
+ expect(fallbackOnly.map((d) => d.split(' โ†’ ')[0])).toEqual([
279
+ '@layer utilities โ€– .animate-progress-indeterminate',
280
+ ]);
281
+ // Four: the `@theme inline` aliases in src/theme.css that no utility reads.
282
+ // A number, not a list, because which four is an implementation detail of
283
+ // Tailwind's theme tree-shaking; a JUMP here means the allowance is covering
284
+ // something it was not written for.
285
+ expect(aliasOnly.length).toBeLessThanOrEqual(8);
286
+ });
287
+
288
+ it('is exported as a subpath that resolves into a directory `files` ships', () => {
289
+ const exports = (pkg as { exports: Record<string, unknown> }).exports;
290
+ expect(exports['./styles-utilities.css']).toBe(`./${UTILITY_STYLESHEET}`);
291
+ // Out of `src/`, beside the two stylesheets it completes โ€” a trio of
292
+ // app-facing stylesheets served from two different directories is a
293
+ // difference nobody can see in CSS.
294
+ expect(exports['./styles-static.css']).toBe('./src/styles-static.css');
295
+ expect((pkg as { files: string[] }).files).toContain('src');
296
+ });
297
+
298
+ it('resolves as `cursedbelt/styles-utilities.css` through the real resolver', () => {
299
+ // The assertions above read the manifest; this one RESOLVES the specifier the
300
+ // way a consumer's bundler does. An export entry pointing at a path that does
301
+ // not exist satisfies every string comparison in this file and fails here.
302
+ expect(Bun.resolveSync(`${pkg.name}/styles-utilities.css`, REPO_ROOT)).toBe(
303
+ `${REPO_ROOT}/${UTILITY_STYLESHEET}`,
304
+ );
305
+ });
306
+
307
+ it('is regenerated by the build, so a stale artifact cannot be published', () => {
308
+ // `prepublishOnly` โ†’ `verify` โ†’ `build`, so the tarball's copy is always the
309
+ // one this repo's current src/react produces.
310
+ expect((pkg as { scripts: Record<string, string> }).scripts.build).toContain(
311
+ 'scripts/generateUtilityStyles.ts',
312
+ );
313
+ });
314
+ });
@@ -0,0 +1,150 @@
1
+ import { describe, expect, it } from 'bun:test';
2
+ import { Scanner } from '@tailwindcss/oxide';
3
+ import { compile } from 'tailwindcss';
4
+ import {
5
+ TAP_TARGET,
6
+ TAP_TARGET_ALWAYS,
7
+ TAP_TARGET_HALO,
8
+ TAP_TARGET_HEIGHT,
9
+ TAP_TARGET_SQUARE,
10
+ } from './react/lib/tapTarget';
11
+
12
+ /**
13
+ * ๐Ÿ”ด THE TAP FLOOR SURVIVES THE JIT.
14
+ *
15
+ * `src/react/lib/tapTarget.ts` collapsed 48 hand-written copies of `DESIGN.md`
16
+ * ยง5's 44px floor โ€” and 12 of the hover-reveal fix that goes with it โ€” into five
17
+ * constants. That refactor has one failure mode, and it is silent: **Tailwind's
18
+ * JIT scans source TEXT, it does not evaluate code.** A
19
+ * class that stops being a literal inside this package's own `@source "."` glob โ€”
20
+ * moved to a file the glob does not cover, assembled from a variable, split
21
+ * across a template it cannot read โ€” is a class Tailwind never emits. Nothing
22
+ * reds. The types are fine, the build is fine, every component still carries the
23
+ * class name in its `className`, and the rule it names simply does not exist in
24
+ * the stylesheet any more. Every tap target on every phone in the fleet quietly
25
+ * loses its floor.
26
+ *
27
+ * So this compiles the REAL `src/styles.css` โ€” its own `@source` directive, its
28
+ * own scan of this package's tree, Tailwind's own candidate extractor โ€” and
29
+ * asserts the emitted CSS still carries a rule for every utility the constants
30
+ * name. It is the one check that can tell "the constant is exported" apart from
31
+ * "the constant does anything".
32
+ *
33
+ * ๐Ÿ”ด NOTHING IN THIS FILE MAY SPELL A TAP UTILITY OUT. The `@source` glob covers
34
+ * `src/`, and a spec is source: the first draft of this header quoted the height
35
+ * class in its own prose, and that comment alone kept the class in the candidate
36
+ * set after the constant had been broken. The check passed against a stylesheet
37
+ * held up by a sentence about the check. Utilities come from the imports above
38
+ * and from nowhere else in here.
39
+ *
40
+ * Verified failing, 2026-09-14, before it was trusted โ€” each probe applied,
41
+ * observed and removed again:
42
+ * ยท `TAP_TARGET_HEIGHT` rewritten as a template that interpolates its `11`
43
+ * โ†’ both the extraction test and "utilities the emitted stylesheet has no
44
+ * rule for: <the height class>". `TAP_TARGET` composes the same constant,
45
+ * so every button in the package loses the floor from this one edit.
46
+ * ยท `TAP_TARGET_HEIGHT` truncated to its scale-less prefix (the trailing `11`
47
+ * dropped) โ†’ same failure, which is the anchored-selector half. A plain
48
+ * `includes()` would have PASSED this one: the truncated name is a substring
49
+ * of the rule the untruncated class emits elsewhere in the same stylesheet.
50
+ * ๐Ÿ”ด Truncating by one DIGIT instead does not fail, and should not โ€” the
51
+ * result is another real Tailwind utility with a real rule; what would be
52
+ * broken there is the design, not the pipeline this file measures.
53
+ * ยท the `@source` line removed from `src/styles.css` โ†’ "scanned no candidates",
54
+ * the guard below that stops every other assertion passing vacuously.
55
+ *
56
+ * ~1.5s: one Tailwind compile of ~118 KB over ~25k candidates.
57
+ */
58
+
59
+ const REPO_ROOT = import.meta.dir.replace(/\/src$/, '');
60
+
61
+ /** Directory half of an absolute path โ€” `node:path` is virtualized by the test preload. */
62
+ const dirOf = (path: string): string => path.slice(0, path.lastIndexOf('/'));
63
+
64
+ /**
65
+ * Resolve a CSS `@import` the way a bundler would.
66
+ *
67
+ * ๐Ÿ”ด `Bun.file`, never `node:fs`: this package's test preload virtualizes node
68
+ * builtins, so a `readFileSync` here would read MOCK data and the whole
69
+ * measurement would be of nothing (same trap as `publishShape.spec.ts`). A CSS
70
+ * package announces its entry through the `style` condition, not `main`.
71
+ */
72
+ const loadStylesheet = async (
73
+ id: string,
74
+ base: string,
75
+ ): Promise<{ path: string; base: string; content: string }> => {
76
+ const read = async (path: string) => ({
77
+ path,
78
+ base: dirOf(path),
79
+ content: await Bun.file(path).text(),
80
+ });
81
+ if (id.startsWith('.')) return read(`${base}/${id}`);
82
+ const packageDir = `${REPO_ROOT}/node_modules/${id}`;
83
+ const manifest = (await Bun.file(`${packageDir}/package.json`).json()) as {
84
+ exports?: { '.'?: { style?: string } };
85
+ style?: string;
86
+ main?: string;
87
+ };
88
+ const entry = manifest.exports?.['.']?.style ?? manifest.style ?? manifest.main;
89
+ if (!entry) throw new Error(`no stylesheet entry for "${id}"`);
90
+ return read(`${packageDir}/${entry.replace(/^\.\//, '')}`);
91
+ };
92
+
93
+ /** Every utility the five constants name, deduped โ€” the thing that must survive. */
94
+ const UTILITIES = [
95
+ ...new Set(
96
+ [TAP_TARGET_HEIGHT, TAP_TARGET, TAP_TARGET_SQUARE, TAP_TARGET_HALO, TAP_TARGET_ALWAYS]
97
+ .join(' ')
98
+ .split(/\s+/)
99
+ .filter(Boolean),
100
+ ),
101
+ ];
102
+
103
+ const emitted = await (async () => {
104
+ // An app imports Tailwind first, then this package's stylesheet โ€” exactly the
105
+ // two lines `src/styles.css`'s own header tells a consumer to write.
106
+ const source = await Bun.file(`${REPO_ROOT}/src/styles.css`).text();
107
+ const compiler = await compile(`@import "tailwindcss";\n${source}`, {
108
+ base: `${REPO_ROOT}/src`,
109
+ loadStylesheet,
110
+ });
111
+ const candidates = new Scanner({ sources: compiler.sources }).scan();
112
+ return { candidates, css: compiler.build(candidates) };
113
+ })();
114
+
115
+ describe('the tap floor reaches the stylesheet', () => {
116
+ it('scanned this package for candidates at all', () => {
117
+ // Guards every assertion below: with no `@source` directive the scan returns
118
+ // nothing, `build([])` emits no utilities, and "the rule is missing" would be
119
+ // indistinguishable from "the refactor broke it".
120
+ expect(emitted.candidates.length).toBeGreaterThan(1000);
121
+ });
122
+
123
+ it('names utilities Tailwind actually extracted from the source text', () => {
124
+ // The JIT half: each class is a literal in a file the `@source` glob covers.
125
+ expect(UTILITIES.filter((u) => !emitted.candidates.includes(u))).toEqual([]);
126
+ });
127
+
128
+ it('emits a CSS rule for every utility the tap-target constants name', () => {
129
+ // A `:` is backslash-escaped inside a selector, so the class `a:b` is written
130
+ // `.a\:b` in the output โ€” and a candidate that survived extraction but
131
+ // generated no rule (a utility Tailwind does not know) still fails here.
132
+ //
133
+ // ๐Ÿ”ด Anchored on the END of the class name, not a substring: a class truncated
134
+ // by one character is a prefix of the rule its untruncated self emits, so a
135
+ // plain `includes()` would have found it in a stylesheet that never had it.
136
+ const missing = UTILITIES.filter((u) => {
137
+ // The utility โ†’ its escaped selector text โ†’ a regex matching that text, with
138
+ // the CSS backslash itself escaped a second time for the regex.
139
+ const selectorText = `.${u.replace(/:/g, '\\:')}`;
140
+ const anchored = new RegExp(
141
+ `${selectorText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(?![\\w\\\\-])`,
142
+ );
143
+ return !anchored.test(emitted.css);
144
+ });
145
+ expect(
146
+ missing,
147
+ `utilities the emitted stylesheet has no rule for: ${missing.join(', ')}`,
148
+ ).toEqual([]);
149
+ });
150
+ });