@titan-design/react-ui 0.3.0 → 0.4.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.
- package/dist/bodymap.js +441 -97
- package/dist/bodymap.js.map +1 -1
- package/dist/bodymap.mjs +49 -62
- package/dist/bodymap.mjs.map +1 -1
- package/dist/{chunk-TOD2WQBG.mjs → chunk-2SISKTWM.mjs} +22 -43
- package/dist/chunk-2SISKTWM.mjs.map +1 -0
- package/dist/{chunk-P7TSQUN6.mjs → chunk-SNVKL5WZ.mjs} +42 -5
- package/dist/chunk-SNVKL5WZ.mjs.map +1 -0
- package/dist/index.d.mts +42 -2
- package/dist/index.d.ts +42 -2
- package/dist/index.js +431 -328
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +397 -314
- package/dist/index.mjs.map +1 -1
- package/dist/theme/index.d.mts +28 -2
- package/dist/theme/index.d.ts +28 -2
- package/dist/theme/index.js +37 -0
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/index.mjs +1 -1
- package/package.json +1 -1
- package/src/components/custom/Workout/ActiveWorkoutPage.tsx +10 -15
- package/src/components/custom/Workout/BodyMap.tsx +7 -8
- package/src/components/custom/Workout/BodyMapDetailPanel.tsx +25 -28
- package/src/components/custom/Workout/CapacityBandChart.tsx +2 -3
- package/src/components/custom/Workout/ExerciseCard.tsx +12 -27
- package/src/components/custom/Workout/ExerciseDetailPage.tsx +21 -27
- package/src/components/custom/Workout/InputBar.tsx +10 -11
- package/src/components/custom/Workout/MesoCard.tsx +2 -6
- package/src/components/custom/Workout/MesoStatusCard.tsx +17 -15
- package/src/components/custom/Workout/MuscleGroupChip.tsx +2 -4
- package/src/components/custom/Workout/PlaceholderStrip.tsx +2 -3
- package/src/components/custom/Workout/PrHistoryModal.tsx +12 -14
- package/src/components/custom/Workout/ProgramPlanningPage.tsx +8 -12
- package/src/components/custom/Workout/ReadinessCheck.tsx +13 -11
- package/src/components/custom/Workout/RestTimer.tsx +8 -7
- package/src/components/custom/Workout/SetRow.tsx +10 -7
- package/src/components/custom/Workout/StrengthTrendChart.tsx +15 -17
- package/src/components/custom/Workout/TempoBar.stories.tsx +95 -0
- package/src/components/custom/Workout/TempoBar.test.tsx +103 -0
- package/src/components/custom/Workout/TempoBar.tsx +215 -0
- package/src/components/custom/Workout/TrainingStatusPage.tsx +8 -17
- package/src/components/custom/Workout/VelocityStrip.tsx +7 -5
- package/src/components/custom/Workout/WeekRow.tsx +2 -1
- package/src/components/custom/Workout/WorkoutCard.tsx +3 -8
- package/src/components/custom/Workout/index.ts +9 -0
- package/src/test/nativewind-stub.ts +13 -0
- package/src/theme/ThemeProvider.test.tsx +24 -0
- package/src/theme/ThemeProvider.tsx +50 -0
- package/src/theme/index.ts +2 -0
- package/src/theme/resolve-color.ts +19 -0
- package/dist/chunk-P7TSQUN6.mjs.map +0 -1
- package/dist/chunk-TOD2WQBG.mjs.map +0 -1
package/dist/bodymap.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/custom/Workout/muscleTaxonomy.ts","../src/components/custom/Workout/BodyMap.tsx","../src/components/custom/Workout/BodyMapDetailPanel.tsx","../src/components/custom/Workout/TrainingStatusPage.tsx"],"names":["MuscleGroup","SimpleMuscleGroup","TEXT_PRIMARY","TEXT_SECONDARY","useState","Animated","useEffect","Easing","View","Pressable","Text","SURFACE_ELEVATED","BORDER_DEFAULT","TEXT_TERTIARY","useMemo"],"mappings":"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","file":"bodymap.mjs","sourcesContent":["/**\n * Muscle grouping taxonomy for volume tracking, exercise mapping, and the\n * BodyMap visualization. Ported from the Voltras muscle-taxonomy design doc.\n *\n * Level 2 (15 groups) is the primary volume-tracking unit; SimpleMuscleGroup\n * (8 groups) is the beginner-facing aggregation. MUSCLE_TO_SVG_SLUGS maps each\n * group to react-native-body-highlighter slugs using the closest-slug approach\n * (Phase 1: combined colors, no sub-region splitting — deltoids is a single\n * slug, lats and upper back share `upper-back`).\n */\nimport { WORKOUT_TOKENS } from '../../../theme/workout-tokens'\n\n/**\n * Full muscle group taxonomy for volume tracking and exercise mapping.\n * 15 groups — the primary unit for volume accounting.\n */\nexport enum MuscleGroup {\n // Push\n CHEST = 'chest',\n FRONT_DELTS = 'front_delts',\n SIDE_DELTS = 'side_delts',\n TRICEPS = 'triceps',\n\n // Pull\n LATS = 'lats',\n UPPER_BACK = 'upper_back',\n REAR_DELTS = 'rear_delts',\n BICEPS = 'biceps',\n FOREARMS = 'forearms',\n\n // Legs\n QUADS = 'quads',\n HAMSTRINGS = 'hamstrings',\n GLUTES = 'glutes',\n CALVES = 'calves',\n\n // Core\n ABS = 'abs',\n OBLIQUES = 'obliques',\n}\n\n/**\n * Simplified muscle group view for beginners. Maps to one or more MuscleGroup.\n */\nexport enum SimpleMuscleGroup {\n CHEST = 'chest',\n BACK = 'back',\n SHOULDERS = 'shoulders',\n BICEPS = 'biceps',\n TRICEPS = 'triceps',\n LEGS = 'legs',\n CORE = 'core',\n FOREARMS = 'forearms',\n}\n\n/** Mapping from simplified groups to the full taxonomy. */\nexport const SIMPLE_TO_DETAILED: Record<SimpleMuscleGroup, MuscleGroup[]> = {\n [SimpleMuscleGroup.CHEST]: [MuscleGroup.CHEST],\n [SimpleMuscleGroup.BACK]: [MuscleGroup.LATS, MuscleGroup.UPPER_BACK],\n [SimpleMuscleGroup.SHOULDERS]: [\n MuscleGroup.FRONT_DELTS,\n MuscleGroup.SIDE_DELTS,\n MuscleGroup.REAR_DELTS,\n ],\n [SimpleMuscleGroup.BICEPS]: [MuscleGroup.BICEPS],\n [SimpleMuscleGroup.TRICEPS]: [MuscleGroup.TRICEPS],\n [SimpleMuscleGroup.LEGS]: [\n MuscleGroup.QUADS,\n MuscleGroup.HAMSTRINGS,\n MuscleGroup.GLUTES,\n MuscleGroup.CALVES,\n ],\n [SimpleMuscleGroup.CORE]: [MuscleGroup.ABS, MuscleGroup.OBLIQUES],\n [SimpleMuscleGroup.FOREARMS]: [MuscleGroup.FOREARMS],\n}\n\n/** Reverse map: detailed MuscleGroup -> its SimpleMuscleGroup. */\nexport const DETAILED_TO_SIMPLE: Record<MuscleGroup, SimpleMuscleGroup> = Object.entries(\n SIMPLE_TO_DETAILED\n).reduce(\n (acc, [simple, groups]) => {\n for (const group of groups) {\n acc[group] = simple as SimpleMuscleGroup\n }\n return acc\n },\n {} as Record<MuscleGroup, SimpleMuscleGroup>\n)\n\n/** Movement category for training split organization. */\nexport type MovementCategory = 'push' | 'pull' | 'legs' | 'core'\n\nexport const MUSCLE_TO_CATEGORY: Record<MuscleGroup, MovementCategory> = {\n [MuscleGroup.CHEST]: 'push',\n [MuscleGroup.FRONT_DELTS]: 'push',\n [MuscleGroup.SIDE_DELTS]: 'push',\n [MuscleGroup.TRICEPS]: 'push',\n [MuscleGroup.LATS]: 'pull',\n [MuscleGroup.UPPER_BACK]: 'pull',\n [MuscleGroup.REAR_DELTS]: 'pull',\n [MuscleGroup.BICEPS]: 'pull',\n [MuscleGroup.FOREARMS]: 'pull',\n [MuscleGroup.QUADS]: 'legs',\n [MuscleGroup.HAMSTRINGS]: 'legs',\n [MuscleGroup.GLUTES]: 'legs',\n [MuscleGroup.CALVES]: 'legs',\n [MuscleGroup.ABS]: 'core',\n [MuscleGroup.OBLIQUES]: 'core',\n}\n\n/**\n * react-native-body-highlighter slug(s) per muscle group. Phase 1 uses the\n * closest available slug; deltoids share one path and lats/upper-back share\n * `upper-back` (see doc Level 4 \"Recommended approach\").\n */\nexport const MUSCLE_TO_SVG_SLUGS: Record<MuscleGroup, string[]> = {\n [MuscleGroup.CHEST]: ['chest'],\n [MuscleGroup.FRONT_DELTS]: ['deltoids'],\n [MuscleGroup.SIDE_DELTS]: ['deltoids'],\n [MuscleGroup.REAR_DELTS]: ['deltoids'],\n [MuscleGroup.TRICEPS]: ['triceps'],\n [MuscleGroup.LATS]: ['upper-back'],\n [MuscleGroup.UPPER_BACK]: ['upper-back', 'trapezius'],\n [MuscleGroup.BICEPS]: ['biceps'],\n [MuscleGroup.FOREARMS]: ['forearm'],\n [MuscleGroup.QUADS]: ['quadriceps'],\n [MuscleGroup.HAMSTRINGS]: ['hamstring'],\n [MuscleGroup.GLUTES]: ['gluteal'],\n [MuscleGroup.CALVES]: ['calves'],\n [MuscleGroup.ABS]: ['abs'],\n [MuscleGroup.OBLIQUES]: ['obliques'],\n}\n\n/** Human-readable name per muscle group (used in a11y labels). */\nexport const MUSCLE_DISPLAY_NAMES: Record<MuscleGroup, string> = {\n [MuscleGroup.CHEST]: 'Chest',\n [MuscleGroup.FRONT_DELTS]: 'Front Delts',\n [MuscleGroup.SIDE_DELTS]: 'Side Delts',\n [MuscleGroup.REAR_DELTS]: 'Rear Delts',\n [MuscleGroup.TRICEPS]: 'Triceps',\n [MuscleGroup.LATS]: 'Lats',\n [MuscleGroup.UPPER_BACK]: 'Upper Back',\n [MuscleGroup.BICEPS]: 'Biceps',\n [MuscleGroup.FOREARMS]: 'Forearms',\n [MuscleGroup.QUADS]: 'Quads',\n [MuscleGroup.HAMSTRINGS]: 'Hamstrings',\n [MuscleGroup.GLUTES]: 'Glutes',\n [MuscleGroup.CALVES]: 'Calves',\n [MuscleGroup.ABS]: 'Abs',\n [MuscleGroup.OBLIQUES]: 'Obliques',\n}\n\n/** Human-readable name per simple group. */\nexport const SIMPLE_DISPLAY_NAMES: Record<SimpleMuscleGroup, string> = {\n [SimpleMuscleGroup.CHEST]: 'Chest',\n [SimpleMuscleGroup.BACK]: 'Back',\n [SimpleMuscleGroup.SHOULDERS]: 'Shoulders',\n [SimpleMuscleGroup.BICEPS]: 'Biceps',\n [SimpleMuscleGroup.TRICEPS]: 'Triceps',\n [SimpleMuscleGroup.LEGS]: 'Legs',\n [SimpleMuscleGroup.CORE]: 'Core',\n [SimpleMuscleGroup.FOREARMS]: 'Forearms',\n}\n\n/** Volume landmarks per muscle group (weekly working sets). */\nexport interface VolumeLandmarks {\n mev: number // Minimum Effective Volume\n mav: number // Maximum Adaptive Volume\n mrv: number // Maximum Recoverable Volume\n}\n\nexport const DEFAULT_VOLUME_LANDMARKS: Record<MuscleGroup, VolumeLandmarks> = {\n [MuscleGroup.CHEST]: { mev: 8, mav: 14, mrv: 20 },\n [MuscleGroup.LATS]: { mev: 8, mav: 14, mrv: 20 },\n [MuscleGroup.UPPER_BACK]: { mev: 6, mav: 12, mrv: 18 },\n [MuscleGroup.FRONT_DELTS]: { mev: 2, mav: 6, mrv: 10 },\n [MuscleGroup.SIDE_DELTS]: { mev: 6, mav: 14, mrv: 22 },\n [MuscleGroup.REAR_DELTS]: { mev: 6, mav: 12, mrv: 18 },\n [MuscleGroup.BICEPS]: { mev: 4, mav: 10, mrv: 18 },\n [MuscleGroup.TRICEPS]: { mev: 4, mav: 8, mrv: 14 },\n [MuscleGroup.FOREARMS]: { mev: 2, mav: 6, mrv: 12 },\n [MuscleGroup.QUADS]: { mev: 6, mav: 12, mrv: 18 },\n [MuscleGroup.HAMSTRINGS]: { mev: 4, mav: 10, mrv: 16 },\n [MuscleGroup.GLUTES]: { mev: 4, mav: 10, mrv: 16 },\n [MuscleGroup.CALVES]: { mev: 6, mav: 10, mrv: 16 },\n [MuscleGroup.ABS]: { mev: 0, mav: 8, mrv: 16 },\n [MuscleGroup.OBLIQUES]: { mev: 0, mav: 6, mrv: 12 },\n}\n\n/** Weekly-volume status relative to MEV/MAV/MRV landmarks. */\nexport type VolumeStatus = 'under' | 'maintenance' | 'productive' | 'over'\n\n/** Readable label per status for a11y descriptions. */\nexport const VOLUME_STATUS_LABELS: Record<VolumeStatus, string> = {\n under: 'under-trained',\n maintenance: 'maintenance',\n productive: 'productive',\n over: 'over-reaching',\n}\n\n/** Severity ranking — higher wins when several groups share an SVG slug. */\nconst STATUS_SEVERITY: Record<VolumeStatus, number> = {\n under: 1,\n maintenance: 2,\n productive: 3,\n over: 4,\n}\n\n/**\n * Maps a volume status (and intensity, 0-1) to a heatmap fill color. The\n * `approaching` token is used when a productive muscle nears its MRV.\n */\nexport function getHeatmapColor(status: VolumeStatus | null | undefined, intensity = 0): string {\n const heatmap = WORKOUT_TOKENS.heatmap\n switch (status) {\n case 'under':\n return heatmap.under\n case 'maintenance':\n return heatmap.maintenance\n case 'productive':\n return intensity >= 0.85 ? heatmap.approaching : heatmap.productive\n case 'over':\n return heatmap.over\n default:\n return heatmap.none\n }\n}\n\n/** True when one status is at least as severe as another. */\nexport function isMoreSevere(a: VolumeStatus, b: VolumeStatus): boolean {\n return STATUS_SEVERITY[a] >= STATUS_SEVERITY[b]\n}\n\n/**\n * Representative MuscleGroup for each SVG slug, used to resolve taps on shared\n * paths (e.g. `deltoids`, `upper-back`) back to a single group.\n */\nexport const SLUG_TO_PRIMARY_MUSCLE: Record<string, MuscleGroup> = {\n chest: MuscleGroup.CHEST,\n deltoids: MuscleGroup.SIDE_DELTS,\n triceps: MuscleGroup.TRICEPS,\n 'upper-back': MuscleGroup.LATS,\n trapezius: MuscleGroup.UPPER_BACK,\n biceps: MuscleGroup.BICEPS,\n forearm: MuscleGroup.FOREARMS,\n quadriceps: MuscleGroup.QUADS,\n hamstring: MuscleGroup.HAMSTRINGS,\n gluteal: MuscleGroup.GLUTES,\n calves: MuscleGroup.CALVES,\n abs: MuscleGroup.ABS,\n obliques: MuscleGroup.OBLIQUES,\n}\n","// Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)\nimport { useEffect, useMemo, useState } from 'react'\nimport { View, Text, Pressable, Animated, Easing, type ViewProps } from 'react-native'\nimport BodyHighlighter, { type ExtendedBodyPart, type Slug } from 'react-native-body-highlighter'\nimport { cn } from '../../../utils/cn'\nimport {\n MuscleGroup,\n SimpleMuscleGroup,\n MUSCLE_TO_SVG_SLUGS,\n MUSCLE_DISPLAY_NAMES,\n SIMPLE_DISPLAY_NAMES,\n DETAILED_TO_SIMPLE,\n SLUG_TO_PRIMARY_MUSCLE,\n VOLUME_STATUS_LABELS,\n getHeatmapColor,\n isMoreSevere,\n type VolumeStatus,\n} from './muscleTaxonomy'\n\n/**\n * react-native-body-highlighter is published as a CommonJS default export; the\n * interop keeps it working whether the bundler unwraps the default or not.\n */\nconst Body = ((BodyHighlighter as unknown as { default?: typeof BodyHighlighter }).default ??\n BodyHighlighter) as typeof BodyHighlighter\n\nconst OUTLINE_FILL = 'rgba(255,255,255,0.08)'\nconst OUTLINE_BORDER = 'rgba(255,255,255,0.12)'\nconst BODY_SCALE = 0.8 // 200x400 intrinsic -> ~160x320 px\nconst TEXT_PRIMARY = 'var(--color-text-primary)'\nconst TEXT_SECONDARY = 'var(--color-text-secondary)'\n\nexport interface BodyMapData {\n muscleGroup: MuscleGroup\n /** Intensity 0-1 for heatmap color. */\n intensity: number\n /** Volume status for tooltip / heatmap token. */\n volumeStatus: VolumeStatus\n /** Weekly effective sets. */\n weeklySets: number\n}\n\nexport interface BodyMapProps extends ViewProps {\n /** Muscle group intensity data. */\n data: BodyMapData[]\n /** Which view to show. */\n view: 'front' | 'back'\n /** Toggle between front/back. */\n onViewChange?: (view: 'front' | 'back') => void\n /** Called when a muscle group is tapped. */\n onMusclePress?: (muscleGroup: MuscleGroup) => void\n /** Currently highlighted muscle (from external selection). */\n highlightedMuscle?: MuscleGroup | null\n /** Show simplified (8 groups) or detailed (15 groups). */\n mode?: 'simple' | 'detailed'\n className?: string\n}\n\ninterface LegendEntry {\n key: string\n name: string\n status: VolumeStatus\n intensity: number\n sets: number\n /** Detailed group reported to onMusclePress. */\n muscle: MuscleGroup\n}\n\n/** Build the per-slug heatmap fill list, combining groups that share a slug. */\nfunction buildSlugParts(data: BodyMapData[]): ExtendedBodyPart[] {\n const bySlug = new Map<string, { status: VolumeStatus; intensity: number }>()\n for (const d of data) {\n for (const slug of MUSCLE_TO_SVG_SLUGS[d.muscleGroup] ?? []) {\n const existing = bySlug.get(slug)\n if (!existing || isMoreSevere(d.volumeStatus, existing.status)) {\n bySlug.set(slug, { status: d.volumeStatus, intensity: d.intensity })\n }\n }\n }\n return Array.from(bySlug.entries()).map(([slug, v]) => ({\n slug: slug as Slug,\n color: getHeatmapColor(v.status, v.intensity),\n }))\n}\n\n/** Collapse data into per-simple-group legend entries (summed sets). */\nfunction buildSimpleLegend(data: BodyMapData[]): LegendEntry[] {\n const bySimple = new Map<SimpleMuscleGroup, LegendEntry>()\n for (const d of data) {\n const simple = DETAILED_TO_SIMPLE[d.muscleGroup]\n const existing = bySimple.get(simple)\n if (!existing) {\n bySimple.set(simple, {\n key: simple,\n name: SIMPLE_DISPLAY_NAMES[simple],\n status: d.volumeStatus,\n intensity: d.intensity,\n sets: d.weeklySets,\n muscle: d.muscleGroup,\n })\n continue\n }\n existing.sets += d.weeklySets\n existing.intensity = Math.max(existing.intensity, d.intensity)\n if (isMoreSevere(d.volumeStatus, existing.status)) {\n existing.status = d.volumeStatus\n existing.muscle = d.muscleGroup\n }\n }\n return Array.from(bySimple.values())\n}\n\n/** One legend entry per data row, named by detailed group. */\nfunction buildDetailedLegend(data: BodyMapData[]): LegendEntry[] {\n return data.map((d) => ({\n key: d.muscleGroup,\n name: MUSCLE_DISPLAY_NAMES[d.muscleGroup],\n status: d.volumeStatus,\n intensity: d.intensity,\n sets: d.weeklySets,\n muscle: d.muscleGroup,\n }))\n}\n\n/**\n * Interactive SVG body map with tappable muscle groups and a volume heatmap.\n * Renders the front or back view (toggle via onViewChange), colors each muscle\n * by its weekly-volume status, and exposes an accessible muscle legend wired to\n * onMusclePress. Phase 1 uses react-native-body-highlighter's combined slugs\n * (deltoids as one path, lats/upper-back shared); swipe between views and the\n * delt/lat SVG split are follow-ups.\n *\n * @example\n * <BodyMap\n * data={[{ muscleGroup: MuscleGroup.CHEST, intensity: 0.7, volumeStatus: 'productive', weeklySets: 12 }]}\n * view=\"front\"\n * onViewChange={setView}\n * onMusclePress={setSelected}\n * highlightedMuscle={selected}\n * />\n */\nexport function BodyMap({\n data,\n view,\n onViewChange,\n onMusclePress,\n highlightedMuscle,\n mode = 'detailed',\n className,\n ...props\n}: BodyMapProps) {\n const slugParts = useMemo(() => buildSlugParts(data), [data])\n const legend = useMemo(\n () => (mode === 'simple' ? buildSimpleLegend(data) : buildDetailedLegend(data)),\n [data, mode]\n )\n\n const [highlight] = useState(() => new Animated.Value(highlightedMuscle ? 1 : 0))\n useEffect(() => {\n const animation = Animated.timing(highlight, {\n toValue: highlightedMuscle ? 1 : 0,\n duration: 250,\n easing: Easing.out(Easing.ease),\n useNativeDriver: false,\n })\n animation.start()\n return () => animation.stop()\n }, [highlightedMuscle, highlight])\n\n const scale = highlight.interpolate({ inputRange: [0, 1], outputRange: [1, 1.02] })\n const glowColor = highlightedMuscle\n ? getHeatmapColor(\n data.find((d) => d.muscleGroup === highlightedMuscle)?.volumeStatus,\n data.find((d) => d.muscleGroup === highlightedMuscle)?.intensity ?? 0\n )\n : null\n\n const handleBodyPress = (part: ExtendedBodyPart) => {\n if (!onMusclePress || !part.slug) return\n const fromData = data.find((d) =>\n (MUSCLE_TO_SVG_SLUGS[d.muscleGroup] ?? []).includes(part.slug as string)\n )\n const muscle = fromData?.muscleGroup ?? SLUG_TO_PRIMARY_MUSCLE[part.slug]\n if (muscle) onMusclePress(muscle)\n }\n\n return (\n <View className={cn(className)} testID=\"body-map\" {...props}>\n <ViewToggle view={view} onViewChange={onViewChange} />\n\n <Animated.View\n style={[\n {\n width: 200 * BODY_SCALE,\n alignSelf: 'center',\n transform: [{ scale }],\n },\n glowColor ? { boxShadow: `0 0 14px 2px ${glowColor}` } : undefined,\n ]}\n // The SVG is decorative; the accessible muscle legend below is the\n // screen-reader / keyboard interface.\n aria-hidden\n accessibilityElementsHidden\n importantForAccessibility=\"no-hide-descendants\"\n testID=\"body-map-svg\"\n >\n <Body\n side={view}\n data={slugParts}\n scale={BODY_SCALE}\n gender=\"male\"\n defaultFill={OUTLINE_FILL}\n border={OUTLINE_BORDER}\n onBodyPartPress={handleBodyPress}\n />\n </Animated.View>\n\n {legend.length === 0 ? (\n <Text\n style={{\n marginTop: 8,\n fontSize: 12,\n color: TEXT_SECONDARY,\n textAlign: 'center',\n fontFamily: 'Inter, sans-serif',\n }}\n testID=\"body-map-empty\"\n >\n No training data\n </Text>\n ) : (\n <View\n className=\"flex-row flex-wrap\"\n style={{ marginTop: 10, gap: 6, justifyContent: 'center' }}\n testID=\"body-map-legend\"\n >\n {legend.map((entry) => (\n <MuscleButton\n key={entry.key}\n entry={entry}\n highlighted={highlightedMuscle === entry.muscle}\n onMusclePress={onMusclePress}\n />\n ))}\n </View>\n )}\n </View>\n )\n}\n\ninterface ViewToggleProps {\n view: 'front' | 'back'\n onViewChange?: (view: 'front' | 'back') => void\n}\n\nfunction ViewToggle({ view, onViewChange }: ViewToggleProps) {\n return (\n <View\n className=\"flex-row self-center\"\n style={{ gap: 4, marginBottom: 8 }}\n testID=\"body-map-view-toggle\"\n >\n {(['front', 'back'] as const).map((side) => {\n const active = view === side\n return (\n <Pressable\n key={side}\n onPress={() => onViewChange?.(side)}\n accessibilityRole=\"button\"\n accessibilityLabel={`Show ${side} view`}\n aria-pressed={active}\n disabled={!onViewChange}\n style={{\n paddingHorizontal: 12,\n paddingVertical: 4,\n borderRadius: 9999,\n backgroundColor: active ? 'rgba(255,121,0,0.16)' : 'transparent',\n borderWidth: 1,\n borderColor: active ? '#FF7900' : 'var(--color-border-strong)',\n }}\n testID={`body-map-toggle-${side}`}\n >\n <Text\n style={{\n fontSize: 12,\n fontFamily: 'Inter, sans-serif',\n fontWeight: active ? '700' : '500',\n color: active ? '#FF7900' : TEXT_SECONDARY,\n textTransform: 'capitalize',\n }}\n >\n {side}\n </Text>\n </Pressable>\n )\n })}\n </View>\n )\n}\n\ninterface MuscleButtonProps {\n entry: LegendEntry\n highlighted: boolean\n onMusclePress?: (muscleGroup: MuscleGroup) => void\n}\n\nfunction MuscleButton({ entry, highlighted, onMusclePress }: MuscleButtonProps) {\n const dotColor = getHeatmapColor(entry.status, entry.intensity)\n const label = `${entry.name}, ${VOLUME_STATUS_LABELS[entry.status]}, ${entry.sets} sets this week`\n return (\n <Pressable\n onPress={() => onMusclePress?.(entry.muscle)}\n accessibilityRole=\"button\"\n accessibilityLabel={label}\n aria-pressed={highlighted}\n style={{\n flexDirection: 'row',\n alignItems: 'center',\n gap: 5,\n paddingHorizontal: 8,\n paddingVertical: 3,\n borderRadius: 9999,\n borderWidth: 1,\n borderColor: highlighted ? '#FF7900' : 'var(--color-border-default)',\n backgroundColor: 'var(--color-surface-raised)',\n }}\n testID={`body-map-muscle-${entry.key}`}\n >\n <View\n style={{ width: 7, height: 7, borderRadius: 9999, backgroundColor: dotColor }}\n accessibilityElementsHidden\n testID={`body-map-muscle-dot-${entry.key}`}\n />\n <Text\n style={{\n fontSize: 11,\n fontFamily: 'Inter, sans-serif',\n fontWeight: '500',\n color: TEXT_PRIMARY,\n }}\n accessibilityElementsHidden\n >\n {entry.name}\n </Text>\n </Pressable>\n )\n}\n","// Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)\nimport { useEffect, useState } from 'react'\nimport {\n View,\n Text,\n Pressable,\n ScrollView,\n Animated,\n Easing,\n type ViewProps,\n type ViewStyle,\n} from 'react-native'\nimport { Badge, type BadgeColor } from '../../ui/badge'\nimport { Sparkline } from './Sparkline'\nimport {\n MuscleGroup,\n VOLUME_STATUS_LABELS,\n type VolumeLandmarks,\n type VolumeStatus,\n} from './muscleTaxonomy'\n\nconst SURFACE_ELEVATED = 'var(--color-surface-elevated)'\nconst SURFACE_RAISED = 'var(--color-surface-raised)'\nconst BORDER_STRONG = 'var(--color-border-strong)'\nconst BORDER_DEFAULT = 'var(--color-border-default)'\nconst BRAND_PRIMARY = '#FF7900'\nconst TEXT_PRIMARY = 'var(--color-text-primary)'\nconst TEXT_SECONDARY = 'var(--color-text-secondary)'\nconst TEXT_TERTIARY = 'var(--color-text-tertiary)'\n\n/** Volume track gradient: status-info (blue) -> result-improve (teal) -> status-error (red). */\nconst VOLUME_GRADIENT = 'linear-gradient(90deg, #2196F3 0%, #14B8A6 50%, #D14343 100%)'\n\n/** Sheet slides up from this offset (px) and the backdrop fades to this opacity. */\nconst SLIDE_OFFSET = 400\nconst BACKDROP_OPACITY = 0.4\n\n/** Volume status -> Badge color scheme. */\nconst STATUS_BADGE_COLOR: Record<VolumeStatus, BadgeColor> = {\n under: 'info',\n maintenance: 'warning',\n productive: 'success',\n over: 'error',\n}\n\nexport interface ContributingExercise {\n /** Exercise name. */\n name: string\n /** Working sets contributed this week. */\n sets: number\n /** Effective-set multiplier toward this muscle (0-1). */\n contributionWeight: number\n}\n\nexport interface UpcomingExercise {\n /** Exercise name. */\n name: string\n /** Workout the exercise belongs to. */\n workoutName: string\n /** Planned sets. */\n sets: number\n}\n\nexport interface BodyMapDetailPanelProps extends ViewProps {\n /** Muscle group whose volume detail is shown. */\n muscleGroup: MuscleGroup\n /** Human-readable muscle name for the title and a11y label. */\n displayName: string\n /** Weekly effective sets logged for this muscle. */\n weeklySets: number\n /** Volume landmarks (weekly working sets). */\n landmarks: VolumeLandmarks\n /** Weekly-volume status relative to the landmarks. */\n volumeStatus: VolumeStatus\n /** Last trained label, e.g. \"2 days ago\". */\n lastTrained?: string\n /** Volume sparkline data (last 4-8 weeks). */\n weeklyHistory?: number[]\n /** Exercises contributing to this muscle's volume. */\n contributingExercises?: ContributingExercise[]\n /** Upcoming exercises targeting this muscle. */\n upcomingExercises?: UpcomingExercise[]\n /** Whether the bottom sheet is visible. */\n isOpen?: boolean\n /** Alias for `isOpen` (spec wording: \"isOpen/visible\"). `isOpen` wins when both are set. */\n visible?: boolean\n /** Dismiss the panel (backdrop, handle, or close button). */\n onClose: () => void\n /** Navigate to a filtered exercise list. */\n onViewExercises?: () => void\n}\n\nfunction clamp01(value: number): number {\n if (value < 0) return 0\n if (value > 1) return 1\n return value\n}\n\n/** Marker position (0-1) of current sets between MEV (left) and MRV (right). */\nfunction markerFraction(weeklySets: number, { mev, mrv }: VolumeLandmarks): number {\n const span = mrv - mev\n if (span <= 0) return weeklySets >= mrv ? 1 : 0\n return clamp01((weeklySets - mev) / span)\n}\n\n/**\n * Slide-up bottom-sheet panel with detailed weekly-volume info for a tapped\n * muscle group: a MEV|current|MRV gradient progress bar, the big weekly set\n * count against MRV, an optional volume sparkline, and the contributing /\n * upcoming exercise lists. Composes the titan `Badge` and Workout `Sparkline`.\n *\n * Controlled via `isOpen` (or the `visible` alias); renders nothing when closed\n * and animates in on open — sheet translateY 400->0 (400ms ease-out) and a\n * backdrop fade 0->0.4 (RN Animated, useNativeDriver:false). Backdrop, handle,\n * and the header close button all call `onClose`.\n *\n * @example\n * <BodyMapDetailPanel\n * muscleGroup={MuscleGroup.CHEST}\n * displayName=\"Chest\"\n * weeklySets={14}\n * landmarks={{ mev: 8, mav: 14, mrv: 20 }}\n * volumeStatus=\"productive\"\n * lastTrained=\"2 days ago\"\n * weeklyHistory={[8, 10, 12, 14]}\n * isOpen={open}\n * onClose={() => setOpen(false)}\n * />\n */\nexport function BodyMapDetailPanel({\n muscleGroup,\n displayName,\n weeklySets,\n landmarks,\n volumeStatus,\n lastTrained,\n weeklyHistory,\n contributingExercises,\n upcomingExercises,\n isOpen,\n visible,\n onClose,\n onViewExercises,\n ...props\n}: BodyMapDetailPanelProps) {\n const open = isOpen ?? visible ?? false\n\n const [translateY] = useState(() => new Animated.Value(SLIDE_OFFSET))\n const [backdrop] = useState(() => new Animated.Value(0))\n\n useEffect(() => {\n if (!open) return\n const animation = Animated.parallel([\n Animated.timing(translateY, {\n toValue: 0,\n duration: 400,\n easing: Easing.out(Easing.ease),\n useNativeDriver: false,\n }),\n Animated.timing(backdrop, {\n toValue: BACKDROP_OPACITY,\n duration: 300,\n easing: Easing.out(Easing.ease),\n useNativeDriver: false,\n }),\n ])\n animation.start()\n return () => animation.stop()\n }, [open, translateY, backdrop])\n\n if (!open) return null\n\n const dialogLabel = `${displayName} volume details`\n const markerLeft = markerFraction(weeklySets, landmarks) * 100\n const hasContributing = (contributingExercises?.length ?? 0) > 0\n const hasUpcoming = (upcomingExercises?.length ?? 0) > 0\n\n return (\n <View\n style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, justifyContent: 'flex-end' }}\n testID=\"body-map-detail-panel-root\"\n >\n <Animated.View\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundColor: '#000000',\n opacity: backdrop,\n }}\n testID=\"body-map-detail-panel-backdrop-anim\"\n >\n <Pressable\n onPress={onClose}\n accessibilityRole=\"button\"\n accessibilityLabel={`Close ${displayName} details`}\n style={{ flex: 1 }}\n testID=\"body-map-detail-panel-backdrop\"\n />\n </Animated.View>\n\n <Animated.View\n accessibilityRole={'dialog' as ViewProps['accessibilityRole']}\n accessibilityLabel={dialogLabel}\n aria-label={dialogLabel}\n style={{\n backgroundColor: SURFACE_ELEVATED,\n borderTopLeftRadius: 16,\n borderTopRightRadius: 16,\n maxHeight: '88%',\n transform: [{ translateY }],\n }}\n testID=\"body-map-detail-panel\"\n {...props}\n >\n <Pressable\n onPress={onClose}\n accessibilityRole=\"button\"\n accessibilityLabel={`Close ${displayName} details`}\n hitSlop={12}\n style={{ alignSelf: 'center', paddingVertical: 8 }}\n testID=\"body-map-detail-panel-handle\"\n >\n <View\n style={{ width: 40, height: 4, borderRadius: 2, backgroundColor: BORDER_STRONG }}\n accessibilityElementsHidden\n />\n </Pressable>\n\n <ScrollView\n style={{ paddingHorizontal: 16 }}\n contentContainerStyle={{ paddingBottom: 20 }}\n testID=\"body-map-detail-panel-scroll\"\n >\n <View\n className=\"flex-row items-center justify-between\"\n style={{ gap: 8, paddingTop: 4, paddingBottom: 4 }}\n testID=\"body-map-detail-panel-header\"\n >\n <View className=\"flex-row items-center\" style={{ gap: 8, flexShrink: 1 }}>\n <Text\n accessibilityRole=\"header\"\n style={{\n fontSize: 16,\n fontFamily: '\"Space Grotesk\", sans-serif',\n fontWeight: '700',\n color: TEXT_PRIMARY,\n }}\n testID=\"body-map-detail-panel-title\"\n >\n {displayName}\n </Text>\n <Badge\n variant=\"subtle\"\n color={STATUS_BADGE_COLOR[volumeStatus]}\n size=\"sm\"\n testID=\"body-map-detail-panel-status-badge\"\n >\n {VOLUME_STATUS_LABELS[volumeStatus]}\n </Badge>\n </View>\n <Pressable\n onPress={onClose}\n accessibilityRole=\"button\"\n accessibilityLabel={`Close ${displayName} details`}\n hitSlop={8}\n style={{ padding: 4, margin: -4 }}\n testID=\"body-map-detail-panel-close\"\n >\n <Text style={{ fontSize: 22, lineHeight: 22, color: TEXT_SECONDARY }}>{'×'}</Text>\n </Pressable>\n </View>\n\n {lastTrained != null && (\n <Text\n style={{ fontSize: 12, fontFamily: 'Inter, sans-serif', color: TEXT_SECONDARY }}\n testID=\"body-map-detail-panel-last-trained\"\n >\n {`Last trained ${lastTrained}`}\n </Text>\n )}\n\n <View style={{ marginTop: 16 }} testID=\"body-map-detail-panel-volume\">\n <View\n className=\"flex-row items-center justify-between\"\n style={{ marginBottom: 6 }}\n accessibilityElementsHidden\n >\n <Text style={{ fontSize: 10, fontFamily: 'Inter, sans-serif', fontWeight: '600', color: TEXT_TERTIARY }}>\n {`MEV ${landmarks.mev}`}\n </Text>\n <Text style={{ fontSize: 10, fontFamily: 'Inter, sans-serif', fontWeight: '600', color: TEXT_TERTIARY }}>\n {`MRV ${landmarks.mrv}`}\n </Text>\n </View>\n <View\n style={{ height: 14, justifyContent: 'center' }}\n accessibilityRole=\"progressbar\"\n accessibilityValue={{ min: landmarks.mev, max: landmarks.mrv, now: weeklySets }}\n accessibilityLabel={`${weeklySets} weekly sets, between MEV ${landmarks.mev} and MRV ${landmarks.mrv}`}\n aria-valuenow={weeklySets}\n aria-valuemin={landmarks.mev}\n aria-valuemax={landmarks.mrv}\n testID=\"body-map-detail-panel-volume-bar\"\n >\n <View\n style={{ height: 8, borderRadius: 4, backgroundImage: VOLUME_GRADIENT } as ViewStyle}\n accessibilityElementsHidden\n />\n <View\n style={{\n position: 'absolute',\n left: `${markerLeft}%`,\n marginLeft: -7,\n width: 14,\n height: 14,\n borderRadius: 7,\n borderWidth: 2,\n borderColor: TEXT_PRIMARY,\n backgroundColor: SURFACE_ELEVATED,\n boxShadow: '0 0 4px rgba(0,0,0,0.5)',\n }}\n accessibilityElementsHidden\n testID=\"body-map-detail-panel-volume-marker\"\n />\n </View>\n </View>\n\n <View className=\"flex-row items-baseline\" style={{ marginTop: 14, gap: 4 }}>\n <Text\n style={{\n fontSize: 24,\n fontFamily: '\"Space Grotesk\", sans-serif',\n fontWeight: '700',\n color: TEXT_PRIMARY,\n }}\n testID=\"body-map-detail-panel-set-count\"\n >\n {weeklySets}\n </Text>\n <Text\n style={{ fontSize: 12, fontFamily: 'Inter, sans-serif', color: TEXT_SECONDARY }}\n testID=\"body-map-detail-panel-mrv-suffix\"\n >\n {`/ ${landmarks.mrv} MRV`}\n </Text>\n </View>\n\n {weeklyHistory != null && weeklyHistory.length > 0 && (\n <View style={{ marginTop: 14 }} testID=\"body-map-detail-panel-sparkline\">\n <Text\n style={{\n fontSize: 10,\n fontFamily: 'Inter, sans-serif',\n fontWeight: '600',\n color: TEXT_TERTIARY,\n marginBottom: 6,\n }}\n accessibilityElementsHidden\n >\n {'VOLUME TREND'}\n </Text>\n <Sparkline data={weeklyHistory} width={80} height={30} highlightLast />\n </View>\n )}\n\n {hasContributing && (\n <View style={{ marginTop: 16 }} testID=\"body-map-detail-panel-contributing\">\n <Text\n style={{\n fontSize: 10,\n fontFamily: 'Inter, sans-serif',\n fontWeight: '600',\n color: TEXT_TERTIARY,\n marginBottom: 8,\n }}\n >\n {'CONTRIBUTING EXERCISES'}\n </Text>\n {contributingExercises!.map((exercise, index) => (\n <View\n key={`${exercise.name}-${index}`}\n className=\"flex-row items-center justify-between\"\n style={{\n gap: 10,\n paddingVertical: 8,\n paddingHorizontal: 12,\n marginBottom: 6,\n borderRadius: 8,\n backgroundColor: SURFACE_RAISED,\n borderWidth: 1,\n borderColor: BORDER_DEFAULT,\n }}\n testID={`body-map-detail-panel-contributing-${index}`}\n >\n <Text\n style={{ flex: 1, fontSize: 13, fontFamily: 'Inter, sans-serif', fontWeight: '600', color: TEXT_PRIMARY }}\n testID={`body-map-detail-panel-contributing-${index}-name`}\n >\n {exercise.name}\n </Text>\n <Text\n style={{ fontSize: 12, fontFamily: 'Inter, sans-serif', color: TEXT_SECONDARY }}\n testID={`body-map-detail-panel-contributing-${index}-detail`}\n >\n {`${exercise.sets} sets · ${Math.round(exercise.contributionWeight * 100)}%`}\n </Text>\n </View>\n ))}\n </View>\n )}\n\n {hasUpcoming && (\n <View style={{ marginTop: 16 }} testID=\"body-map-detail-panel-upcoming\">\n <Text\n style={{\n fontSize: 10,\n fontFamily: 'Inter, sans-serif',\n fontWeight: '600',\n color: TEXT_TERTIARY,\n marginBottom: 8,\n }}\n >\n {'UPCOMING'}\n </Text>\n {upcomingExercises!.map((exercise, index) => (\n <View\n key={`${exercise.name}-${index}`}\n className=\"flex-row items-center justify-between\"\n style={{ gap: 10, paddingVertical: 6 }}\n testID={`body-map-detail-panel-upcoming-${index}`}\n >\n <Text\n style={{ flex: 1, fontSize: 13, fontFamily: 'Inter, sans-serif', fontWeight: '600', color: TEXT_PRIMARY }}\n testID={`body-map-detail-panel-upcoming-${index}-name`}\n >\n {exercise.name}\n </Text>\n <Text\n style={{ fontSize: 12, fontFamily: 'Inter, sans-serif', color: TEXT_TERTIARY }}\n testID={`body-map-detail-panel-upcoming-${index}-detail`}\n >\n {`${exercise.workoutName} · ${exercise.sets} sets`}\n </Text>\n </View>\n ))}\n </View>\n )}\n\n {onViewExercises != null && (\n <Pressable\n onPress={onViewExercises}\n accessibilityRole=\"button\"\n accessibilityLabel={`View ${displayName} exercises`}\n style={{\n marginTop: 16,\n paddingVertical: 10,\n borderRadius: 8,\n alignItems: 'center',\n backgroundColor: 'rgba(255,121,0,0.12)',\n borderWidth: 1,\n borderColor: 'rgba(255,121,0,0.3)',\n }}\n testID=\"body-map-detail-panel-view-exercises\"\n >\n <Text style={{ fontSize: 13, fontFamily: 'Inter, sans-serif', fontWeight: '700', color: BRAND_PRIMARY }}>\n {'View exercises'}\n </Text>\n </Pressable>\n )}\n </ScrollView>\n </Animated.View>\n </View>\n )\n}\n","// Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)\nimport { useMemo, useState } from 'react'\nimport { View, Text, type ViewProps } from 'react-native'\nimport { BodyMap, type BodyMapData } from './BodyMap'\nimport {\n BodyMapDetailPanel,\n type ContributingExercise,\n type UpcomingExercise,\n} from './BodyMapDetailPanel'\nimport { MesoStatusCard, type MesoStatusCardProps } from './MesoStatusCard'\nimport {\n MuscleGroup,\n VOLUME_STATUS_LABELS,\n getHeatmapColor,\n type VolumeLandmarks,\n type VolumeStatus,\n} from './muscleTaxonomy'\n\nconst SURFACE_ELEVATED = 'var(--color-surface-elevated)'\nconst BORDER_DEFAULT = 'var(--color-border-default)'\nconst TEXT_PRIMARY = 'var(--color-text-primary)'\nconst TEXT_SECONDARY = 'var(--color-text-secondary)'\nconst TEXT_TERTIARY = 'var(--color-text-tertiary)'\nconst PAGE_BG = 'var(--color-background-base)'\n\n/** Volume statuses in display order for the legend and summary cards. */\nconst STATUS_ORDER: VolumeStatus[] = ['under', 'maintenance', 'productive', 'over']\n\n/** One muscle's full volume picture — feeds the body maps and the detail panel. */\nexport interface TrainingStatusMuscle {\n /** Detailed muscle group (drives the SVG heatmap + panel identity). */\n muscleGroup: MuscleGroup\n /** Human-readable name for the legend, summary, and panel title. */\n displayName: string\n /** Which body-map view the muscle belongs to. */\n side: 'front' | 'back'\n /** Heatmap intensity 0-1. */\n intensity: number\n /** Weekly-volume status relative to the landmarks. */\n volumeStatus: VolumeStatus\n /** Weekly effective sets logged. */\n weeklySets: number\n /** Volume landmarks (weekly working sets). */\n landmarks: VolumeLandmarks\n /** Last trained label, e.g. \"2 days ago\". */\n lastTrained?: string\n /** Weekly volume history for the panel sparkline. */\n weeklyHistory?: number[]\n /** Exercises contributing to this muscle's volume. */\n contributingExercises?: ContributingExercise[]\n /** Upcoming exercises targeting this muscle. */\n upcomingExercises?: UpcomingExercise[]\n}\n\n/** Derived, page-level roll-up of the tracked muscles. */\nexport interface TrainingStatusSummary {\n /** Total weekly effective sets across all tracked muscles. */\n totalWeeklySets: number\n /** Number of muscles being tracked. */\n trackedMuscles: number\n /** Count of muscles per volume status. */\n statusCounts: Record<VolumeStatus, number>\n}\n\nexport interface TrainingStatusPageProps extends ViewProps {\n /** Page heading. */\n title?: string\n /** Mesocycle context banner shown at the top. */\n meso: MesoStatusCardProps\n /** Muscles tracked this week. */\n muscles: TrainingStatusMuscle[]\n className?: string\n}\n\n/** Roll up per-muscle rows into the page summary (pure, testable). */\nexport function deriveTrainingSummary(muscles: TrainingStatusMuscle[]): TrainingStatusSummary {\n const statusCounts: Record<VolumeStatus, number> = {\n under: 0,\n maintenance: 0,\n productive: 0,\n over: 0,\n }\n let totalWeeklySets = 0\n for (const muscle of muscles) {\n totalWeeklySets += muscle.weeklySets\n statusCounts[muscle.volumeStatus] += 1\n }\n return { totalWeeklySets, trackedMuscles: muscles.length, statusCounts }\n}\n\n/** Project the muscle rows for one side into `BodyMap` heatmap data. */\nexport function toBodyMapData(\n muscles: TrainingStatusMuscle[],\n side: 'front' | 'back'\n): BodyMapData[] {\n return muscles\n .filter((muscle) => muscle.side === side)\n .map(({ muscleGroup, intensity, volumeStatus, weeklySets }) => ({\n muscleGroup,\n intensity,\n volumeStatus,\n weeklySets,\n }))\n}\n\nconst SUMMARY_CARDS: Array<{\n key: keyof TrainingStatusSummary['statusCounts'] | 'total'\n label: string\n}> = [\n { key: 'total', label: 'Weekly Sets' },\n { key: 'productive', label: 'Productive' },\n { key: 'under', label: 'Under' },\n { key: 'over', label: 'Over' },\n]\n\nfunction SummaryCards({ summary }: { summary: TrainingStatusSummary }) {\n return (\n <View className=\"flex-row flex-wrap\" style={{ gap: 8 }} testID=\"training-status-page-summary\">\n {SUMMARY_CARDS.map(({ key, label }) => {\n const value = key === 'total' ? summary.totalWeeklySets : summary.statusCounts[key]\n return (\n <View\n key={key}\n style={{\n flexGrow: 1,\n flexBasis: '46%',\n padding: 12,\n borderRadius: 10,\n backgroundColor: SURFACE_ELEVATED,\n borderWidth: 1,\n borderColor: BORDER_DEFAULT,\n }}\n testID={`training-status-page-summary-${key}`}\n >\n <Text\n style={{\n fontSize: 22,\n fontFamily: '\"Space Grotesk\", sans-serif',\n fontWeight: '700',\n color: TEXT_PRIMARY,\n }}\n >\n {value}\n </Text>\n <Text\n style={{\n marginTop: 2,\n fontSize: 11,\n fontFamily: 'Inter, sans-serif',\n fontWeight: '600',\n letterSpacing: 0.4,\n textTransform: 'uppercase',\n color: TEXT_TERTIARY,\n }}\n >\n {label}\n </Text>\n </View>\n )\n })}\n </View>\n )\n}\n\nfunction StatusLegend() {\n return (\n <View\n className=\"flex-row flex-wrap\"\n style={{ gap: 10, justifyContent: 'center' }}\n testID=\"training-status-page-legend\"\n >\n {STATUS_ORDER.map((status) => (\n <View\n key={status}\n className=\"flex-row items-center\"\n style={{ gap: 5 }}\n testID={`training-status-page-legend-${status}`}\n >\n <View\n style={{\n width: 8,\n height: 8,\n borderRadius: 9999,\n backgroundColor: getHeatmapColor(status, 0.6),\n }}\n accessibilityElementsHidden\n />\n <Text\n style={{\n fontSize: 11,\n fontFamily: 'Inter, sans-serif',\n color: TEXT_SECONDARY,\n textTransform: 'capitalize',\n }}\n >\n {VOLUME_STATUS_LABELS[status]}\n </Text>\n </View>\n ))}\n </View>\n )\n}\n\ninterface BodyMapColumnProps {\n side: 'front' | 'back'\n muscles: TrainingStatusMuscle[]\n selected: MuscleGroup | null\n onSelect: (muscle: MuscleGroup) => void\n}\n\nfunction BodyMapColumn({ side, muscles, selected, onSelect }: BodyMapColumnProps) {\n const data = useMemo(() => toBodyMapData(muscles, side), [muscles, side])\n return (\n <View style={{ flexGrow: 1, flexBasis: '46%' }} testID={`training-status-page-bodymap-${side}`}>\n <BodyMap\n data={data}\n view={side}\n onMusclePress={onSelect}\n highlightedMuscle={selected}\n mode=\"detailed\"\n />\n </View>\n )\n}\n\n/**\n * TrainingStatusPage — a body-map training dashboard that composes the\n * mesocycle context banner (`MesoStatusCard`), side-by-side front/back\n * `BodyMap`s with a shared heatmap legend, per-status summary cards, and a\n * tap-to-detail `BodyMapDetailPanel`. Tapping any muscle (SVG or legend chip)\n * opens the slide-up panel for that group; the summary is derived from the\n * supplied muscle rows.\n *\n * @example\n * <TrainingStatusPage meso={meso} muscles={muscles} />\n */\nexport function TrainingStatusPage({\n title = 'Training Status',\n meso,\n muscles,\n className,\n ...props\n}: TrainingStatusPageProps) {\n const [selected, setSelected] = useState<MuscleGroup | null>(null)\n const summary = useMemo(() => deriveTrainingSummary(muscles), [muscles])\n const active = selected != null ? (muscles.find((m) => m.muscleGroup === selected) ?? null) : null\n\n return (\n <View\n className={className}\n style={{ position: 'relative', width: 390, backgroundColor: PAGE_BG }}\n accessibilityRole={'main' as ViewProps['accessibilityRole']}\n aria-label={title}\n testID=\"training-status-page\"\n {...props}\n >\n <View style={{ padding: 16, gap: 16 }} testID=\"training-status-page-content\">\n <Text\n accessibilityRole=\"header\"\n style={{\n fontSize: 20,\n fontFamily: '\"Space Grotesk\", sans-serif',\n fontWeight: '700',\n color: TEXT_PRIMARY,\n }}\n testID=\"training-status-page-title\"\n >\n {title}\n </Text>\n\n <MesoStatusCard {...meso} />\n\n <SummaryCards summary={summary} />\n\n <View\n style={{\n backgroundColor: SURFACE_ELEVATED,\n borderWidth: 1,\n borderColor: BORDER_DEFAULT,\n borderRadius: 12,\n padding: 12,\n gap: 12,\n }}\n testID=\"training-status-page-bodymaps\"\n >\n <View className=\"flex-row\" style={{ gap: 8 }}>\n <BodyMapColumn\n side=\"front\"\n muscles={muscles}\n selected={selected}\n onSelect={setSelected}\n />\n <BodyMapColumn\n side=\"back\"\n muscles={muscles}\n selected={selected}\n onSelect={setSelected}\n />\n </View>\n <StatusLegend />\n </View>\n </View>\n\n {active != null && (\n <BodyMapDetailPanel\n muscleGroup={active.muscleGroup}\n displayName={active.displayName}\n weeklySets={active.weeklySets}\n landmarks={active.landmarks}\n volumeStatus={active.volumeStatus}\n lastTrained={active.lastTrained}\n weeklyHistory={active.weeklyHistory}\n contributingExercises={active.contributingExercises}\n upcomingExercises={active.upcomingExercises}\n isOpen\n onClose={() => setSelected(null)}\n />\n )}\n </View>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/custom/Workout/muscleTaxonomy.ts","../src/components/custom/Workout/BodyMap.tsx","../src/components/custom/Workout/BodyMapDetailPanel.tsx","../src/components/custom/Workout/TrainingStatusPage.tsx"],"names":["MuscleGroup","SimpleMuscleGroup","useState","Animated","useEffect","Easing","View","Pressable","Text","useMemo"],"mappings":"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","file":"bodymap.mjs","sourcesContent":["/**\n * Muscle grouping taxonomy for volume tracking, exercise mapping, and the\n * BodyMap visualization. Ported from the Voltras muscle-taxonomy design doc.\n *\n * Level 2 (15 groups) is the primary volume-tracking unit; SimpleMuscleGroup\n * (8 groups) is the beginner-facing aggregation. MUSCLE_TO_SVG_SLUGS maps each\n * group to react-native-body-highlighter slugs using the closest-slug approach\n * (Phase 1: combined colors, no sub-region splitting — deltoids is a single\n * slug, lats and upper back share `upper-back`).\n */\nimport { WORKOUT_TOKENS } from '../../../theme/workout-tokens'\n\n/**\n * Full muscle group taxonomy for volume tracking and exercise mapping.\n * 15 groups — the primary unit for volume accounting.\n */\nexport enum MuscleGroup {\n // Push\n CHEST = 'chest',\n FRONT_DELTS = 'front_delts',\n SIDE_DELTS = 'side_delts',\n TRICEPS = 'triceps',\n\n // Pull\n LATS = 'lats',\n UPPER_BACK = 'upper_back',\n REAR_DELTS = 'rear_delts',\n BICEPS = 'biceps',\n FOREARMS = 'forearms',\n\n // Legs\n QUADS = 'quads',\n HAMSTRINGS = 'hamstrings',\n GLUTES = 'glutes',\n CALVES = 'calves',\n\n // Core\n ABS = 'abs',\n OBLIQUES = 'obliques',\n}\n\n/**\n * Simplified muscle group view for beginners. Maps to one or more MuscleGroup.\n */\nexport enum SimpleMuscleGroup {\n CHEST = 'chest',\n BACK = 'back',\n SHOULDERS = 'shoulders',\n BICEPS = 'biceps',\n TRICEPS = 'triceps',\n LEGS = 'legs',\n CORE = 'core',\n FOREARMS = 'forearms',\n}\n\n/** Mapping from simplified groups to the full taxonomy. */\nexport const SIMPLE_TO_DETAILED: Record<SimpleMuscleGroup, MuscleGroup[]> = {\n [SimpleMuscleGroup.CHEST]: [MuscleGroup.CHEST],\n [SimpleMuscleGroup.BACK]: [MuscleGroup.LATS, MuscleGroup.UPPER_BACK],\n [SimpleMuscleGroup.SHOULDERS]: [\n MuscleGroup.FRONT_DELTS,\n MuscleGroup.SIDE_DELTS,\n MuscleGroup.REAR_DELTS,\n ],\n [SimpleMuscleGroup.BICEPS]: [MuscleGroup.BICEPS],\n [SimpleMuscleGroup.TRICEPS]: [MuscleGroup.TRICEPS],\n [SimpleMuscleGroup.LEGS]: [\n MuscleGroup.QUADS,\n MuscleGroup.HAMSTRINGS,\n MuscleGroup.GLUTES,\n MuscleGroup.CALVES,\n ],\n [SimpleMuscleGroup.CORE]: [MuscleGroup.ABS, MuscleGroup.OBLIQUES],\n [SimpleMuscleGroup.FOREARMS]: [MuscleGroup.FOREARMS],\n}\n\n/** Reverse map: detailed MuscleGroup -> its SimpleMuscleGroup. */\nexport const DETAILED_TO_SIMPLE: Record<MuscleGroup, SimpleMuscleGroup> = Object.entries(\n SIMPLE_TO_DETAILED\n).reduce(\n (acc, [simple, groups]) => {\n for (const group of groups) {\n acc[group] = simple as SimpleMuscleGroup\n }\n return acc\n },\n {} as Record<MuscleGroup, SimpleMuscleGroup>\n)\n\n/** Movement category for training split organization. */\nexport type MovementCategory = 'push' | 'pull' | 'legs' | 'core'\n\nexport const MUSCLE_TO_CATEGORY: Record<MuscleGroup, MovementCategory> = {\n [MuscleGroup.CHEST]: 'push',\n [MuscleGroup.FRONT_DELTS]: 'push',\n [MuscleGroup.SIDE_DELTS]: 'push',\n [MuscleGroup.TRICEPS]: 'push',\n [MuscleGroup.LATS]: 'pull',\n [MuscleGroup.UPPER_BACK]: 'pull',\n [MuscleGroup.REAR_DELTS]: 'pull',\n [MuscleGroup.BICEPS]: 'pull',\n [MuscleGroup.FOREARMS]: 'pull',\n [MuscleGroup.QUADS]: 'legs',\n [MuscleGroup.HAMSTRINGS]: 'legs',\n [MuscleGroup.GLUTES]: 'legs',\n [MuscleGroup.CALVES]: 'legs',\n [MuscleGroup.ABS]: 'core',\n [MuscleGroup.OBLIQUES]: 'core',\n}\n\n/**\n * react-native-body-highlighter slug(s) per muscle group. Phase 1 uses the\n * closest available slug; deltoids share one path and lats/upper-back share\n * `upper-back` (see doc Level 4 \"Recommended approach\").\n */\nexport const MUSCLE_TO_SVG_SLUGS: Record<MuscleGroup, string[]> = {\n [MuscleGroup.CHEST]: ['chest'],\n [MuscleGroup.FRONT_DELTS]: ['deltoids'],\n [MuscleGroup.SIDE_DELTS]: ['deltoids'],\n [MuscleGroup.REAR_DELTS]: ['deltoids'],\n [MuscleGroup.TRICEPS]: ['triceps'],\n [MuscleGroup.LATS]: ['upper-back'],\n [MuscleGroup.UPPER_BACK]: ['upper-back', 'trapezius'],\n [MuscleGroup.BICEPS]: ['biceps'],\n [MuscleGroup.FOREARMS]: ['forearm'],\n [MuscleGroup.QUADS]: ['quadriceps'],\n [MuscleGroup.HAMSTRINGS]: ['hamstring'],\n [MuscleGroup.GLUTES]: ['gluteal'],\n [MuscleGroup.CALVES]: ['calves'],\n [MuscleGroup.ABS]: ['abs'],\n [MuscleGroup.OBLIQUES]: ['obliques'],\n}\n\n/** Human-readable name per muscle group (used in a11y labels). */\nexport const MUSCLE_DISPLAY_NAMES: Record<MuscleGroup, string> = {\n [MuscleGroup.CHEST]: 'Chest',\n [MuscleGroup.FRONT_DELTS]: 'Front Delts',\n [MuscleGroup.SIDE_DELTS]: 'Side Delts',\n [MuscleGroup.REAR_DELTS]: 'Rear Delts',\n [MuscleGroup.TRICEPS]: 'Triceps',\n [MuscleGroup.LATS]: 'Lats',\n [MuscleGroup.UPPER_BACK]: 'Upper Back',\n [MuscleGroup.BICEPS]: 'Biceps',\n [MuscleGroup.FOREARMS]: 'Forearms',\n [MuscleGroup.QUADS]: 'Quads',\n [MuscleGroup.HAMSTRINGS]: 'Hamstrings',\n [MuscleGroup.GLUTES]: 'Glutes',\n [MuscleGroup.CALVES]: 'Calves',\n [MuscleGroup.ABS]: 'Abs',\n [MuscleGroup.OBLIQUES]: 'Obliques',\n}\n\n/** Human-readable name per simple group. */\nexport const SIMPLE_DISPLAY_NAMES: Record<SimpleMuscleGroup, string> = {\n [SimpleMuscleGroup.CHEST]: 'Chest',\n [SimpleMuscleGroup.BACK]: 'Back',\n [SimpleMuscleGroup.SHOULDERS]: 'Shoulders',\n [SimpleMuscleGroup.BICEPS]: 'Biceps',\n [SimpleMuscleGroup.TRICEPS]: 'Triceps',\n [SimpleMuscleGroup.LEGS]: 'Legs',\n [SimpleMuscleGroup.CORE]: 'Core',\n [SimpleMuscleGroup.FOREARMS]: 'Forearms',\n}\n\n/** Volume landmarks per muscle group (weekly working sets). */\nexport interface VolumeLandmarks {\n mev: number // Minimum Effective Volume\n mav: number // Maximum Adaptive Volume\n mrv: number // Maximum Recoverable Volume\n}\n\nexport const DEFAULT_VOLUME_LANDMARKS: Record<MuscleGroup, VolumeLandmarks> = {\n [MuscleGroup.CHEST]: { mev: 8, mav: 14, mrv: 20 },\n [MuscleGroup.LATS]: { mev: 8, mav: 14, mrv: 20 },\n [MuscleGroup.UPPER_BACK]: { mev: 6, mav: 12, mrv: 18 },\n [MuscleGroup.FRONT_DELTS]: { mev: 2, mav: 6, mrv: 10 },\n [MuscleGroup.SIDE_DELTS]: { mev: 6, mav: 14, mrv: 22 },\n [MuscleGroup.REAR_DELTS]: { mev: 6, mav: 12, mrv: 18 },\n [MuscleGroup.BICEPS]: { mev: 4, mav: 10, mrv: 18 },\n [MuscleGroup.TRICEPS]: { mev: 4, mav: 8, mrv: 14 },\n [MuscleGroup.FOREARMS]: { mev: 2, mav: 6, mrv: 12 },\n [MuscleGroup.QUADS]: { mev: 6, mav: 12, mrv: 18 },\n [MuscleGroup.HAMSTRINGS]: { mev: 4, mav: 10, mrv: 16 },\n [MuscleGroup.GLUTES]: { mev: 4, mav: 10, mrv: 16 },\n [MuscleGroup.CALVES]: { mev: 6, mav: 10, mrv: 16 },\n [MuscleGroup.ABS]: { mev: 0, mav: 8, mrv: 16 },\n [MuscleGroup.OBLIQUES]: { mev: 0, mav: 6, mrv: 12 },\n}\n\n/** Weekly-volume status relative to MEV/MAV/MRV landmarks. */\nexport type VolumeStatus = 'under' | 'maintenance' | 'productive' | 'over'\n\n/** Readable label per status for a11y descriptions. */\nexport const VOLUME_STATUS_LABELS: Record<VolumeStatus, string> = {\n under: 'under-trained',\n maintenance: 'maintenance',\n productive: 'productive',\n over: 'over-reaching',\n}\n\n/** Severity ranking — higher wins when several groups share an SVG slug. */\nconst STATUS_SEVERITY: Record<VolumeStatus, number> = {\n under: 1,\n maintenance: 2,\n productive: 3,\n over: 4,\n}\n\n/**\n * Maps a volume status (and intensity, 0-1) to a heatmap fill color. The\n * `approaching` token is used when a productive muscle nears its MRV.\n */\nexport function getHeatmapColor(status: VolumeStatus | null | undefined, intensity = 0): string {\n const heatmap = WORKOUT_TOKENS.heatmap\n switch (status) {\n case 'under':\n return heatmap.under\n case 'maintenance':\n return heatmap.maintenance\n case 'productive':\n return intensity >= 0.85 ? heatmap.approaching : heatmap.productive\n case 'over':\n return heatmap.over\n default:\n return heatmap.none\n }\n}\n\n/** True when one status is at least as severe as another. */\nexport function isMoreSevere(a: VolumeStatus, b: VolumeStatus): boolean {\n return STATUS_SEVERITY[a] >= STATUS_SEVERITY[b]\n}\n\n/**\n * Representative MuscleGroup for each SVG slug, used to resolve taps on shared\n * paths (e.g. `deltoids`, `upper-back`) back to a single group.\n */\nexport const SLUG_TO_PRIMARY_MUSCLE: Record<string, MuscleGroup> = {\n chest: MuscleGroup.CHEST,\n deltoids: MuscleGroup.SIDE_DELTS,\n triceps: MuscleGroup.TRICEPS,\n 'upper-back': MuscleGroup.LATS,\n trapezius: MuscleGroup.UPPER_BACK,\n biceps: MuscleGroup.BICEPS,\n forearm: MuscleGroup.FOREARMS,\n quadriceps: MuscleGroup.QUADS,\n hamstring: MuscleGroup.HAMSTRINGS,\n gluteal: MuscleGroup.GLUTES,\n calves: MuscleGroup.CALVES,\n abs: MuscleGroup.ABS,\n obliques: MuscleGroup.OBLIQUES,\n}\n","// Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)\nimport { useEffect, useMemo, useState } from 'react'\nimport { View, Text, Pressable, Animated, Easing, type ViewProps } from 'react-native'\nimport BodyHighlighter, { type ExtendedBodyPart, type Slug } from 'react-native-body-highlighter'\nimport { cn } from '../../../utils/cn'\nimport { resolveColor } from '../../../theme/resolve-color'\nimport {\n MuscleGroup,\n SimpleMuscleGroup,\n MUSCLE_TO_SVG_SLUGS,\n MUSCLE_DISPLAY_NAMES,\n SIMPLE_DISPLAY_NAMES,\n DETAILED_TO_SIMPLE,\n SLUG_TO_PRIMARY_MUSCLE,\n VOLUME_STATUS_LABELS,\n getHeatmapColor,\n isMoreSevere,\n type VolumeStatus,\n} from './muscleTaxonomy'\n\n/**\n * react-native-body-highlighter is published as a CommonJS default export; the\n * interop keeps it working whether the bundler unwraps the default or not.\n */\nconst Body = ((BodyHighlighter as unknown as { default?: typeof BodyHighlighter }).default ??\n BodyHighlighter) as typeof BodyHighlighter\n\nconst OUTLINE_FILL = 'rgba(255,255,255,0.08)'\nconst OUTLINE_BORDER = 'rgba(255,255,255,0.12)'\nconst BODY_SCALE = 0.8 // 200x400 intrinsic -> ~160x320 px\n\nexport interface BodyMapData {\n muscleGroup: MuscleGroup\n /** Intensity 0-1 for heatmap color. */\n intensity: number\n /** Volume status for tooltip / heatmap token. */\n volumeStatus: VolumeStatus\n /** Weekly effective sets. */\n weeklySets: number\n}\n\nexport interface BodyMapProps extends ViewProps {\n /** Muscle group intensity data. */\n data: BodyMapData[]\n /** Which view to show. */\n view: 'front' | 'back'\n /** Toggle between front/back. */\n onViewChange?: (view: 'front' | 'back') => void\n /** Called when a muscle group is tapped. */\n onMusclePress?: (muscleGroup: MuscleGroup) => void\n /** Currently highlighted muscle (from external selection). */\n highlightedMuscle?: MuscleGroup | null\n /** Show simplified (8 groups) or detailed (15 groups). */\n mode?: 'simple' | 'detailed'\n className?: string\n}\n\ninterface LegendEntry {\n key: string\n name: string\n status: VolumeStatus\n intensity: number\n sets: number\n /** Detailed group reported to onMusclePress. */\n muscle: MuscleGroup\n}\n\n/** Build the per-slug heatmap fill list, combining groups that share a slug. */\nfunction buildSlugParts(data: BodyMapData[]): ExtendedBodyPart[] {\n const bySlug = new Map<string, { status: VolumeStatus; intensity: number }>()\n for (const d of data) {\n for (const slug of MUSCLE_TO_SVG_SLUGS[d.muscleGroup] ?? []) {\n const existing = bySlug.get(slug)\n if (!existing || isMoreSevere(d.volumeStatus, existing.status)) {\n bySlug.set(slug, { status: d.volumeStatus, intensity: d.intensity })\n }\n }\n }\n return Array.from(bySlug.entries()).map(([slug, v]) => ({\n slug: slug as Slug,\n color: getHeatmapColor(v.status, v.intensity),\n }))\n}\n\n/** Collapse data into per-simple-group legend entries (summed sets). */\nfunction buildSimpleLegend(data: BodyMapData[]): LegendEntry[] {\n const bySimple = new Map<SimpleMuscleGroup, LegendEntry>()\n for (const d of data) {\n const simple = DETAILED_TO_SIMPLE[d.muscleGroup]\n const existing = bySimple.get(simple)\n if (!existing) {\n bySimple.set(simple, {\n key: simple,\n name: SIMPLE_DISPLAY_NAMES[simple],\n status: d.volumeStatus,\n intensity: d.intensity,\n sets: d.weeklySets,\n muscle: d.muscleGroup,\n })\n continue\n }\n existing.sets += d.weeklySets\n existing.intensity = Math.max(existing.intensity, d.intensity)\n if (isMoreSevere(d.volumeStatus, existing.status)) {\n existing.status = d.volumeStatus\n existing.muscle = d.muscleGroup\n }\n }\n return Array.from(bySimple.values())\n}\n\n/** One legend entry per data row, named by detailed group. */\nfunction buildDetailedLegend(data: BodyMapData[]): LegendEntry[] {\n return data.map((d) => ({\n key: d.muscleGroup,\n name: MUSCLE_DISPLAY_NAMES[d.muscleGroup],\n status: d.volumeStatus,\n intensity: d.intensity,\n sets: d.weeklySets,\n muscle: d.muscleGroup,\n }))\n}\n\n/**\n * Interactive SVG body map with tappable muscle groups and a volume heatmap.\n * Renders the front or back view (toggle via onViewChange), colors each muscle\n * by its weekly-volume status, and exposes an accessible muscle legend wired to\n * onMusclePress. Phase 1 uses react-native-body-highlighter's combined slugs\n * (deltoids as one path, lats/upper-back shared); swipe between views and the\n * delt/lat SVG split are follow-ups.\n *\n * @example\n * <BodyMap\n * data={[{ muscleGroup: MuscleGroup.CHEST, intensity: 0.7, volumeStatus: 'productive', weeklySets: 12 }]}\n * view=\"front\"\n * onViewChange={setView}\n * onMusclePress={setSelected}\n * highlightedMuscle={selected}\n * />\n */\nexport function BodyMap({\n data,\n view,\n onViewChange,\n onMusclePress,\n highlightedMuscle,\n mode = 'detailed',\n className,\n ...props\n}: BodyMapProps) {\n const slugParts = useMemo(() => buildSlugParts(data), [data])\n const legend = useMemo(\n () => (mode === 'simple' ? buildSimpleLegend(data) : buildDetailedLegend(data)),\n [data, mode]\n )\n\n const [highlight] = useState(() => new Animated.Value(highlightedMuscle ? 1 : 0))\n useEffect(() => {\n const animation = Animated.timing(highlight, {\n toValue: highlightedMuscle ? 1 : 0,\n duration: 250,\n easing: Easing.out(Easing.ease),\n useNativeDriver: false,\n })\n animation.start()\n return () => animation.stop()\n }, [highlightedMuscle, highlight])\n\n const scale = highlight.interpolate({ inputRange: [0, 1], outputRange: [1, 1.02] })\n const glowColor = highlightedMuscle\n ? getHeatmapColor(\n data.find((d) => d.muscleGroup === highlightedMuscle)?.volumeStatus,\n data.find((d) => d.muscleGroup === highlightedMuscle)?.intensity ?? 0\n )\n : null\n\n const handleBodyPress = (part: ExtendedBodyPart) => {\n if (!onMusclePress || !part.slug) return\n const fromData = data.find((d) =>\n (MUSCLE_TO_SVG_SLUGS[d.muscleGroup] ?? []).includes(part.slug as string)\n )\n const muscle = fromData?.muscleGroup ?? SLUG_TO_PRIMARY_MUSCLE[part.slug]\n if (muscle) onMusclePress(muscle)\n }\n\n return (\n <View className={cn(className)} testID=\"body-map\" {...props}>\n <ViewToggle view={view} onViewChange={onViewChange} />\n\n <Animated.View\n style={[\n {\n width: 200 * BODY_SCALE,\n alignSelf: 'center',\n transform: [{ scale }],\n },\n glowColor ? { boxShadow: `0 0 14px 2px ${glowColor}` } : undefined,\n ]}\n // The SVG is decorative; the accessible muscle legend below is the\n // screen-reader / keyboard interface.\n aria-hidden\n accessibilityElementsHidden\n importantForAccessibility=\"no-hide-descendants\"\n testID=\"body-map-svg\"\n >\n <Body\n side={view}\n data={slugParts}\n scale={BODY_SCALE}\n gender=\"male\"\n defaultFill={OUTLINE_FILL}\n border={OUTLINE_BORDER}\n onBodyPartPress={handleBodyPress}\n />\n </Animated.View>\n\n {legend.length === 0 ? (\n <Text\n className=\"text-text-secondary\"\n style={{\n marginTop: 8,\n fontSize: 12,\n textAlign: 'center',\n fontFamily: 'Inter, sans-serif',\n }}\n testID=\"body-map-empty\"\n >\n No training data\n </Text>\n ) : (\n <View\n className=\"flex-row flex-wrap\"\n style={{ marginTop: 10, gap: 6, justifyContent: 'center' }}\n testID=\"body-map-legend\"\n >\n {legend.map((entry) => (\n <MuscleButton\n key={entry.key}\n entry={entry}\n highlighted={highlightedMuscle === entry.muscle}\n onMusclePress={onMusclePress}\n />\n ))}\n </View>\n )}\n </View>\n )\n}\n\ninterface ViewToggleProps {\n view: 'front' | 'back'\n onViewChange?: (view: 'front' | 'back') => void\n}\n\nfunction ViewToggle({ view, onViewChange }: ViewToggleProps) {\n return (\n <View\n className=\"flex-row self-center\"\n style={{ gap: 4, marginBottom: 8 }}\n testID=\"body-map-view-toggle\"\n >\n {(['front', 'back'] as const).map((side) => {\n const active = view === side\n return (\n <Pressable\n key={side}\n onPress={() => onViewChange?.(side)}\n accessibilityRole=\"button\"\n accessibilityLabel={`Show ${side} view`}\n aria-pressed={active}\n disabled={!onViewChange}\n style={{\n paddingHorizontal: 12,\n paddingVertical: 4,\n borderRadius: 9999,\n backgroundColor: active ? 'rgba(255,121,0,0.16)' : 'transparent',\n borderWidth: 1,\n borderColor: active ? '#FF7900' : resolveColor('border-strong'),\n }}\n testID={`body-map-toggle-${side}`}\n >\n <Text\n style={{\n fontSize: 12,\n fontFamily: 'Inter, sans-serif',\n fontWeight: active ? '700' : '500',\n color: active ? '#FF7900' : resolveColor('text-secondary'),\n textTransform: 'capitalize',\n }}\n >\n {side}\n </Text>\n </Pressable>\n )\n })}\n </View>\n )\n}\n\ninterface MuscleButtonProps {\n entry: LegendEntry\n highlighted: boolean\n onMusclePress?: (muscleGroup: MuscleGroup) => void\n}\n\nfunction MuscleButton({ entry, highlighted, onMusclePress }: MuscleButtonProps) {\n const dotColor = getHeatmapColor(entry.status, entry.intensity)\n const label = `${entry.name}, ${VOLUME_STATUS_LABELS[entry.status]}, ${entry.sets} sets this week`\n return (\n <Pressable\n onPress={() => onMusclePress?.(entry.muscle)}\n accessibilityRole=\"button\"\n accessibilityLabel={label}\n aria-pressed={highlighted}\n className=\"bg-surface-raised\"\n style={{\n flexDirection: 'row',\n alignItems: 'center',\n gap: 5,\n paddingHorizontal: 8,\n paddingVertical: 3,\n borderRadius: 9999,\n borderWidth: 1,\n borderColor: highlighted ? '#FF7900' : resolveColor('border-default'),\n }}\n testID={`body-map-muscle-${entry.key}`}\n >\n <View\n style={{ width: 7, height: 7, borderRadius: 9999, backgroundColor: dotColor }}\n accessibilityElementsHidden\n testID={`body-map-muscle-dot-${entry.key}`}\n />\n <Text\n className=\"text-text-primary\"\n style={{\n fontSize: 11,\n fontFamily: 'Inter, sans-serif',\n fontWeight: '500',\n }}\n accessibilityElementsHidden\n >\n {entry.name}\n </Text>\n </Pressable>\n )\n}\n","// Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)\nimport { useEffect, useState } from 'react'\nimport {\n View,\n Text,\n Pressable,\n ScrollView,\n Animated,\n Easing,\n type ViewProps,\n type ViewStyle,\n} from 'react-native'\nimport { Badge, type BadgeColor } from '../../ui/badge'\nimport { Sparkline } from './Sparkline'\nimport {\n MuscleGroup,\n VOLUME_STATUS_LABELS,\n type VolumeLandmarks,\n type VolumeStatus,\n} from './muscleTaxonomy'\n\nconst BRAND_PRIMARY = '#FF7900'\n\n/** Volume track gradient: status-info (blue) -> result-improve (teal) -> status-error (red). */\nconst VOLUME_GRADIENT = 'linear-gradient(90deg, #2196F3 0%, #14B8A6 50%, #D14343 100%)'\n\n/** Sheet slides up from this offset (px) and the backdrop fades to this opacity. */\nconst SLIDE_OFFSET = 400\nconst BACKDROP_OPACITY = 0.4\n\n/** Volume status -> Badge color scheme. */\nconst STATUS_BADGE_COLOR: Record<VolumeStatus, BadgeColor> = {\n under: 'info',\n maintenance: 'warning',\n productive: 'success',\n over: 'error',\n}\n\nexport interface ContributingExercise {\n /** Exercise name. */\n name: string\n /** Working sets contributed this week. */\n sets: number\n /** Effective-set multiplier toward this muscle (0-1). */\n contributionWeight: number\n}\n\nexport interface UpcomingExercise {\n /** Exercise name. */\n name: string\n /** Workout the exercise belongs to. */\n workoutName: string\n /** Planned sets. */\n sets: number\n}\n\nexport interface BodyMapDetailPanelProps extends ViewProps {\n /** Muscle group whose volume detail is shown. */\n muscleGroup: MuscleGroup\n /** Human-readable muscle name for the title and a11y label. */\n displayName: string\n /** Weekly effective sets logged for this muscle. */\n weeklySets: number\n /** Volume landmarks (weekly working sets). */\n landmarks: VolumeLandmarks\n /** Weekly-volume status relative to the landmarks. */\n volumeStatus: VolumeStatus\n /** Last trained label, e.g. \"2 days ago\". */\n lastTrained?: string\n /** Volume sparkline data (last 4-8 weeks). */\n weeklyHistory?: number[]\n /** Exercises contributing to this muscle's volume. */\n contributingExercises?: ContributingExercise[]\n /** Upcoming exercises targeting this muscle. */\n upcomingExercises?: UpcomingExercise[]\n /** Whether the bottom sheet is visible. */\n isOpen?: boolean\n /** Alias for `isOpen` (spec wording: \"isOpen/visible\"). `isOpen` wins when both are set. */\n visible?: boolean\n /** Dismiss the panel (backdrop, handle, or close button). */\n onClose: () => void\n /** Navigate to a filtered exercise list. */\n onViewExercises?: () => void\n}\n\nfunction clamp01(value: number): number {\n if (value < 0) return 0\n if (value > 1) return 1\n return value\n}\n\n/** Marker position (0-1) of current sets between MEV (left) and MRV (right). */\nfunction markerFraction(weeklySets: number, { mev, mrv }: VolumeLandmarks): number {\n const span = mrv - mev\n if (span <= 0) return weeklySets >= mrv ? 1 : 0\n return clamp01((weeklySets - mev) / span)\n}\n\n/**\n * Slide-up bottom-sheet panel with detailed weekly-volume info for a tapped\n * muscle group: a MEV|current|MRV gradient progress bar, the big weekly set\n * count against MRV, an optional volume sparkline, and the contributing /\n * upcoming exercise lists. Composes the titan `Badge` and Workout `Sparkline`.\n *\n * Controlled via `isOpen` (or the `visible` alias); renders nothing when closed\n * and animates in on open — sheet translateY 400->0 (400ms ease-out) and a\n * backdrop fade 0->0.4 (RN Animated, useNativeDriver:false). Backdrop, handle,\n * and the header close button all call `onClose`.\n *\n * @example\n * <BodyMapDetailPanel\n * muscleGroup={MuscleGroup.CHEST}\n * displayName=\"Chest\"\n * weeklySets={14}\n * landmarks={{ mev: 8, mav: 14, mrv: 20 }}\n * volumeStatus=\"productive\"\n * lastTrained=\"2 days ago\"\n * weeklyHistory={[8, 10, 12, 14]}\n * isOpen={open}\n * onClose={() => setOpen(false)}\n * />\n */\nexport function BodyMapDetailPanel({\n muscleGroup,\n displayName,\n weeklySets,\n landmarks,\n volumeStatus,\n lastTrained,\n weeklyHistory,\n contributingExercises,\n upcomingExercises,\n isOpen,\n visible,\n onClose,\n onViewExercises,\n ...props\n}: BodyMapDetailPanelProps) {\n const open = isOpen ?? visible ?? false\n\n const [translateY] = useState(() => new Animated.Value(SLIDE_OFFSET))\n const [backdrop] = useState(() => new Animated.Value(0))\n\n useEffect(() => {\n if (!open) return\n const animation = Animated.parallel([\n Animated.timing(translateY, {\n toValue: 0,\n duration: 400,\n easing: Easing.out(Easing.ease),\n useNativeDriver: false,\n }),\n Animated.timing(backdrop, {\n toValue: BACKDROP_OPACITY,\n duration: 300,\n easing: Easing.out(Easing.ease),\n useNativeDriver: false,\n }),\n ])\n animation.start()\n return () => animation.stop()\n }, [open, translateY, backdrop])\n\n if (!open) return null\n\n const dialogLabel = `${displayName} volume details`\n const markerLeft = markerFraction(weeklySets, landmarks) * 100\n const hasContributing = (contributingExercises?.length ?? 0) > 0\n const hasUpcoming = (upcomingExercises?.length ?? 0) > 0\n\n return (\n <View\n style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, justifyContent: 'flex-end' }}\n testID=\"body-map-detail-panel-root\"\n >\n <Animated.View\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundColor: '#000000',\n opacity: backdrop,\n }}\n testID=\"body-map-detail-panel-backdrop-anim\"\n >\n <Pressable\n onPress={onClose}\n accessibilityRole=\"button\"\n accessibilityLabel={`Close ${displayName} details`}\n style={{ flex: 1 }}\n testID=\"body-map-detail-panel-backdrop\"\n />\n </Animated.View>\n\n <Animated.View\n accessibilityRole={'dialog' as ViewProps['accessibilityRole']}\n accessibilityLabel={dialogLabel}\n aria-label={dialogLabel}\n className=\"bg-surface-elevated\"\n style={{\n borderTopLeftRadius: 16,\n borderTopRightRadius: 16,\n maxHeight: '88%',\n transform: [{ translateY }],\n }}\n testID=\"body-map-detail-panel\"\n {...props}\n >\n <Pressable\n onPress={onClose}\n accessibilityRole=\"button\"\n accessibilityLabel={`Close ${displayName} details`}\n hitSlop={12}\n style={{ alignSelf: 'center', paddingVertical: 8 }}\n testID=\"body-map-detail-panel-handle\"\n >\n <View\n className=\"bg-border-strong\"\n style={{ width: 40, height: 4, borderRadius: 2 }}\n accessibilityElementsHidden\n />\n </Pressable>\n\n <ScrollView\n style={{ paddingHorizontal: 16 }}\n contentContainerStyle={{ paddingBottom: 20 }}\n testID=\"body-map-detail-panel-scroll\"\n >\n <View\n className=\"flex-row items-center justify-between\"\n style={{ gap: 8, paddingTop: 4, paddingBottom: 4 }}\n testID=\"body-map-detail-panel-header\"\n >\n <View className=\"flex-row items-center\" style={{ gap: 8, flexShrink: 1 }}>\n <Text\n accessibilityRole=\"header\"\n className=\"text-text-primary\"\n style={{\n fontSize: 16,\n fontFamily: '\"Space Grotesk\", sans-serif',\n fontWeight: '700',\n }}\n testID=\"body-map-detail-panel-title\"\n >\n {displayName}\n </Text>\n <Badge\n variant=\"subtle\"\n color={STATUS_BADGE_COLOR[volumeStatus]}\n size=\"sm\"\n testID=\"body-map-detail-panel-status-badge\"\n >\n {VOLUME_STATUS_LABELS[volumeStatus]}\n </Badge>\n </View>\n <Pressable\n onPress={onClose}\n accessibilityRole=\"button\"\n accessibilityLabel={`Close ${displayName} details`}\n hitSlop={8}\n style={{ padding: 4, margin: -4 }}\n testID=\"body-map-detail-panel-close\"\n >\n <Text className=\"text-text-secondary\" style={{ fontSize: 22, lineHeight: 22 }}>{'×'}</Text>\n </Pressable>\n </View>\n\n {lastTrained != null && (\n <Text\n className=\"text-text-secondary\"\n style={{ fontSize: 12, fontFamily: 'Inter, sans-serif' }}\n testID=\"body-map-detail-panel-last-trained\"\n >\n {`Last trained ${lastTrained}`}\n </Text>\n )}\n\n <View style={{ marginTop: 16 }} testID=\"body-map-detail-panel-volume\">\n <View\n className=\"flex-row items-center justify-between\"\n style={{ marginBottom: 6 }}\n accessibilityElementsHidden\n >\n <Text className=\"text-text-tertiary\" style={{ fontSize: 10, fontFamily: 'Inter, sans-serif', fontWeight: '600' }}>\n {`MEV ${landmarks.mev}`}\n </Text>\n <Text className=\"text-text-tertiary\" style={{ fontSize: 10, fontFamily: 'Inter, sans-serif', fontWeight: '600' }}>\n {`MRV ${landmarks.mrv}`}\n </Text>\n </View>\n <View\n style={{ height: 14, justifyContent: 'center' }}\n accessibilityRole=\"progressbar\"\n accessibilityValue={{ min: landmarks.mev, max: landmarks.mrv, now: weeklySets }}\n accessibilityLabel={`${weeklySets} weekly sets, between MEV ${landmarks.mev} and MRV ${landmarks.mrv}`}\n aria-valuenow={weeklySets}\n aria-valuemin={landmarks.mev}\n aria-valuemax={landmarks.mrv}\n testID=\"body-map-detail-panel-volume-bar\"\n >\n <View\n style={{ height: 8, borderRadius: 4, backgroundImage: VOLUME_GRADIENT } as ViewStyle}\n accessibilityElementsHidden\n />\n <View\n className=\"border-text-primary bg-surface-elevated\"\n style={{\n position: 'absolute',\n left: `${markerLeft}%`,\n marginLeft: -7,\n width: 14,\n height: 14,\n borderRadius: 7,\n borderWidth: 2,\n boxShadow: '0 0 4px rgba(0,0,0,0.5)',\n }}\n accessibilityElementsHidden\n testID=\"body-map-detail-panel-volume-marker\"\n />\n </View>\n </View>\n\n <View className=\"flex-row items-baseline\" style={{ marginTop: 14, gap: 4 }}>\n <Text\n className=\"text-text-primary\"\n style={{\n fontSize: 24,\n fontFamily: '\"Space Grotesk\", sans-serif',\n fontWeight: '700',\n }}\n testID=\"body-map-detail-panel-set-count\"\n >\n {weeklySets}\n </Text>\n <Text\n className=\"text-text-secondary\"\n style={{ fontSize: 12, fontFamily: 'Inter, sans-serif' }}\n testID=\"body-map-detail-panel-mrv-suffix\"\n >\n {`/ ${landmarks.mrv} MRV`}\n </Text>\n </View>\n\n {weeklyHistory != null && weeklyHistory.length > 0 && (\n <View style={{ marginTop: 14 }} testID=\"body-map-detail-panel-sparkline\">\n <Text\n className=\"text-text-tertiary\"\n style={{\n fontSize: 10,\n fontFamily: 'Inter, sans-serif',\n fontWeight: '600',\n marginBottom: 6,\n }}\n accessibilityElementsHidden\n >\n {'VOLUME TREND'}\n </Text>\n <Sparkline data={weeklyHistory} width={80} height={30} highlightLast />\n </View>\n )}\n\n {hasContributing && (\n <View style={{ marginTop: 16 }} testID=\"body-map-detail-panel-contributing\">\n <Text\n className=\"text-text-tertiary\"\n style={{\n fontSize: 10,\n fontFamily: 'Inter, sans-serif',\n fontWeight: '600',\n marginBottom: 8,\n }}\n >\n {'CONTRIBUTING EXERCISES'}\n </Text>\n {contributingExercises!.map((exercise, index) => (\n <View\n key={`${exercise.name}-${index}`}\n className=\"flex-row items-center justify-between bg-surface-raised border-border\"\n style={{\n gap: 10,\n paddingVertical: 8,\n paddingHorizontal: 12,\n marginBottom: 6,\n borderRadius: 8,\n borderWidth: 1,\n }}\n testID={`body-map-detail-panel-contributing-${index}`}\n >\n <Text\n className=\"text-text-primary\"\n style={{ flex: 1, fontSize: 13, fontFamily: 'Inter, sans-serif', fontWeight: '600' }}\n testID={`body-map-detail-panel-contributing-${index}-name`}\n >\n {exercise.name}\n </Text>\n <Text\n className=\"text-text-secondary\"\n style={{ fontSize: 12, fontFamily: 'Inter, sans-serif' }}\n testID={`body-map-detail-panel-contributing-${index}-detail`}\n >\n {`${exercise.sets} sets · ${Math.round(exercise.contributionWeight * 100)}%`}\n </Text>\n </View>\n ))}\n </View>\n )}\n\n {hasUpcoming && (\n <View style={{ marginTop: 16 }} testID=\"body-map-detail-panel-upcoming\">\n <Text\n className=\"text-text-tertiary\"\n style={{\n fontSize: 10,\n fontFamily: 'Inter, sans-serif',\n fontWeight: '600',\n marginBottom: 8,\n }}\n >\n {'UPCOMING'}\n </Text>\n {upcomingExercises!.map((exercise, index) => (\n <View\n key={`${exercise.name}-${index}`}\n className=\"flex-row items-center justify-between\"\n style={{ gap: 10, paddingVertical: 6 }}\n testID={`body-map-detail-panel-upcoming-${index}`}\n >\n <Text\n className=\"text-text-primary\"\n style={{ flex: 1, fontSize: 13, fontFamily: 'Inter, sans-serif', fontWeight: '600' }}\n testID={`body-map-detail-panel-upcoming-${index}-name`}\n >\n {exercise.name}\n </Text>\n <Text\n className=\"text-text-tertiary\"\n style={{ fontSize: 12, fontFamily: 'Inter, sans-serif' }}\n testID={`body-map-detail-panel-upcoming-${index}-detail`}\n >\n {`${exercise.workoutName} · ${exercise.sets} sets`}\n </Text>\n </View>\n ))}\n </View>\n )}\n\n {onViewExercises != null && (\n <Pressable\n onPress={onViewExercises}\n accessibilityRole=\"button\"\n accessibilityLabel={`View ${displayName} exercises`}\n style={{\n marginTop: 16,\n paddingVertical: 10,\n borderRadius: 8,\n alignItems: 'center',\n backgroundColor: 'rgba(255,121,0,0.12)',\n borderWidth: 1,\n borderColor: 'rgba(255,121,0,0.3)',\n }}\n testID=\"body-map-detail-panel-view-exercises\"\n >\n <Text style={{ fontSize: 13, fontFamily: 'Inter, sans-serif', fontWeight: '700', color: BRAND_PRIMARY }}>\n {'View exercises'}\n </Text>\n </Pressable>\n )}\n </ScrollView>\n </Animated.View>\n </View>\n )\n}\n","// Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)\nimport { useMemo, useState } from 'react'\nimport { View, Text, type ViewProps } from 'react-native'\nimport { BodyMap, type BodyMapData } from './BodyMap'\nimport {\n BodyMapDetailPanel,\n type ContributingExercise,\n type UpcomingExercise,\n} from './BodyMapDetailPanel'\nimport { MesoStatusCard, type MesoStatusCardProps } from './MesoStatusCard'\nimport {\n MuscleGroup,\n VOLUME_STATUS_LABELS,\n getHeatmapColor,\n type VolumeLandmarks,\n type VolumeStatus,\n} from './muscleTaxonomy'\n\n/** Volume statuses in display order for the legend and summary cards. */\nconst STATUS_ORDER: VolumeStatus[] = ['under', 'maintenance', 'productive', 'over']\n\n/** One muscle's full volume picture — feeds the body maps and the detail panel. */\nexport interface TrainingStatusMuscle {\n /** Detailed muscle group (drives the SVG heatmap + panel identity). */\n muscleGroup: MuscleGroup\n /** Human-readable name for the legend, summary, and panel title. */\n displayName: string\n /** Which body-map view the muscle belongs to. */\n side: 'front' | 'back'\n /** Heatmap intensity 0-1. */\n intensity: number\n /** Weekly-volume status relative to the landmarks. */\n volumeStatus: VolumeStatus\n /** Weekly effective sets logged. */\n weeklySets: number\n /** Volume landmarks (weekly working sets). */\n landmarks: VolumeLandmarks\n /** Last trained label, e.g. \"2 days ago\". */\n lastTrained?: string\n /** Weekly volume history for the panel sparkline. */\n weeklyHistory?: number[]\n /** Exercises contributing to this muscle's volume. */\n contributingExercises?: ContributingExercise[]\n /** Upcoming exercises targeting this muscle. */\n upcomingExercises?: UpcomingExercise[]\n}\n\n/** Derived, page-level roll-up of the tracked muscles. */\nexport interface TrainingStatusSummary {\n /** Total weekly effective sets across all tracked muscles. */\n totalWeeklySets: number\n /** Number of muscles being tracked. */\n trackedMuscles: number\n /** Count of muscles per volume status. */\n statusCounts: Record<VolumeStatus, number>\n}\n\nexport interface TrainingStatusPageProps extends ViewProps {\n /** Page heading. */\n title?: string\n /** Mesocycle context banner shown at the top. */\n meso: MesoStatusCardProps\n /** Muscles tracked this week. */\n muscles: TrainingStatusMuscle[]\n className?: string\n}\n\n/** Roll up per-muscle rows into the page summary (pure, testable). */\nexport function deriveTrainingSummary(muscles: TrainingStatusMuscle[]): TrainingStatusSummary {\n const statusCounts: Record<VolumeStatus, number> = {\n under: 0,\n maintenance: 0,\n productive: 0,\n over: 0,\n }\n let totalWeeklySets = 0\n for (const muscle of muscles) {\n totalWeeklySets += muscle.weeklySets\n statusCounts[muscle.volumeStatus] += 1\n }\n return { totalWeeklySets, trackedMuscles: muscles.length, statusCounts }\n}\n\n/** Project the muscle rows for one side into `BodyMap` heatmap data. */\nexport function toBodyMapData(\n muscles: TrainingStatusMuscle[],\n side: 'front' | 'back'\n): BodyMapData[] {\n return muscles\n .filter((muscle) => muscle.side === side)\n .map(({ muscleGroup, intensity, volumeStatus, weeklySets }) => ({\n muscleGroup,\n intensity,\n volumeStatus,\n weeklySets,\n }))\n}\n\nconst SUMMARY_CARDS: Array<{\n key: keyof TrainingStatusSummary['statusCounts'] | 'total'\n label: string\n}> = [\n { key: 'total', label: 'Weekly Sets' },\n { key: 'productive', label: 'Productive' },\n { key: 'under', label: 'Under' },\n { key: 'over', label: 'Over' },\n]\n\nfunction SummaryCards({ summary }: { summary: TrainingStatusSummary }) {\n return (\n <View className=\"flex-row flex-wrap\" style={{ gap: 8 }} testID=\"training-status-page-summary\">\n {SUMMARY_CARDS.map(({ key, label }) => {\n const value = key === 'total' ? summary.totalWeeklySets : summary.statusCounts[key]\n return (\n <View\n key={key}\n className=\"bg-surface-elevated border-border\"\n style={{\n flexGrow: 1,\n flexBasis: '46%',\n padding: 12,\n borderRadius: 10,\n borderWidth: 1,\n }}\n testID={`training-status-page-summary-${key}`}\n >\n <Text\n className=\"text-text-primary\"\n style={{\n fontSize: 22,\n fontFamily: '\"Space Grotesk\", sans-serif',\n fontWeight: '700',\n }}\n >\n {value}\n </Text>\n <Text\n className=\"text-text-tertiary\"\n style={{\n marginTop: 2,\n fontSize: 11,\n fontFamily: 'Inter, sans-serif',\n fontWeight: '600',\n letterSpacing: 0.4,\n textTransform: 'uppercase',\n }}\n >\n {label}\n </Text>\n </View>\n )\n })}\n </View>\n )\n}\n\nfunction StatusLegend() {\n return (\n <View\n className=\"flex-row flex-wrap\"\n style={{ gap: 10, justifyContent: 'center' }}\n testID=\"training-status-page-legend\"\n >\n {STATUS_ORDER.map((status) => (\n <View\n key={status}\n className=\"flex-row items-center\"\n style={{ gap: 5 }}\n testID={`training-status-page-legend-${status}`}\n >\n <View\n style={{\n width: 8,\n height: 8,\n borderRadius: 9999,\n backgroundColor: getHeatmapColor(status, 0.6),\n }}\n accessibilityElementsHidden\n />\n <Text\n className=\"text-text-secondary\"\n style={{\n fontSize: 11,\n fontFamily: 'Inter, sans-serif',\n textTransform: 'capitalize',\n }}\n >\n {VOLUME_STATUS_LABELS[status]}\n </Text>\n </View>\n ))}\n </View>\n )\n}\n\ninterface BodyMapColumnProps {\n side: 'front' | 'back'\n muscles: TrainingStatusMuscle[]\n selected: MuscleGroup | null\n onSelect: (muscle: MuscleGroup) => void\n}\n\nfunction BodyMapColumn({ side, muscles, selected, onSelect }: BodyMapColumnProps) {\n const data = useMemo(() => toBodyMapData(muscles, side), [muscles, side])\n return (\n <View style={{ flexGrow: 1, flexBasis: '46%' }} testID={`training-status-page-bodymap-${side}`}>\n <BodyMap\n data={data}\n view={side}\n onMusclePress={onSelect}\n highlightedMuscle={selected}\n mode=\"detailed\"\n />\n </View>\n )\n}\n\n/**\n * TrainingStatusPage — a body-map training dashboard that composes the\n * mesocycle context banner (`MesoStatusCard`), side-by-side front/back\n * `BodyMap`s with a shared heatmap legend, per-status summary cards, and a\n * tap-to-detail `BodyMapDetailPanel`. Tapping any muscle (SVG or legend chip)\n * opens the slide-up panel for that group; the summary is derived from the\n * supplied muscle rows.\n *\n * @example\n * <TrainingStatusPage meso={meso} muscles={muscles} />\n */\nexport function TrainingStatusPage({\n title = 'Training Status',\n meso,\n muscles,\n className,\n ...props\n}: TrainingStatusPageProps) {\n const [selected, setSelected] = useState<MuscleGroup | null>(null)\n const summary = useMemo(() => deriveTrainingSummary(muscles), [muscles])\n const active = selected != null ? (muscles.find((m) => m.muscleGroup === selected) ?? null) : null\n\n return (\n <View\n className={['bg-background-base', className].filter(Boolean).join(' ')}\n style={{ position: 'relative', width: 390 }}\n accessibilityRole={'main' as ViewProps['accessibilityRole']}\n aria-label={title}\n testID=\"training-status-page\"\n {...props}\n >\n <View style={{ padding: 16, gap: 16 }} testID=\"training-status-page-content\">\n <Text\n accessibilityRole=\"header\"\n className=\"text-text-primary\"\n style={{\n fontSize: 20,\n fontFamily: '\"Space Grotesk\", sans-serif',\n fontWeight: '700',\n }}\n testID=\"training-status-page-title\"\n >\n {title}\n </Text>\n\n <MesoStatusCard {...meso} />\n\n <SummaryCards summary={summary} />\n\n <View\n className=\"bg-surface-elevated border-border\"\n style={{\n borderWidth: 1,\n borderRadius: 12,\n padding: 12,\n gap: 12,\n }}\n testID=\"training-status-page-bodymaps\"\n >\n <View className=\"flex-row\" style={{ gap: 8 }}>\n <BodyMapColumn\n side=\"front\"\n muscles={muscles}\n selected={selected}\n onSelect={setSelected}\n />\n <BodyMapColumn\n side=\"back\"\n muscles={muscles}\n selected={selected}\n onSelect={setSelected}\n />\n </View>\n <StatusLegend />\n </View>\n </View>\n\n {active != null && (\n <BodyMapDetailPanel\n muscleGroup={active.muscleGroup}\n displayName={active.displayName}\n weeklySets={active.weeklySets}\n landmarks={active.landmarks}\n volumeStatus={active.volumeStatus}\n lastTrained={active.lastTrained}\n weeklyHistory={active.weeklyHistory}\n contributingExercises={active.contributingExercises}\n upcomingExercises={active.upcomingExercises}\n isOpen\n onClose={() => setSelected(null)}\n />\n )}\n </View>\n )\n}\n"]}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import { getValidatedElevation, getBaseSurfaceColor, getElevationSurface, getElevationShadow } from './chunk-
|
|
1
|
+
import { resolveColor, getValidatedElevation, getBaseSurfaceColor, getElevationSurface, getElevationShadow, jsxs, Fragment, jsx } from './chunk-SNVKL5WZ.mjs';
|
|
2
2
|
import { clsx } from 'clsx';
|
|
3
3
|
import { twMerge } from 'tailwind-merge';
|
|
4
4
|
import { useState, useMemo, useSyncExternalStore, Fragment as Fragment$1 } from 'react';
|
|
5
5
|
import { View, Pressable, Text } from 'react-native';
|
|
6
|
-
import { Fragment, jsx as jsx$1, jsxs as jsxs$1 } from 'react/jsx-runtime';
|
|
7
|
-
export { Fragment } from 'react/jsx-runtime';
|
|
8
6
|
|
|
9
7
|
function cn(...inputs) {
|
|
10
8
|
return twMerge(clsx(inputs));
|
|
@@ -47,23 +45,6 @@ function getServerSnapshot() {
|
|
|
47
45
|
function useTheme() {
|
|
48
46
|
return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
49
47
|
}
|
|
50
|
-
function wrapJsx(fn) {
|
|
51
|
-
return function(type, props, ...rest) {
|
|
52
|
-
if (props && typeof props.className === "string" && props.className) {
|
|
53
|
-
const cn2 = props.className;
|
|
54
|
-
const cssStyle = { $$css: true, [cn2]: cn2 };
|
|
55
|
-
const existing = props.style;
|
|
56
|
-
props = {
|
|
57
|
-
...props,
|
|
58
|
-
style: existing ? [cssStyle, existing] : cssStyle
|
|
59
|
-
};
|
|
60
|
-
delete props.className;
|
|
61
|
-
}
|
|
62
|
-
return fn(type, props, ...rest);
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
var jsx = wrapJsx(jsx$1);
|
|
66
|
-
var jsxs = wrapJsx(jsxs$1);
|
|
67
48
|
|
|
68
49
|
// src/components/ui/card/Card.tsx
|
|
69
50
|
var variantStyles = {
|
|
@@ -625,14 +606,11 @@ function Sparkline({
|
|
|
625
606
|
var BRAND_PRIMARY2 = "#FF7900";
|
|
626
607
|
var BRAND_PRIMARY_DARK = "#C45E00";
|
|
627
608
|
var BRAND_PRIMARY_LIGHT = "#FFB066";
|
|
628
|
-
var TEXT_PRIMARY = "var(--color-text-primary)";
|
|
629
|
-
var TEXT_SECONDARY = "var(--color-text-secondary)";
|
|
630
|
-
var TEXT_TERTIARY = "var(--color-text-tertiary)";
|
|
631
609
|
var SUCCESS = "#14B8A6";
|
|
632
610
|
var WARNING = "#FFB020";
|
|
633
611
|
var ERROR = "#D14343";
|
|
634
612
|
var ACCENT_STOPS = [BRAND_PRIMARY_DARK, BRAND_PRIMARY2, BRAND_PRIMARY_LIGHT];
|
|
635
|
-
var CARD_GRADIENT =
|
|
613
|
+
var CARD_GRADIENT = `linear-gradient(135deg, ${resolveColor("surface-elevated")} 0%, ${resolveColor("surface-raised")} 100%)`;
|
|
636
614
|
var GAUGE_GRADIENT = "linear-gradient(90deg, rgba(20,184,166,0.25) 0%, rgba(255,176,32,0.25) 50%, rgba(209,67,67,0.25) 100%)";
|
|
637
615
|
var STATUS_VARIANTS = {
|
|
638
616
|
success: { bg: "rgba(20,184,166,0.15)", border: "rgba(20,184,166,0.3)", text: SUCCESS },
|
|
@@ -659,7 +637,8 @@ function renderCoachingText(text, highlights) {
|
|
|
659
637
|
(part, index) => highlights.includes(part) ? /* @__PURE__ */ jsx(
|
|
660
638
|
Text,
|
|
661
639
|
{
|
|
662
|
-
|
|
640
|
+
className: "text-text-primary",
|
|
641
|
+
style: { fontWeight: "700" },
|
|
663
642
|
children: part
|
|
664
643
|
},
|
|
665
644
|
`${part}-${index}`
|
|
@@ -706,13 +685,13 @@ function MetricCell({ metric }) {
|
|
|
706
685
|
/* @__PURE__ */ jsx(
|
|
707
686
|
Text,
|
|
708
687
|
{
|
|
688
|
+
className: "text-text-tertiary",
|
|
709
689
|
style: {
|
|
710
690
|
fontSize: 10,
|
|
711
691
|
fontFamily: "Inter, sans-serif",
|
|
712
692
|
fontWeight: "600",
|
|
713
693
|
letterSpacing: 0.5,
|
|
714
|
-
textTransform: "uppercase"
|
|
715
|
-
color: TEXT_TERTIARY
|
|
694
|
+
textTransform: "uppercase"
|
|
716
695
|
},
|
|
717
696
|
children: metric.label
|
|
718
697
|
}
|
|
@@ -720,12 +699,12 @@ function MetricCell({ metric }) {
|
|
|
720
699
|
/* @__PURE__ */ jsx(
|
|
721
700
|
Text,
|
|
722
701
|
{
|
|
702
|
+
className: "text-text-primary",
|
|
723
703
|
style: {
|
|
724
704
|
marginTop: 2,
|
|
725
705
|
fontSize: 13,
|
|
726
706
|
fontFamily: "Inter, sans-serif",
|
|
727
|
-
fontWeight: "600"
|
|
728
|
-
color: TEXT_PRIMARY
|
|
707
|
+
fontWeight: "600"
|
|
729
708
|
},
|
|
730
709
|
children: metric.value
|
|
731
710
|
}
|
|
@@ -757,13 +736,13 @@ function Gauge({ gauge }) {
|
|
|
757
736
|
/* @__PURE__ */ jsx(
|
|
758
737
|
Text,
|
|
759
738
|
{
|
|
739
|
+
className: "text-text-secondary",
|
|
760
740
|
style: {
|
|
761
741
|
fontSize: 10,
|
|
762
742
|
fontFamily: "Inter, sans-serif",
|
|
763
743
|
fontWeight: "500",
|
|
764
744
|
letterSpacing: 0.5,
|
|
765
|
-
textTransform: "uppercase"
|
|
766
|
-
color: TEXT_SECONDARY
|
|
745
|
+
textTransform: "uppercase"
|
|
767
746
|
},
|
|
768
747
|
children: gauge.label
|
|
769
748
|
}
|
|
@@ -771,11 +750,11 @@ function Gauge({ gauge }) {
|
|
|
771
750
|
gauge.sublabel != null && /* @__PURE__ */ jsx(
|
|
772
751
|
Text,
|
|
773
752
|
{
|
|
753
|
+
className: "text-text-tertiary",
|
|
774
754
|
style: {
|
|
775
755
|
fontSize: 10,
|
|
776
756
|
fontFamily: "Inter, sans-serif",
|
|
777
|
-
fontWeight: "500"
|
|
778
|
-
color: TEXT_TERTIARY
|
|
757
|
+
fontWeight: "500"
|
|
779
758
|
},
|
|
780
759
|
children: gauge.sublabel
|
|
781
760
|
}
|
|
@@ -812,6 +791,7 @@ function Gauge({ gauge }) {
|
|
|
812
791
|
/* @__PURE__ */ jsx(
|
|
813
792
|
View,
|
|
814
793
|
{
|
|
794
|
+
className: "border-text-primary",
|
|
815
795
|
style: {
|
|
816
796
|
position: "absolute",
|
|
817
797
|
left: `${percentage}%`,
|
|
@@ -821,7 +801,6 @@ function Gauge({ gauge }) {
|
|
|
821
801
|
height: 14,
|
|
822
802
|
borderRadius: 9999,
|
|
823
803
|
borderWidth: 2,
|
|
824
|
-
borderColor: TEXT_PRIMARY,
|
|
825
804
|
backgroundColor: markerColor,
|
|
826
805
|
boxShadow: "0 0 4px rgba(0,0,0,0.5)"
|
|
827
806
|
},
|
|
@@ -884,12 +863,12 @@ function MesoStatusCard({
|
|
|
884
863
|
/* @__PURE__ */ jsx(
|
|
885
864
|
Text,
|
|
886
865
|
{
|
|
866
|
+
className: "text-text-primary",
|
|
887
867
|
style: {
|
|
888
868
|
flexShrink: 1,
|
|
889
869
|
fontSize: 15,
|
|
890
870
|
fontFamily: '"Space Grotesk", sans-serif',
|
|
891
|
-
fontWeight: "700"
|
|
892
|
-
color: TEXT_PRIMARY
|
|
871
|
+
fontWeight: "700"
|
|
893
872
|
},
|
|
894
873
|
testID: "meso-status-card-name",
|
|
895
874
|
children: mesoName
|
|
@@ -902,11 +881,11 @@ function MesoStatusCard({
|
|
|
902
881
|
/* @__PURE__ */ jsx(
|
|
903
882
|
Text,
|
|
904
883
|
{
|
|
884
|
+
className: "text-text-secondary",
|
|
905
885
|
style: {
|
|
906
886
|
marginTop: 4,
|
|
907
887
|
fontSize: 12,
|
|
908
|
-
fontFamily: "Inter, sans-serif"
|
|
909
|
-
color: TEXT_SECONDARY
|
|
888
|
+
fontFamily: "Inter, sans-serif"
|
|
910
889
|
},
|
|
911
890
|
testID: "meso-status-card-subtitle",
|
|
912
891
|
children: mesoSubtitle
|
|
@@ -938,11 +917,11 @@ function MesoStatusCard({
|
|
|
938
917
|
children: /* @__PURE__ */ jsx(
|
|
939
918
|
Text,
|
|
940
919
|
{
|
|
920
|
+
className: "text-text-secondary",
|
|
941
921
|
style: {
|
|
942
922
|
fontSize: 12,
|
|
943
923
|
lineHeight: 17,
|
|
944
|
-
fontFamily: "Inter, sans-serif"
|
|
945
|
-
color: TEXT_SECONDARY
|
|
924
|
+
fontFamily: "Inter, sans-serif"
|
|
946
925
|
},
|
|
947
926
|
children: renderCoachingText(coaching.text, coaching.highlights)
|
|
948
927
|
}
|
|
@@ -1043,6 +1022,6 @@ var WORKOUT_TOKENS = {
|
|
|
1043
1022
|
}
|
|
1044
1023
|
};
|
|
1045
1024
|
|
|
1046
|
-
export { Badge, BadgeText, Card, CardContent, CardDescription, CardFooter, CardHeader, CardSkeleton, CardTitle, Indicator, MesoStatusCard, Sparkline, StatusDot, WORKOUT_TOKENS, cn
|
|
1047
|
-
//# sourceMappingURL=chunk-
|
|
1048
|
-
//# sourceMappingURL=chunk-
|
|
1025
|
+
export { Badge, BadgeText, Card, CardContent, CardDescription, CardFooter, CardHeader, CardSkeleton, CardTitle, Indicator, MesoStatusCard, Sparkline, StatusDot, WORKOUT_TOKENS, cn };
|
|
1026
|
+
//# sourceMappingURL=chunk-2SISKTWM.mjs.map
|
|
1027
|
+
//# sourceMappingURL=chunk-2SISKTWM.mjs.map
|