@titan-design/react-ui 0.2.6 → 0.2.7

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 (157) hide show
  1. package/dist/chunk-3VLOBS6O.mjs +846 -0
  2. package/dist/chunk-3VLOBS6O.mjs.map +1 -0
  3. package/dist/{chunk-UXVRPOME.mjs → chunk-5SSKGS6E.mjs} +3 -783
  4. package/dist/chunk-5SSKGS6E.mjs.map +1 -0
  5. package/dist/index.d.mts +1005 -4
  6. package/dist/index.d.ts +1005 -4
  7. package/dist/index.js +6043 -213
  8. package/dist/index.js.map +1 -1
  9. package/dist/index.mjs +5901 -177
  10. package/dist/index.mjs.map +1 -1
  11. package/dist/theme/index.d.mts +57 -1
  12. package/dist/theme/index.d.ts +57 -1
  13. package/dist/theme/index.js +63 -0
  14. package/dist/theme/index.js.map +1 -1
  15. package/dist/theme/index.mjs +2 -1
  16. package/dist/theme/tokens-css.d.mts +18 -0
  17. package/dist/theme/tokens-css.d.ts +18 -0
  18. package/dist/theme/tokens-css.js +289 -0
  19. package/dist/theme/tokens-css.js.map +1 -0
  20. package/dist/theme/tokens-css.mjs +24 -0
  21. package/dist/theme/tokens-css.mjs.map +1 -0
  22. package/package.json +16 -5
  23. package/src/components/custom/DateTime/DateTime.stories.tsx +1 -1
  24. package/src/components/custom/Gauge/Gauge.stories.tsx +45 -0
  25. package/src/components/custom/Gauge/Gauge.test.tsx +71 -0
  26. package/src/components/custom/Gauge/Gauge.tsx +167 -0
  27. package/src/components/custom/Gauge/index.ts +2 -0
  28. package/src/components/custom/Scatter/Scatter.stories.tsx +85 -0
  29. package/src/components/custom/Scatter/Scatter.test.tsx +96 -0
  30. package/src/components/custom/Scatter/Scatter.tsx +260 -0
  31. package/src/components/custom/Scatter/index.ts +2 -0
  32. package/src/components/custom/Sidebar/Sidebar.tsx +1 -1
  33. package/src/components/custom/Treemap/Treemap.stories.tsx +60 -0
  34. package/src/components/custom/Treemap/Treemap.test.tsx +67 -0
  35. package/src/components/custom/Treemap/Treemap.tsx +192 -0
  36. package/src/components/custom/Treemap/index.ts +2 -0
  37. package/src/components/custom/Workout/BaseBadge.stories.tsx +75 -0
  38. package/src/components/custom/Workout/BaseBadge.test.tsx +102 -0
  39. package/src/components/custom/Workout/BaseBadge.tsx +113 -0
  40. package/src/components/custom/Workout/BodyMap.stories.tsx +121 -0
  41. package/src/components/custom/Workout/BodyMap.test.tsx +124 -0
  42. package/src/components/custom/Workout/BodyMap.tsx +348 -0
  43. package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +171 -0
  44. package/src/components/custom/Workout/BodyMapDetailPanel.test.tsx +225 -0
  45. package/src/components/custom/Workout/BodyMapDetailPanel.tsx +478 -0
  46. package/src/components/custom/Workout/CapacityBandChart.stories.tsx +125 -0
  47. package/src/components/custom/Workout/CapacityBandChart.test.tsx +193 -0
  48. package/src/components/custom/Workout/CapacityBandChart.tsx +493 -0
  49. package/src/components/custom/Workout/DeviationBar.stories.tsx +58 -0
  50. package/src/components/custom/Workout/DeviationBar.test.tsx +86 -0
  51. package/src/components/custom/Workout/DeviationBar.tsx +78 -0
  52. package/src/components/custom/Workout/ExerciseCard.stories.tsx +186 -0
  53. package/src/components/custom/Workout/ExerciseCard.test.tsx +319 -0
  54. package/src/components/custom/Workout/ExerciseCard.tsx +429 -0
  55. package/src/components/custom/Workout/InputBar.stories.tsx +75 -0
  56. package/src/components/custom/Workout/InputBar.test.tsx +116 -0
  57. package/src/components/custom/Workout/InputBar.tsx +163 -0
  58. package/src/components/custom/Workout/IntensityBar.stories.tsx +60 -0
  59. package/src/components/custom/Workout/IntensityBar.test.tsx +113 -0
  60. package/src/components/custom/Workout/IntensityBar.tsx +166 -0
  61. package/src/components/custom/Workout/MesoCard.stories.tsx +152 -0
  62. package/src/components/custom/Workout/MesoCard.test.tsx +170 -0
  63. package/src/components/custom/Workout/MesoCard.tsx +235 -0
  64. package/src/components/custom/Workout/MesoProgressBar.stories.tsx +85 -0
  65. package/src/components/custom/Workout/MesoProgressBar.test.tsx +141 -0
  66. package/src/components/custom/Workout/MesoProgressBar.tsx +161 -0
  67. package/src/components/custom/Workout/MesoStatusCard.stories.tsx +126 -0
  68. package/src/components/custom/Workout/MesoStatusCard.test.tsx +209 -0
  69. package/src/components/custom/Workout/MesoStatusCard.tsx +456 -0
  70. package/src/components/custom/Workout/MuscleGroupChip.stories.tsx +118 -0
  71. package/src/components/custom/Workout/MuscleGroupChip.test.tsx +91 -0
  72. package/src/components/custom/Workout/MuscleGroupChip.tsx +92 -0
  73. package/src/components/custom/Workout/PlaceholderStrip.stories.tsx +94 -0
  74. package/src/components/custom/Workout/PlaceholderStrip.test.tsx +83 -0
  75. package/src/components/custom/Workout/PlaceholderStrip.tsx +91 -0
  76. package/src/components/custom/Workout/PrBadge.stories.tsx +105 -0
  77. package/src/components/custom/Workout/PrBadge.test.tsx +111 -0
  78. package/src/components/custom/Workout/PrBadge.tsx +103 -0
  79. package/src/components/custom/Workout/PrHistoryModal.stories.tsx +116 -0
  80. package/src/components/custom/Workout/PrHistoryModal.test.tsx +161 -0
  81. package/src/components/custom/Workout/PrHistoryModal.tsx +244 -0
  82. package/src/components/custom/Workout/ReadinessCheck.stories.tsx +126 -0
  83. package/src/components/custom/Workout/ReadinessCheck.test.tsx +181 -0
  84. package/src/components/custom/Workout/ReadinessCheck.tsx +266 -0
  85. package/src/components/custom/Workout/RestTimer.tsx +8 -6
  86. package/src/components/custom/Workout/SetRow.stories.tsx +165 -0
  87. package/src/components/custom/Workout/SetRow.test.tsx +222 -0
  88. package/src/components/custom/Workout/SetRow.tsx +253 -0
  89. package/src/components/custom/Workout/Sparkline.stories.tsx +125 -0
  90. package/src/components/custom/Workout/Sparkline.test.tsx +113 -0
  91. package/src/components/custom/Workout/Sparkline.tsx +188 -0
  92. package/src/components/custom/Workout/StatusDot.stories.tsx +150 -0
  93. package/src/components/custom/Workout/StatusDot.test.tsx +165 -0
  94. package/src/components/custom/Workout/StatusDot.tsx +159 -0
  95. package/src/components/custom/Workout/StrengthTrendChart.stories.tsx +130 -0
  96. package/src/components/custom/Workout/StrengthTrendChart.test.tsx +217 -0
  97. package/src/components/custom/Workout/StrengthTrendChart.tsx +628 -0
  98. package/src/components/custom/Workout/SupersetWrapper.tsx +1 -2
  99. package/src/components/custom/Workout/TempoDisplay.stories.tsx +66 -0
  100. package/src/components/custom/Workout/TempoDisplay.test.tsx +90 -0
  101. package/src/components/custom/Workout/TempoDisplay.tsx +207 -0
  102. package/src/components/custom/Workout/VelocityStrip.stories.tsx +125 -0
  103. package/src/components/custom/Workout/VelocityStrip.test.tsx +234 -0
  104. package/src/components/custom/Workout/VelocityStrip.tsx +287 -0
  105. package/src/components/custom/Workout/WeekRow.stories.tsx +121 -0
  106. package/src/components/custom/Workout/WeekRow.test.tsx +117 -0
  107. package/src/components/custom/Workout/WeekRow.tsx +140 -0
  108. package/src/components/custom/Workout/WeightBadge.stories.tsx +87 -0
  109. package/src/components/custom/Workout/WeightBadge.test.tsx +164 -0
  110. package/src/components/custom/Workout/WeightBadge.tsx +113 -0
  111. package/src/components/custom/Workout/WorkoutCard.stories.tsx +135 -0
  112. package/src/components/custom/Workout/WorkoutCard.test.tsx +172 -0
  113. package/src/components/custom/Workout/WorkoutCard.tsx +226 -0
  114. package/src/components/custom/Workout/WorkoutPill.stories.tsx +63 -0
  115. package/src/components/custom/Workout/WorkoutPill.test.tsx +153 -0
  116. package/src/components/custom/Workout/WorkoutPill.tsx +177 -0
  117. package/src/components/custom/Workout/index.ts +113 -0
  118. package/src/components/custom/Workout/muscleTaxonomy.ts +252 -0
  119. package/src/components/custom/index.ts +3 -0
  120. package/src/components/custom/stepper/Stepper.stories.tsx +1 -1
  121. package/src/components/custom/stepper/Stepper.tsx +2 -2
  122. package/src/components/ui/autocomplete/Autocomplete.stories.tsx +1 -1
  123. package/src/components/ui/autocomplete/Autocomplete.tsx +1 -1
  124. package/src/components/ui/card/Card.tsx +1 -1
  125. package/src/components/ui/checkbox/Checkbox.tsx +1 -1
  126. package/src/components/ui/collapse/Collapse.tsx +1 -1
  127. package/src/components/ui/data-row/DataRow.stories.tsx +1 -1
  128. package/src/components/ui/drawer/Drawer.tsx +3 -3
  129. package/src/components/ui/form-field/FormField.tsx +1 -1
  130. package/src/components/ui/help-tip/HelpTip.tsx +1 -1
  131. package/src/components/ui/menu/Menu.tsx +2 -2
  132. package/src/components/ui/pill/Pill.tsx +1 -1
  133. package/src/components/ui/popover/Popover.stories.tsx +2 -2
  134. package/src/components/ui/popover/Popover.tsx +1 -1
  135. package/src/components/ui/radio/Radio.stories.tsx +1 -1
  136. package/src/components/ui/section/Section.stories.tsx +4 -4
  137. package/src/components/ui/select/Select.tsx +1 -1
  138. package/src/components/ui/stack/Stack.stories.tsx +4 -4
  139. package/src/components/ui/tabs/Tabs.tsx +2 -2
  140. package/src/components/ui/toolbar-button/ToolbarButton.stories.tsx +1 -1
  141. package/src/components/ui/toolbar-button/ToolbarButton.tsx +1 -1
  142. package/src/examples/react-hook-form/ControlledFields.tsx +171 -0
  143. package/src/examples/react-hook-form/ReactHookForm.stories.tsx +51 -0
  144. package/src/examples/react-hook-form/ReactHookForm.test.tsx +61 -0
  145. package/src/examples/react-hook-form/RhfContactForm.tsx +99 -0
  146. package/src/stories/PresetShowcase.stories.tsx +15 -15
  147. package/src/theme/index.ts +2 -1
  148. package/src/theme/manifest/css-property-manifest.example.json +79 -0
  149. package/src/theme/manifest/css-property-manifest.schema.json +93 -0
  150. package/src/theme/manifest/css-property-manifest.test.ts +81 -0
  151. package/src/theme/manifest/css-property-manifest.types.ts +49 -0
  152. package/src/theme/manifest/css-property-manifest.validate.ts +84 -0
  153. package/src/theme/manifest/index.ts +11 -0
  154. package/src/theme/tokens-css.test.ts +28 -0
  155. package/src/theme/tokens-css.ts +34 -0
  156. package/src/theme/workout-tokens.ts +61 -0
  157. package/dist/chunk-UXVRPOME.mjs.map +0 -1
