cursedbelt 1.0.0 → 2.3.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 (533) 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 +391 -0
  227. package/dist/styles.css +27 -0
  228. package/package.json +19 -167
  229. package/scripts/generateStaticStyles.ts +122 -0
  230. package/scripts/publicSurface.ts +455 -0
  231. package/scripts/testTmpRoot.ts +34 -5
  232. package/src/client/index.ts +1 -1
  233. package/src/core/category/index.ts +2 -1
  234. package/src/core/category/types.ts +1 -1
  235. package/src/core/file-tree/fileTreeModel.spec.ts +134 -0
  236. package/src/core/file-tree/fileTreeModel.ts +104 -0
  237. package/src/core/layout/index.ts +1 -1
  238. package/src/core/media/index.ts +1 -1
  239. package/src/core/media/types.ts +1 -1
  240. package/src/core/media/uploadLimits.ts +1 -1
  241. package/src/core/sharing/model.ts +1 -1
  242. package/src/ctgr/index.ts +1 -1
  243. package/src/declaredDepsAreImported.spec.ts +87 -0
  244. package/src/demoFixture.spec.ts +133 -0
  245. package/src/index.ts +1 -1
  246. package/src/lockfileIsTracked.spec.ts +50 -0
  247. package/src/namedSubpathsResolve.spec.ts +119 -0
  248. package/src/publicSurface.spec.ts +72 -0
  249. package/src/react/activity-bar/ActivityBar.tsx +17 -0
  250. package/src/react/analytics/index.ts +1 -1
  251. package/src/react/chat/MessageComposer.tsx +5 -4
  252. package/src/react/components/Button.tsx +3 -2
  253. package/src/react/components/Checkbox.spec.tsx +51 -0
  254. package/src/react/components/Checkbox.tsx +68 -26
  255. package/src/react/components/CodeArea.tsx +2 -1
  256. package/src/react/components/CodeChip.spec.tsx +2 -2
  257. package/src/react/components/Collapsible.tsx +2 -1
  258. package/src/react/components/ComboboxField.tsx +3 -2
  259. package/src/react/components/CopyButton.tsx +2 -1
  260. package/src/react/components/CopyableText.spec.tsx +1 -1
  261. package/src/react/components/DataTable/ColumnChecklist.tsx +2 -1
  262. package/src/react/components/DataTable/Pagination.tsx +2 -1
  263. package/src/react/components/DataTable/SortHeader.tsx +2 -1
  264. package/src/react/components/DataTable/{FilterBuilder.tsx → TableFilterBuilder.tsx} +33 -5
  265. package/src/react/components/DataTable/Toolbar.tsx +3 -3
  266. package/src/react/components/DataTable/cells/LinkCell.tsx +2 -1
  267. package/src/react/components/DataTable/index.ts +8 -1
  268. package/src/react/components/DragHandle.tsx +2 -1
  269. package/src/react/components/EmojiField.tsx +2 -1
  270. package/src/react/components/EventTimeline.tsx +3 -2
  271. package/src/react/components/FileLocation.spec.tsx +1 -1
  272. package/src/react/components/IconButton.tsx +1 -1
  273. package/src/react/components/InfoHint.tsx +5 -4
  274. package/src/react/components/InheritBadge.tsx +1 -1
  275. package/src/react/components/InlineEditableText.tsx +2 -1
  276. package/src/react/components/MeterList.tsx +2 -1
  277. package/src/react/components/PathText.tsx +4 -3
  278. package/src/react/components/RatingField.tsx +2 -1
  279. package/src/react/components/SecretInput.tsx +3 -3
  280. package/src/react/components/SegmentedControl.tsx +2 -2
  281. package/src/react/components/StarRating.spec.tsx +2 -2
  282. package/src/react/components/StarRating.tsx +9 -5
  283. package/src/react/components/StatStrip.tsx +2 -1
  284. package/src/react/components/StatTile.tsx +3 -3
  285. package/src/react/components/Tabs.spec.tsx +3 -2
  286. package/src/react/components/Tabs.tsx +2 -1
  287. package/src/react/components/TruncatedText.tsx +2 -1
  288. package/src/react/components/calendar/MonthGrid.spec.tsx +2 -1
  289. package/src/react/components/calendar/MonthGrid.tsx +2 -1
  290. package/src/react/components/calendar/WeekView.tsx +2 -1
  291. package/src/react/components/revealOnHover.ts +3 -2
  292. package/src/react/file-tree/FileTree.spec.tsx +248 -0
  293. package/src/react/file-tree/FileTree.tsx +304 -4
  294. package/src/react/file-tree/fileTree.css +52 -0
  295. package/src/react/file-tree/fileTreeGeometry.fixture.json +151 -0
  296. package/src/react/file-tree/fileTreeGeometry.spec.ts +33 -52
  297. package/src/react/filter-rail/FilterRail.spec.tsx +2 -1
  298. package/src/react/filter-rail/FilterRail.tsx +5 -4
  299. package/src/react/folder-tree/FolderTreeRail.tsx +2 -1
  300. package/src/react/index.ts +13 -3
  301. package/src/react/layoutEngine/index.ts +1 -1
  302. package/src/react/layoutEngine/types.ts +1 -1
  303. package/src/react/lib/field.ts +4 -2
  304. package/src/react/lib/floatingStyles.spec.ts +2 -1
  305. package/src/react/lib/floatingStyles.ts +3 -1
  306. package/src/react/lib/tapTarget.ts +100 -0
  307. package/src/react/media/MaskPainter.tsx +2 -2
  308. package/src/react/media/VideoTrimmer.tsx +1 -1
  309. package/src/react/media/denseGallery.css +3 -3
  310. package/src/react/media/ffmpegWasm.ts +2 -2
  311. package/src/react/media/videoPlayer.css +42 -0
  312. package/src/react/namespace/NamespaceTargetCapsule.tsx +2 -2
  313. package/src/react/nav/BreadcrumbTrail.tsx +4 -3
  314. package/src/react/nav/HubTileGrid.tsx +2 -1
  315. package/src/react/nav/SideNav.tsx +4 -3
  316. package/src/react/nav/SideNavCustomize.tsx +2 -1
  317. package/src/react/palette/CommandPalette.tsx +3 -2
  318. package/src/server/ctgr.ts +1 -1
  319. package/src/server/drivers/pooledControlStores.pg.test.ts +1 -0
  320. package/src/server/drivers/pooledIdentityStore.pg.test.ts +1 -0
  321. package/src/server/drivers/retentionPolicy.pg.test.ts +1 -0
  322. package/src/server/guard/argon2Binding.ts +1 -1
  323. package/src/server/incidents/store.ts +3 -3
  324. package/src/server/index.ts +1 -1
  325. package/src/server/master-lock/masterLock.spec.ts +18 -2
  326. package/src/server/master-lock/masterLock.ts +1 -1
  327. package/src/server/media-bun/image.spec.ts +1 -0
  328. package/src/server/media-bun/index.ts +1 -1
  329. package/src/server/media-bun/video.spec.ts +1 -0
  330. package/src/server/paths/appDataHome.spec.ts +87 -0
  331. package/src/server/paths/appDataHome.ts +84 -0
  332. package/src/server/retention/archive.spec.ts +26 -4
  333. package/src/server/retention/archive.ts +20 -15
  334. package/src/server/retention/index.ts +1 -1
  335. package/src/server/retention/policy.ts +2 -2
  336. package/src/server/retention/store.spec.ts +38 -10
  337. package/src/server/retention/store.ts +26 -19
  338. package/src/server/runtime/localHost.spec.ts +22 -3
  339. package/src/server/runtime/localHost.ts +12 -9
  340. package/src/server/runtime/meterRollup.pg.test.ts +1 -0
  341. package/src/server/runtime/recipe.ts +4 -4
  342. package/src/server/runtime/retentionJob.pg.test.ts +1 -0
  343. package/src/server/search/pgSearchProvider.pg.test.ts +1 -0
  344. package/src/server/storage/binaryServerProcessing.integration.spec.ts +6 -2
  345. package/src/server/storage/chunked.integration.spec.ts +5 -2
  346. package/src/server/storage/fileUploadClient-chunked.integration.spec.ts +5 -2
  347. package/src/server/storage/files/adapter.photo.display.spec.ts +1 -0
  348. package/src/server/storage/imageThumbnail.spec.ts +1 -0
  349. package/src/server/storage/transcode.integration.spec.ts +5 -2
  350. package/src/server/storage/videoProcessor.posterOnly.spec.ts +1 -0
  351. package/src/shared/errors.ts +1 -1
  352. package/src/skippedTestsAreAnswered.spec.ts +215 -0
  353. package/src/styles-static.css +391 -0
  354. package/src/styles.css +27 -0
  355. package/src/stylesStaticMatches.spec.ts +134 -0
  356. package/src/tapTargetStylesheet.spec.ts +150 -0
  357. package/src/testTmpRoot.spec.ts +102 -0
  358. package/dist/core/duplicates/index.d.ts +0 -116
  359. package/dist/core/duplicates/index.d.ts.map +0 -1
  360. package/dist/core/duplicates/index.js +0 -178
  361. package/dist/core/duplicates/index.js.map +0 -1
  362. package/dist/core/namespace/helpers.d.ts +0 -14
  363. package/dist/core/namespace/helpers.d.ts.map +0 -1
  364. package/dist/core/namespace/helpers.js +0 -29
  365. package/dist/core/namespace/helpers.js.map +0 -1
  366. package/dist/core/namespace/index.d.ts +0 -4
  367. package/dist/core/namespace/index.d.ts.map +0 -1
  368. package/dist/core/namespace/index.js +0 -6
  369. package/dist/core/namespace/index.js.map +0 -1
  370. package/dist/core/namespace/memoryStore.d.ts +0 -19
  371. package/dist/core/namespace/memoryStore.d.ts.map +0 -1
  372. package/dist/core/namespace/memoryStore.js +0 -70
  373. package/dist/core/namespace/memoryStore.js.map +0 -1
  374. package/dist/core/namespace/types.d.ts +0 -44
  375. package/dist/core/namespace/types.d.ts.map +0 -1
  376. package/dist/core/namespace/types.js +0 -8
  377. package/dist/core/namespace/types.js.map +0 -1
  378. package/dist/game/core/DisposeRegistry.d.ts +0 -42
  379. package/dist/game/core/DisposeRegistry.d.ts.map +0 -1
  380. package/dist/game/core/DisposeRegistry.js +0 -67
  381. package/dist/game/core/DisposeRegistry.js.map +0 -1
  382. package/dist/game/core/drawBudget.d.ts +0 -26
  383. package/dist/game/core/drawBudget.d.ts.map +0 -1
  384. package/dist/game/core/drawBudget.js +0 -55
  385. package/dist/game/core/drawBudget.js.map +0 -1
  386. package/dist/game/core/fixedTimestep.d.ts +0 -38
  387. package/dist/game/core/fixedTimestep.d.ts.map +0 -1
  388. package/dist/game/core/fixedTimestep.js +0 -47
  389. package/dist/game/core/fixedTimestep.js.map +0 -1
  390. package/dist/game/core/index.d.ts +0 -9
  391. package/dist/game/core/index.d.ts.map +0 -1
  392. package/dist/game/core/index.js +0 -8
  393. package/dist/game/core/index.js.map +0 -1
  394. package/dist/game/core/inputCollector.d.ts +0 -82
  395. package/dist/game/core/inputCollector.d.ts.map +0 -1
  396. package/dist/game/core/inputCollector.js +0 -176
  397. package/dist/game/core/inputCollector.js.map +0 -1
  398. package/dist/game/core/resizeCanvas.d.ts +0 -19
  399. package/dist/game/core/resizeCanvas.d.ts.map +0 -1
  400. package/dist/game/core/resizeCanvas.js +0 -29
  401. package/dist/game/core/resizeCanvas.js.map +0 -1
  402. package/dist/game/react/index.d.ts +0 -3
  403. package/dist/game/react/index.d.ts.map +0 -1
  404. package/dist/game/react/index.js +0 -5
  405. package/dist/game/react/index.js.map +0 -1
  406. package/dist/game/react/useGameEngine.d.ts +0 -64
  407. package/dist/game/react/useGameEngine.d.ts.map +0 -1
  408. package/dist/game/react/useGameEngine.js +0 -78
  409. package/dist/game/react/useGameEngine.js.map +0 -1
  410. package/dist/react/canvas/CanvasNavHUD.d.ts +0 -64
  411. package/dist/react/canvas/CanvasNavHUD.d.ts.map +0 -1
  412. package/dist/react/canvas/CanvasNavHUD.js +0 -58
  413. package/dist/react/canvas/CanvasNavHUD.js.map +0 -1
  414. package/dist/react/canvas/fitLabel.d.ts +0 -53
  415. package/dist/react/canvas/fitLabel.d.ts.map +0 -1
  416. package/dist/react/canvas/fitLabel.js +0 -104
  417. package/dist/react/canvas/fitLabel.js.map +0 -1
  418. package/dist/react/canvas/index.d.ts +0 -4
  419. package/dist/react/canvas/index.d.ts.map +0 -1
  420. package/dist/react/canvas/index.js +0 -4
  421. package/dist/react/canvas/index.js.map +0 -1
  422. package/dist/react/canvas/lod.d.ts +0 -40
  423. package/dist/react/canvas/lod.d.ts.map +0 -1
  424. package/dist/react/canvas/lod.js +0 -37
  425. package/dist/react/canvas/lod.js.map +0 -1
  426. package/dist/react/components/DataTable/FilterBuilder.d.ts +0 -38
  427. package/dist/react/components/DataTable/FilterBuilder.d.ts.map +0 -1
  428. package/dist/react/components/DataTable/FilterBuilder.js.map +0 -1
  429. package/dist/react/seo/HeadProvider.d.ts +0 -14
  430. package/dist/react/seo/HeadProvider.d.ts.map +0 -1
  431. package/dist/react/seo/HeadProvider.js +0 -44
  432. package/dist/react/seo/HeadProvider.js.map +0 -1
  433. package/dist/react/seo/applyHeadToDocument.d.ts +0 -3
  434. package/dist/react/seo/applyHeadToDocument.d.ts.map +0 -1
  435. package/dist/react/seo/applyHeadToDocument.js +0 -66
  436. package/dist/react/seo/applyHeadToDocument.js.map +0 -1
  437. package/dist/react/seo/index.d.ts +0 -3
  438. package/dist/react/seo/index.d.ts.map +0 -1
  439. package/dist/react/seo/index.js +0 -7
  440. package/dist/react/seo/index.js.map +0 -1
  441. package/dist/react/timeline/ClipView.d.ts +0 -29
  442. package/dist/react/timeline/ClipView.d.ts.map +0 -1
  443. package/dist/react/timeline/ClipView.js +0 -53
  444. package/dist/react/timeline/ClipView.js.map +0 -1
  445. package/dist/react/timeline/Playhead.d.ts +0 -16
  446. package/dist/react/timeline/Playhead.d.ts.map +0 -1
  447. package/dist/react/timeline/Playhead.js +0 -26
  448. package/dist/react/timeline/Playhead.js.map +0 -1
  449. package/dist/react/timeline/TimeRuler.d.ts +0 -21
  450. package/dist/react/timeline/TimeRuler.d.ts.map +0 -1
  451. package/dist/react/timeline/TimeRuler.js +0 -31
  452. package/dist/react/timeline/TimeRuler.js.map +0 -1
  453. package/dist/react/timeline/TimelineSurface.d.ts +0 -29
  454. package/dist/react/timeline/TimelineSurface.d.ts.map +0 -1
  455. package/dist/react/timeline/TimelineSurface.js +0 -56
  456. package/dist/react/timeline/TimelineSurface.js.map +0 -1
  457. package/dist/react/timeline/TrackLane.d.ts +0 -31
  458. package/dist/react/timeline/TrackLane.d.ts.map +0 -1
  459. package/dist/react/timeline/TrackLane.js +0 -32
  460. package/dist/react/timeline/TrackLane.js.map +0 -1
  461. package/dist/react/timeline/index.d.ts +0 -6
  462. package/dist/react/timeline/index.d.ts.map +0 -1
  463. package/dist/react/timeline/index.js +0 -12
  464. package/dist/react/timeline/index.js.map +0 -1
  465. package/dist/server/private-media/index.d.ts +0 -7
  466. package/dist/server/private-media/index.d.ts.map +0 -1
  467. package/dist/server/private-media/index.js +0 -13
  468. package/dist/server/private-media/index.js.map +0 -1
  469. package/dist/server/seo/index.d.ts +0 -3
  470. package/dist/server/seo/index.d.ts.map +0 -1
  471. package/dist/server/seo/index.js +0 -6
  472. package/dist/server/seo/index.js.map +0 -1
  473. package/dist/server/seo/mountSeoRoutes.d.ts +0 -9
  474. package/dist/server/seo/mountSeoRoutes.d.ts.map +0 -1
  475. package/dist/server/seo/mountSeoRoutes.js +0 -19
  476. package/dist/server/seo/mountSeoRoutes.js.map +0 -1
  477. package/dist/server/seo/serveHeadInjectedIndex.d.ts +0 -9
  478. package/dist/server/seo/serveHeadInjectedIndex.d.ts.map +0 -1
  479. package/dist/server/seo/serveHeadInjectedIndex.js +0 -20
  480. package/dist/server/seo/serveHeadInjectedIndex.js.map +0 -1
  481. package/dist/upload.d.ts +0 -148
  482. package/dist/upload.d.ts.map +0 -1
  483. package/dist/upload.js +0 -159
  484. package/dist/upload.js.map +0 -1
  485. package/dist/verify/runtime/index.d.ts +0 -16
  486. package/dist/verify/runtime/index.d.ts.map +0 -1
  487. package/dist/verify/runtime/index.js +0 -16
  488. package/dist/verify/runtime/index.js.map +0 -1
  489. package/scripts/demoCheck.ts +0 -42
  490. package/src/core/duplicates/index.spec.ts +0 -116
  491. package/src/core/duplicates/index.ts +0 -203
  492. package/src/core/namespace/helpers.ts +0 -31
  493. package/src/core/namespace/index.ts +0 -12
  494. package/src/core/namespace/memoryStore.ts +0 -77
  495. package/src/core/namespace/namespace.spec.ts +0 -117
  496. package/src/core/namespace/types.ts +0 -53
  497. package/src/game/core/DisposeRegistry.spec.ts +0 -53
  498. package/src/game/core/DisposeRegistry.ts +0 -70
  499. package/src/game/core/drawBudget.spec.ts +0 -51
  500. package/src/game/core/drawBudget.ts +0 -75
  501. package/src/game/core/fixedTimestep.spec.ts +0 -91
  502. package/src/game/core/fixedTimestep.ts +0 -79
  503. package/src/game/core/index.ts +0 -16
  504. package/src/game/core/inputCollector.spec.ts +0 -29
  505. package/src/game/core/inputCollector.ts +0 -245
  506. package/src/game/core/resizeCanvas.ts +0 -31
  507. package/src/game/react/index.ts +0 -10
  508. package/src/game/react/useGameEngine.ts +0 -125
  509. package/src/react/canvas/CanvasNavHUD.spec.tsx +0 -62
  510. package/src/react/canvas/CanvasNavHUD.tsx +0 -210
  511. package/src/react/canvas/fitLabel.spec.ts +0 -82
  512. package/src/react/canvas/fitLabel.ts +0 -150
  513. package/src/react/canvas/index.ts +0 -15
  514. package/src/react/canvas/lod.ts +0 -53
  515. package/src/react/seo/HeadProvider.tsx +0 -67
  516. package/src/react/seo/applyHeadToDocument.ts +0 -73
  517. package/src/react/seo/index.ts +0 -12
  518. package/src/react/seo/seo.spec.tsx +0 -101
  519. package/src/react/timeline/ClipView.tsx +0 -146
  520. package/src/react/timeline/Playhead.tsx +0 -63
  521. package/src/react/timeline/TimeRuler.tsx +0 -85
  522. package/src/react/timeline/TimelineSurface.tsx +0 -157
  523. package/src/react/timeline/TrackLane.tsx +0 -87
  524. package/src/react/timeline/index.ts +0 -12
  525. package/src/react/timeline/timeline.spec.tsx +0 -175
  526. package/src/server/private-media/index.ts +0 -45
  527. package/src/server/seo/index.ts +0 -8
  528. package/src/server/seo/mountSeoRoutes.ts +0 -37
  529. package/src/server/seo/seo.spec.ts +0 -128
  530. package/src/server/seo/serveHeadInjectedIndex.ts +0 -36
  531. package/src/upload.spec.ts +0 -300
  532. package/src/upload.ts +0 -288
  533. package/src/verify/runtime/index.ts +0 -64
