@titan-design/react-ui 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/dist/MesoStatusCard-CQk71hSi.d.mts +77 -0
  2. package/dist/MesoStatusCard-CQk71hSi.d.ts +77 -0
  3. package/dist/bodymap.d.mts +246 -3
  4. package/dist/bodymap.d.ts +246 -3
  5. package/dist/bodymap.js +441 -97
  6. package/dist/bodymap.js.map +1 -1
  7. package/dist/bodymap.mjs +1958 -66
  8. package/dist/bodymap.mjs.map +1 -1
  9. package/dist/index.d.mts +71 -738
  10. package/dist/index.d.ts +71 -738
  11. package/dist/index.js +888 -1583
  12. package/dist/index.js.map +1 -1
  13. package/dist/index.mjs +4515 -2348
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/pages-D7Jlssvp.d.ts +791 -0
  16. package/dist/pages-MO0JCySL.d.mts +791 -0
  17. package/dist/pages.d.mts +4 -0
  18. package/dist/pages.d.ts +4 -0
  19. package/dist/pages.js +6646 -0
  20. package/dist/pages.js.map +1 -0
  21. package/dist/pages.mjs +6626 -0
  22. package/dist/pages.mjs.map +1 -0
  23. package/dist/theme/index.d.mts +28 -2
  24. package/dist/theme/index.d.ts +28 -2
  25. package/dist/theme/index.js +37 -0
  26. package/dist/theme/index.js.map +1 -1
  27. package/dist/theme/index.mjs +1880 -2
  28. package/dist/theme/index.mjs.map +1 -1
  29. package/dist/theme/tokens-css.mjs +573 -1
  30. package/dist/theme/tokens-css.mjs.map +1 -1
  31. package/package.json +9 -7
  32. package/src/components/custom/Workout/ActiveWorkoutPage.tsx +10 -15
  33. package/src/components/custom/Workout/BaseBadge.stories.tsx +3 -3
  34. package/src/components/custom/Workout/BaseBadge.test.tsx +1 -1
  35. package/src/components/custom/Workout/BaseBadge.tsx +1 -1
  36. package/src/components/custom/Workout/BodyMap.tsx +7 -8
  37. package/src/components/custom/Workout/BodyMapDetailPanel.tsx +25 -28
  38. package/src/components/custom/Workout/CapacityBandChart.tsx +2 -3
  39. package/src/components/custom/Workout/ExerciseCard.tsx +17 -28
  40. package/src/components/custom/Workout/ExerciseDetailPage.tsx +38 -31
  41. package/src/components/custom/Workout/InputBar.tsx +10 -11
  42. package/src/components/custom/Workout/IntensityBar.test.tsx +112 -60
  43. package/src/components/custom/Workout/IntensityBar.tsx +109 -58
  44. package/src/components/custom/Workout/MesoCard.tsx +2 -6
  45. package/src/components/custom/Workout/MesoStatusCard.tsx +17 -15
  46. package/src/components/custom/Workout/MuscleGroupChip.tsx +2 -4
  47. package/src/components/custom/Workout/PlaceholderStrip.tsx +5 -10
  48. package/src/components/custom/Workout/PrBadge.tsx +3 -3
  49. package/src/components/custom/Workout/PrHistoryModal.tsx +14 -16
  50. package/src/components/custom/Workout/ProgramPlanningPage.tsx +8 -12
  51. package/src/components/custom/Workout/README.md +50 -0
  52. package/src/components/custom/Workout/ReadinessCheck.tsx +13 -11
  53. package/src/components/custom/Workout/RestTimer.test.tsx +41 -10
  54. package/src/components/custom/Workout/RestTimer.tsx +55 -49
  55. package/src/components/custom/Workout/SetRow.tsx +20 -8
  56. package/src/components/custom/Workout/StrengthTrendChart.tsx +15 -17
  57. package/src/components/custom/Workout/TempoBar.stories.tsx +95 -0
  58. package/src/components/custom/Workout/TempoBar.test.tsx +103 -0
  59. package/src/components/custom/Workout/TempoBar.tsx +215 -0
  60. package/src/components/custom/Workout/TempoDisplay.stories.tsx +69 -2
  61. package/src/components/custom/Workout/TempoDisplay.test.tsx +35 -0
  62. package/src/components/custom/Workout/TempoDisplay.tsx +104 -1
  63. package/src/components/custom/Workout/TrainingStatusPage.tsx +8 -17
  64. package/src/components/custom/Workout/VelocityStrip.test.tsx +89 -2
  65. package/src/components/custom/Workout/VelocityStrip.tsx +210 -43
  66. package/src/components/custom/Workout/WeekRow.test.tsx +2 -2
  67. package/src/components/custom/Workout/WeekRow.tsx +2 -1
  68. package/src/components/custom/Workout/WeightBadge.test.tsx +2 -2
  69. package/src/components/custom/Workout/WeightBadge.tsx +2 -2
  70. package/src/components/custom/Workout/WorkoutCard.tsx +3 -8
  71. package/src/components/custom/Workout/icons.tsx +68 -0
  72. package/src/components/custom/Workout/index.ts +47 -47
  73. package/src/index.ts +3 -2
  74. package/src/pages.ts +61 -0
  75. package/src/test/nativewind-stub.ts +13 -0
  76. package/src/test/stories-smoke.test.tsx +50 -0
  77. package/src/theme/ThemeProvider.test.tsx +24 -0
  78. package/src/theme/ThemeProvider.tsx +50 -0
  79. package/src/theme/barrel.ts +53 -0
  80. package/src/theme/index.ts +8 -41
  81. package/src/theme/native-theming-guard.test.ts +117 -0
  82. package/src/theme/resolve-color.ts +19 -0
  83. package/dist/bodymap-BhG55xHM.d.mts +0 -318
  84. package/dist/bodymap-BhG55xHM.d.ts +0 -318
  85. package/dist/chunk-7XPB4NAO.mjs +0 -1013
  86. package/dist/chunk-7XPB4NAO.mjs.map +0 -1
  87. package/dist/chunk-P7TSQUN6.mjs +0 -846
  88. package/dist/chunk-P7TSQUN6.mjs.map +0 -1
  89. package/dist/chunk-TOD2WQBG.mjs +0 -1048
  90. package/dist/chunk-TOD2WQBG.mjs.map +0 -1