@@ -1,2 +1,115 @@
1
+ export {
2
+ BaseBadge,
3
+ type BaseBadgeProps,
4
+ type BaseBadgeVariant,
5
+ type BaseBadgeSize,
6
+ } from './BaseBadge'
7
+ export {
8
+ WeightBadge,
9
+ type WeightBadgeProps,
10
+ type WeightBadgeSize,
11
+ } from './WeightBadge'
12
+ export { PrBadge, type PrBadgeProps, type PRType } from './PrBadge'
13
+ export { StatusDot, type StatusDotVariant, type StatusDotProps } from './StatusDot'
14
+ export { PlaceholderStrip, type PlaceholderStripProps } from './PlaceholderStrip'
15
+ export { TempoDisplay, type TempoDisplayProps } from './TempoDisplay'
16
+ export { DeviationBar, type DeviationBarProps } from './DeviationBar'
17
+ export { IntensityBar, type IntensityBarProps } from './IntensityBar'
18
+ export { WorkoutPill, type WorkoutPillProps, type WorkoutPillStatus } from './WorkoutPill'
19
+ export {
20
+ VelocityStrip,
21
+ type VelocityStripProps,
22
+ getVelocityZoneColor,
23
+ getVelocityZoneName,
24
+ calculateVelocityLoss,
25
+ calculateMeanVelocity,
26
+ } from './VelocityStrip'
27
+ export {
28
+ MuscleGroupChip,
29
+ type MuscleGroupChipProps,
30
+ type VolumeStatus,
31
+ } from './MuscleGroupChip'
32
+ export { Sparkline, type SparklineProps } from './Sparkline'
33
+ export { SetRow, type SetRowProps, type SetRowMode } from './SetRow'
34
+ export { InputBar, type InputBarProps } from './InputBar'
1
35
  export { RestTimer, type RestTimerProps } from './RestTimer'