@@ -4,30 +4,38 @@
4
4
  * ── Why a test reads a stylesheet ───────────────────────────────────────────────────────
5
5
  * Owner, 2026-09-10: *"We have two sidenav components now. I need updates and we need them
6
6
  * in two places because of the copying."* The two are this one and
7
- * `cursed-embeddable-spreadsheet`'s, and they cannot be merged into one — cb is `private`
8
- * and unpublished while ces ships on npm, and cb's tree is a deliberate generalisation that
9
- * has fewer features than ces's, not the same ones. The full reasoning is in the spec file
10
- * this reads.
7
+ * `cursed-embeddable-spreadsheet`'s, and they cannot be merged into one — the two ship as
8
+ * separate published packages, and cb's tree is a deliberate generalisation that has fewer
9
+ * features than ces's, not the same ones. The full reasoning is in the spec file this reads.
11
10
  *
12
11
  * So the design is shared and the code is not, and this is the seam that keeps the design
13
- * shared: **a number changed here without being changed there fails on the next run**,
14
- * rather than being noticed by eye some months later. Its twin is
12
+ * shared: **a number changed here without being changed in the design file fails on the next
13
+ * run**, rather than being noticed by eye some months later. Its twin is
15
14
  * `test/ui/tree-geometry.test.ts` over in the spreadsheet.
