@titan-design/react-ui 0.4.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.
- package/dist/MesoStatusCard-CQk71hSi.d.mts +77 -0
- package/dist/MesoStatusCard-CQk71hSi.d.ts +77 -0
- package/dist/bodymap.d.mts +246 -3
- package/dist/bodymap.d.ts +246 -3
- package/dist/bodymap.mjs +1911 -6
- package/dist/bodymap.mjs.map +1 -1
- package/dist/index.d.mts +31 -738
- package/dist/index.d.ts +31 -738
- package/dist/index.js +894 -1692
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +10287 -8203
- package/dist/index.mjs.map +1 -1
- package/dist/pages-D7Jlssvp.d.ts +791 -0
- package/dist/pages-MO0JCySL.d.mts +791 -0
- package/dist/pages.d.mts +4 -0
- package/dist/pages.d.ts +4 -0
- package/dist/pages.js +6646 -0
- package/dist/pages.js.map +1 -0
- package/dist/pages.mjs +6626 -0
- package/dist/pages.mjs.map +1 -0
- package/dist/theme/index.d.mts +12 -12
- package/dist/theme/index.d.ts +12 -12
- package/dist/theme/index.js +30 -30
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/index.mjs +1880 -2
- package/dist/theme/index.mjs.map +1 -1
- package/dist/theme/tokens-css.mjs +573 -1
- package/dist/theme/tokens-css.mjs.map +1 -1
- package/package.json +9 -7
- package/src/components/custom/Workout/BaseBadge.stories.tsx +3 -3
- package/src/components/custom/Workout/BaseBadge.test.tsx +1 -1
- package/src/components/custom/Workout/BaseBadge.tsx +1 -1
- package/src/components/custom/Workout/ExerciseCard.tsx +5 -1
- package/src/components/custom/Workout/ExerciseDetailPage.tsx +17 -4
- package/src/components/custom/Workout/IntensityBar.test.tsx +112 -60
- package/src/components/custom/Workout/IntensityBar.tsx +109 -58
- package/src/components/custom/Workout/PlaceholderStrip.tsx +5 -9
- package/src/components/custom/Workout/PrBadge.tsx +3 -3
- package/src/components/custom/Workout/PrHistoryModal.tsx +2 -2
- package/src/components/custom/Workout/README.md +50 -0
- package/src/components/custom/Workout/RestTimer.test.tsx +41 -10
- package/src/components/custom/Workout/RestTimer.tsx +48 -43
- package/src/components/custom/Workout/SetRow.tsx +10 -1
- package/src/components/custom/Workout/TempoDisplay.stories.tsx +69 -2
- package/src/components/custom/Workout/TempoDisplay.test.tsx +35 -0
- package/src/components/custom/Workout/TempoDisplay.tsx +104 -1
- package/src/components/custom/Workout/VelocityStrip.test.tsx +89 -2
- package/src/components/custom/Workout/VelocityStrip.tsx +203 -38
- package/src/components/custom/Workout/WeekRow.test.tsx +2 -2
- package/src/components/custom/Workout/WeightBadge.test.tsx +2 -2
- package/src/components/custom/Workout/WeightBadge.tsx +2 -2
- package/src/components/custom/Workout/icons.tsx +68 -0
- package/src/components/custom/Workout/index.ts +38 -47
- package/src/index.ts +3 -2
- package/src/pages.ts +61 -0
- package/src/test/stories-smoke.test.tsx +50 -0
- package/src/theme/barrel.ts +53 -0
- package/src/theme/index.ts +8 -43
- package/src/theme/native-theming-guard.test.ts +117 -0
- package/dist/bodymap-BhG55xHM.d.mts +0 -318
- package/dist/bodymap-BhG55xHM.d.ts +0 -318
- package/dist/chunk-2SISKTWM.mjs +0 -1027
- package/dist/chunk-2SISKTWM.mjs.map +0 -1
- package/dist/chunk-7XPB4NAO.mjs +0 -1013
- package/dist/chunk-7XPB4NAO.mjs.map +0 -1
- package/dist/chunk-SNVKL5WZ.mjs +0 -883
- package/dist/chunk-SNVKL5WZ.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 };
|
package/dist/bodymap.d.mts
CHANGED
|
@@ -1,3 +1,246 @@
|
|
|
1
|
-
|
|
2
|
-
import 'react
|
|
3
|
-
import '
|
|
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
|
-
|
|
2
|
-
import 'react
|
|
3
|
-
import '
|
|
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 };
|