@titan-design/react-ui 0.6.0 → 0.8.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 (258) hide show
  1. package/dist/bodymap.js +12 -7
  2. package/dist/bodymap.js.map +1 -1
  3. package/dist/bodymap.mjs +12 -7
  4. package/dist/bodymap.mjs.map +1 -1
  5. package/dist/index.d.mts +956 -128
  6. package/dist/index.d.ts +956 -128
  7. package/dist/index.js +2873 -981
  8. package/dist/index.js.map +1 -1
  9. package/dist/index.mjs +2826 -982
  10. package/dist/index.mjs.map +1 -1
  11. package/dist/{pages-MO0JCySL.d.mts → pages-DCFBqp79.d.mts} +289 -57
  12. package/dist/{pages-D7Jlssvp.d.ts → pages-_fI3-x7Z.d.ts} +289 -57
  13. package/dist/pages.d.mts +1 -1
  14. package/dist/pages.d.ts +1 -1
  15. package/dist/pages.js +1659 -799
  16. package/dist/pages.js.map +1 -1
  17. package/dist/pages.mjs +1660 -800
  18. package/dist/pages.mjs.map +1 -1
  19. package/dist/theme/index.d.mts +16 -82
  20. package/dist/theme/index.d.ts +16 -82
  21. package/dist/theme/index.js +13 -115
  22. package/dist/theme/index.js.map +1 -1
  23. package/dist/theme/index.mjs +13 -115
  24. package/dist/theme/index.mjs.map +1 -1
  25. package/dist/theme/tokens-css.js +14 -6
  26. package/dist/theme/tokens-css.js.map +1 -1
  27. package/dist/theme/tokens-css.mjs +14 -6
  28. package/dist/theme/tokens-css.mjs.map +1 -1
  29. package/package.json +1 -1
  30. package/src/arch/Architecture.stories.tsx +870 -0
  31. package/src/arch/annotations.json +48 -0
  32. package/src/arch/arch-graph.json +4301 -0
  33. package/src/components/custom/CircularTimer/CircularTimer.stories.tsx +90 -0
  34. package/src/components/custom/CircularTimer/CircularTimer.test.tsx +62 -0
  35. package/src/components/custom/CircularTimer/CircularTimer.tsx +112 -0
  36. package/src/components/custom/CircularTimer/index.ts +1 -0
  37. package/src/components/custom/DateTime/DateTime.stories.tsx +1 -1
  38. package/src/components/custom/EmptyState/EmptyState.stories.tsx +1 -1
  39. package/src/components/custom/Gauge/Gauge.stories.tsx +1 -1
  40. package/src/components/custom/Metric/Metric.stories.tsx +1 -1
  41. package/src/components/custom/Scatter/Scatter.stories.tsx +1 -1
  42. package/src/components/custom/Sidebar/Sidebar.stories.tsx +1 -1
  43. package/src/components/custom/Table/Table.stories.tsx +1 -1
  44. package/src/components/custom/TimerReadout/TimerReadout.stories.tsx +62 -0
  45. package/src/components/custom/TimerReadout/TimerReadout.test.tsx +72 -0
  46. package/src/components/custom/TimerReadout/TimerReadout.tsx +75 -0
  47. package/src/components/custom/TimerReadout/index.ts +1 -0
  48. package/src/components/custom/Treemap/Treemap.stories.tsx +1 -1
  49. package/src/components/custom/Typography/Typography.stories.tsx +1 -1
  50. package/src/components/custom/Workout/ActiveWorkoutPage.stories.tsx +21 -13
  51. package/src/components/custom/Workout/ActiveWorkoutPage.test.tsx +16 -13
  52. package/src/components/custom/Workout/ActiveWorkoutPage.tsx +9 -15
  53. package/src/components/custom/Workout/BaseBadge.stories.tsx +1 -1
  54. package/src/components/custom/Workout/BodyMap.stories.tsx +1 -1
  55. package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +1 -1
  56. package/src/components/custom/Workout/CapacityBandChart.stories.tsx +1 -1
  57. package/src/components/custom/Workout/DeviationBar.stories.tsx +1 -1
  58. package/src/components/custom/Workout/ExerciseCard.stories.tsx +51 -66
  59. package/src/components/custom/Workout/ExerciseCard.test.tsx +146 -143
  60. package/src/components/custom/Workout/ExerciseCard.tsx +176 -198
  61. package/src/components/custom/Workout/ExerciseCardHeading.stories.tsx +99 -0
  62. package/src/components/custom/Workout/ExerciseCardHeading.test.tsx +72 -0
  63. package/src/components/custom/Workout/ExerciseCardHeading.tsx +43 -0
  64. package/src/components/custom/Workout/ExerciseCardUnified.stories.tsx +151 -0
  65. package/src/components/custom/Workout/ExerciseDetailPage.stories.tsx +5 -3
  66. package/src/components/custom/Workout/ExerciseDetailPage.test.tsx +4 -4
  67. package/src/components/custom/Workout/ExerciseDetailPage.tsx +4 -5
  68. package/src/components/custom/Workout/ExerciseHeading.stories.tsx +81 -0
  69. package/src/components/custom/Workout/ExerciseHeading.test.tsx +77 -0
  70. package/src/components/custom/Workout/ExerciseHeading.tsx +85 -0
  71. package/src/components/custom/Workout/ExerciseIndicator.stories.tsx +110 -0
  72. package/src/components/custom/Workout/ExerciseIndicator.test.tsx +93 -0
  73. package/src/components/custom/Workout/ExerciseIndicator.tsx +120 -0
  74. package/src/components/custom/Workout/FatigueMeter.stories.tsx +51 -0
  75. package/src/components/custom/Workout/FatigueMeter.test.tsx +85 -0
  76. package/src/components/custom/Workout/FatigueMeter.tsx +86 -0
  77. package/src/components/custom/Workout/InputBar.stories.tsx +1 -1
  78. package/src/components/custom/Workout/IntensityBar.stories.tsx +1 -1
  79. package/src/components/custom/Workout/LiveAuraFrame.stories.tsx +153 -0
  80. package/src/components/custom/Workout/LiveAuraFrame.test.tsx +74 -0
  81. package/src/components/custom/Workout/LiveAuraFrame.tsx +105 -0
  82. package/src/components/custom/Workout/MesoCard.stories.tsx +1 -1
  83. package/src/components/custom/Workout/MesoProgressBar.stories.tsx +1 -1
  84. package/src/components/custom/Workout/MesoStatusCard.stories.tsx +1 -1
  85. package/src/components/custom/Workout/MetricTiles.stories.tsx +60 -0
  86. package/src/components/custom/Workout/MetricTiles.test.tsx +58 -0
  87. package/src/components/custom/Workout/MetricTiles.tsx +48 -0
  88. package/src/components/custom/Workout/MuscleGroupChip.stories.tsx +1 -1
  89. package/src/components/custom/Workout/PlaceholderStrip.stories.tsx +1 -1
  90. package/src/components/custom/Workout/PrBadge.stories.tsx +1 -1
  91. package/src/components/custom/Workout/PrHistoryModal.stories.tsx +1 -1
  92. package/src/components/custom/Workout/ProgramPlanningPage.stories.tsx +4 -16
  93. package/src/components/custom/Workout/ProgramPlanningPage.tsx +8 -6
  94. package/src/components/custom/Workout/README.md +193 -4
  95. package/src/components/custom/Workout/ReadinessCheck.stories.tsx +1 -1
  96. package/src/components/custom/Workout/RestTimer.stories.tsx +133 -3
  97. package/src/components/custom/Workout/RestTimer.test.tsx +73 -0
  98. package/src/components/custom/Workout/RestTimer.tsx +155 -59
  99. package/src/components/custom/Workout/RowInventory.stories.tsx +405 -0
  100. package/src/components/custom/Workout/S3FullRail.stories.tsx +34 -0
  101. package/src/components/custom/Workout/S3SessionPace.stories.tsx +95 -0
  102. package/src/components/custom/Workout/S3SessionRailHeading.stories.tsx +61 -0
  103. package/src/components/custom/Workout/S3SetTypes.stories.tsx +176 -0
  104. package/src/components/custom/Workout/S3WorkoutExpansion.stories.tsx +240 -0
  105. package/src/components/custom/Workout/ScheduleTiles.stories.tsx +40 -0
  106. package/src/components/custom/Workout/ScheduleTiles.test.tsx +34 -0
  107. package/src/components/custom/Workout/ScheduleTiles.tsx +70 -0
  108. package/src/components/custom/Workout/SegmentedBar.stories.tsx +99 -0
  109. package/src/components/custom/Workout/SegmentedBar.test.tsx +77 -0
  110. package/src/components/custom/Workout/SegmentedBar.tsx +172 -0
  111. package/src/components/custom/Workout/SegmentedProgressBar.stories.tsx +50 -0
  112. package/src/components/custom/Workout/SegmentedProgressBar.test.tsx +80 -0
  113. package/src/components/custom/Workout/SegmentedProgressBar.tsx +67 -0
  114. package/src/components/custom/Workout/SessionHeader.stories.tsx +121 -0
  115. package/src/components/custom/Workout/SessionHeader.test.tsx +122 -0
  116. package/src/components/custom/Workout/SessionHeader.tsx +152 -0
  117. package/src/components/custom/Workout/SessionRail.stories.tsx +153 -0
  118. package/src/components/custom/Workout/SessionRail.test.tsx +86 -0
  119. package/src/components/custom/Workout/SessionRail.tsx +126 -0
  120. package/src/components/custom/Workout/SetBar.stories.tsx +124 -0
  121. package/src/components/custom/Workout/SetBar.test.tsx +123 -0
  122. package/src/components/custom/Workout/SetBar.tsx +171 -0
  123. package/src/components/custom/Workout/SetRow.stories.tsx +50 -100
  124. package/src/components/custom/Workout/SetRow.test.tsx +94 -166
  125. package/src/components/custom/Workout/SetRow.tsx +169 -232
  126. package/src/components/custom/Workout/SetStrip.stories.tsx +154 -0
  127. package/src/components/custom/Workout/SetStrip.test.tsx +109 -0
  128. package/src/components/custom/Workout/SetStrip.tsx +71 -0
  129. package/src/components/custom/Workout/SetTableHeader.stories.tsx +66 -0
  130. package/src/components/custom/Workout/SetTableHeader.test.tsx +47 -0
  131. package/src/components/custom/Workout/SetTableHeader.tsx +88 -0
  132. package/src/components/custom/Workout/SetsRepsLoad.stories.tsx +47 -0
  133. package/src/components/custom/Workout/SetsRepsLoad.test.tsx +44 -0
  134. package/src/components/custom/Workout/SetsRepsLoad.tsx +52 -0
  135. package/src/components/custom/Workout/Sparkline.stories.tsx +1 -1
  136. package/src/components/custom/Workout/StatusDot.stories.tsx +1 -1
  137. package/src/components/custom/Workout/StatusPill.stories.tsx +59 -0
  138. package/src/components/custom/Workout/StatusPill.test.tsx +63 -0
  139. package/src/components/custom/Workout/StatusPill.tsx +88 -0
  140. package/src/components/custom/Workout/StrengthTrendChart.stories.tsx +1 -1
  141. package/src/components/custom/Workout/SupersetWrapper.stories.tsx +1 -1
  142. package/src/components/custom/Workout/TempoBar.stories.tsx +70 -1
  143. package/src/components/custom/Workout/TempoBar.test.tsx +119 -4
  144. package/src/components/custom/Workout/TempoBar.tsx +107 -22
  145. package/src/components/custom/Workout/TempoDisplay.stories.tsx +12 -1
  146. package/src/components/custom/Workout/TempoDisplay.tsx +23 -33
  147. package/src/components/custom/Workout/TrainingStatusPage.stories.tsx +1 -1
  148. package/src/components/custom/Workout/VelocityStrip.modalities.stories.tsx +254 -0
  149. package/src/components/custom/Workout/VelocityStrip.responsive.stories.tsx +145 -0
  150. package/src/components/custom/Workout/VelocityStrip.stories.tsx +262 -56
  151. package/src/components/custom/Workout/VelocityStrip.test.tsx +440 -141
  152. package/src/components/custom/Workout/VelocityStrip.tsx +776 -141
  153. package/src/components/custom/Workout/VolumeLandmarkBar.stories.tsx +73 -0
  154. package/src/components/custom/Workout/VolumeLandmarkBar.test.tsx +119 -0
  155. package/src/components/custom/Workout/VolumeLandmarkBar.tsx +154 -0
  156. package/src/components/custom/Workout/WeekRow.stories.tsx +1 -1
  157. package/src/components/custom/Workout/WeightBadge.stories.tsx +1 -1
  158. package/src/components/custom/Workout/WorkoutCard.stories.tsx +2 -6
  159. package/src/components/custom/Workout/WorkoutCard.test.tsx +13 -46
  160. package/src/components/custom/Workout/WorkoutPill.stories.tsx +1 -1
  161. package/src/components/custom/Workout/ZoneTrack.stories.tsx +139 -0
  162. package/src/components/custom/Workout/ZoneTrack.test.tsx +234 -0
  163. package/src/components/custom/Workout/ZoneTrack.tsx +373 -0
  164. package/src/components/custom/Workout/index.ts +55 -2
  165. package/src/components/custom/Workout/metricText.stories.tsx +69 -0
  166. package/src/components/custom/Workout/metricText.tsx +34 -0
  167. package/src/components/custom/Workout/paceTone.test.ts +29 -0
  168. package/src/components/custom/Workout/paceTone.ts +27 -0
  169. package/src/components/custom/Workout/setHeadingKit.tsx +177 -0
  170. package/src/components/custom/index.ts +2 -0
  171. package/src/components/custom/stepper/Stepper.stories.tsx +1 -1
  172. package/src/components/icons/icons.stories.tsx +67 -2
  173. package/src/components/icons/icons.test.tsx +32 -2
  174. package/src/components/icons/icons.tsx +108 -0
  175. package/src/components/shell/BrandLockup.stories.tsx +3 -3
  176. package/src/components/shell/DashboardShell.stories.tsx +65 -0
  177. package/src/components/shell/DashboardShell.test.tsx +42 -0
  178. package/src/components/shell/DashboardShell.tsx +74 -0
  179. package/src/components/shell/DeviceIndicator.stories.tsx +2 -2
  180. package/src/components/shell/DeviceMenu.stories.tsx +5 -5
  181. package/src/components/shell/DeviceRow.stories.tsx +3 -3
  182. package/src/components/shell/NavItem.stories.tsx +52 -0
  183. package/src/components/shell/NavItem.test.tsx +35 -0
  184. package/src/components/shell/NavItem.tsx +75 -0
  185. package/src/components/shell/README.md +30 -0
  186. package/src/components/shell/SessionRailSpecimen.stories.tsx +753 -0
  187. package/src/components/shell/SessionStatePill.stories.tsx +3 -3
  188. package/src/components/shell/SessionStatePill.tsx +1 -1
  189. package/src/components/shell/SideNav.stories.tsx +81 -0
  190. package/src/components/shell/SideNav.test.tsx +51 -0
  191. package/src/components/shell/SideNav.tsx +74 -0
  192. package/src/components/shell/TopBar.stories.tsx +5 -5
  193. package/src/components/shell/index.ts +5 -0
  194. package/src/components/ui/alert/Alert.stories.tsx +86 -3
  195. package/src/components/ui/alert/Alert.test.tsx +52 -0
  196. package/src/components/ui/alert/Alert.tsx +54 -20
  197. package/src/components/ui/autocomplete/Autocomplete.stories.tsx +1 -1
  198. package/src/components/ui/avatar/Avatar.stories.tsx +1 -1
  199. package/src/components/ui/badge/Badge.stories.tsx +1 -1
  200. package/src/components/ui/breadcrumbs/Breadcrumbs.stories.tsx +1 -1
  201. package/src/components/ui/button/Button.stories.tsx +1 -1
  202. package/src/components/ui/card/Card.stories.tsx +1 -1
  203. package/src/components/ui/checkbox/Checkbox.stories.tsx +1 -1
  204. package/src/components/ui/chip/Chip.stories.tsx +1 -1
  205. package/src/components/ui/collapse/Collapse.stories.tsx +1 -1
  206. package/src/components/ui/data-row/DataRow.stories.tsx +1 -1
  207. package/src/components/ui/divider/Divider.stories.tsx +1 -1
  208. package/src/components/ui/drawer/Drawer.stories.tsx +1 -1
  209. package/src/components/ui/form-field/FormField.stories.tsx +1 -1
  210. package/src/components/ui/help-tip/HelpTip.stories.tsx +1 -1
  211. package/src/components/ui/icon-box/IconBox.stories.tsx +1 -1
  212. package/src/components/ui/index.ts +1 -0
  213. package/src/components/ui/indicator/Indicator.stories.tsx +2 -2
  214. package/src/components/ui/indicator/Indicator.test.tsx +1 -0
  215. package/src/components/ui/indicator/Indicator.tsx +6 -1
  216. package/src/components/ui/input/Input.stories.tsx +1 -1
  217. package/src/components/ui/link/Link.stories.tsx +1 -1
  218. package/src/components/ui/list-item/ListItem.stories.tsx +1 -1
  219. package/src/components/ui/menu/Menu.stories.tsx +1 -1
  220. package/src/components/ui/modal/Modal.stories.tsx +1 -1
  221. package/src/components/ui/pill/Pill.stories.tsx +1 -1
  222. package/src/components/ui/popover/Popover.stories.tsx +1 -1
  223. package/src/components/ui/progress/Progress.stories.tsx +1 -1
  224. package/src/components/ui/progress/Progress.tsx +47 -22
  225. package/src/components/ui/radio/Radio.stories.tsx +1 -1
  226. package/src/components/ui/section/Section.stories.tsx +1 -1
  227. package/src/components/ui/select/Select.stories.tsx +1 -1
  228. package/src/components/ui/skeleton/Skeleton.stories.tsx +1 -1
  229. package/src/components/ui/spinner/Spinner.stories.tsx +1 -1
  230. package/src/components/ui/stack/Stack.stories.tsx +1 -1
  231. package/src/components/ui/surface/Surface.stories.tsx +1 -1
  232. package/src/components/ui/switch/Switch.stories.tsx +1 -1
  233. package/src/components/ui/tabs/Tabs.stories.tsx +1 -1
  234. package/src/components/ui/tile/Tile.stories.tsx +79 -0
  235. package/src/components/ui/tile/Tile.test.tsx +48 -0
  236. package/src/components/ui/tile/Tile.tsx +64 -0
  237. package/src/components/ui/tile/index.ts +2 -0
  238. package/src/components/ui/toast/Toast.stories.tsx +1 -1
  239. package/src/components/ui/toolbar-button/ToolbarButton.stories.tsx +1 -1
  240. package/src/components/ui/tooltip/Tooltip.stories.tsx +1 -1
  241. package/src/examples/react-hook-form/ReactHookForm.stories.tsx +1 -1
  242. package/src/hooks/index.ts +2 -0
  243. package/src/hooks/useTimer.test.ts +150 -0
  244. package/src/hooks/useTimer.ts +77 -0
  245. package/src/index.ts +3 -0
  246. package/src/pages.ts +1 -1
  247. package/src/stories/PresetShowcase.stories.tsx +1 -1
  248. package/src/stories/ThemePresets.stories.tsx +1 -1
  249. package/src/theme/ColorSystem.stories.tsx +1 -1
  250. package/src/theme/Colors.stories.tsx +5 -8
  251. package/src/theme/config.ts +4 -0
  252. package/src/theme/elevation.stories.tsx +1 -1
  253. package/src/theme/global.css +5 -1
  254. package/src/theme/shadows.stories.tsx +1 -1
  255. package/src/theme/tokens/primitives.ts +11 -107
  256. package/src/theme/tokens/semantic.ts +8 -0
  257. package/src/theme/workout-tokens.ts +11 -7
  258. package/tailwind.config.js +5 -0
