@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
|
@@ -2,15 +2,14 @@
|
|
|
2
2
|
import { View, Text, Pressable, type ViewProps } from 'react-native'
|
|
3
3
|
import { Star } from 'lucide-react'
|
|
4
4
|
import { Drawer, DrawerBody } from '../../ui/drawer'
|
|
5
|
+
import { resolveColor } from '../../../theme/resolve-color'
|
|
5
6
|
|
|
6
7
|
const BRAND_PRIMARY = '#FF7900'
|
|
7
8
|
const RECENT_BORDER = 'rgba(255,176,32,0.3)'
|
|
8
9
|
const RECENT_GLOW = '0 0 12px rgba(255,176,32,0.06)'
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
const TEXT_SECONDARY = 'var(--color-text-secondary)'
|
|
13
|
-
const TEXT_TERTIARY = 'var(--color-text-tertiary)'
|
|
10
|
+
// Native-safe fallback for the conditional row border (recent uses a computed
|
|
11
|
+
// rgba, so className can't express both branches).
|
|
12
|
+
const BORDER_DEFAULT = resolveColor('border-default')
|
|
14
13
|
|
|
15
14
|
export type PrRecordType = 'e1rm' | 'weight' | 'reps' | 'volume' | 'velocity'
|
|
16
15
|
|
|
@@ -72,14 +71,13 @@ function PrRecordRow({ record, index }: { record: PrRecord; index: number }) {
|
|
|
72
71
|
<View
|
|
73
72
|
accessibilityRole="text"
|
|
74
73
|
accessibilityLabel={a11yLabel}
|
|
75
|
-
className="flex-row items-center"
|
|
74
|
+
className="flex-row items-center bg-surface-raised"
|
|
76
75
|
style={{
|
|
77
76
|
gap: 10,
|
|
78
77
|
paddingVertical: 10,
|
|
79
78
|
paddingHorizontal: 12,
|
|
80
79
|
marginBottom: 8,
|
|
81
80
|
borderRadius: 8,
|
|
82
|
-
backgroundColor: SURFACE_RAISED,
|
|
83
81
|
borderWidth: 1,
|
|
84
82
|
borderColor: record.isRecent ? RECENT_BORDER : BORDER_DEFAULT,
|
|
85
83
|
...(record.isRecent ? { boxShadow: RECENT_GLOW } : {}),
|
|
@@ -88,35 +86,35 @@ function PrRecordRow({ record, index }: { record: PrRecord; index: number }) {
|
|
|
88
86
|
>
|
|
89
87
|
<Star size={16} color={BRAND_PRIMARY} fill={BRAND_PRIMARY} strokeWidth={2} />
|
|
90
88
|
<Text
|
|
89
|
+
className="text-text-secondary"
|
|
91
90
|
style={{
|
|
92
91
|
flex: 1,
|
|
93
92
|
fontSize: 13,
|
|
94
93
|
fontFamily: 'Inter, sans-serif',
|
|
95
94
|
fontWeight: '600',
|
|
96
|
-
color: TEXT_SECONDARY,
|
|
97
95
|
}}
|
|
98
96
|
testID={`pr-history-modal-record-${index}-type`}
|
|
99
97
|
>
|
|
100
98
|
{label}
|
|
101
99
|
</Text>
|
|
102
100
|
<Text
|
|
101
|
+
className="text-text-primary"
|
|
103
102
|
style={{
|
|
104
103
|
fontSize: 14,
|
|
105
104
|
fontFamily: '"Space Grotesk", sans-serif',
|
|
106
105
|
fontWeight: '700',
|
|
107
|
-
color: TEXT_PRIMARY,
|
|
108
106
|
}}
|
|
109
107
|
testID={`pr-history-modal-record-${index}-value`}
|
|
110
108
|
>
|
|
111
109
|
{valueText}
|
|
112
110
|
</Text>
|
|
113
111
|
<Text
|
|
112
|
+
className="text-text-tertiary"
|
|
114
113
|
style={{
|
|
115
114
|
minWidth: 64,
|
|
116
115
|
textAlign: 'right',
|
|
117
116
|
fontSize: 11,
|
|
118
117
|
fontFamily: 'Inter, sans-serif',
|
|
119
|
-
color: TEXT_TERTIARY,
|
|
120
118
|
}}
|
|
121
119
|
testID={`pr-history-modal-record-${index}-date`}
|
|
122
120
|
>
|
|
@@ -173,13 +171,13 @@ export function PrHistoryModal({
|
|
|
173
171
|
>
|
|
174
172
|
<View
|
|
175
173
|
accessibilityElementsHidden
|
|
174
|
+
className="bg-border"
|
|
176
175
|
style={{
|
|
177
176
|
alignSelf: 'center',
|
|
178
177
|
width: 40,
|
|
179
178
|
height: 4,
|
|
180
179
|
borderRadius: 2,
|
|
181
180
|
marginTop: 8,
|
|
182
|
-
backgroundColor: BORDER_DEFAULT,
|
|
183
181
|
}}
|
|
184
182
|
testID="pr-history-modal-handle"
|
|
185
183
|
/>
|
|
@@ -191,11 +189,11 @@ export function PrHistoryModal({
|
|
|
191
189
|
>
|
|
192
190
|
<Text
|
|
193
191
|
accessibilityRole="header"
|
|
192
|
+
className="text-text-primary"
|
|
194
193
|
style={{
|
|
195
194
|
fontSize: 16,
|
|
196
195
|
fontFamily: '"Space Grotesk", sans-serif',
|
|
197
196
|
fontWeight: '700',
|
|
198
|
-
color: TEXT_PRIMARY,
|
|
199
197
|
}}
|
|
200
198
|
testID="pr-history-modal-title"
|
|
201
199
|
>
|
|
@@ -209,7 +207,7 @@ export function PrHistoryModal({
|
|
|
209
207
|
style={{ padding: 4, margin: -4 }}
|
|
210
208
|
testID="pr-history-modal-close"
|
|
211
209
|
>
|
|
212
|
-
<Text style={{ fontSize: 22, lineHeight: 22
|
|
210
|
+
<Text className="text-text-secondary" style={{ fontSize: 22, lineHeight: 22 }}>
|
|
213
211
|
{'×'}
|
|
214
212
|
</Text>
|
|
215
213
|
</Pressable>
|
|
@@ -219,11 +217,11 @@ export function PrHistoryModal({
|
|
|
219
217
|
{records.length === 0 ? (
|
|
220
218
|
<View style={{ paddingVertical: 24 }} testID="pr-history-modal-empty">
|
|
221
219
|
<Text
|
|
220
|
+
className="text-text-tertiary"
|
|
222
221
|
style={{
|
|
223
222
|
textAlign: 'center',
|
|
224
223
|
fontSize: 13,
|
|
225
224
|
fontFamily: 'Inter, sans-serif',
|
|
226
|
-
color: TEXT_TERTIARY,
|
|
227
225
|
}}
|
|
228
226
|
>
|
|
229
227
|
No personal records yet
|
|
@@ -7,13 +7,9 @@ import { type WeekRowProps, type WeekRowWorkout } from './WeekRow'
|
|
|
7
7
|
import { WorkoutCard, type WorkoutStatus, type WorkoutMuscleGroup } from './WorkoutCard'
|
|
8
8
|
import { type WorkoutPillStatus } from './WorkoutPill'
|
|
9
9
|
import { type ExerciseCardProps } from './ExerciseCard'
|
|
10
|
+
import { cn } from '../../../utils/cn'
|
|
10
11
|
|
|
11
|
-
const SURFACE_ELEVATED = 'var(--color-surface-elevated)'
|
|
12
|
-
const BORDER_DEFAULT = 'var(--color-border-default)'
|
|
13
12
|
const BRAND_PRIMARY = '#FF7900'
|
|
14
|
-
const TEXT_PRIMARY = 'var(--color-text-primary)'
|
|
15
|
-
const TEXT_TERTIARY = 'var(--color-text-tertiary)'
|
|
16
|
-
const PAGE_BG = 'var(--color-background-base)'
|
|
17
13
|
|
|
18
14
|
/** A single workout within a planned week, plus its exercise breakdown. */
|
|
19
15
|
export interface PlanWorkout {
|
|
@@ -157,7 +153,7 @@ function Breadcrumbs({ crumbs, onNavigate }: BreadcrumbsProps) {
|
|
|
157
153
|
const isLast = index === crumbs.length - 1
|
|
158
154
|
return (
|
|
159
155
|
<View key={crumb.key} className="flex-row items-center" style={{ gap: 4 }}>
|
|
160
|
-
{index > 0 && <Text style={{ fontSize: 12
|
|
156
|
+
{index > 0 && <Text className="text-text-tertiary" style={{ fontSize: 12 }}>{'›'}</Text>}
|
|
161
157
|
<Pressable
|
|
162
158
|
onPress={() => onNavigate(crumb.level)}
|
|
163
159
|
disabled={isLast}
|
|
@@ -165,11 +161,12 @@ function Breadcrumbs({ crumbs, onNavigate }: BreadcrumbsProps) {
|
|
|
165
161
|
testID={`program-planning-page-crumb-${crumb.key}`}
|
|
166
162
|
>
|
|
167
163
|
<Text
|
|
164
|
+
className={isLast ? 'text-text-primary' : undefined}
|
|
168
165
|
style={{
|
|
169
166
|
fontSize: 12,
|
|
170
167
|
fontFamily: 'Inter, sans-serif',
|
|
171
168
|
fontWeight: isLast ? '700' : '500',
|
|
172
|
-
color: isLast ?
|
|
169
|
+
color: isLast ? undefined : BRAND_PRIMARY,
|
|
173
170
|
}}
|
|
174
171
|
>
|
|
175
172
|
{crumb.label}
|
|
@@ -351,8 +348,8 @@ export function ProgramPlanningPage({
|
|
|
351
348
|
|
|
352
349
|
return (
|
|
353
350
|
<View
|
|
354
|
-
className={className}
|
|
355
|
-
style={{ width: 390
|
|
351
|
+
className={cn(className, 'bg-background-base')}
|
|
352
|
+
style={{ width: 390 }}
|
|
356
353
|
accessibilityRole={'main' as ViewProps['accessibilityRole']}
|
|
357
354
|
aria-label={title}
|
|
358
355
|
testID="program-planning-page"
|
|
@@ -361,11 +358,11 @@ export function ProgramPlanningPage({
|
|
|
361
358
|
<View style={{ padding: 16, gap: 14 }} testID="program-planning-page-content">
|
|
362
359
|
<Text
|
|
363
360
|
accessibilityRole="header"
|
|
361
|
+
className="text-text-primary"
|
|
364
362
|
style={{
|
|
365
363
|
fontSize: 20,
|
|
366
364
|
fontFamily: '"Space Grotesk", sans-serif',
|
|
367
365
|
fontWeight: '700',
|
|
368
|
-
color: TEXT_PRIMARY,
|
|
369
366
|
}}
|
|
370
367
|
testID="program-planning-page-title"
|
|
371
368
|
>
|
|
@@ -388,10 +385,9 @@ export function ProgramPlanningPage({
|
|
|
388
385
|
)}
|
|
389
386
|
|
|
390
387
|
<View
|
|
388
|
+
className="bg-surface-elevated border-border"
|
|
391
389
|
style={{
|
|
392
|
-
backgroundColor: SURFACE_ELEVATED,
|
|
393
390
|
borderWidth: 1,
|
|
394
|
-
borderColor: BORDER_DEFAULT,
|
|
395
391
|
borderRadius: 12,
|
|
396
392
|
padding: 12,
|
|
397
393
|
}}
|
|
@@ -8,8 +8,6 @@ const BRAND_PRIMARY_SUBTLE = 'rgba(255,121,0,0.12)'
|
|
|
8
8
|
const STATUS_SUCCESS = '#14B8A6'
|
|
9
9
|
const STATUS_WARNING = '#FFB020'
|
|
10
10
|
const STATUS_ERROR = '#D14343'
|
|
11
|
-
const TEXT_PRIMARY = 'var(--color-text-primary)'
|
|
12
|
-
const TEXT_SECONDARY = 'var(--color-text-secondary)'
|
|
13
11
|
|
|
14
12
|
/** Emoji option sets per known factor, keyed by lowercase id/label. */
|
|
15
13
|
const EMOJI_SETS: Record<string, readonly string[]> = {
|
|
@@ -91,7 +89,8 @@ function EmojiSlider({ factor }: EmojiSliderProps) {
|
|
|
91
89
|
return (
|
|
92
90
|
<View style={{ marginTop: 14 }} testID={`readiness-check-factor-${factor.id}`}>
|
|
93
91
|
<Text
|
|
94
|
-
|
|
92
|
+
className="text-text-secondary"
|
|
93
|
+
style={{ fontSize: 12, fontWeight: '500', fontFamily: 'Inter, sans-serif' }}
|
|
95
94
|
testID="readiness-check-factor-label"
|
|
96
95
|
>
|
|
97
96
|
{factor.label}
|
|
@@ -114,14 +113,15 @@ function EmojiSlider({ factor }: EmojiSliderProps) {
|
|
|
114
113
|
accessibilityLabel={`${factor.label} level ${level} of 5`}
|
|
115
114
|
aria-checked={selected}
|
|
116
115
|
testID="readiness-check-emoji"
|
|
116
|
+
className={selected ? undefined : 'border-border bg-surface-raised'}
|
|
117
117
|
style={({ pressed }) => ({
|
|
118
118
|
flex: 1,
|
|
119
119
|
alignItems: 'center',
|
|
120
120
|
paddingVertical: 8,
|
|
121
121
|
borderRadius: 8,
|
|
122
122
|
borderWidth: 1,
|
|
123
|
-
borderColor: selected ? BRAND_PRIMARY :
|
|
124
|
-
backgroundColor: selected ? BRAND_PRIMARY_SUBTLE :
|
|
123
|
+
borderColor: selected ? BRAND_PRIMARY : undefined,
|
|
124
|
+
backgroundColor: selected ? BRAND_PRIMARY_SUBTLE : undefined,
|
|
125
125
|
opacity: selected ? 1 : pressed ? 0.8 : 0.55,
|
|
126
126
|
transform: [{ scale: selected ? 1.06 : 1 }],
|
|
127
127
|
})}
|
|
@@ -143,13 +143,13 @@ function ScoreGauge({ score }: { score: number }) {
|
|
|
143
143
|
accessibilityRole="image"
|
|
144
144
|
accessibilityLabel={`Readiness score: ${score} out of 100`}
|
|
145
145
|
testID="readiness-check-score"
|
|
146
|
+
className="bg-surface-raised"
|
|
146
147
|
style={{
|
|
147
148
|
width: 60,
|
|
148
149
|
height: 60,
|
|
149
150
|
borderRadius: 30,
|
|
150
151
|
borderWidth: 4,
|
|
151
152
|
borderColor: color,
|
|
152
|
-
backgroundColor: 'var(--color-surface-raised)',
|
|
153
153
|
alignItems: 'center',
|
|
154
154
|
justifyContent: 'center',
|
|
155
155
|
}}
|
|
@@ -169,19 +169,19 @@ function WarmUpCard({ validation }: { validation: WarmUpValidation }) {
|
|
|
169
169
|
const badge = WARMUP_BADGE[validation.status]
|
|
170
170
|
return (
|
|
171
171
|
<View
|
|
172
|
+
className="border-border bg-surface-raised"
|
|
172
173
|
style={{
|
|
173
174
|
marginTop: 16,
|
|
174
175
|
padding: 12,
|
|
175
176
|
borderRadius: 8,
|
|
176
177
|
borderWidth: 1,
|
|
177
|
-
borderColor: 'var(--color-border-default)',
|
|
178
|
-
backgroundColor: 'var(--color-surface-raised)',
|
|
179
178
|
}}
|
|
180
179
|
testID="readiness-check-warmup"
|
|
181
180
|
>
|
|
182
181
|
<View className="flex-row items-center justify-between" style={{ gap: 8 }}>
|
|
183
182
|
<Text
|
|
184
|
-
|
|
183
|
+
className="text-text-secondary"
|
|
184
|
+
style={{ fontSize: 12, fontWeight: '600', fontFamily: 'Inter, sans-serif' }}
|
|
185
185
|
testID="readiness-check-warmup-deficit"
|
|
186
186
|
>
|
|
187
187
|
{velocityDeficitText(validation.velocityDeficit)}
|
|
@@ -191,7 +191,8 @@ function WarmUpCard({ validation }: { validation: WarmUpValidation }) {
|
|
|
191
191
|
</Badge>
|
|
192
192
|
</View>
|
|
193
193
|
<Text
|
|
194
|
-
|
|
194
|
+
className="text-text-primary"
|
|
195
|
+
style={{ marginTop: 6, fontSize: 13, fontFamily: 'Inter, sans-serif' }}
|
|
195
196
|
testID="readiness-check-warmup-recommendation"
|
|
196
197
|
>
|
|
197
198
|
{validation.recommendation}
|
|
@@ -226,7 +227,8 @@ export function ReadinessCheck({
|
|
|
226
227
|
<View style={{ padding: 16 }}>
|
|
227
228
|
<View className="flex-row items-center justify-between" style={{ gap: 12 }}>
|
|
228
229
|
<Text
|
|
229
|
-
|
|
230
|
+
className="text-text-primary"
|
|
231
|
+
style={{ fontSize: 18, fontWeight: '700', fontFamily: '"Space Grotesk", sans-serif' }}
|
|
230
232
|
testID="readiness-check-title"
|
|
231
233
|
>
|
|
232
234
|
How are you feeling?
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Font mapping: font-heading=Space Grotesk, font-body=Nunito Sans (UI), font-sans=Inter (body)
|
|
2
2
|
import { View, Text, Pressable } from 'react-native'
|
|
3
|
+
import { resolveColor } from '../../../theme/resolve-color'
|
|
3
4
|
|
|
4
5
|
const BRAND_PRIMARY = '#FF7900'
|
|
5
6
|
|
|
@@ -34,11 +35,11 @@ export function RestTimer({
|
|
|
34
35
|
|
|
35
36
|
return (
|
|
36
37
|
<View
|
|
38
|
+
className="bg-surface-raised"
|
|
37
39
|
style={{
|
|
38
40
|
width: '100%',
|
|
39
|
-
backgroundColor: 'var(--color-surface-raised)',
|
|
40
41
|
borderTopWidth: 1,
|
|
41
|
-
borderTopColor: '
|
|
42
|
+
borderTopColor: resolveColor('border-default'),
|
|
42
43
|
paddingVertical: 12,
|
|
43
44
|
paddingHorizontal: 16,
|
|
44
45
|
}}
|
|
@@ -58,13 +59,13 @@ export function RestTimer({
|
|
|
58
59
|
{/* Left side */}
|
|
59
60
|
<View style={{ flexDirection: 'column' }}>
|
|
60
61
|
<Text
|
|
62
|
+
className="text-text-secondary"
|
|
61
63
|
style={{
|
|
62
64
|
fontSize: 11,
|
|
63
65
|
fontFamily: 'Inter, sans-serif',
|
|
64
66
|
fontWeight: '600',
|
|
65
67
|
textTransform: 'uppercase',
|
|
66
68
|
letterSpacing: 1,
|
|
67
|
-
color: 'var(--color-text-secondary)',
|
|
68
69
|
}}
|
|
69
70
|
testID="rest-timer-label"
|
|
70
71
|
>
|
|
@@ -72,10 +73,10 @@ export function RestTimer({
|
|
|
72
73
|
</Text>
|
|
73
74
|
{nextSetInfo != null && (
|
|
74
75
|
<Text
|
|
76
|
+
className="text-text-tertiary"
|
|
75
77
|
style={{
|
|
76
78
|
fontSize: 11,
|
|
77
79
|
fontFamily: 'Inter, sans-serif',
|
|
78
|
-
color: 'var(--color-text-tertiary)',
|
|
79
80
|
marginTop: 2,
|
|
80
81
|
}}
|
|
81
82
|
testID="rest-timer-next-set"
|
|
@@ -87,11 +88,11 @@ export function RestTimer({
|
|
|
87
88
|
|
|
88
89
|
{/* Right side - time display */}
|
|
89
90
|
<Text
|
|
91
|
+
className="text-text-primary"
|
|
90
92
|
style={{
|
|
91
93
|
fontSize: 28,
|
|
92
94
|
fontFamily: '"Space Grotesk", sans-serif',
|
|
93
95
|
fontWeight: '700',
|
|
94
|
-
color: 'var(--color-text-primary)',
|
|
95
96
|
fontVariant: ['tabular-nums'],
|
|
96
97
|
letterSpacing: -0.5,
|
|
97
98
|
}}
|
|
@@ -103,9 +104,9 @@ export function RestTimer({
|
|
|
103
104
|
|
|
104
105
|
{/* Progress bar */}
|
|
105
106
|
<View
|
|
107
|
+
className="bg-border"
|
|
106
108
|
style={{
|
|
107
109
|
height: 3,
|
|
108
|
-
backgroundColor: 'var(--color-border-default)',
|
|
109
110
|
borderRadius: 2,
|
|
110
111
|
marginBottom: 12,
|
|
111
112
|
}}
|
|
@@ -137,11 +138,11 @@ export function RestTimer({
|
|
|
137
138
|
testID="rest-timer-add-time"
|
|
138
139
|
>
|
|
139
140
|
<Text
|
|
141
|
+
className="text-text-secondary"
|
|
140
142
|
style={{
|
|
141
143
|
fontSize: 11,
|
|
142
144
|
fontFamily: 'Inter, sans-serif',
|
|
143
145
|
fontWeight: '600',
|
|
144
|
-
color: 'var(--color-text-secondary)',
|
|
145
146
|
}}
|
|
146
147
|
>
|
|
147
148
|
+30s
|
|
@@ -106,11 +106,11 @@ export function SetRow({
|
|
|
106
106
|
</Text>
|
|
107
107
|
) : (
|
|
108
108
|
<Text
|
|
109
|
+
className="text-text-secondary"
|
|
109
110
|
style={{
|
|
110
111
|
fontSize: 13,
|
|
111
112
|
fontWeight: '600',
|
|
112
113
|
fontFamily: 'Inter, sans-serif',
|
|
113
|
-
color: 'var(--color-text-secondary)',
|
|
114
114
|
}}
|
|
115
115
|
>
|
|
116
116
|
{setNumber}
|
|
@@ -123,10 +123,10 @@ export function SetRow({
|
|
|
123
123
|
testID="set-row-previous"
|
|
124
124
|
>
|
|
125
125
|
<Text
|
|
126
|
+
className="text-text-secondary"
|
|
126
127
|
style={{
|
|
127
128
|
fontSize: 12,
|
|
128
129
|
fontFamily: 'Inter, sans-serif',
|
|
129
|
-
color: 'var(--color-text-secondary)',
|
|
130
130
|
}}
|
|
131
131
|
>
|
|
132
132
|
{previous
|
|
@@ -141,11 +141,11 @@ export function SetRow({
|
|
|
141
141
|
>
|
|
142
142
|
{isActive && reps == null && targets ? (
|
|
143
143
|
<Text
|
|
144
|
+
className="text-text-tertiary"
|
|
144
145
|
style={{
|
|
145
146
|
fontSize: 13,
|
|
146
147
|
fontStyle: 'italic',
|
|
147
148
|
fontFamily: 'Inter, sans-serif',
|
|
148
|
-
color: 'var(--color-text-tertiary)',
|
|
149
149
|
}}
|
|
150
150
|
testID="set-row-target-reps"
|
|
151
151
|
>
|
|
@@ -153,11 +153,11 @@ export function SetRow({
|
|
|
153
153
|
</Text>
|
|
154
154
|
) : (
|
|
155
155
|
<Text
|
|
156
|
+
className={reps != null ? 'text-text-primary' : 'text-text-tertiary'}
|
|
156
157
|
style={{
|
|
157
158
|
fontSize: 14,
|
|
158
159
|
fontWeight: '600',
|
|
159
160
|
fontFamily: 'Inter, sans-serif',
|
|
160
|
-
color: reps != null ? 'var(--color-text-primary)' : 'var(--color-text-tertiary)',
|
|
161
161
|
}}
|
|
162
162
|
>
|
|
163
163
|
{reps != null ? reps : '\u2014'}
|
|
@@ -171,11 +171,11 @@ export function SetRow({
|
|
|
171
171
|
>
|
|
172
172
|
{isActive && weight == null && targets ? (
|
|
173
173
|
<Text
|
|
174
|
+
className="text-text-tertiary"
|
|
174
175
|
style={{
|
|
175
176
|
fontSize: 13,
|
|
176
177
|
fontStyle: 'italic',
|
|
177
178
|
fontFamily: 'Inter, sans-serif',
|
|
178
|
-
color: 'var(--color-text-tertiary)',
|
|
179
179
|
}}
|
|
180
180
|
testID="set-row-target-weight"
|
|
181
181
|
>
|
|
@@ -183,11 +183,11 @@ export function SetRow({
|
|
|
183
183
|
</Text>
|
|
184
184
|
) : (
|
|
185
185
|
<Text
|
|
186
|
+
className={weight != null ? 'text-text-primary' : 'text-text-tertiary'}
|
|
186
187
|
style={{
|
|
187
188
|
fontSize: 14,
|
|
188
189
|
fontWeight: '600',
|
|
189
190
|
fontFamily: 'Inter, sans-serif',
|
|
190
|
-
color: weight != null ? 'var(--color-text-primary)' : 'var(--color-text-tertiary)',
|
|
191
191
|
}}
|
|
192
192
|
>
|
|
193
193
|
{weight != null ? roundWeight(weight) : '\u2014'}
|
|
@@ -200,11 +200,14 @@ export function SetRow({
|
|
|
200
200
|
testID="set-row-rpe"
|
|
201
201
|
>
|
|
202
202
|
<Text
|
|
203
|
+
className={rpe != null ? undefined : 'text-text-tertiary'}
|
|
203
204
|
style={{
|
|
204
205
|
fontSize: 13,
|
|
205
206
|
fontWeight: '600',
|
|
206
207
|
fontFamily: 'Inter, sans-serif',
|
|
207
|
-
|
|
208
|
+
// rpeColor returns a concrete hex (native-safe); only the tertiary
|
|
209
|
+
// fallback needs the className token.
|
|
210
|
+
color: rpe != null ? rpeColor(rpe) : undefined,
|
|
208
211
|
}}
|
|
209
212
|
>
|
|
210
213
|
{rpe != null ? roundRpe(rpe) : '\u2014'}
|
|
@@ -2,17 +2,16 @@
|
|
|
2
2
|
import { useEffect, useMemo, useState } from 'react'
|
|
3
3
|
import { View, Text, Pressable, Animated, Easing, type ViewProps } from 'react-native'
|
|
4
4
|
import { cn } from '../../../utils/cn'
|
|
5
|
+
import { resolveColor } from '../../../theme/resolve-color'
|
|
5
6
|
|
|
6
7
|
const BRAND_PRIMARY = '#FF7900'
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
const BORDER_STRONG = 'var(--color-border-strong)'
|
|
8
|
+
// Line/border color for the dashed projection, used where a className cannot
|
|
9
|
+
// apply (passed as a prop into an inline style, and a per-edge borderTopColor).
|
|
10
|
+
const PROJECTION_LINE_COLOR = resolveColor('text-tertiary')
|
|
11
11
|
const STATUS_SUCCESS = '#14B8A6'
|
|
12
12
|
const STATUS_ERROR = '#D14343'
|
|
13
13
|
const STATUS_WARNING = '#FFB020'
|
|
14
14
|
const GRID_LINE = 'rgba(255,255,255,0.06)'
|
|
15
|
-
const TOOLTIP_BG = 'var(--color-surface-elevated)'
|
|
16
15
|
const SUCCESS_PILL_BG = 'rgba(20,184,166,0.10)'
|
|
17
16
|
const SUCCESS_PILL_BORDER = 'rgba(20,184,166,0.20)'
|
|
18
17
|
const ERROR_PILL_BG = 'rgba(209,67,67,0.10)'
|
|
@@ -312,7 +311,7 @@ export function StrengthTrendChart({
|
|
|
312
311
|
justifyContent: 'center',
|
|
313
312
|
}}
|
|
314
313
|
>
|
|
315
|
-
<Text style={{ fontSize: 12, fontFamily: 'Inter, sans-serif'
|
|
314
|
+
<Text className="text-text-tertiary" style={{ fontSize: 12, fontFamily: 'Inter, sans-serif' }}>
|
|
316
315
|
No strength data yet
|
|
317
316
|
</Text>
|
|
318
317
|
</View>
|
|
@@ -358,6 +357,7 @@ export function StrengthTrendChart({
|
|
|
358
357
|
}}
|
|
359
358
|
>
|
|
360
359
|
<Text
|
|
360
|
+
className="text-text-tertiary"
|
|
361
361
|
style={{
|
|
362
362
|
position: 'absolute',
|
|
363
363
|
left: -PLOT_LEFT,
|
|
@@ -366,7 +366,6 @@ export function StrengthTrendChart({
|
|
|
366
366
|
textAlign: 'right',
|
|
367
367
|
fontSize: 9,
|
|
368
368
|
fontFamily: 'Inter, sans-serif',
|
|
369
|
-
color: TEXT_TERTIARY,
|
|
370
369
|
}}
|
|
371
370
|
>
|
|
372
371
|
{line.label}
|
|
@@ -406,7 +405,7 @@ export function StrengthTrendChart({
|
|
|
406
405
|
<View style={{ width, height, position: 'absolute', top: 0, left: 0 }}>
|
|
407
406
|
<ChartLine
|
|
408
407
|
coords={geometry.projection}
|
|
409
|
-
color={
|
|
408
|
+
color={PROJECTION_LINE_COLOR}
|
|
410
409
|
strokeWidth={2}
|
|
411
410
|
dashed
|
|
412
411
|
testID="strength-trend-chart-projection-segment"
|
|
@@ -475,6 +474,7 @@ export function StrengthTrendChart({
|
|
|
475
474
|
<View
|
|
476
475
|
testID="strength-trend-chart-tooltip"
|
|
477
476
|
accessibilityElementsHidden
|
|
477
|
+
className="bg-surface-elevated border-border-strong"
|
|
478
478
|
style={{
|
|
479
479
|
position: 'absolute',
|
|
480
480
|
left: Math.max(
|
|
@@ -483,30 +483,28 @@ export function StrengthTrendChart({
|
|
|
483
483
|
),
|
|
484
484
|
top: Math.max(0, selectedCoord.y - 52),
|
|
485
485
|
maxWidth: TOOLTIP_WIDTH,
|
|
486
|
-
backgroundColor: TOOLTIP_BG,
|
|
487
486
|
borderWidth: 1,
|
|
488
|
-
borderColor: BORDER_STRONG,
|
|
489
487
|
borderRadius: 8,
|
|
490
488
|
paddingVertical: 8,
|
|
491
489
|
paddingHorizontal: 10,
|
|
492
490
|
}}
|
|
493
491
|
>
|
|
494
492
|
<Text
|
|
493
|
+
className="text-text-tertiary"
|
|
495
494
|
style={{
|
|
496
495
|
fontSize: 10,
|
|
497
496
|
fontFamily: 'Inter, sans-serif',
|
|
498
|
-
color: TEXT_TERTIARY,
|
|
499
497
|
}}
|
|
500
498
|
>
|
|
501
499
|
{selectedCoord.point.sessionLabel ?? selectedCoord.point.date}
|
|
502
500
|
</Text>
|
|
503
501
|
<Text
|
|
502
|
+
className="text-text-primary"
|
|
504
503
|
style={{
|
|
505
504
|
marginTop: 2,
|
|
506
505
|
fontSize: 13,
|
|
507
506
|
fontFamily: 'Inter, sans-serif',
|
|
508
507
|
fontWeight: '700',
|
|
509
|
-
color: TEXT_PRIMARY,
|
|
510
508
|
}}
|
|
511
509
|
>
|
|
512
510
|
{`${formatValue(selectedCoord.point.e1rm)} ${unit}`}
|
|
@@ -547,6 +545,7 @@ export function StrengthTrendChart({
|
|
|
547
545
|
<Text
|
|
548
546
|
key={`axis-${i}`}
|
|
549
547
|
testID="strength-trend-chart-axis-label"
|
|
548
|
+
className="text-text-tertiary"
|
|
550
549
|
style={{
|
|
551
550
|
position: 'absolute',
|
|
552
551
|
left: boundary.x - 24,
|
|
@@ -554,7 +553,6 @@ export function StrengthTrendChart({
|
|
|
554
553
|
textAlign: 'center',
|
|
555
554
|
fontSize: 10,
|
|
556
555
|
fontFamily: 'Inter, sans-serif',
|
|
557
|
-
color: TEXT_TERTIARY,
|
|
558
556
|
}}
|
|
559
557
|
>
|
|
560
558
|
{boundary.label}
|
|
@@ -598,7 +596,7 @@ export function StrengthTrendChart({
|
|
|
598
596
|
>
|
|
599
597
|
<View className="flex-row items-center" style={{ gap: 5 }}>
|
|
600
598
|
<View style={{ width: 14, height: 2.5, borderRadius: 1.5, backgroundColor: BRAND_PRIMARY }} />
|
|
601
|
-
<Text style={{ fontSize: 10, fontFamily: 'Inter, sans-serif'
|
|
599
|
+
<Text className="text-text-secondary" style={{ fontSize: 10, fontFamily: 'Inter, sans-serif' }}>
|
|
602
600
|
Actual
|
|
603
601
|
</Text>
|
|
604
602
|
</View>
|
|
@@ -609,16 +607,16 @@ export function StrengthTrendChart({
|
|
|
609
607
|
height: 0,
|
|
610
608
|
borderTopWidth: 2,
|
|
611
609
|
borderStyle: 'dashed',
|
|
612
|
-
borderTopColor:
|
|
610
|
+
borderTopColor: PROJECTION_LINE_COLOR,
|
|
613
611
|
}}
|
|
614
612
|
/>
|
|
615
|
-
<Text style={{ fontSize: 10, fontFamily: 'Inter, sans-serif'
|
|
613
|
+
<Text className="text-text-secondary" style={{ fontSize: 10, fontFamily: 'Inter, sans-serif' }}>
|
|
616
614
|
Projected
|
|
617
615
|
</Text>
|
|
618
616
|
</View>
|
|
619
617
|
<View className="flex-row items-center" style={{ gap: 5 }}>
|
|
620
618
|
<Text style={{ fontSize: 12, color: STATUS_WARNING }}>★</Text>
|
|
621
|
-
<Text style={{ fontSize: 10, fontFamily: 'Inter, sans-serif'
|
|
619
|
+
<Text className="text-text-secondary" style={{ fontSize: 10, fontFamily: 'Inter, sans-serif' }}>
|
|
622
620
|
PR
|
|
623
621
|
</Text>
|
|
624
622
|
</View>
|