16
15
  *
17
- * 🔴 The INVARIANTS are asserted unconditionally and the shared numbers only when the fleet
18
- * checkout is readable. That split is deliberate: the relationships below are properties of
19
- * this stylesheet alone and must hold in a clone with no fleet beside it, while cross-repo
20
- * agreement is a fact about this machine.
16
+ * 🔴 EVERY assertion here runs unconditionally, on any machine. Until 2026-09-13 the shared
17
+ * numbers were read out of a checkout in the owner's home directory and SKIPPED when it was
18
+ * missing — in a package that is published to npm. That is a test that passes for one person
19
+ * and quietly does nothing for everybody else, which is worse than no test: half this file
20
+ * would have been inert for every installer. The design now lives in
21
+ * `fileTreeGeometry.fixture.json`, committed beside this spec, and nothing is conditional.
21
22
  */
22
23
  import { describe, expect, it } from 'bun:test';
23
24
  import { readFileSync } from 'node:fs';
24
- import { homedir } from 'node:os';
25
25
  import { join } from 'node:path';
26
26
  import { flattenFileTree } from '../../core/file-tree/fileTreeModel';
27
27
 
28
28
  const CSS = readFileSync(join(import.meta.dir, 'fileTree.css'), 'utf8');
29
29
 
30
- const SPEC_PATH = join(homedir(), '.app-managed/repos/fleet/standards/file-tree-geometry.json');
30
+ /**
31
+ * The shared design, committed in this repo. Read once — a published package's suite may not
32
+ * depend on a directory outside its own checkout.
33
+ */
34
+ const DESIGN = JSON.parse(readFileSync(join(import.meta.dir, 'fileTreeGeometry.fixture.json'), 'utf8')) as {
35
+ geometry: Record<string, number>;
36
+ scrollbar: { width: number; thumbInset: number };
37
+ behaviour: Record<string, { value: boolean }>;
38
+ };
31
39
 
