@titan-design/react-ui 0.12.0 → 0.13.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 (509) hide show
  1. package/README.md +46 -47
  2. package/dist/bodymap.js +768 -701
  3. package/dist/bodymap.js.map +1 -1
  4. package/dist/bodymap.mjs +770 -703
  5. package/dist/bodymap.mjs.map +1 -1
  6. package/dist/index.d.mts +1320 -215
  7. package/dist/index.d.ts +1320 -215
  8. package/dist/index.js +5996 -4498
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.mjs +5773 -4357
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/{pages-CvsFqNtx.d.mts → pages-CpW3OB3g.d.mts} +21 -3
  13. package/dist/{pages-B1hqnGIC.d.ts → pages-_3Ajpiqu.d.ts} +21 -3
  14. package/dist/pages.d.mts +1 -1
  15. package/dist/pages.d.ts +1 -1
  16. package/dist/pages.js +1435 -1428
  17. package/dist/pages.js.map +1 -1
  18. package/dist/pages.mjs +1443 -1436
  19. package/dist/pages.mjs.map +1 -1
  20. package/dist/theme/index.d.mts +202 -1042
  21. package/dist/theme/index.d.ts +202 -1042
  22. package/dist/theme/index.js +215 -300
  23. package/dist/theme/index.js.map +1 -1
  24. package/dist/theme/index.mjs +202 -296
  25. package/dist/theme/index.mjs.map +1 -1
  26. package/dist/theme/tokens-css.js +62 -5
  27. package/dist/theme/tokens-css.js.map +1 -1
  28. package/dist/theme/tokens-css.mjs +62 -5
  29. package/dist/theme/tokens-css.mjs.map +1 -1
  30. package/dist/theme/tokens.d.mts +972 -0
  31. package/dist/theme/tokens.d.ts +972 -0
  32. package/dist/theme/tokens.js +904 -0
  33. package/dist/theme/tokens.js.map +1 -0
  34. package/dist/theme/tokens.mjs +880 -0
  35. package/dist/theme/tokens.mjs.map +1 -0
  36. package/docs/audits/2026-09-08-critique-addenda.md +51 -0
  37. package/docs/audits/2026-09-08-library-critique.md +212 -0
  38. package/docs/library-roadmap.md +99 -0
  39. package/package.json +7 -1
  40. package/src/arch/arch-graph.freshness.test.ts +52 -0
  41. package/src/arch/arch-graph.json +5021 -1617
  42. package/src/components/custom/ActiveWork/CoChangeChip.stories.tsx +44 -0
  43. package/src/components/custom/ActiveWork/CoChangeChip.test.tsx +29 -0
  44. package/src/components/custom/ActiveWork/CoChangeChip.tsx +48 -0
  45. package/src/components/custom/ActiveWork/Eyebrow.stories.tsx +25 -0
  46. package/src/components/custom/ActiveWork/Eyebrow.test.tsx +16 -0
  47. package/src/components/custom/ActiveWork/Eyebrow.tsx +26 -0
  48. package/src/components/custom/ActiveWork/FileActivityDetail.stories.tsx +50 -0
  49. package/src/components/custom/ActiveWork/FileActivityDetail.test.tsx +66 -0
  50. package/src/components/custom/ActiveWork/FileActivityDetail.tsx +202 -0
  51. package/src/components/custom/ActiveWork/FileActivityRow.stories.tsx +70 -0
  52. package/src/components/custom/ActiveWork/FileActivityRow.test.tsx +67 -0
  53. package/src/components/custom/ActiveWork/FileActivityRow.tsx +130 -0
  54. package/src/components/custom/ActiveWork/FileHistoryExplorer.stories.tsx +84 -0
  55. package/src/components/custom/ActiveWork/FileHistoryExplorer.test.tsx +99 -0
  56. package/src/components/custom/ActiveWork/FileHistoryExplorer.tsx +138 -0
  57. package/src/components/custom/ActiveWork/FilePathLabel.stories.tsx +39 -0
  58. package/src/components/custom/ActiveWork/FilePathLabel.test.tsx +53 -0
  59. package/src/components/custom/ActiveWork/FilePathLabel.tsx +63 -0
  60. package/src/components/custom/ActiveWork/InitiativeBrief.stories.tsx +50 -0
  61. package/src/components/custom/ActiveWork/InitiativeBrief.test.tsx +62 -0
  62. package/src/components/custom/ActiveWork/InitiativeBrief.tsx +181 -0
  63. package/src/components/custom/ActiveWork/InitiativeCard.stories.tsx +73 -0
  64. package/src/components/custom/ActiveWork/InitiativeCard.test.tsx +68 -0
  65. package/src/components/custom/ActiveWork/InitiativeCard.tsx +136 -0
  66. package/src/components/custom/ActiveWork/InitiativeHeader.stories.tsx +59 -0
  67. package/src/components/custom/ActiveWork/InitiativeHeader.test.tsx +40 -0
  68. package/src/components/custom/ActiveWork/InitiativeHeader.tsx +73 -0
  69. package/src/components/custom/ActiveWork/InitiativeReader.stories.tsx +145 -0
  70. package/src/components/custom/ActiveWork/OpenLoops.stories.tsx +58 -0
  71. package/src/components/custom/ActiveWork/OpenLoops.test.tsx +61 -0
  72. package/src/components/custom/ActiveWork/OpenLoops.tsx +107 -0
  73. package/src/components/custom/ActiveWork/PortfolioOverview.stories.tsx +101 -0
  74. package/src/components/custom/ActiveWork/PortfolioOverview.test.tsx +81 -0
  75. package/src/components/custom/ActiveWork/PortfolioOverview.tsx +83 -0
  76. package/src/components/custom/ActiveWork/README.md +305 -0
  77. package/src/components/custom/ActiveWork/SessionDetail.stories.tsx +71 -0
  78. package/src/components/custom/ActiveWork/SessionDetail.test.tsx +84 -0
  79. package/src/components/custom/ActiveWork/SessionDetail.tsx +180 -0
  80. package/src/components/custom/ActiveWork/SessionList.stories.tsx +69 -0
  81. package/src/components/custom/ActiveWork/SessionList.test.tsx +78 -0
  82. package/src/components/custom/ActiveWork/SessionList.tsx +103 -0
  83. package/src/components/custom/ActiveWork/SessionListItem.stories.tsx +64 -0
  84. package/src/components/custom/ActiveWork/SessionListItem.test.tsx +62 -0
  85. package/src/components/custom/ActiveWork/SessionListItem.tsx +152 -0
  86. package/src/components/custom/ActiveWork/SessionReader.stories.tsx +113 -0
  87. package/src/components/custom/ActiveWork/SeverityLabel.stories.tsx +51 -0
  88. package/src/components/custom/ActiveWork/SeverityLabel.test.tsx +68 -0
  89. package/src/components/custom/ActiveWork/SeverityLabel.tsx +97 -0
  90. package/src/components/custom/ActiveWork/TaskRow.stories.tsx +63 -0
  91. package/src/components/custom/ActiveWork/TaskRow.test.tsx +112 -0
  92. package/src/components/custom/ActiveWork/TaskRow.tsx +176 -0
  93. package/src/components/custom/ActiveWork/TaskTable.stories.tsx +123 -0
  94. package/src/components/custom/ActiveWork/TaskTable.test.tsx +233 -0
  95. package/src/components/custom/ActiveWork/TaskTable.tsx +321 -0
  96. package/src/components/custom/ActiveWork/active-work-depth.test.tsx +102 -0
  97. package/src/components/custom/ActiveWork/file-history-fixture.ts +91 -0
  98. package/src/components/custom/ActiveWork/format-time.test.ts +23 -0
  99. package/src/components/custom/ActiveWork/format-time.ts +32 -0
  100. package/src/components/custom/ActiveWork/index.ts +19 -0
  101. package/src/components/custom/ActiveWork/initiative-fixture.ts +104 -0
  102. package/src/components/custom/ActiveWork/session-fixture.ts +267 -0
  103. package/src/components/custom/ActiveWork/session-linkers.ts +56 -0
  104. package/src/components/custom/ActiveWork/task-list-fixture.ts +97 -0
  105. package/src/components/custom/CircularTimer/CircularTimer.stories.tsx +4 -3
  106. package/src/components/custom/DateTime/DateTime.stories.tsx +2 -1
  107. package/src/components/custom/DateTime/DateTime.test.tsx +3 -1
  108. package/src/components/custom/EmptyState/EmptyState.stories.tsx +22 -9
  109. package/src/components/custom/EmptyState/EmptyState.test.tsx +7 -13
  110. package/src/components/custom/EmptyState/EmptyState.tsx +4 -18
  111. package/src/components/custom/Fatigue/DualGhostSpark.stories.tsx +4 -3
  112. package/src/components/custom/Fatigue/FatigueLights.stories.tsx +2 -2
  113. package/src/components/custom/Fatigue/GhostSpark.stories.tsx +4 -3
  114. package/src/components/custom/Fatigue/LiveFatigueCard.stories.tsx +2 -2
  115. package/src/components/custom/Fatigue/LiveFatigueCard.tsx +8 -4
  116. package/src/components/custom/Fatigue/LiveFatiguePanel.stories.tsx +116 -6
  117. package/src/components/custom/Fatigue/LiveFatiguePanel.test.tsx +134 -0
  118. package/src/components/custom/Fatigue/LiveFatiguePanel.tsx +54 -83
  119. package/src/components/custom/Fatigue/README.md +40 -3
  120. package/src/components/custom/Fatigue/RomProgressionChart.stories.tsx +2 -2
  121. package/src/components/custom/Fatigue/SilverRedPalette.stories.tsx +2 -1
  122. package/src/components/custom/Fatigue/VelocityHero.stories.tsx +4 -3
  123. package/src/components/custom/Fatigue/VerdictHero.stories.tsx +2 -2
  124. package/src/components/custom/Fatigue/fatigue-mock.test.ts +0 -5
  125. package/src/components/custom/Fatigue/fatigue-mock.ts +2 -10
  126. package/src/components/custom/Fatigue/fatigue-tokens.ts +12 -0
  127. package/src/components/custom/Fatigue/index.ts +17 -5
  128. package/src/components/custom/Fatigue/panel-layout.test.ts +149 -0
  129. package/src/components/custom/Fatigue/panel-layout.ts +185 -0
  130. package/src/components/custom/Gauge/Gauge.stories.tsx +2 -2
  131. package/src/components/custom/Gauge/Gauge.test.tsx +1 -1
  132. package/src/components/custom/Gauge/Gauge.tsx +4 -1
  133. package/src/components/custom/Metric/Metric.stories.tsx +10 -1
  134. package/src/components/custom/Metric/Metric.test.tsx +1 -3
  135. package/src/components/custom/Metric/Metric.tsx +5 -20
  136. package/src/components/custom/Prose/MarkdownProse.stories.tsx +88 -0
  137. package/src/components/custom/Prose/MarkdownProse.test.tsx +87 -0
  138. package/src/components/custom/Prose/MarkdownProse.tsx +201 -0
  139. package/src/components/custom/Prose/README.md +58 -0
  140. package/src/components/custom/Prose/index.ts +1 -0
  141. package/src/components/custom/Scatter/Scatter.stories.tsx +46 -8
  142. package/src/components/custom/Scatter/Scatter.test.tsx +2 -2
  143. package/src/components/custom/Scatter/Scatter.tsx +116 -14
  144. package/src/components/custom/Sidebar/Sidebar.stories.tsx +40 -7
  145. package/src/components/custom/Sidebar/Sidebar.test.tsx +5 -1
  146. package/src/components/custom/Sidebar/Sidebar.tsx +16 -33
  147. package/src/components/custom/Table/Table.stories.tsx +98 -15
  148. package/src/components/custom/Table/Table.test.tsx +273 -86
  149. package/src/components/custom/Table/Table.tsx +159 -67
  150. package/src/components/custom/Table/column-fit.test.ts +75 -0
  151. package/src/components/custom/Table/column-fit.ts +116 -0
  152. package/src/components/custom/Table/index.ts +9 -0
  153. package/src/components/custom/TimerReadout/TimerReadout.stories.tsx +8 -6
  154. package/src/components/custom/Treemap/Treemap.stories.tsx +2 -2
  155. package/src/components/custom/Treemap/Treemap.test.tsx +1 -1
  156. package/src/components/custom/Treemap/Treemap.tsx +7 -2
  157. package/src/components/custom/Typography/Typography.stories.tsx +28 -1
  158. package/src/components/custom/Typography/Typography.test.tsx +34 -0
  159. package/src/components/custom/Typography/Typography.tsx +6 -0
  160. package/src/components/custom/Typography/index.ts +1 -8
  161. package/src/components/custom/Workout/ActiveWorkoutPage.stories.tsx +9 -1
  162. package/src/components/custom/Workout/BaseBadge.stories.tsx +19 -7
  163. package/src/components/custom/Workout/BaseBadge.test.tsx +31 -11
  164. package/src/components/custom/Workout/BaseBadge.tsx +3 -0
  165. package/src/components/custom/Workout/BodyMap.stories.tsx +4 -1
  166. package/src/components/custom/Workout/BodyMap.tsx +3 -1
  167. package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +16 -4
  168. package/src/components/custom/Workout/BodyMapDetailPanel.test.tsx +11 -15
  169. package/src/components/custom/Workout/BodyMapDetailPanel.tsx +45 -9
  170. package/src/components/custom/Workout/CapacityBandChart.stories.tsx +10 -8
  171. package/src/components/custom/Workout/CapacityBandChart.test.tsx +24 -51
  172. package/src/components/custom/Workout/CapacityBandChart.tsx +139 -108
  173. package/src/components/custom/Workout/DeviationBar.stories.tsx +1 -1
  174. package/src/components/custom/Workout/DeviationBar.test.tsx +5 -2
  175. package/src/components/custom/Workout/DeviationBar.tsx +21 -16
  176. package/src/components/custom/Workout/DualVelocityStrip.stories.tsx +182 -0
  177. package/src/components/custom/Workout/DualVelocityStrip.test.tsx +3 -2
  178. package/src/components/custom/Workout/ExerciseCard.stories.tsx +8 -7
  179. package/src/components/custom/Workout/ExerciseCard.test.tsx +13 -3
  180. package/src/components/custom/Workout/ExerciseCard.tsx +42 -51
  181. package/src/components/custom/Workout/ExerciseCardHeading.stories.tsx +7 -7
  182. package/src/components/custom/Workout/ExerciseDetailPage.stories.tsx +9 -1
  183. package/src/components/custom/Workout/ExerciseHeading.stories.tsx +8 -8
  184. package/src/components/custom/Workout/ExerciseHeading.tsx +8 -5
  185. package/src/components/custom/Workout/ExerciseIndicator.stories.tsx +6 -4
  186. package/src/components/custom/Workout/ExerciseIndicator.test.tsx +27 -11
  187. package/src/components/custom/Workout/ExerciseIndicator.tsx +14 -15
  188. package/src/components/custom/Workout/FatigueMeter.stories.tsx +5 -5
  189. package/src/components/custom/Workout/InputBar.stories.tsx +4 -5
  190. package/src/components/custom/Workout/IntensityBar.stories.tsx +1 -1
  191. package/src/components/custom/Workout/IntensityBar.test.tsx +5 -1
  192. package/src/components/custom/Workout/IntensityBar.tsx +4 -2
  193. package/src/components/custom/Workout/LiveAuraFrame.stories.tsx +5 -4
  194. package/src/components/custom/Workout/MesoCard.stories.tsx +4 -1
  195. package/src/components/custom/Workout/MesoCard.test.tsx +7 -18
  196. package/src/components/custom/Workout/MesoCard.tsx +12 -9
  197. package/src/components/custom/Workout/MesoProgressBar.stories.tsx +1 -1
  198. package/src/components/custom/Workout/MesoProgressBar.test.tsx +18 -11
  199. package/src/components/custom/Workout/MesoProgressBar.tsx +15 -13
  200. package/src/components/custom/Workout/MesoStatusCard.stories.tsx +2 -1
  201. package/src/components/custom/Workout/MesoStatusCard.test.tsx +14 -44
  202. package/src/components/custom/Workout/MesoStatusCard.tsx +9 -23
  203. package/src/components/custom/Workout/MetricTiles.stories.tsx +3 -2
  204. package/src/components/custom/Workout/MuscleGroupChip.stories.tsx +2 -8
  205. package/src/components/custom/Workout/MuscleGroupChip.test.tsx +23 -31
  206. package/src/components/custom/Workout/MuscleGroupChip.tsx +28 -67
  207. package/src/components/custom/Workout/PlaceholderStrip.stories.tsx +1 -1
  208. package/src/components/custom/Workout/PlaceholderStrip.test.tsx +17 -10
  209. package/src/components/custom/Workout/PlaceholderStrip.tsx +9 -8
  210. package/src/components/custom/Workout/PrBadge.stories.tsx +2 -1
  211. package/src/components/custom/Workout/PrBadge.test.tsx +3 -9
  212. package/src/components/custom/Workout/PrBadge.tsx +13 -17
  213. package/src/components/custom/Workout/PrHistoryModal.stories.tsx +4 -1
  214. package/src/components/custom/Workout/PrHistoryModal.test.tsx +13 -36
  215. package/src/components/custom/Workout/PrHistoryModal.tsx +8 -4
  216. package/src/components/custom/Workout/ProgramPlanningPage.stories.tsx +6 -1
  217. package/src/components/custom/Workout/README.md +12 -7
  218. package/src/components/custom/Workout/ReadinessCheck.stories.tsx +3 -2
  219. package/src/components/custom/Workout/ReadinessCheck.test.tsx +12 -18
  220. package/src/components/custom/Workout/ReadinessCheck.tsx +19 -3
  221. package/src/components/custom/Workout/RestTimer.stories.tsx +3 -2
  222. package/src/components/custom/Workout/ScheduleTiles.stories.tsx +3 -2
  223. package/src/components/custom/Workout/ScheduleTiles.test.tsx +3 -4
  224. package/src/components/custom/Workout/ScheduleTiles.tsx +4 -7
  225. package/src/components/custom/Workout/SegmentedBar.stories.tsx +5 -5
  226. package/src/components/custom/Workout/SegmentedBar.tsx +6 -2
  227. package/src/components/custom/Workout/SegmentedProgressBar.stories.tsx +5 -5
  228. package/src/components/custom/Workout/SessionHeader.stories.tsx +6 -6
  229. package/src/components/custom/Workout/SessionHeader.tsx +12 -12
  230. package/src/components/custom/Workout/SessionRail.stories.tsx +12 -11
  231. package/src/components/custom/Workout/SessionRail.tsx +7 -9
  232. package/src/components/custom/Workout/SetBar.stories.tsx +10 -6
  233. package/src/components/custom/Workout/SetBar.test.tsx +49 -4
  234. package/src/components/custom/Workout/SetBar.tsx +38 -12
  235. package/src/components/custom/Workout/SetRow.stories.tsx +3 -2
  236. package/src/components/custom/Workout/SetRow.test.tsx +16 -2
  237. package/src/components/custom/Workout/SetRow.tsx +61 -23
  238. package/src/components/custom/Workout/SetStrip.stories.tsx +60 -5
  239. package/src/components/custom/Workout/SetStrip.test.tsx +25 -0
  240. package/src/components/custom/Workout/SetStrip.tsx +24 -4
  241. package/src/components/custom/Workout/SetTableHeader.stories.tsx +6 -6
  242. package/src/components/custom/Workout/SetTableHeader.tsx +9 -12
  243. package/src/components/custom/Workout/SetsRepsLoad.stories.tsx +7 -7
  244. package/src/components/custom/Workout/SetsRepsLoad.tsx +3 -5
  245. package/src/components/custom/Workout/Sparkline.stories.tsx +1 -1
  246. package/src/components/custom/Workout/Sparkline.test.tsx +37 -19
  247. package/src/components/custom/Workout/Sparkline.tsx +14 -18
  248. package/src/components/custom/Workout/StatusDot.stories.tsx +1 -1
  249. package/src/components/custom/Workout/StatusDot.test.tsx +44 -5
  250. package/src/components/custom/Workout/StatusDot.tsx +93 -63
  251. package/src/components/custom/Workout/StatusPill.stories.tsx +1 -1
  252. package/src/components/custom/Workout/StatusPill.test.tsx +6 -15
  253. package/src/components/custom/Workout/StatusPill.tsx +27 -38
  254. package/src/components/custom/Workout/StrengthTrendChart.stories.tsx +9 -3
  255. package/src/components/custom/Workout/StrengthTrendChart.test.tsx +15 -37
  256. package/src/components/custom/Workout/StrengthTrendChart.tsx +31 -30
  257. package/src/components/custom/Workout/SupersetWrapper.stories.tsx +27 -64
  258. package/src/components/custom/Workout/SupersetWrapper.test.tsx +16 -14
  259. package/src/components/custom/Workout/SupersetWrapper.tsx +17 -21
  260. package/src/components/custom/Workout/TempoDisplay.stories.tsx +22 -7
  261. package/src/components/custom/Workout/TempoDisplay.test.tsx +18 -4
  262. package/src/components/custom/Workout/TrainingStatusPage.stories.tsx +9 -1
  263. package/src/components/custom/Workout/VelocityStrip.compact.stories.tsx +4 -1
  264. package/src/components/custom/Workout/VelocityStrip.dual.stories.tsx +7 -4
  265. package/src/components/custom/Workout/VelocityStrip.expanded.stories.tsx +4 -1
  266. package/src/components/custom/Workout/VelocityStrip.hero.stories.tsx +4 -1
  267. package/src/components/custom/Workout/VelocityStrip.stories.tsx +12 -6
  268. package/src/components/custom/Workout/VelocityStrip.tsx +3 -0
  269. package/src/components/custom/Workout/VolumeLandmarkBar.stories.tsx +6 -7
  270. package/src/components/custom/Workout/VolumeLandmarkBar.tsx +15 -6
  271. package/src/components/custom/Workout/WeekRow.stories.tsx +4 -1
  272. package/src/components/custom/Workout/WeekRow.test.tsx +18 -15
  273. package/src/components/custom/Workout/WeekRow.tsx +23 -16
  274. package/src/components/custom/Workout/WeightBadge.stories.tsx +2 -1
  275. package/src/components/custom/Workout/WeightBadge.test.tsx +50 -19
  276. package/src/components/custom/Workout/WeightBadge.tsx +28 -27
  277. package/src/components/custom/Workout/WorkoutCard.stories.tsx +6 -1
  278. package/src/components/custom/Workout/WorkoutCard.test.tsx +18 -0
  279. package/src/components/custom/Workout/WorkoutCard.tsx +35 -57
  280. package/src/components/custom/Workout/WorkoutPill.stories.tsx +5 -2
  281. package/src/components/custom/Workout/WorkoutPill.test.tsx +39 -7
  282. package/src/components/custom/Workout/WorkoutPill.tsx +88 -57
  283. package/src/components/custom/Workout/ZoneTrack.stories.tsx +7 -6
  284. package/src/components/custom/Workout/ZoneTrack.tsx +10 -9
  285. package/src/components/custom/Workout/index.ts +5 -0
  286. package/src/components/custom/Workout/metricText.stories.tsx +6 -5
  287. package/src/components/custom/Workout/metricText.tsx +4 -0
  288. package/src/components/custom/Workout/setHeadingKit.tsx +207 -26
  289. package/src/components/custom/charts/README.md +61 -0
  290. package/src/components/custom/charts/SetBarChart.test.tsx +30 -1
  291. package/src/components/custom/charts/SetBarChart.tsx +42 -4
  292. package/src/components/custom/charts/SparkBars.stories.tsx +55 -0
  293. package/src/components/custom/charts/SparkBars.test.tsx +69 -0
  294. package/src/components/custom/charts/SparkBars.tsx +85 -0
  295. package/src/components/custom/charts/index.ts +3 -0
  296. package/src/components/custom/index.ts +3 -0
  297. package/src/components/custom/stepper/Stepper.stories.tsx +13 -10
  298. package/src/components/custom/stepper/Stepper.test.tsx +1 -7
  299. package/src/components/custom/stepper/Stepper.tsx +13 -28
  300. package/src/components/icons/icons.stories.tsx +1 -1
  301. package/src/components/icons/icons.tsx +51 -0
  302. package/src/components/shell/AppShell.stories.tsx +150 -0
  303. package/src/components/shell/AppShell.test.tsx +70 -0
  304. package/src/components/shell/AppShell.tsx +90 -0
  305. package/src/components/shell/BrandLockup.stories.tsx +66 -5
  306. package/src/components/shell/BrandLockup.test.tsx +34 -1
  307. package/src/components/shell/BrandLockup.tsx +27 -11
  308. package/src/components/shell/NavItem.stories.tsx +4 -4
  309. package/src/components/shell/NavItem.test.tsx +17 -0
  310. package/src/components/shell/NavItem.tsx +17 -5
  311. package/src/components/shell/README.md +90 -27
  312. package/src/components/shell/SideNav.stories.tsx +38 -7
  313. package/src/components/shell/SideNav.test.tsx +16 -8
  314. package/src/components/shell/SideNav.tsx +17 -17
  315. package/src/components/shell/TopBar.stories.tsx +44 -19
  316. package/src/components/shell/TopBar.test.tsx +34 -12
  317. package/src/components/shell/TopBar.tsx +61 -40
  318. package/src/components/shell/brands.tsx +66 -0
  319. package/src/components/shell/index.ts +9 -8
  320. package/src/components/shell/{DeviceIndicator.stories.tsx → workout/DeviceIndicator.stories.tsx} +2 -2
  321. package/src/components/shell/{DeviceIndicator.tsx → workout/DeviceIndicator.tsx} +2 -2
  322. package/src/components/shell/{DeviceMenu.stories.tsx → workout/DeviceMenu.stories.tsx} +2 -2
  323. package/src/components/shell/{DeviceMenu.tsx → workout/DeviceMenu.tsx} +3 -3
  324. package/src/components/shell/{DeviceRow.stories.tsx → workout/DeviceRow.stories.tsx} +2 -2
  325. package/src/components/shell/{DeviceRow.tsx → workout/DeviceRow.tsx} +3 -3
  326. package/src/components/shell/{SessionStatePill.stories.tsx → workout/SessionStatePill.stories.tsx} +2 -2
  327. package/src/components/shell/{SessionStatePill.tsx → workout/SessionStatePill.tsx} +5 -3
  328. package/src/components/shell/workout/WorkoutShell.stories.tsx +71 -0
  329. package/src/components/shell/{DashboardShell.test.tsx → workout/WorkoutShell.test.tsx} +19 -8
  330. package/src/components/shell/workout/WorkoutShell.tsx +77 -0
  331. package/src/components/shell/workout/WorkoutTopBar.stories.tsx +58 -0
  332. package/src/components/shell/workout/WorkoutTopBar.test.tsx +39 -0
  333. package/src/components/shell/workout/WorkoutTopBar.tsx +52 -0
  334. package/src/components/shell/workout/index.ts +9 -0
  335. package/src/components/shell/workout/workoutNavItems.tsx +16 -0
  336. package/src/components/ui/README.md +110 -0
  337. package/src/components/ui/alert/Alert.stories.tsx +1 -1
  338. package/src/components/ui/autocomplete/Autocomplete.stories.tsx +11 -13
  339. package/src/components/ui/autocomplete/Autocomplete.test.tsx +7 -25
  340. package/src/components/ui/autocomplete/Autocomplete.tsx +21 -28
  341. package/src/components/ui/avatar/Avatar.stories.tsx +1 -1
  342. package/src/components/ui/avatar/Avatar.tsx +2 -10
  343. package/src/components/ui/badge/Badge.stories.tsx +83 -28
  344. package/src/components/ui/badge/Badge.test.tsx +19 -3
  345. package/src/components/ui/badge/Badge.tsx +48 -55
  346. package/src/components/ui/breadcrumbs/Breadcrumbs.stories.tsx +1 -1
  347. package/src/components/ui/breadcrumbs/Breadcrumbs.tsx +4 -16
  348. package/src/components/ui/button/Button.stories.tsx +46 -12
  349. package/src/components/ui/button/Button.tsx +32 -25
  350. package/src/components/ui/card/Card.stories.tsx +90 -94
  351. package/src/components/ui/card/Card.test.tsx +80 -6
  352. package/src/components/ui/card/Card.tsx +150 -203
  353. package/src/components/ui/checkbox/Checkbox.stories.tsx +1 -1
  354. package/src/components/ui/checkbox/Checkbox.tsx +6 -26
  355. package/src/components/ui/chip/Chip.stories.tsx +37 -13
  356. package/src/components/ui/chip/Chip.test.tsx +10 -6
  357. package/src/components/ui/chip/Chip.tsx +76 -91
  358. package/src/components/ui/collapse/Collapse.stories.tsx +23 -23
  359. package/src/components/ui/collapse/Collapse.tsx +6 -11
  360. package/src/components/ui/data-row/DataRow.stories.tsx +9 -2
  361. package/src/components/ui/data-row/DataRow.test.tsx +5 -15
  362. package/src/components/ui/data-row/DataRow.tsx +18 -7
  363. package/src/components/ui/divider/Divider.stories.tsx +1 -1
  364. package/src/components/ui/divider/Divider.tsx +1 -5
  365. package/src/components/ui/drawer/Drawer.stories.tsx +5 -16
  366. package/src/components/ui/drawer/Drawer.tsx +13 -30
  367. package/src/components/ui/floating-overlay-depth.test.tsx +143 -0
  368. package/src/components/ui/form-field/FormField.stories.tsx +6 -20
  369. package/src/components/ui/form-field/FormField.test.tsx +1 -5
  370. package/src/components/ui/form-field/FormField.tsx +10 -46
  371. package/src/components/ui/help-tip/HelpTip.stories.tsx +8 -19
  372. package/src/components/ui/help-tip/HelpTip.test.tsx +1 -3
  373. package/src/components/ui/help-tip/HelpTip.tsx +21 -22
  374. package/src/components/ui/help-tip/index.ts +7 -1
  375. package/src/components/ui/icon-box/IconBox.stories.tsx +1 -1
  376. package/src/components/ui/icon-box/IconBox.test.tsx +1 -7
  377. package/src/components/ui/icon-box/IconBox.tsx +2 -12
  378. package/src/components/ui/indicator/Indicator.stories.tsx +1 -1
  379. package/src/components/ui/indicator/Indicator.tsx +20 -14
  380. package/src/components/ui/input/Input.stories.tsx +3 -11
  381. package/src/components/ui/input/Input.test.tsx +2 -10
  382. package/src/components/ui/input/Input.tsx +10 -25
  383. package/src/components/ui/input/index.ts +7 -1
  384. package/src/components/ui/link/Link.stories.tsx +19 -7
  385. package/src/components/ui/list-item/ListItem.stories.tsx +11 -2
  386. package/src/components/ui/list-item/ListItem.tsx +2 -9
  387. package/src/components/ui/menu/Menu.stories.tsx +21 -15
  388. package/src/components/ui/menu/Menu.test.tsx +2 -11
  389. package/src/components/ui/menu/Menu.tsx +12 -14
  390. package/src/components/ui/menu/index.ts +8 -1
  391. package/src/components/ui/modal/Modal.stories.tsx +2 -2
  392. package/src/components/ui/modal/Modal.tsx +29 -19
  393. package/src/components/ui/pill/Pill.stories.tsx +58 -23
  394. package/src/components/ui/pill/Pill.test.tsx +101 -3
  395. package/src/components/ui/pill/Pill.tsx +164 -49
  396. package/src/components/ui/pill/index.ts +1 -1
  397. package/src/components/ui/popover/Popover.stories.tsx +5 -7
  398. package/src/components/ui/popover/Popover.test.tsx +1 -6
  399. package/src/components/ui/popover/Popover.tsx +20 -15
  400. package/src/components/ui/popover/index.ts +7 -1
  401. package/src/components/ui/progress/Progress.stories.tsx +3 -12
  402. package/src/components/ui/progress/Progress.test.tsx +1 -5
  403. package/src/components/ui/radio/Radio.stories.tsx +42 -21
  404. package/src/components/ui/radio/Radio.test.tsx +6 -2
  405. package/src/components/ui/radio/Radio.tsx +23 -22
  406. package/src/components/ui/section/Section.stories.tsx +5 -14
  407. package/src/components/ui/section/Section.test.tsx +1 -6
  408. package/src/components/ui/section/Section.tsx +1 -3
  409. package/src/components/ui/section/index.ts +1 -5
  410. package/src/components/ui/select/Select.stories.tsx +3 -13
  411. package/src/components/ui/select/Select.test.tsx +2 -11
  412. package/src/components/ui/select/Select.tsx +14 -14
  413. package/src/components/ui/skeleton/Skeleton.stories.tsx +3 -11
  414. package/src/components/ui/skeleton/Skeleton.tsx +3 -14
  415. package/src/components/ui/skeleton/index.ts +1 -7
  416. package/src/components/ui/spinner/Spinner.stories.tsx +1 -1
  417. package/src/components/ui/spinner/Spinner.tsx +1 -4
  418. package/src/components/ui/stack/Stack.stories.tsx +1 -1
  419. package/src/components/ui/stack/Stack.tsx +1 -1
  420. package/src/components/ui/surface/Surface.stories.tsx +17 -5
  421. package/src/components/ui/surface/Surface.test.tsx +88 -28
  422. package/src/components/ui/surface/Surface.tsx +37 -87
  423. package/src/components/ui/surface/SurfaceContext.ts +22 -62
  424. package/src/components/ui/surface/index.ts +8 -0
  425. package/src/components/ui/surface/resolveSurface.ts +98 -0
  426. package/src/components/ui/surface/surface.contract.test.ts +6 -1
  427. package/src/components/ui/switch/Switch.stories.tsx +1 -1
  428. package/src/components/ui/switch/Switch.tsx +7 -6
  429. package/src/components/ui/tabs/Tabs.stories.tsx +1 -1
  430. package/src/components/ui/tabs/Tabs.tsx +7 -22
  431. package/src/components/ui/tabs/index.ts +1 -7
  432. package/src/components/ui/tile/Tile.stories.tsx +1 -1
  433. package/src/components/ui/tile/Tile.tsx +3 -0
  434. package/src/components/ui/toast/Toast.stories.tsx +1 -1
  435. package/src/components/ui/toast/Toast.test.tsx +2 -8
  436. package/src/components/ui/toast/Toast.tsx +43 -53
  437. package/src/components/ui/toast/index.ts +0 -1
  438. package/src/components/ui/toolbar-button/ToolbarButton.stories.tsx +92 -71
  439. package/src/components/ui/toolbar-button/ToolbarButton.test.tsx +3 -18
  440. package/src/components/ui/toolbar-button/ToolbarButton.tsx +25 -43
  441. package/src/components/ui/tooltip/Tooltip.stories.tsx +12 -3
  442. package/src/components/ui/tooltip/Tooltip.test.tsx +21 -3
  443. package/src/components/ui/tooltip/Tooltip.tsx +55 -36
  444. package/src/components/ui/tooltip/index.ts +1 -1
  445. package/src/components/ui/trigger/TriggerSurface.test.tsx +215 -0
  446. package/src/components/ui/trigger/TriggerSurface.tsx +81 -0
  447. package/src/components/ui/trigger/index.ts +2 -0
  448. package/src/stories/PresetShowcase.stories.tsx +100 -47
  449. package/src/test/no-device-internals.test.ts +3 -3
  450. package/src/theme/ChoosingTokens.stories.tsx +48 -0
  451. package/src/theme/ColorPalettes.stories.tsx +62 -45
  452. package/src/theme/ColorPrimitives.stories.tsx +35 -35
  453. package/src/theme/Depth.stories.tsx +132 -65
  454. package/src/theme/DepthCalibration.stories.tsx +24 -22
  455. package/src/theme/ThemeProvider.test.tsx +4 -4
  456. package/src/theme/barrel.ts +7 -6
  457. package/src/theme/color-stories.coverage.test.ts +1 -1
  458. package/src/theme/color-utils.ts +41 -29
  459. package/src/theme/config.completeness.test.ts +1 -1
  460. package/src/theme/config.ts +28 -0
  461. package/src/theme/elevation.test.ts +82 -56
  462. package/src/theme/elevation.ts +77 -561
  463. package/src/theme/global.css +30 -2
  464. package/src/theme/grey-ramp.test.ts +24 -8
  465. package/src/theme/lift.test.ts +39 -0
  466. package/src/theme/lift.ts +102 -0
  467. package/src/theme/materials.test.ts +5 -2
  468. package/src/theme/materials.ts +38 -4
  469. package/src/theme/native-theming-guard.test.ts +5 -5
  470. package/src/theme/presets/apply.ts +4 -0
  471. package/src/theme/presets/audiobook.ts +5 -2
  472. package/src/theme/presets/default.ts +4 -0
  473. package/src/theme/presets/index.ts +14 -1
  474. package/src/theme/presets/types.ts +1 -1
  475. package/src/theme/semantic-contrast.test.ts +13 -4
  476. package/src/theme/status-distinctness.test.ts +66 -0
  477. package/src/theme/surface-planes.test.ts +37 -0
  478. package/src/theme/surface-planes.ts +68 -0
  479. package/src/theme/token-export-guard.test.ts +102 -0
  480. package/src/theme/tokens/primitives.test.ts +15 -7
  481. package/src/theme/tokens/primitives.ts +67 -35
  482. package/src/theme/tokens/semantic.ts +71 -37
  483. package/src/theme/wash-ladder.test.ts +58 -0
  484. package/src/theme/workout-tokens.ts +1 -7
  485. package/src/types/jest-axe.d.ts +2 -6
  486. package/src/types/raw-md.d.ts +5 -0
  487. package/src/utils/colors.ts +4 -4
  488. package/src/utils/form.ts +1 -3
  489. package/src/utils/index.ts +2 -7
  490. package/src/utils/number-format.ts +17 -0
  491. package/src/utils/workout-format.ts +15 -6
  492. package/src/web-jsx/jsx-runtime.ts +1 -5
  493. package/tailwind.config.js +5 -0
  494. package/src/components/custom/Workout/ExerciseCardUnified.stories.tsx +0 -151
  495. package/src/components/custom/Workout/RowInventory.stories.tsx +0 -408
  496. package/src/components/custom/Workout/S3FullRail.stories.tsx +0 -46
  497. package/src/components/custom/Workout/S3SessionPace.stories.tsx +0 -95
  498. package/src/components/custom/Workout/S3SessionRailHeading.stories.tsx +0 -61
  499. package/src/components/custom/Workout/S3SetTypes.stories.tsx +0 -176
  500. package/src/components/custom/Workout/S3WorkoutExpansion.stories.tsx +0 -240
  501. package/src/components/shell/DashboardShell.stories.tsx +0 -65
  502. package/src/components/shell/DashboardShell.tsx +0 -75
  503. package/src/components/shell/SessionRailSpecimen.stories.tsx +0 -753
  504. package/src/theme/elevation.stories.tsx +0 -346
  505. package/src/utils/useTheme.ts +0 -72
  506. /package/src/components/shell/{DeviceIndicator.test.tsx → workout/DeviceIndicator.test.tsx} +0 -0
  507. /package/src/components/shell/{DeviceMenu.test.tsx → workout/DeviceMenu.test.tsx} +0 -0
  508. /package/src/components/shell/{DeviceRow.test.tsx → workout/DeviceRow.test.tsx} +0 -0
  509. /package/src/components/shell/{SessionStatePill.test.tsx → workout/SessionStatePill.test.tsx} +0 -0