@@ -0,0 +1,77 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ViewProps } from 'react-native';
3
+
4
+ type MesoStatusBadgeVariant = 'success' | 'warning' | 'error';
5
+ interface MesoStatusBadge {
6
+ /** Short status label, e.g. "On Track". */
7
+ label: string;
8
+ /** Color treatment for the badge. */
9
+ variant: MesoStatusBadgeVariant;
10
+ }
11
+ interface MesoStatusMetric {
12
+ /** Cell label, e.g. "Prescribed". */
13
+ label: string;
14
+ /** Cell value, e.g. "3×8 @ RPE 8". */
15
+ value: string;
16
+ }
17
+ interface MesoStatusGauge {
18
+ /** Gauge label, e.g. "Intensity". */
19
+ label: string;
20
+ /** Fill position 0-1; the 14px marker sits at this level. */
21
+ level: number;
22
+ /** Optional right-aligned sublabel, e.g. "Prescribed". */
23
+ sublabel?: string;
24
+ }
25
+ interface MesoStatusCoaching {
26
+ /** Coaching recommendation copy. */
27
+ text: string;
28
+ /** Substrings within `text` to render in bold. */
29
+ highlights?: string[];
30
+ }
31
+ interface MesoStatusNextTarget {
32
+ /** Leading glyph/emoji, e.g. "→" or "🎯". */
33
+ icon: string;
34
+ /** Next-session target copy. */
35
+ text: string;
36
+ }
37
+ interface MesoStatusCardProps extends ViewProps {
38
+ /** Mesocycle name, e.g. "Hypertrophy Block". */
39
+ mesoName: string;
40
+ /** Context line, e.g. "Week 6 of 8 · Upper/Lower". */
41
+ mesoSubtitle: string;
42
+ /** Status pill in the header. */
43
+ statusBadge: MesoStatusBadge;
44
+ /** Prescription-vs-actual metrics rendered as a 2x2 grid. */
45
+ metrics: MesoStatusMetric[];
46
+ /** Intensity / volume gauges stacked vertically. */
47
+ gauges: MesoStatusGauge[];
48
+ /** Optional coaching recommendation box. */
49
+ coaching?: MesoStatusCoaching;
50
+ /** Optional next-session target box. */
51
+ nextTarget?: MesoStatusNextTarget;
52
+ className?: string;
53
+ }
54
+ /**
55
+ * Mesocycle context card for a specific exercise: prescription vs actual
56
+ * metrics, intensity/volume gauges, and coaching guidance. Composes the titan
57
+ * `Card` plus the Workout `StatusDot`, and renders the §25 gauge (8px track,
58
+ * 50% center line, 14px marker) inline since that visual differs from the
59
+ * IntensityBar/DeviationBar primitives.
60
+ *
61
+ * @example
62
+ * <MesoStatusCard
63
+ * mesoName="Hypertrophy Block"
64
+ * mesoSubtitle="Week 6 of 8 · Upper/Lower"
65
+ * statusBadge={{ label: 'On Track', variant: 'success' }}
66
+ * metrics={[
67
+ * { label: 'Prescribed', value: '3×8 @ RPE 8' },
68
+ * { label: 'Actual', value: '3×8 @ 185 lbs' },
69
+ * ]}
70
+ * gauges={[{ label: 'Intensity', level: 0.7, sublabel: 'Actual' }]}
71
+ * coaching={{ text: 'Add load next session.', highlights: ['Add load'] }}
72
+ * nextTarget={{ icon: '→', text: '190 lbs × 8' }}
73
+ * />
74
+ */
75
+ declare function MesoStatusCard({ mesoName, mesoSubtitle, statusBadge, metrics, gauges, coaching, nextTarget, className, ...props }: MesoStatusCardProps): react_jsx_runtime.JSX.Element;
76
+
77
+ export { type MesoStatusBadge as M, type MesoStatusBadgeVariant as a, MesoStatusCard as b, type MesoStatusCardProps as c, type MesoStatusCoaching as d, type MesoStatusGauge as e, type MesoStatusMetric as f, type MesoStatusNextTarget as g };
@@ -0,0 +1,77 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ViewProps } from 'react-native';
3
+
4
+ type MesoStatusBadgeVariant = 'success' | 'warning' | 'error';
5
+ interface MesoStatusBadge {
6
+ /** Short status label, e.g. "On Track". */
7
+ label: string;
8
+ /** Color treatment for the badge. */
9
+ variant: MesoStatusBadgeVariant;
10
+ }
11
+ interface MesoStatusMetric {
12
+ /** Cell label, e.g. "Prescribed". */
13
+ label: string;
14
+ /** Cell value, e.g. "3×8 @ RPE 8". */
15
+ value: string;
16
+ }
17
+ interface MesoStatusGauge {
18
+ /** Gauge label, e.g. "Intensity". */
19
+ label: string;
20
+ /** Fill position 0-1; the 14px marker sits at this level. */
21
+ level: number;
22
+ /** Optional right-aligned sublabel, e.g. "Prescribed". */
23
+ sublabel?: string;
24
+ }
25
+ interface MesoStatusCoaching {
26
+ /** Coaching recommendation copy. */
27
+ text: string;
28
+ /** Substrings within `text` to render in bold. */
29
+ highlights?: string[];
30
+ }
31
+ interface MesoStatusNextTarget {
32
+ /** Leading glyph/emoji, e.g. "→" or "🎯". */
33
+ icon: string;
34
+ /** Next-session target copy. */
35
+ text: string;
36
+ }
37
+ interface MesoStatusCardProps extends ViewProps {
38
+ /** Mesocycle name, e.g. "Hypertrophy Block". */
39
+ mesoName: string;
40
+ /** Context line, e.g. "Week 6 of 8 · Upper/Lower". */
41
+ mesoSubtitle: string;
42
+ /** Status pill in the header. */
43
+ statusBadge: MesoStatusBadge;
44
+ /** Prescription-vs-actual metrics rendered as a 2x2 grid. */
45
+ metrics: MesoStatusMetric[];
46
+ /** Intensity / volume gauges stacked vertically. */
47
+ gauges: MesoStatusGauge[];
48
+ /** Optional coaching recommendation box. */
49
+ coaching?: MesoStatusCoaching;
50
+ /** Optional next-session target box. */
51
+ nextTarget?: MesoStatusNextTarget;
52
+ className?: string;
53
+ }
54
+ /**
55
+ * Mesocycle context card for a specific exercise: prescription vs actual
56
+ * metrics, intensity/volume gauges, and coaching guidance. Composes the titan
57
+ * `Card` plus the Workout `StatusDot`, and renders the §25 gauge (8px track,
58
+ * 50% center line, 14px marker) inline since that visual differs from the
59
+ * IntensityBar/DeviationBar primitives.
60
+ *
61
+ * @example
62
+ * <MesoStatusCard
63
+ * mesoName="Hypertrophy Block"
64
+ * mesoSubtitle="Week 6 of 8 · Upper/Lower"
65
+ * statusBadge={{ label: 'On Track', variant: 'success' }}
66
+ * metrics={[
67
+ * { label: 'Prescribed', value: '3×8 @ RPE 8' },
68
+ * { label: 'Actual', value: '3×8 @ 185 lbs' },
69
+ * ]}
70
+ * gauges={[{ label: 'Intensity', level: 0.7, sublabel: 'Actual' }]}
71
+ * coaching={{ text: 'Add load next session.', highlights: ['Add load'] }}
72
+ * nextTarget={{ icon: '→', text: '190 lbs × 8' }}
73
+ * />
74
+ */
75
+ declare function MesoStatusCard({ mesoName, mesoSubtitle, statusBadge, metrics, gauges, coaching, nextTarget, className, ...props }: MesoStatusCardProps): react_jsx_runtime.JSX.Element;
76
+
77
+ export { type MesoStatusBadge as M, type MesoStatusBadgeVariant as a, MesoStatusCard as b, type MesoStatusCardProps as c, type MesoStatusCoaching as d, type MesoStatusGauge as e, type MesoStatusMetric as f, type MesoStatusNextTarget as g };
@@ -1,3 +1,246 @@
1
- export { n as BodyMap, B as BodyMapData, o as BodyMapDetailPanel, a as BodyMapDetailPanelProps, b as BodyMapProps, C as ContributingExercise, D as DEFAULT_VOLUME_LANDMARKS, p as DETAILED_TO_SIMPLE, q as MUSCLE_DISPLAY_NAMES, r as MUSCLE_TO_CATEGORY, s as MUSCLE_TO_SVG_SLUGS, j as MovementCategory, k as MuscleGroup, t as SIMPLE_DISPLAY_NAMES, u as SIMPLE_TO_DETAILED, S as SimpleMuscleGroup, T as TrainingStatusMuscle, v as TrainingStatusPage, l as TrainingStatusPageProps, m as TrainingStatusSummary, U as UpcomingExercise, w as VOLUME_STATUS_LABELS, V as VolumeLandmarks, x as deriveTrainingSummary, y as getHeatmapColor, z as toBodyMapData } from './bodymap-BhG55xHM.mjs';
2
- import 'react/jsx-runtime';
3
- import 'react-native';
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ViewProps } from 'react-native';
3
+ import { c as MesoStatusCardProps } from './MesoStatusCard-CQk71hSi.mjs';
4
+
5
+ /**
6
+ * Full muscle group taxonomy for volume tracking and exercise mapping.
7
+ * 15 groups — the primary unit for volume accounting.
8
+ */
9
+ declare enum MuscleGroup {
10
+ CHEST = "chest",
11
+ FRONT_DELTS = "front_delts",
12
+ SIDE_DELTS = "side_delts",
13
+ TRICEPS = "triceps",
14
+ LATS = "lats",
15
+ UPPER_BACK = "upper_back",
16
+ REAR_DELTS = "rear_delts",
17
+ BICEPS = "biceps",
18
+ FOREARMS = "forearms",
19
+ QUADS = "quads",
20
+ HAMSTRINGS = "hamstrings",
21
+ GLUTES = "glutes",
22
+ CALVES = "calves",
23
+ ABS = "abs",
24
+ OBLIQUES = "obliques"
25
+ }
26
+ /**
27
+ * Simplified muscle group view for beginners. Maps to one or more MuscleGroup.
28
+ */
29
+ declare enum SimpleMuscleGroup {
30
+ CHEST = "chest",
31
+ BACK = "back",
32
+ SHOULDERS = "shoulders",
33
+ BICEPS = "biceps",
34
+ TRICEPS = "triceps",
35
+ LEGS = "legs",
36
+ CORE = "core",
37
+ FOREARMS = "forearms"
38
+ }
39
+ /** Mapping from simplified groups to the full taxonomy. */
40
+ declare const SIMPLE_TO_DETAILED: Record<SimpleMuscleGroup, MuscleGroup[]>;
41
+ /** Reverse map: detailed MuscleGroup -> its SimpleMuscleGroup. */
42
+ declare const DETAILED_TO_SIMPLE: Record<MuscleGroup, SimpleMuscleGroup>;
43
+ /** Movement category for training split organization. */
44
+ type MovementCategory = 'push' | 'pull' | 'legs' | 'core';
45
+ declare const MUSCLE_TO_CATEGORY: Record<MuscleGroup, MovementCategory>;
46
+ /**
47
+ * react-native-body-highlighter slug(s) per muscle group. Phase 1 uses the
48
+ * closest available slug; deltoids share one path and lats/upper-back share
49
+ * `upper-back` (see doc Level 4 "Recommended approach").
50
+ */
51
+ declare const MUSCLE_TO_SVG_SLUGS: Record<MuscleGroup, string[]>;
52
+ /** Human-readable name per muscle group (used in a11y labels). */
53
+ declare const MUSCLE_DISPLAY_NAMES: Record<MuscleGroup, string>;
54
+ /** Human-readable name per simple group. */
55
+ declare const SIMPLE_DISPLAY_NAMES: Record<SimpleMuscleGroup, string>;
56
+ /** Volume landmarks per muscle group (weekly working sets). */
57
+ interface VolumeLandmarks {
58
+ mev: number;
59
+ mav: number;
60
+ mrv: number;
61
+ }
62
+ declare const DEFAULT_VOLUME_LANDMARKS: Record<MuscleGroup, VolumeLandmarks>;
63
+ /** Weekly-volume status relative to MEV/MAV/MRV landmarks. */
64
+ type VolumeStatus = 'under' | 'maintenance' | 'productive' | 'over';
65
+ /** Readable label per status for a11y descriptions. */
66
+ declare const VOLUME_STATUS_LABELS: Record<VolumeStatus, string>;
67
+ /**
68
+ * Maps a volume status (and intensity, 0-1) to a heatmap fill color. The
69
+ * `approaching` token is used when a productive muscle nears its MRV.
70
+ */
71
+ declare function getHeatmapColor(status: VolumeStatus | null | undefined, intensity?: number): string;
72
+
73
+ interface BodyMapData {
74
+ muscleGroup: MuscleGroup;
75
+ /** Intensity 0-1 for heatmap color. */
76
+ intensity: number;
77
+ /** Volume status for tooltip / heatmap token. */
78
+ volumeStatus: VolumeStatus;
79
+ /** Weekly effective sets. */
80
+ weeklySets: number;
81
+ }
82
+ interface BodyMapProps extends ViewProps {
83
+ /** Muscle group intensity data. */
84
+ data: BodyMapData[];
85
+ /** Which view to show. */
86
+ view: 'front' | 'back';
87
+ /** Toggle between front/back. */
88
+ onViewChange?: (view: 'front' | 'back') => void;
89
+ /** Called when a muscle group is tapped. */
90
+ onMusclePress?: (muscleGroup: MuscleGroup) => void;
91
+ /** Currently highlighted muscle (from external selection). */
92
+ highlightedMuscle?: MuscleGroup | null;
93
+ /** Show simplified (8 groups) or detailed (15 groups). */
94
+ mode?: 'simple' | 'detailed';
95
+ className?: string;
96
+ }
97
+ /**
98
+ * Interactive SVG body map with tappable muscle groups and a volume heatmap.
99
+ * Renders the front or back view (toggle via onViewChange), colors each muscle
100
+ * by its weekly-volume status, and exposes an accessible muscle legend wired to
101
+ * onMusclePress. Phase 1 uses react-native-body-highlighter's combined slugs
102
+ * (deltoids as one path, lats/upper-back shared); swipe between views and the
103
+ * delt/lat SVG split are follow-ups.
104
+ *
105
+ * @example
106
+ * <BodyMap
107
+ * data={[{ muscleGroup: MuscleGroup.CHEST, intensity: 0.7, volumeStatus: 'productive', weeklySets: 12 }]}
108
+ * view="front"
109
+ * onViewChange={setView}
110
+ * onMusclePress={setSelected}
111
+ * highlightedMuscle={selected}
112
+ * />
113
+ */
114
+ declare function BodyMap({ data, view, onViewChange, onMusclePress, highlightedMuscle, mode, className, ...props }: BodyMapProps): react_jsx_runtime.JSX.Element;
115
+
116
+ interface ContributingExercise {
117
+ /** Exercise name. */
118
+ name: string;
119
+ /** Working sets contributed this week. */
120
+ sets: number;
121
+ /** Effective-set multiplier toward this muscle (0-1). */
122
+ contributionWeight: number;
123
+ }
124
+ interface UpcomingExercise {
125
+ /** Exercise name. */
126
+ name: string;
127
+ /** Workout the exercise belongs to. */
128
+ workoutName: string;
129
+ /** Planned sets. */
130
+ sets: number;
131
+ }
132
+ interface BodyMapDetailPanelProps extends ViewProps {
133
+ /** Muscle group whose volume detail is shown. */
134
+ muscleGroup: MuscleGroup;
135
+ /** Human-readable muscle name for the title and a11y label. */
136
+ displayName: string;
137
+ /** Weekly effective sets logged for this muscle. */
138
+ weeklySets: number;
139
+ /** Volume landmarks (weekly working sets). */
140
+ landmarks: VolumeLandmarks;
141
+ /** Weekly-volume status relative to the landmarks. */
142
+ volumeStatus: VolumeStatus;
143
+ /** Last trained label, e.g. "2 days ago". */
144
+ lastTrained?: string;
145
+ /** Volume sparkline data (last 4-8 weeks). */
146
+ weeklyHistory?: number[];
147
+ /** Exercises contributing to this muscle's volume. */
148
+ contributingExercises?: ContributingExercise[];
149
+ /** Upcoming exercises targeting this muscle. */
150
+ upcomingExercises?: UpcomingExercise[];
151
+ /** Whether the bottom sheet is visible. */
152
+ isOpen?: boolean;
153
+ /** Alias for `isOpen` (spec wording: "isOpen/visible"). `isOpen` wins when both are set. */
154
+ visible?: boolean;
155
+ /** Dismiss the panel (backdrop, handle, or close button). */
156
+ onClose: () => void;
157
+ /** Navigate to a filtered exercise list. */
158
+ onViewExercises?: () => void;
159
+ }
160
+ /**
161
+ * Slide-up bottom-sheet panel with detailed weekly-volume info for a tapped
162
+ * muscle group: a MEV|current|MRV gradient progress bar, the big weekly set
163
+ * count against MRV, an optional volume sparkline, and the contributing /
164
+ * upcoming exercise lists. Composes the titan `Badge` and Workout `Sparkline`.
165
+ *
166
+ * Controlled via `isOpen` (or the `visible` alias); renders nothing when closed
167
+ * and animates in on open — sheet translateY 400->0 (400ms ease-out) and a
168
+ * backdrop fade 0->0.4 (RN Animated, useNativeDriver:false). Backdrop, handle,
169
+ * and the header close button all call `onClose`.
170
+ *
171
+ * @example
172
+ * <BodyMapDetailPanel
173
+ * muscleGroup={MuscleGroup.CHEST}
174
+ * displayName="Chest"
175
+ * weeklySets={14}
176
+ * landmarks={{ mev: 8, mav: 14, mrv: 20 }}
177
+ * volumeStatus="productive"
178
+ * lastTrained="2 days ago"
179
+ * weeklyHistory={[8, 10, 12, 14]}
180
+ * isOpen={open}
181
+ * onClose={() => setOpen(false)}
182
+ * />
183
+ */
184
+ declare function BodyMapDetailPanel({ muscleGroup, displayName, weeklySets, landmarks, volumeStatus, lastTrained, weeklyHistory, contributingExercises, upcomingExercises, isOpen, visible, onClose, onViewExercises, ...props }: BodyMapDetailPanelProps): react_jsx_runtime.JSX.Element | null;
185
+
186
+ /** One muscle's full volume picture — feeds the body maps and the detail panel. */
187
+ interface TrainingStatusMuscle {
188
+ /** Detailed muscle group (drives the SVG heatmap + panel identity). */
189
+ muscleGroup: MuscleGroup;
190
+ /** Human-readable name for the legend, summary, and panel title. */
191
+ displayName: string;
192
+ /** Which body-map view the muscle belongs to. */
193
+ side: 'front' | 'back';
194
+ /** Heatmap intensity 0-1. */
195
+ intensity: number;
196
+ /** Weekly-volume status relative to the landmarks. */
197
+ volumeStatus: VolumeStatus;
198
+ /** Weekly effective sets logged. */
199
+ weeklySets: number;
200
+ /** Volume landmarks (weekly working sets). */
201
+ landmarks: VolumeLandmarks;
202
+ /** Last trained label, e.g. "2 days ago". */
203
+ lastTrained?: string;
204
+ /** Weekly volume history for the panel sparkline. */
205
+ weeklyHistory?: number[];
206
+ /** Exercises contributing to this muscle's volume. */
207
+ contributingExercises?: ContributingExercise[];
208
+ /** Upcoming exercises targeting this muscle. */
209
+ upcomingExercises?: UpcomingExercise[];
210
+ }
211
+ /** Derived, page-level roll-up of the tracked muscles. */
212
+ interface TrainingStatusSummary {
213
+ /** Total weekly effective sets across all tracked muscles. */
214
+ totalWeeklySets: number;
215
+ /** Number of muscles being tracked. */
216
+ trackedMuscles: number;
217
+ /** Count of muscles per volume status. */
218
+ statusCounts: Record<VolumeStatus, number>;
219
+ }
220
+ interface TrainingStatusPageProps extends ViewProps {
221
+ /** Page heading. */
222
+ title?: string;
223
+ /** Mesocycle context banner shown at the top. */
224
+ meso: MesoStatusCardProps;
225
+ /** Muscles tracked this week. */
226
+ muscles: TrainingStatusMuscle[];
227
+ className?: string;
228
+ }
229
+ /** Roll up per-muscle rows into the page summary (pure, testable). */
230
+ declare function deriveTrainingSummary(muscles: TrainingStatusMuscle[]): TrainingStatusSummary;
231
+ /** Project the muscle rows for one side into `BodyMap` heatmap data. */
232
+ declare function toBodyMapData(muscles: TrainingStatusMuscle[], side: 'front' | 'back'): BodyMapData[];
233
+ /**
234
+ * TrainingStatusPage — a body-map training dashboard that composes the
235
+ * mesocycle context banner (`MesoStatusCard`), side-by-side front/back
236
+ * `BodyMap`s with a shared heatmap legend, per-status summary cards, and a
237
+ * tap-to-detail `BodyMapDetailPanel`. Tapping any muscle (SVG or legend chip)
238
+ * opens the slide-up panel for that group; the summary is derived from the
239
+ * supplied muscle rows.
240
+ *
241
+ * @example
242
+ * <TrainingStatusPage meso={meso} muscles={muscles} />
243
+ */
244
+ declare function TrainingStatusPage({ title, meso, muscles, className, ...props }: TrainingStatusPageProps): react_jsx_runtime.JSX.Element;
245
+
246
+ export { BodyMap, type BodyMapData, BodyMapDetailPanel, type BodyMapDetailPanelProps, type BodyMapProps, type ContributingExercise, DEFAULT_VOLUME_LANDMARKS, DETAILED_TO_SIMPLE, MUSCLE_DISPLAY_NAMES, MUSCLE_TO_CATEGORY, MUSCLE_TO_SVG_SLUGS, type MovementCategory, MuscleGroup, SIMPLE_DISPLAY_NAMES, SIMPLE_TO_DETAILED, SimpleMuscleGroup, type TrainingStatusMuscle, TrainingStatusPage, type TrainingStatusPageProps, type TrainingStatusSummary, type UpcomingExercise, VOLUME_STATUS_LABELS, type VolumeLandmarks, deriveTrainingSummary, getHeatmapColor, toBodyMapData };
package/dist/bodymap.d.ts CHANGED
@@ -1,3 +1,246 @@
1
- export { n as BodyMap, B as BodyMapData, o as BodyMapDetailPanel, a as BodyMapDetailPanelProps, b as BodyMapProps, C as ContributingExercise, D as DEFAULT_VOLUME_LANDMARKS, p as DETAILED_TO_SIMPLE, q as MUSCLE_DISPLAY_NAMES, r as MUSCLE_TO_CATEGORY, s as MUSCLE_TO_SVG_SLUGS, j as MovementCategory, k as MuscleGroup, t as SIMPLE_DISPLAY_NAMES, u as SIMPLE_TO_DETAILED, S as SimpleMuscleGroup, T as TrainingStatusMuscle, v as TrainingStatusPage, l as TrainingStatusPageProps, m as TrainingStatusSummary, U as UpcomingExercise, w as VOLUME_STATUS_LABELS, V as VolumeLandmarks, x as deriveTrainingSummary, y as getHeatmapColor, z as toBodyMapData } from './bodymap-BhG55xHM.js';
2
- import 'react/jsx-runtime';
3
- import 'react-native';
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ViewProps } from 'react-native';
3
+ import { c as MesoStatusCardProps } from './MesoStatusCard-CQk71hSi.js';
4
+
5
+ /**
6
+ * Full muscle group taxonomy for volume tracking and exercise mapping.
7
+ * 15 groups — the primary unit for volume accounting.
8
+ */
9
+ declare enum MuscleGroup {
10
+ CHEST = "chest",
11
+ FRONT_DELTS = "front_delts",
12
+ SIDE_DELTS = "side_delts",
13
+ TRICEPS = "triceps",
14
+ LATS = "lats",
15
+ UPPER_BACK = "upper_back",
16
+ REAR_DELTS = "rear_delts",
17
+ BICEPS = "biceps",
18
+ FOREARMS = "forearms",
19
+ QUADS = "quads",
20
+ HAMSTRINGS = "hamstrings",
21
+ GLUTES = "glutes",
22
+ CALVES = "calves",
23
+ ABS = "abs",
24
+ OBLIQUES = "obliques"
25
+ }
26
+ /**
27
+ * Simplified muscle group view for beginners. Maps to one or more MuscleGroup.
28
+ */
29
+ declare enum SimpleMuscleGroup {
30
+ CHEST = "chest",
31
+ BACK = "back",
32
+ SHOULDERS = "shoulders",
33
+ BICEPS = "biceps",
34
+ TRICEPS = "triceps",
35
+ LEGS = "legs",
36
+ CORE = "core",
37
+ FOREARMS = "forearms"
38
+ }
39
+ /** Mapping from simplified groups to the full taxonomy. */
40
+ declare const SIMPLE_TO_DETAILED: Record<SimpleMuscleGroup, MuscleGroup[]>;
41
+ /** Reverse map: detailed MuscleGroup -> its SimpleMuscleGroup. */
42
+ declare const DETAILED_TO_SIMPLE: Record<MuscleGroup, SimpleMuscleGroup>;
43
+ /** Movement category for training split organization. */
44
+ type MovementCategory = 'push' | 'pull' | 'legs' | 'core';
45
+ declare const MUSCLE_TO_CATEGORY: Record<MuscleGroup, MovementCategory>;
46
+ /**
47
+ * react-native-body-highlighter slug(s) per muscle group. Phase 1 uses the
48
+ * closest available slug; deltoids share one path and lats/upper-back share
49
+ * `upper-back` (see doc Level 4 "Recommended approach").
50
+ */
51
+ declare const MUSCLE_TO_SVG_SLUGS: Record<MuscleGroup, string[]>;
52
+ /** Human-readable name per muscle group (used in a11y labels). */
53
+ declare const MUSCLE_DISPLAY_NAMES: Record<MuscleGroup, string>;
54
+ /** Human-readable name per simple group. */
55
+ declare const SIMPLE_DISPLAY_NAMES: Record<SimpleMuscleGroup, string>;
56
+ /** Volume landmarks per muscle group (weekly working sets). */
57
+ interface VolumeLandmarks {
58
+ mev: number;
59
+ mav: number;
60
+ mrv: number;
61
+ }
62
+ declare const DEFAULT_VOLUME_LANDMARKS: Record<MuscleGroup, VolumeLandmarks>;
63
+ /** Weekly-volume status relative to MEV/MAV/MRV landmarks. */
64
+ type VolumeStatus = 'under' | 'maintenance' | 'productive' | 'over';
65
+ /** Readable label per status for a11y descriptions. */
66
+ declare const VOLUME_STATUS_LABELS: Record<VolumeStatus, string>;
67
+ /**
68
+ * Maps a volume status (and intensity, 0-1) to a heatmap fill color. The
69
+ * `approaching` token is used when a productive muscle nears its MRV.
70
+ */
71
+ declare function getHeatmapColor(status: VolumeStatus | null | undefined, intensity?: number): string;
72
+
73
+ interface BodyMapData {
74
+ muscleGroup: MuscleGroup;
75
+ /** Intensity 0-1 for heatmap color. */
76
+ intensity: number;
77
+ /** Volume status for tooltip / heatmap token. */
78
+ volumeStatus: VolumeStatus;
79
+ /** Weekly effective sets. */
80
+ weeklySets: number;
81
+ }
82
+ interface BodyMapProps extends ViewProps {
83
+ /** Muscle group intensity data. */
84
+ data: BodyMapData[];
85
+ /** Which view to show. */
86
+ view: 'front' | 'back';
87
+ /** Toggle between front/back. */
88
+ onViewChange?: (view: 'front' | 'back') => void;
89
+ /** Called when a muscle group is tapped. */
90
+ onMusclePress?: (muscleGroup: MuscleGroup) => void;
91
+ /** Currently highlighted muscle (from external selection). */
92
+ highlightedMuscle?: MuscleGroup | null;
93
+ /** Show simplified (8 groups) or detailed (15 groups). */
94
+ mode?: 'simple' | 'detailed';
95
+ className?: string;
96
+ }
97
+ /**
98
+ * Interactive SVG body map with tappable muscle groups and a volume heatmap.
99
+ * Renders the front or back view (toggle via onViewChange), colors each muscle
100
+ * by its weekly-volume status, and exposes an accessible muscle legend wired to
101
+ * onMusclePress. Phase 1 uses react-native-body-highlighter's combined slugs
102
+ * (deltoids as one path, lats/upper-back shared); swipe between views and the
103
+ * delt/lat SVG split are follow-ups.
104
+ *
105
+ * @example
106
+ * <BodyMap
107
+ * data={[{ muscleGroup: MuscleGroup.CHEST, intensity: 0.7, volumeStatus: 'productive', weeklySets: 12 }]}
108
+ * view="front"
109
+ * onViewChange={setView}
110
+ * onMusclePress={setSelected}
111
+ * highlightedMuscle={selected}
112
+ * />
113
+ */
114
+ declare function BodyMap({ data, view, onViewChange, onMusclePress, highlightedMuscle, mode, className, ...props }: BodyMapProps): react_jsx_runtime.JSX.Element;
115
+
116
+ interface ContributingExercise {
117
+ /** Exercise name. */
118
+ name: string;
119
+ /** Working sets contributed this week. */
120
+ sets: number;
121
+ /** Effective-set multiplier toward this muscle (0-1). */
122
+ contributionWeight: number;
123
+ }
124
+ interface UpcomingExercise {
125
+ /** Exercise name. */
126
+ name: string;
127
+ /** Workout the exercise belongs to. */
128
+ workoutName: string;
129
+ /** Planned sets. */
130
+ sets: number;
131
+ }
132
+ interface BodyMapDetailPanelProps extends ViewProps {
133
+ /** Muscle group whose volume detail is shown. */
134
+ muscleGroup: MuscleGroup;
135
+ /** Human-readable muscle name for the title and a11y label. */
136
+ displayName: string;
137
+ /** Weekly effective sets logged for this muscle. */
138
+ weeklySets: number;
139
+ /** Volume landmarks (weekly working sets). */
140
+ landmarks: VolumeLandmarks;
141
+ /** Weekly-volume status relative to the landmarks. */
142
+ volumeStatus: VolumeStatus;
143
+ /** Last trained label, e.g. "2 days ago". */
144
+ lastTrained?: string;
145
+ /** Volume sparkline data (last 4-8 weeks). */
146
+ weeklyHistory?: number[];
147
+ /** Exercises contributing to this muscle's volume. */
148
+ contributingExercises?: ContributingExercise[];
149
+ /** Upcoming exercises targeting this muscle. */
150
+ upcomingExercises?: UpcomingExercise[];
151
+ /** Whether the bottom sheet is visible. */
152
+ isOpen?: boolean;
153
+ /** Alias for `isOpen` (spec wording: "isOpen/visible"). `isOpen` wins when both are set. */
154
+ visible?: boolean;
155
+ /** Dismiss the panel (backdrop, handle, or close button). */
156
+ onClose: () => void;
157
+ /** Navigate to a filtered exercise list. */
158
+ onViewExercises?: () => void;
159
+ }
160
+ /**
161
+ * Slide-up bottom-sheet panel with detailed weekly-volume info for a tapped
162
+ * muscle group: a MEV|current|MRV gradient progress bar, the big weekly set
163
+ * count against MRV, an optional volume sparkline, and the contributing /
164
+ * upcoming exercise lists. Composes the titan `Badge` and Workout `Sparkline`.
165
+ *
166
+ * Controlled via `isOpen` (or the `visible` alias); renders nothing when closed
167
+ * and animates in on open — sheet translateY 400->0 (400ms ease-out) and a
168
+ * backdrop fade 0->0.4 (RN Animated, useNativeDriver:false). Backdrop, handle,
169
+ * and the header close button all call `onClose`.
170
+ *
171
+ * @example
172
+ * <BodyMapDetailPanel
173
+ * muscleGroup={MuscleGroup.CHEST}
174
+ * displayName="Chest"
175
+ * weeklySets={14}
176
+ * landmarks={{ mev: 8, mav: 14, mrv: 20 }}
177
+ * volumeStatus="productive"
178
+ * lastTrained="2 days ago"
179
+ * weeklyHistory={[8, 10, 12, 14]}
180
+ * isOpen={open}
181
+ * onClose={() => setOpen(false)}
182
+ * />
183
+ */
184
+ declare function BodyMapDetailPanel({ muscleGroup, displayName, weeklySets, landmarks, volumeStatus, lastTrained, weeklyHistory, contributingExercises, upcomingExercises, isOpen, visible, onClose, onViewExercises, ...props }: BodyMapDetailPanelProps): react_jsx_runtime.JSX.Element | null;
185
+
186
+ /** One muscle's full volume picture — feeds the body maps and the detail panel. */
187
+ interface TrainingStatusMuscle {
188
+ /** Detailed muscle group (drives the SVG heatmap + panel identity). */
189
+ muscleGroup: MuscleGroup;
190
+ /** Human-readable name for the legend, summary, and panel title. */
191
+ displayName: string;
192
+ /** Which body-map view the muscle belongs to. */
193
+ side: 'front' | 'back';
194
+ /** Heatmap intensity 0-1. */
195
+ intensity: number;
196
+ /** Weekly-volume status relative to the landmarks. */
197
+ volumeStatus: VolumeStatus;
198
+ /** Weekly effective sets logged. */
199
+ weeklySets: number;
200
+ /** Volume landmarks (weekly working sets). */
201
+ landmarks: VolumeLandmarks;
202
+ /** Last trained label, e.g. "2 days ago". */
203
+ lastTrained?: string;
204
+ /** Weekly volume history for the panel sparkline. */
205
+ weeklyHistory?: number[];
206
+ /** Exercises contributing to this muscle's volume. */
207
+ contributingExercises?: ContributingExercise[];
208
+ /** Upcoming exercises targeting this muscle. */
209
+ upcomingExercises?: UpcomingExercise[];
210
+ }
211
+ /** Derived, page-level roll-up of the tracked muscles. */
212
+ interface TrainingStatusSummary {
213
+ /** Total weekly effective sets across all tracked muscles. */
214
+ totalWeeklySets: number;
215
+ /** Number of muscles being tracked. */
216
+ trackedMuscles: number;
217
+ /** Count of muscles per volume status. */
218
+ statusCounts: Record<VolumeStatus, number>;
219
+ }
220
+ interface TrainingStatusPageProps extends ViewProps {
221
+ /** Page heading. */
222
+ title?: string;
223
+ /** Mesocycle context banner shown at the top. */
224
+ meso: MesoStatusCardProps;
225
+ /** Muscles tracked this week. */
226
+ muscles: TrainingStatusMuscle[];
227
+ className?: string;
228
+ }
229
+ /** Roll up per-muscle rows into the page summary (pure, testable). */
230
+ declare function deriveTrainingSummary(muscles: TrainingStatusMuscle[]): TrainingStatusSummary;
231
+ /** Project the muscle rows for one side into `BodyMap` heatmap data. */
232
+ declare function toBodyMapData(muscles: TrainingStatusMuscle[], side: 'front' | 'back'): BodyMapData[];
233
+ /**
234
+ * TrainingStatusPage — a body-map training dashboard that composes the
235
+ * mesocycle context banner (`MesoStatusCard`), side-by-side front/back
236
+ * `BodyMap`s with a shared heatmap legend, per-status summary cards, and a
237
+ * tap-to-detail `BodyMapDetailPanel`. Tapping any muscle (SVG or legend chip)
238
+ * opens the slide-up panel for that group; the summary is derived from the
239
+ * supplied muscle rows.
240
+ *
241
+ * @example
242
+ * <TrainingStatusPage meso={meso} muscles={muscles} />
243
+ */
244
+ declare function TrainingStatusPage({ title, meso, muscles, className, ...props }: TrainingStatusPageProps): react_jsx_runtime.JSX.Element;
245
+
246
+ export { BodyMap, type BodyMapData, BodyMapDetailPanel, type BodyMapDetailPanelProps, type BodyMapProps, type ContributingExercise, DEFAULT_VOLUME_LANDMARKS, DETAILED_TO_SIMPLE, MUSCLE_DISPLAY_NAMES, MUSCLE_TO_CATEGORY, MUSCLE_TO_SVG_SLUGS, type MovementCategory, MuscleGroup, SIMPLE_DISPLAY_NAMES, SIMPLE_TO_DETAILED, SimpleMuscleGroup, type TrainingStatusMuscle, TrainingStatusPage, type TrainingStatusPageProps, type TrainingStatusSummary, type UpcomingExercise, VOLUME_STATUS_LABELS, type VolumeLandmarks, deriveTrainingSummary, getHeatmapColor, toBodyMapData };