32
40
  /**
33
41
  * A token's value in px, resolved one level through `var()` and `calc(a / 2)`.
@@ -141,15 +149,6 @@ describe('the file tree geometry', () => {
141
149
  expect(CSS.indexOf('-webkit-font-smoothing')).toBeGreaterThan(CSS.indexOf(':where(.dark) .cbft {'));
142
150
  });
143
151
 
144
- /*
145
- * ── The cross-repo half ───────────────────────────────────────────────────────────────
146
- *
147
- * Skipped rather than failed when fleet is not beside this checkout, because a clone
148
- * without it is a legitimate state and a red suite there would teach people to ignore this
149
- * file. On this machine it is the whole point: it is what makes "update it in two places"
150
- * something the machine reports instead of something a person has to remember.
151
- */
152
-
153
152
  /*
154
153
  * ── The shared BEHAVIOUR, not just the numbers ────────────────────────────────────────
155
154
  *
@@ -157,26 +156,24 @@ describe('the file tree geometry', () => {
157
156
  * never against itself. A test that read `true` out of the JSON and then asserted `true`
158
157
  * would pass on a tree that does neither thing — it would gate nothing while looking
159
158
  * exactly like a gate. So the flag is the CONDITION and the behaviour is the assertion:
160
- * flip the flag in fleet and this suite reds until the code here follows it.
159
+ * flip the flag in the design file and this suite reds until the code here follows it.
161
160
  */
162
- const behaviour = (): Record<string, { value: boolean }> | null => {
163
- try {
164
- return JSON.parse(readFileSync(SPEC_PATH, 'utf8')).behaviour;
165
- } catch {
166
- return null; // no fleet checkout here — see above
167
- }
168
- };
161
+ it('declares every behaviour flag this suite asserts against', () => {
162
+ // The fixture is the CONDITION for the two tests below, so a missing key would turn
163
+ // each of them into a silent pass — the exact failure mode that vendoring it fixed.
164
+ expect(Object.keys(DESIGN.behaviour).sort()).toEqual(
165
+ ['$comment', 'everyFolderDrawsATwisty', 'mediaRowDrawsItsThumbnail'].sort(),
166
+ );
167
+ });
169
168
 
170
169
  it('draws a twisty on EVERY folder, empty ones included, as the shared design declares', () => {
171
- const declared = behaviour()?.everyFolderDrawsATwisty;
172
- if (!declared) return;
170
+ const declared = DESIGN.behaviour.everyFolderDrawsATwisty!;
173
171
  const rows = flattenFileTree([{ id: 'empty', name: 'Empty', kind: 'folder', children: [] }], []);
174
172
  expect(rows[0]!.expandable).toBe(declared.value);
175
173
  });
176
174
 