@@ -1,176 +0,0 @@
1
- /**
2
- * SHEET · Session Rail — set-type encodings (R&D). Throwaway specimen at real rail width, on real tokens.
3
- * Explores the cases the flat `sets × reps @ load` strip doesn't model:
4
- * 1. Variable rep-range — range-max segments; the variable zone (floor→max) upcoming part gets its OWN color.
5
- * 2. Drop set — ONE bar, sub-loads separated by thin NOTCHES (< the between-set gap); reps velocity-colored.
6
- * 3. Myo-rep / rest-pause — activation chunk + mini-clusters separated by small cluster gaps.
7
- * Gap hierarchy: butted reps (0) < notch (2, drop sub-load) < cluster gap (3, myo rest-pause) < SET_GAP (5, sets).
8
- * Hardens into a SetStrip model extension (SetState variants: range/drop/myo) — a post-harden follow-up.
9
- */
10
- import type { Meta, StoryObj } from '@storybook/react-vite'
11
- import { Fragment } from 'react'
12
- import { primitiveRamps as ramp, greyRamp } from '../../../theme/tokens/primitives'
13
- import { GREY, RAIL_W, SET_GAP, T_PRIMARY, T_SECONDARY, T_TERTIARY, INSET, velColor, reps, Page, sectionTitle } from './setHeadingKit'
14
-
15
- // ---- variable-zone (floor→max) upcoming color — real ramp candidates (no invented hex)
16
- const VAR_GREY = greyRamp[800] // #3C3C3C — lighter grey (the paler-grey reference)
17
- const VAR_BLUE_800 = ramp.blue[800] // #14407E — clearly blue, a touch brighter
18
- const VAR_BLUE_900 = ramp.blue[900] // #112C5A — dark muted navy, recessive
19
- const VAR_CYAN_900 = ramp.cyan[900] // #0B3149 — teal alt, sidesteps info-blue adjacency
20
- const NOTCH = 2 // drop sub-load divider
21
- const CLUSTER_GAP = 3 // myo rest-pause divider
22
-
23
- type Chunk = { colors: string[]; gapAfter?: number }
24
- function Bar({ chunks, h }: { chunks: Chunk[]; h: number }) {
25
- return (
26
- <div style={{ display: 'flex', width: '100%', height: h, borderRadius: 2, overflow: 'hidden' }}>
27
- {chunks.map((ch, ci) => (
28
- <Fragment key={ci}>
29
- {ch.colors.map((c, i) => (
30
- <div key={i} style={{ flex: 1, minWidth: 0, height: '100%', background: c }} />
31
- ))}
32
- {ci < chunks.length - 1 && <div style={{ flex: `0 0 ${ch.gapAfter ?? NOTCH}px`, height: '100%', background: INSET }} />}
33
- </Fragment>
34
- ))}
35
- </div>
36
- )
37
- }
38
-
39
- // ---- 1. variable rep-range: `max` segments; committed 0..floor, variable floor..max; variable-todo gets VAR color
40
- function rangeColors(floor: number, max: number, doneVels: number[], varColor: string): string[] {
41
- return Array.from({ length: max }, (_, i) => {
42
- if (i < doneVels.length) return velColor(doneVels[i])
43
- return i < floor ? GREY : varColor
44
- })
45
- }
46
- function RangeBar({ floor, max, done, varColor, h }: { floor: number; max: number; done: number[]; varColor: string; h: number }) {
47
- return <Bar chunks={[{ colors: rangeColors(floor, max, done, varColor) }]} h={h} />
48
- }
49
-
50
- // ---- 2. drop set: one bar, sub-loads butted internally, separated by thin notches
51
- function DropBar({ subloads, h }: { subloads: number[][]; h: number }) {
52
- const chunks: Chunk[] = subloads.map((vels, i) => ({ colors: vels.map(velColor), gapAfter: NOTCH, ...(i === subloads.length - 1 ? { gapAfter: undefined } : {}) }))
53
- return <Bar chunks={chunks} h={h} />
54
- }
55
-
56
- // ---- 3. myo-rep: activation chunk + mini-clusters, separated by cluster gaps
57
- function MyoBar({ activation, clusters, h }: { activation: number[]; clusters: number[][]; h: number }) {
58
- const chunks: Chunk[] = [{ colors: activation.map(velColor), gapAfter: CLUSTER_GAP }, ...clusters.map((c) => ({ colors: c.map(velColor), gapAfter: CLUSTER_GAP }))]
59
- return <Bar chunks={chunks} h={h} />
60
- }
61
-
62
- // ---- 3b. UPCOMING myo, unknown length: grey activation (expected) + a blue "clusters-to-failure" trail
63
- // that fades and leaves the right edge open — signalling "N more clusters, count unknown".
64
- function MyoUpcomingBar({ activationLen, blue, h }: { activationLen: number; blue: string; h: number }) {
65
- const fades = [1, 0.6, 0.32] // decreasing opacity per expected cluster → "and maybe more"
66
- return (
67
- <div style={{ display: 'flex', width: '100%', height: h, gap: 0 }}>
68
- <div style={{ display: 'flex', flex: activationLen, height: '100%', borderRadius: '2px 0 0 2px', overflow: 'hidden' }}>
69
- {Array.from({ length: activationLen }, (_, i) => (
70
- <div key={i} style={{ flex: 1, height: '100%', background: GREY }} />
71
- ))}
72
- </div>
73
- {fades.map((op, ci) => (
74
- <Fragment key={ci}>
75
- <div style={{ flex: `0 0 ${CLUSTER_GAP}px`, height: '100%', background: INSET }} />
76
- <div style={{ display: 'flex', flex: 5, height: '100%', overflow: 'hidden', opacity: op }}>
77
- {Array.from({ length: 5 }, (_, i) => (
78
- <div key={i} style={{ flex: 1, height: '100%', background: blue }} />
79
- ))}
80
- </div>
81
- </Fragment>
82
- ))}
83
- </div>
84
- )
85
- }
86
-
87
- // ---- row scaffold at real rail width, on the sunk inset surface
88
- function Row({ name, meta, children }: { name: string; meta: string; children: React.ReactNode }) {
89
- return (
90
- <div style={{ width: RAIL_W, background: INSET, padding: '9px 12px', borderRadius: 4 }}>
91
- <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, marginBottom: 6 }}>
92
- <span style={{ fontSize: 14, fontWeight: 800, color: T_PRIMARY }}>{name}</span>
93
- <div style={{ flex: 1 }} />
94
- <span style={{ fontSize: 10, fontFamily: 'monospace', color: T_TERTIARY }}>{meta}</span>
95
- </div>
96
- {children}
97
- </div>
98
- )
99
- }
100
- function Col({ label, children }: { label: string; children: React.ReactNode }) {
101
- return (
102
- <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
103
- <span style={{ ...sectionTitle, color: T_SECONDARY }}>{label}</span>
104
- {children}
105
- </div>
106
- )
107
- }
108
-
109
- const H = 8
110
-
111
- function Sheet() {
112
- return (
113
- <Page title="Session Rail — set-type encodings" note="R&D for prescriptions the flat sets×reps strip doesn't model. Rail width, real velocity ramp pins. Rep-range: range-max segments, the variable zone (floor→max) upcoming part gets its own color. Drop: one bar, sub-loads split by thin notches. Myo: activation + mini-clusters split by cluster gaps.">
114
- <div style={{ display: 'flex', gap: 40, flexWrap: 'wrap', alignItems: 'flex-start' }}>
115
- {/* 1. variable rep-range — real ramp candidates for the variable zone */}
116
- <Col label="1 · variable rep-range — LOCKED: cyan 900">
117
- {([
118
- ['grey · grey 200', VAR_GREY],
119
- ['blue 800 · #14407E', VAR_BLUE_800],
120
- ['blue 900 · #112C5A', VAR_BLUE_900],
121
- ['cyan 900 · #0B3149', VAR_CYAN_900],
122
- ] as const).map(([label, c]) => (
123
- <Row key={label} name="Face Pull" meta="3 × 15–20 @ 40">
124
- <span style={{ fontSize: 9, color: T_TERTIARY, display: 'block', marginBottom: 5 }}>{label}</span>
125
- <div style={{ display: 'flex', flexDirection: 'column', gap: SET_GAP }}>
126
- <RangeBar floor={15} max={20} done={[]} varColor={c} h={H} />
127
- <RangeBar floor={15} max={20} done={reps(12, 0.9)} varColor={c} h={H} />
128
- <RangeBar floor={15} max={20} done={reps(17, 0.8)} varColor={c} h={H} />
129
- </div>
130
- </Row>
131
- ))}
132
- <span style={{ fontSize: 10, color: T_TERTIARY, maxWidth: RAIL_W }}>Each block: todo · 12 done (committed) · 17 done (into the variable zone). Variable-todo = the swatch; committed-todo = grey.</span>
133
- </Col>
134
-
135
- {/* 2. drop set */}
136
- <Col label="2 · drop set">
137
- <Row name="Lat Pulldown" meta="1 drop · 10→8→6 @ 120→80">
138
- <DropBar subloads={[reps(10, 0.85), reps(8, 0.7), reps(6, 0.6)]} h={H} />
139
- </Row>
140
- <Row name="Leg Extension" meta="1 drop · 12→10→8→6 @ 90→45">
141
- <DropBar subloads={[reps(12, 0.8), reps(10, 0.7), reps(8, 0.62), reps(6, 0.55)]} h={H} />
142
- </Row>
143
- <span style={{ fontSize: 10, color: T_TERTIARY, maxWidth: RAIL_W }}>One set, no rest; notches mark each load drop. Notch (2px) &lt; set gap (5px) so drops read as sub-structure of a single set.</span>
144
- </Col>
145
-
146
- {/* 3. myo-rep */}
147
- <Col label="3 · myo-rep / rest-pause">
148
- <Row name="Cable Curl" meta="myo · done · 15 + 5 + 5 + 5">
149
- <MyoBar activation={reps(15, 0.75)} clusters={[reps(5, 0.6), reps(5, 0.55), reps(5, 0.5)]} h={H} />
150
- </Row>
151
- <Row name="Triceps Pushdown" meta="myo · done · 12 + 4 + 4">
152
- <MyoBar activation={reps(12, 0.7)} clusters={[reps(4, 0.55), reps(4, 0.5)]} h={H} />
153
- </Row>
154
- <span style={{ fontSize: 10, color: T_TERTIARY, maxWidth: RAIL_W }}>Done: activation to near-failure, then rest-pause clusters. Cluster gap (3px) between notch and set gap.</span>
155
- <span style={{ ...sectionTitle, color: T_SECONDARY, marginTop: 6 }}>upcoming · length unknown</span>
156
- <Row name="Cable Curl" meta="myo · ~15 + clusters to failure">
157
- <MyoUpcomingBar activationLen={15} blue={VAR_CYAN_900} h={H} />
158
- </Row>
159
- <Row name="Triceps Pushdown" meta="myo · ~12 + clusters to failure">
160
- <MyoUpcomingBar activationLen={12} blue={VAR_CYAN_900} h={H} />
161
- </Row>
162
- <span style={{ fontSize: 10, color: T_TERTIARY, maxWidth: RAIL_W }}>{'Grey activation (expected) + blue "clusters-to-failure" trail that fades and leaves the right edge open — reuses the variable/opportunity blue, signalling "more coming, count unknown."'}</span>
163
- </Col>
164
- </div>
165
- </Page>
166
- )
167
- }
168
-
169
- const meta: Meta = {
170
- title: 'Lab/Explorations/Set Types',
171
- parameters: { layout: 'fullscreen' },
172
- }
173
- export default meta
174
- type Story = StoryObj
175
-
176
- export const Encodings: Story = { render: () => <Sheet /> }
@@ -1,240 +0,0 @@
1
- /**
2
- * SHEET · Workout Expansion (page 2) — what a rail item reveals when expanded.
3
- * Anchored on the REAL unexpanded rail row (`ExerciseCardHeading`) as the persistent header, then the
4
- * revealed body in two REAL-component directions so the fork is concrete:
5
- * A — Table (real `SetTableHeader` + real `SetRow`s — the current expanded body).
6
- * C — Embed (real `VelocityStrip` full/expanded per set + a compact caption — the bar IS the set).
7
- * B (drop PREV) is a trivial prop on the table, noted but not forked here. Same data across both: set 1 done
8
- * · set 2 LIVE 5/10 · set 3 upcoming, with velocities that DECAY within a set so the "shape" reading is real.
9
- * OPEN: A-vs-C · live-set treatment in the body · read-only density (drop TEMPO row? per-row strips?). DECISIONS doc.
10
- */
11
- import type { Meta, StoryObj } from '@storybook/react-vite'
12
- import { View, Text } from 'react-native'
13
- import { ExerciseCardHeading } from './ExerciseCardHeading'
14
- import { SetTableHeader } from './SetTableHeader'
15
- import { SetRow, type SetRowProps } from './SetRow'
16
- import { VelocityStrip } from './VelocityStrip'
17
- import { type SetStripSet } from './SetStrip'
18
- import {
19
- INSET,
20
- INSET_SHADOW,
21
- RAISED,
22
- BORDER_SUBTLE,
23
- GREEN,
24
- T_PRIMARY,
25
- T_SECONDARY,
26
- T_TERTIARY,
27
- Page,
28
- sectionTitle,
29
- monoTag,
30
- } from './setHeadingKit'
31
-
32
- // Per-rep mean velocity that DECAYS across a set (fast → slow) so bar height/color carries shape.
33
- const decay = (n: number, start: number, span = 0.5) =>
34
- Array.from({ length: n }, (_, r) => +(start - (span * r) / Math.max(1, n - 1)).toFixed(3))
35
-
36
- // ---- shared data (real prop shapes) ------------------------------------------------
37
- // Heading strip (SetStripSet[]): set1 done · set2 active 5/10 · set3 todo.
38
- const HEADING_STATES: SetStripSet[] = [
39
- { status: 'done', velocities: decay(10, 1.05) },
40
- { status: 'active', velocities: decay(5, 0.95, 0.3), planned: 10 },
41
- { status: 'todo', planned: 10 },
42
- ]
43
- // Expanded-body per-set rows (real SetRowProps): set 1 done · set 2 LIVE · set 3 todo.
44
- const BODY_SETS: SetRowProps[] = [
45
- {
46
- state: 'done',
47
- setNumber: 1,
48
- reps: 10,
49
- weight: 90,
50
- rpe: 7.5,
51
- unit: 'lbs',
52
- velocities: decay(10, 1.05),
53
- },
54
- {
55
- state: 'live',
56
- setNumber: 2,
57
- unit: 'lbs',
58
- target: { reps: 10, weight: 90 },
59
- reps: 10,
60
- weight: 90,
61
- velocities: decay(5, 0.95, 0.3),
62
- },
63
- { state: 'todo', setNumber: 3, unit: 'lbs', target: { reps: 10, weight: 90 } },
64
- ]
65
-
66
- // ---- the real unexpanded rail row, used as the persistent expansion header ---------
67
- function RailHeader() {
68
- return (
69
- <View style={{ position: 'relative', zIndex: 2, backgroundColor: RAISED }}>
70
- <ExerciseCardHeading
71
- name="Cable Chest Press"
72
- sets={3}
73
- reps={10}
74
- load={90}
75
- unit="lbs"
76
- tempo={[2, 1, 2, 0]}
77
- indicator="info"
78
- setStates={HEADING_STATES}
79
- />
80
- </View>
81
- )
82
- }
83
-
84
- // ---- A · table body: real SetTableHeader + real SetRow (LOCKED: drop PREV, keep strips)
85
- function TableBody() {
86
- return (
87
- <View>
88
- <SetTableHeader unit="lbs" showPrevious={false} />
89
- {BODY_SETS.map((s, i) => (
90
- <SetRow key={i} {...s} />
91
- ))}
92
- </View>
93
- )
94
- }
95
-
96
- // ---- C · embed body: real VelocityStrip (full/expanded) per set + compact caption ---
97
- const capText = {
98
- fontFamily: 'Inter, sans-serif',
99
- fontSize: 11,
100
- fontWeight: '600' as const,
101
- color: T_PRIMARY,
102
- }
103
- const dimText = { ...capText, color: T_SECONDARY, fontWeight: '500' as const }
104
- function EmbedSetRow({ s }: { s: SetRowProps }) {
105
- const live = s.state === 'live'
106
- const todo = s.state === 'todo'
107
- const vels = s.state === 'done' || s.state === 'live' ? s.velocities : []
108
- const rpe = s.state === 'todo' ? null : s.rpe
109
- return (
110
- <View
111
- style={{
112
- paddingVertical: 7,
113
- paddingHorizontal: 10,
114
- marginHorizontal: 2,
115
- marginBottom: 4,
116
- borderRadius: 8,
117
- opacity: todo ? 0.55 : 1,
118
- ...(live
119
- ? {
120
- backgroundColor: 'rgba(46,213,115,0.06)',
121
- borderWidth: 1,
122
- borderColor: 'rgba(46,213,115,0.30)',
123
- }
124
- : {}),
125
- }}
126
- >
127
- <View style={{ flexDirection: 'row', alignItems: 'baseline', marginBottom: 6 }}>
128
- <Text style={{ ...dimText, width: 22, color: T_TERTIARY }}>{s.setNumber}</Text>
129
- {s.state === 'live' ? (
130
- <Text style={{ ...capText, color: GREEN, fontWeight: '700' }}>
131
- {vels.length}/{s.target.reps} × {s.target.weight}
132
- </Text>
133
- ) : s.state === 'done' ? (
134
- <Text style={capText}>
135
- {s.reps} × {s.weight}
136
- </Text>
137
- ) : (
138
- <Text style={dimText}>
139
- {s.target.reps} × {s.target.weight}
140
- </Text>
141
- )}
142
- <View style={{ flex: 1 }} />
143
- {rpe != null && <Text style={dimText}>RPE {rpe}</Text>}
144
- {live && <Text style={{ ...capText, color: GREEN, fontWeight: '700' }}>live</Text>}
145
- </View>
146
- {vels.length > 0 ? (
147
- <VelocityStrip velocities={vels} variant="expanded" showInfo={false} />
148
- ) : (
149
- <View style={{ height: 24, flexDirection: 'row', gap: 2 }}>
150
- {Array.from({ length: s.state === 'todo' ? s.target.reps : 10 }).map((_, i) => (
151
- <View
152
- key={i}
153
- style={{
154
- flex: 1,
155
- height: 6,
156
- alignSelf: 'flex-end',
157
- backgroundColor: '#2C2C2C',
158
- borderRadius: 1,
159
- opacity: 0.5,
160
- }}
161
- />
162
- ))}
163
- </View>
164
- )}
165
- </View>
166
- )
167
- }
168
- function EmbedBody() {
169
- return (
170
- <View style={{ paddingTop: 6 }}>
171
- {BODY_SETS.map((s, i) => (
172
- <EmbedSetRow key={i} s={s} />
173
- ))}
174
- </View>
175
- )
176
- }
177
-
178
- // ---- expanded item = real rail header + revealed body ------------------------------
179
- function ExpandedItem({ label, children }: { label: string; children: React.ReactNode }) {
180
- return (
181
- <View style={{ gap: 8 }}>
182
- <Text style={{ ...monoTag, color: T_SECONDARY }}>{label}</Text>
183
- <View
184
- style={
185
- {
186
- width: 260,
187
- backgroundColor: INSET,
188
- boxShadow: INSET_SHADOW,
189
- borderRadius: 4,
190
- overflow: 'hidden',
191
- } as object
192
- }
193
- >
194
- <RailHeader />
195
- <View
196
- style={{
197
- backgroundColor: INSET,
198
- paddingBottom: 8,
199
- borderTopWidth: 1,
200
- borderTopColor: BORDER_SUBTLE,
201
- }}
202
- >
203
- {children}
204
- </View>
205
- </View>
206
- </View>
207
- )
208
- }
209
-
210
- const meta: Meta = {
211
- title: 'Lab/Explorations/Workout Expansion',
212
- parameters: { layout: 'fullscreen' },
213
- }
214
- export default meta
215
- type Story = StoryObj
216
-
217
- export const DirectionStudy: Story = {
218
- name: 'Expanded item · A table / C embed-in-bar (real components)',
219
- render: () => (
220
- <Page
221
- title="Workout expansion — direction study (page 2)"
222
- note="LOCKED (2026-07-10): body = direction A, the SetTableHeader+SetRow table, with PREV dropped (real showPrevious={false}) and the per-row velocity strips kept. C (per-rep VelocityStrip becomes the set row) shown for the record — rejected as too novel; the table already carries velocity shape via the per-row strip. Anchored on the REAL unexpanded rail row (ExerciseCardHeading) as the persistent header; data: set 1 done · set 2 live 5/10 · set 3 upcoming, velocities decaying within a set."
223
- >
224
- <View style={{ flexDirection: 'row', gap: 44, alignItems: 'flex-start', flexWrap: 'wrap' }}>
225
- <View style={{ gap: 12 }}>
226
- <Text style={sectionTitle}>A · Table (current body)</Text>
227
- <ExpandedItem label="real SetTableHeader + SetRow">
228
- <TableBody />
229
- </ExpandedItem>
230
- </View>
231
- <View style={{ gap: 12 }}>
232
- <Text style={sectionTitle}>C · Embed in the bar</Text>
233
- <ExpandedItem label="real VelocityStrip (full) + caption">
234
- <EmbedBody />
235
- </ExpandedItem>
236
- </View>
237
- </View>
238
- </Page>
239
- ),
240
- }
@@ -1,65 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite'
2
- import { View, Text } from 'react-native'
3
- import { DashboardShell } from './DashboardShell'
4
-
5
- /**
6
- * `Pages/DashboardShell` — the wall-dashboard chrome as one registered surface.
7
- * Composes the shell-nav island (SideNav + TopBar and everything they pull in) over a
8
- * `children` content slot, so the dashboard app mounts a single component.
9
- */
10
- const meta: Meta<typeof DashboardShell> = {
11
- title: 'Pages/DashboardShell',
12
- component: DashboardShell,
13
- tags: ['autodocs'],
14
- parameters: {
15
- layout: 'fullscreen',
16
- docs: {
17
- description: {
18
- component:
19
- '**Page shell.** The wall-dashboard chrome. Composes ' +
20
- '[SideNav](?path=/docs/shell-sidenav--docs) + ' +
21
- '[TopBar](?path=/docs/shell-topbar--docs) — which pulls in DeviceMenu, DeviceRow, ' +
22
- 'DeviceIndicator, SessionStatePill, BrandLockup, DateTime and Divider — over a ' +
23
- '`children` content slot. Mount this instead of re-assembling the chrome per view.',
24
- },
25
- },
26
- },
27
- argTypes: {
28
- state: { control: 'select', options: ['live', 'rest', 'idle'] },
29
- activeKey: { control: 'select', options: ['live', 'review', 'program', 'body'] },
30
- liveKey: { control: 'select', options: [null, 'live', 'review', 'program', 'body'] },
31
- onNavigate: { control: false },
32
- onSelectDevice: { control: false },
33
- },
34
- decorators: [
35
- (Story) => (
36
- <View style={{ height: '100vh' as unknown as number, backgroundColor: '#0E0E0E' }}>
37
- <Story />
38
- </View>
39
- ),
40
- ],
41
- }
42
-
43
- export default meta
44
- type Story = StoryObj<typeof DashboardShell>
45
-
46
- export const Default: Story = {
47
- args: { activeKey: 'live', state: 'live' },
48
- }
49
-
50
- export const WithContent: Story = {
51
- args: { activeKey: 'review', state: 'rest', liveKey: 'live' },
52
- render: (args) => (
53
- <DashboardShell {...args}>
54
- <View style={{ flex: 1, padding: 28 }}>
55
- <Text style={{ color: '#E5E5E5', fontSize: 22, fontWeight: '700' }}>Review</Text>
56
- <Text style={{ color: '#8A8A8A', fontSize: 13, marginTop: 6 }}>
57
- A page mounts its content here; the shell keeps the nav + top-bar chrome persistent.
58
- </Text>
59
- </View>
60
- </DashboardShell>
61
- ),
62
- parameters: {
63
- docs: { description: { story: 'The shell with a page mounted in its content slot.' } },
64
- },
65
- }
@@ -1,75 +0,0 @@
1
- import type { ReactNode } from 'react'
2
- import { View, Text } from 'react-native'
3
- import { cn } from '../../utils/cn'
4
- import { Surface } from '../ui/surface'
5
- import { SideNav, type SideNavItem } from './SideNav'
6
- import { TopBar } from './TopBar'
7
- import { type Device } from './DeviceRow'
8
- import { type SessionState } from './SessionStatePill'
9
-
10
- /**
11
- * `DashboardShell` — the wall-dashboard chrome: a persistent {@link SideNav} rail +
12
- * {@link TopBar} over a main content region. A thin frame that wires the shell-nav
13
- * organisms together and exposes a `children` content slot, so the dashboard app
14
- * mounts one component instead of re-assembling the chrome. Driven entirely by props.
15
- */
16
- export interface DashboardShellProps {
17
- /** Active nav category key. */
18
- activeKey?: string
19
- /** Nav categories, top → bottom. Defaults to SideNav's four dashboard categories. */
20
- navItems?: SideNavItem[]
21
- /** A category with off-view live activity → a quiet cue on that item. */
22
- liveKey?: string | null
23
- /** Global session state → the TopBar status pill. */
24
- state?: SessionState
25
- /** Connected devices → the TopBar connection glyph + dropdown. */
26
- devices?: Device[]
27
- /** TopBar brand subtitle. */
28
- subtitle?: string
29
- onNavigate?: (key: string) => void
30
- onSelectDevice?: (device: Device) => void
31
- /** Main content region. A placeholder renders when omitted. */
32
- children?: ReactNode
33
- className?: string
34
- }
35
-
36
- const DEMO_DEVICES: Device[] = [
37
- { id: 'Voltra-A3F2', nickname: 'Left Cable', slot: 'L', state: 'connected' },
38
- { id: 'Voltra-9B1C', nickname: 'Right Cable', slot: 'R', state: 'connected' },
39
- ]
40
-
41
- function ContentPlaceholder() {
42
- return (
43
- <View className="flex-1 items-center justify-center">
44
- <Text className="font-heading text-sm text-text-tertiary">main content region</Text>
45
- </View>
46
- )
47
- }
48
-
49
- export function DashboardShell({
50
- activeKey = 'live',
51
- navItems,
52
- liveKey = null,
53
- state = 'live',
54
- devices = DEMO_DEVICES,
55
- subtitle = 'wall dashboard',
56
- onNavigate,
57
- onSelectDevice,
58
- children,
59
- className,
60
- }: DashboardShellProps) {
61
- return (
62
- // Column: the TopBar spans the FULL width across the top, and the SideNav sits BELOW it
63
- // in the content row (not a full-height left rail). This keeps the brand/status band
64
- // unbroken edge-to-edge and lets the nav align under it. The shell is the outermost
65
- // Surface — it owns the base plane and seeds the on-surface colour context (mode) for
66
- // the whole dashboard tree.
67
- <Surface level="base" className={cn('flex-1', className)}>
68
- <TopBar state={state} devices={devices} subtitle={subtitle} onSelectDevice={onSelectDevice} />
69
- <View className="flex-1 flex-row">
70
- <SideNav activeKey={activeKey} items={navItems} liveKey={liveKey} onNavigate={onNavigate} />
71
- <View className="flex-1">{children ?? <ContentPlaceholder />}</View>
72
- </View>
73
- </Surface>
74
- )
75
- }