36
+ export { ExerciseCard, type ExerciseCardProps, type ExerciseCardState } from './ExerciseCard'
2
37
  export { SupersetWrapper, type SupersetWrapperProps } from './SupersetWrapper'
38
+ export {
39
+ MesoProgressBar,
40
+ type MesoProgressBarProps,
41
+ type Meso,
42
+ type MesoStatus,
43
+ } from './MesoProgressBar'
44
+ export { WeekRow, type WeekRowProps, type WeekRowWorkout } from './WeekRow'
45
+ export {
46
+ WorkoutCard,
47
+ type WorkoutCardProps,
48
+ type WorkoutStatus,
49
+ type WorkoutMuscleGroup,
50
+ type WorkoutMuscleVolumeStatus,
51
+ } from './WorkoutCard'
52
+ export {
53
+ MesoCard,
54
+ type MesoCardProps,
55
+ type MesoVolumeHeatmapEntry,
56
+ } from './MesoCard'
57
+ export {
58
+ PrHistoryModal,
59
+ type PrHistoryModalProps,
60
+ type PrRecord,
61
+ type PrRecordType,
62
+ } from './PrHistoryModal'
63
+ export {
64
+ ReadinessCheck,
65
+ type ReadinessCheckProps,
66
+ type ReadinessFactor,
67
+ type WarmUpValidation,
68
+ type WarmUpStatus,
69
+ } from './ReadinessCheck'
70
+ export {
71
+ MesoStatusCard,
72
+ type MesoStatusCardProps,
73
+ type MesoStatusBadge,
74
+ type MesoStatusBadgeVariant,
75
+ type MesoStatusMetric,
76
+ type MesoStatusGauge,
77
+ type MesoStatusCoaching,
78
+ type MesoStatusNextTarget,
79
+ } from './MesoStatusCard'
80
+ export {
81
+ StrengthTrendChart,
82
+ type StrengthTrendChartProps,
83
+ type StrengthTrendDataPoint,
84
+ type StrengthTrendChartMesoBoundary,
85
+ } from './StrengthTrendChart'
86
+ export {
87
+ CapacityBandChart,
88
+ type CapacityBandChartProps,
89
+ type CapacityBandDataPoint,
90
+ type CapacityBandProjection,
91
+ type WorkoutDot,
92
+ type WorkoutDotStatus,
93
+ } from './CapacityBandChart'
94
+ export { BodyMap, type BodyMapProps, type BodyMapData } from './BodyMap'
95
+ export {
96
+ BodyMapDetailPanel,
97
+ type BodyMapDetailPanelProps,
98
+ type ContributingExercise,
99
+ type UpcomingExercise,
100
+ } from './BodyMapDetailPanel'
101
+ export {
102
+ MuscleGroup,
103
+ SimpleMuscleGroup,
104
+ SIMPLE_TO_DETAILED,
105
+ DETAILED_TO_SIMPLE,
106
+ MUSCLE_TO_SVG_SLUGS,
107
+ MUSCLE_TO_CATEGORY,
108
+ MUSCLE_DISPLAY_NAMES,
109
+ SIMPLE_DISPLAY_NAMES,
110
+ DEFAULT_VOLUME_LANDMARKS,
111
+ VOLUME_STATUS_LABELS,
112
+ getHeatmapColor,
113
+ type MovementCategory,
114
+ type VolumeLandmarks,
115
+ } from './muscleTaxonomy'
@@ -0,0 +1,252 @@
1
+ /**
2
+ * Muscle grouping taxonomy for volume tracking, exercise mapping, and the
3
+ * BodyMap visualization. Ported from the Voltras muscle-taxonomy design doc.
4
+ *
5
+ * Level 2 (15 groups) is the primary volume-tracking unit; SimpleMuscleGroup
6
+ * (8 groups) is the beginner-facing aggregation. MUSCLE_TO_SVG_SLUGS maps each
7
+ * group to react-native-body-highlighter slugs using the closest-slug approach
8
+ * (Phase 1: combined colors, no sub-region splitting — deltoids is a single
9
+ * slug, lats and upper back share `upper-back`).
10
+ */
11
+ import { WORKOUT_TOKENS } from '../../../theme/workout-tokens'
12
+
13
+ /**
14
+ * Full muscle group taxonomy for volume tracking and exercise mapping.
15
+ * 15 groups — the primary unit for volume accounting.
16
+ */
17
+ export enum MuscleGroup {
18
+ // Push
19
+ CHEST = 'chest',
20
+ FRONT_DELTS = 'front_delts',
21
+ SIDE_DELTS = 'side_delts',
22
+ TRICEPS = 'triceps',
23
+
24
+ // Pull
25
+ LATS = 'lats',
26
+ UPPER_BACK = 'upper_back',
27
+ REAR_DELTS = 'rear_delts',
28
+ BICEPS = 'biceps',
29
+ FOREARMS = 'forearms',
30
+
31
+ // Legs
32
+ QUADS = 'quads',
33
+ HAMSTRINGS = 'hamstrings',
34
+ GLUTES = 'glutes',
35
+ CALVES = 'calves',
36
+
37
+ // Core
38
+ ABS = 'abs',
39
+ OBLIQUES = 'obliques',
40
+ }
41
+
42
+ /**
43
+ * Simplified muscle group view for beginners. Maps to one or more MuscleGroup.
44
+ */
45
+ export enum SimpleMuscleGroup {
46
+ CHEST = 'chest',
47
+ BACK = 'back',
48
+ SHOULDERS = 'shoulders',
49
+ BICEPS = 'biceps',
50
+ TRICEPS = 'triceps',
51
+ LEGS = 'legs',
52
+ CORE = 'core',
53
+ FOREARMS = 'forearms',
54
+ }
55
+
56
+ /** Mapping from simplified groups to the full taxonomy. */
57
+ export const SIMPLE_TO_DETAILED: Record<SimpleMuscleGroup, MuscleGroup[]> = {
58
+ [SimpleMuscleGroup.CHEST]: [MuscleGroup.CHEST],
59
+ [SimpleMuscleGroup.BACK]: [MuscleGroup.LATS, MuscleGroup.UPPER_BACK],
60
+ [SimpleMuscleGroup.SHOULDERS]: [
61
+ MuscleGroup.FRONT_DELTS,
62
+ MuscleGroup.SIDE_DELTS,
63
+ MuscleGroup.REAR_DELTS,
64
+ ],
65
+ [SimpleMuscleGroup.BICEPS]: [MuscleGroup.BICEPS],
66
+ [SimpleMuscleGroup.TRICEPS]: [MuscleGroup.TRICEPS],
67
+ [SimpleMuscleGroup.LEGS]: [
68
+ MuscleGroup.QUADS,
69
+ MuscleGroup.HAMSTRINGS,
70
+ MuscleGroup.GLUTES,
71
+ MuscleGroup.CALVES,
72
+ ],
73
+ [SimpleMuscleGroup.CORE]: [MuscleGroup.ABS, MuscleGroup.OBLIQUES],
74
+ [SimpleMuscleGroup.FOREARMS]: [MuscleGroup.FOREARMS],
75
+ }
76
+
77
+ /** Reverse map: detailed MuscleGroup -> its SimpleMuscleGroup. */
78
+ export const DETAILED_TO_SIMPLE: Record<MuscleGroup, SimpleMuscleGroup> = Object.entries(
79
+ SIMPLE_TO_DETAILED
80
+ ).reduce(
81
+ (acc, [simple, groups]) => {
82
+ for (const group of groups) {
83
+ acc[group] = simple as SimpleMuscleGroup
84
+ }
85
+ return acc
86
+ },
87
+ {} as Record<MuscleGroup, SimpleMuscleGroup>
88
+ )
89
+
90
+ /** Movement category for training split organization. */
91
+ export type MovementCategory = 'push' | 'pull' | 'legs' | 'core'
92
+
93
+ export const MUSCLE_TO_CATEGORY: Record<MuscleGroup, MovementCategory> = {
94
+ [MuscleGroup.CHEST]: 'push',
95
+ [MuscleGroup.FRONT_DELTS]: 'push',
96
+ [MuscleGroup.SIDE_DELTS]: 'push',
97
+ [MuscleGroup.TRICEPS]: 'push',
98
+ [MuscleGroup.LATS]: 'pull',
99
+ [MuscleGroup.UPPER_BACK]: 'pull',
100
+ [MuscleGroup.REAR_DELTS]: 'pull',
101
+ [MuscleGroup.BICEPS]: 'pull',
102
+ [MuscleGroup.FOREARMS]: 'pull',
103
+ [MuscleGroup.QUADS]: 'legs',
104
+ [MuscleGroup.HAMSTRINGS]: 'legs',
105
+ [MuscleGroup.GLUTES]: 'legs',
106
+ [MuscleGroup.CALVES]: 'legs',
107
+ [MuscleGroup.ABS]: 'core',
108
+ [MuscleGroup.OBLIQUES]: 'core',
109
+ }
110
+
111
+ /**
112
+ * react-native-body-highlighter slug(s) per muscle group. Phase 1 uses the
113
+ * closest available slug; deltoids share one path and lats/upper-back share
114
+ * `upper-back` (see doc Level 4 "Recommended approach").
115
+ */
116
+ export const MUSCLE_TO_SVG_SLUGS: Record<MuscleGroup, string[]> = {
117
+ [MuscleGroup.CHEST]: ['chest'],
118
+ [MuscleGroup.FRONT_DELTS]: ['deltoids'],
119
+ [MuscleGroup.SIDE_DELTS]: ['deltoids'],
120
+ [MuscleGroup.REAR_DELTS]: ['deltoids'],
121
+ [MuscleGroup.TRICEPS]: ['triceps'],
122
+ [MuscleGroup.LATS]: ['upper-back'],
123
+ [MuscleGroup.UPPER_BACK]: ['upper-back', 'trapezius'],
124
+ [MuscleGroup.BICEPS]: ['biceps'],
125
+ [MuscleGroup.FOREARMS]: ['forearm'],
126
+ [MuscleGroup.QUADS]: ['quadriceps'],
127
+ [MuscleGroup.HAMSTRINGS]: ['hamstring'],
128
+ [MuscleGroup.GLUTES]: ['gluteal'],
129
+ [MuscleGroup.CALVES]: ['calves'],
130
+ [MuscleGroup.ABS]: ['abs'],
131
+ [MuscleGroup.OBLIQUES]: ['obliques'],
132
+ }
133
+
134
+ /** Human-readable name per muscle group (used in a11y labels). */
135
+ export const MUSCLE_DISPLAY_NAMES: Record<MuscleGroup, string> = {
136
+ [MuscleGroup.CHEST]: 'Chest',
137
+ [MuscleGroup.FRONT_DELTS]: 'Front Delts',
138
+ [MuscleGroup.SIDE_DELTS]: 'Side Delts',
139
+ [MuscleGroup.REAR_DELTS]: 'Rear Delts',
140
+ [MuscleGroup.TRICEPS]: 'Triceps',
141
+ [MuscleGroup.LATS]: 'Lats',
142
+ [MuscleGroup.UPPER_BACK]: 'Upper Back',
143
+ [MuscleGroup.BICEPS]: 'Biceps',
144
+ [MuscleGroup.FOREARMS]: 'Forearms',
145
+ [MuscleGroup.QUADS]: 'Quads',
146
+ [MuscleGroup.HAMSTRINGS]: 'Hamstrings',
147
+ [MuscleGroup.GLUTES]: 'Glutes',
148
+ [MuscleGroup.CALVES]: 'Calves',
149
+ [MuscleGroup.ABS]: 'Abs',
150
+ [MuscleGroup.OBLIQUES]: 'Obliques',
151
+ }
152
+
153
+ /** Human-readable name per simple group. */
154
+ export const SIMPLE_DISPLAY_NAMES: Record<SimpleMuscleGroup, string> = {
155
+ [SimpleMuscleGroup.CHEST]: 'Chest',
156
+ [SimpleMuscleGroup.BACK]: 'Back',
157
+ [SimpleMuscleGroup.SHOULDERS]: 'Shoulders',
158
+ [SimpleMuscleGroup.BICEPS]: 'Biceps',
159
+ [SimpleMuscleGroup.TRICEPS]: 'Triceps',
160
+ [SimpleMuscleGroup.LEGS]: 'Legs',
161
+ [SimpleMuscleGroup.CORE]: 'Core',
162
+ [SimpleMuscleGroup.FOREARMS]: 'Forearms',
163
+ }
164
+
165
+ /** Volume landmarks per muscle group (weekly working sets). */
166
+ export interface VolumeLandmarks {
167
+ mev: number // Minimum Effective Volume
168
+ mav: number // Maximum Adaptive Volume
169
+ mrv: number // Maximum Recoverable Volume
170
+ }
171
+
172
+ export const DEFAULT_VOLUME_LANDMARKS: Record<MuscleGroup, VolumeLandmarks> = {
173
+ [MuscleGroup.CHEST]: { mev: 8, mav: 14, mrv: 20 },
174
+ [MuscleGroup.LATS]: { mev: 8, mav: 14, mrv: 20 },
175
+ [MuscleGroup.UPPER_BACK]: { mev: 6, mav: 12, mrv: 18 },
176
+ [MuscleGroup.FRONT_DELTS]: { mev: 2, mav: 6, mrv: 10 },
177
+ [MuscleGroup.SIDE_DELTS]: { mev: 6, mav: 14, mrv: 22 },
178
+ [MuscleGroup.REAR_DELTS]: { mev: 6, mav: 12, mrv: 18 },
179
+ [MuscleGroup.BICEPS]: { mev: 4, mav: 10, mrv: 18 },
180
+ [MuscleGroup.TRICEPS]: { mev: 4, mav: 8, mrv: 14 },
181
+ [MuscleGroup.FOREARMS]: { mev: 2, mav: 6, mrv: 12 },
182
+ [MuscleGroup.QUADS]: { mev: 6, mav: 12, mrv: 18 },
183
+ [MuscleGroup.HAMSTRINGS]: { mev: 4, mav: 10, mrv: 16 },
184
+ [MuscleGroup.GLUTES]: { mev: 4, mav: 10, mrv: 16 },
185
+ [MuscleGroup.CALVES]: { mev: 6, mav: 10, mrv: 16 },
186
+ [MuscleGroup.ABS]: { mev: 0, mav: 8, mrv: 16 },
187
+ [MuscleGroup.OBLIQUES]: { mev: 0, mav: 6, mrv: 12 },
188
+ }
189
+
190
+ /** Weekly-volume status relative to MEV/MAV/MRV landmarks. */
191
+ export type VolumeStatus = 'under' | 'maintenance' | 'productive' | 'over'
192
+
193
+ /** Readable label per status for a11y descriptions. */
194
+ export const VOLUME_STATUS_LABELS: Record<VolumeStatus, string> = {
195
+ under: 'under-trained',
196
+ maintenance: 'maintenance',
197
+ productive: 'productive',
198
+ over: 'over-reaching',
199
+ }
200
+
201
+ /** Severity ranking — higher wins when several groups share an SVG slug. */
202
+ const STATUS_SEVERITY: Record<VolumeStatus, number> = {
203
+ under: 1,
204
+ maintenance: 2,
205
+ productive: 3,
206
+ over: 4,
207
+ }
208
+
209
+ /**
210
+ * Maps a volume status (and intensity, 0-1) to a heatmap fill color. The
211
+ * `approaching` token is used when a productive muscle nears its MRV.
212
+ */
213
+ export function getHeatmapColor(status: VolumeStatus | null | undefined, intensity = 0): string {
214
+ const heatmap = WORKOUT_TOKENS.heatmap
215
+ switch (status) {
216
+ case 'under':
217
+ return heatmap.under
218
+ case 'maintenance':
219
+ return heatmap.maintenance
220
+ case 'productive':
221
+ return intensity >= 0.85 ? heatmap.approaching : heatmap.productive
222
+ case 'over':
223
+ return heatmap.over
224
+ default:
225
+ return heatmap.none
226
+ }
227
+ }
228
+
229
+ /** True when one status is at least as severe as another. */
230
+ export function isMoreSevere(a: VolumeStatus, b: VolumeStatus): boolean {
231
+ return STATUS_SEVERITY[a] >= STATUS_SEVERITY[b]
232
+ }
233
+
234
+ /**
235
+ * Representative MuscleGroup for each SVG slug, used to resolve taps on shared
236
+ * paths (e.g. `deltoids`, `upper-back`) back to a single group.
237
+ */
238
+ export const SLUG_TO_PRIMARY_MUSCLE: Record<string, MuscleGroup> = {
239
+ chest: MuscleGroup.CHEST,
240
+ deltoids: MuscleGroup.SIDE_DELTS,
241
+ triceps: MuscleGroup.TRICEPS,
242
+ 'upper-back': MuscleGroup.LATS,
243
+ trapezius: MuscleGroup.UPPER_BACK,
244
+ biceps: MuscleGroup.BICEPS,
245
+ forearm: MuscleGroup.FOREARMS,
246
+ quadriceps: MuscleGroup.QUADS,
247
+ hamstring: MuscleGroup.HAMSTRINGS,
248
+ gluteal: MuscleGroup.GLUTES,
249
+ calves: MuscleGroup.CALVES,
250
+ abs: MuscleGroup.ABS,
251
+ obliques: MuscleGroup.OBLIQUES,
252
+ }
@@ -7,3 +7,6 @@ export * from './stepper'
7
7
  export * from './DateTime'