177
175
  it('gives a media row a thumbnail slot, as the shared design declares', () => {
178
- const declared = behaviour()?.mediaRowDrawsItsThumbnail;
179
- if (!declared) return;
176
+ const declared = DESIGN.behaviour.mediaRowDrawsItsThumbnail!;
180
177
  // The three constraints the shared file names, each asserted where it lives:
181
178
  // · one glyph box, never a second track — the box is `--cbft-glyph` wide either way;
182
179
  // · the row height does not move — `.cbft-thumb` declares no height of its own beyond it;
@@ -212,17 +209,8 @@ describe('the file tree geometry', () => {
212
209
  * Both APIs are required rather than interchangeable: `scrollbar-width` is the standard
213
210
  * property and the `::-webkit-` rules are what Safari and older Chrome read.
214
211
  */
215
- const scrollbar = (): { width: number; thumbInset: number } | null => {
216
- try {
217
- return JSON.parse(readFileSync(SPEC_PATH, 'utf8')).scrollbar;
218
- } catch {
219
- return null; // no fleet checkout here — see above
220
- }
221
- };
222
-
223
212
  it('draws a very thin gutter, at the width the shared design names', () => {
224
- const width = scrollbar()?.width;
225
- if (width === undefined) return;
213
+ const width = DESIGN.scrollbar.width;
226
214
  // The standard property first — a stylesheet with only the `-webkit-` half is thin in
227
215
  // Firefox and fat in Safari, or the other way round, depending which half went missing.
228
216
  expect(CSS).toContain('scrollbar-width: thin;');
@@ -231,9 +219,7 @@ describe('the file tree geometry', () => {
231
219
  });
232
220
 
233
221
  it('keeps the marker FLUSH with the edge — no border, no margin on the thumb', () => {
234
- const inset = scrollbar()?.thumbInset;
235
- if (inset === undefined) return;
236
- expect(inset).toBe(0);
222
+ expect(DESIGN.scrollbar.thumbInset).toBe(0);
237
223
  const thumb = CSS.slice(
238
224
  CSS.indexOf('.cbft-scroll::-webkit-scrollbar-thumb {'),
239
225
  CSS.indexOf('.cbft-scroll::-webkit-scrollbar-thumb:hover'),
@@ -261,12 +247,7 @@ describe('the file tree geometry', () => {
261
247
  });
262
248
 
263
249
  it('agrees with the shared design the spreadsheet also implements', () => {
264
- let spec: { geometry: Record<string, number> };
265
- try {
266
- spec = JSON.parse(readFileSync(SPEC_PATH, 'utf8'));
267
- } catch {
268
- return; // no fleet checkout here — see above
269
- }
250
+ const spec = DESIGN;
270
251
  expect({
271
252
  row: token('cbft-row'),
272
253
  pad: token('cbft-pad'),
@@ -2,6 +2,7 @@ import { afterEach, describe, expect, test } from 'bun:test';
2
2
  import { cleanup, fireEvent, render, waitFor } from '@testing-library/react';
3
3
  import { FilterRail, type FilterRailSection } from './FilterRail';
4
4
  import { hoverHint } from '../../testing/tooltip';
5
+ import { TAP_TARGET_ALWAYS } from '../lib/tapTarget';
5
6
 
6
7
  afterEach(cleanup);
7
8
 
@@ -331,7 +332,7 @@ describe('FilterRail — rows that are more than a choice', () => {
331
332
  expect(shelf?.className).toContain('group-hover/rail-row:opacity-100');
332
333
  expect(shelf?.className).toContain('group-focus-within/rail-row:opacity-100');
333
334
  // A phone has no hover at all; without this the control is unreachable by any gesture.
334
- expect(shelf?.className).toContain('pointer-coarse:opacity-100');
335
+ expect(shelf?.className).toContain(TAP_TARGET_ALWAYS);
335
336
  // DESIGN.md §5 — a row control is a real tap target, whatever glyph the host put in it.
336
337
  expect(shelf?.className).toContain('pointer-coarse:[&_button]:min-h-11');
337
338
  });
@@ -3,6 +3,7 @@ import type { DragEvent, ReactNode } from 'react';
3
3
  import { ScrollArea } from '../components/ScrollArea';
4
4
  import { cn } from '../lib/cn';
5
5
  import { Tooltip } from '../components/Tooltip';
6
+ import { TAP_TARGET, TAP_TARGET_ALWAYS, TAP_TARGET_HEIGHT } from '../lib/tapTarget';
6
7
 
7
8
  export interface FilterRailItem {
8
9
  /** Stable key, and the value handed to `onSelect`. */
@@ -260,7 +261,7 @@ export function FilterRail({
260
261
  onClick={() => onCollapsedChange(!collapsed)}
261
262
  aria-label={collapsed ? `Expand ${label}` : `Collapse ${label}`}
262
263
  aria-expanded={!collapsed}
263
- className='grid size-8 place-items-center rounded-md text-muted-foreground transition-colors hover:bg-card-raised hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11 pointer-coarse:min-w-11 [&_svg]:size-4'
264
+ className={`grid size-8 place-items-center rounded-md text-muted-foreground transition-colors hover:bg-card-raised hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${TAP_TARGET} [&_svg]:size-4`}
264
265
  >
265
266
  {collapsed ? <ChevronsRight /> : <ChevronsLeft />}
266
267
  </button>
@@ -387,7 +388,7 @@ function FilterRailRow({
387
388
  <span
388
389
  data-cb-rail-tools={active ? 'solid' : 'quiet'}
389
390
  className={cn(
390
- 'flex shrink-0 items-center gap-px transition-opacity pointer-coarse:opacity-100',
391
+ `flex shrink-0 items-center gap-px transition-opacity ${TAP_TARGET_ALWAYS}`,
391
392
  // 🔴 A rail row is DENSE, and the shelf is now always visible, so its width
392
393
  // comes straight out of the label's. Measured at 14rem with three tools at
393
394
  // the `sm` control height (32px each): `screencaps` rendered as ":" and a
@@ -486,8 +487,8 @@ function FilterRailButton({
486
487
  'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
487
488
  // 44px touch floor on coarse pointers only, so the dense desktop rail stays dense.
488
489
  collapsed
489
- ? 'size-10 justify-center pointer-coarse:min-h-11 pointer-coarse:min-w-11'
490
- : 'px-2.5 py-1.5 pointer-coarse:min-h-11',
490
+ ? `size-10 justify-center ${TAP_TARGET}`
491
+ : `px-2.5 py-1.5 ${TAP_TARGET_HEIGHT}`,
491
492
  item.disabled && 'cursor-not-allowed opacity-50',
492
493
  // 🔴 THREE states, TWO channels — see the component doc. Hover gets a real
493
494
  // background rather than a suggestion of one; active steps up again AND takes the
@@ -33,6 +33,7 @@ import type { FolderNode } from "../../core/folder-tree/tree";
33
33
  import { isRowDrag, readRowDrag, type RowDragPayload } from "../components/DataTable/rowDrag";
34
34
  import { Tooltip } from '../components/Tooltip';
35
35
  import { NewFolderControl } from './NewFolderControl';
36
+ import { TAP_TARGET_HEIGHT } from "../lib/tapTarget";
36
37
 
37
38
  export interface FolderTreeRailProps {
38
39
  nodes: readonly FolderNode[];
@@ -167,7 +168,7 @@ export function FolderTreeRail({
167
168
  aria-expanded={open}
168
169
  // `pointer-coarse:` only — see FilterRail's twisty for why a finger-sized
169
170
  // box everywhere would re-indent the whole tree for a mouse.
170
- className="w-4 shrink-0 self-stretch text-[var(--muted-foreground)] pointer-coarse:min-h-11 pointer-coarse:w-11"
171
+ className={`w-4 shrink-0 self-stretch text-[var(--muted-foreground)] ${TAP_TARGET_HEIGHT} pointer-coarse:w-11`}
171
172
  onClick={() => toggle(node)}
172
173
  >
173
174
  {open ? "▾" : "▸"}
@@ -217,9 +217,6 @@ export {
217
217
  EMPTY_FILTER_QUERY,
218
218
  evaluateFilterQuery,
219
219
  FILTER_OP_LABELS,
220
- FilterBuilder,
221
- type FilterBuilderColumn,
222
- type FilterBuilderProps,
223
220
  type FilterCondition,
224
221
  type FilterGroup,
225
222
  type FilterOp,
@@ -255,6 +252,9 @@ export {
255
252
  SortHeader,
256
253
  type SortHeaderProps,
257
254
  setAssetUrlResolver,
255
+ TableFilterBuilder,
256
+ type TableFilterBuilderColumn,
257
+ type TableFilterBuilderProps,
258
258
  TablePagination,
259
259
  type TablePaginationProps,
260
260
  TableToolbar,
@@ -765,6 +765,16 @@ export { makeFormConfig } from './lib/form';
765
765
  * writing a literal delay; `no-fast-tooltip` fails a build on a smaller one. */
766
766
  export { HOVER_HINT_DELAY_MS, HOVER_HINT_INSTANT_MS } from './lib/hoverIntent';
767
767
  export { createPersistedStore } from './lib/store';
768
+ /** `DESIGN.md` §5's 44px tap floor, as the four class strings it actually takes —
769
+ * import these rather than writing `pointer-coarse:` utilities by hand, so the floor
770
+ * moves once when it moves. See `react/lib/tapTarget.ts` for which shape is which. */
771
+ export {
772
+ TAP_TARGET,
773
+ TAP_TARGET_ALWAYS,
774
+ TAP_TARGET_HALO,
775
+ TAP_TARGET_HEIGHT,
776
+ TAP_TARGET_SQUARE,
777
+ } from './lib/tapTarget';
768
778
  export * from './nav';
769
779
  export * from './palette';
770
780
  export * from './prompt';
@@ -1,6 +1,6 @@
1
1
  // cursedbelt layout engine (React) — the read-only renderer + the from-scratch
2
2
  // WYSIWYG drag editor (canvas, inspector, palette, dialog) for the
3
- // `cursedbelt/layout` model. Generic over the app's field type; the app supplies a
3
+ // `cwip/layout` model (re-exported at `src/core/layout`). Generic over the app's field type; the app supplies a
4
4
  // widget registry (how each node type renders) + optionally a custom binding
5
5
  // resolver. Built on the design-system primitives (Surface/Grid, Modal/Drawer,
6
6
  // Collapsible) and @atlaskit/pragmatic-drag-and-drop. Exported as part of `cursedbelt/react`.
@@ -9,7 +9,7 @@ import type {
9
9
  } from '../../core/layout';
10
10
 
11
11
  // The React widget contract for the layout engine. The pure model + binding
12
- // resolution live in `cursedbelt/layout`; this adds the rendering + editing side.
12
+ // resolution live in `cwip/layout` (re-exported at `src/core/layout`); this adds the rendering + editing side.
13
13
  // Everything is generic over the app's field type `F` (which must extend
14
14
  // `LayoutField`), so an app keeps its full column type inside `render`.
15
15
 
@@ -1,3 +1,5 @@
1
+ import { TAP_TARGET_HEIGHT } from './tapTarget';
2
+
1
3
  /**
2
4
  * The single field-control class — driven ENTIRELY by the `--field-*` token layer
3
5
  * (see theme.css), so restyling every form control app-wide is a one-block change.
@@ -54,11 +56,11 @@ export const CONTROL_MIN_HEIGHT_CLASS: Record<ControlSize, string> = {
54
56
  * line up on the same baseline as every other control at the same `size`.
55
57
  */
56
58
  export function fieldControlClass(size: ControlSize = 'md'): string {
57
- // `pointer-coarse:min-h-11` — the `sm`/`md` tokens (32px/36px) clear a mouse
59
+ // `TAP_TARGET_HEIGHT` — the `sm`/`md` tokens (32px/36px) clear a mouse
58
60
  // pointer's norms but fall short of the 44px WCAG/HIG touch-target floor; widen
59
61
  // only on coarse pointers, same pattern as Button (owner orch-host 390px
60
62
  // teardown — the orchChat composer's task-type SelectField trigger measured
61
63
  // 356×32). Every `fieldControlClass` consumer (Input, SelectField, Date,
62
64
  // Combobox, …) inherits the fix for free.
63
- return `w-full rounded-field border border-field-border bg-field-bg px-3 ${CONTROL_HEIGHT_CLASS[size]} pointer-coarse:min-h-11 text-base text-field-fg placeholder:text-field-placeholder sm:text-sm focus-visible:border-field-ring focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-field-ring/30 aria-[invalid=true]:border-field-error aria-[invalid=true]:ring-field-error/30 disabled:cursor-not-allowed disabled:opacity-50`;
65
+ return `w-full rounded-field border border-field-border bg-field-bg px-3 ${CONTROL_HEIGHT_CLASS[size]} ${TAP_TARGET_HEIGHT} text-base text-field-fg placeholder:text-field-placeholder sm:text-sm focus-visible:border-field-ring focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-field-ring/30 aria-[invalid=true]:border-field-error aria-[invalid=true]:ring-field-error/30 disabled:cursor-not-allowed disabled:opacity-50`;
64
66
  }
@@ -6,6 +6,7 @@ import {
6
6
  FLOATING_CONTENT_BASE,
7
7
  FLOATING_ITEM_BASE,
8
8
  } from './floatingStyles';
9
+ import { TAP_TARGET_HEIGHT } from './tapTarget';
9
10
 
10
11
  const REACT_DIR = join(import.meta.dir, '..');
11
12
 
@@ -52,6 +53,6 @@ describe('the floating layer — DESIGN.md §5 containment', () => {
52
53
 
53
54
  test('a menu row clears 44px on a touch pointer', () => {
54
55
  // A mis-tap in a MENU costs the most: the neighbouring row is a different action.
55
- expect(FLOATING_ITEM_BASE).toContain('pointer-coarse:min-h-11');
56
+ expect(FLOATING_ITEM_BASE).toContain(TAP_TARGET_HEIGHT);
56
57
  });
57
58
  });
@@ -10,6 +10,8 @@
10
10
  * from `tw-animate-css`, which `src/styles.css` imports.
11
11
  */
12
12
 
13
+ import { TAP_TARGET_HEIGHT } from './tapTarget';
14
+
13
15
  /**
14
16
  * The gap a floating panel keeps from every viewport edge, in px.
15
17
  *
@@ -44,7 +46,7 @@ export const FLOATING_ITEM_BASE =
44
46
  // DESIGN.md §5's 44px floor, on coarse pointers only so the dense desktop menu
45
47
  // keeps its rhythm. A 32px menu row is a miss on a phone, and a menu is exactly
46
48
  // where a mis-tap costs the most: the neighbouring row is a different action.
47
- 'pointer-coarse:min-h-11 ' +
49
+ `${TAP_TARGET_HEIGHT} ` +
48
50
  'data-[disabled]:pointer-events-none data-[disabled]:opacity-50 ' +
49
51
  'focus:bg-accent/10 focus:text-accent';
50
52
 
@@ -0,0 +1,100 @@
1
+ /**
2
+ * `DESIGN.md` §5's tap floor, written once.
3
+ *
4
+ * > *"Every interactive text link, button, or tab on a mobile screen viewport MUST
5
+ * > maintain a minimum tap footprint of 44px x 44px."*
6
+ *
7
+ * ── 🔴 Why `pointer-coarse:` and not a plain `min-h-11` ─────────────────────
8
+ * The floor is about a FINGER, not about a narrow window. `pointer-coarse:` is a
9
+ * media query on the INPUT DEVICE, so a 390px-wide desktop window matches none of
10
+ * these utilities and a phone matches all of them. That is deliberate twice over:
11
+ * a 44px row of chips on a desktop toolbar is a toolbar that has lost its density
12
+ * (`DESIGN.md` §2 wants those controls on ONE line), and a mouse does not need the
13
+ * padding. The corollary is that **a narrow desktop window proves nothing** —
14
+ * `e2e/touch-targets.spec.ts` runs in a real touch profile, the only configuration
15
+ * in which any of this is switched on at all.
16
+ *
17
+ * ── Why a constant rather than the classes inline ───────────────────────────
18
+ * Because the floor was written out by hand 48 times across 33 files in this
19
+ * package, and a floor written 48 times is a floor that moves 47 times the next
20
+ * time it moves. The hover half below was hand-rolled in 12 separate places, each
21
+ * of which had to independently re-derive that a control revealed on hover does
22
+ * not exist on a phone. `apps/flix` then grew its own fourth-generation copy of
23
+ * all of it, because at the time it could not consume this package.
24
+ *
25
+ * Same kind of file, same reasons, as `floatingStyles.ts` next door — which
26
+ * carries this very floor inside `FLOATING_ITEM_BASE`.
27
+ *
28
+ * ── 🔴 Tailwind has to SEE these strings ────────────────────────────────────
29
+ * The JIT scans source TEXT for candidates; it does not evaluate anything. These
30
+ * constants therefore have to live under this package's own `@source "."` glob
31
+ * (declared in `src/styles.css`, rooted at `src/`) and has to spell each utility
32
+ * out as a literal — a class assembled at runtime from a variable is a class
33
+ * Tailwind never emits, and the symptom is not a type error or a failed build but
34
+ * a stylesheet with no `pointer-coarse` utilities in it at all, i.e. the floor
35
+ * silently gone fleet-wide. `src/tapTargetStylesheet.spec.ts` compiles the real
36
+ * stylesheet and fails on exactly that.
37
+ */
38
+
39
+ /**
40
+ * The HEIGHT half of the floor, alone — for a control that is already at least
41
+ * 44px wide by construction: a full-width row, a menu item, a table header, a
42
+ * text input, a chip with real padding.
43
+ *
44
+ * Kept separate from {@link TAP_TARGET} rather than folded into it because a
45
+ * `min-width` is not free everywhere: on a dense desktop-first control that a
46
+ * touch device merely needs to make TALLER, forcing 44px of width too is a layout
47
+ * change on a phone that nothing asked for.
48
+ */
49
+ export const TAP_TARGET_HEIGHT = 'pointer-coarse:min-h-11';
50
+
51
+ /**
52
+ * The floor for a control that sizes itself from its content — a text button, a
53
+ * chip, a nav tab, an icon button drawn small. Grows the box to 44×44 without
54
+ * touching padding, so nothing re-flows on a mouse.
55
+ *
56
+ * Pair it with `inline-flex items-center justify-center` on anything that is not
57
+ * already a flex container: a `min-height` on a plain `<button>` leaves the label
58
+ * riding at the top of the taller box in Firefox and Safari.
59
+ */
60
+ export const TAP_TARGET = `${TAP_TARGET_HEIGHT} pointer-coarse:min-w-11`;
61
+
62
+ /**
63
+ * The floor for a fixed-size ICON button — one that is deliberately a small
64
+ * square on a desktop (`h-7 w-7`, `h-9 w-9`) and must become a 44×44 target on a
65
+ * phone without its glyph growing with it.
66
+ */
67
+ export const TAP_TARGET_SQUARE = 'pointer-coarse:h-11 pointer-coarse:w-11';
68
+
69
+ /**
70
+ * The same 44×44, taken out of the surrounding layout.
71
+ *
72
+ * A poster's ⋯ trigger is anchored to a corner of the artwork. Growing it from
73
+ * 28px to 44px in place would push its visible disc 8px in from that corner on a
74
+ * phone and nowhere else, so the pill moves when you change device. The negative
75
+ * margin spends the extra 16px OUTWARD instead: the disc stays exactly where the
76
+ * design put it and the finger gets the other 8px on every side, over the poster
77
+ * and the gutter, where there is nothing else to hit.
78
+ *
79
+ * Use it for a control that is corner-anchored or overlaid on artwork. Do NOT use
80
+ * it inside a scrolling row or a clipped frame, where the 8px it takes back is
81
+ * somebody else's overflow.
82
+ */
83
+ export const TAP_TARGET_HALO = `${TAP_TARGET_SQUARE} pointer-coarse:-m-2`;
84
+
85
+ /**
86
+ * 🔴 A control that is only revealed on HOVER does not exist on a phone.
87
+ *
88
+ * The ⋯ menu on a poster rests at `opacity-0` and comes back on
89
+ * `group-hover`/`group-focus-within`. On a touch device there is no hover, and
90
+ * `:focus-within` needs a tap that has nowhere to land — so the whole tile menu
91
+ * (save, favorite, mark watched, hide) was measurable, invisible and unreachable
92
+ * on a phone when `apps/flix` measured it on 2026-09-07. The same fix was already
93
+ * hand-written at twelve sites in here — `FilterRail`'s action shelf and
94
+ * `StatTile`'s trend caption among them — which is twelve separate copies of
95
+ * knowing the trap and no way to find the thirteenth site that forgot.
96
+ *
97
+ * Anything that reveals itself on hover must pair that with this; the packaged
98
+ * version of the whole pattern is `REVEAL_ON_HOVER`.
99
+ */
100
+ export const TAP_TARGET_ALWAYS = 'pointer-coarse:opacity-100';
@@ -69,8 +69,8 @@ import {
69
69
  import { buildMaskImageData, rgbaToAlpha } from './maskRaster';
70
70
  import type { MaskPainterProps, MaskRegionResult } from './types';
71
71
 
72
- // Re-exported so the granular `cursedbelt/react/media/mask-painter` entry carries the
73
- // prop type without pulling the heavy media barrel (react-photo-album/vidstack/…).
72
+ // Re-exported alongside the component so a consumer of `cursedbelt/react/media` gets
73
+ // the prop type from the same module it imports the component from.
74
74
  export type { MaskPainterProps, MaskRegionResult } from './types';
75
75
 
76
76
  const DEFAULT_BRUSH = 40;
@@ -32,7 +32,7 @@ const QUALITY_OPTIONS = [
32
32
  * In-browser trim UI: a native `<video>` preview + a dual-handle range slider (with a
33
33
  * mediabunny/`<video>` filmstrip), format + quality choices, and a Trim action. No
34
34
  * ffmpeg in the browser — `onTrim` hands the chosen range to the app, which routes it
35
- * to the server (`cursedbelt/server/media` `trimVideo`). A Spinner overlays while the
35
+ * to the server (`cursedbelt/server` `trimVideo`). A Spinner overlays while the
36
36
  * server trims.
37
37
  */
38
38
  export function VideoTrimmer({
@@ -655,9 +655,9 @@
655
655
  }
656
656
  }
657
657
 
658
- /* ≥44px touch target on coarse pointers only — mirrors cursedbelt's shared
659
- Tailwind `pointer-coarse:min-h-11` convention (STANDARDS.md §4a), hand-rolled
660
- here since this is a plain `.cbgd-` CSS file, not a Tailwind className. */
658
+ /* ≥44px touch target on coarse pointers only — mirrors `TAP_TARGET_HEIGHT` from
659
+ src/react/lib/tapTarget.ts (STANDARDS.md §4a), hand-rolled here since this is a
660
+ plain `.cbgd-` CSS file, not a Tailwind className. */
661
661
  @media (pointer: coarse) {
662
662
  .cbgd-order-btn {
663
663
  min-height: 44px;
@@ -1,4 +1,4 @@
1
- // cursedbelt/react/media/ffmpeg-wasm — the browser executor for core/media
1
+ // src/react/media/ffmpegWasm — the browser executor for core/media
2
2
  // render plans. A DEDICATED subpath (like video-player): `@ffmpeg/ffmpeg` +
3
3
  // `@ffmpeg/util` are heavy OPTIONAL peers, loaded via dynamic import only when
4
4
  // an engine actually loads — apps that never export video bundle nothing.
@@ -83,7 +83,7 @@ export function createFfmpegWasmEngine(config: FfmpegWasmConfig = {}): FfmpegWas
83
83
  ]);
84
84
  } catch (cause) {
85
85
  throw new Error(
86
- 'cursedbelt/react/media/ffmpeg-wasm needs the optional peers "@ffmpeg/ffmpeg" and "@ffmpeg/util" — install them in your app to export video in the browser.',
86
+ 'cursedbelt/react/media needs the optional peers "@ffmpeg/ffmpeg" and "@ffmpeg/util" to export video in the browser — install them in your app.',
87
87
  { cause },
88
88
  );
89
89
  }
@@ -25,3 +25,45 @@
25
25
  width: var(--media-button-icon-size, 80%);
26
26
  height: var(--media-button-icon-size, 80%);
27
27
  }
28
+
29
+ /*
30
+ * ── 🔴 DESIGN.md §5's 44px tap floor, inside a DEPENDENCY's control bar ──────────────
31
+ *
32
+ * Vidstack draws its own buttons, and on a phone they are under the floor:
33
+ *
34
+ * theme.css --media-button-size 38px (every layout)
35
+ * layouts/video.css:111 --video-sm-button-size 36px (the small layout)
36
+ * theme.css --media-fullscreen-button-size 42px
37
+ * theme.css --media-sm-fullscreen-button-size 42px
38
+ *
39
+ * Measured 2026-09-14 on a Pixel 7 profile: `.vds-menu-button` ("Settings") and
40
+ * `.vds-fullscreen-button` both rendered 36×36 and reddened
41
+ * `e2e/touch-targets.spec.ts`. Nothing in this package had ever looked, because the
42
+ * floor was only ever enforced against controls THIS package draws — and the player
43
+ * is one of the few surfaces where a third party draws the buttons a thumb aims at.
44
+ *
45
+ * 🔴 Set the VARIABLES, never `.vds-button { width }`. Those four names are Vidstack's
46
+ * published override hooks, declared behind `:where()` so a plain custom property wins
47
+ * with no specificity war; overriding the box itself would be a second declaration of
48
+ * the bar's geometry and would drift on the next upgrade — the rule this file opens
49
+ * with. All four are needed, not just the small one: a tablet in landscape gets the
50
+ * wide layout (38px) and fullscreen has its own pair (42px). Every one of them is
51
+ * under 44.
52
+ *
53
+ * The glyph is deliberately left proportional (`--media-button-icon-size` stays at its
54
+ * 70% default) rather than pinned: it keeps `.cbvp-step`'s 80%-of-button relationship
55
+ * above intact — that rule reads the same variable — and a video control bar is the
56
+ * one place where a finger-sized target SHOULD carry a finger-sized glyph.
57
+ *
58
+ * `(pointer: coarse)`, not a width breakpoint: the floor is about a finger, and a
59
+ * narrow desktop window must not get a taller control bar. Same reasoning, and the
60
+ * same media query, as `src/react/lib/tapTarget.ts`.
61
+ */
62
+ @media (pointer: coarse) {
63
+ [data-media-player] {
64
+ --video-sm-button-size: 44px;
65
+ --media-button-size: 44px;
66
+ --media-fullscreen-button-size: 44px;
67
+ --media-sm-fullscreen-button-size: 44px;
68
+ }
69
+ }
@@ -8,8 +8,8 @@ export interface NamespaceTargetOption {
8
8
  /** `null` = the General pool (no namespace). */
9
9
  id: string | null;
10
10
  label: string;
11
- /** Colorway seed (0-359), same convention as `cursedbelt/namespace`'s
12
- * `Namespace.hue`. Omitted (e.g. General) renders a neutral dot. */
11
+ /** Colorway seed (0-359), hue-on-a-colour-wheel. Omitted (e.g. General)
12
+ * renders a neutral dot. */
13
13
  hue?: number;
14
14
  }
15
15
 
@@ -57,6 +57,7 @@ import {
57
57
  planOverflow,
58
58
  } from './breadcrumbModel';
59
59
  import { NavLink, type NavNavigationProps } from './navShared';
60
+ import { TAP_TARGET } from '../lib/tapTarget';
60
61
 
61
62
  /** Fallback width for the `…` trigger before one has ever been rendered. */
62
63
  const ESTIMATED_TRIGGER_WIDTH = 36;
@@ -552,7 +553,7 @@ const Crumb = memo(function Crumb({
552
553
  'flex min-w-0 items-center gap-1.5 rounded px-0.5 text-muted-foreground transition-colors ' +
553
554
  'hover:text-foreground hover:underline hover:decoration-border hover:underline-offset-4 ' +
554
555
  'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ' +
555
- 'pointer-coarse:min-h-11 pointer-coarse:min-w-11';
556
+ TAP_TARGET;
556
557
 
557
558
  const body = isLeaf ? (
558
559
  <span
@@ -651,7 +652,7 @@ function PivotTrigger({ node }: { node: BreadcrumbTrailNode }) {
651
652
  );
652
653
  const buttonClass =
653
654
  'h-6 w-6 shrink-0 rounded p-0 text-muted-foreground hover:text-foreground ' +
654
- 'pointer-coarse:min-h-11 pointer-coarse:min-w-11';
655
+ TAP_TARGET;
655
656
 
656
657
  if (isAsyncAction(action)) {
657
658
  const trigger = (
@@ -732,7 +733,7 @@ function OverflowMenu({
732
733
  onPointerEnter={onPointerEnter}
733
734
  onFocus={onFocus}
734
735
  onClick={onClick}
735
- className='h-6 w-8 shrink-0 rounded p-0 text-muted-foreground hover:text-foreground pointer-coarse:min-h-11 pointer-coarse:min-w-11'
736
+ className={`h-6 w-8 shrink-0 rounded p-0 text-muted-foreground hover:text-foreground ${TAP_TARGET}`}
736
737
  >
737
738
  <MoreHorizontal className='size-4' />
738
739
  </Button>
@@ -27,6 +27,7 @@ import {
27
27
  } from './navShared';
28
28
 
29
29
  import { Tooltip } from '../components/Tooltip';
30
+ import { TAP_TARGET } from '../lib/tapTarget';
30
31
  export interface HubTileGridProps extends NavNavigationProps {
31
32
  /** The domain whose items become tiles. */
32
33
  domain: NavDomain;
@@ -223,7 +224,7 @@ function Tile({
223
224
  // tabIndex AFTER the spread so it overrides dnd-kit's tabIndex=0 — the grip
224
225
  // is a pointer affordance only, never a Tab stop.
225
226
  tabIndex={-1}
226
- className={`inline-flex size-7 cursor-grab items-center justify-center rounded-md bg-background/80 text-muted-foreground backdrop-blur hover:text-foreground ${'pointer-coarse:min-h-11 pointer-coarse:min-w-11'}`}
227
+ className={`inline-flex size-7 cursor-grab items-center justify-center rounded-md bg-background/80 text-muted-foreground backdrop-blur hover:text-foreground ${TAP_TARGET}`}
227
228
  >
228
229
  <GripVertical className='size-4' />
229
230
  </button>
@@ -23,6 +23,7 @@ import {
23
23
  rankBySavedOrder,
24
24
  renderIcon,
25
25
  } from './navShared';
26
+ import { TAP_TARGET, TAP_TARGET_HEIGHT } from '../lib/tapTarget';
26
27
 
27
28
  /**
28
29
  * 🔴 Lazy on purpose, and the number is why: drag-to-reorder pulls three
@@ -335,14 +336,14 @@ function DomainRow({
335
336
  // A place that cannot work on THIS host stays VISIBLE and reads as
336
337
  // unavailable — never hidden. See `NavHostLimit`.
337
338
  limited && 'opacity-55',
338
- // `pointer-coarse:min-h-11`/`min-w-11` — a 36px-tall row (icon + `py-2`) or a
339
+ // `TAP_TARGET`/`TAP_TARGET_HEIGHT` — a 36px-tall row (icon + `py-2`) or a
339
340
  // 40px collapsed icon square both clear desktop mouse-target norms but fall
340
341
  // short of the 44px WCAG/HIG touch-target floor; widen only on coarse
341
342
  // pointers so the dense desktop rail keeps its compact rows (owner orch-host
342
343
  // 390px mobile-drawer teardown — sidenav rows measured 223×36).
343
344
  collapsed
344
- ? 'size-10 justify-center pointer-coarse:min-h-11 pointer-coarse:min-w-11'
345
- : 'w-full gap-3 px-3 py-2 pointer-coarse:min-h-11',
345
+ ? `size-10 justify-center ${TAP_TARGET}`
346
+ : `w-full gap-3 px-3 py-2 ${TAP_TARGET_HEIGHT}`,
346
347
  active ? 'bg-muted text-foreground' : 'text-foreground hover:bg-muted',
347
348
  )}
348
349
  >