@@ -1,26 +1,68 @@
1
1
  import { useState } from 'react'
2
- import type { Meta, StoryObj } from '@storybook/react-vite'
3
- import { View } from 'react-native'
2
+ import type { Decorator, Meta, StoryObj } from '@storybook/react-vite'
3
+ import { View, Text } from 'react-native'
4
4
  import { VelocityStrip } from './VelocityStrip'
5
5
 
6
6
  const meta: Meta<typeof VelocityStrip> = {
7
- title: 'Custom/Workout/VelocityStrip',
7
+ title: 'Workout/DataViz/VelocityStrip',
8
8
  component: VelocityStrip,
9
9
  tags: ['autodocs'],
10
- argTypes: {
11
- expanded: {
12
- control: 'boolean',
13
- description: 'Whether the strip is expanded into a bar chart',
10
+ parameters: {
11
+ docs: {
12
+ description: {
13
+ component:
14
+ 'Per-rep velocity strip. Three variants: `mini` (a flat 3px static strip), `expanded` ' +
15
+ '(the velocity-HEIGHT bar chart, rounded tops), and `hero` (the across-the-room, single-set ' +
16
+ 'wall treatment — tall bars, per-bar value labels, a dashed running-best reference line, and ' +
17
+ 'dashed placeholders for the reps still to come via `targetReps`). The `expanded` chrome is ' +
18
+ 'prop-driven — with `showNumbers`/`showInfo` on it is the framed chart (raised surface, per-bar ' +
19
+ 'm/s labels, mean/loss info row, interactive tap-to-expand); with both off it is a bare strip, ' +
20
+ 'the active-set spotlight. `height` sets the plot height; `scale` is `peak` (to the set max) ' +
21
+ 'or `fixed` (a fixed ceiling, cross-set-comparable — recommended for the live `hero` so bar ' +
22
+ 'heights never reflow as reps land). Feed either `velocities` or a `set` ' +
23
+ 'descriptor (set-type aware — see the ' +
24
+ '[modalities](?path=/docs/workout-dataviz-velocitystrip-modalities--docs) sheet).',
25
+ },
14
26
  },
27
+ },
28
+ argTypes: {
15
29
  variant: {
16
30
  control: 'select',
17
- options: ['full', 'mini'],
31
+ options: ['mini', 'expanded', 'hero'],
18
32
  description: 'Display variant',
19
33
  },
34
+ targetReps: {
35
+ control: 'number',
36
+ description: 'hero: planned rep count — reps beyond `velocities` draw as dashed placeholders',
37
+ },
38
+ expanded: {
39
+ control: 'boolean',
40
+ description: 'expanded (framed): whether the chart is open (toggle for tap-to-expand)',
41
+ },
42
+ showNumbers: {
43
+ control: 'boolean',
44
+ description: 'expanded framed chart: per-bar m/s labels (default true)',
45
+ },
20
46
  showInfo: {
21
47
  control: 'boolean',
22
- description: 'Whether to show the info row (zone name + loss %) in expanded mode',
48
+ description: 'expanded framed chart: the mean/loss info row (default true)',
49
+ },
50
+ height: {
51
+ control: { type: 'number', min: 12, max: 260, step: 2 },
52
+ description: 'expanded/hero plot height in px (bars scale to this). Default 60 / 220 (hero).',
23
53
  },
54
+ scale: {
55
+ control: 'inline-radio',
56
+ options: ['peak', 'fixed'],
57
+ description: 'expanded bar scaling: peak (set max) or fixed (cross-set ceiling)',
58
+ },
59
+ liveRepIndex: {
60
+ control: 'number',
61
+ description:
62
+ 'expanded framed chart: index of the newest rep to animate (pop / new-peak bounce)',
63
+ },
64
+ set: { control: false, description: 'Structured set descriptor (supersedes `velocities`)' },
65
+ zones: { control: false, description: 'Velocity-zone bands (WA); default scale when absent' },
24
66
  },
25
67
  }
26
68
 
@@ -32,94 +74,258 @@ const slowSet = [0.65, 0.58, 0.52, 0.48, 0.42]
32
74
  const mixedSet = [1.1, 0.95, 0.82, 0.68, 0.55, 0.45]
33
75
  const moderateSet = [0.88, 0.85, 0.82, 0.78, 0.76]
34
76
 
35
- export const DefaultCollapsed: Story = {
77
+ /** Controls-driven: flip `variant` / `showNumbers` / `showInfo` / `height` / `scale` in the panel. */
78
+ export const Playground: Story = {
36
79
  args: {
37
80
  velocities: moderateSet,
81
+ variant: 'expanded',
82
+ expanded: true,
83
+ showNumbers: true,
84
+ showInfo: true,
85
+ height: 60,
86
+ scale: 'peak',
38
87
  onToggle: () => {},
39
88
  },
89
+ decorators: [
90
+ (Story) => (
91
+ <View style={{ width: 300, padding: 16 }}>
92
+ <Story />
93
+ </View>
94
+ ),
95
+ ],
96
+ }
97
+
98
+ /** The flat 3px static strip — the collapsed glance used in cards and rails. */
99
+ export const Mini: Story = {
100
+ args: { velocities: mixedSet, variant: 'mini' },
40
101
  }
41
102
 
42
- export const Expanded: Story = {
103
+ /** Framed chart with per-bar m/s labels + info row (numbers ON) — the rich readout. */
104
+ export const ExpandedWithNumbers: Story = {
105
+ args: { velocities: mixedSet, variant: 'expanded', expanded: true },
106
+ decorators: [
107
+ (Story) => (
108
+ <View style={{ width: 300, padding: 16 }}>
109
+ <Story />
110
+ </View>
111
+ ),
112
+ ],
113
+ }
114
+
115
+ /** Bare velocity-height strip (numbers OFF, info OFF, fixed 24px) — the active-set spotlight. */
116
+ export const ExpandedBareSpotlight: Story = {
43
117
  args: {
44
- velocities: moderateSet,
45
- expanded: true,
46
- onToggle: () => {},
118
+ variant: 'expanded',
119
+ showNumbers: false,
120
+ showInfo: false,
121
+ height: 24,
122
+ scale: 'fixed',
123
+ set: { type: 'straight', velocities: [0.95, 0.9, 0.86, 0.8, 0.72], planned: 10 },
47
124
  },
48
125
  }
49
126
 
50
- export const ExpandedNoInfo: Story = {
127
+ // --- Hero variant ------------------------------------------------------------
128
+ // The across-the-room, single-set wall treatment. Rendered on the north-star wall
129
+ // background so the dashed reference line + placeholders read the way they will live.
130
+
131
+ /**
132
+ * Wall-background frame for the hero stories. The eyebrow label is ORGANISM chrome
133
+ * (the north-star live page renders it), NOT part of the primitive — it sits here only
134
+ * to show the component in the context it will live in. The `VelocityStrip` hero variant
135
+ * itself renders no title.
136
+ */
137
+ const heroDecorator: Decorator = (Story) => (
138
+ <View style={{ width: 560, padding: 28, backgroundColor: '#0E0E0E' }}>
139
+ <Text
140
+ style={{
141
+ color: '#5A5A5A',
142
+ fontSize: 10,
143
+ fontWeight: '700',
144
+ letterSpacing: 1,
145
+ marginBottom: 12,
146
+ }}
147
+ >
148
+ CONCENTRIC VELOCITY · THIS SET · (organism chrome — not the component)
149
+ </Text>
150
+ <Story />
151
+ </View>
152
+ )
153
+
154
+ const heroMidSet = [0.82, 0.79, 0.81, 0.76]
155
+ const heroNearComplete = [0.82, 0.79, 0.81, 0.76, 0.74, 0.71, 0.68]
156
+ const heroFatigue = [0.96, 0.91, 0.83, 0.72, 0.61, 0.5]
157
+
158
+ /** Controls-driven hero: flip `velocities` / `targetReps` / `liveRepIndex` / `scale` / `height`. */
159
+ export const HeroPlayground: Story = {
51
160
  args: {
52
- velocities: moderateSet,
53
- expanded: true,
54
- showInfo: false,
55
- onToggle: () => {},
161
+ velocities: heroMidSet,
162
+ variant: 'hero',
163
+ targetReps: 8,
164
+ liveRepIndex: 3,
165
+ scale: 'fixed',
166
+ height: 220,
56
167
  },
168
+ decorators: [heroDecorator],
169
+ }
170
+
171
+ /** Mid-set: 4 of 8 reps done, the newest bar popping, 4 dashed reps still to come. */
172
+ export const HeroMidSet: Story = {
173
+ args: { velocities: heroMidSet, variant: 'hero', targetReps: 8, liveRepIndex: 3, scale: 'fixed' },
174
+ decorators: [heroDecorator],
57
175
  }
58
176
 
59
- export const FastEasySet: Story = {
177
+ /** Near complete: 7 of 8, one placeholder left; the running-best line sits at rep 3. */
178
+ export const HeroNearComplete: Story = {
60
179
  args: {
61
- velocities: fastSet,
62
- expanded: true,
63
- onToggle: () => {},
180
+ velocities: heroNearComplete,
181
+ variant: 'hero',
182
+ targetReps: 8,
183
+ liveRepIndex: 6,
184
+ scale: 'fixed',
64
185
  },
186
+ decorators: [heroDecorator],
65
187
  }
66
188
 
67
- export const SlowGrindingSet: Story = {
189
+ /** Fatigue decline: velocity falling rep over rep — the shape you read across the room. */
190
+ export const HeroFatigueDecline: Story = {
68
191
  args: {
69
- velocities: slowSet,
70
- expanded: true,
71
- onToggle: () => {},
192
+ velocities: heroFatigue,
193
+ variant: 'hero',
194
+ targetReps: 8,
195
+ liveRepIndex: 5,
196
+ scale: 'fixed',
72
197
  },
198
+ decorators: [heroDecorator],
73
199
  }
74
200
 
75
- export const MixedVelocities: Story = {
201
+ /** Ends on the best rep: the running-best line lands on the last (live) bar's top. */
202
+ export const HeroEndsOnBest: Story = {
76
203
  args: {
77
- velocities: mixedSet,
78
- expanded: true,
79
- onToggle: () => {},
204
+ velocities: [0.7, 0.76, 0.83, 0.9],
205
+ variant: 'hero',
206
+ targetReps: 4,
207
+ liveRepIndex: 3,
208
+ scale: 'peak',
80
209
  },
210
+ decorators: [heroDecorator],
81
211
  }
82
212
 
83
- export const Mini: Story = {
213
+ /**
214
+ * Set expansion — reps performed BEYOND `targetReps` (11 done vs 8 planned). Placeholders
215
+ * are gone (target met) and the extra reps just render as more bars; `flex` bars narrow to
216
+ * fit, so the chart absorbs the overflow with no clipping. The AMRAP "keep going" case.
217
+ */
218
+ export const HeroExceedsTarget: Story = {
219
+ args: {
220
+ velocities: [0.9, 0.87, 0.84, 0.8, 0.77, 0.74, 0.71, 0.68, 0.64, 0.6, 0.55],
221
+ variant: 'hero',
222
+ targetReps: 8,
223
+ liveRepIndex: 10,
224
+ scale: 'fixed',
225
+ },
226
+ decorators: [heroDecorator],
227
+ }
228
+
229
+ /** Set complete: 8 of 8, no placeholders. */
230
+ export const HeroComplete: Story = {
231
+ args: {
232
+ velocities: [0.96, 0.91, 0.83, 0.79, 0.76, 0.72, 0.68, 0.61],
233
+ variant: 'hero',
234
+ targetReps: 8,
235
+ scale: 'fixed',
236
+ },
237
+ decorators: [heroDecorator],
238
+ }
239
+
240
+ /** The same set at three container widths — the hero is width-fluid (flex bars, capped width, fixed height). */
241
+ export const HeroResponsive: Story = {
242
+ render: () => (
243
+ <View style={{ gap: 24, padding: 24, backgroundColor: '#0E0E0E' }}>
244
+ {[360, 560, 900].map((w) => (
245
+ <View key={w} style={{ width: w }}>
246
+ <Text style={{ color: '#5A5A5A', fontSize: 10, fontWeight: '700', marginBottom: 8 }}>
247
+ {w}px
248
+ </Text>
249
+ <VelocityStrip
250
+ velocities={heroFatigue}
251
+ variant="hero"
252
+ targetReps={8}
253
+ liveRepIndex={5}
254
+ scale="fixed"
255
+ height={180}
256
+ />
257
+ </View>
258
+ ))}
259
+ </View>
260
+ ),
261
+ }
262
+
263
+ /** A structured set descriptor (a drop set): the mini variant carries the set-type gap/color encoding. */
264
+ export const SetTypeMini: Story = {
84
265
  args: {
85
- velocities: mixedSet,
86
266
  variant: 'mini',
267
+ set: {
268
+ type: 'drop',
269
+ subloads: [
270
+ [1.0, 0.92],
271
+ [0.85, 0.78],
272
+ [0.7, 0.62],
273
+ ],
274
+ },
87
275
  },
88
276
  }
89
277
 
90
278
  function InteractiveVelocityStrip() {
91
- const [expanded, setExpanded] = useState(false)
279
+ const [open, setOpen] = useState(false)
280
+ // Tap-to-expand: `onToggle` + the controlled `expanded` boolean. Tapping the strip
281
+ // toggles both ways (collapsed 3px ↔ chart). No `onRepPress` here — per-bar rep
282
+ // presses would intercept bar taps and block collapse; that's a separate mode.
92
283
  return (
93
284
  <View style={{ width: 300, padding: 16 }}>
94
- <VelocityStrip
95
- velocities={moderateSet}
96
- expanded={expanded}
97
- onToggle={() => setExpanded(!expanded)}
98
- onRepPress={(index, velocity) =>
99
- console.log(`Rep ${index + 1}: ${velocity}`)
100
- }
101
- />
285
+ <VelocityStrip velocities={moderateSet} expanded={open} onToggle={() => setOpen((v) => !v)} />
102
286
  </View>
103
287
  )
104
288
  }
105
289
 
290
+ /** Tap to expand; tap again to collapse (3px ↔ chart, animated). */
106
291
  export const Interactive: Story = {
107
292
  render: () => <InteractiveVelocityStrip />,
108
293
  }
109
294
 
110
- export const AllProfiles: Story = {
111
- render: () => (
112
- <View style={{ gap: 24, padding: 16 }}>
113
- <View style={{ gap: 8 }}>
114
- <VelocityStrip velocities={fastSet} expanded onToggle={() => {}} />
115
- <VelocityStrip
116
- velocities={moderateSet}
117
- expanded
118
- onToggle={() => {}}
119
- />
120
- <VelocityStrip velocities={slowSet} expanded onToggle={() => {}} />
121
- <VelocityStrip velocities={mixedSet} expanded onToggle={() => {}} />
295
+ /** The four zone profiles across the treatments, so the color scale reads at a glance. */
296
+ export const Profiles: Story = {
297
+ render: () => {
298
+ const rows: [string, number[]][] = [
299
+ ['Speed', fastSet],
300
+ ['Power', moderateSet],
301
+ ['Strength', slowSet],
302
+ ['Mixed', mixedSet],
303
+ ]
304
+ return (
305
+ <View style={{ gap: 20, padding: 16, width: 320 }}>
306
+ {rows.map(([label, velocities]) => (
307
+ <View key={label} style={{ gap: 6 }}>
308
+ <Text style={{ fontFamily: 'Inter, sans-serif', fontSize: 11, color: '#9CA3AF' }}>
309
+ {label}
310
+ </Text>
311
+ <VelocityStrip
312
+ velocities={velocities}
313
+ variant="expanded"
314
+ showInfo={false}
315
+ onToggle={() => {}}
316
+ />
317
+ <VelocityStrip
318
+ variant="expanded"
319
+ showNumbers={false}
320
+ showInfo={false}
321
+ height={24}
322
+ scale="fixed"
323
+ set={{ type: 'straight', velocities, planned: velocities.length }}
324
+ />
325
+ <VelocityStrip velocities={velocities} variant="mini" />
326
+ </View>
327
+ ))}
122
328
  </View>
123
- </View>
124
- ),
329
+ )
330
+ },
125
331
  }