8
8
  export * from './Metric'
9
9
  export * from './Workout'
10
+ export * from './Treemap'
11
+ export * from './Scatter'
12
+ export * from './Gauge'
@@ -137,7 +137,7 @@ export const VerticalWithContent: Story = {
137
137
  <Text className="text-text-secondary text-sm">
138
138
  Fill in your profile details to continue.
139
139
  </Text>
140
- <View className="bg-surface-inset border border-border-default rounded-md px-3 py-2">
140
+ <View className="bg-surface-input border border-border rounded-md px-3 py-2">
141
141
  <Text className="text-text-secondary text-sm">Display Name</Text>
142
142
  </View>
143
143
  </View>
@@ -91,7 +91,7 @@ function StepConnector({ index }: StepConnectorProps) {
91
91
  <View
92
92
  className={cn(
93
93
  'flex-1 h-0.5 mx-2',
94
- isCompleted ? 'bg-brand-primary' : 'bg-border-default'
94
+ isCompleted ? 'bg-brand-primary' : 'bg-border'
95
95
  )}
96
96
  />
97
97
  )
@@ -101,7 +101,7 @@ function StepConnector({ index }: StepConnectorProps) {
101
101
  <View
102
102
  className={cn(
103
103
  'w-0.5 h-8 ml-4 my-1',
104
- isCompleted ? 'bg-brand-primary' : 'bg-border-default'
104
+ isCompleted ? 'bg-brand-primary' : 'bg-border'
105
105
  )}
106
106
  />
107
107
  )
@@ -287,7 +287,7 @@ export const FormExample: Story = {
287
287
  isRequired
288
288
  />
289
289
 
290
- <View className="pt-2 border-t border-border-default">
290
+ <View className="pt-2 border-t border-border">
291
291
  <Text className="text-sm text-text-secondary">
292
292
  Selected: {country ? `${countryOptions.find(c => c.value === country)?.label}` : '-'}
293
293
  {city ? `, ${cityOptions[country!]?.find(c => c.value === city)?.label}` : ''}
@@ -238,7 +238,7 @@ export function Autocomplete<T extends string = string>({
238
238
  <View
239
239
  className={cn(
240
240
  'absolute z-50 top-full left-0 right-0 mt-1',
241
- 'bg-surface-elevated rounded-md shadow-lg border border-border-default',
241
+ 'bg-surface-elevated rounded-md shadow-lg border border-border',
242
242
  'max-h-60 overflow-hidden'
243
243
  )}
244
244
  >
@@ -47,7 +47,7 @@ const variantStyles: Record<CardVariant, string> = {
47
47
  elevated: '', // Will be set dynamically via elevation system
48
48
  outline: 'border-2 border-border-strong', // Thicker border with stronger contrast
49
49
  filled: '', // Will be set dynamically via elevation system
50
- accent: 'border border-border-default',
50
+ accent: 'border border-border',
51
51
  subtle: 'border border-border-subtle',
52
52
  }
53
53
 
@@ -91,7 +91,7 @@ export const Checkbox = forwardRef<View, CheckboxProps>(function Checkbox(
91
91
  styles.box,
92
92
  isChecked || isIndeterminate
93
93
  ? 'bg-brand-primary border-brand-primary'
94
- : 'bg-transparent border-border-default',
94
+ : 'bg-transparent border-border',
95
95
  isInvalid && 'border-status-error',
96
96
  !isDisabled && 'web:hover:border-brand-primary'
97
97
  )}
@@ -180,7 +180,7 @@ export function Accordion({
180
180
 
181
181
  return (
182
182
  <AccordionContext.Provider value={{ openIndices, toggleIndex, allowMultiple }}>
183
- <View className={cn('w-full divide-y divide-border-default', className)} {...props}>
183
+ <View className={cn('w-full divide-y divide-border', className)} {...props}>
184
184
  {React.Children.map(children, (child, index) => {
185
185
  if (React.isValidElement(child)) {
186
186
  return React.cloneElement(child as React.ReactElement<any>, { index })
@@ -73,6 +73,6 @@ export const CustomClassName: Story = {
73
73
  args: {
74
74
  label: 'Bordered Row',
75
75
  value: 'With custom styles',
76
- className: 'border-b border-border-primary px-4',
76
+ className: 'border-b border-border px-4',
77
77
  },
78
78
  }
@@ -125,7 +125,7 @@ export function Drawer({
125
125
  >
126
126
  {/* Header */}
127
127
  {(title || showCloseButton) && (
128
- <View className="flex-row items-center justify-between px-4 py-3 border-b border-border-default">
128
+ <View className="flex-row items-center justify-between px-4 py-3 border-b border-border">
129
129
  {title && (
130
130
  <Text className="text-lg font-semibold text-text-primary">
131
131
  {title}
@@ -165,7 +165,7 @@ export interface DrawerHeaderProps extends ViewProps {
165
165
  export function DrawerHeader({ className, children, ...props }: DrawerHeaderProps) {
166
166
  return (
167
167
  <View
168
- className={cn('px-4 py-3 border-b border-border-default', className)}
168
+ className={cn('px-4 py-3 border-b border-border', className)}
169
169
  {...props}
170
170
  >
171
171
  {children}
@@ -217,7 +217,7 @@ export function DrawerFooter({ className, children, ...props }: DrawerFooterProp
217
217
  <View
218
218
  className={cn(
219
219
  'flex-row items-center justify-end gap-3',
220
- 'px-4 py-3 border-t border-border-default',
220
+ 'px-4 py-3 border-t border-border',
221
221
  className
222
222
  )}
223
223
  {...props}
@@ -253,7 +253,7 @@ export function FormActions({
253
253
  <View
254
254
  className={cn(
255
255
  'flex-row items-center gap-3 pt-4',
256
- 'border-t border-border-default mt-4',
256
+ 'border-t border-border mt-4',
257
257
  alignStyles[align],
258
258
  className
259
259
  )}
@@ -155,7 +155,7 @@ export function HelpTip({
155
155
  className={cn(
156
156
  'absolute z-50',
157
157
  'bg-surface-elevated rounded-lg shadow-lg',
158
- 'border border-border-default',
158
+ 'border border-border',
159
159
  'px-3 py-2',
160
160
  placementStyles[placement],
161
161
  tooltipClassName
@@ -116,7 +116,7 @@ export function MenuList({ children, className }: MenuListProps) {
116
116
  <View
117
117
  className={cn(
118
118
  'absolute z-50 top-full left-0 mt-1 min-w-[160px]',
119
- 'bg-surface-elevated rounded-lg shadow-lg border border-border-default',
119
+ 'bg-surface-elevated rounded-lg shadow-lg border border-border',
120
120
  'py-1 overflow-hidden',
121
121
  className
122
122
  )}
@@ -195,7 +195,7 @@ export interface MenuDividerProps {
195
195
  * Divider between menu items.
196
196
  */
197
197
  export function MenuDivider({ className }: MenuDividerProps) {
198
- return <View className={cn('h-px bg-border-default my-1', className)} />
198
+ return <View className={cn('h-px bg-border my-1', className)} />
199
199
  }
200
200
 
201
201
  export interface MenuGroupProps {
@@ -36,7 +36,7 @@ const variantColorStyles: Record<PillVariant, Record<PillColor, string>> = {
36
36
  info: 'bg-status-info/10 border-status-info/25 text-status-info',
37
37
  },
38
38
  outline: {
39
- default: 'border-border-default text-text-secondary',
39
+ default: 'border-border text-text-secondary',
40
40
  primary: 'border-brand-primary text-brand-primary',
41
41
  secondary: 'border-brand-secondary text-brand-secondary',
42
42
  success: 'border-status-success text-status-success',
@@ -152,12 +152,12 @@ export const WithFormContent: Story = {
152
152
  <Text className="text-text-secondary text-xs">
153
153
  Enter your new display name below.
154
154
  </Text>
155
- <View className="bg-surface-inset border border-border-default rounded-md px-3 py-2">
155
+ <View className="bg-surface-input border border-border rounded-md px-3 py-2">
156
156
  <Text className="text-text-secondary text-sm">John Doe</Text>
157
157
  </View>
158
158
  <View style={{ flexDirection: 'row', gap: 8, justifyContent: 'flex-end' }}>
159
159
  <PopoverCloseButton>
160
- <View className="px-3 py-1.5 rounded-md bg-surface-elevated border border-border-default">
160
+ <View className="px-3 py-1.5 rounded-md bg-surface-elevated border border-border">
161
161
  <Text className="text-text-primary text-sm">Cancel</Text>
162
162
  </View>
163
163
  </PopoverCloseButton>
@@ -188,7 +188,7 @@ export function PopoverContent({ children, className }: PopoverContentProps) {
188
188
  <View
189
189
  className={cn(
190
190
  'absolute z-50 min-w-[200px]',
191
- 'bg-surface-elevated rounded-lg shadow-lg border border-border-default',
191
+ 'bg-surface-elevated rounded-lg shadow-lg border border-border',
192
192
  'p-4',
193
193
  placementStyles[placement],
194
194
  className
@@ -188,7 +188,7 @@ export const FormExample: Story = {
188
188
  <Radio value="yearly">Yearly (save 20%)</Radio>
189
189
  </RadioGroup>
190
190
 
191
- <View className="pt-4 border-t border-border-default">
191
+ <View className="pt-4 border-t border-border">
192
192
  <Text className="text-sm text-text-secondary">
193
193
  Selected: {plan} plan, billed {billing}
194
194
  </Text>
@@ -62,7 +62,7 @@ export const FullExample: Story = {
62
62
  <Text style={{ color: '#6366f1', fontSize: 13 }}>Details</Text>
63
63
  }
64
64
  />
65
- <SectionContent className="rounded-lg bg-surface-secondary p-4">
65
+ <SectionContent className="rounded-lg bg-surface-elevated p-4">
66
66
  <Text style={{ color: '#a0a0a0' }}>Chart or data visualization</Text>
67
67
  </SectionContent>
68
68
  </Section>
@@ -74,7 +74,7 @@ export const MultipleSections: Story = {
74
74
  <View>
75
75
  <Section>
76
76
  <SectionHeader title="Today" subtitle="3 exercises" />
77
- <SectionContent className="rounded-lg bg-surface-secondary p-4">
77
+ <SectionContent className="rounded-lg bg-surface-elevated p-4">
78
78
  <Text style={{ color: '#a0a0a0' }}>Today&apos;s workout data</Text>
79
79
  </SectionContent>
80
80
  </Section>
@@ -87,14 +87,14 @@ export const MultipleSections: Story = {
87
87
  <Text style={{ color: '#6366f1', fontSize: 13 }}>See All</Text>
88
88
  }
89
89
  />
90
- <SectionContent className="rounded-lg bg-surface-secondary p-4">
90
+ <SectionContent className="rounded-lg bg-surface-elevated p-4">
91
91
  <Text style={{ color: '#a0a0a0' }}>Weekly summary</Text>
92
92
  </SectionContent>
93
93
  </Section>
94
94
 
95
95
  <Section>
96
96
  <SectionHeader title="Personal Records" />
97
- <SectionContent className="rounded-lg bg-surface-secondary p-4">
97
+ <SectionContent className="rounded-lg bg-surface-elevated p-4">
98
98
  <Text style={{ color: '#a0a0a0' }}>PR list</Text>
99
99
  </SectionContent>
100
100
  </Section>
@@ -187,7 +187,7 @@ export function Select<T extends string = string>({
187
187
  <View
188
188
  className={cn(
189
189
  'absolute z-50 top-full left-0 right-0 mt-1',
190
- 'bg-surface-elevated rounded-md shadow-lg border border-border-default',
190
+ 'bg-surface-elevated rounded-md shadow-lg border border-border',
191
191
  'max-h-60 overflow-hidden'
192
192
  )}
193
193
  >
@@ -34,7 +34,7 @@ type Story = StoryObj<typeof Stack>
34
34
 
35
35
  function Box({ children }: { children: string }) {
36
36
  return (
37
- <View className="rounded bg-primary-500 px-4 py-2">
37
+ <View className="rounded bg-brand-primary px-4 py-2">
38
38
  <Text className="text-sm text-white">{children}</Text>
39
39
  </View>
40
40
  )
@@ -85,13 +85,13 @@ export const WithAlignment: Story = {
85
85
 
86
86
  <Text className="text-sm font-medium text-neutral-400">align=&quot;center&quot;</Text>
87
87
  <HStack gap={2} align="center">
88
- <View className="rounded bg-primary-500 px-4 py-1">
88
+ <View className="rounded bg-brand-primary px-4 py-1">
89
89
  <Text className="text-sm text-white">Short</Text>
90
90
  </View>
91
- <View className="rounded bg-primary-500 px-4 py-4">
91
+ <View className="rounded bg-brand-primary px-4 py-4">
92
92
  <Text className="text-sm text-white">Tall</Text>
93
93
  </View>
94
- <View className="rounded bg-primary-500 px-4 py-2">
94
+ <View className="rounded bg-brand-primary px-4 py-2">
95
95
  <Text className="text-sm text-white">Medium</Text>
96
96
  </View>
97
97
  </HStack>
@@ -100,8 +100,8 @@ export function TabList({ children, className }: TabListProps) {
100
100
 
101
101
  const variantStyles = {
102
102
  line: orientation === 'horizontal'
103
- ? 'border-b border-border-default'
104
- : 'border-r border-border-default',
103
+ ? 'border-b border-border'
104
+ : 'border-r border-border',
105
105
  enclosed: 'bg-surface-raised rounded-lg p-1',
106
106
  'soft-rounded': 'bg-surface-raised rounded-full p-1',
107
107
  }